<commit_before>//===-- PhiElimination.cpp - Eliminate PHI nodes by inserting copies ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates machine instruction PHI nodes by inserting copy
// instructions.  This destroys SSA information, but is the desired input for
// some register allocators.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "Support/DenseMap.h"
#include "Support/STLExtras.h"
using namespace llvm;

namespace {
  struct PNE : public MachineFunctionPass {
    bool runOnMachineFunction(MachineFunction &Fn) {
      bool Changed = false;

      // Eliminate PHI instructions by inserting copies into predecessor blocks.
      //
      for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
	Changed |= EliminatePHINodes(Fn, *I);

      //std::cerr << "AFTER PHI NODE ELIM:\n";
      //Fn.dump();
      return Changed;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<LiveVariables>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

  private:
    /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
    /// in predecessor basic blocks.
    ///
    bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB);
  };

  RegisterPass<PNE> X("phi-node-elimination",
		      "Eliminate PHI nodes for register allocation");
}

const PassInfo *llvm::PHIEliminationID = X.getPassInfo();

/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks.
///
bool PNE::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) {
  if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
    return false;   // Quick exit for normal case...

  LiveVariables *LV = getAnalysisToUpdate<LiveVariables>();
  const TargetInstrInfo &MII = MF.getTarget().getInstrInfo();
  const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();

  // VRegPHIUseCount - Keep track of the number of times each virtual register
  // is used by PHI nodes in this block.
  DenseMap<unsigned, VirtReg2IndexFunctor> VRegPHIUseCount;
  VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg());

  // Get an iterator to the first instruction after the last PHI node (this may
  // allso be the end of the basic block).  While we are scanning the PHIs,
  // populate the VRegPHIUseCount map.
  MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
  while (AfterPHIsIt != MBB.end() &&
         AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) {
    MachineInstr *PHI = AfterPHIsIt;
    for (unsigned i = 1, e = PHI->getNumOperands(); i < e; i += 2)
      VRegPHIUseCount[PHI->getOperand(i).getReg()]++;
    ++AfterPHIsIt;    // Skip over all of the PHI nodes...
  }

  while (MBB.front().getOpcode() == TargetInstrInfo::PHI) {
    // Unlink the PHI node from the basic block... but don't delete the PHI yet
    MachineInstr *MI = MBB.remove(MBB.begin());

    assert(MRegisterInfo::isVirtualRegister(MI->getOperand(0).getReg()) &&
           "PHI node doesn't write virt reg?");

    unsigned DestReg = MI->getOperand(0).getReg();

    // Create a new register for the incoming PHI arguments
    const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(DestReg);
    unsigned IncomingReg = MF.getSSARegMap()->createVirtualRegister(RC);

    // Insert a register to register copy in the top of the current block (but
    // after any remaining phi nodes) which copies the new incoming register
    // into the phi node destination.
    //
    RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC);

    // Update live variable information if there is any...
    if (LV) {
      MachineInstr *PHICopy = prior(AfterPHIsIt);

      // Add information to LiveVariables to know that the incoming value is
      // killed.  Note that because the value is defined in several places (once
      // each for each incoming block), the "def" block and instruction fields
      // for the VarInfo is not filled in.
      //
      LV->addVirtualRegisterKilled(IncomingReg, &MBB, PHICopy);

      // Since we are going to be deleting the PHI node, if it is the last use
      // of any registers, or if the value itself is dead, we need to move this
      // information over to the new copy we just inserted...
      //
      std::pair<LiveVariables::killed_iterator, LiveVariables::killed_iterator>
        RKs = LV->killed_range(MI);
      std::vector<std::pair<MachineInstr*, unsigned> > Range;
      if (RKs.first != RKs.second) {
        // Copy the range into a vector...
        Range.assign(RKs.first, RKs.second);

        // Delete the range...
        LV->removeVirtualRegistersKilled(RKs.first, RKs.second);

        // Add all of the kills back, which will update the appropriate info...
        for (unsigned i = 0, e = Range.size(); i != e; ++i)
          LV->addVirtualRegisterKilled(Range[i].second, &MBB, PHICopy);
      }

      RKs = LV->dead_range(MI);
      if (RKs.first != RKs.second) {
        // Works as above...
        Range.assign(RKs.first, RKs.second);
        LV->removeVirtualRegistersDead(RKs.first, RKs.second);
        for (unsigned i = 0, e = Range.size(); i != e; ++i)
          LV->addVirtualRegisterDead(Range[i].second, &MBB, PHICopy);
      }
    }

    // Adjust the VRegPHIUseCount map to account for the removal of this PHI
    // node.
    for (unsigned i = 1; i != MI->getNumOperands(); i += 2)
      VRegPHIUseCount[MI->getOperand(i).getReg()]--;

    // Now loop over all of the incoming arguments, changing them to copy into
    // the IncomingReg register in the corresponding predecessor basic block.
    //
    for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) {
      MachineOperand &opVal = MI->getOperand(i-1);

      // Get the MachineBasicBlock equivalent of the BasicBlock that is the
      // source path the PHI.
      MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock();

      MachineBasicBlock::iterator I = opBlock.getFirstTerminator();

      // Check to make sure we haven't already emitted the copy for this block.
      // This can happen because PHI nodes may have multiple entries for the
      // same basic block.  It doesn't matter which entry we use though, because
      // all incoming values are guaranteed to be the same for a particular bb.
      //
      // If we emitted a copy for this basic block already, it will be right
      // where we want to insert one now.  Just check for a definition of the
      // register we are interested in!
      //
      bool HaveNotEmitted = true;

      if (I != opBlock.begin()) {
        MachineBasicBlock::iterator PrevInst = prior(I);
        for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) {
          MachineOperand &MO = PrevInst->getOperand(i);
          if (MO.isRegister() && MO.getReg() == IncomingReg)
            if (MO.isDef()) {
              HaveNotEmitted = false;
              break;
            }
        }
      }

      if (HaveNotEmitted) { // If the copy has not already been emitted, do it.
        assert(MRegisterInfo::isVirtualRegister(opVal.getReg()) &&
               "Machine PHI Operands must all be virtual registers!");
        unsigned SrcReg = opVal.getReg();
        RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC);

        // Now update live variable information if we have it.
        if (LV) {
          // We want to be able to insert a kill of the register if this PHI
          // (aka, the copy we just inserted) is the last use of the source
          // value.  Live variable analysis conservatively handles this by
          // saying that the value is live until the end of the block the PHI
          // entry lives in.  If the value really is dead at the PHI copy, there
          // will be no successor blocks which have the value live-in.
          //
          // Check to see if the copy is the last use, and if so, update the
          // live variables information so that it knows the copy source
          // instruction kills the incoming value.
          //
          LiveVariables::VarInfo &InRegVI = LV->getVarInfo(SrcReg);

          // Loop over all of the successors of the basic block, checking to see
          // if the value is either live in the block, or if it is killed in the
          // block.  Also check to see if this register is in use by another PHI
          // node which has not yet been eliminated.  If so, it will be killed
          // at an appropriate point later.
          //
          bool ValueIsLive = false;
          for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(),
                 E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) {
            MachineBasicBlock *MBB = *SI;

            // Is it alive in this successor?
            unsigned SuccIdx = LV->getMachineBasicBlockIndex(MBB);
            if (SuccIdx < InRegVI.AliveBlocks.size() &&
                InRegVI.AliveBlocks[SuccIdx]) {
              ValueIsLive = true;
              break;
            }

            // Is it killed in this successor?
            for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i)
              if (InRegVI.Kills[i].first == MBB) {
                ValueIsLive = true;
                break;
              }

            // Is it used by any PHI instructions in this block?
            if (!ValueIsLive)
              ValueIsLive = VRegPHIUseCount[SrcReg] != 0;
          }

          // Okay, if we now know that the value is not live out of the block,
          // we can add a kill marker to the copy we inserted saying that it
          // kills the incoming value!
          //
          if (!ValueIsLive) {
            MachineBasicBlock::iterator Prev = prior(I);
            LV->addVirtualRegisterKilled(SrcReg, &opBlock, Prev);
          }
        }
      }
    }

    // really delete the PHI instruction now!
    delete MI;
  }
  return true;
}
<commit_msg>Fix a really nasty bug from my changes on Monday to PHIElim.  These changes broke obsequi and a lot of other things.  It all boiled down to MBB being overloaded in an inner scope and me confusing it with the one in the outer scope.  Ugh!<commit_after>//===-- PhiElimination.cpp - Eliminate PHI nodes by inserting copies ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates machine instruction PHI nodes by inserting copy
// instructions.  This destroys SSA information, but is the desired input for
// some register allocators.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "Support/DenseMap.h"
#include "Support/STLExtras.h"
using namespace llvm;

namespace {
  struct PNE : public MachineFunctionPass {
    bool runOnMachineFunction(MachineFunction &Fn) {
      bool Changed = false;

      // Eliminate PHI instructions by inserting copies into predecessor blocks.
      //
      for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
	Changed |= EliminatePHINodes(Fn, *I);

      //std::cerr << "AFTER PHI NODE ELIM:\n";
      //Fn.dump();
      return Changed;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<LiveVariables>();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

  private:
    /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions
    /// in predecessor basic blocks.
    ///
    bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB);
  };

  RegisterPass<PNE> X("phi-node-elimination",
		      "Eliminate PHI nodes for register allocation");
}

const PassInfo *llvm::PHIEliminationID = X.getPassInfo();

/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks.
///
bool PNE::EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB) {
  if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
    return false;   // Quick exit for normal case...

  LiveVariables *LV = getAnalysisToUpdate<LiveVariables>();
  const TargetInstrInfo &MII = MF.getTarget().getInstrInfo();
  const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();

  // VRegPHIUseCount - Keep track of the number of times each virtual register
  // is used by PHI nodes in successors of this block.
  DenseMap<unsigned, VirtReg2IndexFunctor> VRegPHIUseCount;
  VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg());

  unsigned BBIsSuccOfPreds = 0;  // Number of times MBB is a succ of preds
  for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin(),
         E = MBB.pred_end(); PI != E; ++PI)
    for (MachineBasicBlock::succ_iterator SI = (*PI)->succ_begin(),
           E = (*PI)->succ_end(); SI != E; ++SI) {
    BBIsSuccOfPreds += *SI == &MBB;
    for (MachineBasicBlock::iterator BBI = (*SI)->begin(); BBI !=(*SI)->end() &&
           BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI)
      for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2)
        VRegPHIUseCount[BBI->getOperand(i).getReg()]++;
  }

  // Get an iterator to the first instruction after the last PHI node (this may
  // also be the end of the basic block).  While we are scanning the PHIs,
  // populate the VRegPHIUseCount map.
  MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
  while (AfterPHIsIt != MBB.end() &&
         AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
    ++AfterPHIsIt;    // Skip over all of the PHI nodes...

  while (MBB.front().getOpcode() == TargetInstrInfo::PHI) {
    // Unlink the PHI node from the basic block... but don't delete the PHI yet
    MachineInstr *MI = MBB.remove(MBB.begin());

    assert(MRegisterInfo::isVirtualRegister(MI->getOperand(0).getReg()) &&
           "PHI node doesn't write virt reg?");

    unsigned DestReg = MI->getOperand(0).getReg();

    // Create a new register for the incoming PHI arguments
    const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(DestReg);
    unsigned IncomingReg = MF.getSSARegMap()->createVirtualRegister(RC);

    // Insert a register to register copy in the top of the current block (but
    // after any remaining phi nodes) which copies the new incoming register
    // into the phi node destination.
    //
    RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC);

    // Update live variable information if there is any...
    if (LV) {
      MachineInstr *PHICopy = prior(AfterPHIsIt);

      // Add information to LiveVariables to know that the incoming value is
      // killed.  Note that because the value is defined in several places (once
      // each for each incoming block), the "def" block and instruction fields
      // for the VarInfo is not filled in.
      //
      LV->addVirtualRegisterKilled(IncomingReg, &MBB, PHICopy);

      // Since we are going to be deleting the PHI node, if it is the last use
      // of any registers, or if the value itself is dead, we need to move this
      // information over to the new copy we just inserted...
      //
      std::pair<LiveVariables::killed_iterator, LiveVariables::killed_iterator>
        RKs = LV->killed_range(MI);
      std::vector<std::pair<MachineInstr*, unsigned> > Range;
      if (RKs.first != RKs.second) {
        // Copy the range into a vector...
        Range.assign(RKs.first, RKs.second);

        // Delete the range...
        LV->removeVirtualRegistersKilled(RKs.first, RKs.second);

        // Add all of the kills back, which will update the appropriate info...
        for (unsigned i = 0, e = Range.size(); i != e; ++i)
          LV->addVirtualRegisterKilled(Range[i].second, &MBB, PHICopy);
      }

      RKs = LV->dead_range(MI);
      if (RKs.first != RKs.second) {
        // Works as above...
        Range.assign(RKs.first, RKs.second);
        LV->removeVirtualRegistersDead(RKs.first, RKs.second);
        for (unsigned i = 0, e = Range.size(); i != e; ++i)
          LV->addVirtualRegisterDead(Range[i].second, &MBB, PHICopy);
      }
    }

    // Adjust the VRegPHIUseCount map to account for the removal of this PHI
    // node.
    for (unsigned i = 1; i != MI->getNumOperands(); i += 2)
      VRegPHIUseCount[MI->getOperand(i).getReg()] -= BBIsSuccOfPreds;

    // Now loop over all of the incoming arguments, changing them to copy into
    // the IncomingReg register in the corresponding predecessor basic block.
    //
    for (int i = MI->getNumOperands() - 1; i >= 2; i-=2) {
      MachineOperand &opVal = MI->getOperand(i-1);

      // Get the MachineBasicBlock equivalent of the BasicBlock that is the
      // source path the PHI.
      MachineBasicBlock &opBlock = *MI->getOperand(i).getMachineBasicBlock();

      MachineBasicBlock::iterator I = opBlock.getFirstTerminator();

      // Check to make sure we haven't already emitted the copy for this block.
      // This can happen because PHI nodes may have multiple entries for the
      // same basic block.  It doesn't matter which entry we use though, because
      // all incoming values are guaranteed to be the same for a particular bb.
      //
      // If we emitted a copy for this basic block already, it will be right
      // where we want to insert one now.  Just check for a definition of the
      // register we are interested in!
      //
      bool HaveNotEmitted = true;

      if (I != opBlock.begin()) {
        MachineBasicBlock::iterator PrevInst = prior(I);
        for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) {
          MachineOperand &MO = PrevInst->getOperand(i);
          if (MO.isRegister() && MO.getReg() == IncomingReg)
            if (MO.isDef()) {
              HaveNotEmitted = false;
              break;
            }
        }
      }

      if (HaveNotEmitted) { // If the copy has not already been emitted, do it.
        assert(MRegisterInfo::isVirtualRegister(opVal.getReg()) &&
               "Machine PHI Operands must all be virtual registers!");
        unsigned SrcReg = opVal.getReg();
        RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC);

        // Now update live variable information if we have it.
        if (LV) {
          // We want to be able to insert a kill of the register if this PHI
          // (aka, the copy we just inserted) is the last use of the source
          // value.  Live variable analysis conservatively handles this by
          // saying that the value is live until the end of the block the PHI
          // entry lives in.  If the value really is dead at the PHI copy, there
          // will be no successor blocks which have the value live-in.
          //
          // Check to see if the copy is the last use, and if so, update the
          // live variables information so that it knows the copy source
          // instruction kills the incoming value.
          //
          LiveVariables::VarInfo &InRegVI = LV->getVarInfo(SrcReg);

          // Loop over all of the successors of the basic block, checking to see
          // if the value is either live in the block, or if it is killed in the
          // block.  Also check to see if this register is in use by another PHI
          // node which has not yet been eliminated.  If so, it will be killed
          // at an appropriate point later.
          //
          bool ValueIsLive = false;
          for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(),
                 E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) {
            MachineBasicBlock *SuccMBB = *SI;

            // Is it alive in this successor?
            unsigned SuccIdx = LV->getMachineBasicBlockIndex(SuccMBB);
            if (SuccIdx < InRegVI.AliveBlocks.size() &&
                InRegVI.AliveBlocks[SuccIdx]) {
              ValueIsLive = true;
              break;
            }

            // Is it killed in this successor?
            for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i)
              if (InRegVI.Kills[i].first == SuccMBB) {
                ValueIsLive = true;
                break;
              }

            // Is it used by any PHI instructions in this block?
            if (!ValueIsLive)
              ValueIsLive = VRegPHIUseCount[SrcReg] != 0;
          }

          // Okay, if we now know that the value is not live out of the block,
          // we can add a kill marker to the copy we inserted saying that it
          // kills the incoming value!
          //
          if (!ValueIsLive) {
            MachineBasicBlock::iterator Prev = prior(I);
            LV->addVirtualRegisterKilled(SrcReg, &opBlock, Prev);
          }
        }
      }
    }

    // really delete the PHI instruction now!
    delete MI;
  }
  return true;
}
<|endoftext|>


<commit_before><commit_msg>natpmp fix<commit_after><|endoftext|>


<commit_before>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/render/normals.hpp
 *
 * Copyright 2014-2019 Patrik Huber
 *
 * 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.
 */
#pragma once

#ifndef EOS_RENDER_NORMALS_HPP
#define EOS_RENDER_NORMALS_HPP

#include "glm/vec3.hpp"
#include "glm/geometric.hpp"

#include "Eigen/Core"

namespace eos {
namespace render {

/**
 * Calculates the normal of a face (or triangle), i.e. the
 * per-face normal. Return normal will be normalised.
 * Assumes the triangle is given in CCW order, i.e. vertices
 * in counterclockwise order on the screen are front-facing.
 *
 * @param[in] v0 First vertex.
 * @param[in] v1 Second vertex.
 * @param[in] v2 Third vertex.
 * @return The unit-length normal of the given triangle.
 */
inline Eigen::Vector3f compute_face_normal(const Eigen::Vector3f& v0, const Eigen::Vector3f& v1,
                                           const Eigen::Vector3f& v2)
{
    Eigen::Vector3f n = (v1 - v0).cross(v2 - v0); // v0-to-v1 x v0-to-v2
    return n.normalized();
};

// Todo: Doxygen. Actually this is the overload that's probably most used?
inline Eigen::Vector3f compute_face_normal(const Eigen::Vector4f& v0, const Eigen::Vector4f& v1,
                                           const Eigen::Vector4f& v2)
{
    Eigen::Vector4f n = (v1 - v0).cross3(v2 - v0); // v0-to-v1 x v0-to-v2
    return n.head<3>().normalized();
};

/**
 * Computes the normal of a face (or triangle), i.e. the
 * per-face normal. Return normal will be normalised.
 * Assumes the triangle is given in CCW order, i.e. vertices
 * in counterclockwise order on the screen are front-facing.
 *
 * @param[in] v0 First vertex.
 * @param[in] v1 Second vertex.
 * @param[in] v2 Third vertex.
 * @return The unit-length normal of the given triangle.
 */
inline glm::vec3 compute_face_normal(const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2)
{
    glm::vec3 n = glm::cross(v1 - v0, v2 - v0); // v0-to-v1 x v0-to-v2
    n = glm::normalize(n);
    return n;
};

} /* namespace render */
} /* namespace eos */

#endif /* EOS_RENDER_NORMALS_HPP */
<commit_msg>Run clang-format on normals.hpp<commit_after>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/render/normals.hpp
 *
 * Copyright 2014-2019 Patrik Huber
 *
 * 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.
 */
#pragma once

#ifndef EOS_RENDER_NORMALS_HPP
#define EOS_RENDER_NORMALS_HPP

#include "glm/vec3.hpp"
#include "glm/geometric.hpp"

#include "Eigen/Core"

namespace eos {
namespace render {

/**
 * Calculates the normal of a face (or triangle), i.e. the per-face normal. Returned normal will be unit
 * length.
 *
 * Assumes the triangle is given in CCW order, i.e. vertices in counterclockwise order on the screen are
 * front-facing.
 *
 * @param[in] v0 First vertex.
 * @param[in] v1 Second vertex.
 * @param[in] v2 Third vertex.
 * @return The unit-length normal of the given triangle.
 */
inline Eigen::Vector3f compute_face_normal(const Eigen::Vector3f& v0, const Eigen::Vector3f& v1,
                                           const Eigen::Vector3f& v2)
{
    Eigen::Vector3f n = (v1 - v0).cross(v2 - v0); // v0-to-v1 x v0-to-v2
    return n.normalized();
};

/**
 * Calculates the normal of a face (or triangle), i.e. the per-face normal. Returned normal will be unit
 * length.
 *
 * Assumes the triangle is given in CCW order, i.e. vertices in counterclockwise order on the screen are
 * front-facing.
 *
 * @param[in] v0 First vertex.
 * @param[in] v1 Second vertex.
 * @param[in] v2 Third vertex.
 * @return The unit-length normal of the given triangle.
 */
inline Eigen::Vector3f compute_face_normal(const Eigen::Vector4f& v0, const Eigen::Vector4f& v1,
                                           const Eigen::Vector4f& v2)
{
    Eigen::Vector4f n = (v1 - v0).cross3(v2 - v0); // v0-to-v1 x v0-to-v2
    return n.head<3>().normalized();
};

/**
 * Calculates the normal of a face (or triangle), i.e. the per-face normal. Returned normal will be unit
 * length.
 *
 * Assumes the triangle is given in CCW order, i.e. vertices in counterclockwise order on the screen are
 * front-facing.
 *
 * @param[in] v0 First vertex.
 * @param[in] v1 Second vertex.
 * @param[in] v2 Third vertex.
 * @return The unit-length normal of the given triangle.
 */
inline glm::vec3 compute_face_normal(const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2)
{
    glm::vec3 n = glm::cross(v1 - v0, v2 - v0); // v0-to-v1 x v0-to-v2
    n = glm::normalize(n);
    return n;
};

} /* namespace render */
} /* namespace eos */

#endif /* EOS_RENDER_NORMALS_HPP */
<|endoftext|>


<commit_before>/*=========================================================================

Program:   openCherry Platform
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#ifdef __MINGW32__
// We need to inlclude winbase.h here in order to declare
// atomic intrinsics like InterlockedIncrement correctly.
// Otherwhise, they would be declared wrong within qatomic_windows.h .
#include <windows.h>
#endif

#include "cherryQtPlatformLogModel.h"

#include "cherryPlatform.h"
#include "event/cherryPlatformEvents.h"

#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>

#include <Poco/Message.h>
#include "mbilog.h"
#include <QTimer>

namespace cherry {

const QString QtPlatformLogModel::Error = QString("Error");
const QString QtPlatformLogModel::Warn = QString("Warn");
const QString QtPlatformLogModel::Fatal = QString("Fatal");
const QString QtPlatformLogModel::Info = QString("Info");
const QString QtPlatformLogModel::Debug = QString("Debug");

void QtPlatformLogModel::slotFlushLogEntries()
{
  m_Mutex.lock();
  std::list<ExtendedLogMessage> *tmp=m_Active;
  m_Active=m_Pending; m_Pending=tmp;
  m_Mutex.unlock();

  std::list<ExtendedLogMessage>::size_type num = m_Pending->size();

  if (num > 0)
  {
    int row = static_cast<int>(m_Entries.size());
    this->beginInsertRows(QModelIndex(), row, row+num-1);
    do {
      m_Entries.push_back(m_Pending->front());
      m_Pending->pop_front();
    } while(--num);
    this->endInsertRows();
  }
}

void QtPlatformLogModel::addLogEntry(const mbilog::LogMessage &msg)
{
  m_Mutex.lock();
  mbilog::BackendCout::FormatSmart(msg);
  m_Active->push_back(ExtendedLogMessage(msg));
  m_Mutex.unlock();

  emit signalFlushLogEntries();
}

void
QtPlatformLogModel::addLogEntry(const PlatformEvent& event)
{
  const Poco::Message& entry = Poco::RefAnyCast<const Poco::Message>(*event.GetData());
  mbilog::LogMessage msg(mbilog::Info,"n/a",-1,"n/a");
  msg.message += entry.getText();
  msg.category = "openCherry."+entry.getSource();
  msg.moduleName = "n/a";
  addLogEntry(msg);
}

QtPlatformLogModel::QtPlatformLogModel(QObject* parent) : QAbstractTableModel(parent)
{
  m_Active=new std::list<ExtendedLogMessage>;
  m_Pending=new std::list<ExtendedLogMessage>;
  connect(this, SIGNAL(signalFlushLogEntries()), this, SLOT( slotFlushLogEntries() ), Qt::QueuedConnection );
  Platform::GetEvents().logged += PlatformEventDelegate(this, &QtPlatformLogModel::addLogEntry);
  myBackend = new QtLogBackend(this);
}

QtPlatformLogModel::~QtPlatformLogModel()
{
  disconnect(this, SIGNAL(signalFlushLogEntries()), this, SLOT( slotFlushLogEntries() ));

  // dont delete and unregister backend, only deactivate it to avoid thread syncronization issues cause mbilog::UnregisterBackend is not threadsafe
  // will be fixed.
  //  delete myBackend;
  //  delete m_Active;
  //  delete m_Pending;
  m_Mutex.lock();
  myBackend->Deactivate();
  m_Mutex.unlock();
}

// QT Binding

int
QtPlatformLogModel::rowCount(const QModelIndex&) const
{
  return static_cast<int>(m_Entries.size());
}

int
QtPlatformLogModel::columnCount(const QModelIndex&) const
{
  return 8;
}
          /*
  struct LogEntry {
    LogEntry(const std::string& msg, const std::string& src, std::time_t t)
    : message(msg.c_str()), moduleName(src.c_str()),time(std::clock())
    {
    }

    QString message;
    clock_t time;

    QString level;
    QString filePath;
    QString lineNumber;
    QString moduleName;
    QString category;
    QString function;

    LogEntry(const mbilog::LogMessage &msg)
    {
      message = msg.message.c_str();

      filePath = msg.filePath;

      std::stringstream out;
      out << msg.lineNumber;
      lineNumber = out.str().c_str();

      moduleName = msg.moduleName;
      category = msg.category.c_str();
      function = msg.functionName;

      time=std::clock();
    }
  };        */

QVariant
QtPlatformLogModel::data(const QModelIndex& index, int role) const
{
  const ExtendedLogMessage *msg = &m_Entries[index.row()];
  if (role == Qt::DisplayRole)
  {
    switch (index.column()) {

      case 0: {
        std::stringstream ss;
        ss << std::setw(7) << std::setprecision(3) << std::fixed << ((double)msg->time)/CLOCKS_PER_SEC;
        return QVariant(QString(ss.str().c_str()));
      }

      case 1:
        {
          switch(msg->message.level)
          {
            default:
            case mbilog::Info:
              return QVariant(Info);

            case mbilog::Warn:
              return QVariant(Warn);

            case mbilog::Error:
              return QVariant(Error);

            case mbilog::Fatal:
              return QVariant(Fatal);

            case mbilog::Debug:
              return QVariant(Debug);
          }
        }

      case 2:
        return QVariant(QString(msg->message.message.c_str()));

      case 3:
        return QVariant(QString(msg->message.category.c_str()));

      case 4:
        return QVariant(QString(msg->message.moduleName));

      case 5:
        return QVariant(QString(msg->message.functionName));

      case 6:
        return QVariant(QString(msg->message.filePath));

      case 7:
      {
        std::stringstream out;
        out << msg->message.lineNumber;
        return QVariant(QString(out.str().c_str()));
      }
    }
  }

  return QVariant();
}

QVariant
QtPlatformLogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
  {
    switch (section) {
    case 0: return QVariant("Time");
    case 1: return QVariant("Level");
    case 2: return QVariant("Message");
    case 3: return QVariant("Category");
    case 4: return QVariant("Module");
    case 5: return QVariant("Function");
    case 6: return QVariant("File");
    case 7: return QVariant("Line");
    }
  }

  return QVariant();
}

}
<commit_msg>COMP: fix compiler warning<commit_after>/*=========================================================================

Program:   openCherry Platform
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#ifdef __MINGW32__
// We need to inlclude winbase.h here in order to declare
// atomic intrinsics like InterlockedIncrement correctly.
// Otherwhise, they would be declared wrong within qatomic_windows.h .
#include <windows.h>
#endif

#include "cherryQtPlatformLogModel.h"

#include "cherryPlatform.h"
#include "event/cherryPlatformEvents.h"

#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>

#include <Poco/Message.h>
#include "mbilog.h"
#include <QTimer>

namespace cherry {

const QString QtPlatformLogModel::Error = QString("Error");
const QString QtPlatformLogModel::Warn = QString("Warn");
const QString QtPlatformLogModel::Fatal = QString("Fatal");
const QString QtPlatformLogModel::Info = QString("Info");
const QString QtPlatformLogModel::Debug = QString("Debug");

void QtPlatformLogModel::slotFlushLogEntries()
{
  m_Mutex.lock();
  std::list<ExtendedLogMessage> *tmp=m_Active;
  m_Active=m_Pending; m_Pending=tmp;
  m_Mutex.unlock();

  int num = static_cast<int>(m_Pending->size());

  if (num > 0)
  {
    int row = static_cast<int>(m_Entries.size());
    this->beginInsertRows(QModelIndex(), row, row+num-1);
    do {
      m_Entries.push_back(m_Pending->front());
      m_Pending->pop_front();
    } while(--num);
    this->endInsertRows();
  }
}

void QtPlatformLogModel::addLogEntry(const mbilog::LogMessage &msg)
{
  m_Mutex.lock();
  mbilog::BackendCout::FormatSmart(msg);
  m_Active->push_back(ExtendedLogMessage(msg));
  m_Mutex.unlock();

  emit signalFlushLogEntries();
}

void
QtPlatformLogModel::addLogEntry(const PlatformEvent& event)
{
  const Poco::Message& entry = Poco::RefAnyCast<const Poco::Message>(*event.GetData());
  mbilog::LogMessage msg(mbilog::Info,"n/a",-1,"n/a");
  msg.message += entry.getText();
  msg.category = "openCherry."+entry.getSource();
  msg.moduleName = "n/a";
  addLogEntry(msg);
}

QtPlatformLogModel::QtPlatformLogModel(QObject* parent) : QAbstractTableModel(parent)
{
  m_Active=new std::list<ExtendedLogMessage>;
  m_Pending=new std::list<ExtendedLogMessage>;
  connect(this, SIGNAL(signalFlushLogEntries()), this, SLOT( slotFlushLogEntries() ), Qt::QueuedConnection );
  Platform::GetEvents().logged += PlatformEventDelegate(this, &QtPlatformLogModel::addLogEntry);
  myBackend = new QtLogBackend(this);
}

QtPlatformLogModel::~QtPlatformLogModel()
{
  disconnect(this, SIGNAL(signalFlushLogEntries()), this, SLOT( slotFlushLogEntries() ));

  // dont delete and unregister backend, only deactivate it to avoid thread syncronization issues cause mbilog::UnregisterBackend is not threadsafe
  // will be fixed.
  //  delete myBackend;
  //  delete m_Active;
  //  delete m_Pending;
  m_Mutex.lock();
  myBackend->Deactivate();
  m_Mutex.unlock();
}

// QT Binding

int
QtPlatformLogModel::rowCount(const QModelIndex&) const
{
  return static_cast<int>(m_Entries.size());
}

int
QtPlatformLogModel::columnCount(const QModelIndex&) const
{
  return 8;
}
          /*
  struct LogEntry {
    LogEntry(const std::string& msg, const std::string& src, std::time_t t)
    : message(msg.c_str()), moduleName(src.c_str()),time(std::clock())
    {
    }

    QString message;
    clock_t time;

    QString level;
    QString filePath;
    QString lineNumber;
    QString moduleName;
    QString category;
    QString function;

    LogEntry(const mbilog::LogMessage &msg)
    {
      message = msg.message.c_str();

      filePath = msg.filePath;

      std::stringstream out;
      out << msg.lineNumber;
      lineNumber = out.str().c_str();

      moduleName = msg.moduleName;
      category = msg.category.c_str();
      function = msg.functionName;

      time=std::clock();
    }
  };        */

QVariant
QtPlatformLogModel::data(const QModelIndex& index, int role) const
{
  const ExtendedLogMessage *msg = &m_Entries[index.row()];
  if (role == Qt::DisplayRole)
  {
    switch (index.column()) {

      case 0: {
        std::stringstream ss;
        ss << std::setw(7) << std::setprecision(3) << std::fixed << ((double)msg->time)/CLOCKS_PER_SEC;
        return QVariant(QString(ss.str().c_str()));
      }

      case 1:
        {
          switch(msg->message.level)
          {
            default:
            case mbilog::Info:
              return QVariant(Info);

            case mbilog::Warn:
              return QVariant(Warn);

            case mbilog::Error:
              return QVariant(Error);

            case mbilog::Fatal:
              return QVariant(Fatal);

            case mbilog::Debug:
              return QVariant(Debug);
          }
        }

      case 2:
        return QVariant(QString(msg->message.message.c_str()));

      case 3:
        return QVariant(QString(msg->message.category.c_str()));

      case 4:
        return QVariant(QString(msg->message.moduleName));

      case 5:
        return QVariant(QString(msg->message.functionName));

      case 6:
        return QVariant(QString(msg->message.filePath));

      case 7:
      {
        std::stringstream out;
        out << msg->message.lineNumber;
        return QVariant(QString(out.str().c_str()));
      }
    }
  }

  return QVariant();
}

QVariant
QtPlatformLogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
  {
    switch (section) {
    case 0: return QVariant("Time");
    case 1: return QVariant("Level");
    case 2: return QVariant("Message");
    case 3: return QVariant("Category");
    case 4: return QVariant("Module");
    case 5: return QVariant("Function");
    case 6: return QVariant("File");
    case 7: return QVariant("Line");
    }
  }

  return QVariant();
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The Silk Network developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "proofs.h"

#include "chainparams.h"
#include "main.h"
#include "uint256.h"
#include "util.h"
#include "amount.h"
#include "checkpoints.h"

#include <math.h>
#include <stdint.h>

unsigned int nStakeMinAge       = 8 * 60 * 60;
unsigned int nModifierInterval  = 2 * 60 * 60;

uint256 CBlock::GetHash() const {
	return GetPoWHash();
}

uint256 CBlock::GetPoWHash() const {
	return Hash(BEGIN(nVersion), END(nNonce));
}

int DetermineCoinbaseMaturity() {
	if(pindexBest->nHeight <= 100) {
		return (int)10; // This will allow for premine distribution to propogate faster
	} else {
		return (int)60; // Coinbase will take approx. 1 hr to reach confirmation
	}
}

// miner's coin base reward
int64_t GetCoinbaseValue(int nHeight, CAmount nFees)
{
    CAmount nSubsidy = 0;

	if(nHeight == 1) {
		nSubsidy = 16400000 * COIN;
	}

    return nSubsidy;
}

// miner's coin stake reward based on coin age spent (coin-days)
int64_t GetCoinstakeValue(int64_t nCoinAge, CAmount nFees, int nHeight)
{
	CAmount nSubsidy = 0.2 * COIN;

	if(nHeight <= 125146) {
		nSubsidy = 23 * COIN;
	} else if(nHeight <= 568622) {
		nSubsidy = 17 * COIN;
	} else if(nHeight <= 1012098) {
		nSubsidy = 11.5 * COIN;
	} else if(nHeight <= 1455574) {
		nSubsidy = 5.75 * COIN;
	} else if(nHeight <= 3675950) {
		nSubsidy = 1.85 * COIN;
	} else {
		nSubsidy = 0.2 * COIN;
	}

    return nSubsidy + nFees;
}

unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
    uint256 bnTargetLimit = fProofOfStake ? Params().ProofOfStakeLimit() : Params().ProofOfWorkLimit();

    if (pindexLast == NULL)
        return bnTargetLimit.GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();

    if (nActualSpacing < 0) {
        nActualSpacing = nTargetSpacing;
    }
    else if (fProofOfStake && nActualSpacing > nTargetSpacing * 10) {
         nActualSpacing = nTargetSpacing * 10;
    }

    // target change every block
    // retarget with exponential moving toward target spacing
    // Includes fix for wrong retargeting difficulty by Mammix2
    uint256 bnNew;
    bnNew.SetCompact(pindexPrev->nBits);

    int64_t nInterval = fProofOfStake ? 10 : 10;
    bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
    bnNew /= ((nInterval + 1) * nTargetSpacing);

    if (bnNew <= 0 || bnNew > bnTargetLimit)
        bnNew = bnTargetLimit;

    return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits)
{
    uint256 bnTarget;
    bnTarget.SetCompact(nBits);

    // Check range
    if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
        return error("CheckProofOfWork() : nBits below minimum work");

    // Check proof of work matches claimed amount
    if (hash > bnTarget)
        return error("CheckProofOfWork() : hash doesn't match nBits");

    return true;
}
<commit_msg>[Stake Age] Reduce<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The Silk Network developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "proofs.h"

#include "chainparams.h"
#include "main.h"
#include "uint256.h"
#include "util.h"
#include "amount.h"
#include "checkpoints.h"

#include <math.h>
#include <stdint.h>

unsigned int nStakeMinAge       = 1 * 60 * 60;
unsigned int nModifierInterval  = 2 * 60 * 60;

uint256 CBlock::GetHash() const {
	return GetPoWHash();
}

uint256 CBlock::GetPoWHash() const {
	return Hash(BEGIN(nVersion), END(nNonce));
}

int DetermineCoinbaseMaturity() {
	if(pindexBest->nHeight <= 100) {
		return (int)10; // This will allow for premine distribution to propogate faster
	} else {
		return (int)60; // Coinbase will take approx. 1 hr to reach confirmation
	}
}

// miner's coin base reward
int64_t GetCoinbaseValue(int nHeight, CAmount nFees)
{
    CAmount nSubsidy = 0;

	if(nHeight == 1) {
		nSubsidy = 16400000 * COIN;
	}

    return nSubsidy;
}

// miner's coin stake reward based on coin age spent (coin-days)
int64_t GetCoinstakeValue(int64_t nCoinAge, CAmount nFees, int nHeight)
{
	CAmount nSubsidy = 0.2 * COIN;

	if(nHeight <= 125146) {
		nSubsidy = 23 * COIN;
	} else if(nHeight <= 568622) {
		nSubsidy = 17 * COIN;
	} else if(nHeight <= 1012098) {
		nSubsidy = 11.5 * COIN;
	} else if(nHeight <= 1455574) {
		nSubsidy = 5.75 * COIN;
	} else if(nHeight <= 3675950) {
		nSubsidy = 1.85 * COIN;
	} else {
		nSubsidy = 0.2 * COIN;
	}

    return nSubsidy + nFees;
}

unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
{
    uint256 bnTargetLimit = fProofOfStake ? Params().ProofOfStakeLimit() : Params().ProofOfWorkLimit();

    if (pindexLast == NULL)
        return bnTargetLimit.GetCompact(); // genesis block

    const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake);
    if (pindexPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // first block
    const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake);
    if (pindexPrevPrev->pprev == NULL)
        return bnTargetLimit.GetCompact(); // second block

    int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime();

    if (nActualSpacing < 0) {
        nActualSpacing = nTargetSpacing;
    }
    else if (fProofOfStake && nActualSpacing > nTargetSpacing * 10) {
         nActualSpacing = nTargetSpacing * 10;
    }

    // target change every block
    // retarget with exponential moving toward target spacing
    // Includes fix for wrong retargeting difficulty by Mammix2
    uint256 bnNew;
    bnNew.SetCompact(pindexPrev->nBits);

    int64_t nInterval = fProofOfStake ? 10 : 10;
    bnNew *= ((nInterval - 1) * nTargetSpacing + nActualSpacing + nActualSpacing);
    bnNew /= ((nInterval + 1) * nTargetSpacing);

    if (bnNew <= 0 || bnNew > bnTargetLimit)
        bnNew = bnTargetLimit;

    return bnNew.GetCompact();
}

bool CheckProofOfWork(uint256 hash, unsigned int nBits)
{
    uint256 bnTarget;
    bnTarget.SetCompact(nBits);

    // Check range
    if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
        return error("CheckProofOfWork() : nBits below minimum work");

    // Check proof of work matches claimed amount
    if (hash > bnTarget)
        return error("CheckProofOfWork() : hash doesn't match nBits");

    return true;
}
<|endoftext|>


<commit_before>#include "joedb/journal/Readonly_Journal.h"
#include "joedb/journal/Generic_File.h"
#include "joedb/Exception.h"

#include <sstream>

const uint32_t joedb::Readonly_Journal::version_number = 0x00000004;
const uint32_t joedb::Readonly_Journal::compatible_version = 0x00000004;
const int64_t joedb::Readonly_Journal::header_size = 41;

/////////////////////////////////////////////////////////////////////////////
joedb::Readonly_Journal::Readonly_Journal
/////////////////////////////////////////////////////////////////////////////
(
 Generic_File &file,
 bool ignore_errors
):
 file(file),
 checkpoint_index(0),
 checkpoint_position(0),
 table_of_last_operation(0),
 record_of_last_operation(0),
 field_of_last_update(0)
{
 auto format_exception = [ignore_errors](const char *message)
 {
  if (!ignore_errors)
   throw Exception(message);
 };

 //
 // Check the format of an existing joedb file
 //
 if (file.get_mode() != Open_Mode::create_new)
 {
  //
  // First, check for initial "joedb"
  //
  if (file.read<uint8_t>() != 'j' ||
      file.read<uint8_t>() != 'o' ||
      file.read<uint8_t>() != 'e' ||
      file.read<uint8_t>() != 'd' ||
      file.read<uint8_t>() != 'b')
  {
   format_exception("File does not start by 'joedb'");
  }
  else
  {
   //
   // Check version number
   //
   const uint32_t version = file.read<uint32_t>();
   if (version < compatible_version || version > version_number)
    format_exception("Unsupported format version");

   //
   // Find the most recent checkpoint
   //
   int64_t pos[4];
   for (int i = 0; i < 4; i++)
    pos[i] = file.read<int64_t>();

   if (pos[0] != pos[1] || pos[2] != pos[3])
    format_exception("Checkpoint mismatch");

   checkpoint_position = 0;

   for (unsigned i = 0; i < 2; i++)
    if (pos[2 * i] == pos[2 * i + 1] && pos[2 * i] > checkpoint_position)
    {
     if (int64_t(size_t(pos[2 * i])) != pos[2 * i])
      throw Exception("size_t is too small for this file");
     checkpoint_position = pos[2 * i];
     checkpoint_index = i;
    }

   if (checkpoint_position < header_size)
    format_exception("Checkpoint too small");

   //
   // Compare to file size (if available)
   //
   int64_t file_size = file.get_size();

   if (file_size > 0 && file_size != checkpoint_position)
    format_exception("Checkpoint different from file size");

   if (ignore_errors)
    checkpoint_position = file_size;
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
std::vector<char> joedb::Readonly_Journal::get_raw_tail
/////////////////////////////////////////////////////////////////////////////
(
 int64_t starting_position
)
{
 std::vector<char> result;
 const int64_t size = get_checkpoint_position() - starting_position;

 if (size > 0)
 {
  result.resize(size_t(size));
  get_tail_reader(starting_position).read(result.data(), result.size());
 }

 return result;
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::replay_log(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 rewind();
 play_until_checkpoint(writable);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::rewind()
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(header_size);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::seek(int64_t position)
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(position);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::play_until(Writable &writable, int64_t end)
/////////////////////////////////////////////////////////////////////////////
{
 while(file.get_position() < end)
  one_step(writable);
 file.set_position(file.get_position()); // get ready for writing
}

/////////////////////////////////////////////////////////////////////////////
bool joedb::Readonly_Journal::at_end_of_file() const
/////////////////////////////////////////////////////////////////////////////
{
 return file.get_position() >= checkpoint_position;
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::one_step(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 switch(file.read<operation_t>())
 {
  case operation_t::end_of_file:
   if (file.get_position() != checkpoint_position)
    throw Exception("Unexpected end of file");
  break;

  case operation_t::create_table:
  {
   std::string name = safe_read_string();
   writable.create_table(name);
  }
  break;

  case operation_t::drop_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   writable.drop_table(table_id);
  }
  break;

  case operation_t::rename_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   writable.rename_table(table_id, name);
  }
  break;

  case operation_t::add_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   Type type = read_type();
   writable.add_field(table_id, name, type);
  }
  break;

  case operation_t::drop_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   writable.drop_field(table_id, field_id);
  }
  break;

  case operation_t::rename_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   std::string name = safe_read_string();
   writable.rename_field(table_id, field_id, name);
  }
  break;

  case operation_t::insert_into:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.insert_into(table_id, record_id);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::insert_vector:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   Record_Id size = file.compact_read<Record_Id>();
   writable.insert_vector(table_id, record_id, size);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::append:
   writable.insert_into(table_of_last_operation,
                         ++record_of_last_operation);
  break;

  case operation_t::delete_from:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.delete_from(table_id, record_id);
  }
  break;

  #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
  case operation_t::update_##type_id:\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_last_##type_id:\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_next_##type_id:\
   record_of_last_operation++;\
  goto lbl_perform_update_##type_id;\
\
  lbl_perform_update_##type_id:\
  {\
   cpp_type value = read_method();\
   writable.update_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    value\
   );\
  }\
  break;\
\
  case operation_t::update_vector_##type_id:\
  {\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
   Record_Id size = file.compact_read<Record_Id>();\
   if (int64_t(size) > checkpoint_position || size < 0)\
    throw Exception("update_vector too big");\
   Record_Id capacity;\
   cpp_type *data = writable.get_own_##type_id##_storage\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    capacity\
   );\
   std::vector<cpp_type> buffer;\
   if (!data)\
   {\
    buffer.resize(size);\
    data = &buffer[0];\
   }\
   else if (record_of_last_operation <= 0 || record_of_last_operation + size - 1 > capacity)\
    throw Exception("update_vector out of range");\
   read_vector_of_##type_id(data, size);\
   writable.update_vector_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    size,\
    data\
   );\
  }\
  break;
  #include "joedb/TYPE_MACRO.h"

  case operation_t::custom:
  {
   std::string name = safe_read_string();
   writable.custom(name);
  }
  break;

  case operation_t::comment:
  {
   std::string comment = safe_read_string();
   writable.comment(comment);
  }
  break;

  case operation_t::timestamp:
  {
   int64_t timestamp = file.read<int64_t>();
   writable.timestamp(timestamp);
  }
  break;

  case operation_t::valid_data:
   writable.valid_data();
  break;

  default:
  {
   std::ostringstream error;
   error << "Unexpected operation: file.get_position() = ";
   error << file.get_position();
   throw Exception(error.str());
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
joedb::Type joedb::Readonly_Journal::read_type()
/////////////////////////////////////////////////////////////////////////////
{
 Type::Type_Id type_id = Type::Type_Id(file.read<Type_Id_Storage>());
 if (type_id == Type::Type_Id::reference)
  return Type::reference(file.compact_read<Table_Id>());
 else
  return Type(type_id);
}

/////////////////////////////////////////////////////////////////////////////
std::string joedb::Readonly_Journal::safe_read_string()
/////////////////////////////////////////////////////////////////////////////
{
 return file.safe_read_string(size_t(checkpoint_position));
}

#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
{\
 for (size_t i = 0; i < size; i++)\
  data[i] = read_method();\
}
#define TYPE_MACRO_NO_INT
#define TYPE_MACRO_NO_FLOAT
#include "joedb/TYPE_MACRO.h"

#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
{\
 file.read_data((char *)data, size * sizeof(cpp_type));\
 if (is_big_endian() && sizeof(cpp_type) > 1)\
  for (size_t i = 0; i < size; i++)\
   Generic_File::R<cpp_type, sizeof(cpp_type)>::swap(data[i]);\
}
#define TYPE_MACRO_NO_STRING
#define TYPE_MACRO_NO_REFERENCE
#include "joedb/TYPE_MACRO.h"
<commit_msg>better behaviour when ignore_errors with unknown file_size<commit_after>#include "joedb/journal/Readonly_Journal.h"
#include "joedb/journal/Generic_File.h"
#include "joedb/Exception.h"

#include <sstream>

const uint32_t joedb::Readonly_Journal::version_number = 0x00000004;
const uint32_t joedb::Readonly_Journal::compatible_version = 0x00000004;
const int64_t joedb::Readonly_Journal::header_size = 41;

/////////////////////////////////////////////////////////////////////////////
joedb::Readonly_Journal::Readonly_Journal
/////////////////////////////////////////////////////////////////////////////
(
 Generic_File &file,
 bool ignore_errors
):
 file(file),
 checkpoint_index(0),
 checkpoint_position(0),
 table_of_last_operation(0),
 record_of_last_operation(0),
 field_of_last_update(0)
{
 auto format_exception = [ignore_errors](const char *message)
 {
  if (!ignore_errors)
   throw Exception(message);
 };

 //
 // Check the format of an existing joedb file
 //
 if (file.get_mode() != Open_Mode::create_new)
 {
  //
  // First, check for initial "joedb"
  //
  if (file.read<uint8_t>() != 'j' ||
      file.read<uint8_t>() != 'o' ||
      file.read<uint8_t>() != 'e' ||
      file.read<uint8_t>() != 'd' ||
      file.read<uint8_t>() != 'b')
  {
   format_exception("File does not start by 'joedb'");
  }
  else
  {
   //
   // Check version number
   //
   const uint32_t version = file.read<uint32_t>();
   if (version < compatible_version || version > version_number)
    format_exception("Unsupported format version");

   //
   // Find the most recent checkpoint
   //
   int64_t pos[4];
   for (int i = 0; i < 4; i++)
    pos[i] = file.read<int64_t>();

   if (pos[0] != pos[1] || pos[2] != pos[3])
    format_exception("Checkpoint mismatch");

   checkpoint_position = 0;

   for (unsigned i = 0; i < 2; i++)
    if (pos[2 * i] == pos[2 * i + 1] && pos[2 * i] > checkpoint_position)
    {
     if (int64_t(size_t(pos[2 * i])) != pos[2 * i])
      throw Exception("size_t is too small for this file");
     checkpoint_position = pos[2 * i];
     checkpoint_index = i;
    }

   if (checkpoint_position < header_size)
    format_exception("Checkpoint too small");

   //
   // Compare to file size (if available)
   //
   int64_t file_size = file.get_size();

   if (file_size > 0)
   {
    if (file_size != checkpoint_position)
     format_exception("Checkpoint different from file size");

    if (ignore_errors)
     checkpoint_position = file_size;
   }
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
std::vector<char> joedb::Readonly_Journal::get_raw_tail
/////////////////////////////////////////////////////////////////////////////
(
 int64_t starting_position
)
{
 std::vector<char> result;
 const int64_t size = get_checkpoint_position() - starting_position;

 if (size > 0)
 {
  result.resize(size_t(size));
  get_tail_reader(starting_position).read(result.data(), result.size());
 }

 return result;
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::replay_log(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 rewind();
 play_until_checkpoint(writable);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::rewind()
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(header_size);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::seek(int64_t position)
/////////////////////////////////////////////////////////////////////////////
{
 file.set_position(position);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::play_until(Writable &writable, int64_t end)
/////////////////////////////////////////////////////////////////////////////
{
 while(file.get_position() < end)
  one_step(writable);
 file.set_position(file.get_position()); // get ready for writing
}

/////////////////////////////////////////////////////////////////////////////
bool joedb::Readonly_Journal::at_end_of_file() const
/////////////////////////////////////////////////////////////////////////////
{
 return file.get_position() >= checkpoint_position;
}

/////////////////////////////////////////////////////////////////////////////
void joedb::Readonly_Journal::one_step(Writable &writable)
/////////////////////////////////////////////////////////////////////////////
{
 switch(file.read<operation_t>())
 {
  case operation_t::end_of_file:
   if (file.get_position() != checkpoint_position)
    throw Exception("Unexpected end of file");
  break;

  case operation_t::create_table:
  {
   std::string name = safe_read_string();
   writable.create_table(name);
  }
  break;

  case operation_t::drop_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   writable.drop_table(table_id);
  }
  break;

  case operation_t::rename_table:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   writable.rename_table(table_id, name);
  }
  break;

  case operation_t::add_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   std::string name = safe_read_string();
   Type type = read_type();
   writable.add_field(table_id, name, type);
  }
  break;

  case operation_t::drop_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   writable.drop_field(table_id, field_id);
  }
  break;

  case operation_t::rename_field:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Field_Id field_id = file.compact_read<Field_Id>();
   std::string name = safe_read_string();
   writable.rename_field(table_id, field_id, name);
  }
  break;

  case operation_t::insert_into:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.insert_into(table_id, record_id);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::insert_vector:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   Record_Id size = file.compact_read<Record_Id>();
   writable.insert_vector(table_id, record_id, size);
   table_of_last_operation = table_id;
   record_of_last_operation = record_id;
  }
  break;

  case operation_t::append:
   writable.insert_into(table_of_last_operation,
                         ++record_of_last_operation);
  break;

  case operation_t::delete_from:
  {
   Table_Id table_id = file.compact_read<Table_Id>();
   Record_Id record_id = file.compact_read<Record_Id>();
   writable.delete_from(table_id, record_id);
  }
  break;

  #define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
  case operation_t::update_##type_id:\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_last_##type_id:\
   field_of_last_update = file.compact_read<Field_Id>();\
  goto lbl_perform_update_##type_id;\
\
  case operation_t::update_next_##type_id:\
   record_of_last_operation++;\
  goto lbl_perform_update_##type_id;\
\
  lbl_perform_update_##type_id:\
  {\
   cpp_type value = read_method();\
   writable.update_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    value\
   );\
  }\
  break;\
\
  case operation_t::update_vector_##type_id:\
  {\
   table_of_last_operation = file.compact_read<Table_Id>();\
   record_of_last_operation = file.compact_read<Record_Id>();\
   field_of_last_update = file.compact_read<Field_Id>();\
   Record_Id size = file.compact_read<Record_Id>();\
   if (int64_t(size) > checkpoint_position || size < 0)\
    throw Exception("update_vector too big");\
   Record_Id capacity;\
   cpp_type *data = writable.get_own_##type_id##_storage\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    capacity\
   );\
   std::vector<cpp_type> buffer;\
   if (!data)\
   {\
    buffer.resize(size);\
    data = &buffer[0];\
   }\
   else if (record_of_last_operation <= 0 || record_of_last_operation + size - 1 > capacity)\
    throw Exception("update_vector out of range");\
   read_vector_of_##type_id(data, size);\
   writable.update_vector_##type_id\
   (\
    table_of_last_operation,\
    record_of_last_operation,\
    field_of_last_update,\
    size,\
    data\
   );\
  }\
  break;
  #include "joedb/TYPE_MACRO.h"

  case operation_t::custom:
  {
   std::string name = safe_read_string();
   writable.custom(name);
  }
  break;

  case operation_t::comment:
  {
   std::string comment = safe_read_string();
   writable.comment(comment);
  }
  break;

  case operation_t::timestamp:
  {
   int64_t timestamp = file.read<int64_t>();
   writable.timestamp(timestamp);
  }
  break;

  case operation_t::valid_data:
   writable.valid_data();
  break;

  default:
  {
   std::ostringstream error;
   error << "Unexpected operation: file.get_position() = ";
   error << file.get_position();
   throw Exception(error.str());
  }
 }
}

/////////////////////////////////////////////////////////////////////////////
joedb::Type joedb::Readonly_Journal::read_type()
/////////////////////////////////////////////////////////////////////////////
{
 Type::Type_Id type_id = Type::Type_Id(file.read<Type_Id_Storage>());
 if (type_id == Type::Type_Id::reference)
  return Type::reference(file.compact_read<Table_Id>());
 else
  return Type(type_id);
}

/////////////////////////////////////////////////////////////////////////////
std::string joedb::Readonly_Journal::safe_read_string()
/////////////////////////////////////////////////////////////////////////////
{
 return file.safe_read_string(size_t(checkpoint_position));
}

#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
{\
 for (size_t i = 0; i < size; i++)\
  data[i] = read_method();\
}
#define TYPE_MACRO_NO_INT
#define TYPE_MACRO_NO_FLOAT
#include "joedb/TYPE_MACRO.h"

#define TYPE_MACRO(cpp_type, return_type, type_id, read_method, W)\
void joedb::Readonly_Journal::read_vector_of_##type_id(cpp_type *data, size_t size)\
{\
 file.read_data((char *)data, size * sizeof(cpp_type));\
 if (is_big_endian() && sizeof(cpp_type) > 1)\
  for (size_t i = 0; i < size; i++)\
   Generic_File::R<cpp_type, sizeof(cpp_type)>::swap(data[i]);\
}
#define TYPE_MACRO_NO_STRING
#define TYPE_MACRO_NO_REFERENCE
#include "joedb/TYPE_MACRO.h"
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_STORAGE_HPP_INCLUDE
#define TORRENT_STORAGE_HPP_INCLUDE

#include <vector>
#include <bitset>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/limits.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/torrent_info.hpp"
#include "libtorrent/config.hpp"

namespace libtorrent
{
	namespace detail
	{
		struct piece_checker_data;
	}

	class session;

	TORRENT_EXPORT std::wstring safe_convert(std::string const& s);

	TORRENT_EXPORT std::vector<std::pair<size_type, std::time_t> > get_filesizes(
		torrent_info const& t
		, boost::filesystem::path p);

	TORRENT_EXPORT bool match_filesizes(
		torrent_info const& t
		, boost::filesystem::path p
		, std::vector<std::pair<size_type, std::time_t> > const& sizes
		, std::string* error = 0);

	struct TORRENT_EXPORT file_allocation_failed: std::exception
	{
		file_allocation_failed(const char* error_msg): m_msg(error_msg) {}
		virtual const char* what() const throw() { return m_msg.c_str(); }
		virtual ~file_allocation_failed() throw() {}
		std::string m_msg;
	};

	class TORRENT_EXPORT storage
	{
	public:
		storage(
			const torrent_info& info
		  , const boost::filesystem::path& path);

		void swap(storage&);

		// may throw file_error if storage for slot does not exist
		size_type read(char* buf, int slot, int offset, int size);

		// may throw file_error if storage for slot hasn't been allocated
		void write(const char* buf, int slot, int offset, int size);

		bool move_storage(boost::filesystem::path save_path);

		// this will close all open files that are opened for
		// writing. This is called when a torrent has finished
		// downloading.
		void release_files();

#ifndef NDEBUG
		// overwrites some slots with the
		// contents of others
		void shuffle();
#endif

	private:
		class impl;
		boost::shared_ptr<impl> m_pimpl;
	};

	class TORRENT_EXPORT piece_manager : boost::noncopyable
	{
	public:

		piece_manager(
			const torrent_info& info
			, const boost::filesystem::path& path);

		~piece_manager();

		bool check_fastresume(detail::piece_checker_data& d
			, std::vector<bool>& pieces, bool compact_mode);
		std::pair<bool, float> check_files(std::vector<bool>& pieces);

		void release_files();

		bool is_allocating() const;
		void allocate_slots(int num_slots);
		void mark_failed(int index);

		unsigned long piece_crc(
			int slot_index
			, int block_size
			, const std::bitset<256>& bitmask);
		int slot_for_piece(int piece_index) const;

		size_type read(
			char* buf
			, int piece_index
			, int offset
			, int size);

		void write(
			const char* buf
			, int piece_index
			, int offset
			, int size);

		boost::filesystem::path const& save_path() const;
		bool move_storage(boost::filesystem::path const&);

		// fills the vector that maps all allocated
		// slots to the piece that is stored (or
		// partially stored) there. -2 is the index
		// of unassigned pieces and -1 is unallocated
		void export_piece_map(std::vector<int>& pieces) const;

	private:
		class impl;
		std::auto_ptr<impl> m_pimpl;
	};

}

#endif // TORRENT_STORAGE_HPP_INCLUDED

<commit_msg>fixed ifdef problem<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_STORAGE_HPP_INCLUDE
#define TORRENT_STORAGE_HPP_INCLUDE

#include <vector>
#include <bitset>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/limits.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/torrent_info.hpp"
#include "libtorrent/config.hpp"

namespace libtorrent
{
	namespace detail
	{
		struct piece_checker_data;
	}

	class session;

#if defined(_WIN32) && defined(UNICODE)

	TORRENT_EXPORT std::wstring safe_convert(std::string const& s);

#endif

	TORRENT_EXPORT std::vector<std::pair<size_type, std::time_t> > get_filesizes(
		torrent_info const& t
		, boost::filesystem::path p);

	TORRENT_EXPORT bool match_filesizes(
		torrent_info const& t
		, boost::filesystem::path p
		, std::vector<std::pair<size_type, std::time_t> > const& sizes
		, std::string* error = 0);

	struct TORRENT_EXPORT file_allocation_failed: std::exception
	{
		file_allocation_failed(const char* error_msg): m_msg(error_msg) {}
		virtual const char* what() const throw() { return m_msg.c_str(); }
		virtual ~file_allocation_failed() throw() {}
		std::string m_msg;
	};

	class TORRENT_EXPORT storage
	{
	public:
		storage(
			const torrent_info& info
		  , const boost::filesystem::path& path);

		void swap(storage&);

		// may throw file_error if storage for slot does not exist
		size_type read(char* buf, int slot, int offset, int size);

		// may throw file_error if storage for slot hasn't been allocated
		void write(const char* buf, int slot, int offset, int size);

		bool move_storage(boost::filesystem::path save_path);

		// this will close all open files that are opened for
		// writing. This is called when a torrent has finished
		// downloading.
		void release_files();

#ifndef NDEBUG
		// overwrites some slots with the
		// contents of others
		void shuffle();
#endif

	private:
		class impl;
		boost::shared_ptr<impl> m_pimpl;
	};

	class TORRENT_EXPORT piece_manager : boost::noncopyable
	{
	public:

		piece_manager(
			const torrent_info& info
			, const boost::filesystem::path& path);

		~piece_manager();

		bool check_fastresume(detail::piece_checker_data& d
			, std::vector<bool>& pieces, bool compact_mode);
		std::pair<bool, float> check_files(std::vector<bool>& pieces);

		void release_files();

		bool is_allocating() const;
		void allocate_slots(int num_slots);
		void mark_failed(int index);

		unsigned long piece_crc(
			int slot_index
			, int block_size
			, const std::bitset<256>& bitmask);
		int slot_for_piece(int piece_index) const;

		size_type read(
			char* buf
			, int piece_index
			, int offset
			, int size);

		void write(
			const char* buf
			, int piece_index
			, int offset
			, int size);

		boost::filesystem::path const& save_path() const;
		bool move_storage(boost::filesystem::path const&);

		// fills the vector that maps all allocated
		// slots to the piece that is stored (or
		// partially stored) there. -2 is the index
		// of unassigned pieces and -1 is unallocated
		void export_piece_map(std::vector<int>& pieces) const;

	private:
		class impl;
		std::auto_ptr<impl> m_pimpl;
	};

}

#endif // TORRENT_STORAGE_HPP_INCLUDED

<|endoftext|>


<commit_before>#include <sstream>

#include "pixels.h"
#include "viewport.h"
#include "rng.h"
#include "screenmessage.h"
#include "setup.h"
#include "state.h"

using namespace std;

Pixels::Pixels (GlobalData* global)
:
   global(global), pixels(TPixels(global->setup->pixels)), stepn(1), steps(1),
   stepw(1), stepe(1), speed(4)
{
   Rng* rng = global->rng;
   Viewport* viewport = global->viewport;
   for (int i = 0; i <= global->setup->pixels-1; i++) pixels[i] = Pixel(
      rng->rnd () % viewport->resx,
      rng->rnd () % viewport->resy,
      viewport->mapColor (rng->rnd () % 256, rng->rnd () % 256, rng->rnd () % 256)
   );
}

void Pixels::render () {
   Viewport* viewport = global->viewport;
   viewport->lock ();
   for (TPixels::const_iterator i = pixels.begin (); i != pixels.end (); i++)
      viewport->putpixel (i->x, i->y, i->color);
   viewport->unlock ();
}

void Pixels::tick () {
   if (global->state->isFrozen ()) return;

   Uint32 rval;
   Rng* rng = global->rng;
   Viewport* viewport = global->viewport;
   int shift = rng->bits - 1;
   int mshift = rng->bits - 2;

   State::ModeT mode = global->state->getMode ();
   int px, py, step, xmax=viewport->resx-1, ymax=viewport->resy-1;
   global->event_source->getMouseCoords (px, py);

   for (int j = 1; j <= speed; j++) {
      for (TPixels::iterator i = pixels.begin (); i != pixels.end (); i++) {
         if (shift > mshift) {
            rval = rng->rnd ();
            shift = 0;
         }
         switch (mode) {
            case State::Static:
               switch ((rval >> shift) & 3) {
                  case 0:
                     if ((i->x += stepe) >= xmax) i->x -= stepe;
                     break;
                  case 1:
                     if ((i->x -= stepw) < 0) i->x += stepw;
                     break;
                  case 2:
                     if ((i->y += steps) >= ymax) i->y -= steps;
                     break;
                  case 3:
                     if ((i->y -= stepn) < 0) i->y += stepn;
                     break;
               }
               break;
            case State::Magnetic:
               switch ((rval >> shift) & 3) {
                  case 0:
                     step = (px > i->x)?((px - i->x) / 10 + 1):1;
                     step = (step>5)?10:step;
                     if ((i->x += step) > xmax) i->x -= step;
                     break;
                  case 1:
                     step = (px < i->x)?((i->x - px) / 10 + 1):1;
                     step = (step>5)?10:step;
                     if ((i->x -= step) < 0) i->x += step;
                     break;
                  case 2:
                     step = (py > i->y)?((py - i->y) / 10 + 1):1;
                     step = (step>5)?10:step;
                     if ((i->y += step) > ymax) i->y -= step;
                     break;
                  case 3:
                     step = (py < i->y)?((i->y - py) / 10 + 1):1;
                     step = (step>5)?10:step;
                     if ((i->y -= step) < 0) i->y += step;
                     break;
               }
               break;
         }
         shift += 2;
      }
   }
}

void Pixels::receiveEvent (const Event& evt) {
   stringstream ss;
   ScreenMessage* messages = global->messages;
   switch (evt.type) {
      case Event::Left:
         if (stepe > 1) {
            stepe--;
            ss << "step width east: " << stepe;
            messages->pushMessage (ss.str ());
         } else {
            stepw++;
            ss << "step width west: " << stepw;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::Right:
         if (stepw > 1) {
            stepw--;
            ss << "step width west: " << stepw;
            messages->pushMessage (ss.str ());
         } else {
            stepe++;
            ss << "step width east: " << stepe;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::Up:
         if (steps > 1) {
            steps--;
            ss << "step width south: " << steps;
            messages->pushMessage (ss.str ());
         } else {
            stepn++;
            ss << "step width north: " << stepn;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::Down:
         if (stepn > 1) {
            stepn--;
            ss << "step width north: " << stepn;
            messages->pushMessage (ss.str ());
         } else {
            steps++;
            ss << "step width south: " << steps;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::SpeedUp:
         speed++;
         ss << "speed: " << speed;
         messages->pushMessage (ss.str ());
         break;
      case Event::SpeedDown:
         if (speed > 1) speed--;
         ss << "speed: " << speed;
         messages->pushMessage (ss.str ());
         break;
      case Event::ChangeRng:
         global->rng->cycle ();
         messages->pushMessage ("rng set to " + global->rng->name ());
         break;
      case Event::Dump:
         ss <<    "north: " << stepn << "   west: " << stepw;
         ss << "   south: " << steps << "   east: " << stepe;
         ss << "   speed: " << speed;
         messages->pushMessage (ss.str ());
         messages->pushMessage ("random number generator: " + global->rng-> name ());
         break;
   }
}

<commit_msg>Tune magnetic mode.<commit_after>#include <sstream>

#include "pixels.h"
#include "viewport.h"
#include "rng.h"
#include "screenmessage.h"
#include "setup.h"
#include "state.h"

using namespace std;

Pixels::Pixels (GlobalData* global)
:
   global(global), pixels(TPixels(global->setup->pixels)), stepn(1), steps(1),
   stepw(1), stepe(1), speed(4)
{
   Rng* rng = global->rng;
   Viewport* viewport = global->viewport;
   for (int i = 0; i <= global->setup->pixels-1; i++) pixels[i] = Pixel(
      rng->rnd () % viewport->resx,
      rng->rnd () % viewport->resy,
      viewport->mapColor (rng->rnd () % 256, rng->rnd () % 256, rng->rnd () % 256)
   );
}

void Pixels::render () {
   Viewport* viewport = global->viewport;
   viewport->lock ();
   for (TPixels::const_iterator i = pixels.begin (); i != pixels.end (); i++)
      viewport->putpixel (i->x, i->y, i->color);
   viewport->unlock ();
}

void Pixels::tick () {
   if (global->state->isFrozen ()) return;

   Uint32 rval;
   Rng* rng = global->rng;
   Viewport* viewport = global->viewport;
   int shift = rng->bits - 1;
   int mshift = rng->bits - 2;

   State::ModeT mode = global->state->getMode ();
   int px, py, step, xmax=viewport->resx-1, ymax=viewport->resy-1;
   global->event_source->getMouseCoords (px, py);

   for (int j = 1; j <= speed; j++) {
      for (TPixels::iterator i = pixels.begin (); i != pixels.end (); i++) {
         if (shift > mshift) {
            rval = rng->rnd ();
            shift = 0;
         }
         switch (mode) {
            case State::Static:
               switch ((rval >> shift) & 3) {
                  case 0:
                     if ((i->x += stepe) >= xmax) i->x -= stepe;
                     break;
                  case 1:
                     if ((i->x -= stepw) < 0) i->x += stepw;
                     break;
                  case 2:
                     if ((i->y += steps) >= ymax) i->y -= steps;
                     break;
                  case 3:
                     if ((i->y -= stepn) < 0) i->y += stepn;
                     break;
               }
               break;
            case State::Magnetic:
               switch ((rval >> shift) & 3) {
                  case 0:
                     step = (px > i->x)?((px - i->x) / 10 + 1):1;
                     if (step > 7) step = 7;
                     if ((i->x += step) > xmax) i->x -= step;
                     break;
                  case 1:
                     step = (px < i->x)?((i->x - px) / 10 + 1):1;
                     if (step > 7) step = 7;
                     if ((i->x -= step) < 0) i->x += step;
                     break;
                  case 2:
                     step = (py > i->y)?((py - i->y) / 10 + 1):1;
                     if (step > 7) step = 7;
                     if ((i->y += step) > ymax) i->y -= step;
                     break;
                  case 3:
                     step = (py < i->y)?((i->y - py) / 10 + 1):1;
                     if (step > 7) step = 7;
                     if ((i->y -= step) < 0) i->y += step;
                     break;
               }
               break;
         }
         shift += 2;
      }
   }
}

void Pixels::receiveEvent (const Event& evt) {
   stringstream ss;
   ScreenMessage* messages = global->messages;
   switch (evt.type) {
      case Event::Left:
         if (stepe > 1) {
            stepe--;
            ss << "step width east: " << stepe;
            messages->pushMessage (ss.str ());
         } else {
            stepw++;
            ss << "step width west: " << stepw;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::Right:
         if (stepw > 1) {
            stepw--;
            ss << "step width west: " << stepw;
            messages->pushMessage (ss.str ());
         } else {
            stepe++;
            ss << "step width east: " << stepe;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::Up:
         if (steps > 1) {
            steps--;
            ss << "step width south: " << steps;
            messages->pushMessage (ss.str ());
         } else {
            stepn++;
            ss << "step width north: " << stepn;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::Down:
         if (stepn > 1) {
            stepn--;
            ss << "step width north: " << stepn;
            messages->pushMessage (ss.str ());
         } else {
            steps++;
            ss << "step width south: " << steps;
            messages->pushMessage (ss.str ());
         }
         break;
      case Event::SpeedUp:
         speed++;
         ss << "speed: " << speed;
         messages->pushMessage (ss.str ());
         break;
      case Event::SpeedDown:
         if (speed > 1) speed--;
         ss << "speed: " << speed;
         messages->pushMessage (ss.str ());
         break;
      case Event::ChangeRng:
         global->rng->cycle ();
         messages->pushMessage ("rng set to " + global->rng->name ());
         break;
      case Event::Dump:
         ss <<    "north: " << stepn << "   west: " << stepw;
         ss << "   south: " << steps << "   east: " << stepe;
         ss << "   speed: " << speed;
         messages->pushMessage (ss.str ());
         messages->pushMessage ("random number generator: " + global->rng-> name ());
         break;
   }
}

<|endoftext|>


<commit_before><commit_msg>added the while loop to main and some preliminary function definitions<commit_after><|endoftext|>


<commit_before>/***************************************************************************/
/**
**  @file Option.cpp
**  @brief Functions for class tOption
**
**  A. Desitter - March 2004
**
**  $Id: tOption.cpp,v 1.2 2004-04-01 09:57:28 childcvs Exp $
*/
/***************************************************************************/

#if !defined(HAVE_NO_NAMESPACE)
# include <iostream>
using namespace std;
#else
# include <iostream.h>
#endif
#include <stdlib.h>
#include <string.h>

#include "tOption.h"

tOption::tOption(int argc, char const * const argv[])
  : exeName(argv[0]),
    silent_mode(false), checkMeshConsistency(true),
    inputFile(0)
{
  argv++;
  while(argc > 1){
    int i = parseOptions(argv);
    argc -= i;
    argv += i;
  }
}

// Parse options one at a time. Returns number of options consumed.
int tOption::parseOptions(char const * const argv[]) {

  const char * const thisOption = argv[0];

  if (strcmp(thisOption, "--silent-mode") == 0){
    silent_mode = true;
    return 1;
  }
  if (strcmp(thisOption, "--no-check") == 0){
    checkMeshConsistency = false;
    return 1;
  }
  if (strcmp(thisOption, "--help") == 0){
    usage();
    exit(EXIT_SUCCESS);
  }
  if (thisOption[0] == '-') {
    usage();
    exit(EXIT_FAILURE);
  }
  if (inputFile != NULL)  {
    cerr << exeName << ": Several input files given." << endl;
    exit(EXIT_FAILURE);
  }

  inputFile = thisOption;
  return 1;
}

void tOption::usage() const {
  cerr
    << "Usage: " << exeName << " [options] <input file>\n"
    << " --help: display this help message.\n"
    << " --no-check: disable CheckMeshConsistency().\n"
    << " --silent-mode: silent mode.\n"
    << endl;
}
<commit_msg>(Arnaud) Abort when input file was not given.<commit_after>/***************************************************************************/
/**
**  @file Option.cpp
**  @brief Functions for class tOption
**
**  A. Desitter - March 2004
**
**  $Id: tOption.cpp,v 1.3 2004-04-01 11:02:25 childcvs Exp $
*/
/***************************************************************************/

#if !defined(HAVE_NO_NAMESPACE)
# include <iostream>
using namespace std;
#else
# include <iostream.h>
#endif
#include <stdlib.h>
#include <string.h>

#include "tOption.h"

tOption::tOption(int argc, char const * const argv[])
  : exeName(argv[0]),
    silent_mode(false), checkMeshConsistency(true),
    inputFile(0)
{
  argv++;
  while(argc > 1){
    int i = parseOptions(argv);
    argc -= i;
    argv += i;
  }
  if (inputFile ==NULL){
    usage();
    exit(EXIT_FAILURE);
  }
}

// Parse options one at a time. Returns number of options consumed.
int tOption::parseOptions(char const * const argv[]) {

  const char * const thisOption = argv[0];

  if (strcmp(thisOption, "--silent-mode") == 0){
    silent_mode = true;
    return 1;
  }
  if (strcmp(thisOption, "--no-check") == 0){
    checkMeshConsistency = false;
    return 1;
  }
  if (strcmp(thisOption, "--help") == 0){
    usage();
    exit(EXIT_SUCCESS);
  }
  if (thisOption[0] == '-') {
    usage();
    exit(EXIT_FAILURE);
  }
  if (inputFile != NULL)  {
    cerr << exeName << ": Several input files given." << endl;
    exit(EXIT_FAILURE);
  }

  inputFile = thisOption;
  return 1;
}

void tOption::usage() const {
  cerr
    << "Usage: " << exeName << " [options] <input file>\n"
    << " --help: display this help message.\n"
    << " --no-check: disable CheckMeshConsistency().\n"
    << " --silent-mode: silent mode.\n"
    << endl;
}
<|endoftext|>