text:
#include <albert/utp/utp.hpp>

#include <random>
#include <iostream>

#include <boost/bind/bind.hpp>
#include <boost/asio/placeholders.hpp>

#include <albert/log/log.hpp>
#include <albert/utils/utils.hpp>

namespace {

using namespace albert;
class PacketReader {
 public:
  PacketReader(const uint8_t *data, size_t size) : data_(data), size_(size), offset_(0) { }
  template <typename T>
  T read() {
    if (offset_ + sizeof(T) > size_) {
      throw std::overflow_error("T PacketReader::read(): overflow");
    }
    T t = *reinterpret_cast<const T*>(data_ + offset_);
    t = utils::network_to_host(t);
    offset_ += sizeof(T);
    return t;
  }

  template <typename T>
  void read(T &t) {
    if (offset_ + sizeof(T) > size_) {
      throw std::overflow_error("PacketReader::read(T): overflow");
    }
    t = *reinterpret_cast<const T*>(data_ + offset_);
    t = utils::network_to_host(t);
    offset_ += sizeof(T);
  }

  template <typename T>
  void read(T *output, size_t size) {
    if (offset_ + size > size_) {
      throw std::overflow_error("PacketReader::read(T*, size_t): overflow");
    }
    memcpy(output, data_ + offset_, size * sizeof(T));
    offset_ += size * sizeof(T);
  }

  size_t offset() const { return offset_; }
  void skip(size_t size) {
    if (offset_ + size > size_) {
      throw std::overflow_error("PacketReader::skip(" + std::to_string(size) + ") overflow");
    }
    offset_ += size;
  }

  operator bool() const {
    return offset_ < size_;
  }
 private:
  const uint8_t *data_;
  size_t size_;
  size_t offset_;
};

class PacketWriter {
 public:
  PacketWriter(uint8_t *data, size_t size) : data_(data), size_(size), offset_(0) { }
  template <typename T>
  void write(T t) {
    if (offset_ + sizeof(T) > size_) {
      throw std::overflow_error("T PacketWriter::write(): overflow");
    }
    *reinterpret_cast<T*>(data_ + offset_) = utils::host_to_network(t);
    offset_ += sizeof(T);
  }

  template <typename T>
  void write(const T *input, size_t size) {
    if (offset_ + size > size_) {
      throw std::overflow_error("PacketWrite::write(T*, size_t): overflow");
    }
    memcpy(data_ + offset_, input, size * sizeof(T));
    offset_ += size * sizeof(T);
  }

  size_t data_size() const { return offset_; }
//  void skip(size_t size) {
//    if (offset_ + size > size_) {
//      throw std::overflow_error("PacketWriter::skip(" + std::to_string(size) + ") overflow");
//    }
//    offset_ += size;
//  }

  operator bool() const {
    return offset_ < size_;
  }
 private:
  uint8_t *data_;
  size_t size_;
  size_t offset_;
};

}

namespace albert::utp {

size_t Packet::encode(const uint8_t *data, size_t size) {
  PacketWriter writer(udp_data->data(), udp_data->size());
  writer.write(static_cast<uint8_t>((type << 4u) | version));
  if (!extensions.empty()) {
    writer.write<uint8_t>(std::get<0>(extensions[0]));
  } else {
    writer.write<uint8_t>(0);
  }

  writer.write(connection_id);
  writer.write(timestamp_microseconds);
  writer.write(timestamp_difference_microseconds);
  writer.write(wnd_size);
  writer.write(seq_nr);
  writer.write(ack_nr);

  for (size_t i = 0; i < extensions.size(); i++) {
    if (i == extensions.size() - 1) {
      writer.write<uint8_t>(0);
    } else {
      writer.write<uint8_t>(std::get<0>(extensions[i+1]));
    }
    auto ext = std::get<1>(extensions[i]);
    writer.write(ext.data(), ext.size());
  }

  auto data_offset = writer.data_size();
  if (data && size) {
    writer.write(data, size);
  }
  this->utp_data = gsl::span<const uint8_t>(udp_data->data() + data_offset, size);
  return writer.data_size();
}
std::ostream &Packet::pretty(std::ostream &os) const {
  os << "type: " << int(type) << std::endl;
  os << "connection_id: " << connection_id << std::endl;
  os << "timestamp_us: " << timestamp_microseconds << std::endl;
  os << "timestamp_diff_us: " << timestamp_difference_microseconds << std::endl;
  os << "wnd_size: " << wnd_size << ", "
     << "seq: " << seq_nr << ", "
     << "ack: " << ack_nr << std::endl;

  for (size_t i = 0; i < extensions.size(); i++) {
    os << "extension: " << (int)std::get<0>(extensions[i]) << ", size: " << std::get<1>(extensions[i]).size() << std::endl;
  }

  os << utils::hexdump(utp_data.data(), utp_data.size(), true);
  return os;
}

Packet Packet::decode(Allocator::Buffer buffer, size_t size) {
  Packet pkt;
  pkt.udp_data = buffer;

  PacketReader reader(pkt.udp_data->data(), size);
  auto version_type = reader.read<uint8_t>();
  pkt.version = version_type & 0xf;
  if (pkt.version != UTPVersion) {
    throw InvalidHeader("Unknown uTP version: " + std::to_string(pkt.version));
  }
  pkt.type = (version_type >> 4u) & 0xf;
  auto ext = reader.read<uint8_t>();

  reader.read(pkt.connection_id);
  reader.read(pkt.timestamp_microseconds);
  reader.read(pkt.timestamp_difference_microseconds);
  reader.read(pkt.wnd_size);
  reader.read(pkt.seq_nr);
  reader.read(pkt.ack_nr);

  while (ext != 0 && reader) {
    auto ext_type = ext;
    ext = reader.read<uint8_t>();
    auto ext_size = reader.read<uint8_t>();
    std::string ext_data(ext_size, 0);
    reader.read(ext_data.data(), ext_data.size());
    pkt.extensions.emplace_back(ext_type, ext_data);
  }

  pkt.utp_data = gsl::span<const uint8_t>(pkt.udp_data->data()+reader.offset(), size - reader.offset());
  return std::move(pkt);
}
std::string Packet::pretty() const {
  std::stringstream ss;
  pretty(ss);
  return ss.str();
}

Socket::Socket(boost::asio::io_service &io,
               boost::asio::ip::udp::endpoint bind_ep)
    : io_(io), socket_(io, bind_ep), bind_ep_(bind_ep), timer_(io),
      receive_buffer_allocator_("receive", 100*1024*1024ul, 2),
      send_buffer_allocator_("send", 16*1024ul, 64) {

  timer_.expires_at(timer_.expiry() + boost::asio::chrono::seconds(1));
  timer_.async_wait(boost::bind(&Socket::handle_timer, this, boost::asio::placeholders::error));
}

Socket::~Socket() {
  close();
}

void Socket::async_connect(
    boost::asio::ip::udp::endpoint ep,
    std::function<void(const boost::system::error_code &error)> handler) {

  if (connections_.find(ep) != connections_.end()) {
    throw InvalidStatus("Cannot connect when connection exists " + ep.address().to_string() + ":" + std::to_string(ep.port()));
  }

  continue_receive();

  auto c = std::make_shared<Connection>();
  c->ep = ep;
  c->connect_handler = std::move(handler);
  connections_.emplace(ep, c);
  send_syn(*c);
}

void Socket::async_receive(boost::asio::mutable_buffer buffer,
                           std::function<void(const boost::system::error_code &error, size_t bytes_transfered)> handler) {

  for (auto &c : connections_) {
    c.second->receive_handler = handler;
    c.second->user_buffer = buffer;
    poll_receive(c.second);
  }

}

void Socket::async_send(boost::asio::const_buffer buffer,
                        std::function<void(const boost::system::error_code &error, size_t bytes_transfered)> handler) {

  for (auto &item : connections_) {
    auto &c = item.second;
    if (c->status_ != Status::Connected) {
      throw InvalidStatus("Invalid status, cannot send in status " + std::to_string(int(c->status_)));
    }

    send_data(*c, buffer);
  }

}

void Socket::close(boost::asio::ip::udp::endpoint ep) {
  if (connections_.find(ep) != connections_.end()) {
    auto c = connections_.at(ep);
    c->status_ = Status::Closed;

    io_.post([socket_weak = weak_from_this(), c]() {
      if (c->connect_handler) {
        c->connect_handler(boost::asio::error::eof);
      }
      if (c->receive_handler) {
        c->receive_handler(boost::asio::error::eof, 0);
      }
      if (!socket_weak.expired()) {
        auto socket = socket_weak.lock();
        socket->send_fin(*c);
      }
    });
  }
}

void Socket::handle_receive_from(const boost::system::error_code &error, size_t size) {
  if (error) {
    if (error == boost::asio::error::operation_aborted) {
      return;
    } else {
      LOG(info) << "utp::Socket::handle_receive_from: " << error.message();
      close(receive_ep_);
    }
    return;
  }

//  LOG(info) << "handle_receive buffer size " << size;

  Packet packet;
  try {
    packet = Packet::decode(receive_buffer_, size);
    receive_buffer_ = nullptr;
//    LOG(debug) << "uTP: received packet from " << receive_ep_ << std::endl
//               << packet.pretty() << std::endl;
  } catch (const InvalidHeader &e) {
    LOG(error) << "uTP: invalid header received from " << receive_ep_;
    reset(receive_ep_);
    return;
  } catch (const std::overflow_error &e) {
    LOG(error) << "uTP: unexpected EOF while decoding packet: " << e.what();
    reset(receive_ep_);
    return;
  }

  auto connection_it = connections_.find(receive_ep_);
  if (connection_it == connections_.end()) {
    if (packet.type == UTPTypeSyn) {
      LOG(error) << "uTP: New connection, not implemented";
    } else {
      // ignore
      LOG(debug) << "uTP: Received packet from unknown connection: " << packet.type;
    }
  } else {
    auto &connection = connection_it->second;

    if (connection->status_ == Status::Closed ||
        connection->status_ == Status::Timeout ||
        connection->status_ == Status::Error) {

      LOG(debug) << "uTP: connection status: " << int(connection->status_) << " ignored packet";
      return;
    }

    if (connection->status_ == Status::SynSent) {
      if (packet.connection_id != connection->conn_id_recv) {
        LOG(error) << "Multiple connections with one ep not implemented, ignored";
      } else {
        if (packet.type == UTPTypeState) {
          connection->status_ = Status::Connected;
          // NOTE:
          // This "ack_nr = seq_nr - 1" is not written in BEP, but by capture packets from qbittorrent
          connection->ack_nr = packet.seq_nr - 1;

          if (connection->connect_handler) {
            connection->connect_handler(boost::system::error_code());
            connection->connect_handler = nullptr;
          }
          connection->reset_timeout_from_now();
        } else {
          LOG(error) << "Invalid status, closing connection";
          close(connection->ep);
          return;
        }
      }
    } else if (connection->status_ == Status::Connecting) {
      LOG(error) << "connection not implemented, ignored";
    } else if (connection->status_ == Status::Connected) {
      if (packet.type == UTPTypeData) {
        auto diff = static_cast<int16_t>(packet.seq_nr - connection->ack_nr);
        if (diff == 1) {
          connection->ack_nr = packet.seq_nr;
          // TODO: drop packets when we have too many buffered_received_packets
          connection->buffered_received_packets.emplace_back(packet.udp_data, packet.utp_data);
          poll_receive(connection);
          send_state(*connection);
//          LOG(debug) << "uTP: received packet normal " << packet.seq_nr;
        } else if (diff < 1) {
          // duplicate packet
          send_state(*connection);
          LOG(warning) << "uTP: received packet duplicate " << packet.seq_nr;
        } else /*(diff > 1)*/ {
          // TODO use extension selective ack
          // NAK [ack_nr + 1, packet.seq_nr - 1]
          send_state(*connection);
          LOG(warning) << "uTP: received packet lost " << connection->ack_nr << " to " << packet.seq_nr - 1;
        }
      } else if (packet.type == UTPTypeFin) {
        poll_receive(connection);
        LOG(error) << "FIN received from " << receive_ep_ << " closing connection";
        close(connection->ep);
        return;
      } else if (packet.type == UTPTypeReset) {
        poll_receive(connection);
        LOG(error) << "RST received from " << receive_ep_ << " closing connection";
        reset(connection->ep);
        return;
      } else if (packet.type == UTPTypeState) {
        connection->acked = packet.ack_nr;
      } else {
        LOG(error) << "connected, not implemented type " << int(packet.type);
      }
      if (packet.ack_nr > connection->acked) {
        connection->acked = packet.ack_nr;
      }
    }

    connection->reset_timeout_from_now();
  }

  if (socket_.is_open()) {
//    LOG(info) << "Socket::handle_receive_from handle_receive_from handler";
    continue_receive();
  }
}

void Socket::handle_send_to(boost::asio::ip::udp::endpoint ep, Allocator::Buffer buf, const boost::system::error_code &error) {
  if (error) {
    LOG(error) << "utp::Socket failed to async_send_to " << ep << ", error: " << error.message();
  }
//  if (connections_.find(ep) == connections_.end()) {
//    LOG(debug) << "unknown handle_send_to ep " << ep << " success";
//  }
}

void Socket::handle_send_to_fin(boost::asio::ip::udp::endpoint ep, Allocator::Buffer buf, const boost::system::error_code &error) {
  if (error) {
    LOG(error) << "utp::Socket failed to async_send_to " << ep << ", error: " << error.message();
  }
  if (connections_.find(ep) != connections_.end()) {
    cleanup(ep);
  }
}

void Socket::handle_timer(const boost::system::error_code &error) {
  if (error) {
    LOG(error) << "Socket timer error " << error.message();
    return;
  }

  for (auto &c : connections_) {
    if (c.second->status_ == Status::Connected && std::chrono::high_resolution_clock::now() > c.second->timeout_at) {
      timeout(*c.second);
    }
  }

  timer_.expires_at(timer_.expiry() + boost::asio::chrono::seconds(1));
  timer_.async_wait(boost::bind(&Socket::handle_timer, this, boost::asio::placeholders::error));
}
void Socket::timeout(Connection &c) {
  LOG(debug) << "uTP: connection timeout, closing connection to " << c.ep;
  poll_receive(connections_[c.ep]);

  c.status_ = Status::Timeout;
  if (c.receive_handler) {
    c.receive_handler(boost::asio::error::timed_out, 0);
  }

  if (c.connect_handler) {
    c.connect_handler(boost::asio::error::timed_out);
  }
  if (c.receive_handler) {
    c.receive_handler(boost::asio::error::timed_out, 0);
  }
  cleanup(c.ep);
}

#include <sys/time.h>
namespace {
uint32_t get_usec() {
  struct timeval tv; struct timezone tz;
  if (gettimeofday(&tv, &tz) != 0) {
    throw SystemError(std::string("Failed to send_syn, error: ") + strerror(errno));
  }
  return static_cast<uint32_t>(tv.tv_sec*1000u*1000u + tv.tv_usec);
}
}

void Socket::send_syn(Connection &connection) {
  auto usec = get_usec();
  std::random_device rng;
  std::uniform_int_distribution<uint16_t> cid_rng;
  connection.conn_id_recv = cid_rng(rng);
  connection.conn_id_send = connection.conn_id_recv+1;
  connection.seq_nr = 1;
  connection.ack_nr = 0;

  Packet packet{
      UTPTypeSyn, UTPVersion, connection.conn_id_recv,
      usec, 0,
      (uint32_t)receive_buffer_allocator_.buffer_size(),
      connection.seq_nr, connection.ack_nr};

  connection.seq_nr++;
  auto buf = send_buffer_allocator_.allocate();
  packet.udp_data = buf;
  auto size = packet.encode();

  LOG(debug) << "utp::Socket SYNC send to " << connection.ep << std::endl << packet.pretty();

  socket_.async_send_to(
      boost::asio::buffer(buf->data(), size),
      connection.ep,
      boost::bind(&Socket::handle_send_to, this, connection.ep, buf, boost::asio::placeholders::error()));
}

void Socket::send_data(Connection &c, boost::asio::const_buffer data_to_send) {
  auto usec = get_usec();
  // TODO: time diff
  Packet packet{
      UTPTypeData, UTPVersion, c.conn_id_send,
      usec, 0,
      (uint32_t)receive_buffer_allocator_.buffer_size(),
      c.seq_nr, c.ack_nr};

  auto buf = send_buffer_allocator_.allocate();
  packet.udp_data = buf;
  auto size = packet.encode((const uint8_t*)data_to_send.data(), data_to_send.size());

  c.seq_nr++;

//  LOG(debug) << "utp::Socket send data to " << c.ep << std::endl << packet.pretty();

  socket_.async_send_to(
      boost::asio::buffer(buf->data(), size),
      c.ep,
      boost::bind(&Socket::handle_send_to, this, c.ep, buf, boost::asio::placeholders::error()));
}

void Socket::send_state(Connection &c) {
  auto usec = get_usec();
  // TODO: time diff
  Packet packet{
      UTPTypeState, UTPVersion, c.conn_id_send,
      usec, 0,
      (uint32_t)receive_buffer_allocator_.buffer_size(),
      c.seq_nr, c.ack_nr};

  auto buf = send_buffer_allocator_.allocate();
  packet.udp_data = buf;
  auto size = packet.encode();
  // This is too slow
//  LOG(debug) << "utp::Socket send STATE to " << c.ep << std::endl << packet.pretty();

  socket_.async_send_to(
      boost::asio::buffer(buf->data(), size),
      c.ep,
      boost::bind(&Socket::handle_send_to, this, c.ep, buf, boost::asio::placeholders::error()));
}

void Socket::send_fin(Connection &c) {
  auto usec = get_usec();
  Packet packet{
      UTPTypeFin, UTPVersion, c.conn_id_send,
      usec, 0,
      (uint32_t)receive_buffer_allocator_.buffer_size(),
      c.seq_nr, c.ack_nr};

  auto buf = send_buffer_allocator_.allocate();
  packet.udp_data = buf;
  auto size = packet.encode();

  LOG(debug) << "utp::Socket send FIN to " << c.ep << std::endl << packet.pretty();
  socket_.async_send_to(
      boost::asio::buffer(buf->data(), size),
      c.ep,
      boost::bind(&Socket::handle_send_to_fin, this, c.ep, buf, boost::asio::placeholders::error()));
}

void Socket::continue_receive() {
  auto buffer = receive_buffer_allocator_.allocate();
  receive_buffer_ = buffer;
//  LOG(info) << "continue_receive buffer size " << buffer->size();
  socket_.async_receive_from(
      boost::asio::buffer(buffer->data(), buffer->size()),
      receive_ep_,
      [socket_weak = weak_from_this()](const boost::system::error_code &e, size_t bytes_transferred) {
        if (!socket_weak.expired()) {
          auto socket = socket_weak.lock();
          socket->handle_receive_from(e, bytes_transferred);
        }
      });
}

void Socket::close() {
  std::list<boost::asio::ip::udp::endpoint> keys;
  for (auto &item : connections_) {
    keys.push_back(item.first);
  }
  for (const auto& key : keys) {
    close(key);
  }
}

void Socket::cleanup(boost::asio::ip::udp::endpoint ep) {
  connections_.erase(ep);
  if (connections_.empty()) {
    socket_.cancel();
    socket_.close();
  }
}

void Socket::reset(boost::asio::ip::udp::endpoint ep) {
  if (connections_.find(ep) != connections_.end()) {
    auto &c = connections_.at(ep);
    c->status_ = Status::Closed;

    if (c->connect_handler) {
      c->connect_handler(boost::asio::error::connection_reset);
    }
    if (c->receive_handler) {
      c->receive_handler(boost::asio::error::connection_reset, 0);
    }
    cleanup(ep);
  }
}

bool Socket::poll_receive(std::shared_ptr<Connection> c) {
  if (c->receive_handler && !c->buffered_received_packets.empty()) {
    bool user_buffer_full = false;
    // fill the user buffer as much as possible
    while (!c->buffered_received_packets.empty()) {
      auto &data = c->buffered_received_packets.front();
      size_t user_buffer_remaining = c->user_buffer.size() - c->user_buffer_data_size;
      if (user_buffer_remaining <= data.size()) {
        // user buffer full after copying
        std::copy(
            data.data(),
            data.data() + user_buffer_remaining,
            (uint8_t *) c->user_buffer.data() + c->user_buffer_data_size);
//        std::copy(
//            data.begin(),
//            std::next(data.begin(), user_buffer_remaining),
//            (uint8_t *) c->user_buffer.data() + user_buffer_remaining);
        c->user_buffer_data_size = c->user_buffer.size();
        data.skip_front(user_buffer_remaining);
        break;
      } else {
        // pop one packet
        std::copy(data.data(), data.data() + data.size(), (uint8_t *) c->user_buffer.data()+c->user_buffer_data_size);
        c->user_buffer_data_size += data.size();
        c->buffered_received_packets.pop_front();
      }
    }
    if (c->user_buffer_data_size > 0 || c->user_buffer.size() == 0) {
      io_.post([c, socket_weak = weak_from_this()]() {
        if (!socket_weak.expired()) {
          auto socket = socket_weak.lock();
          if (c->user_buffer_data_size > 0 || c->user_buffer.size() == 0) {
            c->invoke_handler();
          }

          if (c->receive_handler && !c->buffered_received_packets.empty()) {
            socket->poll_receive(c);
          }
        }
      });
    }
  }
  return true;
}

}


text:
#define BOOST_TEST_MODULE initial_test

#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_CASE( FixedPoint )
{
    BOOST_CHECK_EQUAL(0,0);
}

ext: cpp

max_stars_repo_name: mile-core/mile-crypto

max_issues_repo_name: mile-core/mile-crypto

max_forks_repo_name: mile-core/mile-crypto


text:
#ifndef OSRM_GEOJSON_DEBUG_POLICY_TOOLKIT_HPP
#define OSRM_GEOJSON_DEBUG_POLICY_TOOLKIT_HPP

#include "util/json_container.hpp"

#include <algorithm>

#include <boost/optional.hpp>

namespace osrm
{
namespace util
{

enum GeojsonStyleSize
{
    tiny,
    small,
    medium,
    large,
    extra_large,
    num_styles
};

enum GeojsonStyleColors
{
    red,
    purple,
    blue,
    green,
    yellow,
    cyan,
    brown,
    pink,
    num_colors
};

const constexpr char *geojson_debug_predifined_colors[GeojsonStyleColors::num_colors] = {
    "#FF4848", "#800080", "#5757FF", "#1FCB4A", "#FFE920", "#29AFD6", "#B05F3C", "#FE67EB"};

const constexpr double geojson_predefined_sizes[GeojsonStyleSize::num_styles] = {
    2.0, 3.5, 5.0, 6.5, 8};

inline util::json::Object makeStyle(const GeojsonStyleSize size_type,
                                    const GeojsonStyleColors predefined_color)
{
    util::json::Object style;
    // style everything, since we don't know the feature type
    style.values["stroke"] = geojson_debug_predifined_colors[predefined_color];
    style.values["circle-color"] = geojson_debug_predifined_colors[predefined_color];
    style.values["line-width"] = geojson_predefined_sizes[size_type];
    style.values["circle-radius"] = geojson_predefined_sizes[size_type];
    return style;
}

struct CoordinateToJsonArray
{
    util::json::Array operator()(const util::Coordinate coordinate)
    {
        util::json::Array json_coordinate;
        json_coordinate.values.push_back(static_cast<double>(toFloating(coordinate.lon)));
        json_coordinate.values.push_back(static_cast<double>(toFloating(coordinate.lat)));
        return json_coordinate;
    }
};

struct NodeIdToCoordinate
{
    NodeIdToCoordinate(const std::vector<extractor::QueryNode> &node_coordinates)
        : node_coordinates(node_coordinates)
    {
    }

    const std::vector<extractor::QueryNode> &node_coordinates;

    util::json::Array operator()(const NodeID nid)
    {
        auto coordinate = node_coordinates[nid];
        CoordinateToJsonArray converter;
        return converter(coordinate);
    }
};

inline util::json::Object makeFeature(std::string type,
                                      util::json::Array coordinates,
                                      const boost::optional<util::json::Object> &properties = {})
{
    util::json::Object result;
    result.values["type"] = "Feature";
    result.values["properties"] = properties ? *properties : util::json::Object();
    util::json::Object geometry;
    geometry.values["type"] = std::move(type);
    geometry.values["properties"] = util::json::Object();
    geometry.values["coordinates"] = std::move(coordinates);
    result.values["geometry"] = geometry;

    return result;
}

inline util::json::Array makeJsonArray(const std::vector<util::Coordinate> &input_coordinates)
{
    util::json::Array coordinates;
    std::transform(input_coordinates.begin(),
                   input_coordinates.end(),
                   std::back_inserter(coordinates.values),
                   CoordinateToJsonArray());
    return coordinates;
}
} // namespace util
} // namespace osrm

#endif /* OSRM_GEOJSON_DEBUG_POLICY_TOOLKIT_HPP */

ext: hpp

max_stars_repo_name: edudude/osrm-backend

max_issues_repo_name: edudude/osrm-backend

max_forks_repo_name: edudude/osrm-backend


text:
//------------------------------------------------------------------------------
// @file   : tms_db_writer.cpp
// @brief  : write data into rostms database
// @author : Yoonseok Pyo
// @version: Ver0.2.3 (since 2014.05.07)
// @date   : 2015.08.26
//------------------------------------------------------------------------------
//include for ROS
#include <ros/ros.h>
#include <unistd.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <tms_msg_db/TmsdbStamped.h>
#include <tms_msg_db/Tmsdb.h>

//include for Mysql
#include <mysql/mysql.h>

//include for std
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>

#define STRUCTURE_ID      4000
#define MAX_STRUCTURE_NUM 1
#define SPACE_ID          5000
#define MAX_SPACE_NUM     4
#define FURNITURE_ID      6000
#define MAX_FURNITURE_NUM 23

//------------------------------------------------------------------------------
using std::string;

//------------------------------------------------------------------------------
class DbWriter
{
//------------------------------------------------------------------------------
private:
  // ROS NodeHandle
  ros::NodeHandle nh;
  ros::NodeHandle nh_priv;
  // ROS Topic Subscriber
  ros::Subscriber     data_sub;
  ros::ServiceClient  get_data_client;
  // ROS Parameters:
  bool is_debug;
  // MySQL structures
  // https://dev.mysql.com/doc/refman/5.6/en/c-api-data-structures.html
  MYSQL     *connector;
  MYSQL_RES *result;
  MYSQL_ROW row;
  // MySQL information
  string dbhost;
  string dbuser;
  string dbpass;
  string dbname;
  string dbdata[100];

//------------------------------------------------------------------------------
public:
  DbWriter() :
    nh_priv("~"),
    dbhost("192.168.4.170"),
    dbuser("root"),
    dbpass("tmsdb"),
    dbname("rostmsdb"),
    is_debug(false)
  {
    //Init parameter
    nh_priv.param("is_debug", is_debug, is_debug);
    //Init Vicon Stream
    ROS_ASSERT(initDbWriter());
    // Subscriber for tms_db_data topic
    data_sub = nh.subscribe("tms_db_data", 1, &DbWriter::dbWriteCallback, this);
    writeInitData();
  }

  //----------------------------------------------------------------------------
  ~DbWriter()
  {
    ROS_ASSERT(shutdownDbWriter());
  }

//------------------------------------------------------------------------------
private:
  bool initDbWriter()
  {
    ROS_INFO("tms_db_writer : Init OK!\n");

    //Connection to a MySQL database
    connector = mysql_init(NULL);
    if (!mysql_real_connect(connector,
                            dbhost.c_str(),
                            dbuser.c_str(),
                            dbpass.c_str(),
                            dbname.c_str(),
                            3306,
                            NULL, CLIENT_MULTI_STATEMENTS)) {
      fprintf(stderr, "%s\n", mysql_error(connector));
      return false;
    }

    ROS_INFO("MySQL(rostmsdb) opened.\n");
    return true;
  }

  //----------------------------------------------------------------------------
  bool shutdownDbWriter()
  {
    //Close connection
    mysql_close(connector);
    ROS_INFO("MySQL(rostmsdb) closed.\n");
    return true;
  }

  //----------------------------------------------------------------------------
  bool writeInitData()
  {
    tms_msg_db::Tmsdb temp_dbdata;

    writeData(2008);  // ardrone
    writeData(2009);  // refrigerator

    for(int32_t i=1; i <= MAX_STRUCTURE_NUM; i++)
    {
      writeData(STRUCTURE_ID + i);
    }

    for(int32_t i=1; i <= MAX_SPACE_NUM; i++)
    {
      writeData(SPACE_ID + i);
    }

    for(int32_t i=1; i <= MAX_FURNITURE_NUM; i++)
    {
      writeData(FURNITURE_ID + i);
    }

    return true;
  }

  //----------------------------------------------------------------------------
  bool writeData(int32_t id)
  {
    tms_msg_db::Tmsdb temp_dbdata;
    ros::Time now;
    char select_query[1024];
    char insert_query[1024];
    char delete_query[1024];

    sprintf(select_query, "SELECT * FROM rostmsdb.id WHERE id=%d;", id);
    if(is_debug) ROS_INFO("%s\n", select_query);
    mysql_query(connector, select_query);
    result = mysql_use_result(connector);
    while ((row = mysql_fetch_row(result)) != NULL)
    {
      for(int32_t j=0;j<25;j++) if(is_debug) ROS_INFO("%s, ",row[j]);
      now = ros::Time::now() + ros::Duration(9*60*60); // GMT +9
      temp_dbdata.time        = boost::posix_time::to_iso_extended_string(now.toBoost());
      temp_dbdata.type        = row[1];
      temp_dbdata.id          = atoi(row[2]);
      temp_dbdata.name        = row[3];
      temp_dbdata.x           = atof(row[4]);
      temp_dbdata.y           = atof(row[5]);
      temp_dbdata.z           = atof(row[6]);
      temp_dbdata.rr          = atof(row[7]);
      temp_dbdata.rp          = atof(row[8]);
      temp_dbdata.ry          = atof(row[9]);
      temp_dbdata.offset_x    = atof(row[10]);
      temp_dbdata.offset_y    = atof(row[11]);
      temp_dbdata.offset_z    = atof(row[12]);
      temp_dbdata.joint       = row[13];
      temp_dbdata.weight      = atof(row[14]);
      temp_dbdata.rfid        = row[15];
      temp_dbdata.etcdata     = row[16];
      temp_dbdata.place       = atoi(row[17]);
      temp_dbdata.extfile     = row[18];
      temp_dbdata.sensor      = atoi(row[19]);
      temp_dbdata.probability = atof(row[20]);
      temp_dbdata.state       = atoi(row[21]);
      temp_dbdata.task        = row[22];
      temp_dbdata.note        = row[23];
      temp_dbdata.tag         = row[24];
    }
    if(mysql_num_rows(result) != 0)
      mysql_free_result(result);

    //------------------------------------------------------------------------
    // Delete old data in rostmsdb.data_xxx
    sprintf(delete_query,
            "DELETE FROM rostmsdb.data_%s WHERE time <'%s' AND id=%d AND sensor=%d;",
            temp_dbdata.type.c_str(),
            temp_dbdata.time.c_str(),
            temp_dbdata.id,
            temp_dbdata.sensor);

    if(is_debug) ROS_INFO("%s\n", delete_query);

    if (mysql_query(connector, delete_query))
    {
      ROS_ERROR("%s", mysql_error(connector));
      ROS_ERROR("DB write error!");
    }

    //------------------------------------------------------------------------
    // Insert new data to rostmsdb.data_xxx
    sprintf(insert_query,
      "INSERT INTO rostmsdb.data_%s VALUES ('%s','%s',%d,'%s',%f,%f,%f,%f,%f,%f,%f,%f,%f,'%s',%f,'%s','%s',%d,'%s',%d,%f,%d,'%s','%s','%s');",
      temp_dbdata.type.c_str(),
      temp_dbdata.time.c_str(),
      temp_dbdata.type.c_str(),
      temp_dbdata.id,
      temp_dbdata.name.c_str(),
      temp_dbdata.x,
      temp_dbdata.y,
      temp_dbdata.z,
      temp_dbdata.rr,
      temp_dbdata.rp,
      temp_dbdata.ry,
      temp_dbdata.offset_x,
      temp_dbdata.offset_y,
      temp_dbdata.offset_z,
      temp_dbdata.joint.c_str(),
      temp_dbdata.weight,
      temp_dbdata.rfid.c_str(),
      temp_dbdata.etcdata.c_str(),
      temp_dbdata.place,
      temp_dbdata.extfile.c_str(),
      temp_dbdata.sensor,
      temp_dbdata.probability,
      temp_dbdata.state,
      temp_dbdata.task.c_str(),
      temp_dbdata.note.c_str(),
      temp_dbdata.tag.c_str());

    if(is_debug) ROS_INFO("%s\n",insert_query);

    if (mysql_query(connector, insert_query))
    {
      fprintf(stderr, "%s\n", mysql_error(connector));
      ROS_ERROR("Write error!\n");
    }

    return true;
  }

  //----------------------------------------------------------------------------
  // dbWriteCallback function
  void dbWriteCallback(const ros::MessageEvent<tms_msg_db::TmsdbStamped const>& event)
  {
    const std::string& publisher_name   = event.getPublisherName();
    const tms_msg_db::TmsdbStampedConstPtr& msg = event.getMessage();

    if(is_debug) ROS_INFO("publisher name = %s", publisher_name.c_str());

    int32_t msg_size;
    char select_query[1024];
    char insert_query[1024];
    char delete_query[1024];
    MYSQL_ROW   temp_row;
    std::string temp_type;
    std::string temp_name;
    std::string temp_probability;

    if(is_debug) ROS_INFO("id = %d", msg->tmsdb[0].id);

    msg_size = msg->tmsdb.size();
    if(is_debug) ROS_INFO("msg_size = %d", msg_size);

    for(int32_t i=0; i<msg_size; i++)
    {
      // Search the type, name, etc infomation in ID table
      sprintf(select_query, "SELECT type,name,probability FROM rostmsdb.id WHERE id=%d", msg->tmsdb[i].id);
      if(is_debug) ROS_INFO("%s\n", select_query);
      mysql_query(connector, select_query);
      result   = mysql_use_result(connector);
      row      = mysql_fetch_row(result);
      temp_row = row;
      if(is_debug) ROS_INFO("%s,%s\n",temp_row[0],temp_row[1]);
      temp_type         = temp_row[0];
      temp_name         = temp_row[1];
      temp_probability  = 0.0;
      mysql_free_result(result);

      if (msg->tmsdb[i].sensor != 0)
      {
        // Search the sensor's probability infomation in ID table
        sprintf(select_query, "SELECT probability FROM rostmsdb.id WHERE id=%d", msg->tmsdb[i].sensor);
        if(is_debug) ROS_INFO("%s\n", select_query);
        mysql_query(connector, select_query);
        result  = mysql_use_result(connector);
        row     = mysql_fetch_row(result);
        temp_row = row;
        if(is_debug) ROS_INFO("%s\n",temp_row[0]);
        temp_probability  = temp_row[0]==NULL?"0.0":temp_row[0];
        mysql_free_result(result);
      }

      //------------------------------------------------------------------------
      // Insert new data to rostmsdb.history_data
      sprintf(insert_query,
        "INSERT INTO rostmsdb.history_data VALUES ('%s','%s',%d,'%s',%f,%f,%f,%f,%f,%f,%f,%f,%f,'%s',%f,'%s','%s',%d,'%s',%d,%f,%d,'%s','%s','%s');",
        msg->tmsdb[i].time.c_str(),
        msg->tmsdb[i].type.empty()?temp_type.c_str():msg->tmsdb[i].type.c_str(),
        msg->tmsdb[i].id,
        msg->tmsdb[i].name.empty()?temp_name.c_str():msg->tmsdb[i].name.c_str(),
        msg->tmsdb[i].x,
        msg->tmsdb[i].y,
        msg->tmsdb[i].z,
        msg->tmsdb[i].rr,
        msg->tmsdb[i].rp,
        msg->tmsdb[i].ry,
        msg->tmsdb[i].offset_x,
        msg->tmsdb[i].offset_y,
        msg->tmsdb[i].offset_z,
        msg->tmsdb[i].joint.empty()?"":msg->tmsdb[i].joint.c_str(),
        msg->tmsdb[i].weight,
        msg->tmsdb[i].rfid.empty()?"":msg->tmsdb[i].rfid.c_str(),
        msg->tmsdb[i].etcdata.empty()?"":msg->tmsdb[i].etcdata.c_str(),
        msg->tmsdb[i].place,
        msg->tmsdb[i].extfile.empty()?"":msg->tmsdb[i].extfile.c_str(),
        msg->tmsdb[i].sensor,
        atof(temp_probability.c_str()),
        msg->tmsdb[i].state,
        msg->tmsdb[i].task.empty()?"":msg->tmsdb[i].task.c_str(),
        msg->tmsdb[i].note.empty()?"":msg->tmsdb[i].note.c_str(),
        msg->tmsdb[i].tag.empty()?"":msg->tmsdb[i].tag.c_str());

      if(is_debug) ROS_INFO("%s\n",insert_query);

      if (mysql_query(connector, insert_query))
      {
        ROS_INFO("Publisher name = %s", publisher_name.c_str());
        ROS_INFO("DB write error!");
        ROS_INFO("%s", mysql_error(connector));
      }

      //------------------------------------------------------------------------
      // Delete old data in rostmsdb.data_xxx
      sprintf(delete_query,
              "DELETE FROM rostmsdb.data_%s WHERE time <'%s' AND id=%d AND sensor=%d;",
              temp_type.c_str(),
              msg->tmsdb[i].time.c_str(),
              msg->tmsdb[i].id,
              msg->tmsdb[i].sensor);

      if(is_debug) ROS_INFO("%s\n", delete_query);

      if (mysql_query(connector, delete_query))
      {
        ROS_INFO("Publisher name = %s", publisher_name.c_str());
        ROS_INFO("DB write error!");
        ROS_INFO("%s", mysql_error(connector));
      }

      //------------------------------------------------------------------------
      // Insert new data to rostmsdb.data_xxx
      sprintf(insert_query,
        "INSERT INTO rostmsdb.data_%s VALUES ('%s','%s',%d,'%s',%f,%f,%f,%f,%f,%f,%f,%f,%f,'%s',%f,'%s','%s',%d,'%s',%d,%f,%d,'%s','%s','%s');",
        temp_type.c_str(),
        msg->tmsdb[i].time.c_str(),
        msg->tmsdb[i].type.empty()?temp_type.c_str():msg->tmsdb[i].type.c_str(),
        msg->tmsdb[i].id,
        msg->tmsdb[i].name.empty()?temp_name.c_str():msg->tmsdb[i].name.c_str(),
        msg->tmsdb[i].x,
        msg->tmsdb[i].y,
        msg->tmsdb[i].z,
        msg->tmsdb[i].rr,
        msg->tmsdb[i].rp,
        msg->tmsdb[i].ry,
        msg->tmsdb[i].offset_x,
        msg->tmsdb[i].offset_y,
        msg->tmsdb[i].offset_z,
        msg->tmsdb[i].joint.empty()?"":msg->tmsdb[i].joint.c_str(),
        msg->tmsdb[i].weight,
        msg->tmsdb[i].rfid.empty()?"":msg->tmsdb[i].rfid.c_str(),
        msg->tmsdb[i].etcdata.empty()?"":msg->tmsdb[i].etcdata.c_str(),
        msg->tmsdb[i].place,
        msg->tmsdb[i].extfile.empty()?"":msg->tmsdb[i].extfile.c_str(),
        msg->tmsdb[i].sensor,
        atof(temp_probability.c_str()),
        msg->tmsdb[i].state,
        msg->tmsdb[i].task.empty()?"":msg->tmsdb[i].task.c_str(),
        msg->tmsdb[i].note.empty()?"":msg->tmsdb[i].note.c_str(),
        msg->tmsdb[i].tag.empty()?"":msg->tmsdb[i].tag.c_str());

      if(is_debug) ROS_INFO("%s\n",insert_query);

      if (mysql_query(connector, insert_query))
      {
        ROS_INFO("Publisher name = %s", publisher_name.c_str());
        ROS_INFO("DB write error!");
        ROS_INFO("%s", mysql_error(connector));
      }
    }
  }
};

//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
  //Init ROS node
  ros::init(argc, argv, "tms_db_writer");
  DbWriter dw;
  ros::spin();
  return 0;
}

//------------------------------------------------------------------------------
//EOF


#include "query.hpp"
#include <boost/algorithm/string.hpp>
#include <functional>
#include <iterator>
#include <algorithm>
#include <utility>

using namespace boost::asio;
using ip::tcp;

void query::on_connect(const boost::system::error_code &ec,
        tcp::resolver::iterator it){
        if (!ec) {
            auto buf = buffer(ip.to_string() + "\r\n");
            async_write(*socket, buf,
                std::bind(&query::on_write,
                    this, std::placeholders::_1, std::placeholders::_2,
                    buffer_size(buf)));
        }else {
            //...
        }
}

void query::parse_info(std::istream &is) {
    is.unsetf(std::ios::skipws);
    std::copy(std::istream_iterator<char>(is), std::istream_iterator<char>() ,
        std::back_inserter(info));
}

void query::on_write(const boost::system::error_code &ec,
        std::size_t bytes_sent, const std::size_t message_size) {
    if (!ec && bytes_sent == message_size) {
        async_read(*socket, *response_stream, transfer_all(),
            std::bind(&query::on_read, this, std::placeholders::_1,
                std::placeholders::_2));
    }
}

void query::on_read(const boost::system::error_code &ec,
        std::size_t bytes_received){
    if (ec == error::eof) {
        std::istream is(response_stream.get());
        parse_info(is);
        static const std::string REFER_KEY("refer");
        auto refer_pos = info.find(REFER_KEY);
        if (refer_pos != std::string::npos) {
            // follow referrals
            auto refer_value_start = std::find(std::begin(info) + refer_pos,
                std::end(info), ':');
            auto refer_value_end = std::find(refer_value_start,
                std::end(info), '\n');

            if (refer_value_start != std::end(info) &&
                refer_value_end != std::end(info) ) {
                std::string refer_value(refer_value_start + 1, refer_value_end);
                boost::trim(refer_value);
                std::cout << "[Referred to " << refer_value << " for "
                    << ip << " ]\n";
                socket.reset(new ip::tcp::socket(socket->get_io_service()));
                tcp::resolver resolver(socket->get_io_service());
                auto endpoint_itr = resolver.resolve({refer_value, "43"});
                info.clear();
                async_connect(*socket, endpoint_itr,
                    std::bind(&query::on_connect, this,
                        std::placeholders::_1, std::placeholders::_2 ));
            }else {
                std::cerr << "[could not parse refer value]" << std::endl;
            }

        }
    }
}

query::query(const std::string &ip_str, io_service &service) :
    ip(ip::address::from_string(ip_str)), socket( new tcp::socket(service)),
    response_stream(new streambuf()){}

void query::start(io_service &service) {
    if (!socket->is_open()) {
        tcp::resolver resolver(service);
        auto endpoint_itr = resolver.resolve({"whois.iana.org", "43"});
        async_connect(*socket, endpoint_itr,
                std::bind(&query::on_connect, this,
                    std::placeholders::_1, std::placeholders::_2));
    }
}


text:
// libtcp_client.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "ClientManager.hpp"
#include <boost/asio/io_service.hpp>
#include <vector>

std::vector<Client::pointer> s;
int _tmain(int argc, _TCHAR* argv[])
{
	static const char * szFormat = "libtcp_win::client(%d) <-> ul  [0 kb/s]   /   dn  [0 kb/s]";
	char buf[1024];

	ClientManager mgr;
	sprintf_s(buf, szFormat,mgr.GetClientCount());
	SetConsoleTitleA(buf);
	mgr.Run();
	getchar();
	return 0;
}


text:
//********************************************************************************//
// MIT License                                                                    //
//                                                                                //
// Copyright (c) 2019 TeamViewer Germany GmbH                                     //
//                                                                                //
// Permission is hereby granted, free of charge, to any person obtaining a copy   //
// of this software and associated documentation files (the "Software"), to deal  //
// in the Software without restriction, including without limitation the rights   //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      //
// copies of the Software, and to permit persons to whom the Software is          //
// furnished to do so, subject to the following conditions:                       //
//                                                                                //
// The above copyright notice and this permission notice shall be included in all //
// copies or substantial portions of the Software.                                //
//                                                                                //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    //
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  //
// SOFTWARE.                                                                      //
//********************************************************************************//
#include "CommunicationChannel.h"
#include "logging.hpp"

#include <TVRemoteScreenSDKCommunication/ConnectivityService/IConnectivityServiceServer.h>
#include <TVRemoteScreenSDKCommunication/ConnectivityService/IConnectivityServiceClient.h>
#include <TVRemoteScreenSDKCommunication/ConnectivityService/ServiceFactory.h>

#include <TVRemoteScreenSDKCommunication/ImageService/IImageServiceClient.h>
#include <TVRemoteScreenSDKCommunication/ImageService/ServiceFactory.h>

#include <TVRemoteScreenSDKCommunication/ImageNotificationService/IImageNotificationServiceClient.h>
#include <TVRemoteScreenSDKCommunication/ImageNotificationService/ServiceFactory.h>

#include <TVRemoteScreenSDKCommunication/InputService/IInputServiceServer.h>
#include <TVRemoteScreenSDKCommunication/InputService/ServiceFactory.h>

#include <TVRemoteScreenSDKCommunication/RegistrationService/IRegistrationServiceClient.h>
#include <TVRemoteScreenSDKCommunication/RegistrationService/ServiceFactory.h>

#include <TVRemoteScreenSDKCommunication/SessionControlService/ISessionControlServiceClient.h>
#include <TVRemoteScreenSDKCommunication/SessionControlService/ServiceFactory.h>

#include <TVRemoteScreenSDKCommunication/SessionStatusService/ISessionStatusServiceServer.h>
#include <TVRemoteScreenSDKCommunication/SessionStatusService/ServiceFactory.h>

#include <boost/filesystem.hpp>

namespace
{
constexpr const char* ClientVersion = "1.0";
constexpr const char* SocketPrefix = "unix://";

const boost::filesystem::path ConnectivityLocation = "/tmp/TVQtRC/connectivity/";
const boost::filesystem::path InputLocation = "/tmp/TVQtRC/input/";
const boost::filesystem::path SessionStatusLocation = "/tmp/TVQtRC/sessionStatus/";

TVRemoteScreenSDKCommunication::ImageService::ColorFormat getSdkCommunicationColorFormat(const vncplugin::ColorFormat colorFormat)
{
	printLog("Entry");
	switch (colorFormat)
	{
	case vncplugin::ColorFormat::BGRA32: return TVRemoteScreenSDKCommunication::ImageService::ColorFormat::BGRA32;
	case vncplugin::ColorFormat::R5G6B5: return TVRemoteScreenSDKCommunication::ImageService::ColorFormat::R5G6B5;
	case vncplugin::ColorFormat::RGBA32: return TVRemoteScreenSDKCommunication::ImageService::ColorFormat::RGBA32;
	case vncplugin::ColorFormat::Unsupported: return TVRemoteScreenSDKCommunication::ImageService::ColorFormat::Unknown;
	}

	return TVRemoteScreenSDKCommunication::ImageService::ColorFormat::Unknown;
}

TVRemoteScreenSDKCommunication::SessionControlService::ControlMode getSdkCommunicationControlMode(vncplugin::ControlMode mode)
{
	printLog("Entry");
	switch (mode)
	{
		case vncplugin::ControlMode::Disabled:    return TVRemoteScreenSDKCommunication::SessionControlService::ControlMode::Disable;
		case vncplugin::ControlMode::ViewOnly:    return TVRemoteScreenSDKCommunication::SessionControlService::ControlMode::ScreenSharing;
		case vncplugin::ControlMode::FullControl: return TVRemoteScreenSDKCommunication::SessionControlService::ControlMode::FullControl;
	}

	return TVRemoteScreenSDKCommunication::SessionControlService::ControlMode::Unknown;
}

template<typename FactoryFuncT, class ClientT>
bool setupClient(const std::string& serviceLocation, FactoryFuncT factory, typename std::unique_ptr<ClientT>& client, std::mutex& mutex)
{
	printLog("Entry");
	if (serviceLocation.empty())
	{
		return false;
	}

	std::lock_guard<std::mutex> clientLock(mutex);
	client = factory();
	client->StartClient(serviceLocation);

	return true;
}

template<class ClientT>
void teardownClient(typename std::unique_ptr<ClientT>& client, std::mutex& mutex)
{
	printLog("Entry");
	std::lock_guard<std::mutex> clientLock(mutex);
	if (client)
	{
		client->StopClient();
		client.reset();
	}
}

template<class ServerT>
void teardownServer(typename std::unique_ptr<ServerT>& client, std::mutex& mutex)
{
	printLog("Entry");
	std::lock_guard<std::mutex> clientLock(mutex);
	if (client)
	{
		client->StopServer();
		client.reset();
	}
}

bool setupDir()
{
	printLog("Entry");
	if (!boost::filesystem::is_directory(ConnectivityLocation))
	{
		printLog("1");
		if (!boost::filesystem::create_directories(ConnectivityLocation))
		{
			printLog("2");
			return false;
		}
	}
	printLog("3");
	if (!boost::filesystem::is_directory(InputLocation))
	{
		printLog("4");
		if (!boost::filesystem::create_directories(InputLocation))
		{
			printLog("5");
			return false;
		}
	}
	printLog("6");

	if (!boost::filesystem::is_directory(SessionStatusLocation))
	{
		printLog("7");
		if (!boost::filesystem::create_directories(SessionStatusLocation))
		{
			printLog("8");
			return false;
		}
	}
	printLog("9");
	return true;
}

} // namespace

namespace vncplugin
{

std::shared_ptr<CommunicationChannel> CommunicationChannel::Create(
	const std::string& registrationSocket)
{
	printLog("Entry");
	const std::shared_ptr<CommunicationChannel> communicationChannel (new CommunicationChannel(registrationSocket));

	communicationChannel->m_weakThis = communicationChannel;
	return communicationChannel;
}

CommunicationChannel::CommunicationChannel(
	const std::string& registrationSocket)
	: m_registrationSocket(registrationSocket)
	, m_disconnectCondition(std::make_unique<Condition>())
	, m_shutdownCondition(std::make_unique<Condition>())
{
	printLog("Entry");
}

void CommunicationChannel::setStartServerConnection(const StartServerConnectionCB& cb)
{
	m_sessionStarted = cb;
}

void CommunicationChannel::setMouseMovementConnection(const MouseMovementCB& cb)
{
	m_mouseMoved = cb;
}

void CommunicationChannel::setStartRemoteConnection(const StartRemoteConnectionCB& cb)
{
	m_RCsessionStarted = cb;
}

CommunicationChannel::~CommunicationChannel()
{
	printLog("Entry");
	shutdownInternal();
}

void CommunicationChannel::startup()
{
	printLog("Entry");
	std::lock_guard<std::mutex> shutdownLock(m_shutdownCondition->mutex);
	if (m_isRunning)
	{
		return;
	}

	if (setupDir() == false)
	{
		printLog("[Communication Channel] Directory setup failed.");
		return;
	}

	m_isRunning = true;

	m_thread = std::thread([this]()
	{
		constexpr uint8_t ShutdownRetryTime = 1; //seconds

		while (m_isRunning)
		{
			if (establishConnection())
			{
				if (setupClientAndServer())
				{
					printLog("[Communication Channel] Setup successful.");
					m_sessionStarted();
					startPing();
				}
			}

			sendDisconnect();
			tearDown();

			std::unique_lock<std::mutex> shutdownLockLoop(m_shutdownCondition->mutex);
			m_shutdownCondition->condition.wait_for(
				 shutdownLockLoop, std::chrono::seconds(ShutdownRetryTime));
		}
	});
}

void CommunicationChannel::shutdown()
{
	printLog("Entry");
	shutdownInternal();
}

void CommunicationChannel::shutdownInternal()
{
	printLog("Entry");
	sendDisconnect();

	m_isRunning = false;

	{
		std::lock_guard<std::mutex> lock(m_shutdownCondition->mutex);
		m_shutdownCondition->condition.notify_all();
	}

	if (m_thread.joinable())
	{
		m_thread.join();
	}

	tearDown();
}

void CommunicationChannel::sendStop()
{
	printLog("Entry");
	std::lock_guard<std::mutex> lock(m_sessionControlServiceClientMutex);
	if (m_sessionControlServiceClient)
	{
		const TVRemoteScreenSDKCommunication::CallStatus status =
			m_sessionControlServiceClient->CloseRc(m_communicationId);

		if (status.IsOk() == false)
		{
			printError("[Communication Channel] Error in closing the remote control. Reason: " + status.errorMessage);
		}
	}
	else
	{
		printError("[CommunicationChannel] Session control service client not available.");
	}
}

void CommunicationChannel::sendControlMode(ControlMode mode)
{
	printLog("Entry");
	std::lock_guard<std::mutex> lock(m_sessionControlServiceClientMutex);
	if (m_sessionControlServiceClient)
	{
		const TVRemoteScreenSDKCommunication::SessionControlService::ControlMode requestedControlMode = getSdkCommunicationControlMode(mode);

		const TVRemoteScreenSDKCommunication::CallStatus status =
			m_sessionControlServiceClient->ChangeControlMode(
				m_communicationId,
				requestedControlMode);

		if (status.IsOk() == false)
		{
			const std::string errorMsg =
				"[CommunicationChannel] Disabling of remote control failed. Reason: " + status.errorMessage;
			printError(errorMsg.c_str());
		}
	}
	else
	{
		printError("[CommunicationChannel] Session control service client not available.");
	}
}

void CommunicationChannel::sendScreenGrabResult(int x, int y, int w, int h, const std::string &pictureData) const
{
	//printLog("Entry");
	TVRemoteScreenSDKCommunication::CallStatus callStatus;

	std::lock_guard<std::mutex> lock(m_imageServiceClientMutex);
	if (m_imageServiceClient)
	{
		callStatus = m_imageServiceClient->UpdateImage(
			m_communicationId,
			x,
			y,
			w,
			h,
			pictureData);

		if (!callStatus.IsOk())
		{
			printError("[Communication Channel] Image update failed: ", callStatus.errorMessage);
		}
	}
	else
	{
		printError("[Communication Channel] Client not available for image service");
	}
}

void CommunicationChannel::sendImageDefinitionForGrabResult(const std::string& title,
		size_t width,
		size_t height,
		double dpi,
		ColorFormat colorFormat) const
{
	printLog("Entry");
	std::lock_guard<std::mutex> lock(m_imageServiceClientMutex);
	if (m_imageServiceClient)
	{
		const TVRemoteScreenSDKCommunication::CallStatus response =
			m_imageServiceClient->UpdateImageDefinition(
				m_communicationId,
				title,
				width,
				height,
				getSdkCommunicationColorFormat(colorFormat),
				dpi);

		if (response.IsOk() == false)
		{
			printError("[CommunicationChannel] Sending image definition failed. Reason: ", response.errorMessage);
		}
	}
	else
	{
		printError("[CommunicationChannel] Image service client not available.");
	}
}

std::string CommunicationChannel::getServerLocation(const TVRemoteScreenSDKCommunication::ServiceType serviceType) const
{
	printLog("Entry");
	for (const TVRemoteScreenSDKCommunication::RegistrationService::ServiceInformation& serviceInformation : m_serviceInformations)
	{
		if (serviceInformation.type == serviceType)
		{
			return serviceInformation.location;
		}
	}

	return std::string();
}

bool CommunicationChannel::establishConnection()
{
	printLog("Entry");
	using namespace TVRemoteScreenSDKCommunication::RegistrationService;

	std::lock_guard<std::mutex> lock(m_registrationServiceClientMutex);
	m_registrationServiceClient = TVRemoteScreenSDKCommunication::RegistrationService::ServiceFactory::CreateClient();
	m_registrationServiceClient->StartClient(m_registrationSocket);

	const IRegistrationServiceClient::ExchangeVersionResponse exchangeResponse =
		m_registrationServiceClient->ExchangeVersion(ClientVersion);

	if (exchangeResponse.callStatus.IsOk() == false)
	{
		const std::string errorMsg =
			"[CommunicationChannel] Exchange of version failed. Reason: " + exchangeResponse.callStatus.errorMessage;
		printError(errorMsg.c_str());
		return false;
	}

	const std::string ServerVersion = exchangeResponse.versionNumber;
	std::string version = ServerVersion;

	if (std::strtof(ClientVersion, nullptr) < std::strtof(ServerVersion.c_str(), nullptr))
	{
		version = ClientVersion;
	}

	const IRegistrationServiceClient::DiscoverResponse discoverResponse = m_registrationServiceClient->Discover(version);

	if (!discoverResponse.callStatus.IsOk())
	{
		const std::string errorMsg =
			"[CommunicationChannel] Version Handshake failed. Reason: " + exchangeResponse.callStatus.errorMessage;
		printError(errorMsg.c_str());
		return false;
	}

	m_communicationId = discoverResponse.communicationId;
	m_serviceInformations = discoverResponse.services;

	return true;
}

bool CommunicationChannel::setupClientAndServer()
{
	printLog("Entry");
	return setupConnectivityClient() &&
		setupImageClient() &&
		setupImageNotificationClient() &&
		setupSessionControlClient() &&
		setupSessionStatusService() &&
		setupInputService() &&
		setupConnectivityService() &&
		registerServices();
}

bool CommunicationChannel::setupConnectivityService()
{
	printLog("Entry");
	using namespace TVRemoteScreenSDKCommunication::ConnectivityService;

	std::lock_guard<std::mutex> lock(m_connectivityServiceServerMutex);
	m_connectivityServiceServer = ServiceFactory::CreateServer();

	if (m_connectivityServiceServer->StartServer(std::string(SocketPrefix) + ConnectivityLocation.string() + m_communicationId) == false)
	{
		return false;
	}

	auto availableCallback = [communicationId{m_communicationId}](
		const std::string& comId, const IConnectivityServiceServer::IsAvailableResponseCallback& response)
	{
		if (comId == communicationId)
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_connectivityServiceServer->SetIsAvailableCallback(availableCallback);

	std::weak_ptr<CommunicationChannel> weakThis = m_weakThis;
	auto disconnectCallback = [weakThis](
		const std::string& comId, const IConnectivityServiceServer::IsAvailableResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			const std::lock_guard<std::mutex> disconnectLock(communicationChannel->m_disconnectCondition->mutex);
			communicationChannel->m_disconnectCondition->condition.notify_all();
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_connectivityServiceServer->SetDisconnectCallback(disconnectCallback);

	return true;
}

bool CommunicationChannel::setupInputService()
{
	printLog("Entry");
	std::lock_guard<std::mutex> lock(m_inputServiceServerMutex);
	m_inputServiceServer = TVRemoteScreenSDKCommunication::InputService::ServiceFactory::CreateServer();

	if (!m_inputServiceServer->StartServer(std::string(SocketPrefix) + InputLocation.string() + m_communicationId))
	{
		return false;
	}

	std::weak_ptr<CommunicationChannel> weakThis = m_weakThis;

	auto receivedKeyCallback = [weakThis](
		const std::string& comId,
		TVRemoteScreenSDKCommunication::InputService::KeyState keyState,
		uint32_t xkbSymbol,
		uint32_t unicodeCharacter,
		uint32_t xkbModifiers,
		const TVRemoteScreenSDKCommunication::InputService::IInputServiceServer::KeyResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			switch(keyState)
			{
			case TVRemoteScreenSDKCommunication::InputService::KeyState::Down:
				communicationChannel->m_keyboardKeyEvent(xkbSymbol, unicodeCharacter, xkbModifiers, false);
				break;
			case TVRemoteScreenSDKCommunication::InputService::KeyState::Up:
				communicationChannel->m_keyboardKeyEvent(xkbSymbol, unicodeCharacter, xkbModifiers, true);
				break;
			case TVRemoteScreenSDKCommunication::InputService::KeyState::Unknown:
				break;
			}

			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_inputServiceServer->SetReceivedKeyCallback(receivedKeyCallback);

	auto mouseMoveCallback = [weakThis](
		const std::string& comId,
		int32_t posX,
		int32_t posY,
		const TVRemoteScreenSDKCommunication::InputService::IInputServiceServer::MouseMoveResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			communicationChannel->m_mouseMoved(posX, posY);
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_inputServiceServer->SetMouseMoveCallback(mouseMoveCallback);

	auto mousePressReleaseCallback = [weakThis](
		const std::string& comId,
		TVRemoteScreenSDKCommunication::InputService::KeyState keyState,
		int32_t posX,
		int32_t posY,
		TVRemoteScreenSDKCommunication::InputService::MouseButton button,
		const TVRemoteScreenSDKCommunication::InputService::IInputServiceServer::MousePressReleaseResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			switch(button)
			{
			case TVRemoteScreenSDKCommunication::InputService::MouseButton::Left:
				communicationChannel->m_mouseClick(posX, posY, 1);
				break;
			case TVRemoteScreenSDKCommunication::InputService::MouseButton::Middle:
				communicationChannel->m_mouseClick(posX, posY, 2);
				break;
			case TVRemoteScreenSDKCommunication::InputService::MouseButton::Right:
				communicationChannel->m_mouseClick(posX, posY, 3);
				break;
			default:
				response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
				return;
			}

			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_inputServiceServer->SetMousePressReleaseCallback(mousePressReleaseCallback);

	auto mouseWheelCallback = [weakThis](
		const std::string& comId,
		int32_t posX,
		int32_t posY,
		int32_t angle,
		const TVRemoteScreenSDKCommunication::InputService::IInputServiceServer::MouseWheelResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_inputServiceServer->SetMouseWheelCallback(mouseWheelCallback);

	return true;
}

bool CommunicationChannel::setupSessionStatusService()
{
	printLog("Entry");
	using namespace TVRemoteScreenSDKCommunication::SessionStatusService;

	std::lock_guard<std::mutex> lock(m_sessionStatusServiceServerMutex);
	m_sessionStatusServiceServer = ServiceFactory::CreateServer();

	if (m_sessionStatusServiceServer->StartServer(std::string(SocketPrefix) + SessionStatusLocation.string() + m_communicationId) == false)
	{
		return false;
	}

	std::weak_ptr<CommunicationChannel> weakThis = m_weakThis;
	auto remoteControlStarted = [weakThis](
		const std::string& comId,
		const GrabStrategy strategy,
		const ISessionStatusServiceServer::RemoteControllStartedResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));

			communicationChannel->m_RCsessionStarted();
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_sessionStatusServiceServer->SetRemoteControlStartedCallback(remoteControlStarted);

	auto remoteControlStopped = [weakThis](
		const std::string& comId,
		const ISessionStatusServiceServer::RemoteControllStartedResponseCallback& response)
	{
		printLog("Entry");
		const std::shared_ptr<CommunicationChannel> communicationChannel = weakThis.lock();
		if (communicationChannel && (communicationChannel->m_communicationId == comId))
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Ok));
			communicationChannel->m_RCsessionStopped();
		}
		else
		{
			response(TVRemoteScreenSDKCommunication::CallStatus(TVRemoteScreenSDKCommunication::CallState::Failed));
		}
	};
	m_sessionStatusServiceServer->SetRemoteControlStoppedCallback(remoteControlStopped);

	return true;
}

bool CommunicationChannel::setupConnectivityClient()
{
	printLog("Entry");
	const std::string ServiceLocation = getServerLocation(TVRemoteScreenSDKCommunication::ServiceType::Connectivity);
	return setupClient(
		ServiceLocation,
		TVRemoteScreenSDKCommunication::ConnectivityService::ServiceFactory::CreateClient,
		m_connectivityServiceClient,
		m_connectivityServiceClientMutex);
}

bool CommunicationChannel::setupImageClient()
{
	printLog("Entry");
	const std::string ServiceLocation = getServerLocation(TVRemoteScreenSDKCommunication::ServiceType::Image);
	return setupClient(
		ServiceLocation,
		TVRemoteScreenSDKCommunication::ImageService::ServiceFactory::CreateClient,
		m_imageServiceClient,
		m_imageServiceClientMutex);
}

bool CommunicationChannel::setupImageNotificationClient()
{
	printLog("Entry");
	const std::string ServiceLocation = getServerLocation(TVRemoteScreenSDKCommunication::ServiceType::ImageNotification);
	return setupClient(
		ServiceLocation,
		TVRemoteScreenSDKCommunication::ImageNotificationService::ServiceFactory::CreateClient,
		m_imageNotificationServiceClient,
		m_imageNotificationServiceClientMutex);
}

bool CommunicationChannel::setupSessionControlClient()
{
	printLog("Entry");
	const std::string ServiceLocation = getServerLocation(TVRemoteScreenSDKCommunication::ServiceType::SessionControl);
	return setupClient(
		ServiceLocation,
		TVRemoteScreenSDKCommunication::SessionControlService::ServiceFactory::CreateClient,
		m_sessionControlServiceClient,
		m_sessionControlServiceClientMutex);
}

bool CommunicationChannel::registerServices() const
{
	printLog("Entry");
	TVRemoteScreenSDKCommunication::CallStatus status;

	std::lock_guard<std::mutex> lock(m_registrationServiceClientMutex);

	status = m_registrationServiceClient->RegisterService(
		m_communicationId,
		TVRemoteScreenSDKCommunication::ServiceType::Connectivity,
		std::string(SocketPrefix) + ConnectivityLocation.string() + m_communicationId);

	if (!status.IsOk())
	{
		printLog("Error registering service ", ConnectivityLocation.string());
		return false;
	}

	status = m_registrationServiceClient->RegisterService(
		m_communicationId,
		TVRemoteScreenSDKCommunication::ServiceType::Input,
		std::string(SocketPrefix) + InputLocation.string() + m_communicationId);

	if (!status.IsOk())
	{
		printLog("Error registering service ", InputLocation.string());
		return false;
	}

	status = m_registrationServiceClient->RegisterService(
		m_communicationId,
		TVRemoteScreenSDKCommunication::ServiceType::SessionStatus,
		std::string(SocketPrefix) + SessionStatusLocation.string() + m_communicationId);

	if (!status.IsOk())
	{
		printLog("Error registering service ", SessionStatusLocation.string());
		return false;
	}

	return true;
}

void CommunicationChannel::sendDisconnect() const
{
	printLog("Entry");
	std::lock_guard<std::mutex> connectivityServiceClientLock(m_connectivityServiceClientMutex);
	if (m_connectivityServiceClient)
	{
		m_connectivityServiceClient->Disconnect(m_communicationId);
	}

	std::lock_guard<std::mutex> disconnectConditionLock(m_disconnectCondition->mutex);
	m_disconnectCondition->condition.notify_all();
}

void CommunicationChannel::startPing()
{
	printLog("Entry");
	constexpr uint8_t PingTimeout = 5; //seconds

	std::unique_lock<std::mutex> lock(m_disconnectCondition->mutex);
	while (m_isRunning &&
		   m_disconnectCondition->condition.wait_for(lock, std::chrono::seconds(PingTimeout)) == std::cv_status::timeout)
	{
		std::unique_lock<std::mutex> connectivityServiceClientLock(m_connectivityServiceClientMutex);
		if (m_connectivityServiceClient &&
			m_connectivityServiceClient->IsAvailable(m_communicationId).IsOk())
		{
			connectivityServiceClientLock.unlock();
		}
		else
		{
			break;
		}
	}
}

void CommunicationChannel::tearDown()
{
	printLog("Entry");
	teardownServer(m_connectivityServiceServer,  m_connectivityServiceServerMutex);
	teardownServer(m_inputServiceServer,         m_inputServiceServerMutex);
	teardownServer(m_sessionStatusServiceServer, m_sessionStatusServiceServerMutex);

	teardownClient(m_connectivityServiceClient,      m_connectivityServiceClientMutex);
	teardownClient(m_imageNotificationServiceClient, m_imageNotificationServiceClientMutex);
	teardownClient(m_imageServiceClient,             m_imageServiceClientMutex);
	teardownClient(m_registrationServiceClient,      m_registrationServiceClientMutex);
	teardownClient(m_sessionControlServiceClient,    m_sessionControlServiceClientMutex);
}

} // namespace vncplugin

max_stars_repo_name: AdrianRK/vncplugin

max_issues_repo_name: AdrianRK/vncplugin

max_forks_repo_name: AdrianRK/vncplugin


text:
#include <iostream>
#include <boost/program_options.hpp>
#include "vptree.h"

using namespace std;
namespace po = boost::program_options;

/* Functions taken from Laurens van der Maaten's original implementation of t-SNE */
/* Source: https://github.com/lvdmaaten/bhtsne                                    */
static void computeGaussianPerplexity(double* X, int N, int D, unsigned int** _row_P, unsigned int** _col_P, double** _val_P, double perplexity, int K);
static void symmetrizeMatrix(unsigned int** _row_P, unsigned int** _col_P, double** _val_P, int N);
static void computeSquaredEuclideanDistance(double* X, int N, int D, double* DD);
static void zeroMean(double* X, int N, int D);
/**********************************************************************************/

static bool load_data(string infile, double **data, int &num_instances, int &num_features) {

  FILE *fp = fopen(infile.c_str(), "rb");
	if (fp == NULL) {
		cout << "Error: could not open data file " << infile << endl;
		return false;
	}

  uint64_t ret;
	ret = fread(&num_instances, sizeof(int), 1, fp);
	ret = fread(&num_features, sizeof(int), 1, fp);

	*data = (double *)malloc(num_instances * num_features * sizeof(double));
  if (*data == NULL) {
    cout << "Error: memory allocation of " << num_instances << " by "
         << num_features << " matrix failed" << endl;
    return false;
  }

  uint64_t nelem = (uint64_t)num_instances * num_features;

  size_t batch_size = 1e8;
  double *ptr = *data;
  ret = 0;
  for (uint64_t remaining = nelem; remaining > 0; remaining -= batch_size) {
    if (remaining < batch_size) {
      batch_size = remaining;
    }
    ret += fread(ptr, sizeof(double), batch_size, fp);
    ptr += batch_size;
  }

  if (ret != nelem) {
    cout << "Error: reading input returned incorrect number of elements (" << ret
         << ", expected " << nelem << ")" << endl;
    return false;
  }

	fclose(fp);

	return true;
}

static void truncate_data(double *X, int num_instances, int num_features, int target_dims) {
  size_t i_old = 0;
  size_t i_new = 0;
  for (int r = 0; r < num_instances; r++) {
    for (int c = 0; c < num_features; c++) {
      if (c < target_dims) {
        X[i_new++] = X[i_old];
      }
      i_old++;
    }
  }
}

static bool run(double *X, int num_instances, int num_features, double perplexity, string outfile) {

  // Apply lower bound on perplexity from original t-SNE implementation
  if (num_instances - 1 < 3 * perplexity) {
    cout << "Error: target perplexity (" << perplexity << ") is too large "
         << "for the number of data points (" << num_instances << ")" << endl;
    return false;
  }

  printf("Processing %d data points, %d features with target perplexity %f\n",
         num_instances, num_features, perplexity);

  // Normalize input data (to prevent numerical problems)
  zeroMean(X, num_instances, num_features);
  cout << "Normalizing the features" << endl;
  double max_X = 0;
  for (size_t i = 0; i < num_instances * num_features; i++) {
    if (fabs(X[i]) > max_X) {
      max_X = fabs(X[i]);
    }
  }

  for (size_t i = 0; i < num_instances * num_features; i++) {
    X[i] /= max_X;
  }

  // Compute input similarities for exact t-SNE
  double* P; unsigned int* row_P; unsigned int* col_P; double* val_P;

  // Compute asymmetric pairwise input similarities
  cout << "Computing conditional distributions" << endl;
  computeGaussianPerplexity(X, num_instances, num_features,
    &row_P, &col_P, &val_P, perplexity, (int) (3 * perplexity));

  // Symmetrize input similarities
  cout << "Symmetrizing matrix" << endl;
  symmetrizeMatrix(&row_P, &col_P, &val_P, num_instances);
  double sum_P = .0;
  for (int i = 0; i < row_P[num_instances]; i++) {
    sum_P += val_P[i];
  }
  for (int i = 0; i < row_P[num_instances]; i++) {
    val_P[i] /= sum_P;
  }

  cout << "Saving to " << outfile << endl;
	FILE *fp = fopen(outfile.c_str(), "wb");
	if (fp == NULL) {
		cout << "Error: could not open output file " << outfile << endl;
    return false;
	}

	fwrite(&num_instances, sizeof(int), 1, fp);
  fwrite(row_P, sizeof(unsigned int), num_instances + 1, fp);
	fwrite(col_P, sizeof(unsigned int), row_P[num_instances], fp);
  fwrite(val_P, sizeof(double), row_P[num_instances], fp);

  free(row_P);
  free(col_P);
  free(val_P);

  return true;
}

int main(int argc, char **argv) {
  // Declare the supported options.
  po::options_description desc("Allowed options");
  desc.add_options()
    ("help", "produce help message")
    ("input-file", po::value<string>()->value_name("FILE")->default_value("data.dat"), "name of binary input file (see prepare_input.m)")
    ("output-file", po::value<string>()->value_name("FILE")->default_value("P.dat"), "name of output file to be created")
    ("perp", po::value<double>()->value_name("NUM")->default_value(30, "30"), "set target perplexity for conditional distributions")
    ("num-dims", po::value<int>()->value_name("NUM"), "if provided, only the first NUM features in the input will be used")
  ;

  po::variables_map vm;
  po::store(po::command_line_parser(argc, argv).
                options(desc).run(), vm);
  po::notify(vm);

  if (vm.count("help")) {
    cout << "Usage: ComputeP [options]" << endl;
    cout << desc << "\n";
    return 1;
  }

	double perplexity = vm["perp"].as<double>();
  string infile = vm["input-file"].as<string>();
  string outfile = vm["output-file"].as<string>();

  double *data;
  int num_instances;
  int num_features;

	if (!load_data(infile, &data, num_instances, num_features)) {
    return 1;
  }

  cout << infile << " successfully loaded" << endl;

  if (vm.count("num-dims")) {
    int num_dims = vm["num-dims"].as<int>();
    cout << "Using only the first " << num_dims << " dimensions" << endl;
    truncate_data(data, num_instances, num_features, num_dims);
    num_features = num_dims;
  }

  if (!run(data, num_instances, num_features, perplexity, outfile)) {
    return 1;
  }

  cout << "Done" << endl;

  return 0;
}

// Compute input similarities with a fixed perplexity using ball trees (this function allocates memory another function should free)
// Source: https://github.com/lvdmaaten/bhtsne
static void computeGaussianPerplexity(double* X, int N, int D, unsigned int** _row_P, unsigned int** _col_P, double** _val_P, double perplexity, int K) {

    if(perplexity > K) printf("Perplexity should be lower than K!\n");

    // Allocate the memory we need
    *_row_P = (unsigned int*)    malloc((N + 1) * sizeof(unsigned int));
    *_col_P = (unsigned int*)    calloc(N * K, sizeof(unsigned int));
    *_val_P = (double*) calloc(N * K, sizeof(double));
    if(*_row_P == NULL || *_col_P == NULL || *_val_P == NULL) { printf("Memory allocation failed!\n"); exit(1); }
    unsigned int* row_P = *_row_P;
    unsigned int* col_P = *_col_P;
    double* val_P = *_val_P;
    double* cur_P = (double*) malloc((N - 1) * sizeof(double));
    if(cur_P == NULL) { printf("Memory allocation failed!\n"); exit(1); }
    row_P[0] = 0;
    for(int n = 0; n < N; n++) row_P[n + 1] = row_P[n] + (unsigned int) K;

    // Build ball tree on data set
    VpTree<DataPoint, euclidean_distance>* tree = new VpTree<DataPoint, euclidean_distance>();
    vector<DataPoint> obj_X(N, DataPoint(D, -1, X));
    for(int n = 0; n < N; n++) obj_X[n] = DataPoint(D, n, X + n * D);
    tree->create(obj_X);

    // Loop over all points to find nearest neighbors
    printf("Building tree...\n");
    vector<DataPoint> indices;
    vector<double> distances;
    for(int n = 0; n < N; n++) {

        if(n % 10000 == 0) printf(" - point %d of %d\n", n, N);

        // Find nearest neighbors
        indices.clear();
        distances.clear();
        tree->search(obj_X[n], K + 1, &indices, &distances);

        // Initialize some variables for binary search
        bool found = false;
        double beta = 1.0;
        double min_beta = -DBL_MAX;
        double max_beta =  DBL_MAX;
        double tol = 1e-5;

        // Iterate until we found a good perplexity
        int iter = 0; double sum_P;
        while(!found && iter < 200) {

            // Compute Gaussian kernel row
            for(int m = 0; m < K; m++) cur_P[m] = exp(-beta * distances[m + 1] * distances[m + 1]);

            // Compute entropy of current row
            sum_P = DBL_MIN;
            for(int m = 0; m < K; m++) sum_P += cur_P[m];
            double H = .0;
            for(int m = 0; m < K; m++) H += beta * (distances[m + 1] * distances[m + 1] * cur_P[m]);
            H = (H / sum_P) + log(sum_P);

            // Evaluate whether the entropy is within the tolerance level
            double Hdiff = H - log(perplexity);
            if(Hdiff < tol && -Hdiff < tol) {
                found = true;
            }
            else {
                if(Hdiff > 0) {
                    min_beta = beta;
                    if(max_beta == DBL_MAX || max_beta == -DBL_MAX)
                        beta *= 2.0;
                    else
                        beta = (beta + max_beta) / 2.0;
                }
                else {
                    max_beta = beta;
                    if(min_beta == -DBL_MAX || min_beta == DBL_MAX)
                        beta /= 2.0;
                    else
                        beta = (beta + min_beta) / 2.0;
                }
            }

            // Update iteration counter
            iter++;
        }

        // Row-normalize current row of P and store in matrix
        for(unsigned int m = 0; m < K; m++) cur_P[m] /= sum_P;
        for(unsigned int m = 0; m < K; m++) {
            col_P[row_P[n] + m] = (unsigned int) indices[m + 1].index();
            val_P[row_P[n] + m] = cur_P[m];
        }
    }

    // Clean up memory
    obj_X.clear();
    free(cur_P);
    delete tree;
}

// Symmetrizes a sparse matrix
// Source: https://github.com/lvdmaaten/bhtsne
static void symmetrizeMatrix(unsigned int** _row_P, unsigned int** _col_P, double** _val_P, int N) {

    // Get sparse matrix
    unsigned int* row_P = *_row_P;
    unsigned int* col_P = *_col_P;
    double* val_P = *_val_P;

    // Count number of elements and row counts of symmetric matrix
    int* row_counts = (int*) calloc(N, sizeof(int));
    if(row_counts == NULL) { printf("Memory allocation failed!\n"); exit(1); }
    for(int n = 0; n < N; n++) {
        for(int i = row_P[n]; i < row_P[n + 1]; i++) {

            // Check whether element (col_P[i], n) is present
            bool present = false;
            for(int m = row_P[col_P[i]]; m < row_P[col_P[i] + 1]; m++) {
                if(col_P[m] == n) present = true;
            }
            if(present) row_counts[n]++;
            else {
                row_counts[n]++;
                row_counts[col_P[i]]++;
            }
        }
    }
    int no_elem = 0;
    for(int n = 0; n < N; n++) no_elem += row_counts[n];

    // Allocate memory for symmetrized matrix
    unsigned int* sym_row_P = (unsigned int*) malloc((N + 1) * sizeof(unsigned int));
    unsigned int* sym_col_P = (unsigned int*) malloc(no_elem * sizeof(unsigned int));
    double* sym_val_P = (double*) malloc(no_elem * sizeof(double));
    if(sym_row_P == NULL || sym_col_P == NULL || sym_val_P == NULL) { printf("Memory allocation failed!\n"); exit(1); }

    // Construct new row indices for symmetric matrix
    sym_row_P[0] = 0;
    for(int n = 0; n < N; n++) sym_row_P[n + 1] = sym_row_P[n] + (unsigned int) row_counts[n];

    // Fill the result matrix
    int* offset = (int*) calloc(N, sizeof(int));
    if(offset == NULL) { printf("Memory allocation failed!\n"); exit(1); }
    for(int n = 0; n < N; n++) {
        for(unsigned int i = row_P[n]; i < row_P[n + 1]; i++) {                                  // considering element(n, col_P[i])

            // Check whether element (col_P[i], n) is present
            bool present = false;
            for(unsigned int m = row_P[col_P[i]]; m < row_P[col_P[i] + 1]; m++) {
                if(col_P[m] == n) {
                    present = true;
                    if(n <= col_P[i]) {                                                 // make sure we do not add elements twice
                        sym_col_P[sym_row_P[n]        + offset[n]]        = col_P[i];
                        sym_col_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = n;
                        sym_val_P[sym_row_P[n]        + offset[n]]        = val_P[i] + val_P[m];
                        sym_val_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = val_P[i] + val_P[m];
                    }
                }
            }

            // If (col_P[i], n) is not present, there is no addition involved
            if(!present) {
                sym_col_P[sym_row_P[n]        + offset[n]]        = col_P[i];
                sym_col_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = n;
                sym_val_P[sym_row_P[n]        + offset[n]]        = val_P[i];
                sym_val_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = val_P[i];
            }

            // Update offsets
            if(!present || (present && n <= col_P[i])) {
                offset[n]++;
                if(col_P[i] != n) offset[col_P[i]]++;
            }
        }
    }

    // Divide the result by two
    for(int i = 0; i < no_elem; i++) sym_val_P[i] /= 2.0;

    // Return symmetrized matrices
    free(*_row_P); *_row_P = sym_row_P;
    free(*_col_P); *_col_P = sym_col_P;
    free(*_val_P); *_val_P = sym_val_P;

    // Free up some memery
    free(offset); offset = NULL;
    free(row_counts); row_counts  = NULL;
}

// Compute squared Euclidean distance matrix
// Source: https://github.com/lvdmaaten/bhtsne
static void computeSquaredEuclideanDistance(double* X, int N, int D, double* DD) {
    const double* XnD = X;
    for(int n = 0; n < N; ++n, XnD += D) {
        const double* XmD = XnD + D;
        double* curr_elem = &DD[n*N + n];
        *curr_elem = 0.0;
        double* curr_elem_sym = curr_elem + N;
        for(int m = n + 1; m < N; ++m, XmD+=D, curr_elem_sym+=N) {
            *(++curr_elem) = 0.0;
            for(int d = 0; d < D; ++d) {
                *curr_elem += (XnD[d] - XmD[d]) * (XnD[d] - XmD[d]);
            }
            *curr_elem_sym = *curr_elem;
        }
    }
}

// Makes data zero-mean
// Source: https://github.com/lvdmaaten/bhtsne
static void zeroMean(double* X, int N, int D) {

	// Compute data mean
	double* mean = (double*) calloc(D, sizeof(double));
    if(mean == NULL) { printf("Memory allocation failed!\n"); exit(1); }
    int nD = 0;
	for(int n = 0; n < N; n++) {
		for(int d = 0; d < D; d++) {
			mean[d] += X[nD + d];
		}
        nD += D;
	}
	for(int d = 0; d < D; d++) {
		mean[d] /= (double) N;
	}

	// Subtract data mean
    nD = 0;
	for(int n = 0; n < N; n++) {
		for(int d = 0; d < D; d++) {
			X[nD + d] -= mean[d];
		}
        nD += D;
	}
    free(mean); mean = NULL;
}

max_stars_repo_name: hhcho/netsne

max_issues_repo_name: hhcho/netsne

max_forks_repo_name: hhcho/netsne


text:
#ifndef __CXXU_UTILS_H__
#define __CXXU_UTILS_H__

#include <stdint.h>

#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <chrono>
#include <typeinfo>
#include <type_traits>
#include <functional>

#include <boost/mpl/if.hpp>

#include <cxxutils/config.h>
#include <cxxu/types.hpp>

// Black magic stolen from:
// http://stackoverflow.com/questions/1005476/
//  how-to-detect-whether-there-is-a-specific-member-variable-in-class
//
// Explanation:
// http://cpptalk.wordpress.com/2009/09/12/
//   substitution-failure-is-not-an-error-2/
#define CXXU_MAKE_HAS(WHAT)                                \
template <typename T>                                      \
struct has_ ## WHAT {                                      \
    struct Fallback { int WHAT; };                         \
    struct Derived : T, Fallback { };                      \
                                                           \
    template<typename C, C> struct ChT;                    \
                                                           \
    template<typename C>                                   \
    static char (&f(ChT<int Fallback::*, &C::WHAT>*))[1];  \
                                                           \
    template<typename C>                                   \
    static char (&f(...))[2];                              \
                                                           \
    static bool const value = sizeof(f<Derived>(0)) == 2;  \
};

#define CXXU_MAKE_HAS_MEMBER(WHAT, PARAMS)                 \
template <typename K>                                      \
struct has_member_ ## WHAT                                 \
{                                                          \
    template <typename T, void(T::*)(PARAMS)>              \
    struct S;                                              \
                                                           \
    template <typename T>                                  \
    static One f(S<T, &T::WHAT>*);                         \
                                                           \
    template <typename T>                                  \
    static Two f(...);                                     \
                                                           \
    enum { value = sizeof(f<K>(0)) == sizeof(One) };       \
};

#define CXXU_AUTO_RET(x) -> decltype(x) { return x; }

/// @file

/// Collections of file and string utilities not unlike those found in Perl
namespace cxxu {

/// Checks if current program is running interactively
///
/// @return true if current program is running interactively
CXXUTILS_API
bool interactive(void);

/// Display a progress bar
///
/// @param x current value
/// @param n maximum value
/// @param w progress bar width
/// @return true if current program is running interactively
CXXUTILS_API
void set_progress(std::size_t x, std::size_t n, std::size_t w = 50);

/// Clear a progress bar
///
/// @param w progress bar width
CXXUTILS_API
void clear_progress(std::size_t w = 50);

/// Path to user's HOME directory
CXXUTILS_API
std::string home_directory(void);

/// Checks if path exists
CXXUTILS_API
bool exists(const std::string& path);

/// Checks if directory exists
CXXUTILS_API
bool directory_exists(const std::string& path);

/// Checks if file exists
CXXUTILS_API
bool file_exists(const std::string& path);

/// Same as the touch system utility
CXXUTILS_API
bool touch_file(const std::string& path);

/// Truncates/creates file at the specified size
CXXUTILS_API
bool truncate_file(const std::string& path, std::size_t size);

/// Copies file
CXXUTILS_API
bool copy_file(const std::string& from, const std::string& to);

using write_file_cb = std::function<void(std::ofstream& ofs)>;

/// Write a file in a transaction like manner
/// Calls cb when you should write
CXXUTILS_API
bool write_file(const std::string& file, write_file_cb cb);

using read_file_cb = std::function<void(std::ifstream& ifs)>;

/// Reads a file in a transaction like manner
/// Calls cb when you should read
CXXUTILS_API
bool read_file(const std::string& file, read_file_cb cb);

/// Returns file size in bytes
CXXUTILS_API
uint64_t file_size(const std::string& path);

/// Creates a path ala mkdir -p
CXXUTILS_API
bool mkpath(const std::string& path);

/// Removes a path ala rm -rf
CXXUTILS_API
unsigned long rmpath(const std::string& path);

/// Removes a file
CXXUTILS_API
bool rmfile(const std::string& path);

/// Creates the path for the a file path
CXXUTILS_API
bool mkfilepath(const std::string& path);

/// Rename a file
CXXUTILS_API
void rename(const std::string& from_path, const std::string& to_path);

/// Returns absolute path to the file
CXXUTILS_API
std::string fullpath(const std::string& rel);

/// Returns absolute path to the file in the specified directory
CXXUTILS_API
std::string fullpath(const std::string& dir, const std::string& file);

/// Strips the directory portion of a file path
CXXUTILS_API
std::string basename(const std::string& path, const std::string& ext = "");

/// Strips the file portion of a file path
CXXUTILS_API
std::string dirname(const std::string& path);

/// Converts a human readable size (1GB) to bytes
CXXUTILS_API
unsigned long long human_readable_size(const std::string& expr);

/// Converts a size to a human readable size (1024 --> 1KB)
CXXUTILS_API
std::string human_readable_size(uint64_t size, const std::string& user_unit = "B");

/// Splits expr into list according to re
CXXUTILS_API
void split(const std::string& re, const std::string& expr, cxxu::string_list& list);

/// Trims whitespaces and end-of-line characters
CXXUTILS_API
void chomp(std::string& s);

/// Removes quotes
CXXUTILS_API
void unquote(std::string& s);

/// Returns filesystem entries corresponding to the specified glob
/// expression
CXXUTILS_API
cxxu::string_list glob(const std::string& expr);

/// @return true if \c expr matches \c re
CXXUTILS_API
bool match(const std::string& expr, const std::string& re);

CXXUTILS_API bool
extract_delimited(
    std::string& from,
    std::string& to,
    unsigned char delim = ';',
    unsigned char quote = '\0'
);

CXXUTILS_API
std::string demangle_type_name(const std::string& mangled);
CXXUTILS_API
std::string md5sum(const std::string& file);
CXXUTILS_API
std::string escape(const char c);
CXXUTILS_API
std::string escape_for_string(const char c);
CXXUTILS_API
std::string escape(const std::string& s);
CXXUTILS_API
ssize_t
send_file(int out_fd, int in_fd, off_t* offset, size_t count);

template <typename T>
inline
std::string
type_info(const T& t)
{ return demangle_type_name(typeid(t).name()); }

template <typename T>
inline
std::string
type_info(void)
{ return demangle_type_name(typeid(T).name()); }

inline
cxxu::string_list
split(const std::string& re, const std::string& expr)
{
    cxxu::string_list list;
    split(re, expr, list);

    return list;
}

template <typename S>
inline
std::string
join(const std::string& sep, const std::vector<S>& v)
{
    std::string joined;

    if (v.size() > 0) {
        joined = v[0];
    }

    for (std::size_t i = 1; i < v.size(); i++) {
        joined += sep;
        joined += v[i];
    }

    return joined;
}

inline
std::string
indent(const std::string& what)
{
    std::string sep = "\n";
    std::string pad = "    ";
    std::string s;

    if (what.size() > 0) {
        s = pad + join(sep + pad, split(sep, what));
    }

    return s;
}

inline
std::string
trim_left(const std::string& str, const char* tokens = " \t")
{
    std::string::size_type begin = str.find_first_not_of(tokens);
    if (begin == std::string::npos) {
        begin = str.size();
    }

    return std::string(str, begin);
}

inline
std::string
trim_right(const std::string& str, const char* tokens = " \t")
{
    std::string::size_type end = str.find_last_not_of(tokens);
    if (end == std::string::npos) {
        end = -1;
    }

    return std::string(str, 0, end+1);
}

inline
std::string
trim(const std::string& str, const char* tokens = " \t")
{
    return trim_left(trim_right(str, tokens), tokens);
}

template<typename T>
std::string to_string_fr(T i) {
    std::string str = std::to_string(i);

    for(int i = str.size(), current_digit = 0; i > 0; --i, ++current_digit) {
        if (current_digit && !(current_digit % 3)) {
            str.insert(i, 1, '.');
        }
    }

    return str;
}

template<typename UINT>
std::string
to_hex(UINT value, int size = sizeof(UINT)) {
    char buffer[32];
    size_t length = sprintf(buffer, "%0*X", size * 2, value);
    return std::string(buffer, length);
}

inline
std::string
to_hex(uint64_t value, int size = sizeof(uint64_t)) {
    char buffer[32];
    size_t length = sprintf(buffer, "%0*lX", size * 2, value);
    return std::string(buffer, length);
}

template <typename T>
struct make_vector {
    typedef std::vector<T> vector_type;

    static
    void make(vector_type& v)
    {}

    template <typename Item, typename... Items>
    static
    void make(vector_type& v, Item& i, Items... items)
    {
        v.push_back(T(i));
        make(v, items...);
    }
};

template <typename... Args>
std::string
join(const std::string& sep, Args... args)
{
    std::vector<std::string> v;
    make_vector<std::string>::make(v, args...);

    return join(sep, v);
}

template <typename... Args>
std::string
cat_dir(Args... args)
{
    std::vector<std::string> v;
    make_vector<std::string>::make(v, args...);

    return join("/", v);
}

template <typename... Args>
std::string
cat_file(Args... args)
{ return cat_dir(std::forward<Args>(args)...); }

template <typename T>
inline
T to_num(const std::string& s)
{
    return ((T) strtoull(s.c_str(), NULL, 10));
}

// Number of bits used by v
template <typename T>
inline
__attribute__ ((const))
uint32_t
used_bits(const T v)
{
    if (v == 0) {
        return 0;
    }

    T index;

    __asm__("bsr %1, %0;" :"=r"(index) :"r"(v));

    return index + 1;
}

template <>
inline
__attribute__ ((const))
uint32_t
used_bits<int8_t>(const int8_t v)
{ return used_bits((int16_t) v); }

template <>
inline
__attribute__ ((const))
uint32_t
used_bits<uint8_t>(const uint8_t v)
{ return used_bits((uint16_t) v); }

inline
uint32_t
byte_size_of(uint32_t bits, uint32_t count)
{
    uint32_t bit_size = bits * count;

    return (bit_size / 8) + ((bit_size % 8) != 0 ? 1 : 0);
}

inline
uint32_t
byte_size_of(uint32_t bits)
{
    return byte_size_of(bits, 1);
}

template <typename T>
inline
void
inc_ptr(T*& ptr, std::size_t bytes)
{
    ptr = (T*)(
        ((uintptr_t) (ptr)) + bytes
    );
}

template <typename T>
inline
void
dec_ptr(T*& ptr, std::size_t bytes)
{
    ptr = (T*)(
        ((uintptr_t) (ptr)) - bytes
    );
}

template <typename R, typename T>
inline
R*
inc_ptr(T*& ptr, std::size_t bytes)
{
    return (R*)(
        ((uintptr_t) (ptr)) + bytes
    );
}

template <typename T>
inline
__attribute__ ((const))
T*
align_to_128bits(T* ptr)
{
    return (T*)(
        (((uintptr_t) (ptr)) + 15) & ~15
    );
}

template <typename T>
inline
__attribute__ ((const))
const T*
align_to_128bits(const T* ptr)
{
    return (const T*)(
        (((uintptr_t) (ptr)) + 15) & ~15
    );
}

inline
__attribute__ ((const))
std::size_t
align_to_128bits(std::size_t size_in_bytes)
{
    return ((size_in_bytes + 15) & ~15);
}

template <typename T>
inline
__attribute__ ((const))
std::size_t
aligned_sizeof(T& t)
{
    return align_to_128bits(sizeof(T));
}

template <typename T>
inline
__attribute__ ((const))
std::size_t
aligned_sizeof(const T& t)
{
    return align_to_128bits(sizeof(T));
}

inline
__attribute__ ((const))
std::size_t
align_to_128(std::size_t count)
{
    return ((count + 127) & ~127);
}

template <std::size_t Size>
struct make_aligned {
    static const std::size_t value = ((Size + 15) & ~15);
};

template <
    typename T,
    typename = typename std::enable_if<
        std::is_arithmetic<T>::value
    >::type
>
inline
auto
as_printable(T i) -> decltype(+i)
{ return +i; }

template <typename T>
inline
const T&
as_printable(
    const T& s,
    typename std::enable_if<
        !std::is_arithmetic<T>::value
    >::type* = 0
)
{ return s; }

template <typename T>
constexpr
typename std::underlying_type<T>::type
integral(T value)
{
    return static_cast<typename std::underlying_type<T>::type>(value);
}

template <typename T>
inline
std::size_t
digit_count(T v)
{
    return
        v == 0
        ? 1
        : ((std::size_t) std::log10(v)) + 1
        ;
}

template <typename C>
struct extract_iterator {
    typedef typename boost::mpl::if_<
        std::is_const<C>,
        typename C::const_iterator,
        typename C::iterator
    >::type type;
};

template <typename C>
struct extract_reference {
    typedef typename extract_iterator<C>::type::reference type;
};

template <typename C>
struct extract_value {
    typedef typename std::remove_reference<
        typename extract_reference<C>::type
    >::type type;
};

template <typename V>
struct make_const_reference {
    typedef const typename std::remove_cv<
        typename std::remove_reference<V>::type
    >::type& type;
};

} // namespace cxxu

#endif // __CXXU_UTILS_H__

max_stars_repo_name: ExpandiumSAS/cxxutils

max_issues_repo_name: ExpandiumSAS/cxxutils

max_forks_repo_name: ExpandiumSAS/cxxutils


text:
#include "stdafx.h"
#include <boost/test/unit_test.hpp>
#include <boost/shared_ptr.hpp>

BOOST_AUTO_TEST_SUITE( ClassFactory_Suite )

bool is_critical( CStdErrorInfo const& ex ) { return ex.m_lError < 0; }

BOOST_AUTO_TEST_CASE( CreateClassFactory )
{
	//boost::shared_ptr<IStdClassFactory> lpFactory(IStdClassFactory::LoadModule("StdClassFactoryTester.dll"));
	boost::shared_ptr<IStdClassFactory> lpFactory(IStdClassFactory::LoadModule("BulletAnimatSim_vc10D.dll"));

	BOOST_CHECK( lpFactory != NULL );

	CStdSerialize *lpTest = NULL;
	BOOST_CHECK_EXCEPTION( lpTest = lpFactory->CreateObject("test1", "TestObject"), CStdErrorInfo, is_critical );
	BOOST_CHECK_EXCEPTION( lpTest = lpFactory->CreateObject("test", "TestObject1"), CStdErrorInfo, is_critical );

	boost::shared_ptr<CStdSerialize> lpTest2(lpFactory->CreateObject("test", "TestObject"));
	BOOST_CHECK( lpTest2 != NULL );

	CStdSerialize *lpClone = lpTest2->Clone();
	BOOST_CHECK( lpClone == NULL );
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: NeuroRoboticTech/AnimatLabPublicSource

max_issues_repo_name: NeuroRoboticTech/AnimatLabPublicSource

max_forks_repo_name: NeuroRoboticTech/AnimatLabPublicSource