<commit_before>/*
* (In)Visibible Entities List Adjuster
* Copyright (c) 2014 ThirteenAG <thirteenag@gmail.com>
* Licensed under the MIT License (http://opensource.org/licenses/MIT)
*/
#include "LimitAdjuster.h"
std::vector<char> aInVisibleEntityPtrs;
std::vector<char> aVisibleEntityPtrs;

class InVisibleEntityPtrsIII : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsIII() ? "InVisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
	{
		aInVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x4A7850 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A78D3 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A7950 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A9300 + 0x33 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A9BB0 + 0xB8 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A9E30 + 0xC5 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4AA0A0 + 0x6C + 0x3, &aInVisibleEntityPtrs[0], true);
	}

} InVisibleEntityPtrsIII;

class VisibleEntityPtrsIII : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsIII() ? "VisibleEntityPtrs" : nullptr; }

		void ChangeLimit(int, const std::string& value)
		{
			aVisibleEntityPtrs.resize(std::stoi(value));

			injector::WriteMemory(0x4A7870 + 0x3, &aVisibleEntityPtrs[0], true);
			injector::WriteMemory(0x4A9BB0 + 0x1C7 + 0x3, &aVisibleEntityPtrs[0], true);
			injector::WriteMemory(0x4A9E30 + 0x1D7 + 0x3, &aVisibleEntityPtrs[0], true);
			injector::WriteMemory(0x4AA0A0 + 0xE3 + 0x3, &aVisibleEntityPtrs[0], true);
		}
} VisibleEntityPtrsIII;

class InVisibleEntityPtrsVC : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsVC() ? "InVisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
		{
		aInVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x4C7560 + 0xBE + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C7740 + 0xB8 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C8540 + 0x78 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C9F80 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4CA1B8 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4CA200 + 0x3, &aInVisibleEntityPtrs[0], true);
		}
} InVisibleEntityPtrsVC;

class VisibleEntityPtrsVC : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsVC() ? "VisibleEntityPtrs" : nullptr; }
	void ChangeLimit(int, const std::string& value)
	{
		aVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x4C7560 + 0x185 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C7740 + 0x17F + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4CA220 + 0x3, &aVisibleEntityPtrs[0], true);
	}
} VisibleEntityPtrsVC;

class InVisibleEntityPtrsSA : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsSA() ? "InVisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
	{
		aInVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x5534B0 + 0x42 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553920 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553CB0 + 0x3, &aInVisibleEntityPtrs[0], true);
	}

    // TODO GetUsage

} InVisibleEntityPtrsSA;

class VisibleEntityPtrsSA : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsSA() ? "VisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
	{
		aVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x5534B0 + 0x76 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553941 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553A50 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553B00 + 0x3, &aVisibleEntityPtrs[0], true);
	}

    // TODO GetUsage

} VisibleEntityPtrsSA;
<commit_msg>Size fix<commit_after>/*
* (In)Visibible Entities List Adjuster
* Copyright (c) 2014 ThirteenAG <thirteenag@gmail.com>
* Licensed under the MIT License (http://opensource.org/licenses/MIT)
*/
#include "LimitAdjuster.h"

static std::vector<void*> aInVisibleEntityPtrs;
static std::vector<void*> aVisibleEntityPtrs;

class InVisibleEntityPtrsIII : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsIII() ? "InVisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
	{
		aInVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x4A7850 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A78D3 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A7950 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A9300 + 0x33 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A9BB0 + 0xB8 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4A9E30 + 0xC5 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4AA0A0 + 0x6C + 0x3, &aInVisibleEntityPtrs[0], true);
	}

} InVisibleEntityPtrsIII;

class VisibleEntityPtrsIII : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsIII() ? "VisibleEntityPtrs" : nullptr; }

		void ChangeLimit(int, const std::string& value)
		{
			aVisibleEntityPtrs.resize(std::stoi(value));

			injector::WriteMemory(0x4A7870 + 0x3, &aVisibleEntityPtrs[0], true);
			injector::WriteMemory(0x4A9BB0 + 0x1C7 + 0x3, &aVisibleEntityPtrs[0], true);
			injector::WriteMemory(0x4A9E30 + 0x1D7 + 0x3, &aVisibleEntityPtrs[0], true);
			injector::WriteMemory(0x4AA0A0 + 0xE3 + 0x3, &aVisibleEntityPtrs[0], true);
		}
} VisibleEntityPtrsIII;

class InVisibleEntityPtrsVC : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsVC() ? "InVisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
		{
		aInVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x4C7560 + 0xBE + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C7740 + 0xB8 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C8540 + 0x78 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C9F80 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4CA1B8 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4CA200 + 0x3, &aInVisibleEntityPtrs[0], true);
		}
} InVisibleEntityPtrsVC;

class VisibleEntityPtrsVC : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsVC() ? "VisibleEntityPtrs" : nullptr; }
	void ChangeLimit(int, const std::string& value)
	{
		aVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x4C7560 + 0x185 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4C7740 + 0x17F + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x4CA220 + 0x3, &aVisibleEntityPtrs[0], true);
	}
} VisibleEntityPtrsVC;

class InVisibleEntityPtrsSA : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsSA() ? "InVisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
	{
		aInVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x5534B0 + 0x42 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553920 + 0x3, &aInVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553CB0 + 0x3, &aInVisibleEntityPtrs[0], true);
	}

    // TODO GetUsage

} InVisibleEntityPtrsSA;

class VisibleEntityPtrsSA : public SimpleAdjuster
{
public:
	const char* GetLimitName() { return GetGVM().IsSA() ? "VisibleEntityPtrs" : nullptr; }

	void ChangeLimit(int, const std::string& value)
	{
		aVisibleEntityPtrs.resize(std::stoi(value));

		injector::WriteMemory(0x5534B0 + 0x76 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553941 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553A50 + 0x3, &aVisibleEntityPtrs[0], true);
		injector::WriteMemory(0x553B00 + 0x3, &aVisibleEntityPtrs[0], true);
	}

    // TODO GetUsage

} VisibleEntityPtrsSA;
<|endoftext|>


<commit_before>#define FASTLED_INTERNAL
#include "FastLED.h"

#if defined(__SAM3X8E__)
volatile uint32_t fuckit;
#endif

FASTLED_NAMESPACE_BEGIN

void *pSmartMatrix = NULL;

CFastLED FastLED;

CLEDController *CLEDController::m_pHead = NULL;
CLEDController *CLEDController::m_pTail = NULL;
static uint32_t lastshow = 0;

uint32_t _frame_cnt=0;
uint32_t _retry_cnt=0;

// uint32_t CRGB::Squant = ((uint32_t)((__TIME__[4]-'0') * 28))<<16 | ((__TIME__[6]-'0')*50)<<8 | ((__TIME__[7]-'0')*28);

CFastLED::CFastLED() {
	// clear out the array of led controllers
	// m_nControllers = 0;
	m_Scale = 255;
	m_nFPS = 0;
	m_pPowerFunc = NULL;
	m_nPowerData = 0xFFFFFFFF;
}

CLEDController &CFastLED::addLeds(CLEDController *pLed,
								  struct CRGB *data,
								  int nLedsOrOffset, int nLedsIfOffset) {
	int nOffset = (nLedsIfOffset > 0) ? nLedsOrOffset : 0;
	int nLeds = (nLedsIfOffset > 0) ? nLedsIfOffset : nLedsOrOffset;

	pLed->init();
	pLed->setLeds(data + nOffset, nLeds);
	FastLED.setMaxRefreshRate(pLed->getMaxRefreshRate(),true);
	return *pLed;
}

void CFastLED::show(uint8_t scale) {
	// guard against showing too rapidly
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	// If we have a function for computing power, use it!
	if(m_pPowerFunc) {
		scale = (*m_pPowerFunc)(scale, m_nPowerData);
	}

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showLeds(scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

int CFastLED::count() {
    int x = 0;
	CLEDController *pCur = CLEDController::head();
	while( pCur) {
        ++x;
		pCur = pCur->next();
	}
    return x;
}

CLEDController & CFastLED::operator[](int x) {
	CLEDController *pCur = CLEDController::head();
	while(x-- && pCur) {
		pCur = pCur->next();
	}
	if(pCur == NULL) {
		return *(CLEDController::head());
	} else {
		return *pCur;
	}
}

void CFastLED::showColor(const struct CRGB & color, uint8_t scale) {
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	// If we have a function for computing power, use it!
	if(m_pPowerFunc) {
		scale = (*m_pPowerFunc)(scale, m_nPowerData);
	}

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showColor(color, scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

void CFastLED::clear(bool writeData) {
	if(writeData) {
		showColor(CRGB(0,0,0), 0);
	}
    clearData();
}

void CFastLED::clearData() {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->clearLedData();
		pCur = pCur->next();
	}
}

void CFastLED::delay(unsigned long ms) {
	unsigned long start = millis();
        do {
#ifndef FASTLED_ACCURATE_CLOCK
		// make sure to allow at least one ms to pass to ensure the clock moves
		// forward
		::delay(1);
#endif
		show();
		yield();
	}
	while((millis()-start) < ms);
}

void CFastLED::setTemperature(const struct CRGB & temp) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setTemperature(temp);
		pCur = pCur->next();
	}
}

void CFastLED::setCorrection(const struct CRGB & correction) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setCorrection(correction);
		pCur = pCur->next();
	}
}

void CFastLED::setDither(uint8_t ditherMode)  {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setDither(ditherMode);
		pCur = pCur->next();
	}
}

//
// template<int m, int n> void transpose8(unsigned char A[8], unsigned char B[8]) {
// 	uint32_t x, y, t;
//
// 	// Load the array and pack it into x and y.
//   	y = *(unsigned int*)(A);
// 	x = *(unsigned int*)(A+4);
//
// 	// x = (A[0]<<24)   | (A[m]<<16)   | (A[2*m]<<8) | A[3*m];
// 	// y = (A[4*m]<<24) | (A[5*m]<<16) | (A[6*m]<<8) | A[7*m];
//
        // // pre-transform x
        // t = (x ^ (x >> 7)) & 0x00AA00AA;  x = x ^ t ^ (t << 7);
        // t = (x ^ (x >>14)) & 0x0000CCCC;  x = x ^ t ^ (t <<14);
				//
        // // pre-transform y
        // t = (y ^ (y >> 7)) & 0x00AA00AA;  y = y ^ t ^ (t << 7);
        // t = (y ^ (y >>14)) & 0x0000CCCC;  y = y ^ t ^ (t <<14);
				//
        // // final transform
        // t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F);
        // y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F);
        // x = t;
//
// 	B[7*n] = y; y >>= 8;
// 	B[6*n] = y; y >>= 8;
// 	B[5*n] = y; y >>= 8;
// 	B[4*n] = y;
//
//   B[3*n] = x; x >>= 8;
// 	B[2*n] = x; x >>= 8;
// 	B[n] = x; x >>= 8;
// 	B[0] = x;
// 	// B[0]=x>>24;    B[n]=x>>16;    B[2*n]=x>>8;  B[3*n]=x>>0;
// 	// B[4*n]=y>>24;  B[5*n]=y>>16;  B[6*n]=y>>8;  B[7*n]=y>>0;
// }
//
// void transposeLines(Lines & out, Lines & in) {
// 	transpose8<1,2>(in.bytes, out.bytes);
// 	transpose8<1,2>(in.bytes + 8, out.bytes + 1);
// }

extern int noise_min;
extern int noise_max;

void CFastLED::countFPS(int nFrames) {
	static int br = 0;
	static uint32_t lastframe = 0; // millis();

	if(br++ >= nFrames) {
		uint32_t now = millis();
		now -= lastframe;
		if(now == 0) {
			now = 1; // prevent division by zero below
		}
		m_nFPS = (br * 1000) / now;
		br = 0;
		lastframe = millis();
	}
}

void CFastLED::setMaxRefreshRate(uint16_t refresh, bool constrain) {
	if(constrain) {
		// if we're constraining, the new value of m_nMinMicros _must_ be higher than previously (because we're only
		// allowed to slow things down if constraining)
		if(refresh > 0) {
			m_nMinMicros = ((1000000 / refresh) > m_nMinMicros) ? (1000000 / refresh) : m_nMinMicros;
		}
	} else if(refresh > 0) {
		m_nMinMicros = 1000000 / refresh;
	} else {
		m_nMinMicros = 0;
	}
}

extern "C" int atexit(void (* /*func*/ )()) { return 0; }

#ifdef FASTLED_NEEDS_YIELD
extern "C" void yield(void) { }
#endif

#ifdef NEED_CXX_BITS
namespace __cxxabiv1
{
	#if !defined(ESP8266) && !defined(ESP32)
	extern "C" void __cxa_pure_virtual (void) {}
	#endif

	/* guard variables */

	/* The ABI requires a 64-bit type.  */
	__extension__ typedef int __guard __attribute__((mode(__DI__)));

	extern "C" int __cxa_guard_acquire (__guard *) __attribute__((weak));
	extern "C" void __cxa_guard_release (__guard *) __attribute__((weak));
	extern "C" void __cxa_guard_abort (__guard *) __attribute__((weak));

	extern "C" int __cxa_guard_acquire (__guard *g)
	{
		return !*(char *)(g);
	}

	extern "C" void __cxa_guard_release (__guard *g)
	{
		*(char *)g = 1;
	}

	extern "C" void __cxa_guard_abort (__guard *)
	{

	}
}
#endif

FASTLED_NAMESPACE_END
<commit_msg>Update FastLED.cpp documentation<commit_after>#define FASTLED_INTERNAL
#include "FastLED.h"

/// @file FastLED.cpp
/// Central source file for FastLED, implements the CFastLED class/object

#if defined(__SAM3X8E__)
volatile uint32_t fuckit;
#endif

FASTLED_NAMESPACE_BEGIN

/// Pointer to the matrix object when using the Smart Matrix Library
/// @see https://github.com/pixelmatix/SmartMatrix
void *pSmartMatrix = NULL;

CFastLED FastLED;

CLEDController *CLEDController::m_pHead = NULL;
CLEDController *CLEDController::m_pTail = NULL;
static uint32_t lastshow = 0;

/// Global frame counter, used for debugging ESP implementations
/// @todo Include in FASTLED_DEBUG_COUNT_FRAME_RETRIES block?
uint32_t _frame_cnt=0;

/// Global frame retry counter, used for debugging ESP implementations
/// @todo Include in FASTLED_DEBUG_COUNT_FRAME_RETRIES block?
uint32_t _retry_cnt=0;

// uint32_t CRGB::Squant = ((uint32_t)((__TIME__[4]-'0') * 28))<<16 | ((__TIME__[6]-'0')*50)<<8 | ((__TIME__[7]-'0')*28);

CFastLED::CFastLED() {
	// clear out the array of led controllers
	// m_nControllers = 0;
	m_Scale = 255;
	m_nFPS = 0;
	m_pPowerFunc = NULL;
	m_nPowerData = 0xFFFFFFFF;
}

CLEDController &CFastLED::addLeds(CLEDController *pLed,
								  struct CRGB *data,
								  int nLedsOrOffset, int nLedsIfOffset) {
	int nOffset = (nLedsIfOffset > 0) ? nLedsOrOffset : 0;
	int nLeds = (nLedsIfOffset > 0) ? nLedsIfOffset : nLedsOrOffset;

	pLed->init();
	pLed->setLeds(data + nOffset, nLeds);
	FastLED.setMaxRefreshRate(pLed->getMaxRefreshRate(),true);
	return *pLed;
}

void CFastLED::show(uint8_t scale) {
	// guard against showing too rapidly
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	// If we have a function for computing power, use it!
	if(m_pPowerFunc) {
		scale = (*m_pPowerFunc)(scale, m_nPowerData);
	}

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showLeds(scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

int CFastLED::count() {
    int x = 0;
	CLEDController *pCur = CLEDController::head();
	while( pCur) {
        ++x;
		pCur = pCur->next();
	}
    return x;
}

CLEDController & CFastLED::operator[](int x) {
	CLEDController *pCur = CLEDController::head();
	while(x-- && pCur) {
		pCur = pCur->next();
	}
	if(pCur == NULL) {
		return *(CLEDController::head());
	} else {
		return *pCur;
	}
}

void CFastLED::showColor(const struct CRGB & color, uint8_t scale) {
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	// If we have a function for computing power, use it!
	if(m_pPowerFunc) {
		scale = (*m_pPowerFunc)(scale, m_nPowerData);
	}

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showColor(color, scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

void CFastLED::clear(bool writeData) {
	if(writeData) {
		showColor(CRGB(0,0,0), 0);
	}
    clearData();
}

void CFastLED::clearData() {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->clearLedData();
		pCur = pCur->next();
	}
}

void CFastLED::delay(unsigned long ms) {
	unsigned long start = millis();
        do {
#ifndef FASTLED_ACCURATE_CLOCK
		// make sure to allow at least one ms to pass to ensure the clock moves
		// forward
		::delay(1);
#endif
		show();
		yield();
	}
	while((millis()-start) < ms);
}

void CFastLED::setTemperature(const struct CRGB & temp) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setTemperature(temp);
		pCur = pCur->next();
	}
}

void CFastLED::setCorrection(const struct CRGB & correction) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setCorrection(correction);
		pCur = pCur->next();
	}
}

void CFastLED::setDither(uint8_t ditherMode)  {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setDither(ditherMode);
		pCur = pCur->next();
	}
}

//
// template<int m, int n> void transpose8(unsigned char A[8], unsigned char B[8]) {
// 	uint32_t x, y, t;
//
// 	// Load the array and pack it into x and y.
//   	y = *(unsigned int*)(A);
// 	x = *(unsigned int*)(A+4);
//
// 	// x = (A[0]<<24)   | (A[m]<<16)   | (A[2*m]<<8) | A[3*m];
// 	// y = (A[4*m]<<24) | (A[5*m]<<16) | (A[6*m]<<8) | A[7*m];
//
        // // pre-transform x
        // t = (x ^ (x >> 7)) & 0x00AA00AA;  x = x ^ t ^ (t << 7);
        // t = (x ^ (x >>14)) & 0x0000CCCC;  x = x ^ t ^ (t <<14);
				//
        // // pre-transform y
        // t = (y ^ (y >> 7)) & 0x00AA00AA;  y = y ^ t ^ (t << 7);
        // t = (y ^ (y >>14)) & 0x0000CCCC;  y = y ^ t ^ (t <<14);
				//
        // // final transform
        // t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F);
        // y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F);
        // x = t;
//
// 	B[7*n] = y; y >>= 8;
// 	B[6*n] = y; y >>= 8;
// 	B[5*n] = y; y >>= 8;
// 	B[4*n] = y;
//
//   B[3*n] = x; x >>= 8;
// 	B[2*n] = x; x >>= 8;
// 	B[n] = x; x >>= 8;
// 	B[0] = x;
// 	// B[0]=x>>24;    B[n]=x>>16;    B[2*n]=x>>8;  B[3*n]=x>>0;
// 	// B[4*n]=y>>24;  B[5*n]=y>>16;  B[6*n]=y>>8;  B[7*n]=y>>0;
// }
//
// void transposeLines(Lines & out, Lines & in) {
// 	transpose8<1,2>(in.bytes, out.bytes);
// 	transpose8<1,2>(in.bytes + 8, out.bytes + 1);
// }

/// Unused value
/// @todo Remove?
extern int noise_min;

/// Unused value
/// @todo Remove?
extern int noise_max;

void CFastLED::countFPS(int nFrames) {
	static int br = 0;
	static uint32_t lastframe = 0; // millis();

	if(br++ >= nFrames) {
		uint32_t now = millis();
		now -= lastframe;
		if(now == 0) {
			now = 1; // prevent division by zero below
		}
		m_nFPS = (br * 1000) / now;
		br = 0;
		lastframe = millis();
	}
}

void CFastLED::setMaxRefreshRate(uint16_t refresh, bool constrain) {
	if(constrain) {
		// if we're constraining, the new value of m_nMinMicros _must_ be higher than previously (because we're only
		// allowed to slow things down if constraining)
		if(refresh > 0) {
			m_nMinMicros = ((1000000 / refresh) > m_nMinMicros) ? (1000000 / refresh) : m_nMinMicros;
		}
	} else if(refresh > 0) {
		m_nMinMicros = 1000000 / refresh;
	} else {
		m_nMinMicros = 0;
	}
}

/// Called at program exit when run in a desktop environment.
/// Extra C definition that some environments may need.
/// @returns 0 to indicate success
extern "C" int atexit(void (* /*func*/ )()) { return 0; }

#ifdef FASTLED_NEEDS_YIELD
extern "C" void yield(void) { }
#endif

#ifdef NEED_CXX_BITS
namespace __cxxabiv1
{
	#if !defined(ESP8266) && !defined(ESP32)
	extern "C" void __cxa_pure_virtual (void) {}
	#endif

	/* guard variables */

	/* The ABI requires a 64-bit type.  */
	__extension__ typedef int __guard __attribute__((mode(__DI__)));

	extern "C" int __cxa_guard_acquire (__guard *) __attribute__((weak));
	extern "C" void __cxa_guard_release (__guard *) __attribute__((weak));
	extern "C" void __cxa_guard_abort (__guard *) __attribute__((weak));

	extern "C" int __cxa_guard_acquire (__guard *g)
	{
		return !*(char *)(g);
	}

	extern "C" void __cxa_guard_release (__guard *g)
	{
		*(char *)g = 1;
	}

	extern "C" void __cxa_guard_abort (__guard *)
	{

	}
}
#endif

FASTLED_NAMESPACE_END
<|endoftext|>


<commit_before>#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
using namespace std;

int main()
{
  while(cin)
  {
    string path;
    getline(cin, path);
    cv::Mat input = cv::imread(path+".jpg");
    cv::Mat hsv_filtered15;//画像の初期化
    cv::Mat hsv_filtered180;//画像の初期化
    cv::Mat hsv;
    cv::Mat output;
    cv::cvtColor(input,hsv,CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
    //inRange(入力画像,下界画像,上界画像,出力画像)
    //「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
    cv::inRange(hsv,cv::Scalar(0,120,97),cv::Scalar(13,255,255),hsv_filtered15);
    cv::inRange(hsv,cv::Scalar(175,120,97),cv::Scalar(180,255,255),hsv_filtered180);
    cv::add(hsv_filtered15,hsv_filtered180,output);
    cv::imwrite(path+"BINARY"+".jpg",output);
  }
return 0;
}
<commit_msg>debug<commit_after>#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
using namespace std;

int main()
{
  while(1)
  {
    string path;
    getline(cin, path);
    cv::Mat input = cv::imread(path+".jpg");
    cv::Mat hsv_filtered15;//画像の初期化
    cv::Mat hsv_filtered180;//画像の初期化
    cv::Mat hsv;
    cv::Mat output;
    cv::cvtColor(input,hsv,CV_BGR2HSV);//入力画像(src)をhsv色空間(dst)に変換
    //inRange(入力画像,下界画像,上界画像,出力画像)
    //「HSV」は、色を色相(Hue)・彩度(Saturation)・明度(Value)
    cv::inRange(hsv,cv::Scalar(0,120,97),cv::Scalar(13,255,255),hsv_filtered15);
    cv::inRange(hsv,cv::Scalar(175,120,97),cv::Scalar(180,255,255),hsv_filtered180);
    cv::add(hsv_filtered15,hsv_filtered180,output);
    cv::imwrite(path+"BINARY"+".jpg",output);
  }
return 0;
}
<|endoftext|>


<commit_before><?hh //strict

namespace hhpack\migrate;

use hhpack\publisher\Message;

final class MigrationLoadedEvent implements Message
{

    public function __construct(
        private ImmVector<Migration> $migrations
    )
    {
    }

    public function queries(): ImmVector<string>
    {
        return $this->migrations->map(($migration) ==> $migration->query());
    }

}
<commit_msg>add migrationCount method<commit_after><?hh //strict

namespace hhpack\migrate;

use hhpack\publisher\Message;

final class MigrationLoadedEvent implements Message
{

    public function __construct(
        private ImmVector<Migration> $migrations
    )
    {
    }

    public function queries(): ImmVector<string>
    {
        return $this->migrations->map(($migration) ==> $migration->query());
    }

    public function migrationCount(): ImmVector<string>
    {
        return $this->migrations->count();
    }

}
<|endoftext|>


<commit_before>/*
    Copyright 2012 <copyright holder> <email>

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "asset.hpp"

#include <boost/foreach.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <utility>

#include <lib/weak_fn.hpp>

#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>

using namespace bithorded::router;
using namespace std;

namespace bithorded { namespace router {
	log4cplus::Logger assetLogger = log4cplus::Logger::getInstance("router");
} }

UpstreamAsset::UpstreamAsset(const bithorde::ReadAsset::ClientPointer& client, const BitHordeIds& requestIds)
	: ReadAsset(client, requestIds)
{}

void UpstreamAsset::handleMessage(const bithorde::Read::Response& resp)
{
	auto self_ref = shared_from_this();
	bithorde::ReadAsset::handleMessage(resp);
}

bool bithorded::router::ForwardedAsset::hasUpstream(const std::string peername)
{
	return _upstream.count(peername);
}

void bithorded::router::ForwardedAsset::bindUpstreams(const std::map< string, bithorded::Client::Ptr >& friends, uint64_t uuid, int timeout)
{
	BOOST_FOREACH(auto f_, friends) {
		auto f = f_.second;
		if (f->requestsAsset(_ids)) // This path surely doesn't have the asset.
			continue;
		auto peername = f->peerName();
		auto& upstream = _upstream[peername] = make_shared<UpstreamAsset>(f, _ids);
		auto self = boost::weak_ptr<ForwardedAsset>(shared_from_this());
		upstream->statusUpdate.connect(boost::bind(boost::weak_fn(&ForwardedAsset::onUpstreamStatus, self), peername, bithorde::ASSET_ARG_STATUS));
		upstream->dataArrived.connect(boost::bind(boost::weak_fn(&ForwardedAsset::onData, self),
			bithorde::ASSET_ARG_OFFSET, bithorde::ASSET_ARG_DATA, bithorde::ASSET_ARG_TAG));
		if (!f->bind(*upstream, timeout, uuid))
			dropUpstream(peername);
	}
	updateStatus();
}

void bithorded::router::ForwardedAsset::onUpstreamStatus(const string& peername, const bithorde::AssetStatus& status)
{
	if (status.status() == bithorde::Status::SUCCESS) {
		LOG4CPLUS_DEBUG(assetLogger, _ids << " Found upstream " << peername);
		if (status.has_size()) {
			if (_size == -1) {
				_size = status.size();
			} else if (_size != (int64_t)status.size()) {
				LOG4CPLUS_WARN(assetLogger, peername << " " << _ids << " responded with mismatching size, ignoring...");
				dropUpstream(peername);
			}
		} else {
			LOG4CPLUS_WARN(assetLogger, peername << " " << _ids << " SUCCESS response not accompanied with asset-size.");
		}
	} else {
		LOG4CPLUS_DEBUG(assetLogger, _ids << "Failed upstream " << peername);
		dropUpstream(peername);
	}
	updateStatus();
}

void bithorded::router::ForwardedAsset::updateStatus() {
	bithorde::Status status = _upstream.empty() ? bithorde::Status::NOTFOUND : bithorde::Status::NONE;
	for (auto iter=_upstream.begin(); iter!=_upstream.end(); iter++) {
		auto& asset = iter->second;
		if (asset->status == bithorde::Status::SUCCESS)
			status = bithorde::Status::SUCCESS;
	}
	setStatus(status);
}

size_t bithorded::router::ForwardedAsset::can_read(uint64_t offset, size_t size)
{
	return size;
}

bool bithorded::router::ForwardedAsset::getIds(BitHordeIds& ids) const
{
	ids = _ids;
	return true;
}

void bithorded::router::ForwardedAsset::async_read(uint64_t offset, size_t& size, uint32_t timeout, ReadCallback cb)
{
	if (_upstream.empty())
		return cb(-1, string());
	auto chosen = _upstream.begin();
	uint32_t current_best = 1000*60*60*24;
	for (auto iter = _upstream.begin(); iter != _upstream.end(); iter++) {
		auto& a = iter->second;
		if (current_best > a->readResponseTime.value()) {
			current_best = a->readResponseTime.value();
			chosen = iter;
		}
	}
	PendingRead read;
	read.offset = offset;
	read.size = size;
	read.cb = cb;
	_pendingReads.push_back(read);
	chosen->second->aSyncRead(offset, size, timeout);
}

void bithorded::router::ForwardedAsset::onData(uint64_t offset, const std::string& data, int tag) {
	for (auto iter=_pendingReads.begin(); iter != _pendingReads.end(); ) {
		if (iter->offset == offset) {
			iter->cb(offset, data);
			iter = _pendingReads.erase(iter); // Will increase the iterator
		} else {
			iter++;	// Move to next
		}
	}
}

uint64_t bithorded::router::ForwardedAsset::size()
{
	return _size;
}

void ForwardedAsset::inspect(bithorded::management::InfoList& target) const
{
	target.append("type") << "forwarded";
}

void ForwardedAsset::inspect_upstreams(bithorded::management::InfoList& target) const
{
	for (auto iter = _upstream.begin(); iter != _upstream.end(); iter++) {
		ostringstream buf;
		buf << "upstream_" << iter->first;
		target.append(buf.str()) << bithorde::Status_Name(iter->second->status) << ", responseTime: " << iter->second->readResponseTime;
	}
}

void ForwardedAsset::dropUpstream(const string& peername)
{
	auto upstream = _upstream.find(peername);
	if (upstream != _upstream.end()) {
		upstream->second->statusUpdate.disconnect(boost::bind(&ForwardedAsset::onUpstreamStatus, this, peername, bithorde::ASSET_ARG_STATUS));
		upstream->second->dataArrived.disconnect(boost::bind(&ForwardedAsset::onData, this,
			bithorde::ASSET_ARG_OFFSET, bithorde::ASSET_ARG_DATA, bithorde::ASSET_ARG_TAG));
		_upstream.erase(upstream);
	}
}
<commit_msg>[bithorded/router/asset]Ignore assets without successful binding. Kudos to Adam for reporting and identifying the problem.<commit_after>/*
    Copyright 2012 <copyright holder> <email>

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "asset.hpp"

#include <boost/foreach.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <utility>

#include <lib/weak_fn.hpp>

#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>

using namespace bithorded::router;
using namespace std;

namespace bithorded { namespace router {
	log4cplus::Logger assetLogger = log4cplus::Logger::getInstance("router");
} }

UpstreamAsset::UpstreamAsset(const bithorde::ReadAsset::ClientPointer& client, const BitHordeIds& requestIds)
	: ReadAsset(client, requestIds)
{}

void UpstreamAsset::handleMessage(const bithorde::Read::Response& resp)
{
	auto self_ref = shared_from_this();
	bithorde::ReadAsset::handleMessage(resp);
}

bool bithorded::router::ForwardedAsset::hasUpstream(const std::string peername)
{
	return _upstream.count(peername);
}

void bithorded::router::ForwardedAsset::bindUpstreams(const std::map< string, bithorded::Client::Ptr >& friends, uint64_t uuid, int timeout)
{
	BOOST_FOREACH(auto f_, friends) {
		auto f = f_.second;
		if (f->requestsAsset(_ids)) // This path surely doesn't have the asset.
			continue;
		auto peername = f->peerName();
		auto& upstream = _upstream[peername] = make_shared<UpstreamAsset>(f, _ids);
		auto self = boost::weak_ptr<ForwardedAsset>(shared_from_this());
		upstream->statusUpdate.connect(boost::bind(boost::weak_fn(&ForwardedAsset::onUpstreamStatus, self), peername, bithorde::ASSET_ARG_STATUS));
		upstream->dataArrived.connect(boost::bind(boost::weak_fn(&ForwardedAsset::onData, self),
			bithorde::ASSET_ARG_OFFSET, bithorde::ASSET_ARG_DATA, bithorde::ASSET_ARG_TAG));
		if (!f->bind(*upstream, timeout, uuid))
			dropUpstream(peername);
	}
	updateStatus();
}

void bithorded::router::ForwardedAsset::onUpstreamStatus(const string& peername, const bithorde::AssetStatus& status)
{
	if (status.status() == bithorde::Status::SUCCESS) {
		LOG4CPLUS_DEBUG(assetLogger, _ids << " Found upstream " << peername);
		if (status.has_size()) {
			if (_size == -1) {
				_size = status.size();
			} else if (_size != (int64_t)status.size()) {
				LOG4CPLUS_WARN(assetLogger, peername << " " << _ids << " responded with mismatching size, ignoring...");
				dropUpstream(peername);
			}
		} else {
			LOG4CPLUS_WARN(assetLogger, peername << " " << _ids << " SUCCESS response not accompanied with asset-size.");
		}
	} else {
		LOG4CPLUS_DEBUG(assetLogger, _ids << "Failed upstream " << peername);
		dropUpstream(peername);
	}
	updateStatus();
}

void bithorded::router::ForwardedAsset::updateStatus() {
	bithorde::Status status = _upstream.empty() ? bithorde::Status::NOTFOUND : bithorde::Status::NONE;
	for (auto iter=_upstream.begin(); iter!=_upstream.end(); iter++) {
		auto& asset = iter->second;
		if (asset->status == bithorde::Status::SUCCESS)
			status = bithorde::Status::SUCCESS;
	}
	setStatus(status);
}

size_t bithorded::router::ForwardedAsset::can_read(uint64_t offset, size_t size)
{
	return size;
}

bool bithorded::router::ForwardedAsset::getIds(BitHordeIds& ids) const
{
	ids = _ids;
	return true;
}

void bithorded::router::ForwardedAsset::async_read(uint64_t offset, size_t& size, uint32_t timeout, ReadCallback cb)
{
	if (_upstream.empty())
		return cb(-1, string());
	auto chosen = _upstream.begin();
	uint32_t current_best = 1000*60*60*24;
	for (auto iter = _upstream.begin(); iter != _upstream.end(); iter++) {
		auto& a = iter->second;
		if (a->status != bithorde::SUCCESS)
			continue;
		if (current_best > a->readResponseTime.value()) {
			current_best = a->readResponseTime.value();
			chosen = iter;
		}
	}
	PendingRead read;
	read.offset = offset;
	read.size = size;
	read.cb = cb;
	_pendingReads.push_back(read);
	chosen->second->aSyncRead(offset, size, timeout);
}

void bithorded::router::ForwardedAsset::onData(uint64_t offset, const std::string& data, int tag) {
	for (auto iter=_pendingReads.begin(); iter != _pendingReads.end(); ) {
		if (iter->offset == offset) {
			iter->cb(offset, data);
			iter = _pendingReads.erase(iter); // Will increase the iterator
		} else {
			iter++;	// Move to next
		}
	}
}

uint64_t bithorded::router::ForwardedAsset::size()
{
	return _size;
}

void ForwardedAsset::inspect(bithorded::management::InfoList& target) const
{
	target.append("type") << "forwarded";
}

void ForwardedAsset::inspect_upstreams(bithorded::management::InfoList& target) const
{
	for (auto iter = _upstream.begin(); iter != _upstream.end(); iter++) {
		ostringstream buf;
		buf << "upstream_" << iter->first;
		target.append(buf.str()) << bithorde::Status_Name(iter->second->status) << ", responseTime: " << iter->second->readResponseTime;
	}
}

void ForwardedAsset::dropUpstream(const string& peername)
{
	auto upstream = _upstream.find(peername);
	if (upstream != _upstream.end()) {
		upstream->second->statusUpdate.disconnect(boost::bind(&ForwardedAsset::onUpstreamStatus, this, peername, bithorde::ASSET_ARG_STATUS));
		upstream->second->dataArrived.disconnect(boost::bind(&ForwardedAsset::onData, this,
			bithorde::ASSET_ARG_OFFSET, bithorde::ASSET_ARG_DATA, bithorde::ASSET_ARG_TAG));
		_upstream.erase(upstream);
	}
}
<|endoftext|>


<commit_before>#ifndef __RMOL_RMOL_TYPES_HPP
#define __RMOL_RMOL_TYPES_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <vector>
#include <list>
// Boost
#include <boost/shared_ptr.hpp>

namespace RMOL {

  // Forward declarations
  class RMOL_Service;

   // ///////// Exceptions ///////////
  class RootException : public std::exception {
  };

  class FileNotFoundException : public RootException {
  };

  class NonInitialisedServiceException : public RootException {
  };

  class MemoryAllocationException : public RootException {
  };

  class ObjectNotFoundException : public RootException {
  };

  class DocumentNotFoundException : public RootException {
  };

  // /////////////// Log /////////////
  /** Level of logs. */
  namespace LOG {
    typedef enum {
      CRITICAL = 0,
      ERROR,
      NOTIFICATION,
      WARNING,
      DEBUG,
      VERBOSE,
      LAST_VALUE
    } EN_LogLevel;
  }

  // //////// Type definitions /////////
  /** Pointer on the RMOL Service handler. */
  typedef boost::shared_ptr<RMOL_Service> RMOL_ServicePtr_T;

}
#endif // __RMOL_RMOL_TYPES_HPP
<commit_msg>[RMOL][Dev] Fixed a merge issue in RMOL_Types.<commit_after>#ifndef __RMOL_RMOL_TYPES_HPP
#define __RMOL_RMOL_TYPES_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// Boost
#include <boost/shared_ptr.hpp>
// StdAir
#include <stdair/stdair_exceptions.hpp>

namespace RMOL {

  // Forward declarations
  class RMOL_Service;

  // ///////// Exceptions ///////////
  /**
   * @brief Overbooking-related exception.
   */
  class OverbookingException : public stdair::RootException {
  public:
    /** Constructor. */
    OverbookingException (const std::string& iWhat)
      : stdair::RootException (iWhat) {}
  };

  /**
   * @brief Unconstraining-related exception.
   */
  class UnconstrainingException : public stdair::RootException {
  public:
    /** Constructor. */
    UnconstrainingException (const std::string& iWhat)
      : stdair::RootException (iWhat) {}
  };

  /**
   * @brief Forecast-related exception.
   */
  class ForecastException : public stdair::RootException {
  public:
    /** Constructor. */
    ForecastException (const std::string& iWhat)
      : stdair::RootException (iWhat) {}
  };

  /**
   * @brief Optimisation-related exception.
   */
  class OptimisationException : public stdair::RootException {
  public:
    /** Constructor. */
    OptimisationException (const std::string& iWhat)
      : stdair::RootException (iWhat) {}
  };

  // //////// Type definitions /////////
  /**
   * Pointer on the RMOL Service handler.
   */
  typedef boost::shared_ptr<RMOL_Service> RMOL_ServicePtr_T;

}
#endif // __RMOL_RMOL_TYPES_HPP
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdint.h>
#include <time.h>

#include <v8.h>
#include <node.h>
#include "nan.h"

using namespace node;
using namespace v8;

class Time {
  public:
  static void Init(Handle<Object> target) {
    NanScope();

    // time(3)
    NODE_SET_METHOD(target, "time", Time_);

    // tzset(3)
    NODE_SET_METHOD(target, "tzset", Tzset);

    // localtime
    NODE_SET_METHOD(target, "localtime", Localtime);

    // mktime
    NODE_SET_METHOD(target, "mktime", Mktime);
  }

  static NAN_METHOD(Time_) {
    NanReturnValue(Integer::New(time(NULL)));
  }

  static NAN_METHOD(Tzset) {
    NanScope();

    // Set up the timezone info from the current TZ environ variable
    tzset();

    // Set up a return object that will hold the results of the timezone change
    Local<Object> obj = Object::New();

    // The 'tzname' char * [] gets put into a JS Array
    int tznameLength = 2;
    Local<Array> tznameArray = Array::New( tznameLength );
    for (int i=0; i < tznameLength; i++) {
      tznameArray->Set(Number::New(i), String::NewSymbol( tzname[i] ));
    }
    obj->Set(String::NewSymbol("tzname"), tznameArray);

    // The 'timezone' long is the "seconds West of UTC"
    obj->Set(String::NewSymbol("timezone"), Number::New( timezone ));

    // The 'daylight' int is obselete actually, but I'll include it here for
    // curiosity's sake. See the "Notes" section of "man tzset"
    obj->Set(String::NewSymbol("daylight"), Number::New( daylight ));

    NanReturnValue(obj);
  }

  static NAN_METHOD(Localtime) {
    NanScope();

    // Construct the 'tm' struct
    time_t rawtime = static_cast<time_t>(args[0]->IntegerValue());
    struct tm *timeinfo = localtime( &rawtime );

    // Create the return "Object"
    Local<Object> obj = Object::New();

    if (timeinfo) {
      obj->Set(String::NewSymbol("seconds"), Integer::New(timeinfo->tm_sec) );
      obj->Set(String::NewSymbol("minutes"), Integer::New(timeinfo->tm_min) );
      obj->Set(String::NewSymbol("hours"), Integer::New(timeinfo->tm_hour) );
      obj->Set(String::NewSymbol("dayOfMonth"), Integer::New(timeinfo->tm_mday) );
      obj->Set(String::NewSymbol("month"), Integer::New(timeinfo->tm_mon) );
      obj->Set(String::NewSymbol("year"), Integer::New(timeinfo->tm_year) );
      obj->Set(String::NewSymbol("dayOfWeek"), Integer::New(timeinfo->tm_wday) );
      obj->Set(String::NewSymbol("dayOfYear"), Integer::New(timeinfo->tm_yday) );
      obj->Set(String::NewSymbol("isDaylightSavings"), Boolean::New(timeinfo->tm_isdst > 0) );

#if defined HAVE_TM_GMTOFF
      // Only available with glibc's "tm" struct. Most Linuxes, Mac OS X...
      obj->Set(String::NewSymbol("gmtOffset"), Integer::New(timeinfo->tm_gmtoff) );
      obj->Set(String::NewSymbol("timezone"), String::NewSymbol(timeinfo->tm_zone) );

#elif defined HAVE_TIMEZONE
      // Compatibility for Cygwin, Solaris, probably others...
      long scd;
      if (timeinfo->tm_isdst > 0) {
  #ifdef HAVE_ALTZONE
        scd = -altzone;
  #else
        scd = -timezone + 3600;
  #endif // HAVE_ALTZONE
      } else {
        scd = -timezone;
      }
      obj->Set(String::NewSymbol("gmtOffset"), Integer::New(scd));
      obj->Set(String::NewSymbol("timezone"), String::NewSymbol(tzname[timeinfo->tm_isdst]));
#endif // HAVE_TM_GMTOFF
    } else {
      obj->Set(String::NewSymbol("invalid"), True());
    }

    NanReturnValue(obj);
  }

  static NAN_METHOD(Mktime) {
    NanScope();
    if (args.Length() < 1) {
      return NanThrowTypeError("localtime() Object expected");
    }

    Local<Object> arg = args[0]->ToObject();

    struct tm tmstr;
    tmstr.tm_sec   = arg->Get(String::NewSymbol("seconds"))->Int32Value();
    tmstr.tm_min   = arg->Get(String::NewSymbol("minutes"))->Int32Value();
    tmstr.tm_hour  = arg->Get(String::NewSymbol("hours"))->Int32Value();
    tmstr.tm_mday  = arg->Get(String::NewSymbol("dayOfMonth"))->Int32Value();
    tmstr.tm_mon   = arg->Get(String::NewSymbol("month"))->Int32Value();
    tmstr.tm_year  = arg->Get(String::NewSymbol("year"))->Int32Value();
    tmstr.tm_isdst = arg->Get(String::NewSymbol("isDaylightSavings"))->Int32Value();
    // tm_wday and tm_yday are ignored for input, but properly set after 'mktime' is called

    NanReturnValue(Number::New(static_cast<double>(mktime( &tmstr ))));
  }

};

extern "C" {
  static void init (Handle<Object> target) {
    Time::Init(target);
  }
  NODE_MODULE(time, init)
}
<commit_msg>Fix of missing scope.<commit_after>#include <stdio.h>
#include <stdint.h>
#include <time.h>

#include <v8.h>
#include <node.h>
#include "nan.h"

using namespace node;
using namespace v8;

class Time {
  public:
  static void Init(Handle<Object> target) {
    NanScope();

    // time(3)
    NODE_SET_METHOD(target, "time", Time_);

    // tzset(3)
    NODE_SET_METHOD(target, "tzset", Tzset);

    // localtime
    NODE_SET_METHOD(target, "localtime", Localtime);

    // mktime
    NODE_SET_METHOD(target, "mktime", Mktime);
  }

  static NAN_METHOD(Time_) {
    NanScope();
    NanReturnValue(Integer::New(time(NULL)));
  }

  static NAN_METHOD(Tzset) {
    NanScope();

    // Set up the timezone info from the current TZ environ variable
    tzset();

    // Set up a return object that will hold the results of the timezone change
    Local<Object> obj = Object::New();

    // The 'tzname' char * [] gets put into a JS Array
    int tznameLength = 2;
    Local<Array> tznameArray = Array::New( tznameLength );
    for (int i=0; i < tznameLength; i++) {
      tznameArray->Set(Number::New(i), String::NewSymbol( tzname[i] ));
    }
    obj->Set(String::NewSymbol("tzname"), tznameArray);

    // The 'timezone' long is the "seconds West of UTC"
    obj->Set(String::NewSymbol("timezone"), Number::New( timezone ));

    // The 'daylight' int is obselete actually, but I'll include it here for
    // curiosity's sake. See the "Notes" section of "man tzset"
    obj->Set(String::NewSymbol("daylight"), Number::New( daylight ));

    NanReturnValue(obj);
  }

  static NAN_METHOD(Localtime) {
    NanScope();

    // Construct the 'tm' struct
    time_t rawtime = static_cast<time_t>(args[0]->IntegerValue());
    struct tm *timeinfo = localtime( &rawtime );

    // Create the return "Object"
    Local<Object> obj = Object::New();

    if (timeinfo) {
      obj->Set(String::NewSymbol("seconds"), Integer::New(timeinfo->tm_sec) );
      obj->Set(String::NewSymbol("minutes"), Integer::New(timeinfo->tm_min) );
      obj->Set(String::NewSymbol("hours"), Integer::New(timeinfo->tm_hour) );
      obj->Set(String::NewSymbol("dayOfMonth"), Integer::New(timeinfo->tm_mday) );
      obj->Set(String::NewSymbol("month"), Integer::New(timeinfo->tm_mon) );
      obj->Set(String::NewSymbol("year"), Integer::New(timeinfo->tm_year) );
      obj->Set(String::NewSymbol("dayOfWeek"), Integer::New(timeinfo->tm_wday) );
      obj->Set(String::NewSymbol("dayOfYear"), Integer::New(timeinfo->tm_yday) );
      obj->Set(String::NewSymbol("isDaylightSavings"), Boolean::New(timeinfo->tm_isdst > 0) );

#if defined HAVE_TM_GMTOFF
      // Only available with glibc's "tm" struct. Most Linuxes, Mac OS X...
      obj->Set(String::NewSymbol("gmtOffset"), Integer::New(timeinfo->tm_gmtoff) );
      obj->Set(String::NewSymbol("timezone"), String::NewSymbol(timeinfo->tm_zone) );

#elif defined HAVE_TIMEZONE
      // Compatibility for Cygwin, Solaris, probably others...
      long scd;
      if (timeinfo->tm_isdst > 0) {
  #ifdef HAVE_ALTZONE
        scd = -altzone;
  #else
        scd = -timezone + 3600;
  #endif // HAVE_ALTZONE
      } else {
        scd = -timezone;
      }
      obj->Set(String::NewSymbol("gmtOffset"), Integer::New(scd));
      obj->Set(String::NewSymbol("timezone"), String::NewSymbol(tzname[timeinfo->tm_isdst]));
#endif // HAVE_TM_GMTOFF
    } else {
      obj->Set(String::NewSymbol("invalid"), True());
    }

    NanReturnValue(obj);
  }

  static NAN_METHOD(Mktime) {
    NanScope();
    if (args.Length() < 1) {
      return NanThrowTypeError("localtime() Object expected");
    }

    Local<Object> arg = args[0]->ToObject();

    struct tm tmstr;
    tmstr.tm_sec   = arg->Get(String::NewSymbol("seconds"))->Int32Value();
    tmstr.tm_min   = arg->Get(String::NewSymbol("minutes"))->Int32Value();
    tmstr.tm_hour  = arg->Get(String::NewSymbol("hours"))->Int32Value();
    tmstr.tm_mday  = arg->Get(String::NewSymbol("dayOfMonth"))->Int32Value();
    tmstr.tm_mon   = arg->Get(String::NewSymbol("month"))->Int32Value();
    tmstr.tm_year  = arg->Get(String::NewSymbol("year"))->Int32Value();
    tmstr.tm_isdst = arg->Get(String::NewSymbol("isDaylightSavings"))->Int32Value();
    // tm_wday and tm_yday are ignored for input, but properly set after 'mktime' is called

    NanReturnValue(Number::New(static_cast<double>(mktime( &tmstr ))));
  }

};

extern "C" {
  static void init (Handle<Object> target) {
    Time::Init(target);
  }
  NODE_MODULE(time, init)
}
<|endoftext|>


<commit_before>/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#include <SymbolicEngine.h>
#include <Registers.h>

SymbolicEngine::SymbolicEngine() {
  /* Init all symbolic registers/flags to UNSET (init state) */
  for (uint64 i = 0; i < ID_LAST_ITEM; i++)
    this->symbolicReg[i] = UNSET;
  this->uniqueID = 0;
}

void SymbolicEngine::init(const SymbolicEngine &other) {
  for (uint64 i = 0; i < ID_LAST_ITEM; i++)
    this->symbolicReg[i] = other.symbolicReg[i];

  this->uniqueID                      = other.uniqueID;
  this->memoryReference               = other.memoryReference;
  this->pathConstaints                = other.pathConstaints;
  this->symbolicExpressions           = other.symbolicExpressions;
  this->symbolicVariables             = other.symbolicVariables;
}

SymbolicEngine::SymbolicEngine(const SymbolicEngine &copy) {
  this->init(copy);
}

void SymbolicEngine::operator=(const SymbolicEngine &other) {
  this->init(other);
}

SymbolicEngine::~SymbolicEngine() {
  std::vector<SymbolicExpression *>::iterator it1 = this->symbolicExpressions.begin();
  std::vector<SymbolicVariable *>::iterator it2 = this->symbolicVariables.begin();

  /* Delete all symbolic expressions */
  for (; it1 != this->symbolicExpressions.end(); ++it1)
    delete *it1;

  /* Delete all symbolic variables */
  for (; it2 != this->symbolicVariables.end(); ++it2)
    delete *it2;
}

/*
 * Concretize a register. If the register is setup at UNSETthe next assignment
 * will be over the concretization. This method must be called before symbolic
 * processing.
 */
void SymbolicEngine::concretizeReg(uint64 regID) {
  if (regID >= ID_LAST_ITEM)
    return ;
  this->symbolicReg[regID] = UNSET;
}

/* Same as concretizeReg but with all registers */
void SymbolicEngine::concretizeAllReg(void) {
  for (uint64 i = 0; i < ID_LAST_ITEM; i++)
    this->symbolicReg[i] = UNSET;
}

/*
 * Concretize a memory. If the memory is not found into the map, the next
 * assignment will be over the concretization. This method must be called
 * before symbolic processing.
 */
void SymbolicEngine::concretizeMem(uint64 mem) {
  this->memoryReference.erase(mem);
}

/* Same as concretizeMem but with all address memory */
void SymbolicEngine::concretizeAllMem(void) {
  this->memoryReference.clear();
}

/* Returns the reference memory if it's referenced otherwise returns UNSET */
uint64 SymbolicEngine::getMemSymbolicID(uint64 addr) {
  std::map<uint64, uint64>::iterator it;
  if ((it = this->memoryReference.find(addr)) != this->memoryReference.end())
    return it->second;
  return UNSET;
}

/* Returns the symbolic variable otherwise returns nullptr */
SymbolicVariable *SymbolicEngine::getSymVar(uint64 symVarId) {
  if (symVarId >= this->symbolicVariables.size())
    return nullptr;
  return this->symbolicVariables[symVarId];
}

/* Returns the symbolic variable otherwise returns nullptr */
SymbolicVariable *SymbolicEngine::getSymVar(std::string symVarName) {
  std::vector<SymbolicVariable *>::iterator it;

  for (it = this->symbolicVariables.begin(); it != this->symbolicVariables.end(); it++){
    if ((*it)->getSymVarName() == symVarName)
      return *it;
  }
  return nullptr;
}

/* Returns all symbolic variables */
std::vector<SymbolicVariable *> SymbolicEngine::getSymVars(void) {
  return this->symbolicVariables;
}

/* Return the reg reference or UNSET */
uint64 SymbolicEngine::getRegSymbolicID(uint64 regID) {
  if (regID >= ID_LAST_ITEM)
    return UNSET;
  return this->symbolicReg[regID];
}

/* Create a new symbolic expression */
/* Get an unique ID.
 * Mainly used when a new symbolic expression is created */
uint64 SymbolicEngine::getUniqueID() {
  return this->uniqueID++;
}

/* Create a new symbolic expression with comment */
SymbolicExpression *SymbolicEngine::newSymbolicExpression(smt2lib::smtAstAbstractNode *node, std::string comment) {
  uint64 id = this->getUniqueID();
  SymbolicExpression *expr = new SymbolicExpression(node, id, comment);
  this->symbolicExpressions.push_back(expr);
  return expr;
}

/* Get the symbolic expression pointer from a symbolic ID */
SymbolicExpression *SymbolicEngine::getExpressionFromId(uint64 id) {
  if (id >= this->symbolicExpressions.size())
    return nullptr;
  return this->symbolicExpressions[id];
}

/* Returns all symbolic expressions */
std::vector<SymbolicExpression *> SymbolicEngine::getExpressions(void) {
  return this->symbolicExpressions;
}

/* Returns the full symbolic expression backtracked. */
smt2lib::smtAstAbstractNode *SymbolicEngine::getFullExpression(smt2lib::smtAstAbstractNode *node) {
  uint64 index = 0;
  std::vector<smt2lib::smtAstAbstractNode *> &childs = node->getChilds();

  for ( ; index < childs.size(); index++) {
    if (childs[index]->getKind() == smt2lib::REFERENCE_NODE) {
      uint64 id = reinterpret_cast<smt2lib::smtAstReferenceNode*>(childs[index])->getValue();
      smt2lib::smtAstAbstractNode *ref = this->getExpressionFromId(id)->getExpression();
      childs[index] = smt2lib::newInstance(ref);
    }
    this->getFullExpression(childs[index]);
  }

  return node;
}

/* Returns a list which contains all tainted expressions */
std::list<SymbolicExpression *> SymbolicEngine::getTaintedExpressions(void) {
  uint64 index = 0;
  std::list<SymbolicExpression *> taintedExprs;

  for ( ; index < this->symbolicExpressions.size(); index++) {
    if (symbolicExpressions[index]->isTainted == true)
      taintedExprs.push_back(symbolicExpressions[index]);
  }
  return taintedExprs;
}

/* Returns the list of the symbolic variables declared in the trace */
std::string SymbolicEngine::getVariablesDeclaration(void) {
  std::vector<SymbolicVariable*>::iterator it;
  std::stringstream stream;

  for(it = this->symbolicVariables.begin(); it != this->symbolicVariables.end(); it++)
    stream << smt2lib::declare((*it)->getSymVarName(), (*it)->getSymVarSize());

  return stream.str();
}

/*
 * Converts an expression ID to a symbolic variable.
 * e.g:
 * #43 = (_ bv10 8)
 * convertExprToSymVar(43, 8)
 * #43 = SymVar_4
 */
SymbolicVariable *SymbolicEngine::convertExprToSymVar(uint64 exprId, uint64 symVarSize, std::string symVarComment) {
  SymbolicVariable    *symVar = nullptr;
  SymbolicExpression  *expression = this->getExpressionFromId(exprId);

  if (expression == nullptr)
    return nullptr;

  symVar = this->addSymbolicVariable(SymVar::kind::UNDEF, 0, symVarSize, symVarComment);

  expression->setExpression(smt2lib::variable(symVar->getSymVarName()));

  return symVar;
}

SymbolicVariable *SymbolicEngine::convertMemToSymVar(uint64 memAddr, uint64 symVarSize, std::string symVarComment) {
  SymbolicVariable   *symVar = nullptr;
  SymbolicExpression *expression = nullptr;
  uint64             memSymId = UNSET;

  memSymId = this->getMemSymbolicID(memAddr);
  if (memSymId == UNSET)
    throw std::runtime_error("SymbolicEngine::convertMemToSymVar() - This memory address is UNSET");

  expression = this->getExpressionFromId(memSymId);

  if (expression == nullptr)
    return nullptr;

  symVar = this->addSymbolicVariable(SymVar::kind::MEM, memAddr, symVarSize, symVarComment);

  expression->setExpression(smt2lib::variable(symVar->getSymVarName()));

  return symVar;
}

SymbolicVariable *SymbolicEngine::convertRegToSymVar(uint64 regId, uint64 symVarSize, std::string symVarComment) {
  SymbolicVariable   *symVar = nullptr;
  SymbolicExpression *expression = nullptr;
  uint64             regSymId = UNSET;

  if (regId >= ID_LAST_ITEM)
    throw std::runtime_error("SymbolicEngine::convertRegToSymVar() - Invalid register ID");

  regSymId = this->getRegSymbolicID(regId);
  if (regSymId == UNSET)
    throw std::runtime_error("SymbolicEngine::convertRegToSymVar() - This register ID is UNSET");

  expression = this->getExpressionFromId(regSymId);

  if (expression == nullptr)
    return nullptr;

  symVar = this->addSymbolicVariable(SymVar::kind::REG, regId, symVarSize, symVarComment);

  expression->setExpression(smt2lib::variable(symVar->getSymVarName()));

  return symVar;
}

/* Add a new symbolic variable */
SymbolicVariable *SymbolicEngine::addSymbolicVariable(SymVar::kind kind, uint64 kindValue, uint64 size, std::string comment) {
  uint64 uniqueID = this->symbolicVariables.size();
  SymbolicVariable *symVar = new SymbolicVariable(kind, kindValue, uniqueID, size, comment);

  if (symVar == nullptr)
    throw std::runtime_error("SymbolicEngine::addSymbolicVariable() - Cannot allocate a new symbolic variable");

  this->symbolicVariables.push_back(symVar);
  return symVar;
}

/* Add and assign a new memory reference */
void SymbolicEngine::addMemoryReference(uint64 mem, uint64 id) {
  this->memoryReference[mem] = id;
}

/* The a path constraint in the PC list */
void SymbolicEngine::addPathConstraint(uint64 exprId) {
  this->pathConstaints.push_back(exprId);
}

/* Returns the path constrains list */
std::list<uint64> SymbolicEngine::getPathConstraints(void) {
  return this->pathConstaints;
}

<commit_msg>#109 in progress - Create symVar when it is UNSET<commit_after>/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#include <SymbolicEngine.h>
#include <Registers.h>

SymbolicEngine::SymbolicEngine() {
  /* Init all symbolic registers/flags to UNSET (init state) */
  for (uint64 i = 0; i < ID_LAST_ITEM; i++)
    this->symbolicReg[i] = UNSET;
  this->uniqueID = 0;
}

void SymbolicEngine::init(const SymbolicEngine &other) {
  for (uint64 i = 0; i < ID_LAST_ITEM; i++)
    this->symbolicReg[i] = other.symbolicReg[i];

  this->uniqueID                      = other.uniqueID;
  this->memoryReference               = other.memoryReference;
  this->pathConstaints                = other.pathConstaints;
  this->symbolicExpressions           = other.symbolicExpressions;
  this->symbolicVariables             = other.symbolicVariables;
}

SymbolicEngine::SymbolicEngine(const SymbolicEngine &copy) {
  this->init(copy);
}

void SymbolicEngine::operator=(const SymbolicEngine &other) {
  this->init(other);
}

SymbolicEngine::~SymbolicEngine() {
  std::vector<SymbolicExpression *>::iterator it1 = this->symbolicExpressions.begin();
  std::vector<SymbolicVariable *>::iterator it2 = this->symbolicVariables.begin();

  /* Delete all symbolic expressions */
  for (; it1 != this->symbolicExpressions.end(); ++it1)
    delete *it1;

  /* Delete all symbolic variables */
  for (; it2 != this->symbolicVariables.end(); ++it2)
    delete *it2;
}

/*
 * Concretize a register. If the register is setup at UNSETthe next assignment
 * will be over the concretization. This method must be called before symbolic
 * processing.
 */
void SymbolicEngine::concretizeReg(uint64 regID) {
  if (regID >= ID_LAST_ITEM)
    return ;
  this->symbolicReg[regID] = UNSET;
}

/* Same as concretizeReg but with all registers */
void SymbolicEngine::concretizeAllReg(void) {
  for (uint64 i = 0; i < ID_LAST_ITEM; i++)
    this->symbolicReg[i] = UNSET;
}

/*
 * Concretize a memory. If the memory is not found into the map, the next
 * assignment will be over the concretization. This method must be called
 * before symbolic processing.
 */
void SymbolicEngine::concretizeMem(uint64 mem) {
  this->memoryReference.erase(mem);
}

/* Same as concretizeMem but with all address memory */
void SymbolicEngine::concretizeAllMem(void) {
  this->memoryReference.clear();
}

/* Returns the reference memory if it's referenced otherwise returns UNSET */
uint64 SymbolicEngine::getMemSymbolicID(uint64 addr) {
  std::map<uint64, uint64>::iterator it;
  if ((it = this->memoryReference.find(addr)) != this->memoryReference.end())
    return it->second;
  return UNSET;
}

/* Returns the symbolic variable otherwise returns nullptr */
SymbolicVariable *SymbolicEngine::getSymVar(uint64 symVarId) {
  if (symVarId >= this->symbolicVariables.size())
    return nullptr;
  return this->symbolicVariables[symVarId];
}

/* Returns the symbolic variable otherwise returns nullptr */
SymbolicVariable *SymbolicEngine::getSymVar(std::string symVarName) {
  std::vector<SymbolicVariable *>::iterator it;

  for (it = this->symbolicVariables.begin(); it != this->symbolicVariables.end(); it++){
    if ((*it)->getSymVarName() == symVarName)
      return *it;
  }
  return nullptr;
}

/* Returns all symbolic variables */
std::vector<SymbolicVariable *> SymbolicEngine::getSymVars(void) {
  return this->symbolicVariables;
}

/* Return the reg reference or UNSET */
uint64 SymbolicEngine::getRegSymbolicID(uint64 regID) {
  if (regID >= ID_LAST_ITEM)
    return UNSET;
  return this->symbolicReg[regID];
}

/* Create a new symbolic expression */
/* Get an unique ID.
 * Mainly used when a new symbolic expression is created */
uint64 SymbolicEngine::getUniqueID() {
  return this->uniqueID++;
}

/* Create a new symbolic expression with comment */
SymbolicExpression *SymbolicEngine::newSymbolicExpression(smt2lib::smtAstAbstractNode *node, std::string comment) {
  uint64 id = this->getUniqueID();
  SymbolicExpression *expr = new SymbolicExpression(node, id, comment);
  this->symbolicExpressions.push_back(expr);
  return expr;
}

/* Get the symbolic expression pointer from a symbolic ID */
SymbolicExpression *SymbolicEngine::getExpressionFromId(uint64 id) {
  if (id >= this->symbolicExpressions.size())
    return nullptr;
  return this->symbolicExpressions[id];
}

/* Returns all symbolic expressions */
std::vector<SymbolicExpression *> SymbolicEngine::getExpressions(void) {
  return this->symbolicExpressions;
}

/* Returns the full symbolic expression backtracked. */
smt2lib::smtAstAbstractNode *SymbolicEngine::getFullExpression(smt2lib::smtAstAbstractNode *node) {
  uint64 index = 0;
  std::vector<smt2lib::smtAstAbstractNode *> &childs = node->getChilds();

  for ( ; index < childs.size(); index++) {
    if (childs[index]->getKind() == smt2lib::REFERENCE_NODE) {
      uint64 id = reinterpret_cast<smt2lib::smtAstReferenceNode*>(childs[index])->getValue();
      smt2lib::smtAstAbstractNode *ref = this->getExpressionFromId(id)->getExpression();
      childs[index] = smt2lib::newInstance(ref);
    }
    this->getFullExpression(childs[index]);
  }

  return node;
}

/* Returns a list which contains all tainted expressions */
std::list<SymbolicExpression *> SymbolicEngine::getTaintedExpressions(void) {
  uint64 index = 0;
  std::list<SymbolicExpression *> taintedExprs;

  for ( ; index < this->symbolicExpressions.size(); index++) {
    if (symbolicExpressions[index]->isTainted == true)
      taintedExprs.push_back(symbolicExpressions[index]);
  }
  return taintedExprs;
}

/* Returns the list of the symbolic variables declared in the trace */
std::string SymbolicEngine::getVariablesDeclaration(void) {
  std::vector<SymbolicVariable*>::iterator it;
  std::stringstream stream;

  for(it = this->symbolicVariables.begin(); it != this->symbolicVariables.end(); it++)
    stream << smt2lib::declare((*it)->getSymVarName(), (*it)->getSymVarSize());

  return stream.str();
}

/*
 * Converts an expression ID to a symbolic variable.
 * e.g:
 * #43 = (_ bv10 8)
 * convertExprToSymVar(43, 8)
 * #43 = SymVar_4
 */
SymbolicVariable *SymbolicEngine::convertExprToSymVar(uint64 exprId, uint64 symVarSize, std::string symVarComment) {
  SymbolicVariable    *symVar = nullptr;
  SymbolicExpression  *expression = this->getExpressionFromId(exprId);

  if (expression == nullptr)
    return nullptr;

  symVar = this->addSymbolicVariable(SymVar::kind::UNDEF, 0, symVarSize, symVarComment);

  expression->setExpression(smt2lib::variable(symVar->getSymVarName()));

  return symVar;
}

SymbolicVariable *SymbolicEngine::convertMemToSymVar(uint64 memAddr, uint64 symVarSize, std::string symVarComment) {
  SymbolicVariable   *symVar = nullptr;
  SymbolicExpression *expression = nullptr;
  uint64             memSymId = UNSET;

  memSymId = this->getMemSymbolicID(memAddr);
  if (memSymId == UNSET)
    /* TODO #109: Create it if UNSET */
    throw std::runtime_error("SymbolicEngine::convertMemToSymVar() - This memory address is UNSET");

  expression = this->getExpressionFromId(memSymId);

  if (expression == nullptr)
    return nullptr;

  symVar = this->addSymbolicVariable(SymVar::kind::MEM, memAddr, symVarSize, symVarComment);

  expression->setExpression(smt2lib::variable(symVar->getSymVarName()));

  return symVar;
}

SymbolicVariable *SymbolicEngine::convertRegToSymVar(uint64 regId, uint64 symVarSize, std::string symVarComment) {
  SymbolicVariable   *symVar = nullptr;
  SymbolicExpression *expression = nullptr;
  uint64             regSymId = UNSET;

  if (regId >= ID_LAST_ITEM)
    throw std::runtime_error("SymbolicEngine::convertRegToSymVar() - Invalid register ID");

  regSymId = this->getRegSymbolicID(regId);
  if (regSymId == UNSET) {
    symVar = this->addSymbolicVariable(SymVar::kind::REG, regId, symVarSize, symVarComment);

    smt2lib::smtAstAbstractNode *tmp = smt2lib::variable(symVar->getSymVarName());
    if (tmp == nullptr)
      throw std::runtime_error("convertRegToSymVar can't create smtAstAbstractNode (nullptr)");

    SymbolicExpression *se = this->newSymbolicExpression(tmp);
    if (se == nullptr)
      throw std::runtime_error("convertRegToSymVar can't create symbolic expression (nullptr)");

    this->symbolicReg[regId] = se->getID();
  }

  else {
    expression = this->getExpressionFromId(regSymId);
    if (expression == nullptr)
      return nullptr;
    symVar = this->addSymbolicVariable(SymVar::kind::REG, regId, symVarSize, symVarComment);
    expression->setExpression(smt2lib::variable(symVar->getSymVarName()));
  }

  return symVar;
}

/* Add a new symbolic variable */
SymbolicVariable *SymbolicEngine::addSymbolicVariable(SymVar::kind kind, uint64 kindValue, uint64 size, std::string comment) {
  uint64 uniqueID = this->symbolicVariables.size();
  SymbolicVariable *symVar = new SymbolicVariable(kind, kindValue, uniqueID, size, comment);

  if (symVar == nullptr)
    throw std::runtime_error("SymbolicEngine::addSymbolicVariable() - Cannot allocate a new symbolic variable");

  this->symbolicVariables.push_back(symVar);
  return symVar;
}

/* Add and assign a new memory reference */
void SymbolicEngine::addMemoryReference(uint64 mem, uint64 id) {
  this->memoryReference[mem] = id;
}

/* The a path constraint in the PC list */
void SymbolicEngine::addPathConstraint(uint64 exprId) {
  this->pathConstaints.push_back(exprId);
}

/* Returns the path constrains list */
std::list<uint64> SymbolicEngine::getPathConstraints(void) {
  return this->pathConstaints;
}

<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// File contains modifications by: The Gulden developers
// All modifications:
// Copyright (c) 2016-2018 The Gulden developers
// Authored by: Malcolm MacLeod (mmacleod@webmail.co.za)
// Distributed under the GULDEN software license, see the accompanying
// file COPYING

#if defined(HAVE_CONFIG_H)
#include "config/gulden-config.h"
#endif

#include "chainparams.h"
#include "clientversion.h"
#include "compat.h"
#include "fs.h"
#include "rpc/server.h"
#include "init.h"
#include "noui.h"
#include "scheduler.h"
#include "util.h"
#include "httpserver.h"
#include "httprpc.h"
#include "utilstrencodings.h"
#include "net.h"
#include <unity/appmanager.h>

#include <boost/thread.hpp>
#include <boost/interprocess/sync/file_lock.hpp>

#include <stdio.h>

#define _(x) std::string(x)/* Keep the _() around in case gettext or such will be used later to translate non-UI */

/* Introduction text for doxygen: */

/*! \mainpage Developer documentation
 *
 * \section intro_sec Introduction
 *
 * This is the developer documentation of the reference client for an experimental new digital currency called Gulden (https://www.gulden.com),
 * which enables instant payments to anyone, anywhere in the world. Gulden uses peer-to-peer technology to operate
 * with no central authority: managing transactions and issuing money are carried out collectively by the network.
 *
 * The software is a community-driven open source project, released under the MIT license.
 *
 * \section Navigation
 * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code.
 */

int exitStatus = EXIT_SUCCESS;
bool shutDownFinalised = false;

static void handleFinalShutdown()
{
    shutDownFinalised = true;
}

static void WaitForShutdown()
{
    while (!shutDownFinalised)
    {
        MilliSleep(200);
    }
}

static void handlePostInitMain()
{
    //fixme: (UNITY) - This is now duplicated, factor this out into a common helper.
    //Also shouldn't this happen earlier in the init process?
    // Make sure only a single Gulden process is using the data directory.
    fs::path pathLockFile = GetDataDir() / ".lock";
    FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
    if (file) fclose(file);

    try
    {
        static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
        if (!lock.try_lock())
        {
            fprintf(stderr, "Cannot obtain a lock on data directory %s. %s is probably already running.", GetDataDir().string().c_str(), _(PACKAGE_NAME).c_str());
            exitStatus = EXIT_FAILURE;
            GuldenAppManager::gApp->shutdown();
            return;
        }
    }
    catch(const boost::interprocess::interprocess_exception& e)
    {
        fprintf(stderr, "Cannot obtain a lock on data directory %s. %s is probably already running.", GetDataDir().string().c_str(), _(PACKAGE_NAME).c_str());
        exitStatus = EXIT_FAILURE;
        GuldenAppManager::gApp->shutdown();
        return;
    }
}

static void handleAppInitResult(bool bResult)
{
    if (!bResult)
    {
        // InitError will have been called with detailed error, which ends up on console
        exitStatus = EXIT_FAILURE;
        GuldenAppManager::gApp->shutdown();
        return;
    }
    handlePostInitMain();
}

static bool handlePreInitMain()
{
    return true;
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
static void AppInit(int argc, char* argv[])
{
    GuldenAppManager appManager;
    appManager.signalAppInitializeResult.connect(boost::bind(handleAppInitResult, _1));
    appManager.signalAboutToInitMain.connect(&handlePreInitMain);
    appManager.signalAppShutdownFinished.connect(&handleFinalShutdown);

    //fixme: (UNITY) - refactor this some more so that init is taken care of inside the app manager (like with qt app)

    //
    // Parameters
    //
    // If Qt is used, parameters/Gulden.conf are parsed in qt/Gulden.cpp's main()
    ParseParameters(argc, argv);

    // Process help and version before taking care about datadir
    if (IsArgSet("-?") || IsArgSet("-h") ||  IsArgSet("-help") || IsArgSet("-version"))
    {
        std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";

        if (IsArgSet("-version"))
        {
            strUsage += FormatParagraph(LicenseInfo());
        }
        else
        {
            strUsage += "\n" + _("Usage:") + "\n" + "  GuldenD [options]                     " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";
            strUsage += "\n" + HelpMessage(HMM_GULDEND);
        }
        fprintf(stdout, "%s", strUsage.c_str());
        return;
    }

    //NB! Must be set before AppInitMain.
    fNoUI = true;

    try
    {
        if (!fs::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
            exitStatus = EXIT_FAILURE;
            return;
        }
        try
        {
            ReadConfigFile(GetArg("-conf", GULDEN_CONF_FILENAME));
        }
        catch (const std::exception& e)
        {
            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
            exitStatus = EXIT_FAILURE;
            return;
        }
        // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
        try
        {
            SelectParams(ChainNameFromCommandLine());
        }
        catch (const std::exception& e)
        {
            fprintf(stderr, "Error: %s\n", e.what());
            exitStatus = EXIT_FAILURE;
            return;
        }

        // Error out when loose non-argument tokens are encountered on command line
        for (int i = 1; i < argc; i++)
        {
            if (!IsSwitchChar(argv[i][0]))
            {
                fprintf(stderr, "Error: Command line contains unexpected token '%s', see GuldenD -h for a list of options.\n", argv[i]);
                exitStatus = EXIT_FAILURE;
                return;
            }
        }

        // -server defaults to true for GuldenD but not for the GUI so do this here
        SoftSetBoolArg("-server", true);
        // Set this early so that parameter interactions go to console
        InitLogging();
        InitParameterInteraction();

        if (GetBoolArg("-daemon", false))
        {
            fprintf(stdout, "Gulden server starting\n");
            if (!GuldenAppManager::gApp->daemonise())
            {
                LogPrintf("Failed to daemonise\n");
                exitStatus = EXIT_FAILURE;
                return;
            }
        }

        appManager.initialize();
    }
    catch (const std::exception& e)
    {
        PrintExceptionContinue(&e, "AppInit()");
    }
    catch (...)
    {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    //fixme: (UNITY) - It would be much better to wait on a condition variable here.
    // Busy poll for shutdown and allow app to exit when we reach there.
    WaitForShutdown();
}

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

    // Connect GuldenD signal handlers
    noui_connect();

    AppInit(argc, argv);

    return exitStatus;
}
<commit_msg>Fix an issue with GuldenD not checking lock early enough when -daemon flag is passed.<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// File contains modifications by: The Gulden developers
// All modifications:
// Copyright (c) 2016-2018 The Gulden developers
// Authored by: Malcolm MacLeod (mmacleod@webmail.co.za)
// Distributed under the GULDEN software license, see the accompanying
// file COPYING

#if defined(HAVE_CONFIG_H)
#include "config/gulden-config.h"
#endif

#include "chainparams.h"
#include "clientversion.h"
#include "compat.h"
#include "fs.h"
#include "rpc/server.h"
#include "init.h"
#include "noui.h"
#include "scheduler.h"
#include "util.h"
#include "httpserver.h"
#include "httprpc.h"
#include "utilstrencodings.h"
#include "net.h"
#include <unity/appmanager.h>

#include <boost/thread.hpp>
#include <boost/interprocess/sync/file_lock.hpp>

#include <stdio.h>

#define _(x) std::string(x)/* Keep the _() around in case gettext or such will be used later to translate non-UI */

/* Introduction text for doxygen: */

/*! \mainpage Developer documentation
 *
 * \section intro_sec Introduction
 *
 * This is the developer documentation of the reference client for an experimental new digital currency called Gulden (https://www.gulden.com),
 * which enables instant payments to anyone, anywhere in the world. Gulden uses peer-to-peer technology to operate
 * with no central authority: managing transactions and issuing money are carried out collectively by the network.
 *
 * The software is a community-driven open source project, released under the MIT license.
 *
 * \section Navigation
 * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code.
 */

int exitStatus = EXIT_SUCCESS;
bool shutDownFinalised = false;

static void handleFinalShutdown()
{
    shutDownFinalised = true;
}

static void WaitForShutdown()
{
    while (!shutDownFinalised)
    {
        MilliSleep(200);
    }
}

static void handlePostInitMain()
{
}

static void handleAppInitResult(bool bResult)
{
    if (!bResult)
    {
        // InitError will have been called with detailed error, which ends up on console
        exitStatus = EXIT_FAILURE;
        GuldenAppManager::gApp->shutdown();
        return;
    }
    handlePostInitMain();
}

static bool handlePreInitMain()
{
    return true;
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
static void AppInit(int argc, char* argv[])
{
    GuldenAppManager appManager;
    appManager.signalAppInitializeResult.connect(boost::bind(handleAppInitResult, _1));
    appManager.signalAboutToInitMain.connect(&handlePreInitMain);
    appManager.signalAppShutdownFinished.connect(&handleFinalShutdown);

    //fixme: (UNITY) - refactor this some more so that init is taken care of inside the app manager (like with qt app)

    //
    // Parameters
    //
    // If Qt is used, parameters/Gulden.conf are parsed in qt/Gulden.cpp's main()
    ParseParameters(argc, argv);

    // Process help and version before taking care about datadir
    if (IsArgSet("-?") || IsArgSet("-h") ||  IsArgSet("-help") || IsArgSet("-version"))
    {
        std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";

        if (IsArgSet("-version"))
        {
            strUsage += FormatParagraph(LicenseInfo());
        }
        else
        {
            strUsage += "\n" + _("Usage:") + "\n" + "  GuldenD [options]                     " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";
            strUsage += "\n" + HelpMessage(HMM_GULDEND);
        }
        fprintf(stdout, "%s", strUsage.c_str());
        return;
    }

    //NB! Must be set before AppInitMain.
    fNoUI = true;

    try
    {
        if (!fs::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
            exitStatus = EXIT_FAILURE;
            return;
        }
        try
        {
            ReadConfigFile(GetArg("-conf", GULDEN_CONF_FILENAME));
        }
        catch (const std::exception& e)
        {
            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
            exitStatus = EXIT_FAILURE;
            return;
        }
        // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
        try
        {
            SelectParams(ChainNameFromCommandLine());
        }
        catch (const std::exception& e)
        {
            fprintf(stderr, "Error: %s\n", e.what());
            exitStatus = EXIT_FAILURE;
            return;
        }

        // Error out when loose non-argument tokens are encountered on command line
        for (int i = 1; i < argc; i++)
        {
            if (!IsSwitchChar(argv[i][0]))
            {
                fprintf(stderr, "Error: Command line contains unexpected token '%s', see GuldenD -h for a list of options.\n", argv[i]);
                exitStatus = EXIT_FAILURE;
                return;
            }
        }

        // -server defaults to true for GuldenD but not for the GUI so do this here
        SoftSetBoolArg("-server", true);
        // Set this early so that parameter interactions go to console
        InitLogging();
        InitParameterInteraction();

        //fixme: (UNITY) - This is now duplicated, factor this out into a common helper.
        // NB! This has to happen before we deamonise
        // Make sure only a single Gulden process is using the data directory.
        {
            fs::path pathLockFile = GetDataDir() / ".lock";
            FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
            if (file)
                fclose(file);

            try
            {
                static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
                if (!lock.try_lock())
                {
                    fprintf(stderr, "Cannot obtain a lock on data directory %s. %s is probably already running.", GetDataDir().string().c_str(), _(PACKAGE_NAME).c_str());
                    exitStatus = EXIT_FAILURE;
                    GuldenAppManager::gApp->shutdown();
                    return;
                }
            }
            catch(const boost::interprocess::interprocess_exception& e)
            {
                fprintf(stderr, "Cannot obtain a lock on data directory %s. %s is probably already running.", GetDataDir().string().c_str(), _(PACKAGE_NAME).c_str());
                exitStatus = EXIT_FAILURE;
                GuldenAppManager::gApp->shutdown();
                return;
            }
        }

        if (GetBoolArg("-daemon", false))
        {
            fprintf(stdout, "Gulden server starting\n");
            if (!GuldenAppManager::gApp->daemonise())
            {
                LogPrintf("Failed to daemonise\n");
                exitStatus = EXIT_FAILURE;
                return;
            }
        }

        appManager.initialize();
    }
    catch (const std::exception& e)
    {
        PrintExceptionContinue(&e, "AppInit()");
    }
    catch (...)
    {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    //fixme: (UNITY) - It would be much better to wait on a condition variable here.
    // Busy poll for shutdown and allow app to exit when we reach there.
    WaitForShutdown();
}

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

    // Connect GuldenD signal handlers
    noui_connect();

    AppInit(argc, argv);

    return exitStatus;
}
<|endoftext|>


<commit_before>/**
Copyright (c) 2016, Philip Deegan.
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 Philip Deegan 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.
*/
#ifndef _KUL_DB_HPP_
#define _KUL_DB_HPP_

#include <vector>
#include <sstream>

#include "kul/map.hpp"
#include "kul/except.hpp"

#include "kul/db/def.hpp"

namespace kul{
namespace db{
class Exception : public kul::Exception{
    public:
        Exception(const char*f, const uint16_t& l, std::string s) : kul::Exception(f, l, s){}
};
}

class ORM;

class DB{
    protected:
        const std::string n;
        DB(const std::string& n = "") : n(n){}
        friend class kul::ORM;
    public:
        virtual std::string exec_return(const std::string& sql) throw(db::Exception) = 0;
        virtual void exec(const std::string& s) throw(db::Exception) = 0;
};

namespace orm{

template <class T>
class AObject{
    private:
        bool n = 0;
        kul::hash::set::String di;
        kul::hash::map::S2S fs;
        template <class R> friend std::ostream& operator<<(std::ostream&, const AObject<R>&);
    protected:
        const std::string& field(const std::string& s) const{
            if(!fs.count(s))                KEXCEPTION("ORM error, no field: " + s);
            return (*fs.find(s)).second;
        }
        template<class R>
        const R field(const std::string& s) const{
            std::stringstream ss(field(s));
            R r;
            ss >> r;
            return r;
        }
    public:
        const std::string& created() const { return (*fs.find(_KUL_DB_CREATED_COL_)).second; }
        const std::string& updated() const { return (*fs.find(_KUL_DB_UPDATED_COL_)).second; }
        template<class V = std::string>
        AObject<T>& set(const std::string& s, const V& v){
            std::stringstream ss;
            ss << v;
            fs[s] = ss.str();
            di.insert(s);
            return *this;
        }
        const std::string& operator[](const std::string& s) const{
            return field(s);
        }
        template<class R>
        R get(const std::string& s) const{
            return this->template field<R>(s);
        }
        friend class kul::ORM;
};
template <class T> std::ostream& operator<<(std::ostream &s, const kul::orm::AObject<T>& o);
}

class ORM{
    protected:
        DB& db;
        virtual void populate(const std::string& s, std::vector<kul::hash::map::S2S>& vals) = 0;
        template <class T>
        std::string table(){
            return db.n.size() ? (db.n+"."+T::TABLE()) : T::TABLE();
        }
        template <class T>
        void update(orm::AObject<T>& o){
            if(o.di.size() == 0) return;
            std::time_t now = std::time(0);
            std::stringstream ss;
            ss << "UPDATE " << table<T>() << " SET ";
            for(const auto& d : o.di)
                ss << d << "='" << o.fs[d] << "',";
            ss << " updated = " << now;
            ss << " WHERE id = '" << o.fs[_KUL_DB_ID_COL_] << "'";
            db.exec(ss.str());
            o.set(_KUL_DB_UPDATED_COL_, now);
            o.di.clear();
        }
        template <class T>
        void insert(orm::AObject<T>& o){
            std::time_t now = std::time(0);
            std::stringstream ss;
            ss << "INSERT INTO " << table<T>() << "(";
            for(const auto& p : o.fs) ss << p.first << ", ";
            ss << _KUL_DB_CREATED_COL_ << " ," << _KUL_DB_UPDATED_COL_ << ") VALUES(";
            for(const auto& p : o.fs) ss << "'" << p.second << "', ";
            ss << now << ", " << now << ") RETURNING " << _KUL_DB_ID_COL_;
            o.set(_KUL_DB_ID_COL_     , db.exec_return(ss.str()));
            o.set(_KUL_DB_CREATED_COL_, now);
            o.set(_KUL_DB_UPDATED_COL_, now);
            o.n = 0;
            o.di.clear();
        }
    public:
        ORM(DB& db) : db(db){}
        template <class T>
        void commit(orm::AObject<T>& o){
            if(o.n) insert(o);
            else    update(o);
        }
        template <class T>
        void remove(const orm::AObject<T>& o){
            std::stringstream ss;
            ss << "DELETE FROM " << table<T>() << " t WHERE t." << _KUL_DB_ID_COL_ << " = '" << o[_KUL_DB_ID_COL_] << "'";
            db.exec(ss.str());
        }
        template <class T>
        void remove(const std::string& w){
            std::stringstream ss;
            ss << "DELETE FROM " << table<T>() << " t WHERE t." << w;
            db.exec(ss.str());
        }
        template <class T>
        void get(std::vector<T>& ts, const std::string& w = "", const uint16_t& l = 100, const uint16_t& o = 0, const std::string& g = ""){
            std::stringstream ss;
            ss << "SELECT * FROM " << table<T>() << " t ";
            if(!w.empty()) ss << " WHERE " << w;
            ss << " LIMIT " << l << " OFFSET " << o;
            if(!g.empty()) ss << " GROUP BY " << g;
            for(auto& t : ts) t.n = 0;
            std::vector<kul::hash::map::S2S> vals;
            populate(ss.str(), vals);
            for(const auto& v : vals){
                T t;
                for(const auto& m : v) t.fs.insert(m.first, m.second);
                ts.push_back(t);
            }
        }
        template <class T, class V = std::string>
        T by(const std::string& c, const V& v) throw(db::Exception) {
            std::vector<T> ts;
            std::stringstream ss, id;
            id << v;
            ss << "t." << c << " = '" << v << "'";
            get(ts, ss.str(), 2, 0);
            if(ts.size() == 0) KEXCEPT(db::Exception, "Table("+table<T>()+") : "+ _KUL_DB_ID_COL_ +":"+ id.str() +" does not exist");
            if(ts.size() >  1) KEXCEPT(db::Exception, "Table("+table<T>()+") : "+ _KUL_DB_ID_COL_ +":"+ id.str() +" is a duplicate");
            return ts[0];
        }
        template <class T>
        T id(const _KUL_DB_ID_TYPE_& id) throw(db::Exception) {
            return by<T, _KUL_DB_ID_TYPE_>(_KUL_DB_ID_COL_, id);
        }
};

}
template <class T> std::ostream& kul::orm::operator<<(std::ostream &s, const kul::orm::AObject<T>& o){
    std::stringstream ss;
    for(const auto& p : o.fs)
        ss << p.first << " : " << p.second << std::endl;
    return s << ss.str();
}
#endif /* _KUL_DB_HPP_ */
<commit_msg>insert instead of []<commit_after>/**
Copyright (c) 2016, Philip Deegan.
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 Philip Deegan 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.
*/
#ifndef _KUL_DB_HPP_
#define _KUL_DB_HPP_

#include <vector>
#include <sstream>

#include "kul/map.hpp"
#include "kul/except.hpp"

#include "kul/db/def.hpp"

namespace kul{
namespace db{
class Exception : public kul::Exception{
    public:
        Exception(const char*f, const uint16_t& l, std::string s) : kul::Exception(f, l, s){}
};
}

class ORM;

class DB{
    protected:
        const std::string n;
        DB(const std::string& n = "") : n(n){}
        friend class kul::ORM;
    public:
        virtual std::string exec_return(const std::string& sql) throw(db::Exception) = 0;
        virtual void exec(const std::string& s) throw(db::Exception) = 0;
};

namespace orm{

template <class T>
class AObject{
    private:
        bool n = 1;
        kul::hash::set::String di;
        kul::hash::map::S2S fs;
        template <class R> friend std::ostream& operator<<(std::ostream&, const AObject<R>&);
    protected:
        const std::string& field(const std::string& s) const{
            if(!fs.count(s))                KEXCEPTION("ORM error, no field: " + s);
            return (*fs.find(s)).second;
        }
        template<class R>
        const R field(const std::string& s) const{
            std::stringstream ss(field(s));
            R r;
            ss >> r;
            return r;
        }
    public:
        const std::string& created() const { return (*fs.find(_KUL_DB_CREATED_COL_)).second; }
        const std::string& updated() const { return (*fs.find(_KUL_DB_UPDATED_COL_)).second; }
        template<class V = std::string>
        AObject<T>& set(const std::string& s, const V& v){
            std::stringstream ss;
            ss << v;
            fs.insert(s, ss.str());
            di.insert(s);
            return *this;
        }
        const std::string& operator[](const std::string& s) const{
            return field(s);
        }
        template<class R>
        R get(const std::string& s) const{
            return this->template field<R>(s);
        }
        friend class kul::ORM;
};
template <class T> std::ostream& operator<<(std::ostream &s, const kul::orm::AObject<T>& o);
}

class ORM{
    protected:
        DB& db;
        virtual void populate(const std::string& s, std::vector<kul::hash::map::S2S>& vals) = 0;
        template <class T>
        std::string table(){
            return db.n.size() ? (db.n+"."+T::TABLE()) : T::TABLE();
        }
        template <class T>
        void update(orm::AObject<T>& o){
            if(o.di.size() == 0) return;
            std::time_t now = std::time(0);
            std::stringstream ss;
            ss << "UPDATE " << table<T>() << " SET ";
            for(const auto& d : o.di)
                ss << d << "='" << o.fs[d] << "',";
            ss << " updated = " << now;
            ss << " WHERE id = '" << o.fs[_KUL_DB_ID_COL_] << "'";
            db.exec(ss.str());
            o.set(_KUL_DB_UPDATED_COL_, now);
            o.di.clear();
        }
        template <class T>
        void insert(orm::AObject<T>& o){
            std::time_t now = std::time(0);
            std::string nsw = std::to_string(now);
            std::stringstream ss;
            ss << "INSERT INTO " << table<T>() << "(";
            for(const auto& p : o.fs) ss << p.first << ", ";
            ss << _KUL_DB_CREATED_COL_ << " ," << _KUL_DB_UPDATED_COL_ << ") VALUES(";
            for(const auto& p : o.fs) ss << "'" << p.second << "', ";
            ss << now << ", " << now << ") RETURNING " << _KUL_DB_ID_COL_;
            o.fs.insert(_KUL_DB_ID_COL_     , db.exec_return(ss.str()));
            o.fs.insert(_KUL_DB_CREATED_COL_, nsw);
            o.fs.insert(_KUL_DB_UPDATED_COL_, nsw);
            o.n = 0;
            o.di.clear();
        }
    public:
        ORM(DB& db) : db(db){}
        template <class T>
        void commit(orm::AObject<T>& o){
            if(o.n) insert(o);
            else    update(o);
        }
        template <class T>
        void remove(const orm::AObject<T>& o){
            std::stringstream ss;
            ss << "DELETE FROM " << table<T>() << " t WHERE t." << _KUL_DB_ID_COL_ << " = '" << o[_KUL_DB_ID_COL_] << "'";
            db.exec(ss.str());
        }
        template <class T>
        void remove(const std::string& w){
            std::stringstream ss;
            ss << "DELETE FROM " << table<T>() << " t WHERE t." << w;
            db.exec(ss.str());
        }
        template <class T>
        void get(std::vector<T>& ts, const std::string& w = "", const uint16_t& l = 100, const uint16_t& o = 0, const std::string& g = ""){
            std::stringstream ss;
            ss << "SELECT * FROM " << table<T>() << " t ";
            if(!w.empty()) ss << " WHERE " << w;
            ss << " LIMIT " << l << " OFFSET " << o;
            if(!g.empty()) ss << " GROUP BY " << g;
            for(auto& t : ts) t.n = 0;
            std::vector<kul::hash::map::S2S> vals;
            populate(ss.str(), vals);
            for(const auto& v : vals){
                T t;
                for(const auto& m : v) t.fs.insert(m.first, m.second);
                ts.push_back(t);
            }
        }
        template <class T, class V = std::string>
        T by(const std::string& c, const V& v) throw(db::Exception) {
            std::vector<T> ts;
            std::stringstream ss, id;
            id << v;
            ss << "t." << c << " = '" << v << "'";
            get(ts, ss.str(), 2, 0);
            if(ts.size() == 0) KEXCEPT(db::Exception, "Table("+table<T>()+") : "+ _KUL_DB_ID_COL_ +":"+ id.str() +" does not exist");
            if(ts.size() >  1) KEXCEPT(db::Exception, "Table("+table<T>()+") : "+ _KUL_DB_ID_COL_ +":"+ id.str() +" is a duplicate");
            return ts[0];
        }
        template <class T>
        T id(const _KUL_DB_ID_TYPE_& id) throw(db::Exception) {
            return by<T, _KUL_DB_ID_TYPE_>(_KUL_DB_ID_COL_, id);
        }
};

}
template <class T> std::ostream& kul::orm::operator<<(std::ostream &s, const kul::orm::AObject<T>& o){
    std::stringstream ss;
    for(const auto& p : o.fs)
        ss << p.first << " : " << p.second << std::endl;
    return s << ss.str();
}
#endif /* _KUL_DB_HPP_ */
<|endoftext|>