text:
//
// file RDKitMolToQPainter.cc
//
// Contributed by:
// David Cosgrove
// AstraZeneca
// 28th June 2012
//
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
// Draw an RDKit Drawing into a QPainter object.
// Hacked together by analogy with the SVG drawer in
// $RDBASE/Code/Demos/RDKit/Draw/demo.cpp
//

#include <GraphMol/RDKitBase.h>
#include <GraphMol/Depictor/RDDepictor.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <GraphMol/MolDrawing/MolDrawing.h> // this is what does the 2D drawing!

#include <QFont>
#include <QPainter>
#include <QString>

#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <string>

#include <boost/scoped_ptr.hpp>

using namespace boost;
using namespace std;
using namespace RDKit;

typedef scoped_ptr<RWMol> pRWMol;

static const int LINE_WIDTH_MULT = 4;
static const float ORIGINAL_FONT_SIZE = 35.0; // this size seems to work well with the relative scale of the Drawing

// ****************************************************************************
QColor &colour_for_atomic_num( int atnum ) {

  static QColor colours[10] = { QColor( "Black" ) , QColor( "Blue" ) ,
                                QColor( "Red" ) , QColor( "LightGreen" ) ,
                                QColor( "Orange" ) , QColor( "Yellow" ) ,
                                QColor( "Green" ) , QColor( "Brown" ) ,
                                QColor( "Purple" ) , QColor( "Cyan" ) };

  switch( atnum ) {
  case 6 : return colours[0];
  case 7 : return colours[1];
  case 8 : return colours[2];
  case 9 : return colours[3];
  case 15 : return colours[4];
  case 16 : return colours[5];
  case 17 : return colours[6];
  case 37 : return colours[7];
  case 53 : return colours[8];
  default : return colours[9];
  }

}

#ifdef NOTYET
// ****************************************************************************
string colour_for_atomic_num( int atnum ) {

  static map<int,string> colours;
  if( colours.empty() ) {
    colours.insert( make_pair( 6 , "Black" ) ); //carbon
    colours.insert( make_pair( 7 , "Blue" ) ); // nitrogen
    colours.insert( make_pair( 8 , "Red" ) ); // oxygen
    colours.insert( make_pair( 9 , "LightGreen" ) ); // fluorine
    colours.insert( make_pair( 15 , "Orange" ) ); // phosphorous
    colours.insert( make_pair( 16 , "Yellow" ) ); // sulfur
    colours.insert( make_pair( 17 , "Green" ) ); // chlorine
    colours.insert( make_pair( 37 , "Brown" ) ); // bromine
    colours.insert( make_pair( 53 , "Purple" ) ); // iodine
  }

  map<int,string>::iterator q = colours.find( atnum );
  if( q == colours.end() ) {
    return "Cyan";
  } else {
    return q->second;
  }

}
#endif

// ****************************************************************************
void get_scale( int width , int height , int qp_width , int qp_height ,
                qreal &gscale ) {

  qreal xscale = qreal( qp_width ) / qreal( width );
  qreal yscale = qreal( qp_height ) / qreal( height );

  gscale = std::min( xscale , yscale );

#ifdef NOTYET
  cout << "Scale for picture " << width << " by " << height << endl
       << " qpainter " << qp_width << " by " << qp_height << endl
       << "x and y scales : " << xscale << " , " << yscale << endl;
  cout << "Final scale : " << gscale << endl;
#endif

}

// ****************************************************************************
void set_scale( int width , int height , int min_x , int min_y ,
                int qp_width , int qp_height ,
                QPainter &qp , qreal &gscale ) {

  qp.scale( gscale , gscale );
  qreal qp_width_in_scale = qreal( qp_width ) / gscale;
  qreal qp_height_in_scale = qreal( qp_height ) / gscale;

  // move it to a central point in the window
  qp.translate( -min_x + 0.5 * ( qp_width_in_scale - width ) , -min_y + 0.5 * ( qp_height_in_scale - height ) );

}

// ****************************************************************************
void set_font( QPainter &qp ) {

  static QFont *font = 0;
  if( !font ) {
    font = new QFont( qp.font() );
  }

  font->setPointSizeF( ORIGINAL_FONT_SIZE );
  qp.setFont( *font );

}

// ****************************************************************************
void draw_line( vector<int>::iterator &pos , bool bow , QPainter &qp ) {

  int width = *pos++;
  pos++; // skip 'dashed' flag
  int atom1 = *pos++;
  int atom2 = *pos++;

  int xp1 = *pos++;
  int yp1 = *pos++;
  int xp2 = *pos++;
  int yp2 = *pos++;

  static QPen pen( "Black" );
  pen.setJoinStyle( Qt::RoundJoin );
  pen.setWidth( width * LINE_WIDTH_MULT );
  qp.setPen( pen );

  if( atom1 == atom2 ) {
    if( !bow ) {
      pen.setColor( colour_for_atomic_num( atom1 ) );
      qp.setPen( pen );
    }
    qp.drawLine( xp1 , yp1 , xp2 , yp2 );
  } else  {
    int mx = xp1 + ( xp2 - xp1 ) / 2;
    int my = yp1 + ( yp2 - yp1 ) / 2;
    if( !bow ) {
      pen.setColor( colour_for_atomic_num( atom1 ) );
      qp.setPen( pen );
    }
    qp.drawLine( xp1 , yp1 , mx , my );
    if( !bow ) {
      pen.setColor( colour_for_atomic_num( atom2 ) );
      qp.setPen( pen );
    }
    qp.drawLine( mx , my , xp2 , yp2 );
  }
}

// ****************************************************************************
void draw_atom( vector<int>::iterator &pos , bool bow , QPainter &qp ) {

  int atnum = *pos++;
  int xp = *pos++;
  int yp = *pos++;
  int slen = *pos++;
  QString label;
  for(int i = 0 ; i < slen ; ++i ){
    label += static_cast<char>( *pos++ );
  }
  pos++; // move past orient flag, which is not being used

  char letter[2] = { '\0' , '\0' };

  qp.save();

  QRectF whole_br = qp.boundingRect( 0 , 0 , 100 , 100 , Qt::AlignHCenter , label );
  qp.translate( xp - whole_br.width() / 2.0 , yp - whole_br.height() / 2.0 );

  static QPen pen( "Black" );
  qp.setPen( pen );
  pen.setJoinStyle( Qt::RoundJoin );
  if( !bow ) {
    pen.setColor( colour_for_atomic_num( atnum ) );
    qp.setPen( pen );
  }

  // blank out behind the letters, so bonds don't go through where the label is. I think
  // circles work better than rectangles for this, but it means going through it all twice,
  // as the circles overlap so would obscure the letter that came afterwards
  // This assumes the bonds are drawn before the atoms, which is how it is set up in MolDrawing.h.
  static QBrush letter_brush( qp.background() );
  letter_brush.setStyle( Qt::SolidPattern );

  qp.save();
  qp.setPen( qp.background().color() ); // so the ellipse doesn't have a border
  qp.setBrush( letter_brush );

  // do things 1 letter at a time. We needed to stuff the characters into label first, so as to
  // get the bounding rectangle for the whole label.
  for( int i = 0 ; i < slen ; ++i ) {

    letter[0] = label.toLocal8Bit().data()[i];
    QString at_lab( letter );
    QRectF br = qp.boundingRect( 0 , 0 , 1000 , 1000 , Qt::AlignHCenter , at_lab );

    // subscript for numbers, superscript for charge. Stretch the ellipse out so the bond
    // is obscured over the whole of its extent.
    qreal letter_top = 0.0 , letter_height = br.height();
    if( isdigit( letter[0] ) ) {
      qp.translate( 0.0 , br.height() / 2.0 );
      letter_top = -br.height() / 2.0;
      letter_height += br.height() / 2.0;
    } else if( '+' == letter[0] || '-' == letter[0] ) {
      qp.translate( 0.0 , -br.height() / 2.0 );
      letter_height += br.height() / 2.0;
    }
    qp.drawEllipse( QRectF( -2.0 , -2.0 + letter_top , br.width() + 2.0 , letter_height + 2.0 ) );
    qp.translate( br.width() , 0.0 );

    // remove superscript/subscript
    if( isdigit( letter[0] ) ) {
      qp.translate( 0.0 , -br.height() / 2.0 );
    } else if( '+' == letter[0] || '-' == letter[0] ) {
      qp.translate( 0.0 , br.height() / 2.0 );
    }
  }
  qp.setPen( pen );
  qp.restore();

  // now the letters
  for( int i = 0 ; i < slen ; ++i ) {

    letter[0] = label.toLocal8Bit().data()[i];
    QString at_lab( letter );
    QRectF br = qp.boundingRect( 0 , 0 , 1000 , 1000 , Qt::AlignHCenter , at_lab );

    // subscript for numbers, superscript for charge
    if( isdigit( letter[0] ) ) {
      qp.translate( 0.0 , br.height() / 2.0 );
    } else if( '+' == letter[0] || '-' == letter[0] ) {
      qp.translate( 0.0 , -br.height() / 2.0 );
    }
    qp.drawText( QRectF( 0.0 , 0.0 , br.width() , br.height() ) , Qt::AlignHCenter , at_lab , &br );
    qp.translate( br.width() , 0.0 );

    // remove superscript/subscript
    if( isdigit( letter[0] ) ) {
      qp.translate( 0.0 , -br.height() / 2.0 );
    } else if( '+' == letter[0] || '-' == letter[0] ) {
      qp.translate( 0.0 , br.height() / 2.0 );
    }
  }

  qp.restore();

}

// ****************************************************************************
void line_extremes( vector<int>::const_iterator &pos ,
                    int &min_x , int &max_x ,
                    int &min_y , int &max_y ) {

  pos += 4; // past the line width, type and atom numbers
  int xp1 = *pos++;
  int yp1 = *pos++;
  int xp2 = *pos++;
  int yp2 = *pos++;

  min_x = xp1 < min_x ? xp1 : min_x;
  max_x = xp1 > max_x ? xp1 : max_x;
  min_y = yp1 < min_y ? yp1 : min_y;
  max_y = yp1 > max_y ? yp1 : max_y;

  min_x = xp2 < min_x ? xp2 : min_x;
  max_x = xp2 > max_x ? xp2 : max_x;
  min_y = yp2 < min_y ? yp2 : min_y;
  max_y = yp2 > max_y ? yp2 : max_y;

}

// ****************************************************************************
void atom_extremes( vector<int>::const_iterator &pos ,
                    QPainter &qp ,
                    int &min_x , int &max_x ,
                    int &min_y , int &max_y ) {

  pos++; // skip the atomic number, not needed for this
  int xp = *pos++;
  int yp = *pos++;
  int slen = *pos++;
  QString label;
  for(int i = 0 ; i < slen ; ++i ){
    label += static_cast<char>( *pos++ );
  }
  pos++; // move past orient flag, which is not being used, and indeed is not understood!

  QRectF whole_br = qp.boundingRect( 0 , 0 , 1000 , 1000 , Qt::AlignHCenter , label );

  int labx1 = xp - int( whole_br.width() / 2.0 );
  int labx2 = xp + int( whole_br.width() );
  // subscripts and superscripts may occur in the atom label. Just allow for that willy-nilly.
  int laby1 = yp - int( 0.5 * whole_br.height() );
  int laby2 = yp + int( 0.5 * whole_br.height() );

  min_x = labx1 < min_x ? labx1 : min_x;
  max_x = labx2 > max_x ? labx2 : max_x;
  min_y = laby1 < min_y ? laby1 : min_y;
  max_y = laby2 > max_y ? laby2 : max_y;

}

// ****************************************************************************
void setup_scale( vector<int> &drawing , QPainter &qp ,
                  int qp_width , int qp_height ) {

  // calculate the width of the drawing. The values for width and height as
  // supplied in drawing by MolDrawing.h don't allow for the width of atom labels
  // so if there are non-carbon atoms at the extremes of the picture, these
  // will be drawn off the page.
  vector<int>::const_iterator pos = drawing.begin() + 7;
  int min_x = numeric_limits<int>::max();
  int max_x = numeric_limits<int>::min();
  int min_y = numeric_limits<int>::max();
  int max_y = numeric_limits<int>::min();

  while( pos != drawing.end() ) {
    int token = *pos++;
    switch( token ) {
    case Drawing::LINE :
      line_extremes( pos , min_x , max_x , min_y , max_y );
      break;
    case Drawing::ATOM :
      atom_extremes( pos , qp , min_x , max_x , min_y , max_y );
      break;
    default :
      break;
    }
  }

  // allow for width of lines
  min_x -= LINE_WIDTH_MULT;
  max_x += LINE_WIDTH_MULT;
  min_y -= LINE_WIDTH_MULT;
  max_y += LINE_WIDTH_MULT;

  int width = max_x - min_x;
  int height = max_y - min_y;

  qreal gscale;
  get_scale( width , height , qp_width , qp_height , gscale );
  set_scale( width , height , min_x , min_y , qp_width , qp_height , qp , gscale );

}

// ****************************************************************************
void MolToQPainter( vector<int> &drawing , int qp_width , int qp_height ,
                    bool bow , QPainter &qp ) {

  vector<int>::iterator pos = drawing.begin() + 2;
  if( *pos != Drawing::BOUNDS ) {
    // no drawing made by RDKit
    QString msg( "Bad Drawing" );
    qp.drawText( 0 , qp_height / 2 , msg );
    return;
  }
  pos += 3;

  // save current transformation matrix()
  qp.save();

  set_font( qp );
  setup_scale( drawing , qp, qp_width , qp_height );

  pos += 2; // for the width and height in the drawing
  while( pos != drawing.end() ) {
    int token = *pos++;
    switch( token ) {
    case Drawing::LINE :
      draw_line( pos , bow , qp );
      break;
    case Drawing::ATOM :
      draw_atom( pos , bow , qp );
      break;
    default :
      cerr << "Duff token, expect a crash." << token << endl;
      break;
    }
  }

  // put the transformation matrix back to how it was on entry
  qp.restore();

}

// ****************************************************************************
void label_molecule( const QString &label , int width , int height ,
                     int label_height , QPainter &qp ) {

  int label_y = height - label_height;
  qp.drawText( QRect( 0 , label_y , width , label_height ) , Qt::AlignHCenter , label );

}

// ****************************************************************************
// width and height are the size of the rectangle in qp we are drawing into.
// bow is black on white- when false,  colours are used in drawing
void smiles_to_qpainter( const string &smiles , const QString &label ,
                         int width , int height , bool bow ,
                         QPainter &qp ) {

  // render into an RDKit drawing
  pRWMol mol( SmilesToMol( smiles ) );
  MolOps::Kekulize( *mol );
  RDDepict::compute2DCoords( *mol );
  vector<int> drawing = Drawing::DrawMol( *mol );

  qp.setRenderHint( QPainter::Antialiasing , true );
  qp.setRenderHint( QPainter::TextAntialiasing , true );

  // get the height that will be needed for the label, and allow the picture to accommodate it
  QRect br;
  if( !label.isEmpty() ) {
    br = qp.boundingRect( QRect( 0 , 0 , width , height ) , Qt::AlignHCenter , label );
  }

  int label_height = br.height() + 5;
  int pict_height = height - label_height;
  MolToQPainter( drawing , width , pict_height , bow , qp );

  if( !label.isEmpty() ) {
    label_molecule( label , width , height , label_height , qp );
  }

}

max_stars_repo_name: jungb-basf/rdkit

max_issues_repo_name: jungb-basf/rdkit

max_forks_repo_name: bp-kelley/rdkit


text:
/*
@copyright Louis Dionne 2014
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#include <boost/hana/detail/assert.hpp>
#include <boost/hana/ext/std/array.hpp>
#include <boost/hana/ext/std/tuple.hpp>
#include <boost/hana/integral.hpp>
#include <boost/hana/list/instance.hpp>
#include <boost/hana/range.hpp>

#include <array>
#include <tuple>
using namespace boost::hana;

int main() {
    //! [main]
    BOOST_HANA_CONSTEXPR_ASSERT(
        to<List>(std::make_tuple(1, '2', 3.3)) == list(1, '2', 3.3)
    );

    BOOST_HANA_CONSTANT_ASSERT(
        to<List>(range(int_<1>, int_<4>)) == list(int_<1>, int_<2>, int_<3>)
    );

    BOOST_HANA_CONSTEXPR_ASSERT(
        to<List>(std::array<int, 3>{{1, 2, 3}}) == list(1, 2, 3)
    );
    //! [main]
}

ext: cpp

max_stars_repo_name: rbock/hana

max_issues_repo_name: rbock/hana

max_forks_repo_name: rbock/hana


text:
// __BEGIN_LICENSE__
// Copyright (C) 2006-2011 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <gtest/gtest.h>
#include <test/Helpers.h>
#include <vw/Plate/RpcChannel.h>
#include <vw/Plate/HTTPUtils.h>
#include <vw/Plate/Exception.h>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <cstdlib>

using namespace std;
using namespace vw;
using namespace vw::platefile;
using namespace vw::test;

TEST(TestRpcChannel, Checksum) {
  RpcWrapper msg;
  msg.set_method("ab");
  msg.set_payload("cd");

  uint16 high = 'a' + 'b' + 'c' + 'd';
  uint16 low  = 'a' + ('a' + 'b') + ('a' + 'b' + 'c') + ('a' + 'b' + 'c' + 'd');
  uint32 sum = (uint32(high) << 16) + low;

  // magic number is hand-calculated, but should equal the above
  ASSERT_EQ(0x18a03d4, sum);
  EXPECT_EQ(sum, IChannel::checksum(msg));
}

const uint64 TIMEOUT = 1000;
typedef boost::shared_ptr<IChannel> Chan;

struct GenClient {
  const Url& url;
  uint64 num;
  GenClient(const Url& url) : url(url), num(0) {}
  Chan operator()() {
    Chan ret(IChannel::make_conn(url, "unittest_client" + stringify(num++)));
    ret->set_timeout(TIMEOUT);
    return ret;
  }
};

struct IChannelTest : public ::testing::TestWithParam<Url> {
  std::vector<uint8> e1,e2;
  Chan server;
  vector<Chan> clients;

  void SetUp() {
    static const char m1[] = "13", m2[] = "26";
    std::copy(m1, m1+sizeof(m1), std::back_inserter(e1));
    std::copy(m2, m2+sizeof(m2), std::back_inserter(e2));
    ASSERT_NO_THROW(server.reset(IChannel::make_bind(GetParam(), "unittest_server")));
    server->set_timeout(TIMEOUT);
    clients.resize(0);
  }

  void make_clients(uint64 count) {
    clients.resize(count);
    ASSERT_NO_THROW(std::generate(clients.begin(), clients.end(), GenClient(GetParam())));
  }

  void TearDown() {
    clients.resize(0);
    server.reset();
  }
};

TEST_P(IChannelTest, ChecksumFailure) {
  RpcWrapper message, a;
  make_clients(1);

  // Need to bake the message by hand to falsify the checksum
  message.set_method("test");
  message.set_payload("rawr!");
  message.set_checksum(clients[0]->checksum(message) + 1);

  size_t len = message.ByteSize();
  boost::scoped_array<uint8> bytes(new uint8[len]);
  message.SerializeToArray(bytes.get(), boost::numeric_cast<int>(len));
  clients[0]->send_bytes(bytes.get(), len);

  // corrupted checksum: should return error
  EXPECT_EQ(-1, server->recv_message(a));

  // Now resend the message properly (though as a response, so we don't violate
  // send/receive order
  message.set_checksum(clients[0]->checksum(message));

  len = message.ByteSize();
  bytes.reset(new uint8[len]);
  message.SerializeToArray(bytes.get(), boost::numeric_cast<int>(len));
  server->send_bytes(bytes.get(), len);

  EXPECT_EQ(1, clients[0]->recv_message(a));
}

TEST_P(IChannelTest, Request) {
  std::vector<uint8> a1;
  make_clients(1);

  clients[0]->send_bytes(&e1[0], e1.size());
  EXPECT_TRUE(server->recv_bytes(&a1));
  EXPECT_RANGE_EQ(e1.begin(), e1.end(), a1.begin(), a1.end());
}

TEST_P(IChannelTest, RequestReply) {
  std::vector<uint8> a1, a2;
  make_clients(1);

  clients[0]->send_bytes(&e1[0], e1.size());
  ASSERT_TRUE(server->recv_bytes(&a1));
  EXPECT_RANGE_EQ(e1.begin(), e1.end(), a1.begin(), a1.end());

  server->send_bytes(&e2[0], e2.size());
  ASSERT_TRUE(clients[0]->recv_bytes(&a2));
  EXPECT_RANGE_EQ(e2.begin(), e2.end(), a2.begin(), a2.end());
}

struct NumberTask {
  struct Msg {
    uint64 id;
    uint64 num;
    Msg(uint64 id, uint64 num) : id(id), num(num) {}
  };

  const Url& url;
  uint64 id;
  bool done;
  std::vector<Msg> received;
  static const uint64 COUNT = 250;

  NumberTask(const Url& url) : url(url), done(false) {}

  Msg unmake(const std::vector<uint8>& b) {
    Msg m(-1,-1);
    VW_ASSERT(b.size() == sizeof(m), LogicErr() << "Error in message size");
    ::memcpy(&m, &b[0], sizeof(m));
    return m;
  }

  void operator()() {
    id = Thread::id();
    ASSERT_NE(0, id) << "None of the threads should be thread 0";
    Chan client(IChannel::make_conn(url, "unittest_client" + stringify(id)));
    client->set_timeout(TIMEOUT);

    received.resize(COUNT, Msg(-1,-1));
    std::vector<uint8> in;
    for (uint64 i = 0; i < COUNT; ++i) {
      Msg out(id, i);
      client->send_bytes(reinterpret_cast<const uint8*>(&out), sizeof(Msg));
      ASSERT_TRUE(client->recv_bytes(&in));
      received[i] = unmake(in);
    }
    done = true;
  }
};

TEST_P(IChannelTest, MultiThreadTorture) {
  uint64 COUNT = 20;

  typedef boost::shared_ptr<NumberTask> task_t;
  typedef boost::shared_ptr<Thread> thread_t;

  vector<task_t>   tasks(COUNT);
  vector<thread_t> threads(COUNT);

  EXPECT_EQ(Thread::id(), 0);

  for (uint64 i = 0; i < COUNT; ++i) {
    tasks[i]   = task_t(new NumberTask(GetParam()));
    threads[i] = thread_t(new Thread(tasks[i]));
  }

  uint64 msgs = 0;
  std::vector<uint8> msg;
  while (1) {
    if (!server->recv_bytes(&msg))
      break;
    server->send_bytes(&msg[0], msg.size());
    msgs++;
  }

  BOOST_FOREACH(thread_t& t, threads)
    t->join();

  ASSERT_EQ(COUNT * NumberTask::COUNT, msgs);

  BOOST_FOREACH(task_t& t, tasks) {
    uint64 i = 0;
    BOOST_FOREACH(const NumberTask::Msg& msg, t->received) {
      EXPECT_EQ(t->id, msg.id);
      EXPECT_EQ(i,     msg.num);
      i++;
    }
  }
}

Url amqp_url(string hostname = "", short port = -1) {
  if (hostname.empty())
    hostname = getenv2("AMQP_TEST_HOSTNAME", "localhost");

  string sport = getenv2("AMQP_TEST_PORT", "5672");
  if (port != -1) {
    sport = boost::lexical_cast<string>(port);
  }
  return string("amqp://") + hostname + ":" + sport + "/unittest/server";
}

std::vector<Url> test_urls() {
  std::vector<Url> v;
#if defined(VW_HAVE_PKG_RABBITMQ_C) && VW_HAVE_PKG_RABBITMQ_C==1
  v.push_back(amqp_url());
#endif
#if defined(VW_HAVE_PKG_ZEROMQ) && VW_HAVE_PKG_ZEROMQ==1
    v.push_back(Url("zmq+ipc://" TEST_OBJDIR "/unittest"));
    v.push_back(Url("zmq+tcp://127.0.0.1:54321"));
    v.push_back(Url("zmq+inproc://unittest"));
#endif
    return v;
}

INSTANTIATE_TEST_CASE_P(URLs, IChannelTest, ::testing::ValuesIn(test_urls()));

struct TestUrls : ::testing::Test {
  Chan server(const Url& u) {
    return Chan(IChannel::make_bind(u, "unittest_server"));
  }
  Chan client(const Url& u) {
    return Chan(IChannel::make_conn(u, "unittest_client"));
  }
};

// Make sure some illegal urls don't pass
TEST_F(TestUrls, Illegal) {
#if defined(VW_HAVE_PKG_ZEROMQ) && VW_HAVE_PKG_ZEROMQ==1
  // can't connect to a wildcard
  EXPECT_THROW(client("zmq+tcp://*:12345"), ArgumentErr);
  // can't connect or bind without a port
  EXPECT_THROW(client("zmq+tcp://127.0.0.1"), ArgumentErr);
  EXPECT_THROW(server("zmq+tcp://127.0.0.1"), ArgumentErr);
  // tcp urls don't take a path
  EXPECT_THROW(server("zmq+tcp://127.0.0.1:12345/b"), ArgumentErr);
  EXPECT_THROW(client("zmq+tcp://127.0.0.1:12345/a"), ArgumentErr);
  // ipc must have a path; / isn't good enough
  EXPECT_THROW(server("zmq+ipc:///"), ArgumentErr);
  EXPECT_THROW(client("zmq+ipc:///"), ArgumentErr);
#endif
}

ext: cxx

max_stars_repo_name: digimatronics/ComputerVision

max_issues_repo_name: rkrishnasanka/visionworkbench

max_forks_repo_name: rkrishnasanka/visionworkbench


text:
/* $Id: image.cpp 49317 2011-04-25 07:19:48Z mordante $ */
/*
   Copyright (C) 2003 - 2011 by David White <dave@whitevine.net>
   Part of the Battle for Wesnoth Project http://www.wesnoth.org/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

/**
 * @file
 * Routines for images: load, scale, re-color, etc.
 */

#define GETTEXT_DOMAIN "wesnoth-lib"

#include "global.hpp"

#include "color_range.hpp"
#include "config.hpp"
#include "filesystem.hpp"
#include "foreach.hpp"
#include "game_config.hpp"
#include "image.hpp"
#include "image_modifications.hpp"
#include "log.hpp"
#include "gettext.hpp"
#include "serialization/string_utils.hpp"

#include "SDL_image.h"

#include <boost/functional/hash.hpp>

#include <list>
#include <set>

static lg::log_domain log_display("display");
#define ERR_DP LOG_STREAM(err, log_display)
#define LOG_DP LOG_STREAM(info, log_display)

template<typename T>
struct cache_item
{
	cache_item(): item(), loaded(false)
	{}

	cache_item(const T &item): item(item), loaded(true)
	{}

	T item;
	bool loaded;
};

namespace image {

template<typename T>
class cache_type
{
public:
	cache_type(): content_()
	{}

	cache_item<T> &get_element(int index) {
		if (static_cast<unsigned>(index) >= content_.size())
			content_.resize(index + 1);
		return content_[index];
	}

	void flush() { content_.clear(); }

private:
	std::vector<cache_item<T> > content_;
};

template <typename T>
bool locator::in_cache(cache_type<T> &cache) const
{
	return index_ < 0 ? false : cache.get_element(index_).loaded;
}

template <typename T>
const T &locator::locate_in_cache(cache_type<T> &cache) const
{
	static T dummy;
	return index_ < 0 ? dummy : cache.get_element(index_).item;
}

template <typename T>
void locator::add_to_cache(cache_type<T> &cache, const T &data) const
{
	if (index_ >= 0)
		cache.get_element(index_) = cache_item<T>(data);
}

}

namespace {

image::locator::locator_finder_t locator_finder;

/** Definition of all image maps */
image::image_cache images_,
		scaled_to_zoom_,
		hexed_images_,
		scaled_to_hex_images_,
		tod_colored_images_,
		brightened_images_,
		semi_brightened_images_;

// cache storing if each image fit in a hex
image::bool_cache in_hex_info_;

// const int cache_version_ = 0;

std::map<std::string,bool> image_existence_map;

// directories where we already cached file existence
std::set<std::string> precached_dirs;

std::map<surface, surface> reversed_images_;

int red_adjust = 0, green_adjust = 0, blue_adjust = 0;

/** List of colors used by the TC image modification */
std::vector<std::string> team_colors;

int zoom = image::tile_size;
int cached_zoom = 0;

} // end anon namespace

namespace image {

std::list<int> dummy_list;

mini_terrain_cache_map mini_terrain_cache;
mini_terrain_cache_map mini_fogged_terrain_cache;

static int last_index_ = 0;

void flush_cache()
{
#ifdef _OPENMP
#pragma omp critical(image_cache)
#endif //_OPENMP
	{
		images_.flush();
		hexed_images_.flush();
		tod_colored_images_.flush();
		scaled_to_zoom_.flush();
		scaled_to_hex_images_.flush();
		brightened_images_.flush();
		semi_brightened_images_.flush();
		in_hex_info_.flush();
		mini_terrain_cache.clear();
		mini_fogged_terrain_cache.clear();
		reversed_images_.clear();
		image_existence_map.clear();
		precached_dirs.clear();
	}
	/* We can't reset last_index_, since some locators are still alive
	   when using :refresh. That would cause them to point to the wrong
	   images. Not resetting the variable causes a memory leak, though. */
	// last_index_ = 0;
}

void locator::init_index()
{
	std::map<value, int>& finder = locator_finder[hash_value(val_)];
	std::map<value, int>::iterator i = finder.find(val_);

	if(i == finder.end()) {
		index_ = last_index_++;
		finder.insert(std::make_pair(val_, index_));
	} else {
		index_ = i->second;
	}
}

void locator::parse_arguments()
{
	std::string& fn = val_.filename_;
	if(fn.empty()) {
		return;
	}
	size_t markup_field = fn.find('~');

	if(markup_field != std::string::npos) {
		val_.type_ = SUB_FILE;
		val_.modifications_ = fn.substr(markup_field, fn.size() - markup_field);
		fn = fn.substr(0,markup_field);
	}
}

locator::locator() :
	index_(-1),
	val_()
{
}

locator::locator(const locator &a, const std::string& mods):
	index_(-1),
	val_(a.val_)
{
	if(mods.size()){
			val_.modifications_ += mods;
			val_.type_=SUB_FILE;
			init_index();
	}
	else index_=a.index_;
}

locator::locator(const char *filename) :
	index_(-1),
	val_(filename)
{
	parse_arguments();
	init_index();
}

locator::locator(const std::string &filename) :
	index_(-1),
	val_(filename)
{
	parse_arguments();
	init_index();
}

locator::locator(const std::string &filename, const std::string& modifications) :
	index_(-1),
	val_(filename, modifications)
{
	init_index();
}

locator::locator(const std::string &filename, const map_location &loc,
		int center_x, int center_y, const std::string& modifications) :
	index_(-1),
	val_(filename, loc, center_x, center_y, modifications)
{
	init_index();
}

locator& locator::operator=(const locator &a)
{
	index_ = a.index_;
	val_ = a.val_;

	return *this;
}

locator::value::value(const locator::value& a) :
  type_(a.type_), filename_(a.filename_), loc_(a.loc_),
  modifications_(a.modifications_),
  center_x_(a.center_x_), center_y_(a.center_y_)
{
}

locator::value::value() :
	type_(NONE), filename_(), loc_(), modifications_(),
  center_x_(0), center_y_(0)

{}

locator::value::value(const char *filename) :
  type_(FILE), filename_(filename), loc_(), modifications_(),
  center_x_(0), center_y_(0)

{
}

locator::value::value(const std::string& filename) :
  type_(FILE), filename_(filename),  loc_(), modifications_(),
  center_x_(0), center_y_(0)

{
}

locator::value::value(const std::string& filename, const std::string& modifications) :
  type_(SUB_FILE), filename_(filename), loc_(), modifications_(modifications),
  center_x_(0), center_y_(0)

{
}

locator::value::value(const std::string& filename, const map_location& loc, int center_x, int center_y, const std::string& modifications) :
  type_(SUB_FILE), filename_(filename), loc_(loc), modifications_(modifications), center_x_(center_x), center_y_(center_y)
{
}

bool locator::value::operator==(const value& a) const
{
	if(a.type_ != type_) {
		return false;
	} else if(type_ == FILE) {
		return filename_ == a.filename_;
	} else if(type_ == SUB_FILE) {
	  return filename_ == a.filename_ && loc_ == a.loc_ && modifications_ == a.modifications_
          && center_x_ == a.center_x_ && center_y_ == a.center_y_;
	} else {
		return false;
	}
}

bool locator::value::operator<(const value& a) const
{
	if(type_ != a.type_) {
		return type_ < a.type_;
	} else if(type_ == FILE) {
		return filename_ < a.filename_;
	} else if(type_ == SUB_FILE) {
		if(filename_ != a.filename_)
			return filename_ < a.filename_;
		if(loc_ != a.loc_)
		        return loc_ < a.loc_;
        if(center_x_ != a.center_x_)
            return center_x_ < a.center_x_;
        if(center_y_ != a.center_y_)
            return center_y_ < a.center_y_;

		return(modifications_ < a.modifications_);
	} else {
		return false;
	}
}

size_t hash_value(const locator::value& val) {
	using boost::hash_value;
	using boost::hash_combine;

	size_t hash = hash_value(val.type_);
	if (val.type_ == locator::FILE || val.type_ == locator::SUB_FILE) {
		hash_combine(hash, val.filename_);
	}
	if (val.type_ == locator::SUB_FILE) {
		hash_combine(hash, val.loc_.x);
		hash_combine(hash, val.loc_.y);
		hash_combine(hash, val.center_x_);
		hash_combine(hash, val.center_y_);
		hash_combine(hash, val.modifications_);
	}

	return hash;
}

// Check if localized file is uptodate according to l10n track index.
// Make sure only that the image is not explicitly recorded as fuzzy,
// in order to be able to use non-tracked images (e.g. from UMC).
static std::set<std::string> fuzzy_localized_files;
static bool localized_file_uptodate (const std::string& loc_file)
{
	if (fuzzy_localized_files.empty()) {
		// First call, parse track index to collect fuzzy files by path.
		std::string fsep = "\xC2\xA6"; // UTF-8 for "broken bar"
		std::string trackpath = get_binary_file_location("", "l10n-track");
		std::string contents = read_file(trackpath);
		std::vector<std::string> lines = utils::split(contents, '\n');
		foreach (const std::string &line, lines) {
			size_t p1 = line.find(fsep);
			if (p1 == std::string::npos)
				continue;
			std::string state = line.substr(0, p1);
			utils::strip(state);
			if (state == "fuzzy") {
				size_t p2 = line.find(fsep, p1 + fsep.length());
				if (p2 == std::string::npos)
					continue;
				std::string relpath = line.substr(p1 + fsep.length(), p2 - p1 - fsep.length());
				fuzzy_localized_files.insert(game_config::path + '/' + relpath);
			}
		}
		fuzzy_localized_files.insert(""); // make sure not empty any more
	}
	return fuzzy_localized_files.count(loc_file) == 0;
}

// Return path to localized counterpart of the given file, if any, or empty string.
// Localized counterpart may also be requested to have a suffix to base name.
static std::string get_localized_path (const std::string& file, const std::string& suff = "")
{
	std::string dir = directory_name(file);
	std::string base = file_name(file);
	const size_t pos_ext = base.rfind(".");
	std::string loc_base;
	if (pos_ext != std::string::npos) {
		loc_base = base.substr(0, pos_ext) + suff + base.substr(pos_ext);
	} else {
		loc_base = base + suff;
	}
	// TRANSLATORS: This is the language code which will be used
	// to store and fetch localized non-textual resources, such as images,
	// when they exist. Normally it is just the code of the PO file itself,
	// e.g. "de" of de.po for German. But it can also be a comma-separated
	// list of language codes by priority, when the localized resource
	// found for first of those languages will be used. This is useful when
	// two languages share sufficient commonality, that they can use each
	// other's resources rather than duplicating them. For example,
	// Swedish (sv) and Danish (da) are such, so Swedish translator could
	// translate this message as "sv,da", while Danish as "da,sv".
	std::vector<std::string> langs = utils::split(_("language code for localized resources^en_US"));
	// In case even the original image is split into base and overlay,
	// add en_US with lowest priority, since the message above will
	// not have it when translated.
	langs.push_back("en_US");
	foreach (const std::string &lang, langs) {
		std::string loc_file = dir + "l10n" + "/" + lang + "/" + loc_base;
		if (file_exists(loc_file) && localized_file_uptodate(loc_file)) {
			return loc_file;
		}
	}
	return "";
}

// Load overlay image and compose it with the original surface.
static void add_localized_overlay (const std::string& ovr_file, surface &orig_surf)
{
	surface ovr_surf = IMG_Load(ovr_file.c_str());
	if (ovr_surf.null()) {
		return;
	}
	SDL_Rect area;
	area.x = 0;
	area.y = 0;
	area.w = ovr_surf->w;
	area.h = ovr_surf->h;
	sdl_blit(ovr_surf, 0, orig_surf, &area);
}

surface locator::load_image_file() const
{
	surface res;

	std::string location = get_binary_file_location("images", val_.filename_);

	{
		if (!location.empty()) {
			// Check if there is a localized image.
			const std::string loc_location = get_localized_path(location);
			if (!loc_location.empty()) {
				location = loc_location;
			}
			res = IMG_Load(location.c_str());
			// If there was no standalone localized image, check if there is an overlay.
			if (!res.null() && loc_location.empty()) {
				const std::string ovr_location = get_localized_path(location, "--overlay");
				if (!ovr_location.empty()) {
					add_localized_overlay(ovr_location, res);
				}
			}
		}
	}

	if (res.null() && !val_.filename_.empty()) {
		ERR_DP << "could not open image '" << val_.filename_ << "'\n";
		if (game_config::debug && val_.filename_ != game_config::images::missing)
			return get_image(game_config::images::missing, UNSCALED);
	}

	return res;
}

surface locator::load_image_sub_file() const
{
	surface surf = get_image(val_.filename_, UNSCALED);
	if(surf == NULL)
		return NULL;

	if(val_.loc_.valid()) {
		SDL_Rect srcrect = create_rect(
				((tile_size*3) / 4) * val_.loc_.x
				, tile_size * val_.loc_.y + (tile_size / 2) * (val_.loc_.x % 2)
				, tile_size
				, tile_size);

		if(val_.center_x_ >= 0 && val_.center_y_>= 0){
			srcrect.x += surf->w/2 - val_.center_x_;
			srcrect.y += surf->h/2 - val_.center_y_;
		}

		surface cut(cut_surface(surf, srcrect));
		surf = mask_surface(cut, get_hexmask());
	}

	modification_queue mods = modification::decode(val_.modifications_);

	while(!mods.empty()) {
		modification* mod = mods.top();
		mods.pop();

		surf = (*mod)(surf);
		delete mod;
	}

	return surf;
}

bool locator::file_exists()
{
	return !get_binary_file_location("images", val_.filename_).empty();
}

surface locator::load_from_disk() const
{
	switch(val_.type_) {
		case FILE:
			return load_image_file();
		case SUB_FILE:
			return load_image_sub_file();
		default:
			return surface(NULL);
	}
}

manager::manager() {}

manager::~manager()
{
	flush_cache();
}

SDL_PixelFormat last_pixel_format;

void set_pixel_format(SDL_PixelFormat* format)
{
	assert(format != NULL);

	SDL_PixelFormat &f = *format;
	SDL_PixelFormat &l = last_pixel_format;
	// if the pixel format change, we clear the cache,
	// because some images are now optimized for the wrong display format
	// FIXME: 8 bpp use palette, need to compare them. For now assume a change
	if (format->BitsPerPixel == 8 ||
		f.BitsPerPixel != l.BitsPerPixel || f.BytesPerPixel != l.BytesPerPixel ||
		f.Rmask != l.Rmask || f.Gmask != l.Gmask || f.Bmask != l.Bmask ||
		f.Rloss != l.Rloss || f.Gloss != l.Gloss || f.Bloss != l.Bloss ||
		f.Rshift != l.Rshift || f.Gshift != l.Gshift || f.Bshift != l.Bshift ||
		f.colorkey != l.colorkey || f.alpha != l.alpha)
	{
		LOG_DP << "detected a new display format\n";
		flush_cache();
	}
	last_pixel_format = *format;
}

void set_color_adjustment(int r, int g, int b)
{
	if(r != red_adjust || g != green_adjust || b != blue_adjust) {
		red_adjust = r;
		green_adjust = g;
		blue_adjust = b;
		tod_colored_images_.flush();
		brightened_images_.flush();
		semi_brightened_images_.flush();
		reversed_images_.clear();
	}
}

color_adjustment_resetter::color_adjustment_resetter()
: r_(red_adjust), g_(green_adjust), b_(blue_adjust)
{
}

void color_adjustment_resetter::reset()
{
	set_color_adjustment(r_, g_, b_);
}

void set_team_colors(const std::vector<std::string>* colors)
{
	if (colors == NULL)
		team_colors.clear();
	else {
		team_colors = *colors;
	}
}

const std::vector<std::string>& get_team_colors()
{
	return team_colors;
}

void set_zoom(int amount)
{
	if(amount != zoom) {
		zoom = amount;
		tod_colored_images_.flush();
		brightened_images_.flush();
		semi_brightened_images_.flush();
		reversed_images_.clear();

		// We keep these caches if:
		// we use default zoom (it doesn't need those)
		// or if they are already at the wanted zoom.
		if (zoom != tile_size && zoom != cached_zoom) {
			scaled_to_zoom_.flush();
			scaled_to_hex_images_.flush();
			cached_zoom = zoom;
		}
	}
}

static surface get_hexed(const locator& i_locator)
{
	surface image(get_image(i_locator, UNSCALED));
	// Re-cut scaled tiles according to a mask.
	return mask_surface(image, get_hexmask());
}

static surface get_scaled_to_hex(const locator& i_locator)
{
	surface img = get_image(i_locator, HEXED);
	return scale_surface(img, zoom, zoom);
}

static surface get_tod_colored(const locator& i_locator)
{
	surface img = get_image(i_locator, SCALED_TO_HEX);
	return adjust_surface_color(img, red_adjust, green_adjust, blue_adjust);
}

static surface get_scaled_to_zoom(const locator& i_locator)
{
	assert(zoom != tile_size);
	assert(tile_size != 0);

	surface res(get_image(i_locator, UNSCALED));
	// For some reason haloes seems to have invalid images, protect against crashing
	if(!res.null()) {
		return scale_surface(res, ((res.get()->w * zoom) / tile_size), ((res.get()->h * zoom) / tile_size));
	} else {
		return surface(NULL);
	}
}

static surface get_brightened(const locator& i_locator)
{
	surface image(get_image(i_locator, TOD_COLORED));
	return surface(brighten_image(image, ftofxp(game_config::hex_brightening)));
}

static surface get_semi_brightened(const locator& i_locator)
{
	surface image(get_image(i_locator, TOD_COLORED));
	return surface(brighten_image(image, ftofxp(game_config::hex_semi_brightening)));
}

///translate type to a simpler one when possible
static TYPE simplify_type(const image::locator& i_locator, TYPE type){
	switch(type) {
	case SCALED_TO_ZOOM:
		if(zoom == tile_size)
			type = UNSCALED;
		break;
	case BRIGHTENED:
		if(ftofxp(game_config::hex_brightening) == ftofxp(1.0))
			type = TOD_COLORED;
		break;
	case SEMI_BRIGHTENED:
		if(ftofxp(game_config::hex_semi_brightening) == ftofxp(1.0))
			type = TOD_COLORED;
		break;
	default:
		break;
	}

	if(type == TOD_COLORED) {
		if (red_adjust==0 && green_adjust==0 && blue_adjust==0)
			type = SCALED_TO_HEX;
	}

	if(type == SCALED_TO_HEX) {
		if(zoom == tile_size)
			type = HEXED;
	}

	if(type == HEXED) {
		// check if the image is already hex-cut by the location system
		if(i_locator.get_loc().valid())
			type = UNSCALED;
	}

	return type;
}

surface get_image(const image::locator& i_locator, TYPE type)
{
	surface res;

	if(i_locator.is_void())
		return res;

	type = simplify_type(i_locator, type);

	image_cache *imap;
	// select associated cache
	switch(type) {
	case UNSCALED:
		imap = &images_;
		break;
	case TOD_COLORED:
		imap = &tod_colored_images_;
		break;
	case SCALED_TO_ZOOM:
		imap = &scaled_to_zoom_;
		break;
	case HEXED:
		imap = &hexed_images_;
		break;
	case SCALED_TO_HEX:
		imap = &scaled_to_hex_images_;
		break;
	case BRIGHTENED:
		imap = &brightened_images_;
		break;
	case SEMI_BRIGHTENED:
		imap = &semi_brightened_images_;
		break;
	default:
		return res;
	}

	// return the image if already cached
	bool tmp;
#ifdef _OPENMP
#pragma omp critical(image_cache)
#endif //_OPENMP
	tmp=i_locator.in_cache(*imap);

	if(tmp) {
		surface result;
#ifdef _OPENMP
#pragma omp critical(image_cache)
#endif //_OPENMP
		result = i_locator.locate_in_cache(*imap);
		return result;
	}

	// not cached, generate it
	switch(type) {
	case UNSCALED:
		// If type is unscaled, directly load the image from the disk.
		res = i_locator.load_from_disk();
		break;
	case TOD_COLORED:
		res = get_tod_colored(i_locator);
		break;
	case SCALED_TO_ZOOM:
		res = get_scaled_to_zoom(i_locator);
		break;
	case HEXED:
		res = get_hexed(i_locator);
		break;
	case SCALED_TO_HEX:
		res = get_scaled_to_hex(i_locator);
		break;
	case BRIGHTENED:
		res = get_brightened(i_locator);
		break;
	case SEMI_BRIGHTENED:
		res = get_semi_brightened(i_locator);
		break;
	default:
		return res;
	}

	// Optimizes surface before storing it
	if(res)
		res = create_optimized_surface(res);

#ifdef _OPENMP
#pragma omp critical(image_cache)
#endif //_OPENMP
	i_locator.add_to_cache(*imap, res);

	return res;
}

surface get_hexmask()
{
	static const image::locator terrain_mask(game_config::images::terrain_mask);
	return get_image(terrain_mask, UNSCALED);
}

bool is_in_hex(const locator& i_locator)
{
	bool result;
#ifdef _OPENMP
#pragma omp critical(in_hex_info_)
#endif //_OPENMP
	{
	if(i_locator.in_cache(in_hex_info_)) {
		result= i_locator.locate_in_cache(in_hex_info_);
	} else {
		const surface image(get_image(i_locator, UNSCALED));

		bool res = in_mask_surface(image, get_hexmask());

		i_locator.add_to_cache(in_hex_info_, res);

		//std::cout << "in_hex : " << i_locator.get_filename()
		//		<< " " << (res ? "yes" : "no") << "\n";

		result= res;
	}
	}
	return result;
}

surface reverse_image(const surface& surf)
{
	if(surf == NULL) {
		return surface(NULL);
	}

	const std::map<surface,surface>::iterator itor = reversed_images_.find(surf);
	if(itor != reversed_images_.end()) {
		// sdl_add_ref(itor->second);
		return itor->second;
	}

	const surface rev(flip_surface(surf));
	if(rev == NULL) {
		return surface(NULL);
	}

	reversed_images_.insert(std::pair<surface,surface>(surf,rev));
	// sdl_add_ref(rev);
	return rev;
}

bool exists(const image::locator& i_locator)
{
	typedef image::locator loc;
	loc::type type = i_locator.get_type();
	if (type != loc::FILE && type != loc::SUB_FILE)
		return false;

	// The insertion will fail if there is already an element in the cache
	std::pair< std::map< std::string, bool >::iterator, bool >
		it = image_existence_map.insert(std::make_pair(i_locator.get_filename(), false));
	bool &cache = it.first->second;
	if (it.second)
		cache = !get_binary_file_location("images", i_locator.get_filename()).empty();
	return cache;
}

static void precache_file_existence_internal(const std::string& dir, const std::string& subdir)
{
	const std::string checked_dir = dir + "/" + subdir;
	if (precached_dirs.find(checked_dir) != precached_dirs.end())
		return;
	precached_dirs.insert(checked_dir);

	std::vector<std::string> files_found;
	std::vector<std::string> dirs_found;
	get_files_in_dir(checked_dir, &files_found, &dirs_found,
			FILE_NAME_ONLY, NO_FILTER, DONT_REORDER);

	for(std::vector<std::string>::const_iterator f = files_found.begin();
			f != files_found.end(); ++f) {
		image_existence_map[subdir + *f] = true;
	}

	for(std::vector<std::string>::const_iterator d = dirs_found.begin();
			d != dirs_found.end(); ++d) {
		precache_file_existence_internal(dir, subdir + *d + "/");
	}
}

void precache_file_existence(const std::string& subdir)
{
	const std::vector<std::string>& paths = get_binary_paths("images");

	for(std::vector<std::string>::const_iterator p = paths.begin();
			 p != paths.end(); ++p) {

		const std::string dir = *p + "/" + subdir;
		precache_file_existence_internal(*p, subdir);
	}
}

bool precached_file_exists(const std::string& file)
{
	std::map<std::string, bool>::const_iterator b =  image_existence_map.find(file);
	if (b != image_existence_map.end())
		return b->second;
	else
		return false;
}

} // end namespace image

max_stars_repo_name: blackberry/Wesnoth

max_issues_repo_name: blackberry/Wesnoth

max_forks_repo_name: blackberry/Wesnoth


text:
// log.inl
//
// Copyright (c) 2016 Piotr K. Semenov (piotr.k.semenov at gmail dot com)
// Distributed under the New BSD License. (See accompanying file LICENSE)

/*!
 \file log.inl

 Provides CORDIC for ln function
 \ref see C. Baumann, "A simple and fast look-up table method to compute the
 exp(x) and ln(x) functions", 2004
*/

#ifndef INC_STD_LOG_INL_
#define INC_STD_LOG_INL_

#include <boost/integer/static_min_max.hpp>
#include <boost/integer/static_log2.hpp>

#include <cassert>

namespace libq {
namespace details {
/*!
 \brief
 \note
*/
template<typename T, std::size_t n, std::size_t f, int e, typename op, typename up>  // NOLINT
class log_of
    : public type_promotion_base<
        fixed_point<typename std::make_signed<T>::type, n, f, e, op, up>
        , boost::static_unsigned_max<
                      (f > 0) ? (boost::static_log2<f>::value) : 0,
                      (n > 0) ? (boost::static_log2<n>::value) : 0>::value + 1u
        , 0
        , 0> {
};
}  // namespace details
}  // namespace libq

namespace std {
template<typename T, std::size_t n, std::size_t f, int e, typename op, typename up>  // NOLINT
typename libq::details::log_of<T, n, f, e, op, up>::promoted_type
    log(libq::fixed_point<T, n, f, e, op, up> _val) {
    using Q = libq::fixed_point<T, n, f, e, op, up>;
    using log_type =
        typename libq::details::log_of<T, n, f, e, op, up>::promoted_type;
    using lut = libq::cordic::lut<f, Q>;

    assert(("[std::log] argument is negaitve", _val >= Q(0)));
    if (_val <= Q(0)) {
        throw std::logic_error("[std::log]: argument is negative");
    }

    // one need 1 bit to represent integer part of reals from [1.0, 2.0]
    using work_type = libq::UQ<f + 1u, f, 0, op, up>;

    // reduces argument to interval [1.0, 2.0]
    int power(0);
    Q arg(_val);
    while (arg >= Q(2.0)) {
        libq::lift(arg) >>= 1u;
        power++;
    }
    while (arg < Q(1.0)) {
        libq::lift(arg) <<= 1u;
        power--;
    }

    // one can consider 0 < y = log(2, x) < 1 as x = 2^y
    // so CORDIC rotation is just a multiplication by 2^{1/2^i}:
    // 2^y = 2^{a1/2} * 2^{a2/4} * ... * 2^{ai/2^i}, where ai is from
    // {0, 1}
    static libq::cordic::lut<f, Q> const inv_pow2_lut = lut::inv_pow2();

    work_type result(0);

#ifdef LOOP_UNROLLING
    auto const iteration_body = [&](std::size_t i) {  // NOLINT
#else
    for (std::size_t i = 0; i != f; ++i) {
#endif
        if (work_type(arg * inv_pow2_lut[i]) >= work_type(1.0)) {
            arg = work_type(arg * inv_pow2_lut[i]);

            libq::lift(result) +=
                typename work_type::storage_type(1u) << (f - i - 1u);
        }
    };  // NOLINT
#ifdef LOOP_UNROLLING
    libq::details::unroll(iteration_body, 0u, libq::details::loop_size<f-1>());
#endif

    log_type const r0(log_type(result) + log_type(power));
    log_type const r1(r0 * work_type::CONST_1_LOG2E);

    return r1;
}
}  // namespace std

#endif  // INC_STD_LOG_INL_

ext: inl

max_stars_repo_name: piotr-semenov/libq

max_issues_repo_name: aka-sps/libq

max_forks_repo_name: aka-sps/libq


text:
// chapter 3

#include <iostream>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_float.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/static_assert.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/equal.hpp>
using namespace boost::mpl::placeholders;
#include <iterator>
#include <utility>
#include <list>
#include <vector>
#include <string>
#include <assert.h>

namespace mpl = boost::mpl;

typedef mpl::vector_c<int, 1, 0, 0, 0> mass;
typedef mpl::vector_c<int, 0, 1, 0, 0> length;
typedef mpl::vector_c<int, 0, 0, 1, 0> time;
typedef mpl::vector_c<int, 0, 1, -2, 0> accel;
typedef mpl::vector_c<int, 1, 1, -2, 0> force;
typedef mpl::vector_c<int, 0, 0, 0, 0> scalar;

template <class T, class Dimension>
struct Quantity
{
	Quantity(T x) : m_value(x) {}
	template <class OtherDimension>
	Quantity( Quantity<T, OtherDimension> &rhs) : m_value(rhs.value())
	{
		BOOST_STATIC_ASSERT((
			mpl::equal< Dimension, OtherDimension >::type::value
			));
	}

	T m_value;
	T value() const { return m_value; }

	template<class OtherDimension>
	Quantity<T, Dimension>& operator=(Quantity<T, OtherDimension> &rhs)
	{
		BOOST_STATIC_ASSERT((
			mpl::equal< Dimension, OtherDimension >::type::value
			));

		if (this != &rhs)
		{
			m_value = rhs.value();
		}
		return *this;
	}

	Quantity<T, Dimension> operator+(const Quantity<T, Dimension> &rhs)
	{
		return Quantity<T, Dimension>(value() + rhs.value());
	}
	Quantity<T, Dimension> operator-(const Quantity<T, Dimension> &rhs)
	{
		return Quantity<T, Dimension>(value() - rhs.value());
	}

	struct minus_f
	{
		template <class T1, class T2>
		struct apply : mpl::minus<T1,T2> {};
	};

	template <class OtherDimension>
	Quantity<
		T,
		typename mpl::transform<Dimension, OtherDimension, mpl::plus<_1,_2> >::type
	>
		operator*(const Quantity<T, OtherDimension> &rhs)
	{
		typedef typename mpl::transform<Dimension, OtherDimension, mpl::plus<_1,_2> >::type dim;
		return Quantity<T, dim>(value() * rhs.value());
	}

	template <class OtherDimension>
	Quantity<T, typename mpl::transform<Dimension, OtherDimension, minus_f>::type >
		operator/(const Quantity<T, OtherDimension> &rhs)
	{
		typedef typename mpl::transform<Dimension, OtherDimension, minus_f>::type dim;
		return Quantity<T, dim>(value() / rhs.value());
	}

};

void main()
{
	Quantity<float, mass> m(3.f);
	Quantity<float, mass> m2(4.f);
	Quantity<float, length> l(5.f);
	Quantity<float, accel> a(5.f);
	Quantity<float, mass> m3 = m + m2;
	Quantity<float, mass> m4 = m - m2;
	Quantity<float, force> f = m * a;

	m4 = f/a;

	BOOST_STATIC_ASSERT((
		mpl::plus<
		mpl::int_<2>
		,mpl::int_<3>
		,mpl::int_<4>
		>::type::value == 9
		));

}

max_stars_repo_name: jjuiddong/TemplateMetaProgramming

max_issues_repo_name: jjuiddong/TemplateMetaProgramming

max_forks_repo_name: jjuiddong/TemplateMetaProgramming


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

#include <boost/filesystem.hpp>

#include "test_helpers.h"
#include "wallet/core/common.h"
#include "wallet/core/simple_transaction.h"
#include "wallet/core/wallet_network.h"
#include "keykeeper/local_private_key_keeper.h"
// for wallet_test_environment.cpp
#include "core/unittest/mini_blockchain.h"
#include "core/radixtree.h"
#include "utility/test_helpers.h"
#include "node/node.h"

WALLET_TEST_INIT
#include "wallet_test_environment.cpp"
#include "mock_bbs_network.cpp"

#include "wallet/client/extensions/broadcast_gateway/broadcast_router.h"
#include "wallet/client/extensions/news_channels/interface.h"
#include "wallet/client/extensions/news_channels/broadcast_msg_validator.h"
#include "wallet/client/extensions/news_channels/broadcast_msg_creator.h"
#include "wallet/client/extensions/news_channels/updates_provider.h"

#include <tuple>

using namespace beam;
using namespace beam::wallet;

namespace
{
    using PrivateKey = ECC::Scalar::Native;
    using PublicKey = PeerID;

    /**
     *  Class to test correct notification of news channels observers
     */
    struct MockNewsObserver : public INewsObserver, public IExchangeRateObserver
    {
        using OnVersion = function<void(const VersionInfo&, const ECC::uintBig&)>;
        using OnRate = function<void(const ExchangeRates&)>;

        MockNewsObserver(OnVersion onVers, OnRate onRate)
            : m_onVers(onVers)
            , m_onRate(onRate) {};

        virtual void onNewWalletVersion(const VersionInfo& v, const ECC::uintBig& s) override
        {
            m_onVers(v, s);
        }
        virtual void onExchangeRates(const ExchangeRates& r) override
        {
            m_onRate(r);
        }

        OnVersion m_onVers;
        OnRate m_onRate;
    };

    /**
     *  Derive key pair with specified @keyIndex
     */
    std::tuple<PublicKey, PrivateKey> deriveKeypair(IWalletDB::Ptr walletDB, uint64_t keyIndex)
    {
        PrivateKey sk;
        PublicKey pk;
        walletDB->get_MasterKdf()->DeriveKey(sk, ECC::Key::ID(keyIndex, Key::Type::Bbs));
        pk.FromSk(sk);
        return std::make_tuple(pk, sk);
    }

    /**
     *  Create signature for @data using key derived with specified @keyIndex
     *  return derived public key and signature
     */
    std::tuple<PublicKey, ByteBuffer> signData(const ByteBuffer& data, uint64_t keyIndex, IWalletDB::Ptr walletDB)
    {
        const auto& [pk, sk] = deriveKeypair(walletDB, keyIndex);
        SignatureHandler signHandler;
        signHandler.m_data = data;
        signHandler.Sign(sk);
        ByteBuffer rawSignature = toByteBuffer(signHandler.m_Signature);
        return std::make_tuple(pk, rawSignature);
    }

    /**
     *  Create message with Protocol header according to broadcast protocol
     */
    ByteBuffer addProtocolHeader(const BroadcastMsg& body, BroadcastContentType type)
    {
        ByteBuffer content = toByteBuffer(body);
        ByteBuffer msg(MsgHeader::SIZE + content.size());
        MsgHeader header(0, // V0
                         0, // V1
                         1, // V2
                         static_cast<uint8_t>(type),
                         static_cast<uint8_t>(content.size()));
        header.write(msg.data());
        std::copy(std::cbegin(content),
                  std::cend(content),
                  std::begin(msg) + MsgHeader::SIZE);
        return msg;
    };

    /**
     * Create BroadcastMsg with specified string
     */
    // BroadcastMsg createBroadcastMsg(std::string testString)
    // {
    //     BroadcastMsg res = { toByteBuffer(testString), };
    //     return res;
    // }

    /**
     *  Tests:
     *  - only correctly signed with PrivateKey messageas are accepted
     *  - publishers PublicKeys are correcly accepted
     */
    void TestSignatureValidation()
    {
        cout << endl << "Test BroadcastMsgValidator signature verification" << endl;

        auto senderWalletDB = createSenderWalletDB();
        BroadcastMsgValidator validator;

        // generate key pairs for test
        std::array<std::pair<PublicKey,PrivateKey>,10> keyPairsArray;
        for (size_t i = 0; i < keyPairsArray.size(); ++i)
        {
            const auto [pk, sk] = deriveKeypair(senderWalletDB, i);
            keyPairsArray[i] = std::make_pair(pk, sk);
        }

        // generate cases for test
        const std::array<std::pair<bool, bool>, keyPairsArray.size()> keyDistributionTable =
        {
            // different combinations with keys:
            // (loadKeyToEndpoint, signDataWithKey)
            std::make_pair(true, true),
            std::make_pair(true, false),
            std::make_pair(false, true),
            std::make_pair(false, false),
            std::make_pair(true, true),
            std::make_pair(true, false),
            std::make_pair(false, true),
            std::make_pair(false, false),
            std::make_pair(true, true),
            std::make_pair(true, true)
        };

        // prepare messages and publisher keys
        std::array<ByteBuffer, keyPairsArray.size()> messages;  // messages for test
        std::vector<PublicKey> publisherKeys;   // keys to load in NewsEndpoint
        for (size_t i = 0; i < keyPairsArray.size(); ++i)
        {
            const auto [to_load, to_sign] = keyDistributionTable[i];
            const auto& [pubKey, privKey] = keyPairsArray[i];

            if (to_load) publisherKeys.push_back(pubKey);

            BroadcastMsg msg;
            msg.m_content = toByteBuffer(std::to_string(i));
            SignatureHandler signHandler;
            signHandler.m_data = msg.m_content;
            if (to_sign) signHandler.Sign(privKey);
            msg.m_signature = toByteBuffer(signHandler.m_Signature);
            messages[i] = toByteBuffer(msg);
        }

        WALLET_CHECK_NO_THROW(validator.setPublisherKeys(publisherKeys));

        // Push messages and check validation result
        for (size_t i = 0; i < messages.size(); ++i)
        {
            const ByteBuffer& data = messages[i];
            BroadcastMsg msg;
            bool res = false;
            WALLET_CHECK_NO_THROW(res = validator.processMessage(data, msg));

            auto [keyLoaded, msgSigned] = keyDistributionTable[i];

            if (res)
            {
                // Only messages with signed with correct keys have to pass validation
                WALLET_CHECK(keyLoaded && msgSigned);
                // Check content
                ByteBuffer referenceContent = toByteBuffer(std::to_string(i));
                WALLET_CHECK(referenceContent == msg.m_content);
            }
            else
            {
                WALLET_CHECK(!keyLoaded || !msgSigned);
                // key not loaded to validator or message not correctly signed
                // are the reasons to fail
            }
        }
        cout << "Test end" << endl;
    }

    /**
     *  Test BroadcastMsgValidator key loading
     */
    void TestPublisherKeysLoading()
    {
        cout << endl << "Test BroadcastMsgValidator keys loading" << endl;

        auto senderWalletDB = createSenderWalletDB();
        BroadcastMsgValidator validator;

        {
            cout << "Case: no keys loaded, not signed message" << endl;

            BroadcastMsg msg;
            msg.m_content = toByteBuffer(std::string("not signed message"));
            SignatureHandler signHandler;
            signHandler.m_data = msg.m_content;
            msg.m_signature = toByteBuffer(signHandler.m_Signature);
            ByteBuffer data = toByteBuffer(msg);

            bool res = false;
            WALLET_CHECK_NO_THROW(res = validator.processMessage(data, msg));
            WALLET_CHECK(!res);
        }
        {
            cout << "Case: no keys loaded, correct message" << endl;

            BroadcastMsg msg;
            msg.m_content = toByteBuffer(std::string("correct message"));

            const auto& [pk, signature] = signData(msg.m_content, 123, senderWalletDB);
            msg.m_signature = signature;
            ByteBuffer data = toByteBuffer(msg);

            bool res = false;
            BroadcastMsg resMsg;
            WALLET_CHECK_NO_THROW(res = validator.processMessage(data, resMsg));
            WALLET_CHECK(!res);

            cout << "Case: key loaded, correct message" << endl;
            WALLET_CHECK_NO_THROW(validator.setPublisherKeys({pk}));
            WALLET_CHECK_NO_THROW(res = validator.processMessage(data, resMsg));
            WALLET_CHECK(res);
            WALLET_CHECK(msg == resMsg);

            cout << "Case: keys cleared" << endl;

            WALLET_CHECK_NO_THROW(validator.setPublisherKeys({}));
            WALLET_CHECK(!validator.processMessage(data, resMsg));
        }
        {
            cout << "Case: new key loaded" << endl;

            BroadcastMsg msg;
            msg.m_content = toByteBuffer(std::string("test message"));
            const auto& [pk, signature] = signData(msg.m_content, 159, senderWalletDB);
            msg.m_signature = signature;
            ByteBuffer data = toByteBuffer(msg);

            WALLET_CHECK_NO_THROW(validator.setPublisherKeys({pk}));
            bool res = false;
            BroadcastMsg resMsg;
            WALLET_CHECK_NO_THROW(res = validator.processMessage(data, resMsg));
            WALLET_CHECK(res);
            WALLET_CHECK(msg == resMsg);
        }
        cout << "Test end" << endl;
    }

    void TestNewsChannelsObservers()
    {
        cout << endl << "Test news channels observers" << endl;

        MockBbsNetwork network;
        BroadcastRouter broadcastRouter(network, network);
        BroadcastMsgValidator validator;
        AppUpdateInfoProvider updatesProvider(broadcastRouter, validator);
        // TODO exchange rates provider test
        auto senderWalletDB = createSenderWalletDB();

        int notificationCount = 0;

        const VersionInfo verInfo = { VersionInfo::Application::DesktopWallet, Version {123,456,789} };
        // const ExchangeRates rates = {getTimestamp(), { ExchangeRate { ExchangeRates::Currency::Beam,
        //                                                               147852369,
        //                                                               ExchangeRates::Currency::Usd
        //                                                             }}};

        BroadcastMsg msg;
        msg.m_content = toByteBuffer(verInfo);
        const auto& [pk, signature] = signData(msg.m_content, 321, senderWalletDB);
        msg.m_signature = signature;

        MockNewsObserver testObserver(
            [&notificationCount, &verInfo/*, &signature*/]
            (const VersionInfo& v, const ECC::uintBig& s)
            {
                WALLET_CHECK(verInfo == v);
                // WALLET_CHECK(signature == toByteBuffer(s));
                ++notificationCount;
            },
            [&notificationCount/*, &rates*/]
            (const ExchangeRates& r)
            {
                // WALLET_CHECK(rates == r);
                ++notificationCount;
            });

        {
            // loading correct key with 2 additional just for filling
            PublicKey pk2, pk3;
            std::tie(pk2, std::ignore) = deriveKeypair(senderWalletDB, 789);
            std::tie(pk3, std::ignore) = deriveKeypair(senderWalletDB, 456);
            validator.setPublisherKeys({pk, pk2, pk3});
        }

        {
            cout << "Case: subscribed on valid message" << endl;
            updatesProvider.Subscribe(&testObserver);
            broadcastRouter.sendMessage(BroadcastContentType::SoftwareUpdates, msg);
            WALLET_CHECK(notificationCount == 1);
        }
        {
            cout << "Case: unsubscribed on valid message" << endl;
            updatesProvider.Unsubscribe(&testObserver);
            broadcastRouter.sendMessage(BroadcastContentType::SoftwareUpdates, msg);
            WALLET_CHECK(notificationCount == 1);
        }
        {
            cout << "Case: subscribed back" << endl;
            updatesProvider.Subscribe(&testObserver);
            broadcastRouter.sendMessage(BroadcastContentType::SoftwareUpdates, msg);
            WALLET_CHECK(notificationCount == 2);
        }
        {
            cout << "Case: subscribed on invalid message" << endl;
            // sign the same message with other key
            ByteBuffer newSignature;
            std::tie(std::ignore, newSignature) = signData(msg.m_content, 322, senderWalletDB);
            msg.m_signature = newSignature;

            broadcastRouter.sendMessage(BroadcastContentType::SoftwareUpdates, msg);
            WALLET_CHECK(notificationCount == 2);
        }
        cout << "Test end" << endl;
    }

    void TestStringToKeyConvertation()
    {
        cout << endl << "Test string to key convertation" << endl;

        {
            ECC::uintBig referencePubKey = {
                0xdb, 0x61, 0x7c, 0xed, 0xb1, 0x75, 0x43, 0x37,
                0x5b, 0x60, 0x20, 0x36, 0xab, 0x22, 0x3b, 0x67,
                0xb0, 0x6f, 0x86, 0x48, 0xde, 0x2b, 0xb0, 0x4d,
                0xe0, 0x47, 0xf4, 0x85, 0xe7, 0xa9, 0xda, 0xec
            };

            bool res = false;
            PeerID key;
            WALLET_CHECK_NO_THROW(res = BroadcastMsgValidator::stringToPublicKey("db617cedb17543375b602036ab223b67b06f8648de2bb04de047f485e7a9daec", key));
            WALLET_CHECK(res && key == referencePubKey);
        }
        {
            ECC::uintBig referencePrivateKey = {
                0xf7, 0x0c, 0x36, 0xf2, 0xd8, 0x34, 0x2b, 0x66,
                0xe3, 0x08, 0x1e, 0xa4, 0xd8, 0x75, 0x43, 0x56,
                0x6d, 0x6a, 0xd2, 0x42, 0xc6, 0xe6, 0x1d, 0xbf,
                0x92, 0x6d, 0x57, 0xff, 0x42, 0xde, 0x0c, 0x59
            };
            ECC::Scalar refKey;
            refKey.m_Value = referencePrivateKey;
            ECC::Scalar::Native nativeKey;
            nativeKey.Import(refKey);

            bool res = false;
            ECC::Scalar::Native key;
            WALLET_CHECK_NO_THROW(res = BroadcastMsgCreator::stringToPrivateKey("f70c36f2d8342b66e3081ea4d87543566d6ad242c6e61dbf926d57ff42de0c59", key));
            WALLET_CHECK(res && key == nativeKey);
        }
    }

    void TestProtocolBuilder()
    {
        cout << endl << "Test BroadcastMsgCreator" << endl;
        // TODO Newscast test
        /// Create message signed with private key
        // static ByteBuffer createMessage(const NewsMessage& content, const PrivateKey& key);
    }

    void TestSoftwareVersion()
    {
        cout << endl << "Test Version" << endl;

        {
            Version v {123, 456, 789};
            WALLET_CHECK(to_string(v) == "123.456.789");
            // WALLET_CHECK(to_string(Version::getCurrent()) == PROJECT_VERSION);
        }

        {
            WALLET_CHECK(Version(12,12,12) == Version(12,12,12));
            WALLET_CHECK(!(Version(12,12,12) != Version(12,12,12)));
            WALLET_CHECK(Version(12,13,12) != Version(12,12,12));
            WALLET_CHECK(!(Version(12,13,12) == Version(12,12,12)));

            WALLET_CHECK(Version(12,12,12) < Version(13,12,12));
            WALLET_CHECK(Version(12,12,12) < Version(12,13,12));
            WALLET_CHECK(Version(12,12,12) < Version(12,12,13));
            WALLET_CHECK(Version(12,12,12) < Version(13,13,13));
            WALLET_CHECK(!(Version(12,12,12) < Version(12,12,12)));
        }

        {
            Version v;
            bool res = false;

            WALLET_CHECK_NO_THROW(res = v.from_string("12.345.6789"));
            WALLET_CHECK(res == true);
            WALLET_CHECK(v == Version(12,345,6789));

            WALLET_CHECK_NO_THROW(res = v.from_string("0.0.0"));
            WALLET_CHECK(res == true);
            WALLET_CHECK(v == Version());

            WALLET_CHECK_NO_THROW(res = v.from_string("12345.6789"));
            WALLET_CHECK(res == false);

            WALLET_CHECK_NO_THROW(res = v.from_string("12,345.6789"));
            WALLET_CHECK(res == false);

            WALLET_CHECK_NO_THROW(res = v.from_string("12.345.6e89"));
            WALLET_CHECK(res == false);

            WALLET_CHECK_NO_THROW(res = v.from_string("12345.6789.12.52"));
            WALLET_CHECK(res == false);

            WALLET_CHECK_NO_THROW(res = v.from_string("f12345.6789.52"));
            WALLET_CHECK(res == false);
        }

        {
            WALLET_CHECK("desktop" == VersionInfo::to_string(VersionInfo::Application::DesktopWallet));
            WALLET_CHECK(VersionInfo::Application::DesktopWallet == VersionInfo::from_string("desktop"));
        }
    }

} // namespace

int main()
{
    cout << "News channels tests:" << endl;

    io::Reactor::Ptr mainReactor{ io::Reactor::create() };
    io::Reactor::Scope scope(*mainReactor);

    TestSignatureValidation();
    TestPublisherKeysLoading();
    TestNewsChannelsObservers();
    TestStringToKeyConvertation();
    // TestProtocolBuilder();
    TestSoftwareVersion();

    assert(g_failureCount == 0);
    return WALLET_CHECK_RESULT;
}

max_stars_repo_name: DrakenTech/beam

max_issues_repo_name: dickieminton/full-beam

max_forks_repo_name: dickieminton/full-beam


text:
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkNumericTraits.h"

#include "vnl/vnl_matrix_ref.h"
#include "vnl/vnl_matrix.h"
#include "tkdCmdParser.h"

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/small_world_generator.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/graph/graph_utility.hpp>

/**
 * Date: 16-11-2009
 */
class CreateSmallWorld {

public:

	typedef double PixelType;
	typedef itk::Image< PixelType, 2 > ImageType;
	typedef vnl_matrix_ref< PixelType > DataMatrixType;
	typedef itk::ImageFileWriter< ImageType > WriterType;

	typedef boost::adjacency_list<> GraphType;
	typedef boost::small_world_iterator< boost::minstd_rand, GraphType > SWGenerator;

	/**
	 * Run.
	 */
	void run( const std::string& output, unsigned int size, unsigned int k, PixelType probability, bool verbose )
	{
		WriterType::Pointer writer = WriterType::New();

		writer->SetFileName( output.c_str() );
		writer->SetInput( GetMatrix( size, k, probability, verbose ) );

		try {
			writer->Update();
		} catch ( itk::ExceptionObject& e ) {
			std::cerr << "Error writing: " << output << std::endl;
			std::cerr << e.GetDescription() << std::endl;
		}

	}

protected:

	/**
	 * Return regular matrix.
	 */
	ImageType::Pointer GetMatrix( unsigned int matrixSize, unsigned int k, PixelType probability, bool verbose )
	{
		ImageType::Pointer outputImage = ImageType::New();
		ImageType::SizeType size;
		ImageType::RegionType region;
		size[ 0 ] = matrixSize;
		size[ 1 ] = matrixSize;

		region.SetSize( size );
		outputImage->SetRegions( region );
		outputImage->Allocate();

		boost::minstd_rand generator;

		GraphType g( SWGenerator( generator, matrixSize, k, probability ), SWGenerator(), matrixSize );

		boost::property_map< GraphType, boost::vertex_index_t >::type vertices
			= boost::get( boost::vertex_index, g );

		for( boost::graph_traits< GraphType >::edge_iterator e = edges( g ).first; e != edges( g ).second; ++e )
	    {
			ImageType::IndexType index;
			index[0] = boost::get( vertices, boost::source( *e, g ) );
	    	index[1] = boost::get( vertices, boost::target( *e, g ) );
	    	outputImage->SetPixel( index, static_cast< PixelType >( 1.0 ) );
	    }

		if ( verbose )
			boost::print_graph( g );

		return outputImage;
	}
};

/**
 * Create regular matrix.
 */
int main( int argc, char ** argv ) {
	tkd::CmdParser p( "create_smallworld", "Construct smallworld graph." );

	std::string output;
	int size = 10;
	int k = 2;
	float probability = 0.03;
	bool verbose;

	p.AddArgument( output, "output" ) ->AddAlias( "o" ) ->SetInput( "filename" ) ->SetDescription( "Output matrix file name" ) ->SetRequired(
			true ) -> SetMinMax( 1, 1 );

	p.AddArgument( size, "size" ) ->AddAlias( "s" ) ->SetInput( "uint" ) ->SetDescription( "Number of nodes [ default: 10 ]" );

	p.AddArgument( k, "k" ) ->AddAlias( "k" ) ->SetInput( "uint" ) ->SetDescription( "K [ default: 2 ]" );

	p.AddArgument( probability, "probability" ) ->AddAlias( "p" ) ->SetInput( "float" ) ->SetDescription( "Rewire probability [ default: 0.03 ]" );

	p.AddArgument( verbose, "verbose" ) ->AddAlias( "v" ) ->SetInput( "bool" ) ->SetDescription( "Print graph to screen" );

	if ( !p.Parse( argc, argv ) ) {
		p.PrintUsage( std::cout );
		return EXIT_FAILURE;
	}

	CreateSmallWorld createSmallWorld;

	createSmallWorld.run( output, size, k, probability, verbose );

	return EXIT_SUCCESS;
}

max_stars_repo_name: wmotte/toolkid

max_issues_repo_name: wmotte/toolkid

max_forks_repo_name: wmotte/toolkid


text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
//
// The following only applies to changes made to this file as part of YugaByte development.
//
// Portions Copyright (c) YugaByte, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied.  See the License for the specific language governing permissions and limitations
// under the License.
//

#include "yb/util/net/dns_resolver.h"

#include <mutex>
#include <shared_mutex>
#include <unordered_map>
#include <vector>

#include <boost/optional.hpp>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "yb/util/concurrent_value.h"
#include "yb/util/flag_tags.h"
#include "yb/util/metrics.h"
#include "yb/util/net/net_util.h"
#include "yb/util/net/sockaddr.h"

using namespace std::literals;

DEFINE_int64(dns_cache_expiration_ms, 60000, "Time to store DNS resolution results in cache.");

namespace yb {

namespace {

Result<IpAddress> PickResolvedAddress(
    const std::string& host, const boost::system::error_code& error,
    const ResolverResults& entries) {
  if (error) {
    return STATUS_FORMAT(NetworkError, "Resolve failed $0: $1", host, error.message());
  }
  std::vector<IpAddress> addresses;
  for (const auto& entry : entries) {
    addresses.push_back(entry.endpoint().address());
    VLOG(3) << "Resolved address " << entry.endpoint().address().to_string()
            << " for host " << host;
  }
  FilterAddresses(FLAGS_net_address_filter, &addresses);
  if (addresses.empty()) {
    return STATUS_FORMAT(NetworkError, "No endpoints resolved for: $0", host);
  }
  std::sort(addresses.begin(), addresses.end());
  addresses.erase(std::unique(addresses.begin(), addresses.end()), addresses.end());
  if (addresses.size() > 1) {
    LOG(WARNING) << "Peer address '" << host << "' "
                 << "resolves to " << yb::ToString(addresses) << " different addresses. Using "
                 << yb::ToString(addresses.front());
  }

  VLOG(3) << "Returned address " << addresses[0].to_string() << " for host "
          << host;
  return addresses.front();
}

} // namespace

class DnsResolver::Impl {
 public:
  explicit Impl(IoService* io_service) : resolver_(*io_service) {}

  std::shared_future<Result<IpAddress>> ResolveFuture(const std::string& host) {
    return ObtainEntry(host)->DoResolve(host, /* callback= */ nullptr, &resolver_);
  }

  void AsyncResolve(const std::string& host, const AsyncResolveCallback& callback) {
    ObtainEntry(host)->DoResolve(host, &callback, &resolver_);
  }

 private:
  using Resolver = boost::asio::ip::basic_resolver<boost::asio::ip::tcp>;

  struct CacheEntry {
    std::mutex mutex;
    CoarseTimePoint expiration GUARDED_BY(mutex) = CoarseTimePoint::min();
    std::shared_future<Result<IpAddress>> future GUARDED_BY(mutex);
    std::vector<AsyncResolveCallback> waiters GUARDED_BY(mutex);

    void SetResult(
        const Result<IpAddress>& result,
        std::promise<Result<IpAddress>>* promise) EXCLUDES(mutex) {
      try {
        promise->set_value(result);
      } catch (std::future_error& error) {
        return;
      }

      decltype(waiters) to_notify;
      {
        std::lock_guard<std::mutex> lock(mutex);
        expiration = CoarseMonoClock::now() + FLAGS_dns_cache_expiration_ms * 1ms;
        waiters.swap(to_notify);
      }
      for (const auto& waiter : to_notify) {
        waiter(result);
      }
    }

    std::shared_future<Result<IpAddress>> DoResolve(
        const std::string& host, const AsyncResolveCallback* callback, Resolver* resolver) {
      std::shared_ptr<std::promise<Result<IpAddress>>> promise;
      std::shared_future<Result<IpAddress>> result;
      {
        std::lock_guard<std::mutex> lock(mutex);
        promise = StartResolve(host);
        result = future;
        if (callback && expiration == CoarseTimePoint::max()) {
          // Resolve is in progress by a different caller.
          waiters.push_back(*callback);
          callback = nullptr;
        }
      }

      if (callback) {
        (*callback)(result.get());
      }

      if (promise) {
        static const std::string kService = "";
        resolver->async_resolve(
            Resolver::query(host, kService),
            [this, host, promise](
                const boost::system::error_code& error,
                const Resolver::results_type& entries) mutable {
          // Unfortunately there is no safe way to set promise value from 2 different threads, w/o
          // catching exception in case of concurrency.
          SetResult(PickResolvedAddress(host, error, entries), promise.get());
        });

        if (resolver->get_io_context().stopped()) {
          SetResult(STATUS(Aborted, "Messenger already stopped"), promise.get());
        }
      }

      return result;
    }

    std::shared_ptr<std::promise<Result<IpAddress>>> StartResolve(
        const std::string& host) REQUIRES(mutex) {
      if (expiration >= CoarseMonoClock::now()) {
        return nullptr;
      }

      auto promise = std::make_shared<std::promise<Result<IpAddress>>>();
      future = promise->get_future().share();

      auto address = TryFastResolve(host);
      if (address) {
        expiration = CoarseTimePoint::max() - 1ms;
        promise->set_value(*address);
        return nullptr;
      } else {
        expiration = CoarseTimePoint::max();
      }

      return promise;
    }
  };

  CacheEntry* ObtainEntry(const std::string& host) {
    {
      std::shared_lock<decltype(mutex_)> lock(mutex_);
      auto it = cache_.find(host);
      if (it != cache_.end()) {
        return &it->second;
      }
    }

    std::lock_guard<decltype(mutex_)> lock(mutex_);
    return &cache_[host];
  }

  Resolver resolver_;
  std::shared_timed_mutex mutex_;
  std::unordered_map<std::string, CacheEntry> cache_;
};

DnsResolver::DnsResolver(IoService* io_service) : impl_(new Impl(io_service)) {
}

DnsResolver::~DnsResolver() {
}

namespace {

thread_local Histogram* active_metric_ = nullptr;

} // anonymous namespace

ScopedDnsTracker::ScopedDnsTracker(const scoped_refptr<Histogram>& metric)
    : old_metric_(active_metric()), metric_(metric) {
  active_metric_ = metric.get();
}

ScopedDnsTracker::~ScopedDnsTracker() {
  DCHECK_EQ(metric_.get(), active_metric());
  active_metric_ = old_metric_;
}

Histogram* ScopedDnsTracker::active_metric() {
  return active_metric_;
}

std::shared_future<Result<IpAddress>> DnsResolver::ResolveFuture(const std::string& host) {
  return impl_->ResolveFuture(host);
}

void DnsResolver::AsyncResolve(const std::string& host, const AsyncResolveCallback& callback) {
  impl_->AsyncResolve(host, callback);
}

Result<IpAddress> DnsResolver::Resolve(const std::string& host) {
  return ResolveFuture(host).get();
}

} // namespace yb

ext: cc

max_stars_repo_name: impira/yugabyte-db

max_issues_repo_name: impira/yugabyte-db

max_forks_repo_name: impira/yugabyte-db


text:
//==============================================================================
//         Copyright 2003 - 2012   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2012   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//         Copyright 2011 - 2012   MetaScale SAS
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_CORE_FUNCTIONS_EXPR_ARRAYFUN_HPP_INCLUDED
#define NT2_CORE_FUNCTIONS_EXPR_ARRAYFUN_HPP_INCLUDED

#include <nt2/core/functions/arrayfun.hpp>
#include <nt2/include/functions/run.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/dispatch/meta/result_of.hpp>
#include <boost/dispatch/meta/as_ref.hpp>

namespace nt2 { namespace ext
{
  #define M0(z, n, t) (A##n)
  #define M1(z, n, t) (generic_< unspecified_<A##n> >)

  #define M3(z, n, t)                                                                              \
  typename boost::dispatch::meta::                                                                 \
  as_ref< typename meta::                                                                          \
          call< tag::run_( typename boost::proto::result_of::child_c<Expr&, n+1>::type             \
                         , State const&                                                            \
                         , typename boost::simd::ext::                                             \
                           adapt_data< typename boost::proto::result_of::child_c<Expr, n+1>::type  \
                                     , Data                                                        \
                                     >::type                                                       \
                         )                                                                         \
              >::type                                                                              \
        >::type                                                                                \
  /**/

  #define M4(z, n, t) nt2::run(boost::proto::child_c<n+1>(expr), state, boost::simd::ext::adapt_data<typename boost::proto::result_of::child_c<Expr, n+1>::type, Data>::call(data))

  #define M2(z, n, t)                                                                              \
  BOOST_DISPATCH_IMPLEMENT  ( arrayfun_, tag::cpu_                                       \
                            , (F)BOOST_PP_REPEAT(n, M0, ~)                                         \
                            , (unspecified_<F>)                                                    \
                              BOOST_PP_REPEAT(n, M1, ~)                                            \
                            )                                                                      \
  {                                                                                \
    typedef typename meta::result_of<F(BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& a))>::type result_type; \
                                                                                \
    BOOST_FORCEINLINE result_type                                                                  \
    operator()(F const& f, BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& a)) const                      \
    {                                                                                \
      return f(BOOST_PP_ENUM_PARAMS(n, a));                                                        \
    }                                                                                \
  };                                                                                \
                                                                                \
  BOOST_DISPATCH_IMPLEMENT  ( run_, tag::cpu_                                            \
                            , (Expr)(State)(Data)                                                   \
                            , ((node_<Expr, nt2::tag::arrayfun_, boost::mpl::long_<n+1>, nt2::container::domain>)) \
                              (generic_< integer_<State> >)                                        \
                              (unspecified_<Data>)                                                 \
                            )                                                                      \
  {                                                                                \
    typedef typename meta::                                                                        \
            result_of< typename boost::proto::result_of::value< typename boost::proto::result_of::child_c<Expr, 0>::type >::type \
                       ( BOOST_PP_ENUM(n, M3, ~) )                                                 \
                     >::type result_type;                                                          \
                                                                                \
    BOOST_FORCEINLINE result_type                                                                  \
    operator()(Expr& expr, State const& state, Data const& data) const                             \
    {                                                                                \
      return boost::proto::value(boost::proto::child_c<0>(expr))(BOOST_PP_ENUM(n, M4, ~));         \
    }                                                                                \
  };
  /**/

  BOOST_PP_REPEAT_FROM_TO(1, 4, M2, ~)
  #undef M4
  #undef M3
  #undef M2
  #undef M1
  #undef M0

} }

#endif

ext: hpp


text: #include <boost/spirit/include/classic_debug_node.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/*
 * dawn_multithread_test.cpp
 *
 *  Created on: Jul 15, 2019
 *      Author: Yanzhao Wu
 */

#include <api/components.h>
#include <api/kvstore_itf.h>
#include <common/cpu.h>
#include <common/str_utils.h>
#include <core/dpdk.h>
#include <core/task.h>
#include <gtest/gtest.h>
#include <sys/mman.h>
#include <boost/program_options.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

#include <chrono> /* milliseconds */

#define TEST_MULTIPLE_SHARD_CLIENT
#define TEST_SINGLE_SHARD_MULTIPLE_CLIENT

#define TEST_BARRIER

#ifdef TEST_BARRIER
#include <boost/thread/barrier.hpp>
boost::barrier * g_barrier;
#endif

static constexpr unsigned long ITERATIONS = 10;
static constexpr unsigned long VALUE_SIZE = MB(64);
static constexpr unsigned long KEY_SIZE   = 8;

struct {
  std::string addr;
  std::string pool_prefix;
  std::string device;
  unsigned    debug_level;
  unsigned    base_core;
  unsigned    port_base;
  unsigned	  num_thread;
} Options;

struct record_t {
  std::string key;
  char        value[VALUE_SIZE];
};

using namespace Component;

namespace {

	// mutex for display
	boost::mutex g_display_mutex;
	// mutex for generating data
	boost::mutex gen_mutex;

	// Generate Test Data
	// Generate a single shard
	void generateTestData(IKVStore * _dawn, std::string _pool_name,
			std::vector<std::string> keys, unsigned _id) {
		IKVStore::pool_t pool = _dawn->create_pool(_pool_name, MB(256));
		ASSERT_FALSE(pool == IKVStore::POOL_ERROR);
		size_t data_size = sizeof(record_t) * ITERATIONS;
		record_t * data = (record_t *) aligned_alloc(MiB(2), data_size);
		ASSERT_FALSE(data == nullptr);
		auto handle = _dawn->register_direct_memory(data, data_size);
		// generate data
		for (unsigned long i = 0; i < ITERATIONS; i++) {
			gen_mutex.lock();
			std::string val = Common::random_string(VALUE_SIZE);
			gen_mutex.unlock();
			data[i].key = keys[i];
			memcpy(data[i].value, val.c_str(), VALUE_SIZE);
		}
		int rc;
		auto start = std::chrono::high_resolution_clock::now();
		for (unsigned long i = 0; i < ITERATIONS; i++) {
			rc = _dawn->put_direct(pool, data[i].key, data[i].value, VALUE_SIZE, handle);
			ASSERT_TRUE(rc == S_OK || rc == -6);
		}
		auto end = std::chrono::high_resolution_clock::now();
		auto micro_secs = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

		//output results
		g_display_mutex.lock();
		PMAJOR("Thread ID: %d PutDirect Latency: %lf us", _id, (micro_secs/(double)ITERATIONS));
		g_display_mutex.unlock();

		_dawn->unregister_direct_memory(handle);
		_dawn->close_pool(pool);
		free(data);
		//_dawn->delete_pool(_pool_name); // TODO: After test
	}

	// Get_direct Test
	void getDirectTest(unsigned _debug_level, std::string _serverPort, std::string _device,
			std::string _pool_name, std::vector<std::string> keys, unsigned _id) {
		Component::IBase * comp = Component::load_component("libcomanche-dawn-client.so", dawn_client_factory);
		ASSERT_TRUE(comp);
		IKVStore_factory * fact = (IKVStore_factory *) comp->query_interface(IKVStore_factory::iid());
		IKVStore * _dawn = fact ->create(_debug_level, "dawnTest", _serverPort, _device);
		ASSERT_TRUE(_dawn);
		fact->release_ref();

		// Test get direct
		IKVStore::pool_t pool = _dawn->open_pool(_pool_name);
		ASSERT_FALSE(pool == IKVStore::POOL_ERROR);

		PLOG("Allocating buffer for test data ...");

		size_t data_size = VALUE_SIZE * ITERATIONS;
		char * data = (char*) aligned_alloc(MiB(2), data_size);
		ASSERT_FALSE(data == nullptr);
		auto handle = _dawn->register_direct_memory(data, data_size);

		int rc;

		auto start = std::chrono::high_resolution_clock::now();
		for (unsigned long i = 0; i < ITERATIONS; i++) {
			size_t value_len = VALUE_SIZE;
			rc = _dawn->get_direct(pool, keys[i], &data[i*VALUE_SIZE], value_len, handle);
			ASSERT_TRUE(rc == S_OK || rc == -6);
#ifdef TEST_BARRIER
			g_barrier -> wait();
#endif
		}
		auto end = std::chrono::high_resolution_clock::now();
		auto micro_secs = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

		g_display_mutex.lock();
		PMAJOR("Thread ID: %d GetDirect Latency: %lf us", _id, (micro_secs/(double)ITERATIONS));
		g_display_mutex.unlock();

		_dawn->unregister_direct_memory(handle);
		_dawn->close_pool(pool);
		_dawn->delete_pool(_pool_name);
	}
#ifdef TEST_MULTIPLE_SHARD_CLIENT
	TEST(Dawn_client_multithread_test, MultipleShardsAndClients) {
		std::vector<std::string> keys;
		for(unsigned long i = 0; i < ITERATIONS; i++) {
			std::string key = Common::random_string(KEY_SIZE);
			keys.push_back(key);
		}

		Component::IBase * comp = Component::load_component("libcomanche-dawn-client.so", dawn_client_factory);
                ASSERT_TRUE(comp);
		std::vector<boost::thread> threads;
		IKVStore_factory * fact = (IKVStore_factory *) comp->query_interface(IKVStore_factory::iid());
		// Perform generateTestData
		for(unsigned i = 0; i < Options.num_thread; i++) {
			IKVStore * _dawn = fact ->create(Options.debug_level, "dawnTest",
					Options.addr+":"+std::to_string(Options.port_base+i), Options.device);
			threads.push_back(boost::thread(generateTestData,_dawn, Options.pool_prefix+std::to_string(i), keys, i));
		}
		for(unsigned i = 0; i < Options.num_thread; i++) {
			threads[i].join();
		}
		fact->release_ref();
		// Perform getDirectTest
		threads.clear();
		for(unsigned i = 0; i < Options.num_thread; i++) {
			threads.push_back(boost::thread(getDirectTest, Options.debug_level, Options.addr+":"+std::to_string(Options.port_base+i),
					Options.device, Options.pool_prefix+std::to_string(i), keys, i));
		}
		for(unsigned i = 0; i < Options.num_thread; i++) {
			threads[i].join();
		}
	}
#endif

#ifdef TEST_SINGLE_SHARD_MULTIPLE_CLIENT
	TEST(Dawn_client_multithread_test, SingleShardMultipleClients) {
		std::vector<std::string> keys;
		for(unsigned long i = 0; i < ITERATIONS; i++) {
			std::string key = Common::random_string(KEY_SIZE);
			keys.push_back(key);
		}

		std::vector<boost::thread> threads;
		Component::IBase * comp = Component::load_component("libcomanche-dawn-client.so", dawn_client_factory);
                ASSERT_TRUE(comp);
		// Perform generateTestData
		IKVStore_factory * fact = (IKVStore_factory *) comp->query_interface(IKVStore_factory::iid());
		IKVStore * _dawn = fact ->create(Options.debug_level, "dawnTest",
					Options.addr+":"+std::to_string(Options.port_base), Options.device);
		generateTestData(_dawn, Options.pool_prefix, keys, 0);
		fact->release_ref();
		// Perform getDirectTest
		threads.clear();
		for(unsigned i = 0; i < Options.num_thread; i++) {
			threads.push_back(boost::thread(getDirectTest, Options.debug_level, Options.addr+":"+std::to_string(Options.port_base),
					Options.device, Options.pool_prefix, keys, i));
		}
		for(unsigned i = 0; i < Options.num_thread; i++) {
			threads[i].join();
		}
	}
#endif

}

// Main Function
int main(int argc, char **argv)
{
  try {
    namespace po = boost::program_options;
    po::options_description desc("Options");
    desc.add_options()("help", "Show help")
      ("debug", po::value<unsigned>()->default_value(0), "Debug level 0-3")
      ("server-addr", po::value<std::string>()->default_value("10.0.0.91"), "Server address IP")
	  ("port_base", po::value<unsigned>()->default_value(11900), "Port base")
      ("device", po::value<std::string>()->default_value("mlx5_0"), "Network device (e.g., mlx5_0)")
      ("pool", po::value<std::string>()->default_value("myPool"), "Pool name prefix")
      ("base", po::value<unsigned>()->default_value(0), "Base core")
	  ("num_thread", po::value<unsigned>()->default_value(1), "Number of threads.");

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);

    if (vm.count("help") > 0) {
      std::cout << desc;
      return -1;
    }

    Options.addr        = vm["server-addr"].as<std::string>();
    Options.port_base   = vm["port_base"].as<unsigned>();
    Options.debug_level = vm["debug"].as<unsigned>();
    Options.pool_prefix = vm["pool"].as<std::string>();
    Options.device      = vm["device"].as<std::string>();
    Options.base_core   = vm["base"].as<unsigned>();
    Options.num_thread  = vm["num_thread"].as<unsigned>();

#ifdef TEST_BARRIER
    g_barrier = new boost::barrier(Options.num_thread);
#endif
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
  }
  catch (...) {
    PLOG("bad command line option configuration");
    return -1;
  }

  return 0;
}

max_stars_repo_name: ghsecuritylab/comanche

max_issues_repo_name: ghsecuritylab/comanche

max_forks_repo_name: ghsecuritylab/comanche