<commit_before>//===-- MachineFunction.cpp -----------------------------------------------===//
//
// Collect native machine code information for a function.  This allows
// target-specific information about the generated code to be stored with each
// function.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineFrameInfo.h"
#include "llvm/Target/MachineCacheInfo.h"
#include "llvm/Function.h"
#include "llvm/iOther.h"
#include "llvm/Pass.h"
#include <limits.h>

const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max();

static AnnotationID MF_AID(
                 AnnotationManager::getID("CodeGen::MachineCodeForFunction"));

//===---------------------------------------------------------------------===//
// Code generation/destruction passes
//===---------------------------------------------------------------------===//

namespace {
  class ConstructMachineFunction : public FunctionPass {
    TargetMachine &Target;
  public:
    ConstructMachineFunction(TargetMachine &T) : Target(T) {}

    const char *getPassName() const {
      return "ConstructMachineFunction";
    }

    bool runOnFunction(Function &F) {
      MachineFunction::construct(&F, Target).CalculateArgSize();
      return false;
    }
  };

  struct DestroyMachineFunction : public FunctionPass {
    const char *getPassName() const { return "FreeMachineFunction"; }

    static void freeMachineCode(Instruction &I) {
      MachineCodeForInstruction::destroy(&I);
    }

    bool runOnFunction(Function &F) {
      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
          MachineCodeForInstruction::get(I).dropAllReferences();

      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for_each(FI->begin(), FI->end(), freeMachineCode);

      return false;
    }
  };

  struct Printer : public FunctionPass {
    const char *getPassName() const { return "MachineFunction Printer"; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }

    bool runOnFunction(Function &F) {
      MachineFunction::get(&F).dump();
      return false;
    }
  };
}

Pass *createMachineCodeConstructionPass(TargetMachine &Target) {
  return new ConstructMachineFunction(Target);
}

Pass *createMachineCodeDestructionPass() {
  return new DestroyMachineFunction();
}

Pass *createMachineFunctionPrinterPass() {
  return new Printer();
}

//===---------------------------------------------------------------------===//
// MachineFunction implementation
//===---------------------------------------------------------------------===//

MachineFunction::MachineFunction(const Function *F,
                                 const TargetMachine& target)
  : Annotation(MF_AID), Fn(F), Target(target) {
  SSARegMapping = new SSARegMap();

  // FIXME: move state into another class
  staticStackSize = automaticVarsSize = regSpillsSize = 0;
  maxOptionalArgsSize = maxOptionalNumArgs = currentTmpValuesSize = 0;
  maxTmpValuesSize = 0;
  compiledAsLeaf = spillsAreaFrozen = automaticVarsAreaFrozen = false;
}

MachineFunction::~MachineFunction() {
  delete SSARegMapping;
}

void MachineFunction::dump() const { print(std::cerr); }

void MachineFunction::print(std::ostream &OS) const {
  OS << "\n" << *(Value*)Fn->getReturnType() << " \"" << Fn->getName()<< "\"\n";

  for (const_iterator BB = begin(); BB != end(); ++BB) {
    BasicBlock *LBB = BB->getBasicBlock();
    OS << "\n" << LBB->getName() << " (" << (const void*)LBB << "):\n";
    for (MachineBasicBlock::const_iterator I = BB->begin(); I != BB->end();++I){
      OS << "\t";
      (*I)->print(OS, Target);
    }
  }
  OS << "\nEnd function \"" << Fn->getName() << "\"\n\n";
}

// The next two methods are used to construct and to retrieve
// the MachineCodeForFunction object for the given function.
// construct() -- Allocates and initializes for a given function and target
// get()       -- Returns a handle to the object.
//                This should not be called before "construct()"
//                for a given Function.
//
MachineFunction&
MachineFunction::construct(const Function *Fn, const TargetMachine &Tar)
{
  assert(Fn->getAnnotation(MF_AID) == 0 &&
         "Object already exists for this function!");
  MachineFunction* mcInfo = new MachineFunction(Fn, Tar);
  Fn->addAnnotation(mcInfo);
  return *mcInfo;
}

void
MachineFunction::destruct(const Function *Fn)
{
  bool Deleted = Fn->deleteAnnotation(MF_AID);
  assert(Deleted && "Machine code did not exist for function!");
}

MachineFunction& MachineFunction::get(const Function *F)
{
  MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID);
  assert(mc && "Call construct() method first to allocate the object");
  return *mc;
}

void MachineFunction::clearSSARegMap() {
  delete SSARegMapping;
  SSARegMapping = 0;
}

static unsigned
ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
                           unsigned &maxOptionalNumArgs)
{
  const MachineFrameInfo& frameInfo = target.getFrameInfo();

  unsigned maxSize = 0;

  for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB)
    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
      if (const CallInst *callInst = dyn_cast<CallInst>(&*I))
        {
          unsigned numOperands = callInst->getNumOperands() - 1;
          int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs();
          if (numExtra <= 0)
            continue;

          unsigned int sizeForThisCall;
          if (frameInfo.argsOnStackHaveFixedSize())
            {
              int argSize = frameInfo.getSizeOfEachArgOnStack();
              sizeForThisCall = numExtra * (unsigned) argSize;
            }
          else
            {
              assert(0 && "UNTESTED CODE: Size per stack argument is not "
                     "fixed on this architecture: use actual arg sizes to "
                     "compute MaxOptionalArgsSize");
              sizeForThisCall = 0;
              for (unsigned i = 0; i < numOperands; ++i)
                sizeForThisCall += target.DataLayout.getTypeSize(callInst->
                                              getOperand(i)->getType());
            }

          if (maxSize < sizeForThisCall)
            maxSize = sizeForThisCall;

          if ((int)maxOptionalNumArgs < numExtra)
            maxOptionalNumArgs = (unsigned) numExtra;
        }

  return maxSize;
}

// Align data larger than one L1 cache line on L1 cache line boundaries.
// Align all smaller data on the next higher 2^x boundary (4, 8, ...),
// but not higher than the alignment of the largest type we support
// (currently a double word). -- see class TargetData).
//
// This function is similar to the corresponding function in EmitAssembly.cpp
// but they are unrelated.  This one does not align at more than a
// double-word boundary whereas that one might.
//
inline unsigned int
SizeToAlignment(unsigned int size, const TargetMachine& target)
{
  unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
  if (size > (unsigned) cacheLineSize / 2)
    return cacheLineSize;
  else
    for (unsigned sz=1; /*no condition*/; sz *= 2)
      if (sz >= size || sz >= target.DataLayout.getDoubleAlignment())
        return sz;
}

void MachineFunction::CalculateArgSize() {
  maxOptionalArgsSize = ComputeMaxOptionalArgsSize(Target, Fn,
                                                   maxOptionalNumArgs);
  staticStackSize = maxOptionalArgsSize
    + Target.getFrameInfo().getMinStackFrameSize();
}

int
MachineFunction::computeOffsetforLocalVar(const TargetMachine& target,
                                               const Value* val,
                                               unsigned int& getPaddedSize,
                                               unsigned int  sizeToUse)
{
  if (sizeToUse == 0)
    sizeToUse = target.findOptimalStorageSize(val->getType());
  unsigned int align = SizeToAlignment(sizeToUse, target);

  bool growUp;
  int firstOffset = target.getFrameInfo().getFirstAutomaticVarOffset(*this,
                                                                     growUp);
  int offset = growUp? firstOffset + getAutomaticVarsSize()
                     : firstOffset - (getAutomaticVarsSize() + sizeToUse);

  int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align);
  getPaddedSize = sizeToUse + abs(aligned - offset);

  return aligned;
}

int
MachineFunction::allocateLocalVar(const TargetMachine& target,
                                       const Value* val,
                                       unsigned int sizeToUse)
{
  assert(! automaticVarsAreaFrozen &&
         "Size of auto vars area has been used to compute an offset so "
         "no more automatic vars should be allocated!");

  // Check if we've allocated a stack slot for this value already
  //
  int offset = getOffset(val);
  if (offset == INVALID_FRAME_OFFSET)
    {
      unsigned int getPaddedSize;
      offset = computeOffsetforLocalVar(target, val, getPaddedSize, sizeToUse);
      offsets[val] = offset;
      incrementAutomaticVarsSize(getPaddedSize);
    }
  return offset;
}

int
MachineFunction::allocateSpilledValue(const TargetMachine& target,
                                           const Type* type)
{
  assert(! spillsAreaFrozen &&
         "Size of reg spills area has been used to compute an offset so "
         "no more register spill slots should be allocated!");

  unsigned int size  = target.DataLayout.getTypeSize(type);
  unsigned char align = target.DataLayout.getTypeAlignment(type);

  bool growUp;
  int firstOffset = target.getFrameInfo().getRegSpillAreaOffset(*this, growUp);

  int offset = growUp? firstOffset + getRegSpillsSize()
                     : firstOffset - (getRegSpillsSize() + size);

  int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align);
  size += abs(aligned - offset); // include alignment padding in size

  incrementRegSpillsSize(size);  // update size of reg. spills area

  return aligned;
}

int
MachineFunction::pushTempValue(const TargetMachine& target,
                                    unsigned int size)
{
  unsigned int align = SizeToAlignment(size, target);

  bool growUp;
  int firstOffset = target.getFrameInfo().getTmpAreaOffset(*this, growUp);

  int offset = growUp? firstOffset + currentTmpValuesSize
                     : firstOffset - (currentTmpValuesSize + size);

  int aligned = target.getFrameInfo().adjustAlignment(offset, growUp, align);
  size += abs(aligned - offset); // include alignment padding in size

  incrementTmpAreaSize(size);    // update "current" size of tmp area

  return aligned;
}

void
MachineFunction::popAllTempValues(const TargetMachine& target)
{
  resetTmpAreaSize();            // clear tmp area to reuse
}

int
MachineFunction::getOffset(const Value* val) const
{
  hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
  return (pair == offsets.end()) ? INVALID_FRAME_OFFSET : pair->second;
}
<commit_msg>* A bunch of functionality and data was removed from MachineFunction and put   into a new MachineFunctionInfo class * Implement new FunctionFrameInfo class<commit_after>//===-- MachineFunction.cpp -----------------------------------------------===//
//
// Collect native machine code information for a function.  This allows
// target-specific information about the generated code to be stored with each
// function.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/FunctionFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineFrameInfo.h"
#include "llvm/Target/MachineCacheInfo.h"
#include "llvm/Function.h"
#include "llvm/iOther.h"
#include "llvm/Pass.h"
#include <limits.h>

const int INVALID_FRAME_OFFSET = INT_MAX; // std::numeric_limits<int>::max();

static AnnotationID MF_AID(
                 AnnotationManager::getID("CodeGen::MachineCodeForFunction"));

//===---------------------------------------------------------------------===//
// Code generation/destruction passes
//===---------------------------------------------------------------------===//

namespace {
  class ConstructMachineFunction : public FunctionPass {
    TargetMachine &Target;
  public:
    ConstructMachineFunction(TargetMachine &T) : Target(T) {}

    const char *getPassName() const {
      return "ConstructMachineFunction";
    }

    bool runOnFunction(Function &F) {
      MachineFunction::construct(&F, Target).getInfo()->CalculateArgSize();
      return false;
    }
  };

  struct DestroyMachineFunction : public FunctionPass {
    const char *getPassName() const { return "FreeMachineFunction"; }

    static void freeMachineCode(Instruction &I) {
      MachineCodeForInstruction::destroy(&I);
    }

    bool runOnFunction(Function &F) {
      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
          MachineCodeForInstruction::get(I).dropAllReferences();

      for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
        for_each(FI->begin(), FI->end(), freeMachineCode);

      return false;
    }
  };

  struct Printer : public FunctionPass {
    const char *getPassName() const { return "MachineFunction Printer"; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }

    bool runOnFunction(Function &F) {
      MachineFunction::get(&F).dump();
      return false;
    }
  };
}

Pass *createMachineCodeConstructionPass(TargetMachine &Target) {
  return new ConstructMachineFunction(Target);
}

Pass *createMachineCodeDestructionPass() {
  return new DestroyMachineFunction();
}

Pass *createMachineFunctionPrinterPass() {
  return new Printer();
}

//===---------------------------------------------------------------------===//
// MachineFunction implementation
//===---------------------------------------------------------------------===//

MachineFunction::MachineFunction(const Function *F,
                                 const TargetMachine &TM)
  : Annotation(MF_AID), Fn(F), Target(TM) {
  SSARegMapping = new SSARegMap();
  MFInfo = new MachineFunctionInfo(*this);
  FrameInfo = new FunctionFrameInfo();
}

MachineFunction::~MachineFunction() {
  delete SSARegMapping;
  delete MFInfo;
  delete FrameInfo;
}

void MachineFunction::dump() const { print(std::cerr); }

void MachineFunction::print(std::ostream &OS) const {
  OS << "\n" << *(Value*)Fn->getFunctionType() << " \"" << Fn->getName()
     << "\"\n";

  // Print Frame Information
  getFrameInfo()->print(OS);

  for (const_iterator BB = begin(); BB != end(); ++BB) {
    BasicBlock *LBB = BB->getBasicBlock();
    OS << "\n" << LBB->getName() << " (" << (const void*)LBB << "):\n";
    for (MachineBasicBlock::const_iterator I = BB->begin(); I != BB->end();++I){
      OS << "\t";
      (*I)->print(OS, Target);
    }
  }
  OS << "\nEnd function \"" << Fn->getName() << "\"\n\n";
}

// The next two methods are used to construct and to retrieve
// the MachineCodeForFunction object for the given function.
// construct() -- Allocates and initializes for a given function and target
// get()       -- Returns a handle to the object.
//                This should not be called before "construct()"
//                for a given Function.
//
MachineFunction&
MachineFunction::construct(const Function *Fn, const TargetMachine &Tar)
{
  assert(Fn->getAnnotation(MF_AID) == 0 &&
         "Object already exists for this function!");
  MachineFunction* mcInfo = new MachineFunction(Fn, Tar);
  Fn->addAnnotation(mcInfo);
  return *mcInfo;
}

void
MachineFunction::destruct(const Function *Fn)
{
  bool Deleted = Fn->deleteAnnotation(MF_AID);
  assert(Deleted && "Machine code did not exist for function!");
}

MachineFunction& MachineFunction::get(const Function *F)
{
  MachineFunction *mc = (MachineFunction*)F->getAnnotation(MF_AID);
  assert(mc && "Call construct() method first to allocate the object");
  return *mc;
}

void MachineFunction::clearSSARegMap() {
  delete SSARegMapping;
  SSARegMapping = 0;
}

//===----------------------------------------------------------------------===//
//  FunctionFrameInfo implementation
//===----------------------------------------------------------------------===//

void FunctionFrameInfo::print(std::ostream &OS) const {
  for (unsigned i = 0, e = Objects.size(); i != e; ++i) {
    const StackObject &SO = Objects[i];
    OS << "  <fi# " << (int)(i-NumFixedObjects) << "> is ";
    if (SO.Size == 0)
      OS << "variable sized";
    else
      OS << SO.Size << " byte" << (SO.Size != 1 ? "s" : " ");

    if (i < NumFixedObjects)
      OS << " fixed";
    if (i < NumFixedObjects || SO.SPOffset != -1) {
      OS << " at location [SP";
      if (SO.SPOffset > 0)
	OS << "+" << SO.SPOffset;
      else if (SO.SPOffset < 0)
	OS << SO.SPOffset;
      OS << "]";
    }
    OS << "\n";
  }

  if (HasVarSizedObjects)
    OS << "  Stack frame contains variable sized objects\n";
}

void FunctionFrameInfo::dump() const { print(std::cerr); }

//===----------------------------------------------------------------------===//
//  MachineFunctionInfo implementation
//===----------------------------------------------------------------------===//

static unsigned
ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
                           unsigned &maxOptionalNumArgs)
{
  const TargetFrameInfo &frameInfo = target.getFrameInfo();

  unsigned maxSize = 0;

  for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB)
    for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
      if (const CallInst *callInst = dyn_cast<CallInst>(&*I))
        {
          unsigned numOperands = callInst->getNumOperands() - 1;
          int numExtra = (int)numOperands-frameInfo.getNumFixedOutgoingArgs();
          if (numExtra <= 0)
            continue;

          unsigned sizeForThisCall;
          if (frameInfo.argsOnStackHaveFixedSize())
            {
              int argSize = frameInfo.getSizeOfEachArgOnStack();
              sizeForThisCall = numExtra * (unsigned) argSize;
            }
          else
            {
              assert(0 && "UNTESTED CODE: Size per stack argument is not "
                     "fixed on this architecture: use actual arg sizes to "
                     "compute MaxOptionalArgsSize");
              sizeForThisCall = 0;
              for (unsigned i = 0; i < numOperands; ++i)
                sizeForThisCall += target.getTargetData().getTypeSize(callInst->
                                              getOperand(i)->getType());
            }

          if (maxSize < sizeForThisCall)
            maxSize = sizeForThisCall;

          if ((int)maxOptionalNumArgs < numExtra)
            maxOptionalNumArgs = (unsigned) numExtra;
        }

  return maxSize;
}

// Align data larger than one L1 cache line on L1 cache line boundaries.
// Align all smaller data on the next higher 2^x boundary (4, 8, ...),
// but not higher than the alignment of the largest type we support
// (currently a double word). -- see class TargetData).
//
// This function is similar to the corresponding function in EmitAssembly.cpp
// but they are unrelated.  This one does not align at more than a
// double-word boundary whereas that one might.
//
inline unsigned
SizeToAlignment(unsigned size, const TargetMachine& target)
{
  unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
  if (size > (unsigned) cacheLineSize / 2)
    return cacheLineSize;
  else
    for (unsigned sz=1; /*no condition*/; sz *= 2)
      if (sz >= size || sz >= target.getTargetData().getDoubleAlignment())
        return sz;
}

void MachineFunctionInfo::CalculateArgSize() {
  maxOptionalArgsSize = ComputeMaxOptionalArgsSize(MF.getTarget(),
						   MF.getFunction(),
                                                   maxOptionalNumArgs);
  staticStackSize = maxOptionalArgsSize
    + MF.getTarget().getFrameInfo().getMinStackFrameSize();
}

int
MachineFunctionInfo::computeOffsetforLocalVar(const Value* val,
					      unsigned &getPaddedSize,
					      unsigned  sizeToUse)
{
  if (sizeToUse == 0)
    sizeToUse = MF.getTarget().findOptimalStorageSize(val->getType());
  unsigned align = SizeToAlignment(sizeToUse, MF.getTarget());

  bool growUp;
  int firstOffset = MF.getTarget().getFrameInfo().getFirstAutomaticVarOffset(MF,
									     growUp);
  int offset = growUp? firstOffset + getAutomaticVarsSize()
                     : firstOffset - (getAutomaticVarsSize() + sizeToUse);

  int aligned = MF.getTarget().getFrameInfo().adjustAlignment(offset, growUp, align);
  getPaddedSize = sizeToUse + abs(aligned - offset);

  return aligned;
}

int
MachineFunctionInfo::allocateLocalVar(const Value* val,
				      unsigned sizeToUse)
{
  assert(! automaticVarsAreaFrozen &&
         "Size of auto vars area has been used to compute an offset so "
         "no more automatic vars should be allocated!");

  // Check if we've allocated a stack slot for this value already
  //
  int offset = getOffset(val);
  if (offset == INVALID_FRAME_OFFSET)
    {
      unsigned getPaddedSize;
      offset = computeOffsetforLocalVar(val, getPaddedSize, sizeToUse);
      offsets[val] = offset;
      incrementAutomaticVarsSize(getPaddedSize);
    }
  return offset;
}

int
MachineFunctionInfo::allocateSpilledValue(const Type* type)
{
  assert(! spillsAreaFrozen &&
         "Size of reg spills area has been used to compute an offset so "
         "no more register spill slots should be allocated!");

  unsigned size  = MF.getTarget().getTargetData().getTypeSize(type);
  unsigned char align = MF.getTarget().getTargetData().getTypeAlignment(type);

  bool growUp;
  int firstOffset = MF.getTarget().getFrameInfo().getRegSpillAreaOffset(MF, growUp);

  int offset = growUp? firstOffset + getRegSpillsSize()
                     : firstOffset - (getRegSpillsSize() + size);

  int aligned = MF.getTarget().getFrameInfo().adjustAlignment(offset, growUp, align);
  size += abs(aligned - offset); // include alignment padding in size

  incrementRegSpillsSize(size);  // update size of reg. spills area

  return aligned;
}

int
MachineFunctionInfo::pushTempValue(unsigned size)
{
  unsigned align = SizeToAlignment(size, MF.getTarget());

  bool growUp;
  int firstOffset = MF.getTarget().getFrameInfo().getTmpAreaOffset(MF, growUp);

  int offset = growUp? firstOffset + currentTmpValuesSize
                     : firstOffset - (currentTmpValuesSize + size);

  int aligned = MF.getTarget().getFrameInfo().adjustAlignment(offset, growUp,
							      align);
  size += abs(aligned - offset); // include alignment padding in size

  incrementTmpAreaSize(size);    // update "current" size of tmp area

  return aligned;
}

void MachineFunctionInfo::popAllTempValues() {
  resetTmpAreaSize();            // clear tmp area to reuse
}

int
MachineFunctionInfo::getOffset(const Value* val) const
{
  hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
  return (pair == offsets.end()) ? INVALID_FRAME_OFFSET : pair->second;
}
<|endoftext|>


<commit_before>//
// Copyright (C) 2011-2014 Jeff Bush
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library 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.
//

#include <stdint.h>
#include <stdlib.h>
#include "Surface.h"

using namespace librender;

Surface::Surface(int width, int height, void *base)
    :	fWidth(width),
        fHeight(height),
        fStride(width * kBytesPerPixel),
        fBaseAddress((unsigned int) base),
		fOwnedPointer(false)
{
	initializePointerVec();
}

Surface::Surface(int fbWidth, int fbHeight)
    :	fWidth(fbWidth),
        fHeight(fbHeight),
        fStride(fbWidth * kBytesPerPixel),
		fOwnedPointer(true)
{
	fBaseAddress = (unsigned int) memalign(kCacheLineSize, fbWidth * fbHeight * kBytesPerPixel);
	initializePointerVec();
}

Surface::~Surface()
{
	if (fOwnedPointer)
		::free((void*) fBaseAddress);
}

void Surface::initializePointerVec()
{
    f4x4AtOrigin = {
		fBaseAddress,
   		fBaseAddress + 4,
   		fBaseAddress + 8,
   		fBaseAddress + 12,
   		fBaseAddress + (fWidth * 4),
   		fBaseAddress + (fWidth * 4) + 4,
   		fBaseAddress + (fWidth * 4) + 8,
   		fBaseAddress + (fWidth * 4) + 12,
   		fBaseAddress + (fWidth * 8),
   		fBaseAddress + (fWidth * 8) + 4,
   		fBaseAddress + (fWidth * 8) + 8,
   		fBaseAddress + (fWidth * 8) + 12,
   		fBaseAddress + (fWidth * 12),
   		fBaseAddress + (fWidth * 12) + 4,
   		fBaseAddress + (fWidth * 12) + 8,
   		fBaseAddress + (fWidth * 12) + 12
	};
}

void Surface::clearTileSlow(int left, int top, unsigned int value)
{
    veci16_t *ptr = (veci16_t*)(fBaseAddress + (left + top * fWidth) * kBytesPerPixel);
    const veci16_t kClearColor = splati(value);
	int right = min(kTileSize, fWidth - left);
	int bottom = min(kTileSize, fHeight - top);
    const int kStride = ((fWidth - right) * kBytesPerPixel / sizeof(veci16_t));

    for (int y = 0; y < bottom; y++)
    {
		// XXX LLVM ends up turning this into memset
        for (int x = 0; x < right; x += 16)
            *ptr++ = kClearColor;

        ptr += kStride;
    }
}

// Push a NxN tile from the L2 cache back to system memory
void Surface::flushTile(int left, int top)
{
    unsigned int ptr = fBaseAddress + (left + top * fWidth) * kBytesPerPixel;
	int right = min(kTileSize, fWidth - left);
	int bottom = min(kTileSize, fHeight - top);
    const int kStride = (fWidth - right) * kBytesPerPixel;
    for (int y = 0; y < bottom; y++)
    {
        for (int x = 0; x < right; x += 16)
        {
			asm("dflush %0" : : "s" (ptr));
            ptr += kCacheLineSize;
        }

        ptr += kStride;
    }
}
<commit_msg>Fix mixed tabs/spaces<commit_after>//
// Copyright (C) 2011-2014 Jeff Bush
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library 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.
//

#include <stdint.h>
#include <stdlib.h>
#include "Surface.h"

using namespace librender;

Surface::Surface(int width, int height, void *base)
    :	fWidth(width),
        fHeight(height),
        fStride(width * kBytesPerPixel),
        fBaseAddress((unsigned int) base),
		fOwnedPointer(false)
{
	initializePointerVec();
}

Surface::Surface(int fbWidth, int fbHeight)
    :	fWidth(fbWidth),
        fHeight(fbHeight),
        fStride(fbWidth * kBytesPerPixel),
		fOwnedPointer(true)
{
	fBaseAddress = (unsigned int) memalign(kCacheLineSize, fbWidth * fbHeight * kBytesPerPixel);
	initializePointerVec();
}

Surface::~Surface()
{
	if (fOwnedPointer)
		::free((void*) fBaseAddress);
}

void Surface::initializePointerVec()
{
    f4x4AtOrigin = {
		fBaseAddress,
   		fBaseAddress + 4,
   		fBaseAddress + 8,
   		fBaseAddress + 12,
   		fBaseAddress + (fWidth * 4),
   		fBaseAddress + (fWidth * 4) + 4,
   		fBaseAddress + (fWidth * 4) + 8,
   		fBaseAddress + (fWidth * 4) + 12,
   		fBaseAddress + (fWidth * 8),
   		fBaseAddress + (fWidth * 8) + 4,
   		fBaseAddress + (fWidth * 8) + 8,
   		fBaseAddress + (fWidth * 8) + 12,
   		fBaseAddress + (fWidth * 12),
   		fBaseAddress + (fWidth * 12) + 4,
   		fBaseAddress + (fWidth * 12) + 8,
   		fBaseAddress + (fWidth * 12) + 12
	};
}

void Surface::clearTileSlow(int left, int top, unsigned int value)
{
	veci16_t *ptr = (veci16_t*)(fBaseAddress + (left + top * fWidth) * kBytesPerPixel);
	const veci16_t kClearColor = splati(value);
	int right = min(kTileSize, fWidth - left);
	int bottom = min(kTileSize, fHeight - top);
	const int kStride = ((fWidth - right) * kBytesPerPixel / sizeof(veci16_t));

	for (int y = 0; y < bottom; y++)
	{
		// XXX LLVM ends up turning this into memset
		for (int x = 0; x < right; x += 16)
			*ptr++ = kClearColor;

		ptr += kStride;
	}
}

// Push a NxN tile from the L2 cache back to system memory
void Surface::flushTile(int left, int top)
{
	unsigned int ptr = fBaseAddress + (left + top * fWidth) * kBytesPerPixel;
	int right = min(kTileSize, fWidth - left);
	int bottom = min(kTileSize, fHeight - top);
	const int kStride = (fWidth - right) * kBytesPerPixel;
	for (int y = 0; y < bottom; y++)
	{
		for (int x = 0; x < right; x += 16)
		{
			asm("dflush %0" : : "s" (ptr));
			ptr += kCacheLineSize;
		}

		ptr += kStride;
	}
}
<|endoftext|>


<commit_before>// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair

// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t k 2>&1 | FileCheck %s -check-prefix=OK -allow-empty
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t g 2>&1 | FileCheck %s -check-prefix=CMP -check-prefix=ALL-ERRORS
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t s 2>&1 | FileCheck %s -check-prefix=SUB -check-prefix=ALL-ERRORS
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t f 2>&1 | FileCheck %s -check-prefix=FREE -check-prefix=ALL-ERRORS

#include <assert.h>
#include <stdlib.h>

int f(char c, char *p, char *q) {
  // ALL-ERRORS: ERROR: AddressSanitizer: invalid-pointer-pair
  // [[PTR1:0x[0-9a-f]+]] [[PTR2:0x[0-9a-f]+]]
  switch (c) {
  case 'g':
    // CMP: #0 {{.*}} in f({{char, char\*, char\*|char,char \*,char \*}}) {{.*}}invalid-pointer-pairs.cc:[[@LINE+1]]:14
    return p > q;
  case 's':
    // SUB: #0 {{.*}} in f({{char, char\*, char\*|char,char \*,char \*}}) {{.*}}invalid-pointer-pairs.cc:[[@LINE+1]]:14
    return p - q;
  case 'k': {
    // OK-NOT: ERROR
    char *p2 = p + 20;
    return p > p2;
  }
  case 'f': {
    char *p3 = p + 20;
    free(p);
    // FREE: #0 {{.*}} in f({{char, char\*, char\*|char,char \*,char \*}}) {{.*}}invalid-pointer-pairs.cc:[[@LINE+2]]:14
    // FREE: freed by thread
    return p < p3;
  }
  }
  assert(0);
}

int main(int argc, char **argv) {
  char *p = (char *)malloc(42);
  char *q = (char *)malloc(42);
  assert(argc >= 2);
  f(argv[1][0], p, q);
  free(p);
  free(q);
}
<commit_msg>[asan] Relax a flaky invalid-pointer-pairs test<commit_after>// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair

// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t k 2>&1 | FileCheck %s -check-prefix=OK -allow-empty
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t g 2>&1 | FileCheck %s -check-prefix=CMP -check-prefix=ALL-ERRORS
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t s 2>&1 | FileCheck %s -check-prefix=SUB -check-prefix=ALL-ERRORS
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t f 2>&1 | FileCheck %s -check-prefix=FREE -check-prefix=ALL-ERRORS

#include <assert.h>
#include <stdlib.h>

int f(char c, char *p, char *q) {
  // ALL-ERRORS: ERROR: AddressSanitizer: invalid-pointer-pair
  // [[PTR1:0x[0-9a-f]+]] [[PTR2:0x[0-9a-f]+]]
  switch (c) {
  case 'g':
    // CMP: #{{[0-9]+ .*}} in f({{char, char\*, char\*|char,char \*,char \*}}) {{.*}}invalid-pointer-pairs.cc:[[@LINE+1]]:14
    return p > q;
  case 's':
    // SUB: #{{[0-9]+ .*}} in f({{char, char\*, char\*|char,char \*,char \*}}) {{.*}}invalid-pointer-pairs.cc:[[@LINE+1]]:14
    return p - q;
  case 'k': {
    // OK-NOT: ERROR
    char *p2 = p + 20;
    return p > p2;
  }
  case 'f': {
    char *p3 = p + 20;
    free(p);
    // FREE: #{{[0-9]+ .*}} in f({{char, char\*, char\*|char,char \*,char \*}}) {{.*}}invalid-pointer-pairs.cc:[[@LINE+2]]:14
    // FREE: freed by thread
    return p < p3;
  }
  }
  assert(0);
}

int main(int argc, char **argv) {
  char *p = (char *)malloc(42);
  char *q = (char *)malloc(42);
  assert(argc >= 2);
  f(argv[1][0], p, q);
  free(p);
  free(q);
}
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>

#include "util.hpp"

static constexpr auto external_sensor =
    "/xyz/openbmc_project/extsensors/"; // type/
static constexpr auto openbmc_sensor = "/xyz/openbmc_project/"; // type/
static constexpr auto sysfs = "/sys/";

IOInterfaceType GetWriteInterfaceType(const std::string& path)
{
    std::string::size_type n;

    if (path.empty() || "None" == path)
    {
        return IOInterfaceType::NONE;
    }

    if (path.find(sysfs) != std::string::npos)
    {
        // A sysfs read sensor.
        return IOInterfaceType::SYSFS;
    }

    return IOInterfaceType::UNKNOWN;
}

IOInterfaceType GetReadInterfaceType(const std::string& path)
{
    std::string::size_type n;

    if (path.empty() || "None" == path)
    {
        return IOInterfaceType::NONE;
    }

    if (path.find(external_sensor) != std::string::npos)
    {
        return IOInterfaceType::EXTERNAL;
    }

    if (path.find(openbmc_sensor) != std::string::npos)
    {
        return IOInterfaceType::DBUSPASSIVE;
    }

    if (path.find(sysfs) != std::string::npos)
    {
        return IOInterfaceType::SYSFS;
    }

    return IOInterfaceType::UNKNOWN;
}

<commit_msg>util: remove unused variable<commit_after>/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>

#include "util.hpp"

static constexpr auto external_sensor =
    "/xyz/openbmc_project/extsensors/"; // type/
static constexpr auto openbmc_sensor = "/xyz/openbmc_project/"; // type/
static constexpr auto sysfs = "/sys/";

IOInterfaceType GetWriteInterfaceType(const std::string& path)
{
    if (path.empty() || "None" == path)
    {
        return IOInterfaceType::NONE;
    }

    if (path.find(sysfs) != std::string::npos)
    {
        // A sysfs read sensor.
        return IOInterfaceType::SYSFS;
    }

    return IOInterfaceType::UNKNOWN;
}

IOInterfaceType GetReadInterfaceType(const std::string& path)
{
    if (path.empty() || "None" == path)
    {
        return IOInterfaceType::NONE;
    }

    if (path.find(external_sensor) != std::string::npos)
    {
        return IOInterfaceType::EXTERNAL;
    }

    if (path.find(openbmc_sensor) != std::string::npos)
    {
        return IOInterfaceType::DBUSPASSIVE;
    }

    if (path.find(sysfs) != std::string::npos)
    {
        return IOInterfaceType::SYSFS;
    }

    return IOInterfaceType::UNKNOWN;
}

<|endoftext|>


<commit_before>/*
 * trend: display live data on a trend graph
 * Copyright(c) 2003-2004 by wave++ "Yuri D'Elia" <wavexx@users.sf.net>
 * Distributed under GNU LGPL WITHOUT ANY WARRANTY.
 */

/*
 * Headers
 */

// defaults
#include "defaults.hh"

// system headers
#include <stdexcept>
#include <deque>
using std::deque;

#include <iostream>
using std::cout;
using std::cerr;
using std::cin;

#include <string>
using std::string;

#include <utility>
using std::pair;

#include <cmath>
using std::isnan;

// c system headers
#include <cstdlib>
using std::strtod;
using std::strtoul;

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <pthread.h>

// OpenGL/GLU
#include <GL/glut.h>

/*
 * Data structures
 */

struct Value
{
  Value(double value, size_t count)
  : value(value), count(count)
  {}

  double value;
  size_t count;
};

/*
 * Graph/Program state
 */

namespace
{
  // Basic data
  const char* fileName;
  pthread_mutex_t mutex;
  bool damaged = false;

  // Data and fixed parameters
  deque<Value> data;
  double loLimit;
  double hiLimit;
  size_t history;
  size_t divisions;

  // Visual/Fixed settings
  const char* title = NULL;

  // Visual/Changeable settings
  bool autoLimit;
  bool smooth = Trend::smooth;
  bool scroll = Trend::scroll;
  bool values = Trend::values;
  bool marker = Trend::marker;
  bool grid = Trend::grid;
  double gridres = Trend::gridres;
}

/*
 * I/O and data manipulation
 */

// skip whitespace
void
skipSpc(FILE* fd)
{
  char c;

  do { c = getc_unlocked(fd); }
  while(isspace(c) && c != EOF);
  ungetc(c, fd);
}

// skip a space-separated string
void
skipStr(FILE* fd)
{
  char c;

  do { c = getc_unlocked(fd); }
  while(!isspace(c) && c != EOF);
  ungetc(c, fd);
}

// read a space-separated string
char*
readStr(FILE* fd, char* buf, size_t len)
{
  char* p(buf);
  int c;

  while(len--)
  {
    c = getc_unlocked(fd);
    if(c == EOF || isspace(c))
    {
      ungetc(c, fd);
      return p;
    }
    *p++ = c;
  }

  // overflow
  return NULL;
}

// read a number from the stream
double
readNum(FILE* fd)
{
  // discard initial whitespace
  skipSpc(fd);
  if(feof(fd))
    return NAN;

  // read the number
  char buf[Trend::maxNumLen];
  char* end = readStr(fd, buf, sizeof(buf));
  if(feof(fd))
    return NAN;
  if(!end)
  {
    // long string, skip it.
    skipStr(fd);
    return NAN;
  }

  // convert the number
  double num = strtod(buf, &end);
  if(end == buf)
    return NAN;

  return num;
}

// producer thread
void*
thread(void*)
{
  // iostreams under gcc 3.x are completely unusable for advanced tasks such as
  // customizable buffering/locking/etc. They also removed the (really
  // standard) ->fd() access for "encapsulation"...
  FILE* in;

  for(size_t pos = 0; fileName;)
  {
    // open the file and disable buffering
    in = fopen(fileName, "r");
    if(!in) break;
    setvbuf(in, NULL, _IONBF, 0);

    // read all data
    double num;

    while(!isnan(num = readNum(in)) && fileName)
    {
      // append the value
      pthread_mutex_lock(&mutex);

      data.push_back(Value(num, pos));
      if(data.size() == history + 2)
	data.pop_front();
      damaged = true;

      pthread_mutex_unlock(&mutex);

      // wrap pos when possible
      if(!(++pos % divisions))
	pos = 0;
    }

    // close the stream
    fclose(in);
  }

  return NULL;
}

/*
 * OpenGL functions
 */

// OpenGL state initializer
void
init()
{
  // Smoothing
  if(smooth)
  {
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
  }
  else
    glDisable(GL_LINE_SMOOTH);

  // Blending should be enabled by default
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // Clear color
  glClearColor(0.0, 0.0, 0.0, 0.0);
}

#if 0
// Write an OpenGL string using glut.
void
drawString(const float scale, const float x, const float y, const char* string)
{
  glPushMatrix();
  glTranslatef(x, y, 0);
  glScalef(scale, scale, 0);
  for(const char* p = string; *p; ++p)
    glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
  glPopMatrix();
}
#endif

void
drawGrid()
{
  glBegin(GL_LINES);

  // horizontal scanlines
  for(size_t it = 1; it != divisions; ++it)
  {
    glVertex2f(it, loLimit);
    glVertex2f(it, hiLimit);
  }

  // vertical rasterlines
  for(float it = loLimit; it <= hiLimit; it += gridres)
  {
    glVertex2f(0, it);
    glVertex2f(divisions, it);
  }

  glEnd();
}

void
drawMarker(const float x)
{
  glBegin(GL_LINES);
  glVertex2f(x, loLimit);
  glVertex2f(x, hiLimit);
  glEnd();
}

// redraw handler
void
display()
{
  glLoadIdentity();
  gluOrtho2D(0, divisions, loLimit, hiLimit);

  // Clear the device.
  pthread_mutex_lock(&mutex);
  glClear(GL_COLOR_BUFFER_BIT);

  if(grid)
  {
    glColor3f(0.5, 0., 0.5);
    drawGrid();
  }

  deque<Value>::const_iterator it(data.begin());
  size_t pos;

  glBegin(GL_LINE_STRIP);
  for(size_t i = 0; i != data.size(); ++i, ++it)
  {
    glColor4f(1., 1., 1., static_cast<float>(i) / data.size());
    pos = ((scroll? i: it->count) % divisions);
    if(!pos)
    {
      // Cursor at the end
      glVertex2f(divisions, it->value);
      glEnd();
      glBegin(GL_LINE_STRIP);
      glVertex2f(0, it->value);
    }
    else
      glVertex2f(pos, it->value);
  }
  glEnd();

  if(marker)
  {
    glColor3f(0.5, 0.5, 0.);
    drawMarker(pos);
  }

  // Flush buffers
  glutSwapBuffers();
  pthread_mutex_unlock(&mutex);
}

// Resize handler
void
reshape(const int w, const int h)
{
  glViewport(0, 0, w, h);
  glutPostRedisplay();
}

void
setLimits()
{
  deque<Value>::const_iterator it(data.begin());
  float lo(it->value);
  float hi(lo);

  for(; it != data.end(); ++it)
  {
    if(it->value > hi)
      hi = it->value;

    if(it->value < lo)
      lo = it->value;
  }

  hiLimit = hi + gridres;
  loLimit = lo - gridres;
}

void
idle(int)
{
  // re-register the callback
  glutTimerFunc(1, idle, 0);

  // check if a redraw is necessary
  pthread_mutex_lock(&mutex);
  if(damaged)
  {
    if(autoLimit)
      setLimits();

    glutPostRedisplay();
    damaged = false;
  }
  pthread_mutex_unlock(&mutex);
}

/*
 * Keyboard interation
 */

void
showToggleStatus(const char* str, bool& var)
{
  var = !var;
  std::cout << str << ": " << (var? "enabled": "disabled") << std::endl;
}

double
getUnit()
{
  cout << "u? ";
  double u;
  cin >> u;

  return u;
}

void
keyboard(const unsigned char key, const int x, const int y)
{
  switch(key)
  {
  case Trend::quitKey:
    exit(Trend::success);
    break;

  // Redraw alteration
  case Trend::smoothKey:
    showToggleStatus("smoothing", smooth);
    init();
    break;

  case Trend::scrollKey:
    showToggleStatus("scrolling", scroll);
    break;

  case Trend::markerKey:
    showToggleStatus("marker", marker);
    break;

  case Trend::gridKey:
    showToggleStatus("grid", grid);
    break;

  case Trend::valuesKey:
    showToggleStatus("values", values);
    break;

  case Trend::setResKey:
    gridres = getUnit();
    break;

  default:
    return;
  }

  glutPostRedisplay();
}

/*
 * CLI and options
 */

// Initialize globals through command line
int
parseOptions(int argc, char* const argv[])
{
  // starting options
  autoLimit = false;

  int arg;
  while((arg = getopt(argc, argv, "aSsvmgG:ht:")) != -1)
    switch(arg)
    {
    case 'a':
      autoLimit = true;
      break;

    case 'S':
      smooth = true;
      break;

    case 's':
      scroll = true;
      break;

    case 'v':
      values = true;
      break;

    case 'm':
      marker = true;
      break;

    case 'g':
      grid = true;
      break;

    case 'G':
      gridres = strtod(optarg, NULL);
      break;

    case 't':
      title = optarg;
      break;

    case 'h':
      cout << argv[0] << " usage: " <<
	argv[0] << " [options] fifo hist-sz x-div [-y +y]\n" <<
	argv[0] << " version: $Revision$ $Date$\n";
      return 1;

    default:
      return -1;
    }

  // main parameters
  argc -= optind;
  if(argc != 3 && argc != 5)
  {
    cerr << argv[0] << ": bad parameters\n";
    return -1;
  }

  fileName = argv[1];
  history = strtoul(argv[2], NULL, 0);
  divisions = strtoul(argv[3], NULL, 0);

  // optional limiting factors
  if(argc == 5)
  {
    loLimit = strtod(argv[4], NULL);
    hiLimit = strtod(argv[5], NULL);
  }
  else
    autoLimit = true;

  return 0;
}

int
main(int argc, char* const argv[]) try
{
  // parameters
  if(parseOptions(argc, argv))
    return Trend::args;

  // start the producer thread
  pthread_t thrd;
  pthread_mutex_init(&mutex, NULL);
  pthread_create(&thrd, NULL, thread, NULL);

  // display
  glutInit(const_cast<int*>(&argc), const_cast<char**>(argv));
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

  // main mindow and callbacks
  glutCreateWindow(title? title: argv[0]);
  glutReshapeFunc(reshape);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  // first redraw
  init();
  idle(0);

  // processing
  glutMainLoop();
  return Trend::success;
}
catch(const std::exception& e)
{
  std::cerr << argv[0] << ": " << e.what() << std::endl;
  throw;
}
<commit_msg>Colours are configurable. Fixed producer for errors in data stream. Grid is correctly positioned now. Fixed argument parsing.<commit_after>/*
 * trend: display live data on a trend graph
 * Copyright(c) 2003-2004 by wave++ "Yuri D'Elia" <wavexx@users.sf.net>
 * Distributed under GNU LGPL WITHOUT ANY WARRANTY.
 */

/*
 * Headers
 */

// defaults
#include "defaults.hh"
#include "color.hh"

// system headers
#include <stdexcept>
#include <deque>
using std::deque;

#include <iostream>
using std::cout;
using std::cerr;
using std::cin;

#include <string>
using std::string;

#include <utility>
using std::pair;

#include <cmath>
using std::isnan;

// c system headers
#include <cstdlib>
using std::strtod;
using std::strtoul;

#include <cstring>
using std::memcpy;

#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <pthread.h>

// OpenGL/GLU
#include <GL/glut.h>

/*
 * Data structures
 */

struct Value
{
  Value(double value, size_t count)
  : value(value), count(count)
  {}

  double value;
  size_t count;
};

/*
 * Graph/Program state
 */

namespace
{
  // Basic data
  const char* fileName;
  pthread_mutex_t mutex;
  bool damaged = false;

  // Data and fixed parameters
  deque<Value> data;
  double loLimit;
  double hiLimit;
  size_t history;
  size_t divisions;

  // Visual/Fixed settings
  int width;
  int height;
  const char* title = NULL;
  GLfloat backCol[3];
  GLfloat textCol[3];
  GLfloat gridCol[3];
  GLfloat lineCol[3];
  GLfloat markCol[3];

  // Visual/Changeable settings
  bool autoLimit;
  bool smooth = Trend::smooth;
  bool scroll = Trend::scroll;
  bool values = Trend::values;
  bool marker = Trend::marker;
  bool grid = Trend::grid;
  double gridres = Trend::gridres;
}

/*
 * I/O and data manipulation
 */

// skip whitespace
void
skipSpc(FILE* fd)
{
  char c;

  do { c = getc_unlocked(fd); }
  while(isspace(c) && c != EOF);
  ungetc(c, fd);
}

// skip a space-separated string
void
skipStr(FILE* fd)
{
  char c;

  do { c = getc_unlocked(fd); }
  while(!isspace(c) && c != EOF);
  ungetc(c, fd);
}

// read a space-separated string
char*
readStr(FILE* fd, char* buf, size_t len)
{
  char* p(buf);
  int c;

  while(len--)
  {
    c = getc_unlocked(fd);
    if(c == EOF || isspace(c))
    {
      ungetc(c, fd);
      return p;
    }
    *p++ = c;
  }

  // overflow
  return NULL;
}

// read a number from the stream
double
readNum(FILE* fd)
{
  // discard initial whitespace
  skipSpc(fd);
  if(feof(fd))
    return NAN;

  // read the number
  char buf[Trend::maxNumLen];
  char* end = readStr(fd, buf, sizeof(buf));
  if(feof(fd))
    return NAN;
  if(!end)
  {
    // long string, skip it.
    skipStr(fd);
    return NAN;
  }

  // convert the number
  double num = strtod(buf, &end);
  if(end == buf)
    return NAN;

  return num;
}

// producer thread
void*
thread(void*)
{
  // iostreams under gcc 3.x are completely unusable for advanced tasks such as
  // customizable buffering/locking/etc. They also removed the (really
  // standard) ->fd() access for "encapsulation"...
  FILE* in;

  for(size_t pos = 0; fileName;)
  {
    // open the file and disable buffering
    in = fopen(fileName, "r");
    if(!in) break;
    setvbuf(in, NULL, _IONBF, 0);

    // read all data
    double num;

    while(fileName)
    {
      num = readNum(in);
      if(isnan(num) && feof(in))
	break;

      // append the value
      pthread_mutex_lock(&mutex);

      data.push_back(Value(num, pos));
      if(data.size() == history + 2)
	data.pop_front();
      damaged = true;

      pthread_mutex_unlock(&mutex);

      // wrap pos when possible
      if(!(++pos % divisions))
	pos = 0;
    }

    // close the stream
    fclose(in);
  }

  return NULL;
}

/*
 * OpenGL functions
 */

// OpenGL state initializer
void
init()
{
  // Smoothing
  if(smooth)
  {
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
  }
  else
    glDisable(GL_LINE_SMOOTH);

  // Blending should be enabled by default
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // Clear color
  glClearColor(backCol[0], backCol[1], backCol[2], 0.0);
}

// Resize handler
void
reshape(const int w, const int h)
{
  width = w;
  height = w;

  glViewport(0, 0, w, h);
}

#if 0
// Write an OpenGL string using glut.
void
drawString(const float scale, const float x, const float y, const char* string)
{
  glPushMatrix();
  glTranslatef(x, y, 0);
  glScalef(scale, scale, 0);
  for(const char* p = string; *p; ++p)
    glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
  glPopMatrix();
}
#endif

void
drawGrid()
{
  glColor3fv(gridCol);
  glBegin(GL_LINES);
  double it;

  // horizontal scanlines
  for(it = 1; it != divisions; ++it)
  {
    glVertex2d(it, loLimit);
    glVertex2d(it, hiLimit);
  }

  // vertical rasterlines
  it = loLimit + drem(loLimit, gridres);
  for(; it <= hiLimit; it += gridres)
  {
    glVertex2d(0, it);
    glVertex2d(divisions, it);
  }

  glEnd();
}

void
drawMarker(const float x)
{
  glColor3fv(markCol);
  glBegin(GL_LINES);
  glVertex2d(x, loLimit);
  glVertex2d(x, hiLimit);
  glEnd();
}

size_t
drawLine()
{
  deque<Value>::const_iterator it(data.begin());
  size_t pos;

  glBegin(GL_LINE_STRIP);
  for(size_t i = 0; i != data.size(); ++i, ++it)
  {
    // shade the color
    glColor4f(lineCol[0], lineCol[1], lineCol[2],
	static_cast<float>(i) / data.size());

    pos = ((scroll? i: it->count) % divisions);
    if(!pos)
    {
      // Cursor at the end
      glVertex2f(divisions, it->value);
      glEnd();
      glBegin(GL_LINE_STRIP);
      glVertex2d(0, it->value);
    }
    else
      glVertex2d(pos, it->value);
  }
  glEnd();

  return pos;
}

// redraw handler
void
display()
{
  // setup model coordinates
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();
  gluOrtho2D(0, divisions, loLimit, hiLimit);

  // background grid
  if(grid)
    drawGrid();

  // data
  pthread_mutex_lock(&mutex);
  size_t pos(drawLine());
  pthread_mutex_unlock(&mutex);

  // marker
  if(marker)
    drawMarker(pos);

  // flush buffers
  glutSwapBuffers();
}

void
setLimits()
{
  deque<Value>::const_iterator it(data.begin());
  float lo(it->value);
  float hi(lo);

  for(; it != data.end(); ++it)
  {
    if(it->value > hi)
      hi = it->value;

    if(it->value < lo)
      lo = it->value;
  }

  // some vertical bounds
  hiLimit = hi + gridres;
  loLimit = lo - gridres;
}

void
idle(int)
{
  // re-register the callback
  glutTimerFunc(1, idle, 0);

  // check if a redraw is really necessary
  pthread_mutex_lock(&mutex);
  if(damaged)
  {
    // recalculate limits seldom
    if(autoLimit)
      setLimits();

    glutPostRedisplay();
    damaged = false;
  }
  pthread_mutex_unlock(&mutex);
}

/*
 * Keyboard interation
 */

void
toggleStatus(const char* str, bool& var)
{
  var = !var;
  std::cout << str << ": " << (var? "enabled": "disabled") << std::endl;
}

double
getUnit(const char* str)
{
  cout << str << "? ";
  double u;
  cin >> u;

  return u;
}

void
keyboard(const unsigned char key, const int x, const int y)
{
  switch(key)
  {
  case Trend::quitKey:
    exit(Trend::success);
    break;

  // redraw alteration
  case Trend::autolimKey:
    toggleStatus("autolimit", autoLimit);
    break;

  case Trend::smoothKey:
    toggleStatus("smoothing", smooth);
    init();
    break;

  case Trend::scrollKey:
    toggleStatus("scrolling", scroll);
    break;

  case Trend::valuesKey:
    toggleStatus("values", values);
    break;

  case Trend::markerKey:
    toggleStatus("marker", marker);
    break;

  case Trend::gridKey:
    toggleStatus("grid", grid);
    break;

  case Trend::setResKey:
    gridres = getUnit("grid resolution");
    break;

  default:
    return;
  }

  glutPostRedisplay();
}

/*
 * CLI and options
 */

// Initialize globals through command line
int
parseOptions(int argc, char* const argv[])
{
  // starting options
  autoLimit = false;
  memcpy(backCol, Trend::backCol, sizeof(backCol));
  memcpy(textCol, Trend::textCol, sizeof(textCol));
  memcpy(gridCol, Trend::gridCol, sizeof(gridCol));
  memcpy(lineCol, Trend::lineCol, sizeof(lineCol));
  memcpy(markCol, Trend::markCol, sizeof(markCol));

  int arg;
  while((arg = getopt(argc, argv, "aSsvmgG:ht:A:E:R:I:M:")) != -1)
    switch(arg)
    {
    case 'a':
      autoLimit = true;
      break;

    case 'S':
      smooth = true;
      break;

    case 's':
      scroll = true;
      break;

    case 'v':
      values = true;
      break;

    case 'm':
      marker = true;
      break;

    case 'g':
      grid = true;
      break;

    case 'G':
      gridres = strtod(optarg, NULL);
      break;

    case 't':
      title = optarg;
      break;

    case 'A':
      parseColor(backCol, optarg);
      break;

    case 'E':
      parseColor(textCol, optarg);
      break;

    case 'R':
      parseColor(gridCol, optarg);
      break;

    case 'I':
      parseColor(lineCol, optarg);
      break;

    case 'M':
      parseColor(markCol, optarg);
      break;

    case 'h':
      cout << argv[0] << " usage: " <<
	argv[0] << " [options] fifo hist-sz x-div [-y +y]\n" <<
	argv[0] << " version: $Revision$ $Date$\n";
      return 1;

    default:
      return -1;
    }

  // main parameters
  argc -= optind;
  if(argc != 3 && argc != 5)
  {
    cerr << argv[0] << ": bad parameters\n";
    return -1;
  }

  fileName = argv[optind++];
  history = strtoul(argv[optind++], NULL, 0);
  divisions = strtoul(argv[optind++], NULL, 0);

  // optional limiting factors
  if(argc == 5)
  {
    loLimit = strtod(argv[optind++], NULL);
    hiLimit = strtod(argv[optind++], NULL);
  }
  else
    autoLimit = true;

  return 0;
}

int
main(int argc, char* const argv[]) try
{
  // parameters
  if(parseOptions(argc, argv))
    return Trend::args;

  // start the producer thread
  pthread_t thrd;
  pthread_mutex_init(&mutex, NULL);
  pthread_create(&thrd, NULL, thread, NULL);

  // display
  glutInit(const_cast<int*>(&argc), const_cast<char**>(argv));
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

  // main mindow and callbacks
  glutCreateWindow(title? title: argv[0]);
  glutReshapeFunc(reshape);
  glutDisplayFunc(display);
  glutKeyboardFunc(keyboard);

  // first redraw
  init();
  idle(0);

  // processing
  glutMainLoop();
  return Trend::success;
}
catch(const std::exception& e)
{
  std::cerr << argv[0] << ": " << e.what() << std::endl;
  throw;
}
<|endoftext|>


<commit_before>#include "nuclear_burn.hpp"

extern "C" {
  void burn_step_(int* indexeos,
		  double* density,
		  double* energy,
		  double* tburn,
		  double* xn,
		  double* atomw,
		  double* atomn,
		  double* dedtmp,
		  int* matters,
		  double* dt,
		  double* qrec,
		  int* nse,
		  double* tmp_nse,
		  int* key_done,
		  char* screen_type);
}

namespace {

  pair<double,vector<double> > burn_step_wrapper(double density,
						 double energy,
						 double tburn,
						 vector<double> xn,
						 pair<double,double> az,
						 double dt)
  {
    int indexeos = 0;
    double dedtmp = 0;
    int matters = static_cast<int>(xn.size());
    double qrec = 0;
    int nse = 0;
    double tmp_nse = 1e10;
    char screen_type[80] = "default";
    int key_done = 0;
    burn_step_(&indexeos,
	       &density,
	       &energy,
	       &tburn,
	       &xn[0],
	       &az.first,
	       &az.second,
	       &dedtmp,
	       &matters,
	       &dt,
	       &qrec,
	       &nse,
	       &tmp_nse,
	       &key_done,
	       screen_type);
    assert(key_done==1);
    return pair<double,vector<double> >(qrec,xn);
  }

  template<class S, class T> const T& safe_retrieve(const map<S,T>& m,
						    const S& s)
  {
    /*
    map<S,T>::const_iterator it = m.find(s);
    assert(it!=m.end());
    return it->second;
    */
    assert(m.find(s)!=m.end());
    return m.find(s)->second;
  }

  pair<double,double> calc_average_atomic_properties
  (const map<string,pair<double,double> >& atomic_properties,
   const map<string,double>& compositions)
  {
    double total = 0;
    double aa = 0;
    double zz = 0;
    for(map<string,pair<double,double> >::const_iterator it=
	  atomic_properties.begin();
	it!=atomic_properties.end();
	++it){
      const double mass_frac = safe_retrieve(compositions,it->first);
      const double A = it->second.first;
      const double Z = it->second.second;
      total += mass_frac;
      aa += mass_frac/A;
      zz += mass_frac*Z/A;
    }
    return pair<double,double>(total/aa,zz/aa);
  }
}

NuclearBurn::NuclearBurn
(const map<string,pair<double,double> >& atomic_properties,
 const string& ignore_label,
 const FermiTable& eos):
  atomic_properties_(atomic_properties),
  t_prev_(0),
  ignore_label_(ignore_label),
  eos_(eos) {}

void NuclearBurn::operator()(hdsim& sim)
{
  const double dt = sim.getTime() - t_prev_;
  vector<ComputationalCell>& cells = sim.getAllCells();
  for(size_t i=0;i<cells.size();++i){
    ComputationalCell& cell = cells[i];
    if(safe_retrieve(cell.stickers,ignore_label_))
      continue;
  }
  sim.recalculateExtensives();
}
<commit_msg>fix compiler errors<commit_after>#include "nuclear_burn.hpp"

extern "C" {
  void burn_step_(int* indexeos,
		  double* density,
		  double* energy,
		  double* tburn,
		  double* xn,
		  double* atomw,
		  double* atomn,
		  double* dedtmp,
		  int* matters,
		  double* dt,
		  double* qrec,
		  int* nse,
		  double* tmp_nse,
		  int* key_done,
		  char* screen_type);
}

namespace {

  pair<double,vector<double> > burn_step_wrapper(double density,
						 double energy,
						 double tburn,
						 vector<double> xn,
						 pair<double,double> az,
						 double dt)
  {
    int indexeos = 0;
    double dedtmp = 0;
    int matters = static_cast<int>(xn.size());
    double qrec = 0;
    int nse = 0;
    double tmp_nse = 1e10;
    char screen_type[80] = "default";
    int key_done = 0;
    burn_step_(&indexeos,
	       &density,
	       &energy,
	       &tburn,
	       &xn[0],
	       &az.first,
	       &az.second,
	       &dedtmp,
	       &matters,
	       &dt,
	       &qrec,
	       &nse,
	       &tmp_nse,
	       &key_done,
	       screen_type);
    assert(key_done==1);
    return pair<double,vector<double> >(qrec,xn);
  }

  template<class S, class T> const T& safe_retrieve(const map<S,T>& m,
						    const S& s)
  {
    /*
    map<S,T>::const_iterator it = m.find(s);
    assert(it!=m.end());
    return it->second;
    */
    assert(m.find(s)!=m.end());
    return m.find(s)->second;
  }

  vector<double> serialize_tracers(const map<string,double>& tracers)
  {
    vector<double> res;
    for(map<string,double>::const_iterator it=tracers.begin();
	it!=tracers.end();
	++it)
      res.push_back(it->second);
    return res;
  }

  map<string,double> reassemble_tracers(const vector<double>& compositions,
					const map<string,double>& old)
  {
    map<string,double> res;
    for(pair<size_t,map<string,double>::const_iterator> index(0,old.begin());
	index.second!=old.end();
	++index.first,++index.second)
      res[index.second->first] = compositions[index.first];
    return res;
  }
}

NuclearBurn::NuclearBurn
(const map<string,pair<double,double> >& atomic_properties,
 const string& ignore_label,
 const FermiTable& eos):
  atomic_properties_(atomic_properties),
  t_prev_(0),
  ignore_label_(ignore_label),
  eos_(eos) {}

void NuclearBurn::operator()(hdsim& sim)
{
  const double dt = sim.getTime() - t_prev_;
  vector<ComputationalCell>& cells = sim.getAllCells();
  for(size_t i=0;i<cells.size();++i){
    ComputationalCell& cell = cells[i];
    if(safe_retrieve(cell.stickers,ignore_label_))
      continue;
    //    const double temperature = eos_.
  }
  sim.recalculateExtensives();
}
<|endoftext|>


<commit_before>/* -*- mode:c++; tab-width:4; c-basic-offset:4; -*- */
/**
 * \file cryptoki_config.cpp
 * \brief Configuration for the certman library
 */

#include "cryptoki_config.h"
#include <maemosec_common.h>
#include "c_xmldoc.h"

#include <string>
#include <vector>

typedef struct int_slot_info {
	CK_SLOT_ID nr;
	string label;
	string domain;
	bool is_shared;
	bool is_writable;
}* I_SLOT_INFO;

static vector<I_SLOT_INFO> slots;

extern "C" {

	const char config_file_name[] = "/etc/maemosec-certman-cryptoki.conf";

	static void
	strbcpy(CK_UTF8CHAR* to, const char* from, const unsigned blen)
	{
		unsigned slen = strlen(from);
		if (slen < blen) {
			memcpy((char*)to, from, slen);
			memset((char*)to + slen, ' ', blen - slen);
		} else {
			memcpy((char*)to, from, blen);
		}
		// This is not necessary
		// *(to + blen - 1) = '\0';
	}

	CK_RV
	read_config(CK_ULONG* nrof_slots,
				CK_SLOT_ID_PTR slot_list,
				CK_ULONG max_slots)
	{
		c_xmldoc cfile;
		c_xmlnode* cnode;
		string cfilename;
		string appname;
		string tagname;

		process_name(appname);
		MAEMOSEC_DEBUG(1, "Init PKCS11 for '%s'", appname.c_str());
		cfile.parse_file(config_file_name);
		cnode = cfile.root();
		if (!cnode) {
			*nrof_slots = 0;
			goto end;
		}

		for (int i = 0; i < cnode->nbrof_children(); i++) {
			tagname = string(cnode->child(i)->attribute("path", true, ""));
			if ("application" == string(cnode->child(i)->name())
				&& (appname == tagname || "*" == tagname))
			{
				MAEMOSEC_DEBUG(1, "config '%s' applied to '%s'",
							   tagname.c_str(), appname.c_str());
				cnode = cnode->child(i);
				for (int j = 0; j < cnode->nbrof_children(); j++) {
					if ("slot" == string(cnode->child(j)->name())) {
						c_xmlnode* lnode = cnode->child(j);
						I_SLOT_INFO islot = new(struct int_slot_info);
						islot->nr = atoi(lnode->attribute("nbr", true, ""));
						islot->label = lnode->attribute("label", false, "");
						islot->domain = lnode->attribute("domain", false, "");
						islot->is_shared =
							("shared" == string(lnode->attribute("type",true,"")));
						islot->is_writable =
							("y" == string(lnode->attribute("writable",true,"")));
						slots.push_back(islot);

						if (slots.size() == max_slots) {
							MAEMOSEC_DEBUG(1, "All slots filled");
							goto done;
						}
					}
				}
			}
		}

	done:
		MAEMOSEC_DEBUG(1, "found %d slots for this application", slots.size());
		*nrof_slots = slots.size();
		for (int i = 0; i < slots.size(); i++) {
			slot_list[i] = slots[i]->nr;
			MAEMOSEC_DEBUG(1, "Slot %d=%d", i, slot_list[i]);
		}

	end:
		return(CKR_OK);
	}

	void
	release_config(void)
	{
		for (int i = 0; i < slots.size(); i++) {
			slots.erase(slots.begin() + i);
			delete(slots[i]);
		}
	}

	extern CK_RV get_slot_info(CK_SLOT_ID slotID,
							   CK_SLOT_INFO_PTR pInfo)
	{
		I_SLOT_INFO sinfo = NULL;

		MAEMOSEC_DEBUG(1, "%d", slotID);
		for (int i = 0; i < slots.size(); i++) {
			if (slots[i]->nr == slotID) {
				sinfo = slots[i];
				break;
			}
		}
		if (sinfo && pInfo) {
			strbcpy(pInfo->slotDescription,
					"Maemo secure certificate store",
					sizeof(pInfo->slotDescription));
			strbcpy(pInfo->manufacturerID,
					"Nokia corporation",
					sizeof(pInfo->manufacturerID));
			pInfo->flags = CKF_TOKEN_PRESENT;
			pInfo->hardwareVersion.major = 0;
			pInfo->hardwareVersion.minor = 1;
			pInfo->firmwareVersion.major = 0;
			pInfo->firmwareVersion.minor = 1;
			return(CKR_OK);
		} else
			return(CKR_ARGUMENTS_BAD);
	}

	extern CK_RV get_token_info(CK_SLOT_ID slotID,
								CK_TOKEN_INFO_PTR pInfo)
	{
		I_SLOT_INFO sinfo = NULL;

		MAEMOSEC_DEBUG(1, "%d", slotID);
		for (int i = 0; i < slots.size(); i++) {
			if (slots[i]->nr == slotID) {
				sinfo = slots[i];
				break;
			}
		}
		if (sinfo && pInfo) {
			strbcpy(pInfo->label,
					sinfo->label.c_str(),
					sizeof(pInfo->label));
			strbcpy(pInfo->manufacturerID,
					"Nokia corporation",
					sizeof(pInfo->manufacturerID));
			strbcpy(pInfo->model,
					"certman",
					sizeof(pInfo->model));
			strbcpy(pInfo->serialNumber,
					"0000000000000000",
					sizeof(pInfo->serialNumber));
			pInfo->flags = CKF_TOKEN_INITIALIZED;
			if (!sinfo->is_writable) {
				pInfo->flags |= CKF_WRITE_PROTECTED;
				pInfo->ulMaxRwSessionCount = 0;
			} else
				pInfo->ulMaxRwSessionCount = 1;
			pInfo->ulMaxSessionCount = 1;
			pInfo->ulSessionCount = 1;
			pInfo->ulRwSessionCount = 0;
			pInfo->ulMaxPinLen = 0;
			pInfo->ulMinPinLen = 0;
			pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->hardwareVersion.major = 0;
			pInfo->hardwareVersion.minor = 1;
			pInfo->firmwareVersion.major = 0;
			pInfo->firmwareVersion.minor = 1;
			strncpy((char*)pInfo->utcTime,
					"                ",
					sizeof(pInfo->utcTime));
			return(CKR_OK);
		} else
			return(CKR_ARGUMENTS_BAD);
	}

	static CK_SESSION_HANDLE last_session = 0;
	static vector<SESSION> sessions;
	typedef vector<SESSION>::iterator siter;

	CK_SESSION_HANDLE
	open_session(CK_SLOT_ID slot_id)
	{
		SESSION new_session;
		I_SLOT_INFO slot_info = NULL;
		domain_handle domain;
		int rc;

		for (size_t i = 0; i < slots.size(); i++) {
			if (slots[i]->nr == slot_id) {
				slot_info = slots[i];
			}
		}
		if (!slot_info)
			return(CKR_SLOT_ID_INVALID);

		MAEMOSEC_DEBUG(1, "open %s domain %s",
			  slot_info->is_shared
			  ?"shared":"private",
			  slot_info->domain.c_str());

		rc = maemosec_certman_open_domain(slot_info->domain.c_str(),
									  slot_info->is_shared
									  ?MAEMOSEC_CERTMAN_DOMAIN_SHARED
									  :MAEMOSEC_CERTMAN_DOMAIN_PRIVATE,
									  &domain);
		if (rc != 0) {
			return(CKR_SLOT_ID_INVALID);
		}

		new_session = new(struct session);
		memset(new_session, '\0', sizeof(struct session));
		/*
		 * Don't start from zero as zero is an invalid session handle
		 */
		new_session->session_id = ++last_session;
		new_session->slot = slot_id;
		new_session->cmdomain = domain;
		new_session->domain_name = strdup(slot_info->domain.c_str());
		new_session->read_only = !slot_info->is_writable;
		new_session->state = sstat_base;
		sessions.push_back(new_session);
		return(new_session->session_id);
	}

	SESSION
	find_session(CK_SESSION_HANDLE sess_id)
	{
		for (size_t i = 0; i < sessions.size(); i++) {
			if (sessions[i]->session_id == sess_id)
				return(sessions[i]);
		}
		return(NULL);
	}

	typedef vector<X509*> cstore;

	static int
	cb_copy_cert(int ordnr, X509* cert, void* sh)
	{
		cstore* certs = (cstore*)sh;
		certs->push_back(cert);
		MAEMOSEC_DEBUG(1, "Read certificate");
		return(-1);
	}

	X509*
	get_cert(SESSION sess, int ord_nbr)
	{
		cstore* certs;

		if (sess->certs == NULL) {
			certs = new(cstore);
			sess->certs = certs;
			maemosec_certman_iterate_certs(sess->cmdomain,
										   cb_copy_cert,
										   sess->certs);
		} else {
			certs = (cstore*)sess->certs;
		}
		if (ord_nbr < certs->size()) {
			return((*certs)[(size_t)ord_nbr]);
		} else {
			MAEMOSEC_ERROR("invalid object nbr %d", ord_nbr);
			return(NULL);
		}
	}

	CK_RV
	add_cert(SESSION sess, X509* cert, int* ord_nbr)
	{
		int rv;
		cstore* certs;

		if (   !sess
			|| MAEMOSEC_CERTMAN_DOMAIN_NONE == sess->cmdomain)
		{
			MAEMOSEC_DEBUG(1, "sess %p, sess->cmdomain %p",
				  sess, sess->cmdomain);
			return(CKR_SESSION_HANDLE_INVALID);
		}

		if (sess->certs == NULL) {
			certs = new(cstore);
			sess->certs = certs;
		} else {
			certs = (cstore*)sess->certs;
		}

		certs->push_back(cert);
		*ord_nbr = certs->size() - 1;
		rv = maemosec_certman_add_cert(sess->cmdomain, cert);
		if (0 != rv) {
			MAEMOSEC_ERROR("maemosec_certman_add_cert ret %d", rv);
			return(CKR_FUNCTION_FAILED);
		}
		return(CKR_OK);
	}

	CK_RV
	close_session(CK_SESSION_HANDLE sess_id)
	{
		for (size_t i = 0; i < sessions.size(); i++) {
			if (sessions[i]->session_id == sess_id) {
				SESSION sess = sessions[i];
				sessions.erase(sessions.begin() + i);
				if (sess->certs) {
					cstore* certs = (cstore*)sess->certs;
					for (size_t j = 0; j < certs->size(); j++) {
						X509_free((*certs)[j]);
					}
					delete(certs);
				}
				if (sess->cmdomain != MAEMOSEC_CERTMAN_DOMAIN_NONE)
					maemosec_certman_close_domain(sess->cmdomain);
				if (sess->domain_name)
					free((void*)sess->domain_name);
				delete(sess);
				MAEMOSEC_DEBUG(1, "exit, closed session %d", sess_id);
				return(CKR_OK);
			}
		}
		MAEMOSEC_DEBUG(1, "exit, session_not_found");
		return(CKR_SESSION_HANDLE_INVALID);
	}

	CK_RV
	close_all_sessions(CK_SLOT_ID slot_id)
	{
		for (size_t i = 0; i < sessions.size(); i++) {
			if (sessions[i]->slot == slot_id) {
				close_session(sessions[i]->session_id);
			}
		}
		MAEMOSEC_DEBUG(1, "closed all sessions for slot %d", slot_id);
		return(CKR_OK);
	}
} /* extern C */
<commit_msg>Added include<cstring> to cryptoki_config.c as required by gcc 4.3.x<commit_after>/* -*- mode:c++; tab-width:4; c-basic-offset:4; -*- */
/**
 * \file cryptoki_config.cpp
 * \brief Configuration for the certman library
 */

#include "cryptoki_config.h"
#include <maemosec_common.h>
#include "c_xmldoc.h"

#include <cstring>
#include <string>
#include <vector>

typedef struct int_slot_info {
	CK_SLOT_ID nr;
	string label;
	string domain;
	bool is_shared;
	bool is_writable;
}* I_SLOT_INFO;

static vector<I_SLOT_INFO> slots;

extern "C" {

	const char config_file_name[] = "/etc/maemosec-certman-cryptoki.conf";

	static void
	strbcpy(CK_UTF8CHAR* to, const char* from, const unsigned blen)
	{
		unsigned slen = strlen(from);
		if (slen < blen) {
			memcpy((char*)to, from, slen);
			memset((char*)to + slen, ' ', blen - slen);
		} else {
			memcpy((char*)to, from, blen);
		}
		// This is not necessary
		// *(to + blen - 1) = '\0';
	}

	CK_RV
	read_config(CK_ULONG* nrof_slots,
				CK_SLOT_ID_PTR slot_list,
				CK_ULONG max_slots)
	{
		c_xmldoc cfile;
		c_xmlnode* cnode;
		string cfilename;
		string appname;
		string tagname;

		process_name(appname);
		MAEMOSEC_DEBUG(1, "Init PKCS11 for '%s'", appname.c_str());
		cfile.parse_file(config_file_name);
		cnode = cfile.root();
		if (!cnode) {
			*nrof_slots = 0;
			goto end;
		}

		for (int i = 0; i < cnode->nbrof_children(); i++) {
			tagname = string(cnode->child(i)->attribute("path", true, ""));
			if ("application" == string(cnode->child(i)->name())
				&& (appname == tagname || "*" == tagname))
			{
				MAEMOSEC_DEBUG(1, "config '%s' applied to '%s'",
							   tagname.c_str(), appname.c_str());
				cnode = cnode->child(i);
				for (int j = 0; j < cnode->nbrof_children(); j++) {
					if ("slot" == string(cnode->child(j)->name())) {
						c_xmlnode* lnode = cnode->child(j);
						I_SLOT_INFO islot = new(struct int_slot_info);
						islot->nr = atoi(lnode->attribute("nbr", true, ""));
						islot->label = lnode->attribute("label", false, "");
						islot->domain = lnode->attribute("domain", false, "");
						islot->is_shared =
							("shared" == string(lnode->attribute("type",true,"")));
						islot->is_writable =
							("y" == string(lnode->attribute("writable",true,"")));
						slots.push_back(islot);

						if (slots.size() == max_slots) {
							MAEMOSEC_DEBUG(1, "All slots filled");
							goto done;
						}
					}
				}
			}
		}

	done:
		MAEMOSEC_DEBUG(1, "found %d slots for this application", slots.size());
		*nrof_slots = slots.size();
		for (int i = 0; i < slots.size(); i++) {
			slot_list[i] = slots[i]->nr;
			MAEMOSEC_DEBUG(1, "Slot %d=%d", i, slot_list[i]);
		}

	end:
		return(CKR_OK);
	}

	void
	release_config(void)
	{
		for (int i = 0; i < slots.size(); i++) {
			slots.erase(slots.begin() + i);
			delete(slots[i]);
		}
	}

	extern CK_RV get_slot_info(CK_SLOT_ID slotID,
							   CK_SLOT_INFO_PTR pInfo)
	{
		I_SLOT_INFO sinfo = NULL;

		MAEMOSEC_DEBUG(1, "%d", slotID);
		for (int i = 0; i < slots.size(); i++) {
			if (slots[i]->nr == slotID) {
				sinfo = slots[i];
				break;
			}
		}
		if (sinfo && pInfo) {
			strbcpy(pInfo->slotDescription,
					"Maemo secure certificate store",
					sizeof(pInfo->slotDescription));
			strbcpy(pInfo->manufacturerID,
					"Nokia corporation",
					sizeof(pInfo->manufacturerID));
			pInfo->flags = CKF_TOKEN_PRESENT;
			pInfo->hardwareVersion.major = 0;
			pInfo->hardwareVersion.minor = 1;
			pInfo->firmwareVersion.major = 0;
			pInfo->firmwareVersion.minor = 1;
			return(CKR_OK);
		} else
			return(CKR_ARGUMENTS_BAD);
	}

	extern CK_RV get_token_info(CK_SLOT_ID slotID,
								CK_TOKEN_INFO_PTR pInfo)
	{
		I_SLOT_INFO sinfo = NULL;

		MAEMOSEC_DEBUG(1, "%d", slotID);
		for (int i = 0; i < slots.size(); i++) {
			if (slots[i]->nr == slotID) {
				sinfo = slots[i];
				break;
			}
		}
		if (sinfo && pInfo) {
			strbcpy(pInfo->label,
					sinfo->label.c_str(),
					sizeof(pInfo->label));
			strbcpy(pInfo->manufacturerID,
					"Nokia corporation",
					sizeof(pInfo->manufacturerID));
			strbcpy(pInfo->model,
					"certman",
					sizeof(pInfo->model));
			strbcpy(pInfo->serialNumber,
					"0000000000000000",
					sizeof(pInfo->serialNumber));
			pInfo->flags = CKF_TOKEN_INITIALIZED;
			if (!sinfo->is_writable) {
				pInfo->flags |= CKF_WRITE_PROTECTED;
				pInfo->ulMaxRwSessionCount = 0;
			} else
				pInfo->ulMaxRwSessionCount = 1;
			pInfo->ulMaxSessionCount = 1;
			pInfo->ulSessionCount = 1;
			pInfo->ulRwSessionCount = 0;
			pInfo->ulMaxPinLen = 0;
			pInfo->ulMinPinLen = 0;
			pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
			pInfo->hardwareVersion.major = 0;
			pInfo->hardwareVersion.minor = 1;
			pInfo->firmwareVersion.major = 0;
			pInfo->firmwareVersion.minor = 1;
			strncpy((char*)pInfo->utcTime,
					"                ",
					sizeof(pInfo->utcTime));
			return(CKR_OK);
		} else
			return(CKR_ARGUMENTS_BAD);
	}

	static CK_SESSION_HANDLE last_session = 0;
	static vector<SESSION> sessions;
	typedef vector<SESSION>::iterator siter;

	CK_SESSION_HANDLE
	open_session(CK_SLOT_ID slot_id)
	{
		SESSION new_session;
		I_SLOT_INFO slot_info = NULL;
		domain_handle domain;
		int rc;

		for (size_t i = 0; i < slots.size(); i++) {
			if (slots[i]->nr == slot_id) {
				slot_info = slots[i];
			}
		}
		if (!slot_info)
			return(CKR_SLOT_ID_INVALID);

		MAEMOSEC_DEBUG(1, "open %s domain %s",
			  slot_info->is_shared
			  ?"shared":"private",
			  slot_info->domain.c_str());

		rc = maemosec_certman_open_domain(slot_info->domain.c_str(),
									  slot_info->is_shared
									  ?MAEMOSEC_CERTMAN_DOMAIN_SHARED
									  :MAEMOSEC_CERTMAN_DOMAIN_PRIVATE,
									  &domain);
		if (rc != 0) {
			return(CKR_SLOT_ID_INVALID);
		}

		new_session = new(struct session);
		memset(new_session, '\0', sizeof(struct session));
		/*
		 * Don't start from zero as zero is an invalid session handle
		 */
		new_session->session_id = ++last_session;
		new_session->slot = slot_id;
		new_session->cmdomain = domain;
		new_session->domain_name = strdup(slot_info->domain.c_str());
		new_session->read_only = !slot_info->is_writable;
		new_session->state = sstat_base;
		sessions.push_back(new_session);
		return(new_session->session_id);
	}

	SESSION
	find_session(CK_SESSION_HANDLE sess_id)
	{
		for (size_t i = 0; i < sessions.size(); i++) {
			if (sessions[i]->session_id == sess_id)
				return(sessions[i]);
		}
		return(NULL);
	}

	typedef vector<X509*> cstore;

	static int
	cb_copy_cert(int ordnr, X509* cert, void* sh)
	{
		cstore* certs = (cstore*)sh;
		certs->push_back(cert);
		MAEMOSEC_DEBUG(1, "Read certificate");
		return(-1);
	}

	X509*
	get_cert(SESSION sess, int ord_nbr)
	{
		cstore* certs;

		if (sess->certs == NULL) {
			certs = new(cstore);
			sess->certs = certs;
			maemosec_certman_iterate_certs(sess->cmdomain,
										   cb_copy_cert,
										   sess->certs);
		} else {
			certs = (cstore*)sess->certs;
		}
		if (ord_nbr < certs->size()) {
			return((*certs)[(size_t)ord_nbr]);
		} else {
			MAEMOSEC_ERROR("invalid object nbr %d", ord_nbr);
			return(NULL);
		}
	}

	CK_RV
	add_cert(SESSION sess, X509* cert, int* ord_nbr)
	{
		int rv;
		cstore* certs;

		if (   !sess
			|| MAEMOSEC_CERTMAN_DOMAIN_NONE == sess->cmdomain)
		{
			MAEMOSEC_DEBUG(1, "sess %p, sess->cmdomain %p",
				  sess, sess->cmdomain);
			return(CKR_SESSION_HANDLE_INVALID);
		}

		if (sess->certs == NULL) {
			certs = new(cstore);
			sess->certs = certs;
		} else {
			certs = (cstore*)sess->certs;
		}

		certs->push_back(cert);
		*ord_nbr = certs->size() - 1;
		rv = maemosec_certman_add_cert(sess->cmdomain, cert);
		if (0 != rv) {
			MAEMOSEC_ERROR("maemosec_certman_add_cert ret %d", rv);
			return(CKR_FUNCTION_FAILED);
		}
		return(CKR_OK);
	}

	CK_RV
	close_session(CK_SESSION_HANDLE sess_id)
	{
		for (size_t i = 0; i < sessions.size(); i++) {
			if (sessions[i]->session_id == sess_id) {
				SESSION sess = sessions[i];
				sessions.erase(sessions.begin() + i);
				if (sess->certs) {
					cstore* certs = (cstore*)sess->certs;
					for (size_t j = 0; j < certs->size(); j++) {
						X509_free((*certs)[j]);
					}
					delete(certs);
				}
				if (sess->cmdomain != MAEMOSEC_CERTMAN_DOMAIN_NONE)
					maemosec_certman_close_domain(sess->cmdomain);
				if (sess->domain_name)
					free((void*)sess->domain_name);
				delete(sess);
				MAEMOSEC_DEBUG(1, "exit, closed session %d", sess_id);
				return(CKR_OK);
			}
		}
		MAEMOSEC_DEBUG(1, "exit, session_not_found");
		return(CKR_SESSION_HANDLE_INVALID);
	}

	CK_RV
	close_all_sessions(CK_SLOT_ID slot_id)
	{
		for (size_t i = 0; i < sessions.size(); i++) {
			if (sessions[i]->slot == slot_id) {
				close_session(sessions[i]->session_id);
			}
		}
		MAEMOSEC_DEBUG(1, "closed all sessions for slot %d", slot_id);
		return(CKR_OK);
	}
} /* extern C */
<|endoftext|>


<commit_before>#include "imzb/reader.hpp"

#include "blosc.h"

#include <ios>
#include <cassert>
#include <algorithm>
#include <stdexcept>
#include <sstream>

imzb::ImzbReader::ImzbReader(const std::string& filename) :
    fn_(filename),
    in_(filename, std::ios::binary), block_idx_(0), peaks_(imzb::ImzbWriter::BLOCK_SIZE),
    n_peaks_(0), pos_(0), empty_(false)
{
  std::ifstream in_idx(filename + ".idx", std::ios::binary);
  if (!in_.is_open())
    throw std::runtime_error("couldn't open the file");
  if (!in_idx.is_open())
    throw std::runtime_error("couldn't open the index file");

  index_ = std::make_shared<Index>();
  index_->read(in_idx);

  in_.seekg(0, in_.end);
  index_->offsets.push_back(in_.tellg());

  in_.seekg(0, in_.beg);
}

size_t imzb::ImzbReader::decompressBlock(size_t block_idx,
    std::ifstream& in,
    std::vector<char>& inbuf,
    std::vector<ims::Peak>& outbuf) const
{
  assert(block_idx + 1 < index_->offsets.size());
  uint64_t start = index_->offsets[block_idx];
  uint64_t end = index_->offsets[block_idx + 1];
  assert(start > 0);
  assert(start < end);
  inbuf.resize(end - start);
  in.seekg(start);
  in.read(&inbuf[0], end - start);
  int result = blosc_decompress_ctx(&inbuf[0], &outbuf[0],
      outbuf.size() * sizeof(ims::Peak), 1);
  assert(result > 0);
  return result / sizeof(ims::Peak);
}

bool imzb::ImzbReader::readNextBlock()
{
  ++block_idx_;
  if (block_idx_ == index_->mzs.size()) {
    n_peaks_ = 0;
    return false;
  }

  n_peaks_ = decompressBlock(block_idx_, in_, buffer_, peaks_);
  pos_ = 0;
  return true;
}

bool imzb::ImzbReader::readNext(ims::Peak& peak)
{
  if (empty_)
    return false;

  if (pos_ >= n_peaks_) {
    if (!readNextBlock()) {
      empty_ = true;
      return false;
    }
  }

  peak = peaks_[pos_];
  ++pos_;
  return true;
}

void imzb::ImzbReader::reset()
{
  in_.seekg(0, in_.beg);
  n_peaks_ = pos_ = block_idx_ = 0;
  empty_ = false;
}

std::vector<ims::Peak> imzb::ImzbReader::slice(double min_mz, double max_mz) const
{
  assert(min_mz < max_mz);
  std::vector<char> inbuf;
  std::vector<ims::Peak> result, outbuf{imzb::ImzbWriter::BLOCK_SIZE};
  size_t start_block = index_->startBlock(min_mz);
  size_t end_block = index_->endBlock(max_mz);
  std::ifstream in{fn_, std::ios::binary};

  for (size_t i = start_block; i < end_block; ++i) {
    size_t n = decompressBlock(i, in, inbuf, outbuf);
    auto beg = outbuf.cbegin(), end = outbuf.cbegin() + n;
    if (outbuf.front().mz < min_mz)
      beg = std::lower_bound(beg, end, min_mz,
          [](const ims::Peak& p, double mz) { return p.mz < mz; });
    if (outbuf.back().mz > max_mz)
      end = std::upper_bound(beg, end, max_mz,
          [](double mz, const ims::Peak& p) { return mz < p.mz; });
    result.insert(result.end(), beg, end);
  }
  return result;
}

ims::Image<float> imzb::ImzbReader::image(double mz, double ppm) const
{
  assert(ppm > 0);

  ims::Image<float> img(height(), width());
  readImage(mz, ppm, img.rawPtr());
  return img;
}

#define unlikely(x) __builtin_expect(!!(x), 0)

static void initImage(float* image, const imzb::Mask& mask) {
  for (size_t i = 0; i < mask.height; ++i)
    for (size_t j = 0; j < mask.width; ++j) {
      auto idx = ims::pixelIndex(i, j, mask.width);
      if (!mask.hasSpectrumAt(i, j))
        image[idx] = -1.0;
      else
        image[idx] = 0.0;
    }
}

void imzb::ImzbReader::readImage(double mz, double ppm, float* image) const
{
  initImage(image, index_->header.mask);

  auto peaks = slice(mz - mz * ppm * 1e-6, mz + mz * ppm * 1e-6);
  for (auto& peak: peaks) {
    if (unlikely(!index_->header.mask.hasSpectrumAt(peak.coords.x, peak.coords.y))) {
      std::stringstream ss;
      ss << "peak at x=" << peak.coords.x
         << ", y=" << peak.coords.y << ", m/z=" << peak.mz
         << " is outside the spatial mask";
      throw std::runtime_error(ss.str());
    }

    if (unlikely(peak.intensity < 0)) {
      std::stringstream ss;
      ss << "negative intensity peak at x=" << peak.coords.x
         << ", y=" << peak.coords.y << ", m/z=" << peak.mz;
      throw std::runtime_error(ss.str());
    }

    auto idx = ims::pixelIndex(peak.coords.x, peak.coords.y, width());
    image[idx] += peak.intensity;
  }
}

void imzb::ImzbReader::readCentroidedImage(double mz, double ppm, float* image) const
{
  initImage(image, index_->header.mask);

  auto peaks = slice(mz - mz * ppm * 1e-6, mz + mz * ppm * 1e-6);

  auto n = height() * width();
  auto float_inf = std::numeric_limits<float>::infinity();
  std::vector<double> m_prev(n), m_curr(n), m_next(n);
  std::vector<float> i_prev(n, float_inf), i_curr(n, float_inf), i_next(n, float_inf);

  for (auto& peak: peaks) {
    auto i = ims::pixelIndex(peak.coords.x, peak.coords.y, width());

    m_prev[i] = m_curr[i], i_prev[i] = i_curr[i];
    m_curr[i] = m_next[i], i_curr[i] = i_next[i];
    m_next[i] = peak.mz, i_next[i] = peak.intensity;

    if (i_prev[i] < i_curr[i] && i_curr[i] >= i_next[i]) {
      image[i] += i_curr[i];
    }
  }
}
<commit_msg>removed old assert<commit_after>#include "imzb/reader.hpp"

#include "blosc.h"

#include <ios>
#include <cassert>
#include <algorithm>
#include <stdexcept>
#include <sstream>

imzb::ImzbReader::ImzbReader(const std::string& filename) :
    fn_(filename),
    in_(filename, std::ios::binary), block_idx_(0), peaks_(imzb::ImzbWriter::BLOCK_SIZE),
    n_peaks_(0), pos_(0), empty_(false)
{
  std::ifstream in_idx(filename + ".idx", std::ios::binary);
  if (!in_.is_open())
    throw std::runtime_error("couldn't open the file");
  if (!in_idx.is_open())
    throw std::runtime_error("couldn't open the index file");

  index_ = std::make_shared<Index>();
  index_->read(in_idx);

  in_.seekg(0, in_.end);
  index_->offsets.push_back(in_.tellg());

  in_.seekg(0, in_.beg);
}

size_t imzb::ImzbReader::decompressBlock(size_t block_idx,
    std::ifstream& in,
    std::vector<char>& inbuf,
    std::vector<ims::Peak>& outbuf) const
{
  assert(block_idx + 1 < index_->offsets.size());
  uint64_t start = index_->offsets[block_idx];
  uint64_t end = index_->offsets[block_idx + 1];
  assert(start < end);
  inbuf.resize(end - start);
  in.seekg(start);
  in.read(&inbuf[0], end - start);
  int result = blosc_decompress_ctx(&inbuf[0], &outbuf[0],
      outbuf.size() * sizeof(ims::Peak), 1);
  assert(result > 0);
  return result / sizeof(ims::Peak);
}

bool imzb::ImzbReader::readNextBlock()
{
  ++block_idx_;
  if (block_idx_ == index_->mzs.size()) {
    n_peaks_ = 0;
    return false;
  }

  n_peaks_ = decompressBlock(block_idx_, in_, buffer_, peaks_);
  pos_ = 0;
  return true;
}

bool imzb::ImzbReader::readNext(ims::Peak& peak)
{
  if (empty_)
    return false;

  if (pos_ >= n_peaks_) {
    if (!readNextBlock()) {
      empty_ = true;
      return false;
    }
  }

  peak = peaks_[pos_];
  ++pos_;
  return true;
}

void imzb::ImzbReader::reset()
{
  in_.seekg(0, in_.beg);
  n_peaks_ = pos_ = block_idx_ = 0;
  empty_ = false;
}

std::vector<ims::Peak> imzb::ImzbReader::slice(double min_mz, double max_mz) const
{
  assert(min_mz < max_mz);
  std::vector<char> inbuf;
  std::vector<ims::Peak> result, outbuf{imzb::ImzbWriter::BLOCK_SIZE};
  size_t start_block = index_->startBlock(min_mz);
  size_t end_block = index_->endBlock(max_mz);
  std::ifstream in{fn_, std::ios::binary};

  for (size_t i = start_block; i < end_block; ++i) {
    size_t n = decompressBlock(i, in, inbuf, outbuf);
    auto beg = outbuf.cbegin(), end = outbuf.cbegin() + n;
    if (outbuf.front().mz < min_mz)
      beg = std::lower_bound(beg, end, min_mz,
          [](const ims::Peak& p, double mz) { return p.mz < mz; });
    if (outbuf.back().mz > max_mz)
      end = std::upper_bound(beg, end, max_mz,
          [](double mz, const ims::Peak& p) { return mz < p.mz; });
    result.insert(result.end(), beg, end);
  }
  return result;
}

ims::Image<float> imzb::ImzbReader::image(double mz, double ppm) const
{
  assert(ppm > 0);

  ims::Image<float> img(height(), width());
  readImage(mz, ppm, img.rawPtr());
  return img;
}

#define unlikely(x) __builtin_expect(!!(x), 0)

static void initImage(float* image, const imzb::Mask& mask) {
  for (size_t i = 0; i < mask.height; ++i)
    for (size_t j = 0; j < mask.width; ++j) {
      auto idx = ims::pixelIndex(i, j, mask.width);
      if (!mask.hasSpectrumAt(i, j))
        image[idx] = -1.0;
      else
        image[idx] = 0.0;
    }
}

void imzb::ImzbReader::readImage(double mz, double ppm, float* image) const
{
  initImage(image, index_->header.mask);

  auto peaks = slice(mz - mz * ppm * 1e-6, mz + mz * ppm * 1e-6);
  for (auto& peak: peaks) {
    if (unlikely(!index_->header.mask.hasSpectrumAt(peak.coords.x, peak.coords.y))) {
      std::stringstream ss;
      ss << "peak at x=" << peak.coords.x
         << ", y=" << peak.coords.y << ", m/z=" << peak.mz
         << " is outside the spatial mask";
      throw std::runtime_error(ss.str());
    }

    if (unlikely(peak.intensity < 0)) {
      std::stringstream ss;
      ss << "negative intensity peak at x=" << peak.coords.x
         << ", y=" << peak.coords.y << ", m/z=" << peak.mz;
      throw std::runtime_error(ss.str());
    }

    auto idx = ims::pixelIndex(peak.coords.x, peak.coords.y, width());
    image[idx] += peak.intensity;
  }
}

void imzb::ImzbReader::readCentroidedImage(double mz, double ppm, float* image) const
{
  initImage(image, index_->header.mask);

  auto peaks = slice(mz - mz * ppm * 1e-6, mz + mz * ppm * 1e-6);

  auto n = height() * width();
  auto float_inf = std::numeric_limits<float>::infinity();
  std::vector<double> m_prev(n), m_curr(n), m_next(n);
  std::vector<float> i_prev(n, float_inf), i_curr(n, float_inf), i_next(n, float_inf);

  for (auto& peak: peaks) {
    auto i = ims::pixelIndex(peak.coords.x, peak.coords.y, width());

    m_prev[i] = m_curr[i], i_prev[i] = i_curr[i];
    m_curr[i] = m_next[i], i_curr[i] = i_next[i];
    m_next[i] = peak.mz, i_next[i] = peak.intensity;

    if (i_prev[i] < i_curr[i] && i_curr[i] >= i_next[i]) {
      image[i] += i_curr[i];
    }
  }
}
<|endoftext|>


<commit_before>#ifndef MUTEXES_H
#define MUTEXES_H

/*
This header file contains "App" versions of the os/thread.hpp
objects.

The "App" versions have the following characteristics:
1.	If you -Dsingle_threaded, they are completely empty and
	will be removed by a sufficiently-smart compiler.
	We even lose the dependency on pthreads, so in theory
	we can still work in an environment without pthreads.
2.	If you decide to launch hl in single-threaded mode, these
	will not bother to do locking, or allocate and create
	lock.
*/

#ifndef single_threaded
	#include"thread.hpp"
	#include<boost/scoped_ptr.hpp>
#endif
#include<boost/noncopyable.hpp>

class AppLock;
class AppTryLock;
class AppCondVar;

class AppMutex : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<Mutex> mp;
	#endif
	AppMutex(AppMutex const&) : mp() { }
public:
	AppMutex(void) {
		#ifndef single_threaded
			if(!single_threaded) {
				mp.reset(new Mutex());
			}
		#endif
	}
	friend class AppLock;
	friend class AppTryLock;
};

class AppLock : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<Lock> lp;
	#endif
	AppLock(void); // disallowed!
public:
	AppLock(AppMutex& m) {
		#ifndef single_threaded
			if(!single_threaded) {
				lp.reset(new Lock(*m.mp));
			}
		#endif
	}
	friend class AppCondVar;
};

class AppTryLock : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<TryLock> lp;
	#endif
	AppTryLock(void); //disallowed!
public:
	AppTryLock(AppMutex& m) {
		#ifndef single_threaded
			if(!single_threaded) {
				lp.reset(new TryLock(*m.mp));
			}
		#endif
	}
	/*safe bool idiom*/
	inline void unspecified_bool(void) const { }
	typedef void (AppTryLock::*unspecified_bool_type)(void) const;
	operator unspecified_bool_type(void) const {
		#ifndef single_threaded
			if(!lp) return &AppTryLock::unspecified_bool;
			return (*lp) ? &AppTryLock::unspecified_bool : 0;
		#else
			return &AppTryLock::unspecified_bool;
		#endif
	}
	friend class AppCondVar;
};

class AppCondVar : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<CondVar> cp;
	#endif

public:
	AppCondVar(void) {
		#ifndef single_threaded
			if(!single_threaded) {
				cp.reset(new CondVar());
			}
		#endif
	}
	void wait(AppLock const& l) const {
		#ifndef single_threaded
			if(l.lp && cp) {
				cp->wait(*l.lp);
			}
		#endif
	}
	void wait(AppTryLock const& l) const  {
		#ifndef single_threaded
			if(l.lp && cp) {
				cp->wait(*l.lp);
			}
		#endif
	}

	void signal(void) {
		#ifndef single_threaded
			if(cp) {
				cp->signal();
			}
		#endif
	}
	void broadcast(void) {
		#ifndef single_threaded
			if(cp) {
				cp->broadcast();
			}
		#endif
	}
};

#endif // MUTEXES_H

<commit_msg>inc/mutexes.hpp: Corrected compilation with -Dsingle_threaded option<commit_after>#ifndef MUTEXES_H
#define MUTEXES_H

/*
This header file contains "App" versions of the os/thread.hpp
objects.

The "App" versions have the following characteristics:
1.	If you -Dsingle_threaded, they are completely empty and
	will be removed by a sufficiently-smart compiler.
	We even lose the dependency on pthreads, so in theory
	we can still work in an environment without pthreads.
2.	If you decide to launch hl in single-threaded mode, these
	will not bother to do locking, or allocate and create
	lock.
*/

#ifndef single_threaded
	#include"thread.hpp"
	#include<boost/scoped_ptr.hpp>
#endif
#include<boost/noncopyable.hpp>

class AppLock;
class AppTryLock;
class AppCondVar;

class AppMutex : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<Mutex> mp;
	#endif
	AppMutex(AppMutex const&)
	#ifndef single_threaded
		: mp()
	#endif
	{ }
public:
	AppMutex(void) {
		#ifndef single_threaded
			if(!single_threaded) {
				mp.reset(new Mutex());
			}
		#endif
	}
	friend class AppLock;
	friend class AppTryLock;
};

class AppLock : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<Lock> lp;
	#endif
	AppLock(void); // disallowed!
public:
	AppLock(AppMutex& m) {
		#ifndef single_threaded
			if(!single_threaded) {
				lp.reset(new Lock(*m.mp));
			}
		#endif
	}
	friend class AppCondVar;
};

class AppTryLock : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<TryLock> lp;
	#endif
	AppTryLock(void); //disallowed!
public:
	AppTryLock(AppMutex& m) {
		#ifndef single_threaded
			if(!single_threaded) {
				lp.reset(new TryLock(*m.mp));
			}
		#endif
	}
	/*safe bool idiom*/
	inline void unspecified_bool(void) const { }
	typedef void (AppTryLock::*unspecified_bool_type)(void) const;
	operator unspecified_bool_type(void) const {
		#ifndef single_threaded
			if(!lp) return &AppTryLock::unspecified_bool;
			return (*lp) ? &AppTryLock::unspecified_bool : 0;
		#else
			return &AppTryLock::unspecified_bool;
		#endif
	}
	friend class AppCondVar;
};

class AppCondVar : boost::noncopyable {
private:
	#ifndef single_threaded
		boost::scoped_ptr<CondVar> cp;
	#endif

public:
	AppCondVar(void) {
		#ifndef single_threaded
			if(!single_threaded) {
				cp.reset(new CondVar());
			}
		#endif
	}
	void wait(AppLock const& l) const {
		#ifndef single_threaded
			if(l.lp && cp) {
				cp->wait(*l.lp);
			}
		#endif
	}
	void wait(AppTryLock const& l) const  {
		#ifndef single_threaded
			if(l.lp && cp) {
				cp->wait(*l.lp);
			}
		#endif
	}

	void signal(void) {
		#ifndef single_threaded
			if(cp) {
				cp->signal();
			}
		#endif
	}
	void broadcast(void) {
		#ifndef single_threaded
			if(cp) {
				cp->broadcast();
			}
		#endif
	}
};

#endif // MUTEXES_H

<|endoftext|>


<commit_before><commit_msg>Remove unused variable<commit_after><|endoftext|>


<commit_before><commit_msg>Increase delay between sysexes<commit_after><|endoftext|>