<commit_before>#include "internal.h"

///
/// Constructor for the Entity class
///
/// @param xLen Width of entity
/// @param yLen Height of the entity
/// @param xPos Vertical position of the Entity's top left corner
/// @param yPos Horizontal position of the Entity's top left corner
/// @param library Library within which to create the Entity
///
Entity::Entity(float xLen, float yLen, float xPos, float yPos, std::string texturePath, Fade2D *library, float angle){
	pos.x = xPos;
	pos.y = yPos;
	this->angle = angle;
	size = glm::vec2(xLen, yLen);
	scaleMatrix = glm::scale(glm::mat4(), glm::vec3(xLen, yLen, 1));
	translationMatrix = glm::translate(glm::mat4(), glm::vec3(pos, 0));
	rotationMatrix = glm::rotate(glm::mat4(), angle, glm::vec3(0.f, 0.f, 1.f));

	this->texture = new Texture(texturePath);

	init(library);
}

///
/// Draws the entity at it's current position on the sreen
///
void Entity::draw(){
	glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, glm::value_ptr(translationMatrix * rotationMatrix * scaleMatrix));
	ShaderHandler::useProgram();
	texture->Bind();
	library->draw();
}

///
/// Moves the entity
///
void  Entity::move(float x, float y){
	pos.x += x;
	pos.y += y;
	translationMatrix = glm::translate(translationMatrix, glm::vec3(x, y, 0));
}

///
/// Move entity to position
///
void Entity::setPos(float x, float y){
	pos.x += x;
	pos.y += y;
	translationMatrix = glm::translate(glm::mat4(), glm::vec3(x, y, 0));
}

///
/// Rotates the entity
///
void Entity::rotate(float angle)
{
	this->angle += angle;
	rotationMatrix = glm::rotate(rotationMatrix, angle, glm::vec3(0.f, 0.f, 1.f));
}

///
/// Sets entity angle
///
void Entity::setAngle(float angle){
	this->angle = angle;
	rotationMatrix = glm::rotate(glm::mat4(), angle, glm::vec3(0.f, 0.f, 1.f));
}

///
/// Get the entity position
///
/// @return Pointer to a C style array with two elements
///
float* Entity::getPosition(){
	return glm::value_ptr(pos);
}

void Entity::init(Fade2D *library){
	ShaderHandler::useProgram();
	matrixLocation = glGetUniformLocation(ShaderHandler::getProgram(), "transform");
	this->library = library;
}<commit_msg>Fixed Error in the setPos Function.<commit_after>#include "internal.h"

///
/// Constructor for the Entity class
///
/// @param xLen Width of entity
/// @param yLen Height of the entity
/// @param xPos Vertical position of the Entity's top left corner
/// @param yPos Horizontal position of the Entity's top left corner
/// @param library Library within which to create the Entity
///
Entity::Entity(float xLen, float yLen, float xPos, float yPos, std::string texturePath, Fade2D *library, float angle){
	pos.x = xPos;
	pos.y = yPos;
	this->angle = angle;
	size = glm::vec2(xLen, yLen);
	scaleMatrix = glm::scale(glm::mat4(), glm::vec3(xLen, yLen, 1));
	translationMatrix = glm::translate(glm::mat4(), glm::vec3(pos, 0));
	rotationMatrix = glm::rotate(glm::mat4(), angle, glm::vec3(0.f, 0.f, 1.f));

	this->texture = new Texture(texturePath);

	init(library);
}

///
/// Draws the entity at it's current position on the sreen
///
void Entity::draw(){
	glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, glm::value_ptr(translationMatrix * rotationMatrix * scaleMatrix));
	ShaderHandler::useProgram();
	texture->Bind();
	library->draw();
}

///
/// Moves the entity
///
void  Entity::move(float x, float y){
	pos.x += x;
	pos.y += y;
	translationMatrix = glm::translate(translationMatrix, glm::vec3(x, y, 0));
}

///
/// Move entity to position
///
void Entity::setPos(float x, float y){
	pos.x = x;
	pos.y = y;
	translationMatrix = glm::translate(glm::mat4(), glm::vec3(x, y, 0));
}

///
/// Rotates the entity
///
void Entity::rotate(float angle)
{
	this->angle += angle;
	rotationMatrix = glm::rotate(rotationMatrix, angle, glm::vec3(0.f, 0.f, 1.f));
}

///
/// Sets entity angle
///
void Entity::setAngle(float angle){
	this->angle = angle;
	rotationMatrix = glm::rotate(glm::mat4(), angle, glm::vec3(0.f, 0.f, 1.f));
}

///
/// Get the entity position
///
/// @return Pointer to a C style array with two elements
///
float* Entity::getPosition(){
	return glm::value_ptr(pos);
}

void Entity::init(Fade2D *library){
	ShaderHandler::useProgram();
	matrixLocation = glGetUniformLocation(ShaderHandler::getProgram(), "transform");
	this->library = library;
}<|endoftext|>


<commit_before>#include <AltSoftSerial.h>
void clearVars(void);

/**
 *  \brief Software serial port object
 *  \author volodink
 */
AltSoftSerial mySerial;

volatile uint8_t message[512];

/**
 * The first argument to calculate the checksum
 */
uint8_t CK_A = 0, CK_B = 0;
/**< The second argument to calculate the checksum */
/**
 * The first argument to comparison the checksum
 */
uint8_t CK_AU = 0, CK_BU = 0; /**< The second argument to comparison the checksum */
int gpsStep = 0; /**< If the data suits us, this parameter makes the step */
uint8_t UBX_id = 0; /**< Message ID */
uint8_t UBX_class = 0; /**< Message class */
uint8_t meslenL = 0;
uint8_t meslenH = 0;
int16_t meslen = 0;
int count = 0;
boolean gotUBX = false; /**< The parameter which checks getting data */
boolean POSLLH = 0; /**< Geodetic Position Solution; This message outputs
 * the Geodetic position in the currently selected Ellipsoid.
 */
boolean SVINFO = 0;/**< Space Vehicle Information */
boolean SOL = 0;/**< Navigation Solution Information; This message combines Position,
 * velocity and time solution in ECEF, including accuracy figures
 */
boolean VELNED = 0;/**< Velocity Solution in NED */
long int longitude; /**< Longitude */
float longitudef; /**< Output longitude */
long int latitude; /**< Latitude */
float latitudef; /**< Output latitude */
long int height; /**< Height */
float heightf; /**< Output height */
long int speed3; /**< Longitude */
float speed3f; /**< Speed */
char bufer[20];

/**
 * GPSfix Type, range 0..5;
 * Is a measure of the communication
 * required for a GPS receiver to acquire
 * satellite signals and navigation data
 */
unsigned char FixType = 22;
unsigned char NumSVs = 33; /**< Number of SVs used in Nav Solution */

/**
 * \brief uBlox checksum algorithm
 * \param ubx_data Contains the data over
 * which the checksum is to be calculated.
 */
void ubx_checksum(byte ubx_data) //рассчет контрольной суммы
{
    CK_A += ubx_data;
    CK_B += CK_A;
}

/**
 * \brief Getting and comparing data
 */
void getUBX(void) //Получаем пакет и делаем с ним штуки
{
    if (Serial.available() > 0)
    {
        uint8_t c = Serial.read();
        switch (gpsStep)
        {
            case 0:

                if (c == 0xB5){
                    gpsStep++;
    //                mySerial.print("Start 0xB5 ");
                }
                break;

            case 1:

                if (c == 0x62){
                    gpsStep++;
    //                          mySerial.print("Start 0x62 ");
                }
                else{
                    gpsStep = 0;
    //                        mySerial.println(" Error not62 ");
                }
                break;

            case 2:

                UBX_class = c;
                ubx_checksum(c);
                gpsStep++;
    //                   mySerial.println(""); mySerial.print(" UBX_CLASS = "); mySerial.println(UBX_class);
                break;

            case 3:

                UBX_id = c;
                ubx_checksum(c);
                gpsStep++;
  //                     mySerial.println(""); mySerial.print(" UBX_id = "); mySerial.println(UBX_id);
                break;

            case 4:

                meslenL = c;
                ubx_checksum(c);
                gpsStep++;
    //                 mySerial.print(" ml ");
                break;

            case 5:

                meslenH = c;
                ubx_checksum(c);
                gpsStep++;
                meslen = 0xFF & meslenL;
                meslen |= meslenH << 8;
                count = 0;
      //               mySerial.print(" mh ");
     //                mySerial.print("mlen=");
     //                mySerial.print(meslen);
                break;

            case 6:

                message[count] = c;
                ubx_checksum(c);
                count++;
                if (count == meslen)
                {
                    gpsStep++;
                    count = 0;
                }
                break;

            case 7:

                CK_AU = c;
                gpsStep++;

    break;

            case 8:

                CK_BU = c;

                if (CK_A == CK_AU && CK_B == CK_BU) //сравнение контрольной суммы
                {
                    gotUBX = true;
                    gpsStep++;
                }

                break;

        }
    }
}

/**
 * \brief UBX-decoder
 */
void decodeUBX(void)
{
    if (UBX_class == 0x01)
    {
        switch (UBX_id)
        {
            case 0x02:  //NAV-POSLLH
                longitude = 0xFF & message[7];       //долгота
                longitude = longitude << 8;
                longitude |= message[6];
                longitude = longitude << 8;
                longitude |= message[5];
                longitude = longitude << 8;
                longitude |= message[4];
                longitudef = longitude / 10000000.0;

                latitude = 0xFF & message[11];       //широта
                latitude = latitude << 8;
                latitude |= message[10];
                latitude = latitude << 8;
                latitude |= message[9];
                latitude = latitude << 8;
                latitude |= message[8];
                latitudef = latitude / 10000000.0;

                height = 0xFF & message[19];         //высота
                height = height << 8;
                height |= message[18];
                height = height << 8;
                height |= message[17];
                height = height << 8;
                height |= message[16];
                heightf = height / 1000.0;

                POSLLH = true;
  //            mySerial.println("POSLLH got.");
                break;
            case 0x12:  //NAV-VELNED
                speed3 = 0xFF & message[19];        //скорость
                speed3 = speed3 << 8;
                speed3 |= message[18];
                speed3 = speed3 << 8;
                speed3 |= message[17];
                speed3 = speed3 << 8;
                speed3 |= message[16];
                speed3f = speed3 / 100.0;

                VELNED = true;
    //         mySerial.println("VELNED got.");
                break;
            case 0x06:  // NAV-SOL
              NumSVs = message[47];          //кол-во спутников в решении
              FixType = message[10];        //тип фикса
       //       mySerial.println(NumSVs);
       //       mySerial.println(FixType);

              SOL = true;

      //        mySerial.println("SOL got.");

              break;
      //      default:
//            mySerial.print("Unknown ubx id = ");
 //           mySerial.println(UBX_id);

        }
    }
    else
    {
   //   mySerial.print("Unknown ubx class = ");
 //     mySerial.println(UBX_class);
    }
}
/**
* \brief Function output data
*/
void sendGPS(void)
{
    mySerial.print("A");
    mySerial.print(longitudef, 5);

    mySerial.print("  B");
    mySerial.print(latitudef, 5);

    mySerial.print("  C");
    mySerial.print(heightf, 3);

    mySerial.print("  D");
    mySerial.print(speed3f, 3);

    mySerial.print("  E");
    mySerial.print(NumSVs);

    mySerial.print("  F");
    mySerial.println(FixType);

    longitude = 0;
    latitude = 0;
    height = 0;
    speed3 = 0;
    NumSVs = 0;
    FixType = 0;
}
/**
* \brief Data cleansing
*/
void clearVars(void)
{
    gpsStep = 0;
    UBX_id = 0;
    UBX_class = 0;
    meslen = 0;
    count = 0;
    CK_AU = 0;
    CK_BU = 0;
    CK_A = 0;
    CK_B = 0;
    for(int i = 0; i < 60; i++)
    {
      message[i] = 0;
    }
}
/**
 *  \brief Starts only 1 time after reset
 *  \author volodink
 */
void setup() {
    Serial.begin(57600); /**< setup hardware serial for GPS side */
    mySerial.begin(9600);/**< setup hardware serial for GPS side */
    mySerial.println("UBX ready.");
    clearVars();
}
/**
 *  \brief Running in the infinite loop
 *  \author volodink
 */
void loop()
{
    //mySerial.println("enter loop");

    getUBX();
    if (gotUBX == true)
    {
    //    mySerial.println("got ubx packet");
        decodeUBX();
    //    mySerial.println("ubx packet decoded");
        if (POSLLH == 1 && VELNED == 1 && SOL == 1)
        {

        //    mySerial.println("if posllh == 1");
            sendGPS();
            POSLLH = 0;
            VELNED = 0;
            SOL = 0;
        }
        clearVars();
        gotUBX = false;
    }
}
<commit_msg>Update ubx_decoder.cpp<commit_after>#include <AltSoftSerial.h>
void clearVars(void);

/**
 *  \brief Software serial port object
 *  \author volodink
 */
AltSoftSerial mySerial;

volatile uint8_t message[512];

/**
 * The first argument to calculate the checksum
 */
uint8_t CK_A = 0, CK_B = 0;
/**< The second argument to calculate the checksum */
/**
 * The first argument to comparison the checksum
 */
uint8_t CK_AU = 0, CK_BU = 0; /**< The second argument to comparison the checksum */
int gpsStep = 0; /**< If the data suits us, this parameter makes the step */
uint8_t UBX_id = 0; /**< Message ID */
uint8_t UBX_class = 0; /**< Message class */
uint8_t meslenL = 0;
uint8_t meslenH = 0;
int16_t meslen = 0;
int count = 0;
boolean gotUBX = false; /**< The parameter which checks getting data */
boolean POSLLH = 0; /**< Geodetic Position Solution; This message outputs
 * the Geodetic position in the currently selected Ellipsoid.
 */
boolean SVINFO = 0;/**< Space Vehicle Information */
boolean SOL = 0;/**< Navigation Solution Information; This message combines Position,
 * velocity and time solution in ECEF, including accuracy figures
 */
boolean VELNED = 0;/**< Velocity Solution in NED */
long int longitude; /**< Longitude */
float longitudef; /**< Output longitude */
long int latitude; /**< Latitude */
float latitudef; /**< Output latitude */
long int height; /**< Height */
float heightf; /**< Output height */
long int speed3; /**< Longitude */
float speed3f; /**< Speed */
char bufer[20];

/**
 * GPSfix Type, range 0..5;
 * Is a measure of the communication
 * required for a GPS receiver to acquire
 * satellite signals and navigation data
 */
unsigned char FixType = 22;
unsigned char NumSVs = 33; /**< Number of SVs used in Nav Solution */

int ledPin = 13;
int fixStep = 0; /**< If parameter FixType is 0x02 or 0x03, this parameter makes the step */
int nofixStep = 0; /**< If parameter FixType is not 0x02 or 0x03, this parameter makes the step */

/**
 * \brief uBlox checksum algorithm
 * \param ubx_data Contains the data over
 * which the checksum is to be calculated.
 */
void ubx_checksum(byte ubx_data) //рассчет контрольной суммы
{
    CK_A += ubx_data;
    CK_B += CK_A;
}

/**
 * \brief Getting and comparing data
 */
void getUBX(void) //Получаем пакет и делаем с ним штуки
{
    if (Serial.available() > 0)
    {
        uint8_t c = Serial.read();
        switch (gpsStep)
        {
            case 0:

                if (c == 0xB5){
                    gpsStep++;
    //                mySerial.print("Start 0xB5 ");
                }
                break;

            case 1:

                if (c == 0x62){
                    gpsStep++;
    //                          mySerial.print("Start 0x62 ");
                }
                else{
                    gpsStep = 0;
    //                        mySerial.println(" Error not62 ");
                }
                break;

            case 2:

                UBX_class = c;
                ubx_checksum(c);
                gpsStep++;
    //                   mySerial.println(""); mySerial.print(" UBX_CLASS = "); mySerial.println(UBX_class);
                break;

            case 3:

                UBX_id = c;
                ubx_checksum(c);
                gpsStep++;
  //                     mySerial.println(""); mySerial.print(" UBX_id = "); mySerial.println(UBX_id);
                break;

            case 4:

                meslenL = c;
                ubx_checksum(c);
                gpsStep++;
    //                 mySerial.print(" ml ");
                break;

            case 5:

                meslenH = c;
                ubx_checksum(c);
                gpsStep++;
                meslen = 0xFF & meslenL;
                meslen |= meslenH << 8;
                count = 0;
      //               mySerial.print(" mh ");
     //                mySerial.print("mlen=");
     //                mySerial.print(meslen);
                break;

            case 6:

                message[count] = c;
                ubx_checksum(c);
                count++;
                if (count == meslen)
                {
                    gpsStep++;
                    count = 0;
                }
                break;

            case 7:

                CK_AU = c;
                gpsStep++;

    break;

            case 8:

                CK_BU = c;

                if (CK_A == CK_AU && CK_B == CK_BU) //сравнение контрольной суммы
                {
                    gotUBX = true;
                    gpsStep++;
                }

                break;

        }
    }
}

/**
 * \brief UBX-decoder
 */
void decodeUBX(void)
{
    if (UBX_class == 0x01)
    {
        switch (UBX_id)
        {
            case 0x02:  //NAV-POSLLH
                longitude = 0xFF & message[7];       //долгота
                longitude = longitude << 8;
                longitude |= message[6];
                longitude = longitude << 8;
                longitude |= message[5];
                longitude = longitude << 8;
                longitude |= message[4];
                longitudef = longitude / 10000000.0;

                latitude = 0xFF & message[11];       //широта
                latitude = latitude << 8;
                latitude |= message[10];
                latitude = latitude << 8;
                latitude |= message[9];
                latitude = latitude << 8;
                latitude |= message[8];
                latitudef = latitude / 10000000.0;

                height = 0xFF & message[19];         //высота
                height = height << 8;
                height |= message[18];
                height = height << 8;
                height |= message[17];
                height = height << 8;
                height |= message[16];
                heightf = height / 1000.0;

                POSLLH = true;
  //            mySerial.println("POSLLH got.");
                break;
            case 0x12:  //NAV-VELNED
                speed3 = 0xFF & message[19];        //скорость
                speed3 = speed3 << 8;
                speed3 |= message[18];
                speed3 = speed3 << 8;
                speed3 |= message[17];
                speed3 = speed3 << 8;
                speed3 |= message[16];
                speed3f = speed3 / 100.0;

                VELNED = true;
    //         mySerial.println("VELNED got.");
                break;
            case 0x06:  // NAV-SOL
              NumSVs = message[47];          //кол-во спутников в решении
              FixType = message[10];        //тип фикса

              if (FixType == 0x02 || FixType == 0x03)
              {
                fixStep++;
                nofixStep = 0;
              }
              else
              {
                nofixStep++;
                fixStep = 0;
              }

              if (fixStep == 12) digitalWrite(ledPin, HIGH);
              if (nofixStep == 12) digitalWrite(ledPin, LOW);

       //       mySerial.println(NumSVs);
       //       mySerial.println(FixType);

              SOL = true;

      //        mySerial.println("SOL got.");

              break;
      //      default:
//            mySerial.print("Unknown ubx id = ");
 //           mySerial.println(UBX_id);

        }
    }
    else
    {
   //   mySerial.print("Unknown ubx class = ");
 //     mySerial.println(UBX_class);
    }
}
/**
* \brief Function output data
*/
void sendGPS(void)
{
    mySerial.print("A");
    mySerial.print(longitudef, 6);

    mySerial.print("  B");
    mySerial.print(latitudef, 6);

    mySerial.print("  C");
    mySerial.print(heightf, 3);

    mySerial.print("  D");
    mySerial.print(speed3f, 3);

    mySerial.print("  E");
    mySerial.print(NumSVs);

    mySerial.print("  F");
    mySerial.println(FixType);

    longitude = 0;
    latitude = 0;
    height = 0;
    speed3 = 0;
    NumSVs = 0;
    FixType = 0;
}
/**
* \brief Data cleansing
*/
void clearVars(void)
{
    gpsStep = 0;
    UBX_id = 0;
    UBX_class = 0;
    meslen = 0;
    count = 0;
    CK_AU = 0;
    CK_BU = 0;
    CK_A = 0;
    CK_B = 0;
    for(int i = 0; i < 60; i++)
    {
      message[i] = 0;
    }
}
/**
 *  \brief Starts only 1 time after reset
 *  \author volodink
 */
void setup() {
    Serial.begin(57600); /**< setup hardware serial for GPS side */
    mySerial.begin(9600);/**< setup hardware serial for GPS side */
    pinMode(13, OUTPUT);
    mySerial.println("UBX ready.");
    clearVars();
}
/**
 *  \brief Running in the infinite loop
 *  \author volodink
 */
void loop()
{
    //mySerial.println("enter loop");

    getUBX();
    if (gotUBX == true)
    {
    //    mySerial.println("got ubx packet");
        decodeUBX();
    //    mySerial.println("ubx packet decoded");
        if (POSLLH == 1 && VELNED == 1 && SOL == 1)
        {

        //    mySerial.println("if posllh == 1");
            sendGPS();
            POSLLH = 0;
            VELNED = 0;
            SOL = 0;
        }
        clearVars();
        gotUBX = false;
    }
}
<|endoftext|>


<commit_before>// -D_GNU_SOURCE makes SOCK_NONBLOCK etc. available on linux
#undef  _GNU_SOURCE
#define _GNU_SOURCE

#include "uv.h"
#include "node.h"
#include "pipe_wrap.h"
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

using namespace v8;
using namespace node;

namespace {

Persistent<String> errno_symbol;

void SetErrno(int errorno) {
    // set errno in the global context, this is the technique
    // that node uses to propagate system level errors to JS land
    Context::GetCurrent()->Global()->Set(errno_symbol, Integer::New(errorno));
}

void SetNonBlock(int fd) {
    int flags;
	int r;

	flags = fcntl(fd, F_GETFL);
	assert(flags != -1);

	r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
	assert(r != -1);
}

void SetCloExec(int fd) {
	int flags;
	int r;

	flags = fcntl(fd, F_GETFD);
	assert(flags != -1);

	r = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
	assert(r != -1);
}

Handle<Value> Socket(const Arguments& args) {
    HandleScope scope;
    int protocol;
    int domain;
    int type;
    int fd;

    assert(args.Length() == 3);

    domain    = args[0]->Int32Value();
    type      = args[1]->Int32Value();
    protocol  = args[2]->Int32Value();

#if defined(SOCK_NONBLOCK)
    type |= SOCK_NONBLOCK;
#endif
#if defined(SOCK_CLOEXEC)
    type |= SOCK_CLOEXEC;
#endif

    if ((fd = socket(domain, type, protocol)) == -1) {
        SetErrno(errno);
        goto out;
    }

#if !defined(SOCK_NONBLOCK)
    SetNonBlock(fd);
#endif
#if !defined(SOCK_CLOEXEC)
    SetCloExec(fd);
#endif

out:
    return scope.Close(Integer::New(fd));
}

Handle<Value> Bind(const Arguments& args) {
    HandleScope scope;
    sockaddr_un sun;
    int fd;
    int ret;

    assert(args.Length() == 2);

    fd = args[0]->Int32Value();
    String::Utf8Value path(args[1]);

    strncpy(sun.sun_path, *path, sizeof(sun.sun_path) - 1);
    sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
    sun.sun_family = AF_UNIX;

    if ((ret = bind(fd, reinterpret_cast<sockaddr*>(&sun), sizeof(sun))) == -1) {
        SetErrno(errno);
    }

    return scope.Close(Integer::New(ret));
}

Handle<Value> GetPeerName(const Arguments& args) {

    HandleScope scope;
    assert(args.Length() == 1);
    Local<Object> obj = args[0]->ToObject();
    assert(obj->InternalFieldCount() > 0);
    int ret;
    sockaddr_un sun;
    socklen_t addrlen = sizeof(sun);
    memset(&sun, '\0', addrlen);
    PipeWrap* wrap = static_cast<PipeWrap*>(obj->GetPointerFromInternalField(0));
    int fd = wrap->UVHandle()->fd;
    if ((ret = getpeername(fd, reinterpret_cast<sockaddr*>(&sun), &addrlen)) == -1) {
        SetErrno(errno);
        return Null();
    }

    /* If addrlen == 2 --> no path */
    return addrlen == 2 ? Null() : scope.Close(String::New(sun.sun_path));
}

Handle<Value> GetSockName(const Arguments& args) {

    HandleScope scope;
    assert(args.Length() == 1);
    Local<Object> obj = args[0]->ToObject();
    assert(obj->InternalFieldCount() > 0);
    int ret;
    sockaddr_un sun;
    socklen_t addrlen = sizeof(sun);
    memset(&sun, '\0', addrlen);
    PipeWrap* wrap = static_cast<PipeWrap*>(obj->GetPointerFromInternalField(0));
    int fd = wrap->UVHandle()->fd;
    if ((ret = getsockname(fd, reinterpret_cast<sockaddr*>(&sun), &addrlen)) == -1) {
        SetErrno(errno);
        return Null();
    }

    /* If addrlen == 2 --> no path */
    return addrlen == 2 ? Null() : scope.Close(String::New(sun.sun_path));
}

void Initialize(Handle<Object> target) {

    errno_symbol = Persistent<String>::New(String::NewSymbol("errno"));
    target->Set(String::NewSymbol("AF_UNIX"), Integer::New(AF_UNIX));
    target->Set(String::NewSymbol("SOCK_STREAM"), Integer::New(SOCK_STREAM));
    target->Set(String::NewSymbol("socket"), FunctionTemplate::New(Socket)->GetFunction());
    target->Set(String::NewSymbol("bind"), FunctionTemplate::New(Bind)->GetFunction());
    target->Set(String::NewSymbol("getpeername"), FunctionTemplate::New(GetPeerName)->GetFunction());
    target->Set(String::NewSymbol("getsockname"), FunctionTemplate::New(GetSockName)->GetFunction());
}

}

NODE_MODULE(unix_stream, Initialize)
<commit_msg>Remove unused variables<commit_after>// -D_GNU_SOURCE makes SOCK_NONBLOCK etc. available on linux
#undef  _GNU_SOURCE
#define _GNU_SOURCE

#include "uv.h"
#include "node.h"
#include "pipe_wrap.h"
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

using namespace v8;
using namespace node;

namespace {

Persistent<String> errno_symbol;

void SetErrno(int errorno) {
    // set errno in the global context, this is the technique
    // that node uses to propagate system level errors to JS land
    Context::GetCurrent()->Global()->Set(errno_symbol, Integer::New(errorno));
}

void SetNonBlock(int fd) {
    int flags;
	int r;

	flags = fcntl(fd, F_GETFL);
	assert(flags != -1);

	r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
	assert(r != -1);
}

void SetCloExec(int fd) {
	int flags;
	int r;

	flags = fcntl(fd, F_GETFD);
	assert(flags != -1);

	r = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
	assert(r != -1);
}

Handle<Value> Socket(const Arguments& args) {
    HandleScope scope;
    int protocol;
    int domain;
    int type;
    int fd;

    assert(args.Length() == 3);

    domain    = args[0]->Int32Value();
    type      = args[1]->Int32Value();
    protocol  = args[2]->Int32Value();

#if defined(SOCK_NONBLOCK)
    type |= SOCK_NONBLOCK;
#endif
#if defined(SOCK_CLOEXEC)
    type |= SOCK_CLOEXEC;
#endif

    if ((fd = socket(domain, type, protocol)) == -1) {
        SetErrno(errno);
        goto out;
    }

#if !defined(SOCK_NONBLOCK)
    SetNonBlock(fd);
#endif
#if !defined(SOCK_CLOEXEC)
    SetCloExec(fd);
#endif

out:
    return scope.Close(Integer::New(fd));
}

Handle<Value> Bind(const Arguments& args) {
    HandleScope scope;
    sockaddr_un sun;
    int fd;
    int ret;

    assert(args.Length() == 2);

    fd = args[0]->Int32Value();
    String::Utf8Value path(args[1]);

    strncpy(sun.sun_path, *path, sizeof(sun.sun_path) - 1);
    sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
    sun.sun_family = AF_UNIX;

    if ((ret = bind(fd, reinterpret_cast<sockaddr*>(&sun), sizeof(sun))) == -1) {
        SetErrno(errno);
    }

    return scope.Close(Integer::New(ret));
}

Handle<Value> GetPeerName(const Arguments& args) {

    HandleScope scope;
    assert(args.Length() == 1);
    Local<Object> obj = args[0]->ToObject();
    assert(obj->InternalFieldCount() > 0);
    sockaddr_un sun;
    socklen_t addrlen = sizeof(sun);
    memset(&sun, '\0', addrlen);
    PipeWrap* wrap = static_cast<PipeWrap*>(obj->GetPointerFromInternalField(0));
    int fd = wrap->UVHandle()->fd;
    if (getpeername(fd, reinterpret_cast<sockaddr*>(&sun), &addrlen) == -1) {
        SetErrno(errno);
        return Null();
    }

    /* If addrlen == 2 --> no path */
    return addrlen == 2 ? Null() : scope.Close(String::New(sun.sun_path));
}

Handle<Value> GetSockName(const Arguments& args) {

    HandleScope scope;
    assert(args.Length() == 1);
    Local<Object> obj = args[0]->ToObject();
    assert(obj->InternalFieldCount() > 0);
    sockaddr_un sun;
    socklen_t addrlen = sizeof(sun);
    memset(&sun, '\0', addrlen);
    PipeWrap* wrap = static_cast<PipeWrap*>(obj->GetPointerFromInternalField(0));
    int fd = wrap->UVHandle()->fd;
    if (getsockname(fd, reinterpret_cast<sockaddr*>(&sun), &addrlen) == -1) {
        SetErrno(errno);
        return Null();
    }

    /* If addrlen == 2 --> no path */
    return addrlen == 2 ? Null() : scope.Close(String::New(sun.sun_path));
}

void Initialize(Handle<Object> target) {

    errno_symbol = Persistent<String>::New(String::NewSymbol("errno"));
    target->Set(String::NewSymbol("AF_UNIX"), Integer::New(AF_UNIX));
    target->Set(String::NewSymbol("SOCK_STREAM"), Integer::New(SOCK_STREAM));
    target->Set(String::NewSymbol("socket"), FunctionTemplate::New(Socket)->GetFunction());
    target->Set(String::NewSymbol("bind"), FunctionTemplate::New(Bind)->GetFunction());
    target->Set(String::NewSymbol("getpeername"), FunctionTemplate::New(GetPeerName)->GetFunction());
    target->Set(String::NewSymbol("getsockname"), FunctionTemplate::New(GetSockName)->GetFunction());
}

}

NODE_MODULE(unix_stream, Initialize)
<|endoftext|>


<commit_before>

/*
*
*	Copyright (C) 2016 Luxon Jean-Pierre
*	gumichan01.olympe.in
*
*
*	Luxon Jean-Pierre (Gumichan01)
*	luxon.jean.pierre@gmail.com
*
*/

#include "utf8_string.hpp"

UTF8string::UTF8string() : utf8length(0){}

UTF8string::UTF8string(const std::string &str)
 : UTF8string()
{
    for(auto c : str)
    {
        utf8data.push_back(c);
    }

    /// @todo Check if the utf-8 string is valid
    utf8length = utf8_length_();
}

UTF8string::UTF8string(const UTF8string &u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
}

const UTF8string& UTF8string::operator =(const char * str)
{
    utf8data = str;
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const std::string str)
{
    for(auto c : str)
    {
        utf8data.push_back(c);
    }

    /// @todo Check if the utf-8 string is valid
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const UTF8string u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
    return *this;
}

const UTF8string& UTF8string::operator +=(const std::string str)
{
    utf8data += str;
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const UTF8string u8str)
{
    for(auto c : u8str.utf8data)
    {
        utf8data.push_back(c);
    }

    utf8length = utf8_length_();
    return *this;
}

void UTF8string::clear()
{
    utf8data.clear();
    utf8length = 0;
}

bool UTF8string::empty()
{
    return utf8length == 0;
}

/// @bug The substring is not correct
UTF8string UTF8string::substr(size_t pos,size_t len)
{
    if(pos > utf8length)
        return std::string();

    const size_t n = (len == static_cast<size_t>(-1)
                      || len > utf8length) ? (utf8length - pos) : (len - pos);
    std::string s;

    for(auto j = pos; j < n; j++)
    {
        const utf8_len_t cplen = utf8_codepoint_len(j);
        auto i = j;

        while(i < (j+cplen))
        {
            s.push_back(utf8data[i++]);
        }
    }

    return s;
}

utf8_len_t UTF8string::utf8_codepoint_len(size_t j)
{
    if (0xf0 == (0xf8 & utf8data[j]))
    {
        return 4;
    }
    else if (0xe0 == (0xf0 & utf8data[j]))
    {
        return 3;
    }
    else if (0xc0 == (0xe0 & utf8data[j]))
    {
        return 2;
    }
    else
        return 1;
}

utf8_len_t UTF8string::utf8_size()
{
    return utf8data.size();
}

bool UTF8string::utf8_is_valid_()
{
    auto end_data = utf8data.end();
    auto it = utf8data.begin();

    while(it != end_data)
    {
        /// @todo check the validity
        it++;
    }

    return true;
}

utf8_len_t UTF8string::utf8_length_()
{
    auto end_data = utf8data.end();
    auto it = utf8data.begin();
    utf8_len_t len = 0;

    while(it != end_data)
    {
        byte_t byte = *it;

        if (0xf0 == (0xf8 & byte))
        {
            // 4-byte utf8 character
            // (0b11110xxx 0bxxxxxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 4;
        }
        else if (0xe0 == (0xf0 & byte))
        {
            // 3-byte utf8 code point (0b110xxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 3;
        }
        else if (0xc0 == (0xe0 & byte))
        {
            // 2-byte utf8 code point (0b110xxxxx 0bxxxxxxxx)
            it += 2;
        }
        else
        {
            // 1-byte utf8 code point (0b0xxxxxxx)
            it += 1;
        }

        // We want the number of characters (utf-8 code point)
        len += 1;
    }

    return len;
}

utf8_len_t UTF8string::utf8_length()
{
    return utf8length;
}

const char * UTF8string::utf8_str() const
{
    std::string str;

    for(auto c : utf8data)
    {
        str += c;
    }

    return str.c_str();
}

/// @bug Th function fails when the length of the string is greater then than 19
bool operator ==(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 == s2;
}

bool operator !=(const UTF8string &str1, const UTF8string &str2)
{
    return !(str1 == str2);
}

<commit_msg>Refactored the UTF8string class and added an overload of '+='<commit_after>

/*
*
*	Copyright (C) 2016 Luxon Jean-Pierre
*	gumichan01.olympe.in
*
*
*	Luxon Jean-Pierre (Gumichan01)
*	luxon.jean.pierre@gmail.com
*
*/

#include "utf8_string.hpp"

UTF8string::UTF8string() : utf8length(0){}

UTF8string::UTF8string(const std::string &str)
 : utf8data(str)
{

    /// @todo Check if the utf-8 string is valid
    utf8length = utf8_length_();
}

UTF8string::UTF8string(const UTF8string &u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
}

const UTF8string& UTF8string::operator =(const char * str)
{
    utf8data = str;
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const std::string str)
{
    utf8data = str;

    /// @todo Check if the utf-8 string is valid
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator =(const UTF8string u8str)
{
    utf8data = u8str.utf8data;
    utf8length = u8str.utf8length;
    return *this;
}

const UTF8string& UTF8string::operator +=(const std::string str)
{
    utf8data += str;
    utf8length = utf8_length_();
    return *this;
}

const UTF8string& UTF8string::operator +=(const UTF8string u8str)
{
    utf8data += u8str.utf8data;
    utf8length = utf8_length_();
    return *this;
}

void UTF8string::clear()
{
    utf8data.clear();
    utf8length = 0;
}

bool UTF8string::empty()
{
    return utf8length == 0;
}

/// @bug The substring is not correct
UTF8string UTF8string::substr(size_t pos,size_t len)
{
    if(pos > utf8length)
        return std::string();

    const size_t n = (len == static_cast<size_t>(-1)
                      || len > utf8length) ? (utf8length - pos) : (len - pos);
    std::string s;

    for(size_t j = pos; j < n; j++)
    {
        const utf8_len_t cplen = utf8_codepoint_len(j);
        size_t i = j;

        while(i < (j+cplen))
        {
            s.push_back(utf8data[i++]);
        }
    }

    return s;
}

utf8_len_t UTF8string::utf8_codepoint_len(size_t j)
{
    if (0xf0 == (0xf8 & utf8data[j]))
    {
        return 4;
    }
    else if (0xe0 == (0xf0 & utf8data[j]))
    {
        return 3;
    }
    else if (0xc0 == (0xe0 & utf8data[j]))
    {
        return 2;
    }
    else
        return 1;
}

utf8_len_t UTF8string::utf8_size()
{
    return utf8data.size();
}

bool UTF8string::utf8_is_valid_()
{
    auto end_data = utf8data.end();
    auto it = utf8data.begin();

    while(it != end_data)
    {
        /// @todo check the validity
        it++;
    }

    return true;
}

utf8_len_t UTF8string::utf8_length_()
{
    auto end_data = utf8data.end();
    auto it = utf8data.begin();
    utf8_len_t len = 0;

    while(it != end_data)
    {
        byte_t byte = *it;

        if (0xf0 == (0xf8 & byte))
        {
            // 4-byte utf8 character
            // (0b11110xxx 0bxxxxxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 4;
        }
        else if (0xe0 == (0xf0 & byte))
        {
            // 3-byte utf8 code point (0b110xxxxx 0bxxxxxxxx 0bxxxxxxxx)
            it += 3;
        }
        else if (0xc0 == (0xe0 & byte))
        {
            // 2-byte utf8 code point (0b110xxxxx 0bxxxxxxxx)
            it += 2;
        }
        else
        {
            // 1-byte utf8 code point (0b0xxxxxxx)
            it += 1;
        }

        // We want the number of characters (utf-8 code point)
        len += 1;
    }

    return len;
}

utf8_len_t UTF8string::utf8_length()
{
    return utf8length;
}

const char * UTF8string::utf8_str() const
{
    return utf8data.c_str();
}

/// @bug Th function fails when the length of the string is greater then than 19
bool operator ==(const UTF8string &str1, const UTF8string &str2)
{
    const std::string s1 = str1.utf8_str();
    const std::string s2 = str2.utf8_str();

    return s1 == s2;
}

bool operator !=(const UTF8string &str1, const UTF8string &str2)
{
    return !(str1 == str2);
}

<|endoftext|>


<commit_before>/*
 * (C) 2015-2016 Augustin Cavalier
 * All rights reserved. Distributed under the terms of the MIT license.
 */
#include "FSUtil.h"

#include "OSUtil.h"
#include "StringUtil.h"

#include <algorithm>
#include <fstream>
#include <vector>

#include <ctype.h>
#include <cstdlib>

#ifndef _MSC_VER
#  include <sys/types.h>
#  include <sys/stat.h>
#  include <unistd.h>
#  include <dirent.h>
#  include <cstring>
#else /* _MSC_VER */
#  define WIN32_LEAN_AND_MEAN
#  include <direct.h>
#  include <windows.h>
#  define PATH_MAX MAX_PATH
#endif

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

// Static member variables
vector<string> FSUtil::fPATHs;

bool FSUtil::exists(const string& path)
{
	string filename = path;
#ifdef _WIN32
	StringUtil::replaceAll(filename, "/", "\\");
#endif

	std::ifstream f(filename);
	return static_cast<bool>(f);
}

bool FSUtil::isFile(const string& path)
{
	struct ::stat statbuf;
	if (::stat(path.c_str(), &statbuf) == -1)
		return false;
	if (statbuf.st_mode & S_IFREG)
		return true;
	return false;
}

bool FSUtil::isDir(const string& path)
{
	struct ::stat statbuf;
	if (::stat(path.c_str(), &statbuf) == -1)
		return false;
	if (statbuf.st_mode & S_IFDIR)
		return true;
	return false;
}

bool FSUtil::isExec(const string& path)
{
#ifndef _WIN32
	struct ::stat statbuf;
	if (::stat(path.c_str(), &statbuf) == 0) {
		return ((statbuf.st_mode & S_IFREG) && (statbuf.st_mode & 0111));
	}
	return false;
#else
	return !path.empty() && isFile(path); // Because who knows, anyway.
#endif
}

bool FSUtil::isPathAbsolute(const string& path)
{
	return (path[0] == '/'
#ifdef _WIN32
		|| (path.length() > 2 && path[1] == ':' && path[2] == '/') // "C:/" or the like
#endif
		);
}

string FSUtil::getContents(const string& file)
{
	std::ifstream filestream(file);
	// extra ()s here are mandatory
	return string((std::istreambuf_iterator<char>(filestream)),
		std::istreambuf_iterator<char>());
}

void FSUtil::setContents(const string& file, const string& contents)
{
	std::ofstream filestream(file);
	filestream << contents;
}

void FSUtil::deleteFile(const string& file)
{
	::remove(file.c_str());
}

#ifndef _MSC_VER
void FSUtil_fileSearchHelper(vector<string>& ret, const string& dir,
	const vector<string>& exts, bool recursive)
{
	DIR* dp = ::opendir(dir.c_str());
	if (dp == nullptr) {
		// Path does not exist or could not be read
		return;
	}

	struct ::dirent* entry;
	while ((entry = ::readdir(dp)) != nullptr) {
		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
			continue;
		string fullPath = FSUtil::combinePaths({dir, entry->d_name});
		if (recursive && FSUtil::isDir(fullPath))
			FSUtil_fileSearchHelper(ret, fullPath, exts, recursive);
		else {
			for (string ext : exts) {
				if (StringUtil::endsWith(fullPath, ext)) {
					ret.push_back(fullPath);
					break;
				}
			}
		}
	}

	closedir(dp);
}
#else /* _MSC_VER  */
void FSUtil_fileSearchHelper(vector<string>& ret, const string& dir,
	const vector<string>& exts, bool recursive)
{
	// Specify a file mask.
	string path = dir + "\\*";

	WIN32_FIND_DATAA file;
	HANDLE findHndl = nullptr;
	if ((findHndl = FindFirstFileA(path.c_str(), &file)) == INVALID_HANDLE_VALUE) {
		// Path not found
		return;
	}

	do {
		if (strcmp(file.cFileName, ".") == 0 || strcmp(file.cFileName, "..") == 0)
			continue;
		// Build the path
		path = dir + "\\" + file.cFileName;

		if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			FSUtil_fileSearchHelper(ret, path, exts, recursive);
		} else {
			for (string ext : exts) {
				if (StringUtil::endsWith(path, ext)) {
					ret.push_back(FSUtil::normalizePath(path));
					break;
				}
			}
		}
	} while (FindNextFileA(findHndl, &file));

	FindClose(findHndl);
}
#endif

vector<string> FSUtil::searchForFiles(const string& dir, const vector<string>& exts,
	bool recursive)
{
	vector<string> ret;
	FSUtil_fileSearchHelper(ret, dir, exts, recursive);
	return ret;
}

string FSUtil::which(const string& prog)
{
	if (prog.empty())
		return prog;

	const string program = normalizePath(prog);
	if (isPathAbsolute(program))
		return program; // already an absolute path

#ifdef _WIN32
	string pathext = OSUtil::getEnv("PATHEXT");
	std::transform(pathext.begin(), pathext.end(), pathext.begin(), ::tolower);
	const vector<string> pathExts = StringUtil::split(pathext, ";");
	auto permutePathExt = [&](const string& path) {
		for (string ext : pathExts) {
			string fullPath = path + ext;
			if (exists(fullPath))
				return fullPath;
		}
		return string();
	};
#endif

	// The program's name contains a slash, ignore PATH
	if (program.find('/') != string::npos) {
		string normd = normalizePath(program);
		if (isExec(normd))
			return normd;
#ifdef _WIN32
		else
			return permutePathExt(normalizePath(program));
#endif
	}

	if (fPATHs.empty()) {
#ifdef _WIN32
		fPATHs = StringUtil::split(OSUtil::getEnv("PATH"), ";");
#else
		fPATHs = StringUtil::split(OSUtil::getEnv("PATH"), ":");
#endif
	}

	if (fPATHs.empty())
		return "";
	for (string path : fPATHs) {
		string fullPath =
#ifdef _WIN32
			permutePathExt(combinePaths({path, program}));
#else
			combinePaths({path, program});
#endif
		if (isExec(fullPath))
			return fullPath;
	}
	return "";
}

string FSUtil::normalizePath(const string& path)
{
	if (path.empty())
		return path;

	string ret = path;
#ifdef _WIN32
	StringUtil::replaceAll(ret, "\\", "/");
#endif
	vector<string> orig = StringUtil::split(ret, "/"), normd;
	for (string i : orig) {
		if (i == ".")
			continue;
		else if (i.empty() && normd.size() > 0) // preserve the opening '/'
			continue;
		else if (i == ".." && normd.size() > 0 && normd[normd.size() - 1] != "..")
			normd.pop_back();
		else
			normd.push_back(i);
	}

	// Now that we've normalized the vector containing the individual components,
	// rebuild the actual path string.
	ret = "";
	for (vector<string>::size_type i = 0; i < normd.size(); i++) {
		if (i != 0)
			ret += "/";
		ret += normd[i];
	}

#ifdef _WIN32
	// Turn Cygwin/MSYS-style paths (e.g. '/c/Windows/') into drive+path format
	// (e.g. "C:/Windows/").
	if (ret.length() > 2 && ret[0] == '/' && ret[2] == '/') {
		ret[0] = ::toupper(ret[1]);
		ret[1] = ':';
	}
#endif
	return ret;
}

string FSUtil::combinePaths(const vector<string>& paths)
{
	string ret;
	for (string path : paths) {
		bool endsInSeparator =
			ret.length() == 0 ||
			StringUtil::endsWith(ret, "/")
#ifdef _WIN32
			|| StringUtil::endsWith(ret, "\\")
#endif
			;

		if (!endsInSeparator) {
			ret += "/";
		}
		ret += path;
	}
	return normalizePath(ret);
}

string FSUtil::absolutePath(const string& path)
{
	string ret = normalizePath(path);
	if (path[0] == '/'
#ifdef _WIN32
		|| (path.size() > 2 && path[1] == ':' && path[2] == '/')
#endif
		)
		return ret;
	char cwd[PATH_MAX];
	if (getcwd(cwd, sizeof(cwd)) != NULL)
		ret = FSUtil::combinePaths({cwd, path});
	return ret;
}

string FSUtil::parentDirectory(const string& path)
{
	string ret = normalizePath(path);
	string::size_type pos = ret.rfind("/", ret.length() - 1 /* in case it ends with a '/' */);
	if (pos == string::npos)
		return "."; // No '/'s in the path; so it's just a single file.
	return ret.substr(0, pos);
}

void FSUtil::mkdir(const string& path)
{
#ifdef _MSC_VER
	::_mkdir(path.c_str());
#else
	::mkdir(path.c_str()
#ifndef _WIN32
		, 0755 // mode
#endif
		);
#endif
}
void FSUtil::rmdir(const string& path)
{
	::rmdir(path.c_str());
}
<commit_msg>FSUtil: Cleanup.<commit_after>/*
 * (C) 2015-2016 Augustin Cavalier
 * All rights reserved. Distributed under the terms of the MIT license.
 */
#include "FSUtil.h"

#include "OSUtil.h"
#include "StringUtil.h"

#include <algorithm>
#include <fstream>
#include <vector>

#include <cctype>
#include <cstdlib>

#ifndef _MSC_VER
#  include <sys/types.h>
#  include <sys/stat.h>
#  include <unistd.h>
#  include <dirent.h>
#  include <cstring>
#else /* _MSC_VER */
#  define WIN32_LEAN_AND_MEAN
#  include <direct.h>
#  include <windows.h>
#  define PATH_MAX MAX_PATH
#endif

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

// Static member variables
vector<string> FSUtil::fPATHs;

bool FSUtil::exists(const string& path)
{
	string filename = path;
#ifdef _WIN32
	StringUtil::replaceAll(filename, "/", "\\");
#endif

	std::ifstream f(filename);
	return static_cast<bool>(f);
}

bool FSUtil::isFile(const string& path)
{
	struct ::stat statbuf;
	if (::stat(path.c_str(), &statbuf) == -1)
		return false;
	if (statbuf.st_mode & S_IFREG)
		return true;
	return false;
}

bool FSUtil::isDir(const string& path)
{
	struct ::stat statbuf;
	if (::stat(path.c_str(), &statbuf) == -1)
		return false;
	if (statbuf.st_mode & S_IFDIR)
		return true;
	return false;
}

bool FSUtil::isExec(const string& path)
{
#ifndef _WIN32
	struct ::stat statbuf;
	if (::stat(path.c_str(), &statbuf) == 0) {
		return ((statbuf.st_mode & S_IFREG) && (statbuf.st_mode & 0111));
	}
	return false;
#else
	return !path.empty() && isFile(path); // Because who knows, anyway.
#endif
}

bool FSUtil::isPathAbsolute(const string& path)
{
	return (path[0] == '/'
#ifdef _WIN32
		|| (path.length() > 2 && path[1] == ':' && path[2] == '/') // "C:/" or the like
#endif
		);
}

string FSUtil::getContents(const string& file)
{
	std::ifstream filestream(file);
	// extra ()s here are supposedly mandatory?
	return string((std::istreambuf_iterator<char>(filestream)),
		std::istreambuf_iterator<char>());
}

void FSUtil::setContents(const string& file, const string& contents)
{
	std::ofstream filestream(file);
	filestream << contents;
}

void FSUtil::deleteFile(const string& file)
{
	::remove(file.c_str());
}

#ifndef _MSC_VER
void FSUtil_fileSearchHelper(vector<string>& ret, const string& dir,
	const vector<string>& exts, bool recursive)
{
	DIR* dp = ::opendir(dir.c_str());
	if (dp == nullptr) {
		// Path does not exist or could not be read
		return;
	}

	struct ::dirent* entry;
	while ((entry = ::readdir(dp)) != nullptr) {
		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
			continue;
		string fullPath = FSUtil::combinePaths({dir, entry->d_name});
		if (recursive && FSUtil::isDir(fullPath))
			FSUtil_fileSearchHelper(ret, fullPath, exts, recursive);
		else {
			for (string ext : exts) {
				if (StringUtil::endsWith(fullPath, ext)) {
					ret.push_back(fullPath);
					break;
				}
			}
		}
	}

	closedir(dp);
}
#else /* _MSC_VER  */
void FSUtil_fileSearchHelper(vector<string>& ret, const string& dir,
	const vector<string>& exts, bool recursive)
{
	// Specify a file mask.
	string path = dir + "\\*";

	WIN32_FIND_DATAA file;
	HANDLE findHndl = nullptr;
	if ((findHndl = FindFirstFileA(path.c_str(), &file)) == INVALID_HANDLE_VALUE) {
		// Path not found
		return;
	}

	do {
		if (strcmp(file.cFileName, ".") == 0 || strcmp(file.cFileName, "..") == 0)
			continue;
		// Build the path
		path = dir + "\\" + file.cFileName;

		if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
			FSUtil_fileSearchHelper(ret, path, exts, recursive);
		} else {
			for (string ext : exts) {
				if (StringUtil::endsWith(path, ext)) {
					ret.push_back(FSUtil::normalizePath(path));
					break;
				}
			}
		}
	} while (FindNextFileA(findHndl, &file));

	FindClose(findHndl);
}
#endif

vector<string> FSUtil::searchForFiles(const string& dir, const vector<string>& exts,
	bool recursive)
{
	vector<string> ret;
	FSUtil_fileSearchHelper(ret, dir, exts, recursive);
	return ret;
}

string FSUtil::which(const string& prog)
{
	if (prog.empty())
		return prog;

	const string program = normalizePath(prog);
	if (isPathAbsolute(program))
		return program; // already an absolute path

#ifdef _WIN32
	string pathext = OSUtil::getEnv("PATHEXT");
	std::transform(pathext.begin(), pathext.end(), pathext.begin(), ::tolower);
	const vector<string> pathExts = StringUtil::split(pathext, ";");
	auto permutePathExt = [&](const string& path) {
		for (string ext : pathExts) {
			string fullPath = path + ext;
			if (exists(fullPath))
				return fullPath;
		}
		return string();
	};
#endif

	// The program's name contains a slash, ignore PATH
	if (program.find('/') != string::npos) {
		string normd = normalizePath(program);
		if (isExec(normd))
			return normd;
#ifdef _WIN32
		else
			return permutePathExt(normalizePath(program));
#endif
	}

	if (fPATHs.empty()) {
#ifdef _WIN32
		fPATHs = StringUtil::split(OSUtil::getEnv("PATH"), ";");
#else
		fPATHs = StringUtil::split(OSUtil::getEnv("PATH"), ":");
#endif
	}

	if (fPATHs.empty())
		return "";
	for (string path : fPATHs) {
		string fullPath =
#ifdef _WIN32
			permutePathExt(combinePaths({path, program}));
#else
			combinePaths({path, program});
#endif
		if (isExec(fullPath))
			return fullPath;
	}
	return "";
}

string FSUtil::normalizePath(const string& path)
{
	if (path.empty())
		return path;

	string ret = path;
#ifdef _WIN32
	StringUtil::replaceAll(ret, "\\", "/");
#endif
	vector<string> orig = StringUtil::split(ret, "/"), normd;
	for (string i : orig) {
		if (i == ".")
			continue;
		else if (i.empty() && normd.size() > 0) // preserve the opening '/'
			continue;
		else if (i == ".." && normd.size() > 0 && normd[normd.size() - 1] != "..")
			normd.pop_back();
		else
			normd.push_back(i);
	}

	// Now that we've normalized the vector containing the individual components,
	// rebuild the actual path string.
	ret = "";
	for (vector<string>::size_type i = 0; i < normd.size(); i++) {
		if (i != 0)
			ret += "/";
		ret += normd[i];
	}

#ifdef _WIN32
	// Turn Cygwin/MSYS-style paths (e.g. '/c/Windows/') into drive+path format
	// (e.g. "C:/Windows/").
	if (ret.length() > 2 && ret[0] == '/' && ret[2] == '/') {
		ret[0] = ::toupper(ret[1]);
		ret[1] = ':';
	}
#endif
	return ret;
}

string FSUtil::combinePaths(const vector<string>& paths)
{
	string ret;
	for (string path : paths) {
		bool endsInSeparator =
			ret.length() == 0 ||
			StringUtil::endsWith(ret, "/")
#ifdef _WIN32
			|| StringUtil::endsWith(ret, "\\")
#endif
			;

		if (!endsInSeparator) {
			ret += "/";
		}
		ret += path;
	}
	return normalizePath(ret);
}

string FSUtil::absolutePath(const string& path)
{
	string ret = normalizePath(path);
	if (path[0] == '/'
#ifdef _WIN32
		|| (path.size() > 2 && path[1] == ':' && path[2] == '/')
#endif
		)
		return ret;
	char cwd[PATH_MAX];
	if (getcwd(cwd, sizeof(cwd)) != NULL)
		ret = FSUtil::combinePaths({cwd, path});
	return ret;
}

string FSUtil::parentDirectory(const string& path)
{
	string ret = normalizePath(path);
	string::size_type pos = ret.rfind("/", ret.length() - 1 /* in case it ends with a '/' */);
	if (pos == string::npos)
		return "."; // No '/'s in the path; so it's just a single file.
	return ret.substr(0, pos);
}

void FSUtil::mkdir(const string& path)
{
#ifdef _MSC_VER
	::_mkdir(path.c_str());
#else
	::mkdir(path.c_str()
#ifndef _WIN32
		, 0755 // mode
#endif
		);
#endif
}
void FSUtil::rmdir(const string& path)
{
	::rmdir(path.c_str());
}
<|endoftext|>


<commit_before>#include "util/config.hpp"
#include "util/stringutil.hpp"

namespace ve
{
	Config::Config()
	{
	}

	Config::Config(std::string const & filename)
	{
		load(filename);
	}

	void Config::load(std::string const & filename)
	{
		// Clear out data.
		type = String;
		text.clear();
		children.clear();

		// Load new data.
		std::string content = readFile(filename);
		size_t i = 0;
		parse(content, i);
	}

	void Config::save(std::string const & filename) const
	{
		std::string content;
		stringify(content);
		writeFile(filename, content);
	}

	void Config::stringify(std::string & t, size_t tabDepth) const
	{
		if (type == Dictionary)
		{
			t += "{\n";
			for (auto iter : children)
			{
				for (unsigned int i = 0; i < tabDepth + 1; i++)
				{
					t += '\t';
				}
				t += iter.first;
				t += " : ";
				iter.second.stringify(t, tabDepth + 1);
			}
			for (unsigned int i = 0; i < tabDepth; i++)
			{
				t += '\t';
			}
			t += "}\n";
		}
		else if (type == List)
		{
			t += "[\n";
			unsigned int count = 0;
			while (true)
			{
				auto iter = children.find(std::to_string(count));
				if (iter == children.end())
				{
					break;
				}
				for (unsigned int i = 0; i < tabDepth + 1; i++)
				{
					t += '\t';
				}
				iter->second.stringify(t, tabDepth + 1);
				count++;
			}
			for (unsigned int i = 0; i < tabDepth; i++)
			{
				t += '\t';
			}
			t += "]\n";
		}
		else if (type == String)
		{
			t += text;
			t += '\n';
		}
	}

	bool Config::hasChild(std::string const & key) const
	{
		return children.find(key) != children.end();
	}

	std::optional<Config const &> Config::operator [] (std::string const & key) const
	{
		auto it = children.find(key);
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config const &>();
	}

	std::optional<Config &> Config::operator [] (std::string & key)
	{
		auto it = children.find(key);
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config &>();
	}

	std::optional<Config const &> Config::operator [] (int index) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config const &>();
	}

	std::optional<Config &> Config::operator [] (int index)
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config &>();
	}

	void Config::parse(std::string const & content, size_t & i)
	{
		type = String;
		text.clear();
		children.clear();
		unsigned int c = 0;

		skipWhiteSpace(content, i);

		// Find out what type of value this is.
		c = getChar(content, i);

		if (c == '{') // Dictionary
		{
			type = Dictionary;
			while (i < content.size())
			{
				// Get Key
				std::string key;
				skipWhiteSpace(content, i);
				if (isStringNext(content, i, "}"))
				{
					i += 1;
					break;
				}

				key = trim(readUntilAny(content, i, " \t\n\r:"));

				skipWhiteSpace(content, i);
				c = getChar(content, i);
				if (c != ':')
				{
					throw std::runtime_error("Expected colon after character");
				}

				children[key].parse(content, i);
			}
		}
		else if (c == '[') // List
		{
			type = List;
			int count = 0;
			while (i < content.size())
			{
				skipWhiteSpace(content, i);
				if (isStringNext(content, i, "]"))
				{
					i += 1;
					break;
				}
				std::string key = std::to_string(count);
				children[key].parse(content, i);
				count++;
			}
		}
		else // String
		{
			type = String;
			std::string quoteStart;
			if (c == '"' || c == '\'' || c == '`') // Quote, grab all of same characters.
			{
				auto quoteC = c;
				do
				{
					quoteStart += getStringFromChar(c);
					c = getChar(content, i);
				} while (c == quoteC);
			}
			text += getStringFromChar(c);
			if (!quoteStart.empty())
			{
				text = readUntil(content, i, quoteStart);
				i += quoteStart.size();
			}
			else
			{
				text = readUntilAny(content, i, " \t\n\r}]");
			}
		}
	}

	template <> bool Config::getChildAs(std::string const & key, bool defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			if (it->second.text == "true") return true;
			if (it->second.text == "false") return false;
		}
		return defaultValue;
	}

	template <> int Config::getChildAs(std::string const & key, int defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stoi(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> float Config::getChildAs(std::string const & key, float defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stof(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> std::string Config::getChildAs(std::string const & key, std::string defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			return it->second.text;
		}
		return defaultValue;
	}

	template <> bool Config::getChildAs(int index, bool defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			if (it->second.text == "true") return true;
			if (it->second.text == "false") return false;
		}
		return defaultValue;
	}

	template <> int Config::getChildAs(int index, int defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stoi(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> float Config::getChildAs(int index, float defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stof(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> std::string Config::getChildAs(int index, std::string defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			return it->second.text;
		}
		return defaultValue;
	}
}<commit_msg>Fixed config parsing bug<commit_after>#include "util/config.hpp"
#include "util/stringutil.hpp"

namespace ve
{
	Config::Config()
	{
	}

	Config::Config(std::string const & filename)
	{
		load(filename);
	}

	void Config::load(std::string const & filename)
	{
		// Clear out data.
		type = String;
		text.clear();
		children.clear();

		// Load new data.
		std::string content = readFile(filename);
		size_t i = 0;
		parse(content, i);
	}

	void Config::save(std::string const & filename) const
	{
		std::string content;
		stringify(content);
		writeFile(filename, content);
	}

	void Config::stringify(std::string & t, size_t tabDepth) const
	{
		if (type == Dictionary)
		{
			t += "{\n";
			for (auto iter : children)
			{
				for (unsigned int i = 0; i < tabDepth + 1; i++)
				{
					t += '\t';
				}
				t += iter.first;
				t += " : ";
				iter.second.stringify(t, tabDepth + 1);
			}
			for (unsigned int i = 0; i < tabDepth; i++)
			{
				t += '\t';
			}
			t += "}\n";
		}
		else if (type == List)
		{
			t += "[\n";
			unsigned int count = 0;
			while (true)
			{
				auto iter = children.find(std::to_string(count));
				if (iter == children.end())
				{
					break;
				}
				for (unsigned int i = 0; i < tabDepth + 1; i++)
				{
					t += '\t';
				}
				iter->second.stringify(t, tabDepth + 1);
				count++;
			}
			for (unsigned int i = 0; i < tabDepth; i++)
			{
				t += '\t';
			}
			t += "]\n";
		}
		else if (type == String)
		{
			t += text;
			t += '\n';
		}
	}

	bool Config::hasChild(std::string const & key) const
	{
		return children.find(key) != children.end();
	}

	std::optional<Config const &> Config::operator [] (std::string const & key) const
	{
		auto it = children.find(key);
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config const &>();
	}

	std::optional<Config &> Config::operator [] (std::string & key)
	{
		auto it = children.find(key);
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config &>();
	}

	std::optional<Config const &> Config::operator [] (int index) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config const &>();
	}

	std::optional<Config &> Config::operator [] (int index)
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end())
		{
			return it->second;
		}
		return std::optional<Config &>();
	}

	void Config::parse(std::string const & content, size_t & i)
	{
		type = String;
		text.clear();
		children.clear();
		unsigned int c = 0;

		skipWhiteSpace(content, i);

		// Find out what type of value this is.
		c = getChar(content, i);

		if (c == '{') // Dictionary
		{
			type = Dictionary;
			while (i < content.size())
			{
				// Get Key
				std::string key;
				skipWhiteSpace(content, i);
				if (isStringNext(content, i, "}"))
				{
					i += 1;
					break;
				}

				key = trim(readUntilAny(content, i, " \t\n\r:"));

				skipWhiteSpace(content, i);
				c = getChar(content, i);
				if (c != ':')
				{
					throw std::runtime_error("Expected colon after character");
				}

				children[key].parse(content, i);
			}
		}
		else if (c == '[') // List
		{
			type = List;
			int count = 0;
			while (i < content.size())
			{
				skipWhiteSpace(content, i);
				if (isStringNext(content, i, "]"))
				{
					i += 1;
					break;
				}
				std::string key = std::to_string(count);
				children[key].parse(content, i);
				count++;
			}
		}
		else // String
		{
			type = String;
			std::string quoteStart;
			if (c == '"' || c == '\'' || c == '`') // Quote, grab all of same characters.
			{
				auto quoteC = c;
				do
				{
					quoteStart += getStringFromChar(c);
					c = getChar(content, i);
				} while (c == quoteC);
			}
			text += getStringFromChar(c);
			if (!quoteStart.empty())
			{
				text += readUntil(content, i, quoteStart);
				i += quoteStart.size();
			}
			else
			{
				text += readUntilAny(content, i, " \t\n\r}]");
			}
		}
	}

	template <> bool Config::getChildAs(std::string const & key, bool defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			if (it->second.text == "true") return true;
			if (it->second.text == "false") return false;
		}
		return defaultValue;
	}

	template <> int Config::getChildAs(std::string const & key, int defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stoi(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> float Config::getChildAs(std::string const & key, float defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stof(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> std::string Config::getChildAs(std::string const & key, std::string defaultValue) const
	{
		auto it = children.find(key);
		if (it != children.end() && it->second.type == String)
		{
			return it->second.text;
		}
		return defaultValue;
	}

	template <> bool Config::getChildAs(int index, bool defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			if (it->second.text == "true") return true;
			if (it->second.text == "false") return false;
		}
		return defaultValue;
	}

	template <> int Config::getChildAs(int index, int defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stoi(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> float Config::getChildAs(int index, float defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			try
			{
				return std::stof(it->second.text);
			}
			catch (...) {}
		}
		return defaultValue;
	}

	template <> std::string Config::getChildAs(int index, std::string defaultValue) const
	{
		auto it = children.find(std::to_string(index));
		if (it != children.end() && it->second.type == String)
		{
			return it->second.text;
		}
		return defaultValue;
	}
}<|endoftext|>


<commit_before>#include "geom2D.hpp"

namespace boom {
	namespace geo2d {
		Circle::Circle(const Vec2& c, float r): vCenter(c), fRadius(r) {}
		float Circle::bs_getArea() const {
			Assert(Trap, false, "not implemented yet") throw 0;
		}
		float Circle::bs_getInertia() const {
			Assert(Trap, false, "not implemented yet") throw 0;
		}
		const Vec2& Circle::bs_getCenter() const {
			return vCenter;
		}
		const Circle& Circle::bs_getBVolume() const {
			return *this;
		}
		Vec2 Circle::support(const Vec2& dir) const {
			return dir * fRadius + vCenter;
		}
		bool Circle::hit(const Vec2& pt, float t) const {
			return vCenter.dist_sq(pt) <= spn::Square(fRadius + t);
		}
		bool Circle::hit(const Circle& c, float t) const {
			return vCenter.dist_sq(c.vCenter) <= spn::Square(fRadius + c.fRadius + t);
		}
		bool Circle::hit(const Segment& s, float t) const {
			Vec2 np = s.nearest(vCenter).first;
			return np.dist_sq(vCenter) <= spn::Square(fRadius + t);
		}
		Circle Circle::operator * (const AMat32& m) const {
			auto& m2 = reinterpret_cast<const AMat22&>(m);
			Vec2 tx(vCenter + Vec2(fRadius,0)),
				ty(vCenter + Vec2(0,fRadius)),
				ori(vCenter);
			ori = ori.asVec3(1) * m;
			tx = tx * m2 - ori;
			ty = ty * m2 - ori;
			return Circle(ori,
						spn::Sqrt(std::max(tx.len_sq(), ty.len_sq())));
		}
		void Circle::setBoundary(const IModel* p) {
			*this = p->im_getBVolume();
		}
		void Circle::appendBoundary(const IModel* p) {
			Circle c2 = p->im_getBVolume();
			Vec2 toC2 = c2.vCenter - vCenter;
			float lensq = toC2.len_sq();
			if(lensq >= ZEROVEC_LENGTH_SQ) {
				toC2 *= spn::RSqrt(lensq);
				Vec2 tv(support(toC2) - c2.support(-toC2));
				float r_min = std::min(fRadius, c2.fRadius);
				if(tv.dot(toC2) < 0 ||
					tv.len_sq() < spn::Square(r_min*2))
				{
					// 新たな円を算出
					Vec2 tv0(vCenter - toC2*fRadius),
						 tv1(c2.vCenter + toC2*c2.fRadius);
					fRadius = tv0.distance(tv1) * .5f;
					vCenter = (tv0+tv1) * .5f;
				} else {
					// 円が内包されている
					if(fRadius < c2.fRadius) {
						fRadius = c2.fRadius;
						vCenter = c2.vCenter;
					}
				}
			} else {
				// 円の中心が同じ位置にある
				fRadius = std::max(c2.fRadius, fRadius);
			}
		}
		// 半径のみ倍率をかける
		Circle Circle::operator * (float s) const {
			return Circle(vCenter, fRadius*s);
		}
		std::ostream& operator << (std::ostream& os, const Circle& c) {
			return os << "Circle(2d) [ center: " << c.vCenter << std::endl
						<< "radius: " << c.fRadius << ']';
		}
	}
}
<commit_msg>Circle2D: operator * (AMat32)の修正<commit_after>#include "geom2D.hpp"

namespace boom {
	namespace geo2d {
		Circle::Circle(const Vec2& c, float r): vCenter(c), fRadius(r) {}
		float Circle::bs_getArea() const {
			Assert(Trap, false, "not implemented yet") throw 0;
		}
		float Circle::bs_getInertia() const {
			Assert(Trap, false, "not implemented yet") throw 0;
		}
		const Vec2& Circle::bs_getCenter() const {
			return vCenter;
		}
		const Circle& Circle::bs_getBVolume() const {
			return *this;
		}
		Vec2 Circle::support(const Vec2& dir) const {
			return dir * fRadius + vCenter;
		}
		bool Circle::hit(const Vec2& pt, float t) const {
			return vCenter.dist_sq(pt) <= spn::Square(fRadius + t);
		}
		bool Circle::hit(const Circle& c, float t) const {
			return vCenter.dist_sq(c.vCenter) <= spn::Square(fRadius + c.fRadius + t);
		}
		bool Circle::hit(const Segment& s, float t) const {
			Vec2 np = s.nearest(vCenter).first;
			return np.dist_sq(vCenter) <= spn::Square(fRadius + t);
		}
		Circle Circle::operator * (const AMat32& m) const {
			auto& m2 = reinterpret_cast<const AMat22&>(m);
			Vec2 tx(fRadius,0),
				ty(0,fRadius),
				ori(vCenter);
			ori = ori.asVec3(1) * m;
			tx = tx * m2;
			ty = ty * m2;
			return Circle(ori,
						spn::Sqrt(std::max(tx.len_sq(), ty.len_sq())));
		}
		void Circle::setBoundary(const IModel* p) {
			*this = p->im_getBVolume();
		}
		void Circle::appendBoundary(const IModel* p) {
			Circle c2 = p->im_getBVolume();
			Vec2 toC2 = c2.vCenter - vCenter;
			float lensq = toC2.len_sq();
			if(lensq >= ZEROVEC_LENGTH_SQ) {
				toC2 *= spn::RSqrt(lensq);
				Vec2 tv(support(toC2) - c2.support(-toC2));
				float r_min = std::min(fRadius, c2.fRadius);
				if(tv.dot(toC2) < 0 ||
					tv.len_sq() < spn::Square(r_min*2))
				{
					// 新たな円を算出
					Vec2 tv0(vCenter - toC2*fRadius),
						 tv1(c2.vCenter + toC2*c2.fRadius);
					fRadius = tv0.distance(tv1) * .5f;
					vCenter = (tv0+tv1) * .5f;
				} else {
					// 円が内包されている
					if(fRadius < c2.fRadius) {
						fRadius = c2.fRadius;
						vCenter = c2.vCenter;
					}
				}
			} else {
				// 円の中心が同じ位置にある
				fRadius = std::max(c2.fRadius, fRadius);
			}
		}
		// 半径のみ倍率をかける
		Circle Circle::operator * (float s) const {
			return Circle(vCenter, fRadius*s);
		}
		std::ostream& operator << (std::ostream& os, const Circle& c) {
			return os << "Circle(2d) [ center: " << c.vCenter << std::endl
						<< "radius: " << c.fRadius << ']';
		}
	}
}
<|endoftext|>


<commit_before>#include "test.h"

static const char *
formats[] = {
    "flv",
    "vp6_64",
    "vp6_576",
    "vp6_928",
    "h264_1400",
    "best",
    NULL
};

#define TEST_URL \
    "http://www.spiegel.de/video/video-1012584.html"

MAIN_BEGIN
    int i, rc;
    for (i=0,rc=0; formats[i] && !rc; ++i) {
        std::stringstream b;
        b << "-f " << formats[i];
        rc = runtest_host( TEST_URL, b.str() );
    }
    return(rc);
MAIN_END

<commit_msg>tests/spiegel: remove vp6_64.<commit_after>#include "test.h"

static const char *
formats[] = {
    "flv",
    "vp6_576",
    "vp6_928",
    "h264_1400",
    "best",
    NULL
};

#define TEST_URL \
    "http://www.spiegel.de/video/video-1012584.html"

MAIN_BEGIN
    int i, rc;
    for (i=0,rc=0; formats[i] && !rc; ++i) {
        std::stringstream b;
        b << "-f " << formats[i];
        rc = runtest_host( TEST_URL, b.str() );
    }
    return(rc);
MAIN_END

<|endoftext|>


<commit_before>#ifdef HAVE_CONFIG_H
#include "sys_config.h"
#endif

#include "arch/MGSystem.h"
#include "simreadline.h"
#include "commands.h"
#include "sim/config.h"

#ifdef ENABLE_MONITOR
# include "sim/monitor.h"
#endif

#include <sstream>
#include <iostream>
#include <limits>

#ifdef USE_SDL
#include <SDL.h>
#endif

using namespace Simulator;
using namespace std;

struct ProgramConfig
{
    string                           m_configFile;
    string                           m_symtableFile;
    bool                             m_enableMonitor;
    bool                             m_interactive;
    bool                             m_terminate;
    bool                             m_dumpconf;
    bool                             m_quiet;
    bool                             m_dumpvars;
    vector<string>                   m_printvars;
    bool                             m_earlyquit;
    vector<pair<string,string> >     m_overrides;
    vector<string>                   m_extradevs;
    vector<pair<RegAddr, string> >   m_loads;
    vector<pair<RegAddr, RegValue> > m_regs;
};

static void ParseArguments(int argc, const char ** argv, ProgramConfig& config)
{
    config.m_configFile = MGSIM_CONFIG_PATH;
    config.m_enableMonitor = false;
    config.m_interactive = false;
    config.m_terminate = false;
    config.m_dumpconf = false;
    config.m_quiet = false;
    config.m_dumpvars = false;
    config.m_earlyquit = false;

    for (int i = 1; i < argc; ++i)
    {
        const string arg = argv[i];
        if (arg[0] != '-')
        {
            cerr << "Warning: converting extra argument to -o *.ROMFileName=" << arg << endl;
            config.m_overrides.push_back(make_pair("*.ROMFileName", arg));
        }
        else if (arg == "-c" || arg == "--config")      config.m_configFile    = argv[++i];
        else if (arg == "-i" || arg == "--interactive") config.m_interactive   = true;
        else if (arg == "-t" || arg == "--terminate")   config.m_terminate     = true;
        else if (arg == "-q" || arg == "--quiet")       config.m_quiet         = true;
        else if (arg == "-s" || arg == "--symtable")    config.m_symtableFile  = argv[++i];
        else if (arg == "--version")                    { PrintVersion(std::cout); exit(0); }
        else if (arg == "-h" || arg == "--help")        { PrintUsage(std::cout, argv[0]); exit(0); }
        else if (arg == "-d" || arg == "--dump-configuration")    config.m_dumpconf      = true;
        else if (arg == "-m" || arg == "--monitor")     config.m_enableMonitor = true;
        else if (arg == "-l" || arg == "--list-mvars")  config.m_dumpvars      = true;
        else if (arg == "-p" || arg == "--print-final-mvars")
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected variable name");
            }
            config.m_printvars.push_back(argv[i]);
        }
        else if (arg == "-n" || arg == "--do-nothing")  config.m_earlyquit     = true;
        else if (arg == "-o" || arg == "--override")
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected configuration option");
            }
            string arg = argv[i];
            string::size_type eq = arg.find_first_of("=");
            if (eq == string::npos) {
                throw runtime_error("Error: malformed configuration override syntax: " + arg);
            }
            string name = arg.substr(0, eq);
            config.m_overrides.push_back(make_pair(name, arg.substr(eq + 1)));
        }
        else if (arg[1] == 'L')
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected filename");
            }
            string filename(argv[i]);
            string regnum(arg, 2, arg.size());
            char* endptr;
            unsigned long index = strtoul(regnum.c_str(), &endptr, 0);
            if (*endptr != '\0') {
                throw runtime_error("Error: invalid register specifier in option: " + arg);
            }
            RegAddr  regaddr = MAKE_REGADDR(RT_INTEGER, index);

            string devname = "file" + regnum;
            config.m_extradevs.push_back(devname);
            string cfgprefix = "*." + devname + ".";
            config.m_overrides.push_back(make_pair(cfgprefix + "Type", "AROM"));
            config.m_overrides.push_back(make_pair(cfgprefix + "ROMContentSource", "RAW"));
            config.m_overrides.push_back(make_pair(cfgprefix + "ROMFileName", filename));
            config.m_loads.push_back(make_pair(regaddr, "*." + devname));
        }
        else if (arg[1] == 'R' || arg[1] == 'F')
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected register value");
            }
            stringstream value;
            value << argv[i];

            RegAddr  addr;
            RegValue val;

            char* endptr;
            unsigned long index = strtoul(&arg[2], &endptr, 0);
            if (*endptr != '\0') {
                throw runtime_error("Error: invalid register specifier in option");
            }

            if (arg[1] == 'R') {
                value >> *(signed Integer*)&val.m_integer;
                addr = MAKE_REGADDR(RT_INTEGER, index);
            } else {
                double f;
                value >> f;
                val.m_float.fromfloat(f);
                addr = MAKE_REGADDR(RT_FLOAT, index);
            }
            if (value.fail()) {
                throw runtime_error("Error: invalid value for register");
            }
            val.m_state = RST_FULL;
            config.m_regs.push_back(make_pair(addr, val));
        }
    }

    if (config.m_quiet)
    {
        config.m_overrides.push_back(make_pair("*.ROMVerboseLoad", "false"));
    }
}

void PrintFinalVariables(const ProgramConfig& cfg)
{
    if (!cfg.m_printvars.empty())
    {
        std::cout << "### begin end-of-simulation variables" << std::endl;
        for (size_t i = 0; i < cfg.m_printvars.size(); ++i)
            ReadSampleVariables(cout, cfg.m_printvars[i]);
        std::cout << "### end end-of-simulation variables" << std::endl;
    }
}

#ifdef USE_SDL
extern "C"
#endif
int main(int argc, char** argv)
{
    srand(time(NULL));

    try
    {
        // Parse command line arguments
        ProgramConfig config;
        ParseArguments(argc, (const char**)argv, config);

        if (config.m_interactive)
        {
            // Interactive mode
            PrintVersion(std::cout);
        }

        // Read configuration
        Config configfile(config.m_configFile, config.m_overrides);

        // Create the system
        MGSystem sys(configfile,
                     config.m_symtableFile,
                     config.m_regs,
                     config.m_loads,
                     config.m_extradevs,
                     !config.m_interactive,
                     !config.m_earlyquit);

#ifdef ENABLE_MONITOR
        string mo_mdfile = configfile.getValue<string>("MonitorMetadataFile", "mgtrace.md");
        string mo_tfile = configfile.getValue<string>("MonitorTraceFile", "mgtrace.out");
        Monitor mo(sys, config.m_enableMonitor,
                   mo_mdfile, config.m_earlyquit ? "" : mo_tfile, !config.m_interactive);
#endif

        if (config.m_dumpconf)
        {
            std::clog << "### simulator version: " PACKAGE_VERSION << std::endl;
            configfile.dumpConfiguration(std::clog, config.m_configFile);
        }

        if (config.m_dumpvars)
        {
            std::cout << "### begin monitor variables" << std::endl;
            ListSampleVariables(std::cout);
            std::cout << "### end monitor variables" << std::endl;
        }

        if (config.m_earlyquit)
            exit(0);

        bool interactive = config.m_interactive;
        if (!interactive)
        {
            // Non-interactive mode; run and dump cycle count
            try
            {
#ifdef ENABLE_MONITOR
                mo.start();
#endif
                StepSystem(sys, INFINITE_CYCLES);
#ifdef ENABLE_MONITOR
                mo.stop();
#endif

                if (!config.m_quiet)
                {
                    clog << "### begin end-of-simulation statistics" << endl;
                    sys.PrintAllStatistics(clog);
                    clog << "### end end-of-simulation statistics" << endl;
                }
            }
            catch (const exception& e)
            {
#ifdef ENABLE_MONITOR
                mo.stop();
#endif
                if (config.m_terminate)
                {
                    // We do not want to go to interactive mode,
                    // rethrow so it abort the program.
                    PrintFinalVariables(config);
                    throw;
                }

                PrintException(cerr, e);

                // When we get an exception in non-interactive mode,
                // jump into interactive mode
                interactive = true;
            }
        }

        if (interactive)
        {
            // Command loop
            cout << endl;
            CommandLineReader clr;
            cli_context ctx = { clr, sys
#ifdef ENABLE_MONITOR
                                , mo
#endif
            };

            while (HandleCommandLine(ctx) == false)
                /* just loop */;
        }

        PrintFinalVariables(config);
    }
    catch (const exception& e)
    {
        PrintException(cerr, e);
        return 1;
    }

    return 0;
}
<commit_msg>[mgsim-refactor] Implement a command line option --dump-topology with its associated behavior.<commit_after>#ifdef HAVE_CONFIG_H
#include "sys_config.h"
#endif

#include "arch/MGSystem.h"
#include "simreadline.h"
#include "commands.h"
#include "sim/config.h"

#ifdef ENABLE_MONITOR
# include "sim/monitor.h"
#endif

#include <sstream>
#include <iostream>
#include <limits>

#ifdef USE_SDL
#include <SDL.h>
#endif

using namespace Simulator;
using namespace std;

struct ProgramConfig
{
    string                           m_configFile;
    string                           m_symtableFile;
    bool                             m_enableMonitor;
    bool                             m_interactive;
    bool                             m_terminate;
    bool                             m_dumpconf;
    bool                             m_quiet;
    bool                             m_dumpvars;
    vector<string>                   m_printvars;
    bool                             m_earlyquit;
    vector<pair<string,string> >     m_overrides;
    vector<string>                   m_extradevs;
    vector<pair<RegAddr, string> >   m_loads;
    vector<pair<RegAddr, RegValue> > m_regs;
    bool                             m_dumptopo;
    string                           m_topofile;
    bool                             m_dumpnodeprops;
    bool                             m_dumpedgeprops;
};

static void ParseArguments(int argc, const char ** argv, ProgramConfig& config)
{
    config.m_configFile = MGSIM_CONFIG_PATH;
    config.m_enableMonitor = false;
    config.m_interactive = false;
    config.m_terminate = false;
    config.m_dumpconf = false;
    config.m_quiet = false;
    config.m_dumpvars = false;
    config.m_earlyquit = false;
    config.m_dumptopo = false;
    config.m_dumpnodeprops = true;
    config.m_dumpedgeprops = true;

    for (int i = 1; i < argc; ++i)
    {
        const string arg = argv[i];
        if (arg[0] != '-')
        {
            cerr << "Warning: converting extra argument to -o *.ROMFileName=" << arg << endl;
            config.m_overrides.push_back(make_pair("*.ROMFileName", arg));
        }
        else if (arg == "-c" || arg == "--config")      config.m_configFile    = argv[++i];
        else if (arg == "-i" || arg == "--interactive") config.m_interactive   = true;
        else if (arg == "-t" || arg == "--terminate")   config.m_terminate     = true;
        else if (arg == "-q" || arg == "--quiet")       config.m_quiet         = true;
        else if (arg == "-s" || arg == "--symtable")    config.m_symtableFile  = argv[++i];
        else if (arg == "--version")                    { PrintVersion(std::cout); exit(0); }
        else if (arg == "-h" || arg == "--help")        { PrintUsage(std::cout, argv[0]); exit(0); }
        else if (arg == "-d" || arg == "--dump-configuration")    config.m_dumpconf      = true;
        else if (arg == "-m" || arg == "--monitor")     config.m_enableMonitor = true;
        else if (arg == "-l" || arg == "--list-mvars")  config.m_dumpvars      = true;
        else if (arg == "-p" || arg == "--print-final-mvars")
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected variable name");
            }
            config.m_printvars.push_back(argv[i]);
        }
        else if (arg == "-T" || arg == "--dump-topology")
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected file name");
            }
            config.m_dumptopo = true;
            config.m_topofile = argv[i];
        }
        else if (arg == "--no-node-properties") config.m_dumpnodeprops = false;
        else if (arg == "--no-edge-properties") config.m_dumpedgeprops = false;
        else if (arg == "-n" || arg == "--do-nothing")  config.m_earlyquit     = true;
        else if (arg == "-o" || arg == "--override")
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected configuration option");
            }
            string arg = argv[i];
            string::size_type eq = arg.find_first_of("=");
            if (eq == string::npos) {
                throw runtime_error("Error: malformed configuration override syntax: " + arg);
            }
            string name = arg.substr(0, eq);
            config.m_overrides.push_back(make_pair(name, arg.substr(eq + 1)));
        }
        else if (arg[1] == 'L')
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected filename");
            }
            string filename(argv[i]);
            string regnum(arg, 2, arg.size());
            char* endptr;
            unsigned long index = strtoul(regnum.c_str(), &endptr, 0);
            if (*endptr != '\0') {
                throw runtime_error("Error: invalid register specifier in option: " + arg);
            }
            RegAddr  regaddr = MAKE_REGADDR(RT_INTEGER, index);

            string devname = "file" + regnum;
            config.m_extradevs.push_back(devname);
            string cfgprefix = "*." + devname + ".";
            config.m_overrides.push_back(make_pair(cfgprefix + "Type", "AROM"));
            config.m_overrides.push_back(make_pair(cfgprefix + "ROMContentSource", "RAW"));
            config.m_overrides.push_back(make_pair(cfgprefix + "ROMFileName", filename));
            config.m_loads.push_back(make_pair(regaddr, "*." + devname));
        }
        else if (arg[1] == 'R' || arg[1] == 'F')
        {
            if (argv[++i] == NULL) {
                throw runtime_error("Error: expected register value");
            }
            stringstream value;
            value << argv[i];

            RegAddr  addr;
            RegValue val;

            char* endptr;
            unsigned long index = strtoul(&arg[2], &endptr, 0);
            if (*endptr != '\0') {
                throw runtime_error("Error: invalid register specifier in option");
            }

            if (arg[1] == 'R') {
                value >> *(signed Integer*)&val.m_integer;
                addr = MAKE_REGADDR(RT_INTEGER, index);
            } else {
                double f;
                value >> f;
                val.m_float.fromfloat(f);
                addr = MAKE_REGADDR(RT_FLOAT, index);
            }
            if (value.fail()) {
                throw runtime_error("Error: invalid value for register");
            }
            val.m_state = RST_FULL;
            config.m_regs.push_back(make_pair(addr, val));
        }
    }

    if (config.m_quiet)
    {
        config.m_overrides.push_back(make_pair("*.ROMVerboseLoad", "false"));
    }
}

void PrintFinalVariables(const ProgramConfig& cfg)
{
    if (!cfg.m_printvars.empty())
    {
        std::cout << "### begin end-of-simulation variables" << std::endl;
        for (size_t i = 0; i < cfg.m_printvars.size(); ++i)
            ReadSampleVariables(cout, cfg.m_printvars[i]);
        std::cout << "### end end-of-simulation variables" << std::endl;
    }
}

#ifdef USE_SDL
extern "C"
#endif
int main(int argc, char** argv)
{
    srand(time(NULL));

    try
    {
        // Parse command line arguments
        ProgramConfig config;
        ParseArguments(argc, (const char**)argv, config);

        if (config.m_interactive)
        {
            // Interactive mode
            PrintVersion(std::cout);
        }

        // Read configuration
        Config configfile(config.m_configFile, config.m_overrides);

        // Create the system
        MGSystem sys(configfile,
                     config.m_symtableFile,
                     config.m_regs,
                     config.m_loads,
                     config.m_extradevs,
                     !config.m_interactive,
                     !config.m_earlyquit);

#ifdef ENABLE_MONITOR
        string mo_mdfile = configfile.getValue<string>("MonitorMetadataFile", "mgtrace.md");
        string mo_tfile = configfile.getValue<string>("MonitorTraceFile", "mgtrace.out");
        Monitor mo(sys, config.m_enableMonitor,
                   mo_mdfile, config.m_earlyquit ? "" : mo_tfile, !config.m_interactive);
#endif

        if (config.m_dumpconf)
        {
            std::clog << "### simulator version: " PACKAGE_VERSION << std::endl;
            configfile.dumpConfiguration(std::clog, config.m_configFile);
        }

        if (config.m_dumpvars)
        {
            std::cout << "### begin monitor variables" << std::endl;
            ListSampleVariables(std::cout);
            std::cout << "### end monitor variables" << std::endl;
        }

        if (config.m_dumptopo)
        {
            ofstream of(config.m_topofile.c_str(), ios::out);
            configfile.dumpComponentGraph(of, config.m_dumpnodeprops, config.m_dumpedgeprops);
            of.close();
        }

        if (config.m_earlyquit)
            exit(0);

        bool interactive = config.m_interactive;
        if (!interactive)
        {
            // Non-interactive mode; run and dump cycle count
            try
            {
#ifdef ENABLE_MONITOR
                mo.start();
#endif
                StepSystem(sys, INFINITE_CYCLES);
#ifdef ENABLE_MONITOR
                mo.stop();
#endif

                if (!config.m_quiet)
                {
                    clog << "### begin end-of-simulation statistics" << endl;
                    sys.PrintAllStatistics(clog);
                    clog << "### end end-of-simulation statistics" << endl;
                }
            }
            catch (const exception& e)
            {
#ifdef ENABLE_MONITOR
                mo.stop();
#endif
                if (config.m_terminate)
                {
                    // We do not want to go to interactive mode,
                    // rethrow so it abort the program.
                    PrintFinalVariables(config);
                    throw;
                }

                PrintException(cerr, e);

                // When we get an exception in non-interactive mode,
                // jump into interactive mode
                interactive = true;
            }
        }

        if (interactive)
        {
            // Command loop
            cout << endl;
            CommandLineReader clr;
            cli_context ctx = { clr, sys
#ifdef ENABLE_MONITOR
                                , mo
#endif
            };

            while (HandleCommandLine(ctx) == false)
                /* just loop */;
        }

        PrintFinalVariables(config);
    }
    catch (const exception& e)
    {
        PrintException(cerr, e);
        return 1;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "net/TcpAcceptor.h"
#include "net/Socket.h"
#include "net/Channel.h"
#include "net/EventLoop.h"
#include "base/ZLog.h"
#include "net/ActiveSocket.h"
#include "net/InetAddress.h"
NAMESPACE_ZL_NET_START

TcpAcceptor::TcpAcceptor(EventLoop *loop, const InetAddress& listenAddr)
    : loop_(loop)
{
    accept_socket = new Socket(SocketUtil::createSocket());

    accept_socket->setNoDelay();
    accept_socket->setNonBlocking();

    if (!accept_socket->setReuseAddr(true))
    {
        throw SocketException("Could not reuse socket address.");
    }
    if (!accept_socket->bind(listenAddr))
    {
        throw SocketException("Could not bind to port.");
    }

    accept_channel_ = new Channel(loop, accept_socket->fd());
    accept_channel_->setReadCallback(std::bind(&TcpAcceptor::onAccept, this, std::placeholders::_1));
}

TcpAcceptor::~TcpAcceptor()
{
    accept_channel_->disableAll();
    accept_channel_->remove();
    Safe_Delete(accept_channel_);
    Safe_Delete(accept_socket);
}

void TcpAcceptor::listen()
{
    loop_->assertInLoopThread();
    if (!accept_socket->listen(128)) //may be bigger, see 'cat /proc/sys/net/core/somaxconn'
    {
        throw SocketException("Could not listen to port.");
    }
    LOG_INFO("TcpAcceptor::listen on [%s]", accept_socket->getHost().c_str());

    accept_channel_->enableReading();
}

void TcpAcceptor::onAccept(Timestamp now)
{
    loop_->assertInLoopThread();
    int count = 0;
    while(count < 100)
    {
        InetAddress peerAddr;
        ZL_SOCKET newfd = accept_socket->accept(&peerAddr);
        if(newfd > 0)
        {
            if (newConnCallBack_)
            {
                LOG_INFO("TcpAcceptor::OnAccept accept one client from[%d][%s]", newfd, peerAddr.ipPort().c_str());
                newConnCallBack_(newfd, peerAddr);
            }
            else
            {
                LOG_ALERT("TcpAcceptor::OnAccept() no callback , and close the coming connection![%d]", newfd);
				SocketUtil::closeSocket(newfd);
            }
            count ++;
        }
        else
        {
            if(errno == EAGAIN || errno == EWOULDBLOCK) //We have processed all incoming  connections.
            {

            }
            else
            {
                LOG_ALERT("TcpAcceptor::OnAccept() accept connection error![%d][%d]", newfd, errno);
            }
            //  11 : EAGAIN׽ִڷ״̬ǰû
            //	EBADFǷļ
            //	ECONNABORTEDжϡ
            //	EINTRϵͳñźжϡ
            //	EINVAL׽ûдڼ״̬Ƿaddrlen
            //	EMFILEﵽ̴ļơ
            //	ENFILEﵽļơ
            //	ENOTSOCKļΪļļ
            //	EOPNOTSUPP׽ͲSOCK_STREAM
            break;
        }
    }
}

NAMESPACE_ZL_NET_END
<commit_msg>[TODO] accept时达到进程能打开的最大描述时导致的loop busy问题<commit_after>#include "net/TcpAcceptor.h"
#include "net/Socket.h"
#include "net/Channel.h"
#include "net/EventLoop.h"
#include "base/ZLog.h"
#include "net/ActiveSocket.h"
#include "net/InetAddress.h"
NAMESPACE_ZL_NET_START

TcpAcceptor::TcpAcceptor(EventLoop *loop, const InetAddress& listenAddr)
    : loop_(loop)
{
    accept_socket = new Socket(SocketUtil::createSocket());

    accept_socket->setNoDelay();
    accept_socket->setNonBlocking();

    if (!accept_socket->setReuseAddr(true))
    {
        throw SocketException("Could not reuse socket address.");
    }
    if (!accept_socket->bind(listenAddr))
    {
        throw SocketException("Could not bind to port.");
    }

    accept_channel_ = new Channel(loop, accept_socket->fd());
    accept_channel_->setReadCallback(std::bind(&TcpAcceptor::onAccept, this, std::placeholders::_1));
}

TcpAcceptor::~TcpAcceptor()
{
    accept_channel_->disableAll();
    accept_channel_->remove();
    Safe_Delete(accept_channel_);
    Safe_Delete(accept_socket);
}

void TcpAcceptor::listen()
{
    loop_->assertInLoopThread();
    if (!accept_socket->listen(128)) //may be bigger, see 'cat /proc/sys/net/core/somaxconn'
    {
        throw SocketException("Could not listen to port.");
    }
    LOG_INFO("TcpAcceptor::listen on [%s]", accept_socket->getHost().c_str());

    accept_channel_->enableReading();
}

void TcpAcceptor::onAccept(Timestamp now)
{
    loop_->assertInLoopThread();
    int count = 0;
    while(count < 100)
    {
        InetAddress peerAddr;
        ZL_SOCKET newfd = accept_socket->accept(&peerAddr);
        if(newfd > 0)
        {
            if (newConnCallBack_)
            {
                LOG_INFO("TcpAcceptor::OnAccept accept one client from[%d][%s]", newfd, peerAddr.ipPort().c_str());
                newConnCallBack_(newfd, peerAddr);
            }
            else
            {
                LOG_ALERT("TcpAcceptor::OnAccept() no callback , and close the coming connection![%d]", newfd);
                SocketUtil::closeSocket(newfd);
            }
            count ++;
        }
        else
        {
            if(SOCKET_ERROR == SOCK_ERR_EAGAIN || SOCKET_ERROR == SOCK_ERR_EWOULDBLOCK)
            {
                //We have processed all incoming  connections.
            }
            else if(SOCKET_ERROR == SOCK_ERR_EMFILE)
            {
                // TODO ʱΪﵽļʧܣΪpollerʹõˮƽģʽ
                // ᵼpoller֪ͨɶ¼acceptorƵȥacceptֱйر
                // ӶпֹͣᵼCPU 100% loop
                //   http://blog.csdn.net/solstice/article/details/6365666
                // http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem_of_accept_ing_wh
            }
            else
            {
                LOG_ALERT("TcpAcceptor::OnAccept() accept connection error![%d][%d]", newfd, errno);
            }
            break;
        }
    }
}

NAMESPACE_ZL_NET_END
<|endoftext|>