<commit_before>/*! \brief serial_controller_node.
 *         Manages serial communications with AVR-Master.
 *
 *  This node manages serial communications with the AVR-Master.
 *  Therefore it first requests all data from AVR-Master and then sends all
 *  commands to AVR-Master in a Loop. Data read is stored in md49_data.txt,
 *  commands to be send are read from md49_commands.txt.
 *
 */

// Includes
// *********************************************************
#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>                                          /* Input/output stream class to operate on files. */
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <errno.h>                                          /* Error number definitions */
#include <termios.h>                                        /* POSIX terminal control definitions */
#include <ctype.h>                                          /* isxxx() */
//#include<ros/ros.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
   int i;
   for(i=0; i<argc; i++){
      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("\n");
   return 0;
}

// Global variables
const char* serialport_name="/dev/ttyS2";                 /* defines used serialport on BPi. Use "/dev/ttyAMA0" for RPi*/
int serialport_bps=B38400;                                  /* defines used baudrate on serialport */
//int filedesc;                                             /* File descriptor of serial port we will talk to*/
int fd;                                                     /* serial port file descriptor */
int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                     /* speed to set for MD49 */
unsigned char last_speed_l=128, last_speed_r=128;                     /* speed to set for MD49 */
unsigned char serialBuffer[16];                             /* Serial buffer to store uart data */
unsigned char md49_data[18];                                /* keeps data from MD49, read from AVR-Master */
struct termios orig;                                        // Port options

using namespace std;

// Declare functions
// *********************************************************
int openSerialPort(const char * device, int bps);
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void read_MD49_Data_serial (void);
void read_md49_commands_txt(void);
void set_MD49_speed (unsigned char speed_l, unsigned char speed_r);
char* itoa(int value, char* result, int base);

int main( int argc, char* argv[] ){

    //  Open database md49.db and
    // **************************
    sqlite3 *db;
    char *zErrMsg = 0;
    int  rc;
    const char *sql;

    rc = sqlite3_open("md49data.db", &db);
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }else{
        fprintf(stdout, "Opened database successfully\n");
    }

    // Create table md49data
    // *********************
    sql = "CREATE TABLE md49data("  \
     "ID INT PRIMARY KEY     NOT NULL," \
     "Encoderbyte1L  INT," \
     "Encoderbyte2L  INT," \
     "Encoderbyte3L  INT," \
     "Encoderbyte4L  INT," \
     "Encoderbyte1R  INT," \
     "Encoderbyte2R  INT," \
     "Encoderbyte3R  INT," \
     "Encoderbyte4R  INT," \
     "SpeedL         INT," \
     "SpeedR         INT," \
     "Volts          INT," \
     "CurrentL       INT," \
     "CurrentR       INT," \
     "Error          INT," \
     "Acceleration   INT," \
     "Mode           INT," \
     "Regulator      INT," \
     "Timeout        INT );";

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "Table created successfully\n");
    }
    sqlite3_close(db);

    // Init as ROS node
    // ****************
    //ros::init(argc, argv, "serial_controller");
    //ros::NodeHandle n;

    // Open serial port
    // ****************
    fd = openSerialPort(serialport_name, serialport_bps);
    if (fd == -1) exit(1);
    //ROS_INFO("Opend serial port at %s with %i Bps",serialport_name,serialport_bps);
    usleep(10000);                                          // Sleep for UART to power up and set options

    //ROS_DEBUG("Starting Mainloop...");
    //ROS_DEBUG("reading data from MD49 and pushing commands to MD49 @ 5Hz...");

    //while(  n.ok() ){
    while( 1 ){
        // Read encoder and other data from MD49
        // serial. Data ist stored in md49_data.txt
        // ****************************************
        read_MD49_Data_serial();
        usleep(100000);

        // Read commands from md49_commands.txt:
        // *************************************
        read_md49_commands_txt();

        // Set speed and other commands as
        // read from md49_commands.txt
        // *******************************
        set_MD49_speed(speed_l, speed_r);
        usleep(100000);

    }// end.mainloop
    return 1;
} // end.main

void read_MD49_Data_serial (void){
    // Read serial MD49 data from AVR-Master
    // *************************************
    serialBuffer[0] = 82;                                   // 82=R Steuerbyte um alle Daten vom MD49 zu lesen
    writeBytes(fd, 1);
    readBytes(fd, 18);

    // Put toghether encoder values from their
    // corresponding bytes, read from MD49
    // ***************************************
    EncoderL = serialBuffer[0] << 24;                       // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                       // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

    // Write data from MD49 into md49_data.txt
    // ***************************************
    int i=0;
    char buffer[33];
    ofstream myfile;
    myfile.open ("md49_data.txt");
    //myfile << "Writing this to a file.\n";
    for (i=0;i<18;i++){
        if (serialBuffer[i]==0){
            myfile << "000";
        }
        else if (serialBuffer[i]<10){
            myfile << "00";
            myfile << itoa(serialBuffer[i],buffer,10);
        }
        else if (serialBuffer[i]<100){
            myfile << "0";
            myfile << itoa(serialBuffer[i],buffer,10);
        }
        else{
            myfile << itoa(serialBuffer[i],buffer,10);
        }
        myfile << "\n";
    }
    myfile.close();

    // Output MD49 data on screen
    // **************************
    printf("\033[2J");                                      /*  clear the screen  */
    printf("\033[H");                                       /*  position cursor at top-left corner */
    printf ("MD49-Data read from AVR-Master: \n");
    printf("========================================\n");
    printf("Encoder1 Byte1: %i ",serialBuffer[0]);
    printf("Byte2: %i ",serialBuffer[1]);
    printf("Byte3: % i ",serialBuffer[2]);
    printf("Byte4: %i \n",serialBuffer[3]);
    printf("Encoder2 Byte1: %i ",serialBuffer[4]);
    printf("Byte2: %i ",serialBuffer[5]);
    printf("Byte3: %i ",serialBuffer[6]);
    printf("Byte4: %i \n",serialBuffer[7]);
    printf("EncoderL: %i ",EncoderL);
    printf("EncoderR: %i \n",EncoderR);
    printf("========================================\n");
    printf("Speed1: %i ",serialBuffer[8]);
    printf("Speed2: %i \n",serialBuffer[9]);
    printf("Volts: %i \n",serialBuffer[10]);
    printf("Current1: %i ",serialBuffer[11]);
    printf("Current2: %i \n",serialBuffer[12]);
    printf("Error: %i \n",serialBuffer[13]);
    printf("Acceleration: %i \n",serialBuffer[14]);
    printf("Mode: %i \n",serialBuffer[15]);
    printf("Regulator: %i \n",serialBuffer[16]);
    printf("Timeout: %i \n",serialBuffer[17]);

}

void set_MD49_speed (unsigned char speed_l, unsigned char speed_r){
    serialBuffer[0] = 88;                                   // 88 =X Steuerbyte um Commands an MD49 zu senden
    serialBuffer[1] = 115;                                  // 115=s Steuerbyte setSpeed
    serialBuffer[2] = speed_l;                              // set speed1
    serialBuffer[3] = speed_r;                              // set speed2
    writeBytes(fd, 4);
}

void read_md49_commands_txt(void){
    string line;
    ifstream myfile ("md49_commands.txt");
    if (myfile.is_open())
    {
        int i=0;
        while ( getline (myfile,line) )
        {
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            md49_data[i]=atoi(data);
            i =i++;
        }
        myfile.close();
        speed_l=md49_data[0];
        speed_r=md49_data[1];
    }
    else cout << "Unable to open file";
}

int openSerialPort(const char * device, int bps){
   struct termios neu;
   char buf[128];

   //fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
   fd = open(device, O_RDWR | O_NOCTTY);

   if (fd == -1)
   {
      sprintf(buf, "openSerialPort %s error", device);
      perror(buf);
   }
   else
   {
      tcgetattr(fd, &orig);                                 /* save current serial settings */
      tcgetattr(fd, &neu);
      cfmakeraw(&neu);
      cfsetispeed(&neu, bps);
      cfsetospeed(&neu, bps);
      tcflush(fd, TCIFLUSH);
      tcsetattr(fd, TCSANOW, &neu);                         /* set new serial settings */
      fcntl (fd, F_SETFL, O_RDWR);
   }
   return fd;
}

void writeBytes(int descriptor, int count) {
    if ((write(descriptor, serialBuffer, count)) == -1) {   // Send data out
        perror("Error writing");
        close(descriptor);                                  // Close port if there is an error
        exit(1);
    }

}

void readBytes(int descriptor, int count) {
    if (read(descriptor, serialBuffer, count) == -1) {      // Read back data into buf[]
        perror("Error reading ");
        close(descriptor);                                  // Close port if there is an error
        exit(1);
    }
}

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
    }
<commit_msg>Update code<commit_after>/*! \brief serial_controller_node.
 *         Manages serial communications with AVR-Master.
 *
 *  This node manages serial communications with the AVR-Master.
 *  Therefore it first requests all data from AVR-Master and then sends all
 *  commands to AVR-Master in a Loop. Data read is stored in md49_data.txt,
 *  commands to be send are read from md49_commands.txt.
 *
 */

// Includes
// *********************************************************
#include <iostream>                                         /* allows to perform standard input and output operations */
#include <fstream>                                          /* Input/output stream class to operate on files. */
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
#include <unistd.h>                                         /* UNIX standard function definitions */
#include <fcntl.h>                                          /* File control definitions */
#include <errno.h>                                          /* Error number definitions */
#include <termios.h>                                        /* POSIX terminal control definitions */
#include <ctype.h>                                          /* isxxx() */
//#include<ros/ros.h>
#include <sqlite3.h>

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
   int i;
   for(i=0; i<argc; i++){
      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("\n");
   return 0;
}

// Global variables
const char* serialport_name="/dev/ttyS2";                 /* defines used serialport on BPi. Use "/dev/ttyAMA0" for RPi*/
int serialport_bps=B38400;                                  /* defines used baudrate on serialport */
//int filedesc;                                             /* File descriptor of serial port we will talk to*/
int fd;                                                     /* serial port file descriptor */
int32_t EncoderL;                                           /* stores encoder value left read from md49 */
int32_t EncoderR;                                           /* stores encoder value right read from md49 */
unsigned char speed_l=128, speed_r=128;                     /* speed to set for MD49 */
unsigned char last_speed_l=128, last_speed_r=128;                     /* speed to set for MD49 */
unsigned char serialBuffer[16];                             /* Serial buffer to store uart data */
unsigned char md49_data[18];                                /* keeps data from MD49, read from AVR-Master */
struct termios orig;                                        // Port options

using namespace std;

// Declare functions
// *********************************************************
int openSerialPort(const char * device, int bps);
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void read_MD49_Data_serial (void);
void read_md49_commands_txt(void);
void set_MD49_speed (unsigned char speed_l, unsigned char speed_r);
char* itoa(int value, char* result, int base);

int main( int argc, char* argv[] ){

    //  Open database md49.db and
    // **************************
    sqlite3 *db;
    char *zErrMsg = 0;
    int  rc;
    const char *sql;

    rc = sqlite3_open("md49data.db", &db);
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }else{
        fprintf(stdout, "Opened database successfully\n");
    }

    // Create table md49data
    // *********************
    sql = "CREATE TABLE md49data("  \
     "ID INT PRIMARY KEY     NOT NULL," \
     "Encoderbyte1L  INT DEFAULT 0," \
     "Encoderbyte2L  INT DEFAULT 0," \
     "Encoderbyte3L  INT DEFAULT 0," \
     "Encoderbyte4L  INT DEFAULT 0," \
     "Encoderbyte1R  INT DEFAULT 0," \
     "Encoderbyte2R  INT DEFAULT 0," \
     "Encoderbyte3R  INT DEFAULT 0," \
     "Encoderbyte4R  INT DEFAULT 0," \
     "SpeedL         INT DEFAULT 128," \
     "SpeedR         INT DEFAULT 128," \
     "Volts          INT DEFAULT 0," \
     "CurrentL       INT DEFAULT 0," \
     "CurrentR       INT DEFAULT 0," \
     "Error          INT DEFAULT 0," \
     "Acceleration   INT DEFAULT 5," \
     "Mode           INT DEFAULT 0," \
     "Regulator      INT DEFAULT 1," \
     "Timeout        INT DEFAULT 1 );";

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "Table created successfully\n");
    }
    sqlite3_close(db);

    // Init as ROS node
    // ****************
    //ros::init(argc, argv, "serial_controller");
    //ros::NodeHandle n;

    // Open serial port
    // ****************
    fd = openSerialPort(serialport_name, serialport_bps);
    if (fd == -1) exit(1);
    //ROS_INFO("Opend serial port at %s with %i Bps",serialport_name,serialport_bps);
    usleep(10000);                                          // Sleep for UART to power up and set options

    //ROS_DEBUG("Starting Mainloop...");
    //ROS_DEBUG("reading data from MD49 and pushing commands to MD49 @ 5Hz...");

    //while(  n.ok() ){
    while( 1 ){
        // Read encoder and other data from MD49
        // serial. Data ist stored in md49_data.txt
        // ****************************************
        read_MD49_Data_serial();
        usleep(100000);

        // Read commands from md49_commands.txt:
        // *************************************
        read_md49_commands_txt();

        // Set speed and other commands as
        // read from md49_commands.txt
        // *******************************
        set_MD49_speed(speed_l, speed_r);
        usleep(100000);

    }// end.mainloop
    return 1;
} // end.main

void read_MD49_Data_serial (void){
    // Read serial MD49 data from AVR-Master
    // *************************************
    serialBuffer[0] = 82;                                   // 82=R Steuerbyte um alle Daten vom MD49 zu lesen
    writeBytes(fd, 1);
    readBytes(fd, 18);

    // Put toghether encoder values from their
    // corresponding bytes, read from MD49
    // ***************************************
    EncoderL = serialBuffer[0] << 24;                       // Put together first encoder value
    EncoderL |= (serialBuffer[1] << 16);
    EncoderL |= (serialBuffer[2] << 8);
    EncoderL |= (serialBuffer[3]);
    EncoderR = serialBuffer[4] << 24;                       // Put together second encoder value
    EncoderR |= (serialBuffer[5] << 16);
    EncoderR |= (serialBuffer[6] << 8);
    EncoderR |= (serialBuffer[7]);

    // Write data from MD49 into md49_data.txt
    // ***************************************
    int i=0;
    char buffer[33];
    ofstream myfile;
    myfile.open ("md49_data.txt");
    //myfile << "Writing this to a file.\n";
    for (i=0;i<18;i++){
        if (serialBuffer[i]==0){
            myfile << "000";
        }
        else if (serialBuffer[i]<10){
            myfile << "00";
            myfile << itoa(serialBuffer[i],buffer,10);
        }
        else if (serialBuffer[i]<100){
            myfile << "0";
            myfile << itoa(serialBuffer[i],buffer,10);
        }
        else{
            myfile << itoa(serialBuffer[i],buffer,10);
        }
        myfile << "\n";
    }
    myfile.close();

    // Output MD49 data on screen
    // **************************
    printf("\033[2J");                                      /*  clear the screen  */
    printf("\033[H");                                       /*  position cursor at top-left corner */
    printf ("MD49-Data read from AVR-Master: \n");
    printf("========================================\n");
    printf("Encoder1 Byte1: %i ",serialBuffer[0]);
    printf("Byte2: %i ",serialBuffer[1]);
    printf("Byte3: % i ",serialBuffer[2]);
    printf("Byte4: %i \n",serialBuffer[3]);
    printf("Encoder2 Byte1: %i ",serialBuffer[4]);
    printf("Byte2: %i ",serialBuffer[5]);
    printf("Byte3: %i ",serialBuffer[6]);
    printf("Byte4: %i \n",serialBuffer[7]);
    printf("EncoderL: %i ",EncoderL);
    printf("EncoderR: %i \n",EncoderR);
    printf("========================================\n");
    printf("Speed1: %i ",serialBuffer[8]);
    printf("Speed2: %i \n",serialBuffer[9]);
    printf("Volts: %i \n",serialBuffer[10]);
    printf("Current1: %i ",serialBuffer[11]);
    printf("Current2: %i \n",serialBuffer[12]);
    printf("Error: %i \n",serialBuffer[13]);
    printf("Acceleration: %i \n",serialBuffer[14]);
    printf("Mode: %i \n",serialBuffer[15]);
    printf("Regulator: %i \n",serialBuffer[16]);
    printf("Timeout: %i \n",serialBuffer[17]);

}

void set_MD49_speed (unsigned char speed_l, unsigned char speed_r){
    serialBuffer[0] = 88;                                   // 88 =X Steuerbyte um Commands an MD49 zu senden
    serialBuffer[1] = 115;                                  // 115=s Steuerbyte setSpeed
    serialBuffer[2] = speed_l;                              // set speed1
    serialBuffer[3] = speed_r;                              // set speed2
    writeBytes(fd, 4);
}

void read_md49_commands_txt(void){
    string line;
    ifstream myfile ("md49_commands.txt");
    if (myfile.is_open())
    {
        int i=0;
        while ( getline (myfile,line) )
        {
            //cout << line << '\n';
            char data[10];
            std::copy(line.begin(), line.end(), data);
            md49_data[i]=atoi(data);
            i =i++;
        }
        myfile.close();
        speed_l=md49_data[0];
        speed_r=md49_data[1];
    }
    else cout << "Unable to open file";
}

int openSerialPort(const char * device, int bps){
   struct termios neu;
   char buf[128];

   //fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
   fd = open(device, O_RDWR | O_NOCTTY);

   if (fd == -1)
   {
      sprintf(buf, "openSerialPort %s error", device);
      perror(buf);
   }
   else
   {
      tcgetattr(fd, &orig);                                 /* save current serial settings */
      tcgetattr(fd, &neu);
      cfmakeraw(&neu);
      cfsetispeed(&neu, bps);
      cfsetospeed(&neu, bps);
      tcflush(fd, TCIFLUSH);
      tcsetattr(fd, TCSANOW, &neu);                         /* set new serial settings */
      fcntl (fd, F_SETFL, O_RDWR);
   }
   return fd;
}

void writeBytes(int descriptor, int count) {
    if ((write(descriptor, serialBuffer, count)) == -1) {   // Send data out
        perror("Error writing");
        close(descriptor);                                  // Close port if there is an error
        exit(1);
    }

}

void readBytes(int descriptor, int count) {
    if (read(descriptor, serialBuffer, count) == -1) {      // Read back data into buf[]
        perror("Error reading ");
        close(descriptor);                                  // Close port if there is an error
        exit(1);
    }
}

char* itoa(int value, char* result, int base) {
        // check that the base if valid
        if (base < 2 || base > 36) { *result = '\0'; return result; }

        char* ptr = result, *ptr1 = result, tmp_char;
        int tmp_value;

        do {
            tmp_value = value;
            value /= base;
            *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
        } while ( value );

        // Apply negative sign
        if (tmp_value < 0) *ptr++ = '-';
        *ptr-- = '\0';
        while(ptr1 < ptr) {
            tmp_char = *ptr;
            *ptr--= *ptr1;
            *ptr1++ = tmp_char;
        }
        return result;
    }
<|endoftext|>


<commit_before>
#pragma once

#include <cinatra_http/request.h>
#include <cinatra_http/response.h>
#include <cinatra/context_container.hpp>
#include <cinatra/middleware/cookies.hpp>

#include <boost/any.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>

#include <unordered_map>
#include <string>
#include <thread>
#include <atomic>
#include <mutex>

namespace cinatra
{
	class session
	{
	public:
		void before(request const& req, response& res, context_container& ctx)
		{
			ctx.add_req_ctx(context_t(sessions_, ctx));
		}

		void after(request const& req, response& res, context_container& ctx)
		{

		}

		struct session_map_t
		{
			session_map_t()
				:last_used_time(std::time(nullptr))
			{}
			std::time_t last_used_time;
			std::unordered_map<std::string, boost::any> m;
		};

		class context_t
		{
		public:
			context_t(std::unordered_map<std::string, session_map_t>& sessions,context_container& ctx)
				:sessions_(sessions), ctx_(ctx)
			{

			}

			template<typename T>
			T& get(std::string const& key)
			{
				auto sp = get_session_map_with_session_id();
				if (!sp)
				{
					throw std::invalid_argument("key " + key + " not found");
				}

				auto it = sp->m.find(key);
				if (it == sp->m.end())
				{
					throw std::invalid_argument("key " + key + " not found");
				}

				return boost::any_cast<T&>(it->second);
			}

			template<typename T>
			void add(std::string const& key, T const& val)
			{
				auto sp = get_session_map_with_add();
				sp->m.emplace(key, val);
			}

			bool has(std::string const& key)
			{
				auto sp = get_session_map_with_session_id();
				if (!sp)
				{
					return false;
				}

				return sp->m.find(key) != sp->m.end();
			}

			bool del(std::string const& key)
			{
				auto sp = get_session_map_with_session_id();
				if (!sp)
				{
					return false;
				}

				auto it = sp->m.find(key);
				if (it == sp->m.end())
				{
					return false;
				}

				sp->m.erase(it);
				return true;
			}
		private:
			std::string get_session_id()
			{
				auto& cookie = ctx_.get_req_ctx<cookies>();
				return cookie.get("CSESSIONID");
			}

			session_map_t* get_session_map()
			{
				return session_map_ptr_;
			}

			session_map_t* get_session_map_with_session_id()
			{
				if (session_map_ptr_)
				{
					return session_map_ptr_;
				}
				if (session_map_ptr_not_found_)
				{
					return nullptr;
				}

				auto& cookie = ctx_.get_req_ctx<cookies>();
				auto session_id = cookie.get("CSESSIONID");
				if (session_id.empty())
				{
					session_map_ptr_not_found_ = true;
					return nullptr;
				}

				auto it = sessions_.find(session_id);
				if (it == sessions_.end())
				{
					session_map_ptr_not_found_ = true;
					return nullptr;
				}

				session_map_ptr_ = &it->second;

				return session_map_ptr_;
			}

			inline void itoh(int c, char& out1, char& out2)
			{
				unsigned char hexchars[] = "0123456789ABCDEF";
				out1 = hexchars[c >> 4];
				out2 = hexchars[c & 15];
			}

			session_map_t* get_session_map_with_add()
			{
				if (session_map_ptr_)
				{
					return session_map_ptr_;
				}

				auto& cookie = ctx_.get_req_ctx<cookies>();
				auto session_id = cookie.get("CSESSIONID");
				if (session_id.empty())
				{
					boost::uuids::uuid u = boost::uuids::random_generator()();
					for (auto c : u)
					{
						char out1, out2;
						itoh(c, out1, out2);
						session_id.push_back(out1);
						session_id.push_back(out2);
					}

					cookies::cookie_t c;
					c.add("CSESSIONID", session_id);
					cookie.add_cookie(c);
				}

// 				sessions_.emplace(session_id_, session_map_t());
				session_map_ptr_ = &sessions_[session_id];
				return session_map_ptr_;
			}

			context_container& ctx_;
			session_map_t* session_map_ptr_ = nullptr;
			bool session_map_ptr_not_found_ = false;

			std::unordered_map<std::string, session_map_t>& sessions_;
		};
	private:
		std::mutex mtx_;
		std::unordered_map<std::string, session_map_t> sessions_;
	};

}<commit_msg>session中访问全局的map需要加锁<commit_after>
#pragma once

#include <cinatra_http/request.h>
#include <cinatra_http/response.h>
#include <cinatra/context_container.hpp>
#include <cinatra/middleware/cookies.hpp>

#include <boost/any.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>

#include <unordered_map>
#include <string>
#include <thread>
#include <atomic>
#include <mutex>

namespace cinatra
{
	class session
	{
	public:
		void before(request const& req, response& res, context_container& ctx)
		{
			ctx.add_req_ctx(context_t(sessions_, mtx_, ctx));
		}

		void after(request const& req, response& res, context_container& ctx)
		{

		}

		struct session_map_t
		{
			session_map_t()
				:last_used_time(std::time(nullptr))
			{}
			std::time_t last_used_time;
			std::unordered_map<std::string, boost::any> m;
		};

		class context_t
		{
		public:
			context_t(std::unordered_map<std::string, session_map_t>& sessions, std::mutex& mtx, context_container& ctx)
				:sessions_(sessions), mtx_(mtx), ctx_(ctx)
			{

			}

			template<typename T>
			T& get(std::string const& key)
			{
				auto sp = get_session_map_with_session_id();
				if (!sp)
				{
					throw std::invalid_argument("key " + key + " not found");
				}

				auto it = sp->m.find(key);
				if (it == sp->m.end())
				{
					throw std::invalid_argument("key " + key + " not found");
				}

				return boost::any_cast<T&>(it->second);
			}

			template<typename T>
			void add(std::string const& key, T const& val)
			{
				auto sp = get_session_map_with_add();
				sp->m.emplace(key, val);
			}

			bool has(std::string const& key)
			{
				auto sp = get_session_map_with_session_id();
				if (!sp)
				{
					return false;
				}

				return sp->m.find(key) != sp->m.end();
			}

			bool del(std::string const& key)
			{
				auto sp = get_session_map_with_session_id();
				if (!sp)
				{
					return false;
				}

				auto it = sp->m.find(key);
				if (it == sp->m.end())
				{
					return false;
				}

				sp->m.erase(it);
				return true;
			}
		private:
			std::string get_session_id()
			{
				auto& cookie = ctx_.get_req_ctx<cookies>();
				return cookie.get("CSESSIONID");
			}

			session_map_t* get_session_map()
			{
				return session_map_ptr_;
			}

			session_map_t* get_session_map_with_session_id()
			{
				if (session_map_ptr_)
				{
					return session_map_ptr_;
				}
				if (session_map_ptr_not_found_)
				{
					return nullptr;
				}

				auto& cookie = ctx_.get_req_ctx<cookies>();
				auto session_id = cookie.get("CSESSIONID");
				if (session_id.empty())
				{
					session_map_ptr_not_found_ = true;
					return nullptr;
				}

				std::lock_guard<std::mutex> _(mtx_);
				auto it = sessions_.find(session_id);
				if (it == sessions_.end())
				{
					session_map_ptr_not_found_ = true;
					return nullptr;
				}

				session_map_ptr_ = &it->second;

				return session_map_ptr_;
			}

			inline void itoh(int c, char& out1, char& out2)
			{
				unsigned char hexchars[] = "0123456789ABCDEF";
				out1 = hexchars[c >> 4];
				out2 = hexchars[c & 15];
			}

			session_map_t* get_session_map_with_add()
			{
				if (session_map_ptr_)
				{
					return session_map_ptr_;
				}

				auto& cookie = ctx_.get_req_ctx<cookies>();
				auto session_id = cookie.get("CSESSIONID");
				if (session_id.empty())
				{
					boost::uuids::uuid u = boost::uuids::random_generator()();
					for (auto c : u)
					{
						char out1, out2;
						itoh(c, out1, out2);
						session_id.push_back(out1);
						session_id.push_back(out2);
					}

					cookies::cookie_t c;
					c.add("CSESSIONID", session_id);
					cookie.add_cookie(c);
				}

				std::lock_guard<std::mutex> _(mtx_);
// 				sessions_.emplace(session_id_, session_map_t());
				session_map_ptr_ = &sessions_[session_id];
				return session_map_ptr_;
			}

			context_container& ctx_;
			session_map_t* session_map_ptr_ = nullptr;
			bool session_map_ptr_not_found_ = false;

			std::mutex& mtx_;
			std::unordered_map<std::string, session_map_t>& sessions_;
		};
	private:
		std::mutex mtx_;
		std::unordered_map<std::string, session_map_t> sessions_;
	};

}<|endoftext|>


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

#include "private/filament/SamplerBindingMap.h"

#include "private/filament/SamplerInterfaceBlock.h"

#include <private/filament/SibGenerator.h>

#include <utils/Log.h>

namespace filament {

void SamplerBindingMap::populate(const SamplerInterfaceBlock* perMaterialSib,
            const char* materialName) {
    // We assume material variant 0 here, which is sufficient for calculating the binding map.
    // The material variant currently only affects sampler formats (for VSM), not offsets.
    const Variant dummyVariant{};
    uint8_t offset = 0;
    for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) {
        mSamplerBlockOffsets[blockIndex] = offset;
        filament::SamplerInterfaceBlock const* sib;
        if (blockIndex == filament::BindingPoints::PER_MATERIAL_INSTANCE) {
            sib = perMaterialSib;
        } else {
            sib = filament::SibGenerator::getSib(blockIndex, dummyVariant);
        }
        if (sib) {
            auto sibFields = sib->getSamplerInfoList();
            for (const auto& sInfo : sibFields) {
                addSampler({
                    .blockIndex = blockIndex,
                    .localOffset = sInfo.offset,
                    .globalOffset = offset++,
                });
            }
        }
    }

    auto isOverflow = [&perMaterialSib, &dummyVariant]() {
        size_t numVertexSampler = 0, numFragmentSampler = 0;
        for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) {
            filament::SamplerInterfaceBlock const* sib;
            if (blockIndex == filament::BindingPoints::PER_MATERIAL_INSTANCE) {
                sib = perMaterialSib;
            } else {
                sib = filament::SibGenerator::getSib(blockIndex, dummyVariant);
            }
            if (sib) {
                // Shader stage flags is only needed to check if MAX_SAMPLER_COUNT is exceeded.
                // Somehow if we can get shader stage flags from Program then we can remove it in SamplerInterfaceBlock.
                const auto stageFlags = sib->getStageFlags();
                if (stageFlags.vertex) {
                    numVertexSampler += sib->getSamplerInfoList().size();
                }
                if (stageFlags.fragment) {
                    numFragmentSampler += sib->getSamplerInfoList().size();
                }
                if (numVertexSampler >= backend::MAX_VERTEX_SAMPLER_COUNT ||
                    numFragmentSampler >= backend::MAX_FRAGMENT_SAMPLER_COUNT) {
                    return true;
                }
            }
        }
        return false;
    };

    // If an overflow occurred, go back through and list all sampler names. This is helpful to
    // material authors who need to understand where the samplers are coming from.
    if (isOverflow()) {
        utils::slog.e << "WARNING: Exceeded max sampler count of " << backend::MAX_SAMPLER_COUNT;
        if (materialName) {
            utils::slog.e << " (" << materialName << ")";
        }
        utils::slog.e << utils::io::endl;
        offset = 0;
        for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) {
            filament::SamplerInterfaceBlock const* sib;
            if (blockIndex == filament::BindingPoints::PER_MATERIAL_INSTANCE) {
                sib = perMaterialSib;
            } else {
                sib = filament::SibGenerator::getSib(blockIndex, dummyVariant);
            }
            if (sib) {
                auto sibFields = sib->getSamplerInfoList();
                for (auto sInfo : sibFields) {
                    utils::slog.e << "  " << (int) offset << " " << sInfo.name.c_str()
                        << " " << sib->getStageFlags() << utils::io::endl;
                    offset++;
                }
            }
        }
    }
}

void SamplerBindingMap::addSampler(SamplerBindingInfo info) {
    if (info.globalOffset < mSamplerBlockOffsets[info.blockIndex]) {
        mSamplerBlockOffsets[info.blockIndex] = info.globalOffset;
    }
    mBindingMap[getBindingKey(info.blockIndex, info.localOffset)] = info;
}

} // namespace filament
<commit_msg>Fix sampler overflow check in SamplerBindingMap (#5143)<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "private/filament/SamplerBindingMap.h"

#include "private/filament/SamplerInterfaceBlock.h"

#include <private/filament/SibGenerator.h>

#include <utils/Log.h>

namespace filament {

void SamplerBindingMap::populate(const SamplerInterfaceBlock* perMaterialSib,
            const char* materialName) {
    // We assume material variant 0 here, which is sufficient for calculating the binding map.
    // The material variant currently only affects sampler formats (for VSM), not offsets.
    const Variant dummyVariant{};
    uint8_t offset = 0;
    for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) {
        mSamplerBlockOffsets[blockIndex] = offset;
        filament::SamplerInterfaceBlock const* sib;
        if (blockIndex == filament::BindingPoints::PER_MATERIAL_INSTANCE) {
            sib = perMaterialSib;
        } else {
            sib = filament::SibGenerator::getSib(blockIndex, dummyVariant);
        }
        if (sib) {
            auto sibFields = sib->getSamplerInfoList();
            for (const auto& sInfo : sibFields) {
                addSampler({
                    .blockIndex = blockIndex,
                    .localOffset = sInfo.offset,
                    .globalOffset = offset++,
                });
            }
        }
    }

    auto isOverflow = [&perMaterialSib, &dummyVariant]() {
        size_t numVertexSampler = 0, numFragmentSampler = 0;
        for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) {
            filament::SamplerInterfaceBlock const* sib;
            if (blockIndex == filament::BindingPoints::PER_MATERIAL_INSTANCE) {
                sib = perMaterialSib;
            } else {
                sib = filament::SibGenerator::getSib(blockIndex, dummyVariant);
            }
            if (sib) {
                // Shader stage flags is only needed to check if MAX_SAMPLER_COUNT is exceeded.
                // Somehow if we can get shader stage flags from Program then we can remove it in SamplerInterfaceBlock.
                const auto stageFlags = sib->getStageFlags();
                if (stageFlags.vertex) {
                    numVertexSampler += sib->getSamplerInfoList().size();
                }
                if (stageFlags.fragment) {
                    numFragmentSampler += sib->getSamplerInfoList().size();
                }
                if (numVertexSampler > backend::MAX_VERTEX_SAMPLER_COUNT ||
                    numFragmentSampler > backend::MAX_FRAGMENT_SAMPLER_COUNT) {
                    return true;
                }
            }
        }
        return false;
    };

    // If an overflow occurred, go back through and list all sampler names. This is helpful to
    // material authors who need to understand where the samplers are coming from.
    if (isOverflow()) {
        utils::slog.e << "WARNING: Exceeded max sampler count of " << backend::MAX_SAMPLER_COUNT;
        if (materialName) {
            utils::slog.e << " (" << materialName << ")";
        }
        utils::slog.e << utils::io::endl;
        offset = 0;
        for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) {
            filament::SamplerInterfaceBlock const* sib;
            if (blockIndex == filament::BindingPoints::PER_MATERIAL_INSTANCE) {
                sib = perMaterialSib;
            } else {
                sib = filament::SibGenerator::getSib(blockIndex, dummyVariant);
            }
            if (sib) {
                auto sibFields = sib->getSamplerInfoList();
                for (auto sInfo : sibFields) {
                    utils::slog.e << "  " << (int) offset << " " << sInfo.name.c_str()
                        << " " << sib->getStageFlags() << utils::io::endl;
                    offset++;
                }
            }
        }
    }
}

void SamplerBindingMap::addSampler(SamplerBindingInfo info) {
    if (info.globalOffset < mSamplerBlockOffsets[info.blockIndex]) {
        mSamplerBlockOffsets[info.blockIndex] = info.globalOffset;
    }
    mBindingMap[getBindingKey(info.blockIndex, info.localOffset)] = info;
}

} // namespace filament
<|endoftext|>


<commit_before>#include "SIO/LCIORecords.h"

#include <SIO/SIORunHeaderHandler.h>
#include <SIO/SIOEventHandler.h>
#include <SIO/SIOCollectionHandler.h>
#include <SIO/SIORandomAccessHandler.h>
#include <SIO/SIOIndexHandler.h>
#include <EVENT/LCEvent.h>
#include <Exceptions.h>

// -- sio headers
#include <sio/exception.h>
#include <sio/api.h>

namespace SIO {

  void SIOEventHeaderRecord::readBlocks( const sio::buffer_span &buffer, EVENT::LCEvent *event, const std::vector<std::string> &readCol ) {
    sio::block_list blocks {} ;
    auto headerBlock = std::make_shared<SIOEventHandler>() ;
    headerBlock->setEvent( event ) ;
    headerBlock->setReadCollectionNames( readCol ) ;
    blocks.push_back( headerBlock ) ;
    sio::api::read_blocks( buffer, blocks ) ;
  }

  //----------------------------------------------------------------------------

  void SIOEventHeaderRecord::writeRecord( sio::buffer &outbuf, EVENT::LCEvent *event, sio::record_info& rec_info, sio::options_type opts ) {
    sio::block_list blocks {} ;
    auto headerBlock = std::make_shared<SIOEventHandler>() ;
    headerBlock->setEvent( event ) ;
    blocks.push_back( headerBlock ) ;
    rec_info = sio::api::write_record( LCSIO::HeaderRecordName, outbuf, blocks, opts ) ;
  }

  //----------------------------------------------------------------------------

  void SIOEventRecord::setupBlocks( EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr, sio::block_list &blocks ) {
    auto collectionNames = event->getCollectionNames();
    for( auto collectionName : *collectionNames ) {
      auto collection = event->getCollection( collectionName ) ;
      // this is never true while reading. Can only appear on writing
      if( collection->isTransient() ) {
        continue;
      }
      auto handler = handlerMgr.getHandler( collection->getTypeName() ) ;
      auto block = std::make_shared<SIOCollectionHandler>( collectionName, handler ) ;
      block->setCollection( collection );
      blocks.push_back( block ) ;
    }
  }

  //----------------------------------------------------------------------------

  void SIOEventRecord::readBlocks( const sio::buffer_span &buffer, EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr ) {
    sio::block_list blocks {} ;
    SIOEventRecord::setupBlocks( event, handlerMgr, blocks ) ;
    sio::api::read_blocks( buffer, blocks ) ;
  }

  //----------------------------------------------------------------------------

  void SIOEventRecord::writeRecord( sio::buffer &outbuf, EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr, sio::record_info& rec_info, sio::options_type opts ) {
    sio::block_list blocks {} ;
    SIOEventRecord::setupBlocks( event, handlerMgr, blocks ) ;
    rec_info = sio::api::write_record( LCSIO::HeaderRecordName, outbuf, blocks, opts ) ;
  }

  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------

  void SIORunHeaderRecord::readBlocks( const sio::buffer_span &buffer, EVENT::LCRunHeader *rhdr ) {
    sio::block_list blocks {} ;
    auto runBlock = std::make_shared<SIORunHeaderHandler>() ;
    runBlock->setRunHeader( rhdr ) ;
    blocks.push_back( runBlock ) ;
    sio::api::read_blocks( buffer, blocks ) ;
  }

  //----------------------------------------------------------------------------

  void SIORunHeaderRecord::writeRecord( sio::buffer &outbuf, EVENT::LCRunHeader *rhdr, sio::record_info& rec_info, sio::options_type opts ) {
    sio::block_list blocks {} ;
    auto runBlock = std::make_shared<SIORunHeaderHandler>() ;
    runBlock->setRunHeader( rhdr ) ;
    blocks.push_back( runBlock ) ;
    rec_info = sio::api::write_record( LCSIO::RunRecordName, outbuf, blocks, opts ) ;
  }

} // namespace
<commit_msg>Fixed wrong record name<commit_after>#include "SIO/LCIORecords.h"

#include <SIO/SIORunHeaderHandler.h>
#include <SIO/SIOEventHandler.h>
#include <SIO/SIOCollectionHandler.h>
#include <SIO/SIORandomAccessHandler.h>
#include <SIO/SIOIndexHandler.h>
#include <EVENT/LCEvent.h>
#include <Exceptions.h>

// -- sio headers
#include <sio/exception.h>
#include <sio/api.h>

namespace SIO {

  void SIOEventHeaderRecord::readBlocks( const sio::buffer_span &buffer, EVENT::LCEvent *event, const std::vector<std::string> &readCol ) {
    sio::block_list blocks {} ;
    auto headerBlock = std::make_shared<SIOEventHandler>() ;
    headerBlock->setEvent( event ) ;
    headerBlock->setReadCollectionNames( readCol ) ;
    blocks.push_back( headerBlock ) ;
    sio::api::read_blocks( buffer, blocks ) ;
  }

  //----------------------------------------------------------------------------

  void SIOEventHeaderRecord::writeRecord( sio::buffer &outbuf, EVENT::LCEvent *event, sio::record_info& rec_info, sio::options_type opts ) {
    sio::block_list blocks {} ;
    auto headerBlock = std::make_shared<SIOEventHandler>() ;
    headerBlock->setEvent( event ) ;
    blocks.push_back( headerBlock ) ;
    rec_info = sio::api::write_record( LCSIO::HeaderRecordName, outbuf, blocks, opts ) ;
  }

  //----------------------------------------------------------------------------

  void SIOEventRecord::setupBlocks( EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr, sio::block_list &blocks ) {
    auto collectionNames = event->getCollectionNames();
    for( auto collectionName : *collectionNames ) {
      auto collection = event->getCollection( collectionName ) ;
      // this is never true while reading. Can only appear on writing
      if( collection->isTransient() ) {
        continue;
      }
      auto handler = handlerMgr.getHandler( collection->getTypeName() ) ;
      auto block = std::make_shared<SIOCollectionHandler>( collectionName, handler ) ;
      block->setCollection( collection );
      blocks.push_back( block ) ;
    }
  }

  //----------------------------------------------------------------------------

  void SIOEventRecord::readBlocks( const sio::buffer_span &buffer, EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr ) {
    sio::block_list blocks {} ;
    SIOEventRecord::setupBlocks( event, handlerMgr, blocks ) ;
    sio::api::read_blocks( buffer, blocks ) ;
  }

  //----------------------------------------------------------------------------

  void SIOEventRecord::writeRecord( sio::buffer &outbuf, EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr, sio::record_info& rec_info, sio::options_type opts ) {
    sio::block_list blocks {} ;
    SIOEventRecord::setupBlocks( event, handlerMgr, blocks ) ;
    rec_info = sio::api::write_record( LCSIO::EventRecordName, outbuf, blocks, opts ) ;
  }

  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------

  void SIORunHeaderRecord::readBlocks( const sio::buffer_span &buffer, EVENT::LCRunHeader *rhdr ) {
    sio::block_list blocks {} ;
    auto runBlock = std::make_shared<SIORunHeaderHandler>() ;
    runBlock->setRunHeader( rhdr ) ;
    blocks.push_back( runBlock ) ;
    sio::api::read_blocks( buffer, blocks ) ;
  }

  //----------------------------------------------------------------------------

  void SIORunHeaderRecord::writeRecord( sio::buffer &outbuf, EVENT::LCRunHeader *rhdr, sio::record_info& rec_info, sio::options_type opts ) {
    sio::block_list blocks {} ;
    auto runBlock = std::make_shared<SIORunHeaderHandler>() ;
    runBlock->setRunHeader( rhdr ) ;
    blocks.push_back( runBlock ) ;
    rec_info = sio::api::write_record( LCSIO::RunRecordName, outbuf, blocks, opts ) ;
  }

} // namespace
<|endoftext|>


<commit_before>#include "SIO/RunEventMap.h"

#include <iostream>

namespace SIO {

  bool operator < ( const RunEvent& r0, const RunEvent& other) {

    //std::cout << r0 << " < " << other << " : ["
    //<<  ( r0.RunNum == other.RunNum ?  r0.EvtNum < other.EvtNum  :  r0.RunNum < other.RunNum )  << "]" << std::endl;

    if( r0.EvtNum < 0 ) { // sort run records (evtNu == -1 ) first

      return ( other.EvtNum < 0 ?  r0.RunNum < other.RunNum : true ) ;
    }
    else if( other.EvtNum < 0 ) return false ;

    return ( r0.RunNum == other.RunNum ?  r0.EvtNum < other.EvtNum  :  r0.RunNum < other.RunNum ) ;
  }

  //----------------------------------------------------------------------------

  std::ostream & operator<<(std::ostream& os, const RunEvent& re ) {

    os << " run: " << re.RunNum << " - evt: " << re.EvtNum ;

    return os ;
  }

  //----------------------------------------------------------------------------

  void RunEventMap::add(const RunEvent& re, long64 pos ) {
    auto p = _map.insert( std::make_pair( (long64) re , pos ) ) ;
    // if event/run exists don't count as new entry
    if( p.second ) {
      if( re.EvtNum > -1 ) {
        ++_nEvt ;
      }
      else {
        ++ _nRun ;
      }

    }
    // overwrite with new entry
    else {
      p.first->second = pos ;
    }
  }

  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------

  RunEventMap::long64 RunEventMap::getPosition( long64 re ) {
    auto it = _map.find( re ) ;
    return ( it != _map.end() ? it->second : npos ) ;
  }

  //----------------------------------------------------------------------------

  RunEvent RunEventMap::minRunEvent() const {
    if( _map.empty() ) {
      return RunEvent( -1 , -1 ) ;
    }
    return _map.begin()->first ;
  }

  //----------------------------------------------------------------------------

  RunEvent RunEventMap::maxRunEvent() const {
    if( _map.empty() ) {
      return RunEvent( -1 , -1 ) ;
    }
    auto it =  _map.rbegin() ;
    return it->first ;
  }

  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------

  std::ostream & operator<<(std::ostream& os, const RunEventMap& rm ) {
    os << " ------- RunEventMap : " << std::endl ;
    for( auto it = rm.begin() ; it != rm.end() ; ++it ) {
      os << "  " << RunEvent( it->first ).RunNum << ", " << RunEvent( it->first ).EvtNum << "  :  " << it->second << std::endl;
    }
    return os ;
  }

}
<commit_msg>Missing const for getters<commit_after>#include "SIO/RunEventMap.h"

#include <iostream>

namespace SIO {

  bool operator < ( const RunEvent& r0, const RunEvent& other) {

    //std::cout << r0 << " < " << other << " : ["
    //<<  ( r0.RunNum == other.RunNum ?  r0.EvtNum < other.EvtNum  :  r0.RunNum < other.RunNum )  << "]" << std::endl;

    if( r0.EvtNum < 0 ) { // sort run records (evtNu == -1 ) first

      return ( other.EvtNum < 0 ?  r0.RunNum < other.RunNum : true ) ;
    }
    else if( other.EvtNum < 0 ) return false ;

    return ( r0.RunNum == other.RunNum ?  r0.EvtNum < other.EvtNum  :  r0.RunNum < other.RunNum ) ;
  }

  //----------------------------------------------------------------------------

  std::ostream & operator<<(std::ostream& os, const RunEvent& re ) {

    os << " run: " << re.RunNum << " - evt: " << re.EvtNum ;

    return os ;
  }

  //----------------------------------------------------------------------------

  void RunEventMap::add(const RunEvent& re, long64 pos ) {
    auto p = _map.insert( std::make_pair( (long64) re , pos ) ) ;
    // if event/run exists don't count as new entry
    if( p.second ) {
      if( re.EvtNum > -1 ) {
        ++_nEvt ;
      }
      else {
        ++ _nRun ;
      }

    }
    // overwrite with new entry
    else {
      p.first->second = pos ;
    }
  }

  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------

  RunEventMap::long64 RunEventMap::getPosition( long64 re ) {
    auto it = _map.find( re ) ;
    return ( it != _map.end() ? it->second : npos ) ;
  }

  //----------------------------------------------------------------------------

  RunEvent RunEventMap::minRunEvent() const {
    if( _map.empty() ) {
      return RunEvent( -1 , -1 ) ;
    }
    return _map.begin()->first ;
  }

  //----------------------------------------------------------------------------

  RunEvent RunEventMap::maxRunEvent() const {
    if( _map.empty() ) {
      return RunEvent( -1 , -1 ) ;
    }
    auto it =  _map.rbegin() ;
    return it->first ;
  }

  //----------------------------------------------------------------------------

  //----------------------------------------------------------------------------

  std::ostream & operator<<(std::ostream& os, const RunEventMap& rm ) {
    os << " ------- RunEventMap : " << std::endl ;
    for( auto it = rm.begin() ; it != rm.end() ; ++it ) {
      os << "  " << RunEvent( it->first ).RunNum << ", " << RunEvent( it->first ).EvtNum << "  :  " << it->second << std::endl;
    }
    return os ;
  }

}
<|endoftext|>


<commit_before>#include "SparseVector.h"
#include "Matrix.h"
#include "../file_parser/FileParser.h"
#include "../file_parser/MatrixElement.h"
#include "../utils/GapsAssert.h"

#include <iterator>

Matrix::Matrix() : mNumRows(0), mNumCols(0) {}

Matrix::Matrix(unsigned nrow, unsigned ncol)
    :
mCols(ncol, Vector(nrow)),
mNumRows(nrow),
mNumCols(ncol)
{}

void Matrix::pad(float val)
{
    for (unsigned j = 0; j < mNumCols; ++j)
    {
        mCols[j].pad(val);
    }
}

// constructor from data set read in as a matrix
Matrix::Matrix(const Matrix &mat, bool genesInCols, bool subsetGenes,
std::vector<unsigned> indices)
{
#ifdef GAPS_DEBUG
    for (unsigned i = 0; i < indices.size(); ++i)
    {
        GAPS_ASSERT_MSG(indices[i] > 0,
            "index 0 detected in subset: R indices should start at 1\n");
    }
#endif

    bool subsetData = !indices.empty();

    unsigned nGenes = (subsetData && subsetGenes)
        ? indices.size()
        : genesInCols ? mat.nCol() : mat.nRow();
    unsigned nSamples = (subsetData && !subsetGenes)
        ? indices.size()
        : genesInCols ? mat.nRow() : mat.nCol();

    for (unsigned j = 0; j < nSamples; ++j)
    {
        mCols.push_back(Vector(nGenes));
        for (unsigned i = 0; i < nGenes; ++i)
        {
            unsigned dataRow = (subsetData && (subsetGenes != genesInCols))
                ? indices[genesInCols ? j : i] - 1
                : genesInCols ? j : i;

            unsigned dataCol = (subsetData && (subsetGenes == genesInCols))
                ? indices[genesInCols ? i : j] - 1
                : genesInCols ? i : j;

            mCols[j][i] = mat(dataRow, dataCol);
        }
    }
    mNumRows = nGenes;
    mNumCols = nSamples;
}

// constructor from data set given as a file path
Matrix::Matrix(const std::string &path, bool genesInCols, bool subsetGenes,
std::vector<unsigned> indices)
{
#ifdef GAPS_DEBUG
    for (unsigned i = 0; i < indices.size(); ++i)
    {
        GAPS_ASSERT_MSG(indices[i] > 0,
            "index 0 detected in subset: R indices should start at 1\n");
    }
#endif

    FileParser fp(path);

    // calculate the number of rows and columns
    bool subsetData = !indices.empty();
    mNumRows = (subsetData && subsetGenes) // nGenes
        ? indices.size()
        : genesInCols ? fp.nCol() : fp.nRow();
    mNumCols = (subsetData && !subsetGenes) // nSamples
        ? indices.size()
        : genesInCols ? fp.nRow() : fp.nCol();

    // allocate space for the data
    for (unsigned j = 0; j < mNumCols; ++j)
    {
        mCols.push_back(Vector(mNumRows));
    }

    // read from file
    if (!subsetData)
    {
        while (fp.hasNext())
        {
            MatrixElement e(fp.getNext());
            unsigned row = genesInCols ? e.col : e.row;
            unsigned col = genesInCols ? e.row : e.col;
            mCols[col][row] = e.value;
        }
    }
    else
    {
        std::sort(indices.begin(), indices.end());
        while (fp.hasNext())
        {
            MatrixElement e(fp.getNext());
            unsigned searchIndex = 1 + ((subsetGenes != genesInCols) ? e.row : e.col);
            std::vector<unsigned>::iterator pos =
                std::lower_bound(indices.begin(), indices.end(), searchIndex);

            // this index is included in the subset
            if (pos != indices.end() && *pos == searchIndex)
            {
                unsigned row = subsetGenes
                    ? std::distance(indices.begin(), pos)
                    : genesInCols ? e.col : e.row;
                unsigned col = !subsetGenes
                    ? std::distance(indices.begin(), pos)
                    : genesInCols ? e.row : e.col;
                mCols[col][row] = e.value;
            }
        }
    }
}

unsigned Matrix::nRow() const
{
    return mNumRows;
}

unsigned Matrix::nCol() const
{
    return mNumCols;
}

float Matrix::operator()(unsigned i, unsigned j) const
{
    GAPS_ASSERT_MSG(i < mNumRows, i << " : " << mNumRows);
    GAPS_ASSERT_MSG(j < mNumCols, j << " : " << mNumCols);
    return mCols[j][i];
}

float& Matrix::operator()(unsigned i, unsigned j)
{
    GAPS_ASSERT_MSG(i < mNumRows, i << " : " << mNumRows);
    GAPS_ASSERT_MSG(j < mNumCols, j << " : " << mNumCols);
    return mCols[j][i];
}

Vector& Matrix::getCol(unsigned col)
{
    GAPS_ASSERT_MSG(col < mNumCols, col << " : " << mNumCols);
    return mCols[col];
}

const Vector& Matrix::getCol(unsigned col) const
{
    GAPS_ASSERT_MSG(col < mNumCols, col << " : " << mNumCols);
    return mCols[col];
}

bool Matrix::empty() const
{
    return mNumRows == 0;
}

Archive& operator<<(Archive &ar, const Matrix &mat)
{
    ar << mat.mNumRows << mat.mNumCols;
    for (unsigned j = 0; j < mat.mNumCols; ++j)
    {
        ar << mat.mCols[j];
    }
    return ar;
}

Archive& operator>>(Archive &ar, Matrix &mat)
{
    unsigned nr = 0, nc = 0;
    ar >> nr >> nc;
    GAPS_ASSERT(nr == mat.mNumRows);
    GAPS_ASSERT(nc == mat.mNumCols);

    for (unsigned j = 0; j < mat.mNumCols; ++j)
    {
        ar >> mat.mCols[j];
    }
    return ar;
}

void ColMatrix::overwriteWith(const RowMatrix &mat, unsigned nCores)
{
    GAPS_ASSERT_MSG(mat.nRow() == nRow(), mat.nRow() << " " << nRow());
    GAPS_ASSERT_MSG(mat.nCol() == nCol(), mat.nCol() << " " << nCol());

    #pragma omp parallel for num_threads(nCores)
    for (unsigned i = 0; i < mNumRows; ++i)
    {
        for (unsigned j = 0; j < mNumCols; ++j)
        {
            this->operator()(i,j) = mat(i,j);
        }
    }
}
<commit_msg>removed unneccesary function<commit_after>#include "SparseVector.h"
#include "Matrix.h"
#include "../file_parser/FileParser.h"
#include "../file_parser/MatrixElement.h"
#include "../utils/GapsAssert.h"

#include <iterator>

Matrix::Matrix() : mNumRows(0), mNumCols(0) {}

Matrix::Matrix(unsigned nrow, unsigned ncol)
    :
mCols(ncol, Vector(nrow)),
mNumRows(nrow),
mNumCols(ncol)
{}

void Matrix::pad(float val)
{
    for (unsigned j = 0; j < mNumCols; ++j)
    {
        mCols[j].pad(val);
    }
}

// constructor from data set read in as a matrix
Matrix::Matrix(const Matrix &mat, bool genesInCols, bool subsetGenes,
std::vector<unsigned> indices)
{
#ifdef GAPS_DEBUG
    for (unsigned i = 0; i < indices.size(); ++i)
    {
        GAPS_ASSERT_MSG(indices[i] > 0,
            "index 0 detected in subset: R indices should start at 1\n");
    }
#endif

    bool subsetData = !indices.empty();

    unsigned nGenes = (subsetData && subsetGenes)
        ? indices.size()
        : genesInCols ? mat.nCol() : mat.nRow();
    unsigned nSamples = (subsetData && !subsetGenes)
        ? indices.size()
        : genesInCols ? mat.nRow() : mat.nCol();

    for (unsigned j = 0; j < nSamples; ++j)
    {
        mCols.push_back(Vector(nGenes));
        for (unsigned i = 0; i < nGenes; ++i)
        {
            unsigned dataRow = (subsetData && (subsetGenes != genesInCols))
                ? indices[genesInCols ? j : i] - 1
                : genesInCols ? j : i;

            unsigned dataCol = (subsetData && (subsetGenes == genesInCols))
                ? indices[genesInCols ? i : j] - 1
                : genesInCols ? i : j;

            mCols[j][i] = mat(dataRow, dataCol);
        }
    }
    mNumRows = nGenes;
    mNumCols = nSamples;
}

// constructor from data set given as a file path
Matrix::Matrix(const std::string &path, bool genesInCols, bool subsetGenes,
std::vector<unsigned> indices)
{
#ifdef GAPS_DEBUG
    for (unsigned i = 0; i < indices.size(); ++i)
    {
        GAPS_ASSERT_MSG(indices[i] > 0,
            "index 0 detected in subset: R indices should start at 1\n");
    }
#endif

    FileParser fp(path);

    // calculate the number of rows and columns
    bool subsetData = !indices.empty();
    mNumRows = (subsetData && subsetGenes) // nGenes
        ? indices.size()
        : genesInCols ? fp.nCol() : fp.nRow();
    mNumCols = (subsetData && !subsetGenes) // nSamples
        ? indices.size()
        : genesInCols ? fp.nRow() : fp.nCol();

    // allocate space for the data
    for (unsigned j = 0; j < mNumCols; ++j)
    {
        mCols.push_back(Vector(mNumRows));
    }

    // read from file
    if (!subsetData)
    {
        while (fp.hasNext())
        {
            MatrixElement e(fp.getNext());
            unsigned row = genesInCols ? e.col : e.row;
            unsigned col = genesInCols ? e.row : e.col;
            mCols[col][row] = e.value;
        }
    }
    else
    {
        std::sort(indices.begin(), indices.end());
        while (fp.hasNext())
        {
            MatrixElement e(fp.getNext());
            unsigned searchIndex = 1 + ((subsetGenes != genesInCols) ? e.row : e.col);
            std::vector<unsigned>::iterator pos =
                std::lower_bound(indices.begin(), indices.end(), searchIndex);

            // this index is included in the subset
            if (pos != indices.end() && *pos == searchIndex)
            {
                unsigned row = subsetGenes
                    ? std::distance(indices.begin(), pos)
                    : genesInCols ? e.col : e.row;
                unsigned col = !subsetGenes
                    ? std::distance(indices.begin(), pos)
                    : genesInCols ? e.row : e.col;
                mCols[col][row] = e.value;
            }
        }
    }
}

unsigned Matrix::nRow() const
{
    return mNumRows;
}

unsigned Matrix::nCol() const
{
    return mNumCols;
}

float Matrix::operator()(unsigned i, unsigned j) const
{
    GAPS_ASSERT_MSG(i < mNumRows, i << " : " << mNumRows);
    GAPS_ASSERT_MSG(j < mNumCols, j << " : " << mNumCols);
    return mCols[j][i];
}

float& Matrix::operator()(unsigned i, unsigned j)
{
    GAPS_ASSERT_MSG(i < mNumRows, i << " : " << mNumRows);
    GAPS_ASSERT_MSG(j < mNumCols, j << " : " << mNumCols);
    return mCols[j][i];
}

Vector& Matrix::getCol(unsigned col)
{
    GAPS_ASSERT_MSG(col < mNumCols, col << " : " << mNumCols);
    return mCols[col];
}

const Vector& Matrix::getCol(unsigned col) const
{
    GAPS_ASSERT_MSG(col < mNumCols, col << " : " << mNumCols);
    return mCols[col];
}

bool Matrix::empty() const
{
    return mNumRows == 0;
}

Archive& operator<<(Archive &ar, const Matrix &mat)
{
    ar << mat.mNumRows << mat.mNumCols;
    for (unsigned j = 0; j < mat.mNumCols; ++j)
    {
        ar << mat.mCols[j];
    }
    return ar;
}

Archive& operator>>(Archive &ar, Matrix &mat)
{
    unsigned nr = 0, nc = 0;
    ar >> nr >> nc;
    GAPS_ASSERT(nr == mat.mNumRows);
    GAPS_ASSERT(nc == mat.mNumCols);

    for (unsigned j = 0; j < mat.mNumCols; ++j)
    {
        ar >> mat.mCols[j];
    }
    return ar;
}<|endoftext|>


<commit_before>/*============================================================================
  Copyright 2017-2021 Koichi Murakami

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file License for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include <getopt.h>
#include "jsonparser.h"

namespace {
// --------------------------------------------------------------------------
void show_version()
{
  std::cout << "jparser version 1.0.0" << std::endl;
}

// --------------------------------------------------------------------------
void show_help()
{
  std::cout << "j5parser - JSON5 parser" << std::endl;
  std::cout << "usage:" << std::endl;
  std::cout << "j5parser [options] [JSON5 file]"
            << std::endl << std::endl;
  std::cout << "   -h, --help          show this message." << std::endl
            << "   -v  --version       show program name/version." << std::endl
            << std::endl;
  std::cout << std::endl;
}

} // end of namespace

using namespace kut;

// --------------------------------------------------------------------------
int main(int argc, char** argv)
{
  // optional parameters
  bool qhelp = false;
  bool qversion = false;

  struct option long_options[] = {
    {"help",    no_argument,       NULL, 'h'},
    {"version", no_argument,       NULL, 'v'},
    {NULL,      0,                 NULL,  0}
  };

  int c;
  while (1) {
    int option_index = -1;

    c = getopt_long(argc, argv, "hv", long_options, &option_index);

    if (c == -1) break;

    switch (c) {
    case 'h' :
      qhelp = true;
      break;
    case 'v' :
      qversion = true;
      break;
    default:
      std::exit(EXIT_FAILURE);
      break;
    }
  }

  if ( qhelp ) {
    ::show_help();
  }

  if ( qversion ) {
    ::show_version();
  }

  if ( qhelp || qversion ) {
    std::exit(EXIT_SUCCESS);
  }

  // config file
  std::string config_file = "";
  if ( optind < argc ) {
    config_file = argv[optind];
  } else {
    ::show_help();
    std::exit(EXIT_FAILURE);
  }

  // ----------------------------------------------------------------------
  // parsing config JSON file...
  JsonParser* jparser = JsonParser::GetJsonParser();
  bool qload = jparser-> LoadFile(config_file);
  if ( ! qload ) {
    std::cout << "[ERROR] failed on loading a config file. "
              << config_file << std::endl;
    std::exit(EXIT_FAILURE);
  }

  qload = jparser-> LoadFile(config_file, "JSON-B");
  if ( ! qload ) {
    std::cout << "[ERROR] failed on loading a config file. "
              << config_file << std::endl;
    std::exit(EXIT_FAILURE);
  }

  jparser-> SelectJsonData("JSON-B");

  // ----------------------------------------------------------------------
  std::cout << "------------------------------" << std::endl;
  std::cout << "@@@ dump JSON data" << std::endl;
  jparser-> DumpAll();
  std::cout << "------------------------------" << std::endl;

  std::cout << "@@@ yes/no = "
            <<  jparser-> GetBoolValue("yesorno") << std::endl;

  std::vector<bool> ynlist;
  jparser-> GetBoolArray("yesorno_list", ynlist);
  std::cout << "@@@ yes/no list = ["
            << ynlist[0] << ", " << ynlist[1] << "]" << std::endl;

  std::cout << "@@@ Primary/type = "
            <<  jparser-> GetStringValue("Primary/type") << std::endl;

  std::cout << "@@@ Primary/number = "
            << jparser-> GetIntValue("Primary/number") << std::endl;

  std::vector<std::string> legend;
  jparser-> GetStringArray("Primary/legend", legend);
  std::cout << "@@@ Primary/legend = ["
            << legend[0] << ", " << legend[1] << ", "
            << legend[2] << "]" << std::endl;

  std::cout << "@@@ Geometry/size = "
            << jparser-> GetDoubleValue("Geometry/size") << std::endl;

  std::cout << "@@@ Geometry/type/name = "
            << jparser-> GetStringValue("Geometry/type/name") << std::endl;

  std::vector<int> segment;
  jparser-> GetIntArray("Geometry/segment", segment);
  std::cout << "@@@ Geometry/segment = ["
            << segment[0] << ", " << segment[1] << ", "
            << segment[2] << "]" << std::endl;

  std::vector<double> position;
  jparser-> GetDoubleArray("Geometry/position", position);
  std::cout << "@@@ Geometry/position = ["
            << position[0] << ", " << position[1] << ", "
            << position[2] << "]" << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>modify for using c++11 features<commit_after>/*============================================================================
  Copyright 2017-2021 Koichi Murakami

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file License for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include <getopt.h>
#include "jsonparser.h"

namespace {
// --------------------------------------------------------------------------
void show_version()
{
  std::cout << "jparser version 1.0.0" << std::endl;
}

// --------------------------------------------------------------------------
void show_help()
{
  std::cout << "j5parser - JSON5 parser" << std::endl;
  std::cout << "usage:" << std::endl;
  std::cout << "j5parser [options] [JSON5 file]"
            << std::endl << std::endl;
  std::cout << "   -h, --help          show this message." << std::endl
            << "   -v  --version       show program name/version." << std::endl
            << std::endl;
  std::cout << std::endl;
}

} // end of namespace

using namespace kut;

// --------------------------------------------------------------------------
int main(int argc, char** argv)
{
  // optional parameters
  bool qhelp {false};
  bool qversion {false};

  struct option long_options[] = {
    {"help",    no_argument,       NULL, 'h'},
    {"version", no_argument,       NULL, 'v'},
    {NULL,      0,                 NULL,  0}
  };

  int c;
  while (1) {
    int option_index {-1};

    c = getopt_long(argc, argv, "hv", long_options, &option_index);

    if (c == -1) break;

    switch (c) {
    case 'h' :
      qhelp = true;
      break;
    case 'v' :
      qversion = true;
      break;
    default:
      std::exit(EXIT_FAILURE);
      break;
    }
  }

  if ( qhelp ) {
    ::show_help();
  }

  if ( qversion ) {
    ::show_version();
  }

  if ( qhelp || qversion ) {
    std::exit(EXIT_SUCCESS);
  }

  // config file
  std::string config_file = "";
  if ( optind < argc ) {
    config_file = argv[optind];
  } else {
    ::show_help();
    std::exit(EXIT_FAILURE);
  }

  // ----------------------------------------------------------------------
  // parsing config JSON file...
  JsonParser* jparser = JsonParser::GetJsonParser();
  bool qload = jparser-> LoadFile(config_file);
  if ( ! qload ) {
    std::cout << "[ERROR] failed on loading a config file. "
              << config_file << std::endl;
    std::exit(EXIT_FAILURE);
  }

  qload = jparser-> LoadFile(config_file, "JSON-B");
  if ( ! qload ) {
    std::cout << "[ERROR] failed on loading a config file. "
              << config_file << std::endl;
    std::exit(EXIT_FAILURE);
  }

  jparser-> SelectJsonData("JSON-B");

  // ----------------------------------------------------------------------
  std::cout << "------------------------------" << std::endl;
  std::cout << "@@@ dump JSON data" << std::endl;
  jparser-> DumpAll();
  std::cout << "------------------------------" << std::endl;

  std::cout << "@@@ yes/no = "
            <<  jparser-> GetBoolValue("yesorno") << std::endl;

  std::vector<bool> ynlist;
  jparser-> GetBoolArray("yesorno_list", ynlist);
  std::cout << "@@@ yes/no list = ["
            << ynlist[0] << ", " << ynlist[1] << "]" << std::endl;

  std::cout << "@@@ Primary/type = "
            <<  jparser-> GetStringValue("Primary/type") << std::endl;

  std::cout << "@@@ Primary/number = "
            << jparser-> GetIntValue("Primary/number") << std::endl;

  std::vector<std::string> legend;
  jparser-> GetStringArray("Primary/legend", legend);
  std::cout << "@@@ Primary/legend = ["
            << legend[0] << ", " << legend[1] << ", "
            << legend[2] << "]" << std::endl;

  std::cout << "@@@ Geometry/size = "
            << jparser-> GetDoubleValue("Geometry/size") << std::endl;

  std::cout << "@@@ Geometry/type/name = "
            << jparser-> GetStringValue("Geometry/type/name") << std::endl;

  std::vector<int> segment;
  jparser-> GetIntArray("Geometry/segment", segment);
  std::cout << "@@@ Geometry/segment = ["
            << segment[0] << ", " << segment[1] << ", "
            << segment[2] << "]" << std::endl;

  std::vector<double> position;
  jparser-> GetDoubleArray("Geometry/position", position);
  std::cout << "@@@ Geometry/position = ["
            << position[0] << ", " << position[1] << ", "
            << position[2] << "]" << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// 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.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_HOOFS_CXX_STACK_INL
#define IOX_HOOFS_CXX_STACK_INL

#include "iceoryx_hoofs/cxx/stack.hpp"

namespace iox
{
namespace cxx
{
template <typename T, uint64_t Capacity>
inline auto stack<T, Capacity>::pop() noexcept -> cxx::optional<T>
{
    if (m_size == 0U)
    {
        return cxx::nullopt;
    }

    // low level memory management with access to the topmost element on the untyped buffer;
    // type safety is ensured by the template parameter
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    return *reinterpret_cast<T*>(m_data[--m_size]);
}

template <typename T, uint64_t Capacity>
template <typename... Targs>
inline bool stack<T, Capacity>::push(Targs&&... args) noexcept
{
    if (m_size >= Capacity)
    {
        return false;
    }

    // low level memory management with access to the topmost element on the untyped buffer;
    // type safety is ensured by the template parameter
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    new (reinterpret_cast<T*>(m_data[m_size++])) T(std::forward<Targs>(args)...);
    return true;
}

template <typename T, uint64_t Capacity>
inline uint64_t stack<T, Capacity>::size() const noexcept
{
    return m_size;
}

template <typename T, uint64_t Capacity>
inline constexpr uint64_t stack<T, Capacity>::capacity() noexcept
{
    return Capacity;
}

} // namespace cxx
} // namespace iox

#endif // IOX_HOOFS_CXX_STACK_INL
<commit_msg>iox-#1394 Suppress reinterpret_cast + placement new warnings<commit_after>// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// 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.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_HOOFS_CXX_STACK_INL
#define IOX_HOOFS_CXX_STACK_INL

#include "iceoryx_hoofs/cxx/stack.hpp"

namespace iox
{
namespace cxx
{
template <typename T, uint64_t Capacity>
inline auto stack<T, Capacity>::pop() noexcept -> cxx::optional<T>
{
    if (m_size == 0U)
    {
        return cxx::nullopt;
    }

    // AXIVION Next Construct CertC++-EXP36 : every entry of m_data is aligned to alignof(T)
    // AXIVION Next Construct AutosarC++19_03-A5.2.4 : low level memory management with access to the topmost element on
    // the untyped buffer; type safety is ensured by the template parameter
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    return *reinterpret_cast<T*>(m_data[--m_size]);
}

template <typename T, uint64_t Capacity>
template <typename... Targs>
inline bool stack<T, Capacity>::push(Targs&&... args) noexcept
{
    if (m_size >= Capacity)
    {
        return false;
    }

    // AXIVION Next Construct CertC++-MEM54, CertC++-EXP36, AutosarC++19_03-A18.5.10 : every entry of m_data is aligned
    // to alignof(T)
    // AXIVION Next Construct AutosarC++19_03-A5.2.4 : low level memory management with access to the topmost element on
    // the untyped buffer; type safety is ensured by the template parameter
    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    new (reinterpret_cast<T*>(m_data[m_size++])) T(std::forward<Targs>(args)...);
    return true;
}

template <typename T, uint64_t Capacity>
inline uint64_t stack<T, Capacity>::size() const noexcept
{
    return m_size;
}

template <typename T, uint64_t Capacity>
inline constexpr uint64_t stack<T, Capacity>::capacity() noexcept
{
    return Capacity;
}

} // namespace cxx
} // namespace iox

#endif // IOX_HOOFS_CXX_STACK_INL
<|endoftext|>


<commit_before>// Copyright (c) 2020 by Robert Bosch GmbH, Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "iceoryx_posh/popo/base_publisher.hpp"
#include "mocks/chunk_mock.hpp"
#include "mocks/publisher_mock.hpp"

#include "test.hpp"

using namespace ::testing;
using ::testing::_;

struct DummyData
{
    uint64_t val = 42;
};

template <typename T, typename port_t>
class StubbedBasePublisher : public iox::popo::BasePublisher<T, port_t>
{
  public:
    StubbedBasePublisher(iox::capro::ServiceDescription)
        : iox::popo::BasePublisher<T, port_t>::BasePublisher(){};
    uid_t getUid() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::getUid();
    }
    iox::capro::ServiceDescription getServiceDescription() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::getServiceDescription();
    }
    iox::cxx::expected<iox::popo::Sample<T>, iox::popo::AllocationError> loanSample(uint64_t size) noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::loanSample(size);
    }
    void release(iox::popo::Sample<T>& sample) noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::release(sample);
    }
    void publish(iox::popo::Sample<T>&& sample) noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::publish(std::move(sample));
    }
    iox::cxx::optional<iox::popo::Sample<T>> loanPreviousSample() noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::loanPreviousSample();
    }
    void offer() noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::offer();
    }
    void stopOffer() noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::stopOffer();
    }
    bool isOffered() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::isOffered();
    }
    bool hasSubscribers() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::hasSubscribers();
    }
    port_t& getMockedPort()
    {
        return iox::popo::BasePublisher<T, port_t>::m_port;
    }
};

using TestBasePublisher = StubbedBasePublisher<DummyData, MockPublisherPortUser>;

class BasePublisherTest : public Test
{
  public:
    BasePublisherTest()
    {
    }

    void SetUp()
    {
    }

    void TearDown()
    {
    }

  protected:
    ChunkMock<DummyData> chunkMock;
    TestBasePublisher sut{{"", "", ""}};
};

TEST_F(BasePublisherTest, LoanForwardsAllocationErrorsToCaller)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(
            ByMove(iox::cxx::error<iox::popo::AllocationError>(iox::popo::AllocationError::RUNNING_OUT_OF_CHUNKS))));
    // ===== Test ===== //
    auto result = sut.loanSample(sizeof(DummyData));
    // ===== Verify ===== //
    EXPECT_EQ(true, result.has_error());
    EXPECT_EQ(iox::popo::AllocationError::RUNNING_OUT_OF_CHUNKS, result.get_error());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, LoanReturnsAllocatedTypedSampleOnSuccess)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    // ===== Test ===== //
    auto result = sut.loanSample(sizeof(DummyData));
    // ===== Verify ===== //
    // The memory location of the sample should be the same as the chunk payload.
    EXPECT_EQ(chunkMock.chunkHeader()->payload(), result.value().get());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, LoanedSamplesContainPointerToChunkHeader)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    // ===== Test ===== //
    auto result = sut.loanSample(sizeof(DummyData));
    // ===== Verify ===== //
    EXPECT_EQ(chunkMock.chunkHeader(), result.value().getHeader());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, LoanedSamplesAreAutomaticallyReleasedWhenOutOfScope)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));

    EXPECT_CALL(sut.getMockedPort(), freeChunk(chunkMock.chunkHeader())).Times(AtLeast(1));

    // ===== Test ===== //
    {
        auto result = sut.loanSample(sizeof(DummyData));
    }
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, PublishingSendsUnderlyingMemoryChunkOnPublisherPort)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    EXPECT_CALL(sut.getMockedPort(), sendChunk).Times(1);
    // ===== Test ===== //
    sut.loanSample(sizeof(DummyData)).and_then([](auto& sample) { sample.publish(); });
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, PreviousSampleReturnsSampleWhenPreviousChunkIsRetrievable)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), tryGetPreviousChunk)
        .WillOnce(Return(ByMove(iox::cxx::make_optional<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    // ===== Test ===== //
    auto result = sut.loanPreviousSample();
    // ===== Verify ===== //
    EXPECT_EQ(true, result.has_value());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, PreviousSampleReturnsEmptyOptionalWhenChunkNotRetrievable)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), tryGetPreviousChunk).WillOnce(Return(ByMove(iox::cxx::nullopt)));
    // ===== Test ===== //
    auto result = sut.loanPreviousSample();
    // ===== Verify ===== //
    EXPECT_EQ(false, result.has_value());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, OfferDoesOfferServiceOnUnderlyingPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), offer).Times(1);
    // ===== Test ===== //
    sut.offer();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, StopOfferDoesStopOfferServiceOnUnderlyingPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), stopOffer).Times(1);
    // ===== Test ===== //
    sut.stopOffer();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, isOfferedDoesCheckIfPortIsOfferedOnUnderlyingPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), isOffered).Times(1);
    // ===== Test ===== //
    sut.isOffered();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, isOfferedDoesCheckIfUnderylingPortHasSubscribers)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), hasSubscribers).Times(1);
    // ===== Test ===== //
    sut.hasSubscribers();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, GetServiceDescriptionCallForwardedToUnderlyingPublisherPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), getServiceDescription).Times(1);
    // ===== Test ===== //
    sut.getServiceDescription();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, DestroysUnderlyingPortOnDestruction)
{
    EXPECT_CALL(sut.getMockedPort(), destroy).Times(1);
}
<commit_msg>iox-#408 adapted base publisher tests<commit_after>// Copyright (c) 2020 by Robert Bosch GmbH, Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "iceoryx_posh/popo/base_publisher.hpp"
#include "mocks/chunk_mock.hpp"
#include "mocks/publisher_mock.hpp"

#include "test.hpp"

using namespace ::testing;
using ::testing::_;

struct DummyData
{
    uint64_t val = 42;
};

template <typename T, typename port_t>
class StubbedBasePublisher : public iox::popo::BasePublisher<T, port_t>
{
  public:
    StubbedBasePublisher(iox::capro::ServiceDescription)
        : iox::popo::BasePublisher<T, port_t>::BasePublisher(){};
    uid_t getUid() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::getUid();
    }
    iox::capro::ServiceDescription getServiceDescription() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::getServiceDescription();
    }
    iox::cxx::expected<iox::popo::Sample<T>, iox::popo::AllocationError> loanSample(uint64_t size) noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::loanSample(size);
    }
    void release(iox::popo::Sample<T>& sample) noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::release(sample);
    }
    void publish(iox::popo::Sample<T>&& sample) noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::publish(std::move(sample));
    }
    iox::cxx::optional<iox::popo::Sample<T>> loanPreviousSample() noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::loanPreviousSample();
    }
    void offer() noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::offer();
    }
    void stopOffer() noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::stopOffer();
    }
    bool isOffered() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::isOffered();
    }
    bool hasSubscribers() const noexcept
    {
        return iox::popo::BasePublisher<T, port_t>::hasSubscribers();
    }
    port_t& getMockedPort()
    {
        return iox::popo::BasePublisher<T, port_t>::m_port;
    }
};

using TestBasePublisher = StubbedBasePublisher<DummyData, MockPublisherPortUser>;

class BasePublisherTest : public Test
{
  public:
    BasePublisherTest()
    {
    }

    void SetUp()
    {
    }

    void TearDown()
    {
    }

  protected:
    ChunkMock<DummyData> chunkMock;
    TestBasePublisher sut{{"", "", ""}};
};

TEST_F(BasePublisherTest, LoanForwardsAllocationErrorsToCaller)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(
            ByMove(iox::cxx::error<iox::popo::AllocationError>(iox::popo::AllocationError::RUNNING_OUT_OF_CHUNKS))));
    // ===== Test ===== //
    auto result = sut.loanSample(sizeof(DummyData));
    // ===== Verify ===== //
    EXPECT_EQ(true, result.has_error());
    EXPECT_EQ(iox::popo::AllocationError::RUNNING_OUT_OF_CHUNKS, result.get_error());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, LoanReturnsAllocatedTypedSampleOnSuccess)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    // ===== Test ===== //
    auto result = sut.loanSample(sizeof(DummyData));
    // ===== Verify ===== //
    // The memory location of the sample should be the same as the chunk payload.
    EXPECT_EQ(chunkMock.chunkHeader()->payload(), result.value().get());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, LoanedSamplesContainPointerToChunkHeader)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    // ===== Test ===== //
    auto result = sut.loanSample(sizeof(DummyData));
    // ===== Verify ===== //
    EXPECT_EQ(chunkMock.chunkHeader(), result.value().getHeader());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, LoanedSamplesAreAutomaticallyReleasedWhenOutOfScope)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));

    EXPECT_CALL(sut.getMockedPort(), releaseChunk(chunkMock.chunkHeader())).Times(AtLeast(1));

    // ===== Test ===== //
    {
        auto result = sut.loanSample(sizeof(DummyData));
    }
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, PublishingSendsUnderlyingMemoryChunkOnPublisherPort)
{
    // ===== Setup ===== //
    ON_CALL(sut.getMockedPort(), tryAllocateChunk)
        .WillByDefault(Return(ByMove(iox::cxx::success<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    EXPECT_CALL(sut.getMockedPort(), sendChunk).Times(1);
    // ===== Test ===== //
    sut.loanSample(sizeof(DummyData)).and_then([](auto& sample) { sample.publish(); });
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, PreviousSampleReturnsSampleWhenPreviousChunkIsRetrievable)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), tryGetPreviousChunk)
        .WillOnce(Return(ByMove(iox::cxx::make_optional<iox::mepoo::ChunkHeader*>(chunkMock.chunkHeader()))));
    // ===== Test ===== //
    auto result = sut.loanPreviousSample();
    // ===== Verify ===== //
    EXPECT_EQ(true, result.has_value());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, PreviousSampleReturnsEmptyOptionalWhenChunkNotRetrievable)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), tryGetPreviousChunk).WillOnce(Return(ByMove(iox::cxx::nullopt)));
    // ===== Test ===== //
    auto result = sut.loanPreviousSample();
    // ===== Verify ===== //
    EXPECT_EQ(false, result.has_value());
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, OfferDoesOfferServiceOnUnderlyingPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), offer).Times(1);
    // ===== Test ===== //
    sut.offer();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, StopOfferDoesStopOfferServiceOnUnderlyingPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), stopOffer).Times(1);
    // ===== Test ===== //
    sut.stopOffer();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, isOfferedDoesCheckIfPortIsOfferedOnUnderlyingPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), isOffered).Times(1);
    // ===== Test ===== //
    sut.isOffered();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, isOfferedDoesCheckIfUnderylingPortHasSubscribers)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), hasSubscribers).Times(1);
    // ===== Test ===== //
    sut.hasSubscribers();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, GetServiceDescriptionCallForwardedToUnderlyingPublisherPort)
{
    // ===== Setup ===== //
    EXPECT_CALL(sut.getMockedPort(), getServiceDescription).Times(1);
    // ===== Test ===== //
    sut.getServiceDescription();
    // ===== Verify ===== //
    // ===== Cleanup ===== //
}

TEST_F(BasePublisherTest, DestroysUnderlyingPortOnDestruction)
{
    EXPECT_CALL(sut.getMockedPort(), destroy).Times(1);
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  Homework1
//
//  Created by James Savage on 9/13/13.
//  Copyright (c) 2013 James Savage <me@axiixc.com>. All rights reserved.
//

#include "BoardWriterConsole.h"
#include "InputSourceKeyboard.h"

int main(int argc, const char * argv[])
{
    BoardWriter& writer = BoardWriter::create<BoardWriterConsole>();
    InputSource& inputSource = InputSource::create<InputSourceKeyboard>(writer);
    inputSource.startRecievingInputEvents();

    return 0;
}

<commit_msg>Modifications to allow the program to be run in either GPIO (default) or keyboard (--keyboard) modes.<commit_after>//
//  main.cpp
//  Homework1
//
//  Created by James Savage on 9/13/13.
//  Copyright (c) 2013 James Savage <me@axiixc.com>. All rights reserved.
//

#include "BoardWriterConsole.h"
#include "BoardWriterGPIO.h"
#include "InputSourceGPIO.h"
#include "InputSourceKeyboard.h"

#include <stdio.h>
#include <string.h>

int main(int argc, const char **argv)
{
    if (argc == 2 && strncmp("--keyboard", argv[1], strlen("--keyboard")) == 0)
        InputSource::create<InputSourceKeyboard>(BoardWriter::create<BoardWriterConsole>()).startRecievingInputEvents();
    else
        InputSource::create<InputSourceGPIO>(BoardWriter::create<BoardWriterGPIO>()).startRecievingInputEvents();

    return 0;
}

<|endoftext|>