<commit_before>
#include <SkynetClient.h>

// #include <WiFi.h>
// WiFiClient client;

#include <Ethernet.h>
EthernetClient client;

#define TOKEN_STRING(js, t, s) \
	(strncmp(js+(t).start, s, (t).end - (t).start) == 0 \
	 && strlen(s) == (t).end - (t).start)

struct ring_buffer
{
  unsigned char buffer[SKYNET_BUFFER_SIZE];
  volatile unsigned int head;
  volatile unsigned int tail;
};

ring_buffer socket_rx_buffer =    { { 0 }, 0, 0};

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SKYNET_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
}

SkynetClient::SkynetClient(){
}

int SkynetClient::connect(const char* host, uint16_t port) {
	IPAddress remote_addr;
	if (WiFi.hostByName(host, remote_addr))
	{
		return connect(remote_addr, port);
	}
}

int SkynetClient::connect(IPAddress ip, uint16_t port) {

	_rx_buffer = &socket_rx_buffer;
	theip = ip;

	//connect tcp or fail
	if (!client.connect(theip, port))
		return false;

	//establish socket or fail
	sendHandshake();
	if(!readHandshake()){
		stop();
		return false;
	}

	//monitor to initiate communications with skynet TODO some fail condition
	while(!status)
		monitor();

	return status;
}

uint8_t SkynetClient::connected() {
  return status;
}

void SkynetClient::stop() {
	status = 0;
	client.stop();
}

//dump until peek is not a colon
void SkynetClient::dump(){
	if(!client.available())
		return;

	DBGC(F("Dumping: "));
	do{
		char c = client.read();
		DBGC(c);
	}while ( client.available() && client.peek() == ':' );
	DBGCN("");
}

//eg on first connect:
//1::ÿ5:::{"name":"identify","args":[{"socketid":"zb2gh9TSVZ-eyUf8YZ_4"}]}ÿ
// or after 2::ÿ or:
//5:::{"name":"identify","args":[{"socketid":"zb2gh9TSVZ-eyUf8YZ_4"}]}ÿ
void SkynetClient::monitor()
{
	char which = 0;

	if(client.available()){
		which = client.read();
	}else{
		return;
	}

	switch (which) {
		//disconnect
		case '0':
			DBGCN(F("Disconnect"));
			stop();
			break;

		//messages
		case '1':
			DBGCN(F("Socket Connect"));
			break;

		case '3':
		case '5':
			DBGCN(F("Message"));
			dump();
			process();
			break;

		//hearbeat
		case '2':
			client.print((char)0);
			client.print(F("2::"));
			client.print((char)255);
			DBGCN(F("Heartbeat"));
			break;

	    //huh?
		default:
			DBGC(F("Drop: "));
			DBGCN(which);
			break;
	}
}

void SkynetClient::process()
{
	DBGCN(F("Processing Message"));
    if (client.available()) {

	int size = readLine();

	jsmn_parser p;
	jsmntok_t tok[255];

	jsmn_init(&p);

	int r = jsmn_parse(&p, databuffer, tok, 255);
	if (r != 0){
	    DBGCN(F("parse failed"));
		DBGCN(r);
		return;
	}

    if (TOKEN_STRING(databuffer, tok[2], IDENTIFY ))
    {
		DBGCN(F(IDENTIFY));
	    DBGC(F("Sending: "));

	    DBGC((char)0);
		client.print((char)0);

	    DBGC(EMIT);
		client.print(EMIT);

		printByByte("{\"name\":\"identity\",\"args\":[{\"socketid\":\"");
		printToken(databuffer, tok[7]);

		if( eeprom_read_byte( (uint8_t*)EEPROMBLOCKADDRESS) == EEPROMBLOCK )
		{
			eeprom_read_bytes(token, TOKENADDRESS, TOKENSIZE);
			token[TOKENSIZE-1]='\0'; //in case courrupted or not defined

			eeprom_read_bytes(uuid, UUIDADDRESS, UUIDSIZE);
			uuid[UUIDSIZE-1]='\0'; //in case courrupted or not defined

			printByByte("\", \"uuid\":\"");
			printByByte(uuid);

			printByByte("\", \"token\":\"");
			printByByte(token);
		}
		printByByte("\"}]}");

		DBGCN((char)255);
		client.print((char)255);
    }
    else if (TOKEN_STRING(databuffer, tok[2], READY ))
    {
		DBGCN(READY);
		status = 1;

        eeprom_read_bytes(token, TOKENADDRESS, TOKENSIZE);
        token[TOKENSIZE-1]='\0'; //in case courrupted or not defined

        //if token has been refreshed, save it
        if (TOKEN_STRING(databuffer, tok[15], token ))
        {
			DBGCN(F("token refresh"));
		  	strncpy(token, databuffer + tok[15].start, tok[15].end - tok[15].start);

            DBGC(F("new: "));
          	DBGCN(token);

		  	eeprom_write_bytes(token, TOKENADDRESS, TOKENSIZE);

			//write block identifier, arduino should protect us from writing if it doesnt need it?
          	eeprom_write_byte((uint8_t *)EEPROMBLOCKADDRESS, (uint8_t)EEPROMBLOCK);

        }else
        {
			DBGCN(F("no token refresh necessary"));
        }

		eeprom_read_bytes(uuid, UUIDADDRESS, UUIDSIZE);
        uuid[UUIDSIZE-1]='\0'; //in case courrupted or not defined

        //if uuid has been refreshed, save it
        if (TOKEN_STRING(databuffer, tok[13], uuid ))
        {
          	DBGCN(F("uuid refresh"));
			strncpy(uuid, databuffer + tok[13].start, tok[13].end - tok[13].start);

          	DBGC(F("new: "));
          	DBGCN(uuid);

          	eeprom_write_bytes(uuid, UUIDADDRESS, UUIDSIZE);

			//write block identifier, arduino should protect us from writing if it doesnt need it?
          	eeprom_write_byte((uint8_t *)EEPROMBLOCKADDRESS, (uint8_t)EEPROMBLOCK);

         }else
         {
           	DBGCN(F("no uuid refresh necessary"));
         }

    }
    else if (TOKEN_STRING(databuffer, tok[2], NOTREADY ))
    {
		//send blank identify
		DBGCN(NOTREADY);

		printByByte("{\"name\":\"identity\",\"args\":[{\"socketid\":\"");
		printToken(databuffer, tok[7]);
		printByByte("\"}]}");
    }
    else if (TOKEN_STRING(databuffer, tok[2], MESSAGE ))
    {
		DBGCN(MESSAGE);

		DBGCN("Storing: ");
	    for(int i = tok[9].start; i < tok[9].end; i++)
	    {
			DBGC(databuffer[i]);
        	store_char( databuffer[i], &socket_rx_buffer);
	    }
		DBGCN("");

		if (messageDelegate != NULL) {
			messageDelegate(databuffer);
		}
    }
    else
    {
		DBGC(F("Unknown:"));
    }
  }
}

void SkynetClient::sendHandshake() {
	client.println(F("GET /socket.io/1/ HTTP/1.1"));
	client.print(F("Host: "));
	client.println(theip);
	client.println(F("Origin: Arduino\r\n"));
}

bool SkynetClient::waitForInput(void) {
	unsigned long now = millis();
	while (!client.available() && ((millis() - now) < 30000UL)) {;}
	return client.available();
}

void SkynetClient::eatHeader(void) {
	while (client.available()) {	// consume the header
		readLine();
		if (strlen(databuffer) == 0) break;
	}
}

int SkynetClient::readHandshake() {

	if (!waitForInput()) return false;

	// check for happy "HTTP/1.1 200" response
	readLine();
	if (atoi(&databuffer[8]) != 200) {
		while (client.available()) readLine();
		client.stop();
		return 0;
	}
	eatHeader();
	readLine();	// read first line of response
	readLine();	// read sid : transport : timeout

	char *iptr = databuffer;
	char *optr = sid;
	while (*iptr && (*iptr != ':') && (optr < &sid[SID_LEN-2])) *optr++ = *iptr++;
	*optr = 0;

	DBGC(F("Connected. SID="));
	DBGCN(sid);	// sid:transport:timeout

	while (client.available()) readLine();

	client.print(F("GET /socket.io/1/websocket/"));
	client.print(sid);
	client.println(F(" HTTP/1.1"));
	client.print(F("Host: "));
	client.println(theip);
	client.println(F("Origin: ArduinoSkynetClient"));
	client.println(F("Upgrade: WebSocket"));	// must be camelcase ?!
	client.println(F("Connection: Upgrade\r\n"));

	if (!waitForInput()) return 0;

	readLine();
	if (atoi(&databuffer[8]) != 101) {
		while (client.available()) readLine();
		client.stop();
		return false;
	}
	eatHeader();
	monitor();		// treat the response as input
	return 1;
}

int SkynetClient::readLine() {
	int numBytes = 0;
	dataptr = databuffer;
	DBGC(F("Readline: "));
	while (client.available() && (dataptr < &databuffer[DATA_BUFFER_LEN-2])) {
		char c = client.read();
		if (c == 0){
			;
		}else if (c == -1){
			;
		}else if (c == 255){
			;
		}else if (c == '\r') {
			;
		}else if (c == '\n')
			break;
		else {
			DBGC(c);
			*dataptr++ = c;
			numBytes++;
		}
	}
	DBGCN();
	*dataptr = 0;
	return numBytes;
}

//wifi client.print has a buffer that so far we've been unable to locate
//under 154 (our identify size) for sure.. so sending char by char for now
void SkynetClient::printByByte(char *data) {
	int i = 0;
	while ( data[i] != '\0' )
	{
	    DBGC(data[i]);
		client.print(data[i++]);
	}
}

void SkynetClient::printToken(char *js, jsmntok_t t)
{
	int i = 0;
	for(i = t.start; i < t.end; i++) {
	    DBGC(js[i]);
		client.print(js[i]);
	 }
}

size_t SkynetClient::write(const uint8_t *buf, size_t size) {
    DBGC(F("Sending: "));

    DBGC((char)0);
	client.print((char)0);

    DBGC(EMIT);
	client.print(EMIT);

	//wifi client.print has a buffer that so far we've been unable to locate
	//under 154 (our identify size) for sure.. so sending char by char for now
	int i = 0;
	while ( i < size )
	{
	    DBGC(buf[i]);
		client.print(buf[i++]);
	}

    DBGCN((char)255);
	client.print((char)255);
}

int SkynetClient::available() {
  return (unsigned int)(SKYNET_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SKYNET_BUFFER_SIZE
	  ;
}

int SkynetClient::read() {
    // if the head isn't ahead of the tail, we don't have any characters
    if (_rx_buffer->head == _rx_buffer->tail) {
      return -1;
    } else {
      unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
      _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SKYNET_BUFFER_SIZE;
      return c;
    }
}

// //TODO
// int SkynetClient::read(uint8_t *buf, size_t size) {
// }

int SkynetClient::peek() {
    if (_rx_buffer->head == _rx_buffer->tail) {
      return -1;
    } else {
      return _rx_buffer->buffer[_rx_buffer->tail];
    }
}

void SkynetClient::flush() {
	client.flush();
}

// the next function allows us to use the client returned by
// SkynetClient::available() as the condition in an if-statement.

SkynetClient::operator bool() {
  return true;
}

void SkynetClient::setMessageDelegate(MessageDelegate newMessageDelegate) {
	  messageDelegate = newMessageDelegate;
}

void SkynetClient::eeprom_write_bytes(char *buf, int address, int bufSize){
  for(int i = 0; i<bufSize; i++){
    EEPROM.write(address+i, buf[i]);
  }
}

void SkynetClient::eeprom_read_bytes(char *buf, int address, int bufSize){
  for(int i = 0; i<bufSize; i++){
    buf[i] = EEPROM.read(address+i);
  }
}

void SkynetClient::sendMessage(char device[], char object[])
{
    DBGC(F("Sending: "));

    DBGC((char)0);
	client.print((char)0);

    DBGC(EMIT);
	client.print(EMIT);

	printByByte("{\"name\":\"message\",\"args\":[{\"devices\":\"");
	printByByte(device);
	printByByte("\",\"payload\":\"");
	printByByte(object);
	printByByte("\"}]}");

    DBGCN((char)255);
	client.print((char)255);
}<commit_msg>fix and confirm eeprom update from 882b312c105b43f23cbf7c2931e9bf143af96ed8<commit_after>
#include <SkynetClient.h>

// #include <WiFi.h>
// WiFiClient client;

#include <Ethernet.h>
EthernetClient client;

#define TOKEN_STRING(js, t, s) \
	(strncmp(js+(t).start, s, (t).end - (t).start) == 0 \
	 && strlen(s) == (t).end - (t).start)

struct ring_buffer
{
  unsigned char buffer[SKYNET_BUFFER_SIZE];
  volatile unsigned int head;
  volatile unsigned int tail;
};

ring_buffer socket_rx_buffer =    { { 0 }, 0, 0};

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SKYNET_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
}

SkynetClient::SkynetClient(){
}

int SkynetClient::connect(const char* host, uint16_t port) {
	IPAddress remote_addr;
	if (WiFi.hostByName(host, remote_addr))
	{
		return connect(remote_addr, port);
	}
}

int SkynetClient::connect(IPAddress ip, uint16_t port) {

	_rx_buffer = &socket_rx_buffer;
	theip = ip;

	//connect tcp or fail
	if (!client.connect(theip, port))
		return false;

	//establish socket or fail
	sendHandshake();
	if(!readHandshake()){
		stop();
		return false;
	}

	//monitor to initiate communications with skynet TODO some fail condition
	while(!status)
		monitor();

	return status;
}

uint8_t SkynetClient::connected() {
  return status;
}

void SkynetClient::stop() {
	status = 0;
	client.stop();
}

//dump until peek is not a colon
void SkynetClient::dump(){
	if(!client.available())
		return;

	DBGC(F("Dumping: "));
	do{
		char c = client.read();
		DBGC(c);
	}while ( client.available() && client.peek() == ':' );
	DBGCN("");
}

//eg on first connect:
//1::ÿ5:::{"name":"identify","args":[{"socketid":"zb2gh9TSVZ-eyUf8YZ_4"}]}ÿ
// or after 2::ÿ or:
//5:::{"name":"identify","args":[{"socketid":"zb2gh9TSVZ-eyUf8YZ_4"}]}ÿ
void SkynetClient::monitor()
{
	char which = 0;

	if(client.available()){
		which = client.read();
	}else{
		return;
	}

	switch (which) {
		//disconnect
		case '0':
			DBGCN(F("Disconnect"));
			stop();
			break;

		//messages
		case '1':
			DBGCN(F("Socket Connect"));
			break;

		case '3':
		case '5':
			DBGCN(F("Message"));
			dump();
			process();
			break;

		//hearbeat
		case '2':
			client.print((char)0);
			client.print(F("2::"));
			client.print((char)255);
			DBGCN(F("Heartbeat"));
			break;

	    //huh?
		default:
			DBGC(F("Drop: "));
			DBGCN(which);
			break;
	}
}

void SkynetClient::process()
{
	DBGCN(F("Processing Message"));
    if (client.available()) {

	int size = readLine();

	jsmn_parser p;
	jsmntok_t tok[255];

	jsmn_init(&p);

	int r = jsmn_parse(&p, databuffer, tok, 255);
	if (r != 0){
	    DBGCN(F("parse failed"));
		DBGCN(r);
		return;
	}

    if (TOKEN_STRING(databuffer, tok[2], IDENTIFY ))
    {
		DBGCN(F(IDENTIFY));
	    DBGC(F("Sending: "));

	    DBGC((char)0);
		client.print((char)0);

	    DBGC(EMIT);
		client.print(EMIT);

		printByByte("{\"name\":\"identity\",\"args\":[{\"socketid\":\"");
		printToken(databuffer, tok[7]);

		if( eeprom_read_byte( (uint8_t*)EEPROMBLOCKADDRESS) == EEPROMBLOCK )
		{
			eeprom_read_bytes(token, TOKENADDRESS, TOKENSIZE);
			token[TOKENSIZE-1]='\0'; //in case courrupted or not defined

			eeprom_read_bytes(uuid, UUIDADDRESS, UUIDSIZE);
			uuid[UUIDSIZE-1]='\0'; //in case courrupted or not defined

			printByByte("\", \"uuid\":\"");
			printByByte(uuid);

			printByByte("\", \"token\":\"");
			printByByte(token);
		}
		printByByte("\"}]}");

		DBGCN((char)255);
		client.print((char)255);
    }
    else if (TOKEN_STRING(databuffer, tok[2], READY ))
    {
		DBGCN(READY);
		status = 1;

        eeprom_read_bytes(token, TOKENADDRESS, TOKENSIZE);
        token[TOKENSIZE-1]='\0'; //in case courrupted or not defined

        //if token has been refreshed, save it
        if (!TOKEN_STRING(databuffer, tok[15], token ))
        {
			DBGCN(F("token refresh"));
		  	strncpy(token, databuffer + tok[15].start, tok[15].end - tok[15].start);

            DBGC(F("new: "));
          	DBGCN(token);

		  	eeprom_write_bytes(token, TOKENADDRESS, TOKENSIZE);

			//write block identifier, arduino should protect us from writing if it doesnt need it?
          	eeprom_write_byte((uint8_t *)EEPROMBLOCKADDRESS, (uint8_t)EEPROMBLOCK);

        }else
        {
			DBGCN(F("no token refresh necessary"));
        }

		eeprom_read_bytes(uuid, UUIDADDRESS, UUIDSIZE);
        uuid[UUIDSIZE-1]='\0'; //in case courrupted or not defined

        //if uuid has been refreshed, save it
        if (!TOKEN_STRING(databuffer, tok[13], uuid ))
        {
          	DBGCN(F("uuid refresh"));
			strncpy(uuid, databuffer + tok[13].start, tok[13].end - tok[13].start);

          	DBGC(F("new: "));
          	DBGCN(uuid);

          	eeprom_write_bytes(uuid, UUIDADDRESS, UUIDSIZE);

			//write block identifier, arduino should protect us from writing if it doesnt need it?
          	eeprom_write_byte((uint8_t *)EEPROMBLOCKADDRESS, (uint8_t)EEPROMBLOCK);

         }else
         {
           	DBGCN(F("no uuid refresh necessary"));
         }

    }
    else if (TOKEN_STRING(databuffer, tok[2], NOTREADY ))
    {
		//send blank identify
		DBGCN(NOTREADY);

		printByByte("{\"name\":\"identity\",\"args\":[{\"socketid\":\"");
		printToken(databuffer, tok[7]);
		printByByte("\"}]}");
    }
    else if (TOKEN_STRING(databuffer, tok[2], MESSAGE ))
    {
		DBGCN(MESSAGE);

		DBGCN("Storing: ");
	    for(int i = tok[9].start; i < tok[9].end; i++)
	    {
			DBGC(databuffer[i]);
        	store_char( databuffer[i], &socket_rx_buffer);
	    }
		DBGCN("");

		if (messageDelegate != NULL) {
			messageDelegate(databuffer);
		}
    }
    else
    {
		DBGC(F("Unknown:"));
    }
  }
}

void SkynetClient::sendHandshake() {
	client.println(F("GET /socket.io/1/ HTTP/1.1"));
	client.print(F("Host: "));
	client.println(theip);
	client.println(F("Origin: Arduino\r\n"));
}

bool SkynetClient::waitForInput(void) {
	unsigned long now = millis();
	while (!client.available() && ((millis() - now) < 30000UL)) {;}
	return client.available();
}

void SkynetClient::eatHeader(void) {
	while (client.available()) {	// consume the header
		readLine();
		if (strlen(databuffer) == 0) break;
	}
}

int SkynetClient::readHandshake() {

	if (!waitForInput()) return false;

	// check for happy "HTTP/1.1 200" response
	readLine();
	if (atoi(&databuffer[8]) != 200) {
		while (client.available()) readLine();
		client.stop();
		return 0;
	}
	eatHeader();
	readLine();	// read first line of response
	readLine();	// read sid : transport : timeout

	char *iptr = databuffer;
	char *optr = sid;
	while (*iptr && (*iptr != ':') && (optr < &sid[SID_LEN-2])) *optr++ = *iptr++;
	*optr = 0;

	DBGC(F("Connected. SID="));
	DBGCN(sid);	// sid:transport:timeout

	while (client.available()) readLine();

	client.print(F("GET /socket.io/1/websocket/"));
	client.print(sid);
	client.println(F(" HTTP/1.1"));
	client.print(F("Host: "));
	client.println(theip);
	client.println(F("Origin: ArduinoSkynetClient"));
	client.println(F("Upgrade: WebSocket"));	// must be camelcase ?!
	client.println(F("Connection: Upgrade\r\n"));

	if (!waitForInput()) return 0;

	readLine();
	if (atoi(&databuffer[8]) != 101) {
		while (client.available()) readLine();
		client.stop();
		return false;
	}
	eatHeader();
	monitor();		// treat the response as input
	return 1;
}

int SkynetClient::readLine() {
	int numBytes = 0;
	dataptr = databuffer;
	DBGC(F("Readline: "));
	while (client.available() && (dataptr < &databuffer[DATA_BUFFER_LEN-2])) {
		char c = client.read();
		if (c == 0){
			;
		}else if (c == -1){
			;
		}else if (c == 255){
			;
		}else if (c == '\r') {
			;
		}else if (c == '\n')
			break;
		else {
			DBGC(c);
			*dataptr++ = c;
			numBytes++;
		}
	}
	DBGCN();
	*dataptr = 0;
	return numBytes;
}

//wifi client.print has a buffer that so far we've been unable to locate
//under 154 (our identify size) for sure.. so sending char by char for now
void SkynetClient::printByByte(char *data) {
	int i = 0;
	while ( data[i] != '\0' )
	{
	    DBGC(data[i]);
		client.print(data[i++]);
	}
}

void SkynetClient::printToken(char *js, jsmntok_t t)
{
	int i = 0;
	for(i = t.start; i < t.end; i++) {
	    DBGC(js[i]);
		client.print(js[i]);
	 }
}

size_t SkynetClient::write(const uint8_t *buf, size_t size) {
    DBGC(F("Sending: "));

    DBGC((char)0);
	client.print((char)0);

    DBGC(EMIT);
	client.print(EMIT);

	//wifi client.print has a buffer that so far we've been unable to locate
	//under 154 (our identify size) for sure.. so sending char by char for now
	int i = 0;
	while ( i < size )
	{
	    DBGC(buf[i]);
		client.print(buf[i++]);
	}

    DBGCN((char)255);
	client.print((char)255);
}

int SkynetClient::available() {
  return (unsigned int)(SKYNET_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SKYNET_BUFFER_SIZE
	  ;
}

int SkynetClient::read() {
    // if the head isn't ahead of the tail, we don't have any characters
    if (_rx_buffer->head == _rx_buffer->tail) {
      return -1;
    } else {
      unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
      _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SKYNET_BUFFER_SIZE;
      return c;
    }
}

// //TODO
// int SkynetClient::read(uint8_t *buf, size_t size) {
// }

int SkynetClient::peek() {
    if (_rx_buffer->head == _rx_buffer->tail) {
      return -1;
    } else {
      return _rx_buffer->buffer[_rx_buffer->tail];
    }
}

void SkynetClient::flush() {
	client.flush();
}

// the next function allows us to use the client returned by
// SkynetClient::available() as the condition in an if-statement.

SkynetClient::operator bool() {
  return true;
}

void SkynetClient::setMessageDelegate(MessageDelegate newMessageDelegate) {
	  messageDelegate = newMessageDelegate;
}

void SkynetClient::eeprom_write_bytes(char *buf, int address, int bufSize){
  for(int i = 0; i<bufSize; i++){
    EEPROM.write(address+i, buf[i]);
  }
}

void SkynetClient::eeprom_read_bytes(char *buf, int address, int bufSize){
  for(int i = 0; i<bufSize; i++){
    buf[i] = EEPROM.read(address+i);
  }
}

void SkynetClient::sendMessage(char device[], char object[])
{
    DBGC(F("Sending: "));

    DBGC((char)0);
	client.print((char)0);

    DBGC(EMIT);
	client.print(EMIT);

	printByByte("{\"name\":\"message\",\"args\":[{\"devices\":\"");
	printByByte(device);
	printByByte("\",\"payload\":\"");
	printByByte(object);
	printByByte("\"}]}");

    DBGCN((char)255);
	client.print((char)255);
}<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/capturer_mac.h"

#include <stddef.h>

#include <OpenGL/CGLMacro.h>

namespace remoting {

CapturerMac::CapturerMac(MessageLoop* message_loop)
    : Capturer(message_loop),
      cgl_context_(NULL) {
  // TODO(dmaclach): move this initialization out into session_manager,
  // or at least have session_manager call into here to initialize it.
  CGError err =
      CGRegisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback,
                                      this);
  DCHECK_EQ(err, kCGErrorSuccess);
  err = CGScreenRegisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback,
                                     this);
  DCHECK_EQ(err, kCGErrorSuccess);
  err = CGDisplayRegisterReconfigurationCallback(
      CapturerMac::DisplaysReconfiguredCallback, this);
  DCHECK_EQ(err, kCGErrorSuccess);
  ScreenConfigurationChanged();
}

CapturerMac::~CapturerMac() {
  ReleaseBuffers();
  CGUnregisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, this);
  CGScreenUnregisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback, this);
  CGDisplayRemoveReconfigurationCallback(
      CapturerMac::DisplaysReconfiguredCallback, this);
}

void CapturerMac::ReleaseBuffers() {
  if (cgl_context_) {
    CGLDestroyContext(cgl_context_);
    cgl_context_ = NULL;
  }
}

void CapturerMac::ScreenConfigurationChanged() {
  ReleaseBuffers();
  CGDirectDisplayID mainDevice = CGMainDisplayID();

  width_ = CGDisplayPixelsWide(mainDevice);
  height_ = CGDisplayPixelsHigh(mainDevice);
  pixel_format_ = media::VideoFrame::RGB32;
  bytes_per_row_ = width_ * sizeof(uint32_t);
  size_t buffer_size = height() * bytes_per_row_;
  for (int i = 0; i < kNumBuffers; ++i) {
    buffers_[i].reset(new uint8[buffer_size]);
  }
  CGLPixelFormatAttribute attributes[] = {
    kCGLPFAFullScreen,
    kCGLPFADisplayMask,
    (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice),
    (CGLPixelFormatAttribute)0
  };
  CGLPixelFormatObj pixel_format = NULL;
  GLint matching_pixel_format_count = 0;
  CGLError err = CGLChoosePixelFormat(attributes,
                                      &pixel_format,
                                      &matching_pixel_format_count);
  DCHECK_EQ(err, kCGLNoError);
  err = CGLCreateContext(pixel_format, NULL, &cgl_context_);
  DCHECK_EQ(err, kCGLNoError);
  CGLDestroyPixelFormat(pixel_format);
  CGLSetFullScreen(cgl_context_);
  CGLSetCurrentContext(cgl_context_);
}

void CapturerMac::CalculateInvalidRects() {
  // Since the Mac gets its list of invalid rects via calls to InvalidateRect(),
  // this step only needs to perform post-processing optimizations on the rect
  // list (if needed).
}

void CapturerMac::CaptureRects(const InvalidRects& rects,
                               CaptureCompletedCallback* callback) {
  // TODO(dmaclach): something smarter here in the future.
  gfx::Rect dirtyRect;
  for (InvalidRects::const_iterator i = rects.begin(); i != rects.end(); ++i) {
    dirtyRect = dirtyRect.Union(*i);
  }

  CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
  glReadBuffer(GL_FRONT);
  glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);

  glPixelStorei(GL_PACK_ALIGNMENT, 4);  // Force 4-byte alignment.
  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

  // Read a block of pixels from the frame buffer.
  glReadPixels(0, 0, width(), height(), GL_BGRA, GL_UNSIGNED_BYTE,
               buffers_[current_buffer_].get());
  glPopClientAttrib();

  DataPlanes planes;
  planes.data[0] = buffers_[current_buffer_].get();
  planes.strides[0] = bytes_per_row_;

  scoped_refptr<CaptureData> data(new CaptureData(planes,
                                                  width(),
                                                  height(),
                                                  pixel_format()));
  data->mutable_dirty_rects().clear();
  data->mutable_dirty_rects().insert(dirtyRect);
  FinishCapture(data, callback);
}

void CapturerMac::ScreenRefresh(CGRectCount count, const CGRect *rect_array) {
  InvalidRects rects;
  for (CGRectCount i = 0; i < count; ++i) {
    CGRect rect = rect_array[i];
    rect.origin.y = height() - rect.size.height;
    rects.insert(gfx::Rect(rect));
  }
  InvalidateRects(rects);
}

void CapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
                                   size_t count,
                                   const CGRect *rect_array) {
  InvalidRects rects;
  for (CGRectCount i = 0; i < count; ++i) {
    CGRect rect = rect_array[i];
    rect.origin.y = height() - rect.size.height;
    rects.insert(gfx::Rect(rect));
    rect = CGRectOffset(rect, delta.dX, delta.dY);
    rects.insert(gfx::Rect(rect));
  }
  InvalidateRects(rects);
}

void CapturerMac::ScreenRefreshCallback(CGRectCount count,
                                        const CGRect *rect_array,
                                        void *user_parameter) {
  CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter);
  capturer->ScreenRefresh(count, rect_array);
}

void CapturerMac::ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta,
                                           size_t count,
                                           const CGRect *rect_array,
                                           void *user_parameter) {
  CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter);
  capturer->ScreenUpdateMove(delta, count, rect_array);
}

void CapturerMac::DisplaysReconfiguredCallback(
    CGDirectDisplayID display,
    CGDisplayChangeSummaryFlags flags,
    void *user_parameter) {
  if ((display == CGMainDisplayID()) &&
      !(flags & kCGDisplayBeginConfigurationFlag)) {
    CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter);
    capturer->ScreenConfigurationChanged();
  }
}

// static
Capturer* Capturer::Create(MessageLoop* message_loop) {
  return new CapturerMac(message_loop);
}

}  // namespace remoting
<commit_msg>Fix Capturer for Mac to cope gracefully when there are no invalid rects.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/capturer_mac.h"

#include <stddef.h>

#include <OpenGL/CGLMacro.h>

namespace remoting {

CapturerMac::CapturerMac(MessageLoop* message_loop)
    : Capturer(message_loop),
      cgl_context_(NULL) {
  // TODO(dmaclach): move this initialization out into session_manager,
  // or at least have session_manager call into here to initialize it.
  CGError err =
      CGRegisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback,
                                      this);
  DCHECK_EQ(err, kCGErrorSuccess);
  err = CGScreenRegisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback,
                                     this);
  DCHECK_EQ(err, kCGErrorSuccess);
  err = CGDisplayRegisterReconfigurationCallback(
      CapturerMac::DisplaysReconfiguredCallback, this);
  DCHECK_EQ(err, kCGErrorSuccess);
  ScreenConfigurationChanged();
}

CapturerMac::~CapturerMac() {
  ReleaseBuffers();
  CGUnregisterScreenRefreshCallback(CapturerMac::ScreenRefreshCallback, this);
  CGScreenUnregisterMoveCallback(CapturerMac::ScreenUpdateMoveCallback, this);
  CGDisplayRemoveReconfigurationCallback(
      CapturerMac::DisplaysReconfiguredCallback, this);
}

void CapturerMac::ReleaseBuffers() {
  if (cgl_context_) {
    CGLDestroyContext(cgl_context_);
    cgl_context_ = NULL;
  }
}

void CapturerMac::ScreenConfigurationChanged() {
  ReleaseBuffers();
  CGDirectDisplayID mainDevice = CGMainDisplayID();

  width_ = CGDisplayPixelsWide(mainDevice);
  height_ = CGDisplayPixelsHigh(mainDevice);
  pixel_format_ = media::VideoFrame::RGB32;
  bytes_per_row_ = width_ * sizeof(uint32_t);
  size_t buffer_size = height() * bytes_per_row_;
  for (int i = 0; i < kNumBuffers; ++i) {
    buffers_[i].reset(new uint8[buffer_size]);
  }
  CGLPixelFormatAttribute attributes[] = {
    kCGLPFAFullScreen,
    kCGLPFADisplayMask,
    (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice),
    (CGLPixelFormatAttribute)0
  };
  CGLPixelFormatObj pixel_format = NULL;
  GLint matching_pixel_format_count = 0;
  CGLError err = CGLChoosePixelFormat(attributes,
                                      &pixel_format,
                                      &matching_pixel_format_count);
  DCHECK_EQ(err, kCGLNoError);
  err = CGLCreateContext(pixel_format, NULL, &cgl_context_);
  DCHECK_EQ(err, kCGLNoError);
  CGLDestroyPixelFormat(pixel_format);
  CGLSetFullScreen(cgl_context_);
  CGLSetCurrentContext(cgl_context_);
}

void CapturerMac::CalculateInvalidRects() {
  // Since the Mac gets its list of invalid rects via calls to InvalidateRect(),
  // this step only needs to perform post-processing optimizations on the rect
  // list (if needed).
}

void CapturerMac::CaptureRects(const InvalidRects& rects,
                               CaptureCompletedCallback* callback) {
  CGLContextObj CGL_MACRO_CONTEXT = cgl_context_;
  glReadBuffer(GL_FRONT);
  glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);

  glPixelStorei(GL_PACK_ALIGNMENT, 4);  // Force 4-byte alignment.
  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);

  // Read a block of pixels from the frame buffer.
  glReadPixels(0, 0, width(), height(), GL_BGRA, GL_UNSIGNED_BYTE,
               buffers_[current_buffer_].get());
  glPopClientAttrib();

  DataPlanes planes;
  planes.data[0] = buffers_[current_buffer_].get();
  planes.strides[0] = bytes_per_row_;

  scoped_refptr<CaptureData> data(new CaptureData(planes,
                                                  width(),
                                                  height(),
                                                  pixel_format()));
  data->mutable_dirty_rects() = rects;
  FinishCapture(data, callback);
}

void CapturerMac::ScreenRefresh(CGRectCount count, const CGRect *rect_array) {
  InvalidRects rects;
  for (CGRectCount i = 0; i < count; ++i) {
    CGRect rect = rect_array[i];
    rect.origin.y = height() - rect.size.height;
    rects.insert(gfx::Rect(rect));
  }
  InvalidateRects(rects);
}

void CapturerMac::ScreenUpdateMove(CGScreenUpdateMoveDelta delta,
                                   size_t count,
                                   const CGRect *rect_array) {
  InvalidRects rects;
  for (CGRectCount i = 0; i < count; ++i) {
    CGRect rect = rect_array[i];
    rect.origin.y = height() - rect.size.height;
    rects.insert(gfx::Rect(rect));
    rect = CGRectOffset(rect, delta.dX, delta.dY);
    rects.insert(gfx::Rect(rect));
  }
  InvalidateRects(rects);
}

void CapturerMac::ScreenRefreshCallback(CGRectCount count,
                                        const CGRect *rect_array,
                                        void *user_parameter) {
  CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter);
  capturer->ScreenRefresh(count, rect_array);
}

void CapturerMac::ScreenUpdateMoveCallback(CGScreenUpdateMoveDelta delta,
                                           size_t count,
                                           const CGRect *rect_array,
                                           void *user_parameter) {
  CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter);
  capturer->ScreenUpdateMove(delta, count, rect_array);
}

void CapturerMac::DisplaysReconfiguredCallback(
    CGDirectDisplayID display,
    CGDisplayChangeSummaryFlags flags,
    void *user_parameter) {
  if ((display == CGMainDisplayID()) &&
      !(flags & kCGDisplayBeginConfigurationFlag)) {
    CapturerMac *capturer = reinterpret_cast<CapturerMac *>(user_parameter);
    capturer->ScreenConfigurationChanged();
  }
}

// static
Capturer* Capturer::Create(MessageLoop* message_loop) {
  return new CapturerMac(message_loop);
}

}  // namespace remoting
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.5  2003/11/28 22:41:04  neilg
 * fix compilation error
 *
 * Revision 1.4  2003/11/28 20:20:54  neilg
 * make use of canonical representation in PSVIAttribute implementation
 *
 * Revision 1.3  2003/11/27 06:10:32  neilg
 * PSVIAttribute implementation
 *
 * Revision 1.2  2003/11/06 21:50:33  neilg
 * fix compilation errors under gcc 3.3.
 *
 * Revision 1.1  2003/09/16 14:33:36  neilg
 * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
 *
 */

#include <xercesc/framework/psvi/PSVIAttribute.hpp>

XERCES_CPP_NAMESPACE_BEGIN

PSVIAttribute::PSVIAttribute( MemoryManager* const manager ):
        PSVIItem(manager),
        fAttributeDecl(0)
{
}

void PSVIAttribute::reset(
            const XMLCh * const         valContext
            , PSVIItem::VALIDITY_STATE  state
            , PSVIItem::ASSESSMENT_TYPE assessmentType
            , const XMLCh * const       normalizedValue
            , XSSimpleTypeDefinition *  validatingType
            , XSSimpleTypeDefinition *  memberType
            , const XMLCh * const       defaultValue
            , const bool                isSpecified
            , XSAttributeDeclaration *  attrDecl
            , DatatypeValidator *dv
        )
{
    fValidationContext = valContext;
    fValidityState = state;
    fAssessmentType = assessmentType;
    fNormalizedValue = normalizedValue;
    fType = validatingType;
    fMemberType = memberType;
    fDefaultValue = defaultValue;
    fIsSpecified = isSpecified;
    fMemoryManager->deallocate((void *)fCanonicalValue);
    if(normalizedValue && dv)
        fCanonicalValue = (XMLCh *)dv->getCanonicalRepresentation(normalizedValue, fMemoryManager);
    else
        fCanonicalValue = 0;
    fAttributeDecl = attrDecl;
}

XERCES_CPP_NAMESPACE_END

<commit_msg>since there are certain things, such as schemaLocation attributes, that have a datatype and which we nonetheless do not validate, make canonical-value production dependent on validity being valid<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.6  2003/12/02 17:31:42  neilg
 * since there are certain things, such as schemaLocation attributes, that have a datatype and which we nonetheless do not validate, make canonical-value production dependent on validity being valid
 *
 * Revision 1.5  2003/11/28 22:41:04  neilg
 * fix compilation error
 *
 * Revision 1.4  2003/11/28 20:20:54  neilg
 * make use of canonical representation in PSVIAttribute implementation
 *
 * Revision 1.3  2003/11/27 06:10:32  neilg
 * PSVIAttribute implementation
 *
 * Revision 1.2  2003/11/06 21:50:33  neilg
 * fix compilation errors under gcc 3.3.
 *
 * Revision 1.1  2003/09/16 14:33:36  neilg
 * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
 *
 */

#include <xercesc/framework/psvi/PSVIAttribute.hpp>

XERCES_CPP_NAMESPACE_BEGIN

PSVIAttribute::PSVIAttribute( MemoryManager* const manager ):
        PSVIItem(manager),
        fAttributeDecl(0)
{
}

void PSVIAttribute::reset(
            const XMLCh * const         valContext
            , PSVIItem::VALIDITY_STATE  state
            , PSVIItem::ASSESSMENT_TYPE assessmentType
            , const XMLCh * const       normalizedValue
            , XSSimpleTypeDefinition *  validatingType
            , XSSimpleTypeDefinition *  memberType
            , const XMLCh * const       defaultValue
            , const bool                isSpecified
            , XSAttributeDeclaration *  attrDecl
            , DatatypeValidator *dv
        )
{
    fValidationContext = valContext;
    fValidityState = state;
    fAssessmentType = assessmentType;
    fNormalizedValue = normalizedValue;
    fType = validatingType;
    fMemberType = memberType;
    fDefaultValue = defaultValue;
    fIsSpecified = isSpecified;
    fMemoryManager->deallocate((void *)fCanonicalValue);
    if(normalizedValue && dv && fValidityState == VALIDITY_STATE::VALID)
        fCanonicalValue = (XMLCh *)dv->getCanonicalRepresentation(normalizedValue, fMemoryManager);
    else
        fCanonicalValue = 0;
    fAttributeDecl = attrDecl;
}

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>/// @file {{ device.class_name|lower }}.hpp
///
/// (c) Koheron 2014-2015

#ifndef __{{ device.class_name|upper }}_HPP__
#define __{{ device.class_name|upper }}_HPP__

{% for include in device.includes -%}
#include <{{ include }}>
{% endfor -%}
#include <drivers/dev_mem.hpp>

#if KSERVER_HAS_THREADS
#include <mutex>
#endif

#include "../core/kdevice.hpp"
#include "../core/devices_manager.hpp"

namespace kserver {

class {{ device.class_name }} : public KDevice<{{ device.class_name }},{{ device.name }}>
{
  public:
    const device_t kind = {{ device.name }};
    enum { __kind = {{ device.name }} };

  public:
    {{ device.class_name }}(KServer* kserver, Klib::DevMem& dev_mem_)
    : KDevice<{{ device.class_name }},{{ device.name }}>(kserver)
    , dev_mem(dev_mem_)
    {% if device.objects|length -%}
    {% for object in device.objects -%}
    , {{ object["name"] }}(dev_mem_)
    {% endfor -%}
    {% endif -%}
    {}

    enum Operation {
        {% for operation in device.operations -%}
        {{ operation["name"] }},
        {% endfor -%}
        {{ device.name|lower }}_op_num
    };

#if KSERVER_HAS_THREADS
    std::mutex mutex;
#endif

    Klib::DevMem& dev_mem;
    {% if device.objects|length -%}
    {% for object in device.objects -%}
    {{ object["type"] }} {{ object["name"] }};
    {% endfor -%}
    {% endif %}
}; // class KS_{{ device.name|capitalize }}

{% for operation in device.operations -%}
template<>
template<>
struct KDevice<{{ device.class_name }},{{ device.name }}>::
            Argument<{{ device.class_name }}::{{ operation["name"] }}>
{
{%- macro print_param_line(arg) %}
        {{ arg["type"] }} {{ arg["name"]}}; ///< {{ arg["description"] }}
{%- endmacro -%}
{% for arg in operation["arguments"] -%}
{% if not ("flag" in arg and arg["flag"] == 'CLIENT_ONLY') -%}
  {#- TODO : implement elementary type check -#}
  {% if not "cast" in arg -%}
    {% if ("description" in arg) and (arg["description"] != None) -%}
    {{ print_param_line(arg) }}
    {% else -%}
    {{ arg["type"] }} {{ arg["name"]}};
    {% endif -%}
  {% else -%}
    {% if ("description" in arg) and (arg["description"] != None)-%}
    {{ arg["cast"] }} {{ arg["name"]}}; ///< {{ arg["description"] }}
    {% else -%}
    {{ arg["cast"] }} {{ arg["name"]}};
    {% endif -%}
  {% endif -%}
{% endif -%}
{% endfor -%}
};

{% endfor -%}

} // namespace kserver

#endif //__{{ device.class_name|upper }}_HPP__

<commit_msg>Update ks_device.hpp<commit_after>/// @file {{ device.class_name|lower }}.hpp
///
/// (c) Koheron

#ifndef __{{ device.class_name|upper }}_HPP__
#define __{{ device.class_name|upper }}_HPP__

{% for include in device.includes -%}
#include <{{ include }}>
{% endfor -%}
#include <drivers/dev_mem.hpp>

#if KSERVER_HAS_THREADS
#include <mutex>
#endif

#include "../core/kdevice.hpp"
#include "../core/devices_manager.hpp"

namespace kserver {

class {{ device.class_name }} : public KDevice<{{ device.class_name }},{{ device.name }}>
{
  public:
    const device_t kind = {{ device.name }};
    enum { __kind = {{ device.name }} };

  public:
    {{ device.class_name }}(KServer* kserver, Klib::DevMem& dev_mem_)
    : KDevice<{{ device.class_name }},{{ device.name }}>(kserver)
    , dev_mem(dev_mem_)
    {% if device.objects|length -%}
    {% for object in device.objects -%}
    , {{ object["name"] }}(dev_mem_)
    {% endfor -%}
    {% endif -%}
    {}

    enum Operation {
        {% for operation in device.operations -%}
        {{ operation["name"] }},
        {% endfor -%}
        {{ device.name|lower }}_op_num
    };

#if KSERVER_HAS_THREADS
    std::mutex mutex;
#endif

    Klib::DevMem& dev_mem;
    {% if device.objects|length -%}
    {% for object in device.objects -%}
    {{ object["type"] }} {{ object["name"] }};
    {% endfor -%}
    {% endif %}
}; // class KS_{{ device.name|capitalize }}

{% for operation in device.operations -%}
template<>
template<>
struct KDevice<{{ device.class_name }},{{ device.name }}>::
            Argument<{{ device.class_name }}::{{ operation["name"] }}>
{
{%- macro print_param_line(arg) %}
        {{ arg["type"] }} {{ arg["name"]}}; ///< {{ arg["description"] }}
{%- endmacro -%}
{% for arg in operation["arguments"] -%}
{% if not ("flag" in arg and arg["flag"] == 'CLIENT_ONLY') -%}
  {#- TODO : implement elementary type check -#}
  {% if not "cast" in arg -%}
    {% if ("description" in arg) and (arg["description"] != None) -%}
    {{ print_param_line(arg) }}
    {% else -%}
    {{ arg["type"] }} {{ arg["name"]}};
    {% endif -%}
  {% else -%}
    {% if ("description" in arg) and (arg["description"] != None)-%}
    {{ arg["cast"] }} {{ arg["name"]}}; ///< {{ arg["description"] }}
    {% else -%}
    {{ arg["cast"] }} {{ arg["name"]}};
    {% endif -%}
  {% endif -%}
{% endif -%}
{% endfor -%}
};

{% endfor -%}

} // namespace kserver

#endif //__{{ device.class_name|upper }}_HPP__

<|endoftext|>


<commit_before>std::vector<std::string> split(std::string str,std::string sep){
    char* cstr=const_cast<char*>(str.c_str());
    char* current;
    std::vector<std::string> arr;
    current=strtok(cstr,sep.c_str());
    while(current!=NULL){
        arr.push_back(current);
        current=strtok(NULL,sep.c_str());
    }
    return arr;
}
<commit_msg>Add split.cpp<commit_after>#include <string>
#include <vector>

std::vector<std::string> split(std::string str, std::string sep){
  std::vector<std::string> res;
  size_t begin = 0;
  while(1){
    size_t pos = str.find(sep, begin);
    if(pos == std::string::npos) break;
    res.push_back( str.substr(begin, pos-begin) );
    begin = pos + sep.size();
  }
  res.push_back( str.substr(begin, str.length() - begin) );
  return res;
}

#ifdef  EBUG
#include <iostream>
using namespace std;

int main(void){
  string str = "abc def ghi jkl";
  vector<string> v = split(str, "bc");
  for(int i = 0; i < v.size(); i++){
    cout << v[i] << endl;
  }
  return 0;
}
#endif
<|endoftext|>


<commit_before>//
//  Application.cpp
//  ouzel
//
//  Created by Elviss Strazdins on 20/12/15.
//  Copyright © 2015 Bool Games. All rights reserved.
//

#include "Application.h"

namespace ouzel
{
    Application::Application(Engine* engine):
        _engine(engine)
    {
        _engine->addEventHandler(this);

        Sprite* sprite = new Sprite("tim-from-braid.png", _engine->getScene());
        _engine->getScene()->getRootNode()->addChild(sprite);

        Sprite* witch = new Sprite("witch.png", _engine->getScene());
        witch->setPosition(Vector2(100.0f, 100.0f));
        _engine->getScene()->getRootNode()->addChild(witch);

        sprite->release();
    }

    Application::~Application()
    {
        _engine->removeEventHandler(this);
    }

    bool Application::handleEvent(const Event& event)
    {
        return true;
    }

    void Application::update(float delta)
    {

    }
}
<commit_msg>Release leaking witch<commit_after>//
//  Application.cpp
//  ouzel
//
//  Created by Elviss Strazdins on 20/12/15.
//  Copyright © 2015 Bool Games. All rights reserved.
//

#include "Application.h"

namespace ouzel
{
    Application::Application(Engine* engine):
        _engine(engine)
    {
        _engine->addEventHandler(this);

        Sprite* sprite = new Sprite("tim-from-braid.png", _engine->getScene());
        _engine->getScene()->getRootNode()->addChild(sprite);

        Sprite* witch = new Sprite("witch.png", _engine->getScene());
        witch->setPosition(Vector2(100.0f, 100.0f));
        _engine->getScene()->getRootNode()->addChild(witch);

        sprite->release();
        witch->release();
    }

    Application::~Application()
    {
        _engine->removeEventHandler(this);
    }

    bool Application::handleEvent(const Event& event)
    {
        return true;
    }

    void Application::update(float delta)
    {

    }
}
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

#include "routes.hh"
#include "reply.hh"
#include "exception.hh"

namespace httpd {

using namespace std;

void verify_param(const request& req, const sstring& param) {
    if (req.get_query_param(param) == "") {
        throw missing_param_exception(param);
    }
}

routes::~routes() {
    for (int i = 0; i < NUM_OPERATION; i++) {
        for (auto kv : _map[i]) {
            delete kv.second;
        }
    }
    for (int i = 0; i < NUM_OPERATION; i++) {
        for (auto r : _rules[i]) {
            delete r;
        }
    }

}

future<std::unique_ptr<reply> > routes::handle(const sstring& path, std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
    handler_base* handler = get_handler(str2type(req->_method),
            normalize_url(path), req->param);
    if (handler != nullptr) {
        try {
            for (auto& i : handler->_mandatory_param) {
                verify_param(*req.get(), i);
            }
            auto r =  handler->handle(path, std::move(req), std::move(rep));
            return r;
        } catch (const redirect_exception& _e) {
            rep.reset(new reply());
            rep->add_header("Location", _e.url).set_status(_e.status()).done(
                    "json");

        } catch (const base_exception& _e) {
            rep.reset(new reply());
            json_exception e(_e);
            rep->set_status(_e.status(), e.to_json()).done("json");
        } catch (exception& _e) {
            rep.reset(new reply());
            json_exception e(_e);
            cerr << "exception was caught for " << path << ": " << _e.what()
                    << endl;
            rep->set_status(reply::status_type::internal_server_error,
                    e.to_json()).done("json");
        }
    } else {
        rep.reset(new reply());
        json_exception ex(not_found_exception("Not found"));
        rep->set_status(reply::status_type::not_found, ex.to_json()).done(
                "json");
    }
    cerr << "Failed with " << path << " " << rep->_content << endl;
    return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
}

sstring routes::normalize_url(const sstring& url) {
    if (url.length() < 2 || url.at(url.length() - 1) != '/') {
        return url;
    }
    return url.substr(0, url.length() - 1);
}

handler_base* routes::get_handler(operation_type type, const sstring& url,
        parameters& params) {
    handler_base* handler = get_exact_match(type, url);
    if (handler != nullptr) {
        return handler;
    }

    for (auto rule = _rules[type].cbegin(); rule != _rules[type].cend();
            ++rule) {
        handler = (*rule)->get(url, params);
        if (handler != nullptr) {
            return handler;
        }
        params.clear();
    }
    return nullptr;
}

routes& routes::add(operation_type type, const url& url,
        handler_base* handler) {
    match_rule* rule = new match_rule(handler);
    rule->add_str(url._path);
    if (url._param != "") {
        rule->add_param(url._param, true);
    }
    return add(rule, type);
}

}
<commit_msg>httpd: fix future exception handling<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

#include "routes.hh"
#include "reply.hh"
#include "exception.hh"

namespace httpd {

using namespace std;

void verify_param(const request& req, const sstring& param) {
    if (req.get_query_param(param) == "") {
        throw missing_param_exception(param);
    }
}

routes::~routes() {
    for (int i = 0; i < NUM_OPERATION; i++) {
        for (auto kv : _map[i]) {
            delete kv.second;
        }
    }
    for (int i = 0; i < NUM_OPERATION; i++) {
        for (auto r : _rules[i]) {
            delete r;
        }
    }

}

static std::unique_ptr<reply> exception_reply(std::exception_ptr eptr) {
    auto rep = std::make_unique<reply>();
    try {
        std::rethrow_exception(eptr);
    } catch (const base_exception& e) {
        rep->set_status(e.status(), json_exception(e).to_json());
    } catch (exception& e) {
        rep->set_status(reply::status_type::internal_server_error,
                json_exception(e).to_json());
    } catch (...) {
        rep->set_status(reply::status_type::internal_server_error,
                json_exception(std::runtime_error(
                        "Unknown unhandled exception")).to_json());
    }
    rep->done("json");
    return rep;
}

future<std::unique_ptr<reply> > routes::handle(const sstring& path, std::unique_ptr<request> req, std::unique_ptr<reply> rep) {
    handler_base* handler = get_handler(str2type(req->_method),
            normalize_url(path), req->param);
    if (handler != nullptr) {
        try {
            for (auto& i : handler->_mandatory_param) {
                verify_param(*req.get(), i);
            }
            auto r =  handler->handle(path, std::move(req), std::move(rep));
            return r.handle_exception(exception_reply);
        } catch (const redirect_exception& _e) {
            rep.reset(new reply());
            rep->add_header("Location", _e.url).set_status(_e.status()).done(
                    "json");
        } catch (...) {
            rep = exception_reply(std::current_exception());
        }
    } else {
        rep.reset(new reply());
        json_exception ex(not_found_exception("Not found"));
        rep->set_status(reply::status_type::not_found, ex.to_json()).done(
                "json");
    }
    cerr << "Failed with " << path << " " << rep->_content << endl;
    return make_ready_future<std::unique_ptr<reply>>(std::move(rep));
}

sstring routes::normalize_url(const sstring& url) {
    if (url.length() < 2 || url.at(url.length() - 1) != '/') {
        return url;
    }
    return url.substr(0, url.length() - 1);
}

handler_base* routes::get_handler(operation_type type, const sstring& url,
        parameters& params) {
    handler_base* handler = get_exact_match(type, url);
    if (handler != nullptr) {
        return handler;
    }

    for (auto rule = _rules[type].cbegin(); rule != _rules[type].cend();
            ++rule) {
        handler = (*rule)->get(url, params);
        if (handler != nullptr) {
            return handler;
        }
        params.clear();
    }
    return nullptr;
}

routes& routes::add(operation_type type, const url& url,
        handler_base* handler) {
    match_rule* rule = new match_rule(handler);
    rule->add_str(url._path);
    if (url._param != "") {
        rule->add_param(url._param, true);
    }
    return add(rule, type);
}

}
<|endoftext|>


<commit_before>#include "IndexStructureFactory.h"
//
#include "SequentialScan.h"
#include "Octree.h"

namespace mdsearch
{

	/* ALL INDEX STRUCTURE GENERATORS ARE DEFINED HERE */
	IndexStructure* generateSequentialScan(unsigned int numDimensions,
		const std::vector<std::string>& args)
	{
		return new SequentialScan(numDimensions);
	}

	IndexStructure* generateOctree(unsigned int numDimensions,
		const std::vector<std::string>& args)
	{
		// TODO
		return NULL;
	}

	IndexStructureFactory::IndexStructureFactory()
	{
		// Add generators defined in this source file
		addGenerator("sequential_scan", generateSequentialScan);
		addGenerator("octree", generateOctree);
	}

	void IndexStructureFactory::addGenerator(const std::string& structureType,
		StructureGenerator generator)
	{
		std::pair<std::string, StructureGenerator> newEntry(structureType, generator);
		generators.insert(newEntry);
	}

	IndexStructure* IndexStructureFactory::constructIndexStructure(
		const std::string& structureType, unsigned int numDimensions,
		const std::vector<std::string>& arguments) const
	{
		// Search map for a generator for the requested structure type
		GeneratorMap::const_iterator it = generators.find(structureType);
		if (it != generators.end())
		{
			StructureGenerator generator = it->second;
			return generator(numDimensions, arguments);
		}
		// Return NULL if the given structure type does not exist
		else
		{
			return NULL;
		}
	}

}<commit_msg>Implemented Octree factory method<commit_after>#include "IndexStructureFactory.h"
//
#include "SequentialScan.h"
#include "Octree.h"

#include <boost/lexical_cast.hpp>

namespace mdsearch
{

	/* ALL INDEX STRUCTURE GENERATORS ARE DEFINED HERE */
	IndexStructure* generateSequentialScan(unsigned int numDimensions,
		const std::vector<std::string>& args)
	{
		return new SequentialScan(numDimensions);
	}

	IndexStructure* generateOctree(unsigned int numDimensions,
		const std::vector<std::string>& args)
	{
		// Check there are enough arguments to construct n-dimensional boundary
		if (args.size() < numDimensions * 2) // min + max args needed per dimension
			return NULL;

		Region boundary(numDimensions);
		for (unsigned int d = 0; (d < numDimensions); d++)
		{
			// Parse string arguments into real numbers
			try
			{
				Real min = boost::lexical_cast<Real>(args[d * 2]);
				Real max = boost::lexical_cast<Real>(args[d * 2 + 1]);
				boundary[d] = Interval(min, max);
			}
			// If an argument could not be converted into a real number,
			// return NULL as the structure cannot be constructed
			catch (const boost::bad_lexical_cast& ex)
			{
				return NULL;
			}
		}

		return new Octree(numDimensions, boundary);
	}

	IndexStructureFactory::IndexStructureFactory()
	{
		// Add generators defined in this source file
		addGenerator("sequential_scan", generateSequentialScan);
		addGenerator("octree", generateOctree);
	}

	void IndexStructureFactory::addGenerator(const std::string& structureType,
		StructureGenerator generator)
	{
		std::pair<std::string, StructureGenerator> newEntry(structureType, generator);
		generators.insert(newEntry);
	}

	IndexStructure* IndexStructureFactory::constructIndexStructure(
		const std::string& structureType, unsigned int numDimensions,
		const std::vector<std::string>& arguments) const
	{
		// Search map for a generator for the requested structure type
		GeneratorMap::const_iterator it = generators.find(structureType);
		if (it != generators.end())
		{
			StructureGenerator generator = it->second;
			return generator(numDimensions, arguments);
		}
		// Return NULL if the given structure type does not exist
		else
		{
			return NULL;
		}
	}

}<|endoftext|>


<commit_before>// Polygon.cpp

#include "Polygon.h"
#include "Triangle.h"
#include "IndexTriangle.h"
#include "LineSegment.h"
#include "Surface.h"

using namespace _3DMath;

Polygon::Polygon( void )
{
	vertexArray = new VectorArray();
	indexTriangleList = new IndexTriangleList();
}

/*virtual*/ Polygon::~Polygon( void )
{
	delete vertexArray;
	delete indexTriangleList;
}

bool Polygon::GetPlane( Plane& plane ) const
{
	if( vertexArray->size() < 3 )
		return false;

	Vector normal, center;
	normal.Set( 0.0, 0.0, 0.0 );
	center.Set( 0.0, 0.0, 0.0 );

	for( int i = 0; i < ( signed )vertexArray->size(); i++ )
	{
		// This is the Newel method.
		int j = ( i + 1 ) % vertexArray->size();
		const Vector& pointA = ( *vertexArray )[i];
		const Vector& pointB = ( *vertexArray )[j];
		normal.x += ( pointA.y - pointB.y ) * ( pointA.z + pointB.z );
		normal.y += ( pointA.z - pointB.z ) * ( pointA.x + pointB.x );
		normal.z += ( pointA.x - pointB.x ) * ( pointA.y + pointB.y );
		center.Add( pointA );
	}

	center.Scale( 1.0 / double( vertexArray->size() ) );
	plane.SetCenterAndNormal( center, normal );

	return true;
}

bool Polygon::SplitAgainstSurface( const Surface* surface, Polygon& insidePolygon, Polygon& outsidePolygon, double maxDistanceFromSurface ) const
{
	struct Node
	{
		Vector point;
		Surface::Side side;
	};

	std::vector< Node > nodeArray;

	for( int i = 0; i < ( signed )vertexArray->size(); i++ )
	{
		Node node;
		node.point = ( *vertexArray )[i];
		node.side = surface->GetSide( node.point );
		nodeArray.push_back( node );
	}

	for( int i = 0; i < ( signed )nodeArray.size(); i++ )
	{
		int j = ( i + 1 ) % nodeArray.size();

		if( ( nodeArray[i].side == Surface::INSIDE && nodeArray[j].side == Surface::OUTSIDE ) ||
			( nodeArray[i].side == Surface::OUTSIDE && nodeArray[j].side == Surface::INSIDE ) )
		{
			LineSegment lineSegment;
			lineSegment.vertex[0] = nodeArray[i].point;
			lineSegment.vertex[1] = nodeArray[j].point;
			SurfacePoint* surfacePoint = surface->FindSingleIntersection( lineSegment );
			if( !surfacePoint )
				return false;

			Node node;
			surfacePoint->GetLocation( node.point );
			node.side = Surface::NEITHER_SIDE;
			std::vector< Node >::iterator iter( nodeArray.begin() + j );
			nodeArray.insert( iter, node );
		}
	}

	for( int i = 0; i < 2; i++ )
	{
		Polygon* polygon = nullptr;
		Surface::Side currentSide, otherSide;

		if( i == 0 )
		{
			currentSide = Surface::INSIDE;
			otherSide = Surface::OUTSIDE;
			polygon = &insidePolygon;
		}
		else
		{
			currentSide = Surface::OUTSIDE;
			otherSide = Surface::INSIDE;
			polygon = &outsidePolygon;
		}

		int j;
		for( j = 0; j < ( signed )nodeArray.size(); j++ )
			if( nodeArray[j].side == currentSide )
				break;

		if( j == ( signed )nodeArray.size() )
			return false;

		int k = j;

		do
		{
			int l = ( k + 1 ) % nodeArray.size();

			if( nodeArray[k].side == Surface::NEITHER_SIDE && nodeArray[l].side == otherSide )
			{
				while( nodeArray[l].side != Surface::NEITHER_SIDE )
					l = ( l + 1 ) % nodeArray.size();

				SurfacePoint* surfacePointA = surface->GetNearestSurfacePoint( nodeArray[k].point );
				SurfacePoint* surfacePointB = surface->GetNearestSurfacePoint( nodeArray[l].point );

				surface->FindDirectPath( surfacePointA, surfacePointB, *polygon->vertexArray, maxDistanceFromSurface );

				l = ( l + 1 ) % nodeArray.size();
			}
			else
			{
				polygon->vertexArray->push_back( nodeArray[k].point );
			}

			k = l;
		}
		while( k != j );
	}

	return true;
}

bool Polygon::Tessellate( void ) const
{
	indexTriangleList->clear();

	VectorArray pointArray;
	for( int i = 0; i < ( signed )vertexArray->size(); i++ )
		pointArray.push_back( ( *vertexArray )[i] );

	while( pointArray.size() > 2 )
	{
		for( int i = 0; i < ( signed )vertexArray->size(); i++ )
		{
			IndexTriangle indexTriangle( i, ( i + 1 ) % vertexArray->size(), ( i + 2 ) % vertexArray->size() );

			Triangle triangle;
			indexTriangle.GetTriangle( triangle, &pointArray );

			int j;
			for( j = 0; j < ( signed )vertexArray->size(); j++ )
			{
				if( j == i )
					continue;

				if( triangle.ProperlyContainsPoint( ( *vertexArray )[j] ) )
					break;
			}

			if( j < ( signed )vertexArray->size() )
				continue;

			indexTriangleList->push_back( indexTriangle );
			pointArray.erase( pointArray.begin() + ( i + 1 ) % vertexArray->size() );
			break;
		}
	}

	return true;
}

// Polygon.cpp<commit_msg>this has bugs; i need to rethink it<commit_after>// Polygon.cpp

#include "Polygon.h"
#include "Triangle.h"
#include "IndexTriangle.h"
#include "LineSegment.h"
#include "Surface.h"

using namespace _3DMath;

Polygon::Polygon( void )
{
	vertexArray = new VectorArray();
	indexTriangleList = new IndexTriangleList();
}

/*virtual*/ Polygon::~Polygon( void )
{
	delete vertexArray;
	delete indexTriangleList;
}

bool Polygon::GetPlane( Plane& plane ) const
{
	if( vertexArray->size() < 3 )
		return false;

	Vector normal, center;
	normal.Set( 0.0, 0.0, 0.0 );
	center.Set( 0.0, 0.0, 0.0 );

	for( int i = 0; i < ( signed )vertexArray->size(); i++ )
	{
		// This is the Newel method.
		int j = ( i + 1 ) % vertexArray->size();
		const Vector& pointA = ( *vertexArray )[i];
		const Vector& pointB = ( *vertexArray )[j];
		normal.x += ( pointA.y - pointB.y ) * ( pointA.z + pointB.z );
		normal.y += ( pointA.z - pointB.z ) * ( pointA.x + pointB.x );
		normal.z += ( pointA.x - pointB.x ) * ( pointA.y + pointB.y );
		center.Add( pointA );
	}

	center.Scale( 1.0 / double( vertexArray->size() ) );
	plane.SetCenterAndNormal( center, normal );

	return true;
}

bool Polygon::SplitAgainstSurface( const Surface* surface, Polygon& insidePolygon, Polygon& outsidePolygon, double maxDistanceFromSurface ) const
{
	struct Node
	{
		Vector point;
		Surface::Side side;
	};

	std::vector< Node > nodeArray;

	for( int i = 0; i < ( signed )vertexArray->size(); i++ )
	{
		Node node;
		node.point = ( *vertexArray )[i];
		node.side = surface->GetSide( node.point );
		nodeArray.push_back( node );
	}

	for( int i = 0; i < ( signed )nodeArray.size(); i++ )
	{
		int j = ( i + 1 ) % nodeArray.size();

		if( ( nodeArray[i].side == Surface::INSIDE && nodeArray[j].side == Surface::OUTSIDE ) ||
			( nodeArray[i].side == Surface::OUTSIDE && nodeArray[j].side == Surface::INSIDE ) )
		{
			LineSegment lineSegment;
			lineSegment.vertex[0] = nodeArray[i].point;
			lineSegment.vertex[1] = nodeArray[j].point;
			SurfacePoint* surfacePoint = surface->FindSingleIntersection( lineSegment );
			if( !surfacePoint )
				return false;

			Node node;
			surfacePoint->GetLocation( node.point );
			node.side = Surface::NEITHER_SIDE;
			std::vector< Node >::iterator iter( nodeArray.begin() + j );
			nodeArray.insert( iter, node );
		}
	}

	for( int i = 0; i < 2; i++ )
	{
		Polygon* polygon = nullptr;
		Surface::Side currentSide, otherSide;

		if( i == 0 )
		{
			currentSide = Surface::INSIDE;
			otherSide = Surface::OUTSIDE;
			polygon = &insidePolygon;
		}
		else
		{
			currentSide = Surface::OUTSIDE;
			otherSide = Surface::INSIDE;
			polygon = &outsidePolygon;
		}

		int j;
		for( j = 0; j < ( signed )nodeArray.size(); j++ )
			if( nodeArray[j].side == currentSide )
				break;

		if( j == ( signed )nodeArray.size() )
			return false;

		int k = j;

		do
		{
			int l = ( k + 1 ) % nodeArray.size();

			if( nodeArray[k].side == Surface::NEITHER_SIDE && nodeArray[l].side == otherSide )
			{
				while( nodeArray[l].side != Surface::NEITHER_SIDE )
					l = ( l + 1 ) % nodeArray.size();

				SurfacePoint* surfacePointA = surface->GetNearestSurfacePoint( nodeArray[k].point );
				SurfacePoint* surfacePointB = surface->GetNearestSurfacePoint( nodeArray[l].point );

				surface->FindDirectPath( surfacePointA, surfacePointB, *polygon->vertexArray, maxDistanceFromSurface );

				l = ( l + 1 ) % nodeArray.size();
			}
			else
			{
				polygon->vertexArray->push_back( nodeArray[k].point );
			}

			k = l;
		}
		while( k != j );
	}

	return true;
}

bool Polygon::Tessellate( void ) const
{
	indexTriangleList->clear();

	VectorArray pointArray;
	for( int i = 0; i < ( signed )vertexArray->size(); i++ )
		pointArray.push_back( ( *vertexArray )[i] );

	while( pointArray.size() > 2 )
	{
		for( int i = 0; i < ( signed )vertexArray->size(); i++ )
		{
			IndexTriangle indexTriangle( i, ( i + 1 ) % vertexArray->size(), ( i + 2 ) % vertexArray->size() );

			Triangle triangle;
			indexTriangle.GetTriangle( triangle, &pointArray );

			// TODO: I need to rethink this.  There are some obvious things wrong with this.

			int j;
			for( j = 0; j < ( signed )vertexArray->size(); j++ )
			{
				if( j == i )
					continue;

				if( triangle.ProperlyContainsPoint( ( *vertexArray )[j] ) )
					break;
			}

			if( j < ( signed )vertexArray->size() )
				continue;

			indexTriangleList->push_back( indexTriangle );
			pointArray.erase( pointArray.begin() + ( i + 1 ) % vertexArray->size() );
			break;
		}
	}

	return true;
}

// Polygon.cpp<|endoftext|>


<commit_before>#include <yuni/yuni.h>
#include <yuni/core/noncopyable.h>
#include <yuni/io/file.h>
#include <yuni/core/system/console.h>
#include <yuni/core/getopt.h>
#include <yuni/io/directory.h>
#include <yuni/io/directory/info.h>
#include <yuni/datetime/timestamp.h>
#include <yuni/core/logs/logs.h>
#include "nany/nany.h"
#include <algorithm>
#include <yuni/datetime/timestamp.h>
#include <iostream>
#include <vector>

using namespace Yuni;

namespace {

struct Settings {
	//! List of filenames to verify
	std::vector<String> filenames;
	// no colors
	bool noColors = false;
	// Result expected from filename convention
	bool useFilenameConvention = false;
};

template<class LeftType = Logs::NullDecorator>
struct ParseVerbosity: public LeftType {
	template<class Handler, class VerbosityType, class O>
	void internalDecoratorAddPrefix(O& out, const AnyString& s) const {
		// Write the verbosity to the output
		if (VerbosityType::hasName) {
			AnyString name{VerbosityType::Name()};
			if (s.empty()) {
			}
			else if (name == "info")
				printInfo<Handler>(out);
			else if (name == "error")
				printError<Handler>(out);
			else if (name == "warning")
				printWarning<Handler>(out);
			else
				printOtherVerbosity<Handler, VerbosityType>(out);
		}
		// Transmit the message to the next decorator
		LeftType::template internalDecoratorAddPrefix<Handler, VerbosityType,O>(out, s);
	}

	template<class Handler, class O>
	static void printInfo(O& out) {
		if (Handler::colorsAllowed)
			System::Console::TextColor<System::Console::yellow>::Set(out);
		#ifndef YUNI_OS_WINDOWS
		out << "  \u2713   ";
		#else
		out << " ok   ";
		#endif
		if (Handler::colorsAllowed) {
			System::Console::ResetTextColor(out);
			System::Console::TextColor<System::Console::bold>::Set(out);
		}
		out << "parsing";
		if (Handler::colorsAllowed)
			System::Console::ResetTextColor(out);
	}

	template<class Handler, class O>
	static void printError(O& out) {
		if (Handler::colorsAllowed)
			System::Console::TextColor<System::Console::red>::Set(out);
		out << " ERR  ";
		if (Handler::colorsAllowed) {
			System::Console::ResetTextColor(out);
			System::Console::TextColor<System::Console::bold>::Set(out);
		}
		out << "parsing";
		if (Handler::colorsAllowed)
			System::Console::ResetTextColor(out);
	}

	template<class Handler, class O>
	static void printWarning(O& out) {
		if (Handler::colorsAllowed)
			System::Console::TextColor<System::Console::yellow>::Set(out);
		out << " warn ";
		if (Handler::colorsAllowed) {
			System::Console::ResetTextColor(out);
			System::Console::TextColor<System::Console::bold>::Set(out);
		}
		out << "parsing";
		if (Handler::colorsAllowed)
			System::Console::ResetTextColor(out);
	}

	template<class Handler, class VerbosityType, class O>
	static void printOtherVerbosity(O& out) {
		// Set Color
		if (Handler::colorsAllowed && VerbosityType::color != System::Console::none)
			System::Console::TextColor<VerbosityType::color>::Set(out);
		// The verbosity
		VerbosityType::AppendName(out);
		// Reset Color
		if (Handler::colorsAllowed && VerbosityType::color != System::Console::none)
			System::Console::ResetTextColor(out);
	}

}; // struct VerbosityLevel

using Logging = Logs::Logger<Logs::StdCout<>, ParseVerbosity<Logs::Message<>>>;
static Logging logs;

uint32_t findCommonFolderLength(const std::vector<String>& filenames) {
	if (filenames.empty())
		return 0;
	uint32_t len = 0;
	auto& firstElement = filenames[0];
	const char sep = IO::Separator;
	for (; ; ++len) {
		for (auto& filename: filenames) {
			if (len == firstElement.size())
				return len;
			if (len < filename.size() and filename[len] != '\0' and filename[len] == firstElement[len])
				continue;
			while (len > 0 and firstElement[--len] != sep) { // back to the last sep
			}
			return len;
		}
	}
	return len;
}

bool expandAndCanonicalizeFilenames(std::vector<String>& filenames) {
	std::vector<String> filelist;
	filelist.reserve(512);
	String currentfile;
	currentfile.reserve(4096);
	for (auto& filename: filenames) {
		IO::Canonicalize(currentfile, filename);
		switch (IO::TypeOf(currentfile)) {
			case IO::typeFile: {
				filelist.emplace_back(currentfile);
				break;
			}
			case IO::typeFolder: {
				ShortString16 ext;
				IO::Directory::Info info(currentfile);
				auto end = info.recursive_file_end();
				for (auto i = info.recursive_file_begin(); i != end; ++i)
				{
					IO::ExtractExtension(ext, *i);
					if (ext == ".ny")
						filelist.emplace_back(i.filename());
				}
				break;
			}
			default: {
				logs.error() << "impossible to find '" << currentfile << "'";
				return false;
			}
		}
	}
	// for beauty in singled-threaded (and to always produce the same output)
	std::sort(filelist.begin(), filelist.end());
	filenames.swap(filelist);
	return true;
}

template<class F>
bool IterateThroughAllFiles(const std::vector<String>& filenames, const F& callback) {
	String currentfile;
	uint32_t testOK = 0;
	uint32_t testFAILED = 0;
	int64_t maxCheckDuration = 0;
	int64_t startTime = DateTime::NowMilliSeconds();
	for (auto& filename: filenames) {
		int64_t duration = 0;
		if (callback(filename, duration))
			++testOK;
		else
			++testFAILED;
		if (duration > maxCheckDuration)
			maxCheckDuration = duration;
	}
	int64_t endTime = DateTime::NowMilliSeconds();
	uint32_t total = testOK + testFAILED;
	if (total > 0) {
		int64_t duration = (endTime - startTime);
		String durationStr;
		durationStr << " (in " << duration << "ms, max: " << maxCheckDuration << "ms)";
		if (total > 1) {
			if (0 != testFAILED) {
				switch (total) {
					case 1:
						logs.warning() << "-- FAILED -- 1 file, +" << testOK << ", -" << testFAILED << durationStr;
						break;
					default:
						logs.warning() << "-- FAILED -- " << total << " files, +" << testOK << ", -" << testFAILED << durationStr;
				}
			}
			else
			{
				switch (total) {
					case 1:
						logs.info() << "success: 1 file, +" << testOK << ", -0" << durationStr;
						break;
					default:
						logs.info() << "success: " << total << " files, +" << testOK << ", -0" << durationStr;
				}
			}
		}
	}
	else
		logs.warning() << "no input file";
	return (0 == testFAILED);
}

bool batchCheckIfFilenamesConformToGrammar(Settings& settings) {
	if (not expandAndCanonicalizeFilenames(settings.filenames))
		return false;
	auto commonFolder = (settings.filenames.size() > 1 ? findCommonFolderLength(settings.filenames) : 0);
	if (0 != commonFolder)
		++commonFolder;
	return IterateThroughAllFiles(settings.filenames, [&](const AnyString& file, int64_t& duration) -> bool {
		String barefile;
		IO::ExtractFileName(barefile, file);
		bool expected = true;
		bool canfail = false;
		if (settings.useFilenameConvention)
		{
			if (barefile.startsWith("ko-"))
				expected = false;
			if (barefile.find("-canfail-") < barefile.size())
				canfail = true;
		}
		// PARSE
		int64_t start = DateTime::NowMilliSeconds();
		bool success = (nytrue == nytry_parse_file_n(file.c_str(), file.size()));
		duration = DateTime::NowMilliSeconds() - start;
		success = (success == expected);
		if (success and duration < 300) {
			logs.info() << AnyString{file, commonFolder} << " [" << duration << "ms]";
		}
		else {
			if (not success) {
				if (not canfail)
					logs.error() << AnyString{file, commonFolder} << " [" << duration << "ms]";
				else
					logs.warning() << AnyString{file, commonFolder} << " [" << duration << "ms, can fail]";
			}
			else
				logs.error() << AnyString{file, commonFolder} << " [" << duration << "ms - time limit reached]";
			success = canfail;
		}
		return success;
	});
}

bool parseCommandLine(Settings& settings, int argc, char** argv) {
	GetOpt::Parser options;
	options.add(settings.filenames, 'i', "input", "Input files (or folders)");
	options.remainingArguments(settings.filenames);
	options.addFlag(settings.noColors, ' ', "no-color", "Disable color output");
	options.addFlag(settings.useFilenameConvention, ' ', "use-filename-convention",
		"Use the filename to determine if the test should succeed or not (should succeed if starting with 'ok-'");
	bool optVersion = false;
	options.addFlag(optVersion, ' ', "version", "Display the version of the compiler and exit");
	if (not options(argc, argv)) {
		// The program should not continue here
		// The user may have requested the help or an error has happened
		// If an error has happened, the exit status should be different from 0
		if (options.errors())
			throw std::runtime_error("Abort due to error");
		return false;
	}
	if (optVersion) {
		std::cout << "0.0\n";
		return false;
	}
	if (settings.filenames.empty())
		throw std::runtime_error("no input file");
	return true;
}

} // namespace

int main(int argc, char** argv)
{
	try {
		Settings settings;
		if (not parseCommandLine(settings, argc, argv))
			return EXIT_SUCCESS;
		bool success = batchCheckIfFilenamesConformToGrammar(settings);
		return success ? EXIT_SUCCESS : EXIT_FAILURE;
	}
	catch (const std::exception& e) {
		std::cerr << argv[0] << ": " << e.what() << '\n';
	}
	return EXIT_FAILURE;
}
<commit_msg>check-syntax: simplified filenames expansion<commit_after>#include <yuni/yuni.h>
#include <yuni/core/noncopyable.h>
#include <yuni/io/file.h>
#include <yuni/core/system/console.h>
#include <yuni/core/getopt.h>
#include <yuni/io/directory.h>
#include <yuni/io/directory/info.h>
#include <yuni/datetime/timestamp.h>
#include <yuni/core/logs/logs.h>
#include "nany/nany.h"
#include <algorithm>
#include <yuni/datetime/timestamp.h>
#include <iostream>
#include <vector>

using namespace Yuni;

namespace {

struct Settings {
	//! List of filenames to verify
	std::vector<String> filenames;
	// no colors
	bool noColors = false;
	// Result expected from filename convention
	bool useFilenameConvention = false;
};

template<class LeftType = Logs::NullDecorator>
struct ParseVerbosity: public LeftType {
	template<class Handler, class VerbosityType, class O>
	void internalDecoratorAddPrefix(O& out, const AnyString& s) const {
		// Write the verbosity to the output
		if (VerbosityType::hasName) {
			AnyString name{VerbosityType::Name()};
			if (s.empty()) {
			}
			else if (name == "info")
				printInfo<Handler>(out);
			else if (name == "error")
				printError<Handler>(out);
			else if (name == "warning")
				printWarning<Handler>(out);
			else
				printOtherVerbosity<Handler, VerbosityType>(out);
		}
		// Transmit the message to the next decorator
		LeftType::template internalDecoratorAddPrefix<Handler, VerbosityType,O>(out, s);
	}

	template<class Handler, class O>
	static void printInfo(O& out) {
		if (Handler::colorsAllowed)
			System::Console::TextColor<System::Console::yellow>::Set(out);
		#ifndef YUNI_OS_WINDOWS
		out << "  \u2713   ";
		#else
		out << " ok   ";
		#endif
		if (Handler::colorsAllowed) {
			System::Console::ResetTextColor(out);
			System::Console::TextColor<System::Console::bold>::Set(out);
		}
		out << "parsing";
		if (Handler::colorsAllowed)
			System::Console::ResetTextColor(out);
	}

	template<class Handler, class O>
	static void printError(O& out) {
		if (Handler::colorsAllowed)
			System::Console::TextColor<System::Console::red>::Set(out);
		out << " ERR  ";
		if (Handler::colorsAllowed) {
			System::Console::ResetTextColor(out);
			System::Console::TextColor<System::Console::bold>::Set(out);
		}
		out << "parsing";
		if (Handler::colorsAllowed)
			System::Console::ResetTextColor(out);
	}

	template<class Handler, class O>
	static void printWarning(O& out) {
		if (Handler::colorsAllowed)
			System::Console::TextColor<System::Console::yellow>::Set(out);
		out << " warn ";
		if (Handler::colorsAllowed) {
			System::Console::ResetTextColor(out);
			System::Console::TextColor<System::Console::bold>::Set(out);
		}
		out << "parsing";
		if (Handler::colorsAllowed)
			System::Console::ResetTextColor(out);
	}

	template<class Handler, class VerbosityType, class O>
	static void printOtherVerbosity(O& out) {
		// Set Color
		if (Handler::colorsAllowed && VerbosityType::color != System::Console::none)
			System::Console::TextColor<VerbosityType::color>::Set(out);
		// The verbosity
		VerbosityType::AppendName(out);
		// Reset Color
		if (Handler::colorsAllowed && VerbosityType::color != System::Console::none)
			System::Console::ResetTextColor(out);
	}

}; // struct VerbosityLevel

using Logging = Logs::Logger<Logs::StdCout<>, ParseVerbosity<Logs::Message<>>>;
static Logging logs;

uint32_t findCommonFolderLength(const std::vector<String>& filenames) {
	if (filenames.empty())
		return 0;
	uint32_t len = 0;
	auto& firstElement = filenames[0];
	const char sep = IO::Separator;
	for (; ; ++len) {
		for (auto& filename: filenames) {
			if (len == firstElement.size())
				return len;
			if (len < filename.size() and filename[len] != '\0' and filename[len] == firstElement[len])
				continue;
			while (len > 0 and firstElement[--len] != sep) { // back to the last sep
			}
			return len;
		}
	}
	return len;
}

template<class F>
bool IterateThroughAllFiles(const std::vector<String>& filenames, const F& callback) {
	String tmpstr;
	uint32_t testOK = 0;
	uint32_t testFAILED = 0;
	int64_t maxCheckDuration = 0;
	int64_t startTime = DateTime::NowMilliSeconds();
	for (auto& filename: filenames) {
		int64_t duration = 0;
		if (callback(filename, duration))
			++testOK;
		else
			++testFAILED;
		if (duration > maxCheckDuration)
			maxCheckDuration = duration;
	}
	int64_t endTime = DateTime::NowMilliSeconds();
	uint32_t total = testOK + testFAILED;
	if (total > 0) {
		int64_t duration = (endTime - startTime);
		String durationStr;
		durationStr << " (in " << duration << "ms, max: " << maxCheckDuration << "ms)";
		if (total > 1) {
			if (0 != testFAILED) {
				switch (total) {
					case 1:
						logs.warning() << "-- FAILED -- 1 file, +" << testOK << ", -" << testFAILED << durationStr;
						break;
					default:
						logs.warning() << "-- FAILED -- " << total << " files, +" << testOK << ", -" << testFAILED << durationStr;
				}
			}
			else
			{
				switch (total) {
					case 1:
						logs.info() << "success: 1 file, +" << testOK << ", -0" << durationStr;
						break;
					default:
						logs.info() << "success: " << total << " files, +" << testOK << ", -0" << durationStr;
				}
			}
		}
	}
	else
		logs.warning() << "no input file";
	return (0 == testFAILED);
}

bool batchCheckIfFilenamesConformToGrammar(Settings& settings) {
	auto commonFolder = (settings.filenames.size() > 1 ? findCommonFolderLength(settings.filenames) : 0);
	if (0 != commonFolder)
		++commonFolder;
	return IterateThroughAllFiles(settings.filenames, [&](const AnyString& file, int64_t& duration) -> bool {
		String barefile;
		IO::ExtractFileName(barefile, file);
		bool expected = true;
		bool canfail = false;
		if (settings.useFilenameConvention)
		{
			if (barefile.startsWith("ko-"))
				expected = false;
			if (barefile.find("-canfail-") < barefile.size())
				canfail = true;
		}
		// PARSE
		int64_t start = DateTime::NowMilliSeconds();
		bool success = (nytrue == nytry_parse_file_n(file.c_str(), file.size()));
		duration = DateTime::NowMilliSeconds() - start;
		success = (success == expected);
		if (success and duration < 300) {
			logs.info() << AnyString{file, commonFolder} << " [" << duration << "ms]";
		}
		else {
			if (not success) {
				if (not canfail)
					logs.error() << AnyString{file, commonFolder} << " [" << duration << "ms]";
				else
					logs.warning() << AnyString{file, commonFolder} << " [" << duration << "ms, can fail]";
			}
			else
				logs.error() << AnyString{file, commonFolder} << " [" << duration << "ms - time limit reached]";
			success = canfail;
		}
		return success;
	});
}

std::vector<String> expandAndCanonicalizeFilenames(const std::vector<String>& filenames) {
	std::vector<String> filelist;
	filelist.reserve(filenames.size());
	String tmpstr;
	tmpstr.reserve(1024);
	for (auto& filename: filenames) {
		IO::Canonicalize(tmpstr, filename);
		switch (IO::TypeOf(tmpstr)) {
			case IO::typeFile: {
				filelist.emplace_back(tmpstr);
				break;
			}
			case IO::typeFolder: {
				ShortString16 ext;
				IO::Directory::Info info(tmpstr);
				auto end = info.recursive_file_end();
				for (auto i = info.recursive_file_begin(); i != end; ++i)
				{
					IO::ExtractExtension(ext, *i);
					if (ext == ".ny")
						filelist.emplace_back(i.filename());
				}
				break;
			}
			default:
				throw std::runtime_error((std::string("impossible to find '") += tmpstr.c_str()) += '\'');
		}
	}
	// for beauty in singled-threaded (and to always produce the same output)
	std::sort(filelist.begin(), filelist.end());
	return filelist;
}

bool parseCommandLine(Settings& settings, int argc, char** argv) {
	GetOpt::Parser options;
	std::vector<String> filenames;
	options.add(filenames, 'i', "input", "Input files (or folders)");
	options.remainingArguments(filenames);
	options.addFlag(settings.noColors, ' ', "no-color", "Disable color output");
	options.addFlag(settings.useFilenameConvention, ' ', "use-filename-convention",
		"Use the filename to determine if the test should succeed or not (should succeed if starting with 'ok-'");
	bool optVersion = false;
	options.addFlag(optVersion, ' ', "version", "Display the version of the compiler and exit");
	if (not options(argc, argv)) {
		// The program should not continue here
		// The user may have requested the help or an error has happened
		// If an error has happened, the exit status should be different from 0
		if (options.errors())
			throw std::runtime_error("Abort due to error");
		return false;
	}
	if (optVersion) {
		std::cout << "0.0\n";
		return false;
	}
	if (filenames.empty())
		throw std::runtime_error("no input file");
	settings.filenames = expandAndCanonicalizeFilenames(filenames);
	return true;
}

} // namespace

int main(int argc, char** argv)
{
	try {
		Settings settings;
		if (not parseCommandLine(settings, argc, argv))
			return EXIT_SUCCESS;
		bool success = batchCheckIfFilenamesConformToGrammar(settings);
		return success ? EXIT_SUCCESS : EXIT_FAILURE;
	}
	catch (const std::exception& e) {
		std::cerr << argv[0] << ": " << e.what() << '\n';
	}
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_SURFACE_IMPL_MLS_OMP_H_
#define PCL_SURFACE_IMPL_MLS_OMP_H_

#include <pcl/surface/mls_omp.h>

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename NormalOutT> void
pcl::MovingLeastSquaresOMP<PointInT, NormalOutT>::performReconstruction (PointCloudIn &output)
{
  // Compute the number of coefficients
  nr_coeff_ = (order_ + 1) * (order_ + 2) / 2;

  // Allocate enough space to hold the results of nearest neighbor searches
  // \note resize is irrelevant for a radiusSearch ().
  std::vector<int> nn_indices;
  std::vector<float> nn_sqr_dists;

#pragma omp parallel for schedule (dynamic, threads_)
  // For all points
  for (size_t cp = 0; cp < indices_->size (); ++cp)
  {
    // Get the initial estimates of point positions and their neighborhoods
    if (!searchForNeighbors ((*indices_)[cp], nn_indices, nn_sqr_dists))
      continue;

    // Check the number of nearest neighbors for normal estimation (and later
    // for polynomial fit as well)
    if (nn_indices.size () < 3)
      continue;

    PointCloudIn projected_points;
    NormalCloudOut projected_points_normals;
    // Get a plane approximating the local surface's tangent and project point onto it
    computeMLSPointNormal ((*indices_)[cp], *input_, nn_indices, nn_sqr_dists, projected_points, projected_points_normals);

    // Append projected points to output
    output.insert (output.end (), projected_points.begin (), projected_points.end ());
    normals_->insert (normals_->end (), projected_points_normals.begin (), projected_points_normals.end ());
  }

  // Set proper widths and heights for the clouds
  if (upsample_method_ == MovingLeastSquares<PointInT, NormalOutT>::NONE && fake_indices_)
  {
    normals_->width = input_->width;
    normals_->height = input_->height;
    output.width = input_->width;
    output.height = input_->height;
  }
  else
  {
    normals_->height = 1;
    normals_->width = normals_->size ();
    output.height = 1;
    output.width = output.size ();
  }
}

#define PCL_INSTANTIATE_MovingLeastSquaresOMP(T,OutT) template class PCL_EXPORTS pcl::MovingLeastSquaresOMP<T,OutT>;

#endif    // PCL_SURFACE_IMPL_MLS_OMP_H_

<commit_msg>fixed compilation for windows: index variable in OpenMP 'for' statement must have signed integral type<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_SURFACE_IMPL_MLS_OMP_H_
#define PCL_SURFACE_IMPL_MLS_OMP_H_

#include <cstddef>
#include <pcl/surface/mls_omp.h>

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename NormalOutT> void
pcl::MovingLeastSquaresOMP<PointInT, NormalOutT>::performReconstruction (PointCloudIn &output)
{
  typedef std::size_t size_t;
  // Compute the number of coefficients
  nr_coeff_ = (order_ + 1) * (order_ + 2) / 2;

  // Allocate enough space to hold the results of nearest neighbor searches
  // \note resize is irrelevant for a radiusSearch ().
  std::vector<int> nn_indices;
  std::vector<float> nn_sqr_dists;

#pragma omp parallel for schedule (dynamic, threads_)
  // For all points
  for (int cp = 0; cp < (int)indices_->size (); ++cp)
  {
    // Get the initial estimates of point positions and their neighborhoods
    if (!searchForNeighbors ((*indices_)[cp], nn_indices, nn_sqr_dists))
      continue;

    // Check the number of nearest neighbors for normal estimation (and later
    // for polynomial fit as well)
    if (nn_indices.size () < 3)
      continue;

    PointCloudIn projected_points;
    NormalCloudOut projected_points_normals;
    // Get a plane approximating the local surface's tangent and project point onto it
    computeMLSPointNormal ((*indices_)[cp], *input_, nn_indices, nn_sqr_dists, projected_points, projected_points_normals);

    // Append projected points to output
    output.insert (output.end (), projected_points.begin (), projected_points.end ());
    normals_->insert (normals_->end (), projected_points_normals.begin (), projected_points_normals.end ());
  }

  // Set proper widths and heights for the clouds
  if (upsample_method_ == MovingLeastSquares<PointInT, NormalOutT>::NONE && fake_indices_)
  {
    normals_->width = input_->width;
    normals_->height = input_->height;
    output.width = input_->width;
    output.height = input_->height;
  }
  else
  {
    normals_->height = 1;
    normals_->width = normals_->size ();
    output.height = 1;
    output.width = output.size ();
  }
}

#define PCL_INSTANTIATE_MovingLeastSquaresOMP(T,OutT) template class PCL_EXPORTS pcl::MovingLeastSquaresOMP<T,OutT>;

#endif    // PCL_SURFACE_IMPL_MLS_OMP_H_

<|endoftext|>