<commit_before>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
//#include <string>                                         /* String function definitions */
#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>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */

const char* serialport="/dev/ttyAMA0";                      /* defines used serialport */
int serialport_bps=B38400;                                  /* defines baudrate od serialport */
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 */
bool cmd_vel_received=true;
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

int filedesc;                                               // File descriptor of serial port we will talk to
int fd;                                                     /* serial port file descriptor */
unsigned char serialBuffer[16];                             /* Serial buffer to store uart data */
struct termios orig;                                        // Port options

int openSerialPort(const char * device, int bps);
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void read_MD49_Data (void);
void set_MD49_speed (unsigned char speed_l, unsigned char speed_r);

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

//    ROS_DEBUG("geometry_msgs/Twist received: linear.x= %f angular.z= %f", vel_cmd.linear.x, vel_cmd.angular.z);

/*
    //ANFANG Alternative
    if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
    else if(vel_cmd.linear.x == 0){
        // turning
        vr = vel_cmd.angular.z * base_width / 2.0;
        vl = (-1) * vr;
    }
    else if(vel_cmd.angular.z == 0){
        // forward / backward
        vl = vr = vel_cmd.linear.x;
    }
    else{
        // moving doing arcs
        vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
        if (vl > max_vl) {vl=max_vl;}
        if (vl < min_vl) {vl=min_vl;}
        vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
        if (vr > max_vr) {vr=max_vr;}
        if (vr < min_vr) {vr=min_vr;}
    }
    //ENDE Alternative
*/

    if (vel_cmd.linear.x>0){
        speed_l = 255;
        speed_r = 255;
        //serialBuffer[0] = 88;					// 88 =X Steuerbyte um Commands an MD49 zu senden
        //serialBuffer[1] = 115;					// 115=s Steuerbyte setSpeed
        //serialBuffer[2] = 255;					// speed1
        //serialBuffer[3] = 255;					// speed2
        //writeBytes(fd, 4);
    }
    if (vel_cmd.linear.x<0){
        speed_l = 0;
        speed_r = 0;
    }
    if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
        speed_l = 128;
        speed_r = 128;
    }
    if (vel_cmd.angular.z>0){
        speed_l = 0;
        speed_r = 255;
    }
    if (vel_cmd.angular.z<0){
        speed_l = 255;
        speed_r = 0;
    }

    cmd_vel_received=true;
}

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

    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 100, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",100);

    // Open serial port
    // ****************
    filedesc = openSerialPort("/dev/ttyAMA0", B38400);
    if (filedesc == -1) exit(1);
    usleep(10000);                                      // Sleep for UART to power up and set options
    ROS_DEBUG("Serial Port opened \n");

    // Set nodes looprate 10Hz
    // ***********************
    ros::Rate loop_rate(2);

    while( n.ok() )
    {

        // Read encoder and other data from MD49
            // *************************************
            read_MD49_Data();

            // Set speed left and right for MD49
            // ********************************
            if (cmd_vel_received==true) {
                set_MD49_speed(speed_l,speed_r);
                //set_MD49_speed(speed_l,speed_r);
                cmd_vel_received=false;
            }
            //set_MD49_speed(speed_l,speed_r);

            // Publish encoder values to topic /encoders (custom message)
            // ********************************************************************
            base_controller::encoders encoders;
            encoders.encoder_l=EncoderL;
            encoders.encoder_r=EncoderR;
            encoders_pub.publish(encoders);

            // Loop
            // ****
            ros::spinOnce();
            loop_rate.sleep();
    }// end.mainloop

    return 1;
} // end.main

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);
      //fprintf(stderr, "speed=%d\n", bps);
      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);
    }
    //write(fd,serialBuffer, count);

}

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);
    }
}

void read_MD49_Data (void){
    serialBuffer[0] = 82;							// 82=R Steuerbyte um alle Daten vom MD49 zu lesen
    writeBytes(fd, 1);
    //Daten lesen und in Array schreiben
    readBytes(fd, 18);

    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]);

   // printf("vl= %f \n", vl);
  //  printf("vr= %f \n", vr);
    //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]);
}

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;					// speed1
    serialBuffer[3] = speed_r;					// speed2
    writeBytes(fd, 4);
}
<commit_msg>Update code<commit_after>#include <iostream>                                         /* allows to perform standard input and output operations */
#include <stdio.h>                                          /* Standard input/output definitions */
#include <stdint.h>                                         /* Standard input/output definitions */
#include <stdlib.h>                                         /* defines several general purpose functions */
//#include <string>                                         /* String function definitions */
#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>                                        /* ROS */
#include <geometry_msgs/Twist.h>                            /* ROS Twist message */
#include <base_controller/encoders.h>                       /* Custom message /encoders */

const char* serialport="/dev/ttyAMA0";                      /* defines used serialport */
int serialport_bps=B38400;                                  /* defines baudrate od serialport */
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 */
bool cmd_vel_received=true;
double vr = 0.0;
double vl = 0.0;
double max_vr = 0.2;
double max_vl = 0.2;
double min_vr = 0.2;
double min_vl = 0.2;
double base_width = 0.4;                                    /* Base width in meters */

int filedesc;                                               // File descriptor of serial port we will talk to
int fd;                                                     /* serial port file descriptor */
unsigned char serialBuffer[16];                             /* Serial buffer to store uart data */
struct termios orig;                                        // Port options

int openSerialPort(const char * device, int bps);
void writeBytes(int descriptor, int count);
void readBytes(int descriptor, int count);
void read_MD49_Data (void);
void set_MD49_speed (unsigned char speed_l, unsigned char speed_r);

void cmd_vel_callback(const geometry_msgs::Twist& vel_cmd){

//    ROS_DEBUG("geometry_msgs/Twist received: linear.x= %f angular.z= %f", vel_cmd.linear.x, vel_cmd.angular.z);

/*
    //ANFANG Alternative
    if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){vl=0;vr=0;}
    else if(vel_cmd.linear.x == 0){
        // turning
        vr = vel_cmd.angular.z * base_width / 2.0;
        vl = (-1) * vr;
    }
    else if(vel_cmd.angular.z == 0){
        // forward / backward
        vl = vr = vel_cmd.linear.x;
    }
    else{
        // moving doing arcs
        vl = vel_cmd.linear.x - vel_cmd.angular.z * base_width / 2.0;
        if (vl > max_vl) {vl=max_vl;}
        if (vl < min_vl) {vl=min_vl;}
        vr = vel_cmd.linear.x + vel_cmd.angular.z * base_width / 2.0;
        if (vr > max_vr) {vr=max_vr;}
        if (vr < min_vr) {vr=min_vr;}
    }
    //ENDE Alternative
*/

    if (vel_cmd.linear.x>0){
        speed_l = 255;
        speed_r = 255;
        //serialBuffer[0] = 88;					// 88 =X Steuerbyte um Commands an MD49 zu senden
        //serialBuffer[1] = 115;					// 115=s Steuerbyte setSpeed
        //serialBuffer[2] = 255;					// speed1
        //serialBuffer[3] = 255;					// speed2
        //writeBytes(fd, 4);
    }
    if (vel_cmd.linear.x<0){
        speed_l = 0;
        speed_r = 0;
    }
    if (vel_cmd.linear.x==0 && vel_cmd.angular.z==0){
        speed_l = 128;
        speed_r = 128;
    }
    if (vel_cmd.angular.z>0){
        speed_l = 0;
        speed_r = 255;
    }
    if (vel_cmd.angular.z<0){
        speed_l = 255;
        speed_r = 0;
    }

    cmd_vel_received=true;
}

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

    ros::init(argc, argv, "base_controller" );
    ros::NodeHandle n;
    ros::Subscriber sub = n.subscribe("/cmd_vel", 100, cmd_vel_callback);
    ros::Publisher encoders_pub = n.advertise<base_controller::encoders>("encoders",100);

    // Open serial port
    // ****************
    filedesc = openSerialPort("/dev/ttyAMA0", B38400);
    if (filedesc == -1) exit(1);
    usleep(10000);                                      // Sleep for UART to power up and set options
    ROS_DEBUG("Serial Port opened \n");

    // Set nodes looprate 10Hz
    // ***********************
    ros::Rate loop_rate(25);

    while( n.ok() )
    {

        // Read encoder and other data from MD49
            // *************************************
            read_MD49_Data();

            // Set speed left and right for MD49
            // ********************************
            if (cmd_vel_received==true) {
                set_MD49_speed(speed_l,speed_r);
                //set_MD49_speed(speed_l,speed_r);
                cmd_vel_received=false;
            }
            //set_MD49_speed(speed_l,speed_r);

            // Publish encoder values to topic /encoders (custom message)
            // ********************************************************************
            base_controller::encoders encoders;
            encoders.encoder_l=EncoderL;
            encoders.encoder_r=EncoderR;
            encoders_pub.publish(encoders);

            // Loop
            // ****
            ros::spinOnce();
            loop_rate.sleep();
    }// end.mainloop

    return 1;
} // end.main

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);
      //fprintf(stderr, "speed=%d\n", bps);
      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);
    }
    //write(fd,serialBuffer, count);

}

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);
    }
}

void read_MD49_Data (void){
    serialBuffer[0] = 82;							// 82=R Steuerbyte um alle Daten vom MD49 zu lesen
    writeBytes(fd, 1);
    //Daten lesen und in Array schreiben
    readBytes(fd, 18);

    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]);

   // printf("vl= %f \n", vl);
  //  printf("vr= %f \n", vr);
    //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]);
}

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;					// speed1
    serialBuffer[3] = speed_r;					// speed2
    writeBytes(fd, 4);
}
<|endoftext|>


<commit_before>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// 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 <Qt>
#include <QSettings>
#include "preferences.h"
#include "consts.h"

// The base color to generate pastel shades for sources
static const QColor mixColor = QColor("coral");

Preferences *Preferences::m_instance = NULL;

Preferences::Preferences()
{
    RESTART_APP = false;
    loadPreferences();
}

Preferences::~Preferences()
{
    savePreferences();
}

Preferences *Preferences::getInstance()
{
    if(!m_instance)
    {
        m_instance = new Preferences();
    }

    return m_instance;
}

QNetworkInterface Preferences::networkInterface() const
{
    return m_interface;
}

void Preferences::setNetworkInterface(const QNetworkInterface &value)
{
    if(m_interface.name()!=value.name())
    {
        m_interface = value;
        //emit networkInterfaceChanged();
    }
}

QColor Preferences::colorForCID(const CID &cid)
{
    if(m_cidToColor.contains(cid))
        return m_cidToColor[cid];

    int red = qrand() % 255;
    int green = qrand() % 255;
    int blue = qrand() % 255;

    red = (red + mixColor.red()) / 2;
    green = (green + mixColor.green()) / 2;
    blue = (blue + mixColor.blue()) / 2;

    QColor newColor = QColor::fromRgb(red, green, blue);
    m_cidToColor[cid] = newColor;
    return newColor;
}

void Preferences::SetDisplayFormat(unsigned int nDisplayFormat)
{
    Q_ASSERT(nDisplayFormat < TOTAL_NUM_OF_FORMATS);
    m_nDisplayFormat = nDisplayFormat;
    return;
}

QString Preferences::GetFormattedValue(unsigned int nLevelInDecimal)
{
    Q_ASSERT(nLevelInDecimal<=255);
    if (m_nDisplayFormat == DECIMAL)
        return QString::number(nLevelInDecimal, 10);
    else if (m_nDisplayFormat == PERCENT)
        return QString::number(HTOPT[nLevelInDecimal], 10);
    else if (m_nDisplayFormat == HEXADECIMAL)
        return QString::number(nLevelInDecimal, 16);
    else
        return QString ("Err");

}

void Preferences::SetBlindVisualizer (bool bBlindVisualizer)
{
    Q_ASSERT(bBlindVisualizer == 0 || bBlindVisualizer == 1);
    m_bBlindVisualizer = bBlindVisualizer;
    return;
}

void Preferences::SetDefaultTransmitName (QString sDefaultTransmitName)
{
    sDefaultTransmitName.truncate(MAX_SOURCE_NAME_LEN);
    m_sDefaultTransmitName = sDefaultTransmitName.trimmed();
    return;
}

void Preferences::SetNumSecondsOfSacn (int nNumSecondsOfSacn)
{
    Q_ASSERT(nNumSecondsOfSacn >= 0 && nNumSecondsOfSacn <= MAX_SACN_TRANSMIT_TIME_SEC);
    m_nNumSecondsOfSacn = nNumSecondsOfSacn;
    return;
}

unsigned int Preferences::GetDisplayFormat()
{
    return m_nDisplayFormat;
}

unsigned int Preferences::GetMaxLevel()
{
    if(m_nDisplayFormat==PERCENT)
        return 100;
    return MAX_SACN_LEVEL;
}

bool Preferences::GetBlindVisualizer()
{
    return m_bBlindVisualizer;
}

QString Preferences::GetDefaultTransmitName()
{
   return m_sDefaultTransmitName;
}

unsigned int Preferences::GetNumSecondsOfSacn()
{
   return m_nNumSecondsOfSacn;
}

bool Preferences::defaultInterfaceAvailable()
{
    return m_interface.isValid();
}

void Preferences::savePreferences()
{
    QSettings settings;

    if(m_interface.isValid())
        settings.setValue(S_MAC_ADDRESS, m_interface.hardwareAddress());
    settings.setValue(S_DISPLAY_FORMAT, QVariant(m_nDisplayFormat));
    settings.setValue(S_BLIND_VISUALIZER, QVariant(m_bBlindVisualizer));
    settings.setValue(S_DEFAULT_SOURCENAME, m_sDefaultTransmitName);
    settings.setValue(S_TIMEOUT, QVariant(m_nNumSecondsOfSacn));
    settings.setValue(S_FLICKERFINDERSHOWINFO, QVariant(m_flickerFinderShowInfo));
}

void Preferences::loadPreferences()
{
    QSettings settings;

    if(settings.contains(S_MAC_ADDRESS))
    {
        QString mac = settings.value(S_MAC_ADDRESS).toString();
        QList<QNetworkInterface> ifaceList = QNetworkInterface::allInterfaces();
        foreach(QNetworkInterface i, ifaceList)
            if(i.hardwareAddress() == mac)
                m_interface = i;
    }

    m_nDisplayFormat = settings.value(S_DISPLAY_FORMAT, QVariant(DECIMAL)).toInt();
    m_bBlindVisualizer = settings.value(S_BLIND_VISUALIZER, QVariant(false)).toBool();
    m_sDefaultTransmitName = settings.value(S_DEFAULT_SOURCENAME, DEFAULT_SOURCE_NAME).toString();
    m_nNumSecondsOfSacn = settings.value(S_TIMEOUT, QVariant(0)).toInt();
    m_flickerFinderShowInfo = settings.value(S_FLICKERFINDERSHOWINFO, QVariant(true)).toBool();
}

void Preferences::setFlickerFinderShowInfo(bool showIt)
{
    m_flickerFinderShowInfo = showIt;
}

bool Preferences::getFlickerFinderShowInfo()
{
    return m_flickerFinderShowInfo;
}
<commit_msg>Display preview data by default<commit_after>// Copyright 2016 Tom Barthel-Steer
// http://www.tomsteer.net
//
// 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 <Qt>
#include <QSettings>
#include "preferences.h"
#include "consts.h"

// The base color to generate pastel shades for sources
static const QColor mixColor = QColor("coral");

Preferences *Preferences::m_instance = NULL;

Preferences::Preferences()
{
    RESTART_APP = false;
    loadPreferences();
}

Preferences::~Preferences()
{
    savePreferences();
}

Preferences *Preferences::getInstance()
{
    if(!m_instance)
    {
        m_instance = new Preferences();
    }

    return m_instance;
}

QNetworkInterface Preferences::networkInterface() const
{
    return m_interface;
}

void Preferences::setNetworkInterface(const QNetworkInterface &value)
{
    if(m_interface.name()!=value.name())
    {
        m_interface = value;
        //emit networkInterfaceChanged();
    }
}

QColor Preferences::colorForCID(const CID &cid)
{
    if(m_cidToColor.contains(cid))
        return m_cidToColor[cid];

    int red = qrand() % 255;
    int green = qrand() % 255;
    int blue = qrand() % 255;

    red = (red + mixColor.red()) / 2;
    green = (green + mixColor.green()) / 2;
    blue = (blue + mixColor.blue()) / 2;

    QColor newColor = QColor::fromRgb(red, green, blue);
    m_cidToColor[cid] = newColor;
    return newColor;
}

void Preferences::SetDisplayFormat(unsigned int nDisplayFormat)
{
    Q_ASSERT(nDisplayFormat < TOTAL_NUM_OF_FORMATS);
    m_nDisplayFormat = nDisplayFormat;
    return;
}

QString Preferences::GetFormattedValue(unsigned int nLevelInDecimal)
{
    Q_ASSERT(nLevelInDecimal<=255);
    if (m_nDisplayFormat == DECIMAL)
        return QString::number(nLevelInDecimal, 10);
    else if (m_nDisplayFormat == PERCENT)
        return QString::number(HTOPT[nLevelInDecimal], 10);
    else if (m_nDisplayFormat == HEXADECIMAL)
        return QString::number(nLevelInDecimal, 16);
    else
        return QString ("Err");

}

void Preferences::SetBlindVisualizer (bool bBlindVisualizer)
{
    Q_ASSERT(bBlindVisualizer == 0 || bBlindVisualizer == 1);
    m_bBlindVisualizer = bBlindVisualizer;
    return;
}

void Preferences::SetDefaultTransmitName (QString sDefaultTransmitName)
{
    sDefaultTransmitName.truncate(MAX_SOURCE_NAME_LEN);
    m_sDefaultTransmitName = sDefaultTransmitName.trimmed();
    return;
}

void Preferences::SetNumSecondsOfSacn (int nNumSecondsOfSacn)
{
    Q_ASSERT(nNumSecondsOfSacn >= 0 && nNumSecondsOfSacn <= MAX_SACN_TRANSMIT_TIME_SEC);
    m_nNumSecondsOfSacn = nNumSecondsOfSacn;
    return;
}

unsigned int Preferences::GetDisplayFormat()
{
    return m_nDisplayFormat;
}

unsigned int Preferences::GetMaxLevel()
{
    if(m_nDisplayFormat==PERCENT)
        return 100;
    return MAX_SACN_LEVEL;
}

bool Preferences::GetBlindVisualizer()
{
    return m_bBlindVisualizer;
}

QString Preferences::GetDefaultTransmitName()
{
   return m_sDefaultTransmitName;
}

unsigned int Preferences::GetNumSecondsOfSacn()
{
   return m_nNumSecondsOfSacn;
}

bool Preferences::defaultInterfaceAvailable()
{
    return m_interface.isValid();
}

void Preferences::savePreferences()
{
    QSettings settings;

    if(m_interface.isValid())
        settings.setValue(S_MAC_ADDRESS, m_interface.hardwareAddress());
    settings.setValue(S_DISPLAY_FORMAT, QVariant(m_nDisplayFormat));
    settings.setValue(S_BLIND_VISUALIZER, QVariant(m_bBlindVisualizer));
    settings.setValue(S_DEFAULT_SOURCENAME, m_sDefaultTransmitName);
    settings.setValue(S_TIMEOUT, QVariant(m_nNumSecondsOfSacn));
    settings.setValue(S_FLICKERFINDERSHOWINFO, QVariant(m_flickerFinderShowInfo));
}

void Preferences::loadPreferences()
{
    QSettings settings;

    if(settings.contains(S_MAC_ADDRESS))
    {
        QString mac = settings.value(S_MAC_ADDRESS).toString();
        QList<QNetworkInterface> ifaceList = QNetworkInterface::allInterfaces();
        foreach(QNetworkInterface i, ifaceList)
            if(i.hardwareAddress() == mac)
                m_interface = i;
    }

    m_nDisplayFormat = settings.value(S_DISPLAY_FORMAT, QVariant(DECIMAL)).toInt();
    m_bBlindVisualizer = settings.value(S_BLIND_VISUALIZER, QVariant(true)).toBool();
    m_sDefaultTransmitName = settings.value(S_DEFAULT_SOURCENAME, DEFAULT_SOURCE_NAME).toString();
    m_nNumSecondsOfSacn = settings.value(S_TIMEOUT, QVariant(0)).toInt();
    m_flickerFinderShowInfo = settings.value(S_FLICKERFINDERSHOWINFO, QVariant(true)).toBool();
}

void Preferences::setFlickerFinderShowInfo(bool showIt)
{
    m_flickerFinderShowInfo = showIt;
}

bool Preferences::getFlickerFinderShowInfo()
{
    return m_flickerFinderShowInfo;
}
<|endoftext|>


<commit_before>/* nobleNote, a note taking application
 * Copyright (C) 2012 Christian Metscher <hakaishi@web.de>,
                      Fabian Deuchler <Taiko000@gmail.com>

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

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

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

 * nobleNote is licensed under the MIT, see `http://copyfree.org/licenses/mit/license.txt'.
 */

#include "preferences.h"
#include <QDir>
#include <QMessageBox>
#include <QTimer>
#include <QFileDialog>
#include <QDesktopServices>

Preferences::Preferences(QWidget *parent): QDialog(parent){
     setupUi(this);

     settings = new QSettings(this);

     dontQuit->setChecked(settings->value("dont_quit_on_close",false).toBool());
     convertNotes->setChecked(settings->value("convert_notes",true).toBool());
     showSource->setChecked(settings->value("show_source", false).toBool());
     kineticScrolling->setChecked(settings->value("kinetic_scrolling", false).toBool());
     sizeSpinHeight->setValue(settings->value("note_editor_default_size",QSize(335,250)).toSize().height());
     sizeSpinWidth->setValue(settings->value("note_editor_default_size",QSize(335,250)).toSize().width());

     connect(buttonBox, SIGNAL(accepted()), this, SLOT(saveSettings()));
     connect(browseButton, SIGNAL(clicked(bool)), this, SLOT(openDir()));
     connect(kineticScrolling,SIGNAL(toggled(bool)),this,SIGNAL(kineticScrollingEnabledChanged(bool)));
}

void Preferences::showEvent(QShowEvent* show_pref){
     pathLabel->setText(settings->value("root_path").toString());
     rootPath = settings->value("root_path").toString();
     originalRootPath = rootPath;

     QWidget::showEvent(show_pref);
}

void Preferences::saveSettings(){
     if(!settings->isWritable())
       QMessageBox::warning(this,tr("Warning"),tr("Could not write settings!"));

     if(rootPath != originalRootPath){
       if(QMessageBox::question(this,tr("Keep old files in the trash?"),
                                tr("The old folder for the trash is: \"%1\".\n\n"
                                   "If you keep this folder and you change back to "
                                   "the old folder some time, the old files will show up in the trash again.\n\n"
                                   "Do you want to delete this (old) folder?")
                                .arg(settings->value("backup_dir_path").toString()),
                                QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
       {
            QList<QFileInfo> backups = QDir(settings->value("backup_dir_path").toString()).entryInfoList(QDir::Files);
            foreach(QFileInfo backup, backups)
              QFile().remove(backup.absoluteFilePath());
            if(!QDir().rmdir(settings->value("backup_dir_path").toString()))
              QMessageBox::warning(this,tr("Couldn't delete backup folder"), tr("Could not delete the backup folder!"));
       }

       settings->setValue("root_path",rootPath);
       pathChanged();
     }

     settings->setValue("dont_quit_on_close", dontQuit->isChecked());
     settings->setValue("convert_notes", convertNotes->isChecked());
     settings->setValue("note_editor_default_size", QSize(sizeSpinWidth->value(),sizeSpinHeight->value()));
     settings->setValue("show_source", showSource->isChecked());
     settings->setValue("kinetic_scrolling",kineticScrolling->isChecked());

     accept();
}

void Preferences::openDir(){
     QString path;
     path = QFileDialog::getExistingDirectory(this,
                  tr("Open Directory"), rootPath, QFileDialog::ShowDirsOnly
                  | QFileDialog::DontResolveSymlinks);
     QFileInfo file(path);
     if(!file.isWritable() && !path.isEmpty()){
         QMessageBox::warning(this,tr("No Write Access"), tr("The path \"%1\" is not writable!").arg(file.filePath()));
       return;
     }
     if(!path.isEmpty())
     {
          rootPath = path;
          pathLabel->setText(rootPath);
     }
}
<commit_msg>changed backup folder change message<commit_after>/* nobleNote, a note taking application
 * Copyright (C) 2012 Christian Metscher <hakaishi@web.de>,
                      Fabian Deuchler <Taiko000@gmail.com>

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

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

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

 * nobleNote is licensed under the MIT, see `http://copyfree.org/licenses/mit/license.txt'.
 */

#include "preferences.h"
#include <QDir>
#include <QMessageBox>
#include <QTimer>
#include <QFileDialog>
#include <QDesktopServices>

Preferences::Preferences(QWidget *parent): QDialog(parent){
     setupUi(this);

     settings = new QSettings(this);

     dontQuit->setChecked(settings->value("dont_quit_on_close",false).toBool());
     convertNotes->setChecked(settings->value("convert_notes",true).toBool());
     showSource->setChecked(settings->value("show_source", false).toBool());
     kineticScrolling->setChecked(settings->value("kinetic_scrolling", false).toBool());
     sizeSpinHeight->setValue(settings->value("note_editor_default_size",QSize(335,250)).toSize().height());
     sizeSpinWidth->setValue(settings->value("note_editor_default_size",QSize(335,250)).toSize().width());

     connect(buttonBox, SIGNAL(accepted()), this, SLOT(saveSettings()));
     connect(browseButton, SIGNAL(clicked(bool)), this, SLOT(openDir()));
     connect(kineticScrolling,SIGNAL(toggled(bool)),this,SIGNAL(kineticScrollingEnabledChanged(bool)));
}

void Preferences::showEvent(QShowEvent* show_pref){
     pathLabel->setText(settings->value("root_path").toString());
     rootPath = settings->value("root_path").toString();
     originalRootPath = rootPath;

     QWidget::showEvent(show_pref);
}

void Preferences::saveSettings(){
     if(!settings->isWritable())
       QMessageBox::warning(this,tr("Warning"),tr("Could not write settings!"));

     if(rootPath != originalRootPath){
       if(QMessageBox::question(this,tr("Keep old files in the trash?"),
                                tr("Everytime the path to the notes is changed, %1 creates a new backup folder. "
                                   "The current backup folder path is %2. Shall the current backup folder and all its containted backups be removed?"
                                   )
                                .arg(QApplication::applicationName(),settings->value("backup_dir_path").toString()),
                                QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
       {
            QList<QFileInfo> backups = QDir(settings->value("backup_dir_path").toString()).entryInfoList(QDir::Files);
            foreach(QFileInfo backup, backups)
              QFile().remove(backup.absoluteFilePath());
            if(!QDir().rmdir(settings->value("backup_dir_path").toString()))
              QMessageBox::warning(this,tr("Couldn't delete backup folder"), tr("Could not delete the backup folder!"));
       }

       settings->setValue("root_path",rootPath);
       pathChanged();
     }

     settings->setValue("dont_quit_on_close", dontQuit->isChecked());
     settings->setValue("convert_notes", convertNotes->isChecked());
     settings->setValue("note_editor_default_size", QSize(sizeSpinWidth->value(),sizeSpinHeight->value()));
     settings->setValue("show_source", showSource->isChecked());
     settings->setValue("kinetic_scrolling",kineticScrolling->isChecked());

     accept();
}

void Preferences::openDir(){
     QString path;
     path = QFileDialog::getExistingDirectory(this,
                  tr("Open Directory"), rootPath, QFileDialog::ShowDirsOnly
                  | QFileDialog::DontResolveSymlinks);
     QFileInfo file(path);
     if(!file.isWritable() && !path.isEmpty()){
         QMessageBox::warning(this,tr("No Write Access"), tr("The path \"%1\" is not writable!").arg(file.filePath()));
       return;
     }
     if(!path.isEmpty())
     {
          rootPath = path;
          pathLabel->setText(rootPath);
     }
}
<|endoftext|>


<commit_before>/*  This file is part of the Tufão project
    Copyright (C) 2011 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any
    later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "querystring.h"
#include <QtCore/QByteArray>

namespace Tufao {
namespace QueryString {

inline QByteArray escape(const QByteArray &string, bool percentEncoding,
                         char percent)
{
    if (percentEncoding)
        return string.toPercentEncoding(QByteArray(), QByteArray(), percent);
    else
        return string;
}

QByteArray stringify(const QMap<QByteArray, QByteArray> &map, char sep, char eq,
                     bool percentEncoding, char percent)
{
    QByteArray ret;

    for (QMap<QByteArray, QByteArray>::const_iterator i = map.begin()
             ;i != map.end();++i) {
        ret.append(escape(i.key(), percentEncoding, percent) + eq
                   + escape(i.value(), percentEncoding, percent) + sep);
    }

    if (map.size())
        ret.remove(ret.size() - 1, 1);

    return ret;
}

inline QByteArray unescape(const QByteArray &string, bool percentEncoding,
                           char percent)
{
    if (percentEncoding)
        return QByteArray::fromPercentEncoding(string, percent);
    else
        return string;
}

QMap<QByteArray, QByteArray> parse(const QByteArray &string, char sep, char eq,
                                   bool percentEncoding, char percent)
{
    QMap<QByteArray, QByteArray> ret;

    int i = 0;
    while (string[i] == '&') ++i;
    int j = string.indexOf(sep, i + 1);

    while (j != -1) {
        int k = string.indexOf(eq, i);

        if (k == -1 || k > j) {
            QByteArray key(string.mid(i, j - i));
            if (key.size())
                ret[unescape(key, percentEncoding, percent)];
        } else {
            QByteArray key(string.mid(i, k - i));
            if (key.size()) {
                ret[unescape(key, percentEncoding, percent)]
                    = unescape(string.mid(k + 1, j - k - 1), percentEncoding,
                               percent);
            }
        }

        i = j + 1;
        j = string.indexOf(sep, j + 1);
    }

    int k = string.indexOf(eq, i);

    if (k == -1) {
        QByteArray key(string.mid(i, string.size() - i));
        if (key.size())
            ret[unescape(key, percentEncoding, percent)];
    } else {
        QByteArray key(string.mid(i, k - i));
        if (key.size()) {
            ret[unescape(key, percentEncoding, percent)]
                = unescape(string .mid(k + 1, string.size() - k - 1),
                           percentEncoding, percent);
        }
    }

    return ret;
}

} // namespace QueryString
} // namespace Tufao
<commit_msg>fix: QueryString wasn't handling '+' character<commit_after>/*  This file is part of the Tufão project
    Copyright (C) 2011 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any
    later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "querystring.h"
#include <QtCore/QByteArray>

namespace Tufao {
namespace QueryString {

inline QByteArray escape(const QByteArray &string, bool percentEncoding,
                         char percent)
{
    if (percentEncoding)
        return string.toPercentEncoding(QByteArray(), QByteArray(), percent);
    else
        return string;
}

QByteArray stringify(const QMap<QByteArray, QByteArray> &map, char sep, char eq,
                     bool percentEncoding, char percent)
{
    QByteArray ret;

    for (QMap<QByteArray, QByteArray>::const_iterator i = map.begin()
             ;i != map.end();++i) {
        ret.append(escape(i.key(), percentEncoding, percent) + eq
                   + escape(i.value(), percentEncoding, percent) + sep);
    }

    if (map.size())
        ret.remove(ret.size() - 1, 1);

    return ret;
}

inline QByteArray unescape(const QByteArray &string, bool percentEncoding,
                           char percent)
{
    QByteArray ret(percentEncoding
                   ? QByteArray::fromPercentEncoding(string, percent)
                   : string);
    ret.replace('+', ' ');
    return ret;
}

QMap<QByteArray, QByteArray> parse(const QByteArray &string, char sep, char eq,
                                   bool percentEncoding, char percent)
{
    QMap<QByteArray, QByteArray> ret;

    int i = 0;
    while (string[i] == '&') ++i;
    int j = string.indexOf(sep, i + 1);

    while (j != -1) {
        int k = string.indexOf(eq, i);

        if (k == -1 || k > j) {
            QByteArray key(string.mid(i, j - i));
            if (key.size())
                ret[unescape(key, percentEncoding, percent)];
        } else {
            QByteArray key(string.mid(i, k - i));
            if (key.size()) {
                ret[unescape(key, percentEncoding, percent)]
                    = unescape(string.mid(k + 1, j - k - 1), percentEncoding,
                               percent);
            }
        }

        i = j + 1;
        j = string.indexOf(sep, j + 1);
    }

    int k = string.indexOf(eq, i);

    if (k == -1) {
        QByteArray key(string.mid(i, string.size() - i));
        if (key.size())
            ret[unescape(key, percentEncoding, percent)];
    } else {
        QByteArray key(string.mid(i, k - i));
        if (key.size()) {
            ret[unescape(key, percentEncoding, percent)]
                = unescape(string .mid(k + 1, string.size() - k - 1),
                           percentEncoding, percent);
        }
    }

    return ret;
}

} // namespace QueryString
} // namespace Tufao
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#include <string>
#include <vector>

#include <stout/os.hpp>
#include <stout/try.hpp>

#include "linux/ldcache.hpp"

using std::string;
using std::vector;

// There are two formats for ld.so.cache. The pre-glibc format 2.2
// listed the number of library entries, followed by the entries
// themselves, followed by a string table holding strings pointed
// to by the library entries. This format is summarized below:
//
//      HEADER_MAGIC_OLD
//      nlibs
//      libs[0]
//      ...
//      libs[nlibs-1]
//      first string\0second string\0...last string\0
//      ^                                           ^
//      start of string table     end of string table
//
// For glibc 2.2 and beyond, a new format was created so that each
// library entry could hold more meta-data about the libraries they
// reference. To preserve backwards compatibility, the new format was
// embedded in the old format inside its string table (simply moving
// all existing strings further down in the string table). This makes
// sense for backwards compatibility because code that could parse the
// old format still works (the offsets for strings pointed to by
// the library entries are just larger now).
//
// However, it adds complications when parsing for the new format
// because the new format header needs to be aligned on an 8 byte
// boundary (potentially pushing the start address of the string table
// down a few bytes). A summary of the new format embedded in the old
// format with annotations on the start address of the string table
// can be seen below:
//
//      HEADER_MAGIC_OLD
//      nlibs
//      libs[0]
//      ...
//      libs[nlibs-1]
//      pad (align for new format)
//      HEADER_MAGIC_NEW    <-- start of string table
//      nlibs
//      len_strings
//      unused    // 20 bytes reserved for extensions
//      libs[0]
//      ...
//      libs[nlibs-1]
//      first string\0second string\0...last string\0
//                                                  ^
//                                end of string table
//
// We currently only support the new format, since glibc 2.2
// was released in late 2000.

namespace ldcache {

constexpr char HEADER_MAGIC_OLD[] = "ld.so-1.7.0";
constexpr char HEADER_MAGIC_NEW[] = "glibc-ld.so.cache1.1";

#define IS_ELF  0x00000001

struct HeaderOld
{
  char magic[sizeof(HEADER_MAGIC_OLD) - 1];
  uint32_t libraryCount; // Number of library entries.
};

struct EntryOld
{
  int32_t flags;  // 0x01 indicates ELF library.
  uint32_t key;   // String table index.
  uint32_t value; // String table index.
};

struct HeaderNew
{
  char magic[sizeof(HEADER_MAGIC_NEW) - 1];
  uint32_t libraryCount;  // Number of library entries.
  uint32_t stringsLength; // Length of "actual" string table.
  uint32_t unused[5];     // Leave space for future extensions
                          // and align to 8 byte boundary.
};

struct EntryNew
{
  int32_t flags;        // Flags bits determine arch and library type.
  uint32_t key;         // String table index.
  uint32_t value;       // String table index.
  uint32_t osVersion;   // Required OS version.
  uint64_t hwcap;       // Hwcap entry.
};

// Returns a 'boundary' aligned pointer by rounding up to
// the nearest multiple of 'boundary'.
static inline const char* align(const char* address, size_t boundary)
{
  if ((size_t)address % boundary == 0) {
    return address;
  }
  return (address + boundary) - ((size_t)address % boundary);
}

Try<vector<Entry>> parse(const string& path)
{
  // Read the complete file into a buffer
  Try<string> buffer = os::read(path);
  if (buffer.isError()) {
    return Error(buffer.error());
  }

  const char* data = buffer->data();

  // Grab a pointer to the old format header (for verification of
  // HEADER_MAGIC_OLD later on). Then jump forward to the location of
  // the new format header (it is the only format we support).
  HeaderOld* headerOld = (HeaderOld*)data;
  data += sizeof(HeaderOld);
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  data += headerOld->libraryCount * sizeof(EntryOld);
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  // The new format header and all of its library entries are embedded
  // in the old format's string table (the current location of data).
  // However, the header is aligned on an 8 byte boundary, so we
  // need to align 'data' to get it to point to the new header.
  data = align(data, alignof(HeaderNew));
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  // Construct pointers to all of the important regions in the new
  // format: the header, the libentry array, and the new string table
  // (which starts at the same address as the aligned headerNew pointer).
  HeaderNew* headerNew = (HeaderNew*)data;
  data += sizeof(HeaderNew);
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  EntryNew* entriesNew = (EntryNew*)data;
  data += headerNew->libraryCount * sizeof(EntryNew);
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  // The start of the strings table is at the beginning of
  // the new header, per the above format description.
  char* strings = (char*)headerNew;

  // Adjust the pointer to add on the additional size of the strings
  // contained in the string table. At this point, 'data' should
  // point to an address just beyond the end of the file.
  data += headerNew->stringsLength;
  if ((size_t)(data - buffer->data()) != buffer->size()) {
    return Error("Invalid format");
  }

  // Validate our header magic.
  if (strncmp(headerOld->magic,
        HEADER_MAGIC_OLD,
        sizeof(HEADER_MAGIC_OLD) - 1) != 0) {
    return Error("Invalid format");
  }

  if (strncmp(headerNew->magic,
        HEADER_MAGIC_NEW,
        sizeof(HEADER_MAGIC_NEW) - 1) != 0) {
    return Error("Invalid format");
  }

  // Make sure the very last character in the buffer is a '\0'.
  // This way, no matter what strings we index in the string
  // table, we know they will never run beyond the end of the
  // file buffer when extracting them.
  if (*(data - 1) != '\0') {
    return Error("Invalid format");
  }

  // Build our vector of ldcache entries.
  vector<Entry> ldcache;
  for (uint32_t i = 0; i < headerNew->libraryCount; i++) {
    if (!(entriesNew[i].flags & IS_ELF)) {
      continue;
    }

    if (strings + entriesNew[i].key >= data) {
      return Error("Invalid format");
    }

    if (strings + entriesNew[i].value >= data) {
      return Error("Invalid format");
    }

    Entry entry;
    entry.name = &strings[entriesNew[i].key];
    entry.path = &strings[entriesNew[i].value];
    ldcache.push_back(entry);
  }

  return ldcache;
}

} // namespace ldcache {
<commit_msg>Fixed parsing of ld.so.cache on new glibc.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#include <string>
#include <vector>

#include <stout/os.hpp>
#include <stout/try.hpp>

#include "linux/ldcache.hpp"

using std::string;
using std::vector;

// There are three formats for ld.so.cache. The "old" pre-glibc
// format 2.2 listed the number of library entries, followed by
// the entries themselves, followed by a string table holding
// strings pointed to by the library entries. This format is
// summarized below:
//
//      HEADER_MAGIC_OLD
//      nlibs
//      libs[0]
//      ...
//      libs[nlibs-1]
//      first string\0second string\0...last string\0
//      ^                                           ^
//      start of string table     end of string table
//
// For glibc 2.2 and beyond, a "new" format was created so that each
// library entry could hold more meta-data about the libraries they
// reference. To preserve backwards compatibility, a "compat" format
// was introduced where the new format was embedded in the old
// format inside its string table (simply moving all existing strings
// further down in the string table). This makes sense for backwards
// compatibility because code that could parse the old format still
// works (the offsets for strings pointed to by the library entries
// are just larger now).
//
// However, it adds complications when parsing for the compat format
// because the new format header needs to be aligned on an 8 byte
// boundary (potentially pushing the start address of the string table
// down a few bytes). A summary of the compat format with the new
// format embedded in the old format with annotations on the start
// address of the string table can be seen below:
//
//      HEADER_MAGIC_OLD
//      nlibs
//      libs[0]
//      ...
//      libs[nlibs-1]
//      pad (align for new format)
//      HEADER_MAGIC_NEW    <-- start of string table
//      nlibs
//      len_strings
//      unused    // 20 bytes reserved for extensions
//      libs[0]
//      ...
//      libs[nlibs-1]
//      first string\0second string\0...last string\0
//                                                  ^
//                                end of string table
//
// Then from glibc 2.32 the default changed to the new format, without
// the compatibility header:
//
//      HEADER_MAGIC_NEW
//      nlibs
//      len_strings
//      unused    // 20 bytes reserved for extensions
//      libs[0]
//      ...
//      libs[nlibs-1]
//      first string\0second string\0...last string\0
//                                                  ^
//                                end of string table
//
// We support the compat and new formats: no need to support the old
// format since glibc 2.2 was released in late 2000.

namespace ldcache {

constexpr char HEADER_MAGIC_OLD[] = "ld.so-1.7.0";
constexpr char HEADER_MAGIC_NEW[] = "glibc-ld.so.cache1.1";

#define IS_ELF  0x00000001

struct HeaderOld
{
  char magic[sizeof(HEADER_MAGIC_OLD) - 1];
  uint32_t libraryCount; // Number of library entries.
};

struct EntryOld
{
  int32_t flags;  // 0x01 indicates ELF library.
  uint32_t key;   // String table index.
  uint32_t value; // String table index.
};

struct HeaderNew
{
  char magic[sizeof(HEADER_MAGIC_NEW) - 1];
  uint32_t libraryCount;  // Number of library entries.
  uint32_t stringsLength; // Length of "actual" string table.
  uint32_t unused[5];     // Leave space for future extensions
                          // and align to 8 byte boundary.
};

struct EntryNew
{
  int32_t flags;        // Flags bits determine arch and library type.
  uint32_t key;         // String table index.
  uint32_t value;       // String table index.
  uint32_t osVersion;   // Required OS version.
  uint64_t hwcap;       // Hwcap entry.
};

// Returns a 'boundary' aligned pointer by rounding up to
// the nearest multiple of 'boundary'.
static inline const char* align(const char* address, size_t boundary)
{
  if ((size_t)address % boundary == 0) {
    return address;
  }
  return (address + boundary) - ((size_t)address % boundary);
}

Try<vector<Entry>> parse(const string& path)
{
  // Read the complete file into a buffer
  Try<string> buffer = os::read(path);
  if (buffer.isError()) {
    return Error(buffer.error());
  }

  const char* data = buffer->data();

  HeaderNew* headerNew = (HeaderNew*)data;
  if (data + sizeof(HeaderNew) >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  if (strncmp(headerNew->magic,
      HEADER_MAGIC_NEW,
      sizeof(HEADER_MAGIC_NEW) - 1) != 0) {
    // If the data doesn't start with the new header, it must be a
    // compat format, therefore we expect an old header.
    HeaderOld* headerOld = (HeaderOld*)data;
    data += sizeof(HeaderOld);
    if (data >= buffer->data() + buffer->size()) {
      return Error("Invalid format");
    }

    // Validate our header magic.
    if (strncmp(headerOld->magic,
        HEADER_MAGIC_OLD,
        sizeof(HEADER_MAGIC_OLD) - 1) != 0) {
      return Error("Invalid format");
    }

    data += headerOld->libraryCount * sizeof(EntryOld);
    if (data >= buffer->data() + buffer->size()) {
      return Error("Invalid format");
    }

    // The new format header and all of its library entries are embedded
    // in the old format's string table (the current location of data).
    // However, the header is aligned on an 8 byte boundary, so we
    // need to align 'data' to get it to point to the new header.
    data = align(data, alignof(HeaderNew));
    if (data >= buffer->data() + buffer->size()) {
      return Error("Invalid format");
    }

    headerNew = (HeaderNew*)data;
  }

  // Construct pointers to all of the important regions in the new
  // format: the header, the libentry array, and the new string table
  // (which starts at the same address as the aligned headerNew pointer).
  data += sizeof(HeaderNew);
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  EntryNew* entriesNew = (EntryNew*)data;
  data += headerNew->libraryCount * sizeof(EntryNew);
  if (data >= buffer->data() + buffer->size()) {
    return Error("Invalid format");
  }

  // The start of the strings table is at the beginning of
  // the new header, per the above format description.
  char* strings = (char*)headerNew;

  // Adjust the pointer to add on the additional size of the strings
  // contained in the string table. At this point, 'data' should
  // point to an address just beyond the end of the file.
  data += headerNew->stringsLength;
  if ((size_t)(data - buffer->data()) != buffer->size()) {
    return Error("Invalid format");
  }

  // Make sure the very last character in the buffer is a '\0'.
  // This way, no matter what strings we index in the string
  // table, we know they will never run beyond the end of the
  // file buffer when extracting them.
  if (*(data - 1) != '\0') {
    return Error("Invalid format");
  }

  // Build our vector of ldcache entries.
  vector<Entry> ldcache;
  for (uint32_t i = 0; i < headerNew->libraryCount; i++) {
    if (!(entriesNew[i].flags & IS_ELF)) {
      continue;
    }

    if (strings + entriesNew[i].key >= data) {
      return Error("Invalid format");
    }

    if (strings + entriesNew[i].value >= data) {
      return Error("Invalid format");
    }

    Entry entry;
    entry.name = &strings[entriesNew[i].key];
    entry.path = &strings[entriesNew[i].value];
    ldcache.push_back(entry);
  }

  return ldcache;
}

} // namespace ldcache {
<|endoftext|>


<commit_before>/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef EXTRACTION_CONTAINERS_HPP
#define EXTRACTION_CONTAINERS_HPP

#include "internal_extractor_edge.hpp"
#include "first_and_last_segment_of_way.hpp"
#include "scripting_environment.hpp"
#include "../data_structures/external_memory_node.hpp"
#include "../data_structures/restriction.hpp"

#include <stxxl/vector>
#include <unordered_map>

/**
 * Uses external memory containers from stxxl to store all the data that
 * is collected by the extractor callbacks.
 *
 * The data is the filtered, aggregated and finally written to disk.
 */
class ExtractionContainers
{
#ifndef _MSC_VER
    constexpr static unsigned stxxl_memory =
        ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max()
                                    : std::numeric_limits<unsigned>::max());
#else
    const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
    void PrepareNodes();
    void PrepareRestrictions();
    void PrepareEdges(lua_State *segment_state);

    void WriteNodes(std::ofstream& file_out_stream) const;
    void WriteRestrictions(const std::string& restrictions_file_name) const;
    void WriteEdges(std::ofstream& file_out_stream) const;
    void WriteNames(const std::string& names_file_name) const;
  public:
    using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
    using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
    using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
    using STXXLStringVector = stxxl::vector<std::string>;
    using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
    using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;

    STXXLNodeIDVector used_node_id_list;
    STXXLNodeVector all_nodes_list;
    STXXLEdgeVector all_edges_list;
    STXXLStringVector name_list;
    STXXLRestrictionsVector restrictions_list;
    STXXLWayIDStartEndVector way_start_end_id_list;
    std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;
    unsigned max_internal_node_id;

    ExtractionContainers();

    ~ExtractionContainers();

    void PrepareData(const std::string &output_file_name,
                     const std::string &restrictions_file_name,
                     const std::string &names_file_name,
                     lua_State *segment_state);
};

#endif /* EXTRACTION_CONTAINERS_HPP */
<commit_msg>Use a std::vector in place of stxxl:vector for the names list<commit_after>/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef EXTRACTION_CONTAINERS_HPP
#define EXTRACTION_CONTAINERS_HPP

#include "internal_extractor_edge.hpp"
#include "first_and_last_segment_of_way.hpp"
#include "scripting_environment.hpp"
#include "../data_structures/external_memory_node.hpp"
#include "../data_structures/restriction.hpp"

#include <stxxl/vector>
#include <unordered_map>

/**
 * Uses external memory containers from stxxl to store all the data that
 * is collected by the extractor callbacks.
 *
 * The data is the filtered, aggregated and finally written to disk.
 */
class ExtractionContainers
{
#ifndef _MSC_VER
    constexpr static unsigned stxxl_memory =
        ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max()
                                    : std::numeric_limits<unsigned>::max());
#else
    const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
#endif
    void PrepareNodes();
    void PrepareRestrictions();
    void PrepareEdges(lua_State *segment_state);

    void WriteNodes(std::ofstream& file_out_stream) const;
    void WriteRestrictions(const std::string& restrictions_file_name) const;
    void WriteEdges(std::ofstream& file_out_stream) const;
    void WriteNames(const std::string& names_file_name) const;
  public:
    using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
    using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
    using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
    using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
    using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;

    STXXLNodeIDVector used_node_id_list;
    STXXLNodeVector all_nodes_list;
    STXXLEdgeVector all_edges_list;
    std::vector<std::string> name_list;
    STXXLRestrictionsVector restrictions_list;
    STXXLWayIDStartEndVector way_start_end_id_list;
    std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;
    unsigned max_internal_node_id;

    ExtractionContainers();

    ~ExtractionContainers();

    void PrepareData(const std::string &output_file_name,
                     const std::string &restrictions_file_name,
                     const std::string &names_file_name,
                     lua_State *segment_state);
};

#endif /* EXTRACTION_CONTAINERS_HPP */
<|endoftext|>


<commit_before>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);

  // Takes a pointer and returns how much space it holds.
  size_t xxmalloc_usable_size (void *);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

  void (* __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    // Store the old hooks.
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    old_realloc_hook = __realloc_hook;
    old_memalign_hook = __memalign_hook;

    // Point the hooks to the replacement functions.
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    __realloc_hook = my_realloc_hook;
    __memalign_hook = my_memalign_hook;

    initialized = true;
  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size)
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  size_t malloc_usable_size (void * ptr) {
    return xxmalloc_usable_size (ptr);
  }

}

<commit_msg>Added __MALLOC_HOOK_VOLATILE macro for newer glibc versions<commit_after>// -*- C++ -*-

/**
 * @file   gnuwrapper.cpp
 * @brief  Replaces malloc family on GNU/Linux with custom versions.
 * @author Emery Berger <http://www.cs.umass.edu/~emery>
 * @note   Copyright (C) 2010 by Emery Berger, University of Massachusetts Amherst.
 */

#ifndef __GNUC__
#error "This file requires the GNU compiler."
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>

/*
  To use this library,
  you only need to define the following allocation functions:

  - xxmalloc
  - xxfree
  - xxmalloc_usable_size

  See the extern "C" block below for function prototypes and more
  details. YOU SHOULD NOT NEED TO MODIFY ANY OF THE CODE HERE TO
  SUPPORT ANY ALLOCATOR.

  LIMITATIONS:

  - This wrapper assumes that the underlying allocator will do "the
    right thing" when xxfree() is called with a pointer internal to an
    allocated object. Header-based allocators, for example, need not
    apply.

*/

static bool initialized = false;

extern "C" {

  void * xxmalloc (size_t);
  void   xxfree (void *);

  // Takes a pointer and returns how much space it holds.
  size_t xxmalloc_usable_size (void *);

  static void my_init_hook (void);

  // New hooks for allocation functions.
  static void * my_malloc_hook (size_t, const void *);
  static void   my_free_hook (void *, const void *);
  static void * my_realloc_hook (void *, size_t, const void *);
  static void * my_memalign_hook (size_t, size_t, const void *);

  // Store the old hooks just in case.
  static void * (*old_malloc_hook) (size_t, const void *);
  static void   (*old_free_hook) (void *, const void *);
  static void * (*old_realloc_hook)(void *ptr, size_t size, const void *caller);
  static void * (*old_memalign_hook)(size_t alignment, size_t size, const void *caller);

// From GNU libc 2.14 this macro is defined, to declare
// hook variables as volatile. Define it as empty for
// older glibc versions
#ifndef __MALLOC_HOOK_VOLATILE
 #define __MALLOC_HOOK_VOLATILE
#endif

  void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_init_hook;

  static void my_init_hook (void) {
    // Store the old hooks.
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    old_realloc_hook = __realloc_hook;
    old_memalign_hook = __memalign_hook;

    // Point the hooks to the replacement functions.
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    __realloc_hook = my_realloc_hook;
    __memalign_hook = my_memalign_hook;

    initialized = true;
  }

  static void * my_malloc_hook (size_t size, const void *) {
    return xxmalloc(size);
  }

  static void my_free_hook (void * ptr, const void *) {
    xxfree(ptr);
  }

  static void * my_realloc_hook (void * ptr, size_t sz, const void *) {
    // NULL ptr = malloc.
    if (ptr == NULL) {
      return xxmalloc(sz);
    }

    if (sz == 0) {
      xxfree (ptr);
#if defined(__APPLE__)
      // 0 size = free. We return a small object.  This behavior is
      // apparently required under Mac OS X and optional under POSIX.
      return xxmalloc(1);
#else
      // For POSIX, don't return anything.
      return NULL;
#endif
    }

    size_t objSize = xxmalloc_usable_size(ptr);

#if 0
    // Custom logic here to ensure we only do a logarithmic number of
    // reallocations (with a constant space overhead).

    // Don't change size if the object is shrinking by less than half.
    if ((objSize / 2 < sz) && (sz <= objSize)) {
      // Do nothing.
      return ptr;
    }
    // If the object is growing by less than 2X, double it.
    if ((objSize < sz) && (sz < objSize * 2)) {
      sz = objSize * 2;
    }
#endif

    void * buf = xxmalloc(sz);

    if (buf != NULL) {
      // Successful malloc.
      // Copy the contents of the original object
      // up to the size of the new block.
      size_t minSize = (objSize < sz) ? objSize : sz;
      memcpy (buf, ptr, minSize);
      xxfree (ptr);
    }

    // Return a pointer to the new one.
    return buf;
  }

  static void * my_memalign_hook (size_t size, size_t alignment, const void *) {
    // Check for non power-of-two alignment, or mistake in size.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return NULL;
      }

    // Try to just allocate an object of the requested size.
    // If it happens to be aligned properly, just return it.
    void * ptr = xxmalloc (size);
    if (((size_t) ptr & (alignment - 1)) == (size_t) ptr) {
      // It is already aligned just fine; return it.
      return ptr;
    }

    // It was not aligned as requested: free the object.
    xxfree (ptr);

    // Now get a big chunk of memory and align the object within it.
    // NOTE: this REQUIRES that the underlying allocator be able
    // to free the aligned object, or ignore the free request.
    void * buf = xxmalloc (2 * alignment + size);
    void * alignedPtr = (void *) (((size_t) buf + alignment - 1) & ~(alignment - 1));

    return alignedPtr;
  }

  // This is here because, for some reason, the GNU hooks don't
  // necessarily replace all memory operations as they should.

  int posix_memalign (void **memptr, size_t alignment, size_t size)
  {
    if (!initialized) {
      my_init_hook();
    }
    // Check for non power-of-two alignment.
    if ((alignment == 0) ||
	(alignment & (alignment - 1)))
      {
	return EINVAL;
      }
    void * ptr = my_memalign_hook (size, alignment, NULL);
    if (!ptr) {
      return ENOMEM;
    } else {
      *memptr = ptr;
      return 0;
    }
  }

  size_t malloc_usable_size (void * ptr) {
    return xxmalloc_usable_size (ptr);
  }

}

<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QMutableListIterator>

#include "tasservicemanager.h"

#include "tascommandparser.h"
#include "tasconstants.h"
#include "taslogger.h"

static QString NO_SERVICE = "The request did not specify a service!.";

/*!
  \class TasServiceManager
  \brief TasServiceManager manages the service commands used by qttas components.

  TasServiceManager is the manager for the commands in the service architecture
  used by qttas components. The service requests are implemented using a relatively
  standard form of the chain of responsibility pattern. TasServiceManager class
  takes care of the command execution and management. The command implementations
  only need to concern with the actual command implementation.

  Commands which are reqistered to the manager will be invoked on all
  service requests untill on command consumed the request. This is done
  by returning "true" from the execute method.

*/

/*!
  Construct a new TasServiceManager
 */
TasServiceManager::TasServiceManager()
{}

/*!
  Destructor. Destroys all of the reqistered commands.
 */
TasServiceManager::~TasServiceManager()
{
    qDeleteAll(mCommands);
    mCommands.clear();
}

/*!
  Register a command to the TasServiceManager.
 */
void TasServiceManager::registerCommand(TasServiceCommand* command)
{
    mCommands.append(command);
}

/*!
  Slot to listen to service requests coming from clients connecting
  to a QtTas component using the TasSocket connectivity.
  The command xml is parsed into to the TasQtCommandData format
  and passed on the the commands in the command chain. In case no one
  is interested in the command an error message is written to the
  client as a response.
*/
void TasServiceManager::serviceRequest(TasMessage& request, TasSocket* requester)
{
    QString errorMessage;
    TasCommandModel* commandModel = parseMessageString(request.dataAsString(), errorMessage);
    if(commandModel){
        handleServiceRequest(*commandModel, requester, request.messageId());
    }
    else{
        TasResponse response(request.messageId());
        response.setErrorMessage(errorMessage);
        requester->sendMessage(response);
    }
    delete commandModel;
}

void TasServiceManager::handleServiceRequest(TasCommandModel& commandModel, TasSocket* requester, qint32 responseId)
{
    TasLogger::logger()->debug("TasServiceManager::handleServiceRequest " + commandModel.service());
    TasResponse response(responseId);
    response.setRequester(requester);
    performService(commandModel, response);
    requester->sendMessage(response);
}

void TasServiceManager::performService(TasCommandModel& commandModel, TasResponse& response)
{
    TasLogger::logger()->debug("TasServiceManager::performService: " + commandModel.service());
    QMutableListIterator<TasServiceCommand*> i(mCommands);
    bool wasConsumed = false;
    while (i.hasNext()){
        TasServiceCommand* command = i.next();
        if(command->executeService(commandModel, response)){
            wasConsumed = true;
            break;
        }
    }
    if(!wasConsumed){
        TasLogger::logger()->warning("TasServiceManager::executeCommand unknown service");
        response.setData(serviceErrorMessage()+commandModel.service());
        response.setIsError(true);
    }
}

/*!
  Parse and validate command model from the given data string. Will return null if the command model
  could not be parsed or is not valid. Use error message to determine the error.
  Ownership of the model is transferred.
*/
TasCommandModel* TasServiceManager::parseMessageString(const QString& messageBody, QString& errorMessage)
{
    //    TasCommandModel* commandModel = TasCommandParser::parseCommandXml(messageBody);
    TasCommandModel* commandModel = TasCommandModel::makeModel(messageBody);
    if(!commandModel){
        TasLogger::logger()->fatal("TasServiceManager::parseMessageString could not parse message.");
        errorMessage = PARSE_ERROR;
    }
    else if(commandModel && commandModel->service().isEmpty()){
        TasLogger::logger()->fatal("TasServiceManager::parseMessageString command model did not contain a service.");
        errorMessage = NO_SERVICE+commandModel->service();
        delete commandModel;
        commandModel = 0;
    }
    return commandModel;
}

<commit_msg>added symbian leave detection to tas service manager<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QMutableListIterator>

#include "tasservicemanager.h"

#include "tascommandparser.h"
#include "tasconstants.h"
#include "taslogger.h"

static QString NO_SERVICE = "The request did not specify a service!.";

/*!
  \class TasServiceManager
  \brief TasServiceManager manages the service commands used by qttas components.

  TasServiceManager is the manager for the commands in the service architecture
  used by qttas components. The service requests are implemented using a relatively
  standard form of the chain of responsibility pattern. TasServiceManager class
  takes care of the command execution and management. The command implementations
  only need to concern with the actual command implementation.

  Commands which are reqistered to the manager will be invoked on all
  service requests untill on command consumed the request. This is done
  by returning "true" from the execute method.

*/

/*!
  Construct a new TasServiceManager
 */
TasServiceManager::TasServiceManager()
{}

/*!
  Destructor. Destroys all of the reqistered commands.
 */
TasServiceManager::~TasServiceManager()
{
    qDeleteAll(mCommands);
    mCommands.clear();
}

/*!
  Register a command to the TasServiceManager.
 */
void TasServiceManager::registerCommand(TasServiceCommand* command)
{
    mCommands.append(command);
}

/*!
  Slot to listen to service requests coming from clients connecting
  to a QtTas component using the TasSocket connectivity.
  The command xml is parsed into to the TasQtCommandData format
  and passed on the the commands in the command chain. In case no one
  is interested in the command an error message is written to the
  client as a response.
*/
void TasServiceManager::serviceRequest(TasMessage& request, TasSocket* requester)
{
    QString errorMessage;
    TasCommandModel* commandModel = parseMessageString(request.dataAsString(), errorMessage);
    if(commandModel){
        handleServiceRequest(*commandModel, requester, request.messageId());
    }
    else{
        TasResponse response(request.messageId());
        response.setErrorMessage(errorMessage);
        requester->sendMessage(response);
    }
    delete commandModel;
}

void TasServiceManager::handleServiceRequest(TasCommandModel& commandModel, TasSocket* requester, qint32 responseId)
{
    TasLogger::logger()->debug("TasServiceManager::handleServiceRequest " + commandModel.service());
    TasResponse response(responseId);
    response.setRequester(requester);
    performService(commandModel, response);
    requester->sendMessage(response);
}

void TasServiceManager::performService(TasCommandModel& commandModel, TasResponse& response)
{
    TasLogger::logger()->debug("TasServiceManager::performService: " + commandModel.service());
    QMutableListIterator<TasServiceCommand*> i(mCommands);
    bool wasConsumed = false;

#ifdef Q_OS_SYMBIAN
    int err = 0;
    //run under symbian TRAP harness
    TRAP(err,
#endif
    while (i.hasNext()){
        TasServiceCommand* command = i.next();
        if(command->executeService(commandModel, response)){
            wasConsumed = true;
            break;
        }
    }
#ifdef Q_OS_SYMBIAN
    ); //closing TRAPD
    if(err) {
        response.setData(serviceErrorMessage()+commandModel.service() + "\n## Symbian error code(" + QString::number(err) + ")\n");
        response.setIsError(true);
        wasConsumed = true;
    }
#endif
    if(!wasConsumed){
        TasLogger::logger()->warning("TasServiceManager::executeCommand unknown service");
        response.setData(serviceErrorMessage()+commandModel.service());
        response.setIsError(true);
    }
}

/*!
  Parse and validate command model from the given data string. Will return null if the command model
  could not be parsed or is not valid. Use error message to determine the error.
  Ownership of the model is transferred.
*/
TasCommandModel* TasServiceManager::parseMessageString(const QString& messageBody, QString& errorMessage)
{
    //    TasCommandModel* commandModel = TasCommandParser::parseCommandXml(messageBody);
    TasCommandModel* commandModel = TasCommandModel::makeModel(messageBody);
    if(!commandModel){
        TasLogger::logger()->fatal("TasServiceManager::parseMessageString could not parse message.");
        errorMessage = PARSE_ERROR;
    }
    else if(commandModel && commandModel->service().isEmpty()){
        TasLogger::logger()->fatal("TasServiceManager::parseMessageString command model did not contain a service.");
        errorMessage = NO_SERVICE+commandModel->service();
        delete commandModel;
        commandModel = 0;
    }
    return commandModel;
}

<|endoftext|>