<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**  - Nicolas CORNU <ncornu@aldebaran-robotics.com>
**
** Copyright (C) 2010, 2012 Aldebaran Robotics
*/

#include <vector>
#include <iostream>
#include <sstream>
#include <fstream>

#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

#include <qi/application.hpp>
#include <qimessaging/url.hpp>
#include <qimessaging/transportsocket.hpp>
#include <qimessaging/session.hpp>
#include <qiperf/dataperfsuite.hpp>
#include <qiperf/dataperf.hpp>

#include <qimessaging/servicedirectory.hpp>
#include <qimessaging/gateway.hpp>
#include <qitype/genericobject.hpp>
#include <qitype/genericobjectbuilder.hpp>

static int gLoopCount = 10000;
static bool valgrind = false;
static const int gThreadCount = 1;
static bool allInOne = false; // True if sd/server/client are in this process
static qi::Url serverUrl;
static qi::Url gateUrl;
static bool clientDone = false;
static bool serverReady = false;
static qi::DataPerfSuite* out;
static bool noGateway = false;
static int rstart = 0;
static int rend = 20;

static int run_client(qi::ObjectPtr obj);

std::string reply(const std::string &msg)
{
  return msg;
}

qi::Buffer replyBuf(const qi::Buffer& buf)
{
  return qi::Buffer(buf);
}

int main_local()
{
  qi::GenericObjectBuilder ob;
  ob.advertiseMethod("reply", &reply);
  ob.advertiseMethod("replyBuf", &replyBuf);
  qi::ObjectPtr obj(ob.object());
  run_client(obj);
  return 0;
}

int main_client(std::string QI_UNUSED(src))
{
  if (valgrind)
    qi::os::msleep(3000);
  qi::Session session;
  std::cout <<"Connection to sd... " << std::endl;
  qi::FutureSync<bool> isConnected = session.connect((allInOne && !noGateway)?gateUrl:serverUrl);
  isConnected.wait();
  if (!isConnected) {
    std::cerr << "Can't connect to " << session.url().str() << std::endl;
    return -1;
  }
  std::cout <<"Getting service... " << std::endl;
  qi::Future<qi::ObjectPtr> futobj = session.service("serviceTest");
  futobj.wait();
  qi::ObjectPtr obj = futobj.value();
  std::cerr <<"Done" << std::endl;
  if (!obj)
  {
    std::cerr << "cant get serviceTest " << futobj.error() << std::endl;
    return -1;
  }
  return run_client(obj);
}

int run_client(qi::ObjectPtr obj)
{
  qi::DataPerf dp;

  unsigned int numBytes = 1;
  for (int i = rstart; i < rend; i+=2)
  {
    std::ostringstream oss(std::ostringstream::out);
    oss << "transport_" << numBytes << "b";

    qi::Buffer buf;
    buf.reserve(numBytes);
    dp.start(oss.str(), gLoopCount, numBytes);
    unsigned long long latencySum = 0;
    for (int j = 0; j < gLoopCount; ++j)
    {
      static int id = 1;
      id++;
      qi::os::timeval tstart, tstop;
      qi::os::gettimeofday(&tstart);
      qi::Buffer result = obj->call<qi::Buffer>("replyBuf", buf);
      qi::os::gettimeofday(&tstop);
      latencySum += (tstop.tv_sec - tstart.tv_sec)* 1000000LL
        + (tstop.tv_usec - tstart.tv_usec);
      if (result.size() != buf.size())
        std::cout << "error content" << std::endl;
    }

    dp.stop();
    *out << dp;

    numBytes <<= 2;

    // We expect latency to be dp.meanInterval, but just to be sure also show
    // latency.
    std::cerr << "Average latency " << (latencySum / gLoopCount) << std::endl;
  }
  return 0;
}

void start_client(int count)
{
  boost::thread thd[100];

  assert(count < 100);

  for (int i = 0; i < count; ++i)
  {
    std::stringstream ss;
    ss << "remote" << i;
    std::cout << "starting thread: " << ss.str() << std::endl;
    thd[i] = boost::thread(boost::bind(&main_client, ss.str()));
  }

  for (int i = 0; i < count; ++i)
    thd[i].join();
  clientDone = true;
}

#include <qi/os.hpp>

int main_gateway(const qi::Url& serverUrl)
{
  qi::Gateway       gate;

  gate.attachToServiceDirectory(serverUrl);

  gateUrl = "tcp://0.0.0.0:0";
  gate.listen(gateUrl);
  gateUrl = gate.endpoints()[0];

  std::cout << "Gateway listening on " << gate.listenUrl().str() << std::endl;

  while (!clientDone)
    qi::os::sleep(60);

  return 0;
}

int main_server()
{
  qi::ServiceDirectory sd;
  if (!sd.listen(serverUrl)) {
    std::cerr << "Service directory can't listen on " << serverUrl.str() << "." << std::endl;
    return 1;
  }
  serverUrl = sd.endpoints()[0];
  std::cout << "Service Directory ready on " << serverUrl.str() << std::endl;

  qi::Session       session;
  qi::GenericObjectBuilder ob;
  ob.advertiseMethod("reply", &reply);
  ob.advertiseMethod("replyBuf", &replyBuf);
  qi::ObjectPtr obj(ob.object());

  session.connect(sd.endpoints()[0]);

  qi::Url sessionUrl("tcp://0.0.0.0:0");
  session.listen(sessionUrl);
  session.registerService("serviceTest", obj);
  std::cout << "serviceTest ready." << std::endl;
  serverReady = true;
  while (!clientDone)
    qi::os::sleep(60);
  return 0;
}

int main(int argc, char **argv)
{
  qi::Application app(argc, argv);

  std::string usage = "If no mode is specified, run client and server in same process\n";

  po::options_description desc(std::string("Usage:\n ")+argv[0]+"\n" + usage);
  desc.add_options()
    ("help,h", "Print this help.")
    ("all", po::value<std::string>()->default_value("tcp://0.0.0.0:0"), "(default) Run all in the same process.")
    ("client,c", po::value<std::string>(), "Run as a client (tcp://xxx.xxx.xxx.xxx:xxxxx).")
    ("server,s", po::value<std::string>()->implicit_value("tcp://0.0.0.0:0"), "Run as a server.")
    ("gateway", po::value<std::string>(), "Run as a gateway.")
    ("local", "Run in local.")
    ("thread", po::value<int>()->default_value(1, "1"),
     "Number of thread to launch for clients")
    ("valgrind", "Set low loopcount and wait for valgrind.")
    ("no-gateway", "Run without gateway.")
    ("rstart", po::value<int>()->default_value(0, "0"), "rstart")
    ("rend", po::value<int>()->default_value(20, "20"), "rend");

  desc.add(qi::details::getPerfOptions());

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

  if (vm.count("help")) {
    std::cout << desc << std::endl;
    return EXIT_SUCCESS;
  }

  if (vm.count("no-gateway"))
    noGateway = true;

  if (vm.count("valgrind")) {
    gLoopCount = 500;
    valgrind = true;
  }

  if (vm.count("client") + vm.count("server") + !vm["all"].defaulted() + vm.count("gateway") + vm.count("local") > 1) {
    std::cerr << desc << std::endl << "You must put at most one option between [all|client|server|gateway|local]" << std::endl;
    return EXIT_FAILURE;
  }

  if (!vm["thread"].defaulted() && (vm.count("server") != 0 || vm.count("gateway") != 0)) {
    std::cerr << "[thread] is useless with [server] or [gateway]" << std::endl;
  }

  rstart = vm["rstart"].as<int>();
  rend   = vm["rend"].as<int>();

  out = new qi::DataPerfSuite("qimessaging", "transport", qi::DataPerfSuite::OutputData_Period, vm["output"].as<std::string>());

  if (vm.count("client"))
  {
    serverUrl = qi::Url(vm["client"].as<std::string>());
    int threadc = vm["thread"].as<int>();
    start_client(threadc);
  } else if (vm.count("server")) {
    serverUrl = vm["server"].as<std::string>();
    return main_server();
  } else if (vm.count("gateway")) {
    serverUrl = vm["gateway"].as<std::string>();
    return main_gateway(serverUrl);
  } else if (vm.count("local")) {
    return main_local();
  } else {
    //start the server
    int threadc = vm["thread"].as<int>();
    serverUrl = vm["all"].as<std::string>();
    allInOne = true;
    boost::thread threadServer1(boost::bind(&main_server));
    do {
      qi::os::msleep(500); // give it time to listen
    } while (!serverReady); // be nice for valgrind
    if (!noGateway)
      boost::thread threadServer2(boost::bind(&main_gateway, serverUrl));
    qi::os::sleep(1);

    start_client(threadc);
  }

  delete out;

  return EXIT_SUCCESS;
}
<commit_msg>No more use listenUrl in perf_transport.<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**  - Nicolas CORNU <ncornu@aldebaran-robotics.com>
**
** Copyright (C) 2010, 2012 Aldebaran Robotics
*/

#include <vector>
#include <iostream>
#include <sstream>
#include <fstream>

#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

#include <qi/application.hpp>
#include <qimessaging/url.hpp>
#include <qimessaging/transportsocket.hpp>
#include <qimessaging/session.hpp>
#include <qiperf/dataperfsuite.hpp>
#include <qiperf/dataperf.hpp>

#include <qimessaging/servicedirectory.hpp>
#include <qimessaging/gateway.hpp>
#include <qitype/genericobject.hpp>
#include <qitype/genericobjectbuilder.hpp>

static int gLoopCount = 10000;
static bool valgrind = false;
static const int gThreadCount = 1;
static bool allInOne = false; // True if sd/server/client are in this process
static qi::Url serverUrl;
static qi::Url gateUrl;
static bool clientDone = false;
static bool serverReady = false;
static qi::DataPerfSuite* out;
static bool noGateway = false;
static int rstart = 0;
static int rend = 20;

static int run_client(qi::ObjectPtr obj);

std::string reply(const std::string &msg)
{
  return msg;
}

qi::Buffer replyBuf(const qi::Buffer& buf)
{
  return qi::Buffer(buf);
}

int main_local()
{
  qi::GenericObjectBuilder ob;
  ob.advertiseMethod("reply", &reply);
  ob.advertiseMethod("replyBuf", &replyBuf);
  qi::ObjectPtr obj(ob.object());
  run_client(obj);
  return 0;
}

int main_client(std::string QI_UNUSED(src))
{
  if (valgrind)
    qi::os::msleep(3000);
  qi::Session session;
  std::cout <<"Connection to sd... " << std::endl;
  qi::FutureSync<bool> isConnected = session.connect((allInOne && !noGateway)?gateUrl:serverUrl);
  isConnected.wait();
  if (!isConnected) {
    std::cerr << "Can't connect to " << session.url().str() << std::endl;
    return -1;
  }
  std::cout <<"Getting service... " << std::endl;
  qi::Future<qi::ObjectPtr> futobj = session.service("serviceTest");
  futobj.wait();
  qi::ObjectPtr obj = futobj.value();
  std::cerr <<"Done" << std::endl;
  if (!obj)
  {
    std::cerr << "cant get serviceTest " << futobj.error() << std::endl;
    return -1;
  }
  return run_client(obj);
}

int run_client(qi::ObjectPtr obj)
{
  qi::DataPerf dp;

  unsigned int numBytes = 1;
  for (int i = rstart; i < rend; i+=2)
  {
    std::ostringstream oss(std::ostringstream::out);
    oss << "transport_" << numBytes << "b";

    qi::Buffer buf;
    buf.reserve(numBytes);
    dp.start(oss.str(), gLoopCount, numBytes);
    unsigned long long latencySum = 0;
    for (int j = 0; j < gLoopCount; ++j)
    {
      qi::os::timeval tstart, tstop;
      qi::os::gettimeofday(&tstart);
      qi::Buffer result = obj->call<qi::Buffer>("replyBuf", buf);
      qi::os::gettimeofday(&tstop);
      latencySum += (tstop.tv_sec - tstart.tv_sec)* 1000000LL
        + (tstop.tv_usec - tstart.tv_usec);
      if (result.size() != buf.size())
        std::cout << "error content" << std::endl;
    }

    dp.stop();
    *out << dp;

    numBytes <<= 2;

    // We expect latency to be dp.meanInterval, but just to be sure also show
    // latency.
    std::cerr << "Average latency " << (latencySum / gLoopCount) << std::endl;
  }
  return 0;
}

void start_client(int count)
{
  boost::thread thd[100];

  assert(count < 100);

  for (int i = 0; i < count; ++i)
  {
    std::stringstream ss;
    ss << "remote" << i;
    std::cout << "starting thread: " << ss.str() << std::endl;
    thd[i] = boost::thread(boost::bind(&main_client, ss.str()));
  }

  for (int i = 0; i < count; ++i)
    thd[i].join();
  clientDone = true;
}

#include <qi/os.hpp>

int main_gateway(const qi::Url& serverUrl)
{
  qi::Gateway       gate;

  gate.attachToServiceDirectory(serverUrl);

  gateUrl = "tcp://0.0.0.0:0";
  gate.listen(gateUrl);
  gateUrl = gate.endpoints()[0];

  std::cout << "Gateway listening on " << gateUrl.str() << std::endl;

  while (!clientDone)
    qi::os::sleep(60);

  return 0;
}

int main_server()
{
  qi::ServiceDirectory sd;
  if (!sd.listen(serverUrl)) {
    std::cerr << "Service directory can't listen on " << serverUrl.str() << "." << std::endl;
    return 1;
  }
  serverUrl = sd.endpoints()[0];
  std::cout << "Service Directory ready on " << serverUrl.str() << std::endl;

  qi::Session       session;
  qi::GenericObjectBuilder ob;
  ob.advertiseMethod("reply", &reply);
  ob.advertiseMethod("replyBuf", &replyBuf);
  qi::ObjectPtr obj(ob.object());

  session.connect(sd.endpoints()[0]);

  qi::Url sessionUrl("tcp://0.0.0.0:0");
  session.listen(sessionUrl);
  session.registerService("serviceTest", obj);
  std::cout << "serviceTest ready." << std::endl;
  serverReady = true;
  while (!clientDone)
    qi::os::sleep(60);
  return 0;
}

int main(int argc, char **argv)
{
  qi::Application app(argc, argv);

  std::string usage = "If no mode is specified, run client and server in same process\n";

  po::options_description desc(std::string("Usage:\n ")+argv[0]+"\n" + usage);
  desc.add_options()
    ("help,h", "Print this help.")
    ("all", po::value<std::string>()->default_value("tcp://0.0.0.0:0"), "(default) Run all in the same process.")
    ("client,c", po::value<std::string>(), "Run as a client (tcp://xxx.xxx.xxx.xxx:xxxxx).")
    ("server,s", po::value<std::string>()->implicit_value("tcp://0.0.0.0:0"), "Run as a server.")
    ("gateway", po::value<std::string>(), "Run as a gateway.")
    ("local", "Run in local.")
    ("thread", po::value<int>()->default_value(1, "1"),
     "Number of thread to launch for clients")
    ("valgrind", "Set low loopcount and wait for valgrind.")
    ("no-gateway", "Run without gateway.")
    ("rstart", po::value<int>()->default_value(0, "0"), "rstart")
    ("rend", po::value<int>()->default_value(20, "20"), "rend");

  desc.add(qi::details::getPerfOptions());

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

  if (vm.count("help")) {
    std::cout << desc << std::endl;
    return EXIT_SUCCESS;
  }

  if (vm.count("no-gateway"))
    noGateway = true;

  if (vm.count("valgrind")) {
    gLoopCount = 500;
    valgrind = true;
  }

  if (vm.count("client") + vm.count("server") + !vm["all"].defaulted() + vm.count("gateway") + vm.count("local") > 1) {
    std::cerr << desc << std::endl << "You must put at most one option between [all|client|server|gateway|local]" << std::endl;
    return EXIT_FAILURE;
  }

  if (!vm["thread"].defaulted() && (vm.count("server") != 0 || vm.count("gateway") != 0)) {
    std::cerr << "[thread] is useless with [server] or [gateway]" << std::endl;
  }

  rstart = vm["rstart"].as<int>();
  rend   = vm["rend"].as<int>();

  out = new qi::DataPerfSuite("qimessaging", "transport", qi::DataPerfSuite::OutputData_Period, vm["output"].as<std::string>());

  if (vm.count("client"))
  {
    serverUrl = qi::Url(vm["client"].as<std::string>());
    int threadc = vm["thread"].as<int>();
    start_client(threadc);
  } else if (vm.count("server")) {
    serverUrl = vm["server"].as<std::string>();
    return main_server();
  } else if (vm.count("gateway")) {
    serverUrl = vm["gateway"].as<std::string>();
    return main_gateway(serverUrl);
  } else if (vm.count("local")) {
    return main_local();
  } else {
    //start the server
    int threadc = vm["thread"].as<int>();
    serverUrl = vm["all"].as<std::string>();
    allInOne = true;
    boost::thread threadServer1(boost::bind(&main_server));
    do {
      qi::os::msleep(500); // give it time to listen
    } while (!serverReady); // be nice for valgrind
    if (!noGateway)
      boost::thread threadServer2(boost::bind(&main_gateway, serverUrl));
    qi::os::sleep(1);

    start_client(threadc);
  }

  delete out;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2010 Aldebaran Robotics
*/

#include <stdio.h>
#include <signal.h>
#include <iostream>
#include <string>
#include <qi/messaging/publisher.hpp>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

bool gContinue;

void exitHandler(int sig) {
  // Trap CTRL-C
  // The fgets will receive a NULL pointer and exit cleanly.
}

void qichatprompt(std::string& username, const std::string& addr) {
  qi::Publisher publisher("qichat-prompt");
  publisher.connect(addr);
  publisher.advertiseTopic<std::string>("qichat", true);

  std::string connectMessage = "[";
  connectMessage += username;
  connectMessage += " has joined the session]\n";

  std::string disconnectMessage = "[";
  disconnectMessage += username;
  disconnectMessage += " has left the session]\n";

  std::string prompt = username + "> ";
  publisher.publish("qichat", connectMessage);
  std::cout <<
    "============== qichat-prompt ==============" << std::endl <<
    "== Welcome " << username << ","              << std::endl <<
    "== Type a message, and hit return to send."  << std::endl <<
    "== Press CTRL-C to quit."                    << std::endl <<
    "===========================================" << std::endl;

  char textbuf[1024];
  while (gContinue) {
    std::cout << prompt;
    char *rcc = fgets(textbuf, sizeof(textbuf), stdin);
    if (rcc != NULL) {
       publisher.publish("qichat", username + std::string(": ") + std::string(rcc));
    } else {
      // if CTRL-C was pressed we come here
      gContinue = false;
      publisher.publish("qichat", disconnectMessage);
    }
  }
  std::cout << "===========================================" << std::endl;
}

int main(int argc, char *argv[])
{
  gContinue = true;
  (void) signal(SIGINT, exitHandler);
  // declare the program options
  po::options_description desc("Usage:\n  qichat-prompt username masterAddress [options]\nOptions");
  desc.add_options()
    ("help", "Print this help.")
    ("master-address",
    po::value<std::string>()->default_value(std::string("127.0.0.1:5555")),
    "The master address")
    ("username", "Your username");

  // allow master address to be specified as the first arg
  po::positional_options_description pos;
  pos.add("username", 1);
  pos.add("master-address", 2);

  // parse and store
  po::variables_map vm;
  try {
    po::store(po::command_line_parser(argc, argv).
      options(desc).positional(pos).run(), vm);
    po::notify(vm);

    if (vm.count("help")) {
      std::cout << desc << "\n";
      return 0;
    }

    std::string username;
    std::string address;

    if(vm.count("username")==1) {
      username = vm["username"].as<std::string>();
    } else {
      std::cout << desc << "\n";
      return 1;
    }

    if(vm.count("master-address")==1) {
      address = vm["master-address"].as<std::string>();
    } else {
      std::cout << desc << "\n";
      return 1;
    }
    qichatprompt(username, address);

  } catch (const boost::program_options::error&) {
    std::cout << desc << "\n";
  }

  return 0;
}
<commit_msg>chat prompt cleaner output on destruction<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2010 Aldebaran Robotics
*/

#include <stdio.h>
#include <signal.h>
#include <iostream>
#include <string>
#include <qi/messaging/publisher.hpp>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

bool gContinue;

void exitHandler(int sig) {
  // Trap CTRL-C
  // The fgets will receive a NULL pointer and exit cleanly.
}

void qichatprompt(std::string& username, const std::string& addr) {
  qi::Publisher publisher("qichat-prompt");
  publisher.connect(addr);
  publisher.advertiseTopic<std::string>("qichat", true);

  std::string connectMessage = "[";
  connectMessage += username;
  connectMessage += " has joined the session]\n";

  std::string disconnectMessage = "[";
  disconnectMessage += username;
  disconnectMessage += " has left the session]\n";

  std::string prompt = username + "> ";
  publisher.publish("qichat", connectMessage);
  std::cout <<
    "============== qichat-prompt ==============" << std::endl <<
    "== Welcome " << username << ","              << std::endl <<
    "== Type a message, and hit return to send."  << std::endl <<
    "== Press CTRL-C to quit."                    << std::endl <<
    "===========================================" << std::endl;

  char textbuf[1024];
  while (gContinue) {
    std::cout << prompt;
    char *rcc = fgets(textbuf, sizeof(textbuf), stdin);
    if (rcc != NULL) {
       publisher.publish("qichat", username + std::string(": ") + std::string(rcc));
    } else {
      // if CTRL-C was pressed we come here
      gContinue = false;
      publisher.publish("qichat", disconnectMessage);
    }
  }
  std::cout << std::endl <<
    "===========================================" << std::endl;
}

int main(int argc, char *argv[])
{
  gContinue = true;
  (void) signal(SIGINT, exitHandler);
  // declare the program options
  po::options_description desc("Usage:\n  qichat-prompt username masterAddress [options]\nOptions");
  desc.add_options()
    ("help", "Print this help.")
    ("master-address",
    po::value<std::string>()->default_value(std::string("127.0.0.1:5555")),
    "The master address")
    ("username", "Your username");

  // allow master address to be specified as the first arg
  po::positional_options_description pos;
  pos.add("username", 1);
  pos.add("master-address", 2);

  // parse and store
  po::variables_map vm;
  try {
    po::store(po::command_line_parser(argc, argv).
      options(desc).positional(pos).run(), vm);
    po::notify(vm);

    if (vm.count("help")) {
      std::cout << desc << "\n";
      return 0;
    }

    std::string username;
    std::string address;

    if(vm.count("username")==1) {
      username = vm["username"].as<std::string>();
    } else {
      std::cout << desc << "\n";
      return 1;
    }

    if(vm.count("master-address")==1) {
      address = vm["master-address"].as<std::string>();
    } else {
      std::cout << desc << "\n";
      return 1;
    }
    qichatprompt(username, address);

  } catch (const boost::program_options::error&) {
    std::cout << desc << "\n";
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <unistd.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/eventfd.h>
#include <pthread.h>

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cstdint>

using namespace std;

void* thread_start(void* args) {
    int evfd = reinterpret_cast<uint64_t>(args);
    while(true) {
        sleep(5);
        uint64_t value = 5;
        write(evfd, &value, sizeof(value));
    }
    return nullptr;
}

int main(int argc, char *argv[]) {
    printf("event processing demonstration, process id: %d\n", getpid());
    constexpr int MAX_EVENTS = 10;
    struct epoll_event ev, events[MAX_EVENTS];
    auto epollfd = epoll_create1(EPOLL_CLOEXEC);
    if(-1 == epollfd) {
        printf("failed to create epoll file descriptor\n");
        return EXIT_FAILURE;
    }
    // create a notify between two threads
    auto evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if(-1 == evfd) {
        printf("failed to create event file descriptor\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = evfd;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, evfd, &ev)) {
        printf("failed to event file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }
    // add a timer firing every 60 seconds
    auto timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC | TFD_NONBLOCK);
    if(-1 == timerfd) {
        printf("failed to create file descriptor for timer\n");
        return EXIT_FAILURE;
    }
    struct itimerspec timerspec;
    memset(&timerspec, 0, sizeof(timerspec));
    timerspec.it_interval.tv_sec = 5;
    timerspec.it_value.tv_sec = 10;
    if(-1 == timerfd_settime(timerfd, 0, &timerspec, nullptr)) {
        printf("failed to start timer\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = timerfd;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev)) {
        printf("failed to add timer file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }
    // add signal SIGUSR1
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR1);
    sigprocmask(SIG_BLOCK, &mask, nullptr);
    auto sigfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
    if(-1 == sigfd) {
        printf("failed to create file descriptor for signal\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = sigfd;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, sigfd, &ev)) {
        printf("failed to add signal file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }
    // create another thread here so that SIGUSR1 will also be blocked in new thread
    pthread_t thread;
    if(pthread_create(&thread, nullptr, thread_start, reinterpret_cast<void*>(evfd)) == -1) {
        printf("failed to create a new thread\n");
        return EXIT_FAILURE;
    }

    while(true) {
        auto nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        for(auto i = 0; i < nfds; ++i) {
            if(timerfd == events[i].data.fd) {
                printf("timer fired\n");
                uint64_t value;
                read(timerfd, &value, sizeof(value));
            } else if(sigfd ==  events[i].data.fd) {
                printf("SIGUSR1 event received\n");
                struct signalfd_siginfo fdsi;
                read(sigfd, &fdsi, sizeof(fdsi));
            } else if(evfd == events[i].data.fd) {
                printf("thread event received\n");
                uint64_t value;
                read(evfd, &value, sizeof(value));
            } else {
                printf("unknown event received\n");
            }
        }
        if(-1 == nfds) {
            printf("error on epoll waiting\n");
            break;
        }
    }
    timerfd_settime(timerfd, 0, nullptr, nullptr);
    close(timerfd);
    close(sigfd);
    close(epollfd);
    pthread_join(thread, nullptr);
    close(evfd);
    return EXIT_SUCCESS;
}
<commit_msg>more on event<commit_after>#include <unistd.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/eventfd.h>
#include <pthread.h>
#include <fcntl.h>

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cstdint>

using namespace std;

volatile bool stop = false;

void* thread_start(void* args) {
    int evfd = reinterpret_cast<uint64_t>(args);
    while(!stop) {
        sleep(5);
        uint64_t value = 5;
        write(evfd, &value, sizeof(value));
    }
    return nullptr;
}

int main(int argc, char *argv[]) {
    printf("=======================================================================\n");
    printf("   *****event processing demonstration, process id: [%d]*****\n", getpid());
    printf("   to send SIGUSR1 to this process, please use below command in shell:\n");
    printf("   while true; do kill -s SIGUSR1 %d 1>/dev/null 2>&1; if [ $? -ne 0 ]; then break; fi; sleep 5; done\n", getpid());
    printf("=======================================================================\n");
    constexpr int MAX_EVENTS = 10;
    struct epoll_event ev, events[MAX_EVENTS];
    auto epollfd = epoll_create1(EPOLL_CLOEXEC);
    if(-1 == epollfd) {
        printf("failed to create epoll file descriptor\n");
        return EXIT_FAILURE;
    }
    // create a notify between two threads
    // potentially mimic Event on Windows platform
    auto evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if(-1 == evfd) {
        printf("failed to create event file descriptor\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = evfd;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, evfd, &ev)) {
        printf("failed to event file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }
    // add a timer firing every 60 seconds
    auto timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC | TFD_NONBLOCK);
    if(-1 == timerfd) {
        printf("failed to create file descriptor for timer\n");
        return EXIT_FAILURE;
    }
    struct itimerspec timerspec;
    memset(&timerspec, 0, sizeof(timerspec));
    timerspec.it_interval.tv_sec = 5;
    timerspec.it_value.tv_sec = 2;
    if(-1 == timerfd_settime(timerfd, 0, &timerspec, nullptr)) {
        printf("failed to start timer\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = timerfd;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev)) {
        printf("failed to add timer file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }
    // add signal SIGUSR1
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGUSR1);
    sigprocmask(SIG_BLOCK, &mask, nullptr);
    auto sigfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
    if(-1 == sigfd) {
        printf("failed to create file descriptor for signal\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = sigfd;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, sigfd, &ev)) {
        printf("failed to add signal file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }
    // IMPORTANT!
    // create another thread here so that SIGUSR1 will also be blocked in new thread
    pthread_t thread;
    if(pthread_create(&thread, nullptr, thread_start, reinterpret_cast<void*>(evfd)) == -1) {
        printf("failed to create a new thread\n");
        return EXIT_FAILURE;
    }

    // add standard input file descriptor
    auto flags = fcntl(STDIN_FILENO, F_GETFL);
    flags |= O_NONBLOCK;
    if(-1 == fcntl(STDIN_FILENO, F_SETFL, flags)) {
        printf("failed to set NONBLOCK on standard input file descriptor\n");
        return EXIT_FAILURE;
    }
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = STDIN_FILENO;
    if(-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev)) {
        printf("failed to stardard input file descriptor to epoll monitoring\n");
        return EXIT_FAILURE;
    }

    while(true) {
        auto nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        for(auto i = 0; i < nfds; ++i) {
            if(timerfd == events[i].data.fd) {
                uint64_t value;
                read(timerfd, &value, sizeof(value));
                printf("timer event received, value: %lld\n", value);
            } else if(sigfd ==  events[i].data.fd) {
                struct signalfd_siginfo fdsi;
                read(sigfd, &fdsi, sizeof(fdsi));
                printf("signal event received, sender pid: %d, signal no: %d\n", fdsi.ssi_pid, fdsi.ssi_signo);
            } else if(evfd == events[i].data.fd) {
                uint64_t value;
                read(evfd, &value, sizeof(value));
                printf("thread event received, value: %lld\n", value);
            } else if(STDIN_FILENO == events[i].data.fd) {
                constexpr int BUF_SIZE = 10;
                char buf[BUF_SIZE];
                auto n = read(STDIN_FILENO, buf, sizeof(buf));
                memset(buf + n, 0, sizeof(buf) - n);
                buf[sizeof(buf)-1] = '\0';
                printf("standard input ready event received, value: %s", buf);
            }else {
                printf("unknown event received\n");
            }
        }
        if(-1 == nfds) {
            printf("error on epoll waiting or interrupted, exit event loop\n");
            break;
        }
    }
    stop = true;
    timerfd_settime(timerfd, 0, nullptr, nullptr);
    close(timerfd);
    close(sigfd);
    close(epollfd);
    pthread_join(thread, nullptr);
    close(evfd);
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef JSONPP_VALUE_HPP
#define JSONPP_VALUE_HPP

#include "type_traits.hpp"
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <cassert>
#include <memory>

namespace json {
inline namespace v1 {
struct value {
public:
    using object = std::map<std::string, value>;
    using array  = std::vector<value>;
private:
    union storage_t {
        double number;
        bool boolean;
        std::string* str;
        array* arr;
        object* obj;
    } storage;
    type storage_type;

    void copy(const value& other) {
        switch(other.storage_type) {
        case type::array:
            storage.arr = new array(*(other.storage.arr));
            break;
        case type::string:
            storage.str = new std::string(*(other.storage.str));
            break;
        case type::object:
            storage.obj = new object(*(other.storage.obj));
            break;
        case type::number:
            storage.number = other.storage.number;
            break;
        case type::boolean:
            storage.boolean = other.storage.boolean;
            break;
        default:
            break;
        }
        storage_type = other.storage_type;
    }
public:
    value() noexcept: storage_type(type::null) {}
    value(null) noexcept: storage_type(type::null) {}

    ~value() {
        clear();
    }

    value(double v) noexcept: storage_type(type::number) {
        storage.number = v;
    }

    template<typename T, EnableIf<is_bool<T>> = 0>
    value(const T& b) noexcept: storage_type(type::boolean) {
        storage.boolean = b;
    }

    template<typename T, EnableIf<is_string<T>> = 0>
    value(const T& str): storage_type(type::string) {
        storage.str = new std::string(str);
    }

    value(const array& arr): storage_type(type::array) {
        storage.arr = new array(arr);
    }

    value(const object& obj): storage_type(type::object) {
        storage.obj = new object(obj);
    }

    value(std::initializer_list<array::value_type> l): storage_type(type::array) {
        storage.arr = new array(l.begin(), l.end());
    }

    value(const value& other) {
        copy(other);
    }

    value(value&& other) noexcept {
        switch(other.storage_type) {
        case type::array:
            storage.arr = other.storage.arr;
            other.storage.arr = nullptr;
            break;
        case type::string:
            storage.str = other.storage.str;
            other.storage.str = nullptr;
            break;
        case type::object:
            storage.obj = other.storage.obj;
            other.storage.obj = nullptr;
            break;
        case type::boolean:
            storage.boolean = other.storage.boolean;
            break;
        case type::number:
            storage.number = other.storage.number;
            break;
        default:
            break;
        }

        storage_type = other.storage_type;
        other.storage_type = type::null;
    }

    value& operator=(const value& other) noexcept {
        if(this != &other) {
            clear();
            copy(other);
        }
        return *this;
    }

    value& operator=(value&& other) {
        if(this != &other) {
            clear();
            switch(other.storage_type) {
            case type::array:
                storage.arr = other.storage.arr;
                other.storage.arr = nullptr;
                break;
            case type::string:
                storage.str = other.storage.str;
                other.storage.str = nullptr;
                break;
            case type::object:
                storage.obj = other.storage.obj;
                other.storage.obj = nullptr;
                break;
            case type::boolean:
                storage.boolean = other.storage.boolean;
                break;
            case type::number:
                storage.number = other.storage.number;
                break;
            default:
                break;
            }

            storage_type = other.storage_type;
            other.storage_type = type::null;
        }
        return *this;
    }

    void clear() noexcept {
        switch(storage_type) {
        case type::array:
            delete storage.arr;
            break;
        case type::string:
            delete storage.str;
            break;
        case type::object:
            delete storage.obj;
            break;
        default:
            break;
        }
        storage_type = type::null;
    }

    std::string to_string(unsigned precision = 6) const {
        switch(storage_type) {
        case type::null:
            return "null";
        case type::number: {
            char buffer[328];
            std::snprintf(buffer, 328, "%.*g", precision, storage.number);
            return buffer;
        }
        case type::boolean:
            return storage.boolean ? "true" : "false";
        case type::string:
            return '"' + *(storage.str) + '"';
        case type::array: {
            std::ostringstream ss;
            ss.precision(precision);
            ss << "[";
            auto first = storage.arr->begin();
            auto last = storage.arr->end();
            if(first != last) {
                ss << first->to_string(precision);
                ++first;
            }
            while(first != last) {
                ss << ',' << first->to_string(precision);
                ++first;
            }
            ss << "]";
            return ss.str();
        }
        case type::object: {
            std::ostringstream ss;
            ss.precision(precision);
            ss << "{";
            auto begin = storage.obj->begin();
            auto end = storage.obj->end();
            if(begin != end) {
                ss << '"' << begin->first << "\":" << begin->second.to_string(precision);
                ++begin;
            }

            while(begin != end) {
                ss << ",\"" << begin->first << "\":" << begin->second.to_string(precision);
                ++begin;
            }
            ss << "}";
            return ss.str();
        }
        }
        return "";
    }

    template<typename T, EnableIf<is_string<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::string;
    }

    template<typename T, EnableIf<is_null<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::null;
    }

    template<typename T, EnableIf<is_number<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::number;
    }

    template<typename T, EnableIf<is_bool<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::boolean;
    }

    template<typename T, EnableIf<std::is_same<T, object>> = 0>
    bool is() const noexcept {
        return storage_type == type::object;
    }

    template<typename T, EnableIf<std::is_same<T, array>> = 0>
    bool is() const noexcept {
        return storage_type == type::array;
    }

    template<typename T, EnableIf<std::is_same<T, const char*>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return storage.str->c_str();
    }

    template<typename T, EnableIf<std::is_same<T, std::string>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return *(storage.str);
    }

    template<typename T, EnableIf<is_null<T>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return {};
    }

    template<typename T, EnableIf<is_bool<T>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return storage.boolean;
    }

    template<typename T, EnableIf<is_number<T>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return storage.number;
    }

    template<typename T, EnableIf<std::is_same<T, object>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return *(storage.obj);
    }

    template<typename T, EnableIf<std::is_same<T, array>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return *(storage.arr);
    }

    template<typename T>
    T as(Identity<T>&& def) const noexcept {
        return is<T>() ? as<T>() : std::forward<T>(def);
    }
};

using array  = value::array;
using object = value::object;
} // v1
} // json

#endif // JSONPP_VALUE_HPP
<commit_msg>Add [] accessors for json::object and json::array. Extend tests with modifications<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef JSONPP_VALUE_HPP
#define JSONPP_VALUE_HPP

#include "type_traits.hpp"
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <cassert>
#include <memory>

namespace json {
inline namespace v1 {
class value {
public:
    using object = std::map<std::string, value>;
    using array  = std::vector<value>;
private:
    union storage_t {
        double number;
        bool boolean;
        std::string* str;
        array* arr;
        object* obj;
    } storage;
    type storage_type;

    void copy(const value& other) {
        switch(other.storage_type) {
        case type::array:
            storage.arr = new array(*(other.storage.arr));
            break;
        case type::string:
            storage.str = new std::string(*(other.storage.str));
            break;
        case type::object:
            storage.obj = new object(*(other.storage.obj));
            break;
        case type::number:
            storage.number = other.storage.number;
            break;
        case type::boolean:
            storage.boolean = other.storage.boolean;
            break;
        default:
            break;
        }
        storage_type = other.storage_type;
    }
public:
    value() noexcept: storage_type(type::null) {}
    value(null) noexcept: storage_type(type::null) {}

    ~value() {
        clear();
    }

    value(double v) noexcept: storage_type(type::number) {
        storage.number = v;
    }

    template<typename T, EnableIf<is_bool<T>> = 0>
    value(const T& b) noexcept: storage_type(type::boolean) {
        storage.boolean = b;
    }

    template<typename T, EnableIf<is_string<T>> = 0>
    value(const T& str): storage_type(type::string) {
        storage.str = new std::string(str);
    }

    value(const array& arr): storage_type(type::array) {
        storage.arr = new array(arr);
    }

    value(const object& obj): storage_type(type::object) {
        storage.obj = new object(obj);
    }

    value(std::initializer_list<array::value_type> l): storage_type(type::array) {
        storage.arr = new array(l.begin(), l.end());
    }

    value(const value& other) {
        copy(other);
    }

    value(value&& other) noexcept {
        switch(other.storage_type) {
        case type::array:
            storage.arr = other.storage.arr;
            other.storage.arr = nullptr;
            break;
        case type::string:
            storage.str = other.storage.str;
            other.storage.str = nullptr;
            break;
        case type::object:
            storage.obj = other.storage.obj;
            other.storage.obj = nullptr;
            break;
        case type::boolean:
            storage.boolean = other.storage.boolean;
            break;
        case type::number:
            storage.number = other.storage.number;
            break;
        default:
            break;
        }

        storage_type = other.storage_type;
        other.storage_type = type::null;
    }

    value& operator=(const value& other) noexcept {
        if(this != &other) {
            clear();
            copy(other);
        }
        return *this;
    }

    value& operator=(value&& other) {
        if(this != &other) {
            clear();
            switch(other.storage_type) {
            case type::array:
                storage.arr = other.storage.arr;
                other.storage.arr = nullptr;
                break;
            case type::string:
                storage.str = other.storage.str;
                other.storage.str = nullptr;
                break;
            case type::object:
                storage.obj = other.storage.obj;
                other.storage.obj = nullptr;
                break;
            case type::boolean:
                storage.boolean = other.storage.boolean;
                break;
            case type::number:
                storage.number = other.storage.number;
                break;
            default:
                break;
            }

            storage_type = other.storage_type;
            other.storage_type = type::null;
        }
        return *this;
    }

    void clear() noexcept {
        switch(storage_type) {
        case type::array:
            delete storage.arr;
            break;
        case type::string:
            delete storage.str;
            break;
        case type::object:
            delete storage.obj;
            break;
        default:
            break;
        }
        storage_type = type::null;
    }

    std::string to_string(unsigned precision = 6) const {
        switch(storage_type) {
        case type::null:
            return "null";
        case type::number: {
            char buffer[328];
            std::snprintf(buffer, 328, "%.*g", precision, storage.number);
            return buffer;
        }
        case type::boolean:
            return storage.boolean ? "true" : "false";
        case type::string:
            return '"' + *(storage.str) + '"';
        case type::array: {
            std::ostringstream ss;
            ss.precision(precision);
            ss << "[";
            auto first = storage.arr->begin();
            auto last = storage.arr->end();
            if(first != last) {
                ss << first->to_string(precision);
                ++first;
            }
            while(first != last) {
                ss << ',' << first->to_string(precision);
                ++first;
            }
            ss << "]";
            return ss.str();
        }
        case type::object: {
            std::ostringstream ss;
            ss.precision(precision);
            ss << "{";
            auto begin = storage.obj->begin();
            auto end = storage.obj->end();
            if(begin != end) {
                ss << '"' << begin->first << "\":" << begin->second.to_string(precision);
                ++begin;
            }

            while(begin != end) {
                ss << ",\"" << begin->first << "\":" << begin->second.to_string(precision);
                ++begin;
            }
            ss << "}";
            return ss.str();
        }
        }
        return "";
    }

    template<typename T, EnableIf<is_string<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::string;
    }

    template<typename T, EnableIf<is_null<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::null;
    }

    template<typename T, EnableIf<is_number<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::number;
    }

    template<typename T, EnableIf<is_bool<T>> = 0>
    bool is() const noexcept {
        return storage_type == type::boolean;
    }

    template<typename T, EnableIf<std::is_same<T, object>> = 0>
    bool is() const noexcept {
        return storage_type == type::object;
    }

    template<typename T, EnableIf<std::is_same<T, array>> = 0>
    bool is() const noexcept {
        return storage_type == type::array;
    }

    template<typename T, EnableIf<std::is_same<T, const char*>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return storage.str->c_str();
    }

    template<typename T, EnableIf<std::is_same<T, std::string>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return *(storage.str);
    }

    template<typename T, EnableIf<is_null<T>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return {};
    }

    template<typename T, EnableIf<is_bool<T>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return storage.boolean;
    }

    template<typename T, EnableIf<is_number<T>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return storage.number;
    }

    template<typename T, EnableIf<std::is_same<T, object>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return *(storage.obj);
    }

    template<typename T, EnableIf<std::is_same<T, array>> = 0>
    T as() const noexcept {
        assert(is<T>());
        return *(storage.arr);
    }

    template<typename T>
    T as(Identity<T>&& def) const noexcept {
        return is<T>() ? as<T>() : std::forward<T>(def);
    }

    template<typename T>
    value operator[] (T& str) const noexcept{
        if(not is<object>() )
            return value(nullptr);

        auto iter = storage.obj->find(str);
        if(iter == storage.obj->end())
            return value(nullptr);
        else
            return iter->second;
    }

    template<typename T, EnableIf<is_number<T>> = 0>
    value operator[] (T idx) const noexcept{
        if(not is<array>() )
            return value(nullptr);

        if((size_t)idx >= storage.arr->size())
            return value(nullptr);
        else
            return storage.arr->at(idx);
    }
};

using array  = value::array;
using object = value::object;
} // v1
} // json

#endif // JSONPP_VALUE_HPP
<|endoftext|>


<commit_before>#include <libw3d/chunks/animation.hpp>
#include "../util.hpp"
#include <cassert>
using namespace libw3d;

void Animation::Load(std::ifstream & fin, uint32_t chunksize)
{
	uint32_t chunkend = static_cast<uint32_t>(fin.tellg()) + chunksize;
	while (fin.tellg() < chunkend)
	{
		ChunkType type = static_cast<ChunkType>(read<uint32_t>(fin));
		uint32_t info = read<uint32_t>(fin);
		uint32_t size = info & 0x7FFFFFFF;
		uint32_t subend = static_cast<uint32_t>(fin.tellg()) + size;

		switch (type)
		{
		case ANIMATION_HEADER:
			Header = read<AnimationHeader>(fin);
			break;
		case ANIMATION_CHANNEL:
			AddChannel(fin, size);
			break;
		}
	}
}

void Animation::AddChannel(std::ifstream& fin, uint32_t chunksize)
{
	std::shared_ptr<Channel> channel = std::make_shared<Channel>();
	assert(chunksize > sizeof(ChannelHeader));
	ChannelHeader header;
	header.FirstFrame = read<uint16_t>(fin);
	header.LastFrame = read<uint16_t>(fin);
	header.VectorLen = read<uint16_t>(fin);
	header.Flags = read<uint16_t>(fin);
	header.Pivot = read<uint16_t>(fin);
	header.Pad = read<uint16_t>(fin);

	channel->Load(fin, chunksize, header);
	Channels.push_back(channel);
}

void CompressedAnimation::Load(std::ifstream & fin, uint32_t chunksize)
{
	uint32_t chunkend = static_cast<uint32_t>(fin.tellg()) + chunksize;
	while (fin.tellg() < chunkend)
	{
		ChunkType type = static_cast<ChunkType>(read<uint32_t>(fin));
		uint32_t info = read<uint32_t>(fin);
		bool subChunks = (info >> 31);
		uint32_t size = info & 0x7FFFFFFF;
		uint32_t subend = static_cast<uint32_t>(fin.tellg()) + size;

		switch (type)
		{
		case COMPRESSED_ANIMATION_HEADER:
			Header = read<CompressedAnimationHeader>(fin);
			break;
		case COMPRESSED_ANIMATION_MOTION_CHANNEL:
			AddChannel(fin, size);
			break;
		}
	}
}

void CompressedAnimation::AddChannel(std::ifstream& fin, uint32_t chunksize)
{
	std::shared_ptr<MotionChannel> channel;
	assert(chunksize > sizeof(MotionChannelHeader));
	MotionChannelHeader header = read<MotionChannelHeader>(fin);

	switch (header.DeltaType)
	{
	case TIMECODED:
		channel = std::make_shared<TimeCodedChannel>();
		break;
	case DELTA4:
		channel = std::make_shared<AdaptiveDelta4>();
	case DELTA8:
		break;
	}

	if (channel)
	{
		channel->Load(fin, chunksize, header);
		Channels.push_back(channel);
	}
	else
	{
		fin.seekg(chunksize - sizeof(MotionChannelHeader), std::ios::cur);
	}
}

void Channel::Load(std::ifstream &fin, uint32_t chunksize, const ChannelHeader &header)
{
	Header = header;
	Data = readArrayByNum<uint8_t>(fin, chunksize - 12);
}

void TimeCodedChannel::Load(std::ifstream & fin, uint32_t chunksize, const MotionChannelHeader & header)
{
	Header = header;
	Keyframes = readArrayByNum<uint16_t>(fin, Header.Framecount);
	if (Header.Framecount & 1)
		fin.seekg(2, std::ios::cur);
	Data = readArrayByNum<float>(fin, Header.Framecount*Header.VectorLen);
}

void AdaptiveDelta4::Load(std::ifstream & fin, uint32_t chunksize, const MotionChannelHeader & header)
{
	Header = header;
	Increment = read<float>(fin);
	Vector = readArrayByNum<float>(fin, Header.VectorLen);
	uint32_t Remaining = chunksize - sizeof(MotionChannelHeader) - Header.VectorLen * sizeof(float);
	Data = readArrayByNum<uint8_t>(fin, Remaining);
}
<commit_msg>Added defaultcases<commit_after>#include <libw3d/chunks/animation.hpp>
#include "../util.hpp"
#include <cassert>
using namespace libw3d;

void Animation::Load(std::ifstream & fin, uint32_t chunksize)
{
	uint32_t chunkend = static_cast<uint32_t>(fin.tellg()) + chunksize;
	while (fin.tellg() < chunkend)
	{
		ChunkType type = static_cast<ChunkType>(read<uint32_t>(fin));
		uint32_t info = read<uint32_t>(fin);
		uint32_t size = info & 0x7FFFFFFF;
		uint32_t subend = static_cast<uint32_t>(fin.tellg()) + size;

		switch (type)
		{
		case ANIMATION_HEADER:
			Header = read<AnimationHeader>(fin);
			break;
		case ANIMATION_CHANNEL:
			AddChannel(fin, size);
			break;
		default:
			fin.seekg(size, std::ios::cur);
			break;
		}
	}
}

void Animation::AddChannel(std::ifstream& fin, uint32_t chunksize)
{
	std::shared_ptr<Channel> channel = std::make_shared<Channel>();
	assert(chunksize > sizeof(ChannelHeader));
	ChannelHeader header;
	header.FirstFrame = read<uint16_t>(fin);
	header.LastFrame = read<uint16_t>(fin);
	header.VectorLen = read<uint16_t>(fin);
	header.Flags = read<uint16_t>(fin);
	header.Pivot = read<uint16_t>(fin);
	header.Pad = read<uint16_t>(fin);

	channel->Load(fin, chunksize, header);
	Channels.push_back(channel);
}

void CompressedAnimation::Load(std::ifstream & fin, uint32_t chunksize)
{
	uint32_t chunkend = static_cast<uint32_t>(fin.tellg()) + chunksize;
	while (fin.tellg() < chunkend)
	{
		ChunkType type = static_cast<ChunkType>(read<uint32_t>(fin));
		uint32_t info = read<uint32_t>(fin);
		bool subChunks = (info >> 31);
		uint32_t size = info & 0x7FFFFFFF;
		uint32_t subend = static_cast<uint32_t>(fin.tellg()) + size;

		switch (type)
		{
		case COMPRESSED_ANIMATION_HEADER:
			Header = read<CompressedAnimationHeader>(fin);
			break;
		case COMPRESSED_ANIMATION_MOTION_CHANNEL:
			AddChannel(fin, size);
			break;
		default:
			fin.seekg(size, std::ios::cur);
			break;
		}
	}
}

void CompressedAnimation::AddChannel(std::ifstream& fin, uint32_t chunksize)
{
	std::shared_ptr<MotionChannel> channel;
	assert(chunksize > sizeof(MotionChannelHeader));
	MotionChannelHeader header = read<MotionChannelHeader>(fin);

	switch (header.DeltaType)
	{
	case TIMECODED:
		channel = std::make_shared<TimeCodedChannel>();
		break;
	case DELTA4:
		channel = std::make_shared<AdaptiveDelta4>();
	case DELTA8:
		break;
	}

	if (channel)
	{
		channel->Load(fin, chunksize, header);
		Channels.push_back(channel);
	}
	else
	{
		fin.seekg(chunksize - sizeof(MotionChannelHeader), std::ios::cur);
	}
}

void Channel::Load(std::ifstream &fin, uint32_t chunksize, const ChannelHeader &header)
{
	Header = header;
	Data = readArrayByNum<uint8_t>(fin, chunksize - 12);
}

void TimeCodedChannel::Load(std::ifstream & fin, uint32_t chunksize, const MotionChannelHeader & header)
{
	Header = header;
	Keyframes = readArrayByNum<uint16_t>(fin, Header.Framecount);
	if (Header.Framecount & 1)
		fin.seekg(2, std::ios::cur);
	Data = readArrayByNum<float>(fin, Header.Framecount*Header.VectorLen);
}

void AdaptiveDelta4::Load(std::ifstream & fin, uint32_t chunksize, const MotionChannelHeader & header)
{
	Header = header;
	Increment = read<float>(fin);
	Vector = readArrayByNum<float>(fin, Header.VectorLen);
	uint32_t Remaining = chunksize - sizeof(MotionChannelHeader) - Header.VectorLen * sizeof(float);
	Data = readArrayByNum<uint8_t>(fin, Remaining);
}
<|endoftext|>


<commit_before>// A simple HTTP/1.0 web server using Dashel

#include <dashel/dashel.h>
#include <iostream>
#include <fstream>
#include <cassert>

using namespace std;
using namespace Dashel;

// Helper functions for stream

string readLine(Stream* stream)
{
	char c;
	string line;
	do
	{
		stream->read(&c, 1);
		line += c;
	}
	while (c != '\n');
	return line;
}

void sendString(Stream* stream, const string& line)
{
	stream->write(line.c_str(), line.length());
	stream->flush();
}

void shutdownStream(Stream* stream)
{
	// close the stream, this is a hack because Dashel lacks a proper shutdown mechanism
	stream->fail(DashelException::Unknown, 0, "Request handling complete");
}

// Helper functions for string

// inspired from: http://stackoverflow.com/questions/289347/using-strtok-with-a-stdstring
vector<string> split(const string& str, const string& delim)
{
	vector<string> parts;
	size_t start, end = 0;
	while (end < str.size())
	{
		start = end;
		while (start < str.size() && (delim.find(str[start]) != string::npos))
			start++;  // skip initial whitespace
		end = start;
		while (end < str.size() && (delim.find(str[end]) == string::npos))
			end++; // skip to end of word
		if (end-start != 0)  // just ignore zero-length strings.
			parts.push_back(string(str, start, end-start));
	}
	return parts;
}

// Web server itself

class WebServer: public Hub
{
public:
	WebServer(const string& port)
	{
		listenStream = connect("tcpin:port=" + port);
	}

	void connectionCreated(Stream *stream)
	{
		cerr << stream << " Connection created to " << stream->getTargetName() << endl;
	}

	void incomingData(Stream *stream)
	{
		// received request
		const string request(readLine(stream));
		cerr << stream << " Request: " << request;

		// read all options
		readLine(stream);
		string optionLine;
		while ((optionLine = readLine(stream)) != "\r\n")
		{
			cerr << stream << " Option: " << optionLine;
		}

		// parse request
		vector<string> requestParts(split(request, "\n\r\t "));

		// only support GET
		if ((requestParts.size() < 2) or requestParts[0] != "GET")
		{
			cerr << stream << " Unsupported HTTP request" << request << endl;
			sendString(stream, "HTTP/1.0 403\r\n\r\n");
			shutdownStream(stream);
			return;
		}

		// try to open file
		const string fileName(requestParts[1]);
		ifstream ifs(fileName.c_str());
		char c = ifs.get();
		if (!ifs.good())
		{
			cerr << stream << " Cannot open file" << fileName << endl;
			sendString(stream, "HTTP/1.0 404\r\n\r\n");
			shutdownStream(stream);
			return;
		}

		// read and send the file
		// note: this could be made much more efficient by checking the
		// file size and reading it all at once
		cerr << stream << " Serving: " << fileName << endl;
		sendString(stream, "HTTP/1.0 200\r\n\r\n");
		while (ifs.good())
		{
			stream->write(c);
			c = ifs.get();
		}
		stream->flush();

		shutdownStream(stream);
	}

	void connectionClosed(Stream *stream, bool abnormal)
	{
		cerr << stream << " Connection closed to " << stream->getTargetName() << endl;
	}

protected:
	Stream* listenStream;
};

int main(int argc, char* argv[])
{
	try
	{
		WebServer webServer(argc > 1 ? argv[1] : "8080");
		webServer.run();
	}
	catch(DashelException e)
	{
		std::cerr << e.what() << std::endl;
	}

	return 0;
}<commit_msg>do not use ISO646 "or" keyword<commit_after>// A simple HTTP/1.0 web server using Dashel

#include <dashel/dashel.h>
#include <iostream>
#include <fstream>
#include <cassert>

using namespace std;
using namespace Dashel;

// Helper functions for stream

string readLine(Stream* stream)
{
	char c;
	string line;
	do
	{
		stream->read(&c, 1);
		line += c;
	}
	while (c != '\n');
	return line;
}

void sendString(Stream* stream, const string& line)
{
	stream->write(line.c_str(), line.length());
	stream->flush();
}

void shutdownStream(Stream* stream)
{
	// close the stream, this is a hack because Dashel lacks a proper shutdown mechanism
	stream->fail(DashelException::Unknown, 0, "Request handling complete");
}

// Helper functions for string

// inspired from: http://stackoverflow.com/questions/289347/using-strtok-with-a-stdstring
vector<string> split(const string& str, const string& delim)
{
	vector<string> parts;
	size_t start, end = 0;
	while (end < str.size())
	{
		start = end;
		while (start < str.size() && (delim.find(str[start]) != string::npos))
			start++;  // skip initial whitespace
		end = start;
		while (end < str.size() && (delim.find(str[end]) == string::npos))
			end++; // skip to end of word
		if (end-start != 0)  // just ignore zero-length strings.
			parts.push_back(string(str, start, end-start));
	}
	return parts;
}

// Web server itself

class WebServer: public Hub
{
public:
	WebServer(const string& port)
	{
		listenStream = connect("tcpin:port=" + port);
	}

	void connectionCreated(Stream *stream)
	{
		cerr << stream << " Connection created to " << stream->getTargetName() << endl;
	}

	void incomingData(Stream *stream)
	{
		// received request
		const string request(readLine(stream));
		cerr << stream << " Request: " << request;

		// read all options
		readLine(stream);
		string optionLine;
		while ((optionLine = readLine(stream)) != "\r\n")
		{
			cerr << stream << " Option: " << optionLine;
		}

		// parse request
		vector<string> requestParts(split(request, "\n\r\t "));

		// only support GET
		if ((requestParts.size() < 2) || requestParts[0] != "GET")
		{
			cerr << stream << " Unsupported HTTP request" << request << endl;
			sendString(stream, "HTTP/1.0 403\r\n\r\n");
			shutdownStream(stream);
			return;
		}

		// try to open file
		const string fileName(requestParts[1]);
		ifstream ifs(fileName.c_str());
		char c = ifs.get();
		if (!ifs.good())
		{
			cerr << stream << " Cannot open file" << fileName << endl;
			sendString(stream, "HTTP/1.0 404\r\n\r\n");
			shutdownStream(stream);
			return;
		}

		// read and send the file
		// note: this could be made much more efficient by checking the
		// file size and reading it all at once
		cerr << stream << " Serving: " << fileName << endl;
		sendString(stream, "HTTP/1.0 200\r\n\r\n");
		while (ifs.good())
		{
			stream->write(c);
			c = ifs.get();
		}
		stream->flush();

		shutdownStream(stream);
	}

	void connectionClosed(Stream *stream, bool abnormal)
	{
		cerr << stream << " Connection closed to " << stream->getTargetName() << endl;
	}

protected:
	Stream* listenStream;
};

int main(int argc, char* argv[])
{
	try
	{
		WebServer webServer(argc > 1 ? argv[1] : "8080");
		webServer.run();
	}
	catch(DashelException e)
	{
		std::cerr << e.what() << std::endl;
	}

	return 0;
}
<|endoftext|>


<commit_before>/** \addtogroup examples
  * @{
  * \defgroup fft fft
  * @{
  * \brief FFT iterative method using gemv and spmv
  */

#include <ctf.hpp>
using namespace CTF;

namespace CTF_int{
  void factorize(int n, int *nfactor, int **factor);
}

Matrix< std::complex<double> > DFT_matrix(int n, World & wrld){
  int64_t np;
  int64_t * idx;
  std::complex<double> imag(0,1);
  std::complex<double> * data;
  Matrix < std::complex<double> >DFT(n, n, NS, wrld, "DFT");
  DFT.read_local(&np, &idx, &data);

  for (int64_t i=0; i<np; i++){
    data[i] = exp(-2.*(idx[i]/n)*(idx[i]%n)*(M_PI/n)*imag);
  }
  DFT.write(np, idx, data);
  free(idx);
  free(data);
  return DFT;
}

void fft(Vector< std::complex<double> > & v, int n){
  int64_t np;
  int64_t * idx;
  std::complex<double> * data;
  int logn=0;
  while (1<<logn < n){
    logn++;
  }
  assert(1<<logn == n);
  int nfact;
  int * factors;
  CTF_int::factorize(n, &nfact, &factors);
  assert(nfact == logn);

  Tensor< std::complex<double> > V(nfact, factors, *v.wrld, *v.sr, "V");

  v.read_local(&np, &idx, &data);

  V.write(np, idx, data);

  free(idx);
  free(data);

  char inds[nfact+1];
  char rev_inds[nfact];
  for (int i=0; i<nfact; i++){
    inds[i]='a'+i;
    rev_inds[i]='a'+nfact-i-1;
  }
  inds[nfact] = 'a';
  //reverse tensor index order (corresponds to no-op recursion in FFT that picks odds/evens) so that I am less confused
  V[rev_inds] = V[inds];
  for (int i=0; i<nfact; i++){
    inds[nfact+i]='a'+i;
  }

  V.print();
  Matrix< std::complex<double> > DFT = DFT_matrix(2,*v.wrld);
  for (int i=0; i<nfact; i++){
    Tensor< std::complex<double> > S(i+1, factors, *v.wrld, *v.sr, "S");
    S.read_local(&np, &idx, &data);
    std::complex<double> imag(0,1);
    for(int64_t i=0; i<np; i++){
      if (idx[i]%2 == 1){
        data[i] = exp(-2.*(idx[i]/2)*(M_PI/n)*imag);
      } else {
        data[i] = std::complex<double>(1.0,0.0);
      }
    }
    S.write(np, idx, data);

    S.print();
    V[inds+1] *= S[inds];
    char inds_in[nfact];
    char inds_out[nfact];
    char inds_DFT[2];
    memcpy(inds_in, inds, nfact*sizeof(char));
    inds_in[i] = 'z';
    memcpy(inds_out, inds, nfact*sizeof(char));
    inds_DFT[0] = inds_out[i];
    inds_DFT[1] = 'z';
    V[inds_out] = DFT[inds_DFT]*V[inds_in];
  }
  free(idx);
  free(data);

  V.read_local(&np, &idx, &data);

  v.write(np, idx, data);

  free(idx);
  free(data);

}

int fft(int     n,
        World & dw){

  Vector< std::complex<double> > a(n, dw, "a");
  Vector< std::complex<double> > da(n, dw, "da");

  srand48(2*dw.rank);
  Transform< std::complex<double> > set_rand([](std::complex<double> & d){ d=std::complex<double>(drand48(),drand48()); } );
  set_rand(a["i"]);
  /*if (dw.rank == 0){
    std::complex<double> val (1.0, 0.0);
    int64_t idx = 2;
    a.write(1, &idx, &val);
  } else a.write(0,NULL,NULL);
*/
//  a.sparsify([](std::complex<double> d){ return fabs(d.real()) > .8; });

  Matrix< std::complex<double> > DFT = DFT_matrix(n,dw);

  da["i"] = DFT["ij"]*a["j"];

  Vector< std::complex<double> > fa(n, dw, "fa");
  fa["i"] = a["i"];

  fft(fa, n);
  fa.print();

  da.print();
  da["i"] -= fa["i"];

  std::complex<double> dnrm;
  Scalar< std::complex<double> > s(dnrm, dw);
  s.print();
  s[""] += da["i"]*da["i"];
  s.print();
  dnrm = s;
  bool pass = dnrm.real() <= 1.E-6 && dnrm.imag() <= 1.E-6;

  if (dw.rank == 0){
    if (pass)
      printf("{ FFT = DFT } passed \n");
    else
      printf("{ FFT = DFT } failed \n");
  }
  return pass;
}

#ifndef TEST_SUITE
char* getCmdOption(char ** begin,
                   char ** end,
                   const   std::string & option){
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end){
    return *itr;
  }
  return 0;
}

int main(int argc, char ** argv){
  int rank, np, n, pass;
  int const in_num = argc;
  char ** input_str = argv;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);

  if (getCmdOption(input_str, input_str+in_num, "-n")){
    n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
    if (n < 0) n = 7;
  } else n = 7;

  {
    World dw(argc, argv);

    if (rank == 0){
      printf("Running FFT on random dimension %d vector\n",n);
    }
    pass = fft(n, dw);
    assert(pass);
  }

  MPI_Finalize();
  return 0;
}
/**
 * @}
 * @}
 */

#endif
<commit_msg>corrected error check in nonworking fft example<commit_after>/** \addtogroup examples
  * @{
  * \defgroup fft fft
  * @{
  * \brief FFT iterative method using gemv and spmv
  */

#include <ctf.hpp>
using namespace CTF;

namespace CTF_int{
  void factorize(int n, int *nfactor, int **factor);
}

Matrix< std::complex<double> > DFT_matrix(int n, World & wrld){
  int64_t np;
  int64_t * idx;
  std::complex<double> imag(0,1);
  std::complex<double> * data;
  Matrix < std::complex<double> >DFT(n, n, NS, wrld, "DFT");
  DFT.read_local(&np, &idx, &data);

  for (int64_t i=0; i<np; i++){
    data[i] = exp(-2.*(idx[i]/n)*(idx[i]%n)*(M_PI/n)*imag);
  }
  DFT.write(np, idx, data);
  free(idx);
  free(data);
  return DFT;
}

void fft(Vector< std::complex<double> > & v, int n){
  int64_t np;
  int64_t * idx;
  std::complex<double> * data;
  int logn=0;
  while (1<<logn < n){
    logn++;
  }
  assert(1<<logn == n);
  int nfact;
  int * factors;
  CTF_int::factorize(n, &nfact, &factors);
  assert(nfact == logn);

  Tensor< std::complex<double> > V(nfact, factors, *v.wrld, *v.sr, "V");

  v.read_local(&np, &idx, &data);

  V.write(np, idx, data);

  free(idx);
  free(data);

  char inds[nfact+1];
  char rev_inds[nfact];
  for (int i=0; i<nfact; i++){
    inds[i]='a'+i;
    rev_inds[i]='a'+nfact-i-1;
  }
  inds[nfact] = 'a';
  //reverse tensor index order (corresponds to no-op recursion in FFT that picks odds/evens) so that I am less confused
  V[rev_inds] = V[inds];
  for (int i=0; i<nfact; i++){
    inds[nfact+i]='a'+i;
  }

  V.print();
  Matrix< std::complex<double> > DFT = DFT_matrix(2,*v.wrld);
  for (int i=0; i<nfact; i++){
    Tensor< std::complex<double> > S(i+1, factors, *v.wrld, *v.sr, "S");
    S.read_local(&np, &idx, &data);
    std::complex<double> imag(0,1);
    for(int64_t i=0; i<np; i++){
      if (idx[i]%2 == 1){
        data[i] = exp(-2.*(idx[i]/2)*(M_PI/n)*imag);
      } else {
        data[i] = std::complex<double>(1.0,0.0);
      }
    }
    S.write(np, idx, data);

    S.print();
    V[inds+1] *= S[inds];
    char inds_in[nfact];
    char inds_out[nfact];
    char inds_DFT[2];
    memcpy(inds_in, inds, nfact*sizeof(char));
    inds_in[i] = 'z';
    memcpy(inds_out, inds, nfact*sizeof(char));
    inds_DFT[0] = inds_out[i];
    inds_DFT[1] = 'z';
    V[inds_out] = DFT[inds_DFT]*V[inds_in];
  }
  free(idx);
  free(data);

  V.read_local(&np, &idx, &data);

  v.write(np, idx, data);

  free(idx);
  free(data);

}

int fft(int     n,
        World & dw){

  Vector< std::complex<double> > a(n, dw, "a");
  Vector< std::complex<double> > da(n, dw, "da");

  srand48(2*dw.rank);
  Transform< std::complex<double> > set_rand([](std::complex<double> & d){ d=std::complex<double>(drand48(),drand48()); } );
  set_rand(a["i"]);
  /*if (dw.rank == 0){
    std::complex<double> val (1.0, 0.0);
    int64_t idx = 2;
    a.write(1, &idx, &val);
  } else a.write(0,NULL,NULL);
*/
//  a.sparsify([](std::complex<double> d){ return fabs(d.real()) > .8; });

  Matrix< std::complex<double> > DFT = DFT_matrix(n,dw);

  da["i"] = DFT["ij"]*a["j"];

  Vector< std::complex<double> > fa(n, dw, "fa");
  fa["i"] = a["i"];

  fft(fa, n);
  fa.print();

  da.print();
  da["i"] -= fa["i"];

  std::complex<double> dnrm;
  Scalar< std::complex<double> > s(dnrm, dw);
  s.print();
  s[""] += da["i"]*da["i"];
  s.print();
  dnrm = s;
  bool pass = fabs(dnrm.real()) <= 1.E-6 && fabs(dnrm.imag()) <= 1.E-6;

  if (dw.rank == 0){
    if (pass)
      printf("{ FFT = DFT } passed \n");
    else
      printf("{ FFT = DFT } failed \n");
  }
  return pass;
}

#ifndef TEST_SUITE
char* getCmdOption(char ** begin,
                   char ** end,
                   const   std::string & option){
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end){
    return *itr;
  }
  return 0;
}

int main(int argc, char ** argv){
  int rank, np, n, pass;
  int const in_num = argc;
  char ** input_str = argv;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);

  if (getCmdOption(input_str, input_str+in_num, "-n")){
    n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
    if (n < 0) n = 7;
  } else n = 7;

  {
    World dw(argc, argv);

    if (rank == 0){
      printf("Running FFT on random dimension %d vector\n",n);
    }
    pass = fft(n, dw);
    assert(pass);
  }

  MPI_Finalize();
  return 0;
}
/**
 * @}
 * @}
 */

#endif
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>

// Qmitk
#include "QmitkStreamlineTrackingView.h"
#include "QmitkStdMultiWidget.h"

// Qt
#include <QMessageBox>

// MITK
#include <mitkImageToItk.h>
#include <mitkFiberBundleX.h>

// VTK
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkPolyLine.h>
#include <vtkCellData.h>

const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkStreamlineTrackingView::QmitkStreamlineTrackingView()
    : QmitkFunctionality()
    , m_Controls( 0 )
    , m_MultiWidget( NULL )
    , m_TensorImage( NULL )
    , m_SeedRoi( NULL )
{
}

// Destructor
QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView()
{

}

void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent )
{
    if ( !m_Controls )
    {
        // create GUI widgets from the Qt Designer's .ui file
        m_Controls = new Ui::QmitkStreamlineTrackingViewControls;
        m_Controls->setupUi( parent );

        connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) );
        connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) );
        connect( m_Controls->m_MinTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMinTractLengthChanged(int)) );
        connect( m_Controls->m_FaThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnFaThresholdChanged(int)) );
        connect( m_Controls->m_AngularThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAngularThresholdChanged(int)) );
        connect( m_Controls->m_StepsizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnStepsizeChanged(int)) );
        connect( m_Controls->m_fSlider, SIGNAL(valueChanged(int)), this, SLOT(OnfChanged(int)) );
        connect( m_Controls->m_gSlider, SIGNAL(valueChanged(int)), this, SLOT(OngChanged(int)) );
    }
}

void QmitkStreamlineTrackingView::OnfChanged(int value)
{
    m_Controls->m_fLabel->setText(QString("f: ")+QString::number((float)value/100));
}

void QmitkStreamlineTrackingView::OngChanged(int value)
{
    m_Controls->m_gLabel->setText(QString("g: ")+QString::number((float)value/100));
}

void QmitkStreamlineTrackingView::OnAngularThresholdChanged(int value)
{
    m_Controls->m_AngularThresholdLabel->setText(QString("Angular Threshold: ")+QString::number(value)+QString("°"));
}

void QmitkStreamlineTrackingView::OnSeedsPerVoxelChanged(int value)
{
    m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value));
}

void QmitkStreamlineTrackingView::OnMinTractLengthChanged(int value)
{
    m_Controls->m_MinTractLengthLabel->setText(QString("Min. Tract Length: ")+QString::number(value)+QString("mm"));
}

void QmitkStreamlineTrackingView::OnFaThresholdChanged(int value)
{
    m_Controls->m_FaThresholdLabel->setText(QString("FA Threshold: ")+QString::number((float)value/100));
}

void QmitkStreamlineTrackingView::OnStepsizeChanged(int value)
{
    if (value==0)
        m_Controls->m_StepsizeLabel->setText(QString("Stepsize: auto"));
    else
        m_Controls->m_StepsizeLabel->setText(QString("Stepsize: ")+QString::number((float)value/10)+QString("mm"));
}

void QmitkStreamlineTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
    m_MultiWidget = &stdMultiWidget;
}

void QmitkStreamlineTrackingView::StdMultiWidgetNotAvailable()
{
    m_MultiWidget = NULL;
}

void QmitkStreamlineTrackingView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
    m_TensorImageNode = NULL;
    m_TensorImage = NULL;
    m_SeedRoi = NULL;
    m_MaskImage = NULL;
    m_Controls->m_TensorImageLabel->setText("-");
    m_Controls->m_RoiImageLabel->setText("-");
    m_Controls->m_MaskImageLabel->setText("-");

    if(nodes.empty())
        return;

    for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
    {
        mitk::DataNode::Pointer node = *it;

        if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
        {
            if( dynamic_cast<mitk::TensorImage*>(node->GetData()) )
            {
                m_TensorImageNode = node;
                m_TensorImage = dynamic_cast<mitk::TensorImage*>(node->GetData());
                m_Controls->m_TensorImageLabel->setText(node->GetName().c_str());
            }
            else
            {
                bool isBinary = false;
                node->GetPropertyValue<bool>("binary", isBinary);
                if (isBinary && m_SeedRoi.IsNull())
                {
                    m_SeedRoi = dynamic_cast<mitk::Image*>(node->GetData());
                    m_Controls->m_RoiImageLabel->setText(node->GetName().c_str());
                }
                else if (isBinary)
                {
                    m_MaskImage = dynamic_cast<mitk::Image*>(node->GetData());
                    m_Controls->m_MaskImageLabel->setText(node->GetName().c_str());
                }
            }
        }
    }

    if(m_TensorImage.IsNotNull())
        m_Controls->commandLinkButton->setEnabled(true);
    else
        m_Controls->commandLinkButton->setEnabled(false);
}

void QmitkStreamlineTrackingView::DoFiberTracking()
{
    if (m_TensorImage.IsNull())
        return;

    typedef itk::Image< itk::DiffusionTensor3D<float>, 3> TensorImageType;
    typedef mitk::ImageToItk<TensorImageType> CastType;
    typedef mitk::ImageToItk<ItkUCharImageType> CastType2;

    CastType::Pointer caster = CastType::New();
    caster->SetInput(m_TensorImage);
    caster->Update();
    TensorImageType::Pointer image = caster->GetOutput();

    typedef itk::StreamlineTrackingFilter< float > FilterType;
    FilterType::Pointer filter = FilterType::New();
    filter->SetInput(image);
    filter->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelSlider->value());
    filter->SetFaThreshold((float)m_Controls->m_FaThresholdSlider->value()/100);
    filter->SetAngularThreshold(cos((float)m_Controls->m_AngularThresholdSlider->value()*M_PI/180));
    filter->SetStepSize((float)m_Controls->m_StepsizeSlider->value()/10);
    filter->SetF((float)m_Controls->m_fSlider->value()/100);
    filter->SetG((float)m_Controls->m_gSlider->value()/100);
    filter->SetInterpolate(m_Controls->m_InterpolationBox->isChecked());
    //filter->SetNumberOfThreads(1);

    if (m_SeedRoi.IsNotNull())
    {
        CastType2::Pointer caster2 = CastType2::New();
        caster2->SetInput(m_SeedRoi);
        caster2->Update();
        ItkUCharImageType::Pointer mask = caster2->GetOutput();
        filter->SetSeedImage(mask);
    }

    if (m_MaskImage.IsNotNull())
    {
        CastType2::Pointer caster2 = CastType2::New();
        caster2->SetInput(m_MaskImage);
        caster2->Update();
        ItkUCharImageType::Pointer mask = caster2->GetOutput();
        filter->SetMaskImage(mask);
    }

    filter->Update();

    vtkSmartPointer<vtkPolyData> fiberBundle = filter->GetFiberPolyData();
    if ( fiberBundle->GetNumberOfLines()==0 )
        return;
    mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberBundle);

    if (fib->RemoveShortFibers(m_Controls->m_MinTractLengthSlider->value()))
    {
        mitk::DataNode::Pointer node = mitk::DataNode::New();
        node->SetData(fib);
        QString name(m_TensorImageNode->GetName().c_str());
        name += "_FiberBundle";
        node->SetName(name.toStdString());
        node->SetVisibility(true);
        GetDataStorage()->Add(node);
    }
}

<commit_msg>using CastToItkImage instead of filter version<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>

// Qmitk
#include "QmitkStreamlineTrackingView.h"
#include "QmitkStdMultiWidget.h"

// Qt
#include <QMessageBox>

// MITK
#include <mitkImageToItk.h>
#include <mitkFiberBundleX.h>
#include <mitkImageCast.h>

// VTK
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkPolyLine.h>
#include <vtkCellData.h>

const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkStreamlineTrackingView::QmitkStreamlineTrackingView()
    : QmitkFunctionality()
    , m_Controls( 0 )
    , m_MultiWidget( NULL )
    , m_TensorImage( NULL )
    , m_SeedRoi( NULL )
{
}

// Destructor
QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView()
{

}

void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent )
{
    if ( !m_Controls )
    {
        // create GUI widgets from the Qt Designer's .ui file
        m_Controls = new Ui::QmitkStreamlineTrackingViewControls;
        m_Controls->setupUi( parent );

        connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) );
        connect( m_Controls->m_SeedsPerVoxelSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSeedsPerVoxelChanged(int)) );
        connect( m_Controls->m_MinTractLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(OnMinTractLengthChanged(int)) );
        connect( m_Controls->m_FaThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnFaThresholdChanged(int)) );
        connect( m_Controls->m_AngularThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAngularThresholdChanged(int)) );
        connect( m_Controls->m_StepsizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnStepsizeChanged(int)) );
        connect( m_Controls->m_fSlider, SIGNAL(valueChanged(int)), this, SLOT(OnfChanged(int)) );
        connect( m_Controls->m_gSlider, SIGNAL(valueChanged(int)), this, SLOT(OngChanged(int)) );
    }
}

void QmitkStreamlineTrackingView::OnfChanged(int value)
{
    m_Controls->m_fLabel->setText(QString("f: ")+QString::number((float)value/100));
}

void QmitkStreamlineTrackingView::OngChanged(int value)
{
    m_Controls->m_gLabel->setText(QString("g: ")+QString::number((float)value/100));
}

void QmitkStreamlineTrackingView::OnAngularThresholdChanged(int value)
{
    m_Controls->m_AngularThresholdLabel->setText(QString("Angular Threshold: ")+QString::number(value)+QString("°"));
}

void QmitkStreamlineTrackingView::OnSeedsPerVoxelChanged(int value)
{
    m_Controls->m_SeedsPerVoxelLabel->setText(QString("Seeds per Voxel: ")+QString::number(value));
}

void QmitkStreamlineTrackingView::OnMinTractLengthChanged(int value)
{
    m_Controls->m_MinTractLengthLabel->setText(QString("Min. Tract Length: ")+QString::number(value)+QString("mm"));
}

void QmitkStreamlineTrackingView::OnFaThresholdChanged(int value)
{
    m_Controls->m_FaThresholdLabel->setText(QString("FA Threshold: ")+QString::number((float)value/100));
}

void QmitkStreamlineTrackingView::OnStepsizeChanged(int value)
{
    if (value==0)
        m_Controls->m_StepsizeLabel->setText(QString("Stepsize: auto"));
    else
        m_Controls->m_StepsizeLabel->setText(QString("Stepsize: ")+QString::number((float)value/10)+QString("mm"));
}

void QmitkStreamlineTrackingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
    m_MultiWidget = &stdMultiWidget;
}

void QmitkStreamlineTrackingView::StdMultiWidgetNotAvailable()
{
    m_MultiWidget = NULL;
}

void QmitkStreamlineTrackingView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{
    m_TensorImageNode = NULL;
    m_TensorImage = NULL;
    m_SeedRoi = NULL;
    m_MaskImage = NULL;
    m_Controls->m_TensorImageLabel->setText("-");
    m_Controls->m_RoiImageLabel->setText("-");
    m_Controls->m_MaskImageLabel->setText("-");

    if(nodes.empty())
        return;

    for( std::vector<mitk::DataNode*>::iterator it = nodes.begin(); it != nodes.end(); ++it )
    {
        mitk::DataNode::Pointer node = *it;

        if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
        {
            if( dynamic_cast<mitk::TensorImage*>(node->GetData()) )
            {
                m_TensorImageNode = node;
                m_TensorImage = dynamic_cast<mitk::TensorImage*>(node->GetData());
                m_Controls->m_TensorImageLabel->setText(node->GetName().c_str());
            }
            else
            {
                bool isBinary = false;
                node->GetPropertyValue<bool>("binary", isBinary);
                if (isBinary && m_SeedRoi.IsNull())
                {
                    m_SeedRoi = dynamic_cast<mitk::Image*>(node->GetData());
                    m_Controls->m_RoiImageLabel->setText(node->GetName().c_str());
                }
                else if (isBinary)
                {
                    m_MaskImage = dynamic_cast<mitk::Image*>(node->GetData());
                    m_Controls->m_MaskImageLabel->setText(node->GetName().c_str());
                }
            }
        }
    }

    if(m_TensorImage.IsNotNull())
        m_Controls->commandLinkButton->setEnabled(true);
    else
        m_Controls->commandLinkButton->setEnabled(false);
}

void QmitkStreamlineTrackingView::DoFiberTracking()
{
    if (m_TensorImage.IsNull())
        return;

    typedef itk::Image< itk::DiffusionTensor3D<float>, 3> TensorImageType;
    typedef mitk::ImageToItk<TensorImageType> CastType;
    typedef mitk::ImageToItk<ItkUCharImageType> CastType2;

    CastType::Pointer caster = CastType::New();
    caster->SetInput(m_TensorImage);
    caster->Update();
    TensorImageType::Pointer image = caster->GetOutput();

    typedef itk::StreamlineTrackingFilter< float > FilterType;
    FilterType::Pointer filter = FilterType::New();
    filter->SetInput(image);
    filter->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelSlider->value());
    filter->SetFaThreshold((float)m_Controls->m_FaThresholdSlider->value()/100);
    filter->SetAngularThreshold(cos((float)m_Controls->m_AngularThresholdSlider->value()*M_PI/180));
    filter->SetStepSize((float)m_Controls->m_StepsizeSlider->value()/10);
    filter->SetF((float)m_Controls->m_fSlider->value()/100);
    filter->SetG((float)m_Controls->m_gSlider->value()/100);
    filter->SetInterpolate(m_Controls->m_InterpolationBox->isChecked());
    //filter->SetNumberOfThreads(1);

    if (m_SeedRoi.IsNotNull())
    {
        ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
        mitk::CastToItkImage<ItkUCharImageType>(m_SeedRoi, mask);
        filter->SetSeedImage(mask);
    }

    if (m_MaskImage.IsNotNull())
    {
        ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
        mitk::CastToItkImage<ItkUCharImageType>(m_MaskImage, mask);
        filter->SetMaskImage(mask);
    }

    filter->Update();

    vtkSmartPointer<vtkPolyData> fiberBundle = filter->GetFiberPolyData();
    if ( fiberBundle->GetNumberOfLines()==0 )
        return;
    mitk::FiberBundleX::Pointer fib = mitk::FiberBundleX::New(fiberBundle);

    if (fib->RemoveShortFibers(m_Controls->m_MinTractLengthSlider->value()))
    {
        mitk::DataNode::Pointer node = mitk::DataNode::New();
        node->SetData(fib);
        QString name(m_TensorImageNode->GetName().c_str());
        name += "_FiberBundle";
        node->SetName(name.toStdString());
        node->SetVisibility(true);
        GetDataStorage()->Add(node);
    }
}

<|endoftext|>