<commit_before>/**
 * @author Mike Bogochow
 * @version 2.4.0, Dec 8, 2015
 *
 * @file Bidder.cpp
 *
 * Bidder class implementation
 */

#include "Bidder.h"
#include "../lib_graphs/Graph.h"
#include "../lib_graphs/Subgraph.h"
#include "../lib_graphs/SpanningTree.h"
#include "../lib_graphs/Path.h"
#include "../lib_auction/AuctionDefs.h"
#include "../lib_auction/DebugPrinter.h"

#include "MBUtils.h"

#include <boost/lexical_cast.hpp>

#include <algorithm> // std::remove
#include <chrono>
#include <thread>

Bidder::Bidder(void)
{
  g = nullptr;

  rtc = 0;

  roundNumber = 0;
  roundUpdated = false;
  winnerUpdated = false;

  id = -1;
}

Bidder::~Bidder(void)
{
  if (g != nullptr)
    delete g;
}

bool
Bidder::OnNewMail(MOOSMSG_LIST &NewMail)
{
  bool ret = AuctionMOOSApp::OnNewMail(NewMail);

  MOOSMSG_LIST::reverse_iterator p;
  for(p = NewMail.rbegin(); p != NewMail.rend(); p++)
  {
    CMOOSMsg &msg = *p;
    std::string key   = msg.GetKey();

    if (key == MVAR_BID_TARGETS && g == nullptr) // ignore if already have g
    {
      // Parse the targets from the message
      std::string sTargets = msg.GetString();
      pathFromString(sTargets, targets);

      // Add my position to the targets
      targets.push_back(startPos);

      size_t numTargets = targets.size();
      dp.dprintf(LVL_MAX_VERB, "Parsed %lu targets from %s\n", numTargets,
          sTargets.c_str());

      // Connect edges between all targets and calculate weights
      std::vector<Edge> edges;
      std::vector<mbogo_weight_t> weights;
      connectEdges(targets, edges, weights);
      dp.dprintf(LVL_MAX_VERB, "Connected %lu edges\n", edges.size());

      // Make a graph from the edges
      g = new Graph(edges.data(), edges.size(), weights.data(), numTargets);
      dp.dprintf(LVL_MAX_VERB, "Generated Graph:\n%s\n", g->toString().c_str());

      // Intialize allocated and unallocated targets
      allocated.reserve(numTargets);
      unallocated.reserve(numTargets - 1);

      allocated.push_back(numTargets - 1); // allocate my position

      for (Vertex i = 0; i < numTargets - 1; i++)
        unallocated.push_back(i);
    }
    else if (key == MVAR_BID_START)
    {
      size_t num = boost::lexical_cast<size_t>(msg.GetString());
      if (num > roundNumber) // ignore duplicate messages
      {
        if (num != roundNumber + 1)
        {
          MOOSTrace("WARNING: received round number %i while on round %i",
              num, roundNumber);
        }

        roundUpdated = true;
        roundNumber = num;
        dp.dprintf(LVL_MIN_VERB, "Got %s mail: %i\n", MVAR_BID_START.c_str(),
            num);
      }
    }
    else if (key == MVAR_BID_WINNER)
    {
      winnerUpdated = true;
      winningBid = winningBidFromString(msg.GetString());
      dp.dprintf(LVL_MIN_VERB, "Got %s mail: %s\n", MVAR_BID_WINNER.c_str(),
          winningBid);
    }
  }

  return ret;
}

bool
Bidder::Iterate(void)
{
  bool ret = AuctionMOOSApp::Iterate();

  if (g != nullptr)
  {
    if (winnerUpdated)
    { // Update info with new winner
      if (winningBid.winner == id)
      { // I won so add winning target to my allocated targets
        allocated.push_back(winningBid.target);
        rtc += winningBid.bid;
      }
      unallocated.erase(
          std::remove(unallocated.begin(), unallocated.end(),
              winningBid.target), unallocated.end());
      winnerUpdated = false;
    }

    dp.dprintf(LVL_MAX_VERB, "Number of unallocated targets remaining: %lu\n",
        unallocated.size());
    if (unallocated.size() > 0)
    {
      if (roundUpdated)
      { // Do round calculations for new round
        performBiddingRound();
        roundUpdated = false;
      }
    }
    else
    { // All rounds complete so perform final calculation and post
      assert(unallocated.size() == 0);

      performFinalCalc();

      // Exit pBidder
      doNotify("EXITED_NORMALLY", "pBidder");
      RequestQuit();
    }
  }
  else
    dp.dprintf(LVL_MAX_VERB, "Graph not initialized...\n");

  return ret;
}

void
Bidder::performBiddingRound(void)
{
  // Bidding round
  Bid currentBid = std::make_pair(MAX_VERTEX, MAX_WEIGHT);

  Graph *sub;

  // Iterate through unallocated nodes to find bid
  for (std::vector<Vertex>::iterator t = unallocated.begin();
      t != unallocated.end(); t++)
  {
    Path *path;
    SpanningTree *tree;
    mbogo_weight_t cost;
    mbogo_weight_t bid;
    std::vector<Vertex> possibleAllocation;

    possibleAllocation.reserve(allocated.size() + 1);
    possibleAllocation = allocated;
    dp.dprintf(LVL_BID, "Adding %s for possible allocation\n",
        boost::lexical_cast<std::string>(*t).c_str());
    possibleAllocation.push_back(*t);

    // Catch simple cases for efficiency
    if (possibleAllocation.size() == 1)
    {
      cost = bid = 0;
    }
    else if (possibleAllocation.size() == 2)
    {
      path = Path::fromPair(
          std::make_pair(possibleAllocation.front(),
              possibleAllocation.back()));
      cost = path->getTotalCost(g->getGraph());
      bid = cost - rtc;

      delete path;
    }
    else
    {
      sub = g->getSubgraph(possibleAllocation);
      dp.dprintf(LVL_BID, "Subgraph:\n%s\n", sub->toString().c_str());

      tree = SpanningTree::fromGraph(sub->getGraph());
      dp.dprintf(LVL_BID, "Spanning Tree:\n%s\n", tree->toString().c_str());

      path = Path::fromTree(tree);
      dp.dprintf(LVL_BID, "Path:\n%s\n", path->toString().c_str());

      cost = path->getTotalCost(g->getGraph());
      bid = cost - rtc;

      delete path;
      delete tree;
      delete sub;
    }

    dp.dprintf(LVL_BID, "bid[%lu_%s]=%s (cost-rtc)=(%s-%s)\n", roundNumber,
        boost::lexical_cast<std::string>(*t).c_str(),
        boost::lexical_cast<std::string>(bid).c_str(),
        boost::lexical_cast<std::string>(cost).c_str(),
        boost::lexical_cast<std::string>(rtc).c_str()
    );

    if (currentBid.second > bid && bid >= 0)
      currentBid = std::make_pair(*t, bid);

    dp.dprintf(LVL_BID, "cur_bid=%s:%s\n",
        boost::lexical_cast<std::string>(currentBid.first).c_str(),
        boost::lexical_cast<std::string>(currentBid.second).c_str());
  }

  assert(currentBid.first  != MAX_VERTEX
      && currentBid.second != MAX_WEIGHT);

  // Send bid to MOOSDB
  doNotify(getBidVar(id), bidToString(currentBid));
}

void
Bidder::performFinalCalc(void)
{
  // Do final cost calculation and submit path
  Subgraph *sub = Subgraph::fromGraph(g, allocated);
  SpanningTree *tree = SpanningTree::fromGraph(sub->getGraph());
  Path *path = Path::fromTree(tree);
  Point *pathPoints = new Point[path->getLength()];

  // Debug output
  DebugLevel LVL_FINAL_PATH = LVL_MID_VERB;
  if (dp.isValidLevel(LVL_FINAL_PATH)) // extra check to avoid extra work
  {
    dp.dprintf(LVL_FINAL_PATH, "Final allocated:\n");
    int count = 0;
    for (std::vector<Vertex>::iterator it = allocated.begin();
        it != allocated.end(); it++)
    {
      dp.dprintf(LVL_FINAL_PATH, "\tallocated[%i]:%s\n", count++,
          boost::lexical_cast<std::string>(*it).c_str());
    }
    dp.dprintf(LVL_FINAL_PATH, "Final path:\n%s\n", path->toString().c_str());
  }

  // Convert the path indices to those in the origin graph
  path->convertPath(sub->getParentIndices());
  dp.dprintf(LVL_FINAL_PATH, "Converted path:\n%s\n", path->toString().c_str());

  // Get the coordinates of the vertices
  path->getLocations(targets.data(), pathPoints);

  dp.dprintf(LVL_MIN_VERB, "Final cost: %s\n",
      boost::lexical_cast<std::string>(path->getTotalCost(g->getGraph())).c_str());

  // Send the path to the MOOSDB
  doNotify(getPathVar(id),
      getPathVarVal(pathToString(pathPoints, path->getLength())));

  delete sub;
  delete tree;
  delete path;
  delete pathPoints;
}

bool
Bidder::OnStartUp(void)
{
  bool ret;

  // Read the DebugOutput configuration field
  int debugLevel;
  if (!m_MissionReader.GetConfigurationParam("DebugOutput", debugLevel))
    debugLevel = LVL_OFF;
  dp.setLevel((DebugLevel)debugLevel);

  ret = AuctionMOOSApp::OnStartUp();

  // Read the AgentID configuration field
  if (ret && !m_MissionReader.GetConfigurationParam("AgentID", id))
    ret = MissingRequiredParam("AgentID");

  if (ret)
  {
    std::string tmp;
    if (!m_MissionReader.GetConfigurationParam("START_POS", tmp))
      ret = MissingRequiredParam("START_POS");
    else
      startPos = pointFromString(tmp);

    if (ret)
      RegisterVariables();
  }

  return ret;
}

bool
Bidder::OnConnectToServer(void)
{
  bool ret = AuctionMOOSApp::OnConnectToServer();
  RegisterVariables();
  return ret;
}

void
Bidder::RegisterVariables(void)
{
  m_Comms.Register(MVAR_BID_WINNER, 0);
  m_Comms.Register(MVAR_BID_START, 0);
  m_Comms.Register(MVAR_BID_TARGETS, 0);
}
<commit_msg>Adjustment so start position is not part of path<commit_after>/**
 * @author Mike Bogochow
 * @version 2.4.0, Dec 8, 2015
 *
 * @file Bidder.cpp
 *
 * Bidder class implementation
 */

#include "Bidder.h"
#include "../lib_graphs/Graph.h"
#include "../lib_graphs/Subgraph.h"
#include "../lib_graphs/SpanningTree.h"
#include "../lib_graphs/Path.h"
#include "../lib_auction/AuctionDefs.h"
#include "../lib_auction/DebugPrinter.h"

#include "MBUtils.h"

#include <boost/lexical_cast.hpp>

#include <algorithm> // std::remove
#include <chrono>
#include <thread>

Bidder::Bidder(void)
{
  g = nullptr;

  rtc = 0;

  roundNumber = 0;
  roundUpdated = false;
  winnerUpdated = false;

  id = -1;
}

Bidder::~Bidder(void)
{
  if (g != nullptr)
    delete g;
}

bool
Bidder::OnNewMail(MOOSMSG_LIST &NewMail)
{
  bool ret = AuctionMOOSApp::OnNewMail(NewMail);

  MOOSMSG_LIST::reverse_iterator p;
  for(p = NewMail.rbegin(); p != NewMail.rend(); p++)
  {
    CMOOSMsg &msg = *p;
    std::string key   = msg.GetKey();

    if (key == MVAR_BID_TARGETS && g == nullptr) // ignore if already have g
    {
      // Parse the targets from the message
      std::string sTargets = msg.GetString();
      pathFromString(sTargets, targets);

      // Add my position to the targets
      targets.push_back(startPos);

      size_t numTargets = targets.size();
      dp.dprintf(LVL_MAX_VERB, "Parsed %lu targets from %s\n", numTargets,
          sTargets.c_str());

      // Connect edges between all targets and calculate weights
      std::vector<Edge> edges;
      std::vector<mbogo_weight_t> weights;
      connectEdges(targets, edges, weights);
      dp.dprintf(LVL_MAX_VERB, "Connected %lu edges\n", edges.size());

      // Make a graph from the edges
      g = new Graph(edges.data(), edges.size(), weights.data(), numTargets);
      dp.dprintf(LVL_MAX_VERB, "Generated Graph:\n%s\n", g->toString().c_str());

      // Intialize allocated and unallocated targets
      allocated.reserve(numTargets);
      unallocated.reserve(numTargets - 1);

      allocated.push_back(numTargets - 1); // allocate my position

      for (Vertex i = 0; i < numTargets - 1; i++)
        unallocated.push_back(i);
    }
    else if (key == MVAR_BID_START)
    {
      size_t num = boost::lexical_cast<size_t>(msg.GetString());
      if (num > roundNumber) // ignore duplicate messages
      {
        if (num != roundNumber + 1)
        {
          MOOSTrace("WARNING: received round number %i while on round %i",
              num, roundNumber);
        }

        roundUpdated = true;
        roundNumber = num;
        dp.dprintf(LVL_MIN_VERB, "Got %s mail: %i\n", MVAR_BID_START.c_str(),
            num);
      }
    }
    else if (key == MVAR_BID_WINNER)
    {
      winnerUpdated = true;
      winningBid = winningBidFromString(msg.GetString());
      dp.dprintf(LVL_MIN_VERB, "Got %s mail: %s\n", MVAR_BID_WINNER.c_str(),
          winningBid);
    }
  }

  return ret;
}

bool
Bidder::Iterate(void)
{
  bool ret = AuctionMOOSApp::Iterate();

  if (g != nullptr)
  {
    if (winnerUpdated)
    { // Update info with new winner
      if (winningBid.winner == id)
      { // I won so add winning target to my allocated targets
        allocated.push_back(winningBid.target);
        rtc += winningBid.bid;
      }
      unallocated.erase(
          std::remove(unallocated.begin(), unallocated.end(),
              winningBid.target), unallocated.end());
      winnerUpdated = false;
    }

    dp.dprintf(LVL_MAX_VERB, "Number of unallocated targets remaining: %lu\n",
        unallocated.size());
    if (unallocated.size() > 0)
    {
      if (roundUpdated)
      { // Do round calculations for new round
        performBiddingRound();
        roundUpdated = false;
      }
    }
    else
    { // All rounds complete so perform final calculation and post
      assert(unallocated.size() == 0);

      performFinalCalc();

      // Exit pBidder
      doNotify("EXITED_NORMALLY", "pBidder");
      RequestQuit();
    }
  }
  else
    dp.dprintf(LVL_MAX_VERB, "Graph not initialized...\n");

  return ret;
}

void
Bidder::performBiddingRound(void)
{
  // Bidding round
  Bid currentBid = std::make_pair(MAX_VERTEX, MAX_WEIGHT);

  Graph *sub;

  // Iterate through unallocated nodes to find bid
  for (std::vector<Vertex>::iterator t = unallocated.begin();
      t != unallocated.end(); t++)
  {
    Path *path;
    SpanningTree *tree;
    mbogo_weight_t cost;
    mbogo_weight_t bid;
    std::vector<Vertex> possibleAllocation;

    possibleAllocation.reserve(allocated.size() + 1);
    possibleAllocation = allocated;
    dp.dprintf(LVL_BID, "Adding %s for possible allocation\n",
        boost::lexical_cast<std::string>(*t).c_str());
    possibleAllocation.push_back(*t);

    // Catch simple cases for efficiency
    if (possibleAllocation.size() == 1)
    {
      cost = bid = 0;
    }
    else if (possibleAllocation.size() == 2)
    {
      path = Path::fromPair(
          std::make_pair(possibleAllocation.front(),
              possibleAllocation.back()));
      cost = path->getTotalCost(g->getGraph());
      bid = cost - rtc;

      delete path;
    }
    else
    {
      sub = g->getSubgraph(possibleAllocation);
      dp.dprintf(LVL_BID, "Subgraph:\n%s\n", sub->toString().c_str());

      tree = SpanningTree::fromGraph(sub->getGraph());
      dp.dprintf(LVL_BID, "Spanning Tree:\n%s\n", tree->toString().c_str());

      path = Path::fromTree(tree);
      dp.dprintf(LVL_BID, "Path:\n%s\n", path->toString().c_str());

      cost = path->getTotalCost(g->getGraph());
      bid = cost - rtc;

      delete path;
      delete tree;
      delete sub;
    }

    dp.dprintf(LVL_BID, "bid[%lu_%s]=%s (cost-rtc)=(%s-%s)\n", roundNumber,
        boost::lexical_cast<std::string>(*t).c_str(),
        boost::lexical_cast<std::string>(bid).c_str(),
        boost::lexical_cast<std::string>(cost).c_str(),
        boost::lexical_cast<std::string>(rtc).c_str()
    );

    if (currentBid.second > bid && bid >= 0)
      currentBid = std::make_pair(*t, bid);

    dp.dprintf(LVL_BID, "cur_bid=%s:%s\n",
        boost::lexical_cast<std::string>(currentBid.first).c_str(),
        boost::lexical_cast<std::string>(currentBid.second).c_str());
  }

  assert(currentBid.first  != MAX_VERTEX
      && currentBid.second != MAX_WEIGHT);

  // Send bid to MOOSDB
  doNotify(getBidVar(id), bidToString(currentBid));
}

void
Bidder::performFinalCalc(void)
{
  // Do final cost calculation and submit path
  Subgraph *sub = Subgraph::fromGraph(g, allocated);
  SpanningTree *tree = SpanningTree::fromGraph(sub->getGraph());
  Path *path = Path::fromTree(tree);
  Point *pathPoints = new Point[path->getLength()];

  // Debug output
  DebugLevel LVL_FINAL_PATH = LVL_MID_VERB;
  if (dp.isValidLevel(LVL_FINAL_PATH)) // extra check to avoid extra work
  {
    dp.dprintf(LVL_FINAL_PATH, "Final allocated:\n");
    int count = 0;
    for (std::vector<Vertex>::iterator it = allocated.begin();
        it != allocated.end(); it++)
    {
      dp.dprintf(LVL_FINAL_PATH, "\tallocated[%i]:%s\n", count++,
          boost::lexical_cast<std::string>(*it).c_str());
    }
    dp.dprintf(LVL_FINAL_PATH, "Final path:\n%s\n", path->toString().c_str());
  }

  // Convert the path indices to those in the origin graph
  path->convertPath(sub->getParentIndices());
  dp.dprintf(LVL_FINAL_PATH, "Converted path:\n%s\n", path->toString().c_str());

  // Get the coordinates of the vertices
  path->getLocations(targets.data(), pathPoints);

  dp.dprintf(LVL_MIN_VERB, "Final cost: %s\n",
      boost::lexical_cast<std::string>(path->getTotalCost(g->getGraph())).c_str());

  // Send the path to the MOOSDB
  doNotify(getPathVar(id),
      getPathVarVal(pathToString(pathPoints + 1, path->getLength() - 1)));

  delete sub;
  delete tree;
  delete path;
  delete pathPoints;
}

bool
Bidder::OnStartUp(void)
{
  bool ret;

  // Read the DebugOutput configuration field
  int debugLevel;
  if (!m_MissionReader.GetConfigurationParam("DebugOutput", debugLevel))
    debugLevel = LVL_OFF;
  dp.setLevel((DebugLevel)debugLevel);

  ret = AuctionMOOSApp::OnStartUp();

  // Read the AgentID configuration field
  if (ret && !m_MissionReader.GetConfigurationParam("AgentID", id))
    ret = MissingRequiredParam("AgentID");

  if (ret)
  {
    std::string tmp;
    if (!m_MissionReader.GetConfigurationParam("START_POS", tmp))
      ret = MissingRequiredParam("START_POS");
    else
      startPos = pointFromString(tmp);

    if (ret)
      RegisterVariables();
  }

  return ret;
}

bool
Bidder::OnConnectToServer(void)
{
  bool ret = AuctionMOOSApp::OnConnectToServer();
  RegisterVariables();
  return ret;
}

void
Bidder::RegisterVariables(void)
{
  m_Comms.Register(MVAR_BID_WINNER, 0);
  m_Comms.Register(MVAR_BID_START, 0);
  m_Comms.Register(MVAR_BID_TARGETS, 0);
}
<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2017 by Contributors
 * \file arg_binder.cc
 * \brief Helper utility to match and bind arguments.
 */
#include <tvm/ir.h>
#include <tvm/ir_pass.h>
#include <tvm/runtime/device_api.h>
#include "./ir_util.h"
#include "./arg_binder.h"
#include "../arithmetic/compute_expr.h"

namespace tvm {
namespace ir {

void BinderAddAssert(Expr cond,
                     const std::string& arg_name,
                     std::vector<Stmt>* asserts) {
  Expr scond = Simplify(cond);
  if (is_zero(scond)) {
    LOG(FATAL) << "Bind have an unmet assertion: "
               << cond << ", " << " on argument " << arg_name;
  }
  if (!is_one(scond)) {
    std::ostringstream os;
    os << "Argument " << arg_name << " has an unsatisfied constraint";
    asserts->emplace_back(AssertStmt::make(scond, os.str(), Evaluate::make(0)));
  }
}

bool ArgBinder::Bind_(const Expr& arg,
                      const Expr& value,
                      const std::string& arg_name,
                      bool with_lets) {
  CHECK_EQ(arg.type(), value.type());
  if (const Variable* v = arg.as<Variable>()) {
    auto it = def_map_->find(v);
    if (it == def_map_->end()) {
      Var v_arg(arg.node_);
      defs_.emplace_back(v_arg);
      if (with_lets) {
        (*def_map_)[v] = arg;
        init_nest_.emplace_back(LetStmt::make(v_arg, value, Evaluate::make(0)));
      } else {
        (*def_map_)[v] = value;
      }
      return true;
    } else {
      BinderAddAssert(it->second == value, arg_name, &asserts_);
    }
  } else {
    BinderAddAssert(arg == value, arg_name, &asserts_);
  }
  return false;
}

void ArgBinder::Bind(const Expr& arg,
                     const Expr& value,
                     const std::string& arg_name,
                     bool with_let) {
  Bind_(arg, value, arg_name, with_let);
}

void ArgBinder::BindArray(const Array<Expr>& arg,
                          const Array<Expr>& value,
                          const std::string& arg_name) {
  CHECK_EQ(arg.size(), value.size())
      << "Argument " << arg_name << " array size mismatch";
  for (size_t i = 0; i < arg.size(); ++i) {
    std::ostringstream os;
    os << arg_name << "[" << i << "]";
    this->Bind(arg[i], value[i], os.str());
  }
}

void ArgBinder::BindBuffer(const Buffer& arg,
                           const Buffer& value,
                           const std::string& arg_name,
                           bool fuzzy_match) {
  CHECK_EQ(arg->scope, value->scope)
      << "Argument " << arg_name
      << " Buffer bind scope mismatch";
  CHECK_EQ(arg->dtype, value->dtype)
      << "Argument " << arg_name
      << " Buffer bind data type mismatch";
  if (value->data_alignment % arg->data_alignment != 0) {
    LOG(WARNING) << "Trying to bind buffer to another one with lower alignment requirement "
                 << " required_alignment=" << arg->data_alignment
                 << ", provided_alignment=" << value->data_alignment;
  }
  // bind pointer and offset.
  if (is_zero(arg->elem_offset)) {
    CHECK(is_zero(value->elem_offset))
        << "Trying to bind a Buffer with offset into one without offset";
  }

  this->Bind(arg->data, value->data, arg_name + ".data");
  if (Bind_(arg->elem_offset, value->elem_offset, arg_name + ".elem_offset", false)) {
    if (arg->offset_factor > 1) {
      Expr offset = value->elem_offset;
      Expr factor = make_const(offset.type(), arg->offset_factor);
      Expr zero = make_zero(offset.type());
      BinderAddAssert(offset % factor == zero, arg_name + ".elem_offset", &asserts_);
    }
  }

  if (arg->shape.size() < value->shape.size()) {
    CHECK(fuzzy_match) << "Argument " << arg_name << " size mismatch";
    size_t diff = value->shape.size() - arg->shape.size();
    for (size_t i = 0; i < diff; ++i) {
      CHECK(is_one(value->shape[i]))
          << "Argument " << arg_name << " shape mismatch"
          << arg->shape << " vs " << value->shape;
    }
    for (size_t i = 0; i < arg->shape.size(); ++i) {
      std::ostringstream os;
      os << arg_name << ".shape[" << i << "]";
      this->Bind(arg->shape[i], value->shape[i + diff], os.str());
    }
    if (value->strides.size() != 0) {
      CHECK_EQ(arg->strides.size(), arg->shape.size());
      CHECK_EQ(value->strides.size(), value->shape.size());
      for (size_t i = 0; i < arg->strides.size(); ++i) {
        std::ostringstream os;
        os << arg_name << ".strides[" << i << "]";
        this->Bind(arg->strides[i], value->strides[i + diff], os.str());
      }
    }
  } else {
    this->BindArray(arg->shape, value->shape, arg_name + ".shape");
    this->BindArray(arg->strides, value->strides, arg_name + ".strides");
  }
}

inline Expr TVMArrayGet(Type t, Var arr, intrinsic::TVMStructFieldKind kind) {
  return TVMStructGet(t, arr, 0, kind);
}

void ArgBinder::BindDLTensor(const Buffer& buffer,
                             const Expr& device_type,
                             const Expr& device_id,
                             const Var& handle,
                             const std::string& arg_name) {
  const Type tvm_shape_type = TVMShapeIndexType();
  const Type tvm_ndim_type = Int(32);
  const Stmt nop = Evaluate::make(0);
  // dimension checks
  Expr v_ndim = TVMArrayGet(tvm_ndim_type, handle, intrinsic::kArrNDim);
  Expr a_ndim = make_const(tvm_ndim_type,
                           static_cast<int64_t>(buffer->shape.size()));
  std::ostringstream ndim_err_msg;
  ndim_err_msg << arg_name
               << ".ndim is expected to equal "
               << buffer->shape.size();
  asserts_.emplace_back(AssertStmt::make(a_ndim == v_ndim, ndim_err_msg.str(), nop));
  // type checks
  Type dtype = buffer->dtype;
  std::ostringstream type_err_msg;
  type_err_msg << arg_name << ".dtype is expected to be " << dtype;
  Expr cond = (TVMArrayGet(UInt(8), handle, intrinsic::kArrTypeCode) ==
               UIntImm::make(UInt(8), dtype.code()) &&
               TVMArrayGet(UInt(8), handle, intrinsic::kArrTypeBits) ==
               UIntImm::make(UInt(8), dtype.bits()) &&
               TVMArrayGet(UInt(16), handle, intrinsic::kArrTypeLanes) ==
               UIntImm::make(UInt(16), dtype.lanes()));
  asserts_.emplace_back(AssertStmt::make(cond, type_err_msg.str(), nop));
  // data field
  if (Bind_(buffer->data, TVMArrayGet(Handle(), handle, intrinsic::kArrData),
            arg_name + ".data", true)) {
    Var vptr(buffer->data);
    def_handle_dtype_.Set(vptr, make_const(buffer->dtype, 0));
    // mark alignment of external bufs
    init_nest_.emplace_back(AttrStmt::make(
        vptr, ir::attr::storage_alignment,
        IntImm::make(Int(32), buffer->data_alignment), nop));
  }

  Var v_shape(arg_name + ".shape", Handle());
  def_handle_dtype_.Set(v_shape, make_const(tvm_shape_type, 0));
  init_nest_.emplace_back(LetStmt::make(
      v_shape, TVMArrayGet(Handle(), handle, intrinsic::kArrShape), nop));
  for (size_t k = 0; k < buffer->shape.size(); ++k) {
    std::ostringstream field_name;
    field_name << v_shape->name_hint << '[' << k << ']';
    Bind_(buffer->shape[k],
          cast(buffer->shape[k].type(),
               Load::make(tvm_shape_type, v_shape,
                          IntImm::make(Int(32), k), const_true(1))),
          field_name.str(), true);
  }
  // strides field
  Var v_strides(arg_name + ".strides", Handle());
  def_handle_dtype_.Set(v_strides, make_const(tvm_shape_type, 0));
  init_nest_.emplace_back(LetStmt::make(
      v_strides, TVMArrayGet(Handle(), handle, intrinsic::kArrStrides),
      nop));
  Expr is_null = Call::make(
    Bool(1), intrinsic::tvm_handle_is_null,
    {v_strides}, Call::PureIntrinsic);
  if (buffer->strides.size() == 0) {
    // Assert the buffer is compact
    Type stype = buffer->DefaultIndexType();
    Expr expect_stride = make_const(stype, 1);
    Array<Expr> conds;
    for (size_t i = buffer->shape.size(); i != 0; --i) {
      size_t k = i - 1;
      Expr svalue = cast(
          stype,
          Load::make(tvm_shape_type, v_strides,
                     IntImm::make(Int(32), k), const_true(1)));
      conds.push_back(expect_stride == svalue);
      expect_stride = expect_stride * buffer->shape[k];
    }
    std::ostringstream stride_err_msg;
    stride_err_msg << arg_name << ".strides:"
                   << " expected to be compact array";
    if (conds.size() != 0) {
      Stmt check =
          AssertStmt::make(arith::ComputeReduce<ir::And>(conds, Expr()),
                           stride_err_msg.str(), Evaluate::make(0));
      check = IfThenElse::make(Not::make(is_null), check, Stmt());
      init_nest_.emplace_back(Block::make(check, Evaluate::make(0)));
    }
  } else {
    std::ostringstream stride_null_err_msg;
    stride_null_err_msg << arg_name << ".strides: expected non-null strides.";
    asserts_.emplace_back(AssertStmt::make(Not::make(is_null), stride_null_err_msg.str(), nop));

    for (size_t k = 0; k < buffer->strides.size(); ++k) {
      std::ostringstream field_name;
      field_name << v_strides->name_hint << '[' << k << ']';
      Bind_(buffer->strides[k],
            cast(buffer->shape[k].type(),
                 Load::make(tvm_shape_type, v_strides,
                            IntImm::make(Int(32), k), const_true(1))),
            field_name.str(), true);
    }
  }
  // Byte_offset field.
  int data_bytes = GetVectorBytes(buffer->dtype);
  int64_t const_offset;
  if (arith::GetConst(buffer->elem_offset, &const_offset)) {
    Bind_(make_const(UInt(64), const_offset * data_bytes),
               TVMArrayGet(UInt(64), handle, intrinsic::kArrByteOffset),
          arg_name + ".byte_offset", true);
  } else {
    if (Bind_(buffer->elem_offset,
              cast(buffer->elem_offset.type(),
                   (TVMArrayGet(UInt(64), handle, intrinsic::kArrByteOffset) /
                    make_const(UInt(64), data_bytes))),
              arg_name + ".elem_offset", true)) {
      if (buffer->offset_factor > 1) {
        Expr offset = buffer->elem_offset;
        Expr factor = make_const(offset.type(), buffer->offset_factor);
        Expr zero = make_zero(offset.type());
        BinderAddAssert(offset % factor == zero, arg_name + ".elem_offset", &asserts_);
      }
    }
  }
  // device info.
  Bind_(device_type,
        TVMArrayGet(Int(32), handle, intrinsic::kArrDeviceType),
        arg_name + ".device_type", true);
  Bind_(device_id,
        TVMArrayGet(Int(32), handle, intrinsic::kArrDeviceId),
        arg_name + ".device_id", true);
}

}  // namespace ir
}  // namespace tvm
<commit_msg>Fix more type annotation (#1490)<commit_after>/*!
 *  Copyright (c) 2017 by Contributors
 * \file arg_binder.cc
 * \brief Helper utility to match and bind arguments.
 */
#include <tvm/ir.h>
#include <tvm/ir_pass.h>
#include <tvm/runtime/device_api.h>
#include "./ir_util.h"
#include "./arg_binder.h"
#include "../arithmetic/compute_expr.h"

namespace tvm {
namespace ir {

void BinderAddAssert(Expr cond,
                     const std::string& arg_name,
                     std::vector<Stmt>* asserts) {
  Expr scond = Simplify(cond);
  if (is_zero(scond)) {
    LOG(FATAL) << "Bind have an unmet assertion: "
               << cond << ", " << " on argument " << arg_name;
  }
  if (!is_one(scond)) {
    std::ostringstream os;
    os << "Argument " << arg_name << " has an unsatisfied constraint";
    asserts->emplace_back(AssertStmt::make(scond, os.str(), Evaluate::make(0)));
  }
}

bool ArgBinder::Bind_(const Expr& arg,
                      const Expr& value,
                      const std::string& arg_name,
                      bool with_lets) {
  CHECK_EQ(arg.type(), value.type());
  if (const Variable* v = arg.as<Variable>()) {
    auto it = def_map_->find(v);
    if (it == def_map_->end()) {
      Var v_arg(arg.node_);
      defs_.emplace_back(v_arg);
      if (with_lets) {
        (*def_map_)[v] = arg;
        init_nest_.emplace_back(LetStmt::make(v_arg, value, Evaluate::make(0)));
      } else {
        (*def_map_)[v] = value;
      }
      return true;
    } else {
      BinderAddAssert(it->second == value, arg_name, &asserts_);
    }
  } else {
    BinderAddAssert(arg == value, arg_name, &asserts_);
  }
  return false;
}

void ArgBinder::Bind(const Expr& arg,
                     const Expr& value,
                     const std::string& arg_name,
                     bool with_let) {
  Bind_(arg, value, arg_name, with_let);
}

void ArgBinder::BindArray(const Array<Expr>& arg,
                          const Array<Expr>& value,
                          const std::string& arg_name) {
  CHECK_EQ(arg.size(), value.size())
      << "Argument " << arg_name << " array size mismatch";
  for (size_t i = 0; i < arg.size(); ++i) {
    std::ostringstream os;
    os << arg_name << "[" << i << "]";
    this->Bind(arg[i], value[i], os.str());
  }
}

void ArgBinder::BindBuffer(const Buffer& arg,
                           const Buffer& value,
                           const std::string& arg_name,
                           bool fuzzy_match) {
  CHECK_EQ(arg->scope, value->scope)
      << "Argument " << arg_name
      << " Buffer bind scope mismatch";
  CHECK_EQ(arg->dtype, value->dtype)
      << "Argument " << arg_name
      << " Buffer bind data type mismatch";
  if (value->data_alignment % arg->data_alignment != 0) {
    LOG(WARNING) << "Trying to bind buffer to another one with lower alignment requirement "
                 << " required_alignment=" << arg->data_alignment
                 << ", provided_alignment=" << value->data_alignment;
  }
  // bind pointer and offset.
  if (is_zero(arg->elem_offset)) {
    CHECK(is_zero(value->elem_offset))
        << "Trying to bind a Buffer with offset into one without offset";
  }

  this->Bind(arg->data, value->data, arg_name + ".data");
  if (Bind_(arg->elem_offset, value->elem_offset, arg_name + ".elem_offset", false)) {
    if (arg->offset_factor > 1) {
      Expr offset = value->elem_offset;
      Expr factor = make_const(offset.type(), arg->offset_factor);
      Expr zero = make_zero(offset.type());
      BinderAddAssert(offset % factor == zero, arg_name + ".elem_offset", &asserts_);
    }
  }

  if (arg->shape.size() < value->shape.size()) {
    CHECK(fuzzy_match) << "Argument " << arg_name << " size mismatch";
    size_t diff = value->shape.size() - arg->shape.size();
    for (size_t i = 0; i < diff; ++i) {
      CHECK(is_one(value->shape[i]))
          << "Argument " << arg_name << " shape mismatch"
          << arg->shape << " vs " << value->shape;
    }
    for (size_t i = 0; i < arg->shape.size(); ++i) {
      std::ostringstream os;
      os << arg_name << ".shape[" << i << "]";
      this->Bind(arg->shape[i], value->shape[i + diff], os.str());
    }
    if (value->strides.size() != 0) {
      CHECK_EQ(arg->strides.size(), arg->shape.size());
      CHECK_EQ(value->strides.size(), value->shape.size());
      for (size_t i = 0; i < arg->strides.size(); ++i) {
        std::ostringstream os;
        os << arg_name << ".strides[" << i << "]";
        this->Bind(arg->strides[i], value->strides[i + diff], os.str());
      }
    }
  } else {
    this->BindArray(arg->shape, value->shape, arg_name + ".shape");
    this->BindArray(arg->strides, value->strides, arg_name + ".strides");
  }
}

inline Expr TVMArrayGet(Type t, Var arr, intrinsic::TVMStructFieldKind kind) {
  return TVMStructGet(t, arr, 0, kind);
}

void ArgBinder::BindDLTensor(const Buffer& buffer,
                             const Expr& device_type,
                             const Expr& device_id,
                             const Var& handle,
                             const std::string& arg_name) {
  const Type tvm_shape_type = TVMShapeIndexType();
  const Type tvm_ndim_type = Int(32);
  const Stmt nop = Evaluate::make(0);
  // dimension checks
  Expr v_ndim = TVMArrayGet(tvm_ndim_type, handle, intrinsic::kArrNDim);
  Expr a_ndim = make_const(tvm_ndim_type,
                           static_cast<int64_t>(buffer->shape.size()));
  std::ostringstream ndim_err_msg;
  ndim_err_msg << arg_name
               << ".ndim is expected to equal "
               << buffer->shape.size();
  asserts_.emplace_back(AssertStmt::make(a_ndim == v_ndim, ndim_err_msg.str(), nop));
  // type checks
  Type dtype = buffer->dtype;
  std::ostringstream type_err_msg;
  type_err_msg << arg_name << ".dtype is expected to be " << dtype;
  Expr cond = (TVMArrayGet(UInt(8), handle, intrinsic::kArrTypeCode) ==
               UIntImm::make(UInt(8), dtype.code()) &&
               TVMArrayGet(UInt(8), handle, intrinsic::kArrTypeBits) ==
               UIntImm::make(UInt(8), dtype.bits()) &&
               TVMArrayGet(UInt(16), handle, intrinsic::kArrTypeLanes) ==
               UIntImm::make(UInt(16), dtype.lanes()));
  asserts_.emplace_back(AssertStmt::make(cond, type_err_msg.str(), nop));
  // data field
  if (Bind_(buffer->data, TVMArrayGet(Handle(), handle, intrinsic::kArrData),
            arg_name + ".data", true)) {
    Var vptr(buffer->data);
    def_handle_dtype_.Set(vptr, ir::TypeAnnotation(buffer->dtype));
    // mark alignment of external bufs
    init_nest_.emplace_back(AttrStmt::make(
        vptr, ir::attr::storage_alignment,
        IntImm::make(Int(32), buffer->data_alignment), nop));
  }

  Var v_shape(arg_name + ".shape", Handle());
  def_handle_dtype_.Set(v_shape, make_const(tvm_shape_type, 0));
  init_nest_.emplace_back(LetStmt::make(
      v_shape, TVMArrayGet(Handle(), handle, intrinsic::kArrShape), nop));
  for (size_t k = 0; k < buffer->shape.size(); ++k) {
    std::ostringstream field_name;
    field_name << v_shape->name_hint << '[' << k << ']';
    Bind_(buffer->shape[k],
          cast(buffer->shape[k].type(),
               Load::make(tvm_shape_type, v_shape,
                          IntImm::make(Int(32), k), const_true(1))),
          field_name.str(), true);
  }
  // strides field
  Var v_strides(arg_name + ".strides", Handle());
  def_handle_dtype_.Set(v_strides, ir::TypeAnnotation(tvm_shape_type));
  init_nest_.emplace_back(LetStmt::make(
      v_strides, TVMArrayGet(Handle(), handle, intrinsic::kArrStrides),
      nop));
  Expr is_null = Call::make(
    Bool(1), intrinsic::tvm_handle_is_null,
    {v_strides}, Call::PureIntrinsic);
  if (buffer->strides.size() == 0) {
    // Assert the buffer is compact
    Type stype = buffer->DefaultIndexType();
    Expr expect_stride = make_const(stype, 1);
    Array<Expr> conds;
    for (size_t i = buffer->shape.size(); i != 0; --i) {
      size_t k = i - 1;
      Expr svalue = cast(
          stype,
          Load::make(tvm_shape_type, v_strides,
                     IntImm::make(Int(32), k), const_true(1)));
      conds.push_back(expect_stride == svalue);
      expect_stride = expect_stride * buffer->shape[k];
    }
    std::ostringstream stride_err_msg;
    stride_err_msg << arg_name << ".strides:"
                   << " expected to be compact array";
    if (conds.size() != 0) {
      Stmt check =
          AssertStmt::make(arith::ComputeReduce<ir::And>(conds, Expr()),
                           stride_err_msg.str(), Evaluate::make(0));
      check = IfThenElse::make(Not::make(is_null), check, Stmt());
      init_nest_.emplace_back(Block::make(check, Evaluate::make(0)));
    }
  } else {
    std::ostringstream stride_null_err_msg;
    stride_null_err_msg << arg_name << ".strides: expected non-null strides.";
    asserts_.emplace_back(AssertStmt::make(Not::make(is_null), stride_null_err_msg.str(), nop));

    for (size_t k = 0; k < buffer->strides.size(); ++k) {
      std::ostringstream field_name;
      field_name << v_strides->name_hint << '[' << k << ']';
      Bind_(buffer->strides[k],
            cast(buffer->shape[k].type(),
                 Load::make(tvm_shape_type, v_strides,
                            IntImm::make(Int(32), k), const_true(1))),
            field_name.str(), true);
    }
  }
  // Byte_offset field.
  int data_bytes = GetVectorBytes(buffer->dtype);
  int64_t const_offset;
  if (arith::GetConst(buffer->elem_offset, &const_offset)) {
    Bind_(make_const(UInt(64), const_offset * data_bytes),
               TVMArrayGet(UInt(64), handle, intrinsic::kArrByteOffset),
          arg_name + ".byte_offset", true);
  } else {
    if (Bind_(buffer->elem_offset,
              cast(buffer->elem_offset.type(),
                   (TVMArrayGet(UInt(64), handle, intrinsic::kArrByteOffset) /
                    make_const(UInt(64), data_bytes))),
              arg_name + ".elem_offset", true)) {
      if (buffer->offset_factor > 1) {
        Expr offset = buffer->elem_offset;
        Expr factor = make_const(offset.type(), buffer->offset_factor);
        Expr zero = make_zero(offset.type());
        BinderAddAssert(offset % factor == zero, arg_name + ".elem_offset", &asserts_);
      }
    }
  }
  // device info.
  Bind_(device_type,
        TVMArrayGet(Int(32), handle, intrinsic::kArrDeviceType),
        arg_name + ".device_type", true);
  Bind_(device_id,
        TVMArrayGet(Int(32), handle, intrinsic::kArrDeviceId),
        arg_name + ".device_id", true);
}

}  // namespace ir
}  // namespace tvm
<|endoftext|>


<commit_before>#include "Logbook.h"

#define LOGBOOK_FILE_NAME "LOGBOOK.TXT"

const String NEW_LINE = "\n";

Logbook::Logbook() {
}

//////////////////////
// Public interface //
//////////////////////

LogbookData* Logbook::loadLogbookData()
{
	LogbookData* logbookData = new LogbookData;

	if (SD.exists(LOGBOOK_FILE_NAME)) {
		SdFile logbookFile;
		if (logbookFile.open(LOGBOOK_FILE_NAME, O_READ)) {
			String line;
			int counter = 0;
			while (logbookFile.available()) {
				line = readStringUntil(&logbookFile, '\n');

				if (counter == 4) {
					logbookData->totalNumberOfDives = readIntFromLineEnd(line);
				} else if (counter == 5) {
					logbookData->totalDiveHours = readIntFromLineEnd(line);
				} else if (counter == 6) {
					logbookData->totalDiveMinutes = readIntFromLineEnd(line);
				} else if (counter == 7) {
					logbookData->totalMaximumDepth = readFloatFromLineEnd(line);
				} else if (counter == 8) {
					logbookData->lastDiveDateTime = readStringFromLineEnd(line);
				}
				counter++;
			}
			// The first 4 lines were skipped - this is the Summary section
			logbookData->numberOfStoredProfiles = counter - 14;
			logbookFile.close();
		}
	} else {
		//Create a new Logbook file, if it is not on the SD card with default values
		updateLogbookData(logbookData);
	}
	return logbookData;
}

void Logbook::updateLogbookData(LogbookData* logbookData)
{
	SD.remove(LOGBOOK_FILE_NAME);

	SdFile logbookFile;
	if (logbookFile.open(LOGBOOK_FILE_NAME, O_WRITE | O_CREAT | O_APPEND )) {

		logbookFile.print(F("************\n"));
		logbookFile.print(F("* Summary: *\n"));
		logbookFile.print(F("************\n"));
		logbookFile.print(NEW_LINE);
		logbookFile.print(F("Number of dives = "));
		logbookFile.print(logbookData->totalNumberOfDives);
		logbookFile.print(NEW_LINE);
		logbookFile.print(F("Logged dive hours = "));
		logbookFile.print(logbookData->totalDiveHours);
		logbookFile.print(NEW_LINE);
		logbookFile.print(F("Logged dive minutes = "));
		logbookFile.print(logbookData->totalDiveMinutes);
		logbookFile.print(NEW_LINE);
		logbookFile.print(F("Maximum depth (meter) = "));
		logbookFile.print(logbookData->totalMaximumDepth, 1);
		logbookFile.print(NEW_LINE);
		logbookFile.print(F("Last dive = "));
		logbookFile.print(logbookData->lastDiveDateTime);
		logbookFile.print(NEW_LINE);
		logbookFile.print(NEW_LINE);
		logbookFile.flush();

		logbookFile.print(F("**********\n"));
		logbookFile.print(F("* Dives: *\n"));
		logbookFile.print(F("**********\n"));
		logbookFile.print(NEW_LINE);
		logbookFile.flush();

		for (int i=1; i<=logbookData->numberOfStoredProfiles; i++) {
			logbookFile.print(getFileNameFromProfileNumber(i, false));
			logbookFile.print(NEW_LINE);
		}
		logbookFile.flush();

		logbookFile.close();
	}
}

String Logbook::getFileNameFromProfileNumber(int profileNumber, bool isTemp)
{
	//Create the name of the new profile file
	String fileName = "";
	if (isTemp) {
		fileName += "Temp";
	} else {
		fileName += "Dive";
	}

	if (profileNumber < 10) {
		fileName += "000";
	} else if (profileNumber < 100) {
		fileName += "00";
	} else if (profileNumber < 1000) {
		fileName += "0";
	}
	fileName += profileNumber;
	fileName += ".json";

	return fileName;
}

/**
 * The value true is returned for success and the value false is returned for failure.
 */
bool Logbook::createNewProfileFile(int profileNumber)
{
	//The String has to be converted into a char array, otherwise the board will reset itself
    String tempProfileFileName = getFileNameFromProfileNumber(profileNumber, true);
	char tempProfileFileNameArray[tempProfileFileName.length()+1];
	tempProfileFileName.toCharArray(tempProfileFileNameArray, tempProfileFileName.length()+1);

	return profileFile.open(tempProfileFileNameArray, O_WRITE | O_CREAT | O_APPEND );
}

void Logbook::storeProfileItem(float pressure, float depth, float temperature, int duration)
{
	StaticJsonBuffer<JSON_OBJECT_SIZE(4)> jsonBuffer;

	JsonObject& root = jsonBuffer.createObject();
	root.set("depth", depth);
	root.set("pressure", pressure, 5);
	root.set("duration", duration);
	root.set("temperature", temperature);

	root.printTo(profileFile);
	profileFile.flush();

	profileFile.print(F("\n"));
	profileFile.flush();

	if (!profileFile.sync() || profileFile.getWriteError()) {
		error("SD card write error during dive profile save!");
	}
}

void Logbook::storeDiveSummary(int profileNumber, unsigned int duration, float maxDepth, float minTemperature, float oxigenPercentage, String date, String time)
{
    profileFile.close();

	//The String has to be converted into a char array, otherwise the board will reset itself
    String tempProfileFileName = getFileNameFromProfileNumber(profileNumber, true);
	char tempProfileFileNameArray[tempProfileFileName.length()+1];
	tempProfileFileName.toCharArray(tempProfileFileNameArray, tempProfileFileName.length()+1);

	String finalProfileFileName = getFileNameFromProfileNumber(profileNumber, false);
	char finalProfileFileNameArray[finalProfileFileName.length()+1];
	finalProfileFileName.toCharArray(finalProfileFileNameArray, finalProfileFileName.length()+1);

	File finalFile;
	SdFile tempProfileFile;
	if (finalFile.open(finalProfileFileNameArray,  O_WRITE | O_CREAT | O_APPEND ) &&
		tempProfileFile.open(tempProfileFileNameArray, O_READ )) {

		finalFile.print(F("{ \"summary\":\n"));
		finalFile.flush();

		StaticJsonBuffer<JSON_OBJECT_SIZE(6)> jsonBuffer;

		JsonObject& root = jsonBuffer.createObject();
		root.set("diveDuration", duration);
		root.set("maxDepth", maxDepth);
		root.set("minTemperature", minTemperature);
		root.set("oxigenPercentage", oxigenPercentage);
		root.set("diveDate", date.c_str());
		root.set("diveTime", time.c_str());

		root.printTo(finalFile);
		finalFile.flush();

		finalFile.print(F(",\n"));
		finalFile.print(F("\"profile\": [\n"));
		finalFile.flush();

		bool isFirstline = true;
		String line;
		while (tempProfileFile.available()) {
			if (isFirstline) {
				isFirstline = false;
			} else {
				finalFile.print(",\n");
				finalFile.flush();
			}
			line = readStringUntil(&tempProfileFile, '\n');
			finalFile.print(line);
			finalFile.flush();
		}

		finalFile.print(F("\n]\n}\n"));
		finalFile.flush();

		tempProfileFile.close();
		finalFile.close();

		//Remove the temporary dive profile file
		if (SD.exists(tempProfileFileNameArray)) {
			SD.remove(tempProfileFileNameArray);
		}
	}
}

ProfileData* Logbook::loadProfileDataFromFile(String profileFileName)
{
	ProfileData* profileData = new ProfileData;

	//The String has to be converted into a char array, otherwise the board will reset itself
	char fileName[profileFileName.length()+1];
	profileFileName.toCharArray(fileName, profileFileName.length()+1);

	SdFile profileFile;
	if (profileFile.open(fileName, O_READ)) {
		Serial.print(F("Exists: "));
		Serial.println(fileName);

		String line;
		int counter = 0;
		while (profileFile.available()) {
			line = readStringUntil(&profileFile, '\n');
			line.trim();
			if (counter == 4) {
				profileData->diveDuration = readIntFromLineEnd(line);
			} else if (counter == 5) {
				profileData->maximumDepth = readFloatFromLineEnd(line);
			} else if (counter == 6) {
				profileData->minimumTemperature = readFloatFromLineEnd(line);
			} else if (counter == 7) {
				profileData->oxigenPercentage = readFloatFromLineEnd(line);
			} else if (counter == 8) {
				profileData->diveDate = readStringFromLineEnd(line);
			} else if (counter == 9) {
				profileData->diveTime = readStringFromLineEnd(line);
			}
			counter ++;
		}
		profileData->numberOfProfileItems = counter - 24;
		profileFile.close();
	}
	return profileData;
}

void Logbook::drawProfileItems(UTFT* tft, int profileNumber, int pageNumber)
{
	String profileFileName = getFileNameFromProfileNumber(profileNumber, false);
	ProfileData* profileData = loadProfileDataFromFile(profileFileName);

	//The String has to be converted into a char array, otherwise the board will reset itself
	char fileName[profileFileName.length()+1];
	profileFileName.toCharArray(fileName, profileFileName.length()+1);

	if (SD.exists(fileName)) {
		File profileFile = SD.open(fileName);
		if (profileFile) {
			//Skip the Summary section
			profileFile.seek(40);

			int firstLineNumberOnPage = 24 + ((pageNumber-1) * 460);
			int lastLineNumberOnPage = 24 + (pageNumber * 460);
			float heightUnit = 150/profileData->maximumDepth;

			tft->setColor(VGA_BLACK);
			tft->fillRect(10,160,470,315);
			tft->setColor(VGA_FUCHSIA);

			String line;
			int counter = 0;
			int positionOnPage = 0;
			while (profileFile.available()) {
				line = profileFile.readStringUntil('\n');

				if (firstLineNumberOnPage < counter && counter <= lastLineNumberOnPage) {
					tft->drawLine(10+positionOnPage, 160 + heightUnit*getDepthFromProfileLine(line), 10+positionOnPage, 310);
					positionOnPage++;
				}
				counter ++;
			}
			profileFile.close();
		}
	}
}

/////////////////////
// Private methods //
/////////////////////

float Logbook::getDepthFromProfileLine(String line)
{
	return line.substring(line.indexOf(',')+1).substring(0, line.indexOf(',')).toFloat();
}

int Logbook::readIntFromLineEnd(String line) {
	return line.substring(line.indexOf('=')+1).toInt();
}

float Logbook::readFloatFromLineEnd(String line) {
	return line.substring(line.indexOf('=')+1).toFloat();
}

String Logbook::readStringFromLineEnd(String line) {
	return line.substring(line.indexOf('=')+2);
}

String Logbook::readStringUntil(SdFile* file, char terminator)
{
  String ret;
  int c = file->read();
  while (c >= 0 && c != terminator)
  {
    ret += (char)c;
    c = file->read();
  }
  return ret;
}
<commit_msg>Logbook file handling was done in a json file.<commit_after>#include "Logbook.h"

#define LOGBOOK_FILE_NAME "Logbook.json"

const String NEW_LINE = "\n";

Logbook::Logbook() {
}

//////////////////////
// Public interface //
//////////////////////

LogbookData* Logbook::loadLogbookData()
{
	LogbookData* logbookData = new LogbookData;

	if (SD.exists(LOGBOOK_FILE_NAME)) {
		SdFile logbookFile;
		if (logbookFile.open(LOGBOOK_FILE_NAME, O_READ)) {

			char fileContent[logbookFile.fileSize()];
			int counter = 0;
			while (logbookFile.available()) {
				fileContent[counter] = logbookFile.read();
				counter++;
			}
			logbookFile.close();

			StaticJsonBuffer<JSON_OBJECT_SIZE(8)+JSON_ARRAY_SIZE(16)> jsonBuffer;
			JsonObject& root = jsonBuffer.parseObject(fileContent);

			logbookData->totalNumberOfDives = root["numberOfDives"];
			logbookData->totalDiveHours = root["loggedDiveHours"];
			logbookData->totalDiveMinutes = root["loggedDiveMinutes"];
			logbookData->totalMaximumDepth = root["maxDepth"];
			logbookData->lastDiveDateTime = root["lastDiveDate"].as<String>() + " " + root["lastDiveTime"].as<String>();
			logbookData->numberOfStoredProfiles = root["numberOfStoredProfiles"];
		}
	} else {
		//Create a new Logbook file, if it is not on the SD card with default values
		updateLogbookData(logbookData);
	}
	return logbookData;
}

void Logbook::updateLogbookData(LogbookData* logbookData)
{
	SD.remove(LOGBOOK_FILE_NAME);

	SdFile logbookFile;
	if (logbookFile.open(LOGBOOK_FILE_NAME, O_WRITE | O_CREAT | O_APPEND )) {

		StaticJsonBuffer<JSON_OBJECT_SIZE(7)> jsonBuffer;

		String lastDiveDate = "";
		String lastDiveTime = "";

		if (NULL != logbookData->lastDiveDateTime && logbookData->lastDiveDateTime.length() > 12) {
			lastDiveDate = logbookData->lastDiveDateTime.substring(0, 10);
			lastDiveTime = logbookData->lastDiveDateTime.substring(11);
		}

		JsonObject& root = jsonBuffer.createObject();
		root.set("numberOfDives", logbookData->totalNumberOfDives);
		root.set("loggedDiveHours", logbookData->totalDiveHours);
		root.set("loggedDiveMinutes", logbookData->totalDiveMinutes);
		root.set("maxDepth", logbookData->totalMaximumDepth);
		root.set("lastDiveDate", lastDiveDate);
		root.set("lastDiveTime", lastDiveTime);
		root.set("numberOfStoredProfiles", logbookData->numberOfStoredProfiles);

		root.prettyPrintTo(logbookFile);

		logbookFile.flush();
		logbookFile.close();
	}
}

String Logbook::getFileNameFromProfileNumber(int profileNumber, bool isTemp)
{
	//Create the name of the new profile file
	String fileName = "";
	if (isTemp) {
		fileName += "Temp";
	} else {
		fileName += "Dive";
	}

	if (profileNumber < 10) {
		fileName += "000";
	} else if (profileNumber < 100) {
		fileName += "00";
	} else if (profileNumber < 1000) {
		fileName += "0";
	}
	fileName += profileNumber;
	fileName += ".json";

	return fileName;
}

/**
 * The value true is returned for success and the value false is returned for failure.
 */
bool Logbook::createNewProfileFile(int profileNumber)
{
	//The String has to be converted into a char array, otherwise the board will reset itself
    String tempProfileFileName = getFileNameFromProfileNumber(profileNumber, true);
	char tempProfileFileNameArray[tempProfileFileName.length()+1];
	tempProfileFileName.toCharArray(tempProfileFileNameArray, tempProfileFileName.length()+1);

	return profileFile.open(tempProfileFileNameArray, O_WRITE | O_CREAT | O_APPEND );
}

void Logbook::storeProfileItem(float pressure, float depth, float temperature, int duration)
{
	StaticJsonBuffer<JSON_OBJECT_SIZE(4)> jsonBuffer;

	JsonObject& root = jsonBuffer.createObject();
	root.set("depth", depth);
	root.set("pressure", pressure, 5);
	root.set("duration", duration);
	root.set("temperature", temperature);

	root.printTo(profileFile);
	profileFile.flush();

	profileFile.print(F("\n"));
	profileFile.flush();

	if (!profileFile.sync() || profileFile.getWriteError()) {
		error("SD card write error during dive profile save!");
	}
}

void Logbook::storeDiveSummary(int profileNumber, unsigned int duration, float maxDepth, float minTemperature, float oxigenPercentage, String date, String time)
{
    profileFile.close();

	//The String has to be converted into a char array, otherwise the board will reset itself
    String tempProfileFileName = getFileNameFromProfileNumber(profileNumber, true);
	char tempProfileFileNameArray[tempProfileFileName.length()+1];
	tempProfileFileName.toCharArray(tempProfileFileNameArray, tempProfileFileName.length()+1);

	String finalProfileFileName = getFileNameFromProfileNumber(profileNumber, false);
	char finalProfileFileNameArray[finalProfileFileName.length()+1];
	finalProfileFileName.toCharArray(finalProfileFileNameArray, finalProfileFileName.length()+1);

	File finalFile;
	SdFile tempProfileFile;
	if (finalFile.open(finalProfileFileNameArray,  O_WRITE | O_CREAT | O_APPEND ) &&
		tempProfileFile.open(tempProfileFileNameArray, O_READ )) {

		finalFile.print(F("{ \"summary\":\n"));
		finalFile.flush();

		StaticJsonBuffer<JSON_OBJECT_SIZE(6)> jsonBuffer;

		JsonObject& root = jsonBuffer.createObject();
		root.set("diveDuration", duration);
		root.set("maxDepth", maxDepth);
		root.set("minTemperature", minTemperature);
		root.set("oxigenPercentage", oxigenPercentage);
		root.set("diveDate", date.c_str());
		root.set("diveTime", time.c_str());

		root.printTo(finalFile);
		finalFile.flush();

		finalFile.print(F(",\n"));
		finalFile.print(F("\"profile\": [\n"));
		finalFile.flush();

		bool isFirstline = true;
		String line;
		while (tempProfileFile.available()) {
			if (isFirstline) {
				isFirstline = false;
			} else {
				finalFile.print(",\n");
				finalFile.flush();
			}
			line = readStringUntil(&tempProfileFile, '\n');
			finalFile.print(line);
			finalFile.flush();
		}

		finalFile.print(F("\n]\n}\n"));
		finalFile.flush();

		tempProfileFile.close();
		finalFile.close();

		//Remove the temporary dive profile file
		if (SD.exists(tempProfileFileNameArray)) {
			SD.remove(tempProfileFileNameArray);
		}
	}
}

ProfileData* Logbook::loadProfileDataFromFile(String profileFileName)
{
	ProfileData* profileData = new ProfileData;

	//The String has to be converted into a char array, otherwise the board will reset itself
	char fileName[profileFileName.length()+1];
	profileFileName.toCharArray(fileName, profileFileName.length()+1);

	SdFile profileFile;
	if (profileFile.open(fileName, O_READ)) {
		Serial.print(F("Exists: "));
		Serial.println(fileName);

		String line;
		int counter = 0;
		while (profileFile.available()) {
			line = readStringUntil(&profileFile, '\n');
			line.trim();
			if (counter == 4) {
				profileData->diveDuration = readIntFromLineEnd(line);
			} else if (counter == 5) {
				profileData->maximumDepth = readFloatFromLineEnd(line);
			} else if (counter == 6) {
				profileData->minimumTemperature = readFloatFromLineEnd(line);
			} else if (counter == 7) {
				profileData->oxigenPercentage = readFloatFromLineEnd(line);
			} else if (counter == 8) {
				profileData->diveDate = readStringFromLineEnd(line);
			} else if (counter == 9) {
				profileData->diveTime = readStringFromLineEnd(line);
			}
			counter ++;
		}
		profileData->numberOfProfileItems = counter - 24;
		profileFile.close();
	}
	return profileData;
}

void Logbook::drawProfileItems(UTFT* tft, int profileNumber, int pageNumber)
{
	String profileFileName = getFileNameFromProfileNumber(profileNumber, false);
	ProfileData* profileData = loadProfileDataFromFile(profileFileName);

	//The String has to be converted into a char array, otherwise the board will reset itself
	char fileName[profileFileName.length()+1];
	profileFileName.toCharArray(fileName, profileFileName.length()+1);

	if (SD.exists(fileName)) {
		File profileFile = SD.open(fileName);
		if (profileFile) {
			//Skip the Summary section
			profileFile.seek(40);

			int firstLineNumberOnPage = 24 + ((pageNumber-1) * 460);
			int lastLineNumberOnPage = 24 + (pageNumber * 460);
			float heightUnit = 150/profileData->maximumDepth;

			tft->setColor(VGA_BLACK);
			tft->fillRect(10,160,470,315);
			tft->setColor(VGA_FUCHSIA);

			String line;
			int counter = 0;
			int positionOnPage = 0;
			while (profileFile.available()) {
				line = profileFile.readStringUntil('\n');

				if (firstLineNumberOnPage < counter && counter <= lastLineNumberOnPage) {
					tft->drawLine(10+positionOnPage, 160 + heightUnit*getDepthFromProfileLine(line), 10+positionOnPage, 310);
					positionOnPage++;
				}
				counter ++;
			}
			profileFile.close();
		}
	}
}

/////////////////////
// Private methods //
/////////////////////

float Logbook::getDepthFromProfileLine(String line)
{
	return line.substring(line.indexOf(',')+1).substring(0, line.indexOf(',')).toFloat();
}

int Logbook::readIntFromLineEnd(String line) {
	return line.substring(line.indexOf('=')+1).toInt();
}

float Logbook::readFloatFromLineEnd(String line) {
	return line.substring(line.indexOf('=')+1).toFloat();
}

String Logbook::readStringFromLineEnd(String line) {
	return line.substring(line.indexOf('=')+2);
}

String Logbook::readStringUntil(SdFile* file, char terminator)
{
  String ret;
  int c = file->read();
  while (c >= 0 && c != terminator)
  {
    ret += (char)c;
    c = file->read();
  }
  return ret;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "Dialog.h"

#include "../../3RVX/Logger.h"
#include "../UITranslator.h"
#include "Control.h"

Dialog::Dialog() {

}

Dialog::Dialog(HWND parent, LPCWSTR dlgTemplate) :
_parent(parent),
_template(dlgTemplate) {
//    _dlgHwnd = CreateDialogParam(
//        NULL,
//        dlgTemplate,
//        parent,
//        StaticDialogProc,
//        (LPARAM) this);

//    if (_dlgHwnd == NULL) {
//        Logger::LogLastError();
//    }

//    UITranslator::TranslateWindowText(_dlgHwnd);
}

void Dialog::Show() {
    DialogBoxParam(NULL, _template, _parent, StaticDialogProc, (LPARAM) this);
    //UITranslator::TranslateWindowText(_dlgHwnd);
}

void Dialog::Close(int result) {
    EndDialog(_dlgHwnd, result);
}

void Dialog::AddControl(Control *control) {
    if (control == nullptr) {
        return;
    }

    int id = control->ID();
    _controlMap[id] = control;
}

HWND Dialog::DialogHandle() {
    return _dlgHwnd;
}

HWND Dialog::ParentHandle() {
    return _parent;
}

INT_PTR Dialog::StaticDialogProc(
        HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    Dialog *dlg;

    if (uMsg == WM_INITDIALOG) {
        dlg = (Dialog *) lParam;
        dlg->_dlgHwnd = hwndDlg;
        SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) dlg);
    } else {
        dlg = (Dialog *) GetWindowLongPtr(hwndDlg, DWLP_USER);
        if (!dlg) {
            return FALSE;
        }
    }

    return dlg->DialogProc(hwndDlg, uMsg, wParam, lParam);
}

INT_PTR Dialog::DialogProc(HWND hwndDlg, UINT uMsg,
        WPARAM wParam, LPARAM lParam) {

    unsigned short nCode, ctrlId;

    switch (uMsg) {
    case WM_INITDIALOG:
        Initialize();
        return FALSE;

    case WM_CLOSE: {
        Close();
        break;
    }

    case WM_COMMAND: {
        nCode = HIWORD(wParam);
        ctrlId = LOWORD(wParam);
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Command(nCode);
        } else {
            return FALSE;
        }
    }

    case WM_NOTIFY: {
        NMHDR *nHdr = (NMHDR *) lParam;
        ctrlId = nHdr->idFrom;
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Notification(nHdr);
        } else {
            return FALSE;
        }
    }

    case WM_HSCROLL:
    case WM_VSCROLL: {
        WORD request = LOWORD(wParam);
        WORD position = HIWORD(wParam);
        HWND scrollHandle = (HWND) lParam;
        ctrlId = GetDlgCtrlID(scrollHandle);

        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Scroll(
                (uMsg == WM_HSCROLL), request, position);
        } else {
            return FALSE;
        }
    }
    }

    return FALSE;
}
<commit_msg>Remove old dialog construction code<commit_after>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "Dialog.h"

#include "../../3RVX/Logger.h"
#include "../UITranslator.h"
#include "Control.h"

Dialog::Dialog() {

}

Dialog::Dialog(HWND parent, LPCWSTR dlgTemplate) :
_parent(parent),
_template(dlgTemplate) {

}

void Dialog::Show() {
    DialogBoxParam(NULL, _template, _parent, StaticDialogProc, (LPARAM) this);
    //UITranslator::TranslateWindowText(_dlgHwnd);
}

void Dialog::Close(int result) {
    EndDialog(_dlgHwnd, result);
}

void Dialog::AddControl(Control *control) {
    if (control == nullptr) {
        return;
    }

    int id = control->ID();
    _controlMap[id] = control;
}

HWND Dialog::DialogHandle() {
    return _dlgHwnd;
}

HWND Dialog::ParentHandle() {
    return _parent;
}

INT_PTR Dialog::StaticDialogProc(
        HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    Dialog *dlg;

    if (uMsg == WM_INITDIALOG) {
        dlg = (Dialog *) lParam;
        dlg->_dlgHwnd = hwndDlg;
        SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) dlg);
    } else {
        dlg = (Dialog *) GetWindowLongPtr(hwndDlg, DWLP_USER);
        if (!dlg) {
            return FALSE;
        }
    }

    return dlg->DialogProc(hwndDlg, uMsg, wParam, lParam);
}

INT_PTR Dialog::DialogProc(HWND hwndDlg, UINT uMsg,
        WPARAM wParam, LPARAM lParam) {

    unsigned short nCode, ctrlId;

    switch (uMsg) {
    case WM_INITDIALOG:
        Initialize();
        return FALSE;

    case WM_CLOSE: {
        Close();
        break;
    }

    case WM_COMMAND: {
        nCode = HIWORD(wParam);
        ctrlId = LOWORD(wParam);
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Command(nCode);
        } else {
            return FALSE;
        }
    }

    case WM_NOTIFY: {
        NMHDR *nHdr = (NMHDR *) lParam;
        ctrlId = nHdr->idFrom;
        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Notification(nHdr);
        } else {
            return FALSE;
        }
    }

    case WM_HSCROLL:
    case WM_VSCROLL: {
        WORD request = LOWORD(wParam);
        WORD position = HIWORD(wParam);
        HWND scrollHandle = (HWND) lParam;
        ctrlId = GetDlgCtrlID(scrollHandle);

        if (_controlMap.count(ctrlId) > 0) {
            return _controlMap[ctrlId]->Scroll(
                (uMsg == WM_HSCROLL), request, position);
        } else {
            return FALSE;
        }
    }
    }

    return FALSE;
}
<|endoftext|>


<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */
#if !defined(DIRECTORY_ENUMERATOR_HEADER_GUARD_1357924680)
#define DIRECTORY_ENUMERATOR_HEADER_GUARD_1357924680

// Base header file.  Must be first.
#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>

#if defined(_MSC_VER)
#include <io.h>
#else
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>

extern int 	errno;

#endif

#include <functional>
#include <iterator>

#include <xalanc/PlatformSupport/XalanFileOutputStream.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>

XALAN_CPP_NAMESPACE_BEGIN

#if defined(_MSC_VER)

struct FindFileStruct : public _wfinddata_t
{

	enum eAttributes
	{
		eAttributeArchive = _A_ARCH,
		eAttributeDirectory = _A_SUBDIR,
		eAttributeHidden = _A_HIDDEN,
		eAttributeNormal = _A_NORMAL,
		eReadOnly = _A_RDONLY,
		eSystem = _A_SYSTEM
	};

public:

	/**
	 * Retrieve name of file
	 *
	 * @return file name
	 */
	const XalanDOMChar*
	getName() const
	{
		return name;
	}

	/**
	 * Determine whether file is a directory
	 *
	 * @return true if file is a directory
	 */
	bool
	isDirectory() const
	{
		return attrib & eAttributeDirectory ? true : false;
	}

	bool
	isSelfOrParent() const
	{
		if (isDirectory() == false)
		{
			return false;
		}
		else if (name[0] == '.')
		{
			if (name[1] == '\0')
			{
				return true;
			}
			else if (name[1] == '.' &&
					 name[2] == '\0')
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
};

#else

struct FindFileStruct : public dirent
{
public:

	/**
	 * Retrieve name of file
	 *
	 * @return file name
	 */
	const char* getName() const
	{
		return d_name;
	}

	/**
	 * Determine whether file is a directory
	 *
	 * @return true if file is a directory
	 */
	bool isDirectory() const
	{

		struct	stat stat_Info;
		int	retCode = stat (d_name, &stat_Info);

		if ( retCode == -1 )
		{
			typedef	XalanFileOutputStream::XalanFileOutputStreamOpenException XalanStatDirectoryException;
			throw	XalanStatDirectoryException( XalanDOMString(d_name), errno );
		}

		return S_ISDIR(stat_Info.st_mode);

	}

	bool
	isSelfOrParent() const
	{
		if (isDirectory() == false)
		{
			return false;
		}
		else if (d_name[0] == '.')
		{
			if (d_name[1] == '\0')
			{
				return true;
			}
			else if (d_name[1] == '.' &&
					 d_name[2] == '\0')
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
};

#endif

#if defined(XALAN_NO_STD_NAMESPACE)
struct DirectoryFilterPredicate : public unary_function<FindFileStruct, bool>
#else
struct DirectoryFilterPredicate : public std::unary_function<FindFileStruct, bool>
#endif
{
	result_type
	operator()(const argument_type&	theFindData) const
	{
		return theFindData.isDirectory();
	}
};

#if defined(XALAN_NO_STD_NAMESPACE)
struct FilesOnlyFilterPredicate : public unary_function<FindFileStruct, bool>
#else
struct FilesOnlyFilterPredicate : public std::unary_function<FindFileStruct, bool>
#endif
{
	result_type
	operator()(const argument_type&	theFindData) const
	{
		DirectoryFilterPredicate		theDirectoryPredicate;

		return !theDirectoryPredicate(theFindData);

	}
};

template<class OutputIteratorType,
		 class FilterPredicateType,
		 class StringType,
		 class StringConversionFunction>
void
EnumerateDirectory(
			const StringType&			theFullSearchSpec,
			OutputIteratorType			theOutputIterator,
			FilterPredicateType			theFilterPredicate,
			StringConversionFunction	theConversionFunction,
#if defined(XALAN_TEMPLATE_FUNCTION_NO_DEFAULT_PARAMETERS)
			bool						fIncludeSelfAndParent)
#else
			bool						fIncludeSelfAndParent = false)
#endif
{
#if defined(_MSC_VER)
	FindFileStruct 		theFindData;

	#ifdef _WIN64
		typedef	intptr_t	theHandleType;
	#else
		typedef	long	theHandleType;
	#endif

#pragma warning(push)
#pragma warning(disable: 4244)
	theHandleType	theSearchHandle = _wfindfirst(const_cast<wchar_t*>(theConversionFunction(theFullSearchSpec)),
										  &theFindData);
#pragma warning(pop)

	if (theSearchHandle != -1)
	{
		try
		{
			do
			{
				if ((fIncludeSelfAndParent == true || theFindData.isSelfOrParent() == false) &&
					theFilterPredicate(theFindData) == true)
				{
					*theOutputIterator = StringType(theFindData.getName());
				}
			}
			while(_wfindnext(theSearchHandle,
							 &theFindData) == 0);
		}
		catch(...)
		{
			_findclose(theSearchHandle);

			throw;
		}

		_findclose(theSearchHandle);
	}

#else

	CharVectorType	theTargetVector;

	TranscodeToLocalCodePage(theFullSearchSpec, theTargetVector, false);

	const CharVectorType::size_type		theSize = theTargetVector.size();
	int  indexSuffix=0, indexName=0;
	bool target_Dir = false;

	if (theSize > 0)
	{
		if (theTargetVector.back() == '*')
		{
			target_Dir = true;
			theTargetVector.pop_back();

			if (theSize == 1)
			{
				theTargetVector.push_back('.');
			}

		}
		else
        {
			target_Dir = false;

			while(theTargetVector.back() != '*')
			{
				theTargetVector.pop_back();
				indexSuffix++;
			}

			theTargetVector.pop_back();
			while(theTargetVector.back() != '/')
			{
				theTargetVector.pop_back();
				indexName++;
			}
		}

		theTargetVector.push_back('\0');

		const char* const	theSpec = c_str(theTargetVector);
		assert(theSpec != 0);

		XalanDOMString		theName;
		XalanDOMString		theSuffix;
		if ( !target_Dir )
		{
			int lenSpec = strlen(theSpec);
			theName = theFullSearchSpec.substr(lenSpec, indexName);
			theSuffix = theFullSearchSpec.substr(lenSpec+indexName+1, indexSuffix);
		}

		DIR* const	theDirectory = opendir(theSpec);

		if (theDirectory != 0)
		{
			chdir(theSpec);
			try
			{
				const FindFileStruct*	theEntry =
					(FindFileStruct*)readdir(theDirectory);

				while(theEntry != 0)
				{
					if ((fIncludeSelfAndParent == true || theEntry->isSelfOrParent() == false))
					{
						if (theFilterPredicate(*theEntry) == true)
						{
							if( target_Dir )
							{
								*theOutputIterator = StringType(theEntry->getName());
							}
							else
							{
								XalanDOMString	Getname = StringType(theEntry->getName());
								int	Check_1 = Getname.compare(theName);
								XalanDOMString	GetnameSuffix = Getname.substr(length(Getname)-indexSuffix, indexSuffix);
								int Check_2 = GetnameSuffix.compare(theSuffix);
								if ( Check_1 == 1 && (!Check_2) )
								{
									*theOutputIterator = Getname;
								}
							}
						}
					}
					theEntry = (FindFileStruct*)readdir(theDirectory);
				} //while
			}//try

			catch(...)
			{
				closedir(theDirectory);

				throw;
			}
			if( target_Dir )
                           chdir("..");
                         else
                           chdir("../..");
			closedir(theDirectory);
		}
	}

#endif
}

template<class OutputIteratorType,
		 class FilterPredicateType,
		 class StringType,
		 class StringConversionFunction>
void
EnumerateDirectory(
			const StringType&			theDirectory,
			const StringType&			theSearchSpec,
			OutputIteratorType			theOutputIterator,
			FilterPredicateType			theFilterPredicate,
			StringConversionFunction	theConversionFunction,
#if defined(XALAN_TEMPLATE_FUNCTION_NO_DEFAULT_PARAMETERS)
			bool						fIncludeSelfAndParent)
#else
			bool						fIncludeSelfAndParent = false)
#endif
{
	StringType	theFullSearchSpec(theDirectory);

	theFullSearchSpec += theSearchSpec;

	EnumerateDirectory(theFullSearchSpec, theOutputIterator, theFilterPredicate, theConversionFunction, fIncludeSelfAndParent);
}

#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
template<class CollectionType, class StringType>
struct DirectoryEnumeratorFunctor
{
	CollectionType
	operator()(const StringType&	theDirectory) const
	{
		CollectionType		theCollection;

		operator()(theDirectory,
			   theCollection);

		return theCollection;
	}

	void
	operator()(
		const StringType&,
		const CollectionType&) const
	{
	}
};
#else
template<class CollectionType,
  	 class StringType = XalanDOMString,
  	 class FilterPredicateType = FilesOnlyFilterPredicate,
  	 class StringConversionFunction = c_wstr_functor>
#if defined(XALAN_NO_STD_NAMESPACE)
struct DirectoryEnumeratorFunctor : public unary_function<StringType, CollectionType>
#else
struct DirectoryEnumeratorFunctor : public std::unary_function<StringType, CollectionType>
#endif
{
#if defined(XALAN_NO_STD_NAMESPACE)
	typedef unary_function<StringType, CollectionType>	BaseClassType;
#else
	typedef std::unary_function<StringType, CollectionType>	BaseClassType;
#endif

	typedef typename BaseClassType::result_type		result_type;
	typedef typename BaseClassType::argument_type	argument_type;

	explicit
	DirectoryEnumeratorFunctor(bool		fIncludeSelfAndParent = false) :
		m_includeSelfAndParent(fIncludeSelfAndParent)
	{
	}

	void
	operator()(
			const argument_type&	theFullSearchSpec,
			CollectionType&			theCollection) const
	{
		XALAN_USING_STD(back_inserter)

		EnumerateDirectory(
				theFullSearchSpec,
				XALAN_STD_QUALIFIER back_inserter(theCollection),
				m_filterPredicate,
				m_conversionFunction,
				m_includeSelfAndParent);
	}

	result_type
	operator()(const argument_type&		theFullSearchSpec) const
	{
		result_type		theCollection;

		operator()(
				theFullSearchSpec,
				theCollection);

		return theCollection;
	}

	void
	operator()(
			const argument_type&	theDirectory,
			const argument_type&	theSearchSpec,
			CollectionType&			theCollection) const
	{
		EnumerateDirectory(
				theDirectory,
				theSearchSpec,
				XALAN_STD_QUALIFIER back_inserter(theCollection),
				m_filterPredicate,
				m_conversionFunction,
				m_includeSelfAndParent);
	}

	result_type
	operator()(
			const argument_type&	theDirectory,
			const argument_type&	theSearchSpec) const
	{
		result_type		theCollection;

		operator()(
				theDirectory,
				theSearchSpec,
				theCollection);

		return theCollection;
	}

private:

	FilterPredicateType			m_filterPredicate;

	StringConversionFunction	m_conversionFunction;

	const bool					m_includeSelfAndParent;
};
#endif

XALAN_CPP_NAMESPACE_END

#endif	// DIRECTORY_ENUMERATOR_HEADER_GUARD_1357924680
<commit_msg>Fix for Tru64.<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */
#if !defined(DIRECTORY_ENUMERATOR_HEADER_GUARD_1357924680)
#define DIRECTORY_ENUMERATOR_HEADER_GUARD_1357924680

// Base header file.  Must be first.
#include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>

#if defined(_MSC_VER)
#include <io.h>
#else
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>

extern int 	errno;

#endif

#include <functional>
#include <iterator>

#include <xalanc/PlatformSupport/XalanFileOutputStream.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>

XALAN_CPP_NAMESPACE_BEGIN

#if defined(_MSC_VER)

struct FindFileStruct : public _wfinddata_t
{

	enum eAttributes
	{
		eAttributeArchive = _A_ARCH,
		eAttributeDirectory = _A_SUBDIR,
		eAttributeHidden = _A_HIDDEN,
		eAttributeNormal = _A_NORMAL,
		eReadOnly = _A_RDONLY,
		eSystem = _A_SYSTEM
	};

public:

	/**
	 * Retrieve name of file
	 *
	 * @return file name
	 */
	const XalanDOMChar*
	getName() const
	{
		return name;
	}

	/**
	 * Determine whether file is a directory
	 *
	 * @return true if file is a directory
	 */
	bool
	isDirectory() const
	{
		return attrib & eAttributeDirectory ? true : false;
	}

	bool
	isSelfOrParent() const
	{
		if (isDirectory() == false)
		{
			return false;
		}
		else if (name[0] == '.')
		{
			if (name[1] == '\0')
			{
				return true;
			}
			else if (name[1] == '.' &&
					 name[2] == '\0')
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
};

#else

struct FindFileStruct : public dirent
{
public:

	/**
	 * Retrieve name of file
	 *
	 * @return file name
	 */
	const char* getName() const
	{
		return d_name;
	}

	/**
	 * Determine whether file is a directory
	 *
	 * @return true if file is a directory
	 */
	bool isDirectory() const
	{

		struct	stat stat_Info;
		int	retCode = stat (d_name, &stat_Info);

		if ( retCode == -1 )
		{
			typedef	XalanFileOutputStream::XalanFileOutputStreamOpenException XalanStatDirectoryException;
			throw	XalanStatDirectoryException( XalanDOMString(d_name), errno );
		}

		return S_ISDIR(stat_Info.st_mode);

	}

	bool
	isSelfOrParent() const
	{
		if (isDirectory() == false)
		{
			return false;
		}
		else if (d_name[0] == '.')
		{
			if (d_name[1] == '\0')
			{
				return true;
			}
			else if (d_name[1] == '.' &&
					 d_name[2] == '\0')
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
	}
};

#endif

#if defined(XALAN_NO_STD_NAMESPACE)
struct DirectoryFilterPredicate : public unary_function<FindFileStruct, bool>
#else
struct DirectoryFilterPredicate : public std::unary_function<FindFileStruct, bool>
#endif
{
	result_type
	operator()(const argument_type&	theFindData) const
	{
		return theFindData.isDirectory();
	}
};

#if defined(XALAN_NO_STD_NAMESPACE)
struct FilesOnlyFilterPredicate : public unary_function<FindFileStruct, bool>
#else
struct FilesOnlyFilterPredicate : public std::unary_function<FindFileStruct, bool>
#endif
{
	result_type
	operator()(const argument_type&	theFindData) const
	{
		DirectoryFilterPredicate		theDirectoryPredicate;

		return !theDirectoryPredicate(theFindData);

	}
};

template<class OutputIteratorType,
		 class FilterPredicateType,
		 class StringType,
		 class StringConversionFunction>
void
EnumerateDirectory(
			const StringType&			theFullSearchSpec,
			OutputIteratorType			theOutputIterator,
			FilterPredicateType			theFilterPredicate,
			StringConversionFunction	theConversionFunction,
#if defined(XALAN_TEMPLATE_FUNCTION_NO_DEFAULT_PARAMETERS)
			bool						fIncludeSelfAndParent)
#else
			bool						fIncludeSelfAndParent = false)
#endif
{
#if defined(_MSC_VER)
	FindFileStruct 		theFindData;

	#ifdef _WIN64
		typedef	intptr_t	theHandleType;
	#else
		typedef	long	theHandleType;
	#endif

#pragma warning(push)
#pragma warning(disable: 4244)
	theHandleType	theSearchHandle = _wfindfirst(const_cast<wchar_t*>(theConversionFunction(theFullSearchSpec)),
										  &theFindData);
#pragma warning(pop)

	if (theSearchHandle != -1)
	{
		try
		{
			do
			{
				if ((fIncludeSelfAndParent == true || theFindData.isSelfOrParent() == false) &&
					theFilterPredicate(theFindData) == true)
				{
					*theOutputIterator = StringType(theFindData.getName());
				}
			}
			while(_wfindnext(theSearchHandle,
							 &theFindData) == 0);
		}
		catch(...)
		{
			_findclose(theSearchHandle);

			throw;
		}

		_findclose(theSearchHandle);
	}

#else

	CharVectorType	theTargetVector;

	TranscodeToLocalCodePage(theFullSearchSpec, theTargetVector, false);

	const CharVectorType::size_type		theSize = theTargetVector.size();
	int  indexSuffix=0, indexName=0;
	bool target_Dir = false;

	if (theSize > 0)
	{
		if (theTargetVector.back() == '*')
		{
			target_Dir = true;
			theTargetVector.pop_back();

			if (theSize == 1)
			{
				theTargetVector.push_back('.');
			}

		}
		else
        {
			target_Dir = false;

			while(theTargetVector.back() != '*')
			{
				theTargetVector.pop_back();
				indexSuffix++;
			}

			theTargetVector.pop_back();
			while(theTargetVector.back() != '/')
			{
				theTargetVector.pop_back();
				indexName++;
			}
		}

		theTargetVector.push_back('\0');

		const char* const	theSpec = c_str(theTargetVector);
		assert(theSpec != 0);

		XalanDOMString		theName;
		XalanDOMString		theSuffix;
		if ( !target_Dir )
		{
#if defined(XALAN_STRICT_ANSI_HEADERS)
            using std::strlen;
#endif

			int lenSpec = strlen(theSpec);
			theName = theFullSearchSpec.substr(lenSpec, indexName);
			theSuffix = theFullSearchSpec.substr(lenSpec+indexName+1, indexSuffix);
		}

		DIR* const	theDirectory = opendir(theSpec);

		if (theDirectory != 0)
		{
			chdir(theSpec);
			try
			{
				const FindFileStruct*	theEntry =
					(FindFileStruct*)readdir(theDirectory);

				while(theEntry != 0)
				{
					if ((fIncludeSelfAndParent == true || theEntry->isSelfOrParent() == false))
					{
						if (theFilterPredicate(*theEntry) == true)
						{
							if( target_Dir )
							{
								*theOutputIterator = StringType(theEntry->getName());
							}
							else
							{
								XalanDOMString	Getname = StringType(theEntry->getName());
								int	Check_1 = Getname.compare(theName);
								XalanDOMString	GetnameSuffix = Getname.substr(length(Getname)-indexSuffix, indexSuffix);
								int Check_2 = GetnameSuffix.compare(theSuffix);
								if ( Check_1 == 1 && (!Check_2) )
								{
									*theOutputIterator = Getname;
								}
							}
						}
					}
					theEntry = (FindFileStruct*)readdir(theDirectory);
				} //while
			}//try

			catch(...)
			{
				closedir(theDirectory);

				throw;
			}
			if( target_Dir )
                           chdir("..");
                         else
                           chdir("../..");
			closedir(theDirectory);
		}
	}

#endif
}

template<class OutputIteratorType,
		 class FilterPredicateType,
		 class StringType,
		 class StringConversionFunction>
void
EnumerateDirectory(
			const StringType&			theDirectory,
			const StringType&			theSearchSpec,
			OutputIteratorType			theOutputIterator,
			FilterPredicateType			theFilterPredicate,
			StringConversionFunction	theConversionFunction,
#if defined(XALAN_TEMPLATE_FUNCTION_NO_DEFAULT_PARAMETERS)
			bool						fIncludeSelfAndParent)
#else
			bool						fIncludeSelfAndParent = false)
#endif
{
	StringType	theFullSearchSpec(theDirectory);

	theFullSearchSpec += theSearchSpec;

	EnumerateDirectory(theFullSearchSpec, theOutputIterator, theFilterPredicate, theConversionFunction, fIncludeSelfAndParent);
}

#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
template<class CollectionType, class StringType>
struct DirectoryEnumeratorFunctor
{
	CollectionType
	operator()(const StringType&	theDirectory) const
	{
		CollectionType		theCollection;

		operator()(theDirectory,
			   theCollection);

		return theCollection;
	}

	void
	operator()(
		const StringType&,
		const CollectionType&) const
	{
	}
};
#else
template<class CollectionType,
  	 class StringType = XalanDOMString,
  	 class FilterPredicateType = FilesOnlyFilterPredicate,
  	 class StringConversionFunction = c_wstr_functor>
#if defined(XALAN_NO_STD_NAMESPACE)
struct DirectoryEnumeratorFunctor : public unary_function<StringType, CollectionType>
#else
struct DirectoryEnumeratorFunctor : public std::unary_function<StringType, CollectionType>
#endif
{
#if defined(XALAN_NO_STD_NAMESPACE)
	typedef unary_function<StringType, CollectionType>	BaseClassType;
#else
	typedef std::unary_function<StringType, CollectionType>	BaseClassType;
#endif

	typedef typename BaseClassType::result_type		result_type;
	typedef typename BaseClassType::argument_type	argument_type;

	explicit
	DirectoryEnumeratorFunctor(bool		fIncludeSelfAndParent = false) :
		m_includeSelfAndParent(fIncludeSelfAndParent)
	{
	}

	void
	operator()(
			const argument_type&	theFullSearchSpec,
			CollectionType&			theCollection) const
	{
		XALAN_USING_STD(back_inserter)

		EnumerateDirectory(
				theFullSearchSpec,
				XALAN_STD_QUALIFIER back_inserter(theCollection),
				m_filterPredicate,
				m_conversionFunction,
				m_includeSelfAndParent);
	}

	result_type
	operator()(const argument_type&		theFullSearchSpec) const
	{
		result_type		theCollection;

		operator()(
				theFullSearchSpec,
				theCollection);

		return theCollection;
	}

	void
	operator()(
			const argument_type&	theDirectory,
			const argument_type&	theSearchSpec,
			CollectionType&			theCollection) const
	{
		EnumerateDirectory(
				theDirectory,
				theSearchSpec,
				XALAN_STD_QUALIFIER back_inserter(theCollection),
				m_filterPredicate,
				m_conversionFunction,
				m_includeSelfAndParent);
	}

	result_type
	operator()(
			const argument_type&	theDirectory,
			const argument_type&	theSearchSpec) const
	{
		result_type		theCollection;

		operator()(
				theDirectory,
				theSearchSpec,
				theCollection);

		return theCollection;
	}

private:

	FilterPredicateType			m_filterPredicate;

	StringConversionFunction	m_conversionFunction;

	const bool					m_includeSelfAndParent;
};
#endif

XALAN_CPP_NAMESPACE_END

#endif	// DIRECTORY_ENUMERATOR_HEADER_GUARD_1357924680
<|endoftext|>


<commit_before>// TexturePaletteRecord.cpp

#include "flt.h"
#include "Registry.h"
#include "TexturePaletteRecord.h"

using namespace flt;

////////////////////////////////////////////////////////////////////
//
//                       TexturePaletteRecord
//
////////////////////////////////////////////////////////////////////

RegisterRecordProxy<TexturePaletteRecord> g_TexturePaletteProxy;

TexturePaletteRecord::TexturePaletteRecord()
{
}

// virtual
TexturePaletteRecord::~TexturePaletteRecord()
{
}

// virtual
void TexturePaletteRecord::endian()
{
    STexturePalette *pSTexture = (STexturePalette*)getData();

    ENDIAN( pSTexture->diIndex );
    ENDIAN( pSTexture->diX );
    ENDIAN( pSTexture->diY );
}
<commit_msg>From Brede Johansen, fix the TexturePaletteRecord::endian() to handle old flt versions (11, 12 & 13).<commit_after>// TexturePaletteRecord.cpp

#include "flt.h"
#include "Registry.h"
#include "TexturePaletteRecord.h"

using namespace flt;

////////////////////////////////////////////////////////////////////
//
//                       TexturePaletteRecord
//
////////////////////////////////////////////////////////////////////

RegisterRecordProxy<TexturePaletteRecord> g_TexturePaletteProxy;

TexturePaletteRecord::TexturePaletteRecord()
{
}

// virtual
TexturePaletteRecord::~TexturePaletteRecord()
{
}

// virtual
void TexturePaletteRecord::endian()
{

    int flightVersion = getFlightVersion();

    if (flightVersion > 13)
    {
        STexturePalette *pSTexture = (STexturePalette*)getData();

        ENDIAN( pSTexture->diIndex );
        ENDIAN( pSTexture->diX );
        ENDIAN( pSTexture->diY );
    }
    else    // version 11, 12 & 13
    {
        SOldTexturePalette *pSOldTexture = (SOldTexturePalette*)getData();

        ENDIAN( pSOldTexture->diIndex );
        ENDIAN( pSOldTexture->diX );
        ENDIAN( pSOldTexture->diY );
    }
}
<|endoftext|>