<commit_before>#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include "Sleepy.h" //https://github.com/kinasmith/Sleepy
#include "RFM69_ATC.h"
#include "SPIFlash_Marzogh.h"
#include <EEPROM.h>
#include "Adafruit_MAX31856.h"

#define NODEID 11
#define GATEWAYID 0
#define FREQUENCY RF69_433MHZ //frequency of radio
#define ATC_RSSI -70 //ideal Signal Strength of trasmission
#define ACK_WAIT_TIME 100 // # of ms to wait for an ack
#define ACK_RETRIES 10 // # of attempts before giving up
#define SERIAL_BAUD 9600 // Serial comms rate
#define FLASH_CAPACITY 524288

#define LED 9
#define LED2 A0
#define N_SEL_1 A1
#define N_SEL_2 A2
#define N_SEL_4 A3
#define BAT_V A7
#define BAT_EN 3
#define HEATER_EN 4
#define TC1_CS 7
#define TC2_CS 6
#define TC3_CS 5
#define FLASH_CS 8
#define RFM_CS 10

#define SERIAL_EN //Comment this out to remove Serial comms and save a few kb's of space

#ifdef SERIAL_EN
#define DEBUG(input)   {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#define DEBUGFlush() { Serial.flush(); }
#else
#define DEBUG(input);
#define DEBUGln(input);
#define DEBUGFlush();
#endif

ISR(WDT_vect) { Sleepy::watchdogEvent(); }
/*==============|| FUNCTIONS ||==============*/
bool getTime();
void Blink(uint8_t);
void sendFromFlash();
void writeToFlash();
uint8_t setAddress();
float getBatteryVoltage(uint8_t pin, uint8_t en);
bool saveEEPROMTime();
uint32_t getEEPROMTime();
void takeMeasurements();
/*==============|| RFM69 ||==============*/
RFM69_ATC radio; //init radio
uint8_t NETWORKID = 100; //base network address
uint8_t attempt_cnt = 0;
bool HANDSHAKE_SENT;
/*==============|| MEMORY ||==============*/
SPIFlash_Marzogh flash(8);
uint32_t FLASH_ADDR = 0;
uint16_t EEPROM_ADDR = 0;
/*==============|| THERMOCOUPLE ||==============*/
Adafruit_MAX31856 tc1 = Adafruit_MAX31856(TC1_CS);
Adafruit_MAX31856 tc2 = Adafruit_MAX31856(TC2_CS);
Adafruit_MAX31856 tc3 = Adafruit_MAX31856(TC3_CS);
/*==============|| UTIL ||==============*/
bool LED_STATE;
uint16_t count = 0;
uint8_t sentMeasurement = 0;
/*==============|| INTERVAL ||==============*/
const uint8_t REC_MIN = 1; //record interval in minutes
const uint16_t REC_MS = 60000;
const uint16_t REC_INTERVAL = (60000*REC_MIN)/1000; //record interval in seconds
/*==============|| DATA ||==============*/
//Data structure for transmitting the Timestamp from datalogger to sensor (4 bytes)
struct TimeStamp {
	uint32_t timestamp;
};
TimeStamp theTimeStamp; //creates global instantiation of this

//Data structure for storing data locally (12 bytes)
struct Data {
	uint16_t count;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
	int16_t brd_tmp;
	int16_t bat_v;
};

//Data Structure for transmitting data packets to datalogger (16 bytes)
struct Payload {
	uint32_t timestamp;
	uint16_t count;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
	int16_t brd_tmp;
	int16_t bat_v;
};
Payload thePayload;

struct Measurement {
	uint32_t time;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
};

uint32_t current_time;
uint32_t stop_saved_time = 0;
uint32_t log_saved_time = 0;
uint32_t h_saved_time = 0;
uint16_t h_interval = 0;
uint16_t log_interval = 1000;
uint16_t h_pulse_on = 6000;
uint32_t h_pulse_off = 30 * 60000L;
uint16_t stop_time = 30000;
uint8_t h_status = 0;

void setup()
{
	#ifdef SERIAL_EN
		Serial.begin(SERIAL_BAUD);
	#endif
	randomSeed(analogRead(A4)); //set random seed
	NETWORKID += setAddress();
	radio.initialize(FREQUENCY,NODEID,NETWORKID);
	radio.setHighPower();
	radio.encrypt(null);
	radio.enableAutoPower(ATC_RSSI); //Test to see if this is actually working at some point
	DEBUG("--Transmitting on Network: "); DEBUG(NETWORKID); DEBUG(", as Node: "); DEBUGln(NODEID);
	pinMode(LED, OUTPUT);
	//Ping the datalogger. If it's alive, it will return the current time. If not, wait and try again.
	digitalWrite(LED, HIGH); //write LED high to signal attempting connection
	while(!getTime()) { //this saves time to the struct which holds the time globally
		radio.sleep();
		DEBUGFlush();
		delay(10000);
	}
	digitalWrite(LED, LOW); //write low to signal success
	DEBUG("--Time is: "); DEBUG(theTimeStamp.timestamp); DEBUGln("--");
	DEBUG("--Flash Mem: ");
	flash.begin();
	uint16_t _name = flash.getChipName();
	uint32_t capacity = flash.getCapacity();
	DEBUG("W25X"); DEBUG(_name); DEBUG("**  ");
	DEBUG("capacity: "); DEBUG(capacity); DEBUGln(" bytes");
	DEBUGln("Erasing Chip!"); flash.eraseChip();
  tc1.begin(); tc2.begin(); tc3.begin();
  tc1.setThermocoupleType(MAX31856_TCTYPE_E);
  tc2.setThermocoupleType(MAX31856_TCTYPE_E);
  tc3.setThermocoupleType(MAX31856_TCTYPE_E);
	DEBUGln("--Thermocouples are engaged");
}

void loop()
{
	if(sentMeasurement) {
		DEBUG("sleep - sleeping for "); DEBUG(REC_INTERVAL); DEBUG(" seconds"); DEBUGln();
		DEBUGFlush();
		radio.sleep();
		count++;
		for(int i = 0; i < REC_MIN; i++)
			Sleepy::loseSomeTime(REC_MS);
		//===========|| MCU WAKES UP HERE
		//===========|| RESET TIMER VALUES
		sentMeasurement = 0;
		current_time = millis();
		stop_saved_time = current_time;
		h_saved_time = current_time;
		log_saved_time = current_time;
		h_interval = 0;
	} else {
		current_time = millis();
		if(stop_saved_time + stop_time > current_time) {
			if (h_saved_time + h_interval < current_time){
				if(h_status == 0) { //if it is off, turn it on
					// digitalWrite(HEATER_EN, HIGH);
					h_interval = h_pulse_on; //wait for ON time
					h_status = 1;
					DEBUG("Heater - On for "); DEBUG(h_interval/1000); DEBUGln("s");
				} else if(h_status == 1) {//if heat is on....turn it off
						// digitalWrite(HEATER_EN, LOW);
						h_interval = h_pulse_off; //wait for OFF time
						h_status = 0;
					DEBUG("Heater - Off for "); DEBUG(h_interval/1000); DEBUGln("s");
				}
				h_saved_time = current_time;
			}
			if(log_saved_time + log_interval < current_time) {
				Measurement thisMeasurement;
				thisMeasurement.time = 2500;
				thisMeasurement.tc1 = 15;
				thisMeasurement.tc2 = 72;
				thisMeasurement.tc3 = 345;
				delay(500);
				if(flash.writeAnything(FLASH_ADDR, thisMeasurement)) {
					DEBUGln("--> Data Written");
				}
				FLASH_ADDR += sizeof(thisMeasurement);
				DEBUGln(FLASH_ADDR);
				log_saved_time = current_time;
			}
		} else {
			DEBUGln("SEND MEASUREMENTS");
			sentMeasurement = 1;
		}
	}
}

/**
 * [getTime description]
 * @return [description]
 */
bool getTime() {
	LED_STATE = true;
	digitalWrite(LED, LED_STATE);
	//Get the current timestamp from the datalogger
	bool TIME_RECIEVED = false;
	if(!HANDSHAKE_SENT) { //Send request for time to the Datalogger
		DEBUG("time - ");
		if (radio.sendWithRetry(GATEWAYID, "t", 1)) {
			DEBUG("snd . . ");
			HANDSHAKE_SENT = true;
		}
		else {
			DEBUGln("failed . . . no ack");
			return false; //if there is no response, returns false and exits function
		}
	}
	while(!TIME_RECIEVED && HANDSHAKE_SENT) { //Wait for the time to be returned
		if (radio.receiveDone()) {
			if (radio.DATALEN == sizeof(theTimeStamp)) { //check to make sure it's the right size
				theTimeStamp = *(TimeStamp*)radio.DATA; //save data
				DEBUG(" rcv - "); DEBUG('['); DEBUG(radio.SENDERID); DEBUG("] ");
				DEBUG(theTimeStamp.timestamp);
				DEBUG(" [RX_RSSI:"); DEBUG(radio.RSSI); DEBUG("]");
				DEBUGln();
				TIME_RECIEVED = true;
				LED_STATE = false;
				digitalWrite(LED, LED_STATE);
			}
			if (radio.ACKRequested()) radio.sendACK();
		}
	}
	HANDSHAKE_SENT = false;
	return true;
}
/**
 * [Blink description]
 * @param t [description]
 */
void Blink(uint8_t t) {
	LED_STATE = !LED_STATE;
	digitalWrite(LED, LED_STATE);
	delay(t);
	LED_STATE = !LED_STATE;
	digitalWrite(LED, LED_STATE);
	delay(t);
}
/**
 * [setAddress description]
 * @return [description]
 */
uint8_t setAddress() {
	//sets network address based on which solder jumpers are closed
	uint8_t addr01, addr02, addr03;
	pinMode(N_SEL_1, INPUT_PULLUP);
	pinMode(N_SEL_2, INPUT_PULLUP);
	pinMode(N_SEL_4, INPUT_PULLUP);
	addr01 = !digitalRead(N_SEL_1);
	addr02 = !digitalRead(N_SEL_2) * 2;
	addr03 = !digitalRead(N_SEL_4) * 4;
	pinMode(N_SEL_1, OUTPUT);
	pinMode(N_SEL_2, OUTPUT);
	pinMode(N_SEL_4, OUTPUT);
	digitalWrite(N_SEL_1, HIGH);
	digitalWrite(N_SEL_2, HIGH);
	digitalWrite(N_SEL_4, HIGH);
	uint8_t addr = addr01 | addr02 | addr03;
	return addr;
}
<commit_msg>everything is STILL FUCKED<commit_after>#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include "Sleepy.h" //https://github.com/kinasmith/Sleepy
#include "RFM69_ATC.h"
#include "SPIFlash_Marzogh.h"
#include <EEPROM.h>
#include "Adafruit_MAX31856.h"

#define NODEID 11
#define GATEWAYID 0
#define FREQUENCY RF69_433MHZ //frequency of radio
#define ATC_RSSI -70 //ideal Signal Strength of trasmission
#define ACK_WAIT_TIME 100 // # of ms to wait for an ack
#define ACK_RETRIES 10 // # of attempts before giving up
#define SERIAL_BAUD 9600 // Serial comms rate
#define FLASH_CAPACITY 524288

#define LED 9
#define LED2 A0
#define N_SEL_1 A1
#define N_SEL_2 A2
#define N_SEL_4 A3
#define BAT_V A7
#define BAT_EN 3
#define HEATER_EN 4
#define TC1_CS 7
#define TC2_CS 6
#define TC3_CS 5
#define FLASH_CS 8
#define RFM_CS 10

#define SERIAL_EN //Comment this out to remove Serial comms and save a few kb's of space

#ifdef SERIAL_EN
#define DEBUG(input)   {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#define DEBUGFlush() { Serial.flush(); }
#else
#define DEBUG(input);
#define DEBUGln(input);
#define DEBUGFlush();
#endif

ISR(WDT_vect) { Sleepy::watchdogEvent(); }
/*==============|| FUNCTIONS ||==============*/
bool getTime();
void Blink(uint8_t);
void sendFromFlash();
void writeToFlash();
uint8_t setAddress();
float getBatteryVoltage(uint8_t pin, uint8_t en);
bool saveEEPROMTime();
uint32_t getEEPROMTime();
void takeMeasurements();
/*==============|| RFM69 ||==============*/
RFM69_ATC radio; //init radio
uint8_t NETWORKID = 100; //base network address
uint8_t attempt_cnt = 0;
bool HANDSHAKE_SENT;
/*==============|| MEMORY ||==============*/
SPIFlash_Marzogh flash(8);
uint32_t FLASH_ADDR = 100;
uint16_t EEPROM_ADDR = 0;
/*==============|| THERMOCOUPLE ||==============*/
Adafruit_MAX31856 tc1 = Adafruit_MAX31856(TC1_CS);
Adafruit_MAX31856 tc2 = Adafruit_MAX31856(TC2_CS);
Adafruit_MAX31856 tc3 = Adafruit_MAX31856(TC3_CS);
/*==============|| UTIL ||==============*/
bool LED_STATE;
uint16_t count = 0;
uint8_t sentMeasurement = 0;
/*==============|| INTERVAL ||==============*/
const uint8_t REC_MIN = 1; //record interval in minutes
const uint16_t REC_MS = 30000;
const uint16_t REC_INTERVAL = (30000*REC_MIN)/1000; //record interval in seconds
/*==============|| DATA ||==============*/
//Data structure for transmitting the Timestamp from datalogger to sensor (4 bytes)
struct TimeStamp {
	uint32_t timestamp;
};
TimeStamp theTimeStamp; //creates global instantiation of this

//Data structure for storing data locally (12 bytes)
struct Data {
	uint16_t count;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
	int16_t brd_tmp;
	int16_t bat_v;
};

//Data Structure for transmitting data packets to datalogger (16 bytes)
struct Payload {
	uint32_t timestamp;
	uint16_t count;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
	int16_t brd_tmp;
	int16_t bat_v;
};
Payload thePayload;

struct Measurement {
	uint32_t time;
	int16_t tc1;
	int16_t tc2;
	int16_t tc3;
};

uint32_t current_time;
uint32_t stop_saved_time = 0;
uint32_t log_saved_time = 0;
uint32_t h_saved_time = 0;
uint16_t h_interval = 0;
uint16_t log_interval = 1000;
uint16_t h_pulse_on = 6000;
uint32_t h_pulse_off = 30 * 60000L;
uint16_t stop_time = 30000;
uint8_t h_status = 0;

void setup()
{
	#ifdef SERIAL_EN
		Serial.begin(SERIAL_BAUD);
	#endif
	randomSeed(analogRead(A4)); //set random seed
	NETWORKID += setAddress();
	radio.initialize(FREQUENCY,NODEID,NETWORKID);
	radio.setHighPower();
	radio.encrypt(null);
	radio.enableAutoPower(ATC_RSSI); //Test to see if this is actually working at some point
	DEBUG("--Transmitting on Network: "); DEBUG(NETWORKID); DEBUG(", as Node: "); DEBUGln(NODEID);
	pinMode(LED, OUTPUT);
	//Ping the datalogger. If it's alive, it will return the current time. If not, wait and try again.
	digitalWrite(LED, HIGH); //write LED high to signal attempting connection
	while(!getTime()) { //this saves time to the struct which holds the time globally
		radio.sleep();
		DEBUGFlush();
		delay(10000);
	}
	digitalWrite(LED, LOW); //write low to signal success
	DEBUG("--Time is: "); DEBUG(theTimeStamp.timestamp); DEBUGln("--");
	DEBUG("--Flash Mem: ");
	flash.begin();
	uint16_t _name = flash.getChipName();
	uint32_t capacity = flash.getCapacity();
	DEBUG("W25X"); DEBUG(_name); DEBUG("**  ");
	DEBUG("capacity: "); DEBUG(capacity); DEBUGln(" bytes");
	DEBUGln("Erasing Chip!");
	while(!flash.eraseChip()) {
		DEBUGln("Erasing Chip!");
	}
  tc1.begin(); tc2.begin(); tc3.begin();
  tc1.setThermocoupleType(MAX31856_TCTYPE_E);
  tc2.setThermocoupleType(MAX31856_TCTYPE_E);
  tc3.setThermocoupleType(MAX31856_TCTYPE_E);
	DEBUGln("--Thermocouples are engaged");
}

void loop()
{
	if(sentMeasurement) {
		DEBUG("sleep - sleeping for "); DEBUG(REC_INTERVAL); DEBUG(" seconds"); DEBUGln();
		DEBUGFlush();
		radio.sleep();
		count++;
		for(int i = 0; i < REC_MIN; i++)
			Sleepy::loseSomeTime(REC_MS);
		//===========|| MCU WAKES UP HERE
		//===========|| RESET TIMER VALUES
		sentMeasurement = 0;
		current_time = millis();
		stop_saved_time = current_time;
		h_saved_time = current_time;
		log_saved_time = current_time;
		h_interval = 0;
	} else {
		current_time = millis();
		if(stop_saved_time + stop_time > current_time) {
			if (h_saved_time + h_interval < current_time){
				if(h_status == 0) { //if it is off, turn it on
					digitalWrite(HEATER_EN, HIGH);
					h_interval = h_pulse_on; //wait for ON time
					h_status = 1;
					DEBUG("Heater - On for "); DEBUG(h_interval/1000); DEBUGln("s");
				} else if(h_status == 1) {//if heat is on....turn it off
						digitalWrite(HEATER_EN, LOW);
						h_interval = h_pulse_off; //wait for OFF time
						h_status = 0;
					DEBUG("Heater - Off for "); DEBUG(h_interval/1000); DEBUGln("s");
				}
				h_saved_time = current_time;
			}
			if(log_saved_time + log_interval < current_time) {
				// Measurement thisMeasurement;
				// thisMeasurement.time = 2500;
				// thisMeasurement.tc1 = 15;
				// thisMeasurement.tc2 = 72;
				// thisMeasurement.tc3 = 345;
				delay(500);
				if(flash.writeAnything(FLASH_ADDR, FLASH_ADDR)) {
					DEBUGln("--> Data Written");
				}
				FLASH_ADDR += sizeof(FLASH_ADDR);
				DEBUGln(FLASH_ADDR);
				log_saved_time = current_time;
			}
		} else {
			DEBUGln("SEND MEASUREMENTS");
			sentMeasurement = 1;
		}
	}
}

/**
 * [getTime description]
 * @return [description]
 */
bool getTime() {
	LED_STATE = true;
	digitalWrite(LED, LED_STATE);
	//Get the current timestamp from the datalogger
	bool TIME_RECIEVED = false;
	if(!HANDSHAKE_SENT) { //Send request for time to the Datalogger
		DEBUG("time - ");
		if (radio.sendWithRetry(GATEWAYID, "t", 1)) {
			DEBUG("snd . . ");
			HANDSHAKE_SENT = true;
		}
		else {
			DEBUGln("failed . . . no ack");
			return false; //if there is no response, returns false and exits function
		}
	}
	while(!TIME_RECIEVED && HANDSHAKE_SENT) { //Wait for the time to be returned
		if (radio.receiveDone()) {
			if (radio.DATALEN == sizeof(theTimeStamp)) { //check to make sure it's the right size
				theTimeStamp = *(TimeStamp*)radio.DATA; //save data
				DEBUG(" rcv - "); DEBUG('['); DEBUG(radio.SENDERID); DEBUG("] ");
				DEBUG(theTimeStamp.timestamp);
				DEBUG(" [RX_RSSI:"); DEBUG(radio.RSSI); DEBUG("]");
				DEBUGln();
				TIME_RECIEVED = true;
				LED_STATE = false;
				digitalWrite(LED, LED_STATE);
			}
			if (radio.ACKRequested()) radio.sendACK();
		}
	}
	HANDSHAKE_SENT = false;
	return true;
}
/**
 * [Blink description]
 * @param t [description]
 */
void Blink(uint8_t t) {
	LED_STATE = !LED_STATE;
	digitalWrite(LED, LED_STATE);
	delay(t);
	LED_STATE = !LED_STATE;
	digitalWrite(LED, LED_STATE);
	delay(t);
}
/**
 * [setAddress description]
 * @return [description]
 */
uint8_t setAddress() {
	//sets network address based on which solder jumpers are closed
	uint8_t addr01, addr02, addr03;
	pinMode(N_SEL_1, INPUT_PULLUP);
	pinMode(N_SEL_2, INPUT_PULLUP);
	pinMode(N_SEL_4, INPUT_PULLUP);
	addr01 = !digitalRead(N_SEL_1);
	addr02 = !digitalRead(N_SEL_2) * 2;
	addr03 = !digitalRead(N_SEL_4) * 4;
	pinMode(N_SEL_1, OUTPUT);
	pinMode(N_SEL_2, OUTPUT);
	pinMode(N_SEL_4, OUTPUT);
	digitalWrite(N_SEL_1, HIGH);
	digitalWrite(N_SEL_2, HIGH);
	digitalWrite(N_SEL_4, HIGH);
	uint8_t addr = addr01 | addr02 | addr03;
	return addr;
}
<|endoftext|>


<commit_before>#ifndef ROBOCUP2DSIM_ENGINE_PHYSICS_HXX
#define ROBOCUP2DSIM_ENGINE_PHYSICS_HXX

#include <utility>
#include <Box2D/Dynamics/b2Body.h>
#include <Box2D/Dynamics/b2WorldCallbacks.h>
#include <Box2D/Dynamics/Contacts/b2Contact.h>
#include <robocup2Dsim/runtime/resource.hh>

namespace robocup2Dsim {
namespace engine {

template <class contact_category_t>
contact_config<contact_category_t>::contact_config(
	contact_result initial,
	contact_result from_same_entity)
    :
	config_(initial == contact_result::collide
		? std::numeric_limits<decltype(b2Filter::categoryBits)>::max()
		: std::numeric_limits<decltype(b2Filter::categoryBits)>::min()),
	from_same_entity_(from_same_entity)
{ }

template <class contact_category_t>
decltype(b2Filter::categoryBits) contact_config<contact_category_t>::to_uint() const
{
    return config_.to_ulong();
}

template <class contact_category_t>
contact_result contact_config<contact_category_t>::get_from_same_entity_config() const
{
    return from_same_entity_;
}

template <class contact_category_t>
contact_result contact_config<contact_category_t>::get(contact_category_type category) const
{
    return config_[static_cast<category_underlying_type>(category)]
	? contact_result::collide
	: contact_result::pass_over;
}

template <class contact_category_t>
void contact_config<contact_category_t>::set(contact_category_type category, contact_result contact)
{
    switch (contact)
    {
	case contact_result::collide:
	{
	    config_.set(static_cast<category_underlying_type>(category), true);
	    break;
	}
	case contact_result::pass_over:
	{
	    config_.set(static_cast<category_underlying_type>(category), false);
	    break;
	}
	default:
	{
	    break;
	}
    }
}

namespace {

using namespace robocup2Dsim::engine;
namespace rru = robocup2Dsim::runtime;

void set_fixture_data(physics::fixture_def& def, rru::ecs_db::entity_id_type entity_id, physics::fixture_id_type fixture_id)
{
    std::uintptr_t data = fixture_id;
    data <<= std::numeric_limits<rru::ecs_db::entity_id_type>::digits;
    data |= entity_id;
    def.userData = reinterpret_cast<void*>(data);
}

rru::ecs_db::entity_id_type get_entity_id(const b2Fixture& fixture)
{
    std::uintptr_t mask = 0U;
    mask |= std::numeric_limits<rru::ecs_db::entity_id_type>::max();
    return reinterpret_cast<std::uintptr_t>(fixture.GetUserData()) & mask;
}

physics::fixture_id_type get_fixture_id(const b2Fixture& fixture)
{
    std::uintptr_t mask = 0U;
    mask |= std::numeric_limits<physics::fixture_id_type>::max();
    std::uintptr_t raw_data = reinterpret_cast<std::uintptr_t>(fixture.GetUserData());
    return (raw_data >> std::numeric_limits<rru::ecs_db::entity_id_type>::digits) & mask;
}

template <typename collision_func_t, typename separation_func_t>
struct contact_listener : public b2ContactListener
{
    typedef collision_func_t collision_func_type;
    typedef separation_func_t separation_func_type;
    contact_listener(collision_func_type&& collision, separation_func_t&& separation);
    virtual void BeginContact(b2Contact* contact);
    virtual void EndContact(b2Contact* contact);
    collision_func_t on_collision;
    separation_func_t on_separation;
};

template <typename c, typename s>
contact_listener<c, s>::contact_listener(collision_func_type&& collision, separation_func_type&& separation)
    :
	on_collision(std::forward<collision_func_type>(collision)),
	on_separation(std::forward<separation_func_type>(separation))
{ }

template <typename c, typename s>
void contact_listener<c, s>::BeginContact(b2Contact* contact)
{
    if (contact)
    {
	physics::contact_participant participant_a{
		get_entity_id(*(contact->GetFixtureA())),
		get_fixture_id(*(contact->GetFixtureA())),
		*(contact->GetFixtureA()->GetBody())};
	physics::contact_participant participant_b{
		get_entity_id(*(contact->GetFixtureB())),
		get_fixture_id(*(contact->GetFixtureB())),
		*(contact->GetFixtureB()->GetBody())};
	on_collision(participant_a, participant_b);
    }
}

template <typename c, typename s>
void contact_listener<c, s>::EndContact(b2Contact* contact)
{
    if (contact)
    {
	physics::contact_participant participant_a{
		get_entity_id(*(contact->GetFixtureA())),
		get_fixture_id(*(contact->GetFixtureA())),
		*(contact->GetFixtureA()->GetBody())};
	physics::contact_participant participant_b{
		get_entity_id(*(contact->GetFixtureB())),
		get_fixture_id(*(contact->GetFixtureB())),
		*(contact->GetFixtureB()->GetBody())};
	on_separation(participant_a, participant_b);
    }
}

} // anonyous namespace

template <class contact_category_t>
typename physics::fixture_def physics::make_fixture_def(
	robocup2Dsim::runtime::ecs_db::entity_id_type entity_id,
	fixture_id_type fixture_id,
	contact_category_t category,
	const contact_config<contact_category_t>& contact)
{
    fixture_def result;
    result.filter.categoryBits = 1U << static_cast<typename contact_config<contact_category_t>::category_underlying_type>(category);
    result.filter.maskBits = contact.to_uint();
    if (contact.get_from_same_entity_config() == contact_result::pass_over)
    {
	result.filter.groupIndex = entity_id * -1;
    }
    set_fixture_data(result, entity_id, fixture_id);
    return result;
}

template <class joint_t, class def_t>
void physics::make_joint(const def_t& def)
{
    joint_t* result = static_cast<joint_t*>(world_.CreateJoint(&def));
    for (const fixture* fix = result->GetBodyA()->GetFixtureList(); fix != nullptr; fix = fix->GetNext())
    {
	if (fix != nullptr)
	{
	    result->SetUserData(reinterpret_cast<void*>(static_cast<std::uintptr_t>(get_entity_id(*fix))));
	    break;
	}
    }
}

template <typename collision_func_t, typename separation_func_t>
void physics::step(float time_step, collision_func_t&& on_collision, separation_func_t&& on_separation)
{
    contact_listener<collision_func_t, separation_func_t> listener(
	    std::forward<collision_func_t>(on_collision),
	    std::forward<separation_func_t>(on_separation));
    world_.SetContactListener(&listener);
    world_.Step(time_step, solver_conf_.velocity_iteration_limit, solver_conf_.position_iteration_limit);
    world_.SetContactListener(nullptr);
}

} // namespace engine
} // namespace robocup2Dsim

#endif
<commit_msg>fixed a defect where fixtures from the same entity were colliding when the entity ID is 0 because groupIndex cannot be 0 when pass over is desired<commit_after>#ifndef ROBOCUP2DSIM_ENGINE_PHYSICS_HXX
#define ROBOCUP2DSIM_ENGINE_PHYSICS_HXX

#include <utility>
#include <Box2D/Dynamics/b2Body.h>
#include <Box2D/Dynamics/b2WorldCallbacks.h>
#include <Box2D/Dynamics/Contacts/b2Contact.h>
#include <robocup2Dsim/runtime/resource.hh>

namespace robocup2Dsim {
namespace engine {

template <class contact_category_t>
contact_config<contact_category_t>::contact_config(
	contact_result initial,
	contact_result from_same_entity)
    :
	config_(initial == contact_result::collide
		? std::numeric_limits<decltype(b2Filter::categoryBits)>::max()
		: std::numeric_limits<decltype(b2Filter::categoryBits)>::min()),
	from_same_entity_(from_same_entity)
{ }

template <class contact_category_t>
decltype(b2Filter::categoryBits) contact_config<contact_category_t>::to_uint() const
{
    return config_.to_ulong();
}

template <class contact_category_t>
contact_result contact_config<contact_category_t>::get_from_same_entity_config() const
{
    return from_same_entity_;
}

template <class contact_category_t>
contact_result contact_config<contact_category_t>::get(contact_category_type category) const
{
    return config_[static_cast<category_underlying_type>(category)]
	? contact_result::collide
	: contact_result::pass_over;
}

template <class contact_category_t>
void contact_config<contact_category_t>::set(contact_category_type category, contact_result contact)
{
    switch (contact)
    {
	case contact_result::collide:
	{
	    config_.set(static_cast<category_underlying_type>(category), true);
	    break;
	}
	case contact_result::pass_over:
	{
	    config_.set(static_cast<category_underlying_type>(category), false);
	    break;
	}
	default:
	{
	    break;
	}
    }
}

namespace {

using namespace robocup2Dsim::engine;
namespace rru = robocup2Dsim::runtime;

void set_fixture_data(physics::fixture_def& def, rru::ecs_db::entity_id_type entity_id, physics::fixture_id_type fixture_id)
{
    std::uintptr_t data = fixture_id;
    data <<= std::numeric_limits<rru::ecs_db::entity_id_type>::digits;
    data |= entity_id;
    def.userData = reinterpret_cast<void*>(data);
}

rru::ecs_db::entity_id_type get_entity_id(const b2Fixture& fixture)
{
    std::uintptr_t mask = 0U;
    mask |= std::numeric_limits<rru::ecs_db::entity_id_type>::max();
    return reinterpret_cast<std::uintptr_t>(fixture.GetUserData()) & mask;
}

physics::fixture_id_type get_fixture_id(const b2Fixture& fixture)
{
    std::uintptr_t mask = 0U;
    mask |= std::numeric_limits<physics::fixture_id_type>::max();
    std::uintptr_t raw_data = reinterpret_cast<std::uintptr_t>(fixture.GetUserData());
    return (raw_data >> std::numeric_limits<rru::ecs_db::entity_id_type>::digits) & mask;
}

template <typename collision_func_t, typename separation_func_t>
struct contact_listener : public b2ContactListener
{
    typedef collision_func_t collision_func_type;
    typedef separation_func_t separation_func_type;
    contact_listener(collision_func_type&& collision, separation_func_t&& separation);
    virtual void BeginContact(b2Contact* contact);
    virtual void EndContact(b2Contact* contact);
    collision_func_t on_collision;
    separation_func_t on_separation;
};

template <typename c, typename s>
contact_listener<c, s>::contact_listener(collision_func_type&& collision, separation_func_type&& separation)
    :
	on_collision(std::forward<collision_func_type>(collision)),
	on_separation(std::forward<separation_func_type>(separation))
{ }

template <typename c, typename s>
void contact_listener<c, s>::BeginContact(b2Contact* contact)
{
    if (contact)
    {
	physics::contact_participant participant_a{
		get_entity_id(*(contact->GetFixtureA())),
		get_fixture_id(*(contact->GetFixtureA())),
		*(contact->GetFixtureA()->GetBody())};
	physics::contact_participant participant_b{
		get_entity_id(*(contact->GetFixtureB())),
		get_fixture_id(*(contact->GetFixtureB())),
		*(contact->GetFixtureB()->GetBody())};
	on_collision(participant_a, participant_b);
    }
}

template <typename c, typename s>
void contact_listener<c, s>::EndContact(b2Contact* contact)
{
    if (contact)
    {
	physics::contact_participant participant_a{
		get_entity_id(*(contact->GetFixtureA())),
		get_fixture_id(*(contact->GetFixtureA())),
		*(contact->GetFixtureA()->GetBody())};
	physics::contact_participant participant_b{
		get_entity_id(*(contact->GetFixtureB())),
		get_fixture_id(*(contact->GetFixtureB())),
		*(contact->GetFixtureB()->GetBody())};
	on_separation(participant_a, participant_b);
    }
}

static constexpr std::uint16_t group_index_offset = 1U;

} // anonyous namespace

template <class contact_category_t>
typename physics::fixture_def physics::make_fixture_def(
	robocup2Dsim::runtime::ecs_db::entity_id_type entity_id,
	fixture_id_type fixture_id,
	contact_category_t category,
	const contact_config<contact_category_t>& contact)
{
    fixture_def result;
    result.filter.categoryBits = 1U << static_cast<typename contact_config<contact_category_t>::category_underlying_type>(category);
    result.filter.maskBits = contact.to_uint();
    if (contact.get_from_same_entity_config() == contact_result::pass_over)
    {
        // to achieve pass over the groupIndex cannot be 0
	result.filter.groupIndex = (entity_id + group_index_offset) * -1;
    }
    set_fixture_data(result, entity_id, fixture_id);
    return result;
}

template <class joint_t, class def_t>
void physics::make_joint(const def_t& def)
{
    joint_t* result = static_cast<joint_t*>(world_.CreateJoint(&def));
    for (const fixture* fix = result->GetBodyA()->GetFixtureList(); fix != nullptr; fix = fix->GetNext())
    {
	if (fix != nullptr)
	{
	    result->SetUserData(reinterpret_cast<void*>(static_cast<std::uintptr_t>(get_entity_id(*fix))));
	    break;
	}
    }
}

template <typename collision_func_t, typename separation_func_t>
void physics::step(float time_step, collision_func_t&& on_collision, separation_func_t&& on_separation)
{
    contact_listener<collision_func_t, separation_func_t> listener(
	    std::forward<collision_func_t>(on_collision),
	    std::forward<separation_func_t>(on_separation));
    world_.SetContactListener(&listener);
    world_.Step(time_step, solver_conf_.velocity_iteration_limit, solver_conf_.position_iteration_limit);
    world_.SetContactListener(nullptr);
}

} // namespace engine
} // namespace robocup2Dsim

#endif
<|endoftext|>


<commit_before>#include "Element.h"

#include <iostream>

using namespace Eigen;
using namespace std;

namespace DrakeCollision {
Element::Element(const Isometry3d& T_element_to_local)
    : DrakeShapes::Element(T_element_to_local) {
  id = (ElementId) this;
}

Element::Element(const DrakeShapes::Geometry& geometry,
                 const Isometry3d& T_element_to_local)
    : DrakeShapes::Element(geometry, T_element_to_local) {
  id = (ElementId) this;
}

Element::Element(const Element& other)
    : DrakeShapes::Element(other),
      id(reinterpret_cast<ElementId>(this)),
      body_(other.body_), is_static_(other.is_static_) {}

Element* Element::clone() const { return new Element(*this); }

ElementId Element::getId() const { return id; }

const RigidBody* Element::get_body() const { return body_; }

void Element::set_body(const RigidBody *body) { body_ = body; }

ostream& operator<<(ostream& out, const Element& ee) {
  out << "DrakeCollision::Element:\n"
      << "  - id = " << ee.id << "\n"
      << "  - T_element_to_world =\n"
      << ee.T_element_to_world.matrix() << "\n"
      << "  - T_element_to_local =\n"
      << ee.T_element_to_local.matrix() << "\n"
      << "  - geometry = " << *ee.geometry << std::endl;
  return out;
}

}  // namespace DrakeCollision
<commit_msg>Fixes initialization order in Element constructor<commit_after>#include "Element.h"

#include <iostream>

using namespace Eigen;
using namespace std;

namespace DrakeCollision {
Element::Element(const Isometry3d& T_element_to_local)
    : DrakeShapes::Element(T_element_to_local) {
  id = (ElementId) this;
}

Element::Element(const DrakeShapes::Geometry& geometry,
                 const Isometry3d& T_element_to_local)
    : DrakeShapes::Element(geometry, T_element_to_local) {
  id = (ElementId) this;
}

Element::Element(const Element& other)
    : DrakeShapes::Element(other),
      id(reinterpret_cast<ElementId>(this)),
      is_static_(other.is_static_), body_(other.body_) {}

Element* Element::clone() const { return new Element(*this); }

ElementId Element::getId() const { return id; }

const RigidBody* Element::get_body() const { return body_; }

void Element::set_body(const RigidBody *body) { body_ = body; }

ostream& operator<<(ostream& out, const Element& ee) {
  out << "DrakeCollision::Element:\n"
      << "  - id = " << ee.id << "\n"
      << "  - T_element_to_world =\n"
      << ee.T_element_to_world.matrix() << "\n"
      << "  - T_element_to_local =\n"
      << ee.T_element_to_local.matrix() << "\n"
      << "  - geometry = " << *ee.geometry << std::endl;
  return out;
}

}  // namespace DrakeCollision
<|endoftext|>


<commit_before>#/*##########################################################################
#
# The fisx library for X-Ray Fluorescence
#
# Copyright (c) 2014-2016 European Synchrotron Radiation Facility
#
# This file is part of the fisx X-ray developed by V.A. Sole
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#############################################################################*/
#include "fisx_detector.h"
#include <math.h>
#include <stdexcept>

namespace fisx
{

Detector::Detector(const std::string & name, const double & density, const double & thickness, \
                  const double & funnyFactor): Layer(name, density, thickness, funnyFactor)
{
    this->diameter =  0.0;
    this->distance = 10.0;
    this->escapePeakEnergyThreshold = 0.010,
    this->escapePeakIntensityThreshold = 1.0e-7;
    this->escapePeakNThreshold = 4;
    this->escapePeakAlphaIn = 90.;
    this->escapePeakCache.clear();
}

void Detector::setMaterial(const std::string & materialName)
{
    this->escapePeakCache.clear();
    this->Layer::setMaterial(materialName);
}

void Detector::setMaterial(const Material & material)
{
    this->escapePeakCache.clear();
    this->Layer::setMaterial(material);
}

void Detector::setMinimumEscapePeakEnergy(const double & energy)
{
    this->escapePeakEnergyThreshold = energy;
    this->escapePeakCache.clear();
}

void Detector::setMinimumEscapePeakIntensity(const double & intensity)
{
    this->escapePeakIntensityThreshold = intensity;
    this->escapePeakCache.clear();
}

void Detector::setMaximumNumberOfEscapePeaks(const int & nPeaks)
{
    this->escapePeakNThreshold = nPeaks;
    this->escapePeakCache.clear();
}

void Detector::clearEscapePeakCache()
{
    this->escapePeakCache.clear();
}

double Detector::getActiveArea() const
{
    double pi;
    pi = acos(-1.0);
    return (0.25 * pi) * (this->diameter * this->diameter);
}

void Detector::setActiveArea(const double & area)
{
    double pi;
    pi = acos(-1.0);
    if (area < 0)
    {
        throw std::invalid_argument("Negative detector area");
    }
    this->diameter = 2.0 * sqrt(area/pi);
}

void Detector::setDiameter(const double & diameter)
{
    if (diameter < 0)
    {
        throw std::invalid_argument("Negative detector diameter");
    }
    this->diameter = diameter;
}

void Detector::setDistance(const double & distance)
{
    if (distance <= 0)
    {
        throw std::invalid_argument("Negative detector distance");
    }
    this->distance = distance;
}

const double & Detector::getDiameter() const
{
    return this->diameter;
}

const double & Detector::getDistance() const
{
    return this->distance;
}

std::map<std::string, std::map<std::string, double> > Detector::getEscape(const double & energy,
                                                            const Elements & elementsLibrary,
                                                            const std::string & label,
                                                            const int & update)
{
    if (update != 0)
        this->escapePeakCache.clear();
    if (false) //(label.size())
    {
        if (this->escapePeakCache.find(label) == this->escapePeakCache.end())
        {
            // calculate it
            this->escapePeakCache[label] = elementsLibrary.getEscape(this->getComposition(elementsLibrary), \
                                                                     energy, \
                                                                     this->escapePeakEnergyThreshold, \
                                                                     this->escapePeakIntensityThreshold, \
                                                                     this->escapePeakNThreshold, \
                                                                     this->escapePeakAlphaIn,
                                                                     this->getThickness());
        }
        return this->escapePeakCache[label];
    }
    else
    {
        return elementsLibrary.getEscape(this->getComposition(elementsLibrary), \
                                         energy, \
                                         this->escapePeakEnergyThreshold, \
                                         this->escapePeakIntensityThreshold, \
                                         this->escapePeakNThreshold, \
                                         this->escapePeakAlphaIn,
                                         this->getThickness());
    }
}

} // namespace fisx
<commit_msg>Ignore detector cache and thickness in escape calculation.<commit_after>#/*##########################################################################
#
# The fisx library for X-Ray Fluorescence
#
# Copyright (c) 2014-2016 European Synchrotron Radiation Facility
#
# This file is part of the fisx X-ray developed by V.A. Sole
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
#############################################################################*/
#include "fisx_detector.h"
#include <math.h>
#include <stdexcept>

namespace fisx
{

Detector::Detector(const std::string & name, const double & density, const double & thickness, \
                  const double & funnyFactor): Layer(name, density, thickness, funnyFactor)
{
    this->diameter =  0.0;
    this->distance = 10.0;
    this->escapePeakEnergyThreshold = 0.010,
    this->escapePeakIntensityThreshold = 1.0e-7;
    this->escapePeakNThreshold = 4;
    this->escapePeakAlphaIn = 90.;
    this->escapePeakCache.clear();
}

void Detector::setMaterial(const std::string & materialName)
{
    this->escapePeakCache.clear();
    this->Layer::setMaterial(materialName);
}

void Detector::setMaterial(const Material & material)
{
    this->escapePeakCache.clear();
    this->Layer::setMaterial(material);
}

void Detector::setMinimumEscapePeakEnergy(const double & energy)
{
    this->escapePeakEnergyThreshold = energy;
    this->escapePeakCache.clear();
}

void Detector::setMinimumEscapePeakIntensity(const double & intensity)
{
    this->escapePeakIntensityThreshold = intensity;
    this->escapePeakCache.clear();
}

void Detector::setMaximumNumberOfEscapePeaks(const int & nPeaks)
{
    this->escapePeakNThreshold = nPeaks;
    this->escapePeakCache.clear();
}

void Detector::clearEscapePeakCache()
{
    this->escapePeakCache.clear();
}

double Detector::getActiveArea() const
{
    double pi;
    pi = acos(-1.0);
    return (0.25 * pi) * (this->diameter * this->diameter);
}

void Detector::setActiveArea(const double & area)
{
    double pi;
    pi = acos(-1.0);
    if (area < 0)
    {
        throw std::invalid_argument("Negative detector area");
    }
    this->diameter = 2.0 * sqrt(area/pi);
}

void Detector::setDiameter(const double & diameter)
{
    if (diameter < 0)
    {
        throw std::invalid_argument("Negative detector diameter");
    }
    this->diameter = diameter;
}

void Detector::setDistance(const double & distance)
{
    if (distance <= 0)
    {
        throw std::invalid_argument("Negative detector distance");
    }
    this->distance = distance;
}

const double & Detector::getDiameter() const
{
    return this->diameter;
}

const double & Detector::getDistance() const
{
    return this->distance;
}

std::map<std::string, std::map<std::string, double> > Detector::getEscape(const double & energy,
                                                            const Elements & elementsLibrary,
                                                            const std::string & label,
                                                            const int & update)
{
    if (update != 0)
        this->escapePeakCache.clear();
    if (false) //(label.size())
    {
        if (this->escapePeakCache.find(label) == this->escapePeakCache.end())
        {
            // calculate it
            this->escapePeakCache[label] = elementsLibrary.getEscape(this->getComposition(elementsLibrary), \
                                                                     energy, \
                                                                     this->escapePeakEnergyThreshold, \
                                                                     this->escapePeakIntensityThreshold, \
                                                                     this->escapePeakNThreshold, \
                                                                     this->escapePeakAlphaIn,
                                                                     0);
        }
        return this->escapePeakCache[label];
    }
    else
    {
        return elementsLibrary.getEscape(this->getComposition(elementsLibrary), \
                                         energy, \
                                         this->escapePeakEnergyThreshold, \
                                         this->escapePeakIntensityThreshold, \
                                         this->escapePeakNThreshold, \
                                         this->escapePeakAlphaIn,
                                         0);
    }
}

} // namespace fisx
<|endoftext|>


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

#include "ast.h"

void
ast_type_specifier::print(void) const
{
   if (structure) {
      structure->print();
   } else {
      printf("%s ", type_name);
   }

   if (array_specifier) {
      array_specifier->print();
   }
}

bool
ast_fully_specified_type::has_qualifiers() const
{
   return this->qualifier.flags.i != 0;
}

bool ast_type_qualifier::has_interpolation() const
{
   return this->flags.q.smooth
          || this->flags.q.flat
          || this->flags.q.noperspective;
}

bool
ast_type_qualifier::has_layout() const
{
   return this->flags.q.origin_upper_left
          || this->flags.q.pixel_center_integer
          || this->flags.q.depth_any
          || this->flags.q.depth_greater
          || this->flags.q.depth_less
          || this->flags.q.depth_unchanged
          || this->flags.q.std140
          || this->flags.q.shared
          || this->flags.q.column_major
          || this->flags.q.row_major
          || this->flags.q.packed
          || this->flags.q.explicit_location
          || this->flags.q.explicit_index
          || this->flags.q.explicit_binding
          || this->flags.q.explicit_offset;
}

bool
ast_type_qualifier::has_storage() const
{
   return this->flags.q.constant
          || this->flags.q.attribute
          || this->flags.q.varying
          || this->flags.q.in
          || this->flags.q.out
          || this->flags.q.uniform;
}

bool
ast_type_qualifier::has_auxiliary_storage() const
{
   return this->flags.q.centroid
          || this->flags.q.sample;
}

const char*
ast_type_qualifier::interpolation_string() const
{
   if (this->flags.q.smooth)
      return "smooth";
   else if (this->flags.q.flat)
      return "flat";
   else if (this->flags.q.noperspective)
      return "noperspective";
   else
      return NULL;
}

bool
ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
				    _mesa_glsl_parse_state *state,
				    ast_type_qualifier q)
{
   ast_type_qualifier ubo_mat_mask;
   ubo_mat_mask.flags.i = 0;
   ubo_mat_mask.flags.q.row_major = 1;
   ubo_mat_mask.flags.q.column_major = 1;

   ast_type_qualifier ubo_layout_mask;
   ubo_layout_mask.flags.i = 0;
   ubo_layout_mask.flags.q.std140 = 1;
   ubo_layout_mask.flags.q.packed = 1;
   ubo_layout_mask.flags.q.shared = 1;

   ast_type_qualifier ubo_binding_mask;
   ubo_binding_mask.flags.i = 0;
   ubo_binding_mask.flags.q.explicit_binding = 1;
   ubo_binding_mask.flags.q.explicit_offset = 1;

   /* Uniform block layout qualifiers get to overwrite each
    * other (rightmost having priority), while all other
    * qualifiers currently don't allow duplicates.
    */

   if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
				      ubo_layout_mask.flags.i |
                                      ubo_binding_mask.flags.i)) != 0) {
      _mesa_glsl_error(loc, state,
		       "duplicate layout qualifiers used");
      return false;
   }

   if (q.flags.q.prim_type) {
      if (this->flags.q.prim_type && this->prim_type != q.prim_type) {
	 _mesa_glsl_error(loc, state,
			  "conflicting primitive type qualifiers used");
	 return false;
      }
      this->prim_type = q.prim_type;
   }

   if (q.flags.q.max_vertices) {
      if (this->flags.q.max_vertices && this->max_vertices != q.max_vertices) {
	 _mesa_glsl_error(loc, state,
			  "geometry shader set conflicting max_vertices "
			  "(%d and %d)", this->max_vertices, q.max_vertices);
	 return false;
      }
      this->max_vertices = q.max_vertices;
   }

   if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
      this->flags.i &= ~ubo_mat_mask.flags.i;
   if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
      this->flags.i &= ~ubo_layout_mask.flags.i;

   for (int i = 0; i < 3; i++) {
      if (q.flags.q.local_size & (1 << i)) {
         if ((this->flags.q.local_size & (1 << i)) &&
             this->local_size[i] != q.local_size[i]) {
            _mesa_glsl_error(loc, state,
                             "compute shader set conflicting values for "
                             "local_size_%c (%d and %d)", 'x' + i,
                             this->local_size[i], q.local_size[i]);
            return false;
         }
         this->local_size[i] = q.local_size[i];
      }
   }

   this->flags.i |= q.flags.i;

   if (q.flags.q.explicit_location)
      this->location = q.location;

   if (q.flags.q.explicit_index)
      this->index = q.index;

   if (q.flags.q.explicit_binding)
      this->binding = q.binding;

   if (q.flags.q.explicit_offset)
      this->offset = q.offset;

   if (q.precision != ast_precision_none)
      this->precision = q.precision;

   if (q.flags.q.explicit_image_format) {
      this->image_format = q.image_format;
      this->image_base_type = q.image_base_type;
   }

   return true;
}

bool
ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
                                       _mesa_glsl_parse_state *state,
                                       ast_type_qualifier q,
                                       ast_node* &node)
{
   void *mem_ctx = state;
   bool create_gs_ast = false;
   bool create_cs_ast = false;
   ast_type_qualifier valid_in_mask;
   valid_in_mask.flags.i = 0;

   switch (state->stage) {
   case MESA_SHADER_GEOMETRY:
      if (q.flags.q.prim_type) {
         /* Make sure this is a valid input primitive type. */
         switch (q.prim_type) {
         case GL_POINTS:
         case GL_LINES:
         case GL_LINES_ADJACENCY:
         case GL_TRIANGLES:
         case GL_TRIANGLES_ADJACENCY:
            break;
         default:
            _mesa_glsl_error(loc, state,
                             "invalid geometry shader input primitive type");
            break;
         }
      }

      create_gs_ast |=
         q.flags.q.prim_type &&
         !state->in_qualifier->flags.q.prim_type;

      valid_in_mask.flags.q.prim_type = 1;
      valid_in_mask.flags.q.invocations = 1;
      break;
   case MESA_SHADER_FRAGMENT:
      if (q.flags.q.early_fragment_tests) {
         state->early_fragment_tests = true;
      } else {
         _mesa_glsl_error(loc, state, "invalid input layout qualifier");
      }
      break;
   case MESA_SHADER_COMPUTE:
      create_cs_ast |=
         q.flags.q.local_size != 0 &&
         state->in_qualifier->flags.q.local_size == 0;

      valid_in_mask.flags.q.local_size = 1;
      break;
   default:
      _mesa_glsl_error(loc, state,
                       "input layout qualifiers only valid in "
                       "geometry, fragment and compute shaders");
      break;
   }

   /* Generate an error when invalid input layout qualifiers are used. */
   if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
      _mesa_glsl_error(loc, state,
		       "invalid input layout qualifiers used");
      return false;
   }

   /* Input layout qualifiers can be specified multiple
    * times in separate declarations, as long as they match.
    */
   if (this->flags.q.prim_type) {
      if (q.flags.q.prim_type &&
          this->prim_type != q.prim_type) {
         _mesa_glsl_error(loc, state,
                          "conflicting input primitive types specified");
      }
   } else if (q.flags.q.prim_type) {
      state->in_qualifier->flags.q.prim_type = 1;
      state->in_qualifier->prim_type = q.prim_type;
   }

   if (this->flags.q.invocations &&
       q.flags.q.invocations &&
       this->invocations != q.invocations) {
      _mesa_glsl_error(loc, state,
                       "conflicting invocations counts specified");
      return false;
   } else if (q.flags.q.invocations) {
      this->flags.q.invocations = 1;
      this->invocations = q.invocations;
   }

   if (create_gs_ast) {
      node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
   } else if (create_cs_ast) {
      /* Infer a local_size of 1 for every unspecified dimension */
      unsigned local_size[3];
      for (int i = 0; i < 3; i++) {
         if (q.flags.q.local_size & (1 << i))
            local_size[i] = q.local_size[i];
         else
            local_size[i] = 1;
      }
      node = new(mem_ctx) ast_cs_input_layout(*loc, local_size);
   }

   return true;
}
<commit_msg>glsl/cs: Fix local_size_y and local_size_z<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "ast.h"

void
ast_type_specifier::print(void) const
{
   if (structure) {
      structure->print();
   } else {
      printf("%s ", type_name);
   }

   if (array_specifier) {
      array_specifier->print();
   }
}

bool
ast_fully_specified_type::has_qualifiers() const
{
   return this->qualifier.flags.i != 0;
}

bool ast_type_qualifier::has_interpolation() const
{
   return this->flags.q.smooth
          || this->flags.q.flat
          || this->flags.q.noperspective;
}

bool
ast_type_qualifier::has_layout() const
{
   return this->flags.q.origin_upper_left
          || this->flags.q.pixel_center_integer
          || this->flags.q.depth_any
          || this->flags.q.depth_greater
          || this->flags.q.depth_less
          || this->flags.q.depth_unchanged
          || this->flags.q.std140
          || this->flags.q.shared
          || this->flags.q.column_major
          || this->flags.q.row_major
          || this->flags.q.packed
          || this->flags.q.explicit_location
          || this->flags.q.explicit_index
          || this->flags.q.explicit_binding
          || this->flags.q.explicit_offset;
}

bool
ast_type_qualifier::has_storage() const
{
   return this->flags.q.constant
          || this->flags.q.attribute
          || this->flags.q.varying
          || this->flags.q.in
          || this->flags.q.out
          || this->flags.q.uniform;
}

bool
ast_type_qualifier::has_auxiliary_storage() const
{
   return this->flags.q.centroid
          || this->flags.q.sample;
}

const char*
ast_type_qualifier::interpolation_string() const
{
   if (this->flags.q.smooth)
      return "smooth";
   else if (this->flags.q.flat)
      return "flat";
   else if (this->flags.q.noperspective)
      return "noperspective";
   else
      return NULL;
}

bool
ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
				    _mesa_glsl_parse_state *state,
				    ast_type_qualifier q)
{
   ast_type_qualifier ubo_mat_mask;
   ubo_mat_mask.flags.i = 0;
   ubo_mat_mask.flags.q.row_major = 1;
   ubo_mat_mask.flags.q.column_major = 1;

   ast_type_qualifier ubo_layout_mask;
   ubo_layout_mask.flags.i = 0;
   ubo_layout_mask.flags.q.std140 = 1;
   ubo_layout_mask.flags.q.packed = 1;
   ubo_layout_mask.flags.q.shared = 1;

   ast_type_qualifier ubo_binding_mask;
   ubo_binding_mask.flags.i = 0;
   ubo_binding_mask.flags.q.explicit_binding = 1;
   ubo_binding_mask.flags.q.explicit_offset = 1;

   /* Uniform block layout qualifiers get to overwrite each
    * other (rightmost having priority), while all other
    * qualifiers currently don't allow duplicates.
    */

   if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i |
				      ubo_layout_mask.flags.i |
                                      ubo_binding_mask.flags.i)) != 0) {
      _mesa_glsl_error(loc, state,
		       "duplicate layout qualifiers used");
      return false;
   }

   if (q.flags.q.prim_type) {
      if (this->flags.q.prim_type && this->prim_type != q.prim_type) {
	 _mesa_glsl_error(loc, state,
			  "conflicting primitive type qualifiers used");
	 return false;
      }
      this->prim_type = q.prim_type;
   }

   if (q.flags.q.max_vertices) {
      if (this->flags.q.max_vertices && this->max_vertices != q.max_vertices) {
	 _mesa_glsl_error(loc, state,
			  "geometry shader set conflicting max_vertices "
			  "(%d and %d)", this->max_vertices, q.max_vertices);
	 return false;
      }
      this->max_vertices = q.max_vertices;
   }

   if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
      this->flags.i &= ~ubo_mat_mask.flags.i;
   if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
      this->flags.i &= ~ubo_layout_mask.flags.i;

   for (int i = 0; i < 3; i++) {
      if (q.flags.q.local_size & (1 << i)) {
         if ((this->flags.q.local_size & (1 << i)) &&
             this->local_size[i] != q.local_size[i]) {
            _mesa_glsl_error(loc, state,
                             "compute shader set conflicting values for "
                             "local_size_%c (%d and %d)", 'x' + i,
                             this->local_size[i], q.local_size[i]);
            return false;
         }
         this->local_size[i] = q.local_size[i];
      }
   }

   this->flags.i |= q.flags.i;

   if (q.flags.q.explicit_location)
      this->location = q.location;

   if (q.flags.q.explicit_index)
      this->index = q.index;

   if (q.flags.q.explicit_binding)
      this->binding = q.binding;

   if (q.flags.q.explicit_offset)
      this->offset = q.offset;

   if (q.precision != ast_precision_none)
      this->precision = q.precision;

   if (q.flags.q.explicit_image_format) {
      this->image_format = q.image_format;
      this->image_base_type = q.image_base_type;
   }

   return true;
}

bool
ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
                                       _mesa_glsl_parse_state *state,
                                       ast_type_qualifier q,
                                       ast_node* &node)
{
   void *mem_ctx = state;
   bool create_gs_ast = false;
   bool create_cs_ast = false;
   ast_type_qualifier valid_in_mask;
   valid_in_mask.flags.i = 0;

   switch (state->stage) {
   case MESA_SHADER_GEOMETRY:
      if (q.flags.q.prim_type) {
         /* Make sure this is a valid input primitive type. */
         switch (q.prim_type) {
         case GL_POINTS:
         case GL_LINES:
         case GL_LINES_ADJACENCY:
         case GL_TRIANGLES:
         case GL_TRIANGLES_ADJACENCY:
            break;
         default:
            _mesa_glsl_error(loc, state,
                             "invalid geometry shader input primitive type");
            break;
         }
      }

      create_gs_ast |=
         q.flags.q.prim_type &&
         !state->in_qualifier->flags.q.prim_type;

      valid_in_mask.flags.q.prim_type = 1;
      valid_in_mask.flags.q.invocations = 1;
      break;
   case MESA_SHADER_FRAGMENT:
      if (q.flags.q.early_fragment_tests) {
         state->early_fragment_tests = true;
      } else {
         _mesa_glsl_error(loc, state, "invalid input layout qualifier");
      }
      break;
   case MESA_SHADER_COMPUTE:
      create_cs_ast |=
         q.flags.q.local_size != 0 &&
         state->in_qualifier->flags.q.local_size == 0;

      valid_in_mask.flags.q.local_size = 7;
      break;
   default:
      _mesa_glsl_error(loc, state,
                       "input layout qualifiers only valid in "
                       "geometry, fragment and compute shaders");
      break;
   }

   /* Generate an error when invalid input layout qualifiers are used. */
   if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
      _mesa_glsl_error(loc, state,
		       "invalid input layout qualifiers used");
      return false;
   }

   /* Input layout qualifiers can be specified multiple
    * times in separate declarations, as long as they match.
    */
   if (this->flags.q.prim_type) {
      if (q.flags.q.prim_type &&
          this->prim_type != q.prim_type) {
         _mesa_glsl_error(loc, state,
                          "conflicting input primitive types specified");
      }
   } else if (q.flags.q.prim_type) {
      state->in_qualifier->flags.q.prim_type = 1;
      state->in_qualifier->prim_type = q.prim_type;
   }

   if (this->flags.q.invocations &&
       q.flags.q.invocations &&
       this->invocations != q.invocations) {
      _mesa_glsl_error(loc, state,
                       "conflicting invocations counts specified");
      return false;
   } else if (q.flags.q.invocations) {
      this->flags.q.invocations = 1;
      this->invocations = q.invocations;
   }

   if (create_gs_ast) {
      node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
   } else if (create_cs_ast) {
      /* Infer a local_size of 1 for every unspecified dimension */
      unsigned local_size[3];
      for (int i = 0; i < 3; i++) {
         if (q.flags.q.local_size & (1 << i))
            local_size[i] = q.local_size[i];
         else
            local_size[i] = 1;
      }
      node = new(mem_ctx) ast_cs_input_layout(*loc, local_size);
   }

   return true;
}
<|endoftext|>


<commit_before>// Copyright 2008, Google 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 Google 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.
//
// Authors: keith.ray@gmail.com (Keith Ray)

#include <gtest/internal/gtest-filepath.h>
#include <gtest/internal/gtest-port.h>

#include <stdlib.h>

#ifdef _WIN32_WCE
#include <windows.h>
#elif defined(GTEST_OS_WINDOWS)
#include <direct.h>
#include <io.h>
#include <sys/stat.h>
#elif defined(GTEST_OS_SYMBIAN)
// Symbian OpenC has PATH_MAX in sys/syslimits.h
#include <sys/syslimits.h>
#include <unistd.h>
#else
#include <sys/stat.h>
#include <unistd.h>
#endif // _WIN32_WCE or _WIN32

#include <gtest/internal/gtest-string.h>

namespace testing {
namespace internal {

#ifdef GTEST_OS_WINDOWS
const char kPathSeparator = '\\';
const char kPathSeparatorString[] = "\\";
#ifdef _WIN32_WCE
// Windows CE doesn't have a current directory. You should not use
// the current directory in tests on Windows CE, but this at least
// provides a reasonable fallback.
const char kCurrentDirectoryString[] = "\\";
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
const DWORD kInvalidFileAttributes = 0xffffffff;
#else
const char kCurrentDirectoryString[] = ".\\";
#endif  // _WIN32_WCE
#else
const char kPathSeparator = '/';
const char kPathSeparatorString[] = "/";
const char kCurrentDirectoryString[] = "./";
#endif  // GTEST_OS_WINDOWS

// Returns the current working directory, or "" if unsuccessful.
FilePath FilePath::GetCurrentDir() {
#ifdef _WIN32_WCE
// Windows CE doesn't have a current directory, so we just return
// something reasonable.
  return FilePath(kCurrentDirectoryString);
#elif defined(GTEST_OS_WINDOWS)
  char cwd[_MAX_PATH + 1] = {};
  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
#else
  char cwd[PATH_MAX + 1] = {};
  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
#endif
}

// Returns a copy of the FilePath with the case-insensitive extension removed.
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
// FilePath("dir/file"). If a case-insensitive extension is not
// found, returns a copy of the original FilePath.
FilePath FilePath::RemoveExtension(const char* extension) const {
  String dot_extension(String::Format(".%s", extension));
  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
    return FilePath(String(pathname_.c_str(), pathname_.GetLength() - 4));
  }
  return *this;
}

// Returns a copy of the FilePath with the directory part removed.
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
// returns an empty FilePath ("").
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath FilePath::RemoveDirectoryName() const {
  const char* const last_sep = strrchr(c_str(), kPathSeparator);
  return last_sep ? FilePath(String(last_sep + 1)) : *this;
}

// RemoveFileName returns the directory path with the filename removed.
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath FilePath::RemoveFileName() const {
  const char* const last_sep = strrchr(c_str(), kPathSeparator);
  return FilePath(last_sep ? String(c_str(), last_sep + 1 - c_str())
                           : String(kCurrentDirectoryString));
}

// Helper functions for naming files in a directory for xml output.

// Given directory = "dir", base_name = "test", number = 0,
// extension = "xml", returns "dir/test.xml". If number is greater
// than zero (e.g., 12), returns "dir/test_12.xml".
// On Windows platform, uses \ as the separator rather than /.
FilePath FilePath::MakeFileName(const FilePath& directory,
                                const FilePath& base_name,
                                int number,
                                const char* extension) {
  FilePath dir(directory.RemoveTrailingPathSeparator());
  if (number == 0) {
    return FilePath(String::Format("%s%c%s.%s", dir.c_str(), kPathSeparator,
                                   base_name.c_str(), extension));
  }
  return FilePath(String::Format("%s%c%s_%d.%s", dir.c_str(), kPathSeparator,
                                 base_name.c_str(), number, extension));
}

// Returns true if pathname describes something findable in the file-system,
// either a file, directory, or whatever.
bool FilePath::FileOrDirectoryExists() const {
#ifdef GTEST_OS_WINDOWS
#ifdef _WIN32_WCE
  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
  const DWORD attributes = GetFileAttributes(unicode);
  delete [] unicode;
  return attributes != kInvalidFileAttributes;
#else
  struct _stat file_stat = {};
  return _stat(pathname_.c_str(), &file_stat) == 0;
#endif  // _WIN32_WCE
#else
  struct stat file_stat = {};
  return stat(pathname_.c_str(), &file_stat) == 0;
#endif  // GTEST_OS_WINDOWS
}

// Returns true if pathname describes a directory in the file-system
// that exists.
bool FilePath::DirectoryExists() const {
  bool result = false;
#ifdef GTEST_OS_WINDOWS
  // Don't strip off trailing separator if path is a root directory on
  // Windows (like "C:\\").
  const FilePath& path(IsRootDirectory() ? *this :
                                           RemoveTrailingPathSeparator());
#ifdef _WIN32_WCE
  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
  const DWORD attributes = GetFileAttributes(unicode);
  delete [] unicode;
  if ((attributes != kInvalidFileAttributes) &&
      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
    result = true;
  }
#else
  struct _stat file_stat = {};
  result = _stat(path.c_str(), &file_stat) == 0 &&
      (_S_IFDIR & file_stat.st_mode) != 0;
#endif  // _WIN32_WCE
#else
  struct stat file_stat = {};
  result = stat(pathname_.c_str(), &file_stat) == 0 &&
      S_ISDIR(file_stat.st_mode);
#endif  // GTEST_OS_WINDOWS
  return result;
}

// Returns true if pathname describes a root directory. (Windows has one
// root directory per disk drive.)
bool FilePath::IsRootDirectory() const {
#ifdef GTEST_OS_WINDOWS
  const char* const name = pathname_.c_str();
  return pathname_.GetLength() == 3 &&
     ((name[0] >= 'a' && name[0] <= 'z') ||
      (name[0] >= 'A' && name[0] <= 'Z')) &&
     name[1] == ':' &&
     name[2] == kPathSeparator;
#else
  return pathname_ == kPathSeparatorString;
#endif
}

// Returns a pathname for a file that does not currently exist. The pathname
// will be directory/base_name.extension or
// directory/base_name_<number>.extension if directory/base_name.extension
// already exists. The number will be incremented until a pathname is found
// that does not already exist.
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
// There could be a race condition if two or more processes are calling this
// function at the same time -- they could both pick the same filename.
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
                                          const FilePath& base_name,
                                          const char* extension) {
  FilePath full_pathname;
  int number = 0;
  do {
    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
  } while (full_pathname.FileOrDirectoryExists());
  return full_pathname;
}

// Returns true if FilePath ends with a path separator, which indicates that
// it is intended to represent a directory. Returns false otherwise.
// This does NOT check that a directory (or file) actually exists.
bool FilePath::IsDirectory() const {
  return pathname_.EndsWith(kPathSeparatorString);
}

// Create directories so that path exists. Returns true if successful or if
// the directories already exist; returns false if unable to create directories
// for any reason.
bool FilePath::CreateDirectoriesRecursively() const {
  if (!this->IsDirectory()) {
    return false;
  }

  if (pathname_.GetLength() == 0 || this->DirectoryExists()) {
    return true;
  }

  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
}

// Create the directory so that path exists. Returns true if successful or
// if the directory already exists; returns false if unable to create the
// directory for any reason, including if the parent directory does not
// exist. Not named "CreateDirectory" because that's a macro on Windows.
bool FilePath::CreateFolder() const {
#ifdef GTEST_OS_WINDOWS
#ifdef _WIN32_WCE
  FilePath removed_sep(this->RemoveTrailingPathSeparator());
  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
  delete [] unicode;
#else
  int result = _mkdir(pathname_.c_str());
#endif  // !WIN32_WCE
#else
  int result = mkdir(pathname_.c_str(), 0777);
#endif  // _WIN32
  if (result == -1) {
    return this->DirectoryExists();  // An error is OK if the directory exists.
  }
  return true;  // No error.
}

// If input name has a trailing separator character, remove it and return the
// name, otherwise return the name string unmodified.
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath FilePath::RemoveTrailingPathSeparator() const {
  return pathname_.EndsWith(kPathSeparatorString)
      ? FilePath(String(pathname_.c_str(), pathname_.GetLength() - 1))
      : *this;
}

// Normalize removes any redundant separators that might be in the pathname.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..".
void FilePath::Normalize() {
  if (pathname_.c_str() == NULL) {
    pathname_ = "";
    return;
  }
  const char* src = pathname_.c_str();
  char* const dest = new char[pathname_.GetLength() + 1];
  char* dest_ptr = dest;
  memset(dest_ptr, 0, pathname_.GetLength() + 1);

  while (*src != '\0') {
    *dest_ptr++ = *src;
    if (*src != kPathSeparator)
      src++;
    else
      while (*src == kPathSeparator)
        src++;
  }
  *dest_ptr = '\0';
  pathname_ = dest;
  delete[] dest;
}

}  // namespace internal
}  // namespace testing
<commit_msg>On some Linux distros, you need to explicitly #include <limits.h> to get the definition of PATH_MAX. This patch adds it in the appropriate place.<commit_after>// Copyright 2008, Google 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 Google 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.
//
// Authors: keith.ray@gmail.com (Keith Ray)

#include <gtest/internal/gtest-filepath.h>
#include <gtest/internal/gtest-port.h>

#include <stdlib.h>

#ifdef _WIN32_WCE
#include <windows.h>
#elif defined(GTEST_OS_WINDOWS)
#include <direct.h>
#include <io.h>
#include <sys/stat.h>
#elif defined(GTEST_OS_SYMBIAN)
// Symbian OpenC has PATH_MAX in sys/syslimits.h
#include <sys/syslimits.h>
#include <unistd.h>
#else
#include <limits.h>
#include <sys/stat.h>
#include <unistd.h>
#endif // _WIN32_WCE or _WIN32

#include <gtest/internal/gtest-string.h>

namespace testing {
namespace internal {

#ifdef GTEST_OS_WINDOWS
const char kPathSeparator = '\\';
const char kPathSeparatorString[] = "\\";
#ifdef _WIN32_WCE
// Windows CE doesn't have a current directory. You should not use
// the current directory in tests on Windows CE, but this at least
// provides a reasonable fallback.
const char kCurrentDirectoryString[] = "\\";
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
const DWORD kInvalidFileAttributes = 0xffffffff;
#else
const char kCurrentDirectoryString[] = ".\\";
#endif  // _WIN32_WCE
#else
const char kPathSeparator = '/';
const char kPathSeparatorString[] = "/";
const char kCurrentDirectoryString[] = "./";
#endif  // GTEST_OS_WINDOWS

// Returns the current working directory, or "" if unsuccessful.
FilePath FilePath::GetCurrentDir() {
#ifdef _WIN32_WCE
// Windows CE doesn't have a current directory, so we just return
// something reasonable.
  return FilePath(kCurrentDirectoryString);
#elif defined(GTEST_OS_WINDOWS)
  char cwd[_MAX_PATH + 1] = {};
  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
#else
  char cwd[PATH_MAX + 1] = {};
  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
#endif
}

// Returns a copy of the FilePath with the case-insensitive extension removed.
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
// FilePath("dir/file"). If a case-insensitive extension is not
// found, returns a copy of the original FilePath.
FilePath FilePath::RemoveExtension(const char* extension) const {
  String dot_extension(String::Format(".%s", extension));
  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
    return FilePath(String(pathname_.c_str(), pathname_.GetLength() - 4));
  }
  return *this;
}

// Returns a copy of the FilePath with the directory part removed.
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
// returns an empty FilePath ("").
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath FilePath::RemoveDirectoryName() const {
  const char* const last_sep = strrchr(c_str(), kPathSeparator);
  return last_sep ? FilePath(String(last_sep + 1)) : *this;
}

// RemoveFileName returns the directory path with the filename removed.
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath FilePath::RemoveFileName() const {
  const char* const last_sep = strrchr(c_str(), kPathSeparator);
  return FilePath(last_sep ? String(c_str(), last_sep + 1 - c_str())
                           : String(kCurrentDirectoryString));
}

// Helper functions for naming files in a directory for xml output.

// Given directory = "dir", base_name = "test", number = 0,
// extension = "xml", returns "dir/test.xml". If number is greater
// than zero (e.g., 12), returns "dir/test_12.xml".
// On Windows platform, uses \ as the separator rather than /.
FilePath FilePath::MakeFileName(const FilePath& directory,
                                const FilePath& base_name,
                                int number,
                                const char* extension) {
  FilePath dir(directory.RemoveTrailingPathSeparator());
  if (number == 0) {
    return FilePath(String::Format("%s%c%s.%s", dir.c_str(), kPathSeparator,
                                   base_name.c_str(), extension));
  }
  return FilePath(String::Format("%s%c%s_%d.%s", dir.c_str(), kPathSeparator,
                                 base_name.c_str(), number, extension));
}

// Returns true if pathname describes something findable in the file-system,
// either a file, directory, or whatever.
bool FilePath::FileOrDirectoryExists() const {
#ifdef GTEST_OS_WINDOWS
#ifdef _WIN32_WCE
  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
  const DWORD attributes = GetFileAttributes(unicode);
  delete [] unicode;
  return attributes != kInvalidFileAttributes;
#else
  struct _stat file_stat = {};
  return _stat(pathname_.c_str(), &file_stat) == 0;
#endif  // _WIN32_WCE
#else
  struct stat file_stat = {};
  return stat(pathname_.c_str(), &file_stat) == 0;
#endif  // GTEST_OS_WINDOWS
}

// Returns true if pathname describes a directory in the file-system
// that exists.
bool FilePath::DirectoryExists() const {
  bool result = false;
#ifdef GTEST_OS_WINDOWS
  // Don't strip off trailing separator if path is a root directory on
  // Windows (like "C:\\").
  const FilePath& path(IsRootDirectory() ? *this :
                                           RemoveTrailingPathSeparator());
#ifdef _WIN32_WCE
  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
  const DWORD attributes = GetFileAttributes(unicode);
  delete [] unicode;
  if ((attributes != kInvalidFileAttributes) &&
      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
    result = true;
  }
#else
  struct _stat file_stat = {};
  result = _stat(path.c_str(), &file_stat) == 0 &&
      (_S_IFDIR & file_stat.st_mode) != 0;
#endif  // _WIN32_WCE
#else
  struct stat file_stat = {};
  result = stat(pathname_.c_str(), &file_stat) == 0 &&
      S_ISDIR(file_stat.st_mode);
#endif  // GTEST_OS_WINDOWS
  return result;
}

// Returns true if pathname describes a root directory. (Windows has one
// root directory per disk drive.)
bool FilePath::IsRootDirectory() const {
#ifdef GTEST_OS_WINDOWS
  const char* const name = pathname_.c_str();
  return pathname_.GetLength() == 3 &&
     ((name[0] >= 'a' && name[0] <= 'z') ||
      (name[0] >= 'A' && name[0] <= 'Z')) &&
     name[1] == ':' &&
     name[2] == kPathSeparator;
#else
  return pathname_ == kPathSeparatorString;
#endif
}

// Returns a pathname for a file that does not currently exist. The pathname
// will be directory/base_name.extension or
// directory/base_name_<number>.extension if directory/base_name.extension
// already exists. The number will be incremented until a pathname is found
// that does not already exist.
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
// There could be a race condition if two or more processes are calling this
// function at the same time -- they could both pick the same filename.
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
                                          const FilePath& base_name,
                                          const char* extension) {
  FilePath full_pathname;
  int number = 0;
  do {
    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
  } while (full_pathname.FileOrDirectoryExists());
  return full_pathname;
}

// Returns true if FilePath ends with a path separator, which indicates that
// it is intended to represent a directory. Returns false otherwise.
// This does NOT check that a directory (or file) actually exists.
bool FilePath::IsDirectory() const {
  return pathname_.EndsWith(kPathSeparatorString);
}

// Create directories so that path exists. Returns true if successful or if
// the directories already exist; returns false if unable to create directories
// for any reason.
bool FilePath::CreateDirectoriesRecursively() const {
  if (!this->IsDirectory()) {
    return false;
  }

  if (pathname_.GetLength() == 0 || this->DirectoryExists()) {
    return true;
  }

  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
}

// Create the directory so that path exists. Returns true if successful or
// if the directory already exists; returns false if unable to create the
// directory for any reason, including if the parent directory does not
// exist. Not named "CreateDirectory" because that's a macro on Windows.
bool FilePath::CreateFolder() const {
#ifdef GTEST_OS_WINDOWS
#ifdef _WIN32_WCE
  FilePath removed_sep(this->RemoveTrailingPathSeparator());
  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
  delete [] unicode;
#else
  int result = _mkdir(pathname_.c_str());
#endif  // !WIN32_WCE
#else
  int result = mkdir(pathname_.c_str(), 0777);
#endif  // _WIN32
  if (result == -1) {
    return this->DirectoryExists();  // An error is OK if the directory exists.
  }
  return true;  // No error.
}

// If input name has a trailing separator character, remove it and return the
// name, otherwise return the name string unmodified.
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath FilePath::RemoveTrailingPathSeparator() const {
  return pathname_.EndsWith(kPathSeparatorString)
      ? FilePath(String(pathname_.c_str(), pathname_.GetLength() - 1))
      : *this;
}

// Normalize removes any redundant separators that might be in the pathname.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..".
void FilePath::Normalize() {
  if (pathname_.c_str() == NULL) {
    pathname_ = "";
    return;
  }
  const char* src = pathname_.c_str();
  char* const dest = new char[pathname_.GetLength() + 1];
  char* dest_ptr = dest;
  memset(dest_ptr, 0, pathname_.GetLength() + 1);

  while (*src != '\0') {
    *dest_ptr++ = *src;
    if (*src != kPathSeparator)
      src++;
    else
      while (*src == kPathSeparator)
        src++;
  }
  *dest_ptr = '\0';
  pathname_ = dest;
  delete[] dest;
}

}  // namespace internal
}  // namespace testing
<|endoftext|>


<commit_before>//
// Created by dar on 1/25/16.
//

#include "GuiButton.h"

GuiButton::GuiButton(double x, double y, double width, double height) {
    this->x = x;
    this->y = y;
    this->width = width;
    this->height = height;
}

bool GuiButton::onClick(int action, float x, float y) {
    if (onClickListener == NULL) return false;
    return onClickListener(action, x, y);
}

void GuiButton::setOnClickListener(std::function<bool(int, float, float)> onClickListener) {
    this->onClickListener = onClickListener;
}<commit_msg>Added comments<commit_after>//
// Created by dar on 1/25/16.
//

#include "GuiButton.h"

GuiButton::GuiButton(double x, double y, double width, double height) { //TODO add some "placement" flag (TOP-RIGHT, MIDDLE-RIGHT, BOTTOM-RIGHT, etc.)
    this->x = x;
    this->y = y;
    this->width = width;
    this->height = height;
}

bool GuiButton::onClick(int action, float x, float y) {
    if (onClickListener == NULL) return false;
    return onClickListener(action, x, y);
}

void GuiButton::setOnClickListener(std::function<bool(int, float, float)> onClickListener) {
    this->onClickListener = onClickListener;
}<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld, Ash Berlin

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

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

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

#include "flusspferd/io/file_class.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/string_io.hpp"
#include "flusspferd/create.hpp"
#include <boost/scoped_array.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace flusspferd;
using namespace flusspferd::io;

class file_class::impl {
public:
  std::fstream stream;

  static void create(char const *name, boost::optional<int> mode);
  static bool exists(char const *name);
};

file_class::file_class(object const &obj, call_context &x)
  : stream_base(obj, 0), p(new impl)
{
  set_streambuf(p->stream.rdbuf());
  if (!x.arg.empty()) {
    string name = x.arg[0].to_string();
    open(name.c_str());
  }

  register_native_method("open", &file_class::open);
  register_native_method("close", &file_class::close);
}

file_class::~file_class()
{}

void file_class::class_info::augment_constructor(object constructor) {
  create_native_function(constructor, "create", &impl::create);
}

object file_class::class_info::create_prototype() {
  local_root_scope scope;

  object proto = create_object(flusspferd::get_prototype<stream_base>());

  create_native_method(proto, "open", 1);
  create_native_method(proto, "close", 0);
  create_native_method(proto, "exists", 0);

  return proto;
}

void file_class::open(char const *name) {
  security &sec = security::get();

  if (!sec.check_path(name, security::READ_WRITE))
    throw exception("Could not open file (security)");

  p->stream.open(name);

  define_property("fileName", string(name),
                  permanent_property | read_only_property );

  if (!p->stream)
    // TODO: Include some sort of system error message here
    throw exception("Could not open file");
}

void file_class::close() {
  p->stream.close();
  delete_property("fileName");
}

void file_class::impl::create(char const *name, boost::optional<int> mode) {
  security &sec = security::get();

  if (!sec.check_path(name, security::CREATE))
    throw exception("Could not create file (security)");

  if (creat(name, mode.get_value_or(0666)) < 0)
    throw exception("Could not create file");
}

bool file_class::impl::exists(char const *name) {
  return boost::filesystem::exists(name);
}

<commit_msg>IO/File: exists doesn't belong on prototype (And this time remove it from the proto not the ctor)<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld, Ash Berlin

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

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

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

#include "flusspferd/io/file_class.hpp"
#include "flusspferd/security.hpp"
#include "flusspferd/local_root_scope.hpp"
#include "flusspferd/create.hpp"
#include "flusspferd/string.hpp"
#include "flusspferd/string_io.hpp"
#include "flusspferd/create.hpp"
#include <boost/scoped_array.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace flusspferd;
using namespace flusspferd::io;

class file_class::impl {
public:
  std::fstream stream;

  static void create(char const *name, boost::optional<int> mode);
  static bool exists(char const *name);
};

file_class::file_class(object const &obj, call_context &x)
  : stream_base(obj, 0), p(new impl)
{
  set_streambuf(p->stream.rdbuf());
  if (!x.arg.empty()) {
    string name = x.arg[0].to_string();
    open(name.c_str());
  }

  register_native_method("open", &file_class::open);
  register_native_method("close", &file_class::close);
}

file_class::~file_class()
{}

void file_class::class_info::augment_constructor(object constructor) {
  create_native_function(constructor, "create", &impl::create);
  create_native_function(constructor, "exists", &impl::exists);
}

object file_class::class_info::create_prototype() {
  local_root_scope scope;

  object proto = create_object(flusspferd::get_prototype<stream_base>());

  create_native_method(proto, "open", 1);
  create_native_method(proto, "close", 0);

  return proto;
}

void file_class::open(char const *name) {
  security &sec = security::get();

  if (!sec.check_path(name, security::READ_WRITE))
    throw exception("Could not open file (security)");

  p->stream.open(name);

  define_property("fileName", string(name),
                  permanent_property | read_only_property );

  if (!p->stream)
    // TODO: Include some sort of system error message here
    throw exception("Could not open file");
}

void file_class::close() {
  p->stream.close();
  delete_property("fileName");
}

void file_class::impl::create(char const *name, boost::optional<int> mode) {
  security &sec = security::get();

  if (!sec.check_path(name, security::CREATE))
    throw exception("Could not create file (security)");

  if (creat(name, mode.get_value_or(0666)) < 0)
    throw exception("Could not create file");
}

bool file_class::impl::exists(char const *name) {
  return boost::filesystem::exists(name);
}

<|endoftext|>


<commit_before>#include "keymap_manager.hh"

#include "array_view.hh"
#include "assert.hh"

#include <algorithm>

namespace Kakoune
{

void KeymapManager::map_key(Key key, KeymapMode mode,
                            KeyList mapping, String docstring)
{
    m_mapping[KeyAndMode{key, mode}] = {std::move(mapping), std::move(docstring)};
}

void KeymapManager::unmap_key(Key key, KeymapMode mode)
{
    m_mapping.unordered_remove(KeyAndMode{key, mode});
}

bool KeymapManager::is_mapped(Key key, KeymapMode mode) const
{
    return m_mapping.find(KeyAndMode{key, mode}) != m_mapping.end() or
           (m_parent and m_parent->is_mapped(key, mode));
}

const KeymapManager::KeyMapInfo&
KeymapManager::get_mapping(Key key, KeymapMode mode) const
{
    auto it = m_mapping.find(KeyAndMode{key, mode});
    if (it != m_mapping.end())
        return it->value;
    kak_assert(m_parent);
    return m_parent->get_mapping(key, mode);
}

KeymapManager::KeyList KeymapManager::get_mapped_keys(KeymapMode mode) const
{
    KeyList res;
    if (m_parent)
        res = m_parent->get_mapped_keys(mode);
    for (auto& map : m_mapping)
    {
        if (map.key.second == mode)
            res.emplace_back(map.key.first);
    }
    std::sort(res.begin(), res.end());
    res.erase(std::unique(res.begin(), res.end()), res.end());
    return res;
}

}
<commit_msg>Preserve order of definition of mappings when listing them<commit_after>#include "keymap_manager.hh"

#include "array_view.hh"
#include "assert.hh"

#include <algorithm>

namespace Kakoune
{

void KeymapManager::map_key(Key key, KeymapMode mode,
                            KeyList mapping, String docstring)
{
    m_mapping[KeyAndMode{key, mode}] = {std::move(mapping), std::move(docstring)};
}

void KeymapManager::unmap_key(Key key, KeymapMode mode)
{
    m_mapping.remove(KeyAndMode{key, mode});
}

bool KeymapManager::is_mapped(Key key, KeymapMode mode) const
{
    return m_mapping.find(KeyAndMode{key, mode}) != m_mapping.end() or
           (m_parent and m_parent->is_mapped(key, mode));
}

const KeymapManager::KeyMapInfo&
KeymapManager::get_mapping(Key key, KeymapMode mode) const
{
    auto it = m_mapping.find(KeyAndMode{key, mode});
    if (it != m_mapping.end())
        return it->value;
    kak_assert(m_parent);
    return m_parent->get_mapping(key, mode);
}

KeymapManager::KeyList KeymapManager::get_mapped_keys(KeymapMode mode) const
{
    KeyList res;
    if (m_parent)
        res = m_parent->get_mapped_keys(mode);
    for (auto& map : m_mapping)
    {
        if (map.key.second == mode and not contains(res, map.key.first))
            res.emplace_back(map.key.first);
    }
    return res;
}

}
<|endoftext|>