<commit_before>#ifndef VIEW_HPP
#define VIEW_HPP

#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif

#include <GL/gl3w.h>
#include <GLFW/glfw3.h>

#include "util.hpp"
#include "view/shade.hpp"
#include "view/pane.hpp"

namespace View {
	/// Loops over the queued GL errors and prints each (using GLU).
	void printErrors(const char *prefix);

	/// A view structure (state and implementation)
	struct view : public virtual Util::task {
		typedef enum {
			e_id_prog=0, e_id_va,
			e_id_vbuf,   e_id_vnbuf, e_id_fbuf,
			e_id_model,  e_id_view,  e_id_proj,
			e_id_total
		} e_id_index;
		GLuint ids[e_id_total];
		float near = 1, far = 10, fov = 25;
		int nTriangles;
		GLFWwindow *win;
		int frame = 0, fps = 0;
		float phi, theta;

		/// Sets stable shader values (uniforms)
		void setUniforms(void);

		/** Polls for updates; move to control?
 		 * @param alive Shared state; false signals shutdown
 		 */
		void poll(std::atomic_bool &alive) override;

		/*! Calculates and displays the next frame, potentially incorporating
 		 * the frame index (discrete time) and FPS
		 */
		void redraw();

		/** Begins the game loop with the specified callbacks
		 * @param alive Shared status flag; false signals shutdown
		 */
		void run(std::atomic_bool &alive) override;

		/** Initializes any resources not initialized in the constructor
 		 * @param alive Shared status flag; false signals shutdown
 		 */
		void init(std::atomic_bool &alive) override;

		/** Constructor for a view object
 		 * @param alive Shared status flag; false signals shutdown
		 * @param vert Path to a GLSL vertex shader
		 * @param frag Path to a GLSL fragment shader
		 */
		view(std::atomic_bool &alive, const char *vert, const char *frag);

		/// Destructor for a view object
		virtual ~view(void);
	};
}

#endif
<commit_msg>Added definition to inhibit GLFW from importing GL<commit_after>#ifndef VIEW_HPP
#define VIEW_HPP

#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif

#include <GL/gl3w.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include "util.hpp"
#include "view/shade.hpp"
#include "view/pane.hpp"

namespace View {
	/// Loops over the queued GL errors and prints each (using GLU).
	void printErrors(const char *prefix);

	/// A view structure (state and implementation)
	struct view : public virtual Util::task {
		typedef enum {
			e_id_prog=0, e_id_va,
			e_id_vbuf,   e_id_vnbuf, e_id_fbuf,
			e_id_model,  e_id_view,  e_id_proj,
			e_id_total
		} e_id_index;
		GLuint ids[e_id_total];
		float near = 1, far = 10, fov = 25;
		int nTriangles;
		GLFWwindow *win;
		int frame = 0, fps = 0;
		float phi, theta;

		/// Sets stable shader values (uniforms)
		void setUniforms(void);

		/** Polls for updates; move to control?
 		 * @param alive Shared state; false signals shutdown
 		 */
		void poll(std::atomic_bool &alive) override;

		/*! Calculates and displays the next frame, potentially incorporating
 		 * the frame index (discrete time) and FPS
		 */
		void redraw();

		/** Begins the game loop with the specified callbacks
		 * @param alive Shared status flag; false signals shutdown
		 */
		void run(std::atomic_bool &alive) override;

		/** Initializes any resources not initialized in the constructor
 		 * @param alive Shared status flag; false signals shutdown
 		 */
		void init(std::atomic_bool &alive) override;

		/** Constructor for a view object
 		 * @param alive Shared status flag; false signals shutdown
		 * @param vert Path to a GLSL vertex shader
		 * @param frag Path to a GLSL fragment shader
		 */
		view(std::atomic_bool &alive, const char *vert, const char *frag);

		/// Destructor for a view object
		virtual ~view(void);
	};
}

#endif
<|endoftext|>


<commit_before>//===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the "backend" phase of LTO, i.e. it performs
// optimization and code generation on a loaded module. It is generally used
// internally by the LTO class but can also be used independently, for example
// to implement a standalone ThinLTO backend.
//
//===----------------------------------------------------------------------===//

#include "llvm/LTO/LTOBackend.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/LTO/LTO.h"
#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#include "llvm/Transforms/Utils/SplitModule.h"

using namespace llvm;
using namespace lto;

LLVM_ATTRIBUTE_NORETURN void reportOpenError(StringRef Path, Twine Msg) {
  errs() << "failed to open " << Path << ": " << Msg << '\n';
  errs().flush();
  exit(1);
}

Error Config::addSaveTemps(std::string OutputFileName,
                           bool UseInputModulePath) {
  ShouldDiscardValueNames = false;

  std::error_code EC;
  ResolutionFile = llvm::make_unique<raw_fd_ostream>(
      OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::F_Text);
  if (EC)
    return errorCodeToError(EC);

  auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
    // Keep track of the hook provided by the linker, which also needs to run.
    ModuleHookFn LinkerHook = Hook;
    Hook = [=](unsigned Task, const Module &M) {
      // If the linker's hook returned false, we need to pass that result
      // through.
      if (LinkerHook && !LinkerHook(Task, M))
        return false;

      std::string PathPrefix;
      // If this is the combined module (not a ThinLTO backend compile) or the
      // user hasn't requested using the input module's path, emit to a file
      // named from the provided OutputFileName with the Task ID appended.
      if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
        PathPrefix = OutputFileName + utostr(Task);
      } else
        PathPrefix = M.getModuleIdentifier();
      std::string Path = PathPrefix + "." + PathSuffix + ".bc";
      std::error_code EC;
      raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
      // Because -save-temps is a debugging feature, we report the error
      // directly and exit.
      if (EC)
        reportOpenError(Path, EC.message());
      WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false);
      return true;
    };
  };

  setHook("0.preopt", PreOptModuleHook);
  setHook("1.promote", PostPromoteModuleHook);
  setHook("2.internalize", PostInternalizeModuleHook);
  setHook("3.import", PostImportModuleHook);
  setHook("4.opt", PostOptModuleHook);
  setHook("5.precodegen", PreCodeGenModuleHook);

  CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
    std::string Path = OutputFileName + "index.bc";
    std::error_code EC;
    raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
    // Because -save-temps is a debugging feature, we report the error
    // directly and exit.
    if (EC)
      reportOpenError(Path, EC.message());
    WriteIndexToFile(Index, OS);
    return true;
  };

  return Error();
}

namespace {

std::unique_ptr<TargetMachine>
createTargetMachine(Config &Conf, StringRef TheTriple,
                    const Target *TheTarget) {
  SubtargetFeatures Features;
  Features.getDefaultSubtargetFeatures(Triple(TheTriple));
  for (const std::string &A : Conf.MAttrs)
    Features.AddFeature(A);

  return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
      TheTriple, Conf.CPU, Features.getString(), Conf.Options, Conf.RelocModel,
      Conf.CodeModel, Conf.CGOptLevel));
}

static void runNewPMCustomPasses(Module &Mod, TargetMachine *TM,
                                 std::string PipelineDesc,
                                 std::string AAPipelineDesc,
                                 bool DisableVerify) {
  PassBuilder PB(TM);
  AAManager AA;

  // Parse a custom AA pipeline if asked to.
  if (!AAPipelineDesc.empty())
    if (!PB.parseAAPipeline(AA, AAPipelineDesc))
      report_fatal_error("unable to parse AA pipeline description: " +
                         AAPipelineDesc);

  LoopAnalysisManager LAM;
  FunctionAnalysisManager FAM;
  CGSCCAnalysisManager CGAM;
  ModuleAnalysisManager MAM;

  // Register the AA manager first so that our version is the one used.
  FAM.registerPass([&] { return std::move(AA); });

  // Register all the basic analyses with the managers.
  PB.registerModuleAnalyses(MAM);
  PB.registerCGSCCAnalyses(CGAM);
  PB.registerFunctionAnalyses(FAM);
  PB.registerLoopAnalyses(LAM);
  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);

  ModulePassManager MPM;

  // Always verify the input.
  MPM.addPass(VerifierPass());

  // Now, add all the passes we've been requested to.
  if (!PB.parsePassPipeline(MPM, PipelineDesc))
    report_fatal_error("unable to parse pass pipeline description: " +
                       PipelineDesc);

  if (!DisableVerify)
    MPM.addPass(VerifierPass());
  MPM.run(Mod, MAM);
}

static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
                           bool IsThinLto) {
  legacy::PassManager passes;
  passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));

  PassManagerBuilder PMB;
  PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
  PMB.Inliner = createFunctionInliningPass();
  // Unconditionally verify input since it is not verified before this
  // point and has unknown origin.
  PMB.VerifyInput = true;
  PMB.VerifyOutput = !Conf.DisableVerify;
  PMB.LoopVectorize = true;
  PMB.SLPVectorize = true;
  PMB.OptLevel = Conf.OptLevel;
  if (IsThinLto)
    PMB.populateThinLTOPassManager(passes);
  else
    PMB.populateLTOPassManager(passes);
  passes.run(Mod);
}

bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
         bool IsThinLto) {
  Mod.setDataLayout(TM->createDataLayout());
  if (Conf.OptPipeline.empty())
    runOldPMPasses(Conf, Mod, TM, IsThinLto);
  else
    runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
                         Conf.DisableVerify);
  return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
}

void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
             unsigned Task, Module &Mod) {
  if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
    return;

  auto Stream = AddStream(Task);
  legacy::PassManager CodeGenPasses;
  if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
                              TargetMachine::CGFT_ObjectFile))
    report_fatal_error("Failed to setup codegen");
  CodeGenPasses.run(Mod);
}

void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
                  unsigned ParallelCodeGenParallelismLevel,
                  std::unique_ptr<Module> Mod) {
  ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
  unsigned ThreadCount = 0;
  const Target *T = &TM->getTarget();

  SplitModule(
      std::move(Mod), ParallelCodeGenParallelismLevel,
      [&](std::unique_ptr<Module> MPart) {
        // We want to clone the module in a new context to multi-thread the
        // codegen. We do it by serializing partition modules to bitcode
        // (while still on the main thread, in order to avoid data races) and
        // spinning up new threads which deserialize the partitions into
        // separate contexts.
        // FIXME: Provide a more direct way to do this in LLVM.
        SmallString<0> BC;
        raw_svector_ostream BCOS(BC);
        WriteBitcodeToFile(MPart.get(), BCOS);

        // Enqueue the task
        CodegenThreadPool.async(
            [&](const SmallString<0> &BC, unsigned ThreadId) {
              LTOLLVMContext Ctx(C);
              ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
                  MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
                  Ctx);
              if (!MOrErr)
                report_fatal_error("Failed to read bitcode");
              std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());

              std::unique_ptr<TargetMachine> TM =
                  createTargetMachine(C, MPartInCtx->getTargetTriple(), T);

              codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
            },
            // Pass BC using std::move to ensure that it get moved rather than
            // copied into the thread's context.
            std::move(BC), ThreadCount++);
      },
      false);
}

Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
  if (!C.OverrideTriple.empty())
    Mod.setTargetTriple(C.OverrideTriple);
  else if (Mod.getTargetTriple().empty())
    Mod.setTargetTriple(C.DefaultTriple);

  std::string Msg;
  const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
  if (!T)
    return make_error<StringError>(Msg, inconvertibleErrorCode());
  return T;
}

}

static void handleAsmUndefinedRefs(Module &Mod, TargetMachine &TM) {
  // Collect the list of undefined symbols used in asm and update
  // llvm.compiler.used to prevent optimization to drop these from the output.
  StringSet<> AsmUndefinedRefs;
  object::IRObjectFile::CollectAsmUndefinedRefs(
      Triple(Mod.getTargetTriple()), Mod.getModuleInlineAsm(),
      [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
        if (Flags & object::BasicSymbolRef::SF_Undefined)
          AsmUndefinedRefs.insert(Name);
      });
  updateCompilerUsed(Mod, TM, AsmUndefinedRefs);
}

Error lto::backend(Config &C, AddStreamFn AddStream,
                   unsigned ParallelCodeGenParallelismLevel,
                   std::unique_ptr<Module> Mod) {
  Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
  if (!TOrErr)
    return TOrErr.takeError();

  std::unique_ptr<TargetMachine> TM =
      createTargetMachine(C, Mod->getTargetTriple(), *TOrErr);

  handleAsmUndefinedRefs(*Mod, *TM);

  if (!C.CodeGenOnly)
    if (!opt(C, TM.get(), 0, *Mod, /*IsThinLto=*/false))
      return Error();

  if (ParallelCodeGenParallelismLevel == 1) {
    codegen(C, TM.get(), AddStream, 0, *Mod);
  } else {
    splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
                 std::move(Mod));
  }
  return Error();
}

Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
                       Module &Mod, ModuleSummaryIndex &CombinedIndex,
                       const FunctionImporter::ImportMapTy &ImportList,
                       const GVSummaryMapTy &DefinedGlobals,
                       MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
  Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
  if (!TOrErr)
    return TOrErr.takeError();

  std::unique_ptr<TargetMachine> TM =
      createTargetMachine(Conf, Mod.getTargetTriple(), *TOrErr);

  handleAsmUndefinedRefs(Mod, *TM);

  if (Conf.CodeGenOnly) {
    codegen(Conf, TM.get(), AddStream, Task, Mod);
    return Error();
  }

  if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
    return Error();

  renameModuleForThinLTO(Mod, CombinedIndex);

  thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);

  if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
    return Error();

  if (!DefinedGlobals.empty())
    thinLTOInternalizeModule(Mod, DefinedGlobals);

  if (Conf.PostInternalizeModuleHook &&
      !Conf.PostInternalizeModuleHook(Task, Mod))
    return Error();

  auto ModuleLoader = [&](StringRef Identifier) {
    assert(Mod.getContext().isODRUniquingDebugTypes() &&
           "ODR Type uniquing should be enabled on the context");
    return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer(
                                              ModuleMap[Identifier], false),
                                          Mod.getContext(),
                                          /*ShouldLazyLoadMetadata=*/true)
                         .get());
  };

  FunctionImporter Importer(CombinedIndex, ModuleLoader);
  Importer.importFunctions(Mod, ImportList);

  if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
    return Error();

  if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLto=*/true))
    return Error();

  codegen(Conf, TM.get(), AddStream, Task, Mod);
  return Error();
}
<commit_msg>LTO: Fix use-after-scope error.<commit_after>//===-LTOBackend.cpp - LLVM Link Time Optimizer Backend -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the "backend" phase of LTO, i.e. it performs
// optimization and code generation on a loaded module. It is generally used
// internally by the LTO class but can also be used independently, for example
// to implement a standalone ThinLTO backend.
//
//===----------------------------------------------------------------------===//

#include "llvm/LTO/LTOBackend.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LoopPassManager.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/LTO/LTO.h"
#include "llvm/LTO/legacy/UpdateCompilerUsed.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#include "llvm/Transforms/Utils/SplitModule.h"

using namespace llvm;
using namespace lto;

LLVM_ATTRIBUTE_NORETURN void reportOpenError(StringRef Path, Twine Msg) {
  errs() << "failed to open " << Path << ": " << Msg << '\n';
  errs().flush();
  exit(1);
}

Error Config::addSaveTemps(std::string OutputFileName,
                           bool UseInputModulePath) {
  ShouldDiscardValueNames = false;

  std::error_code EC;
  ResolutionFile = llvm::make_unique<raw_fd_ostream>(
      OutputFileName + "resolution.txt", EC, sys::fs::OpenFlags::F_Text);
  if (EC)
    return errorCodeToError(EC);

  auto setHook = [&](std::string PathSuffix, ModuleHookFn &Hook) {
    // Keep track of the hook provided by the linker, which also needs to run.
    ModuleHookFn LinkerHook = Hook;
    Hook = [=](unsigned Task, const Module &M) {
      // If the linker's hook returned false, we need to pass that result
      // through.
      if (LinkerHook && !LinkerHook(Task, M))
        return false;

      std::string PathPrefix;
      // If this is the combined module (not a ThinLTO backend compile) or the
      // user hasn't requested using the input module's path, emit to a file
      // named from the provided OutputFileName with the Task ID appended.
      if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) {
        PathPrefix = OutputFileName + utostr(Task);
      } else
        PathPrefix = M.getModuleIdentifier();
      std::string Path = PathPrefix + "." + PathSuffix + ".bc";
      std::error_code EC;
      raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
      // Because -save-temps is a debugging feature, we report the error
      // directly and exit.
      if (EC)
        reportOpenError(Path, EC.message());
      WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false);
      return true;
    };
  };

  setHook("0.preopt", PreOptModuleHook);
  setHook("1.promote", PostPromoteModuleHook);
  setHook("2.internalize", PostInternalizeModuleHook);
  setHook("3.import", PostImportModuleHook);
  setHook("4.opt", PostOptModuleHook);
  setHook("5.precodegen", PreCodeGenModuleHook);

  CombinedIndexHook = [=](const ModuleSummaryIndex &Index) {
    std::string Path = OutputFileName + "index.bc";
    std::error_code EC;
    raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
    // Because -save-temps is a debugging feature, we report the error
    // directly and exit.
    if (EC)
      reportOpenError(Path, EC.message());
    WriteIndexToFile(Index, OS);
    return true;
  };

  return Error();
}

namespace {

std::unique_ptr<TargetMachine>
createTargetMachine(Config &Conf, StringRef TheTriple,
                    const Target *TheTarget) {
  SubtargetFeatures Features;
  Features.getDefaultSubtargetFeatures(Triple(TheTriple));
  for (const std::string &A : Conf.MAttrs)
    Features.AddFeature(A);

  return std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
      TheTriple, Conf.CPU, Features.getString(), Conf.Options, Conf.RelocModel,
      Conf.CodeModel, Conf.CGOptLevel));
}

static void runNewPMCustomPasses(Module &Mod, TargetMachine *TM,
                                 std::string PipelineDesc,
                                 std::string AAPipelineDesc,
                                 bool DisableVerify) {
  PassBuilder PB(TM);
  AAManager AA;

  // Parse a custom AA pipeline if asked to.
  if (!AAPipelineDesc.empty())
    if (!PB.parseAAPipeline(AA, AAPipelineDesc))
      report_fatal_error("unable to parse AA pipeline description: " +
                         AAPipelineDesc);

  LoopAnalysisManager LAM;
  FunctionAnalysisManager FAM;
  CGSCCAnalysisManager CGAM;
  ModuleAnalysisManager MAM;

  // Register the AA manager first so that our version is the one used.
  FAM.registerPass([&] { return std::move(AA); });

  // Register all the basic analyses with the managers.
  PB.registerModuleAnalyses(MAM);
  PB.registerCGSCCAnalyses(CGAM);
  PB.registerFunctionAnalyses(FAM);
  PB.registerLoopAnalyses(LAM);
  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);

  ModulePassManager MPM;

  // Always verify the input.
  MPM.addPass(VerifierPass());

  // Now, add all the passes we've been requested to.
  if (!PB.parsePassPipeline(MPM, PipelineDesc))
    report_fatal_error("unable to parse pass pipeline description: " +
                       PipelineDesc);

  if (!DisableVerify)
    MPM.addPass(VerifierPass());
  MPM.run(Mod, MAM);
}

static void runOldPMPasses(Config &Conf, Module &Mod, TargetMachine *TM,
                           bool IsThinLto) {
  legacy::PassManager passes;
  passes.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));

  PassManagerBuilder PMB;
  PMB.LibraryInfo = new TargetLibraryInfoImpl(Triple(TM->getTargetTriple()));
  PMB.Inliner = createFunctionInliningPass();
  // Unconditionally verify input since it is not verified before this
  // point and has unknown origin.
  PMB.VerifyInput = true;
  PMB.VerifyOutput = !Conf.DisableVerify;
  PMB.LoopVectorize = true;
  PMB.SLPVectorize = true;
  PMB.OptLevel = Conf.OptLevel;
  if (IsThinLto)
    PMB.populateThinLTOPassManager(passes);
  else
    PMB.populateLTOPassManager(passes);
  passes.run(Mod);
}

bool opt(Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
         bool IsThinLto) {
  Mod.setDataLayout(TM->createDataLayout());
  if (Conf.OptPipeline.empty())
    runOldPMPasses(Conf, Mod, TM, IsThinLto);
  else
    runNewPMCustomPasses(Mod, TM, Conf.OptPipeline, Conf.AAPipeline,
                         Conf.DisableVerify);
  return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
}

void codegen(Config &Conf, TargetMachine *TM, AddStreamFn AddStream,
             unsigned Task, Module &Mod) {
  if (Conf.PreCodeGenModuleHook && !Conf.PreCodeGenModuleHook(Task, Mod))
    return;

  auto Stream = AddStream(Task);
  legacy::PassManager CodeGenPasses;
  if (TM->addPassesToEmitFile(CodeGenPasses, *Stream->OS,
                              TargetMachine::CGFT_ObjectFile))
    report_fatal_error("Failed to setup codegen");
  CodeGenPasses.run(Mod);
}

void splitCodeGen(Config &C, TargetMachine *TM, AddStreamFn AddStream,
                  unsigned ParallelCodeGenParallelismLevel,
                  std::unique_ptr<Module> Mod) {
  ThreadPool CodegenThreadPool(ParallelCodeGenParallelismLevel);
  unsigned ThreadCount = 0;
  const Target *T = &TM->getTarget();

  SplitModule(
      std::move(Mod), ParallelCodeGenParallelismLevel,
      [&](std::unique_ptr<Module> MPart) {
        // We want to clone the module in a new context to multi-thread the
        // codegen. We do it by serializing partition modules to bitcode
        // (while still on the main thread, in order to avoid data races) and
        // spinning up new threads which deserialize the partitions into
        // separate contexts.
        // FIXME: Provide a more direct way to do this in LLVM.
        SmallString<0> BC;
        raw_svector_ostream BCOS(BC);
        WriteBitcodeToFile(MPart.get(), BCOS);

        // Enqueue the task
        CodegenThreadPool.async(
            [&](const SmallString<0> &BC, unsigned ThreadId) {
              LTOLLVMContext Ctx(C);
              ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
                  MemoryBufferRef(StringRef(BC.data(), BC.size()), "ld-temp.o"),
                  Ctx);
              if (!MOrErr)
                report_fatal_error("Failed to read bitcode");
              std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());

              std::unique_ptr<TargetMachine> TM =
                  createTargetMachine(C, MPartInCtx->getTargetTriple(), T);

              codegen(C, TM.get(), AddStream, ThreadId, *MPartInCtx);
            },
            // Pass BC using std::move to ensure that it get moved rather than
            // copied into the thread's context.
            std::move(BC), ThreadCount++);
      },
      false);
  CodegenThreadPool.wait();
}

Expected<const Target *> initAndLookupTarget(Config &C, Module &Mod) {
  if (!C.OverrideTriple.empty())
    Mod.setTargetTriple(C.OverrideTriple);
  else if (Mod.getTargetTriple().empty())
    Mod.setTargetTriple(C.DefaultTriple);

  std::string Msg;
  const Target *T = TargetRegistry::lookupTarget(Mod.getTargetTriple(), Msg);
  if (!T)
    return make_error<StringError>(Msg, inconvertibleErrorCode());
  return T;
}

}

static void handleAsmUndefinedRefs(Module &Mod, TargetMachine &TM) {
  // Collect the list of undefined symbols used in asm and update
  // llvm.compiler.used to prevent optimization to drop these from the output.
  StringSet<> AsmUndefinedRefs;
  object::IRObjectFile::CollectAsmUndefinedRefs(
      Triple(Mod.getTargetTriple()), Mod.getModuleInlineAsm(),
      [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
        if (Flags & object::BasicSymbolRef::SF_Undefined)
          AsmUndefinedRefs.insert(Name);
      });
  updateCompilerUsed(Mod, TM, AsmUndefinedRefs);
}

Error lto::backend(Config &C, AddStreamFn AddStream,
                   unsigned ParallelCodeGenParallelismLevel,
                   std::unique_ptr<Module> Mod) {
  Expected<const Target *> TOrErr = initAndLookupTarget(C, *Mod);
  if (!TOrErr)
    return TOrErr.takeError();

  std::unique_ptr<TargetMachine> TM =
      createTargetMachine(C, Mod->getTargetTriple(), *TOrErr);

  handleAsmUndefinedRefs(*Mod, *TM);

  if (!C.CodeGenOnly)
    if (!opt(C, TM.get(), 0, *Mod, /*IsThinLto=*/false))
      return Error();

  if (ParallelCodeGenParallelismLevel == 1) {
    codegen(C, TM.get(), AddStream, 0, *Mod);
  } else {
    splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
                 std::move(Mod));
  }
  return Error();
}

Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
                       Module &Mod, ModuleSummaryIndex &CombinedIndex,
                       const FunctionImporter::ImportMapTy &ImportList,
                       const GVSummaryMapTy &DefinedGlobals,
                       MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
  Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
  if (!TOrErr)
    return TOrErr.takeError();

  std::unique_ptr<TargetMachine> TM =
      createTargetMachine(Conf, Mod.getTargetTriple(), *TOrErr);

  handleAsmUndefinedRefs(Mod, *TM);

  if (Conf.CodeGenOnly) {
    codegen(Conf, TM.get(), AddStream, Task, Mod);
    return Error();
  }

  if (Conf.PreOptModuleHook && !Conf.PreOptModuleHook(Task, Mod))
    return Error();

  renameModuleForThinLTO(Mod, CombinedIndex);

  thinLTOResolveWeakForLinkerModule(Mod, DefinedGlobals);

  if (Conf.PostPromoteModuleHook && !Conf.PostPromoteModuleHook(Task, Mod))
    return Error();

  if (!DefinedGlobals.empty())
    thinLTOInternalizeModule(Mod, DefinedGlobals);

  if (Conf.PostInternalizeModuleHook &&
      !Conf.PostInternalizeModuleHook(Task, Mod))
    return Error();

  auto ModuleLoader = [&](StringRef Identifier) {
    assert(Mod.getContext().isODRUniquingDebugTypes() &&
           "ODR Type uniquing should be enabled on the context");
    return std::move(getLazyBitcodeModule(MemoryBuffer::getMemBuffer(
                                              ModuleMap[Identifier], false),
                                          Mod.getContext(),
                                          /*ShouldLazyLoadMetadata=*/true)
                         .get());
  };

  FunctionImporter Importer(CombinedIndex, ModuleLoader);
  Importer.importFunctions(Mod, ImportList);

  if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
    return Error();

  if (!opt(Conf, TM.get(), Task, Mod, /*IsThinLto=*/true))
    return Error();

  codegen(Conf, TM.get(), AddStream, Task, Mod);
  return Error();
}
<|endoftext|>


<commit_before>
#include "function.h"
#include "value.h"

using namespace v8;

namespace GINode {

static Handle<Value> FunctionInvoker(const Arguments &args) {
    HandleScope scope;
    GIBaseInfo *info = (GIBaseInfo *) External::Unwrap (args.Data ());
    GIFunctionInfo *function_info = (GIFunctionInfo *) info;
    GError *error = NULL;

    /* XXX: For now, only work on functions without any OUT args at all.
     * Just assume everything is an in arg. */
    int n_in_args = g_callable_info_get_n_args ((GICallableInfo *) info);
    GIArgument in_args[n_in_args];

    if (args.Length() < n_in_args) {
        ThrowException (Exception::TypeError (String::New ("Not enough arguments.")));
        return scope.Close (Undefined ());
    }

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        V8ToGIArgument (&type_info, &in_args[i], args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    GIArgument return_value;
    g_function_info_invoke (function_info,
                            in_args, n_in_args,
                            NULL, 0,
                            &return_value,
                            &error);

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        FreeGIArgument (&type_info, &in_args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    if (error) {
        ThrowException (Exception::TypeError (String::New (error->message)));
        return scope.Close (Undefined ());
    }

    GITypeInfo return_value_type;
    g_callable_info_load_return_type ((GICallableInfo *) info, &return_value_type);
    return scope.Close (GIArgumentToV8 (&return_value_type, &return_value));
}

static void FunctionDestroyed(Persistent<Value> object, void *data) {
    GIBaseInfo *info = (GIBaseInfo *) data;
    g_base_info_unref (info);
}

Handle<Function> MakeFunction(GIBaseInfo *info) {
    Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New (FunctionInvoker, External::Wrap (info)));
    tpl.MakeWeak (g_base_info_ref (info), FunctionDestroyed);
    Local<Function> fn = tpl->GetFunction ();

    const char *function_name = g_base_info_get_name (info);
    fn->SetName (String::NewSymbol (function_name));

    return fn;
}

};
<commit_msg>function: Implement methods<commit_after>
#include "function.h"
#include "value.h"
#include "object.h"

using namespace v8;

namespace GINode {

static Handle<Value> FunctionInvoker(const Arguments &args) {
    HandleScope scope;
    GIBaseInfo *info = (GIBaseInfo *) External::Unwrap (args.Data ());
    GIFunctionInfo *function_info = (GIFunctionInfo *) info;
    GError *error = NULL;

    /* XXX: For now, only work on functions without any OUT args at all.
     * Just assume everything is an in arg. */
    int n_in_args = g_callable_info_get_n_args ((GICallableInfo *) info);
    int n_total_args = n_in_args;

    if (args.Length() < n_in_args) {
        ThrowException (Exception::TypeError (String::New ("Not enough arguments.")));
        return scope.Close (Undefined ());
    }

    gboolean is_method = ((g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD) != 0 &&
                          (g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR) == 0);
    if (is_method)
        n_total_args++;

    GIArgument total_args[n_total_args];
    GIArgument *in_args;

    if (is_method) {
        total_args[0].v_pointer = GObjectFromWrapper (args.This ());
        in_args = &total_args[1];
    } else {
        in_args = &total_args[0];
    }

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        V8ToGIArgument (&type_info, &in_args[i], args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    GIArgument return_value;
    g_function_info_invoke (function_info,
                            total_args, n_total_args,
                            NULL, 0,
                            &return_value,
                            &error);

    for (int i = 0; i < n_in_args; i++) {
        GIArgInfo *arg_info = g_callable_info_get_arg ((GICallableInfo *) info, i);
        GITypeInfo type_info;
        g_arg_info_load_type (arg_info, &type_info);
        FreeGIArgument (&type_info, &in_args[i]);
        g_base_info_unref ((GIBaseInfo *) arg_info);
    }

    if (error) {
        ThrowException (Exception::TypeError (String::New (error->message)));
        return scope.Close (Undefined ());
    }

    GITypeInfo return_value_type;
    g_callable_info_load_return_type ((GICallableInfo *) info, &return_value_type);
    return scope.Close (GIArgumentToV8 (&return_value_type, &return_value));
}

static void FunctionDestroyed(Persistent<Value> object, void *data) {
    GIBaseInfo *info = (GIBaseInfo *) data;
    g_base_info_unref (info);
}

Handle<Function> MakeFunction(GIBaseInfo *info) {
    Persistent<FunctionTemplate> tpl = Persistent<FunctionTemplate>::New (FunctionTemplate::New (FunctionInvoker, External::Wrap (info)));
    tpl.MakeWeak (g_base_info_ref (info), FunctionDestroyed);
    Local<Function> fn = tpl->GetFunction ();

    const char *function_name = g_base_info_get_name (info);
    fn->SetName (String::NewSymbol (function_name));

    return fn;
}

};
<|endoftext|>


<commit_before>/***********************************************************************************
**
** GumpGeneric.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "GumpGeneric.h"
#include "../Managers/ConfigManager.h"
#include "../TextEngine/GameConsole.h"
#include "../Network/Packets.h"
//----------------------------------------------------------------------------------
CGumpGeneric::CGumpGeneric(uint serial, short x, short y, uint id)
: CGump(GT_GENERIC, serial, x, y)
{
	m_Page = 1;
	m_ID = id;
}
//----------------------------------------------------------------------------------
CGumpGeneric::~CGumpGeneric()
{
}
//----------------------------------------------------------------------------------
void CGumpGeneric::AddText(const int &index, const wstring &text, CBaseGUI *start)
{
	if (start == NULL)
		start = (CBaseGUI*)m_Items;

	QFOR(item, start, CBaseGUI*)
	{
		switch (item->Type)
		{
			case GOT_TEXT:
			{
				CGUIGenericText *gt = (CGUIGenericText*)item;

				if (gt->TextID == index)
					gt->CreateTexture(text);

				break;
			}
			case GOT_TEXTENTRY:
			{
				CGUIGenericTextEntry *gte = (CGUIGenericTextEntry*)item;

				if (gte->TextID == index)
					gte->m_Entry.SetText(text);

				break;
			}
			case GOT_HTMLTEXT:
			{
				CGUIHTMLText *gt = (CGUIHTMLText*)item;

				if (gt->TextID == index)
				{
					gt->Text = text;
					gt->CreateTexture();
				}

				break;
			}
			case GOT_HTMLGUMP:
			{
				CGUIHTMLGump *ghtml = (CGUIHTMLGump*)item;

				if (ghtml->Serial == index + 1)
				{
					AddText(index, text, (CBaseGUI*)item->m_Items);
					ghtml->CalculateDataSize();
				}

				break;
			}
			default:
				break;
		}
	}
}
//----------------------------------------------------------------------------------
void CGumpGeneric::SendGumpResponse(int index)
{
	//
	CPacketGumpResponse(this, index).Send();

	//
	m_RemoveMark = true;
}
//----------------------------------------------------------------------------------
void CGumpGeneric::GUMP_BUTTON_EVENT_C
{
	SendGumpResponse(serial);
}
//----------------------------------------------------------------------------------
void CGumpGeneric::GUMP_DIRECT_HTML_LINK_EVENT_C
{
}
//----------------------------------------------------------------------------------
void CGumpGeneric::OnCharPress(const WPARAM &wParam, const LPARAM &lParam)
{
	g_EntryPointer->Insert(wParam);
	m_WantRedraw = true;
}
//----------------------------------------------------------------------------------
void CGumpGeneric::OnKeyDown(const WPARAM &wParam, const LPARAM &lParam)
{
	if (wParam == VK_RETURN)
	{
		if (g_ConfigManager.GetConsoleNeedEnter())
			g_EntryPointer = NULL;
		else
			g_EntryPointer = &g_GameConsole;

		m_WantRedraw = true;
	}
	else
		g_EntryPointer->OnKey(this, wParam);
}
//----------------------------------------------------------------------------------
<commit_msg>Поправил переход по веб-ссылкам из HTMLGump.<commit_after>/***********************************************************************************
**
** GumpGeneric.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "GumpGeneric.h"
#include "../Managers/ConfigManager.h"
#include "../Managers/FontsManager.h"
#include "../TextEngine/GameConsole.h"
#include "../Network/Packets.h"
//----------------------------------------------------------------------------------
CGumpGeneric::CGumpGeneric(uint serial, short x, short y, uint id)
: CGump(GT_GENERIC, serial, x, y)
{
	m_Page = 1;
	m_ID = id;
}
//----------------------------------------------------------------------------------
CGumpGeneric::~CGumpGeneric()
{
}
//----------------------------------------------------------------------------------
void CGumpGeneric::AddText(const int &index, const wstring &text, CBaseGUI *start)
{
	if (start == NULL)
		start = (CBaseGUI*)m_Items;

	QFOR(item, start, CBaseGUI*)
	{
		switch (item->Type)
		{
			case GOT_TEXT:
			{
				CGUIGenericText *gt = (CGUIGenericText*)item;

				if (gt->TextID == index)
					gt->CreateTexture(text);

				break;
			}
			case GOT_TEXTENTRY:
			{
				CGUIGenericTextEntry *gte = (CGUIGenericTextEntry*)item;

				if (gte->TextID == index)
					gte->m_Entry.SetText(text);

				break;
			}
			case GOT_HTMLTEXT:
			{
				CGUIHTMLText *gt = (CGUIHTMLText*)item;

				if (gt->TextID == index)
				{
					gt->Text = text;
					gt->CreateTexture();
				}

				break;
			}
			case GOT_HTMLGUMP:
			{
				CGUIHTMLGump *ghtml = (CGUIHTMLGump*)item;

				if (ghtml->Serial == index + 1)
				{
					AddText(index, text, (CBaseGUI*)item->m_Items);
					ghtml->CalculateDataSize();
				}

				break;
			}
			default:
				break;
		}
	}
}
//----------------------------------------------------------------------------------
void CGumpGeneric::SendGumpResponse(int index)
{
	//
	CPacketGumpResponse(this, index).Send();

	//
	m_RemoveMark = true;
}
//----------------------------------------------------------------------------------
void CGumpGeneric::GUMP_BUTTON_EVENT_C
{
	SendGumpResponse(serial);
}
//----------------------------------------------------------------------------------
void CGumpGeneric::GUMP_DIRECT_HTML_LINK_EVENT_C
{
	g_FontManager.GoToWebLink(link);
}
//----------------------------------------------------------------------------------
void CGumpGeneric::OnCharPress(const WPARAM &wParam, const LPARAM &lParam)
{
	g_EntryPointer->Insert(wParam);
	m_WantRedraw = true;
}
//----------------------------------------------------------------------------------
void CGumpGeneric::OnKeyDown(const WPARAM &wParam, const LPARAM &lParam)
{
	if (wParam == VK_RETURN)
	{
		if (g_ConfigManager.GetConsoleNeedEnter())
			g_EntryPointer = NULL;
		else
			g_EntryPointer = &g_GameConsole;

		m_WantRedraw = true;
	}
	else
		g_EntryPointer->OnKey(this, wParam);
}
//----------------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int

typedef int Status;
typedef struct LNode
{
 int data;
 struct LNode *next;
}LNode,*LinkList;

int CreateLink_L(LinkList &L,int n){
// 创建含有n个元素的单链表
  LinkList p,q;
  int i;
  ElemType e;
  L = (LinkList)malloc(sizeof(LNode));
  L->next = NULL;
  L->data=n;             // 先建立一个带头结点的单链表
  q = (LinkList)malloc(sizeof(LNode));
  q = L;
  for (i=0; i<n; i++) {
   scanf("%d", &e);
    p = (LinkList)malloc(sizeof(LNode));
    p->next=NULL;  // 生成新结点
    q->next=p;
    p->data=e;
    q=p;

  }
  return OK;
}

int LoadLink_L(LinkList &L,char * name){
// 单链表遍历
 LinkList p = L->next;
 if(p==NULL)printf("The List is empty!"); // 请填空
 else
 {
   printf("The %sList is:",name);
   while(p)    // 请填空
   {
    printf("%d ",p->data);
    p=p->next;   // 请填空
   }
 }
 printf("\n");
 return OK;
}

Status ListInsert_L(LinkList &L, int i, ElemType e) {  // 算法2.9
  // 在带头结点的单链线性表L的第i个元素之前插入元素e
  LinkList p,s;
  p = L;
  int j = 0;
  while (p && j < i-1) {  // 寻找第i-1个结点
    p = p->next;
    ++j;
  }
  if (!p || j > i-1) return ERROR;      // i小于1或者大于表长
  s = (LinkList)malloc(sizeof(LNode));  // 生成新结点
  s->data = e;  s->next = p->next;      // 插入L中
  p->next = s;
  L->data++;
  return OK;
} // LinstInsert_L

Status ListDelete_L(LinkList &L, int i, ElemType &e) {  // 算法2.10
  // 在带头结点的单链线性表L中，删除第i个元素，并由e返回其值
  LinkList p,q;
  p = L;
  int j = 0;
  while (p->next && j < i-1) {  // 寻找第i个结点，并令p指向其前趋
    p = p->next;
    ++j;
  }
  if (!(p->next) || j > i-1) return ERROR;  // 删除位置不合理
  q = p->next;
  p->next = q->next;           // 删除并释放结点
  e = q->data;
  free(q);
  L->data--;
  return OK;
} // ListDelete_L

Status Linkunion_L(LinkList a,LinkList b,LinkList c){

  LinkList pa,pb,pc;

  pa=a->next,pb=b->next;
  pc=c;
  int i=1;
  while(pa||pb){

    if(pa==NULL)
      {pc->next=pb;return OK;}
    if(pb==NULL)
      {pc->next=pa;return OK;}

    if((pa->data)<(pb->data)){

      pc->next=pa;
      pc=pa;
      pa=pa->next;
    }else
    {
      pc->next=pb;
      pc=pb;
      pb=pb->next;
    }
  }

}

Status Linkturn(LinkList &L){

    LinkList out;
    CreateLink_L(out,0);

    ElemType e;

    int i=1;
    while(L->data>0){
      ListDelete_L(L,L->data,e) ;
      ListInsert_L(out,i,e);
      i++;
    }

    L=out;
    return OK;

}
int main(int argc, char const *argv[])
{
   int n,m;

   scanf("%d",&n);
   LinkList A;
   CreateLink_L(A,n);
   LoadLink_L(A,"");
   Linkturn(A);
    LoadLink_L(A,"turned ");
  return 0;
}<commit_msg>update uoj8581<commit_after>#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int

typedef int Status;
typedef struct LNode
{
 int data;
 struct LNode *next;
}LNode,*LinkList;

int CreateLink_L(LinkList &L,int n){
// 创建含有n个元素的单链表
  LinkList p,q;
  int i;
  ElemType e;
  L = (LinkList)malloc(sizeof(LNode));
  L->next = NULL;
  L->data=n;             // 先建立一个带头结点的单链表
  q = (LinkList)malloc(sizeof(LNode));
  q = L;
  for (i=0; i<n; i++) {
   scanf("%d", &e);
    p = (LinkList)malloc(sizeof(LNode));
    p->next=NULL;  // 生成新结点
    q->next=p;
    p->data=e;
    q=p;

  }
  return OK;
}

int LoadLink_L(LinkList &L,char * name){
// 单链表遍历
 LinkList p = L->next;
 if(p==NULL)printf("The List is empty!"); // 请填空
 else
 {
   printf("The %sList is:",name);
   while(p)    // 请填空
   {
    printf("%d ",p->data);
    p=p->next;   // 请填空
   }
 }
 printf("\n");
 return OK;
}

Status ListInsert_L(LinkList &L, int i, ElemType e) {  // 算法2.9
  // 在带头结点的单链线性表L的第i个元素之前插入元素e
  LinkList p,s;
  p = L;
  int j = 0;
  while (p && j < i-1) {  // 寻找第i-1个结点
    p = p->next;
    ++j;
  }
  if (!p || j > i-1) return ERROR;      // i小于1或者大于表长
  s = (LinkList)malloc(sizeof(LNode));  // 生成新结点
  s->data = e;  s->next = p->next;      // 插入L中
  p->next = s;
  L->data++;
  return OK;
} // LinstInsert_L

Status ListDelete_L(LinkList &L, int i, ElemType &e) {  // 算法2.10
  // 在带头结点的单链线性表L中，删除第i个元素，并由e返回其值
  LinkList p,q;
  p = L;
  int j = 0;
  while (p->next && j < i-1) {  // 寻找第i个结点，并令p指向其前趋
    p = p->next;
    ++j;
  }
  if (!(p->next) || j > i-1) return ERROR;  // 删除位置不合理
  q = p->next;
  p->next = q->next;           // 删除并释放结点
  e = q->data;
  free(q);
  L->data--;
  return OK;
} // ListDelete_L

Status Linkunion_L(LinkList a,LinkList b,LinkList c){

  LinkList pa,pb,pc;

  pa=a->next,pb=b->next;
  pc=c;
  int i=1;
  while(pa||pb){

    if(pa==NULL)
      {pc->next=pb;return OK;}
    if(pb==NULL)
      {pc->next=pa;return OK;}

    if((pa->data)<(pb->data)){

      pc->next=pa;
      pc=pa;
      pa=pa->next;
    }else
    {
      pc->next=pb;
      pc=pb;
      pb=pb->next;
    }
  }

}

Status Linkturn(LinkList &L){

    LinkList out;
    CreateLink_L(out,0);

    ElemType e;

    int i=1;
    while(L->data>0){
      ListDelete_L(L,L->data,e) ;
      ListInsert_L(out,i,e);
      i++;
    }

    L=out;
    return OK;

}
int main(int argc, char const *argv[])
{
   int n,m;

   scanf("%d",&n);
   LinkList A;
   CreateLink_L(A,n);
   LoadLink_L(A,"");
   Linkturn(A);
    LoadLink_L(A,"turned ");
  return 0;
}
<|endoftext|>


<commit_before>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#include <limits>

#include "vvglew.h"
#include "vvibrclient.h"
#include "vvgltools.h"
#include "vvtexrend.h"
#include "float.h"
#include "vvrayrend.h"
#include "vvshaderfactory.h"
#include "vvshaderprogram.h"
#include "vvtoolshed.h"

using std::cerr;
using std::endl;

vvIbrClient::vvIbrClient(vvVolDesc *vd, vvRenderState renderState,
                         const char* slaveName, int slavePort,
                         const char* slaveFileName,
                         const vvIbrImage::DepthPrecision dp)
  : vvRemoteClient(vd, renderState, slaveName, slavePort, slaveFileName),
    _depthPrecision(dp)
{
  vvDebugMsg::msg(1, "vvIbrClient::vvIbrClient()");

  rendererType = REMOTE_IBR;

  _thread = NULL;
  _threadData = NULL;

  glewInit();
  glGenBuffers(1, &_pointVBO);
  glGenBuffers(1, &_indexBO);
  glGenBuffers(1, &_colorVBO);

  glEnable(GL_TEXTURE_2D);
  glGenTextures(3, _ibrTex);

  _haveFrame = false; // no rendered frame available
  _newFrame = true; // request a new frame

  _shaderFactory = new vvShaderFactory();
  _shader = _shaderFactory->createProgram("ibr", "", "");

  pthread_mutex_init(&_slaveMutex, NULL);

  createImages();
  createThreads();
}

vvIbrClient::~vvIbrClient()
{
  vvDebugMsg::msg(1, "vvIbrClient::~vvIbrClient()");

  destroyThreads();
  glDeleteBuffers(1, &_pointVBO);
  glDeleteBuffers(1, &_indexBO);
  glDeleteBuffers(1, &_colorVBO);
  glDeleteTextures(3, _ibrTex);
  delete _shaderFactory;
  delete _shader;
}

vvRemoteClient::ErrorType vvIbrClient::render()
{
  vvDebugMsg::msg(1, "vvIbrClient::render()");

  // Draw boundary lines
  if (_boundaries)
  {
    const vvVector3 size(vd->getSize()); // volume size [world coordinates]
    drawBoundingBox(&size, &vd->pos, &_boundColor);
  }

  if (_shader == NULL)
  {
    return vvRemoteClient::VV_SHADER_ERROR;
  }

  pthread_mutex_lock(&_slaveMutex);
  bool haveFrame = _haveFrame;
  bool newFrame = _newFrame;
  pthread_mutex_unlock(&_slaveMutex);

  vvGLTools::getModelviewMatrix(&_currentMv);
  vvGLTools::getProjectionMatrix(&_currentPr);
  vvMatrix currentMatrix = _currentMv * _currentPr;

  if(newFrame && haveFrame)
  {
    pthread_mutex_lock(&_slaveMutex);
    initIbrFrame();
    pthread_mutex_unlock(&_slaveMutex);
  }

  if (newFrame) // no frame pending
  {
    // request new ibr frame if anything changed
    vvMatrix imgMatrix;
    if (_ibrImg != NULL)
    {
      imgMatrix = _ibrImg->getReprojectionMatrix();
    }

    if (!currentMatrix.equal(&imgMatrix))
    {
      _changes = true;
    }

    if(_changes)
    {
      pthread_mutex_lock(&_slaveMutex);
      vvRemoteClient::ErrorType err = requestIbrFrame();
      _newFrame = false;
      pthread_mutex_unlock(&_slaveMutex);
      _changes = false;
      if(err != vvRemoteClient::VV_OK)
        std::cerr << "vvibrClient::requestIbrFrame() - error() " << err << std::endl;
    }
  }

  if(!haveFrame)
  {
    // no frame was yet received
    return VV_OK;
  }

  // Index Buffer Object for points
  const Corner c = getNearestCorner();
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBO);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indexArray[c].size() * sizeof(GLuint), &(_indexArray[c])[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // prepare VBOs
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glVertexPointer(3, GL_FLOAT, 0, NULL);
  glEnableClientState(GL_VERTEX_ARRAY);

  glBindBuffer(GL_ARRAY_BUFFER, _colorVBO);
  glColorPointer(4, GL_UNSIGNED_BYTE, 0, NULL);
  glEnableClientState(GL_COLOR_ARRAY);

  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBO);

  _shader->enable();

  vvMatrix imgMatrix = _ibrImg->getReprojectionMatrix();
  vvMatrix invImgMatrix;
  invImgMatrix.copy(&imgMatrix);

  vvMatrix reprojectionMatrix = _ibrImg->getReprojectionMatrix() * currentMatrix;

  reprojectionMatrix.transpose();

  float reprojectionMatrixGL[16];
  reprojectionMatrix.get(reprojectionMatrixGL);
  _shader->setParameterMatrix4f("reprojectionMatrix" , reprojectionMatrixGL);

  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  glDrawElements(GL_POINTS, _width*_height, GL_UNSIGNED_INT, NULL);

  _shader->disable();

  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);

  glBindBuffer(GL_ARRAY_BUFFER, 0);

  glFlush();

  return VV_OK;
}

vvRemoteClient::ErrorType vvIbrClient::requestIbrFrame()
{
  vvDebugMsg::msg(1, "vvIbrClient::requestIbrFrame()");

  if(_socket->putCommReason(vvSocketIO::VV_MATRIX) != vvSocket::VV_OK)
      return vvRemoteClient::VV_SOCKET_ERROR;

  if(_socket->putMatrix(&_currentPr) != vvSocket::VV_OK)
      return vvRemoteClient::VV_SOCKET_ERROR;

  if(_socket->putMatrix(&_currentMv) != vvSocket::VV_OK)
      return vvRemoteClient::VV_SOCKET_ERROR;

  return vvRemoteClient::VV_OK;
}

void vvIbrClient::initIbrFrame()
{
  vvDebugMsg::msg(1, "vvIbrClient::initIbrFrame()");

  _ibrImg = dynamic_cast<vvIbrImage*>(_threadData->images->at(0));
  if(!_ibrImg)
    return;

  const int h = _ibrImg->getHeight();
  const int w = _ibrImg->getWidth();
  _width = w;
  _height = h;

  // get pixel and depth-data
  uchar* dataRGBA = _ibrImg->getCodedImage();
  std::vector<float> depth(w*h);
  switch(_depthPrecision)
  {
  case vvIbrImage::VV_UCHAR:
    {
      uchar* d_uchar = _ibrImg->getpixeldepthUchar();
      for(int y = 0; y<h; y++)
        for(int x = 0; x<w; x++)
          depth[y*w+x] = float(d_uchar[y*w+x]) / float(UCHAR_MAX);
    }
    break;
  case vvIbrImage::VV_USHORT:
    {
      ushort* d_ushort = _ibrImg->getpixeldepthUshort();
      for(int y = 0; y<h; y++)
        for(int x = 0; x<w; x++)
          depth[y*w+x] = float(d_ushort[y*w+x]) / float(USHRT_MAX);
    }
    break;
  case vvIbrImage::VV_UINT:
    {
      uint* d_uint = _ibrImg->getpixeldepthUint();
      for(int y = 0; y<h; y++)
        for(int x = 0; x<w; x++)
          depth[y*w+x] = float(d_uint[y*w+x]) / float(UINT_MAX);
    }
    break;
  }

  std::vector<GLubyte> colors(w*h*4);
  std::vector<GLfloat> points(w*h*3);

  for(int y = 0; y<h; y++)
  {
    for(int x = 0; x<w; x++)
    {
      int colorIndex = (y*w+x)*4;

      // save color
      colors[colorIndex]   = dataRGBA[colorIndex];
      colors[colorIndex+1] = dataRGBA[colorIndex+1];
      colors[colorIndex+2] = dataRGBA[colorIndex+2];

      if(depth[y*w+x] <= 0.0f || depth[y*w+x] >= 1.0f)
        colors[colorIndex+3] = 0;
      else
        colors[colorIndex+3] = static_cast<GLubyte>(dataRGBA[colorIndex+3]);

      points[y*w*3+x*3]   = x;
      points[y*w*3+x*3+1] = y;
      points[y*w*3+x*3+2] = (depth[y*w+x] <= 0.0f) ? 1.0f : depth[y*w+x];
    }
  }

  // VBO for points
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  // VBO for colors
  glBindBuffer(GL_ARRAY_BUFFER, _colorVBO);
  glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLubyte), &colors[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  glBindBuffer(GL_ARRAY_BUFFER, 0);

  initIndexArrays();
}

void vvIbrClient::exit()
{
  vvDebugMsg::msg(1, "vvIbrClient::exit()");

  _socket->putCommReason(vvSocketIO::VV_EXIT);
  delete _socket;
}

void vvIbrClient::initIndexArrays()
{
  vvDebugMsg::msg(3, "vvIbrClient::initIndexArray()");

  const int width = _width;
  const int height = _height;

  for (int i = 0; i < 4; ++i)
  {
    _indexArray[i].clear();
  }

  // Top-left to bottom-right.
  for (int y = 0; y < height; ++y)
  {
    for (int x = 0; x < width; ++x)
    {
      _indexArray[VV_TOP_LEFT].push_back(y * width + x);
    }
  }

  // Top-right to bottom-left.
  for (int y = 0; y < height; ++y)
  {
    for (int x = width - 1; x >= 0; --x)
    {
      _indexArray[VV_TOP_RIGHT].push_back(y * width + x);
    }
  }

  // Bottom-right to top-left.
  for (int y = height - 1; y >= 0; --y)
  {
    for (int x = width - 1; x >= 0; --x)
    {
      _indexArray[VV_BOTTOM_RIGHT].push_back(y * width + x);
    }
  }

  // Bottom-left to top-right.
  for (int y = height - 1; y >= 0; --y)
  {
    for (int x = 0; x < width; ++x)
    {
      _indexArray[VV_BOTTOM_LEFT].push_back(y * width + x);
    }
  }
}

vvIbrClient::Corner vvIbrClient::getNearestCorner() const
{
  vvDebugMsg::msg(3, "vvIbrClient::getNearestCorner()");

  vvVector4 normal = vvVector4(0.0f, 0.0f, 1.0f, 1.0f);

  // Cancel out old matrix from normal.
  vvMatrix oldMatrix = _ibrImg->getReprojectionMatrix();
  // The operations below cancel each other out.
  // Left the code this way for higher legibility.
  // Vectors are transformed.
  oldMatrix.invert();
  oldMatrix.transpose();
  oldMatrix.invert();
  normal.multiply(&oldMatrix);

  vvMatrix newMatrix = _currentMv * _currentPr;
  newMatrix.transpose();
  newMatrix.invert();
  normal.multiply(&newMatrix);

  if ((normal[0] < normal[1]) && (normal[0] < 0.0f))
  {
    return VV_TOP_LEFT;
  }
  else if ((normal[0] >= normal[1]) && (normal[0] >= 0.0f))
  {
    return VV_TOP_RIGHT;
  }
  else if ((normal[1] < normal[0]) && (normal[1] < 0.0f))
  {
    return VV_BOTTOM_RIGHT;
  }
  else if ((normal[1] >= normal[0]) && (normal[1] >= 0.0f))
  {
    return VV_BOTTOM_LEFT;
  }
  else
  {
    // Arbitrary default.
    return VV_TOP_LEFT;
  }
}

void vvIbrClient::createThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::createThreads()");

  _threadData = new ThreadArgs;
  _thread = new pthread_t;
  _threadData->renderMaster = this;
  _threadData->images = &_images;
  pthread_create(_thread, NULL, getImageFromSocket, _threadData);
}

void vvIbrClient::destroyThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::destroyThreads()");

  exit();
  pthread_cancel(*_thread);
  pthread_join(*_thread, NULL);
  delete _thread;
  delete _threadData;
  _thread = NULL;
  _threadData = NULL;
}

void vvIbrClient::setDepthPrecision(vvIbrImage::DepthPrecision dp)
{
  vvDebugMsg::msg(3, "vvIbrClient::setDepthPrecision()");

  _depthPrecision = dp;
}

void* vvIbrClient::getImageFromSocket(void* threadargs)
{
  vvDebugMsg::msg(1, "vvIbrClient::getImageFromSocket()");

  std::cerr << "Image thread start" << std::endl;

  ThreadArgs* data = static_cast<ThreadArgs*>(threadargs);

  while (1)
  {
    vvIbrImage* img = static_cast<vvIbrImage *>(data->images->at(1));
    img->setDepthPrecision(data->renderMaster->_depthPrecision);

    vvSocketIO::ErrorType err = data->renderMaster->_socket->getIbrImage(img);
    if(err != vvSocketIO::VV_OK)
    {
      std::cerr << "vvIbrClient::getImageFromSocket: socket-error (" << err << ") - exiting..." << std::endl;
      break;
    }
#ifdef _WIN32
    Sleep(1000);
#else
    usleep(1000000);
#endif
    // switch pointers securely
    pthread_mutex_lock( &data->renderMaster->_slaveMutex );
    std::swap(data->images->at(0), data->images->at(1));
    data->renderMaster->_newFrame = true;
    data->renderMaster->_haveFrame = true;
    pthread_mutex_unlock( &data->renderMaster->_slaveMutex );
  }
  pthread_exit(NULL);
#ifdef _WIN32
  return NULL;
#endif
}

void vvIbrClient::createImages()
{
  vvDebugMsg::msg(3, "vvIbrClient::createImages()");
  for(int i=0; i<2; ++i)
    _images.push_back(new vvIbrImage);
}
<commit_msg>decode image before using it<commit_after>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#include <limits>

#include "vvglew.h"
#include "vvibrclient.h"
#include "vvgltools.h"
#include "vvtexrend.h"
#include "float.h"
#include "vvrayrend.h"
#include "vvshaderfactory.h"
#include "vvshaderprogram.h"
#include "vvtoolshed.h"

using std::cerr;
using std::endl;

vvIbrClient::vvIbrClient(vvVolDesc *vd, vvRenderState renderState,
                         const char* slaveName, int slavePort,
                         const char* slaveFileName,
                         const vvIbrImage::DepthPrecision dp)
  : vvRemoteClient(vd, renderState, slaveName, slavePort, slaveFileName),
    _depthPrecision(dp)
{
  vvDebugMsg::msg(1, "vvIbrClient::vvIbrClient()");

  rendererType = REMOTE_IBR;

  _thread = NULL;
  _threadData = NULL;

  glewInit();
  glGenBuffers(1, &_pointVBO);
  glGenBuffers(1, &_indexBO);
  glGenBuffers(1, &_colorVBO);

  glEnable(GL_TEXTURE_2D);
  glGenTextures(3, _ibrTex);

  _haveFrame = false; // no rendered frame available
  _newFrame = true; // request a new frame

  _shaderFactory = new vvShaderFactory();
  _shader = _shaderFactory->createProgram("ibr", "", "");

  pthread_mutex_init(&_slaveMutex, NULL);

  createImages();
  createThreads();
}

vvIbrClient::~vvIbrClient()
{
  vvDebugMsg::msg(1, "vvIbrClient::~vvIbrClient()");

  destroyThreads();
  glDeleteBuffers(1, &_pointVBO);
  glDeleteBuffers(1, &_indexBO);
  glDeleteBuffers(1, &_colorVBO);
  glDeleteTextures(3, _ibrTex);
  delete _shaderFactory;
  delete _shader;
}

vvRemoteClient::ErrorType vvIbrClient::render()
{
  vvDebugMsg::msg(1, "vvIbrClient::render()");

  // Draw boundary lines
  if (_boundaries)
  {
    const vvVector3 size(vd->getSize()); // volume size [world coordinates]
    drawBoundingBox(&size, &vd->pos, &_boundColor);
  }

  if (_shader == NULL)
  {
    return vvRemoteClient::VV_SHADER_ERROR;
  }

  pthread_mutex_lock(&_slaveMutex);
  bool haveFrame = _haveFrame;
  bool newFrame = _newFrame;
  pthread_mutex_unlock(&_slaveMutex);

  vvGLTools::getModelviewMatrix(&_currentMv);
  vvGLTools::getProjectionMatrix(&_currentPr);
  vvMatrix currentMatrix = _currentMv * _currentPr;

  if(newFrame && haveFrame)
  {
    pthread_mutex_lock(&_slaveMutex);
    initIbrFrame();
    pthread_mutex_unlock(&_slaveMutex);
  }

  if (newFrame) // no frame pending
  {
    // request new ibr frame if anything changed
    vvMatrix imgMatrix;
    if (_ibrImg != NULL)
    {
      imgMatrix = _ibrImg->getReprojectionMatrix();
    }

    if (!currentMatrix.equal(&imgMatrix))
    {
      _changes = true;
    }

    if(_changes)
    {
      pthread_mutex_lock(&_slaveMutex);
      vvRemoteClient::ErrorType err = requestIbrFrame();
      _newFrame = false;
      pthread_mutex_unlock(&_slaveMutex);
      _changes = false;
      if(err != vvRemoteClient::VV_OK)
        std::cerr << "vvibrClient::requestIbrFrame() - error() " << err << std::endl;
    }
  }

  if(!haveFrame)
  {
    // no frame was yet received
    return VV_OK;
  }

  // Index Buffer Object for points
  const Corner c = getNearestCorner();
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBO);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indexArray[c].size() * sizeof(GLuint), &(_indexArray[c])[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // prepare VBOs
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glVertexPointer(3, GL_FLOAT, 0, NULL);
  glEnableClientState(GL_VERTEX_ARRAY);

  glBindBuffer(GL_ARRAY_BUFFER, _colorVBO);
  glColorPointer(4, GL_UNSIGNED_BYTE, 0, NULL);
  glEnableClientState(GL_COLOR_ARRAY);

  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBO);

  _shader->enable();

  vvMatrix imgMatrix = _ibrImg->getReprojectionMatrix();
  vvMatrix invImgMatrix;
  invImgMatrix.copy(&imgMatrix);

  vvMatrix reprojectionMatrix = _ibrImg->getReprojectionMatrix() * currentMatrix;

  reprojectionMatrix.transpose();

  float reprojectionMatrixGL[16];
  reprojectionMatrix.get(reprojectionMatrixGL);
  _shader->setParameterMatrix4f("reprojectionMatrix" , reprojectionMatrixGL);

  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  glDrawElements(GL_POINTS, _width*_height, GL_UNSIGNED_INT, NULL);

  _shader->disable();

  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);

  glBindBuffer(GL_ARRAY_BUFFER, 0);

  glFlush();

  return VV_OK;
}

vvRemoteClient::ErrorType vvIbrClient::requestIbrFrame()
{
  vvDebugMsg::msg(1, "vvIbrClient::requestIbrFrame()");

  if(_socket->putCommReason(vvSocketIO::VV_MATRIX) != vvSocket::VV_OK)
      return vvRemoteClient::VV_SOCKET_ERROR;

  if(_socket->putMatrix(&_currentPr) != vvSocket::VV_OK)
      return vvRemoteClient::VV_SOCKET_ERROR;

  if(_socket->putMatrix(&_currentMv) != vvSocket::VV_OK)
      return vvRemoteClient::VV_SOCKET_ERROR;

  return vvRemoteClient::VV_OK;
}

void vvIbrClient::initIbrFrame()
{
  vvDebugMsg::msg(1, "vvIbrClient::initIbrFrame()");

  _ibrImg = dynamic_cast<vvIbrImage*>(_threadData->images->at(0));
  if(!_ibrImg)
    return;

  const int h = _ibrImg->getHeight();
  const int w = _ibrImg->getWidth();
  _width = w;
  _height = h;

  // get pixel and depth-data
  uchar* dataRGBA = _ibrImg->getImagePtr();
  std::vector<float> depth(w*h);
  switch(_depthPrecision)
  {
  case vvIbrImage::VV_UCHAR:
    {
      uchar* d_uchar = _ibrImg->getpixeldepthUchar();
      for(int y = 0; y<h; y++)
        for(int x = 0; x<w; x++)
          depth[y*w+x] = float(d_uchar[y*w+x]) / float(UCHAR_MAX);
    }
    break;
  case vvIbrImage::VV_USHORT:
    {
      ushort* d_ushort = _ibrImg->getpixeldepthUshort();
      for(int y = 0; y<h; y++)
        for(int x = 0; x<w; x++)
          depth[y*w+x] = float(d_ushort[y*w+x]) / float(USHRT_MAX);
    }
    break;
  case vvIbrImage::VV_UINT:
    {
      uint* d_uint = _ibrImg->getpixeldepthUint();
      for(int y = 0; y<h; y++)
        for(int x = 0; x<w; x++)
          depth[y*w+x] = float(d_uint[y*w+x]) / float(UINT_MAX);
    }
    break;
  }

  std::vector<GLubyte> colors(w*h*4);
  std::vector<GLfloat> points(w*h*3);

  for(int y = 0; y<h; y++)
  {
    for(int x = 0; x<w; x++)
    {
      int colorIndex = (y*w+x)*4;

      // save color
      colors[colorIndex]   = dataRGBA[colorIndex];
      colors[colorIndex+1] = dataRGBA[colorIndex+1];
      colors[colorIndex+2] = dataRGBA[colorIndex+2];

      if(depth[y*w+x] <= 0.0f || depth[y*w+x] >= 1.0f)
        colors[colorIndex+3] = 0;
      else
        colors[colorIndex+3] = static_cast<GLubyte>(dataRGBA[colorIndex+3]);

      points[y*w*3+x*3]   = x;
      points[y*w*3+x*3+1] = y;
      points[y*w*3+x*3+2] = (depth[y*w+x] <= 0.0f) ? 1.0f : depth[y*w+x];
    }
  }

  // VBO for points
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  // VBO for colors
  glBindBuffer(GL_ARRAY_BUFFER, _colorVBO);
  glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLubyte), &colors[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  glBindBuffer(GL_ARRAY_BUFFER, 0);

  initIndexArrays();
}

void vvIbrClient::exit()
{
  vvDebugMsg::msg(1, "vvIbrClient::exit()");

  _socket->putCommReason(vvSocketIO::VV_EXIT);
  delete _socket;
}

void vvIbrClient::initIndexArrays()
{
  vvDebugMsg::msg(3, "vvIbrClient::initIndexArray()");

  const int width = _width;
  const int height = _height;

  for (int i = 0; i < 4; ++i)
  {
    _indexArray[i].clear();
  }

  // Top-left to bottom-right.
  for (int y = 0; y < height; ++y)
  {
    for (int x = 0; x < width; ++x)
    {
      _indexArray[VV_TOP_LEFT].push_back(y * width + x);
    }
  }

  // Top-right to bottom-left.
  for (int y = 0; y < height; ++y)
  {
    for (int x = width - 1; x >= 0; --x)
    {
      _indexArray[VV_TOP_RIGHT].push_back(y * width + x);
    }
  }

  // Bottom-right to top-left.
  for (int y = height - 1; y >= 0; --y)
  {
    for (int x = width - 1; x >= 0; --x)
    {
      _indexArray[VV_BOTTOM_RIGHT].push_back(y * width + x);
    }
  }

  // Bottom-left to top-right.
  for (int y = height - 1; y >= 0; --y)
  {
    for (int x = 0; x < width; ++x)
    {
      _indexArray[VV_BOTTOM_LEFT].push_back(y * width + x);
    }
  }
}

vvIbrClient::Corner vvIbrClient::getNearestCorner() const
{
  vvDebugMsg::msg(3, "vvIbrClient::getNearestCorner()");

  vvVector4 normal = vvVector4(0.0f, 0.0f, 1.0f, 1.0f);

  // Cancel out old matrix from normal.
  vvMatrix oldMatrix = _ibrImg->getReprojectionMatrix();
  // The operations below cancel each other out.
  // Left the code this way for higher legibility.
  // Vectors are transformed.
  oldMatrix.invert();
  oldMatrix.transpose();
  oldMatrix.invert();
  normal.multiply(&oldMatrix);

  vvMatrix newMatrix = _currentMv * _currentPr;
  newMatrix.transpose();
  newMatrix.invert();
  normal.multiply(&newMatrix);

  if ((normal[0] < normal[1]) && (normal[0] < 0.0f))
  {
    return VV_TOP_LEFT;
  }
  else if ((normal[0] >= normal[1]) && (normal[0] >= 0.0f))
  {
    return VV_TOP_RIGHT;
  }
  else if ((normal[1] < normal[0]) && (normal[1] < 0.0f))
  {
    return VV_BOTTOM_RIGHT;
  }
  else if ((normal[1] >= normal[0]) && (normal[1] >= 0.0f))
  {
    return VV_BOTTOM_LEFT;
  }
  else
  {
    // Arbitrary default.
    return VV_TOP_LEFT;
  }
}

void vvIbrClient::createThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::createThreads()");

  _threadData = new ThreadArgs;
  _thread = new pthread_t;
  _threadData->renderMaster = this;
  _threadData->images = &_images;
  pthread_create(_thread, NULL, getImageFromSocket, _threadData);
}

void vvIbrClient::destroyThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::destroyThreads()");

  exit();
  pthread_cancel(*_thread);
  pthread_join(*_thread, NULL);
  delete _thread;
  delete _threadData;
  _thread = NULL;
  _threadData = NULL;
}

void vvIbrClient::setDepthPrecision(vvIbrImage::DepthPrecision dp)
{
  vvDebugMsg::msg(3, "vvIbrClient::setDepthPrecision()");

  _depthPrecision = dp;
}

void* vvIbrClient::getImageFromSocket(void* threadargs)
{
  vvDebugMsg::msg(1, "vvIbrClient::getImageFromSocket()");

  std::cerr << "Image thread start" << std::endl;

  ThreadArgs* data = static_cast<ThreadArgs*>(threadargs);

  while (1)
  {
    vvIbrImage* img = static_cast<vvIbrImage *>(data->images->at(1));
    img->setDepthPrecision(data->renderMaster->_depthPrecision);

    vvSocketIO::ErrorType err = data->renderMaster->_socket->getIbrImage(img);
    img->decode();
    if(err != vvSocketIO::VV_OK)
    {
      std::cerr << "vvIbrClient::getImageFromSocket: socket-error (" << err << ") - exiting..." << std::endl;
      break;
    }
#ifdef _WIN32
    Sleep(1000);
#else
    usleep(1000000);
#endif
    // switch pointers securely
    pthread_mutex_lock( &data->renderMaster->_slaveMutex );
    std::swap(data->images->at(0), data->images->at(1));
    data->renderMaster->_newFrame = true;
    data->renderMaster->_haveFrame = true;
    pthread_mutex_unlock( &data->renderMaster->_slaveMutex );
  }
  pthread_exit(NULL);
#ifdef _WIN32
  return NULL;
#endif
}

void vvIbrClient::createImages()
{
  vvDebugMsg::msg(3, "vvIbrClient::createImages()");
  for(int i=0; i<2; ++i)
    _images.push_back(new vvIbrImage);
}
<|endoftext|>


<commit_before>/**
    This file is part of Deformable Shape Tracking (DEST).

    Copyright(C) 2015/2016 Christoph Heindl
    All rights reserved.

    This software may be modified and distributed under the terms
    of the BSD license.See the LICENSE file for details.
*/

#include <dest/dest.h>

#include <dest/io/database_io.h>
#include <dest/face/face_detector.h>
#include <dest/io/rect_io.h>
#include <dest/util/draw.h>
#include <dest/util/convert.h>
#include <dest/util/log.h>
#include <iostream>
#include <opencv2/opencv.hpp>

#include <tclap/CmdLine.h>
#include <opencv2/core/ocl.hpp>

float ratioRectShapeOverlap(const dest::core::Rect &r, const dest::core::Shape &s) {
    Eigen::Vector2f minC = r.col(0);
    Eigen::Vector2f maxC = r.col(3);

    int numOverlap = 0;
    for (dest::core::Shape::Index i = 0; i < s.cols(); ++i) {
        Eigen::Vector2f a = s.col(i) - minC;
        Eigen::Vector2f b = s.col(i) - maxC;

        if ((a.array() >= 0.f).all() && (b.array() <= 0.f).all())
            numOverlap += 1;
    }

    return (float)numOverlap / (float)s.cols();
}

/**
    Generate face rectangles for tracker training using OpenCV face detector.

    dest::Tracker training requires initial bounding rectangles to learn from. Use this
    tool to generate rectangles for an exisiting face/shape database.
*/
int main(int argc, char **argv)
{
    enum FallbackMode {
        Fallback_SimulateOpenCV,
        Fallback_TightBounds,
        Fallback_Skip
    };

    struct {
        std::vector<std::string> detectors;
        std::string db;
        std::string output;
        FallbackMode fbm;
        int loadMaxSize;
    } opts;

    try {
        TCLAP::CmdLine cmd("Generate initial bounding boxes for face detection using Viola-Jones algorithm in OpenCV.", ' ', "0.9");
        TCLAP::MultiArg<std::string> detectorsArg("d", "detector", "OpenCV classifier to load", true, "string");
        TCLAP::ValueArg<std::string> outputArg("o", "output", "CSV output file", false, "rectangles.csv", "string");
        TCLAP::ValueArg<std::string> fallbackArg("", "fallback", "What to do when OpenCV detector fails. Default is skip", false, "skip", "simulatecv, tightbounds, skip");

        TCLAP::ValueArg<int> maxImageSizeArg("", "load-max-size", "Maximum size of images in the database", false, 2048, "int");
        TCLAP::UnlabeledValueArg<std::string> databaseArg("database", "Path to database directory to load", true, "./db", "string");

        cmd.add(&detectorsArg);
        cmd.add(&outputArg);
        cmd.add(&maxImageSizeArg);
        cmd.add(&fallbackArg);
        cmd.add(&databaseArg);

        cmd.parse(argc, argv);

        opts.detectors.insert(opts.detectors.end(), detectorsArg.begin(), detectorsArg.end());
        opts.db = databaseArg.getValue();
        opts.output = outputArg.getValue();
        opts.loadMaxSize = maxImageSizeArg.getValue();

        if (fallbackArg.getValue() == "simulatecv") {
            opts.fbm = Fallback_SimulateOpenCV;
        } else if (fallbackArg.getValue() == "tightbounds") {
            opts.fbm = Fallback_TightBounds;
        } else if (fallbackArg.getValue() == "skip") {
            opts.fbm = Fallback_Skip;
        } else {
            throw TCLAP::ArgException("Unknwon fallback method", fallbackArg.getName());
        }

    }
    catch (TCLAP::ArgException &e) {
        std::cerr << "Error: " << e.error() << " for arg " << e.argId() << std::endl;
        return -1;
    }

    // Note that OpenCV 3.0 / CascadeClassifier seems to have troubles when being reused.
    // Current solution is to disable OpenCL
    // See https://github.com/Itseez/opencv/issues/5475
    cv::ocl::setUseOpenCL(false);

    dest::io::ShapeDatabase sd;
    sd.setMaxImageLoadSize(opts.loadMaxSize);

    std::vector<dest::core::Rect> rects;
    std::vector<float> scalings;
    dest::core::InputData inputs;
    if (!sd.load(opts.db, inputs.images, inputs.shapes, rects, &scalings)) {
        std::cerr << "Failed to load database." << std::endl;
        return -1;
    }

    std::vector<dest::face::FaceDetector> detectors(opts.detectors.size());
    for (size_t i = 0; i < opts.detectors.size(); ++i) {
        if (!detectors[i].loadClassifiers(opts.detectors[i])) {
            std::cout << "Failed to load detector " << opts.detectors[i];
            return -1;
        }
    }

    size_t countDetectionSuccess = 0;

    // The OpenCV detector rectangles are significantly different from tight bounds.
    // The values below attempt to match simulate face rects from tight bounds
    // (used when the detector fails).
    float scaleToCV = 1.25f; // Scale between rectangles
    float txToCV = -0.01f;   // Translation in x normalized by image width
    float tyToCV = -0.05f;   // Translation in y normalized by image height

    for (size_t i = 0; i < rects.size(); ++i) {

        std::vector<dest::core::Rect> faces;
        for (size_t j = 0; j < detectors.size(); ++j) {
            std::vector<dest::core::Rect> myrects;
            detectors[j].detectFaces(inputs.images[i], myrects);
            faces.insert(faces.end(), myrects.begin(), myrects.end());
        }

        // Find the face rect with a meaningful shape overlap
        float bestOverlap = 0.f;
        size_t bestId = std::numeric_limits<size_t>::max();

        for (size_t j = 0; j < faces.size(); ++j) {
            float o = ratioRectShapeOverlap(faces[j], inputs.shapes[i]);
            if (o > bestOverlap) {
                bestId = j;
                bestOverlap = o;
            }
        }

        const bool detectionSuccess = (bestId != std::numeric_limits<size_t>::max() && bestOverlap >= 0.5f);

        if (!detectionSuccess) {

            switch(opts.fbm) {
                case Fallback_SimulateOpenCV: {
                    dest::core::Rect r = dest::core::shapeBounds(inputs.shapes[i]);
                    // Match CV detector

                    Eigen::AffineCompact2f t;
                    t.setIdentity();
                    t = Eigen::Translation2f(txToCV * inputs.images[i].cols(), tyToCV * inputs.images[i].rows()) * Eigen::Scaling(scaleToCV);
                    r = t * r.colwise().homogeneous();
                    // Match original image size.
                    rects[i] =  r / scalings[i];
                    break;
                }
                case Fallback_TightBounds: {
                    dest::core::Rect r = dest::core::shapeBounds(inputs.shapes[i]);
                    rects[i] = r / scalings[i];
                    break;
                }
                case Fallback_Skip: {
                    rects[i] = dest::core::Rect::Zero(2, 4);
                    break;
                }
            }

        } else {
            ++countDetectionSuccess;
            rects[i] = faces[bestId] / scalings[i];
        }

        if (i % 10 == 0) {
            std::cout << "Processing " << i << "\r" << std::flush;
        }
    }
    std::cout << "Detector successful on " << countDetectionSuccess << "/" << rects.size() << " shapes." << std::endl;

    dest::io::exportRectangles(opts.output, rects);

    return 0;
}
<commit_msg>OpenCV 2.4 compatibility<commit_after>/**
    This file is part of Deformable Shape Tracking (DEST).

    Copyright(C) 2015/2016 Christoph Heindl
    All rights reserved.

    This software may be modified and distributed under the terms
    of the BSD license.See the LICENSE file for details.
*/

#include <dest/dest.h>

#include <dest/io/database_io.h>
#include <dest/face/face_detector.h>
#include <dest/io/rect_io.h>
#include <dest/util/draw.h>
#include <dest/util/convert.h>
#include <dest/util/log.h>
#include <iostream>
#include <opencv2/opencv.hpp>

#include <tclap/CmdLine.h>

#include <opencv2/core/version.hpp>
#if (defined(CV_VERSION_MAJOR) && CV_VERSION_MAJOR == 3)
	#include <opencv2/core/ocl.hpp>
#endif

float ratioRectShapeOverlap(const dest::core::Rect &r, const dest::core::Shape &s) {
    Eigen::Vector2f minC = r.col(0);
    Eigen::Vector2f maxC = r.col(3);

    int numOverlap = 0;
    for (dest::core::Shape::Index i = 0; i < s.cols(); ++i) {
        Eigen::Vector2f a = s.col(i) - minC;
        Eigen::Vector2f b = s.col(i) - maxC;

        if ((a.array() >= 0.f).all() && (b.array() <= 0.f).all())
            numOverlap += 1;
    }

    return (float)numOverlap / (float)s.cols();
}

/**
    Generate face rectangles for tracker training using OpenCV face detector.

    dest::Tracker training requires initial bounding rectangles to learn from. Use this
    tool to generate rectangles for an exisiting face/shape database.
*/
int main(int argc, char **argv)
{
    enum FallbackMode {
        Fallback_SimulateOpenCV,
        Fallback_TightBounds,
        Fallback_Skip
    };

    struct {
        std::vector<std::string> detectors;
        std::string db;
        std::string output;
        FallbackMode fbm;
        int loadMaxSize;
    } opts;

    try {
        TCLAP::CmdLine cmd("Generate initial bounding boxes for face detection using Viola-Jones algorithm in OpenCV.", ' ', "0.9");
        TCLAP::MultiArg<std::string> detectorsArg("d", "detector", "OpenCV classifier to load", true, "string");
        TCLAP::ValueArg<std::string> outputArg("o", "output", "CSV output file", false, "rectangles.csv", "string");
        TCLAP::ValueArg<std::string> fallbackArg("", "fallback", "What to do when OpenCV detector fails. Default is skip", false, "skip", "simulatecv, tightbounds, skip");

        TCLAP::ValueArg<int> maxImageSizeArg("", "load-max-size", "Maximum size of images in the database", false, 2048, "int");
        TCLAP::UnlabeledValueArg<std::string> databaseArg("database", "Path to database directory to load", true, "./db", "string");

        cmd.add(&detectorsArg);
        cmd.add(&outputArg);
        cmd.add(&maxImageSizeArg);
        cmd.add(&fallbackArg);
        cmd.add(&databaseArg);

        cmd.parse(argc, argv);

        opts.detectors.insert(opts.detectors.end(), detectorsArg.begin(), detectorsArg.end());
        opts.db = databaseArg.getValue();
        opts.output = outputArg.getValue();
        opts.loadMaxSize = maxImageSizeArg.getValue();

        if (fallbackArg.getValue() == "simulatecv") {
            opts.fbm = Fallback_SimulateOpenCV;
        } else if (fallbackArg.getValue() == "tightbounds") {
            opts.fbm = Fallback_TightBounds;
        } else if (fallbackArg.getValue() == "skip") {
            opts.fbm = Fallback_Skip;
        } else {
            throw TCLAP::ArgException("Unknwon fallback method", fallbackArg.getName());
        }

    }
    catch (TCLAP::ArgException &e) {
        std::cerr << "Error: " << e.error() << " for arg " << e.argId() << std::endl;
        return -1;
    }

    // Note that OpenCV 3.0 / CascadeClassifier seems to have troubles when being reused.
    // Current solution is to disable OpenCL
    // See https://github.com/Itseez/opencv/issues/5475
	#if (defined(CV_VERSION_MAJOR) && CV_VERSION_MAJOR == 3)
		cv::ocl::setUseOpenCL(false);
	#endif

    dest::io::ShapeDatabase sd;
    sd.setMaxImageLoadSize(opts.loadMaxSize);

    std::vector<dest::core::Rect> rects;
    std::vector<float> scalings;
    dest::core::InputData inputs;
    if (!sd.load(opts.db, inputs.images, inputs.shapes, rects, &scalings)) {
        std::cerr << "Failed to load database." << std::endl;
        return -1;
    }

    std::vector<dest::face::FaceDetector> detectors(opts.detectors.size());
    for (size_t i = 0; i < opts.detectors.size(); ++i) {
        if (!detectors[i].loadClassifiers(opts.detectors[i])) {
            std::cout << "Failed to load detector " << opts.detectors[i];
            return -1;
        }
    }

    size_t countDetectionSuccess = 0;

    // The OpenCV detector rectangles are significantly different from tight bounds.
    // The values below attempt to match simulate face rects from tight bounds
    // (used when the detector fails).
    float scaleToCV = 1.25f; // Scale between rectangles
    float txToCV = -0.01f;   // Translation in x normalized by image width
    float tyToCV = -0.05f;   // Translation in y normalized by image height

    for (size_t i = 0; i < rects.size(); ++i) {

        std::vector<dest::core::Rect> faces;
        for (size_t j = 0; j < detectors.size(); ++j) {
            std::vector<dest::core::Rect> myrects;
            detectors[j].detectFaces(inputs.images[i], myrects);
            faces.insert(faces.end(), myrects.begin(), myrects.end());
        }

        // Find the face rect with a meaningful shape overlap
        float bestOverlap = 0.f;
        size_t bestId = std::numeric_limits<size_t>::max();

        for (size_t j = 0; j < faces.size(); ++j) {
            float o = ratioRectShapeOverlap(faces[j], inputs.shapes[i]);
            if (o > bestOverlap) {
                bestId = j;
                bestOverlap = o;
            }
        }

        const bool detectionSuccess = (bestId != std::numeric_limits<size_t>::max() && bestOverlap >= 0.5f);

        if (!detectionSuccess) {

            switch(opts.fbm) {
                case Fallback_SimulateOpenCV: {
                    dest::core::Rect r = dest::core::shapeBounds(inputs.shapes[i]);
                    // Match CV detector

                    Eigen::AffineCompact2f t;
                    t.setIdentity();
                    t = Eigen::Translation2f(txToCV * inputs.images[i].cols(), tyToCV * inputs.images[i].rows()) * Eigen::Scaling(scaleToCV);
                    r = t * r.colwise().homogeneous();
                    // Match original image size.
                    rects[i] =  r / scalings[i];
                    break;
                }
                case Fallback_TightBounds: {
                    dest::core::Rect r = dest::core::shapeBounds(inputs.shapes[i]);
                    rects[i] = r / scalings[i];
                    break;
                }
                case Fallback_Skip: {
                    rects[i] = dest::core::Rect::Zero(2, 4);
                    break;
                }
            }

        } else {
            ++countDetectionSuccess;
            rects[i] = faces[bestId] / scalings[i];
        }

        if (i % 10 == 0) {
            std::cout << "Processing " << i << "\r" << std::flush;
        }
    }
    std::cout << "Detector successful on " << countDetectionSuccess << "/" << rects.size() << " shapes." << std::endl;

    dest::io::exportRectangles(opts.output, rects);

    return 0;
}
<|endoftext|>


<commit_before>/* Twofold-Qt
 * (C) Copyright 2014 HicknHack Software GmbH
 *
 * The original code can be found at:
 *     https://github.com/hicknhack-software/Twofold-Qt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "SourceMapTextBuilder.h"

namespace Twofold {
namespace intern {

SourceMapText SourceMapTextBuilder::build() const
{
    return SourceMapText { SourceMapping(m_sourceData), m_textBuilder.build() };
}

void SourceMapTextBuilder::pushCaller(const FileLineColumnPosition &originPosition)
{
    auto parentIndex = m_callerIndexStack.empty() ? CallerIndex{} : m_callerIndexStack.back();
    auto index = CallerIndex{ (int)SourceMap::get< ExtCaller >(m_sourceData).size()};
    SourceMap::get< ExtCaller >(m_sourceData).push_back(Caller { originPosition, parentIndex });
    m_callerIndexStack.push_back(index);
}

void SourceMapTextBuilder::popCaller()
{
    m_callerIndexStack.pop_back();
}

SourceMapTextBuilder &SourceMapTextBuilder::operator <<(const OriginText &originText)
{
    if (originText.span.begin == originText.span.end)
        return *this; // empty span would create double entries

    auto callerIndex = m_callerIndexStack.empty() ? CallerIndex{} : m_callerIndexStack.back();

    auto callers = SourceMap::get< ExtCaller >(m_sourceData);
    const auto indexValue = callerIndex.value;
    if (indexValue >= 0 && indexValue < callers.size()) {
        // this happens for expressions #{<expr>} because pushCaller and this operator is called with the same originPosition
        if (callers[callerIndex.value].original == originText.origin) {
            // take parent index
            callerIndex.value = callers[indexValue].parentIndex.value;

            // remove caller
            callers.erase(callers.begin() + indexValue);
        }
    }

    m_sourceData.addEntry({{m_textBuilder.line(), m_textBuilder.column()},
                            originText.origin,
                            std::make_tuple(originText.interpolation, callerIndex)});

    m_textBuilder << originText.span;
    return *this;
}

SourceMapTextBuilder &SourceMapTextBuilder::operator <<(const OriginNewLine &originNewLine)
{
    const auto callerIndex = m_callerIndexStack.empty() ? CallerIndex{} : m_callerIndexStack.back();
    const auto column = isBlankLine() ? std::max(1, originNewLine.origin.column - 1) : originNewLine.origin.column;
    m_sourceData.addEntry({{m_textBuilder.line(), m_textBuilder.column()},
                           {originNewLine.origin.name, {originNewLine.origin.line, column}},
                            std::make_tuple(Interpolation::None, callerIndex)});

    m_textBuilder << NewLine();
    return *this;
}

SourceMapTextBuilder &SourceMapTextBuilder::operator <<(const NewLine)
{
    m_textBuilder << NewLine();
    return *this;
}

} // namespace intern
} // namespace Twofold
<commit_msg>* fixed compiler warning<commit_after>/* Twofold-Qt
 * (C) Copyright 2014 HicknHack Software GmbH
 *
 * The original code can be found at:
 *     https://github.com/hicknhack-software/Twofold-Qt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "SourceMapTextBuilder.h"

namespace Twofold {
namespace intern {

SourceMapText SourceMapTextBuilder::build() const
{
    return SourceMapText { SourceMapping(m_sourceData), m_textBuilder.build() };
}

void SourceMapTextBuilder::pushCaller(const FileLineColumnPosition &originPosition)
{
    auto parentIndex = m_callerIndexStack.empty() ? CallerIndex{} : m_callerIndexStack.back();
    auto index = CallerIndex{ (int)SourceMap::get< ExtCaller >(m_sourceData).size()};
    SourceMap::get< ExtCaller >(m_sourceData).push_back(Caller { originPosition, parentIndex });
    m_callerIndexStack.push_back(index);
}

void SourceMapTextBuilder::popCaller()
{
    m_callerIndexStack.pop_back();
}

SourceMapTextBuilder &SourceMapTextBuilder::operator <<(const OriginText &originText)
{
    if (originText.span.begin == originText.span.end)
        return *this; // empty span would create double entries

    auto callerIndex = m_callerIndexStack.empty() ? CallerIndex{} : m_callerIndexStack.back();

    auto callers = SourceMap::get< ExtCaller >(m_sourceData);
    const auto indexValue = callerIndex.value;
    if (indexValue >= 0 && static_cast<CallerList::size_type>(indexValue) < callers.size()) {
        // this happens for expressions #{<expr>} because pushCaller and this operator is called with the same originPosition
        if (callers[callerIndex.value].original == originText.origin) {
            // take parent index
            callerIndex.value = callers[indexValue].parentIndex.value;

            // remove caller
            callers.erase(callers.begin() + indexValue);
        }
    }

    m_sourceData.addEntry({{m_textBuilder.line(), m_textBuilder.column()},
                            originText.origin,
                            std::make_tuple(originText.interpolation, callerIndex)});

    m_textBuilder << originText.span;
    return *this;
}

SourceMapTextBuilder &SourceMapTextBuilder::operator <<(const OriginNewLine &originNewLine)
{
    const auto callerIndex = m_callerIndexStack.empty() ? CallerIndex{} : m_callerIndexStack.back();
    const auto column = isBlankLine() ? std::max(1, originNewLine.origin.column - 1) : originNewLine.origin.column;
    m_sourceData.addEntry({{m_textBuilder.line(), m_textBuilder.column()},
                           {originNewLine.origin.name, {originNewLine.origin.line, column}},
                            std::make_tuple(Interpolation::None, callerIndex)});

    m_textBuilder << NewLine();
    return *this;
}

SourceMapTextBuilder &SourceMapTextBuilder::operator <<(const NewLine)
{
    m_textBuilder << NewLine();
    return *this;
}

} // namespace intern
} // namespace Twofold
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "ExecFlagRegistry.h"

#include "MooseUtils.h"

namespace moose
{
namespace internal
{

ExecFlagRegistry &
getExecFlagRegistry()
{
  static ExecFlagRegistry exec_flag_registry;
  return exec_flag_registry;
}

ExecFlagRegistry::ExecFlagRegistry() {}

const ExecFlagType &
ExecFlagRegistry::registerFlag(const std::string & name)
{
  const auto name_upper = MooseUtils::toUpper(name);

  {
    std::shared_lock lock(_flags_mutex);
    if (_flags.contains(name))
      mooseError("The exec flag ", name_upper, "is already registered");
  }

  {
    std::unique_lock lock(_flags_mutex);
    return _flags.addAvailableFlags(ExecFlagType(name_upper, _flags.getNextValidID()));
  }
}

}
}
<commit_msg>Add missing header and clean up locks<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "ExecFlagRegistry.h"

#include <mutex>

#include "MooseUtils.h"

namespace moose
{
namespace internal
{

ExecFlagRegistry &
getExecFlagRegistry()
{
  static ExecFlagRegistry exec_flag_registry;
  return exec_flag_registry;
}

ExecFlagRegistry::ExecFlagRegistry() {}

const ExecFlagType &
ExecFlagRegistry::registerFlag(const std::string & name)
{
  const auto name_upper = MooseUtils::toUpper(name);
  std::unique_lock lock(_flags_mutex);
  if (_flags.contains(name))
    mooseError("The exec flag ", name_upper, "is already registered");
  return _flags.addAvailableFlags(ExecFlagType(name_upper, _flags.getNextValidID()));
}

}
}
<|endoftext|>