<commit_before>/* Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "MKLDNNFcLayer.h"
#include "paddle/utils/Logging.h"
#include "paddle/utils/Stat.h"

using namespace mkldnn;  // NOLINT
typedef memory::format format;
typedef inner_product_forward fc_fwd;
typedef inner_product_backward_weights fc_bwdWgt;
typedef inner_product_backward_data fc_bwdData;

namespace paddle {

REGISTER_LAYER(mkldnn_fc, MKLDNNFcLayer);

bool MKLDNNFcLayer::init(const LayerMap& layerMap,
                         const ParameterMap& parameterMap) {
  if (!MKLDNNLayer::init(layerMap, parameterMap)) {
    return false;
  }

  CHECK_EQ(inputLayers_.size(), 1) << "Only support one input layer yet";
  CHECK_EQ(inputLayers_.size(), parameters_.size());
  CHECK(!parameters_[0]->isSparse()) << "Do not support sparse yet";

  // output size, cat not be changed
  oc_ = getSize();
  oh_ = 1;
  ow_ = 1;

  // input size can not change in FC
  iLayerSize_ = inputLayers_[0]->getSize();
  CHECK_EQ(parameters_[0]->getSize(), iLayerSize_ * oc_);

  // create weight
  weight_ =
      std::unique_ptr<Weight>(new Weight(oc_, iLayerSize_, parameters_[0], 0));

  // create biases
  if (biasParameter_.get() != NULL) {
    biases_ = std::unique_ptr<Weight>(new Weight(1, oc_, biasParameter_));
  }
  return true;
}

void MKLDNNFcLayer::convertWeightsFromPaddle() {
  if (hasInitedWgt_) {
    return;
  }

  CHECK(wgtVal_) << "should have been initialized";
  bool hasNoSpatial_ = ih_ == 1 && iw_ == 1;
  auto targetDim = wgtVal_->getDims();
  auto srcFmt = hasNoSpatial_ ? memory::format::io : memory::format::ihwo;
  wgtVal_->reorderDataFrom(wgtVal_, srcFmt, targetDim);
  hasInitedWgt_ = true;
}

void MKLDNNFcLayer::convertWeightsToPaddle() {
  CHECK(wgtVal_) << "should have been initialized";
  bool hasNoSpatial_ = ih_ == 1 && iw_ == 1;
  auto targetDim = wgtVal_->getDims();
  auto dstFmt = hasNoSpatial_ ? memory::format::io : memory::format::ihwo;
  wgtVal_->reorderDataTo(wgtVal_, dstFmt, targetDim);
}

void MKLDNNFcLayer::reshape() {
  const Argument& input = getInput(0, getPrev(0)->getDeviceId());
  int batchSize = input.getBatchSize();
  if (bs_ == batchSize) {
    return;
  }
  bs_ = batchSize;
  ih_ = input.getFrameHeight();
  iw_ = input.getFrameWidth();
  if (ih_ == 0) {
    ih_ = 1;
  }
  if (iw_ == 0) {
    iw_ = 1;
  }
  CHECK_EQ(iLayerSize_, inputLayers_[0]->getSize());
  ic_ = iLayerSize_ / (ih_ * iw_);
  CHECK_EQ(size_t(ic_ * ih_ * iw_), iLayerSize_) << "not divisible";
  CHECK_EQ(size_t(oc_), getSize());
  printSizeInfo();

  // reset output
  output_.setFrameHeight(oh_);
  output_.setFrameWidth(ow_);
  resetOutput(bs_, oc_);

  // reset mkldnn forward
  resetFwd();
  needResetBwd_ = true;

  convertWeightsFromPaddle();
}

void MKLDNNFcLayer::resetFwd() {
  bool hasBias = biases_ && biases_->getW();
  const MatrixPtr& wgt = weight_->getW();
  const MatrixPtr& bias = hasBias ? biases_->getW() : nullptr;
  const MatrixPtr& out = output_.value;

  if (prevIsMKLDNN()) {
    const MatrixPtr& in = getInputValue(0);
    inVal_ = std::dynamic_pointer_cast<MKLDNNMatrix>(in);
    CHECK(inVal_) << "Input should be MKLDNNMatrix";
  } else {
    CHECK_EQ(getPrev(0)->getDeviceId(), CPU_DEVICE) << "Only support CPU yet";
    const MatrixPtr& in = getInputValue(0, CPU_DEVICE);
    inVal_ = MKLDNNMatrix::create(
        in, memory::dims{bs_, ic_, ih_, iw_}, format::nchw, engine_);
  }
  inVal_->downSpatial();
  wgtVal_ = MKLDNNMatrix::create(
      wgt, memory::dims{oc_, ic_, ih_, iw_}, format::oihw, engine_);
  wgtVal_->downSpatial();
  biasVal_ =
      hasBias ? MKLDNNMatrix::create(bias, {oc_}, format::x, engine_) : nullptr;
  outVal_ = MKLDNNMatrix::create(out, {bs_, oc_}, format::nc, engine_);

  // change original output value to mkldnn output value
  output_.value = std::dynamic_pointer_cast<Matrix>(outVal_);
  if (!nextIsMKLDNN()) {
    Argument cpuOutput;
    for (size_t i = 0; i < outputOtherDevice_.size(); i++) {
      if (outputOtherDevice_[i].deviceId == CPU_DEVICE) {
        cpuOutput = outputOtherDevice_[i];
      }
    }
    cpuOutput.setFrameHeight(output_.getFrameHeight());
    cpuOutput.setFrameWidth(output_.getFrameWidth());

    // fc cpu output value do not need convert
    cpuOutput.value = output_.value;
  }

  // create forward handle
  prop_kind pk = prop_kind::forward;
  fc_fwd::desc fwdDesc =
      hasBias ? fc_fwd::desc(pk,
                             inVal_->getMD(),
                             wgtVal_->getMD(),
                             biasVal_->getMD(),
                             outVal_->getMD())
              : fc_fwd::desc(
                    pk, inVal_->getMD(), wgtVal_->getMD(), outVal_->getMD());
  fc_fwd::primitive_desc fwdPD = fc_fwd::primitive_desc(fwdDesc, engine_);
  if (hasBias) {
    fwd_.reset(new fc_fwd(fwdPD, *inVal_, *wgtVal_, *biasVal_, *outVal_));
  } else {
    fwd_.reset(new fc_fwd(fwdPD, *inVal_, *wgtVal_, *outVal_));
  }
  printValueFormatFlow();

  pipelineFwd_.clear();
  pipelineFwd_.push_back(*fwd_);
}

void MKLDNNFcLayer::resetBwd() {
  if (!needResetBwd_) {
    return;
  }
  needResetBwd_ = false;
  bool hasBias = biases_ && biases_->getWGrad();

  /// backward weight
  CHECK(inVal_) << "Should have input value";
  const MatrixPtr& wgt = weight_->getWGrad();
  const MatrixPtr& bias = hasBias ? biases_->getWGrad() : nullptr;

  if (nextIsMKLDNN()) {
    // can not directly cast outputgrad to mkldnnmatrix,
    // since each layer can not write the inputgrad to mkldnn inputgrad.
    // So just create from matrix with outputvalue format.
    const MatrixPtr& out = getOutput(MKLDNN_DEVICE).grad;
    outGrad_ = MKLDNNMatrix::create(out, outVal_->getPD());
    // TODO: maybe need merge topdiffs
  } else {
    // TODO: merge topdiffs
    const MatrixPtr& out = getOutput(CPU_DEVICE).grad;
    // fc do not need to convert from cpu device since output always nc
    // only need create from cpu device
    outGrad_ = MKLDNNMatrix::create(out, outVal_->getPD());
  }

  wgtGrad_ = MKLDNNMatrix::create(wgt, wgtVal_->getPD());
  biasGrad_ = hasBias ? MKLDNNMatrix::create(bias, biasVal_->getPD()) : nullptr;

  // create memory primitive desc
  fc_fwd::desc fwdDesc = fc_fwd::desc(prop_kind::forward,
                                      inVal_->getMD(),
                                      wgtGrad_->getMD(),
                                      outGrad_->getMD());
  fc_fwd::primitive_desc fwdPD = fc_fwd::primitive_desc(fwdDesc, engine_);
  fc_bwdWgt::desc bwdWgtDesc =
      hasBias ? fc_bwdWgt::desc(inVal_->getMD(),
                                wgtGrad_->getMD(),
                                biasGrad_->getMD(),
                                outGrad_->getMD())
              : fc_bwdWgt::desc(
                    inVal_->getMD(), wgtGrad_->getMD(), outGrad_->getMD());
  fc_bwdWgt::primitive_desc bwdWgtPD =
      fc_bwdWgt::primitive_desc(bwdWgtDesc, engine_, fwdPD);

  if (hasBias) {
    bwdWgt_.reset(
        new fc_bwdWgt(bwdWgtPD, *inVal_, *outGrad_, *wgtGrad_, *biasGrad_));
  } else {
    bwdWgt_.reset(new fc_bwdWgt(bwdWgtPD, *inVal_, *outGrad_, *wgtGrad_));
  }
  pipelineBwd_.clear();
  pipelineBwd_.push_back(*bwdWgt_);

  /// backward data
  if (prevIsMKLDNN()) {
    const MatrixPtr& in = getInputGrad(0, MKLDNN_DEVICE);
    if (in == nullptr) {
      return;
    }
    if (getInput(0, MKLDNN_DEVICE).getAllCount() > 1) {
      // TODO: many mkldnn bots
      // add sum handle
    } else {
      inGrad_ = MKLDNNMatrix::create(in, inVal_->getPD());
    }
  } else {
    const MatrixPtr& in = getInputGrad(0, CPU_DEVICE);
    if (in == nullptr) {
      return;
    }
    if (getInput(0, CPU_DEVICE).getAllCount() > 1) {
      // TODO: many  bots
      // add sum handle
    } else {
      inGrad_ = MKLDNNMatrix::create(in, inVal_->getPD());
    }
  }

  fc_bwdData::desc bwdDataDesc =
      fc_bwdData::desc(inVal_->getMD(), wgtGrad_->getMD(), outGrad_->getMD());
  fc_bwdData::primitive_desc bwdDataPD =
      fc_bwdData::primitive_desc(bwdDataDesc, engine_, fwdPD);

  CHECK(wgtVal_) << "Should have weight memory";
  bwdData_.reset(new fc_bwdData(bwdDataPD, *outGrad_, *wgtVal_, *inGrad_));
  printGradFormatFlow();
  pipelineBwd_.push_back(*bwdData_);
}

void MKLDNNFcLayer::forward(PassType passType) {
  Layer::forward(passType);
  reshape();

  {
    REGISTER_TIMER_INFO("mkldnn_FwdTimer", getName().c_str());
    syncInputValue();

    // just submit forward pipeline
    stream_->submit(pipelineFwd_);
  }

  /* activation */ {
    REGISTER_TIMER_INFO("FwActTimer", getName().c_str());
    forwardActivation();
  }
}

void MKLDNNFcLayer::backward(const UpdateCallback& callback) {
  /* Do derivation */ {
    REGISTER_TIMER_INFO("BpActTimer", getName().c_str());
    backwardActivation();
  }

  {
    REGISTER_TIMER_INFO("mkldnn_bwdTimer", getName().c_str());
    resetBwd();

    syncOutputGrad();
    // just sumbmit backward pipeline
    stream_->submit(pipelineBwd_);
  }

  {
    REGISTER_TIMER_INFO("WeightUpdate", getName().c_str());
    weight_->getParameterPtr()->incUpdate(callback);
    if (biases_ && biases_->getWGrad()) {
      biases_->getParameterPtr()->incUpdate(callback);
    }
  }
}
}  // namespace paddle
<commit_msg>add todo<commit_after>/* Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "MKLDNNFcLayer.h"
#include "paddle/utils/Logging.h"
#include "paddle/utils/Stat.h"

using namespace mkldnn;  // NOLINT
typedef memory::format format;
typedef inner_product_forward fc_fwd;
typedef inner_product_backward_weights fc_bwdWgt;
typedef inner_product_backward_data fc_bwdData;

namespace paddle {

REGISTER_LAYER(mkldnn_fc, MKLDNNFcLayer);

bool MKLDNNFcLayer::init(const LayerMap& layerMap,
                         const ParameterMap& parameterMap) {
  if (!MKLDNNLayer::init(layerMap, parameterMap)) {
    return false;
  }

  CHECK_EQ(inputLayers_.size(), 1) << "Only support one input layer yet";
  CHECK_EQ(inputLayers_.size(), parameters_.size());
  CHECK(!parameters_[0]->isSparse()) << "Do not support sparse yet";

  // output size, cat not be changed
  oc_ = getSize();
  oh_ = 1;
  ow_ = 1;

  // input size can not change in FC
  iLayerSize_ = inputLayers_[0]->getSize();
  CHECK_EQ(parameters_[0]->getSize(), iLayerSize_ * oc_);

  // create weight
  weight_ =
      std::unique_ptr<Weight>(new Weight(oc_, iLayerSize_, parameters_[0], 0));

  // create biases
  if (biasParameter_.get() != NULL) {
    biases_ = std::unique_ptr<Weight>(new Weight(1, oc_, biasParameter_));
  }
  return true;
}

void MKLDNNFcLayer::convertWeightsFromPaddle() {
  if (hasInitedWgt_) {
    return;
  }

  CHECK(wgtVal_) << "should have been initialized";
  bool hasNoSpatial_ = ih_ == 1 && iw_ == 1;
  auto targetDim = wgtVal_->getDims();
  auto srcFmt = hasNoSpatial_ ? memory::format::io : memory::format::ihwo;
  wgtVal_->reorderDataFrom(wgtVal_, srcFmt, targetDim);
  hasInitedWgt_ = true;
}

void MKLDNNFcLayer::convertWeightsToPaddle() {
  CHECK(wgtVal_) << "should have been initialized";
  bool hasNoSpatial_ = ih_ == 1 && iw_ == 1;
  auto targetDim = wgtVal_->getDims();
  auto dstFmt = hasNoSpatial_ ? memory::format::io : memory::format::ihwo;
  wgtVal_->reorderDataTo(wgtVal_, dstFmt, targetDim);
}

void MKLDNNFcLayer::reshape() {
  const Argument& input = getInput(0, getPrev(0)->getDeviceId());
  int batchSize = input.getBatchSize();
  if (bs_ == batchSize) {
    return;
  }
  bs_ = batchSize;
  ih_ = input.getFrameHeight();
  iw_ = input.getFrameWidth();
  if (ih_ == 0) {
    ih_ = 1;
  }
  if (iw_ == 0) {
    iw_ = 1;
  }
  CHECK_EQ(iLayerSize_, inputLayers_[0]->getSize());
  ic_ = iLayerSize_ / (ih_ * iw_);
  CHECK_EQ(size_t(ic_ * ih_ * iw_), iLayerSize_) << "not divisible";
  CHECK_EQ(size_t(oc_), getSize());
  printSizeInfo();

  // reset output
  output_.setFrameHeight(oh_);
  output_.setFrameWidth(ow_);
  resetOutput(bs_, oc_);

  // reset mkldnn forward
  resetFwd();
  needResetBwd_ = true;

  convertWeightsFromPaddle();
}

void MKLDNNFcLayer::resetFwd() {
  bool hasBias = biases_ && biases_->getW();
  const MatrixPtr& wgt = weight_->getW();
  const MatrixPtr& bias = hasBias ? biases_->getW() : nullptr;
  const MatrixPtr& out = output_.value;

  if (prevIsMKLDNN()) {
    const MatrixPtr& in = getInputValue(0);
    inVal_ = std::dynamic_pointer_cast<MKLDNNMatrix>(in);
    CHECK(inVal_) << "Input should be MKLDNNMatrix";
  } else {
    CHECK_EQ(getPrev(0)->getDeviceId(), CPU_DEVICE) << "Only support CPU yet";
    const MatrixPtr& in = getInputValue(0, CPU_DEVICE);
    inVal_ = MKLDNNMatrix::create(
        in, memory::dims{bs_, ic_, ih_, iw_}, format::nchw, engine_);
  }
  inVal_->downSpatial();
  wgtVal_ = MKLDNNMatrix::create(
      wgt, memory::dims{oc_, ic_, ih_, iw_}, format::oihw, engine_);
  wgtVal_->downSpatial();
  biasVal_ =
      hasBias ? MKLDNNMatrix::create(bias, {oc_}, format::x, engine_) : nullptr;
  outVal_ = MKLDNNMatrix::create(out, {bs_, oc_}, format::nc, engine_);

  // change original output value to mkldnn output value
  output_.value = std::dynamic_pointer_cast<Matrix>(outVal_);
  if (!nextIsMKLDNN()) {
    Argument cpuOutput;
    for (size_t i = 0; i < outputOtherDevice_.size(); i++) {
      if (outputOtherDevice_[i].deviceId == CPU_DEVICE) {
        cpuOutput = outputOtherDevice_[i];
      }
    }
    cpuOutput.setFrameHeight(output_.getFrameHeight());
    cpuOutput.setFrameWidth(output_.getFrameWidth());

    // fc cpu output value do not need convert
    cpuOutput.value = output_.value;
  }

  // create forward handle
  prop_kind pk = prop_kind::forward;
  fc_fwd::desc fwdDesc =
      hasBias ? fc_fwd::desc(pk,
                             inVal_->getMD(),
                             wgtVal_->getMD(),
                             biasVal_->getMD(),
                             outVal_->getMD())
              : fc_fwd::desc(
                    pk, inVal_->getMD(), wgtVal_->getMD(), outVal_->getMD());
  fc_fwd::primitive_desc fwdPD = fc_fwd::primitive_desc(fwdDesc, engine_);
  if (hasBias) {
    fwd_.reset(new fc_fwd(fwdPD, *inVal_, *wgtVal_, *biasVal_, *outVal_));
  } else {
    fwd_.reset(new fc_fwd(fwdPD, *inVal_, *wgtVal_, *outVal_));
  }
  printValueFormatFlow();

  pipelineFwd_.clear();
  pipelineFwd_.push_back(*fwd_);
}

void MKLDNNFcLayer::resetBwd() {
  if (!needResetBwd_) {
    return;
  }
  needResetBwd_ = false;
  bool hasBias = biases_ && biases_->getWGrad();

  /// backward weight
  CHECK(inVal_) << "Should have input value";
  const MatrixPtr& wgt = weight_->getWGrad();
  const MatrixPtr& bias = hasBias ? biases_->getWGrad() : nullptr;

  // TODO(TJ): merge topdiffs
  if (nextIsMKLDNN()) {
    // can not directly cast outputgrad to mkldnnmatrix,
    // since each layer can not write the inputgrad to mkldnn inputgrad.
    // So just create from matrix with outputvalue format.
    const MatrixPtr& out = getOutput(MKLDNN_DEVICE).grad;
    outGrad_ = MKLDNNMatrix::create(out, outVal_->getPD());
  } else {
    const MatrixPtr& out = getOutput(CPU_DEVICE).grad;
    // fc do not need to convert from cpu device since output always nc
    // only need create from cpu device
    outGrad_ = MKLDNNMatrix::create(out, outVal_->getPD());
  }

  wgtGrad_ = MKLDNNMatrix::create(wgt, wgtVal_->getPD());
  biasGrad_ = hasBias ? MKLDNNMatrix::create(bias, biasVal_->getPD()) : nullptr;

  // create memory primitive desc
  fc_fwd::desc fwdDesc = fc_fwd::desc(prop_kind::forward,
                                      inVal_->getMD(),
                                      wgtGrad_->getMD(),
                                      outGrad_->getMD());
  fc_fwd::primitive_desc fwdPD = fc_fwd::primitive_desc(fwdDesc, engine_);
  fc_bwdWgt::desc bwdWgtDesc =
      hasBias ? fc_bwdWgt::desc(inVal_->getMD(),
                                wgtGrad_->getMD(),
                                biasGrad_->getMD(),
                                outGrad_->getMD())
              : fc_bwdWgt::desc(
                    inVal_->getMD(), wgtGrad_->getMD(), outGrad_->getMD());
  fc_bwdWgt::primitive_desc bwdWgtPD =
      fc_bwdWgt::primitive_desc(bwdWgtDesc, engine_, fwdPD);

  if (hasBias) {
    bwdWgt_.reset(
        new fc_bwdWgt(bwdWgtPD, *inVal_, *outGrad_, *wgtGrad_, *biasGrad_));
  } else {
    bwdWgt_.reset(new fc_bwdWgt(bwdWgtPD, *inVal_, *outGrad_, *wgtGrad_));
  }
  pipelineBwd_.clear();
  pipelineBwd_.push_back(*bwdWgt_);

  /// backward data
  if (prevIsMKLDNN()) {
    const MatrixPtr& in = getInputGrad(0, MKLDNN_DEVICE);
    if (in == nullptr) {
      return;
    }
    if (getInput(0, MKLDNN_DEVICE).getAllCount() > 1) {
      // TODO(TJ): use outputMaps_ ways when merge topdiff done
    } else {
      inGrad_ = MKLDNNMatrix::create(in, inVal_->getPD());
    }
  } else {
    const MatrixPtr& in = getInputGrad(0, CPU_DEVICE);
    if (in == nullptr) {
      return;
    }
    if (getInput(0, CPU_DEVICE).getAllCount() > 1) {
      // TODO(TJ): use outputMaps_ ways when merge topdiff done
    } else {
      inGrad_ = MKLDNNMatrix::create(in, inVal_->getPD());
    }
  }

  fc_bwdData::desc bwdDataDesc =
      fc_bwdData::desc(inVal_->getMD(), wgtGrad_->getMD(), outGrad_->getMD());
  fc_bwdData::primitive_desc bwdDataPD =
      fc_bwdData::primitive_desc(bwdDataDesc, engine_, fwdPD);

  CHECK(wgtVal_) << "Should have weight memory";
  bwdData_.reset(new fc_bwdData(bwdDataPD, *outGrad_, *wgtVal_, *inGrad_));
  printGradFormatFlow();
  pipelineBwd_.push_back(*bwdData_);
}

void MKLDNNFcLayer::forward(PassType passType) {
  Layer::forward(passType);
  reshape();

  {
    REGISTER_TIMER_INFO("mkldnn_FwdTimer", getName().c_str());
    syncInputValue();

    // just submit forward pipeline
    stream_->submit(pipelineFwd_);
  }

  /* activation */ {
    REGISTER_TIMER_INFO("FwActTimer", getName().c_str());
    forwardActivation();
  }
}

void MKLDNNFcLayer::backward(const UpdateCallback& callback) {
  /* Do derivation */ {
    REGISTER_TIMER_INFO("BpActTimer", getName().c_str());
    backwardActivation();
  }

  {
    REGISTER_TIMER_INFO("mkldnn_bwdTimer", getName().c_str());
    resetBwd();

    syncOutputGrad();
    // just sumbmit backward pipeline
    stream_->submit(pipelineBwd_);
  }

  {
    REGISTER_TIMER_INFO("WeightUpdate", getName().c_str());
    weight_->getParameterPtr()->incUpdate(callback);
    if (biases_ && biases_->getWGrad()) {
      biases_->getParameterPtr()->incUpdate(callback);
    }
  }
}
}  // namespace paddle
<|endoftext|>


<commit_before>/*!
  @file DCDWriter.hpp
  @brief definition of a class that writes dcd file.

  DCDWriter writes DCDData into DCD file. this can write only one snapshot
  step by step. But, when you write trajectory step by step, the consistency
  between header data and trajectory size will not be guaranteed.

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-06-09 15:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_DCD_WRITER
#define COFFEE_MILL_DCD_WRITER
#include "DCDData.hpp"
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cstring>

namespace mill
{

//! DCD writer class.
/*!
 *  DCDWriter writes not only entire DCDData but also many Snapshots into dcd file.
 */
template <typename vectorT>
class DCDWriter
{
  public:
    using vector_type     = vectorT;
    using data_type       = DCDData<vector_type>;
    using header_type     = typename data_type::header_type;
    using snapshot_type   = typename data_type::snapshot_type;
    using trajectory_type = typename data_type::trajectory_type;

  public:

    DCDWriter(){}
    ~DCDWriter() = default;

    void write(const std::string& fname, const data_type& dcd);
    void write(std::ostream& os,         const data_type& dcd);
    void write_header    (const std::string& fname, const header_type& dcd);
    void write_header    (std::ostream& os,         const header_type& dcd);
    void write_trajectory(const std::string& fname, const trajectory_type& traj);
    void write_trajectory(std::ostream& dcdfile,    const trajectory_type& traj);
    void write_snapshot  (const std::string& fname, const snapshot_type& snapshot);
    void write_snapshot  (std::ostream& os,         const snapshot_type& snapshot);

  private:

    void write_head_block1(std::ostream& dcdfile, const header_type& header);
    void write_head_block2(std::ostream& dcdfile, const header_type& header);
    void write_head_block3(std::ostream& dcdfile, const header_type& header);
    void write_coord      (std::ostream& dcdfile, const std::vector<float>& coord);

  private:

    static constexpr int size_int   = sizeof(int);
    static constexpr int size_float = sizeof(float);
    static constexpr int size_char  = sizeof(char);
};

template <typename vectorT>
void DCDWriter<vectorT>::write(const std::string& filename, const data_type& dcd)
{
    std::ifstream ifs(filename);
    if(not ifs.good()) throw std::runtime_error("file open error: " + filename);
    this->write(ifs, dcd);
    ifs.close();
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write(std::ostream& os, const data_type& dcd)
{
    this->write_header(os, dcd.header());
    this->write_trajectory(os, dcd.traj());

#ifdef COFFEE_MILL_DEBUG
    std::cout << "Info   : write_file completed" << std::endl;
#endif

    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_header(
        const std::string& fname, const header_type& dcd)
{
    std::ofstream dcdfile(fname, std::ios::binary);
    if(!dcdfile.good())
        throw std::runtime_error("file open error: " + fname);

    write_header(dcdfile, dcd);
    dcdfile.close();

    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_header(std::ostream& os, const header_type& dcd)
{
    write_head_block1(os, dcd);
    write_head_block2(os, dcd);
    write_head_block3(os, dcd);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_head_block1(
        std::ostream& os, const header_type& data)
{
    int wrote(0);
    const int bytes(84);
    os.write(reinterpret_cast<const char*>(&bytes), size_int);

    const char* signeture = data.signeture.c_str();
    os.write(signeture, size_char*4);
    wrote += size_char*4;

    os.write(reinterpret_cast<const char*>(&(data.nset)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.istart)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.nstep_save)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.nstep)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.nunit)), size_int);
    wrote += size_int;

    // null data
    const int fill_zero(0);
    for(int i(0); i<4; ++i)
    {
        os.write(reinterpret_cast<const char*>(&fill_zero), size_int);
        wrote += size_int;
    }

    const float dt = static_cast<float>(data.delta_t);
    os.write(reinterpret_cast<const char*>(&dt), size_float);
    wrote += size_float;

    // null data
    for(int i(0); i<9; ++i)
    {
        os.write(reinterpret_cast<const char*>(&fill_zero), size_int);
        wrote += size_int;
    }

    os.write(reinterpret_cast<const char*>(&(data.verCHARMM)), size_int);
    wrote += size_int;

    if(wrote != bytes)
        throw std::invalid_argument("byte information error");

    os.write(reinterpret_cast<const char*>(&bytes), size_int);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_head_block2(std::ostream& os, const header_type& data)
{
    if(data.comment.empty())
    {
        const int lines(1);
        const int bytes(84);
        int wrote(0);
        const char* default_comment =
            "==================== This file is modified using Coffee-mill ===================";

        os.write(reinterpret_cast<const char*>(&bytes), size_int);
        os.write(reinterpret_cast<const char*>(&lines), size_int);
        wrote += size_int;
        os << default_comment;
        wrote += 80;
        if(wrote != bytes)
            throw std::logic_error("internal byte information error");
        os.write(reinterpret_cast<const char*>(&bytes), size_int);
    }
    else
    {
        const int lines(data.comment.size());
        const int bytes(4 + 80*lines);
        int wrote(0);

        os.write(reinterpret_cast<const char*>(&bytes), size_int);

        os.write(reinterpret_cast<const char*>(&lines), size_int);
        wrote += size_int;

        for(auto iter = data.comment.cbegin(); iter != data.comment.cend(); ++iter)
        {
            os << iter->c_str();
            wrote += size_char*80;
        }

        if(wrote != bytes)
            throw std::logic_error("internal byte information error");

        os.write(reinterpret_cast<const char*>(&bytes), size_int);
    }
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_head_block3(
        std::ostream& dcdfile, const header_type& data)
{
    int bytes(size_int);
    dcdfile.write(reinterpret_cast<const char*>(&bytes), size_int);
    dcdfile.write(reinterpret_cast<const char*>(&(data.nparticle)), size_int);
    dcdfile.write(reinterpret_cast<const char*>(&bytes), size_int);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_trajectory(
        const std::string& fname, const trajectory_type& traj)
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    this->write_trajectory(ifs, traj);
    ifs.close();
    return ;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_trajectory(
        std::ostream& os, const trajectory_type& traj)
{
    for(auto iter = traj.cbegin(); iter != traj.cend(); ++iter)
        this->write_snapshot(os, *iter);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_snapshot(
        const std::string& fname, const snapshot_type& snapshot)
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    this->write_snapshot(ifs, snapshot);
    ifs.close();
    return ;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_snapshot(
        std::ostream& os, const snapshot_type& snapshot)
{
    std::vector<float> x(snapshot.size());
    std::vector<float> y(snapshot.size());
    std::vector<float> z(snapshot.size());
    std::size_t counter(0);
    for(auto iter = snapshot.cbegin(); iter != snapshot.cend(); ++iter)
    {
        x[counter] = static_cast<float>((*iter)[0]);
        y[counter] = static_cast<float>((*iter)[1]);
        z[counter] = static_cast<float>((*iter)[2]);
        ++counter;
    }

    this->write_coord(os, x);
    this->write_coord(os, y);
    this->write_coord(os, z);

    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_coord(
        std::ostream& os, const std::vector<float>& coord)
{
    int size(coord.size());
    int bytes(size * size_float);
    os.write(reinterpret_cast<const char*>(&bytes), size_int);

    for(auto iter = coord.cbegin(); iter != coord.cend(); ++iter)
    {
        const float tmp = *iter;
        os.write(reinterpret_cast<const char*>(&(tmp)), size_float);
    }

    os.write(reinterpret_cast<const char*>(&bytes), size_int);
    return;
}

}//mill

#endif //COFFEE_MILL_DCD_WRITER
<commit_msg>fix output stream type<commit_after>/*!
  @file DCDWriter.hpp
  @brief definition of a class that writes dcd file.

  DCDWriter writes DCDData into DCD file. this can write only one snapshot
  step by step. But, when you write trajectory step by step, the consistency
  between header data and trajectory size will not be guaranteed.

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-06-09 15:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_DCD_WRITER
#define COFFEE_MILL_DCD_WRITER
#include "DCDData.hpp"
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cstring>

namespace mill
{

//! DCD writer class.
/*!
 *  DCDWriter writes not only entire DCDData but also many Snapshots into dcd file.
 */
template <typename vectorT>
class DCDWriter
{
  public:
    using vector_type     = vectorT;
    using data_type       = DCDData<vector_type>;
    using header_type     = typename data_type::header_type;
    using snapshot_type   = typename data_type::snapshot_type;
    using trajectory_type = typename data_type::trajectory_type;

  public:

    DCDWriter(){}
    ~DCDWriter() = default;

    void write(const std::string& fname, const data_type& dcd);
    void write(std::ostream& os,         const data_type& dcd);
    void write_header    (const std::string& fname, const header_type& dcd);
    void write_header    (std::ostream& os,         const header_type& dcd);
    void write_trajectory(const std::string& fname, const trajectory_type& traj);
    void write_trajectory(std::ostream& dcdfile,    const trajectory_type& traj);
    void write_snapshot  (const std::string& fname, const snapshot_type& snapshot);
    void write_snapshot  (std::ostream& os,         const snapshot_type& snapshot);

  private:

    void write_head_block1(std::ostream& dcdfile, const header_type& header);
    void write_head_block2(std::ostream& dcdfile, const header_type& header);
    void write_head_block3(std::ostream& dcdfile, const header_type& header);
    void write_coord      (std::ostream& dcdfile, const std::vector<float>& coord);

  private:

    static constexpr int size_int   = sizeof(int);
    static constexpr int size_float = sizeof(float);
    static constexpr int size_char  = sizeof(char);
};

template <typename vectorT>
void DCDWriter<vectorT>::write(const std::string& filename, const data_type& dcd)
{
    std::ofstream ifs(filename);
    if(not ifs.good()) throw std::runtime_error("file open error: " + filename);
    this->write(ifs, dcd);
    ifs.close();
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write(std::ostream& os, const data_type& dcd)
{
    this->write_header(os, dcd.header());
    this->write_trajectory(os, dcd.traj());

#ifdef COFFEE_MILL_DEBUG
    std::cout << "Info   : write_file completed" << std::endl;
#endif

    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_header(
        const std::string& fname, const header_type& dcd)
{
    std::ofstream dcdfile(fname, std::ios::binary);
    if(!dcdfile.good())
        throw std::runtime_error("file open error: " + fname);

    write_header(dcdfile, dcd);
    dcdfile.close();

    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_header(std::ostream& os, const header_type& dcd)
{
    write_head_block1(os, dcd);
    write_head_block2(os, dcd);
    write_head_block3(os, dcd);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_head_block1(
        std::ostream& os, const header_type& data)
{
    int wrote(0);
    const int bytes(84);
    os.write(reinterpret_cast<const char*>(&bytes), size_int);

    const char* signeture = data.signeture.c_str();
    os.write(signeture, size_char*4);
    wrote += size_char*4;

    os.write(reinterpret_cast<const char*>(&(data.nset)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.istart)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.nstep_save)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.nstep)), size_int);
    wrote += size_int;

    os.write(reinterpret_cast<const char*>(&(data.nunit)), size_int);
    wrote += size_int;

    // null data
    const int fill_zero(0);
    for(int i(0); i<4; ++i)
    {
        os.write(reinterpret_cast<const char*>(&fill_zero), size_int);
        wrote += size_int;
    }

    const float dt = static_cast<float>(data.delta_t);
    os.write(reinterpret_cast<const char*>(&dt), size_float);
    wrote += size_float;

    // null data
    for(int i(0); i<9; ++i)
    {
        os.write(reinterpret_cast<const char*>(&fill_zero), size_int);
        wrote += size_int;
    }

    os.write(reinterpret_cast<const char*>(&(data.verCHARMM)), size_int);
    wrote += size_int;

    if(wrote != bytes)
        throw std::invalid_argument("byte information error");

    os.write(reinterpret_cast<const char*>(&bytes), size_int);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_head_block2(std::ostream& os, const header_type& data)
{
    if(data.comment.empty())
    {
        const int lines(1);
        const int bytes(84);
        int wrote(0);
        const char* default_comment =
            "==================== This file is modified using Coffee-mill ===================";

        os.write(reinterpret_cast<const char*>(&bytes), size_int);
        os.write(reinterpret_cast<const char*>(&lines), size_int);
        wrote += size_int;
        os << default_comment;
        wrote += 80;
        if(wrote != bytes)
            throw std::logic_error("internal byte information error");
        os.write(reinterpret_cast<const char*>(&bytes), size_int);
    }
    else
    {
        const int lines(data.comment.size());
        const int bytes(4 + 80*lines);
        int wrote(0);

        os.write(reinterpret_cast<const char*>(&bytes), size_int);

        os.write(reinterpret_cast<const char*>(&lines), size_int);
        wrote += size_int;

        for(auto iter = data.comment.cbegin(); iter != data.comment.cend(); ++iter)
        {
            os << iter->c_str();
            wrote += size_char*80;
        }

        if(wrote != bytes)
            throw std::logic_error("internal byte information error");

        os.write(reinterpret_cast<const char*>(&bytes), size_int);
    }
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_head_block3(
        std::ostream& dcdfile, const header_type& data)
{
    int bytes(size_int);
    dcdfile.write(reinterpret_cast<const char*>(&bytes), size_int);
    dcdfile.write(reinterpret_cast<const char*>(&(data.nparticle)), size_int);
    dcdfile.write(reinterpret_cast<const char*>(&bytes), size_int);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_trajectory(
        const std::string& fname, const trajectory_type& traj)
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    this->write_trajectory(ifs, traj);
    ifs.close();
    return ;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_trajectory(
        std::ostream& os, const trajectory_type& traj)
{
    for(auto iter = traj.cbegin(); iter != traj.cend(); ++iter)
        this->write_snapshot(os, *iter);
    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_snapshot(
        const std::string& fname, const snapshot_type& snapshot)
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    this->write_snapshot(ifs, snapshot);
    ifs.close();
    return ;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_snapshot(
        std::ostream& os, const snapshot_type& snapshot)
{
    std::vector<float> x(snapshot.size());
    std::vector<float> y(snapshot.size());
    std::vector<float> z(snapshot.size());
    std::size_t counter(0);
    for(auto iter = snapshot.cbegin(); iter != snapshot.cend(); ++iter)
    {
        x[counter] = static_cast<float>((*iter)[0]);
        y[counter] = static_cast<float>((*iter)[1]);
        z[counter] = static_cast<float>((*iter)[2]);
        ++counter;
    }

    this->write_coord(os, x);
    this->write_coord(os, y);
    this->write_coord(os, z);

    return;
}

template <typename vectorT>
void DCDWriter<vectorT>::write_coord(
        std::ostream& os, const std::vector<float>& coord)
{
    int size(coord.size());
    int bytes(size * size_float);
    os.write(reinterpret_cast<const char*>(&bytes), size_int);

    for(auto iter = coord.cbegin(); iter != coord.cend(); ++iter)
    {
        const float tmp = *iter;
        os.write(reinterpret_cast<const char*>(&(tmp)), size_float);
    }

    os.write(reinterpret_cast<const char*>(&bytes), size_int);
    return;
}

}//mill

#endif //COFFEE_MILL_DCD_WRITER
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <chrono>
#include <cstdio>
#include <string>
#include <vector>
#include <sdbusplus/vtable.hpp>
#include <systemd/sd-bus.h>
#include <systemd/sd-journal.h>
#include "elog-lookup.cpp"
#include <phosphor-logging/elog-errors-HostEvent.hpp>
#include "config.h"
#include "elog_entry.hpp"
#include <phosphor-logging/log.hpp>
#include "log_manager.hpp"

namespace phosphor
{
namespace logging
{

void Manager::commit(uint64_t transactionId, std::string errMsg)
{
    constexpr const auto transactionIdVar = "TRANSACTION_ID";

    sd_journal *j = nullptr;
    int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
    if (rc < 0)
    {
        logging::log<logging::level::ERR>("Failed to open journal",
                           logging::entry("DESCRIPTION=%s", strerror(-rc)));
        return;
    }

    std::string transactionIdStr = std::to_string(transactionId);
    std::vector<std::string> metalist = g_errMetaMap[errMsg];
    std::vector<std::string> metalistHostEvent = g_errMetaMapHostEvent[errMsg];
    std::vector<std::string> additionalData;

    // Read the journal from the end to get the most recent entry first.
    // The result from the sd_journal_get_data() is of the form VARIABLE=value.
    SD_JOURNAL_FOREACH_BACKWARDS(j)
    {
        const char *data = nullptr;
        size_t length = 0;

        // Look for the transaction id metadata variable
        rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
                                &length);
        if (rc < 0)
        {
            // This journal entry does not have the transaction id,
            // continue to next entry
            continue;
        }

        std::string result(data);
        if (result.find(transactionIdStr) == std::string::npos)
        {
            // Requested transaction id  not found,
            // continue to next journal entry.
            continue;
        }

        // Search for the metadata variables in the current journal entry
        for (auto metaVarStr : metalist)
        {
            rc = sd_journal_get_data(j, metaVarStr.c_str(),
                                    (const void **)&data, &length);
            if (rc < 0)
            {
                // Not found, continue to next metadata variable
                logging::log<logging::level::INFO>("Failed to find metadata",
                        logging::entry("META_FIELD=%s", metaVarStr.c_str()));
                continue;
            }

            // Metatdata variable found, write to file
            additionalData.push_back(std::string(data));
        }

        // TODO Remove once host event error header file is auto-generated.
        // Tracking with issue openbmc/phosphor-logging#4
        for (auto metaVarStrHostEvent : metalistHostEvent)
        {
            rc = sd_journal_get_data(j, metaVarStrHostEvent.c_str(),
                                    (const void **)&data, &length);
            if (rc < 0)
            {
                // Not found, continue to next metadata variable
                logging::log<logging::level::INFO>("Failed to find metadata",
                        logging::entry("META_FIELD=%s",
                        metaVarStrHostEvent.c_str()));
                continue;
            }

            // Metatdata variable found, write to file
            additionalData.push_back(std::string(data));
        }

        // TODO Break only once all metadata fields have been found. Implement
        // once this function reads the metadata fields from the header file.
        break;
    }
    sd_journal_close(j);

    // Create error Entry dbus object
    entryId++;
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::system_clock::now().time_since_epoch()).count();
    auto objPath =  std::string(OBJ_ENTRY) + '/' +
            std::to_string(entryId);
    entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
            busLog,
            objPath,
            entryId,
            ms, // Milliseconds since 1970
            (Entry::Level)g_errLevelMap[errMsg],
            std::move(errMsg),
            std::move(additionalData))));
    return;
}

} // namespace logging
} // namepsace phosphor
<commit_msg>commit: Search for all metadata variables in the journal<commit_after>#include <fstream>
#include <iostream>
#include <chrono>
#include <cstdio>
#include <string>
#include <vector>
#include <sdbusplus/vtable.hpp>
#include <systemd/sd-bus.h>
#include <systemd/sd-journal.h>
#include "elog-lookup.cpp"
#include <phosphor-logging/elog-errors-HostEvent.hpp>
#include "config.h"
#include "elog_entry.hpp"
#include <phosphor-logging/log.hpp>
#include "log_manager.hpp"

namespace phosphor
{
namespace logging
{

void Manager::commit(uint64_t transactionId, std::string errMsg)
{
    constexpr const auto transactionIdVar = "TRANSACTION_ID";

    sd_journal *j = nullptr;
    int rc = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
    if (rc < 0)
    {
        logging::log<logging::level::ERR>("Failed to open journal",
                           logging::entry("DESCRIPTION=%s", strerror(-rc)));
        return;
    }

    std::string transactionIdStr = std::to_string(transactionId);
    auto& metalist = g_errMetaMap[errMsg];
    const auto& metalistHostEvent = g_errMetaMapHostEvent[errMsg];
    std::vector<std::string> additionalData;

    // TODO Remove once host event error header file is auto-generated.
    // Also make metalist a const variable.
    // Tracking with issue openbmc/phosphor-logging#4
    for (auto& metaVarStrHostEvent : metalistHostEvent)
    {
        metalist.push_back(metaVarStrHostEvent);
    }

    // Search for each metadata variable in the journal.
    for (auto& metaVarStr : metalist)
    {
        const char *metadata = nullptr;

        // Read the journal from the end to get the most recent entry first.
        // The result from the sd_journal_get_data() is of the form VARIABLE=value.
        SD_JOURNAL_FOREACH_BACKWARDS(j)
        {
            const char *data = nullptr;
            size_t length = 0;
            metadata = nullptr;

            // Search for the metadata variables in the current journal entry
            rc = sd_journal_get_data(j, metaVarStr.c_str(),
                                    (const void **)&metadata, &length);
            if (rc < 0)
            {
                // Metadata value not found, continue to next journal entry.
                continue;
            }

            // Look for the transaction id metadata variable
            rc = sd_journal_get_data(j, transactionIdVar, (const void **)&data,
                                    &length);
            if (rc < 0)
            {
                // This journal entry does not have the transaction id,
                // continue to next entry
                continue;
            }

            std::string result(data);
            if (result.find(transactionIdStr) == std::string::npos)
            {
                // Requested transaction id  not found,
                // continue to next journal entry.
                continue;
            }

            // Metadata matching the transaction id found, save it
            // and break out of the journal search loop
            additionalData.push_back(std::string(metadata));
            break;
        }
        if (!metadata)
        {
            // Metadata value not found in the journal.
            logging::log<logging::level::INFO>("Failed to find metadata",
                    logging::entry("META_FIELD=%s", metaVarStr.c_str()));
            continue;
        }
    }

    sd_journal_close(j);

    // Create error Entry dbus object
    entryId++;
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::system_clock::now().time_since_epoch()).count();
    auto objPath =  std::string(OBJ_ENTRY) + '/' +
            std::to_string(entryId);
    entries.insert(std::make_pair(entryId, std::make_unique<Entry>(
            busLog,
            objPath,
            entryId,
            ms, // Milliseconds since 1970
            (Entry::Level)g_errLevelMap[errMsg],
            std::move(errMsg),
            std::move(additionalData))));
    return;
}

} // namespace logging
} // namepsace phosphor
<|endoftext|>


<commit_before>#include "loganalyzer.h"

#include "mavlink_reader.h"

#include "heart.h"

#include <iostream> // for cout
#include <syslog.h>
#include "la-log.h"

#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>

#include <regex>

#include "dataflash_reader.h"
#include "dataflash_textdump_reader.h"

#include "analyzing_dataflash_message_handler.h"
#include "analyzing_mavlink_message_handler.h"

void LogAnalyzer::parse_path(const char *path)
{
    create_vehicle_from_commandline_arguments();
    if (_vehicle == NULL) {
        _vehicle = new AnalyzerVehicle::Base();
    }

    bool do_stdin = false;

    log_format_t log_format = log_format_none;
    if (!strcmp(path, "-")) {
        do_stdin = true;
    } else if (strstr(path, ".BIN") ||
               strstr(path, ".bin")) {
        log_format = log_format_df;
    } else if (strstr(path, ".log") ||
               strstr(path, ".LOG")) {
        log_format = log_format_log;
    } else if (strstr(path, ".tlog") ||
               strstr(path, ".TLOG")) {
        log_format = log_format_tlog;
    }

    if (force_format() != log_format_none) {
        log_format = force_format();
    }

    if (log_format == log_format_none) {
        if (do_stdin) {
            ::fprintf(stderr, "You asked to parse stdin but did not force a format type\n");
        } else {
            ::fprintf(stderr, "Unable to determine log type from filename; try -i?\n");
        }
        usage();
        exit(1);
    }

    switch (log_format) {
    case log_format_tlog:
        prep_for_tlog();
        break;
    case log_format_df:
        prep_for_df();
        break;
    case log_format_log:
        prep_for_log();
        break;
    default:
        abort();
    }

    int fd;
    if (streq(path, "-")) {
        fd = fileno(stdin);
    } else {
        fd = xopen(path, O_RDONLY);
    }

    if (output_style == Analyze::OUTPUT_BRIEF) {
        printf("%25s: ", path);
    }

    parse_fd(reader, fd);

    if (!streq(path, "-")) {
        close(fd);
    }

    if (output_style == Analyze::OUTPUT_BRIEF) {
        printf("\n");
    }

    switch (log_format) {
    case log_format_tlog:
        cleanup_after_tlog();
        break;
    case log_format_df:
        cleanup_after_df();
        break;
    case log_format_log:
        cleanup_after_log();
        break;
    default:
        abort();
    }

    delete _vehicle;
    _vehicle = NULL;
}

int LogAnalyzer::xopen(const char *filepath, const uint8_t mode)
{
    int fd = open(filepath, mode);
    if (fd == -1) {
        fprintf(stderr, "Failed to open (%s): %s\n", filepath, strerror(errno));
        exit(1);
    }
    return fd;
}

void LogAnalyzer::prep_for_tlog()
{
    reader = new MAVLink_Reader(config());
    ((MAVLink_Reader*)reader)->set_is_tlog(true);

    Analyze *analyze = create_analyze();

    Analyzing_MAVLink_Message_Handler *handler = new Analyzing_MAVLink_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");
}

void LogAnalyzer::cleanup_after_tlog()
{
    reader->clear_message_handlers();
}
void LogAnalyzer::cleanup_after_df()
{
    reader->clear_message_handlers();
}
void LogAnalyzer::cleanup_after_log()
{
    reader->clear_message_handlers();
}

void LogAnalyzer::do_idle_callbacks()
{
    reader->do_idle_callbacks();
}
void LogAnalyzer::pack_select_fds(fd_set &fds_read, fd_set &fds_write, fd_set &fds_err, uint8_t &nfds)
{
    _client->pack_select_fds(fds_read, fds_write, fds_err, nfds);
}

void LogAnalyzer::handle_select_fds(fd_set &fds_read, fd_set &fds_write, fd_set &fds_err, uint8_t &nfds)
{
    _client->handle_select_fds(fds_read, fds_write, fds_err, nfds);

    // FIXME: find a more interesting way of doing this...
    reader->feed(_client->_recv_buf, _client->_recv_buflen_content);
    _client->_recv_buflen_content = 0;
}

void LogAnalyzer::run_live_analysis()
{
    reader = new MAVLink_Reader(config());

    _client = new Telem_Forwarder_Client(_client_recv_buf, sizeof(_client_recv_buf));
    _client->configure(config());

    writer = new MAVLink_Writer(config());
    if (writer == NULL) {
        la_log(LOG_ERR, "Failed to create writer from (%s)\n", config_filename);
        exit(1);
    }

    Heart *heart= new Heart(writer);
    if (heart != NULL) {
        reader->add_message_handler(heart, "Heart");
    } else {
        la_log(LOG_INFO, "Failed to create heart");
    }

    create_vehicle_from_commandline_arguments();
    if (_vehicle == NULL) {
        _vehicle = new AnalyzerVehicle::Base();
    }

    Analyze *analyze = create_analyze();

    Analyzing_MAVLink_Message_Handler *handler = new Analyzing_MAVLink_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");

    select_loop();

    _vehicle = NULL; // leak this memory
}

Analyze *LogAnalyzer::create_analyze()
{
    Analyze *analyze = new Analyze(_vehicle);
    if (analyze == NULL) {
        la_log(LOG_ERR, "Failed to create analyze");
        abort();
    }

    analyze->set_output_style(output_style);
    if (_analyzer_names_to_run.size()) {
        analyze->set_analyzer_names_to_run(_analyzer_names_to_run);
    }
    analyze->instantiate_analyzers(config());

    if (_pure_output) {
        analyze->set_pure_output(true);
    }

    return analyze;
}

void LogAnalyzer::prep_for_df()
{
    reader = new DataFlash_Reader(config());

    Analyze *analyze = create_analyze();

    Analyzing_DataFlash_Message_Handler *handler = new Analyzing_DataFlash_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");
}

void LogAnalyzer::prep_for_log()
{
    reader = new DataFlash_TextDump_Reader(config());

    Analyze *analyze = create_analyze();

    Analyzing_DataFlash_Message_Handler *handler = new Analyzing_DataFlash_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");
}

void LogAnalyzer::show_version_information()
{
    ::printf("Version: " DRONEKIT_LA_VERSION "\n");
    ::printf("Git-Version: " GIT_VERSION "\n");
}

void LogAnalyzer::list_analyzers()
{
    Analyze *analyze = new Analyze(_vehicle);

    analyze->instantiate_analyzers(config());
    std::vector<Analyzer *> analyzers = analyze->analyzers();
    for (std::vector<Analyzer*>::iterator it = analyzers.begin();
         it != analyzers.end();
         ++it) {
        ::printf("%s\n", (*it)->name().c_str());
    }
}

// From: http://stackoverflow.com/questions/236129/split-a-string-in-c
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}
// thanks stackoverflow!

void LogAnalyzer::expand_names_to_run()
{
    std::vector<std::string> new_names;
    for (std::vector<std::string>::const_iterator it = _analyzer_names_to_run.begin();
         it != _analyzer_names_to_run.end();
         ++it) {
        // insert lambda here if you dare.
        std::vector<std::string> tmp = split((*it),',');

        for (std::vector<std::string>::const_iterator iy = tmp.begin();
             iy != tmp.end();
             ++iy) {
            std::string value = std::regex_replace(*iy, std::regex("^ +| +$|( ) +"), "$1");
            new_names.push_back(value);
        }
    }
    _analyzer_names_to_run = new_names;
}

void LogAnalyzer::create_vehicle_from_commandline_arguments()
{
    if (_model_string != NULL) {
        if (streq(_model_string,"copter")) {
            _vehicle = new AnalyzerVehicle::Copter();
//            _analyze->set_vehicle_copter();
            if (_frame_string != NULL) {
                ((AnalyzerVehicle::Copter*)_vehicle)->set_frame(_frame_string);
            }
        } else if (streq(_model_string,"plane")) {
            _vehicle = new AnalyzerVehicle::Plane();
        // } else if (streq(model_string,"rover")) {
        //     model = new AnalyzerVehicle::Rover();
        } else {
            la_log(LOG_ERR, "Unknown model type (%s)", _model_string);
            exit(1);
        }
        _vehicle->set_vehicletype_is_forced(true);
    } else if (_frame_string != NULL) {
        la_log(LOG_ERR, "Can not specify frame type without specifying model type");
        exit(1);
    }
}

void LogAnalyzer::run()
{
    // la_log(LOG_INFO, "loganalyzer starting: built " __DATE__ " " __TIME__);
    // signal(SIGHUP, sighup_handler);
    init_config();

    if (_show_version_information) {
        show_version_information();
        exit(0);
    }
    if (_do_list_analyzers) {
        list_analyzers();
        exit(0);
    }

    expand_names_to_run();

    if (_use_telem_forwarder) {
        return run_live_analysis();
    }

    if (_paths == NULL) {
        usage();
        exit(1);
    }

    output_style = Analyze::OUTPUT_JSON;
    if (output_style_string != NULL) {
        output_style = Analyze::OUTPUT_JSON;
        if (streq(output_style_string, "json")) {
            output_style = Analyze::OUTPUT_JSON;
        } else if(streq(output_style_string, "plain-text")) {
            output_style = Analyze::OUTPUT_PLAINTEXT;
        } else if(streq(output_style_string, "brief")) {
            output_style = Analyze::OUTPUT_BRIEF;
        } else if(streq(output_style_string, "html")) {
            output_style = Analyze::OUTPUT_HTML;
        } else {
            usage();
            exit(1);
        }
    }

    if (forced_format_string != NULL) {
        if (streq(forced_format_string, "tlog")) {
            _force_format = log_format_tlog;
        } else if(streq(forced_format_string, "df")) {
            _force_format = log_format_df;
        } else if(streq(forced_format_string, "log")) {
            _force_format = log_format_log;
        } else {
            usage();
            exit(1);
        }
    }

    for (uint8_t i=0; i<_pathcount; i++) {
        parse_path(_paths[i]);
    }
}

void LogAnalyzer::usage()
{
    ::printf("Usage:\n");
    ::printf("%s [OPTION] [FILE...]\n", program_name());
    ::printf(" -c filepath      use config file filepath\n");
    // ::printf(" -t               connect to telem forwarder to receive data\n");
    ::printf(" -m modeltype     override model; copter|plane|rover\n");
    ::printf(" -f frame         set frame; QUAD|Y6\n");
    ::printf(" -s style         use output style (plain-text|json|brief)\n");
    ::printf(" -h               display usage information\n");
    ::printf(" -l               list analyzers\n");
    ::printf(" -a               specify analyzers to run (comma-separated list)\n");
    ::printf(" -i format        specify input format (tlog|df|log)\n");
    ::printf(" -p	        pure output - no deprecated fields\n");
    ::printf(" -V               display version information\n");
    ::printf("\n");
    ::printf("Example: %s -s json 1.solo.tlog\n", program_name());
    ::printf("Example: %s -a \"Ever Flew, Battery\" 1.solo.tlog\n", program_name());
    ::printf("Example: %s -s brief 1.solo.tlog 2.solo.tlog logs/*.tlog\n", program_name());
    ::printf("Example: %s - (analyze stdin)\n", program_name());
    ::printf("Example: %s x.log (analyze text-dumped dataflash log)\n", program_name());
    exit(0);
}
const char *LogAnalyzer::program_name()
{
    if (_argv == NULL) {
        return "[Unknown]";
    }
    return _argv[0];
}

void LogAnalyzer::parse_arguments(int argc, char *argv[])
{
    int opt;
    _argc = argc;
    _argv = argv;

    while ((opt = getopt(argc, argv, "hc:ts:m:pf:Vla:i:")) != -1) {
        switch(opt) {
        case 'h':
            usage();
            break;
        case 'c':
            config_filename = optarg;
            break;
        case 'i':
            forced_format_string = optarg;
            break;
        case 't':
            _use_telem_forwarder = true;
            break;
        case 's':
            output_style_string = optarg;
            break;
        case 'm':
            _model_string = optarg;
            break;
        case 'p':
            _pure_output = true;
            break;
        case 'f':
            _frame_string = optarg;
            break;
        case 'V':
            _show_version_information = true;
            break;
        case 'l':
            _do_list_analyzers = true;
            break;
        case 'a':
            _analyzer_names_to_run.push_back(optarg);
            break;
        }
    }
    if (optind < argc) {
        _paths = &argv[optind];
        _pathcount = argc-optind;
    }
}

/*
* main - entry point
*/
int main(int argc, char* argv[])
{
    LogAnalyzer analyzer;
    analyzer.parse_arguments(argc, argv);
    analyzer.run();
    exit(0);
}
<commit_msg>loganalyzer: indicate which file path failed<commit_after>#include "loganalyzer.h"

#include "mavlink_reader.h"

#include "heart.h"

#include <iostream> // for cout
#include <syslog.h>
#include "la-log.h"

#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>

#include <regex>

#include "dataflash_reader.h"
#include "dataflash_textdump_reader.h"

#include "analyzing_dataflash_message_handler.h"
#include "analyzing_mavlink_message_handler.h"

void LogAnalyzer::parse_path(const char *path)
{
    create_vehicle_from_commandline_arguments();
    if (_vehicle == NULL) {
        _vehicle = new AnalyzerVehicle::Base();
    }

    bool do_stdin = false;

    log_format_t log_format = log_format_none;
    if (!strcmp(path, "-")) {
        do_stdin = true;
    } else if (strstr(path, ".BIN") ||
               strstr(path, ".bin")) {
        log_format = log_format_df;
    } else if (strstr(path, ".log") ||
               strstr(path, ".LOG")) {
        log_format = log_format_log;
    } else if (strstr(path, ".tlog") ||
               strstr(path, ".TLOG")) {
        log_format = log_format_tlog;
    }

    if (force_format() != log_format_none) {
        log_format = force_format();
    }

    if (log_format == log_format_none) {
        if (do_stdin) {
            ::fprintf(stderr, "You asked to parse stdin but did not force a format type\n");
        } else {
            ::fprintf(stderr, "Unable to determine log type from filename (%s); try -i?\n", path);
        }
        usage();
        exit(1);
    }

    switch (log_format) {
    case log_format_tlog:
        prep_for_tlog();
        break;
    case log_format_df:
        prep_for_df();
        break;
    case log_format_log:
        prep_for_log();
        break;
    default:
        abort();
    }

    int fd;
    if (streq(path, "-")) {
        fd = fileno(stdin);
    } else {
        fd = xopen(path, O_RDONLY);
    }

    if (output_style == Analyze::OUTPUT_BRIEF) {
        printf("%25s: ", path);
    }

    parse_fd(reader, fd);

    if (!streq(path, "-")) {
        close(fd);
    }

    if (output_style == Analyze::OUTPUT_BRIEF) {
        printf("\n");
    }

    switch (log_format) {
    case log_format_tlog:
        cleanup_after_tlog();
        break;
    case log_format_df:
        cleanup_after_df();
        break;
    case log_format_log:
        cleanup_after_log();
        break;
    default:
        abort();
    }

    delete _vehicle;
    _vehicle = NULL;
}

int LogAnalyzer::xopen(const char *filepath, const uint8_t mode)
{
    int fd = open(filepath, mode);
    if (fd == -1) {
        fprintf(stderr, "Failed to open (%s): %s\n", filepath, strerror(errno));
        exit(1);
    }
    return fd;
}

void LogAnalyzer::prep_for_tlog()
{
    reader = new MAVLink_Reader(config());
    ((MAVLink_Reader*)reader)->set_is_tlog(true);

    Analyze *analyze = create_analyze();

    Analyzing_MAVLink_Message_Handler *handler = new Analyzing_MAVLink_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");
}

void LogAnalyzer::cleanup_after_tlog()
{
    reader->clear_message_handlers();
}
void LogAnalyzer::cleanup_after_df()
{
    reader->clear_message_handlers();
}
void LogAnalyzer::cleanup_after_log()
{
    reader->clear_message_handlers();
}

void LogAnalyzer::do_idle_callbacks()
{
    reader->do_idle_callbacks();
}
void LogAnalyzer::pack_select_fds(fd_set &fds_read, fd_set &fds_write, fd_set &fds_err, uint8_t &nfds)
{
    _client->pack_select_fds(fds_read, fds_write, fds_err, nfds);
}

void LogAnalyzer::handle_select_fds(fd_set &fds_read, fd_set &fds_write, fd_set &fds_err, uint8_t &nfds)
{
    _client->handle_select_fds(fds_read, fds_write, fds_err, nfds);

    // FIXME: find a more interesting way of doing this...
    reader->feed(_client->_recv_buf, _client->_recv_buflen_content);
    _client->_recv_buflen_content = 0;
}

void LogAnalyzer::run_live_analysis()
{
    reader = new MAVLink_Reader(config());

    _client = new Telem_Forwarder_Client(_client_recv_buf, sizeof(_client_recv_buf));
    _client->configure(config());

    writer = new MAVLink_Writer(config());
    if (writer == NULL) {
        la_log(LOG_ERR, "Failed to create writer from (%s)\n", config_filename);
        exit(1);
    }

    Heart *heart= new Heart(writer);
    if (heart != NULL) {
        reader->add_message_handler(heart, "Heart");
    } else {
        la_log(LOG_INFO, "Failed to create heart");
    }

    create_vehicle_from_commandline_arguments();
    if (_vehicle == NULL) {
        _vehicle = new AnalyzerVehicle::Base();
    }

    Analyze *analyze = create_analyze();

    Analyzing_MAVLink_Message_Handler *handler = new Analyzing_MAVLink_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");

    select_loop();

    _vehicle = NULL; // leak this memory
}

Analyze *LogAnalyzer::create_analyze()
{
    Analyze *analyze = new Analyze(_vehicle);
    if (analyze == NULL) {
        la_log(LOG_ERR, "Failed to create analyze");
        abort();
    }

    analyze->set_output_style(output_style);
    if (_analyzer_names_to_run.size()) {
        analyze->set_analyzer_names_to_run(_analyzer_names_to_run);
    }
    analyze->instantiate_analyzers(config());

    if (_pure_output) {
        analyze->set_pure_output(true);
    }

    return analyze;
}

void LogAnalyzer::prep_for_df()
{
    reader = new DataFlash_Reader(config());

    Analyze *analyze = create_analyze();

    Analyzing_DataFlash_Message_Handler *handler = new Analyzing_DataFlash_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");
}

void LogAnalyzer::prep_for_log()
{
    reader = new DataFlash_TextDump_Reader(config());

    Analyze *analyze = create_analyze();

    Analyzing_DataFlash_Message_Handler *handler = new Analyzing_DataFlash_Message_Handler(analyze, _vehicle);
    reader->add_message_handler(handler, "Analyze");
}

void LogAnalyzer::show_version_information()
{
    ::printf("Version: " DRONEKIT_LA_VERSION "\n");
    ::printf("Git-Version: " GIT_VERSION "\n");
}

void LogAnalyzer::list_analyzers()
{
    Analyze *analyze = new Analyze(_vehicle);

    analyze->instantiate_analyzers(config());
    std::vector<Analyzer *> analyzers = analyze->analyzers();
    for (std::vector<Analyzer*>::iterator it = analyzers.begin();
         it != analyzers.end();
         ++it) {
        ::printf("%s\n", (*it)->name().c_str());
    }
}

// From: http://stackoverflow.com/questions/236129/split-a-string-in-c
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}
// thanks stackoverflow!

void LogAnalyzer::expand_names_to_run()
{
    std::vector<std::string> new_names;
    for (std::vector<std::string>::const_iterator it = _analyzer_names_to_run.begin();
         it != _analyzer_names_to_run.end();
         ++it) {
        // insert lambda here if you dare.
        std::vector<std::string> tmp = split((*it),',');

        for (std::vector<std::string>::const_iterator iy = tmp.begin();
             iy != tmp.end();
             ++iy) {
            std::string value = std::regex_replace(*iy, std::regex("^ +| +$|( ) +"), "$1");
            new_names.push_back(value);
        }
    }
    _analyzer_names_to_run = new_names;
}

void LogAnalyzer::create_vehicle_from_commandline_arguments()
{
    if (_model_string != NULL) {
        if (streq(_model_string,"copter")) {
            _vehicle = new AnalyzerVehicle::Copter();
//            _analyze->set_vehicle_copter();
            if (_frame_string != NULL) {
                ((AnalyzerVehicle::Copter*)_vehicle)->set_frame(_frame_string);
            }
        } else if (streq(_model_string,"plane")) {
            _vehicle = new AnalyzerVehicle::Plane();
        // } else if (streq(model_string,"rover")) {
        //     model = new AnalyzerVehicle::Rover();
        } else {
            la_log(LOG_ERR, "Unknown model type (%s)", _model_string);
            exit(1);
        }
        _vehicle->set_vehicletype_is_forced(true);
    } else if (_frame_string != NULL) {
        la_log(LOG_ERR, "Can not specify frame type without specifying model type");
        exit(1);
    }
}

void LogAnalyzer::run()
{
    // la_log(LOG_INFO, "loganalyzer starting: built " __DATE__ " " __TIME__);
    // signal(SIGHUP, sighup_handler);
    init_config();

    if (_show_version_information) {
        show_version_information();
        exit(0);
    }
    if (_do_list_analyzers) {
        list_analyzers();
        exit(0);
    }

    expand_names_to_run();

    if (_use_telem_forwarder) {
        return run_live_analysis();
    }

    if (_paths == NULL) {
        usage();
        exit(1);
    }

    output_style = Analyze::OUTPUT_JSON;
    if (output_style_string != NULL) {
        output_style = Analyze::OUTPUT_JSON;
        if (streq(output_style_string, "json")) {
            output_style = Analyze::OUTPUT_JSON;
        } else if(streq(output_style_string, "plain-text")) {
            output_style = Analyze::OUTPUT_PLAINTEXT;
        } else if(streq(output_style_string, "brief")) {
            output_style = Analyze::OUTPUT_BRIEF;
        } else if(streq(output_style_string, "html")) {
            output_style = Analyze::OUTPUT_HTML;
        } else {
            usage();
            exit(1);
        }
    }

    if (forced_format_string != NULL) {
        if (streq(forced_format_string, "tlog")) {
            _force_format = log_format_tlog;
        } else if(streq(forced_format_string, "df")) {
            _force_format = log_format_df;
        } else if(streq(forced_format_string, "log")) {
            _force_format = log_format_log;
        } else {
            usage();
            exit(1);
        }
    }

    for (uint8_t i=0; i<_pathcount; i++) {
        parse_path(_paths[i]);
    }
}

void LogAnalyzer::usage()
{
    ::printf("Usage:\n");
    ::printf("%s [OPTION] [FILE...]\n", program_name());
    ::printf(" -c filepath      use config file filepath\n");
    // ::printf(" -t               connect to telem forwarder to receive data\n");
    ::printf(" -m modeltype     override model; copter|plane|rover\n");
    ::printf(" -f frame         set frame; QUAD|Y6\n");
    ::printf(" -s style         use output style (plain-text|json|brief)\n");
    ::printf(" -h               display usage information\n");
    ::printf(" -l               list analyzers\n");
    ::printf(" -a               specify analyzers to run (comma-separated list)\n");
    ::printf(" -i format        specify input format (tlog|df|log)\n");
    ::printf(" -p	        pure output - no deprecated fields\n");
    ::printf(" -V               display version information\n");
    ::printf("\n");
    ::printf("Example: %s -s json 1.solo.tlog\n", program_name());
    ::printf("Example: %s -a \"Ever Flew, Battery\" 1.solo.tlog\n", program_name());
    ::printf("Example: %s -s brief 1.solo.tlog 2.solo.tlog logs/*.tlog\n", program_name());
    ::printf("Example: %s - (analyze stdin)\n", program_name());
    ::printf("Example: %s x.log (analyze text-dumped dataflash log)\n", program_name());
    exit(0);
}
const char *LogAnalyzer::program_name()
{
    if (_argv == NULL) {
        return "[Unknown]";
    }
    return _argv[0];
}

void LogAnalyzer::parse_arguments(int argc, char *argv[])
{
    int opt;
    _argc = argc;
    _argv = argv;

    while ((opt = getopt(argc, argv, "hc:ts:m:pf:Vla:i:")) != -1) {
        switch(opt) {
        case 'h':
            usage();
            break;
        case 'c':
            config_filename = optarg;
            break;
        case 'i':
            forced_format_string = optarg;
            break;
        case 't':
            _use_telem_forwarder = true;
            break;
        case 's':
            output_style_string = optarg;
            break;
        case 'm':
            _model_string = optarg;
            break;
        case 'p':
            _pure_output = true;
            break;
        case 'f':
            _frame_string = optarg;
            break;
        case 'V':
            _show_version_information = true;
            break;
        case 'l':
            _do_list_analyzers = true;
            break;
        case 'a':
            _analyzer_names_to_run.push_back(optarg);
            break;
        }
    }
    if (optind < argc) {
        _paths = &argv[optind];
        _pathcount = argc-optind;
    }
}

/*
* main - entry point
*/
int main(int argc, char* argv[])
{
    LogAnalyzer analyzer;
    analyzer.parse_arguments(argc, argv);
    analyzer.run();
    exit(0);
}
<|endoftext|>


<commit_before>#include <MutilaDebug.h>
#include <stdint.h>
#include "SmallTextMode.h"
#include "Matrix.h"

SmallTextMode_ SmallTextMode;

void SmallTextMode_::start(const char* data)
{
    DB(F("SmallTextMode::start "));
    DBLN(data);
    String line[3];
    uint8_t lineCount = 1;
    for (uint8_t i=0; i<strlen(data); i++) {
        DB("in: ");
        DB(data[i]);
        DB(" (int)");
        DBLN((int)data[i]);
        if (data[i] == '\r' && lineCount<3) {
            DBLN("newline");
            lineCount++;
            continue;
        }
        DB("append:");
        DB(data[i]);
        DB(" (int)");
        DBLN((int)data[i]);
        line[lineCount-1] += data[i];
    }
    DB("lines=");
    DBLN(lineCount);
    for (uint8_t i=0; i<lineCount; i++) {
        DB(i);
        DB('=');
        DBLN(line[i]);
    }

    uint8_t y;
    if (lineCount == 1) y = 18;
    else if (lineCount == 2) y = 14;
    else y = 10;

    Matrix.clear();
    Matrix.setFont(2);
    for (uint8_t i=0; i<lineCount; i++) {
        Matrix.text(MATRIX_ORANGE, 2, y, line[i]);
        y += 8;
    }
    Matrix.paint();
}

<commit_msg>placement tweak<commit_after>#include <MutilaDebug.h>
#include <stdint.h>
#include "SmallTextMode.h"
#include "Matrix.h"

SmallTextMode_ SmallTextMode;

void SmallTextMode_::start(const char* data)
{
    DB(F("SmallTextMode::start "));
    DBLN(data);
    String line[3];
    uint8_t lineCount = 1;
    for (uint8_t i=0; i<strlen(data); i++) {
        DB("in: ");
        DB(data[i]);
        DB(" (int)");
        DBLN((int)data[i]);
        if (data[i] == '\r' && lineCount<3) {
            DBLN("newline");
            lineCount++;
            continue;
        }
        DB("append:");
        DB(data[i]);
        DB(" (int)");
        DBLN((int)data[i]);
        line[lineCount-1] += data[i];
    }
    DB("lines=");
    DBLN(lineCount);
    for (uint8_t i=0; i<lineCount; i++) {
        DB(i);
        DB('=');
        DBLN(line[i]);
    }

    uint8_t y;
    if (lineCount == 1) y = 18;
    else if (lineCount == 2) y = 14;
    else y = 10;

    Matrix.clear();
    Matrix.setFont(2);
    for (uint8_t i=0; i<lineCount; i++) {
        Matrix.text(MATRIX_ORANGE, 1, y, line[i]);
        y += 8;
    }
    Matrix.paint();
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "network.h"

//Includes common to all platforms
#include "ErrorHandler.h"
#include "Address.h"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <string>

//============================================================================//
#if !defined(WIN32)
//============================================================================//

#include <fcntl.h>
#include <ctype.h>
#include <errno.h>

#ifndef HAVE_HSTRERROR
// POSIX.1-2001 marks this "obsolete" but we need it to interpret
// errors from gethostbyname(), which is likewise obsolete
char* hstrerror(int err)
{
  switch (err) {
  case 0:
    return "Resolver Error 0 (no error)";
  case HOST_NOT_FOUND:
    return "Unknown host";
  case TRY_AGAIN:
    return "Host name lookup failure";
  case NO_RECOVERY:
    return "Unknown server error";
  case NO_DATA:
    return "No address associated with name";
  default:
    return "Unknown resolver error";
    }
}
#endif

#ifndef O_NDELAY
#  define O_NDELAY O_NONBLOCK
#endif

extern "C" {

const char* socket_strerror(int err)
{
  return strerror(err);
}

void nerror(const char* msg)
{
  std::vector<std::string> args;
  if (msg) {
    args.push_back(msg);
    args.push_back(strerror(errno));
    printError("{1}: {2}", &args);
  } else {
    args.push_back(strerror(errno));
    printError("{1}", &args);
  }
}

void bzfherror(const char* msg)
{
  std::vector<std::string> args;
  if (msg) {
    args.push_back(msg);
    args.push_back(hstrerror(h_errno));
    printError("{1}: {2}", &args);
  } else {
    args.push_back(hstrerror(h_errno));
    printError("{1}", &args);
  }
}

int getErrno()
{
  return errno;
}

} /* end 'extern "C"' */

int BzfNetwork::setNonBlocking(int fd)
{
  int mode = fcntl(fd, F_GETFL, 0);
  if (mode == -1 || fcntl(fd, F_SETFL, mode | O_NDELAY) < 0)
    return -1;
  return 0;
}

int BzfNetwork::setBlocking(int fd)
{
  int mode = fcntl(fd, F_GETFL, 0);
  if (mode == -1 || fcntl(fd, F_SETFL, mode & ~O_NDELAY) < 0)
    return -1;
  return 0;
}

BzfNetwork::ConnState BzfNetwork::getConnectionState(int fd)
{
  int optVal;
  socklen_t optLen;
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optVal, &optLen) == -1) {
    return CONNSTATE_QUERY_FAILURE;
  }
  switch (optVal) {
    case 0: {
      return CONNSTATE_CONN_SUCCESS;
    }
    case EINPROGRESS:
    case EINTR: {
      return CONNSTATE_INPROGRESS;
    }
  }
  errno = optVal;
  return CONNSTATE_CONN_FAILURE;
}

int BzfNetwork::closeSocket(int fd)
{
  return close(fd);
}

//============================================================================//
#else /* defined(_WIN32) */
//============================================================================//

extern "C" {

int inet_aton(const char* cp, struct in_addr* pin)
{
  unsigned long a = inet_addr(cp);
  if (a == (unsigned long)-1) {
    // could be an error or cp could be a broadcast address.
    // FIXME -- this check is a little simplistic.
    if (strcmp(cp, "255.255.255.255") != 0) return 0;
  }

  pin->s_addr = a;
  return 1;
}

// win32 apparently cannot lookup error messages for us
static const struct { int code; const char* msg; } netErrorCodes[] = {
	/* 10004 */{WSAEINTR,		"The (blocking) call was canceled via WSACancelBlockingCall"},
	/* 10009 */{WSAEBADF,		"Bad file handle"},
	/* 10013 */{WSAEACCES,		"The requested address is a broadcast address, but the appropriate flag was not set"},
	/* 10014 */{WSAEFAULT,		"Invalid pointer value, or buffer is too small (WSAEFAULT)"},
	/* 10022 */{WSAEINVAL,		"Invalid argument (WSAEINVAL)"},
	/* 10024 */{WSAEMFILE,		"No more file descriptors available"},
	/* 10035 */{WSAEWOULDBLOCK,	"Socket is marked as non-blocking and no connections are present or the receive operation would block"},
	/* 10036 */{WSAEINPROGRESS,	"A blocking Windows Sockets operation is in progress"},
	/* 10037 */{WSAEALREADY,	"The asynchronous routine being canceled has already completed"},
	/* 10038 */{WSAENOTSOCK,	"At least on descriptor is not a socket"},
	/* 10039 */{WSAEDESTADDRREQ,	"A destination address is required"},
	/* 10040 */{WSAEMSGSIZE,	"The datagram was too large to fit into the specified buffer and was truncated"},
	/* 10041 */{WSAEPROTOTYPE,	"The specified protocol is the wrong type for this socket"},
	/* 10042 */{WSAENOPROTOOPT,	"The option is unknown or unsupported"},
	/* 10043 */{WSAEPROTONOSUPPORT, "The specified protocol is not supported"},
	/* 10044 */{WSAESOCKTNOSUPPORT, "The specified socket type is not supported by this address family"},
	/* 10045 */{WSAEOPNOTSUPP,	"The referenced socket is not a type that supports that operation"},
	/* 10046 */{WSAEPFNOSUPPORT,	"BSD: Protocol family not supported"},
	/* 10047 */{WSAEAFNOSUPPORT,	"The specified address family is not supported"},
	/* 10048 */{WSAEADDRINUSE,	"The specified address is already in use"},
	/* 10049 */{WSAEADDRNOTAVAIL,	"The specified address is not available from the local machine"},
	/* 10050 */{WSAENETDOWN,	"The Windows Sockets implementation has detected that the network subsystem has failed"},
	/* 10051 */{WSAENETUNREACH,	"The network can't be reached from this hos at this time"},
	/* 10052 */{WSAENETRESET,	"The connection must be reset because the Windows Sockets implementation dropped it"},
	/* 10053 */{WSAECONNABORTED,	"The virtual circuit was aborted due to timeout or other failure"},
	/* 10054 */{WSAECONNRESET,	"The virtual circuit was reset by the remote side"},
	/* 10055 */{WSAENOBUFS,		"No buffer space is available or a buffer deadlock has occured. The socket cannot be created"},
	/* 10056 */{WSAEISCONN,		"The socket is already connected"},
	/* 10057 */{WSAENOTCONN,	"The socket is not connected"},
	/* 10058 */{WSAESHUTDOWN,	"The socket has been shutdown"},
	/* 10059 */{WSAETOOMANYREFS,	"BSD: Too many references"},
	/* 10060 */{WSAETIMEDOUT,	"Attempt to connect timed out without establishing a connection"},
	/* 10061 */{WSAECONNREFUSED,	"The attempt to connect was forcefully rejected"},
	/* 10062 */{WSAELOOP,		"Undocumented WinSock error code used in BSD"},
	/* 10063 */{WSAENAMETOOLONG,	"Undocumented WinSock error code used in BSD"},
	/* 10064 */{WSAEHOSTDOWN,	"Host is down"},
	/* 10065 */{WSAEHOSTUNREACH,	"No route to host"},
	/* 10066 */{WSAENOTEMPTY,	"Undocumented WinSock error code"},
	/* 10067 */{WSAEPROCLIM,	"Too many processes"},
	/* 10068 */{WSAEUSERS,		"Undocumented WinSock error code"},
	/* 10069 */{WSAEDQUOT,		"Undocumented WinSock error code"},
	/* 10070 */{WSAESTALE,		"Undocumented WinSock error code"},
	/* 10071 */{WSAEREMOTE,		"Undocumented WinSock error code"},
	/* 10091 */{WSASYSNOTREADY,	"Underlying network subsytem is not ready for network communication"},
	/* 10092 */{WSAVERNOTSUPPORTED,	"The version of WinSock API support requested is not provided in this implementation"},
	/* 10093 */{WSANOTINITIALISED,	"WinSock subsystem not properly initialized"},
	/* 10101 */{WSAEDISCON,		"Virtual circuit has gracefully terminated connection"},
	/* 11001 */{WSAHOST_NOT_FOUND,	"Host not found"},
	/* 11002 */{WSATRY_AGAIN,	"Host not found"},
	/* 11003 */{WSANO_RECOVERY,	"Host name lookup error"},
	/* 11004 */{WSANO_DATA,		"No data for host"},
	/* end   */{0,			NULL}
};

const char* socket_strerror(int err)
{
  const char* errmsg = "<unknown winsock error>";
  for (int i = 0; netErrorCodes[i].code != 0; ++i) {
    if (netErrorCodes[i].code == err) {
      return netErrorCodes[i].msg;
    }
  }
  return errmsg;
}

void nerror(const char* msg)
{
  const int err = getErrno();
  const char* errmsg = socket_strerror(err);
  if (msg) {
    char buf[50];
    std::vector<std::string> args;
    args.push_back(msg);
    args.push_back(errmsg);
    sprintf(buf, "%d", err);
    args.push_back(buf);
    printError("{1}: {2} ({3})", &args);
  } else {
    char buf[50];
    std::vector<std::string> args;
    args.push_back(errmsg);
    sprintf(buf, "%d", err);
    args.push_back(buf);
    printError("{1} ({2})", &args);
  }
}

void herror(const char* msg)
{
  nerror(msg);
}

int getErrno()
{
  return WSAGetLastError();
}

} /* end 'extern "C"' */

int BzfNetwork::setNonBlocking(int fd)
{
  int on = 1;
  return ioctl(fd, FIONBIO, &on);
}

int BzfNetwork::setBlocking(int fd)
{
  int off = 0;
  return ioctl(fd, FIONBIO, &off);
}

BzfNetwork::ConnState BzfNetwork::getConnectionState(int fd)
{
  struct timeval timeout = { 0, 0 };
  fd_set wrfds;
  fd_set exfds;
  FD_ZERO(&wrfds);
  FD_SET(fd, &wrfds);
  if (select(fd + 1, NULL, &wrfds, NULL, &timeout) == -1) {
    return CONNSTATE_QUERY_FAILURE;
  }
  if (FD_ISSET(fd, &wrfds)) {
    return CONNSTATE_CONN_SUCCESS; // FIXME -- need to detect connection errors,
                                   //          and WSASetLastError() accordingly
  }
  return CONNSTATE_INPROGRESS; // still connecting
}

int BzfNetwork::closeSocket(int fd)
{
  return closesocket(fd);
}

//============================================================================//
#endif /* defined(_WIN32) */
//============================================================================//

// parse a url into its parts
bool BzfNetwork::parseURL(const std::string& url, std::string& protocol,
                          std::string& hostname, int& port,
                          std::string& pathname)
{
  static const char* defaultHostname = "localhost";

  std::string mungedurl;

  int delimiterpos = 0;
  for(; (delimiterpos < (int)url.length()) && (url[delimiterpos] != ':') && (url[delimiterpos] != ' '); delimiterpos++) {};
  if(url[delimiterpos] != ':')
    return false;

  // set defaults
  hostname = defaultHostname;

  // store protocol
  protocol = url.substr(0, delimiterpos);
  mungedurl = url.substr(delimiterpos + 1);

  // store hostname and optional port for some protocols
  if (protocol == "http") {
    if (mungedurl[0] == '/' && mungedurl[1] == '/') {
      mungedurl = mungedurl.substr(2);
      int pos = 0;
      for(; (pos < (int)mungedurl.length()) && (mungedurl[pos] != ':') && (mungedurl[pos] != '/') && (mungedurl[pos] != '\\') && (mungedurl[pos] != ' '); pos++) {};

      if(mungedurl[pos] == ' ')
	return false;

      if(pos != 0)
	hostname = mungedurl.substr(0, pos);

      mungedurl = mungedurl.substr(pos);
      pos = 0;

      if(mungedurl[0] == ':') {
	pos++;
	char portString[10];
	int i = 0;
	for(; isdigit(mungedurl[pos]) && i < 9; pos++)
	  portString[i++] = mungedurl[pos];
	portString[i] = '\0';
	port = atoi(portString);
      }

      mungedurl = mungedurl.substr(pos);

      if((mungedurl[0] != '\0') && (mungedurl[0] != '/') && (mungedurl[0] != '\\'))
	return false;

    }
  }
  if(mungedurl.length() != 0)
    pathname = mungedurl;
  else
    pathname = "";

  return true;
}

void setNoDelay(int fd)
{
  // turn off TCP delay (collection).  we want packets sent immediately.
#if defined(_WIN32)
  BOOL on = TRUE;
#else
  int on = 1;
#endif
  struct protoent *p = getprotobyname("tcp");
  if (p && setsockopt(fd, p->p_proto, TCP_NODELAY, (SSOType)&on, sizeof(on)) < 0) {
    nerror("enabling TCP_NODELAY");
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>* blind-coding improvements to the WIN32 BzfNetwork::getConnectionState()<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "network.h"

//Includes common to all platforms
#include "ErrorHandler.h"
#include "Address.h"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <string>

//============================================================================//
#if !defined(WIN32)
//============================================================================//

#include <fcntl.h>
#include <ctype.h>
#include <errno.h>

#ifndef HAVE_HSTRERROR
// POSIX.1-2001 marks this "obsolete" but we need it to interpret
// errors from gethostbyname(), which is likewise obsolete
char* hstrerror(int err)
{
  switch (err) {
  case 0:
    return "Resolver Error 0 (no error)";
  case HOST_NOT_FOUND:
    return "Unknown host";
  case TRY_AGAIN:
    return "Host name lookup failure";
  case NO_RECOVERY:
    return "Unknown server error";
  case NO_DATA:
    return "No address associated with name";
  default:
    return "Unknown resolver error";
    }
}
#endif

#ifndef O_NDELAY
#  define O_NDELAY O_NONBLOCK
#endif

extern "C" {

const char* socket_strerror(int err)
{
  return strerror(err);
}

void nerror(const char* msg)
{
  std::vector<std::string> args;
  if (msg) {
    args.push_back(msg);
    args.push_back(strerror(errno));
    printError("{1}: {2}", &args);
  } else {
    args.push_back(strerror(errno));
    printError("{1}", &args);
  }
}

void bzfherror(const char* msg)
{
  std::vector<std::string> args;
  if (msg) {
    args.push_back(msg);
    args.push_back(hstrerror(h_errno));
    printError("{1}: {2}", &args);
  } else {
    args.push_back(hstrerror(h_errno));
    printError("{1}", &args);
  }
}

int getErrno()
{
  return errno;
}

} /* end 'extern "C"' */

int BzfNetwork::setNonBlocking(int fd)
{
  int mode = fcntl(fd, F_GETFL, 0);
  if (mode == -1 || fcntl(fd, F_SETFL, mode | O_NDELAY) < 0)
    return -1;
  return 0;
}

int BzfNetwork::setBlocking(int fd)
{
  int mode = fcntl(fd, F_GETFL, 0);
  if (mode == -1 || fcntl(fd, F_SETFL, mode & ~O_NDELAY) < 0)
    return -1;
  return 0;
}

BzfNetwork::ConnState BzfNetwork::getConnectionState(int fd)
{
  int optVal;
  socklen_t optLen = sizeof(optVal);
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optVal, &optLen) == -1) {
    return CONNSTATE_QUERY_FAILURE;
  }
  switch (optVal) {
    case 0: {
      return CONNSTATE_CONN_SUCCESS;
    }
    case EINPROGRESS:
    case EINTR: {
      return CONNSTATE_INPROGRESS;
    }
  }
  errno = optVal;
  return CONNSTATE_CONN_FAILURE;
}

int BzfNetwork::closeSocket(int fd)
{
  return close(fd);
}

//============================================================================//
#else /* defined(_WIN32) */
//============================================================================//

extern "C" {

int inet_aton(const char* cp, struct in_addr* pin)
{
  unsigned long a = inet_addr(cp);
  if (a == (unsigned long)-1) {
    // could be an error or cp could be a broadcast address.
    // FIXME -- this check is a little simplistic.
    if (strcmp(cp, "255.255.255.255") != 0) return 0;
  }

  pin->s_addr = a;
  return 1;
}

// win32 apparently cannot lookup error messages for us
static const struct { int code; const char* msg; } netErrorCodes[] = {
	/* 10004 */{WSAEINTR,		"The (blocking) call was canceled via WSACancelBlockingCall"},
	/* 10009 */{WSAEBADF,		"Bad file handle"},
	/* 10013 */{WSAEACCES,		"The requested address is a broadcast address, but the appropriate flag was not set"},
	/* 10014 */{WSAEFAULT,		"Invalid pointer value, or buffer is too small (WSAEFAULT)"},
	/* 10022 */{WSAEINVAL,		"Invalid argument (WSAEINVAL)"},
	/* 10024 */{WSAEMFILE,		"No more file descriptors available"},
	/* 10035 */{WSAEWOULDBLOCK,	"Socket is marked as non-blocking and no connections are present or the receive operation would block"},
	/* 10036 */{WSAEINPROGRESS,	"A blocking Windows Sockets operation is in progress"},
	/* 10037 */{WSAEALREADY,	"The asynchronous routine being canceled has already completed"},
	/* 10038 */{WSAENOTSOCK,	"At least on descriptor is not a socket"},
	/* 10039 */{WSAEDESTADDRREQ,	"A destination address is required"},
	/* 10040 */{WSAEMSGSIZE,	"The datagram was too large to fit into the specified buffer and was truncated"},
	/* 10041 */{WSAEPROTOTYPE,	"The specified protocol is the wrong type for this socket"},
	/* 10042 */{WSAENOPROTOOPT,	"The option is unknown or unsupported"},
	/* 10043 */{WSAEPROTONOSUPPORT, "The specified protocol is not supported"},
	/* 10044 */{WSAESOCKTNOSUPPORT, "The specified socket type is not supported by this address family"},
	/* 10045 */{WSAEOPNOTSUPP,	"The referenced socket is not a type that supports that operation"},
	/* 10046 */{WSAEPFNOSUPPORT,	"BSD: Protocol family not supported"},
	/* 10047 */{WSAEAFNOSUPPORT,	"The specified address family is not supported"},
	/* 10048 */{WSAEADDRINUSE,	"The specified address is already in use"},
	/* 10049 */{WSAEADDRNOTAVAIL,	"The specified address is not available from the local machine"},
	/* 10050 */{WSAENETDOWN,	"The Windows Sockets implementation has detected that the network subsystem has failed"},
	/* 10051 */{WSAENETUNREACH,	"The network can't be reached from this hos at this time"},
	/* 10052 */{WSAENETRESET,	"The connection must be reset because the Windows Sockets implementation dropped it"},
	/* 10053 */{WSAECONNABORTED,	"The virtual circuit was aborted due to timeout or other failure"},
	/* 10054 */{WSAECONNRESET,	"The virtual circuit was reset by the remote side"},
	/* 10055 */{WSAENOBUFS,		"No buffer space is available or a buffer deadlock has occured. The socket cannot be created"},
	/* 10056 */{WSAEISCONN,		"The socket is already connected"},
	/* 10057 */{WSAENOTCONN,	"The socket is not connected"},
	/* 10058 */{WSAESHUTDOWN,	"The socket has been shutdown"},
	/* 10059 */{WSAETOOMANYREFS,	"BSD: Too many references"},
	/* 10060 */{WSAETIMEDOUT,	"Attempt to connect timed out without establishing a connection"},
	/* 10061 */{WSAECONNREFUSED,	"The attempt to connect was forcefully rejected"},
	/* 10062 */{WSAELOOP,		"Undocumented WinSock error code used in BSD"},
	/* 10063 */{WSAENAMETOOLONG,	"Undocumented WinSock error code used in BSD"},
	/* 10064 */{WSAEHOSTDOWN,	"Host is down"},
	/* 10065 */{WSAEHOSTUNREACH,	"No route to host"},
	/* 10066 */{WSAENOTEMPTY,	"Undocumented WinSock error code"},
	/* 10067 */{WSAEPROCLIM,	"Too many processes"},
	/* 10068 */{WSAEUSERS,		"Undocumented WinSock error code"},
	/* 10069 */{WSAEDQUOT,		"Undocumented WinSock error code"},
	/* 10070 */{WSAESTALE,		"Undocumented WinSock error code"},
	/* 10071 */{WSAEREMOTE,		"Undocumented WinSock error code"},
	/* 10091 */{WSASYSNOTREADY,	"Underlying network subsytem is not ready for network communication"},
	/* 10092 */{WSAVERNOTSUPPORTED,	"The version of WinSock API support requested is not provided in this implementation"},
	/* 10093 */{WSANOTINITIALISED,	"WinSock subsystem not properly initialized"},
	/* 10101 */{WSAEDISCON,		"Virtual circuit has gracefully terminated connection"},
	/* 11001 */{WSAHOST_NOT_FOUND,	"Host not found"},
	/* 11002 */{WSATRY_AGAIN,	"Host not found"},
	/* 11003 */{WSANO_RECOVERY,	"Host name lookup error"},
	/* 11004 */{WSANO_DATA,		"No data for host"},
	/* end   */{0,			NULL}
};

const char* socket_strerror(int err)
{
  const char* errmsg = "<unknown winsock error>";
  for (int i = 0; netErrorCodes[i].code != 0; ++i) {
    if (netErrorCodes[i].code == err) {
      return netErrorCodes[i].msg;
    }
  }
  return errmsg;
}

void nerror(const char* msg)
{
  const int err = getErrno();
  const char* errmsg = socket_strerror(err);
  if (msg) {
    char buf[50];
    std::vector<std::string> args;
    args.push_back(msg);
    args.push_back(errmsg);
    sprintf(buf, "%d", err);
    args.push_back(buf);
    printError("{1}: {2} ({3})", &args);
  } else {
    char buf[50];
    std::vector<std::string> args;
    args.push_back(errmsg);
    sprintf(buf, "%d", err);
    args.push_back(buf);
    printError("{1} ({2})", &args);
  }
}

void herror(const char* msg)
{
  nerror(msg);
}

int getErrno()
{
  return WSAGetLastError();
}

} /* end 'extern "C"' */

int BzfNetwork::setNonBlocking(int fd)
{
  int on = 1;
  return ioctl(fd, FIONBIO, &on);
}

int BzfNetwork::setBlocking(int fd)
{
  int off = 0;
  return ioctl(fd, FIONBIO, &off);
}

BzfNetwork::ConnState BzfNetwork::getConnectionState(int fd)
{
  // reference:  http://msdn.microsoft.com/en-us/library/ms740141(VS.85).aspx
  struct timeval timeout = { 0, 0 };
  fd_set wrfds, exfds;
  FD_ZERO(&wrfds);
  FD_ZERO(&exfds);
  FD_SET(fd, &wrfds);
  FD_SET(fd, &exfds);
  if (select(fd + 1, NULL, &wrfds, &exfds, &timeout) == -1) {
    return CONNSTATE_QUERY_FAILURE;
  }
  if (FD_ISSET(fd, &wrfds)) {
    return CONNSTATE_CONN_SUCCESS;
  }
  else if (FD_ISSET(fd, &exfds)) {
    int optVal;
    int optLen = sizeof(optVal);
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optVal, &optLen) == -1) {
      // do nothing, return this call's error as getErrno()
    } else {
      WSASetLastError(optVal);
    }
    return CONNSTATE_CONN_FAILURE;
  }
  return CONNSTATE_INPROGRESS; // still connecting
}

int BzfNetwork::closeSocket(int fd)
{
  return closesocket(fd);
}

//============================================================================//
#endif /* defined(_WIN32) */
//============================================================================//

// parse a url into its parts
bool BzfNetwork::parseURL(const std::string& url, std::string& protocol,
                          std::string& hostname, int& port,
                          std::string& pathname)
{
  static const char* defaultHostname = "localhost";

  std::string mungedurl;

  int delimiterpos = 0;
  for(; (delimiterpos < (int)url.length()) && (url[delimiterpos] != ':') && (url[delimiterpos] != ' '); delimiterpos++) {};
  if(url[delimiterpos] != ':')
    return false;

  // set defaults
  hostname = defaultHostname;

  // store protocol
  protocol = url.substr(0, delimiterpos);
  mungedurl = url.substr(delimiterpos + 1);

  // store hostname and optional port for some protocols
  if (protocol == "http") {
    if (mungedurl[0] == '/' && mungedurl[1] == '/') {
      mungedurl = mungedurl.substr(2);
      int pos = 0;
      for(; (pos < (int)mungedurl.length()) && (mungedurl[pos] != ':') && (mungedurl[pos] != '/') && (mungedurl[pos] != '\\') && (mungedurl[pos] != ' '); pos++) {};

      if(mungedurl[pos] == ' ')
	return false;

      if(pos != 0)
	hostname = mungedurl.substr(0, pos);

      mungedurl = mungedurl.substr(pos);
      pos = 0;

      if(mungedurl[0] == ':') {
	pos++;
	char portString[10];
	int i = 0;
	for(; isdigit(mungedurl[pos]) && i < 9; pos++)
	  portString[i++] = mungedurl[pos];
	portString[i] = '\0';
	port = atoi(portString);
      }

      mungedurl = mungedurl.substr(pos);

      if((mungedurl[0] != '\0') && (mungedurl[0] != '/') && (mungedurl[0] != '\\'))
	return false;

    }
  }
  if(mungedurl.length() != 0)
    pathname = mungedurl;
  else
    pathname = "";

  return true;
}

void setNoDelay(int fd)
{
  // turn off TCP delay (collection).  we want packets sent immediately.
#if defined(_WIN32)
  BOOL on = TRUE;
#else
  int on = 1;
#endif
  struct protoent *p = getprotobyname("tcp");
  if (p && setsockopt(fd, p->p_proto, TCP_NODELAY, (SSOType)&on, sizeof(on)) < 0) {
    nerror("enabling TCP_NODELAY");
  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>

#include "geometry/point.hpp"
#include "geometry/triangle.hpp"

#include "triangulation/figure_definition.hpp"
#include "triangulation/triangulation.hpp"

struct HUI : public FigureDefinition {
	int parameter(double x, double y) {
		//return !(y > x + 3 || y > 12 - x || (y > 2 && y < 4 && y < x && y < 9 - x));
		return
		(y<=1 && ((y<=x && y>=x-2) || (y>=4-x && y<=6-x))) ||
		(y>=1 && y<=2 && (y<=x && y<=6-x)) ||
		(y>=2 && y<=3 && (y>=4-x && y>=x-2)) ||
		(y>=3 && y<=4 && ((y<=x && y>=x-2) || (y>=4-x && y<=6-x))) ||

		(y<=2 && y<=x-6 && y>=x-8) ||
		(y>=2 && y<=3 && (y>=10-x && y>=x-8)) ||
		(y>=3 && y<=4 && ((y<=x-6 && y>=x-8) || (y>=10-x && y<=12-x))) ||

		(y<=4 && x>=12 && x<=14) ||
		(x>=14 && x<=16 && y>=x-14 && y<=x-12) ||
		(y<=4 && x>=16 && x<=18) ||

		(y>=19-x && y>=x-11);
	}
};

HUI hui;

// Triangulacia nahui
Triangulation triangulation(&hui);

void print(void) {
	FILE *gmain;

	gmain = fopen("main", "w");
	fprintf(gmain, "plot 'data' with lines\npause mouse close\n");
	fclose(gmain);

	triangulation.dump("data");

	system("gnuplot main");
	unlink("main");
	unlink("data");
}

void demo() {
	triangulation.make_grid(19, 6);
	print();
	triangulation.make_it_smaller();
	print();
	triangulation.make_it_smaller();
	print();
}

void run() {
	triangulation.make_grid(19, 6);
	triangulation.make_it_smaller();
	triangulation.make_it_smaller();
	triangulation.write(stdout);
}

int main() {
	demo();
	return 0;
}
<commit_msg>Changed triangulation task<commit_after>#include <cstdio>
#include <cstdlib>

#include "geometry/point.hpp"
#include "geometry/triangle.hpp"

#include "triangulation/figure_definition.hpp"
#include "triangulation/triangulation.hpp"

struct HUI : public FigureDefinition {
	int parameter(double x, double y) {
		return

		!(  9 - y < x - 3  )

		;
	}
};

HUI hui;

// Triangulacia nahui
Triangulation triangulation(&hui);

void print(void) {
	FILE *gmain;

	gmain = fopen("main", "w");
	fprintf(gmain, "set key off\nplot 'data' with lines\npause mouse close\n");
	fclose(gmain);

	triangulation.dump("data");

	system("gnuplot main");
	unlink("main");
	unlink("data");
}

void demo() {
	triangulation.make_grid(10, 10);
	print();
	triangulation.make_it_smaller();
	print();
	triangulation.make_it_smaller();
	print();
}

void run() {
	triangulation.make_grid(19, 6);
	triangulation.make_it_smaller();
	triangulation.make_it_smaller();
	triangulation.write(stdout);
}

int main() {
	demo();
	return 0;
}
<|endoftext|>