<commit_before>/*
* TLS echo server using BSD sockets
* (C) 2014 Jack Lloyd
*     2017 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "cli.h"
#include "sandbox.h"

#if defined(BOTAN_HAS_TLS) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) && \
   (defined(BOTAN_TARGET_OS_HAS_SOCKETS) || defined(BOTAN_TARGET_OS_HAS_WINSOCK2))

#include <botan/tls_server.h>
#include <botan/tls_policy.h>
#include <botan/hex.h>
#include <botan/internal/os_utils.h>

#include <list>
#include <fstream>

#include "credentials.h"
#include "socket_utils.h"

namespace Botan_CLI {

class TLS_Server final : public Command, public Botan::TLS::Callbacks
   {
   public:
      TLS_Server() : Command("tls_server cert key --port=443 --type=tcp --policy= --dump-traces= --max-clients=0")
         {
         init_sockets();
         }

      ~TLS_Server()
         {
         stop_sockets();
         }

      std::string group() const override
         {
         return "tls";
         }

      std::string description() const override
         {
         return "Accept TLS/DTLS connections from TLS/DTLS clients";
         }

      void go() override
         {
         const std::string server_crt = get_arg("cert");
         const std::string server_key = get_arg("key");
         const int port = get_arg_sz("port");
         const size_t max_clients = get_arg_sz("max-clients");
         const std::string transport = get_arg("type");
         const std::string dump_traces_to = get_arg("dump-traces");

         if(transport != "tcp" && transport != "udp")
            {
            throw CLI_Usage_Error("Invalid transport type '" + transport + "' for TLS");
            }

         m_is_tcp = (transport == "tcp");

         std::unique_ptr<Botan::TLS::Policy> policy;
         const std::string policy_file = get_arg("policy");
         if(policy_file.size() > 0)
            {
            std::ifstream policy_stream(policy_file);
            if(!policy_stream.good())
               {
               error_output() << "Failed reading policy file\n";
               return;
               }
            policy.reset(new Botan::TLS::Text_Policy(policy_stream));
            }

         if(!policy)
            {
            policy.reset(new Botan::TLS::Policy);
            }

         Botan::TLS::Session_Manager_In_Memory session_manager(rng()); // TODO sqlite3

         Basic_Credentials_Manager creds(rng(), server_crt, server_key);

         output() << "Listening for new connections on " << transport << " port " << port << std::endl;

	 if(!m_sandbox.init())
            {
            error_output() << "Failed sandboxing\n";
	    return;
	    }

         int server_fd = make_server_socket(port);
         size_t clients_served = 0;

         while(true)
            {
            if(max_clients > 0 && clients_served >= max_clients)
               break;

            if(m_is_tcp)
               {
               m_socket = ::accept(server_fd, nullptr, nullptr);
               }
            else
               {
               struct sockaddr_in from;
               socklen_t from_len = sizeof(sockaddr_in);

               // macOS handles zero size buffers differently - it will return 0 even if there's no incoming data,
               // and after that connect() will fail as sockaddr_in from is not initialized
               int dummy;
               if(::recvfrom(server_fd, &dummy, sizeof(dummy), MSG_PEEK, reinterpret_cast<struct sockaddr*>(&from), &from_len) != 0)
                  {
                  throw CLI_Error("Could not peek next packet");
                  }

               if(::connect(server_fd, reinterpret_cast<struct sockaddr*>(&from), from_len) != 0)
                  {
                  throw CLI_Error("Could not connect UDP socket");
                  }
               m_socket = server_fd;
               }

            clients_served++;

            Botan::TLS::Server server(
               *this,
               session_manager,
               creds,
               *policy,
               rng(),
               m_is_tcp == false);

            std::unique_ptr<std::ostream> dump_stream;

            if(!dump_traces_to.empty())
               {
               uint64_t timestamp = Botan::OS::get_high_resolution_clock();
               const std::string dump_file =
                  dump_traces_to + "/tls_" + std::to_string(timestamp) + ".bin";
               dump_stream.reset(new std::ofstream(dump_file.c_str()));
               }

            try
               {
               while(!server.is_closed())
                  {
                  try
                     {
                     uint8_t buf[4 * 1024] = { 0 };
                     ssize_t got = ::read(m_socket, buf, sizeof(buf));

                     if(got == -1)
                        {
                        error_output() << "Error in socket read - " << std::strerror(errno) << std::endl;
                        break;
                        }

                     if(got == 0)
                        {
                        error_output() << "EOF on socket" << std::endl;
                        break;
                        }

                     if(dump_stream)
                        {
                        dump_stream->write(reinterpret_cast<const char*>(buf), got);
                        }

                     server.received_data(buf, got);

                     while(server.is_active() && !m_pending_output.empty())
                        {
                        std::string output = m_pending_output.front();
                        m_pending_output.pop_front();
                        server.send(output);

                        if(output == "quit\n")
                           {
                           server.close();
                           }
                        }
                     }
                  catch(std::exception& e)
                     {
                     error_output() << "Connection problem: " << e.what() << std::endl;
                     if(m_is_tcp)
                        {
                        ::close(m_socket);
                        m_socket = -1;
                        }
                     }
                  }
               }
            catch(Botan::Exception& e)
               {
               error_output() << "Connection failed: " << e.what() << "\n";
               }

            if(m_is_tcp)
               {
               ::close(m_socket);
               m_socket = -1;
               }
            }

         ::close(server_fd);
         }
   private:
      int make_server_socket(uint16_t port)
         {
         const int type = m_is_tcp ? SOCK_STREAM : SOCK_DGRAM;

         int fd = ::socket(PF_INET, type, 0);
         if(fd == -1)
            {
            throw CLI_Error("Unable to acquire socket");
            }

         sockaddr_in socket_info;
         Botan::clear_mem(&socket_info, 1);
         socket_info.sin_family = AF_INET;
         socket_info.sin_port = htons(port);

         // FIXME: support limiting listeners
         socket_info.sin_addr.s_addr = INADDR_ANY;

         if(::bind(fd, reinterpret_cast<struct sockaddr*>(&socket_info), sizeof(struct sockaddr)) != 0)
            {
            ::close(fd);
            throw CLI_Error("server bind failed");
            }

         if(m_is_tcp)
            {
            if(::listen(fd, 100) != 0)
               {
               ::close(fd);
               throw CLI_Error("listen failed");
               }
            }
         return fd;
         }

      bool tls_session_established(const Botan::TLS::Session& session) override
         {
         output() << "Handshake complete, " << session.version().to_string()
                  << " using " << session.ciphersuite().to_string() << std::endl;

         if(!session.session_id().empty())
            {
            output() << "Session ID " << Botan::hex_encode(session.session_id()) << std::endl;
            }

         if(!session.session_ticket().empty())
            {
            output() << "Session ticket " << Botan::hex_encode(session.session_ticket()) << std::endl;
            }

         return true;
         }

      void tls_record_received(uint64_t, const uint8_t input[], size_t input_len) override
         {
         for(size_t i = 0; i != input_len; ++i)
            {
            const char c = static_cast<char>(input[i]);
            m_line_buf += c;
            if(c == '\n')
               {
               m_pending_output.push_back(m_line_buf);
               m_line_buf.clear();
               }
            }
         };

      void tls_emit_data(const uint8_t buf[], size_t length) override
         {
         if(m_is_tcp)
            {
            ssize_t sent = ::send(m_socket, buf, length, MSG_NOSIGNAL);

            if(sent == -1)
               {
               error_output() << "Error writing to socket - " << std::strerror(errno) << std::endl;
               }
            else if(sent != static_cast<ssize_t>(length))
               {
               error_output() << "Packet of length " << length << " truncated to " << sent << std::endl;
               }
            }
         else
            {
            while(length)
               {
               ssize_t sent = ::send(m_socket, buf, length, MSG_NOSIGNAL);

               if(sent == -1)
                  {
                  if(errno == EINTR)
                     {
                     sent = 0;
                     }
                  else
                     {
                     throw CLI_Error("Socket write failed");
                     }
                  }

               buf += sent;
               length -= sent;
               }
            }
         }

      void tls_alert(Botan::TLS::Alert alert) override
         {
         output() << "Alert: " << alert.type_string() << std::endl;
         }

      std::string tls_server_choose_app_protocol(const std::vector<std::string>&) override
         {
         // we ignore whatever the client sends here
         return "echo/0.1";
         }

      int m_socket = -1;
      bool m_is_tcp = false;
      std::string m_line_buf;
      std::list<std::string> m_pending_output;
      Sandbox m_sandbox;
   };

BOTAN_REGISTER_COMMAND("tls_server", TLS_Server);

}

#endif
<commit_msg>Windows compilation fix<commit_after>/*
* TLS echo server using BSD sockets
* (C) 2014 Jack Lloyd
*     2017 René Korthaus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "cli.h"
#include "sandbox.h"

#if defined(BOTAN_HAS_TLS) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) && \
   (defined(BOTAN_TARGET_OS_HAS_SOCKETS) || defined(BOTAN_TARGET_OS_HAS_WINSOCK2))

#include <botan/tls_server.h>
#include <botan/tls_policy.h>
#include <botan/hex.h>
#include <botan/internal/os_utils.h>

#include <list>
#include <fstream>

#include "credentials.h"
#include "socket_utils.h"

namespace Botan_CLI {

class TLS_Server final : public Command, public Botan::TLS::Callbacks
   {
   public:
      TLS_Server() : Command("tls_server cert key --port=443 --type=tcp --policy= --dump-traces= --max-clients=0")
         {
         init_sockets();
         }

      ~TLS_Server()
         {
         stop_sockets();
         }

      std::string group() const override
         {
         return "tls";
         }

      std::string description() const override
         {
         return "Accept TLS/DTLS connections from TLS/DTLS clients";
         }

      void go() override
         {
         const std::string server_crt = get_arg("cert");
         const std::string server_key = get_arg("key");
         const int port = get_arg_sz("port");
         const size_t max_clients = get_arg_sz("max-clients");
         const std::string transport = get_arg("type");
         const std::string dump_traces_to = get_arg("dump-traces");

         if(transport != "tcp" && transport != "udp")
            {
            throw CLI_Usage_Error("Invalid transport type '" + transport + "' for TLS");
            }

         m_is_tcp = (transport == "tcp");

         std::unique_ptr<Botan::TLS::Policy> policy;
         const std::string policy_file = get_arg("policy");
         if(policy_file.size() > 0)
            {
            std::ifstream policy_stream(policy_file);
            if(!policy_stream.good())
               {
               error_output() << "Failed reading policy file\n";
               return;
               }
            policy.reset(new Botan::TLS::Text_Policy(policy_stream));
            }

         if(!policy)
            {
            policy.reset(new Botan::TLS::Policy);
            }

         Botan::TLS::Session_Manager_In_Memory session_manager(rng()); // TODO sqlite3

         Basic_Credentials_Manager creds(rng(), server_crt, server_key);

         output() << "Listening for new connections on " << transport << " port " << port << std::endl;

	 if(!m_sandbox.init())
            {
            error_output() << "Failed sandboxing\n";
	    return;
	    }

         int server_fd = make_server_socket(port);
         size_t clients_served = 0;

         while(true)
            {
            if(max_clients > 0 && clients_served >= max_clients)
               break;

            if(m_is_tcp)
               {
               m_socket = ::accept(server_fd, nullptr, nullptr);
               }
            else
               {
               struct sockaddr_in from;
               socklen_t from_len = sizeof(sockaddr_in);

               // macOS handles zero size buffers differently - it will return 0 even if there's no incoming data,
               // and after that connect() will fail as sockaddr_in from is not initialized
               int dummy;
               if(::recvfrom(server_fd, reinterpret_cast<char*>(&dummy), sizeof(dummy), MSG_PEEK, reinterpret_cast<struct sockaddr*>(&from), &from_len) != 0)
                  {
                  throw CLI_Error("Could not peek next packet");
                  }

               if(::connect(server_fd, reinterpret_cast<struct sockaddr*>(&from), from_len) != 0)
                  {
                  throw CLI_Error("Could not connect UDP socket");
                  }
               m_socket = server_fd;
               }

            clients_served++;

            Botan::TLS::Server server(
               *this,
               session_manager,
               creds,
               *policy,
               rng(),
               m_is_tcp == false);

            std::unique_ptr<std::ostream> dump_stream;

            if(!dump_traces_to.empty())
               {
               uint64_t timestamp = Botan::OS::get_high_resolution_clock();
               const std::string dump_file =
                  dump_traces_to + "/tls_" + std::to_string(timestamp) + ".bin";
               dump_stream.reset(new std::ofstream(dump_file.c_str()));
               }

            try
               {
               while(!server.is_closed())
                  {
                  try
                     {
                     uint8_t buf[4 * 1024] = { 0 };
                     ssize_t got = ::read(m_socket, buf, sizeof(buf));

                     if(got == -1)
                        {
                        error_output() << "Error in socket read - " << std::strerror(errno) << std::endl;
                        break;
                        }

                     if(got == 0)
                        {
                        error_output() << "EOF on socket" << std::endl;
                        break;
                        }

                     if(dump_stream)
                        {
                        dump_stream->write(reinterpret_cast<const char*>(buf), got);
                        }

                     server.received_data(buf, got);

                     while(server.is_active() && !m_pending_output.empty())
                        {
                        std::string output = m_pending_output.front();
                        m_pending_output.pop_front();
                        server.send(output);

                        if(output == "quit\n")
                           {
                           server.close();
                           }
                        }
                     }
                  catch(std::exception& e)
                     {
                     error_output() << "Connection problem: " << e.what() << std::endl;
                     if(m_is_tcp)
                        {
                        ::close(m_socket);
                        m_socket = -1;
                        }
                     }
                  }
               }
            catch(Botan::Exception& e)
               {
               error_output() << "Connection failed: " << e.what() << "\n";
               }

            if(m_is_tcp)
               {
               ::close(m_socket);
               m_socket = -1;
               }
            }

         ::close(server_fd);
         }
   private:
      int make_server_socket(uint16_t port)
         {
         const int type = m_is_tcp ? SOCK_STREAM : SOCK_DGRAM;

         int fd = ::socket(PF_INET, type, 0);
         if(fd == -1)
            {
            throw CLI_Error("Unable to acquire socket");
            }

         sockaddr_in socket_info;
         Botan::clear_mem(&socket_info, 1);
         socket_info.sin_family = AF_INET;
         socket_info.sin_port = htons(port);

         // FIXME: support limiting listeners
         socket_info.sin_addr.s_addr = INADDR_ANY;

         if(::bind(fd, reinterpret_cast<struct sockaddr*>(&socket_info), sizeof(struct sockaddr)) != 0)
            {
            ::close(fd);
            throw CLI_Error("server bind failed");
            }

         if(m_is_tcp)
            {
            if(::listen(fd, 100) != 0)
               {
               ::close(fd);
               throw CLI_Error("listen failed");
               }
            }
         return fd;
         }

      bool tls_session_established(const Botan::TLS::Session& session) override
         {
         output() << "Handshake complete, " << session.version().to_string()
                  << " using " << session.ciphersuite().to_string() << std::endl;

         if(!session.session_id().empty())
            {
            output() << "Session ID " << Botan::hex_encode(session.session_id()) << std::endl;
            }

         if(!session.session_ticket().empty())
            {
            output() << "Session ticket " << Botan::hex_encode(session.session_ticket()) << std::endl;
            }

         return true;
         }

      void tls_record_received(uint64_t, const uint8_t input[], size_t input_len) override
         {
         for(size_t i = 0; i != input_len; ++i)
            {
            const char c = static_cast<char>(input[i]);
            m_line_buf += c;
            if(c == '\n')
               {
               m_pending_output.push_back(m_line_buf);
               m_line_buf.clear();
               }
            }
         };

      void tls_emit_data(const uint8_t buf[], size_t length) override
         {
         if(m_is_tcp)
            {
            ssize_t sent = ::send(m_socket, buf, length, MSG_NOSIGNAL);

            if(sent == -1)
               {
               error_output() << "Error writing to socket - " << std::strerror(errno) << std::endl;
               }
            else if(sent != static_cast<ssize_t>(length))
               {
               error_output() << "Packet of length " << length << " truncated to " << sent << std::endl;
               }
            }
         else
            {
            while(length)
               {
               ssize_t sent = ::send(m_socket, buf, length, MSG_NOSIGNAL);

               if(sent == -1)
                  {
                  if(errno == EINTR)
                     {
                     sent = 0;
                     }
                  else
                     {
                     throw CLI_Error("Socket write failed");
                     }
                  }

               buf += sent;
               length -= sent;
               }
            }
         }

      void tls_alert(Botan::TLS::Alert alert) override
         {
         output() << "Alert: " << alert.type_string() << std::endl;
         }

      std::string tls_server_choose_app_protocol(const std::vector<std::string>&) override
         {
         // we ignore whatever the client sends here
         return "echo/0.1";
         }

      int m_socket = -1;
      bool m_is_tcp = false;
      std::string m_line_buf;
      std::list<std::string> m_pending_output;
      Sandbox m_sandbox;
   };

BOTAN_REGISTER_COMMAND("tls_server", TLS_Server);

}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) 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. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * 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 files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include <stdio.h>
#include <math.h>
#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
#ifdef _MSC_VER
#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
#endif

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

//<---- Convex Object
dReal planes[]= // planes for a cube
  {
    1.0f ,0.0f ,0.0f ,0.25f,
    0.0f ,1.0f ,0.0f ,0.25f,
    0.0f ,0.0f ,1.0f ,0.25f,
    -1.0f,0.0f ,0.0f ,0.25f,
    0.0f ,-1.0f,0.0f ,0.25f,
    0.0f ,0.0f ,-1.0f,0.25f
    /*
    1.0f ,0.0f ,0.0f ,2.0f,
    0.0f ,1.0f ,0.0f ,1.0f,
    0.0f ,0.0f ,1.0f ,1.0f,
    0.0f ,0.0f ,-1.0f,1.0f,
    0.0f ,-1.0f,0.0f ,1.0f,
    -1.0f,0.0f ,0.0f ,0.0f
    */
  };
const unsigned int planecount=6;

dReal points[]= // points for a cube
  {
    0.25f,0.25f,0.25f,  //  point 0
    -0.25f,0.25f,0.25f, //  point 1

    0.25f,-0.25f,0.25f, //  point 2
    -0.25f,-0.25f,0.25f,//  point 3

    0.25f,0.25f,-0.25f, //  point 4
    -0.25f,0.25f,-0.25f,//  point 5

    0.25f,-0.25f,-0.25f,//  point 6
    -0.25f,-0.25f,-0.25f,// point 7
  };
const unsigned int pointcount=8;
unsigned int polygons[] = //Polygons for a cube (6 squares)
  {
    4,0,2,6,4, // positive X
    4,1,0,4,5, // positive Y
    4,0,1,3,2, // positive Z
    4,3,1,5,7, // negative X
    4,2,3,7,6, // negative Y
    4,5,4,6,7, // negative Z
  };
//----> Convex Object

#ifdef dDOUBLE
#define dsDrawConvex dsDrawConvexD
#endif

dGeomID geoms[2];
dSpaceID space;
dWorldID world;
dJointGroupID contactgroup;

void start()
{
  // adjust the starting viewpoint a bit
  float xyz[3],hpr[3];
  dsGetViewpoint (xyz,hpr);
  hpr[0] += 7;
  dsSetViewpoint (xyz,hpr);
  geoms[0]=dCreateConvex (space,
			  planes,
			  planecount,
			  points,
			  pointcount,
			  polygons);
  dGeomSetPosition (geoms[0],0,0,0.25);
  geoms[1]=dCreateConvex (space,
			  planes,
			  planecount,
			  points,
			  pointcount,
			  polygons);
  dGeomSetPosition (geoms[1],0.25,0.25,0.70);

}

int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
			  dContactGeom *contact, int skip);
void simLoop (int pause)
{
  static bool DumpInfo=true;
  const dReal ss[3] = {0.02,0.02,0.02};
  dContactGeom contacts[8];
  int contactcount = dCollideConvexConvex(geoms[0],geoms[1],8,contacts,sizeof(dContactGeom));
  //fprintf(stdout,"Contact Count %d\n",contactcount);
  const dReal* pos;
  const dReal* R;
  dsSetTexture (DS_WOOD);
  pos = dGeomGetPosition (geoms[0]);
  R = dGeomGetRotation (geoms[0]);
  dsSetColor (0.6f,0.6f,1);
  dsDrawConvex(pos,R,planes,
	       planecount,
	       points,
	       pointcount,
	       polygons);
  pos = dGeomGetPosition (geoms[1]);
  R = dGeomGetRotation (geoms[1]);
  dsSetColor (0.4f,1,1);
  dsDrawConvex(pos,R,planes,
	       planecount,
	       points,
	       pointcount,
	       polygons);
  /*if (show_contacts) */
  dMatrix3 RI;
  dRSetIdentity (RI);
  dsSetColor (1.0f,0,0);
  for(int i=0;i<contactcount;++i)
    {
      if(DumpInfo)
	{
	  //DumpInfo=false;
	  fprintf(stdout,"Contact %d Normal %f,%f,%f Depth %f\n",
		  i,
		  contacts[i].normal[0],
		  contacts[i].normal[1],
		  contacts[i].normal[2],
		  contacts[i].depth);
	}
      dsDrawBox (contacts[i].pos,RI,ss);
    }
  if(DumpInfo)
    DumpInfo=false;

}

void command (int cmd)
{
  dsPrint ("received command %d (`%c')\n",cmd,cmd);
}

int main (int argc, char **argv)
{
  // setup pointers to callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = command;
  fn.stop = 0;
  fn.path_to_textures = "../../drawstuff/textures";	// uses default
  world = dWorldCreate();
  space = dHashSpaceCreate (0);
  contactgroup = dJointGroupCreate (0);

  // run simulation
  dsSimulationLoop (argc,argv,400,400,&fn);
  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}
<commit_msg>fix double precision build, remove ctrl-M noise<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) 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. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * 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 files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include <stdio.h>
#include <math.h>
#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
#ifdef _MSC_VER
#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
#endif

#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif

//<---- Convex Object
dReal planes[]= // planes for a cube
  {
    1.0f ,0.0f ,0.0f ,0.25f,
    0.0f ,1.0f ,0.0f ,0.25f,
    0.0f ,0.0f ,1.0f ,0.25f,
    -1.0f,0.0f ,0.0f ,0.25f,
    0.0f ,-1.0f,0.0f ,0.25f,
    0.0f ,0.0f ,-1.0f,0.25f
    /*
    1.0f ,0.0f ,0.0f ,2.0f,
    0.0f ,1.0f ,0.0f ,1.0f,
    0.0f ,0.0f ,1.0f ,1.0f,
    0.0f ,0.0f ,-1.0f,1.0f,
    0.0f ,-1.0f,0.0f ,1.0f,
    -1.0f,0.0f ,0.0f ,0.0f
    */
  };
const unsigned int planecount=6;

dReal points[]= // points for a cube
  {
    0.25f,0.25f,0.25f,  //  point 0
    -0.25f,0.25f,0.25f, //  point 1

    0.25f,-0.25f,0.25f, //  point 2
    -0.25f,-0.25f,0.25f,//  point 3

    0.25f,0.25f,-0.25f, //  point 4
    -0.25f,0.25f,-0.25f,//  point 5

    0.25f,-0.25f,-0.25f,//  point 6
    -0.25f,-0.25f,-0.25f,// point 7
  };
const unsigned int pointcount=8;
unsigned int polygons[] = //Polygons for a cube (6 squares)
  {
    4,0,2,6,4, // positive X
    4,1,0,4,5, // positive Y
    4,0,1,3,2, // positive Z
    4,3,1,5,7, // negative X
    4,2,3,7,6, // negative Y
    4,5,4,6,7, // negative Z
  };
//----> Convex Object

#ifdef dDOUBLE
#define dsDrawConvex dsDrawConvexD
#define dsDrawBox dsDrawBoxD
#endif

dGeomID geoms[2];
dSpaceID space;
dWorldID world;
dJointGroupID contactgroup;

void start()
{
  // adjust the starting viewpoint a bit
  float xyz[3],hpr[3];
  dsGetViewpoint (xyz,hpr);
  hpr[0] += 7;
  dsSetViewpoint (xyz,hpr);
  geoms[0]=dCreateConvex (space,
			  planes,
			  planecount,
			  points,
			  pointcount,
			  polygons);
  dGeomSetPosition (geoms[0],0,0,0.25);
  geoms[1]=dCreateConvex (space,
			  planes,
			  planecount,
			  points,
			  pointcount,
			  polygons);
  dGeomSetPosition (geoms[1],0.25,0.25,0.70);

}

int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags,
			  dContactGeom *contact, int skip);
void simLoop (int pause)
{
  static bool DumpInfo=true;
  const dReal ss[3] = {0.02,0.02,0.02};
  dContactGeom contacts[8];
  int contactcount = dCollideConvexConvex(geoms[0],geoms[1],8,contacts,sizeof(dContactGeom));
  //fprintf(stdout,"Contact Count %d\n",contactcount);
  const dReal* pos;
  const dReal* R;
  dsSetTexture (DS_WOOD);
  pos = dGeomGetPosition (geoms[0]);
  R = dGeomGetRotation (geoms[0]);
  dsSetColor (0.6f,0.6f,1);
  dsDrawConvex(pos,R,planes,
	       planecount,
	       points,
	       pointcount,
	       polygons);
  pos = dGeomGetPosition (geoms[1]);
  R = dGeomGetRotation (geoms[1]);
  dsSetColor (0.4f,1,1);
  dsDrawConvex(pos,R,planes,
	       planecount,
	       points,
	       pointcount,
	       polygons);
  /*if (show_contacts) */
  dMatrix3 RI;
  dRSetIdentity (RI);
  dsSetColor (1.0f,0,0);
  for(int i=0;i<contactcount;++i)
    {
      if(DumpInfo)
	{
	  //DumpInfo=false;
	  fprintf(stdout,"Contact %d Normal %f,%f,%f Depth %f\n",
		  i,
		  contacts[i].normal[0],
		  contacts[i].normal[1],
		  contacts[i].normal[2],
		  contacts[i].depth);
	}
      dsDrawBox (contacts[i].pos,RI,ss);
    }
  if(DumpInfo)
    DumpInfo=false;

}

void command (int cmd)
{
  dsPrint ("received command %d (`%c')\n",cmd,cmd);
}

int main (int argc, char **argv)
{
  // setup pointers to callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = command;
  fn.stop = 0;
  fn.path_to_textures = "../../drawstuff/textures";	// uses default
  world = dWorldCreate();
  space = dHashSpaceCreate (0);
  contactgroup = dJointGroupCreate (0);

  // run simulation
  dsSimulationLoop (argc,argv,400,400,&fn);
  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}
<|endoftext|>


<commit_before>// =============================================================================
//
// Copyright (c) 2013-2014 Christopher Baker <http://christopherbaker.net>
//               2014 Brannon Dorsey <http://brannondorsey.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// =============================================================================

#include "Project.h"
#include "ofUtils.h"

namespace of {
namespace Sketch {

const std::string Project::SKETCH_FILE_EXTENSION = "sketch";

Project::~Project()
{
}

Project::Project(const std::string& path): _path(path), _isLoaded(false)
{
    // this is not efficient at all! I am just keeping these FileTemplate loads in the project
    // constructor because it makes the most sense architecure wise.
    _classFileTemplate = ofBufferFromFile(ofToDataPath("Resources/Templates/SketchTemplates/class.tmpl")).getText();
    load(_path, getName());
}

void Project::load(const std::string& path, const std::string& name)
{
    _sketchDir = ofDirectory(ofToDataPath(path + "/sketch"));

    _data.clear();

    if (_sketchDir.exists())
    {
        _sketchDir.listDir();

        std::vector<ofFile> files = _sketchDir.getFiles();

        int classCounter = 0;

        for (std::size_t i = 0; i < files.size(); ++i)
        {
            ofFile file = files[i];

            if (file.getBaseName() == name)
            {
                file.open(file.getAbsolutePath());
                _data["projectFile"]["name"] = file.getBaseName();
                _data["projectFile"]["fileName"] = file.getFileName();
                _data["projectFile"]["fileContents"] = file.readToBuffer().getText();
            }
            else if (file.getExtension() == SKETCH_FILE_EXTENSION)
            {
                file.open(file.getAbsolutePath());
                _data["classes"][classCounter]["name"] = file.getBaseName();
                _data["classes"][classCounter]["fileName"] = file.getFileName();
                _data["classes"][classCounter]["fileContents"] = file.readToBuffer().getText();
                classCounter++;
            }
        }

        _isLoaded = true;
    }
}

bool Project::isLoaded() const
{
    return _isLoaded;
}

// saves differences only
void Project::save(const Json::Value& data)
{
    // this is not working for some reason...
    if (_data != data)
    {
        ofLogVerbose("Project::save") << data.toStyledString();

        if (_data["projectFile"] != data["projectFile"])
        {
            _data["projectFile"] = data["projectFile"];
            _saveFile(_data["projectFile"]);
        }

        // uses nested for loop in case classes are not in the same order
        std::vector<Json::Value> newClasses;
        std::vector<Json::Value> deletedClasses;

        for (int i = 0; i < _data["classes"].size(); ++i)
        {
            Json::Value& classFile = _data["classes"][i];

            bool matchFound = false;

            for (int j = 0; j < data.size(); ++j)
            {
                const Json::Value& newClassFile = data["classes"][j];

                if (classFile["fileName"] == newClassFile["fileName"])
                {
                    if (classFile != newClassFile)
                    {
                        classFile = newClassFile;
                        _saveFile(classFile);
                    }

                    matchFound = true;
                    break;
                }
            }

            if (!matchFound) _saveFile(classFile); // class is new
        }
    }
    else
    {
        ofLogNotice("Project::save") << "Project data is the same. Not saving project.";
    }
}

bool Project::create(const std::string& path)
{
    ofDirectory project(ofToDataPath(path));

    if (!project.exists())
    {
        ofDirectory temp(ofToDataPath("Resources/Templates/SimpleTemplate"));
        temp.copyTo(ofToDataPath(path));
        return true;
    }

    return false;
}

bool Project::remove()
{
    ofDirectory projectDir(getPath());
    return projectDir.remove(true);
}

bool Project::rename(const std::string& newName)
{
    if (isLoaded())
    {
        ofLogVerbose("Project::rename") << "renaming project \"" << getName() << "\" to \"" << newName + "\"";

        ofFile projectDir(getPath());

        std::string oldProjectName = getName();

        ofLogVerbose("Project::rename") << "project path: " << getPath() << " Renamed to: " << projectDir.getEnclosingDirectory() + newName;

        if (!projectDir.renameTo(projectDir.getEnclosingDirectory() + newName)) return false;

        _path = projectDir.getAbsolutePath();

        ofFile projectFile(projectDir.getAbsolutePath() + "/sketch/" + oldProjectName + "." + SKETCH_FILE_EXTENSION);

        ofLogVerbose("Project::rename") << "projectDir path after rename: " << projectDir.getAbsolutePath();

        ofLogVerbose("Project::rename") << "projectFile path: " << projectFile.getAbsolutePath();

        if (!projectFile.renameTo(projectDir.getAbsolutePath() + "/sketch/" + newName + "." + SKETCH_FILE_EXTENSION)) return false;

        ofLogVerbose("Project::rename") << "projectFile path after rename: " << projectFile.getAbsolutePath();

        _data["projectFile"]["name"] = newName;

        _data["projectFile"]["fileName"] = newName + "." + SKETCH_FILE_EXTENSION;

        return true;
    }
    else
    {
        ofLogVerbose("Project::rename") << "Cannot rename project, it is not loaded.";
        return false;
    }

}

Json::Value Project::createClass(const std::string& className)
{
    std::string fileContents = _classFileTemplate;
    ofStringReplace(fileContents, "<classname>", className);

    ofLogVerbose("Project::createClass") << "fileContents: "<< fileContents;

    Json::Value classFile;
    // TODO: Load extension from settings
    classFile["fileName"] = className + "." + SKETCH_FILE_EXTENSION;
    classFile["name"] = className;
    classFile["fileContents"] = fileContents;
    _data["classes"][getNumClasses()] = classFile;
    // TODO: re-loading is a terribly slow way to delete. Come back and optimize.
    // Simply need to remove the Json::Value class in _data["classes"]
    _saveFile(classFile);
    return classFile;
}

bool Project::deleteClass(const std::string& className)
{
    if (isLoaded())
    {
        ofFile file(_sketchDir.getAbsolutePath() + "/" + className + "." + SKETCH_FILE_EXTENSION);

        if (file.exists())
        {
            file.remove();
            // TODO: re-loading is a terribly slow way to delete. Come back and optimize.
            // Simply need to remove the Json::Value class in _data["classes"]
            load(_path, getName());
            return true;
        }
    }

    return false;
}

bool Project::renameClass(const std::string& currentName, const std::string& newName)
{
    if (isLoaded())
    {
        ofLogVerbose("Project::renameClass") << "Renaming class...";

        ofFile file(_sketchDir.getAbsolutePath() + "/" + currentName + "." + SKETCH_FILE_EXTENSION);
        if (file.exists() && hasClasses())
        {
            for (int i = 0; i < getNumClasses(); ++i)
            {
                if (_data["classes"][i]["name"] == currentName)
                {
                    _data["classes"][i]["name"] = newName;
                    _data["classes"][i]["fileName"] = newName + "." + SKETCH_FILE_EXTENSION;

                    file.renameTo(_sketchDir.getAbsolutePath() + "/" + newName + "." + SKETCH_FILE_EXTENSION);
                    return true;
                }
            }
        }
    }

    return false;
}

bool Project::hasClasses() const
{
    return !_data["classes"].empty();
}

bool Project::isClassName(const std::string& className) const
{
    if (hasClasses())
    {
        for (int i = 0; i < getNumClasses(); ++i)
        {
            if (_data["classes"][i]["name"] == className)
            {
                return true;
            }
        }
    }

    return false;
}

int Project::getNumClasses() const
{
    return _data["classes"].size();
}

const std::string& Project::getPath() const
{
    return _path;
}

std::string Project::getName() const
{
    ofFile project(_path);
    return project.getBaseName();
}

const Json::Value& Project::getData() const
{
    return _data;
}

void Project::_saveFile(const Json::Value& fileData)
{
    ofBuffer fileBuffer(fileData["fileContents"].asString());
    ofBufferToFile(getPath() + "/sketch/" + fileData["fileName"].asString(), fileBuffer);
}

} } // namespace of::Sketch
<commit_msg>Remove some iteration warnings.<commit_after>// =============================================================================
//
// Copyright (c) 2013-2014 Christopher Baker <http://christopherbaker.net>
//               2014 Brannon Dorsey <http://brannondorsey.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// =============================================================================

#include "Project.h"
#include "ofUtils.h"

namespace of {
namespace Sketch {

const std::string Project::SKETCH_FILE_EXTENSION = "sketch";

Project::~Project()
{
}

Project::Project(const std::string& path): _path(path), _isLoaded(false)
{
    // this is not efficient at all! I am just keeping these FileTemplate loads in the project
    // constructor because it makes the most sense architecure wise.
    _classFileTemplate = ofBufferFromFile(ofToDataPath("Resources/Templates/SketchTemplates/class.tmpl")).getText();
    load(_path, getName());
}

void Project::load(const std::string& path, const std::string& name)
{
    _sketchDir = ofDirectory(ofToDataPath(path + "/sketch"));

    _data.clear();

    if (_sketchDir.exists())
    {
        _sketchDir.listDir();

        std::vector<ofFile> files = _sketchDir.getFiles();

        int classCounter = 0;

        for (std::size_t i = 0; i < files.size(); ++i)
        {
            ofFile file = files[i];

            if (file.getBaseName() == name)
            {
                file.open(file.getAbsolutePath());
                _data["projectFile"]["name"] = file.getBaseName();
                _data["projectFile"]["fileName"] = file.getFileName();
                _data["projectFile"]["fileContents"] = file.readToBuffer().getText();
            }
            else if (file.getExtension() == SKETCH_FILE_EXTENSION)
            {
                file.open(file.getAbsolutePath());
                _data["classes"][classCounter]["name"] = file.getBaseName();
                _data["classes"][classCounter]["fileName"] = file.getFileName();
                _data["classes"][classCounter]["fileContents"] = file.readToBuffer().getText();
                classCounter++;
            }
        }

        _isLoaded = true;
    }
}

bool Project::isLoaded() const
{
    return _isLoaded;
}

// saves differences only
void Project::save(const Json::Value& data)
{
    // this is not working for some reason...
    if (_data != data)
    {
        ofLogVerbose("Project::save") << data.toStyledString();

        if (_data["projectFile"] != data["projectFile"])
        {
            _data["projectFile"] = data["projectFile"];
            _saveFile(_data["projectFile"]);
        }

        // uses nested for loop in case classes are not in the same order
        std::vector<Json::Value> newClasses;
        std::vector<Json::Value> deletedClasses;

        for (int i = 0; i < _data["classes"].size(); ++i)
        {
            Json::Value& classFile = _data["classes"][i];

            bool matchFound = false;

            for (int j = 0; j < data.size(); ++j)
            {
                const Json::Value& newClassFile = data["classes"][j];

                if (classFile["fileName"] == newClassFile["fileName"])
                {
                    if (classFile != newClassFile)
                    {
                        classFile = newClassFile;
                        _saveFile(classFile);
                    }

                    matchFound = true;
                    break;
                }
            }

            if (!matchFound) _saveFile(classFile); // class is new
        }
    }
    else
    {
        ofLogNotice("Project::save") << "Project data is the same. Not saving project.";
    }
}

bool Project::create(const std::string& path)
{
    ofDirectory project(ofToDataPath(path));

    if (!project.exists())
    {
        ofDirectory temp(ofToDataPath("Resources/Templates/SimpleTemplate"));
        temp.copyTo(ofToDataPath(path));
        return true;
    }

    return false;
}

bool Project::remove()
{
    ofDirectory projectDir(getPath());
    return projectDir.remove(true);
}

bool Project::rename(const std::string& newName)
{
    if (isLoaded())
    {
        ofLogVerbose("Project::rename") << "renaming project \"" << getName() << "\" to \"" << newName + "\"";

        ofFile projectDir(getPath());

        std::string oldProjectName = getName();

        ofLogVerbose("Project::rename") << "project path: " << getPath() << " Renamed to: " << projectDir.getEnclosingDirectory() + newName;

        if (!projectDir.renameTo(projectDir.getEnclosingDirectory() + newName)) return false;

        _path = projectDir.getAbsolutePath();

        ofFile projectFile(projectDir.getAbsolutePath() + "/sketch/" + oldProjectName + "." + SKETCH_FILE_EXTENSION);

        ofLogVerbose("Project::rename") << "projectDir path after rename: " << projectDir.getAbsolutePath();

        ofLogVerbose("Project::rename") << "projectFile path: " << projectFile.getAbsolutePath();

        if (!projectFile.renameTo(projectDir.getAbsolutePath() + "/sketch/" + newName + "." + SKETCH_FILE_EXTENSION)) return false;

        ofLogVerbose("Project::rename") << "projectFile path after rename: " << projectFile.getAbsolutePath();

        _data["projectFile"]["name"] = newName;

        _data["projectFile"]["fileName"] = newName + "." + SKETCH_FILE_EXTENSION;

        return true;
    }
    else
    {
        ofLogVerbose("Project::rename") << "Cannot rename project, it is not loaded.";
        return false;
    }

}

Json::Value Project::createClass(const std::string& className)
{
    std::string fileContents = _classFileTemplate;
    ofStringReplace(fileContents, "<classname>", className);

    ofLogVerbose("Project::createClass") << "fileContents: "<< fileContents;

    Json::Value classFile;
    // TODO: Load extension from settings
    classFile["fileName"] = className + "." + SKETCH_FILE_EXTENSION;
    classFile["name"] = className;
    classFile["fileContents"] = fileContents;
    _data["classes"][getNumClasses()] = classFile;
    // TODO: re-loading is a terribly slow way to delete. Come back and optimize.
    // Simply need to remove the Json::Value class in _data["classes"]
    _saveFile(classFile);
    return classFile;
}

bool Project::deleteClass(const std::string& className)
{
    if (isLoaded())
    {
        ofFile file(_sketchDir.getAbsolutePath() + "/" + className + "." + SKETCH_FILE_EXTENSION);

        if (file.exists())
        {
            file.remove();
            // TODO: re-loading is a terribly slow way to delete. Come back and optimize.
            // Simply need to remove the Json::Value class in _data["classes"]
            load(_path, getName());
            return true;
        }
    }

    return false;
}

bool Project::renameClass(const std::string& currentName, const std::string& newName)
{
    if (isLoaded())
    {
        ofLogVerbose("Project::renameClass") << "Renaming class...";

        ofFile file(_sketchDir.getAbsolutePath() + "/" + currentName + "." + SKETCH_FILE_EXTENSION);
        if (file.exists() && hasClasses())
        {
            for (int i = 0; i < getNumClasses(); ++i)
            {
                if (_data["classes"][i]["name"] == currentName)
                {
                    _data["classes"][i]["name"] = newName;
                    _data["classes"][i]["fileName"] = newName + "." + SKETCH_FILE_EXTENSION;

                    file.renameTo(_sketchDir.getAbsolutePath() + "/" + newName + "." + SKETCH_FILE_EXTENSION);
                    return true;
                }
            }
        }
    }

    return false;
}

bool Project::hasClasses() const
{
    return !_data["classes"].empty();
}

bool Project::isClassName(const std::string& className) const
{
    if (hasClasses())
    {
        Json::ArrayIndex numClasses = getNumClasses();

        for (Json::ArrayIndex i = 0; i < numClasses; ++i)
        {
            if (_data["classes"][i]["name"] == className)
            {
                return true;
            }
        }
    }

    return false;
}

int Project::getNumClasses() const
{
    return _data["classes"].size();
}

const std::string& Project::getPath() const
{
    return _path;
}

std::string Project::getName() const
{
    ofFile project(_path);
    return project.getBaseName();
}

const Json::Value& Project::getData() const
{
    return _data;
}

void Project::_saveFile(const Json::Value& fileData)
{
    ofBuffer fileBuffer(fileData["fileContents"].asString());
    ofBufferToFile(getPath() + "/sketch/" + fileData["fileName"].asString(), fileBuffer);
}

} } // namespace of::Sketch
<|endoftext|>


<commit_before>#include <cmath>
#include <fstream>
#include <sstream>
#include <thread>

#include "io.hh"
#include "Bigrams.hh"
#include "FactorEncoder.hh"

using namespace std;

void
Bigrams::update_trans_stats(const transitions_t &collected_stats,
                            flt_type weight,
                            transitions_t &trans_stats,
                            map<string, flt_type> &unigram_stats)
{
    for (auto srcit = collected_stats.cbegin(); srcit != collected_stats.cend(); ++srcit) {
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit) {
            trans_stats[srcit->first][tgtit->first] += weight * tgtit->second;
            unigram_stats[tgtit->first] += weight * tgtit->second;
        }
    }
}

void
Bigrams::collect_trans_stats(const transitions_t &transitions,
                             const map<string, flt_type> &words,
                             map<string, FactorGraph*> &fg_words,
                             transitions_t &trans_stats,
                             map<string, flt_type> &unigram_stats,
                             bool fb)
{
    trans_stats.clear();
    unigram_stats.clear();

    for (auto it = fg_words.begin(); it != fg_words.end(); ++it) {
        transitions_t word_stats;
        if (fb)
            forward_backward(transitions, *it->second, word_stats);
        else
            viterbi(transitions, *it->second, word_stats);
        update_trans_stats(word_stats, words.at(it->first), trans_stats, unigram_stats);
    }
}

void
Bigrams::threaded_backward(const MultiStringFactorGraph *msfg,
                           const std::vector<flt_type> *fw,
                           const map<string, flt_type> *words,
                           transitions_t *trans_stats,
                           int thread_index,
                           int thread_count,
                           flt_type *total_lp)
{
    *total_lp = 0.0;

    auto it = msfg->string_end_nodes.begin();
    for (int i=0; i<thread_index; i++)
        it++;

    while (true) {
        flt_type lp = backward(*msfg, it->first, *fw, *trans_stats, words->at(it->first));
        (*total_lp) += words->at(it->first) * lp;
        for (int i=0; i<thread_count; i++) {
            it++;
            if (it == msfg->string_end_nodes.end()) break;
        }
        if (it == msfg->string_end_nodes.end()) break;
    }
}

flt_type
Bigrams::collect_trans_stats(const transitions_t &transitions,
                             const map<string, flt_type> &words,
                             MultiStringFactorGraph &msfg,
                             transitions_t &trans_stats,
                             map<string, flt_type> &unigram_stats,
                             bool fb,
                             bool threaded)
{
    trans_stats.clear();
    unigram_stats.clear();

    vector<flt_type> fw(msfg.nodes.size(), MIN_FLOAT);
    fw[0] = 0.0;

    forward(transitions, msfg, fw);

    flt_type total_lp = 0.0;

    if (!threaded) {
        for (auto it = msfg.string_end_nodes.begin(); it != msfg.string_end_nodes.end(); ++it) {
            transitions_t word_stats;
            flt_type lp = backward(msfg, it->first, fw, word_stats);
            total_lp += words.at(it->first) * lp;
            update_trans_stats(word_stats, words.at(it->first), trans_stats, unigram_stats);
        }
        return total_lp;
    }

    vector<transitions_t*> thread_stats(NUM_THREADS);
    vector<flt_type> total_lps(NUM_THREADS);
    thread thrs[NUM_THREADS];

    for (int i=0; i<NUM_THREADS; i++) {
        thread_stats[i] = new transitions_t;
        thrs[i] = thread(threaded_backward, &msfg, &fw, &words, thread_stats[i], i, NUM_THREADS, &(total_lps[i]));
    }

    for (int i=0; i<NUM_THREADS; i++) {
        thrs[i].join();
        total_lp += total_lps[i];
        update_trans_stats(*(thread_stats[i]), 1.0, trans_stats, unigram_stats);
    }

    return total_lp;
}

flt_type
Bigrams::collect_trans_stats(const map<string, flt_type> &vocab,
                             const map<string, flt_type> &words,
                             MultiStringFactorGraph &msfg,
                             transitions_t &trans_stats,
                             map<string, flt_type> &unigram_stats,
                             bool fb)
{
    trans_stats.clear();
    unigram_stats.clear();

    vector<flt_type> fw(msfg.nodes.size(), MIN_FLOAT);
    fw[0] = 0.0;

    forward(vocab, msfg, fw);
    flt_type total_lp = 0.0;

    transitions_t word_stats;
    for (auto it = msfg.string_end_nodes.begin(); it != msfg.string_end_nodes.end(); ++it) {
        total_lp += words.at(it->first) * backward(msfg, it->first, fw, word_stats, words.at(it->first));
    }
    update_trans_stats(word_stats, 1.0, trans_stats, unigram_stats);

    return total_lp;
}

void
Bigrams::normalize(transitions_t &trans_stats,
                   flt_type min_cost)
{
    for (auto srcit = trans_stats.begin(); srcit != trans_stats.end(); ++srcit) {

        flt_type normalizer = 0.0;
        for (auto tgtit = srcit->second.begin(); tgtit != srcit->second.end(); ++tgtit)
            normalizer += tgtit->second;
        normalizer = log(normalizer);

        for (auto tgtit = srcit->second.begin(); tgtit != srcit->second.end(); ++tgtit) {

            tgtit->second = log(tgtit->second) - normalizer;
            if (!std::isfinite(tgtit->second)) {
                cerr << "transition " << srcit->first << " " << tgtit->first << " value " << tgtit->second << endl;
                exit(0);
            }
            if (tgtit->second < min_cost) tgtit->second = min_cost;
        }
    }
}

void
Bigrams::write_transitions(const transitions_t &transitions,
                           const string &filename)
{
    io::Stream transfile(filename, "w");

    for (auto srcit = transitions.cbegin(); srcit != transitions.cend(); ++srcit)
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit)
            fprintf(transfile.file, "%s %s %f\n", srcit->first.c_str(), tgtit->first.c_str(), tgtit->second);

    transfile.close();
}

int
Bigrams::read_transitions(transitions_t &transitions,
                          const string &filename)
{
    ifstream transfile(filename);
    if (!transfile) return -1;

    string line;
    flt_type count;
    int num_trans = 0;
    while (getline(transfile, line)) {
        stringstream ss(line);
        string src, tgt;
        ss >> src;
        ss >> tgt;
        ss >> count;
        transitions[src][tgt] = count;
        num_trans++;
    }
    transfile.close();

    return num_trans;
}

flt_type
Bigrams::bigram_cost(const transitions_t &transitions,
                     const transitions_t &trans_stats)
{
    flt_type total = 0.0;
    flt_type tmp = 0.0;

    for (auto srcit = trans_stats.cbegin(); srcit != trans_stats.cend(); ++srcit)
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit) {
            if (std::isfinite(tgtit->second))
                tmp = tgtit->second * transitions.at(srcit->first).at(tgtit->first);
            if (std::isfinite(tmp)) total += tmp;
            if (!std::isfinite(tmp)) cout << srcit->first << " " << tgtit->first << ": "
                    << tgtit->second << " " << transitions.at(srcit->first).at(tgtit->first) << endl;
        }

    return total;
}

void
Bigrams::remove_transitions(vector<string> &to_remove,
                            transitions_t &transitions)
{
    for (auto it = to_remove.begin(); it != to_remove.end(); ++it)
        transitions.erase(*it);

    for (auto srcit = transitions.begin(); srcit != transitions.end(); ++srcit)
        for (auto it = to_remove.begin(); it != to_remove.end(); ++it)
            srcit->second.erase(*it);

    for (auto srcit = transitions.begin(); srcit != transitions.end();)
        if (srcit->second.size() == 0) transitions.erase(srcit++);
        else ++srcit;
}

int
Bigrams::cutoff(const map<string, flt_type> &unigram_stats,
                flt_type cutoff,
                transitions_t &transitions,
                map<string, FactorGraph*> &fg_words)
{
    vector<string> to_remove;
    for (auto it = unigram_stats.begin(); it != unigram_stats.end(); ++it)
        if (it->second < cutoff && it->first.length() > 2) to_remove.push_back(it->first);

    remove_transitions(to_remove, transitions);

    for (auto fgit = fg_words.begin(); fgit != fg_words.end(); ++fgit) {
        for (int i=0; i<to_remove.size(); i++) {
            size_t found = fgit->first.find(to_remove[i]);
            if (found != std::string::npos) fgit->second->remove_arcs(to_remove[i]);
        }
    }

    return to_remove.size();
}

int
Bigrams::cutoff(const map<string, flt_type> &unigram_stats,
                flt_type cutoff,
                transitions_t &transitions,
                MultiStringFactorGraph &msfg)
{
    vector<string> to_remove;
    for (auto it = unigram_stats.begin(); it != unigram_stats.end(); ++it)
        if (it->second < cutoff && it->first.length() > 2) to_remove.push_back(it->first);

    remove_transitions(to_remove, transitions);

    for (int i=0; i<to_remove.size(); i++)
        msfg.remove_arcs(to_remove[i]);
    msfg.prune_unreachable();

    return to_remove.size();
}

int
Bigrams::remove_least_common(const map<string, flt_type> &unigram_stats,
                             int num_removals,
                             transitions_t &transitions,
                             map<string, FactorGraph*> &fg_words)
{
    vector<pair<string, flt_type> > sorted_stats;
    sort_vocab(unigram_stats, sorted_stats, false);
    vector<string> to_remove;
    for (auto it = sorted_stats.begin(); it != sorted_stats.end(); ++it) {
        if (it->first.length() < 3) continue;
        to_remove.push_back(it->first);
        if (to_remove.size() >= num_removals) break;
    }

    remove_transitions(to_remove, transitions);

    for (auto fgit = fg_words.begin(); fgit != fg_words.end(); ++fgit) {
        for (int i=0; i<num_removals; i++) {
            size_t found = fgit->first.find(sorted_stats[i].first);
            if (found != std::string::npos) fgit->second->remove_arcs(sorted_stats[i].first);
        }
    }

    return to_remove.size();
}

int
Bigrams::remove_least_common(const map<string, flt_type> &unigram_stats,
                             int num_removals,
                             transitions_t &transitions,
                             MultiStringFactorGraph &msfg)
{
    vector<pair<string, flt_type> > sorted_stats;
    sort_vocab(unigram_stats, sorted_stats, false);
    vector<string> to_remove;
    for (auto it = sorted_stats.begin(); it != sorted_stats.end(); ++it) {
        if (it->first.length() < 3) continue;
        to_remove.push_back(it->first);
        if (to_remove.size() >= num_removals) break;
    }

    remove_transitions(to_remove, transitions);

    for (int i=0; i<to_remove.size(); i++)
        msfg.remove_arcs(to_remove[i]);
    msfg.prune_unreachable();

    return to_remove.size();
}

int
Bigrams::transition_count(const transitions_t &transitions)
{
    int count = 0;
    for (auto srcit = transitions.cbegin(); srcit != transitions.cend(); ++srcit)
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit)
            count++;
    return count;
}

void
Bigrams::trans_to_vocab(const transitions_t &transitions,
                        map<string, flt_type> &vocab)
{
    vocab.clear();
    for (auto srcit = transitions.cbegin(); srcit != transitions.cend(); ++srcit)
        vocab[srcit->first] = 0.0;
}

<commit_msg>Fixed a memory leak.<commit_after>#include <cmath>
#include <fstream>
#include <sstream>
#include <thread>

#include "io.hh"
#include "Bigrams.hh"
#include "FactorEncoder.hh"

using namespace std;

void
Bigrams::update_trans_stats(const transitions_t &collected_stats,
                            flt_type weight,
                            transitions_t &trans_stats,
                            map<string, flt_type> &unigram_stats)
{
    for (auto srcit = collected_stats.cbegin(); srcit != collected_stats.cend(); ++srcit) {
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit) {
            trans_stats[srcit->first][tgtit->first] += weight * tgtit->second;
            unigram_stats[tgtit->first] += weight * tgtit->second;
        }
    }
}

void
Bigrams::collect_trans_stats(const transitions_t &transitions,
                             const map<string, flt_type> &words,
                             map<string, FactorGraph*> &fg_words,
                             transitions_t &trans_stats,
                             map<string, flt_type> &unigram_stats,
                             bool fb)
{
    trans_stats.clear();
    unigram_stats.clear();

    for (auto it = fg_words.begin(); it != fg_words.end(); ++it) {
        transitions_t word_stats;
        if (fb)
            forward_backward(transitions, *it->second, word_stats);
        else
            viterbi(transitions, *it->second, word_stats);
        update_trans_stats(word_stats, words.at(it->first), trans_stats, unigram_stats);
    }
}

void
Bigrams::threaded_backward(const MultiStringFactorGraph *msfg,
                           const std::vector<flt_type> *fw,
                           const map<string, flt_type> *words,
                           transitions_t *trans_stats,
                           int thread_index,
                           int thread_count,
                           flt_type *total_lp)
{
    *total_lp = 0.0;

    auto it = msfg->string_end_nodes.begin();
    for (int i=0; i<thread_index; i++)
        it++;

    while (true) {
        flt_type lp = backward(*msfg, it->first, *fw, *trans_stats, words->at(it->first));
        (*total_lp) += words->at(it->first) * lp;
        for (int i=0; i<thread_count; i++) {
            it++;
            if (it == msfg->string_end_nodes.end()) break;
        }
        if (it == msfg->string_end_nodes.end()) break;
    }
}

flt_type
Bigrams::collect_trans_stats(const transitions_t &transitions,
                             const map<string, flt_type> &words,
                             MultiStringFactorGraph &msfg,
                             transitions_t &trans_stats,
                             map<string, flt_type> &unigram_stats,
                             bool fb,
                             bool threaded)
{
    trans_stats.clear();
    unigram_stats.clear();

    vector<flt_type> fw(msfg.nodes.size(), MIN_FLOAT);
    fw[0] = 0.0;

    forward(transitions, msfg, fw);

    flt_type total_lp = 0.0;

    if (!threaded) {
        for (auto it = msfg.string_end_nodes.begin(); it != msfg.string_end_nodes.end(); ++it) {
            transitions_t word_stats;
            flt_type lp = backward(msfg, it->first, fw, word_stats);
            total_lp += words.at(it->first) * lp;
            update_trans_stats(word_stats, words.at(it->first), trans_stats, unigram_stats);
        }
        return total_lp;
    }

    vector<transitions_t> thread_stats(NUM_THREADS);
    vector<flt_type> total_lps(NUM_THREADS);
    thread thrs[NUM_THREADS];

    for (int i=0; i<NUM_THREADS; i++)
        thrs[i] = thread(threaded_backward, &msfg, &fw, &words, &(thread_stats[i]), i, NUM_THREADS, &(total_lps[i]));

    for (int i=0; i<NUM_THREADS; i++) {
        thrs[i].join();
        total_lp += total_lps[i];
        update_trans_stats(thread_stats[i], 1.0, trans_stats, unigram_stats);
    }

    return total_lp;
}

flt_type
Bigrams::collect_trans_stats(const map<string, flt_type> &vocab,
                             const map<string, flt_type> &words,
                             MultiStringFactorGraph &msfg,
                             transitions_t &trans_stats,
                             map<string, flt_type> &unigram_stats,
                             bool fb)
{
    trans_stats.clear();
    unigram_stats.clear();

    vector<flt_type> fw(msfg.nodes.size(), MIN_FLOAT);
    fw[0] = 0.0;

    forward(vocab, msfg, fw);
    flt_type total_lp = 0.0;

    transitions_t word_stats;
    for (auto it = msfg.string_end_nodes.begin(); it != msfg.string_end_nodes.end(); ++it) {
        total_lp += words.at(it->first) * backward(msfg, it->first, fw, word_stats, words.at(it->first));
    }
    update_trans_stats(word_stats, 1.0, trans_stats, unigram_stats);

    return total_lp;
}

void
Bigrams::normalize(transitions_t &trans_stats,
                   flt_type min_cost)
{
    for (auto srcit = trans_stats.begin(); srcit != trans_stats.end(); ++srcit) {

        flt_type normalizer = 0.0;
        for (auto tgtit = srcit->second.begin(); tgtit != srcit->second.end(); ++tgtit)
            normalizer += tgtit->second;
        normalizer = log(normalizer);

        for (auto tgtit = srcit->second.begin(); tgtit != srcit->second.end(); ++tgtit) {

            tgtit->second = log(tgtit->second) - normalizer;
            if (!std::isfinite(tgtit->second)) {
                cerr << "transition " << srcit->first << " " << tgtit->first << " value " << tgtit->second << endl;
                exit(0);
            }
            if (tgtit->second < min_cost) tgtit->second = min_cost;
        }
    }
}

void
Bigrams::write_transitions(const transitions_t &transitions,
                           const string &filename)
{
    io::Stream transfile(filename, "w");

    for (auto srcit = transitions.cbegin(); srcit != transitions.cend(); ++srcit)
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit)
            fprintf(transfile.file, "%s %s %f\n", srcit->first.c_str(), tgtit->first.c_str(), tgtit->second);

    transfile.close();
}

int
Bigrams::read_transitions(transitions_t &transitions,
                          const string &filename)
{
    ifstream transfile(filename);
    if (!transfile) return -1;

    string line;
    flt_type count;
    int num_trans = 0;
    while (getline(transfile, line)) {
        stringstream ss(line);
        string src, tgt;
        ss >> src;
        ss >> tgt;
        ss >> count;
        transitions[src][tgt] = count;
        num_trans++;
    }
    transfile.close();

    return num_trans;
}

flt_type
Bigrams::bigram_cost(const transitions_t &transitions,
                     const transitions_t &trans_stats)
{
    flt_type total = 0.0;
    flt_type tmp = 0.0;

    for (auto srcit = trans_stats.cbegin(); srcit != trans_stats.cend(); ++srcit)
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit) {
            if (std::isfinite(tgtit->second))
                tmp = tgtit->second * transitions.at(srcit->first).at(tgtit->first);
            if (std::isfinite(tmp)) total += tmp;
            if (!std::isfinite(tmp)) cout << srcit->first << " " << tgtit->first << ": "
                    << tgtit->second << " " << transitions.at(srcit->first).at(tgtit->first) << endl;
        }

    return total;
}

void
Bigrams::remove_transitions(vector<string> &to_remove,
                            transitions_t &transitions)
{
    for (auto it = to_remove.begin(); it != to_remove.end(); ++it)
        transitions.erase(*it);

    for (auto srcit = transitions.begin(); srcit != transitions.end(); ++srcit)
        for (auto it = to_remove.begin(); it != to_remove.end(); ++it)
            srcit->second.erase(*it);

    for (auto srcit = transitions.begin(); srcit != transitions.end();)
        if (srcit->second.size() == 0) transitions.erase(srcit++);
        else ++srcit;
}

int
Bigrams::cutoff(const map<string, flt_type> &unigram_stats,
                flt_type cutoff,
                transitions_t &transitions,
                map<string, FactorGraph*> &fg_words)
{
    vector<string> to_remove;
    for (auto it = unigram_stats.begin(); it != unigram_stats.end(); ++it)
        if (it->second < cutoff && it->first.length() > 2) to_remove.push_back(it->first);

    remove_transitions(to_remove, transitions);

    for (auto fgit = fg_words.begin(); fgit != fg_words.end(); ++fgit) {
        for (int i=0; i<to_remove.size(); i++) {
            size_t found = fgit->first.find(to_remove[i]);
            if (found != std::string::npos) fgit->second->remove_arcs(to_remove[i]);
        }
    }

    return to_remove.size();
}

int
Bigrams::cutoff(const map<string, flt_type> &unigram_stats,
                flt_type cutoff,
                transitions_t &transitions,
                MultiStringFactorGraph &msfg)
{
    vector<string> to_remove;
    for (auto it = unigram_stats.begin(); it != unigram_stats.end(); ++it)
        if (it->second < cutoff && it->first.length() > 2) to_remove.push_back(it->first);

    remove_transitions(to_remove, transitions);

    for (int i=0; i<to_remove.size(); i++)
        msfg.remove_arcs(to_remove[i]);
    msfg.prune_unreachable();

    return to_remove.size();
}

int
Bigrams::remove_least_common(const map<string, flt_type> &unigram_stats,
                             int num_removals,
                             transitions_t &transitions,
                             map<string, FactorGraph*> &fg_words)
{
    vector<pair<string, flt_type> > sorted_stats;
    sort_vocab(unigram_stats, sorted_stats, false);
    vector<string> to_remove;
    for (auto it = sorted_stats.begin(); it != sorted_stats.end(); ++it) {
        if (it->first.length() < 3) continue;
        to_remove.push_back(it->first);
        if (to_remove.size() >= num_removals) break;
    }

    remove_transitions(to_remove, transitions);

    for (auto fgit = fg_words.begin(); fgit != fg_words.end(); ++fgit) {
        for (int i=0; i<num_removals; i++) {
            size_t found = fgit->first.find(sorted_stats[i].first);
            if (found != std::string::npos) fgit->second->remove_arcs(sorted_stats[i].first);
        }
    }

    return to_remove.size();
}

int
Bigrams::remove_least_common(const map<string, flt_type> &unigram_stats,
                             int num_removals,
                             transitions_t &transitions,
                             MultiStringFactorGraph &msfg)
{
    vector<pair<string, flt_type> > sorted_stats;
    sort_vocab(unigram_stats, sorted_stats, false);
    vector<string> to_remove;
    for (auto it = sorted_stats.begin(); it != sorted_stats.end(); ++it) {
        if (it->first.length() < 3) continue;
        to_remove.push_back(it->first);
        if (to_remove.size() >= num_removals) break;
    }

    remove_transitions(to_remove, transitions);

    for (int i=0; i<to_remove.size(); i++)
        msfg.remove_arcs(to_remove[i]);
    msfg.prune_unreachable();

    return to_remove.size();
}

int
Bigrams::transition_count(const transitions_t &transitions)
{
    int count = 0;
    for (auto srcit = transitions.cbegin(); srcit != transitions.cend(); ++srcit)
        for (auto tgtit = srcit->second.cbegin(); tgtit != srcit->second.cend(); ++tgtit)
            count++;
    return count;
}

void
Bigrams::trans_to_vocab(const transitions_t &transitions,
                        map<string, flt_type> &vocab)
{
    vocab.clear();
    for (auto srcit = transitions.cbegin(); srcit != transitions.cend(); ++srcit)
        vocab[srcit->first] = 0.0;
}

<|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.

#ifndef IP4_PACKET_IP4_HPP
#define IP4_PACKET_IP4_HPP

#include <cassert>
#include <net/packet.hpp>
#include <net/inet_common.hpp>
#include <net/ip4/ip4.hpp>

namespace net {

  class PacketIP4 : public Packet
  {
  public:
    static constexpr size_t DEFAULT_TTL {64};

    const ip4::Addr& src() const noexcept
    { return ip_header().saddr; }

    void set_src(const ip4::Addr& addr) noexcept
    { ip_header().saddr = addr; }

    const ip4::Addr& dst() const noexcept
    { return ip_header().daddr; }

    void set_dst(const ip4::Addr& addr) noexcept
    { ip_header().daddr = addr; }

    void set_protocol(Protocol p) noexcept
    { ip_header().protocol = static_cast<uint8_t>(p); }

    Protocol protocol() const noexcept
    { return static_cast<Protocol>(ip_header().protocol); }

    uint16_t ip_segment_length() const noexcept
    { return ntohs(ip_header().tot_len); }

    uint8_t ip_header_length() const noexcept
    { return (ip_header().version_ihl & 0xf) * 4; }

    uint16_t ip_data_length() const noexcept
    { return ip_segment_length() - ip_header_length(); }

    uint16_t ip_capacity() const noexcept
    { return capacity() - ip_header_length(); }

    void set_ip_data_length(uint16_t length) {
      Expects(sizeof(IP4::header) + length <= (size_t) capacity());
      set_data_end(sizeof(IP4::header) + length);

      set_segment_length();
    }

    /** Last modifications before transmission */
    void make_flight_ready() noexcept {
      assert( ip_header().protocol );
      set_segment_length();
      set_ip4_checksum();
    }

    void init(Protocol proto = Protocol::HOPOPT) noexcept {
      Expects(size() == 0);
      auto& hdr = ip_header();
      hdr.version_ihl    = 0x45;
      hdr.tos            = 0;
      hdr.id             = 0;
      hdr.frag_off_flags = 0;
      hdr.ttl            = DEFAULT_TTL;
      hdr.protocol       = static_cast<uint8_t>(proto);
      set_ip_data_length(0);
    }

  protected:
    Byte* ip_data() noexcept __attribute__((assume_aligned(4)))
    {
      return layer_begin() + ip_header_length();
    }

    const Byte* ip_data() const noexcept __attribute__((assume_aligned(4)))
    {
      return layer_begin() + ip_header_length();
    }

    /**
     *  Set IP4 header length
     *  Inferred from packet size
     */
    void set_segment_length() noexcept
    { ip_header().tot_len = htons(size()); }

  private:

    void set_header_length() noexcept
    { }

    const ip4::Header& ip_header() const noexcept
    { return *reinterpret_cast<const IP4::header*>(layer_begin()); }

    ip4::Header& ip_header() noexcept
    { return *reinterpret_cast<IP4::header*>(layer_begin()); }

    void set_ip4_checksum() noexcept {
      auto& hdr = ip_header();
      hdr.check = 0;
      hdr.check = net::checksum(&hdr, ip_header_length());
    }

  }; //< class PacketIP4
} //< namespace net

#endif //< IP4_PACKET_IP4_HPP
<commit_msg>IP4 Packet: Getter for TTL added<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.

#ifndef IP4_PACKET_IP4_HPP
#define IP4_PACKET_IP4_HPP

#include <cassert>
#include <net/packet.hpp>
#include <net/inet_common.hpp>
#include <net/ip4/ip4.hpp>

namespace net {

  class PacketIP4 : public Packet
  {
  public:
    static constexpr size_t DEFAULT_TTL {64};

    const ip4::Addr& src() const noexcept
    { return ip_header().saddr; }

    void set_src(const ip4::Addr& addr) noexcept
    { ip_header().saddr = addr; }

    const ip4::Addr& dst() const noexcept
    { return ip_header().daddr; }

    void set_dst(const ip4::Addr& addr) noexcept
    { ip_header().daddr = addr; }

    void set_protocol(Protocol p) noexcept
    { ip_header().protocol = static_cast<uint8_t>(p); }

    Protocol protocol() const noexcept
    { return static_cast<Protocol>(ip_header().protocol); }

    uint8_t ttl() const noexcept
    { return ip_header().ttl; }

    uint16_t ip_segment_length() const noexcept
    { return ntohs(ip_header().tot_len); }

    uint8_t ip_header_length() const noexcept
    { return (ip_header().version_ihl & 0xf) * 4; }

    uint16_t ip_data_length() const noexcept
    { return ip_segment_length() - ip_header_length(); }

    uint16_t ip_capacity() const noexcept
    { return capacity() - ip_header_length(); }

    void set_ip_data_length(uint16_t length) {
      Expects(sizeof(IP4::header) + length <= (size_t) capacity());
      set_data_end(sizeof(IP4::header) + length);

      set_segment_length();
    }

    /** Last modifications before transmission */
    void make_flight_ready() noexcept {
      assert( ip_header().protocol );
      set_segment_length();
      set_ip4_checksum();
    }

    void init(Protocol proto = Protocol::HOPOPT) noexcept {
      Expects(size() == 0);
      auto& hdr = ip_header();
      hdr.version_ihl    = 0x45;
      hdr.tos            = 0;
      hdr.id             = 0;
      hdr.frag_off_flags = 0;
      hdr.ttl            = DEFAULT_TTL;
      hdr.protocol       = static_cast<uint8_t>(proto);
      set_ip_data_length(0);
    }

  protected:
    Byte* ip_data() noexcept __attribute__((assume_aligned(4)))
    {
      return layer_begin() + ip_header_length();
    }

    const Byte* ip_data() const noexcept __attribute__((assume_aligned(4)))
    {
      return layer_begin() + ip_header_length();
    }

    /**
     *  Set IP4 header length
     *  Inferred from packet size
     */
    void set_segment_length() noexcept
    { ip_header().tot_len = htons(size()); }

  private:

    void set_header_length() noexcept
    { }

    const ip4::Header& ip_header() const noexcept
    { return *reinterpret_cast<const IP4::header*>(layer_begin()); }

    ip4::Header& ip_header() noexcept
    { return *reinterpret_cast<IP4::header*>(layer_begin()); }

    void set_ip4_checksum() noexcept {
      auto& hdr = ip_header();
      hdr.check = 0;
      hdr.check = net::checksum(&hdr, ip_header_length());
    }

  }; //< class PacketIP4
} //< namespace net

#endif //< IP4_PACKET_IP4_HPP
<|endoftext|>


<commit_before>#include "DelegateTest.h"
#include "capu/Config.h"
#include <capu/container/Vector.h>

namespace capu
{

    bool_t g_simpleVoidFunctionCalled = false;
    uint32_t g_uint32Parameter = 0;

    class SimpleClass
    {
    public:
        static uint32_t DoStaticStuff(const uint32_t value)
        {
            return value;
        }

        void doStuff()
        {

        }

        uint32_t doNonStaticStuff(uint32_t value)
        {
            return value;
        }

        uint32_t doMoreNonStaticStuff(uint32_t value1, uint32_t value2)
        {
            return value1 + value2;
        }
    };

    DelegateTest::DelegateTest()
    {
        g_simpleVoidFunctionCalled = false;
        g_uint32Parameter = 0;
    }

    void SimpleVoidFunction()
    {
        g_simpleVoidFunctionCalled = true;
    }

    void OneParameterVoidFunction(const uint32_t value)
    {
        g_uint32Parameter = value;
    }

    uint32_t OneParameterFunctionWithReturnValue(const uint32_t value)
    {
        return value;
    }

    TEST_F(DelegateTest, DelegateSimpleVoidFunction)
    {
        Delegate<void> delegate = Delegate<void>::Create<&SimpleVoidFunction>();

        delegate();

        EXPECT_TRUE(g_simpleVoidFunctionCalled);
    }

    TEST_F(DelegateTest, DelegateSimpleOneParameterFunction)
    {
        Delegate<void, uint32_t> delegate = Delegate<void, uint32_t>::Create<&OneParameterVoidFunction>();
        delegate(5);

        EXPECT_EQ(5u, g_uint32Parameter);
    }

    TEST_F(DelegateTest, DelegateSimpleOneParameterFunctionWithReturnValue)
    {
        Delegate<uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t>::Create<&OneParameterFunctionWithReturnValue>();

        EXPECT_EQ(5u, delegate(5u));
    }

    TEST_F(DelegateTest, DelegateStaticMemberFunctionWithReturnValue)
    {
        Delegate<uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t>::Create<&SimpleClass::DoStaticStuff>();

        EXPECT_EQ(5u, delegate(5u));
    }

    TEST_F(DelegateTest, DelegateNonStaticMemberFunctionWithReturnValue)
    {
        SimpleClass simpleClass;
        Delegate<uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t>::Create<SimpleClass, &SimpleClass::doNonStaticStuff>(simpleClass);

        EXPECT_EQ(5u, delegate(5u));
    }

    TEST_F(DelegateTest, DelegateNonStaticMemberFuncionWithTwoParametersAndReturnValue)
    {
        SimpleClass simpleClass;
        Delegate<uint32_t, uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t, uint32_t>::Create<SimpleClass, &SimpleClass::doMoreNonStaticStuff>(simpleClass);

        EXPECT_EQ(9u, delegate(5u, 4u));
    }
}

<commit_msg>Added Delegate tests for virtual methods<commit_after>#include "DelegateTest.h"
#include "capu/Config.h"
#include <capu/container/Vector.h>

namespace capu
{

    bool_t g_simpleVoidFunctionCalled = false;
    uint32_t g_uint32Parameter = 0;

    class SimpleClass
    {
    public:
        static uint32_t DoStaticStuff(const uint32_t value)
        {
            return value;
        }

        void doStuff()
        {

        }

        virtual void doVirtualStuff(uint32_t)
        {
        }

        virtual void doPureVirtualStuff(uint32_t value) = 0;

        uint32_t doNonStaticStuff(uint32_t value)
        {
            return value;
        }

        uint32_t doMoreNonStaticStuff(uint32_t value1, uint32_t value2)
        {
            return value1 + value2;
        }
    };

    class MockSimpleClass: public SimpleClass
    {
    public:
        MOCK_METHOD1(doVirtualStuff, void(uint32_t value));
        MOCK_METHOD1(doPureVirtualStuff, void(uint32_t value));
    };

    DelegateTest::DelegateTest()
    {
        g_simpleVoidFunctionCalled = false;
        g_uint32Parameter = 0;
    }

    void SimpleVoidFunction()
    {
        g_simpleVoidFunctionCalled = true;
    }

    void OneParameterVoidFunction(const uint32_t value)
    {
        g_uint32Parameter = value;
    }

    uint32_t OneParameterFunctionWithReturnValue(const uint32_t value)
    {
        return value;
    }

    TEST_F(DelegateTest, DelegateSimpleVoidFunction)
    {
        Delegate<void> delegate = Delegate<void>::Create<&SimpleVoidFunction>();

        delegate();

        EXPECT_TRUE(g_simpleVoidFunctionCalled);
    }

    TEST_F(DelegateTest, DelegateSimpleOneParameterFunction)
    {
        Delegate<void, uint32_t> delegate = Delegate<void, uint32_t>::Create<&OneParameterVoidFunction>();
        delegate(5);

        EXPECT_EQ(5u, g_uint32Parameter);
    }

    TEST_F(DelegateTest, DelegateSimpleOneParameterFunctionWithReturnValue)
    {
        Delegate<uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t>::Create<&OneParameterFunctionWithReturnValue>();

        EXPECT_EQ(5u, delegate(5u));
    }

    TEST_F(DelegateTest, DelegateStaticMemberFunctionWithReturnValue)
    {
        Delegate<uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t>::Create<&MockSimpleClass::DoStaticStuff>();

        EXPECT_EQ(5u, delegate(5u));
    }

    TEST_F(DelegateTest, DelegateNonStaticMemberFunctionWithReturnValue)
    {
        MockSimpleClass simpleClass;
        Delegate<uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t>::Create<SimpleClass, &MockSimpleClass::doNonStaticStuff>(simpleClass);

        EXPECT_EQ(5u, delegate(5u));
    }

    TEST_F(DelegateTest, DelegateNonStaticMemberFuncionWithTwoParametersAndReturnValue)
    {
        MockSimpleClass simpleClass;
        Delegate<uint32_t, uint32_t, uint32_t> delegate = Delegate<uint32_t, uint32_t, uint32_t>::Create<SimpleClass, &MockSimpleClass::doMoreNonStaticStuff>(simpleClass);

        EXPECT_EQ(9u, delegate(5u, 4u));
    }

    TEST_F(DelegateTest, DelegateVirtualMethod)
    {
        MockSimpleClass simpleClass;
        Delegate<void, uint32_t> delegate = Delegate<void, uint32_t>::Create<SimpleClass, &SimpleClass::doVirtualStuff>(simpleClass);

        EXPECT_CALL(simpleClass, doVirtualStuff(5));
        delegate(5);
    }

    TEST_F(DelegateTest, DelegatePureVirtualMethod)
    {
        MockSimpleClass simpleClass;
        Delegate<void, uint32_t> delegate = Delegate<void, uint32_t>::Create<SimpleClass, &SimpleClass::doPureVirtualStuff>(simpleClass);

        EXPECT_CALL(simpleClass, doPureVirtualStuff(5));
        delegate(5);
    }
}

<|endoftext|>