<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SBTRACE_HXX
#define _SBTRACE_HXX

#define DBG_TRACE_BASIC

// ###############################################################################
// ###
// ###    ATTENTION:
// ###
// ###  - DBG_TRACE_PROFILING can only be activated together with DBG_TRACE_BASIC
// ###
// ###  - If you activate DBG_TRACE_PROFILING you also need to uncomment line
// ###    # SHL1STDLIBS+=$(CANVASTOOLSLIB) in basic/util/makefile.mk (search
// ###    for DBG_TRACE_PROFILING there)
// ###
// ###############################################################################
//#define DBG_TRACE_PROFILING

#ifdef DBG_TRACE_BASIC
void dbg_InitTrace( void );
void dbg_DeInitTrace( void );
void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl );
void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallLvl, bool bLeave = false );
void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, sal_Int32 nCallLvl );
void dbg_RegisterTraceTextForPC( SbModule* pModule, sal_uInt32 nPC,
    const String& aTraceStr_STMNT, const String& aTraceStr_PCode );
void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite );
#endif

#endif
<commit_msg>calcvba: disable basic tracing by default<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SBTRACE_HXX
#define _SBTRACE_HXX

//#define DBG_TRACE_BASIC

// ###############################################################################
// ###
// ###    ATTENTION:
// ###
// ###  - DBG_TRACE_PROFILING can only be activated together with DBG_TRACE_BASIC
// ###
// ###  - If you activate DBG_TRACE_PROFILING you also need to uncomment line
// ###    # SHL1STDLIBS+=$(CANVASTOOLSLIB) in basic/util/makefile.mk (search
// ###    for DBG_TRACE_PROFILING there)
// ###
// ###############################################################################
//#define DBG_TRACE_PROFILING

#ifdef DBG_TRACE_BASIC
void dbg_InitTrace( void );
void dbg_DeInitTrace( void );
void dbg_traceStep( SbModule* pModule, sal_uInt32 nPC, sal_Int32 nCallLvl );
void dbg_traceNotifyCall( SbModule* pModule, SbMethod* pMethod, sal_Int32 nCallLvl, bool bLeave = false );
void dbg_traceNotifyError( SbError nTraceErr, const String& aTraceErrMsg, bool bTraceErrHandled, sal_Int32 nCallLvl );
void dbg_RegisterTraceTextForPC( SbModule* pModule, sal_uInt32 nPC,
    const String& aTraceStr_STMNT, const String& aTraceStr_PCode );
void RTL_Impl_TraceCommand( StarBASIC* pBasic, SbxArray& rPar, sal_Bool bWrite );
#endif

#endif
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include "OsiSolverInterface.hpp"
#include "OsiClpSolverInterface.hpp"
#include "CoinPackedMatrix.hpp"
#include "CoinModel.hpp"

#include "exchange_graph.h"
#include "equality_helpers.h"
#include "prog_translator.h"
#include "solver_factory.h"

namespace cyclus {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(ProgTranslatorTests, translation) {
  int narcs = 5;
  int nfaux = 2;
  int nrows = 8;

  double prefs [] = {0.2, 1.2, 4, 5, 1.3, -1, -1};
  double ucaps_a_0 [] = {0.5, 0.4};
  double ucaps_a_3 [] = {0.3, 0.6};
  double ucaps_b_1 [] = {0.9};
  double ucaps_b_2 [] = {0.8};
  double ucaps_b_4 [] = {0.7};
  double ucaps_c_0 [] = {0.7};
  double ucaps_c_1 [] = {0.8};
  double ucaps_c_2 [] = {0.9};
  double ucaps_d_3 [] = {1.3, 2};
  double ucaps_d_4 [] = {1.4, 1.9};
  double ucaps_5 [] = {1.0};
  double ucaps_6 [] = {1.0};

  double dem_a [] = {5.0, 4.9};
  double dem_b [] = {4.0};
  double sup_c [] = {10.0};
  double sup_d [] = {10.1, 9.1};

  int excl_arcs [] = {1, 2, 4};
  double excl_flow [] = {0, 2, 2, 0, 2, 0, 0};

  std::vector<double> obj_coeffs;
  for (int i = 0; i != narcs + nfaux; i++) {
    obj_coeffs.push_back((excl_flow[i] != 0) ?
                         excl_flow[i] * prefs[i] : prefs[i]);
  }

  ExchangeNode::Ptr a0(new ExchangeNode());
  ExchangeNode::Ptr a1(new ExchangeNode());
  ExchangeNode::Ptr b0(new ExchangeNode());
  ExchangeNode::Ptr b1(new ExchangeNode());
  ExchangeNode::Ptr c0(new ExchangeNode());
  ExchangeNode::Ptr c1(new ExchangeNode());
  ExchangeNode::Ptr c2(new ExchangeNode());
  ExchangeNode::Ptr d0(new ExchangeNode());
  ExchangeNode::Ptr d1(new ExchangeNode());

  Arc x0(a0, c0);
  Arc x1(b0, c1, true, excl_flow[1]);
  Arc x2(b1, c2, true, excl_flow[2]);
  Arc x3(a1, d0);
  Arc x4(b1, d1, true, excl_flow[4]);

  a0->unit_capacities[x0] = std::vector<double>(
      ucaps_a_0, ucaps_a_0 + sizeof(ucaps_a_0) / sizeof(ucaps_a_0[0]) );
  a1->unit_capacities[x3] = std::vector<double>(
      ucaps_a_3, ucaps_a_3 + sizeof(ucaps_a_3) / sizeof(ucaps_a_3[0]) );
  b0->unit_capacities[x1] = std::vector<double>(
      ucaps_b_1, ucaps_b_1 + sizeof(ucaps_b_1) / sizeof(ucaps_b_1[0]) );
  b1->unit_capacities[x2] = std::vector<double>(
      ucaps_b_2, ucaps_b_2 + sizeof(ucaps_b_2) / sizeof(ucaps_b_2[0]) );
  b1->unit_capacities[x4] = std::vector<double>(
      ucaps_b_4, ucaps_b_4 + sizeof(ucaps_b_4) / sizeof(ucaps_b_4[0]) );
  c0->unit_capacities[x0] = std::vector<double>(
      ucaps_c_0, ucaps_c_0 + sizeof(ucaps_c_0) / sizeof(ucaps_c_0[0]) );
  c1->unit_capacities[x1] = std::vector<double>(
      ucaps_c_1, ucaps_c_1 + sizeof(ucaps_c_1) / sizeof(ucaps_c_1[0]) );
  c2->unit_capacities[x2] = std::vector<double>(
      ucaps_c_2, ucaps_c_2 + sizeof(ucaps_c_2) / sizeof(ucaps_c_2[0]) );
  d0->unit_capacities[x3] = std::vector<double>(
      ucaps_d_3, ucaps_d_3 + sizeof(ucaps_d_3) / sizeof(ucaps_d_3[0]) );
  d1->unit_capacities[x4] = std::vector<double>(
      ucaps_d_4, ucaps_d_4 + sizeof(ucaps_d_4) / sizeof(ucaps_d_4[0]) );

  a0->prefs[x0] = prefs[0];
  b0->prefs[x1] = prefs[1];
  b1->prefs[x2] = prefs[2];
  a1->prefs[x3] = prefs[3];
  b1->prefs[x4] = prefs[4];

  RequestGroup::Ptr a(new RequestGroup()); // new RequestGroup(dem_a[0])?
  a->AddExchangeNode(a0);
  a->AddExchangeNode(a1);
  a->AddCapacity(dem_a[0]);
  a->AddCapacity(dem_a[1]);
  RequestGroup::Ptr b(new RequestGroup()); // new RequestGroup(dem_b[0])?
  b->AddExchangeNode(b0);
  b->AddExchangeNode(b1);
  b->AddCapacity(dem_b[0]);
  ExchangeNodeGroup::Ptr c(new ExchangeNodeGroup());
  c->AddExchangeNode(c0);
  c->AddExchangeNode(c1);
  c->AddExchangeNode(c2);
  c->AddCapacity(sup_c[0]);
  ExchangeNodeGroup::Ptr d(new ExchangeNodeGroup());
  d->AddExchangeNode(d0);
  d->AddExchangeNode(d1);
  d->AddCapacity(sup_d[0]);
  d->AddCapacity(sup_d[1]);

  ExchangeGraph g;
  g.AddRequestGroup(a);
  g.AddRequestGroup(b);
  g.AddSupplyGroup(c);
  g.AddSupplyGroup(d);
  g.AddArc(x0);
  g.AddArc(x1);
  g.AddArc(x2);
  g.AddArc(x3);
  g.AddArc(x4);

  SolverFactory sf;
  sf.solver_t("clp");
  OsiSolverInterface* iface = sf.get();
  bool excl = true;
  ProgTranslator pt(&g, iface, excl);
  EXPECT_NO_THROW(pt.Translate());

  double inf = iface->getInfinity();

  // test non-coin xlate members
  double col_lbs [] = {0, 0, 0, 0, 0, 0, 0};
  double col_ubs [] = {inf, 1, 1, inf, 1, inf, inf};
  double row_lbs [] = {0, 0, 0, dem_a[0], dem_a[1], dem_b[0], 0, 0};
  double row_ubs [] = {sup_c[0], sup_d[0], sup_d[1], inf, inf, inf, 1, 1};
  array_double_eq(&obj_coeffs[0], &pt.ctx().obj_coeffs[0], narcs + nfaux, "obj");
  array_double_eq(col_ubs, &pt.ctx().col_ubs[0], narcs + nfaux, "col_ub");
  array_double_eq(col_lbs, &pt.ctx().col_lbs[0], narcs + nfaux, "col_lb");
  array_double_eq(row_ubs, &pt.ctx().row_ubs[0], nrows, "row_ub");
  array_double_eq(row_lbs, &pt.ctx().row_lbs[0], nrows, "row_lb");

  // test coin xlate members
  CoinPackedMatrix m(false, 0, 0);
  m.setDimensions(0, narcs + nfaux);

  int row_ind_0 [] = {0, 1, 2};
  double row_val_0 [] = {ucaps_c_0[0],
                         ucaps_c_1[0] * excl_flow[1],
                         ucaps_c_2[0] * excl_flow[2]};
  m.appendRow(3, row_ind_0, row_val_0);

  int row_ind_1 [] = {3, 4};
  double row_val_1 [] = {ucaps_d_3[0],
                         ucaps_d_4[0] * excl_flow[4]};
  m.appendRow(2, row_ind_1, row_val_1);

  int row_ind_2 [] = {3, 4};
  double row_val_2 [] = {ucaps_d_3[1],
                         ucaps_d_4[1] * excl_flow[4]};
  m.appendRow(2, row_ind_2, row_val_2);

  int row_ind_3 [] = {0, 3, 5};
  double row_val_3 [] = {ucaps_a_0[0], ucaps_a_3[0], 1};
  m.appendRow(3, row_ind_3, row_val_3);

  int row_ind_4 [] = {0, 3, 5};
  double row_val_4 [] = {ucaps_a_0[1], ucaps_a_3[1], 1};
  m.appendRow(3, row_ind_4, row_val_4);

  int row_ind_5 [] = {1, 2, 4, 6};
  double row_val_5 [] = {ucaps_b_1[0] * excl_flow[1],
                         ucaps_b_2[0] * excl_flow[2],
                         ucaps_b_4[0] * excl_flow[4],
                         1};
  m.appendRow(4, row_ind_5, row_val_5);

  int row_ind_6 [] = {1};
  double row_val_6 [] = {1};
  m.appendRow(1, row_ind_6, row_val_6);

  int row_ind_7 [] = {2, 4};
  double row_val_7 [] = {1, 1};
  m.appendRow(2, row_ind_7, row_val_7);

  EXPECT_TRUE(m.isEquivalent2(pt.ctx().m));

  // test population
  EXPECT_NO_THROW(pt.Populate());

  CoinModel model(nrows, narcs + nfaux, &m, &row_lbs[0], &row_ubs[0],
                  &col_lbs[0], &col_ubs[0], &obj_coeffs[0]);
  ClpSimplex* compare = dynamic_cast<OsiClpSolverInterface*>(iface)->getModelPtr();
  // EXPECT_EQ(0, model.differentModel(*(compare->createCoinModel()), true));

  delete iface;
};

} // namespace cyclus
<commit_msg>ok, all testing plumbing in, and will fully pass once coin model equality testing is clarified on the coin mailing list<commit_after>#include <gtest/gtest.h>

#include "OsiSolverInterface.hpp"
#include "OsiClpSolverInterface.hpp"
#include "CoinPackedMatrix.hpp"
#include "CoinModel.hpp"

#include "exchange_graph.h"
#include "equality_helpers.h"
#include "prog_translator.h"
#include "solver_factory.h"

namespace cyclus {

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TEST(ProgTranslatorTests, translation) {
  int narcs = 5;
  int nfaux = 2;
  int nrows = 8;
  int nexcl = 3;

  double prefs [] = {0.2, 1.2, 4, 5, 1.3, -1, -1};
  double ucaps_a_0 [] = {0.5, 0.4};
  double ucaps_a_3 [] = {0.3, 0.6};
  double ucaps_b_1 [] = {0.9};
  double ucaps_b_2 [] = {0.8};
  double ucaps_b_4 [] = {0.7};
  double ucaps_c_0 [] = {0.7};
  double ucaps_c_1 [] = {0.8};
  double ucaps_c_2 [] = {0.9};
  double ucaps_d_3 [] = {1.3, 2};
  double ucaps_d_4 [] = {1.4, 1.9};
  double ucaps_5 [] = {1.0};
  double ucaps_6 [] = {1.0};

  double dem_a [] = {5.0, 4.9};
  double dem_b [] = {4.0};
  double sup_c [] = {10.0};
  double sup_d [] = {10.1, 9.1};

  int excl_arcs [] = {1, 2, 4};
  double excl_flow [] = {0, 2, 2, 0, 2, 0, 0};

  std::vector<double> obj_coeffs;
  for (int i = 0; i != narcs + nfaux; i++) {
    obj_coeffs.push_back((excl_flow[i] != 0) ?
                         excl_flow[i] * prefs[i] : prefs[i]);
  }

  ExchangeNode::Ptr a0(new ExchangeNode());
  ExchangeNode::Ptr a1(new ExchangeNode());
  ExchangeNode::Ptr b0(new ExchangeNode());
  ExchangeNode::Ptr b1(new ExchangeNode());
  ExchangeNode::Ptr c0(new ExchangeNode());
  ExchangeNode::Ptr c1(new ExchangeNode());
  ExchangeNode::Ptr c2(new ExchangeNode());
  ExchangeNode::Ptr d0(new ExchangeNode());
  ExchangeNode::Ptr d1(new ExchangeNode());

  Arc x0(a0, c0);
  Arc x1(b0, c1, true, excl_flow[1]);
  Arc x2(b1, c2, true, excl_flow[2]);
  Arc x3(a1, d0);
  Arc x4(b1, d1, true, excl_flow[4]);

  a0->unit_capacities[x0] = std::vector<double>(
      ucaps_a_0, ucaps_a_0 + sizeof(ucaps_a_0) / sizeof(ucaps_a_0[0]) );
  a1->unit_capacities[x3] = std::vector<double>(
      ucaps_a_3, ucaps_a_3 + sizeof(ucaps_a_3) / sizeof(ucaps_a_3[0]) );
  b0->unit_capacities[x1] = std::vector<double>(
      ucaps_b_1, ucaps_b_1 + sizeof(ucaps_b_1) / sizeof(ucaps_b_1[0]) );
  b1->unit_capacities[x2] = std::vector<double>(
      ucaps_b_2, ucaps_b_2 + sizeof(ucaps_b_2) / sizeof(ucaps_b_2[0]) );
  b1->unit_capacities[x4] = std::vector<double>(
      ucaps_b_4, ucaps_b_4 + sizeof(ucaps_b_4) / sizeof(ucaps_b_4[0]) );
  c0->unit_capacities[x0] = std::vector<double>(
      ucaps_c_0, ucaps_c_0 + sizeof(ucaps_c_0) / sizeof(ucaps_c_0[0]) );
  c1->unit_capacities[x1] = std::vector<double>(
      ucaps_c_1, ucaps_c_1 + sizeof(ucaps_c_1) / sizeof(ucaps_c_1[0]) );
  c2->unit_capacities[x2] = std::vector<double>(
      ucaps_c_2, ucaps_c_2 + sizeof(ucaps_c_2) / sizeof(ucaps_c_2[0]) );
  d0->unit_capacities[x3] = std::vector<double>(
      ucaps_d_3, ucaps_d_3 + sizeof(ucaps_d_3) / sizeof(ucaps_d_3[0]) );
  d1->unit_capacities[x4] = std::vector<double>(
      ucaps_d_4, ucaps_d_4 + sizeof(ucaps_d_4) / sizeof(ucaps_d_4[0]) );

  a0->prefs[x0] = prefs[0];
  b0->prefs[x1] = prefs[1];
  b1->prefs[x2] = prefs[2];
  a1->prefs[x3] = prefs[3];
  b1->prefs[x4] = prefs[4];

  RequestGroup::Ptr a(new RequestGroup()); // new RequestGroup(dem_a[0])?
  a->AddExchangeNode(a0);
  a->AddExchangeNode(a1);
  a->AddCapacity(dem_a[0]);
  a->AddCapacity(dem_a[1]);
  RequestGroup::Ptr b(new RequestGroup()); // new RequestGroup(dem_b[0])?
  b->AddExchangeNode(b0);
  b->AddExchangeNode(b1);
  b->AddCapacity(dem_b[0]);
  ExchangeNodeGroup::Ptr c(new ExchangeNodeGroup());
  c->AddExchangeNode(c0);
  c->AddExchangeNode(c1);
  c->AddExchangeNode(c2);
  c->AddCapacity(sup_c[0]);
  ExchangeNodeGroup::Ptr d(new ExchangeNodeGroup());
  d->AddExchangeNode(d0);
  d->AddExchangeNode(d1);
  d->AddCapacity(sup_d[0]);
  d->AddCapacity(sup_d[1]);

  ExchangeGraph g;
  g.AddRequestGroup(a);
  g.AddRequestGroup(b);
  g.AddSupplyGroup(c);
  g.AddSupplyGroup(d);
  g.AddArc(x0);
  g.AddArc(x1);
  g.AddArc(x2);
  g.AddArc(x3);
  g.AddArc(x4);

  SolverFactory sf;
  sf.solver_t("clp");
  OsiSolverInterface* iface = sf.get();
  bool excl = true;
  ProgTranslator pt(&g, iface, excl);
  EXPECT_NO_THROW(pt.Translate());

  double inf = iface->getInfinity();

  // test non-coin xlate members
  double col_lbs [] = {0, 0, 0, 0, 0, 0, 0};
  double col_ubs [] = {inf, 1, 1, inf, 1, inf, inf};
  double row_lbs [] = {0, 0, 0, dem_a[0], dem_a[1], dem_b[0], 0, 0};
  double row_ubs [] = {sup_c[0], sup_d[0], sup_d[1], inf, inf, inf, 1, 1};
  array_double_eq(&obj_coeffs[0], &pt.ctx().obj_coeffs[0], narcs + nfaux, "obj");
  array_double_eq(col_ubs, &pt.ctx().col_ubs[0], narcs + nfaux, "col_ub");
  array_double_eq(col_lbs, &pt.ctx().col_lbs[0], narcs + nfaux, "col_lb");
  array_double_eq(row_ubs, &pt.ctx().row_ubs[0], nrows, "row_ub");
  array_double_eq(row_lbs, &pt.ctx().row_lbs[0], nrows, "row_lb");

  // test coin xlate members
  CoinPackedMatrix m(false, 0, 0);
  m.setDimensions(0, narcs + nfaux);

  int row_ind_0 [] = {0, 1, 2};
  double row_val_0 [] = {ucaps_c_0[0],
                         ucaps_c_1[0] * excl_flow[1],
                         ucaps_c_2[0] * excl_flow[2]};
  m.appendRow(3, row_ind_0, row_val_0);

  int row_ind_1 [] = {3, 4};
  double row_val_1 [] = {ucaps_d_3[0],
                         ucaps_d_4[0] * excl_flow[4]};
  m.appendRow(2, row_ind_1, row_val_1);

  int row_ind_2 [] = {3, 4};
  double row_val_2 [] = {ucaps_d_3[1],
                         ucaps_d_4[1] * excl_flow[4]};
  m.appendRow(2, row_ind_2, row_val_2);

  int row_ind_3 [] = {0, 3, 5};
  double row_val_3 [] = {ucaps_a_0[0], ucaps_a_3[0], 1};
  m.appendRow(3, row_ind_3, row_val_3);

  int row_ind_4 [] = {0, 3, 5};
  double row_val_4 [] = {ucaps_a_0[1], ucaps_a_3[1], 1};
  m.appendRow(3, row_ind_4, row_val_4);

  int row_ind_5 [] = {1, 2, 4, 6};
  double row_val_5 [] = {ucaps_b_1[0] * excl_flow[1],
                         ucaps_b_2[0] * excl_flow[2],
                         ucaps_b_4[0] * excl_flow[4],
                         1};
  m.appendRow(4, row_ind_5, row_val_5);

  int row_ind_6 [] = {1};
  double row_val_6 [] = {1};
  m.appendRow(1, row_ind_6, row_val_6);

  int row_ind_7 [] = {2, 4};
  double row_val_7 [] = {1, 1};
  m.appendRow(2, row_ind_7, row_val_7);

  EXPECT_TRUE(m.isEquivalent2(pt.ctx().m));

  // test population
  EXPECT_NO_THROW(pt.Populate());

  CoinModel model(nrows, narcs + nfaux, &m, &row_lbs[0], &row_ubs[0],
                  &col_lbs[0], &col_ubs[0], &obj_coeffs[0]);
  ClpSimplex* compare = dynamic_cast<OsiClpSolverInterface*>(iface)->getModelPtr();

  for (int i = 0; i != nexcl; i++) {
    EXPECT_TRUE(iface->isInteger(excl_arcs[i]));
  }

  // CoinModel* test = compare->createCoinModel();
  // EXPECT_EQ(0, model.differentModel(*test, true));

  delete iface;
};

} // namespace cyclus
<|endoftext|>


<commit_before>/** \file urdf_loader.cpp
 * \brief Implementation of a URDF loading plugin for OpenRAVE
 * \author Pras Velagapudi
 * \date 2013
 */

/* (C) Copyright 2013 Carnegie Mellon University */

#include "urdf_loader.h"

namespace urdf_loader
{

  /** Opens a URDF file and returns a robot in OpenRAVE */
  bool URDFLoader::load(std::ostream& sout, std::istream& sin)
  {
    // Get filename from input arguments

    // Parse file via XML

    // Recursively construct robot from XML

    // Return reference to created object

    return true;
  }

} /* namespace orcdchomp */
<commit_msg>Fixed missing definitions so OpenRAVE now loads the plugin.<commit_after>/** \file urdf_loader.cpp
 * \brief Implementation of a URDF loading plugin for OpenRAVE
 * \author Pras Velagapudi
 * \date 2013
 */

/* (C) Copyright 2013 Carnegie Mellon University */

#include "urdf_loader.h"

/** Boilerplate plugin definition for OpenRAVE */
OpenRAVE::InterfaceBasePtr CreateInterfaceValidated(OpenRAVE::InterfaceType type, const std::string& interfacename, std::istream& sinput, OpenRAVE::EnvironmentBasePtr env)
{
  if( type == OpenRAVE::PT_Module && interfacename == "urdfloader" ) {
    return OpenRAVE::InterfaceBasePtr(new urdf_loader::URDFLoader(env));
  }
}

/** Boilerplate plugin definition for OpenRAVE */
void GetPluginAttributesValidated(OpenRAVE::PLUGININFO& info)
{
  info.interfacenames[OpenRAVE::PT_Module].push_back("URDFLoader");
}

namespace urdf_loader
{

  /** Opens a URDF file and returns a robot in OpenRAVE */
  bool URDFLoader::load(std::ostream& sout, std::istream& sin)
  {
    // Get filename from input arguments

    // Parse file via XML

    // Recursively construct robot from XML

    // Return reference to created object

    return true;
  }

} /* namespace orcdchomp */
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * 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.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#include <crossbow/program_options.hpp>
#include <crossbow/logger.hpp>

#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <string>
#include <iostream>
#include <cassert>
#include <fstream>

#include <common/Util.hpp>

#include "Client.hpp"

using namespace crossbow::program_options;
using namespace boost::asio;
using err_code = boost::system::error_code;

int main(int argc, const char** argv) {
    bool help = false;
    bool populate = false;
    bool useCHTables = false;
    int16_t numWarehouses = 1;
    crossbow::string host;
    std::string port("8713");
    std::string logLevel("DEBUG");
    std::string outFile("out.csv");
    size_t numClients = 1;
    unsigned time = 5*60;
    bool exit = false;
    auto opts = create_options("tpcc_client",
            value<'h'>("help", &help, tag::description{"print help"})
            , value<'H'>("host", &host, tag::description{"Comma-separated list of hosts"})
            , value<'l'>("log-level", &logLevel, tag::description{"The log level"})
            , value<'c'>("num-clients", &numClients, tag::description{"Number of Clients to run per host"})
            , value<'P'>("populate", &populate, tag::description{"Populate the database"})
            , value<'W'>("num-warehouses", &numWarehouses, tag::description{"Number of warehouses"})
            , value<'t'>("time", &time, tag::description{"Duration of the benchmark in seconds"})
            , value<'o'>("out", &outFile, tag::description{"Path to the output file"})
            , value<-1>("exit", &exit, tag::description{"Quit server"})
            , value<'a'>("ch-bench-analytics", &useCHTables,
                         tag::description{"Populate the database witht he additional tables used in the CHBenchmark"})
            );
    try {
        parse(opts, argc, argv);
    } catch (argument_not_found& e) {
        std::cerr << e.what() << std::endl << std::endl;
        print_help(std::cout, opts);
        return 1;
    }
    if (help) {
        print_help(std::cout, opts);
        return 0;
    }
    if (host.empty()) {
        std::cerr << "No host\n";
        return 1;
    }
    auto startTime = tpcc::Clock::now();
    auto endTime = startTime + std::chrono::seconds(time);
    crossbow::logger::logger->config.level = crossbow::logger::logLevelFromString(logLevel);
    try {
        auto hosts = tpcc::split(host.c_str(), ',');
        io_service service;
        auto sumClients = hosts.size() * numClients;
        std::vector<tpcc::Client> clients;
        clients.reserve(sumClients);
        auto wareHousesPerClient = numWarehouses / sumClients;
        for (decltype(sumClients) i = 0; i < sumClients; ++i) {
            if (i >= unsigned(numWarehouses)) break;
            clients.emplace_back(service, numWarehouses, int16_t(wareHousesPerClient * i + 1), int16_t(wareHousesPerClient * (i + 1)), endTime);
        }
        for (size_t i = 0; i < hosts.size(); ++i) {
            auto h = hosts[i];
            auto addr = tpcc::split(h, ':');
            assert(addr.size() <= 2);
            auto p = addr.size() == 2 ? addr[1] : port;
            ip::tcp::resolver resolver(service);
            ip::tcp::resolver::iterator iter;
            if (host == "") {
                iter = resolver.resolve(ip::tcp::resolver::query(p));
            } else {
                iter = resolver.resolve(ip::tcp::resolver::query(addr[0], p));
            }
            for (unsigned j = 0; j < numClients; ++j) {
                LOG_INFO("Connected to client " + crossbow::to_string(i*numClients + j));
                boost::asio::connect(clients[i*numClients + j].socket(), iter);
            }
        }

        {
            auto t = std::time(nullptr);
            std::string dateString(20, '\0');
            auto len = std::strftime(&dateString.front(), 20, "%T", std::localtime(&t));
            dateString.resize(len);
            LOG_INFO("Starting client at %1%", dateString);
        }

        if (exit) {
            for (auto& client : clients) {
                auto& cmds = client.commands();
                cmds.execute<tpcc::Command::EXIT>([](const err_code& ec){
                    if (ec) {
                        std::cerr << "ERROR: " << ec.message() << std::endl;
                    }
                });
                goto END;
            }
        }

        if (populate) {
            auto& cmds = clients[0].commands();
            cmds.execute<tpcc::Command::CREATE_SCHEMA>(
                    [&clients, &useCHTables](const err_code& ec,
                        const std::tuple<bool, crossbow::string>& res){
                if (ec) {
                    LOG_ERROR(ec.message());
                    return;
                }
                if (!std::get<0>(res)) {
                    LOG_ERROR(std::get<1>(res));
                    return;
                }

                auto& cmds = clients[0].commands();
                cmds.execute<tpcc::Command::POPULATE_DIM_TABLES>([&clients, &useCHTables](const err_code& ec, const std::tuple<bool, crossbow::string>& res){
                    if (ec) {
                        LOG_ERROR(ec.message());
                        return;
                    }
                    if (!std::get<0>(res)) {
                        LOG_ERROR(std::get<1>(res));
                        return;
                    }

                    for (auto& client : clients) {
                        client.populate(useCHTables);
                    }
                }, useCHTables);
            }, useCHTables);
        } else {
            for (decltype(clients.size()) i = 0; i < clients.size(); ++i) {
                auto& client = clients[i];
                client.run();
            }
        }
END:
        service.run();
        LOG_INFO("Done, writing results");
        std::ofstream out(outFile.c_str());
        out << "start,end,transaction,success,error\n";
        for (const auto& client : clients) {
            const auto& queue = client.log();
            for (const auto& e : queue) {
                crossbow::string tName;
                switch (e.transaction) {
                case tpcc::Command::POPULATE_WAREHOUSE:
                    tName = "Populate";
                    break;
                case tpcc::Command::POPULATE_DIM_TABLES:
                    tName = "Populate";
                    break;
                case tpcc::Command::CREATE_SCHEMA:
                    tName = "Schema Create";
                    break;
                case tpcc::Command::STOCK_LEVEL:
                    tName = "Stock Level";
                    break;
                case tpcc::Command::DELIVERY:
                    tName = "Delivery";
                    break;
                case tpcc::Command::NEW_ORDER:
                    tName = "New Order";
                    break;
                case tpcc::Command::ORDER_STATUS:
                    tName = "Order Status";
                    break;
                case tpcc::Command::PAYMENT:
                    tName = "Payment";
                    break;
                case tpcc::Command::EXIT:
                    assert(false);
                    break;
                }
                out << std::chrono::duration_cast<std::chrono::milliseconds>(e.start - startTime).count() << ','
                    << std::chrono::duration_cast<std::chrono::milliseconds>(e.end - startTime).count() << ','
                    << tName << ','
                    << (e.success ? "true" : "false") << ','
                    << e.error << std::endl;
            }
        }
        std::cout << '\a';
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
}
<commit_msg>removed undividable number of warehouses bug<commit_after>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * 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.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#include <crossbow/program_options.hpp>
#include <crossbow/logger.hpp>

#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <string>
#include <iostream>
#include <cassert>
#include <fstream>

#include <common/Util.hpp>

#include "Client.hpp"

using namespace crossbow::program_options;
using namespace boost::asio;
using err_code = boost::system::error_code;

int main(int argc, const char** argv) {
    bool help = false;
    bool populate = false;
    bool useCHTables = false;
    int16_t numWarehouses = 1;
    crossbow::string host;
    std::string port("8713");
    std::string logLevel("DEBUG");
    std::string outFile("out.csv");
    size_t numClients = 1;
    unsigned time = 5*60;
    bool exit = false;
    auto opts = create_options("tpcc_client",
            value<'h'>("help", &help, tag::description{"print help"})
            , value<'H'>("host", &host, tag::description{"Comma-separated list of hosts"})
            , value<'l'>("log-level", &logLevel, tag::description{"The log level"})
            , value<'c'>("num-clients", &numClients, tag::description{"Number of Clients to run per host"})
            , value<'P'>("populate", &populate, tag::description{"Populate the database"})
            , value<'W'>("num-warehouses", &numWarehouses, tag::description{"Number of warehouses"})
            , value<'t'>("time", &time, tag::description{"Duration of the benchmark in seconds"})
            , value<'o'>("out", &outFile, tag::description{"Path to the output file"})
            , value<-1>("exit", &exit, tag::description{"Quit server"})
            , value<'a'>("ch-bench-analytics", &useCHTables,
                         tag::description{"Populate the database witht he additional tables used in the CHBenchmark"})
            );
    try {
        parse(opts, argc, argv);
    } catch (argument_not_found& e) {
        std::cerr << e.what() << std::endl << std::endl;
        print_help(std::cout, opts);
        return 1;
    }
    if (help) {
        print_help(std::cout, opts);
        return 0;
    }
    if (host.empty()) {
        std::cerr << "No host\n";
        return 1;
    }
    auto startTime = tpcc::Clock::now();
    auto endTime = startTime + std::chrono::seconds(time);
    crossbow::logger::logger->config.level = crossbow::logger::logLevelFromString(logLevel);
    try {
        auto hosts = tpcc::split(host.c_str(), ',');
        io_service service;
        auto sumClients = hosts.size() * numClients;
        std::vector<tpcc::Client> clients;
        clients.reserve(sumClients);
        auto wareHousesPerClient = numWarehouses / sumClients;
        for (decltype(sumClients) i = 0; i < sumClients; ++i) {
            if (i >= unsigned(numWarehouses)) break;
            int16_t lastWarehouse =  wareHousesPerClient * (i + 1);
            if (i == sumClients - 1) lastWarehouse = numWarehouses;
            clients.emplace_back(service, numWarehouses, int16_t(wareHousesPerClient * i + 1), lastWarehouse, endTime);
        }
        for (size_t i = 0; i < hosts.size(); ++i) {
            auto h = hosts[i];
            auto addr = tpcc::split(h, ':');
            assert(addr.size() <= 2);
            auto p = addr.size() == 2 ? addr[1] : port;
            ip::tcp::resolver resolver(service);
            ip::tcp::resolver::iterator iter;
            if (host == "") {
                iter = resolver.resolve(ip::tcp::resolver::query(p));
            } else {
                iter = resolver.resolve(ip::tcp::resolver::query(addr[0], p));
            }
            for (unsigned j = 0; j < numClients; ++j) {
                LOG_INFO("Connected to client " + crossbow::to_string(i*numClients + j));
                boost::asio::connect(clients[i*numClients + j].socket(), iter);
            }
        }

        {
            auto t = std::time(nullptr);
            std::string dateString(20, '\0');
            auto len = std::strftime(&dateString.front(), 20, "%T", std::localtime(&t));
            dateString.resize(len);
            LOG_INFO("Starting client at %1%", dateString);
        }

        if (exit) {
            for (auto& client : clients) {
                auto& cmds = client.commands();
                cmds.execute<tpcc::Command::EXIT>([](const err_code& ec){
                    if (ec) {
                        std::cerr << "ERROR: " << ec.message() << std::endl;
                    }
                });
                goto END;
            }
        }

        if (populate) {
            auto& cmds = clients[0].commands();
            cmds.execute<tpcc::Command::CREATE_SCHEMA>(
                    [&clients, &useCHTables](const err_code& ec,
                        const std::tuple<bool, crossbow::string>& res){
                if (ec) {
                    LOG_ERROR(ec.message());
                    return;
                }
                if (!std::get<0>(res)) {
                    LOG_ERROR(std::get<1>(res));
                    return;
                }

                auto& cmds = clients[0].commands();
                cmds.execute<tpcc::Command::POPULATE_DIM_TABLES>([&clients, &useCHTables](const err_code& ec, const std::tuple<bool, crossbow::string>& res){
                    if (ec) {
                        LOG_ERROR(ec.message());
                        return;
                    }
                    if (!std::get<0>(res)) {
                        LOG_ERROR(std::get<1>(res));
                        return;
                    }

                    for (auto& client : clients) {
                        client.populate(useCHTables);
                    }
                }, useCHTables);
            }, useCHTables);
        } else {
            for (decltype(clients.size()) i = 0; i < clients.size(); ++i) {
                auto& client = clients[i];
                client.run();
            }
        }
END:
        service.run();
        LOG_INFO("Done, writing results");
        std::ofstream out(outFile.c_str());
        out << "start,end,transaction,success,error\n";
        for (const auto& client : clients) {
            const auto& queue = client.log();
            for (const auto& e : queue) {
                crossbow::string tName;
                switch (e.transaction) {
                case tpcc::Command::POPULATE_WAREHOUSE:
                    tName = "Populate";
                    break;
                case tpcc::Command::POPULATE_DIM_TABLES:
                    tName = "Populate";
                    break;
                case tpcc::Command::CREATE_SCHEMA:
                    tName = "Schema Create";
                    break;
                case tpcc::Command::STOCK_LEVEL:
                    tName = "Stock Level";
                    break;
                case tpcc::Command::DELIVERY:
                    tName = "Delivery";
                    break;
                case tpcc::Command::NEW_ORDER:
                    tName = "New Order";
                    break;
                case tpcc::Command::ORDER_STATUS:
                    tName = "Order Status";
                    break;
                case tpcc::Command::PAYMENT:
                    tName = "Payment";
                    break;
                case tpcc::Command::EXIT:
                    assert(false);
                    break;
                }
                out << std::chrono::duration_cast<std::chrono::milliseconds>(e.start - startTime).count() << ','
                    << std::chrono::duration_cast<std::chrono::milliseconds>(e.end - startTime).count() << ','
                    << tName << ','
                    << (e.success ? "true" : "false") << ','
                    << e.error << std::endl;
            }
        }
        std::cout << '\a';
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <pthread.h>
#include <time.h>
#include <string>
#include "linenoise.h"
#include "process.h"

#if defined(__DATE__) && defined(__TIME__)
static const char SERVER_BUILT[] = __DATE__ " " __TIME__;
#else
static const char SERVER_BUILT[] = "unknown";
#endif

#ifdef VERSION
const char *VERSION_ID = VERSION;
#else
const char *VERSION_ID = "unknown";
#endif

static void dn_print_version(void)
{
        printf(" Version\t:\t%s\n", VERSION_ID);
        printf(" Built date\t:\t%s\n", SERVER_BUILT);
}

void dn_print_help(void)
{
        printf( "%s", "usage\n");
        printf( "%s", "    --help     | -h     :      print help message\n");
        printf( "%s", "    --version  | -v     :      print version\n");
        printf( "%s", "    --ip       | -i     :      host ip\n");
        printf( "%s", "    --port     | -p     :      host port\n");
        printf( "%s", "    --command  | -c     :      execute command\n");
}

int main(int argc, char **argv)
{
    char c;
    const char* const short_options = "vhc:i:p:";
    const struct option long_options[] =
    {
         {"version", no_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
         {"ip", optional_argument, NULL, 'i'},
         {"port", optional_argument, NULL, 'p'},
         {"command", optional_argument, NULL, 'c'},
         {0, 0, 0, 0}
    };
    std::string ip = "127.0.0.1";
    int port = 3234;
    std::string command = "";
    bool flag = false;
    while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
    {
        switch (c)
        {
            case 'h':
                dn_print_help();
                exit(1);
            case 'v':
                dn_print_version();
                exit(1);
            case 'c':
                command = optarg;
                flag = true;
                break;
            case 'i':
                ip = optarg;
                break;
            case 'p':
                port = atoi(optarg);
                break;
            default:
                dn_print_help();
                exit(1);
        }
    }
    SocketClient client;
    if (!client.init("client", ip.c_str(), port, 1, 200, 10000, 100)) {
        printf("connect %s:%d error\n", ip.c_str(), port);
        exit(1);
    }
    char* res = NULL;
    res = new(std::nothrow) char[100 * 1024 + 1];
    if (res == NULL) {
        printf("new buffer error\n");
        exit(1);
    }
    // if input is command mode then execute the command
    if (flag) {
        // process command
        process(&client, res, ip, port, command);
        exit(1);
    }
    linenoiseHistoryLoad(".tinytable_history");
    char *line;
    char info[100];
    snprintf(info, sizeof(info), "%s:%d> ", ip.c_str(), port);
    while((line = linenoise(info)) != NULL) {
        if (line[0] != '\0' && line[0] != '/') {
            linenoiseHistoryAdd(line); /* Add to the history. */
            linenoiseHistorySave(".tinytable_history"); /* Save the history on disk. */
        }
        process(&client, res, ip, port, line);
        free(line);
    }
    return 0;
}
<commit_msg>modify func<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <pthread.h>
#include <time.h>
#include <string>
#include "linenoise.h"
#include "process.h"

#if defined(__DATE__) && defined(__TIME__)
static const char SERVER_BUILT[] = __DATE__ " " __TIME__;
#else
static const char SERVER_BUILT[] = "unknown";
#endif

#ifdef VERSION
const char *VERSION_ID = VERSION;
#else
const char *VERSION_ID = "unknown";
#endif

static void print_version(void)
{
        printf(" Version\t:\t%s\n", VERSION_ID);
        printf(" Built date\t:\t%s\n", SERVER_BUILT);
}

void print_help(void)
{
        printf( "%s", "usage\n");
        printf( "%s", "    --help     | -h     :      print help message\n");
        printf( "%s", "    --version  | -v     :      print version\n");
        printf( "%s", "    --ip       | -i     :      host ip\n");
        printf( "%s", "    --port     | -p     :      host port\n");
        printf( "%s", "    --command  | -c     :      execute command\n");
}

int main(int argc, char **argv)
{
    char c;
    const char* const short_options = "vhc:i:p:";
    const struct option long_options[] =
    {
         {"version", no_argument, NULL, 'v'},
         {"help", no_argument, NULL, 'h'},
         {"ip", optional_argument, NULL, 'i'},
         {"port", optional_argument, NULL, 'p'},
         {"command", optional_argument, NULL, 'c'},
         {0, 0, 0, 0}
    };
    std::string ip = "127.0.0.1";
    int port = 3234;
    std::string command = "";
    bool flag = false;
    while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
    {
        switch (c)
        {
            case 'h':
                print_help();
                exit(1);
            case 'v':
                print_version();
                exit(1);
            case 'c':
                command = optarg;
                flag = true;
                break;
            case 'i':
                ip = optarg;
                break;
            case 'p':
                port = atoi(optarg);
                break;
            default:
                print_help();
                exit(1);
        }
    }
    SocketClient client;
    if (!client.init("client", ip.c_str(), port, 1, 200, 10000, 100)) {
        printf("connect %s:%d error\n", ip.c_str(), port);
        exit(1);
    }
    char* res = NULL;
    res = new(std::nothrow) char[100 * 1024 + 1];
    if (res == NULL) {
        printf("new buffer error\n");
        exit(1);
    }
    // if input is command mode then execute the command
    if (flag) {
        // process command
        process(&client, res, ip, port, command);
        exit(1);
    }
    linenoiseHistoryLoad(".tinytable_history");
    char *line;
    char info[100];
    snprintf(info, sizeof(info), "%s:%d> ", ip.c_str(), port);
    while((line = linenoise(info)) != NULL) {
        if (line[0] != '\0' && line[0] != '/') {
            linenoiseHistoryAdd(line); /* Add to the history. */
            linenoiseHistorySave(".tinytable_history"); /* Save the history on disk. */
        }
        process(&client, res, ip, port, line);
        free(line);
    }
    return 0;
}
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "libtorrent/pch.hpp"

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

#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <vector>
#include <utility>
#include <numeric>
#include <cstdio>

#include "libtorrent/peer_connection.hpp"
#include "libtorrent/bt_peer_connection.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/extensions/ut_metadata.hpp"
#include "libtorrent/alert_types.hpp"
#ifdef TORRENT_STATS
#include "libtorrent/aux_/session_impl.hpp"
#endif

namespace libtorrent { namespace
{
	int div_round_up(int numerator, int denominator)
	{
		return (numerator + denominator - 1) / denominator;
	}

	void nop(char*) {}

	struct ut_metadata_plugin : torrent_plugin
	{
		ut_metadata_plugin(torrent& t)
			: m_torrent(t)
			, m_metadata_progress(0)
			, m_metadata_size(0)
		{
		}

		virtual void on_files_checked()
		{
			// if the torrent is a seed, copy the metadata from
			// the torrent before it is deallocated
			if (m_torrent.is_seed())
				metadata();
		}

		virtual boost::shared_ptr<peer_plugin> new_connection(
			peer_connection* pc);

		buffer::const_interval metadata() const
		{
			TORRENT_ASSERT(m_torrent.valid_metadata());
			if (!m_metadata)
			{
				m_metadata = m_torrent.torrent_file().metadata();
				m_metadata_size = m_torrent.torrent_file().metadata_size();
				TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
					== m_torrent.torrent_file().info_hash());
			}
			return buffer::const_interval(m_metadata.get(), m_metadata.get()
				+ m_metadata_size);
		}

		bool received_metadata(char const* buf, int size, int piece, int total_size)
		{
			if (m_torrent.valid_metadata()) return false;

			if (!m_metadata)
			{
				// verify the total_size
				if (total_size <= 0 || total_size > 500 * 1024) return false;

				m_metadata.reset(new char[total_size]);
				m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0);
				m_metadata_size = total_size;
			}

			if (piece < 0 || piece >= int(m_requested_metadata.size()))
				return false;

			TORRENT_ASSERT(piece * 16 * 1024 + size <= m_metadata_size);
			std::memcpy(&m_metadata[piece * 16 * 1024], buf, size);
			// mark this piece has 'have'
			m_requested_metadata[piece] = (std::numeric_limits<int>::max)();

			bool have_all = std::count(m_requested_metadata.begin()
				, m_requested_metadata.end(), (std::numeric_limits<int>::max)())
				== int(m_requested_metadata.size());

			if (!have_all) return false;

			if (!m_torrent.set_metadata(&m_metadata[0], m_metadata_size))
			{
				if (!m_torrent.valid_metadata())
					std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0);
				return false;
			}

			// clear the storage for the bitfield
			std::vector<int>().swap(m_requested_metadata);

			return true;
		}

		// returns a piece of the metadata that
		// we should request.
		int metadata_request();

		// this is called from the peer_connection for
		// each piece of metadata it receives
		void metadata_progress(int total_size, int received)
		{
			m_metadata_progress += received;
			m_metadata_size = total_size;
		}

		void on_piece_pass(int)
		{
			// if we became a seed, copy the metadata from
			// the torrent before it is deallocated
			if (m_torrent.is_seed())
				metadata();
		}

		void metadata_size(int size)
		{
			if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return;
			m_metadata_size = size;
			m_metadata.reset(new char[size]);
			m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0);
		}

	private:
		torrent& m_torrent;

		// this buffer is filled with the info-section of
		// the metadata file while downloading it from
		// peers, and while sending it.
		// it is mutable because it's generated lazily
		mutable boost::shared_array<char> m_metadata;

		int m_metadata_progress;
		mutable int m_metadata_size;

		// this vector keeps track of how many times each meatdata
		// block has been requested
		// std::numeric_limits<int>::max() means we have the piece
		std::vector<int> m_requested_metadata;
	};

	struct ut_metadata_peer_plugin : peer_plugin
	{
		ut_metadata_peer_plugin(torrent& t, bt_peer_connection& pc
			, ut_metadata_plugin& tp)
			: m_message_index(0)
			, m_no_metadata(min_time())
			, m_torrent(t)
			, m_pc(pc)
			, m_tp(tp)
		{}

		// can add entries to the extension handshake
		virtual void add_handshake(entry& h)
		{
			entry& messages = h["m"];
			messages["ut_metadata"] = 15;
			if (m_torrent.valid_metadata())
				h["metadata_size"] = m_tp.metadata().left();
		}

		// called when the extension handshake from the other end is received
		virtual bool on_extension_handshake(lazy_entry const& h)
		{
			m_message_index = 0;
			if (h.type() != lazy_entry::dict_t) return false;
			lazy_entry const* messages = h.dict_find("m");
			if (!messages || messages->type() != lazy_entry::dict_t) return false;

			int index = messages->dict_find_int_value("ut_metadata", -1);
			if (index == -1) return false;
			m_message_index = index;

			int metadata_size = h.dict_find_int_value("metadata_size");
			if (metadata_size > 0)
				m_tp.metadata_size(metadata_size);
			return true;
		}

		void write_metadata_packet(int type, int piece)
		{
			TORRENT_ASSERT(type >= 0 && type <= 2);
			TORRENT_ASSERT(piece >= 0);
			TORRENT_ASSERT(!m_pc.associated_torrent().expired());

#ifdef TORRENT_VERBOSE_LOGGING
			(*m_pc.m_logger) << time_now_string() << " ==> UT_METADATA [ "
				"type: " << type << " | piece: " << piece << " ]\n";
#endif
			// abort if the peer doesn't support the metadata extension
			if (m_message_index == 0) return;

			entry e;
			e["msg_type"] = type;
			e["piece"] = piece;

			char const* metadata = 0;
			int metadata_piece_size = 0;

			if (type == 1)
			{
				TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
				e["total_size"] = m_tp.metadata().left();
				int offset = piece * 16 * 1024;
				metadata = m_tp.metadata().begin + offset;
				metadata_piece_size = (std::min)(
					int(m_tp.metadata().left() - offset), 16 * 1024);
				TORRENT_ASSERT(metadata_piece_size > 0);
				TORRENT_ASSERT(offset >= 0);
				TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().left()));
			}

			char msg[200];
			char* header = msg;
			char* p = &msg[6];
			int len = bencode(p, e);
			int total_size = 2 + len + metadata_piece_size;
			namespace io = detail;
			io::write_uint32(total_size, header);
			io::write_uint8(bt_peer_connection::msg_extended, header);
			io::write_uint8(m_message_index, header);

			m_pc.send_buffer(msg, len + 6);
			if (metadata_piece_size) m_pc.append_send_buffer(
				(char*)metadata, metadata_piece_size, &nop);
		}

		virtual bool on_extended(int length
			, int extended_msg, buffer::const_interval body)
		{
			if (extended_msg != 15) return false;
			if (m_message_index == 0) return false;

			if (length > 17 * 1024)
			{
				m_pc.disconnect("ut_metadata message larger than 17 kB", 2);
				return true;
			}

			if (!m_pc.packet_finished()) return true;

			int len;
			entry msg = bdecode(body.begin, body.end, len);
			if (msg.type() == entry::undefined_t)
			{
				m_pc.disconnect("invalid bencoding in ut_metadata message", 2);
				return true;
			}

			int type = msg["msg_type"].integer();
			int piece = msg["piece"].integer();

#ifdef TORRENT_VERBOSE_LOGGING
			(*m_pc.m_logger) << time_now_string() << " <== UT_METADATA [ "
				"type: " << type << " | piece: " << piece << " ]\n";
#endif

			switch (type)
			{
			case 0: // request
				{
					if (!m_torrent.valid_metadata())
					{
						write_metadata_packet(2, piece);
						return true;
					}
					// TODO: put the request on the queue in some cases
					write_metadata_packet(1, piece);
				}
				break;
			case 1: // data
				{
					std::vector<int>::iterator i = std::find(m_sent_requests.begin()
						, m_sent_requests.end(), piece);

					// unwanted piece?
					if (i == m_sent_requests.end()) return true;

					m_sent_requests.erase(i);
					entry const* total_size = msg.find_key("total_size");
					m_tp.received_metadata(body.begin + len, body.left() - len, piece
						, (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0);
				}
				break;
			case 2: // have no data
				{
					m_no_metadata = time_now();
					std::vector<int>::iterator i = std::find(m_sent_requests.begin()
						, m_sent_requests.end(), piece);
					// unwanted piece?
					if (i == m_sent_requests.end()) return true;
					m_sent_requests.erase(i);
				}
				break;
			default:
				{
					std::stringstream msg;
					msg << "unknown ut_metadata extension message: " << type;
					m_pc.disconnect(msg.str().c_str(), 2);
				}
			}
			return true;
		}

		virtual void tick()
		{
			// if we don't have any metadata, and this peer
			// supports the request metadata extension
			// and we aren't currently waiting for a request
			// reply. Then, send a request for some metadata.
			if (!m_torrent.valid_metadata()
				&& m_message_index != 0
				&& m_sent_requests.size() < 2
				&& has_metadata())
			{
				int piece = m_tp.metadata_request();
				m_sent_requests.push_back(piece);
				write_metadata_packet(0, piece);
			}
		}

		bool has_metadata() const
		{
			return time_now() - m_no_metadata > minutes(1);
		}

	private:

		// this is the message index the remote peer uses
		// for metadata extension messages.
		int m_message_index;

		// this is set to the current time each time we get a
		// "I don't have metadata" message.
		ptime m_no_metadata;

		// request queues
		std::vector<int> m_sent_requests;
		std::vector<int> m_incoming_requests;

		torrent& m_torrent;
		bt_peer_connection& m_pc;
		ut_metadata_plugin& m_tp;
	};

	boost::shared_ptr<peer_plugin> ut_metadata_plugin::new_connection(
		peer_connection* pc)
	{
		bt_peer_connection* c = dynamic_cast<bt_peer_connection*>(pc);
		if (!c) return boost::shared_ptr<peer_plugin>();
		return boost::shared_ptr<peer_plugin>(new ut_metadata_peer_plugin(m_torrent, *c, *this));
	}

	int ut_metadata_plugin::metadata_request()
	{
		std::vector<int>::iterator i = std::min_element(
			m_requested_metadata.begin(), m_requested_metadata.end());

		if (m_requested_metadata.empty())
		{
			// if we don't know how many pieces there are
			// just ask for piece 0
			m_requested_metadata.resize(1, 1);
			return 0;
		}

		int piece = i - m_requested_metadata.begin();
		m_requested_metadata[piece] = piece;
		return piece;
	}

} }

namespace libtorrent
{

	boost::shared_ptr<torrent_plugin> create_ut_metadata_plugin(torrent* t, void*)
	{
		return boost::shared_ptr<torrent_plugin>(new ut_metadata_plugin(*t));
	}

}

<commit_msg>ut_metadata fix to not send metadata for private torrents<commit_after>/*

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

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

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

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

*/

#include "libtorrent/pch.hpp"

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

#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <vector>
#include <utility>
#include <numeric>
#include <cstdio>

#include "libtorrent/peer_connection.hpp"
#include "libtorrent/bt_peer_connection.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/extensions.hpp"
#include "libtorrent/extensions/ut_metadata.hpp"
#include "libtorrent/alert_types.hpp"
#ifdef TORRENT_STATS
#include "libtorrent/aux_/session_impl.hpp"
#endif

namespace libtorrent { namespace
{
	int div_round_up(int numerator, int denominator)
	{
		return (numerator + denominator - 1) / denominator;
	}

	void nop(char*) {}

	struct ut_metadata_plugin : torrent_plugin
	{
		ut_metadata_plugin(torrent& t)
			: m_torrent(t)
			, m_metadata_progress(0)
			, m_metadata_size(0)
		{
		}

		virtual void on_files_checked()
		{
			// if the torrent is a seed, copy the metadata from
			// the torrent before it is deallocated
			if (m_torrent.is_seed())
				metadata();
		}

		virtual boost::shared_ptr<peer_plugin> new_connection(
			peer_connection* pc);

		buffer::const_interval metadata() const
		{
			TORRENT_ASSERT(m_torrent.valid_metadata());
			if (!m_metadata)
			{
				m_metadata = m_torrent.torrent_file().metadata();
				m_metadata_size = m_torrent.torrent_file().metadata_size();
				TORRENT_ASSERT(hasher(m_metadata.get(), m_metadata_size).final()
					== m_torrent.torrent_file().info_hash());
			}
			return buffer::const_interval(m_metadata.get(), m_metadata.get()
				+ m_metadata_size);
		}

		bool received_metadata(char const* buf, int size, int piece, int total_size)
		{
			if (m_torrent.valid_metadata()) return false;

			if (!m_metadata)
			{
				// verify the total_size
				if (total_size <= 0 || total_size > 500 * 1024) return false;

				m_metadata.reset(new char[total_size]);
				m_requested_metadata.resize(div_round_up(total_size, 16 * 1024), 0);
				m_metadata_size = total_size;
			}

			if (piece < 0 || piece >= int(m_requested_metadata.size()))
				return false;

			TORRENT_ASSERT(piece * 16 * 1024 + size <= m_metadata_size);
			std::memcpy(&m_metadata[piece * 16 * 1024], buf, size);
			// mark this piece has 'have'
			m_requested_metadata[piece] = (std::numeric_limits<int>::max)();

			bool have_all = std::count(m_requested_metadata.begin()
				, m_requested_metadata.end(), (std::numeric_limits<int>::max)())
				== int(m_requested_metadata.size());

			if (!have_all) return false;

			if (!m_torrent.set_metadata(&m_metadata[0], m_metadata_size))
			{
				if (!m_torrent.valid_metadata())
					std::fill(m_requested_metadata.begin(), m_requested_metadata.end(), 0);
				return false;
			}

			// clear the storage for the bitfield
			std::vector<int>().swap(m_requested_metadata);

			return true;
		}

		// returns a piece of the metadata that
		// we should request.
		int metadata_request();

		// this is called from the peer_connection for
		// each piece of metadata it receives
		void metadata_progress(int total_size, int received)
		{
			m_metadata_progress += received;
			m_metadata_size = total_size;
		}

		void on_piece_pass(int)
		{
			// if we became a seed, copy the metadata from
			// the torrent before it is deallocated
			if (m_torrent.is_seed())
				metadata();
		}

		void metadata_size(int size)
		{
			if (m_metadata_size > 0 || size <= 0 || size > 500 * 1024) return;
			m_metadata_size = size;
			m_metadata.reset(new char[size]);
			m_requested_metadata.resize(div_round_up(size, 16 * 1024), 0);
		}

	private:
		torrent& m_torrent;

		// this buffer is filled with the info-section of
		// the metadata file while downloading it from
		// peers, and while sending it.
		// it is mutable because it's generated lazily
		mutable boost::shared_array<char> m_metadata;

		int m_metadata_progress;
		mutable int m_metadata_size;

		// this vector keeps track of how many times each meatdata
		// block has been requested
		// std::numeric_limits<int>::max() means we have the piece
		std::vector<int> m_requested_metadata;
	};

	struct ut_metadata_peer_plugin : peer_plugin
	{
		ut_metadata_peer_plugin(torrent& t, bt_peer_connection& pc
			, ut_metadata_plugin& tp)
			: m_message_index(0)
			, m_no_metadata(min_time())
			, m_torrent(t)
			, m_pc(pc)
			, m_tp(tp)
		{}

		// can add entries to the extension handshake
		virtual void add_handshake(entry& h)
		{
			entry& messages = h["m"];
			messages["ut_metadata"] = 15;
			if (m_torrent.valid_metadata())
				h["metadata_size"] = m_tp.metadata().left();
		}

		// called when the extension handshake from the other end is received
		virtual bool on_extension_handshake(lazy_entry const& h)
		{
			m_message_index = 0;
			if (h.type() != lazy_entry::dict_t) return false;
			lazy_entry const* messages = h.dict_find("m");
			if (!messages || messages->type() != lazy_entry::dict_t) return false;

			int index = messages->dict_find_int_value("ut_metadata", -1);
			if (index == -1) return false;
			m_message_index = index;

			int metadata_size = h.dict_find_int_value("metadata_size");
			if (metadata_size > 0)
				m_tp.metadata_size(metadata_size);
			return true;
		}

		void write_metadata_packet(int type, int piece)
		{
			TORRENT_ASSERT(type >= 0 && type <= 2);
			TORRENT_ASSERT(piece >= 0);
			TORRENT_ASSERT(!m_pc.associated_torrent().expired());

#ifdef TORRENT_VERBOSE_LOGGING
			(*m_pc.m_logger) << time_now_string() << " ==> UT_METADATA [ "
				"type: " << type << " | piece: " << piece << " ]\n";
#endif
			// abort if the peer doesn't support the metadata extension
			if (m_message_index == 0) return;

			entry e;
			e["msg_type"] = type;
			e["piece"] = piece;

			char const* metadata = 0;
			int metadata_piece_size = 0;

			if (type == 1)
			{
				TORRENT_ASSERT(m_pc.associated_torrent().lock()->valid_metadata());
				e["total_size"] = m_tp.metadata().left();
				int offset = piece * 16 * 1024;
				metadata = m_tp.metadata().begin + offset;
				metadata_piece_size = (std::min)(
					int(m_tp.metadata().left() - offset), 16 * 1024);
				TORRENT_ASSERT(metadata_piece_size > 0);
				TORRENT_ASSERT(offset >= 0);
				TORRENT_ASSERT(offset + metadata_piece_size <= int(m_tp.metadata().left()));
			}

			char msg[200];
			char* header = msg;
			char* p = &msg[6];
			int len = bencode(p, e);
			int total_size = 2 + len + metadata_piece_size;
			namespace io = detail;
			io::write_uint32(total_size, header);
			io::write_uint8(bt_peer_connection::msg_extended, header);
			io::write_uint8(m_message_index, header);

			m_pc.send_buffer(msg, len + 6);
			if (metadata_piece_size) m_pc.append_send_buffer(
				(char*)metadata, metadata_piece_size, &nop);
		}

		virtual bool on_extended(int length
			, int extended_msg, buffer::const_interval body)
		{
			if (extended_msg != 15) return false;
			if (m_message_index == 0) return false;

			if (length > 17 * 1024)
			{
				m_pc.disconnect("ut_metadata message larger than 17 kB", 2);
				return true;
			}

			if (!m_pc.packet_finished()) return true;

			int len;
			entry msg = bdecode(body.begin, body.end, len);
			if (msg.type() == entry::undefined_t)
			{
				m_pc.disconnect("invalid bencoding in ut_metadata message", 2);
				return true;
			}

			int type = msg["msg_type"].integer();
			int piece = msg["piece"].integer();

#ifdef TORRENT_VERBOSE_LOGGING
			(*m_pc.m_logger) << time_now_string() << " <== UT_METADATA [ "
				"type: " << type << " | piece: " << piece << " ]\n";
#endif

			switch (type)
			{
			case 0: // request
				{
					if (!m_torrent.valid_metadata())
					{
						write_metadata_packet(2, piece);
						return true;
					}
					// TODO: put the request on the queue in some cases
					write_metadata_packet(1, piece);
				}
				break;
			case 1: // data
				{
					std::vector<int>::iterator i = std::find(m_sent_requests.begin()
						, m_sent_requests.end(), piece);

					// unwanted piece?
					if (i == m_sent_requests.end()) return true;

					m_sent_requests.erase(i);
					entry const* total_size = msg.find_key("total_size");
					m_tp.received_metadata(body.begin + len, body.left() - len, piece
						, (total_size && total_size->type() == entry::int_t) ? total_size->integer() : 0);
				}
				break;
			case 2: // have no data
				{
					m_no_metadata = time_now();
					std::vector<int>::iterator i = std::find(m_sent_requests.begin()
						, m_sent_requests.end(), piece);
					// unwanted piece?
					if (i == m_sent_requests.end()) return true;
					m_sent_requests.erase(i);
				}
				break;
			default:
				{
					std::stringstream msg;
					msg << "unknown ut_metadata extension message: " << type;
					m_pc.disconnect(msg.str().c_str(), 2);
				}
			}
			return true;
		}

		virtual void tick()
		{
			// if we don't have any metadata, and this peer
			// supports the request metadata extension
			// and we aren't currently waiting for a request
			// reply. Then, send a request for some metadata.
			if (!m_torrent.valid_metadata()
				&& m_message_index != 0
				&& m_sent_requests.size() < 2
				&& has_metadata())
			{
				int piece = m_tp.metadata_request();
				m_sent_requests.push_back(piece);
				write_metadata_packet(0, piece);
			}
		}

		bool has_metadata() const
		{
			return time_now() - m_no_metadata > minutes(1);
		}

	private:

		// this is the message index the remote peer uses
		// for metadata extension messages.
		int m_message_index;

		// this is set to the current time each time we get a
		// "I don't have metadata" message.
		ptime m_no_metadata;

		// request queues
		std::vector<int> m_sent_requests;
		std::vector<int> m_incoming_requests;

		torrent& m_torrent;
		bt_peer_connection& m_pc;
		ut_metadata_plugin& m_tp;
	};

	boost::shared_ptr<peer_plugin> ut_metadata_plugin::new_connection(
		peer_connection* pc)
	{
		bt_peer_connection* c = dynamic_cast<bt_peer_connection*>(pc);
		if (!c) return boost::shared_ptr<peer_plugin>();
		return boost::shared_ptr<peer_plugin>(new ut_metadata_peer_plugin(m_torrent, *c, *this));
	}

	int ut_metadata_plugin::metadata_request()
	{
		std::vector<int>::iterator i = std::min_element(
			m_requested_metadata.begin(), m_requested_metadata.end());

		if (m_requested_metadata.empty())
		{
			// if we don't know how many pieces there are
			// just ask for piece 0
			m_requested_metadata.resize(1, 1);
			return 0;
		}

		int piece = i - m_requested_metadata.begin();
		m_requested_metadata[piece] = piece;
		return piece;
	}

} }

namespace libtorrent
{

	boost::shared_ptr<torrent_plugin> create_ut_metadata_plugin(torrent* t, void*)
	{
		// don't add this extension if the torrent is private
		if (t->valid_metadata() && t->torrent_file().priv()) return boost::shared_ptr<torrent_plugin>();
		return boost::shared_ptr<torrent_plugin>(new ut_metadata_plugin(*t));
	}

}

<|endoftext|>


<commit_before>
/*
*
*	Copyright (C) 2016 Luxon Jean-Pierre
*	gumichan01.olympe.in
*
*   This library is under the MIT license
*
*	Luxon Jean-Pierre (Gumichan01)
*	luxon.jean.pierre@gmail.com
*
*/

#include <map>
#include <stdexcept>
#include "utf8_string.hpp"

typedef char byte_t;

UTF8string::UTF8string() : utf8length(0){}

UTF8string::UTF8string(const std::string &str)
 : utf8data(str)
{
    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
}

UTF8string::UTF8string(const UTF8string &u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
}

const UTF8string& UTF8string::operator =(const char * str)
{
    utf8data = str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const std::string str)
{
    utf8data = str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const UTF8string u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
    return *this;
}

const UTF8string& UTF8string::operator +=(const std::string str)
{
    utf8data += str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const UTF8string u8str)
{
    utf8data += u8str.utf8data;
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const char * str)
{
    utf8data += str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const char c)
{
    utf8data += c;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

bool UTF8string::utf8_is_valid_() const
{
    auto it = utf8data.begin();
    const auto itend = utf8data.end();

    while(it < itend)
    {
        if((0xF8 & *it) == 0xF0)
        {
            // The UTF-8 codepoint begin with 0b11110xxx -> 4-byte codepoint
            // If the iterator reach the end of the string before the
            // end of the 4-byte codepoint -> invalid string
            if((it + 1) == itend || (it + 2) == itend || (it + 3) == itend)
                return false;

            // Each of the following bytes is a value
            // between 0x80 and 0xBF
            if(((0xC0 & *(it + 1)) != 0x80) || ((0xC0 & *(it + 2)) != 0x80)
               || ((0xC0 & *(it + 3)) != 0x80))
            {
                return false;
            }

            // If the first byte of the sequence is 0xF0
            // then the first continuation byte must be between 90 and BF
            // otherwise, if the byte is 0xF4
            // then the first continuation byte must be between 80 and 8F
            if(*it == '\xF0')
            {
                if(*(it + 1) < '\x90' || *(it + 1) > '\xBF')
                    return false;
            }
            else if(*it == '\xF4')
            {
                if(*(it + 1) < '\x80' || *(it + 1) > '\x8F')
                    return false;
            }

            it += 4;    // Jump to the next codepoint
        }
        else if((0xF0 & *it) == 0xE0)
        {
            // The UTF-8 codepoint begin with 0b1110xxxx -> 3-byte codepoint
            if((it + 1) == itend || (it + 2) == itend)
                return false;

            // Each of the following bytes starts with
            // 0b10xxxxxx in a valid string
            if(((0xC0 & *(it + 1)) != 0x80) || ((0xC0 & *(it + 2)) != 0x80))
                return false;

            // If the first byte of the sequence is 0xE0
            // then the first continuation byte must be between A0 and BF
            // otherwise, if the byte is 0xF4
            // then the first continuation byte must be between 80 and 9F
            if(*it == '\xE0')
            {
                if(*(it + 1) < '\xA0' || *(it + 1) > '\xBF')
                    return false;
            }
            else if(*it == '\xED')
            {
                if(*(it + 1) < '\x80' || *(it + 1) > '\x9F')
                    return false;
            }

            it += 3;
        }
        else if((0xE0 & *it) == 0xC0)
        {
            // The UTF-8 codepoint begin with 0b110xxxxx -> 2-byte codepoint
            if((it + 1) == itend)
                return false;

            // The following byte starts with 0b10xxxxxx in a valid string
            if((0xC0 & *(it + 1)) != 0x80)
                return false;

            it += 2;
        }
        else if((0x80 & *it) == 0x00)
        {
            // The UTF-8 codepoint begin with 0b0xxxxxxx -> 1-byte codepoint
            it += 1;
        }
        else
        {
            // Invalid codepoint
            return false;
        }
    }

    return true;
}

size_t UTF8string::utf8_length_() const
{
    auto end_data = utf8data.end();
    auto it = utf8data.begin();
    size_t len = 0;

    while(it != end_data)
    {
        byte_t byte = *it;

        if (0xf0 == (0xf8 & byte))
        {
            // 4-byte utf8 character
            // (0b11110xxx 0bxxxxxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 4;
        }
        else if (0xe0 == (0xf0 & byte))
        {
            // 3-byte utf8 code point (0b110xxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 3;
        }
        else if (0xc0 == (0xe0 & byte))
        {
            // 2-byte utf8 code point (0b110xxxxx 0bxxxxxxxx)
            it += 2;
        }
        else
        {
            // 1-byte utf8 code point (0b0xxxxxxx)
            it += 1;
        }

        // We want the number of characters (utf-8 code point)
        len += 1;
    }

    return len;
}

size_t UTF8string::utf8_codepoint_len_(size_t j) const
{
    if (0xf0 == (0xf8 & utf8data[j]))
    {
        return 4;
    }
    else if (0xe0 == (0xf0 & utf8data[j]))
    {
        return 3;
    }
    else if (0xc0 == (0xe0 & utf8data[j]))
    {
        return 2;
    }
    else
        return 1;
}

void UTF8string::utf8_clear()
{
    utf8data.clear();
    utf8length = 0;
}

bool UTF8string::utf8_empty() const
{
    return utf8length == 0;
}

size_t UTF8string::utf8_bpos_at(const size_t cpos) const
{
    size_t bpos = 0;
    const size_t u8size = utf8_size();

    for(size_t i = 0; bpos < u8size && i < cpos; i++)
    {
        bpos += utf8_codepoint_len_(bpos);
    }
    return bpos;
}

std::string UTF8string::utf8_at(const size_t index) const
{
    if(index >= utf8data.size())
        throw std::out_of_range("index value greater than the size of the string");

    size_t bpos = utf8_bpos_at(index);
    const size_t n = utf8_codepoint_len_(bpos);
    std::string s;

    for(size_t i = 0; i < n; i++)
    {
        s += utf8data[bpos + i];
    }

    return s;
}

UTF8string UTF8string::utf8_substr(size_t pos,size_t len)
{
    if(pos > utf8length)
        return std::string();

    // Length of the substring (number of code points)
    const size_t n = (len == npos || (pos + len) > utf8length) ?
                        (utf8length - pos) : (pos + len - pos);

    UTF8iterator it = utf8_iterator_() + pos;
    UTF8iterator end = (it + n);
    std::string s;

    while(it != end)
    {
        s += *(it++);
    }

    return s;
}

// This fuction implements the Boyer-Moore string search algorithm
size_t UTF8string::utf8_find(const UTF8string& str, size_t pos)
{
    std::map<std::string,size_t> u8map;
    const size_t n = str.utf8_length();
    size_t index = pos;

    // Preprocessing
    for(long i = static_cast<long>(n - 2); i >= 0; i--)
    {
        std::string s = str.utf8_at(i);

        if(u8map.find(s) == u8map.end())
            u8map[s] = static_cast<size_t>(n - 1 - i);
    }

    while(index <= utf8length - n)
    {
        long j = static_cast<long>(n - 1);

        while(j >= 0 && (str.utf8_at(j) == utf8_at(index + j)))
        {
            j--;
        }

        if(j >= 0)
        {
            std::string ss = utf8_at(index + j);
            index += (u8map.find(ss) == u8map.end()) ? n : u8map[ss];
        }
        else
            return index;
    }

    return npos;
}

UTF8string UTF8string::utf8_reverse_aux(UTF8iterator& it,
                                        const UTF8iterator& end,
                                        UTF8string& res)
{
    if(it == end)
        return res;

    UTF8string tmp = res + *(--it);
    return utf8_reverse_aux(it, end, tmp);
}

UTF8string& UTF8string::utf8_reverse()
{
    UTF8iterator it = utf8_end();
    UTF8string rev;
    utf8data = (utf8_reverse_aux(it, utf8_iterator_(), rev)).utf8data;
    return *this;
}

size_t UTF8string::utf8_size() const
{
    return utf8data.size();
}

size_t UTF8string::utf8_length() const
{
    return utf8length;
}

const char * UTF8string::utf8_str() const
{
    return utf8data.c_str();
}

UTF8iterator UTF8string::utf8_iterator_() const noexcept
{
    return UTF8iterator(*this);
}

UTF8iterator UTF8string::utf8_begin() const noexcept
{
    return utf8_iterator_();
}

UTF8iterator UTF8string::utf8_end() const noexcept
{
    return utf8_begin() + utf8length;
}

bool operator ==(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 == s2;
}

bool operator !=(const UTF8string &str1, const UTF8string &str2)
{
    return !(str1 == str2);
}

bool operator <=(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 <= s2;
}

bool operator >=(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 >= s2;
}

bool operator <(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 < s2;
}

bool operator >(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 > s2;
}

UTF8string operator +(const UTF8string &str1, const UTF8string &str2)
{
    return str1 + std::string(str2.utf8_str());
}

UTF8string operator +(const UTF8string &str1, const std::string &str2)
{
    return UTF8string(std::string(str1.utf8_str()) + str2);
}

UTF8string operator +(const std::string &str1, const UTF8string &str2)
{
    return UTF8string(std::string(str1 + str2.utf8_str()));
}

UTF8string operator +(const UTF8string &str1, const char * str2)
{
    return str1 + std::string(str2);
}

UTF8string operator +(const char * str1, const UTF8string &str2)
{
    return std::string(str1) + str2;
}

std::ostream & operator <<(std::ostream &os, const UTF8string &str)
{
    os << str.utf8_str();
    return os;
}

std::istream & operator >>(std::istream &is, UTF8string &str)
{
    std::string tmp;
    std::getline(is,tmp);
    str = tmp;
    return is;
}
<commit_msg>Refactored utf8_find.<commit_after>
/*
*
*	Copyright (C) 2016 Luxon Jean-Pierre
*	gumichan01.olympe.in
*
*   This library is under the MIT license
*
*	Luxon Jean-Pierre (Gumichan01)
*	luxon.jean.pierre@gmail.com
*
*/

#include <map>
#include <stdexcept>
#include "utf8_string.hpp"

typedef char byte_t;

UTF8string::UTF8string() : utf8length(0){}

UTF8string::UTF8string(const std::string &str)
 : utf8data(str)
{
    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
}

UTF8string::UTF8string(const UTF8string &u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
}

const UTF8string& UTF8string::operator =(const char * str)
{
    utf8data = str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const std::string str)
{
    utf8data = str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const UTF8string u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
    return *this;
}

const UTF8string& UTF8string::operator +=(const std::string str)
{
    utf8data += str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const UTF8string u8str)
{
    utf8data += u8str.utf8data;
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const char * str)
{
    utf8data += str;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const char c)
{
    utf8data += c;

    if(!utf8_is_valid_())
        throw std::invalid_argument("Invalid UTF-8 string\n");

    utf8length = utf8_length_();
    return *this;
}

bool UTF8string::utf8_is_valid_() const
{
    auto it = utf8data.begin();
    const auto itend = utf8data.end();

    while(it < itend)
    {
        if((0xF8 & *it) == 0xF0)
        {
            // The UTF-8 codepoint begin with 0b11110xxx -> 4-byte codepoint
            // If the iterator reach the end of the string before the
            // end of the 4-byte codepoint -> invalid string
            if((it + 1) == itend || (it + 2) == itend || (it + 3) == itend)
                return false;

            // Each of the following bytes is a value
            // between 0x80 and 0xBF
            if(((0xC0 & *(it + 1)) != 0x80) || ((0xC0 & *(it + 2)) != 0x80)
               || ((0xC0 & *(it + 3)) != 0x80))
            {
                return false;
            }

            // If the first byte of the sequence is 0xF0
            // then the first continuation byte must be between 90 and BF
            // otherwise, if the byte is 0xF4
            // then the first continuation byte must be between 80 and 8F
            if(*it == '\xF0')
            {
                if(*(it + 1) < '\x90' || *(it + 1) > '\xBF')
                    return false;
            }
            else if(*it == '\xF4')
            {
                if(*(it + 1) < '\x80' || *(it + 1) > '\x8F')
                    return false;
            }

            it += 4;    // Jump to the next codepoint
        }
        else if((0xF0 & *it) == 0xE0)
        {
            // The UTF-8 codepoint begin with 0b1110xxxx -> 3-byte codepoint
            if((it + 1) == itend || (it + 2) == itend)
                return false;

            // Each of the following bytes starts with
            // 0b10xxxxxx in a valid string
            if(((0xC0 & *(it + 1)) != 0x80) || ((0xC0 & *(it + 2)) != 0x80))
                return false;

            // If the first byte of the sequence is 0xE0
            // then the first continuation byte must be between A0 and BF
            // otherwise, if the byte is 0xF4
            // then the first continuation byte must be between 80 and 9F
            if(*it == '\xE0')
            {
                if(*(it + 1) < '\xA0' || *(it + 1) > '\xBF')
                    return false;
            }
            else if(*it == '\xED')
            {
                if(*(it + 1) < '\x80' || *(it + 1) > '\x9F')
                    return false;
            }

            it += 3;
        }
        else if((0xE0 & *it) == 0xC0)
        {
            // The UTF-8 codepoint begin with 0b110xxxxx -> 2-byte codepoint
            if((it + 1) == itend)
                return false;

            // The following byte starts with 0b10xxxxxx in a valid string
            if((0xC0 & *(it + 1)) != 0x80)
                return false;

            it += 2;
        }
        else if((0x80 & *it) == 0x00)
        {
            // The UTF-8 codepoint begin with 0b0xxxxxxx -> 1-byte codepoint
            it += 1;
        }
        else
        {
            // Invalid codepoint
            return false;
        }
    }

    return true;
}

size_t UTF8string::utf8_length_() const
{
    auto end_data = utf8data.end();
    auto it = utf8data.begin();
    size_t len = 0;

    while(it != end_data)
    {
        byte_t byte = *it;

        if (0xf0 == (0xf8 & byte))
        {
            // 4-byte utf8 character
            // (0b11110xxx 0bxxxxxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 4;
        }
        else if (0xe0 == (0xf0 & byte))
        {
            // 3-byte utf8 code point (0b110xxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 3;
        }
        else if (0xc0 == (0xe0 & byte))
        {
            // 2-byte utf8 code point (0b110xxxxx 0bxxxxxxxx)
            it += 2;
        }
        else
        {
            // 1-byte utf8 code point (0b0xxxxxxx)
            it += 1;
        }

        // We want the number of characters (utf-8 code point)
        len += 1;
    }

    return len;
}

size_t UTF8string::utf8_codepoint_len_(size_t j) const
{
    if (0xf0 == (0xf8 & utf8data[j]))
    {
        return 4;
    }
    else if (0xe0 == (0xf0 & utf8data[j]))
    {
        return 3;
    }
    else if (0xc0 == (0xe0 & utf8data[j]))
    {
        return 2;
    }
    else
        return 1;
}

void UTF8string::utf8_clear()
{
    utf8data.clear();
    utf8length = 0;
}

bool UTF8string::utf8_empty() const
{
    return utf8length == 0;
}

size_t UTF8string::utf8_bpos_at(const size_t cpos) const
{
    size_t bpos = 0;
    const size_t u8size = utf8_size();

    for(size_t i = 0; bpos < u8size && i < cpos; i++)
    {
        bpos += utf8_codepoint_len_(bpos);
    }
    return bpos;
}

std::string UTF8string::utf8_at(const size_t index) const
{
    if(index >= utf8data.size())
        throw std::out_of_range("index value greater than the size of the string");

    size_t bpos = utf8_bpos_at(index);
    const size_t n = utf8_codepoint_len_(bpos);
    std::string s;

    for(size_t i = 0; i < n; i++)
    {
        s += utf8data[bpos + i];
    }

    return s;
}

UTF8string UTF8string::utf8_substr(size_t pos,size_t len)
{
    if(pos > utf8length)
        return std::string();

    // Length of the substring (number of code points)
    const size_t n = (len == npos || (pos + len) > utf8length) ?
                        (utf8length - pos) : (pos + len - pos);

    UTF8iterator it = utf8_iterator_() + pos;
    UTF8iterator end = (it + n);
    std::string s;

    while(it != end)
    {
        s += *(it++);
    }

    return s;
}

// This fuction implements the Boyer-Moore string search algorithm
size_t UTF8string::utf8_find(const UTF8string& str, size_t pos)
{
    if(str.utf8length == 0)
        return npos;

    std::map<std::string,size_t> u8map;
    const size_t n = str.utf8_length();
    size_t index = pos;

    // Preprocessing
    if(str.utf8length > 1)
    {
        for(size_t i = n - 2; ; i--)
        {
            std::string s = str.utf8_at(i);

            if(u8map.find(s) == u8map.end())
                u8map[s] = n - 1 - i;

            if(i == 0)
                break;
        }
    }

    // Look for the subtring
    while(index <= utf8length - n)
    {
        size_t j = n - 1;
        bool found = false;

        while((str.utf8_at(j) == utf8_at(index + j)))
        {
            if(j == 0)
            {
                found = true;
                break;
            }

            j--;
        }

        if(!found)
        {
            std::string ss = utf8_at(index + j);
            index += (u8map.find(ss) == u8map.end()) ? n : u8map[ss];
        }
        else
            return index;
    }

    return npos;
}

UTF8string UTF8string::utf8_reverse_aux(UTF8iterator& it,
                                        const UTF8iterator& end,
                                        UTF8string& res)
{
    if(it == end)
        return res;

    UTF8string tmp = res + *(--it);
    return utf8_reverse_aux(it, end, tmp);
}

UTF8string& UTF8string::utf8_reverse()
{
    UTF8iterator it = utf8_end();
    UTF8string rev;
    utf8data = (utf8_reverse_aux(it, utf8_iterator_(), rev)).utf8data;
    return *this;
}

size_t UTF8string::utf8_size() const
{
    return utf8data.size();
}

size_t UTF8string::utf8_length() const
{
    return utf8length;
}

const char * UTF8string::utf8_str() const
{
    return utf8data.c_str();
}

UTF8iterator UTF8string::utf8_iterator_() const noexcept
{
    return UTF8iterator(*this);
}

UTF8iterator UTF8string::utf8_begin() const noexcept
{
    return utf8_iterator_();
}

UTF8iterator UTF8string::utf8_end() const noexcept
{
    return utf8_begin() + utf8length;
}

bool operator ==(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 == s2;
}

bool operator !=(const UTF8string &str1, const UTF8string &str2)
{
    return !(str1 == str2);
}

bool operator <=(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 <= s2;
}

bool operator >=(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 >= s2;
}

bool operator <(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 < s2;
}

bool operator >(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 > s2;
}

UTF8string operator +(const UTF8string &str1, const UTF8string &str2)
{
    return str1 + std::string(str2.utf8_str());
}

UTF8string operator +(const UTF8string &str1, const std::string &str2)
{
    return UTF8string(std::string(str1.utf8_str()) + str2);
}

UTF8string operator +(const std::string &str1, const UTF8string &str2)
{
    return UTF8string(std::string(str1 + str2.utf8_str()));
}

UTF8string operator +(const UTF8string &str1, const char * str2)
{
    return str1 + std::string(str2);
}

UTF8string operator +(const char * str1, const UTF8string &str2)
{
    return std::string(str1) + str2;
}

std::ostream & operator <<(std::ostream &os, const UTF8string &str)
{
    os << str.utf8_str();
    return os;
}

std::istream & operator >>(std::istream &is, UTF8string &str)
{
    std::string tmp;
    std::getline(is,tmp);
    str = tmp;
    return is;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2019, CNRS
 * Copyright 2018-2019, INRIA
 */

#include "eigenpy/eigenpy.hpp"

namespace eigenpy
{

  /* Enable Eigen-Numpy serialization for a set of standard MatrixBase instances. */
  void enableEigenPy()
  {
    using namespace Eigen;
    Exception::registerException();

    bp::def("setNumpyType",&NumpyType::setNumpyType,
            bp::arg("Numpy type (np.ndarray or np.matrix)"),
            "Change the type returned by the converters from an Eigen object.");

    bp::def("switchToNumpyArray",&NumpyType::switchToNumpyArray,
            "Set the conversion from Eigen::Matrix to numpy.ndarray.");

    bp::def("switchToNumpyMatrix",&NumpyType::switchToNumpyMatrix,
            "Set the conversion from Eigen::Matrix to numpy.matrix.");

    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xd);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xf);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xi);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xd);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xf);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xi);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xd);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xf);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xi);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXd);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXf);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXi);

    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXd);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXf);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXi);

    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXd);
    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXf);
    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXi);
  }

} // namespace eigenpy
<commit_msg>python: expose getNumpyType<commit_after>/*
 * Copyright 2014-2019, CNRS
 * Copyright 2018-2019, INRIA
 */

#include "eigenpy/eigenpy.hpp"

namespace eigenpy
{

  /* Enable Eigen-Numpy serialization for a set of standard MatrixBase instances. */
  void enableEigenPy()
  {
    using namespace Eigen;
    Exception::registerException();

    bp::def("setNumpyType",&NumpyType::setNumpyType,
            bp::arg("Numpy type (np.ndarray or np.matrix)"),
            "Change the type returned by the converters from an Eigen object.");

    bp::def("getNumpyType",&NumpyType::getNumpyType,
            "Get the Numpy type returned by the converters from an Eigen object.");

    bp::def("switchToNumpyArray",&NumpyType::switchToNumpyArray,
            "Set the conversion from Eigen::Matrix to numpy.ndarray.");

    bp::def("switchToNumpyMatrix",&NumpyType::switchToNumpyMatrix,
            "Set the conversion from Eigen::Matrix to numpy.matrix.");

    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xd);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xf);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix2Xi);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xd);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xf);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix3Xi);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xd);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xf);
    ENABLE_SPECIFIC_MATRIX_TYPE(Matrix4Xi);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixX4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXd);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXf);
    ENABLE_SPECIFIC_MATRIX_TYPE(MatrixXi);

    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVector4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXd);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXf);
    ENABLE_SPECIFIC_MATRIX_TYPE(RowVectorXi);

    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector2i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector3i);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4d);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4f);
    ENABLE_SPECIFIC_MATRIX_TYPE(Vector4i);
    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXd);
    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXf);
    ENABLE_SPECIFIC_MATRIX_TYPE(VectorXi);
  }

} // namespace eigenpy
<|endoftext|>