<commit_before>/****************************************************************************
**   ncs is the backend's server of nodecast
**   Copyright (C) 2010-2013  Frédéric Logier <frederic@logier.org>
**
**   https://github.com/nodecast/ncs
**
**   This program is free software: you can redistribute it and/or modify
**   it under the terms of the GNU Affero General Public License as
**   published by the Free Software Foundation, either version 3 of the
**   License, or (at your option) any later version.
**
**   This program is distributed in the hope that it will be useful,
**   but WITHOUT ANY WARRANTY; without even the implied warranty of
**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**   GNU Affero General Public License for more details.
**
**   You should have received a copy of the GNU Affero General Public License
**   along with this program.  If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/

#include "service.h"

Service::Service(QObject *parent) : QObject(parent)
{}

Service::~Service()
{
    qDebug() << "delete http server";
    delete(m_http_api);

    qDebug() << "delete tracker";
    delete(m_nodetrack);

    qDebug() << "delete ftp";
    delete(m_nodeftp);

    qDebug() << "delete xmpp server";
    delete(m_xmpp_server);

    qDebug() << "delete xmpp client";
    delete(m_xmpp_client);

    qDebug() << "delete worker api";
    emit shutdown();
    delete(worker_api);
}

void Service::Http_init()
{
    m_session.setPort(4567);
    m_session.setConnector(&m_connector);
    m_session.setAutoCreateSession(false);
    //Http_api s1(&session);

    m_http_api = new Http_api(&m_session);

    m_session.setStaticContentService(m_http_api);

    m_session.setSessionCookieName("nodecast");

    m_session.start();
}

void Service::Nodetrack_init()
{
    m_nodetrack_session.setPort(6969);
    m_nodetrack_session.setConnector(&m_nodetrack_connector);

    m_nodetrack = new Nodetrack(&m_nodetrack_session);

    m_nodetrack_session.setStaticContentService(m_nodetrack);
    m_nodetrack_session.start();
}

void Service::Nodeftp_init(int port)
{
   QThread *node_ftp = new QThread;
   m_nodeftp = new Nodeftp(port);
   m_nodeftp->moveToThread(node_ftp);
   node_ftp->start();

   m_nodeftp->connect(node_ftp, SIGNAL(started()), SLOT(ftp_init()));
}

void Service::Tracker_init()
{
    m_tracker_session.setPort(6060);
    m_tracker_session.setConnector(&m_tracker_connector);

    m_tracker = new Tracker(&m_tracker_session);

    m_tracker_session.setStaticContentService(m_tracker);
    m_tracker_session.start();
}

void Service::Xmpp_init(QString domain_name, int xmpp_client_port, int xmpp_server_port)
{
    qRegisterMetaType<QXmppLogger::MessageType>("QXmppLogger::MessageType");

    m_xmpp_server = new Xmpp_server(domain_name, xmpp_client_port, xmpp_server_port);
    m_xmpp_client = new Xmpp_client(domain_name, xmpp_client_port);
}

void Service::Worker_init()
{
    QThread *worker_pull = new QThread;
    worker_api = new Worker_api();
    worker_api->moveToThread(worker_pull);
    worker_pull->start();
    connect(this, SIGNAL(shutdown()), worker_api, SLOT(destructor()), Qt::BlockingQueuedConnection);

}
<commit_msg>delete only up services<commit_after>/****************************************************************************
**   ncs is the backend's server of nodecast
**   Copyright (C) 2010-2013  Frédéric Logier <frederic@logier.org>
**
**   https://github.com/nodecast/ncs
**
**   This program is free software: you can redistribute it and/or modify
**   it under the terms of the GNU Affero General Public License as
**   published by the Free Software Foundation, either version 3 of the
**   License, or (at your option) any later version.
**
**   This program is distributed in the hope that it will be useful,
**   but WITHOUT ANY WARRANTY; without even the implied warranty of
**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**   GNU Affero General Public License for more details.
**
**   You should have received a copy of the GNU Affero General Public License
**   along with this program.  If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/

#include "service.h"

Service::Service(QObject *parent) : QObject(parent)
{
    m_nodetrack = NULL;
    m_nodeftp = NULL;
    m_xmpp_server = NULL;
    m_xmpp_client = NULL;
}

Service::~Service()
{
    qDebug() << "delete http server";
    delete(m_http_api);

    qDebug() << "delete tracker";
    if (m_nodetrack) delete(m_nodetrack);

    qDebug() << "delete ftp";
    if (m_nodeftp) delete(m_nodeftp);

    qDebug() << "delete xmpp server";
    if (m_xmpp_server) delete(m_xmpp_server);

    qDebug() << "delete xmpp client";
    if (m_xmpp_client) delete(m_xmpp_client);

    qDebug() << "delete worker api";
    emit shutdown();
    delete(worker_api);
}

void Service::Http_init()
{
    m_session.setPort(4567);
    m_session.setConnector(&m_connector);
    m_session.setAutoCreateSession(false);
    //Http_api s1(&session);

    m_http_api = new Http_api(&m_session);

    m_session.setStaticContentService(m_http_api);

    m_session.setSessionCookieName("nodecast");

    m_session.start();
}

void Service::Nodetrack_init()
{
    m_nodetrack_session.setPort(6969);
    m_nodetrack_session.setConnector(&m_nodetrack_connector);

    m_nodetrack = new Nodetrack(&m_nodetrack_session);

    m_nodetrack_session.setStaticContentService(m_nodetrack);
    m_nodetrack_session.start();
}

void Service::Nodeftp_init(int port)
{
   QThread *node_ftp = new QThread;
   m_nodeftp = new Nodeftp(port);
   m_nodeftp->moveToThread(node_ftp);
   node_ftp->start();

   m_nodeftp->connect(node_ftp, SIGNAL(started()), SLOT(ftp_init()));
}

void Service::Tracker_init()
{
    m_tracker_session.setPort(6060);
    m_tracker_session.setConnector(&m_tracker_connector);

    m_tracker = new Tracker(&m_tracker_session);

    m_tracker_session.setStaticContentService(m_tracker);
    m_tracker_session.start();
}

void Service::Xmpp_init(QString domain_name, int xmpp_client_port, int xmpp_server_port)
{
    qRegisterMetaType<QXmppLogger::MessageType>("QXmppLogger::MessageType");

    m_xmpp_server = new Xmpp_server(domain_name, xmpp_client_port, xmpp_server_port);
    m_xmpp_client = new Xmpp_client(domain_name, xmpp_client_port);
}

void Service::Worker_init()
{
    QThread *worker_pull = new QThread;
    worker_api = new Worker_api();
    worker_api->moveToThread(worker_pull);
    worker_pull->start();
    connect(this, SIGNAL(shutdown()), worker_api, SLOT(destructor()), Qt::BlockingQueuedConnection);

}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <service>
#include <net/inet4>
#include <cstdio>
#include "update.hpp"
#include "hw_timer.hpp"
#include "crc32.h"

static const uint16_t TERM_PORT = 6667;

// prevent default serial out
void default_stdout_handlers() {}
#include <hw/serial.hpp>

typedef net::tcp::Connection_ptr Connection_ptr;
Connection_ptr deserialize_connection(void* addr, net::TCP& tcp);
static std::vector<Connection_ptr> saveme;
static std::vector<std::string>    savemsg;

void setup_terminal_connection(Connection_ptr conn)
{
  saveme.push_back(conn);
  // retrieve binary
  conn->on_read(512,
  [conn] (net::tcp::buffer_t buf, size_t n)
  {
    std::string str((const char*) buf.get(), n);
    printf("Received message %u: %s", savemsg.size()+1, str.c_str());
    // save for later as strings
    savemsg.push_back(str);
  });
  conn->on_close(
  [conn] {
    printf("Terminal %s closed\n", conn->to_string().c_str());
  });
}

template <typename T>
void setup_terminal(T& inet)
{
  // mini terminal
  printf("Setting up terminal on port %u\n", TERM_PORT);

  auto& term = inet.tcp().bind(TERM_PORT);
  term.on_connect(
  [] (auto conn) {
    setup_terminal_connection(conn);
    // write a string to change the state
    char BUFFER_CHAR = 'A';
    static CRC32_BEGIN(crc);
    const int LEN = 4096;
    auto buf = net::tcp::buffer_t(new uint8_t[LEN], std::default_delete<uint8_t[]>());

    for (int i = 0; i < 1000; i++) {
      memset(buf.get(), BUFFER_CHAR, LEN);
      conn->write(buf, LEN,
      [conn, buf, LEN] (int) {

        crc = crc32(crc, (char*) buf.get(), LEN);
        printf("[%p] CRC32: %08x   %s\n", buf.get(), CRC32_VALUE(crc), conn->to_string().c_str());
      });

      //BUFFER_CHAR++;
      if (BUFFER_CHAR > 'Z') BUFFER_CHAR = 'A';
    }
  });
}

template <typename T>
void setup_liveupdate_server(T& inet);

void Service::start(const std::string&)
{
  volatile HW_timer timer("Service::start()");
  // add own serial out after service start
  auto& com1 = hw::Serial::port<1>();
  OS::add_stdout(com1.get_print_handler());

  printf("\n");
  printf("-= Starting LiveUpdate test service =-\n");
  //printf("* CPU freq is %f MHz\n", OS::cpu_freq().count());

  auto& inet = net::Inet4::ifconfig<0>(
        { 10,0,0,42 },     // IP
        { 255,255,255,0 }, // Netmask
        { 10,0,0,1 },      // Gateway
        { 10,0,0,1 });     // DNS

  /// attempt to resume (if there is anything to resume)
  void the_string(Restore);
  void the_buffer(Restore);
  void the_timing(Restore);
  void restore_term(Restore);
  void saved_message(Restore);
  void on_update_area(Restore);
  void on_missing(Restore);

  LiveUpdate::on_resume(1,   the_string);
  LiveUpdate::on_resume(2,   the_buffer);
  LiveUpdate::on_resume(100, the_timing);
  LiveUpdate::on_resume(665, saved_message);
  LiveUpdate::on_resume(666, restore_term);
  LiveUpdate::on_resume(999, on_update_area);
  // begin restoring saved data
  if (LiveUpdate::resume(on_missing) == false) {
    printf("* Not restoring data, because no update has happened\n");
    // .. logic for when there is nothing to resume yet
    setup_liveupdate_server(inet);
  }

  // listen for telnet clients
  setup_terminal(inet);

}

#include <hw/cpu.hpp>
void save_stuff(Storage storage, buffer_len final_blob)
{
  storage.add_string(1, "Some string :(");
  storage.add_string(1, "Some other string :(");

  char buffer[] = "Just some random buffer";
  storage.add_buffer(2, {buffer, sizeof(buffer)});

  auto ts = hw::CPU::rdtsc();
  storage.add_buffer(100, &ts, sizeof(ts));
  printf("! CPU ticks before: %lld\n", ts);

  // where the update was stored last
  printf("Storing location %p:%d\n", final_blob.buffer, final_blob.length);
  storage.add_buffer(999, &final_blob, sizeof(buffer_len));

  // messages received from terminals
  for (auto& msg : savemsg)
      storage.add_string(665, msg);
  // open terminals
  for (auto conn : saveme)
    if (conn->is_connected())
      storage.add_connection(666, conn);
}

#include <hertz>
#include <chrono>
void the_string(Restore thing)
{
  auto str = thing.as_string();
  printf("The string [some_string] has value [%s]\n", str.c_str());
  assert(str == "Some string :(" || str == "Some other string :(");
}
void the_buffer(Restore thing)
{
  printf("The buffer is %d bytes long\n", thing.length());
  printf("As text: %.*s\n", thing.length(), thing.as_buffer().buffer);
  // there is an extra zero at the end of the buffer
  auto str = std::string(thing.as_buffer().buffer, thing.as_buffer().length-1);
  assert(str == "Just some random buffer");
}
void saved_message(Restore thing)
{
  static int n = 0;
  auto str = thing.as_string();

  printf("[%d] %s", ++n, str.c_str());
  // re-save it
  //savemsg.push_back(str);
}
void on_missing(Restore thing)
{
  printf("Missing resume function for %u\n", thing.get_id());
}

void the_timing(Restore thing)
{
  auto t1   = thing.as_type<int64_t>();
  auto diff = hw::CPU::rdtsc() - t1;

  using namespace std::chrono;
  double  div  = OS::cpu_freq().count() * 1000000.0;
  int64_t time = diff / div * 1000;

  char buffer[256];
  int len = snprintf(buffer, sizeof(buffer),
             "! Boot time in ticks: %lld (%lld ms)\n", diff, time);

  savemsg.emplace_back(buffer, len);
}
void restore_term(Restore thing)
{
  auto& stack = net::Inet4::stack<0> ();
  // restore connection to terminal
  auto conn = thing.as_tcp_connection(stack.tcp());
  setup_terminal_connection(conn);
  printf("Restored terminal connection to %s\n", conn->remote().to_string().c_str());

  // send all the messages so far
  //for (auto msg : savemsg)
  //  conn->write(msg);
}

#include <timers>
void on_update_area(Restore thing)
{
  buffer_len updloc = thing.as_type<buffer_len> ();
  printf("Reloading from %p:%d\n", updloc.buffer, updloc.length);

  // we are perpetually updating ourselves
  using namespace std::chrono;
  Timers::oneshot(milliseconds(50),
  [updloc] (auto) {
    LiveUpdate::begin(updloc, save_stuff);
  });
}

template <typename T>
void setup_liveupdate_server(T& inet)
{
  // listen for live updates
  auto& server = inet.tcp().bind(666);
  server.on_connect(
  [] (auto conn)
  {
    static const int UPDATE_MAX = 1024*1024 * 3; // 3mb files supported
    char* update_blob = new char[UPDATE_MAX];
    int*  update_size = new int(0);

    // retrieve binary
    conn->on_read(9000,
    [conn, update_blob, update_size] (net::tcp::buffer_t buf, size_t n)
    {
      memcpy(update_blob + *update_size, buf.get(), n);
      assert(*update_size + n <= UPDATE_MAX);
      *update_size += (int) n;

    }).on_close(
    [update_blob, update_size] {
      // we received a binary:
      float frac = *update_size / (float) UPDATE_MAX * 100.f;
      printf("* New update size: %u b  (%.2f%%)\n", *update_size, frac);
      // run live update process
      LiveUpdate::begin({update_blob, *update_size}, save_stuff);
      /// We should never return :-) ///
      assert(0 && "!! Update failed !!");
    });
  });
}
<commit_msg>Show profilers and boot times<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <service>
#include <net/inet4>
#include <profile>
#include <cstdio>
#include "update.hpp"
#include "hw_timer.hpp"
#include "crc32.h"

static const uint16_t TERM_PORT = 6667;

// prevent default serial out
void default_stdout_handlers() {}
#include <hw/serial.hpp>

typedef net::tcp::Connection_ptr Connection_ptr;
Connection_ptr deserialize_connection(void* addr, net::TCP& tcp);
static std::vector<Connection_ptr> saveme;
static std::vector<std::string>    savemsg;

void setup_terminal_connection(Connection_ptr conn)
{
  saveme.push_back(conn);
  // retrieve binary
  conn->on_read(512,
  [conn] (net::tcp::buffer_t buf, size_t n)
  {
    std::string str((const char*) buf.get(), n);
    printf("Received message %u: %s", savemsg.size()+1, str.c_str());
    // save for later as strings
    savemsg.push_back(str);
  });
  conn->on_close(
  [conn] {
    printf("Terminal %s closed\n", conn->to_string().c_str());
  });
}

template <typename T>
void setup_terminal(T& inet)
{
  // mini terminal
  printf("Setting up terminal on port %u\n", TERM_PORT);

  auto& term = inet.tcp().bind(TERM_PORT);
  term.on_connect(
  [] (auto conn) {
    setup_terminal_connection(conn);
    // write a string to change the state
    char BUFFER_CHAR = 'A';
    static CRC32_BEGIN(crc);
    const int LEN = 4096;
    auto buf = net::tcp::buffer_t(new uint8_t[LEN], std::default_delete<uint8_t[]>());

    for (int i = 0; i < 1000; i++) {
      memset(buf.get(), BUFFER_CHAR, LEN);
      conn->write(buf, LEN,
      [conn, buf, LEN] (int) {

        crc = crc32(crc, (char*) buf.get(), LEN);
        printf("[%p] CRC32: %08x   %s\n", buf.get(), CRC32_VALUE(crc), conn->to_string().c_str());
      });

      //BUFFER_CHAR++;
      if (BUFFER_CHAR > 'Z') BUFFER_CHAR = 'A';
    }
  });
}

template <typename T>
void setup_liveupdate_server(T& inet);

void Service::start(const std::string&)
{
  volatile HW_timer timer("Service::start()");
  // add own serial out after service start
  auto& com1 = hw::Serial::port<1>();
  OS::add_stdout(com1.get_print_handler());
  printf("-== BOOT TIME %.2f ms ==-\n", OS::micros_since_boot() / 1000.0);

  printf("\n");
  printf("-= Starting LiveUpdate test service =-\n");
  //printf("* CPU freq is %f MHz\n", OS::cpu_freq().count());

  auto& inet = net::Inet4::ifconfig<0>(
        { 10,0,0,42 },     // IP
        { 255,255,255,0 }, // Netmask
        { 10,0,0,1 },      // Gateway
        { 10,0,0,1 });     // DNS

  /// attempt to resume (if there is anything to resume)
  void the_string(Restore);
  void the_buffer(Restore);
  void the_timing(Restore);
  void restore_term(Restore);
  void saved_message(Restore);
  void on_update_area(Restore);
  void on_missing(Restore);

  LiveUpdate::on_resume(1,   the_string);
  LiveUpdate::on_resume(2,   the_buffer);
  LiveUpdate::on_resume(100, the_timing);
  LiveUpdate::on_resume(665, saved_message);
  LiveUpdate::on_resume(666, restore_term);
  LiveUpdate::on_resume(999, on_update_area);
  // begin restoring saved data
  if (LiveUpdate::resume(on_missing) == false) {
    printf("* Not restoring data, because no update has happened\n");
    // .. logic for when there is nothing to resume yet
    setup_liveupdate_server(inet);
  }

  // listen for telnet clients
  setup_terminal(inet);

}
void Service::ready()
{
  // show profile stats for boot
  printf("%s\n", ScopedProfiler::get_statistics().c_str());
}

#include <hw/cpu.hpp>
void save_stuff(Storage storage, buffer_len final_blob)
{
  storage.add_string(1, "Some string :(");
  storage.add_string(1, "Some other string :(");

  char buffer[] = "Just some random buffer";
  storage.add_buffer(2, {buffer, sizeof(buffer)});

  int64_t ts = hw::CPU::rdtsc();
  storage.add_buffer(100, &ts, sizeof(ts));
  printf("! CPU ticks before: %lld\n", ts);

  // where the update was stored last
  printf("Storing location %p:%d\n", final_blob.buffer, final_blob.length);
  storage.add_buffer(999, &final_blob, sizeof(buffer_len));

  // messages received from terminals
  for (auto& msg : savemsg)
      storage.add_string(665, msg);
  // open terminals
  for (auto conn : saveme)
    if (conn->is_connected())
      storage.add_connection(666, conn);
}

#include <hertz>
#include <chrono>
void the_string(Restore thing)
{
  auto str = thing.as_string();
  printf("The string [some_string] has value [%s]\n", str.c_str());
  assert(str == "Some string :(" || str == "Some other string :(");
}
void the_buffer(Restore thing)
{
  printf("The buffer is %d bytes long\n", thing.length());
  printf("As text: %.*s\n", thing.length(), thing.as_buffer().buffer);
  // there is an extra zero at the end of the buffer
  auto str = std::string(thing.as_buffer().buffer, thing.as_buffer().length-1);
  assert(str == "Just some random buffer");
}
void saved_message(Restore thing)
{
  static int n = 0;
  auto str = thing.as_string();

  printf("[%d] %s", ++n, str.c_str());
  // re-save it
  //savemsg.push_back(str);
}
void on_missing(Restore thing)
{
  printf("Missing resume function for %u\n", thing.get_id());
}

void the_timing(Restore thing)
{
  auto t1   = thing.as_type<int64_t>();
  auto t2 = hw::CPU::rdtsc();
  printf("! CPU ticks after: %lld  (CPU freq: %f)\n", t2, OS::cpu_freq().count());

  using namespace std::chrono;
  double  div  = OS::cpu_freq().count() * 1000.0;
  double  time = (t2-t1) / div;

  char buffer[256];
  int len = snprintf(buffer, sizeof(buffer),
             "! Boot time in ticks: %lld (%.2f ms)\n", t2-t1, time);

  savemsg.emplace_back(buffer, len);
}
void restore_term(Restore thing)
{
  auto& stack = net::Inet4::stack<0> ();
  // restore connection to terminal
  auto conn = thing.as_tcp_connection(stack.tcp());
  setup_terminal_connection(conn);
  printf("Restored terminal connection to %s\n", conn->remote().to_string().c_str());

  // send all the messages so far
  //for (auto msg : savemsg)
  //  conn->write(msg);
}

#include <timers>
void on_update_area(Restore thing)
{
  buffer_len updloc = thing.as_type<buffer_len> ();
  printf("Reloading from %p:%d\n", updloc.buffer, updloc.length);

  // we are perpetually updating ourselves
  using namespace std::chrono;
  Timers::oneshot(milliseconds(50),
  [updloc] (auto) {
    LiveUpdate::begin(updloc, save_stuff);
  });
}

template <typename T>
void setup_liveupdate_server(T& inet)
{
  // listen for live updates
  auto& server = inet.tcp().bind(666);
  server.on_connect(
  [] (auto conn)
  {
    static const int UPDATE_MAX = 1024*1024 * 3; // 3mb files supported
    char* update_blob = new char[UPDATE_MAX];
    int*  update_size = new int(0);

    // retrieve binary
    conn->on_read(9000,
    [conn, update_blob, update_size] (net::tcp::buffer_t buf, size_t n)
    {
      memcpy(update_blob + *update_size, buf.get(), n);
      assert(*update_size + n <= UPDATE_MAX);
      *update_size += (int) n;

    }).on_close(
    [update_blob, update_size] {
      // we received a binary:
      float frac = *update_size / (float) UPDATE_MAX * 100.f;
      printf("* New update size: %u b  (%.2f%%)\n", *update_size, frac);
      // run live update process
      LiveUpdate::begin({update_blob, *update_size}, save_stuff);
      /// We should never return :-) ///
      assert(0 && "!! Update failed !!");
    });
  });
}
<|endoftext|>


<commit_before><commit_msg>Remove completed TODOs<commit_after><|endoftext|>


<commit_before>#include <cmath>
#include <Eigen/Dense>
#include <gtest/gtest.h>

class ReferenceFilter
{
public:
    ReferenceFilter( unsigned inputCount, unsigned outputCount )
        : mW( Eigen::MatrixXf::Random( outputCount, inputCount ) )
    {}

    Eigen::VectorXf operator()( Eigen::VectorXf inputs )
    {
        return mW * inputs;
    }

    Eigen::MatrixXf mW;
};

TEST( AdaptiveFilter, LMS )
{
    const unsigned kInputCount = 10;
    const unsigned kOutputCount = 3;
    const unsigned kSampleCount = 100;
    const float kMaxAmplitude = 1.0f;
    const float kMaxFrequency = 10.0f;
    const float kStep = 0.1f * 1.0f / kMaxFrequency;

    ReferenceFilter referenceFilter( kInputCount, kOutputCount );
    Eigen::VectorXf input( kInputCount );
    Eigen::VectorXf A = kMaxAmplitude / 2.0f *
        ( Eigen::VectorXf::Random( kInputCount ).array() + 1.0f );
    Eigen::VectorXf omega = kMaxFrequency / 2.0f *
        ( Eigen::VectorXf::Random( kInputCount ).array() + 1.0f );

    for ( int i = 0; i < kSampleCount; ++ i )
    {
        float t = kStep * i;
        input = A.array() * ( omega.array() * t ).unaryExpr(
            std::ptr_fun( std::sinf ) );
    }
}
<commit_msg>esn : tests : AdaptiveFilter : LMS : implemented normalized LMS algorithm<commit_after>#include <cmath>
#include <Eigen/Dense>
#include <gtest/gtest.h>

class ReferenceFilter
{
public:
    ReferenceFilter( unsigned inputCount, unsigned outputCount )
        : mW( Eigen::MatrixXf::Random( outputCount, inputCount ) )
    {}

    Eigen::VectorXf operator()( Eigen::VectorXf inputs )
    {
        return mW * inputs;
    }

    Eigen::MatrixXf mW;
};

TEST( AdaptiveFilter, LMS )
{
    const unsigned kInputCount = 5;
    const unsigned kOutputCount = 3;
    const unsigned kSampleCount = 100000;
    const float kMaxAmplitude = 1.0f;
    const float kMaxFrequency = 10.0f;
    const float kStep = 0.1f * 1.0f / kMaxFrequency;

    ReferenceFilter referenceFilter( kInputCount, kOutputCount );
    Eigen::VectorXf input( kInputCount );
    Eigen::VectorXf A = kMaxAmplitude / 2.0f *
        ( Eigen::VectorXf::Random( kInputCount ).array() + 1.0f );
    Eigen::VectorXf omega = kMaxFrequency / 2.0f *
        ( Eigen::VectorXf::Random( kInputCount ).array() + 1.0f );

    Eigen::MatrixXf Wout = Eigen::MatrixXf::Random(
        kOutputCount, kInputCount );

    for ( int i = 1; i < kSampleCount; ++ i )
    {
        float t = kStep * i;
        input = A.array() * ( omega.array() * t ).unaryExpr(
            std::ptr_fun( std::sinf ) );
        Eigen::VectorXf referenceOutput = referenceFilter( input );
        Eigen::VectorXf currentOutput = Wout * input;
        Eigen::VectorXf error = referenceOutput - currentOutput;
        Wout += ( 0.1f * error * input.transpose() / input.squaredNorm() );
    }
}
<|endoftext|>


<commit_before>/**
@file System/Context.hpp
@brief Context class.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_SYSTEM_CONTEXT_HPP_
#define HORD_SYSTEM_CONTEXT_HPP_

#include <Hord/config.hpp>
#include <Hord/aux.hpp>
#include <Hord/Hive/Defs.hpp>
#include <Hord/Hive/Unit.hpp>
#include <Hord/IO/Datastore.hpp>
#include <Hord/Cmd/Defs.hpp>
#include <Hord/Cmd/Stage.hpp>
#include <Hord/System/Driver.hpp>

#include <utility>

namespace Hord {
namespace System {

// Forward declarations
class Context;

/**
	@addtogroup system
	@{
*/

/**
	%Context.

	@warning The context requires the attached datastore and hive
	exist as long as the context exists.

	@remarks This class mediates the behavior of commands one layer
	above the command transmission protocol for a server or client.
*/
class Context final {
public:
	/**
		%Context type.
	*/
	enum class Type : unsigned {
		/**
			Host view.
		*/
		host,

		/**
			Client view.
		*/
		client
	};

	/** Command stage map. */
	using stage_map_type = aux::unordered_map<
		Cmd::ID,
		Cmd::StageUPtr
	>;

	/** Command stage deque. */
	using stage_deque_type = aux::deque<
		Cmd::StageUPtr
	>;

	/** Command %ID and status pair. */
	using id_status_pair_type = std::pair<
		Cmd::ID,
		Cmd::Status
	>;

private:
	Type const m_type;
	System::Driver& m_driver;
	IO::Datastore& m_datastore;
	Hive::Unit& m_hive;
	Cmd::ID m_genid;

	// NB: Stores initiator stages
	stage_map_type m_active;

	// Remote results and local results
	stage_deque_type m_results;
	stage_deque_type m_input;
	stage_deque_type m_output;

	Cmd::ID
	next_id() noexcept;

	void
	terminate(
		stage_map_type::iterator it,
		bool const transmitted
	) noexcept;

	Context() = delete;
	Context(Context const&) = delete;
	Context& operator=(Context const&) = delete;
	Context& operator=(Context&&) = delete;

	Context(
		Type const type,
		System::Driver& driver,
		System::Driver::datastore_hive_pair& hive_pair
	);

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~Context() noexcept;

	/** Move constructor. */
	Context(Context&&) noexcept;

	/**
		Constructor with type, driver, and hive ID.

		@throws Error{ErrorCode::context_invalid_hive}
		If @a hive_id does not exist within @a driver.

		@param type %Type.
		@param driver %Driver.
		@param hive_id %Hive ID.
	*/
	Context(
		Type const type,
		System::Driver& driver,
		Hive::ID const hive_id
	);
/// @}

/** @name Properties */ /// @{
	/**
		Get type.
	*/
	Type
	get_type() const noexcept {
		return m_type;
	}

	/**
		Get driver.
		@{
	*/
	System::Driver&
	get_driver() noexcept {
		return m_driver;
	}
	System::Driver const&
	get_driver() const noexcept {
		return m_driver;
	}
	/** @} */

	/**
		Get datastore.
		@{
	*/
	IO::Datastore&
	get_datastore() noexcept {
		return m_datastore;
	}
	IO::Datastore const&
	get_datastore() const noexcept {
		return m_datastore;
	}
	/** @} */

	/**
		Get hive.
		@{
	*/
	Hive::Unit&
	get_hive() noexcept {
		return m_hive;
	}
	Hive::Unit const&
	get_hive() const noexcept {
		return m_hive;
	}
	/** @} */

	/**
		Get active commands.
	*/
	stage_map_type&
	get_active() noexcept {
		return m_active;
	}

	/**
		Get command results.
	*/
	stage_deque_type&
	get_results() noexcept {
		return m_results;
	}

	/**
		Get input stages.
	*/
	stage_deque_type&
	get_input() noexcept {
		return m_input;
	}

	/**
		Get output stages.
	*/
	stage_deque_type&
	get_output() noexcept {
		return m_output;
	}

	/**
		Check if context is a host.
	*/
	bool
	is_host() const noexcept {
		return Context::Type::host == m_type;
	}

	/**
		Check if context is a client.
	*/
	bool
	is_client() const noexcept {
		return Context::Type::client == m_type;
	}

	/**
		Check if stage is local to the context.
	*/
	bool
	is_local(
		Cmd::Stage const& stage
	) const noexcept {
		return is_host()
			? stage.is_host()
			: stage.is_client()
		;
	}

	/**
		Check if stage is remote to the context.
	*/
	bool
	is_remote(
		Cmd::Stage const& stage
	) const noexcept {
		return !is_local(stage);
	}

	/**
		Check if stage is a context-local initiator.
	*/
	bool
	is_local_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_local(stage) && stage.is_initiator();
	}

	/**
		Check if stage is a context-remote initiator.
	*/
	bool
	is_remote_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_remote(stage) && stage.is_initiator();
	}
/// @}

/** @name Operations */ /// @{
	/**
		Initiate command.

		@note This will push an input stage. The command will not
		be active until the initiator stage is executed from
		execute_input().

		@par
		@note If @a initiator is pushed, the context takes ownership
		(@a initiator is moved). Otherwise, the callee retains
		ownership.

		@pre @code !stage->is_identified() @endcode

		@param initiator Initiator stage.
	*/
	void
	initiate(
		Cmd::StageUPtr& initiator
	) noexcept;

	/**
		Push command input.

		@note This is used by userspace to emplace remote stages.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains
		ownership.

		@pre @code stage->is_identified() @endcode

		@param stage %Stage to push.
	*/
	void
	push_input(
		Cmd::StageUPtr& stage
	) noexcept;

	/**
		Push command output.

		@note This is only used by command stages to emplace local
		results.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains
		ownership.

		@pre @code
			 origin->is_identified() &&
			!stage ->is_identified()
		@endcode

		@throws Error{ErrorCode::context_output_detached}
		If @a origin is not part of an active command.

		@param origin Origin stage.
		@param stage %Stage to push.
		@param remote_initiator Whether the remote endpoint should
		emplace the stage as an initiator (see @c Cmd::IDFields).
	*/
	void
	push_output(
		Cmd::Stage const& origin,
		Cmd::StageUPtr& stage,
		bool const remote_initiator
	);

	/**
		Push command result.

		@note This is only used by command stages to emplace stage
		results to the local endpoint.

		@par
		@warning If @a stage is already identified, it must have the
		same canonical ID as @a origin.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains
		ownership.

		@pre @code
			origin->is_identified() &&
			(
				!stage->is_identified() ||
				stage->get_id() == origin->get_id()
			)
		@endcode

		@throws Error{ErrorCode::context_output_detached}
		If @a origin is not part of an active command.

		@param origin Origin stage.
		@param stage %Stage to push.
	*/
	void
	push_result(
		Cmd::Stage const& origin,
		Cmd::StageUPtr& stage
	);

	/**
		Execute command on the context.

		@note Before an exception is rethrown,
		-# The local command will be terminated;
		-# @a result will be assigned to the offending command %ID
		   and @c Cmd::Status::error; and
		-# a @c GenericTerminate stage will be emitted if either the
		   command is active (i.e., the stage is not a local
		   initiator) or the remote command is waiting for a result.

		@par
		@note If there are no stages to execute, @a result holds
		@c Cmd::NULL_ID and @c static_cast<Cmd::Status>(0u) (an
		invalid status).

		@throws Error{ErrorCode::context_execute_not_active}
		If a non-initiating input stage carries an inactive %ID.

		@throws Error{ErrorCode::context_execute_already_active}
		If an initiating input stage carries an active %ID.

		@throws ...
		Exception from the stage.

		@returns The number of remaining input stages.
		@param result Execution result.
	*/
	std::size_t
	execute_input(
		id_status_pair_type& result
	);
/// @}
};

/** @} */ // end of doc-group system

} // namespace System
} // namespace Hord

#endif // HORD_SYSTEM_CONTEXT_HPP_
<commit_msg>System::Context: clarified purpose of push_output().<commit_after>/**
@file System/Context.hpp
@brief Context class.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_SYSTEM_CONTEXT_HPP_
#define HORD_SYSTEM_CONTEXT_HPP_

#include <Hord/config.hpp>
#include <Hord/aux.hpp>
#include <Hord/Hive/Defs.hpp>
#include <Hord/Hive/Unit.hpp>
#include <Hord/IO/Datastore.hpp>
#include <Hord/Cmd/Defs.hpp>
#include <Hord/Cmd/Stage.hpp>
#include <Hord/System/Driver.hpp>

#include <utility>

namespace Hord {
namespace System {

// Forward declarations
class Context;

/**
	@addtogroup system
	@{
*/

/**
	%Context.

	@warning The context requires the attached datastore and hive
	exist as long as the context exists.

	@remarks This class mediates the behavior of commands one layer
	above the command transmission protocol for a server or client.
*/
class Context final {
public:
	/**
		%Context type.
	*/
	enum class Type : unsigned {
		/**
			Host view.
		*/
		host,

		/**
			Client view.
		*/
		client
	};

	/** Command stage map. */
	using stage_map_type = aux::unordered_map<
		Cmd::ID,
		Cmd::StageUPtr
	>;

	/** Command stage deque. */
	using stage_deque_type = aux::deque<
		Cmd::StageUPtr
	>;

	/** Command %ID and status pair. */
	using id_status_pair_type = std::pair<
		Cmd::ID,
		Cmd::Status
	>;

private:
	Type const m_type;
	System::Driver& m_driver;
	IO::Datastore& m_datastore;
	Hive::Unit& m_hive;
	Cmd::ID m_genid;

	// NB: Stores initiator stages
	stage_map_type m_active;

	// Remote results and local results
	stage_deque_type m_results;
	stage_deque_type m_input;
	stage_deque_type m_output;

	Cmd::ID
	next_id() noexcept;

	void
	terminate(
		stage_map_type::iterator it,
		bool const transmitted
	) noexcept;

	Context() = delete;
	Context(Context const&) = delete;
	Context& operator=(Context const&) = delete;
	Context& operator=(Context&&) = delete;

	Context(
		Type const type,
		System::Driver& driver,
		System::Driver::datastore_hive_pair& hive_pair
	);

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~Context() noexcept;

	/** Move constructor. */
	Context(Context&&) noexcept;

	/**
		Constructor with type, driver, and hive ID.

		@throws Error{ErrorCode::context_invalid_hive}
		If @a hive_id does not exist within @a driver.

		@param type %Type.
		@param driver %Driver.
		@param hive_id %Hive ID.
	*/
	Context(
		Type const type,
		System::Driver& driver,
		Hive::ID const hive_id
	);
/// @}

/** @name Properties */ /// @{
	/**
		Get type.
	*/
	Type
	get_type() const noexcept {
		return m_type;
	}

	/**
		Get driver.
		@{
	*/
	System::Driver&
	get_driver() noexcept {
		return m_driver;
	}
	System::Driver const&
	get_driver() const noexcept {
		return m_driver;
	}
	/** @} */

	/**
		Get datastore.
		@{
	*/
	IO::Datastore&
	get_datastore() noexcept {
		return m_datastore;
	}
	IO::Datastore const&
	get_datastore() const noexcept {
		return m_datastore;
	}
	/** @} */

	/**
		Get hive.
		@{
	*/
	Hive::Unit&
	get_hive() noexcept {
		return m_hive;
	}
	Hive::Unit const&
	get_hive() const noexcept {
		return m_hive;
	}
	/** @} */

	/**
		Get active commands.
	*/
	stage_map_type&
	get_active() noexcept {
		return m_active;
	}

	/**
		Get command results.
	*/
	stage_deque_type&
	get_results() noexcept {
		return m_results;
	}

	/**
		Get input stages.
	*/
	stage_deque_type&
	get_input() noexcept {
		return m_input;
	}

	/**
		Get output stages.
	*/
	stage_deque_type&
	get_output() noexcept {
		return m_output;
	}

	/**
		Check if context is a host.
	*/
	bool
	is_host() const noexcept {
		return Context::Type::host == m_type;
	}

	/**
		Check if context is a client.
	*/
	bool
	is_client() const noexcept {
		return Context::Type::client == m_type;
	}

	/**
		Check if stage is local to the context.
	*/
	bool
	is_local(
		Cmd::Stage const& stage
	) const noexcept {
		return is_host()
			? stage.is_host()
			: stage.is_client()
		;
	}

	/**
		Check if stage is remote to the context.
	*/
	bool
	is_remote(
		Cmd::Stage const& stage
	) const noexcept {
		return !is_local(stage);
	}

	/**
		Check if stage is a context-local initiator.
	*/
	bool
	is_local_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_local(stage) && stage.is_initiator();
	}

	/**
		Check if stage is a context-remote initiator.
	*/
	bool
	is_remote_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_remote(stage) && stage.is_initiator();
	}
/// @}

/** @name Operations */ /// @{
	/**
		Initiate command.

		@note This will push an input stage. The command will not
		be active until the initiator stage is executed from
		execute_input().

		@par
		@note If @a initiator is pushed, the context takes ownership
		(@a initiator is moved). Otherwise, the callee retains
		ownership.

		@pre @code !stage->is_identified() @endcode

		@param initiator Initiator stage.
	*/
	void
	initiate(
		Cmd::StageUPtr& initiator
	) noexcept;

	/**
		Push command input.

		@note This is used by userspace to emplace remote stages.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains
		ownership.

		@pre @code stage->is_identified() @endcode

		@param stage %Stage to push.
	*/
	void
	push_input(
		Cmd::StageUPtr& stage
	) noexcept;

	/**
		Push command output.

		@note This is only used by command stages to emplace stage
		output to the remote endpoint.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains
		ownership.

		@pre @code
			 origin->is_identified() &&
			!stage ->is_identified()
		@endcode

		@throws Error{ErrorCode::context_output_detached}
		If @a origin is not part of an active command.

		@param origin Origin stage.
		@param stage %Stage to push.
		@param remote_initiator Whether the remote endpoint should
		emplace the stage as an initiator (see @c Cmd::IDFields).
	*/
	void
	push_output(
		Cmd::Stage const& origin,
		Cmd::StageUPtr& stage,
		bool const remote_initiator
	);

	/**
		Push command result.

		@note This is only used by command stages to emplace stage
		results to the local endpoint.

		@par
		@warning If @a stage is already identified, it must have the
		same canonical ID as @a origin.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains
		ownership.

		@pre @code
			origin->is_identified() &&
			(
				!stage->is_identified() ||
				stage->get_id() == origin->get_id()
			)
		@endcode

		@throws Error{ErrorCode::context_output_detached}
		If @a origin is not part of an active command.

		@param origin Origin stage.
		@param stage %Stage to push.
	*/
	void
	push_result(
		Cmd::Stage const& origin,
		Cmd::StageUPtr& stage
	);

	/**
		Execute command on the context.

		@note Before an exception is rethrown,
		-# The local command will be terminated;
		-# @a result will be assigned to the offending command %ID
		   and @c Cmd::Status::error; and
		-# a @c GenericTerminate stage will be emitted if either the
		   command is active (i.e., the stage is not a local
		   initiator) or the remote command is waiting for a result.

		@par
		@note If there are no stages to execute, @a result holds
		@c Cmd::NULL_ID and @c static_cast<Cmd::Status>(0u) (an
		invalid status).

		@throws Error{ErrorCode::context_execute_not_active}
		If a non-initiating input stage carries an inactive %ID.

		@throws Error{ErrorCode::context_execute_already_active}
		If an initiating input stage carries an active %ID.

		@throws ...
		Exception from the stage.

		@returns The number of remaining input stages.
		@param result Execution result.
	*/
	std::size_t
	execute_input(
		id_status_pair_type& result
	);
/// @}
};

/** @} */ // end of doc-group system

} // namespace System
} // namespace Hord

#endif // HORD_SYSTEM_CONTEXT_HPP_
<|endoftext|>


<commit_before>#ifndef INCLUDE_AL_FILE_HPP
#define INCLUDE_AL_FILE_HPP

#include <unistd.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <list>

#include "allocore/system/al_Config.h"

#ifdef AL_WIN32
	#define AL_FILE_DELIMITER '\\'
#else
	#define AL_FILE_DELIMITER '/'
#endif

#define AL_PATH_MAX (4096)

namespace al{

/// Strips a qualified path to a file (src) into a path to the containing folder (dst)
void path2dir(char* dst, const char* src);

/// a pair of path (folder/directory) and filename
class FilePath {
public:
	FilePath() {};
	FilePath(std::string file, std::string path = "/") : mPath(path), mFile(file) {}

	const std::string& file() const { return mFile; }
	const std::string& path() const { return mPath; }

	std::string filepath() const { return path()+file(); }

	FilePath& file(const std::string& v) { mFile=v; return *this; }
	FilePath& path(const std::string& v) { mPath=v; return *this; }

protected:
	std::string mPath;
	std::string mFile;
};

/// A handy way to manage several possible search paths
class SearchPaths {
public:
	SearchPaths() {}
	SearchPaths(int argc, char * const argv[], bool recursive=true) { addAppPaths(argc,argv,recursive); }
	~SearchPaths() {}

	/// find a file in the searchpaths
	/// returns true if file found, and fills result with corresponding path & filename
	/// returns false if file not found
	FilePath find(const std::string& filename);

	/// add a path to search in; recursive searching is optional
	void addSearchPath(const std::string& path, bool recursive = true);

	/// adds best estimate of application launch paths (cwd etc.)
	/// can pass in argv from the main() function if desired.
	void addAppPaths(int argc, char * const argv[], bool recursive = true);
	void addAppPaths(bool recursive = true);

	const std::string& appPath() const { return mAppPath; }

	/// todo?
	//void addResourcePath();

	// strips trailing filename from a path; e.g. /usr/bin/man -> /usr/bin/
	static std::string stripFileName(const std::string& src);
	// ensure path ends with the proper delimiter
	static std::string conformPath(const std::string& src);
	// does a file at the given filepath exist?
	static bool fileExists(const std::string& name, const std::string& path);

protected:

	typedef std::pair<std::string, bool> searchpath;
	std::list<searchpath> mSearchPaths;

	std::string mAppPath;

};

/// File
class File{
public:

	/// @param[in] path		path of file
	/// @param[in] mode		i/o mode w, r, wb, rb
	/// @param[in] open		whether to open the file
	File(const std::string& path, const std::string& mode="r", bool open=false);

	~File();

	void close();	///< Close file
	bool open();	///< Open file with specified i/o mode

	File& mode(const std::string& v){ mMode=v; return *this; }
	File& path(const std::string& v){ mPath=v; return *this; }

	/// Write memory elements to file
	int write(const std::string& v){ return fwrite(v.data(), 1, v.length(), mFP); }
	int write(const void * v, int size, int items=1){ return fwrite(v, size, items, mFP); }

	/// Quick and dirty write memory to file
	static int write(const std::string& path, const void * v, int size, int items=1);

	/// Returns character string of file contents (read mode only)
	char * readAll();

	/// Returns whether file is open
	bool opened() const { return 0 != mFP; }

	/// Returns file i/o mode string
	const std::string& mode() const { return mMode; }

	/// Returns path string
	const std::string& path() const { return mPath; }

	/// Returns size (in bytes) of file contents
	int size() const { return mSizeBytes; }

	/// Returns whether file exists
	static bool exists(const std::string& path);

	/// Return modification time of file (or 0 on failure)
	/// as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec modified();
	/// Return last access time of file (or 0 on failure)
	/// as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec accessed();
	/// Return creation time of file (or 0 on failure)
	/// as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec created();

	/// Return size file (or 0 on failure)
	size_t size();
	/// Return space used on disk of file (or 0 on failure)
	size_t storage();

	FILE * filePointer() { return mFP; }

	static al_sec modified(std::string path) { File f(path); return f.modified(); }
	static al_sec accessed(std::string path) { File f(path); return f.accessed(); }
	static al_sec created(std::string path) { File f(path); return f.created(); }
	static size_t size(std::string path) { File f(path); return f.size(); }
	static size_t storage(std::string path) { File f(path); return f.storage(); }

protected:
	class Impl; Impl * mImpl;

	std::string mPath;
	std::string mMode;
	char * mContent;
	int mSizeBytes;
	FILE * mFP;

	void freeContent();
	void allocContent(int n);
	void getSize();
};

//// INLINE IMPLEMENTATION ////

inline std::string SearchPaths::stripFileName(const std::string& src) {
	std::string filepath(src);
	size_t pos = filepath.find_last_of(AL_FILE_DELIMITER);
	if (pos !=std::string::npos) {
		filepath.erase(pos+1);
	}
	return filepath;
}

inline std::string SearchPaths::conformPath(const std::string& src) {
	std::string path(src);
	// paths should end with a delimiter:
	if (path[path.size()-1] != AL_FILE_DELIMITER) {
		path += AL_FILE_DELIMITER;
	}
	return path;
}

inline void SearchPaths::addAppPaths(int argc, char * const argv[], bool recursive) {
	addAppPaths(recursive);
	if (argc > 0) {
		//char path[4096];
		std::string filepath = stripFileName(argv[0]);
		mAppPath = filepath;
		addSearchPath(filepath, recursive);
	}
}

inline void SearchPaths::addAppPaths(bool recursive) {
	char cwd[4096];
	if(getcwd(cwd, sizeof(cwd))){
		addSearchPath(cwd, recursive);
	}
}

inline void SearchPaths::addSearchPath(const std::string& src, bool recursive) {
	std::string path=conformPath(src);

	// check for duplicates
	std::list<searchpath>::iterator iter = mSearchPaths.begin();
	while (iter != mSearchPaths.end()) {
		//printf("path %s\n", iter->first.c_str());
		if (path == iter->first) {
			return;
		}
		iter++;
	}
	printf("adding path %s\n", path.data());
	mSearchPaths.push_front(searchpath(path, recursive));
}

inline bool SearchPaths::fileExists(const std::string& path, const std::string& name) {
	struct stat stFileInfo;
	std::string filename(path+name);
	return (stat((path + name).c_str(),&stFileInfo) == 0);
}

} // al::

#endif

<commit_msg>file update<commit_after>#ifndef INCLUDE_AL_FILE_HPP
#define INCLUDE_AL_FILE_HPP

#include <unistd.h>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <list>

#include "allocore/system/al_Config.h"

#ifdef AL_WIN32
	#define AL_FILE_DELIMITER '\\'
#else
	#define AL_FILE_DELIMITER '/'
#endif

#define AL_PATH_MAX (4096)

namespace al{

/// Strips a qualified path to a file (src) into a path to the containing folder (dst)
void path2dir(char* dst, const char* src);

/// a pair of path (folder/directory) and filename
class FilePath {
public:
	FilePath() {};
	FilePath(std::string file, std::string path = "/") : mPath(path), mFile(file) {}

	const std::string& file() const { return mFile; }
	const std::string& path() const { return mPath; }

	std::string filepath() const { return path()+file(); }

	FilePath& file(const std::string& v) { mFile=v; return *this; }
	FilePath& path(const std::string& v) { mPath=v; return *this; }

protected:
	std::string mPath;
	std::string mFile;
};

/// A handy way to manage several possible search paths
class SearchPaths {
public:
	SearchPaths() {}
	SearchPaths(int argc, char * const argv[], bool recursive=true) { addAppPaths(argc,argv,recursive); }
	~SearchPaths() {}

	/// find a file in the searchpaths
	/// returns true if file found, and fills result with corresponding path & filename
	/// returns false if file not found
	FilePath find(const std::string& filename);

	/// add a path to search in; recursive searching is optional
	void addSearchPath(const std::string& path, bool recursive = true);

	/// adds best estimate of application launch paths (cwd etc.)
	/// can pass in argv from the main() function if desired.
	void addAppPaths(int argc, char * const argv[], bool recursive = true);
	void addAppPaths(bool recursive = true);

	const std::string& appPath() const { return mAppPath; }

	/// todo?
	//void addResourcePath();

	// strips trailing filename from a path; e.g. /usr/bin/man -> /usr/bin/
	static std::string stripFileName(const std::string& src);
	// ensure path ends with the proper delimiter
	static std::string conformPath(const std::string& src);
	// does a file at the given filepath exist?
	static bool fileExists(const std::string& name, const std::string& path);

protected:

	typedef std::pair<std::string, bool> searchpath;
	std::list<searchpath> mSearchPaths;

	std::string mAppPath;

};

/// File
class File{
public:

	/// @param[in] path		path of file
	/// @param[in] mode		i/o mode w, r, wb, rb
	/// @param[in] open		whether to open the file
	File(const std::string& path, const std::string& mode="r", bool open=false);
	File(const FilePath& path, const std::string& mode="r", bool open=false);

	~File();

	void close();	///< Close file
	bool open();	///< Open file with specified i/o mode

	File& mode(const std::string& v){ mMode=v; return *this; }
	File& path(const std::string& v){ mPath=v; return *this; }

	/// Write memory elements to file
	int write(const std::string& v){ return fwrite(v.data(), 1, v.length(), mFP); }
	int write(const void * v, int size, int items=1){ return fwrite(v, size, items, mFP); }

	/// Quick and dirty write memory to file
	static int write(const std::string& path, const void * v, int size, int items=1);

	/// Returns character string of file contents (read mode only)
	const char * readAll();

	/// Returns whether file is open
	bool opened() const { return 0 != mFP; }

	/// Returns file i/o mode string
	const std::string& mode() const { return mMode; }

	/// Returns path string
	const std::string& path() const { return mPath; }

	/// Returns size (in bytes) of file contents
	int size() const { return mSizeBytes; }

	/// Returns whether file exists
	static bool exists(const std::string& path);

	/// Return modification time of file (or 0 on failure)
	/// as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec modified();
	/// Return last access time of file (or 0 on failure)
	/// as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec accessed();
	/// Return creation time of file (or 0 on failure)
	/// as number of seconds since 00:00:00 january 1, 1970 UTC
	al_sec created();

	/// Return size file (or 0 on failure)
	size_t size();
	/// Return space used on disk of file (or 0 on failure)
	size_t storage();

	FILE * filePointer() { return mFP; }

	static al_sec modified(std::string path) { File f(path); return f.modified(); }
	static al_sec accessed(std::string path) { File f(path); return f.accessed(); }
	static al_sec created(std::string path) { File f(path); return f.created(); }
	static size_t size(std::string path) { File f(path); return f.size(); }
	static size_t storage(std::string path) { File f(path); return f.storage(); }

protected:
	class Impl; Impl * mImpl;

	std::string mPath;
	std::string mMode;
	char * mContent;
	int mSizeBytes;
	FILE * mFP;

	void freeContent();
	void allocContent(int n);
	void getSize();
};

//// INLINE IMPLEMENTATION ////

inline std::string SearchPaths::stripFileName(const std::string& src) {
	std::string filepath(src);
	size_t pos = filepath.find_last_of(AL_FILE_DELIMITER);
	if (pos !=std::string::npos) {
		filepath.erase(pos+1);
	}
	return filepath;
}

inline std::string SearchPaths::conformPath(const std::string& src) {
	std::string path(src);
	// paths should end with a delimiter:
	if (path[path.size()-1] != AL_FILE_DELIMITER) {
		path += AL_FILE_DELIMITER;
	}
	return path;
}

inline void SearchPaths::addAppPaths(int argc, char * const argv[], bool recursive) {
	addAppPaths(recursive);
	if (argc > 0) {
		//char path[4096];
		std::string filepath = stripFileName(argv[0]);
		mAppPath = filepath;
		addSearchPath(filepath, recursive);
	}
}

inline void SearchPaths::addAppPaths(bool recursive) {
	char cwd[4096];
	if(getcwd(cwd, sizeof(cwd))){
		addSearchPath(cwd, recursive);
	}
}

inline void SearchPaths::addSearchPath(const std::string& src, bool recursive) {
	std::string path=conformPath(src);

	// check for duplicates
	std::list<searchpath>::iterator iter = mSearchPaths.begin();
	while (iter != mSearchPaths.end()) {
		//printf("path %s\n", iter->first.c_str());
		if (path == iter->first) {
			return;
		}
		iter++;
	}
	printf("adding path %s\n", path.data());
	mSearchPaths.push_front(searchpath(path, recursive));
}

inline bool SearchPaths::fileExists(const std::string& path, const std::string& name) {
	struct stat stFileInfo;
	std::string filename(path+name);
	return (stat((path + name).c_str(),&stFileInfo) == 0);
}

} // al::

#endif

<|endoftext|>


<commit_before>#ifndef ECL_SPLAY_TREE
#define ECL_SPLAY_TREE

#include <ecl/tree/binary_tree_base.hpp>

namespace ecl
{

namespace tree
{

template
<
      typename K
    , typename V
    , template <typename> class Compare = std::less
>
struct splay_node : public node_base<K, V, Compare, ecl::tree::splay_node>
{
    // Full namespace is workaround for clang bug
    // about template-template parameters
    //
    // http://stackoverflow.com/questions/17687459/clang-not-accepting-use-of-template-template-parameter-when-using-crtp
    using base = node_base<K, V, Compare, ecl::tree::splay_node>;

    using node_base<K, V, Compare, ecl::tree::splay_node>::node_base;
};

template
<
      typename K
    , typename V
    , template <typename> class Compare = std::less
>
class splay_tree : public binary_tree_base<K, V, Compare, splay_node>
{
    using base = binary_tree_base<K, V, Compare, splay_node>;

   using base::m_header;
public:
    using typename base::node_t;

    using typename base::pointer;
    using typename base::const_pointer;

    using typename base::key_type;
    using typename base::value_type;

    using typename base::key_compare;

    using typename base::erase_return;

    using typename base::iterator;
    using typename base::const_iterator;
    using typename base::reverse_iterator;
    using typename base::const_reverse_iterator;

    using base::root;
    using base::count;
    using base::empty;

    using base::begin;
    using base::end;
    using base::cbegin;
    using base::cend;
    using base::rbegin;
    using base::rend;
    using base::crbegin;
    using base::crend;

    iterator insert(pointer n)                                          noexcept
    {
        iterator result = this->base::insert(n);

        splay(n);

        return result;
    }

    pointer erase(const key_type& k)                                    noexcept
    {
        if(empty())
        {
            return nullptr;
        }

        pointer to_erase = root()->find(k);
        if(nullptr == to_erase)
        {
            return nullptr;
        }

        erase_return ret = this->base::erase_internal(to_erase);

        if(to_erase->have_parent())
        {
            splay(to_erase->parent);
        }

        return ret.first;
    }

    iterator find(const key_type& k)                                    noexcept
    {
        pointer p = m_header.parent->find(k);
        if(nullptr == p)
        {
            return end();
        }

        splay(p);

        return iterator(p, pointer(&m_header));
    }

private:
    // void join(pointer s, pointer t)                                     noexcept
    // {
    //     splay(s->most_right());
    //     link_as_right(t, s);
    // }

    void splay(pointer n)                                               noexcept
    {
        pointer x = n;
        pointer p = n->parent;

        if(root() == x)
        {
            return;
        }

        bool x_p_is_ll    = p->is_left()  && x->is_left();
        bool x_p_is_rr    = p->is_right() && x->is_right();
        bool x_p_is_ll_rr = x_p_is_ll || x_p_is_rr;
        bool x_p_is_lr_rl = !x_p_is_ll_rr;
        bool p_is_root    = root() == p;

        if(p_is_root)
        {
            zig(x, p);
        }

        if( !p_is_root && x_p_is_ll_rr)
        {
            zig_zig(x, p);
        }

        if( !p_is_root && x_p_is_lr_rl)
        {
            zig_zag(x, p);
        }
    }

    void zig(pointer x, pointer p)                                      noexcept
    {
        if(x->is_left())
        {
            this->rotate_right(p);
        }
        else
        {
            this->rotate_left(p);
        }
    }

    void zig_zig(pointer x, pointer p)                                  noexcept
    {
        if(x->is_left())
        {
            this->rotate_right(p->parent);
            this->rotate_right(p);
        }
        else
        {
            this->rotate_left(p->parent);
            this->rotate_left(p);
        }
    }

    void zig_zag(pointer, pointer p)                                    noexcept
    {
        pointer g = p->parent;

        if(p->is_left())
        {
            this->rotate_left(p);
            this->rotate_right(g);
        }
        else
        {
            this->rotate_right(p);
            this->rotate_left(g);
        }
    }
};

} // namespace tree

} // namespace ecl

#endif // ECL_SPLAY_TREE
<commit_msg>Insert existing fix.<commit_after>#ifndef ECL_SPLAY_TREE
#define ECL_SPLAY_TREE

#include <ecl/tree/binary_tree_base.hpp>

namespace ecl
{

namespace tree
{

template
<
      typename K
    , typename V
    , template <typename> class Compare = std::less
>
struct splay_node : public node_base<K, V, Compare, ecl::tree::splay_node>
{
    // Full namespace is workaround for clang bug
    // about template-template parameters
    //
    // http://stackoverflow.com/questions/17687459/clang-not-accepting-use-of-template-template-parameter-when-using-crtp
    using base = node_base<K, V, Compare, ecl::tree::splay_node>;

    using node_base<K, V, Compare, ecl::tree::splay_node>::node_base;
};

template
<
      typename K
    , typename V
    , template <typename> class Compare = std::less
>
class splay_tree : public binary_tree_base<K, V, Compare, splay_node>
{
    using base = binary_tree_base<K, V, Compare, splay_node>;

   using base::m_header;
public:
    using typename base::node_t;

    using typename base::pointer;
    using typename base::const_pointer;

    using typename base::key_type;
    using typename base::value_type;

    using typename base::key_compare;

    using typename base::erase_return;

    using typename base::iterator;
    using typename base::const_iterator;
    using typename base::reverse_iterator;
    using typename base::const_reverse_iterator;

    using base::root;
    using base::count;
    using base::empty;

    using base::begin;
    using base::end;
    using base::cbegin;
    using base::cend;
    using base::rbegin;
    using base::rend;
    using base::crbegin;
    using base::crend;

    iterator insert(pointer n)                                          noexcept
    {
        auto result        = this->base::insert_internal(n);
        pointer inserted_n = result.second;
        iterator it        = result.first;

        // Node with such key is existing.
        if(n != inserted_n)
        {
            return it;
        }

        splay(inserted_n);

        return it;
    }

    pointer erase(const key_type& k)                                    noexcept
    {
        if(empty())
        {
            return nullptr;
        }

        pointer to_erase = root()->find(k);
        if(nullptr == to_erase)
        {
            return nullptr;
        }

        erase_return ret = this->base::erase_internal(to_erase);

        if(to_erase->have_parent())
        {
            splay(to_erase->parent);
        }

        return ret.first;
    }

    iterator find(const key_type& k)                                    noexcept
    {
        pointer p = m_header.parent->find(k);
        if(nullptr == p)
        {
            return end();
        }

        splay(p);

        return iterator(p, pointer(&m_header));
    }

private:
    // void join(pointer s, pointer t)                                     noexcept
    // {
    //     splay(s->most_right());
    //     link_as_right(t, s);
    // }

    void splay(pointer n)                                               noexcept
    {
        pointer x = n;
        pointer p = n->parent;

        if(root() == x)
        {
            return;
        }

        bool x_p_is_ll    = p->is_left()  && x->is_left();
        bool x_p_is_rr    = p->is_right() && x->is_right();
        bool x_p_is_ll_rr = x_p_is_ll || x_p_is_rr;
        bool x_p_is_lr_rl = !x_p_is_ll_rr;
        bool p_is_root    = root() == p;

        if(p_is_root)
        {
            zig(x, p);
        }

        if( !p_is_root && x_p_is_ll_rr)
        {
            zig_zig(x, p);
        }

        if( !p_is_root && x_p_is_lr_rl)
        {
            zig_zag(x, p);
        }
    }

    void zig(pointer x, pointer p)                                      noexcept
    {
        if(x->is_left())
        {
            this->rotate_right(p);
        }
        else
        {
            this->rotate_left(p);
        }
    }

    void zig_zig(pointer x, pointer p)                                  noexcept
    {
        if(x->is_left())
        {
            this->rotate_right(p->parent);
            this->rotate_right(p);
        }
        else
        {
            this->rotate_left(p->parent);
            this->rotate_left(p);
        }
    }

    void zig_zag(pointer, pointer p)                                    noexcept
    {
        pointer g = p->parent;

        if(p->is_left())
        {
            this->rotate_left(p);
            this->rotate_right(g);
        }
        else
        {
            this->rotate_right(p);
            this->rotate_left(g);
        }
    }
};

} // namespace tree

} // namespace ecl

#endif // ECL_SPLAY_TREE
<|endoftext|>


<commit_before>#ifndef GRL_KUKA_DRIVER
#define GRL_KUKA_DRIVER

#include <tuple>
#include <memory>
#include <thread>
#include <boost/asio.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/exception/all.hpp>
#include <boost/config.hpp>

#include <boost/make_shared.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/transform.hpp>

#include <boost/make_shared.hpp>

#ifdef BOOST_NO_CXX11_ATOMIC_SMART_PTR
#include <boost/thread.hpp>
#endif

#include "Kuka.hpp"
#include "grl/kuka/KukaJAVAdriver.hpp"
#include "grl/kuka/KukaFRIdriver.hpp"
#include "grl/tags.hpp"

namespace grl { namespace robot { namespace arm {

    ///
    ///
    /// @brief Kuka LBR iiwa Primary Multi Mode Driver, supports communication over FRI and JAVA interfaces
    ///
    /// @todo enable commanding and monitoring to be independently configured for both FRI and JAVA interface.
    ///
    class KukaDriver : public std::enable_shared_from_this<KukaDriver> {
    public:

      enum ParamIndex {
        RobotName,
        LocalZMQAddress,
        RemoteZMQAddress,
        LocalHostKukaKoniUDPAddress,
        LocalHostKukaKoniUDPPort,
        RemoteHostKukaKoniUDPAddress,
        RemoteHostKukaKoniUDPPort,
        KukaCommandMode,
        KukaMonitorMode
      };

      /// @todo allow default params
      typedef std::tuple<
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string
          > Params;

      static const Params defaultParams(){
        return std::make_tuple(
            "Robotiiwa"               , // RobotName,
            "tcp://0.0.0.0:30010"     , // LocalZMQAddress
            "tcp://172.31.1.147:30010", // RemoteZMQAddress
            "192.170.10.100"          , // LocalHostKukaKoniUDPAddress,
            "30200"                   , // LocalHostKukaKoniUDPPort,
            "192.170.10.2"            , // RemoteHostKukaKoniUDPAddress,
            "30200"                   , // RemoteHostKukaKoniUDPPort
            "JAVA"                    , // KukaCommandMode (options are FRI, JAVA)
            "JAVA"                      // KukaMonitorMode (options are FRI, JAVA)
            );
      }

      KukaDriver(Params params = defaultParams())
        : params_(params)
      {}

      void construct(){ construct(params_);}

      bool destruct(){ return JAVAdriverP_->destruct(); }

      /// @todo create a function that calls simGetObjectHandle and throws an exception when it fails
      /// @warning getting the ik group is optional, so it does not throw an exception
      void construct(Params params) {

        params_ = params;
        // keep driver threads from exiting immediately after creation, because they have work to do!
        //device_driver_workP_.reset(new boost::asio::io_service::work(device_driver_io_service));

        /// @todo figure out how to re-enable when .so isn't loaded
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI"))
            || boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
        {
          FRIdriverP_.reset(
              new grl::robot::arm::KukaFRIdriver(
                  //device_driver_io_service,
                  std::make_tuple(
                      std::string(std::get<LocalHostKukaKoniUDPAddress >        (params)),
                      std::string(std::get<LocalHostKukaKoniUDPPort    >        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPAddress>        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPPort   >        (params)),
                      ms_per_tick ,
                      grl::robot::arm::KukaFRIClientDataDriver::run_automatically
                      )
                  )

              );
              FRIdriverP_->construct();
        }

        /// @todo implement reading configuration in both FRI and JAVA mode from JAVA interface
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA"))){
        try {
          JAVAdriverP_ = boost::make_shared<KukaJAVAdriver>(params_);
          JAVAdriverP_->construct();

          // start up the driver thread
          /// @todo perhaps allow user to control this?
          //driver_threadP.reset(new std::thread([&]{ device_driver_io_service.run(); }));
        } catch( boost::exception &e) {
          e << errmsg_info("KukaDriver: Unable to connect to ZeroMQ Socket from " +
                           std::get<LocalZMQAddress>             (params_) + " to " +
                           std::get<RemoteZMQAddress>            (params_));
          throw;
        }

        }
      }

      const Params & getParams(){
        return params_;
      }

      ~KukaDriver(){
        device_driver_workP_.reset();

        if(driver_threadP){
          device_driver_io_service.stop();
          driver_threadP->join();
        }
      }

     /**
      * spin once
      *
      */
      bool run_one(){

        // @todo CHECK FOR REAL DATA BEFORE SENDING COMMANDS
        //if(!m_haveReceivedRealDataCount) return;
        bool haveNewData = false;

        /// @todo make this handled by template driver implementations/extensions

        if(JAVAdriverP_.get() != nullptr)
        {
          std::cout << "commandedpos:" << armState_.commandedPosition;
          /////////////////////////////////////////
          // Client sends to server asynchronously!
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;

          haveNewData = JAVAdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->get(armState_);
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;
        }

        if(FRIdriverP_.get() != nullptr)
        {
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }

          haveNewData = FRIdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->get(armState_);
          }
        }

        return haveNewData;
      }

   /// set the mode of the arm. Examples: Teach or MoveArmJointServo
   /// @see grl::flatbuffer::ArmState in ArmControlState_generated.h
   void set(const flatbuffer::ArmState & armControlMode)
   {
        if(JAVAdriverP_)
        {
            JAVAdriverP_->set(armControlMode);
        }
   }

     /**
      * \brief Set the joint positions for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param range Array with the new joint positions (in radians)
      * @param tag identifier object indicating that revolute joint angle commands should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_angle_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedPosition));
       boost::copy(range, std::back_inserter(armState_.commandedPosition_goal));

          std::cout << "set commandedpos:" << armState_.commandedPosition;
    }

     /**
      * \brief Set the applied joint torques for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be joint impedance control mode. The
      * Client Command Mode has to be torque.
      *
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param torques Array with the applied torque values (in Nm)
      * @param tag identifier object indicating that the torqe value command should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_torque_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedTorque));
    }

     /**
      * \brief Set the applied wrench vector of the current interpolation step.
      *
      * The wrench vector consists of:
      * [F_x, F_y, F_z, tau_A, tau_B, tau_C]
      *
      * F ... forces (in N) applied along the Cartesian axes of the
      * currently used motion center.
      * tau ... torques (in Nm) applied along the orientation angles
      * (Euler angles A, B, C) of the currently used motion center.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be Cartesian impedance control mode. The
      * Client Command Mode has to be wrench.
      *
      * @param state object storing the command data that will be sent to the physical device
      * @param range wrench Applied Cartesian wrench vector, in x, y, z, roll, pitch, yaw force measurments.
      * @param tag identifier object indicating that the wrench value command should be modified
      *
      * @todo perhaps support some specific more useful data layouts
      */
   template<typename Range>
   void set(Range&& range, grl::cartesian_wrench_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       std::copy(range,armState_.commandedCartesianWrenchFeedForward);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_angle_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.position,output);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       boost::copy(armState.torque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_external_open_chain_state_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState.externalTorque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::cartesian_external_force_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState.externalForce,output);

    }

      volatile std::size_t m_haveReceivedRealDataCount = 0;
      volatile std::size_t m_attemptedCommunicationCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveFailureCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveSuccessCount = 0;

      boost::asio::io_service device_driver_io_service;
      std::unique_ptr<boost::asio::io_service::work> device_driver_workP_;
      std::unique_ptr<std::thread> driver_threadP;

    private:

      /// @todo read ms_per_tick from JAVA interface
      std::size_t ms_per_tick = 1;
      KukaState armState_;

      boost::mutex jt_mutex;
      boost::shared_ptr<KukaFRIdriver> FRIdriverP_;
      boost::shared_ptr<KukaJAVAdriver> JAVAdriverP_;

      Params params_;

    };

}}}// namespace grl::robot::arm

#endif
<commit_msg>fix minor KukaDriver compiler errors from merge<commit_after>#ifndef GRL_KUKA_DRIVER
#define GRL_KUKA_DRIVER

#include <tuple>
#include <memory>
#include <thread>
#include <boost/asio.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/exception/all.hpp>
#include <boost/config.hpp>

#include <boost/make_shared.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/transform.hpp>

#include <boost/make_shared.hpp>

#ifdef BOOST_NO_CXX11_ATOMIC_SMART_PTR
#include <boost/thread.hpp>
#endif

#include "Kuka.hpp"
#include "grl/kuka/KukaJAVAdriver.hpp"
#include "grl/kuka/KukaFRIdriver.hpp"
#include "grl/tags.hpp"

namespace grl { namespace robot { namespace arm {

    ///
    ///
    /// @brief Kuka LBR iiwa Primary Multi Mode Driver, supports communication over FRI and JAVA interfaces
    ///
    /// @todo enable commanding and monitoring to be independently configured for both FRI and JAVA interface.
    ///
    class KukaDriver : public std::enable_shared_from_this<KukaDriver> {
    public:

      enum ParamIndex {
        RobotName,
        LocalZMQAddress,
        RemoteZMQAddress,
        LocalHostKukaKoniUDPAddress,
        LocalHostKukaKoniUDPPort,
        RemoteHostKukaKoniUDPAddress,
        RemoteHostKukaKoniUDPPort,
        KukaCommandMode,
        KukaMonitorMode
      };

      /// @todo allow default params
      typedef std::tuple<
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string
          > Params;

      static const Params defaultParams(){
        return std::make_tuple(
            "Robotiiwa"               , // RobotName,
            "tcp://0.0.0.0:30010"     , // LocalZMQAddress
            "tcp://172.31.1.147:30010", // RemoteZMQAddress
            "192.170.10.100"          , // LocalHostKukaKoniUDPAddress,
            "30200"                   , // LocalHostKukaKoniUDPPort,
            "192.170.10.2"            , // RemoteHostKukaKoniUDPAddress,
            "30200"                   , // RemoteHostKukaKoniUDPPort
            "JAVA"                    , // KukaCommandMode (options are FRI, JAVA)
            "JAVA"                      // KukaMonitorMode (options are FRI, JAVA)
            );
      }

      KukaDriver(Params params = defaultParams())
        : params_(params)
      {}

      void construct(){ construct(params_);}

      bool destruct(){ return JAVAdriverP_->destruct(); }

      /// @todo create a function that calls simGetObjectHandle and throws an exception when it fails
      /// @warning getting the ik group is optional, so it does not throw an exception
      void construct(Params params) {

        params_ = params;
        // keep driver threads from exiting immediately after creation, because they have work to do!
        //device_driver_workP_.reset(new boost::asio::io_service::work(device_driver_io_service));

        /// @todo figure out how to re-enable when .so isn't loaded
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI"))
            || boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
        {
          FRIdriverP_.reset(
              new grl::robot::arm::KukaFRIdriver(
                  //device_driver_io_service,
                  std::make_tuple(
                      std::string(std::get<LocalHostKukaKoniUDPAddress >        (params)),
                      std::string(std::get<LocalHostKukaKoniUDPPort    >        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPAddress>        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPPort   >        (params)),
                      ms_per_tick ,
                      grl::robot::arm::KukaFRIClientDataDriver::run_automatically
                      )
                  )

              );
              FRIdriverP_->construct();
        }

        /// @todo implement reading configuration in both FRI and JAVA mode from JAVA interface
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA"))){
        try {
          JAVAdriverP_ = boost::make_shared<KukaJAVAdriver>(params_);
          JAVAdriverP_->construct();

          // start up the driver thread
          /// @todo perhaps allow user to control this?
          //driver_threadP.reset(new std::thread([&]{ device_driver_io_service.run(); }));
        } catch( boost::exception &e) {
          e << errmsg_info("KukaDriver: Unable to connect to ZeroMQ Socket from " +
                           std::get<LocalZMQAddress>             (params_) + " to " +
                           std::get<RemoteZMQAddress>            (params_));
          throw;
        }

        }
      }

      const Params & getParams(){
        return params_;
      }

      ~KukaDriver(){
        device_driver_workP_.reset();

        if(driver_threadP){
          device_driver_io_service.stop();
          driver_threadP->join();
        }
      }

     /**
      * spin once
      *
      */
      bool run_one(){

        // @todo CHECK FOR REAL DATA BEFORE SENDING COMMANDS
        //if(!m_haveReceivedRealDataCount) return;
        bool haveNewData = false;

        /// @todo make this handled by template driver implementations/extensions

        if(JAVAdriverP_.get() != nullptr)
        {
          std::cout << "commandedpos:" << armState_.commandedPosition;
          /////////////////////////////////////////
          // Client sends to server asynchronously!
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;

          haveNewData = JAVAdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->get(armState_);
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;
        }

        if(FRIdriverP_.get() != nullptr)
        {
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }

          haveNewData = FRIdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->get(armState_);
          }
        }

        return haveNewData;
      }

   /// set the mode of the arm. Examples: Teach or MoveArmJointServo
   /// @see grl::flatbuffer::ArmState in ArmControlState_generated.h
   void set(const flatbuffer::ArmState & armControlMode)
   {
        if(JAVAdriverP_)
        {
            JAVAdriverP_->set(armControlMode);
        }
   }

     /**
      * \brief Set the joint positions for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param range Array with the new joint positions (in radians)
      * @param tag identifier object indicating that revolute joint angle commands should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_angle_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedPosition));
       boost::copy(range, std::back_inserter(armState_.commandedPosition_goal));

          std::cout << "set commandedpos:" << armState_.commandedPosition;
    }

     /**
      * \brief Set the applied joint torques for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be joint impedance control mode. The
      * Client Command Mode has to be torque.
      *
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param torques Array with the applied torque values (in Nm)
      * @param tag identifier object indicating that the torqe value command should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_torque_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedTorque));
    }

     /**
      * \brief Set the applied wrench vector of the current interpolation step.
      *
      * The wrench vector consists of:
      * [F_x, F_y, F_z, tau_A, tau_B, tau_C]
      *
      * F ... forces (in N) applied along the Cartesian axes of the
      * currently used motion center.
      * tau ... torques (in Nm) applied along the orientation angles
      * (Euler angles A, B, C) of the currently used motion center.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be Cartesian impedance control mode. The
      * Client Command Mode has to be wrench.
      *
      * @param state object storing the command data that will be sent to the physical device
      * @param range wrench Applied Cartesian wrench vector, in x, y, z, roll, pitch, yaw force measurments.
      * @param tag identifier object indicating that the wrench value command should be modified
      *
      * @todo perhaps support some specific more useful data layouts
      */
   template<typename Range>
   void set(Range&& range, grl::cartesian_wrench_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       std::copy(range,armState_.commandedCartesianWrenchFeedForward);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_angle_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.position,output);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       boost::copy(armState_.torque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_external_open_chain_state_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.externalTorque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::cartesian_external_force_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.externalForce,output);

    }

      volatile std::size_t m_haveReceivedRealDataCount = 0;
      volatile std::size_t m_attemptedCommunicationCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveFailureCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveSuccessCount = 0;

      boost::asio::io_service device_driver_io_service;
      std::unique_ptr<boost::asio::io_service::work> device_driver_workP_;
      std::unique_ptr<std::thread> driver_threadP;

    private:

      /// @todo read ms_per_tick from JAVA interface
      std::size_t ms_per_tick = 1;
      KukaState armState_;

      boost::mutex jt_mutex;
      boost::shared_ptr<KukaFRIdriver> FRIdriverP_;
      boost::shared_ptr<KukaJAVAdriver> JAVAdriverP_;

      Params params_;

    };

}}}// namespace grl::robot::arm

#endif
<|endoftext|>


<commit_before>#ifndef LILYPAD_CHOLESKY_QR_HPP
#define LILYPAD_CHOLESKY_QR_HPP

#include <mpi.h>
#include <complex>
#include <iostream>
#include "lilypad/multivector.hpp"
#include "lilypad/localmatrix.hpp"
#include "lilypad/mkl_wrapper.hpp"

using cmplx_z = std::complex<double>;

namespace lilypad {
    // TODO: current: z only
    template <typename T>
    void cholesky_QR(const MultiVector<T>& A, MultiVector<T>& Q, LocalMatrix<T>& R)
    {
        double t_start = MPI_Wtime();
        // TODO: input check
        int M = A.local_rows();
        int L = R.rows();
        const std::complex<double> z_zero(0.0, 0.0), z_one(1.0, 0.0);

        // copy A to Q
        Q = A;
        double t_copy = MPI_Wtime();

        // local GEMM to R
        wrapper::gemm('C', 'N', L, L, M, z_one, A.ptr(), A.ld(), Q.ptr(), Q.ld(),
                z_zero, R.ptr(), R.ld());
        double t_gemm = MPI_Wtime();
        if (Q.comm().is_root())
        {
            std::cout << "R(after GEMM)" << std::endl;
            R.dump();
        }

        // Allreduce R
        Q.comm().Allreduce_sum(R);
        double t_reduce = MPI_Wtime();
        if (Q.comm().is_root())
        {
            std::cout << "R(after Reduce)" << std::endl;
            R.dump();
        }

        // cholesky factorization of R
        wrapper::potrf('U', L, R, R.ld());
        double t_chol = MPI_Wtime();

        // compute R^{-1}
        wrapper::trtri('U', 'N', L, R, R.ld());
        LocalMatrix<T> R_(R);
        R_.erase_lower_diag();
        R.erase_lower_diag();
        double t_inv = MPI_Wtime();
        if (Q.comm().is_root())
        {
            std::cout << "R(calculated)" << std::endl;
            R.dump();
            std::cout << "R^-1(calculated)" << std::endl;
            R_.dump();
        }

        // Q = A*R^{-1}
        wrapper::gemm('N', 'N', M, L, L, z_one, A.ptr(), A.ld(), R_.ptr(), R_.ld(),
                z_zero, Q.ptr(), Q.ld());
        double t_smgemm = MPI_Wtime();
    }

    // check
    template <typename T>
    void check_cholesky_QR(const MultiVector<T>& A, const MultiVector<T>& Q, const LocalMatrix<T>& R)
    {
        // TODO: input check
        int M = A.local_rows();
        int L = R.rows();
        const std::complex<double> z_zero(0.0, 0.0), z_one(1.0, 0.0);

        // tmp <- Q*R
        std::cout << "test1" << std::endl;
        MultiVector<T> tmp(A);
        wrapper::gemm('N', 'N', M, L, L, z_one, Q.ptr(), Q.ld(), R.ptr(), R.ld(),
                z_zero, tmp.ptr(), tmp.ld());

        // tmp -= A
        std::cout << "test2" << std::endl;
        tmp = tmp - A;

        std::cout << "test3" << std::endl;
        double norm = tmp.F_norm();
        if (A.comm().is_root())
            std::cout << "||Q*R - A||_F = " << std::scientific << norm << std::endl;
    }
}

#endif // LILYPAD_CHOLESKY_QR_HPP
<commit_msg>fixed inverse of R generation<commit_after>#ifndef LILYPAD_CHOLESKY_QR_HPP
#define LILYPAD_CHOLESKY_QR_HPP

#include <mpi.h>
#include <complex>
#include <iostream>
#include "lilypad/multivector.hpp"
#include "lilypad/localmatrix.hpp"
#include "lilypad/mkl_wrapper.hpp"

using cmplx_z = std::complex<double>;

namespace lilypad {
    // TODO: current: z only
    template <typename T>
    void cholesky_QR(const MultiVector<T>& A, MultiVector<T>& Q, LocalMatrix<T>& R)
    {
        double t_start = MPI_Wtime();
        // TODO: input check
        int M = A.local_rows();
        int L = R.rows();
        const std::complex<double> z_zero(0.0, 0.0), z_one(1.0, 0.0);

        // copy A to Q
        Q = A;
        double t_copy = MPI_Wtime();

        // local GEMM to R
        wrapper::gemm('C', 'N', L, L, M, z_one, A.ptr(), A.ld(), Q.ptr(), Q.ld(),
                z_zero, R.ptr(), R.ld());
        double t_gemm = MPI_Wtime();
        if (Q.comm().is_root())
        {
            std::cout << "R(after GEMM)" << std::endl;
            R.dump();
        }

        // Allreduce R
        Q.comm().Allreduce_sum(R);
        double t_reduce = MPI_Wtime();
        if (Q.comm().is_root())
        {
            std::cout << "R(after Reduce)" << std::endl;
            R.dump();
        }

        // cholesky factorization of R
        wrapper::potrf('U', L, R, R.ld());
        double t_chol = MPI_Wtime();

        // compute R^{-1}
        R.erase_lower_diag();
        LocalMatrix<T> R_(R);
        wrapper::trtri('U', 'N', L, R_, R_.ld());
        double t_inv = MPI_Wtime();
        if (Q.comm().is_root())
        {
            std::cout << "R(calculated)" << std::endl;
            R.dump();
            std::cout << "R^-1(calculated)" << std::endl;
            R_.dump();
        }

        // Q = A*R^{-1}
        wrapper::gemm('N', 'N', M, L, L, z_one, A.ptr(), A.ld(), R_.ptr(), R_.ld(),
                z_zero, Q.ptr(), Q.ld());
        double t_smgemm = MPI_Wtime();
    }

    // check
    template <typename T>
    void check_cholesky_QR(const MultiVector<T>& A, const MultiVector<T>& Q, const LocalMatrix<T>& R)
    {
        // TODO: input check
        int M = A.local_rows();
        int L = R.rows();
        const std::complex<double> z_zero(0.0, 0.0), z_one(1.0, 0.0);

        // tmp <- Q*R
        std::cout << "test1" << std::endl;
        MultiVector<T> tmp(A);
        wrapper::gemm('N', 'N', M, L, L, z_one, Q.ptr(), Q.ld(), R.ptr(), R.ld(),
                z_zero, tmp.ptr(), tmp.ld());

        // tmp -= A
        std::cout << "test2" << std::endl;
        tmp = tmp - A;

        std::cout << "test3" << std::endl;
        double norm = tmp.F_norm();
        if (A.comm().is_root())
            std::cout << "||Q*R - A||_F = " << std::scientific << norm << std::endl;
    }
}

#endif // LILYPAD_CHOLESKY_QR_HPP
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FILE_IO_HPP
#define MAPNIK_FILE_IO_HPP

// mapnik
#include <mapnik/utils.hpp>
#include <mapnik/make_unique.hpp>
#include <mapnik/util/noncopyable.hpp>
//#include <mapnik/config.hpp>

// stl
#include <cstdio>
#include <memory>
#include <string>

namespace mapnik { namespace util {

class file : public util::noncopyable
{
public:
    using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
    using data_type = std::unique_ptr<char[]>;

    explicit file(std::string const& filename)
#ifdef _WINDOWS
     : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
#else
     : file_(std::fopen(filename.c_str(),"rb"), std::fclose),
#endif
       size_(0)

     {
        if (file_)
        {
            std::fseek(file_.get(), 0, SEEK_END);
            size_ = std::ftell(file_.get());
            std::fseek(file_.get(), 0, SEEK_SET);
        }
     }

    inline bool open() const
    {
        return file_ ? true : false;
    }

    inline std::FILE * get() const
    {
        return file_.get();;
    }

    inline std::size_t size() const
    {
        return size_;
    }

    inline data_type data() const
    {
        if (!size_) return nullptr;
        std::fseek(file_.get(), 0, SEEK_SET);
        data_type buffer(new char[size_]);
        std::fread(buffer.get(), size_, 1, file_.get());
        return buffer;
    }
private:
    file_ptr file_;
    std::size_t size_;
};

}}

#endif // FILE_IO
<commit_msg>format - remove extra ;<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FILE_IO_HPP
#define MAPNIK_FILE_IO_HPP

// mapnik
#include <mapnik/utils.hpp>
#include <mapnik/make_unique.hpp>
#include <mapnik/util/noncopyable.hpp>
//#include <mapnik/config.hpp>

// stl
#include <cstdio>
#include <memory>
#include <string>

namespace mapnik { namespace util {

class file : public util::noncopyable
{
public:
    using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
    using data_type = std::unique_ptr<char[]>;

    explicit file(std::string const& filename)
#ifdef _WINDOWS
     : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
#else
     : file_(std::fopen(filename.c_str(),"rb"), std::fclose),
#endif
       size_(0)

     {
        if (file_)
        {
            std::fseek(file_.get(), 0, SEEK_END);
            size_ = std::ftell(file_.get());
            std::fseek(file_.get(), 0, SEEK_SET);
        }
     }

    inline bool open() const
    {
        return file_ ? true : false;
    }

    inline std::FILE * get() const
    {
        return file_.get();
    }

    inline std::size_t size() const
    {
        return size_;
    }

    inline data_type data() const
    {
        if (!size_) return nullptr;
        std::fseek(file_.get(), 0, SEEK_SET);
        data_type buffer(new char[size_]);
        std::fread(buffer.get(), size_, 1, file_.get());
        return buffer;
    }
private:
    file_ptr file_;
    std::size_t size_;
};

}}

#endif // FILE_IO
<|endoftext|>


<commit_before>#ifndef __MEMORY_WRAPPER_HPP__
#define __MEMORY_WRAPPER_HPP__

#ifdef _MSC_VER
//#include <ot_msvc.h>
#else
#include <ot_config.h>
#endif

//  C++ Defines.
#ifdef OT_USE_TR1
#undef OT_USE_TR1
#endif
#if !defined(_MSC_VER) && defined(OPENTXS_CXX03_TR1)
#define OT_USE_TR1
#endif

#ifndef OT_USE_TR1
#include <cinttypes>
#include <memory>
#else
#include <tr1/cinttypes>
#include <tr1/memory>
#endif

#endif

<commit_msg>change <ot_config.h> to ot_config.h<commit_after>#ifndef __MEMORY_WRAPPER_HPP__
#define __MEMORY_WRAPPER_HPP__

#ifdef _MSC_VER
//#include "ot_msvc.h"
#else
#include "ot_config.h"
#endif

//  C++ Defines.
#ifdef OT_USE_TR1
#undef OT_USE_TR1
#endif
#if !defined(_MSC_VER) && defined(OPENTXS_CXX03_TR1)
#define OT_USE_TR1
#endif

#ifndef OT_USE_TR1
#include <cinttypes>
#include <memory>
#else
#include <tr1/cinttypes>
#include <tr1/memory>
#endif

#endif

<|endoftext|>