<commit_before>//===-- PowerPCTargetMachine.cpp - Define TargetMachine for PowerPC -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "PowerPC.h"
#include "PowerPCTargetMachine.h"
#include "PowerPCFrameInfo.h"
#include "PPC32TargetMachine.h"
#include "PPC64TargetMachine.h"
#include "PPC32JITInfo.h"
#include "PPC64JITInfo.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "Support/CommandLine.h"
#include <iostream>
using namespace llvm;

namespace llvm {
  cl::opt<bool> AIX("aix",
                    cl::desc("Generate AIX/xcoff instead of Darwin/MachO"),
                    cl::Hidden);
}

namespace {
  const std::string PPC32 = "PowerPC/32bit";
  const std::string PPC64 = "PowerPC/64bit";

  // Register the targets
  RegisterTarget<PPC32TargetMachine>
  X("ppc32", "  PowerPC 32-bit (experimental)");
  //RegisterTarget<PPC64TargetMachine>
  //Y("ppc64", "  PowerPC 64-bit (unimplemented)");
}

PowerPCTargetMachine::PowerPCTargetMachine(const std::string &name,
                                           IntrinsicLowering *IL,
                                           const TargetData &TD,
                                           const PowerPCFrameInfo &TFI,
                                           const PowerPCJITInfo &TJI,
                                           bool is64b)
  : TargetMachine(name, IL, TD), InstrInfo(is64b), FrameInfo(TFI), JITInfo(TJI)
{}

unsigned PowerPCTargetMachine::getJITMatchQuality() {
#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
  return 10;
#else
  return 0;
#endif
}

/// addPassesToEmitAssembly - Add passes to the specified pass manager
/// to implement a static compiler for this target.
///
bool PowerPCTargetMachine::addPassesToEmitAssembly(PassManager &PM,
                                                   std::ostream &Out) {
  bool LP64 = (0 != dynamic_cast<PPC64TargetMachine *>(this));

  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // FIXME: Implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // FIXME: Implement the switch instruction in the instruction selector!
  PM.add(createLowerSwitchPass());

  PM.add(createLowerConstantExpressionsPass());

  // Make sure that no unreachable blocks are instruction selected.
  PM.add(createUnreachableBlockEliminationPass());

  if (LP64)
    PM.add(createPPC64ISelSimple(*this));
  else
    PM.add(createPPC32ISelSimple(*this));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr));

  PM.add(createRegisterAllocator());

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr));

  PM.add(createPrologEpilogCodeInserter());

  // Must run branch selection immediately preceding the asm printer
  PM.add(createPPCBranchSelectionPass());

  if (AIX)
    PM.add(createPPC64AsmPrinter(Out, *this));
  else
    PM.add(createPPCAsmPrinter(Out, *this));

  PM.add(createMachineCodeDeleter());
  return false;
}

void PowerPCJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // FIXME: Implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // FIXME: Implement the switch instruction in the instruction selector!
  PM.add(createLowerSwitchPass());

  PM.add(createLowerConstantExpressionsPass());

  // Make sure that no unreachable blocks are instruction selected.
  PM.add(createUnreachableBlockEliminationPass());

  PM.add(createPPC32ISelSimple(TM));
  PM.add(createRegisterAllocator());
  PM.add(createPrologEpilogCodeInserter());
}

void PowerPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
  assert(0 && "Cannot execute PowerPCJITInfo::replaceMachineCodeForFunction()");
}

void *PowerPCJITInfo::getJITStubForFunction(Function *F,
                                            MachineCodeEmitter &MCE) {
  assert(0 && "Cannot execute PowerPCJITInfo::getJITStubForFunction()");
  return 0;
}

/// PowerPCTargetMachine ctor - Create an ILP32 architecture model
///
PPC32TargetMachine::PPC32TargetMachine(const Module &M,
                                               IntrinsicLowering *IL)
  : PowerPCTargetMachine(PPC32, IL,
                         TargetData(PPC32,false,4,4,4,4,4,4,2,1,4),
                         PowerPCFrameInfo(*this), PPC32JITInfo(*this), false) {}

/// PPC64TargetMachine ctor - Create a LP64 architecture model
///
PPC64TargetMachine::PPC64TargetMachine(const Module &M, IntrinsicLowering *IL)
  : PowerPCTargetMachine(PPC64, IL,
                         TargetData(PPC64,false,8,4,4,4,4,4,2,1,4),
                         PowerPCFrameInfo(*this), PPC64JITInfo(*this), true) {}

unsigned PPC32TargetMachine::getModuleMatchQuality(const Module &M) {
  if (M.getEndianness()  == Module::BigEndian &&
      M.getPointerSize() == Module::Pointer32)
    return 10;                                   // Direct match
  else if (M.getEndianness() != Module::AnyEndianness ||
           M.getPointerSize() != Module::AnyPointerSize)
    return 0;                                    // Match for some other target

  return getJITMatchQuality()/2;
}

unsigned PPC64TargetMachine::getModuleMatchQuality(const Module &M) {
  if (M.getEndianness()  == Module::BigEndian &&
      M.getPointerSize() == Module::Pointer64)
    return 10;                                   // Direct match
  else if (M.getEndianness() != Module::AnyEndianness ||
           M.getPointerSize() != Module::AnyPointerSize)
    return 0;                                    // Match for some other target

  return getJITMatchQuality()/2;
}
<commit_msg>No need for an `is64bit' flag<commit_after>//===-- PowerPCTargetMachine.cpp - Define TargetMachine for PowerPC -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "PowerPC.h"
#include "PowerPCTargetMachine.h"
#include "PowerPCFrameInfo.h"
#include "PPC32TargetMachine.h"
#include "PPC64TargetMachine.h"
#include "PPC32JITInfo.h"
#include "PPC64JITInfo.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "Support/CommandLine.h"
#include <iostream>
using namespace llvm;

namespace llvm {
  cl::opt<bool> AIX("aix",
                    cl::desc("Generate AIX/xcoff instead of Darwin/MachO"),
                    cl::Hidden);
}

namespace {
  const std::string PPC32ID = "PowerPC/32bit";
  const std::string PPC64ID = "PowerPC/64bit";

  // Register the targets
  RegisterTarget<PPC32TargetMachine>
  X("ppc32", "  PowerPC 32-bit (experimental)");
  //RegisterTarget<PPC64TargetMachine>
  //Y("ppc64", "  PowerPC 64-bit (unimplemented)");
}

PowerPCTargetMachine::PowerPCTargetMachine(const std::string &name,
                                           IntrinsicLowering *IL,
                                           const TargetData &TD,
                                           const PowerPCFrameInfo &TFI,
                                           const PowerPCJITInfo &TJI)
  : TargetMachine(name, IL, TD), FrameInfo(TFI), JITInfo(TJI)
{}

unsigned PowerPCTargetMachine::getJITMatchQuality() {
#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)
  return 10;
#else
  return 0;
#endif
}

/// addPassesToEmitAssembly - Add passes to the specified pass manager
/// to implement a static compiler for this target.
///
bool PowerPCTargetMachine::addPassesToEmitAssembly(PassManager &PM,
                                                   std::ostream &Out) {
  bool LP64 = (0 != dynamic_cast<PPC64TargetMachine *>(this));

  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // FIXME: Implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // FIXME: Implement the switch instruction in the instruction selector!
  PM.add(createLowerSwitchPass());

  PM.add(createLowerConstantExpressionsPass());

  // Make sure that no unreachable blocks are instruction selected.
  PM.add(createUnreachableBlockEliminationPass());

  if (LP64)
    PM.add(createPPC64ISelSimple(*this));
  else
    PM.add(createPPC32ISelSimple(*this));

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr));

  PM.add(createRegisterAllocator());

  if (PrintMachineCode)
    PM.add(createMachineFunctionPrinterPass(&std::cerr));

  PM.add(createPrologEpilogCodeInserter());

  // Must run branch selection immediately preceding the asm printer
  PM.add(createPPCBranchSelectionPass());

  if (AIX)
    PM.add(createPPC64AsmPrinter(Out, *this));
  else
    PM.add(createPPC32AsmPrinter(Out, *this));

  PM.add(createMachineCodeDeleter());
  return false;
}

void PowerPCJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
  // FIXME: Implement efficient support for garbage collection intrinsics.
  PM.add(createLowerGCPass());

  // FIXME: Implement the invoke/unwind instructions!
  PM.add(createLowerInvokePass());

  // FIXME: Implement the switch instruction in the instruction selector!
  PM.add(createLowerSwitchPass());

  PM.add(createLowerConstantExpressionsPass());

  // Make sure that no unreachable blocks are instruction selected.
  PM.add(createUnreachableBlockEliminationPass());

  PM.add(createPPC32ISelSimple(TM));
  PM.add(createRegisterAllocator());
  PM.add(createPrologEpilogCodeInserter());
}

void PowerPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
  assert(0 && "Cannot execute PowerPCJITInfo::replaceMachineCodeForFunction()");
}

void *PowerPCJITInfo::getJITStubForFunction(Function *F,
                                            MachineCodeEmitter &MCE) {
  assert(0 && "Cannot execute PowerPCJITInfo::getJITStubForFunction()");
  return 0;
}

/// PowerPCTargetMachine ctor - Create an ILP32 architecture model
///
PPC32TargetMachine::PPC32TargetMachine(const Module &M, IntrinsicLowering *IL)
  : PowerPCTargetMachine(PPC32ID, IL,
                         TargetData(PPC32ID,false,4,4,4,4,4,4,2,1,4),
                         PowerPCFrameInfo(*this), PPC32JITInfo(*this)) {}

/// PPC64TargetMachine ctor - Create a LP64 architecture model
///
PPC64TargetMachine::PPC64TargetMachine(const Module &M, IntrinsicLowering *IL)
  : PowerPCTargetMachine(PPC64ID, IL,
                         TargetData(PPC64ID,false,8,4,4,4,4,4,2,1,4),
                         PowerPCFrameInfo(*this), PPC64JITInfo(*this)) {}

unsigned PPC32TargetMachine::getModuleMatchQuality(const Module &M) {
  if (M.getEndianness()  == Module::BigEndian &&
      M.getPointerSize() == Module::Pointer32)
    return 10;                                   // Direct match
  else if (M.getEndianness() != Module::AnyEndianness ||
           M.getPointerSize() != Module::AnyPointerSize)
    return 0;                                    // Match for some other target

  return getJITMatchQuality()/2;
}

unsigned PPC64TargetMachine::getModuleMatchQuality(const Module &M) {
  if (M.getEndianness()  == Module::BigEndian &&
      M.getPointerSize() == Module::Pointer64)
    return 10;                                   // Direct match
  else if (M.getEndianness() != Module::AnyEndianness ||
           M.getPointerSize() != Module::AnyPointerSize)
    return 0;                                    // Match for some other target

  return getJITMatchQuality()/2;
}
<|endoftext|>


<commit_before>//===- RaiseAllocations.cpp - Convert %malloc & %free calls to insts ------===//
//
// This file defines the RaiseAllocations pass which convert malloc and free
// calls to malloc and free instructions.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/DerivedTypes.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
#include "llvm/Pass.h"
#include "Support/StatisticReporter.h"

static Statistic<> NumRaised("raiseallocs\t- Number of allocations raised");

namespace {

// RaiseAllocations - Turn %malloc and %free calls into the appropriate
// instruction.
//
class RaiseAllocations : public BasicBlockPass {
  Function *MallocFunc;   // Functions in the module we are processing
  Function *FreeFunc;     // Initialized by doPassInitializationVirt
public:
  RaiseAllocations() : MallocFunc(0), FreeFunc(0) {}

  // doPassInitialization - For the raise allocations pass, this finds a
  // declaration for malloc and free if they exist.
  //
  bool doInitialization(Module &M);

  // runOnBasicBlock - This method does the actual work of converting
  // instructions over, assuming that the pass has already been initialized.
  //
  bool runOnBasicBlock(BasicBlock &BB);
};

  RegisterOpt<RaiseAllocations>
  X("raiseallocs", "Raise allocations from calls to instructions");
}  // end anonymous namespace

// createRaiseAllocationsPass - The interface to this file...
Pass *createRaiseAllocationsPass() {
  return new RaiseAllocations();
}

bool RaiseAllocations::doInitialization(Module &M) {
  // If the module has a symbol table, they might be referring to the malloc
  // and free functions.  If this is the case, grab the method pointers that
  // the module is using.
  //
  // Lookup %malloc and %free in the symbol table, for later use.  If they
  // don't exist, or are not external, we do not worry about converting calls
  // to that function into the appropriate instruction.
  //
  const FunctionType *MallocType =   // Get the type for malloc
    FunctionType::get(PointerType::get(Type::SByteTy),
                    std::vector<const Type*>(1, Type::ULongTy), false);

  const FunctionType *FreeType =     // Get the type for free
    FunctionType::get(Type::VoidTy,
                   std::vector<const Type*>(1, PointerType::get(Type::SByteTy)),
                      false);

  // Get Malloc and free prototypes if they exist!
  MallocFunc = M.getFunction("malloc", MallocType);
  FreeFunc   = M.getFunction("free"  , FreeType);

  // Check to see if the prototype is wrong, giving us sbyte*(uint) * malloc
  // This handles the common declaration of: 'void *malloc(unsigned);'
  if (MallocFunc == 0) {
    MallocType = FunctionType::get(PointerType::get(Type::SByteTy),
                            std::vector<const Type*>(1, Type::UIntTy), false);
    MallocFunc = M.getFunction("malloc", MallocType);
  }

  // Check to see if the prototype is missing, giving us sbyte*(...) * malloc
  // This handles the common declaration of: 'void *malloc();'
  if (MallocFunc == 0) {
    MallocType = FunctionType::get(PointerType::get(Type::SByteTy),
                                   std::vector<const Type*>(), true);
    MallocFunc = M.getFunction("malloc", MallocType);
  }

  // Check to see if the prototype was forgotten, giving us void (...) * free
  // This handles the common forward declaration of: 'void free();'
  if (FreeFunc == 0) {
    FreeType = FunctionType::get(Type::VoidTy, std::vector<const Type*>(),true);
    FreeFunc = M.getFunction("free", FreeType);
  }

  // Don't mess with locally defined versions of these functions...
  if (MallocFunc && !MallocFunc->isExternal()) MallocFunc = 0;
  if (FreeFunc && !FreeFunc->isExternal())     FreeFunc = 0;
  return false;
}

// runOnBasicBlock - Process a basic block, fixing it up...
//
bool RaiseAllocations::runOnBasicBlock(BasicBlock &BB) {
  bool Changed = false;
  BasicBlock::InstListType &BIL = BB.getInstList();

  for (BasicBlock::iterator BI = BB.begin(); BI != BB.end(); ++BI) {
    Instruction *I = BI;

    if (CallInst *CI = dyn_cast<CallInst>(I)) {
      if (CI->getCalledValue() == MallocFunc) {      // Replace call to malloc?
        const Type *PtrSByte = PointerType::get(Type::SByteTy);
        Value *Source = CI->getOperand(1);

        // If no prototype was provided for malloc, we may need to cast the
        // source size.
        if (Source->getType() != Type::UIntTy)
          Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", BI);

        std::string Name(CI->getName()); CI->setName("");
        BI = new MallocInst(PtrSByte, Source, Name, BI);
        BIL.erase(I);
        Changed = true;
        ++NumRaised;
      } else if (CI->getCalledValue() == FreeFunc) { // Replace call to free?
        // If no prototype was provided for free, we may need to cast the
        // source pointer.  This should be really uncommon, but it's neccesary
        // just in case we are dealing with wierd code like this:
        //   free((long)ptr);
        //
        Value *Source = CI->getOperand(1);
        if (!isa<PointerType>(Source->getType()))
          Source = new CastInst(Source, PointerType::get(Type::SByteTy),
                                "FreePtrCast", BI);
        BI = new FreeInst(Source, BI);
        BIL.erase(I);
        Changed = true;
        ++NumRaised;
      }
    }
  }

  return Changed;
}
<commit_msg>Fix bug in previous checkin<commit_after>//===- RaiseAllocations.cpp - Convert %malloc & %free calls to insts ------===//
//
// This file defines the RaiseAllocations pass which convert malloc and free
// calls to malloc and free instructions.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/DerivedTypes.h"
#include "llvm/iMemory.h"
#include "llvm/iOther.h"
#include "llvm/Pass.h"
#include "Support/StatisticReporter.h"

static Statistic<> NumRaised("raiseallocs\t- Number of allocations raised");

namespace {

// RaiseAllocations - Turn %malloc and %free calls into the appropriate
// instruction.
//
class RaiseAllocations : public BasicBlockPass {
  Function *MallocFunc;   // Functions in the module we are processing
  Function *FreeFunc;     // Initialized by doPassInitializationVirt
public:
  RaiseAllocations() : MallocFunc(0), FreeFunc(0) {}

  // doPassInitialization - For the raise allocations pass, this finds a
  // declaration for malloc and free if they exist.
  //
  bool doInitialization(Module &M);

  // runOnBasicBlock - This method does the actual work of converting
  // instructions over, assuming that the pass has already been initialized.
  //
  bool runOnBasicBlock(BasicBlock &BB);
};

  RegisterOpt<RaiseAllocations>
  X("raiseallocs", "Raise allocations from calls to instructions");
}  // end anonymous namespace

// createRaiseAllocationsPass - The interface to this file...
Pass *createRaiseAllocationsPass() {
  return new RaiseAllocations();
}

bool RaiseAllocations::doInitialization(Module &M) {
  // If the module has a symbol table, they might be referring to the malloc
  // and free functions.  If this is the case, grab the method pointers that
  // the module is using.
  //
  // Lookup %malloc and %free in the symbol table, for later use.  If they
  // don't exist, or are not external, we do not worry about converting calls
  // to that function into the appropriate instruction.
  //
  const FunctionType *MallocType =   // Get the type for malloc
    FunctionType::get(PointerType::get(Type::SByteTy),
                    std::vector<const Type*>(1, Type::ULongTy), false);

  const FunctionType *FreeType =     // Get the type for free
    FunctionType::get(Type::VoidTy,
                   std::vector<const Type*>(1, PointerType::get(Type::SByteTy)),
                      false);

  // Get Malloc and free prototypes if they exist!
  MallocFunc = M.getFunction("malloc", MallocType);
  FreeFunc   = M.getFunction("free"  , FreeType);

  // Check to see if the prototype is wrong, giving us sbyte*(uint) * malloc
  // This handles the common declaration of: 'void *malloc(unsigned);'
  if (MallocFunc == 0) {
    MallocType = FunctionType::get(PointerType::get(Type::SByteTy),
                            std::vector<const Type*>(1, Type::UIntTy), false);
    MallocFunc = M.getFunction("malloc", MallocType);
  }

  // Check to see if the prototype is missing, giving us sbyte*(...) * malloc
  // This handles the common declaration of: 'void *malloc();'
  if (MallocFunc == 0) {
    MallocType = FunctionType::get(PointerType::get(Type::SByteTy),
                                   std::vector<const Type*>(), true);
    MallocFunc = M.getFunction("malloc", MallocType);
  }

  // Check to see if the prototype was forgotten, giving us void (...) * free
  // This handles the common forward declaration of: 'void free();'
  if (FreeFunc == 0) {
    FreeType = FunctionType::get(Type::VoidTy, std::vector<const Type*>(),true);
    FreeFunc = M.getFunction("free", FreeType);
  }

  // Don't mess with locally defined versions of these functions...
  if (MallocFunc && !MallocFunc->isExternal()) MallocFunc = 0;
  if (FreeFunc && !FreeFunc->isExternal())     FreeFunc = 0;
  return false;
}

// runOnBasicBlock - Process a basic block, fixing it up...
//
bool RaiseAllocations::runOnBasicBlock(BasicBlock &BB) {
  bool Changed = false;
  BasicBlock::InstListType &BIL = BB.getInstList();

  for (BasicBlock::iterator BI = BB.begin(); BI != BB.end(); ++BI) {
    Instruction *I = BI;

    if (CallInst *CI = dyn_cast<CallInst>(I)) {
      if (CI->getCalledValue() == MallocFunc) {      // Replace call to malloc?
        const Type *PtrSByte = PointerType::get(Type::SByteTy);
        Value *Source = CI->getOperand(1);

        // If no prototype was provided for malloc, we may need to cast the
        // source size.
        if (Source->getType() != Type::UIntTy)
          Source = new CastInst(Source, Type::UIntTy, "MallocAmtCast", BI);

        std::string Name(CI->getName()); CI->setName("");
        BI = new MallocInst(PtrSByte, Source, Name, BI);
        CI->replaceAllUsesWith(BI);
        BIL.erase(I);
        Changed = true;
        ++NumRaised;
      } else if (CI->getCalledValue() == FreeFunc) { // Replace call to free?
        // If no prototype was provided for free, we may need to cast the
        // source pointer.  This should be really uncommon, but it's neccesary
        // just in case we are dealing with wierd code like this:
        //   free((long)ptr);
        //
        Value *Source = CI->getOperand(1);
        if (!isa<PointerType>(Source->getType()))
          Source = new CastInst(Source, PointerType::get(Type::SByteTy),
                                "FreePtrCast", BI);
        BI = new FreeInst(Source, BI);
        BIL.erase(I);
        Changed = true;
        ++NumRaised;
      }
    }
  }

  return Changed;
}
<|endoftext|>


<commit_before><commit_msg>Added tests for AsyncSampleCollector<commit_after><|endoftext|>


<commit_before>#pragma once

#include "common.hpp"
#include "debug.hpp"
#include <cassert>
#include <climits>
#include <omp.h>

template<typename SizeType, typename WordType>
void copy_bits(WordType* const dst,
               WordType const* const src,
               SizeType& dst_off_ref,
               SizeType& src_off_ref,
               SizeType const block_size)
{
    if (block_size == 0) return;

    WordType constexpr BITS = (sizeof(WordType) * CHAR_BIT);
    WordType constexpr MOD_MASK = BITS - 1;
    WordType constexpr SHIFT = log2(MOD_MASK);

    SizeType dst_off = dst_off_ref;
    SizeType src_off = src_off_ref;
    auto const dst_off_end = dst_off + block_size;

    // NB: Check if source and target block are aligned the same way
    // This is needed because the non-aligned code path would
    // trigger undefined behavior in the aligned case.
    if ((dst_off & MOD_MASK) == (src_off & MOD_MASK)) {
        // Copy unaligned leading bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while ((dst_off & MOD_MASK) != 0 && dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }

        // Copy the the bulk in-between word-wise
        {
            auto const words = (dst_off_end - dst_off) >> SHIFT;

            WordType*       ds = dst + (dst_off >> SHIFT);
            WordType const* sr = src + (src_off >> SHIFT);

            WordType const* const ds_end = ds + words;

            while (ds != ds_end) {
                *ds++ = *sr++;
            }

            dst_off += words * BITS;
            src_off += words * BITS;
        }

        // Copy unaligned trailing bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while (dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }
    } else {
        // Copy unaligned leading bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while ((dst_off & MOD_MASK) != 0 && dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }

        // Copy the the bulk in-between word-wise
        {
            auto const words = (dst_off_end - dst_off) >> SHIFT;

            WordType const src_shift_a = src_off & MOD_MASK;
            WordType const src_shift_b = BITS - src_shift_a;

            WordType*       ds = dst + (dst_off >> SHIFT);
            WordType const* sr = src + (src_off >> SHIFT);
            WordType const* const ds_end = ds + words;

            while (ds != ds_end) {
                *ds++ = (*sr << src_shift_a) | (*(sr+1) >> src_shift_b);
                sr++;
            }

            dst_off += words * BITS;
            src_off += words * BITS;
        }

        // Copy unaligned trailing bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while (dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }
    }

    dst_off_ref += block_size;
    src_off_ref += block_size;
}

template<typename SizeType, typename Rho>
inline auto merge_bvs(SizeType size,
                      SizeType levels,
                      SizeType shards,
                      const std::vector<std::vector<std::vector<SizeType>>>& glob_hist,
                      const std::vector<Bvs<SizeType>>& glob_bv,
                      const Rho& rho) -> Bvs<SizeType>
{
    assert(shards == glob_bv.size());
    assert(shards == glob_hist.size());

    // Initialize bulk data structures centrally

    struct MergeCtx {
        SizeType offset;
        std::vector<std::vector<SizeType>> read_offsets;
        std::vector<SizeType> offsets_in_first_word;
        std::vector<SizeType> first_read_block;
    };

    auto ctxs = std::vector<MergeCtx>(shards, MergeCtx {
        0,
        std::vector<std::vector<SizeType>>(
            levels, std::vector<SizeType>(shards)),
        std::vector<SizeType>(
            levels),
        std::vector<SizeType>(
            levels),
    });

    // Calculate bit offset per merge shard (thread)
    for (size_t rank = 1; rank < shards; rank++) {
        const size_t omp_rank = rank;
        const size_t omp_size = shards;

        const SizeType offset = (omp_rank * (word_size(size) / omp_size)) +
            std::min<SizeType>(omp_rank, word_size(size) % omp_size);

        ctxs[rank - 1].offset = offset * 64ull;
    }
    ctxs[shards - 1].offset = word_size(size) * 64ull;

    for(size_t level = 0; level < levels; level++) {
        const size_t br_size = 1ull << level;

        size_t write_offset = 0; // bit offset in destination bv
        size_t merge_shard = 0; // index of merge thread

        for(size_t i = 0; i < br_size * shards; i++) {
            const auto bit_i = i / shards;
            const auto read_shard = i % shards;

            auto read_offset = [&level, &ctxs](auto merge_shard, auto read_shard) -> SizeType& {
                return ctxs[merge_shard].read_offsets[level][read_shard];
            };

            const auto h = glob_hist[read_shard][level];

            auto block_size = h[rho(level, bit_i)];

            write_offset += block_size;
            read_offset(merge_shard + 1, read_shard) += block_size;

            // If we passed the current right border, split up the block
            if (write_offset > ctxs[merge_shard].offset) {
                // Take back the last step
                write_offset -= block_size;
                read_offset(merge_shard + 1, read_shard) -= block_size;

                SizeType offset_in_first_word = 0;
                do {
                    // Split up the block like this:
                    //       [    left_block_size    |        right_block_size        ]
                    //       ^                       ^                                ^
                    // (write_offset)    (ctxs[merge_shard].offset)      (write_offset + block_size)

                    auto const left_block_size = ctxs[merge_shard].offset - write_offset;

                    write_offset += left_block_size;
                    read_offset(merge_shard + 1, read_shard) += left_block_size;

                    offset_in_first_word += left_block_size;
                    ctxs[merge_shard + 1].offsets_in_first_word[level] = offset_in_first_word;
                    ctxs[merge_shard + 1].first_read_block[level] = i;

                    if (merge_shard + 2 < shards) {
                        for(size_t s = 0; s < shards; s++) {
                            read_offset(merge_shard + 2, s) = read_offset(merge_shard + 1, s);
                        }
                    }

                    merge_shard++;

                    // Once we have calculated the offsets for all merge threads,
                    // break out of the whole nested loop
                    if (merge_shard + 1 == shards) {
                        goto triple_loop_exit;
                    }

                    // Iterate on remaining block, because one block might
                    // span multiple threads
                    block_size -= left_block_size;
                } while ((write_offset + block_size) > ctxs[merge_shard].offset);

                // Process remainder of block
                write_offset += block_size;
                read_offset(merge_shard + 1, read_shard) += block_size;

                assert(write_offset <= ctxs[merge_shard].offset);
            }
        }
        triple_loop_exit:; // we are done
    }

    auto r = Bvs<SizeType>(size, levels);
    auto& _bv = r.vec();

    #pragma omp parallel
    //for(size_t omp_rank = 0; omp_rank < shards; omp_rank++)
    {
        assert(size_t(omp_get_num_threads()) == shards);
        const size_t omp_rank = omp_get_thread_num();
        const size_t merge_shard = omp_rank;

        auto& ctx = ctxs[merge_shard];

        const auto target_right = std::min(ctx.offset, size);
        const auto target_left = std::min((merge_shard > 0 ? ctxs[merge_shard - 1].offset : 0), target_right);

        for (size_t level = 0; level < levels; level++) {
            auto seq_i = ctx.first_read_block[level];

            SizeType write_offset = target_left;
            size_t init_offset = ctx.offsets_in_first_word[level];

            while (write_offset < target_right) {
                const auto i = seq_i / shards;
                const auto shard = seq_i % shards;
                seq_i++;

                const auto& h = glob_hist[shard][level];
                const auto& local_bv = glob_bv[shard].vec()[level];

                auto const block_size = std::min<SizeType>(
                    target_right - write_offset,
                    h[rho(level, i)] - init_offset
                );
                init_offset = 0; // TODO: remove this by doing a initial pass

                auto& local_cursor = ctx.read_offsets[level][shard];

                copy_bits<SizeType, uint64_t>(
                    _bv[level],
                    local_bv,
                    write_offset,
                    local_cursor,
                    block_size
                );
            }
        }
    }

    return r;
}
<commit_msg>name read_shard correctly 2<commit_after>#pragma once

#include "common.hpp"
#include "debug.hpp"
#include <cassert>
#include <climits>
#include <omp.h>

template<typename SizeType, typename WordType>
void copy_bits(WordType* const dst,
               WordType const* const src,
               SizeType& dst_off_ref,
               SizeType& src_off_ref,
               SizeType const block_size)
{
    if (block_size == 0) return;

    WordType constexpr BITS = (sizeof(WordType) * CHAR_BIT);
    WordType constexpr MOD_MASK = BITS - 1;
    WordType constexpr SHIFT = log2(MOD_MASK);

    SizeType dst_off = dst_off_ref;
    SizeType src_off = src_off_ref;
    auto const dst_off_end = dst_off + block_size;

    // NB: Check if source and target block are aligned the same way
    // This is needed because the non-aligned code path would
    // trigger undefined behavior in the aligned case.
    if ((dst_off & MOD_MASK) == (src_off & MOD_MASK)) {
        // Copy unaligned leading bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while ((dst_off & MOD_MASK) != 0 && dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }

        // Copy the the bulk in-between word-wise
        {
            auto const words = (dst_off_end - dst_off) >> SHIFT;

            WordType*       ds = dst + (dst_off >> SHIFT);
            WordType const* sr = src + (src_off >> SHIFT);

            WordType const* const ds_end = ds + words;

            while (ds != ds_end) {
                *ds++ = *sr++;
            }

            dst_off += words * BITS;
            src_off += words * BITS;
        }

        // Copy unaligned trailing bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while (dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }
    } else {
        // Copy unaligned leading bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while ((dst_off & MOD_MASK) != 0 && dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }

        // Copy the the bulk in-between word-wise
        {
            auto const words = (dst_off_end - dst_off) >> SHIFT;

            WordType const src_shift_a = src_off & MOD_MASK;
            WordType const src_shift_b = BITS - src_shift_a;

            WordType*       ds = dst + (dst_off >> SHIFT);
            WordType const* sr = src + (src_off >> SHIFT);
            WordType const* const ds_end = ds + words;

            while (ds != ds_end) {
                *ds++ = (*sr << src_shift_a) | (*(sr+1) >> src_shift_b);
                sr++;
            }

            dst_off += words * BITS;
            src_off += words * BITS;
        }

        // Copy unaligned trailing bits
        {
            auto& word = dst[dst_off >> SHIFT];

            while (dst_off != dst_off_end) {
                bool const bit = bit_at<WordType>(src, src_off++);

                word |= (WordType(bit) << (MOD_MASK - (dst_off++ & MOD_MASK)));
            }
        }
    }

    dst_off_ref += block_size;
    src_off_ref += block_size;
}

template<typename SizeType, typename Rho>
inline auto merge_bvs(SizeType size,
                      SizeType levels,
                      SizeType shards,
                      const std::vector<std::vector<std::vector<SizeType>>>& glob_hist,
                      const std::vector<Bvs<SizeType>>& glob_bv,
                      const Rho& rho) -> Bvs<SizeType>
{
    assert(shards == glob_bv.size());
    assert(shards == glob_hist.size());

    // Initialize bulk data structures centrally

    struct MergeCtx {
        SizeType offset;
        std::vector<std::vector<SizeType>> read_offsets;
        std::vector<SizeType> offsets_in_first_word;
        std::vector<SizeType> first_read_block;
    };

    auto ctxs = std::vector<MergeCtx>(shards, MergeCtx {
        0,
        std::vector<std::vector<SizeType>>(
            levels, std::vector<SizeType>(shards)),
        std::vector<SizeType>(
            levels),
        std::vector<SizeType>(
            levels),
    });

    // Calculate bit offset per merge shard (thread)
    for (size_t rank = 1; rank < shards; rank++) {
        const size_t omp_rank = rank;
        const size_t omp_size = shards;

        const SizeType offset = (omp_rank * (word_size(size) / omp_size)) +
            std::min<SizeType>(omp_rank, word_size(size) % omp_size);

        ctxs[rank - 1].offset = offset * 64ull;
    }
    ctxs[shards - 1].offset = word_size(size) * 64ull;

    for(size_t level = 0; level < levels; level++) {
        const size_t br_size = 1ull << level;

        size_t write_offset = 0; // bit offset in destination bv
        size_t merge_shard = 0; // index of merge thread

        for(size_t i = 0; i < br_size * shards; i++) {
            const auto bit_i = i / shards;
            const auto read_shard = i % shards;

            auto read_offset = [&level, &ctxs](auto merge_shard, auto read_shard) -> SizeType& {
                return ctxs[merge_shard].read_offsets[level][read_shard];
            };

            const auto h = glob_hist[read_shard][level];

            auto block_size = h[rho(level, bit_i)];

            write_offset += block_size;
            read_offset(merge_shard + 1, read_shard) += block_size;

            // If we passed the current right border, split up the block
            if (write_offset > ctxs[merge_shard].offset) {
                // Take back the last step
                write_offset -= block_size;
                read_offset(merge_shard + 1, read_shard) -= block_size;

                SizeType offset_in_first_word = 0;
                do {
                    // Split up the block like this:
                    //       [    left_block_size    |        right_block_size        ]
                    //       ^                       ^                                ^
                    // (write_offset)    (ctxs[merge_shard].offset)      (write_offset + block_size)

                    auto const left_block_size = ctxs[merge_shard].offset - write_offset;

                    write_offset += left_block_size;
                    read_offset(merge_shard + 1, read_shard) += left_block_size;

                    offset_in_first_word += left_block_size;
                    ctxs[merge_shard + 1].offsets_in_first_word[level] = offset_in_first_word;
                    ctxs[merge_shard + 1].first_read_block[level] = i;

                    if (merge_shard + 2 < shards) {
                        for(size_t s = 0; s < shards; s++) {
                            read_offset(merge_shard + 2, s) = read_offset(merge_shard + 1, s);
                        }
                    }

                    merge_shard++;

                    // Once we have calculated the offsets for all merge threads,
                    // break out of the whole nested loop
                    if (merge_shard + 1 == shards) {
                        goto triple_loop_exit;
                    }

                    // Iterate on remaining block, because one block might
                    // span multiple threads
                    block_size -= left_block_size;
                } while ((write_offset + block_size) > ctxs[merge_shard].offset);

                // Process remainder of block
                write_offset += block_size;
                read_offset(merge_shard + 1, read_shard) += block_size;

                assert(write_offset <= ctxs[merge_shard].offset);
            }
        }
        triple_loop_exit:; // we are done
    }

    auto r = Bvs<SizeType>(size, levels);
    auto& _bv = r.vec();

    #pragma omp parallel
    //for(size_t omp_rank = 0; omp_rank < shards; omp_rank++)
    {
        assert(size_t(omp_get_num_threads()) == shards);
        const size_t omp_rank = omp_get_thread_num();
        const size_t merge_shard = omp_rank;

        auto& ctx = ctxs[merge_shard];

        const auto target_right = std::min(ctx.offset, size);
        const auto target_left = std::min((merge_shard > 0 ? ctxs[merge_shard - 1].offset : 0), target_right);

        for (size_t level = 0; level < levels; level++) {
            auto seq_i = ctx.first_read_block[level];

            SizeType write_offset = target_left;
            size_t init_offset = ctx.offsets_in_first_word[level];

            while (write_offset < target_right) {
                const auto i = seq_i / shards;
                const auto read_shard = seq_i % shards;
                seq_i++;

                const auto& h = glob_hist[read_shard][level];
                const auto& local_bv = glob_bv[read_shard].vec()[level];

                auto const block_size = std::min<SizeType>(
                    target_right - write_offset,
                    h[rho(level, i)] - init_offset
                );
                init_offset = 0; // TODO: remove this by doing a initial pass

                auto& local_cursor = ctx.read_offsets[level][read_shard];

                copy_bits<SizeType, uint64_t>(
                    _bv[level],
                    local_bv,
                    write_offset,
                    local_cursor,
                    block_size
                );
            }
        }
    }

    return r;
}
<|endoftext|>


<commit_before>#include "allocator.hpp"

template <typename T>
class stack : private allocator<T>
{
public:
	stack(size_t size = 0); /*noexcept*/
	stack(const stack & _stack); /*strong*/
	stack& operator=(const stack & _stack); /*strong*/
	size_t count() const; /*noexcept*/
	void push(T const &); /*strong*/
	const T & top() const; /*strong*/
	void pop(); /*strong*/
	bool empty() { return this->count_ == 0; } /*noexcept*/
	~stack(); /*noexcept*/
};

template<typename T>
stack<T>::stack(size_t size) : allocator<T>(size) {
	;
}

template<typename T>
stack<T>::stack(const stack & _stack) /*strong*/
{
	this->ptr_ = operatorNewCopiedArray(_stack.ptr_, _stack.count_, _stack.size_);
	this->size_ = _stack.size_;
	this->count_ = _stack.count_;
}

template<typename T>
stack<T> & stack<T>::operator=(const stack & _stack) /*strong*/
{
	if (this != &_stack) {
		stack(_stack).swap(*this);
		/*T* midterm = newCopiedArray(_stack.ptr_, _stack.count_, _stack.size_);
		delete[] this->ptr_;
		this->ptr_ = midterm;
		this->count_ = _stack.count_;
		this->size_ = _stack.size_;*/
	}
	return *this;
}

template<typename T>
size_t stack<T>::count() const /*noexcept*/
{
	return this->count_;
}

template <typename T>
void stack<T>::push(const T & value) /*strong*/
{
	if (this->count_ == this->size_) {
		size_t array_size = (this->size_ * 3) / 2 + 1;

		stack temp(array_size);
		while (temp.count() < this->count_) {
			temp.push(this->ptr_[temp.count()]);
		}

		this->swap(temp);
	}
	construct(this->ptr_ + this->count_, value);
	++this->count_;
}

template<typename T>
const T & stack<T>::top() const /*strong*/
{
	if (this->count_ == 0) {
		throw ("top: count_ == 0");
	}
	return this->ptr_[this->count_ - 1];
}

template<typename T>
void stack<T>::pop() /*strong*/
{
	if (this->count_ == 0) {
		throw("pop(): count_ == 0");
	}
	destroy(&(this->ptr_[this->count_ - 1]));
	this->count_--;
}

template<typename T>
stack<T>::~stack() /*noexcept*/
{
	destroy(this->ptr_, this->ptr_ + this->count_);
}
<commit_msg>Update stack.hpp<commit_after>#include "allocator.hpp"

template <typename T>
class stack {
public:
	explicit stack(size_t size = 0);
	auto operator=(stack const & other) /*strong*/ -> stack &;

	auto count() const -> size_t { return allocator_.count(); } /*noexcept*/
	bool empty() const { return allocator_.empty(); } /*noexcept*/

	void push(T const & value); /*strong*/
	void pop(); /*strong*/
	auto top() -> T &; /*strong*/
	auto top() const -> T const &; /*strong*/
private:
	allocator<T> allocator_;
};

template<typename T>
stack<T>::stack(size_t size) : allocator_(size) {
	;
}

template<typename T>
auto stack<T>::operator=(stack const & other) -> stack & {
	if (this != &other) {
		(allocator<T>(other.allocator_)).swap(allocator_);
	}
	return *this;
}

template<typename T>
void stack<T>::push(T const & value) {
	if (allocator_.full()) {
		allocator_.resize();
	}
	allocator_.construct(this->count(), value);
}

template<typename T>
void stack<T>::pop() {
	if (this->count() > 0) {
		allocator_.destroy(this->count() - 1);
	}
	else {
		throw("stack is empty");
	}
}

template<typename T>
auto stack<T>::top() -> T & {
	if (this->count() > 0) {
		return allocator_.getElement(this->count() - 1);
	}
	else {
		throw("stack is empty");
	}
}

template<typename T>
auto stack<T>::top() const -> T const & {
	if (this->count() > 0) {
		return allocator_.getElement(this->count() - 1);
	}
	else {
		throw("stack is empty");
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <stdexcept>

template <typename T>
class stack
{
public:
	stack()noexcept;
	~stack()noexcept;
	stack(stack<T> const&)noexcept;
	stack& operator=(stack<T> const&)noexcept;
	size_t count()const noexcept;
	size_t array_size()const noexcept;
	void push(T const&)noexcept;
	void pop()noexcept;
	T top()const noexcept;
	void print(std::ostream&stream)const noexcept;
	friend std::ostream&operator << (std::ostream&stream, const stack<T>&)noexcept;
	void swap(stack<T>&)noexcept;
	bool empty()noexcept;
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() : array_{ nullptr }, array_size_{ 0 }, count_{ 0 } {}noexcept
template <typename T>
stack<T>::~stack()noexcept
{
	delete[] array_;
}
template <typename T>
stack<T>::stack(stack<T> const& other)noexcept
{
	array_size_ = other.array_size_;
	count_ = other.count_;
	std::copy(other.array_, other.array_ + count_, array_);
}
template <typename T>
auto stack<T>::operator=(stack<T> const & other) -> stack& noexcept
{
	if (&other != this)
		stack(other).swap(*this);
	return *this;
}
template <typename T>
size_t stack<T>::array_size()const noexcept
{
	return array_size_;
}
template <typename T>
size_t stack<T>::count()const noexcept
{
	return count_;
}
template <typename T>
void stack<T>::push(T const & value)noexcept
{
	if (array_size_ == 0)
	{
		array_size_ = 1;
		array_ = new T[array_size_]();
	}
	else if (array_size_ == count_)
	{
		array_size_ *= 2;
		T * new_array = new T[array_size_]();
		std::copy(array_, array_ + count_, new_array);
		delete[] array_;
		array_ = new_array;
	}
	array_[count_++] = value;
}
template <typename T>
void stack<T>::pop()noexcept
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else
	{
		if (count_ - 1 == array_size_ / 2)
			array_size_ /= 2;
		swap();
	}
}
template <typename T>
T stack<T>::top()const noexcept
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else return array_[count - 1];
}
template <typename T>
void stack<T>::print(std::ostream&stream)const noexcept
{
	for (unsigned int i = 0; i < count_; ++i)
		stream << array_[i] << " ";
	stream << std::endl;
}
template <typename T>
std::ostream& operator << (std::ostream&stream, const stack<T>&stack_)noexcept
{
	return stack_.print(stream);
}
template <typename T>
void stack<T>::swap(stack<T>& other)noexcept
{
	std::swap(array_, other.array_);
	std::swap(array_size_, other.array_size_);
	std::swap(count_, other.count_);
}
template <typename T>
bool stack<T>::empty()noexcept
{
	return (count_ == 0) ? true : false;
}
<commit_msg>Update stack.hpp<commit_after>#include <iostream>
#include <algorithm>
#include <stdexcept>

template <typename T>
class stack
{
public:
	stack()noexcept;
	~stack()noexcept;
	stack(stack<T> const&)noexcept;
	stack& operator=(stack<T> const&)noexcept;
	size_t count()const noexcept;
	size_t array_size()const noexcept;
	void push(T const&)noexcept;
	void pop()noexcept;
	T top()const noexcept;
	void print(std::ostream&stream)const noexcept;
	friend std::ostream&operator << (std::ostream&stream, const stack<T>&)noexcept;
	void swap(stack<T>&)noexcept;
	bool empty()noexcept;
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack() : array_{ nullptr }, array_size_{ 0 }, count_{ 0 } {}noexcept
template <typename T>
stack<T>::~stack()noexcept
{
	delete[] array_;
}
template <typename T>
stack<T>::stack(stack<T> const& other)noexcept
{
	array_size_ = other.array_size_;
	count_ = other.count_;
	std::copy(other.array_, other.array_ + count_, array_);
}
template <typename T>
auto stack<T>::operator=(stack<T> const & other) -> stack& noexcept
{
	if (&other != this)
		stack(other).swap(*this);
	return *this;
}
template <typename T>
size_t stack<T>::array_size()const noexcept
{
	return array_size_;
}
template <typename T>
size_t stack<T>::count()const noexcept
{
	return count_;
}
template <typename T>
void stack<T>::push(T const & value)noexcept
{
	if (empty())
	{
		array_size_ = 1;
		array_ = new T[array_size_]();
	}
	else if (array_size_ == count_)
	{
		array_size_ *= 2;
		T * new_array = new T[array_size_]();
		std::copy(array_, array_ + count_, new_array);
		delete[] array_;
		array_ = new_array;
	}
	array_[count_++] = value;
}
template <typename T>
void stack<T>::pop()noexcept
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else
	{
		if (count_ - 1 == array_size_ / 2)
			array_size_ /= 2;
		swap();
	}
}
template <typename T>
T stack<T>::top()const noexcept
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else return array_[count - 1];
}
template <typename T>
void stack<T>::print(std::ostream&stream)const noexcept
{
	for (unsigned int i = 0; i < count_; ++i)
		stream << array_[i] << " ";
	stream << std::endl;
}
template <typename T>
std::ostream& operator << (std::ostream&stream, const stack<T>&stack_)noexcept
{
	return stack_.print(stream);
}
template <typename T>
void stack<T>::swap(stack<T>& other)noexcept
{
	std::swap(array_, other.array_);
	std::swap(array_size_, other.array_size_);
	std::swap(count_, other.count_);
}
template <typename T>
bool stack<T>::empty()noexcept
{
	return (count_ == 0) ? true : false;
}
<|endoftext|>


<commit_before>#include "ostree.h"
#include <stdio.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include "logger.h"

#include <gio/gio.h>

OstreeSysroot *Ostree::LoadSysroot(const std::string &path) {
  OstreeSysroot *sysroot = NULL;

  if (path.size()) {
    sysroot = ostree_sysroot_new(g_file_new_for_path(path.c_str()));
  } else {
    sysroot = ostree_sysroot_new_default();
  }
  GCancellable *cancellable = NULL;
  GError **error = NULL;
  if (!ostree_sysroot_load(sysroot, cancellable, error)) throw std::runtime_error("could not load sysroot");
  return sysroot;
}

OstreeDeployment *Ostree::getStagedDeployment(const std::string &path) {
  OstreeSysroot *sysroot = Ostree::LoadSysroot(path);
  GPtrArray *deployments = NULL;
  OstreeDeployment *res = NULL;

  deployments = ostree_sysroot_get_deployments(sysroot);

  if (deployments->len == 0) {
    res = NULL;
  } else {
    OstreeDeployment *d = static_cast<OstreeDeployment *>(deployments->pdata[0]);
    res = static_cast<OstreeDeployment *>(g_object_ref(d));
  }

  g_ptr_array_unref(deployments);
  return res;
}

bool Ostree::addRemote(OstreeRepo *repo, const std::string &remote, const std::string &url,
                       const data::PackageManagerCredentials &cred) {
  GCancellable *cancellable = NULL;
  GError *error = NULL;
  GVariantBuilder b;
  GVariant *options;

  g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
  g_variant_builder_add(&b, "{s@v}", "gpg-verify", g_variant_new_variant(g_variant_new_boolean(FALSE)));

  if (cred.cert_file.size() && cred.pkey_file.size() && cred.ca_file.size()) {
    g_variant_builder_add(&b, "{s@v}", "tls-client-cert-path",
                          g_variant_new_variant(g_variant_new_string(cred.cert_file.c_str())));
    g_variant_builder_add(&b, "{s@v}", "tls-client-key-path",
                          g_variant_new_variant(g_variant_new_string(cred.pkey_file.c_str())));
    g_variant_builder_add(&b, "{s@v}", "tls-ca-path",
                          g_variant_new_variant(g_variant_new_string(cred.ca_file.c_str())));
  }
  options = g_variant_builder_end(&b);

  if (!ostree_repo_remote_change(repo, NULL, OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS, remote.c_str(), url.c_str(),
                                 options, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "Error of adding remote: " << error->message);
    return false;
  }
  if (!ostree_repo_remote_change(repo, NULL, OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS, remote.c_str(), url.c_str(),
                                 options, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "Error of adding remote: " << error->message);
    return false;
  }
  return true;
}

#include "ostree-1/ostree.h"

OstreePackage::OstreePackage(const std::string &ecu_serial_in, const std::string &ref_name_in,
                             const std::string &desc_in, const std::string &treehub_in)
    : ecu_serial(ecu_serial_in), ref_name(ref_name_in), description(desc_in), pull_uri(treehub_in) {
  std::size_t pos = ref_name.find_last_of("-");
  branch_name = ref_name.substr(0, pos);
  refhash = ref_name.substr(pos + 1, std::string::npos);
  if (branch_name.empty() || refhash.empty()) throw std::runtime_error("malformed OSTree target name: " + ref_name);
}

data::InstallOutcome OstreePackage::install(const data::PackageManagerCredentials &cred, OstreeConfig config) {
  const char remote[] = "aktualizr-remote";
  const char *const refs[] = {branch_name.c_str()};
  const char *const commit_ids[] = {refhash.c_str()};
  const char *opt_osname = NULL;
  OstreeRepo *repo = NULL;
  GCancellable *cancellable = NULL;
  GError *error = NULL;
  char *revision;
  GVariantBuilder builder;
  GVariant *options;

  if (config.os.size()) {
    opt_osname = config.os.c_str();
  }
  OstreeSysroot *sysroot = Ostree::LoadSysroot(config.sysroot);
  if (!ostree_sysroot_get_repo(sysroot, &repo, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "could not get repo");
    return data::InstallOutcome(data::INSTALL_FAILED, "could not get repo");
  }

  if (!Ostree::addRemote(repo, remote, pull_uri, cred)) {
    return data::InstallOutcome(data::INSTALL_FAILED, "Error of adding remote");
  }

  g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
  g_variant_builder_add(&builder, "{s@v}", "flags", g_variant_new_variant(g_variant_new_int32(0)));

  g_variant_builder_add(&builder, "{s@v}", "refs", g_variant_new_variant(g_variant_new_strv(refs, 1)));
  g_variant_builder_add(&builder, "{s@v}", "override-commit-ids",
                        g_variant_new_variant(g_variant_new_strv(commit_ids, 1)));

  if (cred.access_token.size()) {
    GVariantBuilder hdr_builder;
    std::string av("Bearer ");
    av += cred.access_token;
    g_variant_builder_init(&hdr_builder, G_VARIANT_TYPE("a(ss)"));
    g_variant_builder_add(&hdr_builder, "(ss)", "Authorization", av.c_str());
    g_variant_builder_add(&builder, "{s@v}", "http-headers",
                          g_variant_new_variant(g_variant_builder_end(&hdr_builder)));
  }
  options = g_variant_ref_sink(g_variant_builder_end(&builder));

  if (!ostree_repo_pull_with_options(repo, remote, options, NULL, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "Error of pulling image: " << error->message);
    return data::InstallOutcome(data::INSTALL_FAILED, error->message);
  }

  GKeyFile *origin = ostree_sysroot_origin_new_from_refspec(sysroot, branch_name.c_str());
  if (!ostree_repo_resolve_rev(repo, refhash.c_str(), FALSE, &revision, &error)) {
    LOGGER_LOG(LVL_error, error->message);
    return data::InstallOutcome(data::INSTALL_FAILED, error->message);
  }

  OstreeDeployment *merge_deployment = ostree_sysroot_get_merge_deployment(sysroot, opt_osname);
  if (merge_deployment == NULL) {
    LOGGER_LOG(LVL_error, "No merge deployment");
    return data::InstallOutcome(data::INSTALL_FAILED, "No merge deployment");
  }

  if (!ostree_sysroot_prepare_cleanup(sysroot, cancellable, &error)) {
    LOGGER_LOG(LVL_error, error->message);
    return data::InstallOutcome(data::INSTALL_FAILED, error->message);
  }

  std::ifstream args_stream("/proc/cmdline");
  std::string args_content((std::istreambuf_iterator<char>(args_stream)), std::istreambuf_iterator<char>());
  std::vector<std::string> args_vector;
  boost::split(args_vector, args_content, boost::is_any_of(" "));

  std::vector<const char *> kargs_strv_vector;
  kargs_strv_vector.reserve(args_vector.size() + 1);

  for (std::vector<std::string>::iterator it = args_vector.begin(); it != args_vector.end(); ++it) {
    kargs_strv_vector.push_back((*it).c_str());
  }
  kargs_strv_vector[args_vector.size()] = 0;
  GStrv kargs_strv = const_cast<char **>(&kargs_strv_vector[0]);

  OstreeDeployment *new_deployment = NULL;
  if (!ostree_sysroot_deploy_tree(sysroot, opt_osname, revision, origin, merge_deployment, kargs_strv, &new_deployment,
                                  cancellable, &error)) {
    LOGGER_LOG(LVL_error, "ostree_sysroot_deploy_tree: " << error->message);
    return data::InstallOutcome(data::INSTALL_FAILED, error->message);
  }

  if (!ostree_sysroot_simple_write_deployment(sysroot, "", new_deployment, merge_deployment,
                                              OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN, cancellable,
                                              &error)) {
    LOGGER_LOG(LVL_error, "ostree_sysroot_simple_write_deployment:" << error->message);
    return data::InstallOutcome(data::INSTALL_FAILED, error->message);
  }
  return data::InstallOutcome(data::OK, "Installation succesfull");
}

OstreeBranch OstreeBranch::getCurrent(const std::string &ecu_serial, const std::string &ostree_sysroot) {
  OstreeDeployment *staged_deployment = Ostree::getStagedDeployment(ostree_sysroot);

  GKeyFile *origin = ostree_deployment_get_origin(staged_deployment);
  const char *ref = ostree_deployment_get_csum(staged_deployment);
  char *origin_refspec = g_key_file_get_string(origin, "origin", "refspec", NULL);
  OstreePackage package(ecu_serial, std::string(origin_refspec) + "-" + ref, origin_refspec, "");
  g_free(origin_refspec);
  return OstreeBranch(true, ostree_deployment_get_osname(staged_deployment), package);
}

OstreePackage OstreePackage::fromJson(const Json::Value &json) {
  return OstreePackage(json["ecu_serial"].asString(), json["ref_name"].asString(), json["description"].asString(),
                       json["pull_uri"].asString());
}

Json::Value OstreePackage::toEcuVersion(const Json::Value &custom) {
  Json::Value installed_image;
  installed_image["filepath"] = ref_name;
  installed_image["fileinfo"]["length"] = 0;
  installed_image["fileinfo"]["hashes"]["sha256"] = refhash;

  Json::Value value;
  value["attacks_detected"] = "";
  value["installed_image"] = installed_image;
  value["ecu_serial"] = ecu_serial;
  value["previous_timeserver_time"] = "1970-01-01T00:00:00Z";
  value["timeserver_time"] = "1970-01-01T00:00:00Z";
  if (custom != Json::nullValue) {
    value["custom"] = custom;
  }
  return value;
}

OstreePackage OstreePackage::getEcu(const std::string &ecu_serial, const std::string &ostree_sysroot) {
  return OstreeBranch::getCurrent(ecu_serial, ostree_sysroot).package;
}
<commit_msg>Free Gerror objects<commit_after>#include "ostree.h"
#include <stdio.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include "logger.h"

#include <gio/gio.h>

OstreeSysroot *Ostree::LoadSysroot(const std::string &path) {
  OstreeSysroot *sysroot = NULL;

  if (path.size()) {
    sysroot = ostree_sysroot_new(g_file_new_for_path(path.c_str()));
  } else {
    sysroot = ostree_sysroot_new_default();
  }
  GCancellable *cancellable = NULL;
  GError *error = NULL;
  if (!ostree_sysroot_load(sysroot, cancellable, &error)) {
    g_error_free (error);
    throw std::runtime_error("could not load sysroot");
  }
  return sysroot;
}

OstreeDeployment *Ostree::getStagedDeployment(const std::string &path) {
  OstreeSysroot *sysroot = Ostree::LoadSysroot(path);
  GPtrArray *deployments = NULL;
  OstreeDeployment *res = NULL;

  deployments = ostree_sysroot_get_deployments(sysroot);

  if (deployments->len == 0) {
    res = NULL;
  } else {
    OstreeDeployment *d = static_cast<OstreeDeployment *>(deployments->pdata[0]);
    res = static_cast<OstreeDeployment *>(g_object_ref(d));
  }

  g_ptr_array_unref(deployments);
  return res;
}

bool Ostree::addRemote(OstreeRepo *repo, const std::string &remote, const std::string &url,
                       const data::PackageManagerCredentials &cred) {
  GCancellable *cancellable = NULL;
  GError *error = NULL;
  GVariantBuilder b;
  GVariant *options;

  g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
  g_variant_builder_add(&b, "{s@v}", "gpg-verify", g_variant_new_variant(g_variant_new_boolean(FALSE)));

  if (cred.cert_file.size() && cred.pkey_file.size() && cred.ca_file.size()) {
    g_variant_builder_add(&b, "{s@v}", "tls-client-cert-path",
                          g_variant_new_variant(g_variant_new_string(cred.cert_file.c_str())));
    g_variant_builder_add(&b, "{s@v}", "tls-client-key-path",
                          g_variant_new_variant(g_variant_new_string(cred.pkey_file.c_str())));
    g_variant_builder_add(&b, "{s@v}", "tls-ca-path",
                          g_variant_new_variant(g_variant_new_string(cred.ca_file.c_str())));
  }
  options = g_variant_builder_end(&b);

  if (!ostree_repo_remote_change(repo, NULL, OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS, remote.c_str(), url.c_str(),
                                 options, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "Error of adding remote: " << error->message);
    g_error_free (error);
    return false;
  }
  if (!ostree_repo_remote_change(repo, NULL, OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS, remote.c_str(), url.c_str(),
                                 options, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "Error of adding remote: " << error->message);
    g_error_free (error);
    return false;
  }
  return true;
}

#include "ostree-1/ostree.h"

OstreePackage::OstreePackage(const std::string &ecu_serial_in, const std::string &ref_name_in,
                             const std::string &desc_in, const std::string &treehub_in)
    : ecu_serial(ecu_serial_in), ref_name(ref_name_in), description(desc_in), pull_uri(treehub_in) {
  std::size_t pos = ref_name.find_last_of("-");
  branch_name = ref_name.substr(0, pos);
  refhash = ref_name.substr(pos + 1, std::string::npos);
  if (branch_name.empty() || refhash.empty()) throw std::runtime_error("malformed OSTree target name: " + ref_name);
}

data::InstallOutcome OstreePackage::install(const data::PackageManagerCredentials &cred, OstreeConfig config) {
  const char remote[] = "aktualizr-remote";
  const char *const refs[] = {branch_name.c_str()};
  const char *const commit_ids[] = {refhash.c_str()};
  const char *opt_osname = NULL;
  OstreeRepo *repo = NULL;
  GCancellable *cancellable = NULL;
  GError *error = NULL;
  char *revision;
  GVariantBuilder builder;
  GVariant *options;

  if (config.os.size()) {
    opt_osname = config.os.c_str();
  }
  OstreeSysroot *sysroot = Ostree::LoadSysroot(config.sysroot);
  if (!ostree_sysroot_get_repo(sysroot, &repo, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "could not get repo");
    g_error_free (error);
    return data::InstallOutcome(data::INSTALL_FAILED, "could not get repo");
  }

  if (!Ostree::addRemote(repo, remote, pull_uri, cred)) {
    return data::InstallOutcome(data::INSTALL_FAILED, "Error of adding remote");
  }

  g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
  g_variant_builder_add(&builder, "{s@v}", "flags", g_variant_new_variant(g_variant_new_int32(0)));

  g_variant_builder_add(&builder, "{s@v}", "refs", g_variant_new_variant(g_variant_new_strv(refs, 1)));
  g_variant_builder_add(&builder, "{s@v}", "override-commit-ids",
                        g_variant_new_variant(g_variant_new_strv(commit_ids, 1)));

  if (cred.access_token.size()) {
    GVariantBuilder hdr_builder;
    std::string av("Bearer ");
    av += cred.access_token;
    g_variant_builder_init(&hdr_builder, G_VARIANT_TYPE("a(ss)"));
    g_variant_builder_add(&hdr_builder, "(ss)", "Authorization", av.c_str());
    g_variant_builder_add(&builder, "{s@v}", "http-headers",
                          g_variant_new_variant(g_variant_builder_end(&hdr_builder)));
  }
  options = g_variant_ref_sink(g_variant_builder_end(&builder));

  if (!ostree_repo_pull_with_options(repo, remote, options, NULL, cancellable, &error)) {
    LOGGER_LOG(LVL_error, "Error of pulling image: " << error->message);
    data::InstallOutcome install_outcome(data::INSTALL_FAILED, error->message);
    g_error_free (error);
    return install_outcome;
  }

  GKeyFile *origin = ostree_sysroot_origin_new_from_refspec(sysroot, branch_name.c_str());
  if (!ostree_repo_resolve_rev(repo, refhash.c_str(), FALSE, &revision, &error)) {
    LOGGER_LOG(LVL_error, error->message);
    data::InstallOutcome install_outcome(data::INSTALL_FAILED, error->message);
    g_error_free (error);
    return install_outcome;
  }

  OstreeDeployment *merge_deployment = ostree_sysroot_get_merge_deployment(sysroot, opt_osname);
  if (merge_deployment == NULL) {
    LOGGER_LOG(LVL_error, "No merge deployment");
    return data::InstallOutcome(data::INSTALL_FAILED, "No merge deployment");
  }

  if (!ostree_sysroot_prepare_cleanup(sysroot, cancellable, &error)) {
    LOGGER_LOG(LVL_error, error->message);
    data::InstallOutcome install_outcome(data::INSTALL_FAILED, error->message);
    g_error_free (error);
    return install_outcome;
  }

  std::ifstream args_stream("/proc/cmdline");
  std::string args_content((std::istreambuf_iterator<char>(args_stream)), std::istreambuf_iterator<char>());
  std::vector<std::string> args_vector;
  boost::split(args_vector, args_content, boost::is_any_of(" "));

  std::vector<const char *> kargs_strv_vector;
  kargs_strv_vector.reserve(args_vector.size() + 1);

  for (std::vector<std::string>::iterator it = args_vector.begin(); it != args_vector.end(); ++it) {
    kargs_strv_vector.push_back((*it).c_str());
  }
  kargs_strv_vector[args_vector.size()] = 0;
  GStrv kargs_strv = const_cast<char **>(&kargs_strv_vector[0]);

  OstreeDeployment *new_deployment = NULL;
  if (!ostree_sysroot_deploy_tree(sysroot, opt_osname, revision, origin, merge_deployment, kargs_strv, &new_deployment,
                                  cancellable, &error)) {
    LOGGER_LOG(LVL_error, "ostree_sysroot_deploy_tree: " << error->message);
    data::InstallOutcome install_outcome(data::INSTALL_FAILED, error->message);
    g_error_free (error);
    return install_outcome;
  }

  if (!ostree_sysroot_simple_write_deployment(sysroot, "", new_deployment, merge_deployment,
                                              OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN, cancellable,
                                              &error)) {
    LOGGER_LOG(LVL_error, "ostree_sysroot_simple_write_deployment:" << error->message);
    data::InstallOutcome install_outcome(data::INSTALL_FAILED, error->message);
    g_error_free (error);
    return install_outcome;
  }
  return data::InstallOutcome(data::OK, "Installation succesfull");
}

OstreeBranch OstreeBranch::getCurrent(const std::string &ecu_serial, const std::string &ostree_sysroot) {
  OstreeDeployment *staged_deployment = Ostree::getStagedDeployment(ostree_sysroot);

  GKeyFile *origin = ostree_deployment_get_origin(staged_deployment);
  const char *ref = ostree_deployment_get_csum(staged_deployment);
  char *origin_refspec = g_key_file_get_string(origin, "origin", "refspec", NULL);
  OstreePackage package(ecu_serial, std::string(origin_refspec) + "-" + ref, origin_refspec, "");
  g_free(origin_refspec);
  return OstreeBranch(true, ostree_deployment_get_osname(staged_deployment), package);
}

OstreePackage OstreePackage::fromJson(const Json::Value &json) {
  return OstreePackage(json["ecu_serial"].asString(), json["ref_name"].asString(), json["description"].asString(),
                       json["pull_uri"].asString());
}

Json::Value OstreePackage::toEcuVersion(const Json::Value &custom) {
  Json::Value installed_image;
  installed_image["filepath"] = ref_name;
  installed_image["fileinfo"]["length"] = 0;
  installed_image["fileinfo"]["hashes"]["sha256"] = refhash;

  Json::Value value;
  value["attacks_detected"] = "";
  value["installed_image"] = installed_image;
  value["ecu_serial"] = ecu_serial;
  value["previous_timeserver_time"] = "1970-01-01T00:00:00Z";
  value["timeserver_time"] = "1970-01-01T00:00:00Z";
  if (custom != Json::nullValue) {
    value["custom"] = custom;
  }
  return value;
}

OstreePackage OstreePackage::getEcu(const std::string &ecu_serial, const std::string &ostree_sysroot) {
  return OstreeBranch::getCurrent(ecu_serial, ostree_sysroot).package;
}
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * cxx98IO.cpp
 *
 *  Created on: Apr 5, 2018
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "cxx98IO.h"
#include "cxx98IO.tcc"

#include <adios2_c.h>

namespace adios2
{
namespace cxx98
{

namespace
{

adios2_mode ToMode(const Mode mode)
{
    adios2_mode modeC = adios2_mode_undefined;

    switch (mode)
    {
    case Write:
        modeC = adios2_mode_write;
        break;
    case Read:
        modeC = adios2_mode_read;
        break;
    case Append:
        modeC = adios2_mode_append;
        break;
    default:;
    }

    return modeC;
}
}

IO::IO(adios2_io &io) : m_IO(io) {}

IO::~IO() {}

#ifdef ADIOS2_HAVE_MPI
Engine IO::Open(const std::string &name, const Mode mode, MPI_Comm comm)
{
    return Engine(
        adios2_open_new_comm(&m_IO, name.c_str(), ToMode(mode), comm));
}
#endif

Engine IO::Open(const std::string &name, const Mode mode)
{
    return Engine(adios2_open(&m_IO, name.c_str(), ToMode(mode)));
}

std::string IO::EngineType() const noexcept
{
    size_t length = 0;
    const char *typeC = adios2_io_engine_type(&m_IO, &length);
    return std::string(typeC, length);
}

#define declare_template_instantiation(T)                                      \
    template Variable<T> IO::InquireVariable<T>(const std::string &);

ADIOS2_FOREACH_CXX98_TYPE_1ARG(declare_template_instantiation)
#undef declare_template_instantiation

} // end namespace cxx98
} // end namespace adios2
<commit_msg>CXX98 signature<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * cxx98IO.cpp
 *
 *  Created on: Apr 5, 2018
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "cxx98IO.h"
#include "cxx98IO.tcc"

#include <adios2_c.h>

namespace adios2
{
namespace cxx98
{

namespace
{

adios2_mode ToMode(const Mode mode)
{
    adios2_mode modeC = adios2_mode_undefined;

    switch (mode)
    {
    case Write:
        modeC = adios2_mode_write;
        break;
    case Read:
        modeC = adios2_mode_read;
        break;
    case Append:
        modeC = adios2_mode_append;
        break;
    default:;
    }

    return modeC;
}
}

IO::IO(adios2_io &io) : m_IO(io) {}

IO::~IO() {}

#ifdef ADIOS2_HAVE_MPI
Engine IO::Open(const std::string &name, const Mode mode, MPI_Comm comm)
{
    return Engine(
        adios2_open_new_comm(&m_IO, name.c_str(), ToMode(mode), comm));
}
#endif

Engine IO::Open(const std::string &name, const Mode mode)
{
    return Engine(adios2_open(&m_IO, name.c_str(), ToMode(mode)));
}

std::string IO::EngineType() const
{
    size_t length = 0;
    const char *typeC = adios2_io_engine_type(&m_IO, &length);
    return std::string(typeC, length);
}

#define declare_template_instantiation(T)                                      \
    template Variable<T> IO::InquireVariable<T>(const std::string &);

ADIOS2_FOREACH_CXX98_TYPE_1ARG(declare_template_instantiation)
#undef declare_template_instantiation

} // end namespace cxx98
} // end namespace adios2
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon, Dane Springmeyer
 *
 * This library 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; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $

// boost
#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

// mapnik
#include <mapnik/layer.hpp>
#include <mapnik/datasource.hpp>

using mapnik::Layer;
using mapnik::parameters;
using mapnik::datasource;

struct layer_pickle_suite : boost::python::pickle_suite
{
   static boost::python::tuple
   getinitargs(const Layer& l)
   {
      return boost::python::make_tuple(l.name(),l.srs());
   }

   static  boost::python::tuple
   getstate(const Layer& l)
   {
        boost::python::list s;
        std::vector<std::string> const& style_names = l.styles();
        for (unsigned i = 0; i < style_names.size(); ++i)
        {
            s.append(style_names[i]);
        }
        return boost::python::make_tuple(l.abstract(),l.title(),l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource(),s);
   }

   static void
   setstate (Layer& l, boost::python::tuple state)
   {
        using namespace boost::python;
        if (len(state) != 8)
        {
         PyErr_SetObject(PyExc_ValueError,
                         ("expected 8-item tuple in call to __setstate__; got %s"
                          % state).ptr()
            );
         throw_error_already_set();
        }

        if (state[0])
        {
            l.set_abstract(extract<std::string>(state[0]));
        }

        if (state[1])
        {
            l.set_title(extract<std::string>(state[1]));
        }

        if (state[2])
        {
            l.set_clear_label_cache(extract<bool>(state[2]));
        }

        if (state[3])
        {
            l.setMinZoom(extract<double>(state[3]));
        }

        if (state[4])
        {
            l.setMaxZoom(extract<double>(state[4]));
        }

        if (state[5])
        {
            l.setQueryable(extract<bool>(state[5]));
        }

        if (state[6])
        {
            boost::shared_ptr<datasource> ds = extract<boost::shared_ptr<datasource> >(state[6]);
            l.set_datasource(ds);
        }

        boost::python::list s = extract<boost::python::list>(state[7]);
        for (int i=0;i<len(s);++i)
        {
           l.add_style(extract<std::string>(s[i]));
        }
   }
};

std::vector<std::string> & (mapnik::Layer::*_styles_)() = &mapnik::Layer::styles;

void export_layer()
{
    using namespace boost::python;
    class_<std::vector<std::string> >("Names")
    	.def(vector_indexing_suite<std::vector<std::string>,true >())
    	;

    class_<Layer>("Layer", "A Mapnik map layer.", init<std::string const&,optional<std::string const&> >(
                "Create a Layer with a named string and, optionally, an srs string.\n"
                "\n"
                "The srs can be either a Proj.4 epsg code ('+init=epsg:<code>') or\n"
                "of a Proj.4 literal ('+proj=<literal>').\n"
                "If no srs is specified it will default to '+proj=latlong +datum=WGS84'\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr\n"
                "<mapnik._mapnik.Layer object at 0x6a270>\n"
                ))

        .def_pickle(layer_pickle_suite())

        .def("envelope",&Layer::envelope,
                "Return the geographic envelope/bounding box."
                "\n"
                "Determined based on the layer datasource.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.envelope()\n"
                "Envelope(-1.0,-1.0,0.0,0.0) # default until a datasource is loaded\n"
                )

        .def("visible", &Layer::isVisible,
                "Return True if this layer's data is active and visible at a given scale.\n"
                "\n"
                "Otherwise returns False.\n"
                "Accepts a scale value as an integer or float input.\n"
                "Will return False if:\n"
                "\tscale >= minzoom - 1e-6\n"
                "\tor:\n"
                "\tscale < maxzoom + 1e-6\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.visible(1.0/1000000)\n"
                "True\n"
                ">>> lyr.active = False\n"
                ">>> lyr.visible(1.0/1000000)\n"
                "False\n"
                )

        .add_property("abstract",
                make_function(&Layer::abstract,return_value_policy<copy_const_reference>()),
                &Layer::set_abstract,
                "Get/Set the abstract of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.abstract\n"
                "'' # default is en empty string\n"
                ">>> lyr.abstract = 'My Shapefile rendered with Mapnik'\n"
                ">>> lyr.abstract\n"
                "'My Shapefile rendered with Mapnik'\n"
                )

        .add_property("active",
                &Layer::isActive,
                &Layer::setActive,
                "Get/Set whether this layer is active and will be rendered.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.active\n"
                "True # Active by default\n"
                ">>> lyr.active = False # set False to disable layer rendering\n"
                ">>> lyr.active\n"
                "False\n"
                )

        .add_property("clear_label_cache",
                &Layer::clear_label_cache,
                &Layer::set_clear_label_cache,
                "Get/Set whether this layer's labels are cached.\n"
                "\n"
                "Usage:\n"
                "TODO\n"
                )

        .add_property("datasource",
                &Layer::datasource,
                &Layer::set_datasource,
                "The datasource attached to this layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer, Datasource\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.datasource = Datasource(type='shape',file='world_borders')\n"
                ">>> lyr.datasource\n"
                "<mapnik.Datasource object at 0x65470>\n"
                )

        .add_property("maxzoom",
                &Layer::getMaxZoom,
                &Layer::setMaxZoom,
                "Get/Set the maximum zoom lever of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.maxzoom\n"
                "1.7976931348623157e+308 # default is the numerical maximum\n"
                ">>> lyr.maxzoom = 1.0/1000000\n"
                ">>> lyr.maxzoom\n"
                "9.9999999999999995e-07\n"
                )

        .add_property("minzoom",
                &Layer::getMinZoom,
                &Layer::setMinZoom,
                "Get/Set the minimum zoom lever of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.minzoom # default is 0\n"
                "0.0\n"
                ">>> lyr.minzoom = 1.0/1000000\n"
                ">>> lyr.minzoom\n"
                "9.9999999999999995e-07\n"
                )

        .add_property("name",
                make_function(&Layer::name, return_value_policy<copy_const_reference>()),
                &Layer::set_name,
                "Get/Set the name of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.name\n"
                "'My Layer'\n"
                ">>> lyr.name = 'New Name'\n"
                ">>> lyr.name\n"
                "'New Name'\n"
                )

        .add_property("queryable",
                &Layer::isQueryable,
                &Layer::setQueryable,
                "Get/Set whether this layer is queryable.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.queryable\n"
                "False # Not queryable by default\n"
                ">>> lyr.queryable = True\n"
                ">>> lyr.queryable\n"
                "True\n"
                )

        .add_property("srs",
                make_function(&Layer::srs,return_value_policy<copy_const_reference>()),
                &Layer::set_srs,
                "Get/Set the SRS of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.srs\n"
                "'+proj=latlong +datum=WGS84' # The default srs if not initialized with custom srs\n"
                ">>> # set to google mercator with Proj.4 literal\n"
                "... \n"
                ">>> lyr.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over'\n"
                )

        .add_property("styles",
                make_function(_styles_,return_value_policy<reference_existing_object>()),
                "The styles list attached to this layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.styles\n"
                "<mapnik._mapnik.Names object at 0x6d3e8>\n"
                ">>> len(lyr.styles)\n"
                "0\n # no styles until you append them\n"
                "lyr.styles.append('My Style') # mapnik uses named styles for flexibility\n"
                ">>> len(lyr.styles)\n"
                "1\n"
                ">>> lyr.styles[0]\n"
                "'My Style'\n"
                )

        .add_property("title",
                make_function(&Layer::title, return_value_policy<copy_const_reference>()),
                &Layer::set_title,
                "Get/Set the title of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.title\n"
                "''\n"
                ">>> lyr.title = 'My first layer'\n"
                ">>> lyr.title\n"
                "'My first layer'\n"
                )

        ;
}
<commit_msg>via a layer object pickle datasource params rather than the datasource object itself - see #345<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon, Dane Springmeyer
 *
 * This library 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; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $

// boost
#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

// mapnik
#include <mapnik/layer.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/datasource_cache.hpp>

using mapnik::Layer;
using mapnik::parameters;
using mapnik::datasource_cache;

struct layer_pickle_suite : boost::python::pickle_suite
{
   static boost::python::tuple
   getinitargs(const Layer& l)
   {
      return boost::python::make_tuple(l.name(),l.srs());
   }

   static  boost::python::tuple
   getstate(const Layer& l)
   {
        boost::python::list s;
        std::vector<std::string> const& style_names = l.styles();
        for (unsigned i = 0; i < style_names.size(); ++i)
        {
            s.append(style_names[i]);
        }
        return boost::python::make_tuple(l.abstract(),l.title(),l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),s);
   }

   static void
   setstate (Layer& l, boost::python::tuple state)
   {
        using namespace boost::python;
        if (len(state) != 8)
        {
         PyErr_SetObject(PyExc_ValueError,
                         ("expected 8-item tuple in call to __setstate__; got %s"
                          % state).ptr()
            );
         throw_error_already_set();
        }

        if (state[0])
        {
            l.set_abstract(extract<std::string>(state[0]));
        }

        if (state[1])
        {
            l.set_title(extract<std::string>(state[1]));
        }

        if (state[2])
        {
            l.set_clear_label_cache(extract<bool>(state[2]));
        }

        if (state[3])
        {
            l.setMinZoom(extract<double>(state[3]));
        }

        if (state[4])
        {
            l.setMaxZoom(extract<double>(state[4]));
        }

        if (state[5])
        {
            l.setQueryable(extract<bool>(state[5]));
        }

        if (state[6])
        {
            mapnik::parameters params = extract<parameters>(state[6]);
            l.set_datasource(datasource_cache::instance()->create(params));
        }

        boost::python::list s = extract<boost::python::list>(state[7]);
        for (int i=0;i<len(s);++i)
        {
           l.add_style(extract<std::string>(s[i]));
        }
   }
};

std::vector<std::string> & (mapnik::Layer::*_styles_)() = &mapnik::Layer::styles;

void export_layer()
{
    using namespace boost::python;
    class_<std::vector<std::string> >("Names")
    	.def(vector_indexing_suite<std::vector<std::string>,true >())
    	;

    class_<Layer>("Layer", "A Mapnik map layer.", init<std::string const&,optional<std::string const&> >(
                "Create a Layer with a named string and, optionally, an srs string.\n"
                "\n"
                "The srs can be either a Proj.4 epsg code ('+init=epsg:<code>') or\n"
                "of a Proj.4 literal ('+proj=<literal>').\n"
                "If no srs is specified it will default to '+proj=latlong +datum=WGS84'\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr\n"
                "<mapnik._mapnik.Layer object at 0x6a270>\n"
                ))

        .def_pickle(layer_pickle_suite())

        .def("envelope",&Layer::envelope,
                "Return the geographic envelope/bounding box."
                "\n"
                "Determined based on the layer datasource.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.envelope()\n"
                "Envelope(-1.0,-1.0,0.0,0.0) # default until a datasource is loaded\n"
                )

        .def("visible", &Layer::isVisible,
                "Return True if this layer's data is active and visible at a given scale.\n"
                "\n"
                "Otherwise returns False.\n"
                "Accepts a scale value as an integer or float input.\n"
                "Will return False if:\n"
                "\tscale >= minzoom - 1e-6\n"
                "\tor:\n"
                "\tscale < maxzoom + 1e-6\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.visible(1.0/1000000)\n"
                "True\n"
                ">>> lyr.active = False\n"
                ">>> lyr.visible(1.0/1000000)\n"
                "False\n"
                )

        .add_property("abstract",
                make_function(&Layer::abstract,return_value_policy<copy_const_reference>()),
                &Layer::set_abstract,
                "Get/Set the abstract of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.abstract\n"
                "'' # default is en empty string\n"
                ">>> lyr.abstract = 'My Shapefile rendered with Mapnik'\n"
                ">>> lyr.abstract\n"
                "'My Shapefile rendered with Mapnik'\n"
                )

        .add_property("active",
                &Layer::isActive,
                &Layer::setActive,
                "Get/Set whether this layer is active and will be rendered.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.active\n"
                "True # Active by default\n"
                ">>> lyr.active = False # set False to disable layer rendering\n"
                ">>> lyr.active\n"
                "False\n"
                )

        .add_property("clear_label_cache",
                &Layer::clear_label_cache,
                &Layer::set_clear_label_cache,
                "Get/Set whether this layer's labels are cached.\n"
                "\n"
                "Usage:\n"
                "TODO\n"
                )

        .add_property("datasource",
                &Layer::datasource,
                &Layer::set_datasource,
                "The datasource attached to this layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer, Datasource\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.datasource = Datasource(type='shape',file='world_borders')\n"
                ">>> lyr.datasource\n"
                "<mapnik.Datasource object at 0x65470>\n"
                )

        .add_property("maxzoom",
                &Layer::getMaxZoom,
                &Layer::setMaxZoom,
                "Get/Set the maximum zoom lever of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.maxzoom\n"
                "1.7976931348623157e+308 # default is the numerical maximum\n"
                ">>> lyr.maxzoom = 1.0/1000000\n"
                ">>> lyr.maxzoom\n"
                "9.9999999999999995e-07\n"
                )

        .add_property("minzoom",
                &Layer::getMinZoom,
                &Layer::setMinZoom,
                "Get/Set the minimum zoom lever of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.minzoom # default is 0\n"
                "0.0\n"
                ">>> lyr.minzoom = 1.0/1000000\n"
                ">>> lyr.minzoom\n"
                "9.9999999999999995e-07\n"
                )

        .add_property("name",
                make_function(&Layer::name, return_value_policy<copy_const_reference>()),
                &Layer::set_name,
                "Get/Set the name of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.name\n"
                "'My Layer'\n"
                ">>> lyr.name = 'New Name'\n"
                ">>> lyr.name\n"
                "'New Name'\n"
                )

        .add_property("queryable",
                &Layer::isQueryable,
                &Layer::setQueryable,
                "Get/Set whether this layer is queryable.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.queryable\n"
                "False # Not queryable by default\n"
                ">>> lyr.queryable = True\n"
                ">>> lyr.queryable\n"
                "True\n"
                )

        .add_property("srs",
                make_function(&Layer::srs,return_value_policy<copy_const_reference>()),
                &Layer::set_srs,
                "Get/Set the SRS of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.srs\n"
                "'+proj=latlong +datum=WGS84' # The default srs if not initialized with custom srs\n"
                ">>> # set to google mercator with Proj.4 literal\n"
                "... \n"
                ">>> lyr.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over'\n"
                )

        .add_property("styles",
                make_function(_styles_,return_value_policy<reference_existing_object>()),
                "The styles list attached to this layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.styles\n"
                "<mapnik._mapnik.Names object at 0x6d3e8>\n"
                ">>> len(lyr.styles)\n"
                "0\n # no styles until you append them\n"
                "lyr.styles.append('My Style') # mapnik uses named styles for flexibility\n"
                ">>> len(lyr.styles)\n"
                "1\n"
                ">>> lyr.styles[0]\n"
                "'My Style'\n"
                )

        .add_property("title",
                make_function(&Layer::title, return_value_policy<copy_const_reference>()),
                &Layer::set_title,
                "Get/Set the title of the layer.\n"
                "\n"
                "Usage:\n"
                ">>> from mapnik import Layer\n"
                ">>> lyr = Layer('My Layer','+proj=latlong +datum=WGS84')\n"
                ">>> lyr.title\n"
                "''\n"
                ">>> lyr.title = 'My first layer'\n"
                ">>> lyr.title\n"
                "'My first layer'\n"
                )

        ;
}
<|endoftext|>