<commit_before>
#include "TestUtil.hpp"

#include "LuaCpp/LuaTable.hpp"

using namespace luacpp;

class LuaTableTest : public LuaStateTest
{
};

TEST_F(LuaTableTest, AddValue)
{
	LuaTable table = LuaTable::create(L);
	table.addValue("key", "value");

	ASSERT_TRUE(table.pushValue());

	lua_getfield(L, -1, "key");

	ASSERT_TRUE(lua_isstring(L, -1) == 1);
	ASSERT_STREQ("value", lua_tostring(L, -1));
}

TEST_F(LuaTableTest, SetReference)
{
	LuaTable table = LuaTable::create(L);

	lua_pushliteral(L, "abc");
	ASSERT_THROW(table.setReference(LuaReference::create(L)), LuaException);

	lua_newtable(L);
	ASSERT_NO_THROW(table.setReference(LuaReference::create(L)));
}

TEST_F(LuaTableTest, GetValue)
{
	lua_newtable(L);
	lua_pushstring(L, "value");
	lua_setfield(L, -2, "key");

	LuaTable table;

	EXPECT_TRUE(convert::popValue(L, table));

	std::string val;
	ASSERT_TRUE(table.getValue("key", val));
	ASSERT_STREQ("value", val.c_str());
}

TEST_F(LuaTableTest, GetLength)
{
	lua_newtable(L);

	lua_pushnumber(L, 1);
	lua_pushstring(L, "value1");
	lua_settable(L, -3);

	lua_pushnumber(L, 2);
	lua_pushstring(L, "value2");
	lua_settable(L, -3);

	lua_pushnumber(L, 3);
	lua_pushstring(L, "value3");
	lua_settable(L, -3);

	LuaTable table;

	EXPECT_TRUE(convert::popValue(L, table));

	ASSERT_EQ(3, table.getLength());
}

TEST_F(LuaTableTest, Iterator)
{
	lua_newtable(L);

	lua_pushnumber(L, 1);
	lua_pushstring(L, "value1");
	lua_settable(L, -3);

	lua_pushnumber(L, 2);
	lua_pushstring(L, "value2");
	lua_settable(L, -3);

	lua_pushnumber(L, 3);
	lua_pushstring(L, "value3");
	lua_settable(L, -3);

	lua_pushstring(L, "value4");
	lua_setfield(L, -2, "key");

	LuaTable table;

	EXPECT_TRUE(convert::popValue(L, table));

	table.iterator();
}
<commit_msg>Clean Table tests stack<commit_after>
#include "TestUtil.hpp"

#include "LuaCpp/LuaTable.hpp"

using namespace luacpp;

class LuaTableTest : public LuaStateTest
{
};

TEST_F(LuaTableTest, AddValue)
{
	auto top = lua_gettop(L);
	LuaTable table = LuaTable::create(L);
	table.addValue("key", "value");

	ASSERT_TRUE(table.pushValue());

	lua_getfield(L, -1, "key");

	ASSERT_TRUE(lua_isstring(L, -1) == 1);
	ASSERT_STREQ("value", lua_tostring(L, -1));

	lua_pop(L, 2); // Pop value and table
}

TEST_F(LuaTableTest, SetReference)
{
	LuaTable table = LuaTable::create(L);

	lua_pushliteral(L, "abc");
	ASSERT_THROW(table.setReference(LuaReference::create(L)), LuaException);

	lua_pop(L, 1);

	lua_newtable(L);
	ASSERT_NO_THROW(table.setReference(LuaReference::create(L)));

	lua_pop(L, 1);
}

TEST_F(LuaTableTest, GetValue)
{
	lua_newtable(L);
	lua_pushstring(L, "value");
	lua_setfield(L, -2, "key");

	LuaTable table;

	EXPECT_TRUE(convert::popValue(L, table));

	std::string val;
	ASSERT_TRUE(table.getValue("key", val));
	ASSERT_STREQ("value", val.c_str());
}

TEST_F(LuaTableTest, GetLength)
{
	lua_newtable(L);

	lua_pushnumber(L, 1);
	lua_pushstring(L, "value1");
	lua_settable(L, -3);

	lua_pushnumber(L, 2);
	lua_pushstring(L, "value2");
	lua_settable(L, -3);

	lua_pushnumber(L, 3);
	lua_pushstring(L, "value3");
	lua_settable(L, -3);

	LuaTable table;

	EXPECT_TRUE(convert::popValue(L, table));

	ASSERT_EQ(3, table.getLength());
}

TEST_F(LuaTableTest, Iterator)
{
	lua_newtable(L);

	lua_pushnumber(L, 1);
	lua_pushstring(L, "value1");
	lua_settable(L, -3);

	lua_pushnumber(L, 2);
	lua_pushstring(L, "value2");
	lua_settable(L, -3);

	lua_pushnumber(L, 3);
	lua_pushstring(L, "value3");
	lua_settable(L, -3);

	lua_pushstring(L, "value4");
	lua_setfield(L, -2, "key");

	LuaTable table;

	EXPECT_TRUE(convert::popValue(L, table));

	auto iter = table.iterator();

	int i = 0;
	while (iter.toNext())
	{
		switch (i)
		{
		case 0:
		{
			ASSERT_STREQ("value1", lua_tostring(L, -1));
			lua_pop(L, 1);

			ASSERT_DOUBLE_EQ(1.0, lua_tonumber(L, -1));
			break;
		}
		case 1:
		{
			ASSERT_STREQ("value2", lua_tostring(L, -1));
			lua_pop(L, 1);

			ASSERT_DOUBLE_EQ(2.0, lua_tonumber(L, -1));
			break;
		}
		case 2:
		{
			ASSERT_STREQ("value3", lua_tostring(L, -1));
			lua_pop(L, 1);

			ASSERT_DOUBLE_EQ(3.0, lua_tonumber(L, -1));
			break;
		}
		case 3:
		{
			ASSERT_STREQ("value4", lua_tostring(L, -1));
			lua_pop(L, 1);

			ASSERT_STREQ("key", lua_tostring(L, -1));
			break;
		}
		default:
			FAIL();
			break;
		}
		++i;
	}
}
<|endoftext|>


<commit_before>//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/CodeGen/BackendUtil.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"
using namespace clang;
using namespace llvm;

namespace {

class EmitAssemblyHelper {
  DiagnosticsEngine &Diags;
  const CodeGenOptions &CodeGenOpts;
  const TargetOptions &TargetOpts;
  const LangOptions &LangOpts;
  Module *TheModule;

  Timer CodeGenerationTime;

  mutable PassManager *CodeGenPasses;
  mutable PassManager *PerModulePasses;
  mutable FunctionPassManager *PerFunctionPasses;

private:
  PassManager *getCodeGenPasses() const {
    if (!CodeGenPasses) {
      CodeGenPasses = new PassManager();
      CodeGenPasses->add(new TargetData(TheModule));
    }
    return CodeGenPasses;
  }

  PassManager *getPerModulePasses() const {
    if (!PerModulePasses) {
      PerModulePasses = new PassManager();
      PerModulePasses->add(new TargetData(TheModule));
    }
    return PerModulePasses;
  }

  FunctionPassManager *getPerFunctionPasses() const {
    if (!PerFunctionPasses) {
      PerFunctionPasses = new FunctionPassManager(TheModule);
      PerFunctionPasses->add(new TargetData(TheModule));
    }
    return PerFunctionPasses;
  }

  void CreatePasses();

  /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
  ///
  /// \return True on success.
  bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS);

public:
  EmitAssemblyHelper(DiagnosticsEngine &_Diags,
                     const CodeGenOptions &CGOpts, const TargetOptions &TOpts,
                     const LangOptions &LOpts,
                     Module *M)
    : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts),
      TheModule(M), CodeGenerationTime("Code Generation Time"),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}

  ~EmitAssemblyHelper() {
    delete CodeGenPasses;
    delete PerModulePasses;
    delete PerFunctionPasses;
  }

  void EmitAssembly(BackendAction Action, raw_ostream *OS);
};

}

static void addObjCARCExpandPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createObjCARCExpandPass());
}

static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createObjCARCOptPass());
}

static void addAddressSanitizerPass(const PassManagerBuilder &Builder,
                                    PassManagerBase &PM) {
  PM.add(createAddressSanitizerPass());
}

void EmitAssemblyHelper::CreatePasses() {
  unsigned OptLevel = CodeGenOpts.OptimizationLevel;
  CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining;

  // Handle disabling of LLVM optimization, where we want to preserve the
  // internal module before any optimization.
  if (CodeGenOpts.DisableLLVMOpts) {
    OptLevel = 0;
    Inlining = CodeGenOpts.NoInlining;
  }

  PassManagerBuilder PMBuilder;
  PMBuilder.OptLevel = OptLevel;
  PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;

  PMBuilder.DisableSimplifyLibCalls = !CodeGenOpts.SimplifyLibCalls;
  PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
  PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;

  // In ObjC ARC mode, add the main ARC optimization passes.
  if (LangOpts.ObjCAutoRefCount) {
    PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
                           addObjCARCExpandPass);
    PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                           addObjCARCOptPass);
  }

  if (LangOpts.AddressSanitizer) {
    PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                           addAddressSanitizerPass);
  }

  // Figure out TargetLibraryInfo.
  Triple TargetTriple(TheModule->getTargetTriple());
  PMBuilder.LibraryInfo = new TargetLibraryInfo(TargetTriple);
  if (!CodeGenOpts.SimplifyLibCalls)
    PMBuilder.LibraryInfo->disableAllFunctions();

  switch (Inlining) {
  case CodeGenOptions::NoInlining: break;
  case CodeGenOptions::NormalInlining: {
    // FIXME: Derive these constants in a principled fashion.
    unsigned Threshold = 225;
    if (CodeGenOpts.OptimizeSize == 1)      // -Os
      Threshold = 75;
    else if (CodeGenOpts.OptimizeSize == 2) // -Oz
      Threshold = 25;
    else if (OptLevel > 2)
      Threshold = 275;
    PMBuilder.Inliner = createFunctionInliningPass(Threshold);
    break;
  }
  case CodeGenOptions::OnlyAlwaysInlining:
    // Respect always_inline.
    PMBuilder.Inliner = createAlwaysInlinerPass();
    break;
  }

  // Set up the per-function pass manager.
  FunctionPassManager *FPM = getPerFunctionPasses();
  if (CodeGenOpts.VerifyModule)
    FPM->add(createVerifierPass());
  PMBuilder.populateFunctionPassManager(*FPM);

  // Set up the per-module pass manager.
  PassManager *MPM = getPerModulePasses();

  if (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes) {
    MPM->add(createGCOVProfilerPass(CodeGenOpts.EmitGcovNotes,
                                    CodeGenOpts.EmitGcovArcs,
                                    TargetTriple.isMacOSX()));

    if (!CodeGenOpts.DebugInfo)
      MPM->add(createStripSymbolsPass(true));
  }

  PMBuilder.populateModulePassManager(*MPM);
}

bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
                                       formatted_raw_ostream &OS) {
  // Create the TargetMachine for generating code.
  std::string Error;
  std::string Triple = TheModule->getTargetTriple();
  const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget) {
    Diags.Report(diag::err_fe_unable_to_create_target) << Error;
    return false;
  }

  // FIXME: Expose these capabilities via actual APIs!!!! Aside from just
  // being gross, this is also totally broken if we ever care about
  // concurrency.

  // Set frame pointer elimination mode.
  if (!CodeGenOpts.DisableFPElim) {
    llvm::NoFramePointerElim = false;
    llvm::NoFramePointerElimNonLeaf = false;
  } else if (CodeGenOpts.OmitLeafFramePointer) {
    llvm::NoFramePointerElim = false;
    llvm::NoFramePointerElimNonLeaf = true;
  } else {
    llvm::NoFramePointerElim = true;
    llvm::NoFramePointerElimNonLeaf = true;
  }

  // Set float ABI type.
  if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp")
    llvm::FloatABIType = llvm::FloatABI::Soft;
  else if (CodeGenOpts.FloatABI == "hard")
    llvm::FloatABIType = llvm::FloatABI::Hard;
  else {
    assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
    llvm::FloatABIType = llvm::FloatABI::Default;
  }

  llvm::LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD;
  llvm::NoInfsFPMath = CodeGenOpts.NoInfsFPMath;
  llvm::NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
  NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
  llvm::UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
  llvm::UseSoftFloat = CodeGenOpts.SoftFloat;

  TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose);

  TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections);
  TargetMachine::setDataSections    (CodeGenOpts.DataSections);

  // FIXME: Parse this earlier.
  llvm::CodeModel::Model CM;
  if (CodeGenOpts.CodeModel == "small") {
    CM = llvm::CodeModel::Small;
  } else if (CodeGenOpts.CodeModel == "kernel") {
    CM = llvm::CodeModel::Kernel;
  } else if (CodeGenOpts.CodeModel == "medium") {
    CM = llvm::CodeModel::Medium;
  } else if (CodeGenOpts.CodeModel == "large") {
    CM = llvm::CodeModel::Large;
  } else {
    assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
    CM = llvm::CodeModel::Default;
  }

  std::vector<const char *> BackendArgs;
  BackendArgs.push_back("clang"); // Fake program name.
  if (!CodeGenOpts.DebugPass.empty()) {
    BackendArgs.push_back("-debug-pass");
    BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
  }
  if (!CodeGenOpts.LimitFloatPrecision.empty()) {
    BackendArgs.push_back("-limit-float-precision");
    BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
  }
  if (llvm::TimePassesIsEnabled)
    BackendArgs.push_back("-time-passes");
  for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i)
    BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
  if (CodeGenOpts.NoGlobalMerge)
    BackendArgs.push_back("-global-merge=false");
  BackendArgs.push_back(0);
  llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
                                    const_cast<char **>(&BackendArgs[0]));

  std::string FeaturesStr;
  if (TargetOpts.Features.size()) {
    SubtargetFeatures Features;
    for (std::vector<std::string>::const_iterator
           it = TargetOpts.Features.begin(),
           ie = TargetOpts.Features.end(); it != ie; ++it)
      Features.AddFeature(*it);
    FeaturesStr = Features.getString();
  }

  llvm::Reloc::Model RM = llvm::Reloc::Default;
  if (CodeGenOpts.RelocationModel == "static") {
    RM = llvm::Reloc::Static;
  } else if (CodeGenOpts.RelocationModel == "pic") {
    RM = llvm::Reloc::PIC_;
  } else {
    assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" &&
           "Invalid PIC model!");
    RM = llvm::Reloc::DynamicNoPIC;
  }

  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
  switch (CodeGenOpts.OptimizationLevel) {
  default: break;
  case 0: OptLevel = CodeGenOpt::None; break;
  case 3: OptLevel = CodeGenOpt::Aggressive; break;
  }

  TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU,
                                                     FeaturesStr, RM, CM,
                                                     OptLevel);

  if (CodeGenOpts.RelaxAll)
    TM->setMCRelaxAll(true);
  if (CodeGenOpts.SaveTempLabels)
    TM->setMCSaveTempLabels(true);
  if (CodeGenOpts.NoDwarf2CFIAsm)
    TM->setMCUseCFI(false);
  if (!CodeGenOpts.NoDwarfDirectoryAsm)
    TM->setMCUseDwarfDirectory(true);
  if (CodeGenOpts.NoExecStack)
    TM->setMCNoExecStack(true);

  // Create the code generator passes.
  PassManager *PM = getCodeGenPasses();

  // Normal mode, emit a .s or .o file by running the code generator. Note,
  // this also adds codegenerator level optimization passes.
  TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile;
  if (Action == Backend_EmitObj)
    CGFT = TargetMachine::CGFT_ObjectFile;
  else if (Action == Backend_EmitMCNull)
    CGFT = TargetMachine::CGFT_Null;
  else
    assert(Action == Backend_EmitAssembly && "Invalid action!");

  // Add ObjC ARC final-cleanup optimizations. This is done as part of the
  // "codegen" passes so that it isn't run multiple times when there is
  // inlining happening.
  if (LangOpts.ObjCAutoRefCount)
    PM->add(createObjCARCContractPass());

  if (TM->addPassesToEmitFile(*PM, OS, CGFT,
                              /*DisableVerify=*/!CodeGenOpts.VerifyModule)) {
    Diags.Report(diag::err_fe_unable_to_interface_with_target);
    return false;
  }

  return true;
}

void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
  TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0);
  llvm::formatted_raw_ostream FormattedOS;

  CreatePasses();
  switch (Action) {
  case Backend_EmitNothing:
    break;

  case Backend_EmitBC:
    getPerModulePasses()->add(createBitcodeWriterPass(*OS));
    break;

  case Backend_EmitLL:
    FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
    getPerModulePasses()->add(createPrintModulePass(&FormattedOS));
    break;

  default:
    FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
    if (!AddEmitPasses(Action, FormattedOS))
      return;
  }

  // Before executing passes, print the final values of the LLVM options.
  cl::PrintOptionValues();

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PrettyStackTraceString CrashInfo("Per-function optimization");

    PerFunctionPasses->doInitialization();
    for (Module::iterator I = TheModule->begin(),
           E = TheModule->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses) {
    PrettyStackTraceString CrashInfo("Per-module optimization passes");
    PerModulePasses->run(*TheModule);
  }

  if (CodeGenPasses) {
    PrettyStackTraceString CrashInfo("Code generation");
    CodeGenPasses->run(*TheModule);
  }
}

void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
                              const CodeGenOptions &CGOpts,
                              const TargetOptions &TOpts,
                              const LangOptions &LOpts,
                              Module *M,
                              BackendAction Action, raw_ostream *OS) {
  EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);

  AsmHelper.EmitAssembly(Action, OS);
}
<commit_msg>make asan work at -O0, clang part. Patch by glider@google.com<commit_after>//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/CodeGen/BackendUtil.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Scalar.h"
using namespace clang;
using namespace llvm;

namespace {

class EmitAssemblyHelper {
  DiagnosticsEngine &Diags;
  const CodeGenOptions &CodeGenOpts;
  const TargetOptions &TargetOpts;
  const LangOptions &LangOpts;
  Module *TheModule;

  Timer CodeGenerationTime;

  mutable PassManager *CodeGenPasses;
  mutable PassManager *PerModulePasses;
  mutable FunctionPassManager *PerFunctionPasses;

private:
  PassManager *getCodeGenPasses() const {
    if (!CodeGenPasses) {
      CodeGenPasses = new PassManager();
      CodeGenPasses->add(new TargetData(TheModule));
    }
    return CodeGenPasses;
  }

  PassManager *getPerModulePasses() const {
    if (!PerModulePasses) {
      PerModulePasses = new PassManager();
      PerModulePasses->add(new TargetData(TheModule));
    }
    return PerModulePasses;
  }

  FunctionPassManager *getPerFunctionPasses() const {
    if (!PerFunctionPasses) {
      PerFunctionPasses = new FunctionPassManager(TheModule);
      PerFunctionPasses->add(new TargetData(TheModule));
    }
    return PerFunctionPasses;
  }

  void CreatePasses();

  /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
  ///
  /// \return True on success.
  bool AddEmitPasses(BackendAction Action, formatted_raw_ostream &OS);

public:
  EmitAssemblyHelper(DiagnosticsEngine &_Diags,
                     const CodeGenOptions &CGOpts, const TargetOptions &TOpts,
                     const LangOptions &LOpts,
                     Module *M)
    : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts),
      TheModule(M), CodeGenerationTime("Code Generation Time"),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}

  ~EmitAssemblyHelper() {
    delete CodeGenPasses;
    delete PerModulePasses;
    delete PerFunctionPasses;
  }

  void EmitAssembly(BackendAction Action, raw_ostream *OS);
};

}

static void addObjCARCExpandPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createObjCARCExpandPass());
}

static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
  if (Builder.OptLevel > 0)
    PM.add(createObjCARCOptPass());
}

static void addAddressSanitizerPass(const PassManagerBuilder &Builder,
                                    PassManagerBase &PM) {
  PM.add(createAddressSanitizerPass());
}

void EmitAssemblyHelper::CreatePasses() {
  unsigned OptLevel = CodeGenOpts.OptimizationLevel;
  CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining;

  // Handle disabling of LLVM optimization, where we want to preserve the
  // internal module before any optimization.
  if (CodeGenOpts.DisableLLVMOpts) {
    OptLevel = 0;
    Inlining = CodeGenOpts.NoInlining;
  }

  PassManagerBuilder PMBuilder;
  PMBuilder.OptLevel = OptLevel;
  PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;

  PMBuilder.DisableSimplifyLibCalls = !CodeGenOpts.SimplifyLibCalls;
  PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime;
  PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;

  // In ObjC ARC mode, add the main ARC optimization passes.
  if (LangOpts.ObjCAutoRefCount) {
    PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
                           addObjCARCExpandPass);
    PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                           addObjCARCOptPass);
  }

  if (LangOpts.AddressSanitizer) {
    PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
                           addAddressSanitizerPass);
    PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
                           addAddressSanitizerPass);
  }

  // Figure out TargetLibraryInfo.
  Triple TargetTriple(TheModule->getTargetTriple());
  PMBuilder.LibraryInfo = new TargetLibraryInfo(TargetTriple);
  if (!CodeGenOpts.SimplifyLibCalls)
    PMBuilder.LibraryInfo->disableAllFunctions();

  switch (Inlining) {
  case CodeGenOptions::NoInlining: break;
  case CodeGenOptions::NormalInlining: {
    // FIXME: Derive these constants in a principled fashion.
    unsigned Threshold = 225;
    if (CodeGenOpts.OptimizeSize == 1)      // -Os
      Threshold = 75;
    else if (CodeGenOpts.OptimizeSize == 2) // -Oz
      Threshold = 25;
    else if (OptLevel > 2)
      Threshold = 275;
    PMBuilder.Inliner = createFunctionInliningPass(Threshold);
    break;
  }
  case CodeGenOptions::OnlyAlwaysInlining:
    // Respect always_inline.
    PMBuilder.Inliner = createAlwaysInlinerPass();
    break;
  }

  // Set up the per-function pass manager.
  FunctionPassManager *FPM = getPerFunctionPasses();
  if (CodeGenOpts.VerifyModule)
    FPM->add(createVerifierPass());
  PMBuilder.populateFunctionPassManager(*FPM);

  // Set up the per-module pass manager.
  PassManager *MPM = getPerModulePasses();

  if (CodeGenOpts.EmitGcovArcs || CodeGenOpts.EmitGcovNotes) {
    MPM->add(createGCOVProfilerPass(CodeGenOpts.EmitGcovNotes,
                                    CodeGenOpts.EmitGcovArcs,
                                    TargetTriple.isMacOSX()));

    if (!CodeGenOpts.DebugInfo)
      MPM->add(createStripSymbolsPass(true));
  }

  PMBuilder.populateModulePassManager(*MPM);
}

bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
                                       formatted_raw_ostream &OS) {
  // Create the TargetMachine for generating code.
  std::string Error;
  std::string Triple = TheModule->getTargetTriple();
  const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget) {
    Diags.Report(diag::err_fe_unable_to_create_target) << Error;
    return false;
  }

  // FIXME: Expose these capabilities via actual APIs!!!! Aside from just
  // being gross, this is also totally broken if we ever care about
  // concurrency.

  // Set frame pointer elimination mode.
  if (!CodeGenOpts.DisableFPElim) {
    llvm::NoFramePointerElim = false;
    llvm::NoFramePointerElimNonLeaf = false;
  } else if (CodeGenOpts.OmitLeafFramePointer) {
    llvm::NoFramePointerElim = false;
    llvm::NoFramePointerElimNonLeaf = true;
  } else {
    llvm::NoFramePointerElim = true;
    llvm::NoFramePointerElimNonLeaf = true;
  }

  // Set float ABI type.
  if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp")
    llvm::FloatABIType = llvm::FloatABI::Soft;
  else if (CodeGenOpts.FloatABI == "hard")
    llvm::FloatABIType = llvm::FloatABI::Hard;
  else {
    assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
    llvm::FloatABIType = llvm::FloatABI::Default;
  }

  llvm::LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD;
  llvm::NoInfsFPMath = CodeGenOpts.NoInfsFPMath;
  llvm::NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
  NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
  llvm::UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
  llvm::UseSoftFloat = CodeGenOpts.SoftFloat;

  TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose);

  TargetMachine::setFunctionSections(CodeGenOpts.FunctionSections);
  TargetMachine::setDataSections    (CodeGenOpts.DataSections);

  // FIXME: Parse this earlier.
  llvm::CodeModel::Model CM;
  if (CodeGenOpts.CodeModel == "small") {
    CM = llvm::CodeModel::Small;
  } else if (CodeGenOpts.CodeModel == "kernel") {
    CM = llvm::CodeModel::Kernel;
  } else if (CodeGenOpts.CodeModel == "medium") {
    CM = llvm::CodeModel::Medium;
  } else if (CodeGenOpts.CodeModel == "large") {
    CM = llvm::CodeModel::Large;
  } else {
    assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
    CM = llvm::CodeModel::Default;
  }

  std::vector<const char *> BackendArgs;
  BackendArgs.push_back("clang"); // Fake program name.
  if (!CodeGenOpts.DebugPass.empty()) {
    BackendArgs.push_back("-debug-pass");
    BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
  }
  if (!CodeGenOpts.LimitFloatPrecision.empty()) {
    BackendArgs.push_back("-limit-float-precision");
    BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
  }
  if (llvm::TimePassesIsEnabled)
    BackendArgs.push_back("-time-passes");
  for (unsigned i = 0, e = CodeGenOpts.BackendOptions.size(); i != e; ++i)
    BackendArgs.push_back(CodeGenOpts.BackendOptions[i].c_str());
  if (CodeGenOpts.NoGlobalMerge)
    BackendArgs.push_back("-global-merge=false");
  BackendArgs.push_back(0);
  llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
                                    const_cast<char **>(&BackendArgs[0]));

  std::string FeaturesStr;
  if (TargetOpts.Features.size()) {
    SubtargetFeatures Features;
    for (std::vector<std::string>::const_iterator
           it = TargetOpts.Features.begin(),
           ie = TargetOpts.Features.end(); it != ie; ++it)
      Features.AddFeature(*it);
    FeaturesStr = Features.getString();
  }

  llvm::Reloc::Model RM = llvm::Reloc::Default;
  if (CodeGenOpts.RelocationModel == "static") {
    RM = llvm::Reloc::Static;
  } else if (CodeGenOpts.RelocationModel == "pic") {
    RM = llvm::Reloc::PIC_;
  } else {
    assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" &&
           "Invalid PIC model!");
    RM = llvm::Reloc::DynamicNoPIC;
  }

  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
  switch (CodeGenOpts.OptimizationLevel) {
  default: break;
  case 0: OptLevel = CodeGenOpt::None; break;
  case 3: OptLevel = CodeGenOpt::Aggressive; break;
  }

  TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU,
                                                     FeaturesStr, RM, CM,
                                                     OptLevel);

  if (CodeGenOpts.RelaxAll)
    TM->setMCRelaxAll(true);
  if (CodeGenOpts.SaveTempLabels)
    TM->setMCSaveTempLabels(true);
  if (CodeGenOpts.NoDwarf2CFIAsm)
    TM->setMCUseCFI(false);
  if (!CodeGenOpts.NoDwarfDirectoryAsm)
    TM->setMCUseDwarfDirectory(true);
  if (CodeGenOpts.NoExecStack)
    TM->setMCNoExecStack(true);

  // Create the code generator passes.
  PassManager *PM = getCodeGenPasses();

  // Normal mode, emit a .s or .o file by running the code generator. Note,
  // this also adds codegenerator level optimization passes.
  TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile;
  if (Action == Backend_EmitObj)
    CGFT = TargetMachine::CGFT_ObjectFile;
  else if (Action == Backend_EmitMCNull)
    CGFT = TargetMachine::CGFT_Null;
  else
    assert(Action == Backend_EmitAssembly && "Invalid action!");

  // Add ObjC ARC final-cleanup optimizations. This is done as part of the
  // "codegen" passes so that it isn't run multiple times when there is
  // inlining happening.
  if (LangOpts.ObjCAutoRefCount)
    PM->add(createObjCARCContractPass());

  if (TM->addPassesToEmitFile(*PM, OS, CGFT,
                              /*DisableVerify=*/!CodeGenOpts.VerifyModule)) {
    Diags.Report(diag::err_fe_unable_to_interface_with_target);
    return false;
  }

  return true;
}

void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_ostream *OS) {
  TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0);
  llvm::formatted_raw_ostream FormattedOS;

  CreatePasses();
  switch (Action) {
  case Backend_EmitNothing:
    break;

  case Backend_EmitBC:
    getPerModulePasses()->add(createBitcodeWriterPass(*OS));
    break;

  case Backend_EmitLL:
    FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
    getPerModulePasses()->add(createPrintModulePass(&FormattedOS));
    break;

  default:
    FormattedOS.setStream(*OS, formatted_raw_ostream::PRESERVE_STREAM);
    if (!AddEmitPasses(Action, FormattedOS))
      return;
  }

  // Before executing passes, print the final values of the LLVM options.
  cl::PrintOptionValues();

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PrettyStackTraceString CrashInfo("Per-function optimization");

    PerFunctionPasses->doInitialization();
    for (Module::iterator I = TheModule->begin(),
           E = TheModule->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses) {
    PrettyStackTraceString CrashInfo("Per-module optimization passes");
    PerModulePasses->run(*TheModule);
  }

  if (CodeGenPasses) {
    PrettyStackTraceString CrashInfo("Code generation");
    CodeGenPasses->run(*TheModule);
  }
}

void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
                              const CodeGenOptions &CGOpts,
                              const TargetOptions &TOpts,
                              const LangOptions &LOpts,
                              Module *M,
                              BackendAction Action, raw_ostream *OS) {
  EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);

  AsmHelper.EmitAssembly(Action, OS);
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../Characters/ToString.h"
#include "../Execution/Thread.h"

#include "Sanitizer.h"
#include "Trace.h"

#include "AssertExternallySynchronizedMutex.h"

using namespace Stroika;
using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Debug;

#if qDebug
/*
 ********************************************************************************
 ****************** Debug::AssertExternallySynchronizedMutex ********************
 ********************************************************************************
 */
void AssertExternallySynchronizedMutex::lock_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        if (sharedContext->fLocks_++ == 0) {
            // If first time in, save thread-id
            sharedContext->fCurLockThread_ = this_thread::get_id ();
            if (not sharedContext->GetSharedLockEmpty_ ()) {
                // If first already shared locks - OK - so long as same thread
                Require (sharedContext->CountOfIInSharedLockThreads_ (sharedContext->fCurLockThread_) == sharedContext->GetSharedLockThreadsCount_ ());
            }
        }
        else {
            // If first already locked - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO modify (lock for write) an object which is already in use (debuglocked) in another thread (thisthread=%s)", Characters::ToString (this_thread::get_id ()).c_str ());
                DbgTrace ("Original thread holding lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
        }
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_ () const noexcept
{
    SharedContext* sharedContext = _fSharedContext.get ();
    Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
    Require (sharedContext->fLocks_ > 0); // else unbalanced
    --sharedContext->fLocks_;
    // Note at this point - it would make some sense to CLEAR fCurLockThread_, but that could be a race, cuz someone
    // else could lock just as we are unlocking...
}

void AssertExternallySynchronizedMutex::lock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        // OK to shared lock from various threads
        // But if already locked, NOT OK (would have blocked in real impl) - if you try to shared lock from another thread while locked
        if (sharedContext->fLocks_ != 0) {
            // If first already locks - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO shared_lock (lock for READ) an object which is already in use (debuglocked for WRITE) in another thread");
                DbgTrace ("Original thread holding (write) lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ()); // if this assert fails, and fLocks_==1, see https://stroika.atlassian.net/browse/STK-956 (possible false positive)
        }
        sharedContext->AddSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        sharedContext->RemoveSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

mutex& AssertExternallySynchronizedMutex::GetSharedLockMutexThreads_ ()
{
    static mutex sMutex_; // must be out-of-line so we can have just one mutex object. Could use static member, but then trouble using
                          // AssertExternallySynchronizedMutex before main
    return sMutex_;
}
#endif
<commit_msg>Comment about bug<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../Characters/ToString.h"
#include "../Execution/Thread.h"

#include "Sanitizer.h"
#include "Trace.h"

#include "AssertExternallySynchronizedMutex.h"

using namespace Stroika;
using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Debug;

#if qDebug
/*
 ********************************************************************************
 ****************** Debug::AssertExternallySynchronizedMutex ********************
 ********************************************************************************
 */
void AssertExternallySynchronizedMutex::lock_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        if (sharedContext->fLocks_++ == 0) {
            // If first time in, save thread-id
            sharedContext->fCurLockThread_ = this_thread::get_id ();
            if (not sharedContext->GetSharedLockEmpty_ ()) {
                // If first already shared locks - OK - so long as same thread
                Require (sharedContext->CountOfIInSharedLockThreads_ (sharedContext->fCurLockThread_) == sharedContext->GetSharedLockThreadsCount_ ());
            }
        }
        else {
            // If first already locked - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO modify (lock for write) an object which is already in use (debuglocked) in another thread (thisthread=%s)", Characters::ToString (this_thread::get_id ()).c_str ());
                DbgTrace ("Original thread holding lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ()); // if this is triggered, and sharedContext->fLocks_==1, see https://stroika.atlassian.net/browse/STK-956
        }
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_ () const noexcept
{
    SharedContext* sharedContext = _fSharedContext.get ();
    Require (sharedContext->fCurLockThread_ == this_thread::get_id ());
    Require (sharedContext->fLocks_ > 0); // else unbalanced
    --sharedContext->fLocks_;
    // Note at this point - it would make some sense to CLEAR fCurLockThread_, but that could be a race, cuz someone
    // else could lock just as we are unlocking...
}

void AssertExternallySynchronizedMutex::lock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        // OK to shared lock from various threads
        // But if already locked, NOT OK (would have blocked in real impl) - if you try to shared lock from another thread while locked
        if (sharedContext->fLocks_ != 0) {
            // If first already locks - OK - so long as same thread
            if (sharedContext->fCurLockThread_ != this_thread::get_id ()) {
                // Duplicate the  Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
                // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
                // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
                DbgTrace (L"ATTEMPT TO shared_lock (lock for READ) an object which is already in use (debuglocked for WRITE) in another thread");
                DbgTrace ("Original thread holding (write) lock: threadID=%s, and DbgTraceThreadName=%s", Execution::Thread::FormatThreadID_A (sharedContext->fCurLockThread_).c_str (), Debug::GetDbgTraceThreadName_A (sharedContext->fCurLockThread_).c_str ());
            }
            Require (sharedContext->fCurLockThread_ == this_thread::get_id ()); // if this assert fails, and fLocks_==1, see https://stroika.atlassian.net/browse/STK-956 (possible false positive)
        }
        sharedContext->AddSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

void AssertExternallySynchronizedMutex::unlock_shared_ () const noexcept
{
    try {
        SharedContext* sharedContext = _fSharedContext.get ();
        sharedContext->RemoveSharedLock_ (this_thread::get_id ());
    }
    catch (...) {
        AssertNotReached ();
    }
}

mutex& AssertExternallySynchronizedMutex::GetSharedLockMutexThreads_ ()
{
    static mutex sMutex_; // must be out-of-line so we can have just one mutex object. Could use static member, but then trouble using
                          // AssertExternallySynchronizedMutex before main
    return sMutex_;
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char* argv[]){
  if(argc < 1){
    return 1;
  }
  int pipe_fd = open(argv[1],O_WRONLY);
  if(pipe_fd == -1){
    return 1;
  }
  write(pipe_fd,"test",5);
  std::cout << "Hello Searcher" << std::endl;
}
<commit_msg>Reorder io writes.<commit_after>#include <iostream>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char* argv[]){
  if(argc < 1){
    return 1;
  }
  int pipe_fd = open(argv[1],O_WRONLY);
  if(pipe_fd == -1){
    return 1;
  }
  std::cout << "Hello Searcher" << std::endl;
  write(pipe_fd,"test",5);
}
<|endoftext|>


<commit_before>#include "memory.h"
#include "helpers.h"
#include <iostream>
#include <cstring>
#include <QDataStream>
#include <QFile>
#include <QCryptographicHash>
#include <QDebug>

namespace reverse_hash {
    Memory::Memory(){
        m_nInputSize = 55; // 55 bytes
        m_nOutputSize = 16; // 16 bytes of md5 hash
    }

    // ----------------------------------------------------------------

    void Memory::load(QString filename){
        m_vItems.clear();
        QFile file(filename);
        if (!file.exists()) {
            qDebug().noquote().nospace() << "RHMEMORY:  File did not exists: " << filename;
            return;
        }
        if ( !file.open(QIODevice::ReadOnly) ) {
            qDebug().noquote().nospace() << "RHMEMORY: Could not open file " << filename;
            return;
        }

        QDataStream stream( &file );
        char *pFileType = new char[9];
        std::memset(pFileType, 0, 9);
        int nReaded = stream.readRawData(pFileType, 8);
        if(nReaded > 0){
            if(QString(pFileType) != "RHMEMORY"){
                qDebug().noquote().nospace() << "RHMEMORY: File type did not match with RHMEMORY. " << filename;
                return;
            }
        }else{
            qDebug().noquote().nospace() << "RHMEMORY: Could not read file (1) " << filename;
            return;
        }

        stream >> m_nInputSize;
        stream >> m_nOutputSize;
        int nCount;
        stream >> nCount;
        for(int i = 0; i < nCount; i++){
            MemoryItem memoryItem;
            stream >> memoryItem.input;
            stream >> memoryItem.output;
            m_vItems.push_back(memoryItem);
        }
    };

    // ----------------------------------------------------------------

    void Memory::save(QString filename){
        QFile file(filename);
        if (file.exists()) {
            file.remove();
        }
        if ( !file.open(QIODevice::WriteOnly) ) {
            qDebug().noquote().nospace() << "Could not write file: " << filename;
            return;
        }
        QDataStream stream( &file );
        stream.writeRawData("RHMEMORY", 8);
        stream << m_nInputSize << m_nOutputSize << m_vItems.size();
        for (int i = 0; i < m_vItems.size(); i++) {
            // QByteArray input(m_vItems[i].input);
            /*while(input.size() < m_nInputSize){
                input.append(char(0x00));
            }*/
            // stream.writeRawData(input.data(), input.size());
            // stream.writeRawData(m_vItems[i].output.data(), m_vItems[i].output.size());
            stream << m_vItems[i].input << m_vItems[i].output;
        }
        file.close();
    };

    // ----------------------------------------------------------------

    int Memory::size(){
        return m_vItems.size();
    }

    // ----------------------------------------------------------------

    MemoryItem Memory::at(int i){
        return m_vItems[i];
    };

    // ----------------------------------------------------------------

    void Memory::printData(){
        qDebug().noquote().nospace() <<  " --- Reverse Hash Memory --- ";
        for (int i = 0; i < m_vItems.size(); i++) {
            qDebug().noquote().nospace() << m_vItems[i].input.toHex().toStdString() << " => " << m_vItems[i].output.toHex().toStdString() << "\n";
        }
    }

    // ----------------------------------------------------------------

    void Memory::generateData(int nCount){
        m_vItems.clear();
        for(int i = 0; i < nCount; i++){
            MemoryItem memoryItem;
            memoryItem.input.append(generateRandomString());
            memoryItem.output = QCryptographicHash::hash(memoryItem.input, QCryptographicHash::Md5);
            m_vItems.push_back(memoryItem);
        }
    };

    // ----------------------------------------------------------------

    QString Memory::alphabet() {
        return "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890[]{}:,.<>/?\"'\\*&^%$#!-+=";
    }

    // ----------------------------------------------------------------

    QString Memory::generateRandomString(){
        QString sAlphabet = alphabet();
        int len = qrand() % (m_nInputSize) + 2;
        QString str = "";
        for (int i = 0; i < len; i++) {
            str += sAlphabet[qrand() % sAlphabet.length()];
        }
        return str;
	}
}
<commit_msg>Fixed compile errors<commit_after>#include "memory.h"
#include "helpers.h"
#include <iostream>
#include <cstring>
#include <QDataStream>
#include <QFile>
#include <QCryptographicHash>
#include <QDebug>

namespace reverse_hash {
    Memory::Memory(){
        m_nInputSize = 55; // 55 bytes
        m_nOutputSize = 16; // 16 bytes of md5 hash
    }

    // ----------------------------------------------------------------

    void Memory::load(QString filename){
        m_vItems.clear();
        QFile file(filename);
        if (!file.exists()) {
            qDebug().noquote().nospace() << "RHMEMORY:  File did not exists: " << filename;
            return;
        }
        if ( !file.open(QIODevice::ReadOnly) ) {
            qDebug().noquote().nospace() << "RHMEMORY: Could not open file " << filename;
            return;
        }

        QDataStream stream( &file );
        char *pFileType = new char[9];
        std::memset(pFileType, 0, 9);
        int nReaded = stream.readRawData(pFileType, 8);
        if(nReaded > 0){
            if(QString(pFileType) != "RHMEMORY"){
                qDebug().noquote().nospace() << "RHMEMORY: File type did not match with RHMEMORY. " << filename;
                return;
            }
        }else{
            qDebug().noquote().nospace() << "RHMEMORY: Could not read file (1) " << filename;
            return;
        }

        stream >> m_nInputSize;
        stream >> m_nOutputSize;
        int nCount;
        stream >> nCount;
        for(int i = 0; i < nCount; i++){
            MemoryItem memoryItem;
            stream >> memoryItem.input;
            stream >> memoryItem.output;
            m_vItems.push_back(memoryItem);
        }
    };

    // ----------------------------------------------------------------

    void Memory::save(QString filename){
        QFile file(filename);
        if (file.exists()) {
            file.remove();
        }
        if ( !file.open(QIODevice::WriteOnly) ) {
            qDebug().noquote().nospace() << "Could not write file: " << filename;
            return;
        }
        QDataStream stream( &file );
        stream.writeRawData("RHMEMORY", 8);
        stream << m_nInputSize << m_nOutputSize << m_vItems.size();
        for (int i = 0; i < m_vItems.size(); i++) {
            // QByteArray input(m_vItems[i].input);
            /*while(input.size() < m_nInputSize){
                input.append(char(0x00));
            }*/
            // stream.writeRawData(input.data(), input.size());
            // stream.writeRawData(m_vItems[i].output.data(), m_vItems[i].output.size());
            stream << m_vItems[i].input << m_vItems[i].output;
        }
        file.close();
    };

    // ----------------------------------------------------------------

    int Memory::size(){
        return m_vItems.size();
    }

    // ----------------------------------------------------------------

    MemoryItem Memory::at(int i){
        return m_vItems[i];
    };

    // ----------------------------------------------------------------

    void Memory::printData(){
        qDebug().noquote().nospace() <<  " --- Reverse Hash Memory --- ";
        for (int i = 0; i < m_vItems.size(); i++) {
            qDebug().noquote().nospace() << m_vItems[i].input.toHex() << " => " << m_vItems[i].output.toHex();
        }
    }

    // ----------------------------------------------------------------

    void Memory::generateData(int nCount){
        m_vItems.clear();
        for(int i = 0; i < nCount; i++){
            MemoryItem memoryItem;
            memoryItem.input.append(generateRandomString());
            memoryItem.output = QCryptographicHash::hash(memoryItem.input, QCryptographicHash::Md5);
            m_vItems.push_back(memoryItem);
        }
    };

    // ----------------------------------------------------------------

    QString Memory::alphabet() {
        return "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890[]{}:,.<>/?\"'\\*&^%$#!-+=";
    }

    // ----------------------------------------------------------------

    QString Memory::generateRandomString(){
        QString sAlphabet = alphabet();
        int len = qrand() % (m_nInputSize) + 2;
        QString str = "";
        for (int i = 0; i < len; i++) {
            str += sAlphabet[qrand() % sAlphabet.length()];
        }
        return str;
	}
}
<|endoftext|>


<commit_before>#ifndef WEBSERVER_SERVER_HPP
#define WEBSERVER_SERVER_HPP

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/thread.hpp>
#include "connection.hpp"
#include "request_handler.hpp"

namespace webserver {

typedef boost::asio::ip::tcp::endpoint tcp_endpoint;

class Server {
public:
    Server(const std::string path,
           const std::string &port="8000",
           int thread_count=1)
            : thread_count_(thread_count)
            , acceptor_(io_service_)
            , connection_()
            , signals_(io_service_)
            , request_handler_(path)
            , port_(port) {
        setup_server();
    }

    void run() {
        io_service_.run();
    }

private:
    int thread_count_;
    std::vector<std::thread> thread_poll_;
    boost::asio::io_service io_service_;
    boost::asio::ip::tcp::acceptor acceptor_;
    connection_ptr connection_;
    boost::asio::signal_set signals_;
    request_handler request_handler_;
    std::string port_;

    void setup_server() {
        set_signals();
        tcp_endpoint endpoint = create_endpoint();
        open_acceptor(endpoint);
        start_connection();
    }

    tcp_endpoint create_endpoint() {
        boost::asio::ip::tcp::resolver resolver(io_service_);
        boost::asio::ip::tcp::resolver::query query("127.0.0.1", port_);
        tcp_endpoint endpoint = *resolver.resolve(query);
        return endpoint;
    }

    void open_acceptor(tcp_endpoint endpoint) {
        acceptor_.open(endpoint.protocol());
        acceptor_.bind(endpoint);
        acceptor_.listen();
    }

    void set_signals() {
        /* Set signals for process termination */
        signals_.add(SIGINT);
        signals_.add(SIGTERM);
        signals_.add(SIGQUIT);
        signals_.async_wait(boost::bind(&server::stop, this));
    }

    void start_connection() {
        connection_.reset(new Connection(io_service_, request_handler_));
        acceptor_.async_accept(
            connection_->socket(),
            boost::bind(&server::handle_connection, this,
                        boost::asio::placeholders::error)
        );
    }

    void handle_connection(boost::system::error_code& error_code) {
        if (!error_code) connection_->start();
        start_connection();
    }

    void stop() {
        io_service_.stop();
    }
};

} // namespace webserver

#endif //WEBSERVER_SERVER_HPP
<commit_msg>Add multithreading<commit_after>#ifndef WEBSERVER_SERVER_HPP
#define WEBSERVER_SERVER_HPP

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/thread.hpp>
#include "connection.hpp"
#include "request_handler.hpp"

namespace webserver {

typedef boost::asio::ip::tcp::endpoint tcp_endpoint;

class Server {
public:
    Server(const std::string path,
           const std::string &port="8000",
           int thread_count=1)
            : thread_count_(thread_count)
            , acceptor_(io_service_)
            , connection_()
            , signals_(io_service_)
            , request_handler_(path)
            , port_(port) {
        setup_server();
    }

    void run() {
        initialize_threads_pool();
        join_threads();
    }

private:
    int thread_count_;
    std::vector<boost::thread> thread_poll_;
    boost::asio::io_service io_service_;
    boost::asio::ip::tcp::acceptor acceptor_;
    connection_ptr connection_;
    boost::asio::signal_set signals_;
    request_handler request_handler_;
    std::string port_;

    void initialize_threads_pool() {
        for (std::size_t i = 0; i < thread_count_; ++i) {
            boost::thread thread(new boost::thread(
                  boost::bind(&boost::asio::io_service::run, &io_service_)));
            thread_poll_.push_back(thread);
        }
    }

    void join_threads() {
        // Wait until all threads complete execution
        for (std::size_t i = 0; i < thread_poll_.size(); ++i)
            thread_poll_[i]->join();
    }

    void setup_server() {
        set_signals();
        tcp_endpoint endpoint = create_endpoint();
        open_acceptor(endpoint);
        start_connection();
    }

    tcp_endpoint create_endpoint() {
        boost::asio::ip::tcp::resolver resolver(io_service_);
        boost::asio::ip::tcp::resolver::query query("127.0.0.1", port_);
        tcp_endpoint endpoint = *resolver.resolve(query);
        return endpoint;
    }

    void open_acceptor(tcp_endpoint endpoint) {
        acceptor_.open(endpoint.protocol());
        acceptor_.bind(endpoint);
        acceptor_.listen();
    }

    void set_signals() {
        /* Set signals for process termination */
        signals_.add(SIGINT);
        signals_.add(SIGTERM);
        signals_.add(SIGQUIT);
        signals_.async_wait(boost::bind(&server::stop, this));
    }

    void start_connection() {
        connection_.reset(new Connection(io_service_, request_handler_));
        acceptor_.async_accept(
            connection_->socket(),
            boost::bind(&server::handle_connection, this,
                        boost::asio::placeholders::error)
        );
    }

    void handle_connection(boost::system::error_code& error_code) {
        if (!error_code) connection_->start();
        start_connection();
    }

    void stop() {
        io_service_.stop();
    }
};

} // namespace webserver

#endif //WEBSERVER_SERVER_HPP
<|endoftext|>


<commit_before>/*
 * This file is part of SpeakEasy.
 * Copyright (C) 2012  Lambert Clara <lambert.clara@yahoo.fr>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file    SE_CRenderManager.cpp
 * @brief   3d Rendering Manager
 *
 * @author  Lambert Clara <lambert.clara@yahoo.fr>
 * @date    Created : 2012-07-01
 */

#include "SE_CRenderManager.h"

#include <GL/gl.h>
#include <GL/glu.h>

#include "SE_CLogManager.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SE_CRenderManager::startUp()
{
    SE_CLogManager::getInstance()->log(kInformation, "SE_CRenderManager successfully started");
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SE_CRenderManager::shutDown()
{
    SE_CLogManager::getInstance()->log(kInformation, "SE_CRenderManager successfully shut downed");
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SE_CRenderManager::render(const F32 inElapsedMs)
{
    static const U16 width  = 640;
    static const U16 height = 480;
    glViewport(0, 0, width, height);

    // Clear color buffer to white
    glClearColor(1.f, 1.f, 1.f, 0.f);
    glClear(GL_COLOR_BUFFER_BIT);

    glShadeModel(GL_SMOOTH); // GL_FLAT

    // Select and setup the projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(65.f, (F32)width/height, 1.f, 100.f);

    // Select and setup the modelview matrix
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    gluLookAt(0.f, 1.f, 0.f,    // Eye-position
              0.f, 20.f, 0.f,   // View-point
              0.f, 0.f, 1.f);   // Up-vector

    // Draw a rotating colorful triangle
    glTranslatef(0.f, 14.f, 0.f);
    glRotatef(0.3f * (GLfloat) 0.2f + (GLfloat) inElapsedMs * 0.1f, 0.f, 0.f, 1.f);

    glBegin(GL_TRIANGLES);
    {
        glColor3f(1.f, 0.f, 0.f);
        glVertex3f(-5.f, 0.f, -4.f);
        glColor3f(0.f, 1.f, 0.f);
        glVertex3f(5.f, 0.f, -4.f);
        glColor3f(0.f, 0.f, 1.f);
        glVertex3f(0.f, 0.f, 6.f);
    }
    glEnd();
}
<commit_msg>Use glfw3 header instead of including gl.h and glu.h<commit_after>/*
 * This file is part of SpeakEasy.
 * Copyright (C) 2012  Lambert Clara <lambert.clara@yahoo.fr>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file    SE_CRenderManager.cpp
 * @brief   3d Rendering Manager
 *
 * @author  Lambert Clara <lambert.clara@yahoo.fr>
 * @date    Created : 2012-07-01
 */

#include "SE_CRenderManager.h"

#include "config.h"

#ifdef USE_GLFW
#    define GLFW_INCLUDE_GLU
#    include <GL/glfw3.h>
#elif defined(USE_SFML2)
#    include <GL/gl.h>
#    include <GL/glu.h>
#endif // USE_GLFW USE_SFML2

#include "SE_CLogManager.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SE_CRenderManager::startUp()
{
    SE_CLogManager::getInstance()->log(kInformation, "SE_CRenderManager successfully started");
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SE_CRenderManager::shutDown()
{
    SE_CLogManager::getInstance()->log(kInformation, "SE_CRenderManager successfully shut downed");
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void SE_CRenderManager::render(const F32 inElapsedMs)
{
    static const U16 width  = 640;
    static const U16 height = 480;
    glViewport(0, 0, width, height);

    // Clear color buffer to white
    glClearColor(1.f, 1.f, 1.f, 0.f);
    glClear(GL_COLOR_BUFFER_BIT);

    glShadeModel(GL_SMOOTH); // GL_FLAT

    // Select and setup the projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(65.f, (F32)width/height, 1.f, 100.f);

    // Select and setup the modelview matrix
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    gluLookAt(0.f, 1.f, 0.f,    // Eye-position
              0.f, 20.f, 0.f,   // View-point
              0.f, 0.f, 1.f);   // Up-vector

    // Draw a rotating colorful triangle
    glTranslatef(0.f, 14.f, 0.f);
    glRotatef(0.3f * (GLfloat) 0.2f + (GLfloat) inElapsedMs * 0.1f, 0.f, 0.f, 1.f);

    glBegin(GL_TRIANGLES);
    {
        glColor3f(1.f, 0.f, 0.f);
        glVertex3f(-5.f, 0.f, -4.f);
        glColor3f(0.f, 1.f, 0.f);
        glVertex3f(5.f, 0.f, -4.f);
        glColor3f(0.f, 0.f, 1.f);
        glVertex3f(0.f, 0.f, 6.f);
    }
    glEnd();
}
<|endoftext|>


<commit_before>//
//  nifti_hdr.cpp
//  NiftiImage
//
//  Created by Tobias Wood on 08/07/2013.
//  Copyright (c) 2013 Tobias Wood. All rights reserved.
//

#include <memory>
#include <vector>
#include <iostream>
#include <getopt.h>

#include "Nifti/Nifti.h"

using namespace std;

const string usage = "nifti_hdr - A utility for getting information from Nifti headers.\n\
\n\
Usage: nifti_hdr [options] file1 [other files]\n\
By default the abbreviated header will be printed for each file.\n\
Abbreviated, full and compare modes are mutually exclusive.\n\
\n\
Options:\n\
	-d, --dims :  Print the size of each dimension for each file.\n\
	-v, --vox :   Print the voxel sizes for each file (with units). \n\
	-t, --trans : Print the XForm to physical space with precedence.\n\
	-a, --abbrev: Print the abbreviated header.\n\
	-f, --full:   Print the entire header.\n\
	-c, --comp:   Compare first file to all others and print message if the.\n\
	              physical spaces are different.\n\
	-h, --help:   Print this message and quit.\n\
";

enum Modes {
	Nothing = 0,
	Abbreviated,
	Full,
	Compare
};

static int mode = Nothing;
static int printDims = false, printVoxdims = false, printSize = false, printData = false,
           printTransform = false, printExtensions = false;

static struct option long_options[] =
{
	{"dims",   no_argument, &printDims, true},
	{"vox",    no_argument, &printVoxdims, true},
	{"form",   no_argument, &printTransform, true},
	{"size",   no_argument, &printSize, true},
	{"data",   no_argument, &printData, true},
	{"abbrev", no_argument, &mode, Abbreviated},
	{"full",   no_argument, &mode, Full},
	{"comp",   no_argument, &mode, Compare},
	{"help",   no_argument, 0, 'h'},
	{"ext",    no_argument, 0, 'e'},
	{0, 0, 0, 0}
};

string voxMessage(const Nifti &im) {
	stringstream m;
	m << "Voxel sizes: " << im.voxDims().transpose() << " " << im.spaceUnits();
	if (im.voxDims().rows() > 3) {
		m << "/" << im.timeUnits();
	}
	return m.str();
}

string sizeMessage(const Nifti &im) {
	stringstream m;
	m << "Voxels per slice, per volume, total: "
      << im.dims().head(2).prod() << ", " << im.dims().head(3).prod() << ", " << im.dims().prod();
	return m.str();
}

string dataMessage(const Nifti &im) {
	stringstream m;
	m << "Datatype: " << Nifti::TypeInfo(im.datatype()).name << ", size in bytes: " << Nifti::TypeInfo(im.datatype()).size;
	return m.str();
}

int main(int argc, char **argv) {
	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, "dvtafchse", long_options, &indexptr)) != -1) {
		switch (c) {
			case 'd': printDims = true; break;
			case 'v': printVoxdims = true; break;
			case 't': printTransform = true; break;
			case 's': printSize = true; break;
			case 'e': printExtensions = true; break;
			case 'a': mode = Abbreviated; break;
			case 'f': mode = Full; break;
			case 'c': mode = Compare; break;
			case '?': // getopt will print an error message
			case 'h':
				cout << usage << endl;
				return EXIT_FAILURE;
		}
	}
	if ((argc - optind) <= 0 ) {
		cerr << "No input image file specified." << endl;
		exit(EXIT_FAILURE);
	}
	if (optind == 1) { // No options specified, default is short header
		mode = Abbreviated;
	}
	vector<Nifti> images;
	try {
		images.reserve(argc - optind); // emplace_back can still trigger copies if the vector has to be resized
		for (;optind < argc; optind++) {
			images.emplace_back(argv[optind], Nifti::Mode::Read);
		}
	} catch (exception &e) {
		cerr << e.what() << endl;
	}

	if (mode == Compare) { // Compare first image to all others and check headers are compatible
		for (auto im = images.begin() + 1; im != images.end(); im++) {
			if (!images[0].matchesSpace(*im)) {
				cout << "Header does not match against file: " << im->imagePath() << endl;
			}
		}
	}

	for (auto& im: images) {
		if (printDims) cout << im.dims().transpose() << endl;
		if (printVoxdims) cout << voxMessage(im) << endl;
		if (printTransform) cout << im.transform().matrix() << endl;
		if (printSize) cout << sizeMessage(im) << endl;
		if (printData) cout << dataMessage(im) << endl;

		if (mode == Abbreviated) {
			cout << "Short Nifti Header for file: " << im.imagePath() << endl;
			cout << "Dimensions:  " << im.dims().transpose() << endl;
			cout << voxMessage(im) << endl;
			cout << "XForm matrix: " << endl << im.transform().matrix() << endl;
			cout << "Number of extensions: " << im.extensions().size() << endl;
		} else if (mode == Full) {
			cout << "Full Nifti Header for file: " << im.imagePath() << endl;
			cout << dataMessage(im) << endl;
			cout << "Dimensions: " << im.dims().transpose() << endl;
			cout << voxMessage(im) << endl;

			cout << "Calibration (min, max): " << im.calibration_min << ", " << im.calibration_max << endl;
			cout << "Scaling (slope, inter): " << im.scaling_slope << ", " << im.scaling_inter << endl;
			cout << "Dimension labels (Phase, Freq, Slice):   " << im.phase_dim << ", " << im.freq_dim << ", " << im.slice_dim << endl;
			cout << "Slice info (Code, Start, End, Duration): " << ", " << im.slice_code << ", " << im.slice_start << ", " << im.slice_end << ", " << im.slice_duration << endl;
			cout << "Slice name: " << im.sliceName() << endl;
			cout << "Time offset: " << im.toffset << endl;

			cout << "Intent name:   " << im.intent_name << endl;
			cout << "Intent code:   " << im.intentName() << endl;
			cout << "Intent params: " << im.intent_p1 << ", " << im.intent_p2 << ", " << im.intent_p3 << endl;
			cout << "Description: " << im.description << endl;
			cout << "Aux File:    " << im.aux_file << endl;
			cout << "QForm: " << Nifti::XFormName(im.qcode()) << endl;
			cout << im.qform().matrix() << endl;
			cout << "SForm: " << Nifti::XFormName(im.scode()) << endl;
			cout << im.sform().matrix() << endl;
			cout << "Number of extensions: " << im.extensions().size() << endl;
		}
	}

	return EXIT_SUCCESS;
}

<commit_msg>Removed the print extensions option.<commit_after>//
//  nifti_hdr.cpp
//  NiftiImage
//
//  Created by Tobias Wood on 08/07/2013.
//  Copyright (c) 2013 Tobias Wood. All rights reserved.
//

#include <memory>
#include <vector>
#include <iostream>
#include <getopt.h>

#include "Nifti/Nifti.h"

using namespace std;

const string usage = "nifti_hdr - A utility for getting information from Nifti headers.\n\
\n\
Usage: nifti_hdr [options] file1 [other files]\n\
By default the abbreviated header will be printed for each file.\n\
Abbreviated, full and compare modes are mutually exclusive.\n\
\n\
Options:\n\
	-d, --dims :  Print the size of each dimension for each file.\n\
	-v, --vox :   Print the voxel sizes for each file (with units). \n\
	-t, --trans : Print the XForm to physical space with precedence.\n\
	-a, --abbrev: Print the abbreviated header.\n\
	-f, --full:   Print the entire header.\n\
	-c, --comp:   Compare first file to all others and print message if the.\n\
	              physical spaces are different.\n\
	-h, --help:   Print this message and quit.\n\
";

enum Modes {
	Nothing = 0,
	Abbreviated,
	Full,
	Compare
};

static int mode = Nothing;
static int printDims = false, printVoxdims = false, printSize = false, printData = false,
           printTransform = false;

static struct option long_options[] =
{
	{"dims",   no_argument, &printDims, true},
	{"vox",    no_argument, &printVoxdims, true},
	{"form",   no_argument, &printTransform, true},
	{"size",   no_argument, &printSize, true},
	{"data",   no_argument, &printData, true},
	{"abbrev", no_argument, &mode, Abbreviated},
	{"full",   no_argument, &mode, Full},
	{"comp",   no_argument, &mode, Compare},
	{"help",   no_argument, 0, 'h'}
	{0, 0, 0, 0}
};

string voxMessage(const Nifti &im) {
	stringstream m;
	m << "Voxel sizes: " << im.voxDims().transpose() << " " << im.spaceUnits();
	if (im.voxDims().rows() > 3) {
		m << "/" << im.timeUnits();
	}
	return m.str();
}

string sizeMessage(const Nifti &im) {
	stringstream m;
	m << "Voxels per slice, per volume, total: "
      << im.dims().head(2).prod() << ", " << im.dims().head(3).prod() << ", " << im.dims().prod();
	return m.str();
}

string dataMessage(const Nifti &im) {
	stringstream m;
	m << "Datatype: " << Nifti::TypeInfo(im.datatype()).name << ", size in bytes: " << Nifti::TypeInfo(im.datatype()).size;
	return m.str();
}

int main(int argc, char **argv) {
	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, "dvtafchse", long_options, &indexptr)) != -1) {
		switch (c) {
			case 'd': printDims = true; break;
			case 'v': printVoxdims = true; break;
			case 't': printTransform = true; break;
			case 's': printSize = true; break;
			case 'a': mode = Abbreviated; break;
			case 'f': mode = Full; break;
			case 'c': mode = Compare; break;
			case '?': // getopt will print an error message
			case 'h':
				cout << usage << endl;
				return EXIT_FAILURE;
		}
	}
	if ((argc - optind) <= 0 ) {
		cerr << "No input image file specified." << endl;
		exit(EXIT_FAILURE);
	}
	if (optind == 1) { // No options specified, default is short header
		mode = Abbreviated;
	}
	vector<Nifti> images;
	try {
		images.reserve(argc - optind); // emplace_back can still trigger copies if the vector has to be resized
		for (;optind < argc; optind++) {
			images.emplace_back(argv[optind], Nifti::Mode::Read);
		}
	} catch (exception &e) {
		cerr << e.what() << endl;
	}

	if (mode == Compare) { // Compare first image to all others and check headers are compatible
		for (auto im = images.begin() + 1; im != images.end(); im++) {
			if (!images[0].matchesSpace(*im)) {
				cout << "Header does not match against file: " << im->imagePath() << endl;
			}
		}
	}

	for (auto& im: images) {
		if (printDims) cout << im.dims().transpose() << endl;
		if (printVoxdims) cout << voxMessage(im) << endl;
		if (printTransform) cout << im.transform().matrix() << endl;
		if (printSize) cout << sizeMessage(im) << endl;
		if (printData) cout << dataMessage(im) << endl;

		if (mode == Abbreviated) {
			cout << "Short Nifti Header for file: " << im.imagePath() << endl;
			cout << "Dimensions:  " << im.dims().transpose() << endl;
			cout << voxMessage(im) << endl;
			cout << "XForm matrix: " << endl << im.transform().matrix() << endl;
			cout << "Number of extensions: " << (im.extensions().size() > 0 << endl;
		} else if (mode == Full) {
			cout << "Full Nifti Header for file: " << im.imagePath() << endl;
			cout << dataMessage(im) << endl;
			cout << "Dimensions: " << im.dims().transpose() << endl;
			cout << voxMessage(im) << endl;

			cout << "Calibration (min, max): " << im.calibration_min << ", " << im.calibration_max << endl;
			cout << "Scaling (slope, inter): " << im.scaling_slope << ", " << im.scaling_inter << endl;
			cout << "Dimension labels (Phase, Freq, Slice):   " << im.phase_dim << ", " << im.freq_dim << ", " << im.slice_dim << endl;
			cout << "Slice info (Code, Start, End, Duration): " << ", " << im.slice_code << ", " << im.slice_start << ", " << im.slice_end << ", " << im.slice_duration << endl;
			cout << "Slice name: " << im.sliceName() << endl;
			cout << "Time offset: " << im.toffset << endl;

			cout << "Intent name:   " << im.intent_name << endl;
			cout << "Intent code:   " << im.intentName() << endl;
			cout << "Intent params: " << im.intent_p1 << ", " << im.intent_p2 << ", " << im.intent_p3 << endl;
			cout << "Description: " << im.description << endl;
			cout << "Aux File:    " << im.aux_file << endl;
			cout << "QForm: " << Nifti::XFormName(im.qcode()) << endl;
			cout << im.qform().matrix() << endl;
			cout << "SForm: " << Nifti::XFormName(im.scode()) << endl;
			cout << im.sform().matrix() << endl;
			cout << "Number of extensions: " << im.extensions().size() << endl;
		}
	}

	return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 * Send notifications from a worker thread to the main thread.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "notify.hxx"
#include "gerrno.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"

#include <inline/compiler.h>

#include <atomic>

#include <unistd.h>
#include <sys/eventfd.h>

class Notify {
public:
    notify_callback_t callback;
    void *callback_ctx;

    int fd;

    Event event;

    std::atomic_bool pending;

    Notify()
        :pending(false) {}

    void EventFdCallback();
};

inline void
Notify::EventFdCallback()
{
    uint64_t value;
    (void)read(fd, &value, sizeof(value));

    if (pending.exchange(false))
        callback(callback_ctx);
}

Notify *
notify_new(notify_callback_t callback, void *ctx, GError **error_r)
{
    auto notify = new Notify();

    notify->callback = callback;
    notify->callback_ctx = ctx;

    notify->fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC);
    if (notify->fd < 0) {
        set_error_errno_msg(error_r, "eventfd() failed");
        return nullptr;
    }

    notify->event.Set(notify->fd, EV_READ|EV_PERSIST,
                      MakeSimpleEventCallback(Notify, EventFdCallback),
                      notify);
    notify->event.Add();

    return notify;
}

void
notify_free(Notify *notify)
{
    notify->event.Delete();
    close(notify->fd);

    delete notify;
}

void
notify_signal(Notify *notify)
{
    if (!notify->pending.exchange(true)) {
        static constexpr uint64_t value = 1;
        (void)write(notify->fd, &value, sizeof(value));
    }
}

void
notify_enable(Notify *notify)
{
    notify->event.Add();
}

void
notify_disable(Notify *notify)
{
    notify->event.Delete();
}
<commit_msg>notify: add constructor<commit_after>/*
 * Send notifications from a worker thread to the main thread.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "notify.hxx"
#include "gerrno.h"
#include "event/Event.hxx"
#include "event/Callback.hxx"

#include <inline/compiler.h>

#include <atomic>

#include <unistd.h>
#include <sys/eventfd.h>

class Notify {
public:
    const notify_callback_t callback;
    void *const callback_ctx;

    const int fd;

    Event event;

    std::atomic_bool pending;

    Notify(int _fd, notify_callback_t _callback, void *_ctx)
        :callback(_callback), callback_ctx(_ctx),
         fd(_fd),
         event(fd, EV_READ|EV_PERSIST,
               MakeSimpleEventCallback(Notify, EventFdCallback),
               this),
         pending(false) {
        event.Add();
    }

    ~Notify() {
        event.Delete();
        close(fd);
    }

    void EventFdCallback();
};

inline void
Notify::EventFdCallback()
{
    uint64_t value;
    (void)read(fd, &value, sizeof(value));

    if (pending.exchange(false))
        callback(callback_ctx);
}

Notify *
notify_new(notify_callback_t callback, void *ctx, GError **error_r)
{
    int fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC);
    if (fd < 0) {
        set_error_errno_msg(error_r, "eventfd() failed");
        return nullptr;
    }

    return new Notify(fd, callback, ctx);
}

void
notify_free(Notify *notify)
{
    delete notify;
}

void
notify_signal(Notify *notify)
{
    if (!notify->pending.exchange(true)) {
        static constexpr uint64_t value = 1;
        (void)write(notify->fd, &value, sizeof(value));
    }
}

void
notify_enable(Notify *notify)
{
    notify->event.Add();
}

void
notify_disable(Notify *notify)
{
    notify->event.Delete();
}
<|endoftext|>


<commit_before>//
// Created by monty on 23/11/15.
//

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

#include <string>
#include "GLES2Lesson.h"
#include "NdkGlue.h"

//Counter Clockwise
const float GLES2Lesson::cubeVertices[]{
//    4________5
//    /|       /|
//   / |      / |
// 0/__|___1_/  |
//  | 7|____|___|6
//  |  /    |  /
//  | /     | /
// 3|/______|/2
//x, y, z, r, g, b
        -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
        1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
        1.0f,  -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,
        1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,

};

const unsigned short GLES2Lesson::cubeIndices[] {
  0, 1, 2,
  0, 2, 3,

  5, 4, 7,
  5, 7, 6,

  1, 5, 6,
  1, 6, 2,

  4, 0, 7,
  0, 3, 7,

  4, 5, 1,
  4, 1, 0,

  6, 7, 2,
  2, 7, 3

};

extern void printGLString(const char *name, GLenum s) {
    const char *v = (const char *) glGetString(s);
    LOGI("GL %s = %s\n", name, v);
}

extern void checkGlError(const char *op) {
    for (GLint error = glGetError(); error; error = glGetError()) {
        LOGI("after %s() glError (0x%x)\n", op, error);
    }
}

GLuint GLES2Lesson::loadShader(GLenum shaderType, const char *pSource) {
    GLuint shader = glCreateShader(shaderType);
    if (shader) {
        glShaderSource(shader, 1, &pSource, NULL);
        glCompileShader(shader);
        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char *buf = (char *) malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    LOGE("Could not compile shader %d:\n%s\n", shaderType, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

GLuint GLES2Lesson::createProgram(const char *pVertexSource, const char *pFragmentSource) {
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    if (!vertexShader) {
        return 0;
    }

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader) {
        return 0;
    }

    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertexShader);
        checkGlError("glAttachShader");
        glAttachShader(program, pixelShader);
        checkGlError("glAttachShader");
        glLinkProgram(program);
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char *buf = (char *) malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}

void GLES2Lesson::printVerboseDriverInformation() {
    printGLString("Version", GL_VERSION);
    printGLString("Vendor", GL_VENDOR);
    printGLString("Renderer", GL_RENDERER);
    printGLString("Extensions", GL_EXTENSIONS);
}

GLES2Lesson::GLES2Lesson() {
//start off as identity - late we will init it with proper values.
    cubeTransformMatrix = glm::mat4( 1.0f );
    projectionMatrix = glm::mat4( 1.0f );

    vertexAttributePosition = 0;
    colourAttributePosition = 0;
    modelMatrixAttributePosition = 0;
    projectionMatrixAttributePosition = 0;
    gProgram = 0;
    cubeRotationAngle = 0.0f;
}

GLES2Lesson::~GLES2Lesson() {
    deleteVBOs();
}

bool GLES2Lesson::init(float w, float h, const std::string &vertexShader,
                       const std::string &fragmentShader) {

    printVerboseDriverInformation();

    gProgram = createProgram(vertexShader.c_str(), fragmentShader.c_str());

    if (!gProgram) {
        LOGE("Could not create program.");
        return false;
    }

    fetchShaderLocations();

    glViewport(0, 0, w, h);
    checkGlError("glViewport");

    projectionMatrix = glm::perspective(45.0f, w / h, 0.1f, 100.0f );

    createVBOs();
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LEQUAL );
    glFrontFace( GL_CW );
    glDepthMask( true );
    return true;
}

void GLES2Lesson::resetTransformMatrices() {
    //glTranslatef( -1.5f, 0.0f, -6.0f);
    //glTranslatef(3.0f, 0.0f, 0.0f );
    //= glTranslate( 1.5f, 0.0, -6.0f );
    cubeTransformMatrix = glm::rotate( glm::translate( glm::mat4( 1.0f ), glm::vec3( 1.5f, 0.0f, -6.0f ) ), cubeRotationAngle, glm::vec3( 1.0f, 0.0f, 0.0f ) );
}

void GLES2Lesson::fetchShaderLocations() {

    vertexAttributePosition = glGetAttribLocation( gProgram, "aPosition");
    colourAttributePosition = glGetAttribLocation( gProgram, "aColour");
    modelMatrixAttributePosition = glGetUniformLocation( gProgram, "uModel");
    projectionMatrixAttributePosition = glGetUniformLocation( gProgram, "uProjection");
}

void GLES2Lesson::drawGeometry( const int vertexVbo, const int indexVbo, int vertexCount, const glm::mat4& transform ) {

    glBindBuffer( GL_ARRAY_BUFFER, vertexVbo );

    glEnableVertexAttribArray(vertexAttributePosition);
    glEnableVertexAttribArray(colourAttributePosition);

    glUniformMatrix4fv(modelMatrixAttributePosition, 1, false, &transform[ 0 ][ 0 ]);
    glVertexAttribPointer(vertexAttributePosition, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, 0 );
    glVertexAttribPointer(colourAttributePosition, 3, GL_FLOAT, GL_TRUE, sizeof( float ) * 6, (void*)(sizeof(float ) * 3) );

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexVbo );
    glDrawElements( GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, 0 );

    glDisableVertexAttribArray(vertexAttributePosition);
    glDisableVertexAttribArray(colourAttributePosition);

    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

void GLES2Lesson::deleteVBOs() {
    glDeleteBuffers( 1, &vboCubeVertexDataIndex );
    glDeleteBuffers( 1, &vboCubeVertexIndicesIndex );
}

void GLES2Lesson::createVBOs() {
    glGenBuffers( 1, &vboCubeVertexDataIndex );
    glBindBuffer( GL_ARRAY_BUFFER, vboCubeVertexDataIndex );
    glBufferData( GL_ARRAY_BUFFER, 8 * sizeof( float ) * 6, cubeVertices, GL_STATIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

    glGenBuffers( 1, &vboCubeVertexIndicesIndex );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboCubeVertexIndicesIndex );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof( GLushort ), cubeIndices, GL_STATIC_DRAW );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

void GLES2Lesson::clearBuffers() {
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClearDepthf( 1.0f );
    checkGlError("glClearColor");
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError("glClear");
}

void GLES2Lesson::setPerspective() {
    glUniformMatrix4fv(projectionMatrixAttributePosition, 1, false, &projectionMatrix[ 0 ][ 0 ]);
}

void GLES2Lesson::prepareShaderProgram() {
    glUseProgram(gProgram);
    checkGlError("glUseProgram");
}

void GLES2Lesson::render() {

    clearBuffers();
    prepareShaderProgram();
    setPerspective();
    resetTransformMatrices();

    drawGeometry( vboCubeVertexDataIndex,
                  vboCubeVertexIndicesIndex,
                  36,
                  cubeTransformMatrix
    );
}

void GLES2Lesson::tick() {
    cubeRotationAngle += 1.0f;
}

void GLES2Lesson::shutdown() {
    LOGI("Shutdown!\n");
}<commit_msg>Center cube<commit_after>//
// Created by monty on 23/11/15.
//

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

#include <string>
#include "GLES2Lesson.h"
#include "NdkGlue.h"

//Counter Clockwise
const float GLES2Lesson::cubeVertices[]{
//    4________5
//    /|       /|
//   / |      / |
// 0/__|___1_/  |
//  | 7|____|___|6
//  |  /    |  /
//  | /     | /
// 3|/______|/2
//x, y, z, r, g, b
        -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
        1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
        1.0f,  -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
        -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,
        1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
        -1.0f, -1.0f, -1.0f, 0.5f, 0.5f, 0.5f,

};

const unsigned short GLES2Lesson::cubeIndices[] {
  0, 1, 2,
  0, 2, 3,

  5, 4, 7,
  5, 7, 6,

  1, 5, 6,
  1, 6, 2,

  4, 0, 7,
  0, 3, 7,

  4, 5, 1,
  4, 1, 0,

  6, 7, 2,
  2, 7, 3

};

extern void printGLString(const char *name, GLenum s) {
    const char *v = (const char *) glGetString(s);
    LOGI("GL %s = %s\n", name, v);
}

extern void checkGlError(const char *op) {
    for (GLint error = glGetError(); error; error = glGetError()) {
        LOGI("after %s() glError (0x%x)\n", op, error);
    }
}

GLuint GLES2Lesson::loadShader(GLenum shaderType, const char *pSource) {
    GLuint shader = glCreateShader(shaderType);
    if (shader) {
        glShaderSource(shader, 1, &pSource, NULL);
        glCompileShader(shader);
        GLint compiled = 0;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint infoLen = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
            if (infoLen) {
                char *buf = (char *) malloc(infoLen);
                if (buf) {
                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
                    LOGE("Could not compile shader %d:\n%s\n", shaderType, buf);
                    free(buf);
                }
                glDeleteShader(shader);
                shader = 0;
            }
        }
    }
    return shader;
}

GLuint GLES2Lesson::createProgram(const char *pVertexSource, const char *pFragmentSource) {
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    if (!vertexShader) {
        return 0;
    }

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader) {
        return 0;
    }

    GLuint program = glCreateProgram();
    if (program) {
        glAttachShader(program, vertexShader);
        checkGlError("glAttachShader");
        glAttachShader(program, pixelShader);
        checkGlError("glAttachShader");
        glLinkProgram(program);
        GLint linkStatus = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
        if (linkStatus != GL_TRUE) {
            GLint bufLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
            if (bufLength) {
                char *buf = (char *) malloc(bufLength);
                if (buf) {
                    glGetProgramInfoLog(program, bufLength, NULL, buf);
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            glDeleteProgram(program);
            program = 0;
        }
    }
    return program;
}

void GLES2Lesson::printVerboseDriverInformation() {
    printGLString("Version", GL_VERSION);
    printGLString("Vendor", GL_VENDOR);
    printGLString("Renderer", GL_RENDERER);
    printGLString("Extensions", GL_EXTENSIONS);
}

GLES2Lesson::GLES2Lesson() {
//start off as identity - late we will init it with proper values.
    cubeTransformMatrix = glm::mat4( 1.0f );
    projectionMatrix = glm::mat4( 1.0f );

    vertexAttributePosition = 0;
    colourAttributePosition = 0;
    modelMatrixAttributePosition = 0;
    projectionMatrixAttributePosition = 0;
    gProgram = 0;
    cubeRotationAngle = 0.0f;
}

GLES2Lesson::~GLES2Lesson() {
    deleteVBOs();
}

bool GLES2Lesson::init(float w, float h, const std::string &vertexShader,
                       const std::string &fragmentShader) {

    printVerboseDriverInformation();

    gProgram = createProgram(vertexShader.c_str(), fragmentShader.c_str());

    if (!gProgram) {
        LOGE("Could not create program.");
        return false;
    }

    fetchShaderLocations();

    glViewport(0, 0, w, h);
    checkGlError("glViewport");

    projectionMatrix = glm::perspective(45.0f, w / h, 0.1f, 100.0f );

    createVBOs();
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LEQUAL );
    glFrontFace( GL_CW );
    glDepthMask( true );
    return true;
}

void GLES2Lesson::resetTransformMatrices() {
    cubeTransformMatrix = glm::rotate( glm::translate( glm::mat4( 1.0f ), glm::vec3( 0.0f, 0.0f, -6.0f ) ), cubeRotationAngle, glm::vec3( 1.0f, 0.0f, 0.0f ) );
}

void GLES2Lesson::fetchShaderLocations() {

    vertexAttributePosition = glGetAttribLocation( gProgram, "aPosition");
    colourAttributePosition = glGetAttribLocation( gProgram, "aColour");
    modelMatrixAttributePosition = glGetUniformLocation( gProgram, "uModel");
    projectionMatrixAttributePosition = glGetUniformLocation( gProgram, "uProjection");
}

void GLES2Lesson::drawGeometry( const int vertexVbo, const int indexVbo, int vertexCount, const glm::mat4& transform ) {

    glBindBuffer( GL_ARRAY_BUFFER, vertexVbo );

    glEnableVertexAttribArray(vertexAttributePosition);
    glEnableVertexAttribArray(colourAttributePosition);

    glUniformMatrix4fv(modelMatrixAttributePosition, 1, false, &transform[ 0 ][ 0 ]);
    glVertexAttribPointer(vertexAttributePosition, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, 0 );
    glVertexAttribPointer(colourAttributePosition, 3, GL_FLOAT, GL_TRUE, sizeof( float ) * 6, (void*)(sizeof(float ) * 3) );

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, indexVbo );
    glDrawElements( GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, 0 );

    glDisableVertexAttribArray(vertexAttributePosition);
    glDisableVertexAttribArray(colourAttributePosition);

    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

void GLES2Lesson::deleteVBOs() {
    glDeleteBuffers( 1, &vboCubeVertexDataIndex );
    glDeleteBuffers( 1, &vboCubeVertexIndicesIndex );
}

void GLES2Lesson::createVBOs() {
    glGenBuffers( 1, &vboCubeVertexDataIndex );
    glBindBuffer( GL_ARRAY_BUFFER, vboCubeVertexDataIndex );
    glBufferData( GL_ARRAY_BUFFER, 8 * sizeof( float ) * 6, cubeVertices, GL_STATIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

    glGenBuffers( 1, &vboCubeVertexIndicesIndex );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboCubeVertexIndicesIndex );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof( GLushort ), cubeIndices, GL_STATIC_DRAW );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

void GLES2Lesson::clearBuffers() {
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClearDepthf( 1.0f );
    checkGlError("glClearColor");
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError("glClear");
}

void GLES2Lesson::setPerspective() {
    glUniformMatrix4fv(projectionMatrixAttributePosition, 1, false, &projectionMatrix[ 0 ][ 0 ]);
}

void GLES2Lesson::prepareShaderProgram() {
    glUseProgram(gProgram);
    checkGlError("glUseProgram");
}

void GLES2Lesson::render() {

    clearBuffers();
    prepareShaderProgram();
    setPerspective();
    resetTransformMatrices();

    drawGeometry( vboCubeVertexDataIndex,
                  vboCubeVertexIndicesIndex,
                  36,
                  cubeTransformMatrix
    );
}

void GLES2Lesson::tick() {
    cubeRotationAngle += 1.0f;
}

void GLES2Lesson::shutdown() {
    LOGI("Shutdown!\n");
}<|endoftext|>