<commit_before>/*
 * flightCommand.cpp
 *
 *  Created on: August 18, 2013
 *      Author: Ryler Hockenbury
 */

#include "flightCommand.h"
#include "../../Libraries/Quad_Defines/globals.h"
#include "../../Libraries/Quad_Reciever/receiver.h"

bool controlMode = 0;
bool auxMode = 0;
bool motorArmed  = false;

/*
 * Distribute stick commands to system components
 */
void processFlightCommands(float stickCommands[], float targetFlightAngle[], PID controller[], ITG3200 *gyro, ADXL345 *accel, HMC5883L *comp) {
	// process zero throttle stick commands
    if(stickCommands[THROTTLE_CHANNEL] < STICK_MINCHECK) {
        processZeroThrottleCommands(stickCommands, gyro, accel, comp);
	}

    //if(!inFlight && motorArmed == true)

    // set some in flight check so we cannot disarm motors while flying

    // get flight angles from sticks
	targetFlightAngle[ROLL_AXIS] = AR6210::mapStickCommandToAngle(stickCommands[ROLL_CHANNEL]);
	targetFlightAngle[PITCH_AXIS] = AR6210::mapStickCommandToAngle(stickCommands[PITCH_CHANNEL]);

	// update controller mode
	controlMode = AR6210::mapStickCommandToBool(stickCommands[MODE_CHANNEL]);
	controller[ROLL_AXIS].setMode(controlMode);
	controller[PITCH_AXIS].setMode(controlMode);

	// update aux channel (currently unused)
	//auxMode = AR6210::mapStickCommandToBool(stickCommands[AUX1_CHANNEL]);
}

/*
 * Process system setup and teardown commands
 */
void processZeroThrottleCommands(float stickCommands[], ITG3200 *gyro, ADXL345 *accel, HMC5883L *comp) {
	// zero sensors - can only be zeroed once
	// Left stick bottom left, right stick bottom right
	if(stickCommands[PITCH_CHANNEL] < STICK_MINCHECK && stickCommands[ROLL_CHANNEL] < STICK_MINCHECK &&
	   stickCommands[YAW_CHANNEL] > STICK_MAXCHECK && !SENSORS_ONLINE) {
		  Serial.println("Info: Zeroing sensors");
          gyro->setOffset();
          accel->setOffset();
          comp->setOffset();
	}

	// arm motors
	// Left stick bottom right
	if(stickCommands[YAW_CHANNEL] < STICK_MINCHECK && SENSORS_ONLINE && motorArmed == false) {
        Serial.println("Warning: Arming motors");
        // arm motors here
        motorArmed = true;
        inFlight = true;
	}

	// disarm motors
	// Left stick bottom left
	if(stickCommands[YAW_CHANNEL] > STICK_MAXCHECK && motorArmed == ON /*&& safety*/) {
        Serial.println("Warning: Disarming motors");
        // disarm motors here
        motorArmed = false;
        inFlight = false;
	}

	//if(/* motionless or rotors not spinning*/    ) {
	//	safety = true;
	//}
}

/*
void AR6210::processInitCommands(ITG3200 *gyro, ADXL345 *accel, HMC5883L *comp) {
    // We will keep polling the stick commands until
    // the operator initializes the sensors and motors.
    //Serial.println(SYSTEM_ONLINE);
    //while(!SYSTEM_ONLINE) {
        //if(!SENSORS_ONLINE) { LED::LEDBlink(RED_LED_PIN, 1, 1000); }
        //if(!MOTORS_ONLINE) { LED::LEDBlink(YELLOW_LED_PIN, 1, 1000); }

        // Initialize the sensors when right stick is in bottom right position, and
        // left stick is in bottom left position
        if(rawChannelValue[THROTTLE_CHANNEL] < STICK_MINCHECK &&
            rawChannelValue[YAW_CHANNEL] < STICK_MINCHECK &&
            rawChannelValue[PITCH_CHANNEL] < STICK_MINCHECK &&
            rawChannelValue[ROLL_CHANNEL] < STICK_MINCHECK) {

            // initialize IMU
            Serial.println("Initializing IMU");
            //gyro->init();   // zero instead of initing
            //accel->init();
            //comp->init();

            //Serial.println(SYSTEM_ONLINE);
            // initialize current / voltage sensor

            //if(SENSORS_ONLINE) { LED::turnLEDon(RED_LED_PIN); }
        }

        // Arm the motors when right stick is in bottom left position, and
        // left stick is in bottom right position
        if(rawChannelValue[THROTTLE_CHANNEL] < STICK_MINCHECK &&
              rawChannelValue[YAW_CHANNEL] > STICK_MAXCHECK &&
              rawChannelValue[PITCH_CHANNEL] < STICK_MINCHECK &&
              rawChannelValue[ROLL_CHANNEL] > STICK_MAXCHECK &&
              SENSORS_ONLINE) {

            // arm motors ->
        	// wait for beeps
        	// set motors to min values

        	if(MOTORS_ONLINE) { LED::turnLEDon(YELLOW_LED_PIN); }

            inFlight = TRUE;
        }

    }

}
*/

<commit_msg>Updated flight command<commit_after>/*
 * flightCommand.cpp
 *
 *  Created on: August 18, 2013
 *      Author: Ryler Hockenbury
 */

#include "flightCommand.h"
#include "../../Libraries/Quad_Defines/globals.h"
#include "../../Libraries/Quad_Reciever/receiver.h"

bool controlMode = 0;
bool auxMode = 0;
bool motorArmed  = false;

/*
 * Distribute stick commands to system components
 */
void processFlightCommands(float stickCommands[], float targetFlightAngle[], PID controller[],
		ITG3200 *gyro, ADXL345 *accel, HMC5883L *comp) {

	// process zero throttle stick commands
    if(stickCommands[THROTTLE_CHANNEL] <= STICK_MINCHECK) {
        processZeroThrottleCommands(stickCommands, gyro, accel, comp);
	}

    if(!inFlight && stickCommands[THROTTLE_CHANNEL] > STICK_MINCHECK && motorArmed) {
    	inFlight = true;
    	LED::turnLEDon(RED_LED_PIN);
    }

    // get flight angles from sticks
	targetFlightAngle[ROLL_AXIS] = AR6210::mapStickCommandToAngle(stickCommands[ROLL_CHANNEL], ROLL_CHANNEL);
	targetFlightAngle[PITCH_AXIS] = AR6210::mapStickCommandToAngle(stickCommands[PITCH_CHANNEL], PITCH_CHANNEL);

	// update controller mode
	controlMode = AR6210::mapStickCommandToBool(stickCommands[MODE_CHANNEL], MODE_CHANNEL);
	controller[ROLL_AXIS].setMode(controlMode);
	controller[PITCH_AXIS].setMode(controlMode);

	// update aux channel (currently unused)
	auxMode = AR6210::mapStickCommandToBool(stickCommands[AUX1_CHANNEL], AUX1_CHANNEL);
}

/*
 * Process system setup and teardown commands
 */
void processZeroThrottleCommands(float stickCommands[], ITG3200 *gyro, ADXL345 *accel, HMC5883L *comp) {

	// zero sensors - can only be zeroed once
	// Left stick bottom left, right stick bottom right
	if(stickCommands[PITCH_CHANNEL] < STICK_MINCHECK && stickCommands[ROLL_CHANNEL] < STICK_MINCHECK &&
	   stickCommands[YAW_CHANNEL] > STICK_MAXCHECK && !SENSORS_ONLINE) {
		  Serial.println("Info: Zeroing sensors");
          gyro->setOffset();
          accel->setOffset();
          comp->setOffset();

          LED::turnLEDon(GREEN_LED_PIN);
	}

	// arm motors
	// Left stick bottom right
	if(stickCommands[YAW_CHANNEL] < STICK_MINCHECK && SENSORS_ONLINE && motorArmed == false) {
        Serial.println("Warning: Arming motors");
        Motors::init();
        Motors::armMotors();
        Motors::pulseMotors(3);
        Motors::commandAllMotors(1100);
        motorArmed = true;

        LED::turnLEDon(YELLOW_LED_PIN);
	}

	// disarm motors
	// Left stick bottom left
	if(stickCommands[YAW_CHANNEL] > STICK_MAXCHECK && motorArmed == true /*&& safety*/) {
        Serial.println("Warning: Disarming motors");
        Motors::disarmMotors();
        motorArmed = false;
        inFlight = false;
	}

	//if(/* motionless or rotors not spinning*/    ) {
	//	safety = true;
	//}
}

<|endoftext|>


<commit_before>#define USE_SEQUENCE

#include <cassert>
#include <iostream>
#include <loki/Factory.h>

#ifdef LOKI_DISABLE_TYPELIST_MACROS
	#define USE_WQUENCE
#endif

#ifdef USE_SEQUENCE
	#include <loki/Sequence.h>
#endif

#include <loki/CachedFactory.h>

#if defined(_WIN32) || defined(__CYGWIN__)
#include <windows.h>
#else
#include <unistd.h>
void Sleep(unsigned int t) { usleep(t);}
#endif

using std::cout;
using std::cerr;
using std::endl;
using std::vector;
using namespace Loki;

class AbstractProduct{
public:
    virtual ~AbstractProduct(){};
};

class Product : public AbstractProduct
{
public:
    Product(){}
    Product( int, int ){}
};

class CostlyProduct : public AbstractProduct
{
public:
    CostlyProduct(){Sleep(100);}
    CostlyProduct( int, int ){Sleep(100);}
};

class DebugProduct : public AbstractProduct
{
public:
    DebugProduct()
    { cout << "Product Ctor()" << endl; }
    DebugProduct( int, int )
    { cout << "Product Ctor(int, int)" << endl; }
    ~DebugProduct()
    { cout << "Product Dtor()" << endl; }
};

CostlyProduct* createCostlyProductNull()
{
    return new CostlyProduct;
}

DebugProduct* createDebugProductNull()
{
    return new DebugProduct;
}

Product* createProductNull()
{
    return new Product;
}

Product* createProductInt(int a, int b)
{
    return new Product(a,b);
}

const int nullID(0);
const int intID(1);

bool dispResult(const char* message, bool result)
{
    cout << "## " << message << (result?" ...OK":" ...Failed !") << endl;
    return result;
}

template<class CCache>
bool unitTestCacheOverhead(int loop){
	std::clock_t start, elapsedNoCache, elapsedCache;
    start = std::clock();
    for(int i=0;i<loop;i++)
        delete createProductNull();
    elapsedNoCache = std::clock() - start;
    cout << " " << elapsedNoCache << " ms" ;
    CCache CC;
    CC.Register(nullID, createProductNull);
    start = std::clock();
    for(int i=0;i<loop;i++){
        AbstractProduct *pProduct(CC.CreateObject(nullID));
        CC.ReleaseObject(pProduct);
    }
    elapsedCache = std::clock() - start;
    cout << " " << elapsedCache << " ms";
    cout << " | average overhead per fetch : " <<((static_cast<double>(elapsedCache-elapsedNoCache)) / CLOCKS_PER_SEC * 1000 / loop)  << " ms" << endl;
    return true;
}

void testCacheOverhead(){
    const int loop(1000000);
	cout << "Starting cache overhead test with " << loop << " loops" << endl;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictRandom > CRandomEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictLRU > CLRUEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictAging > CAgingEvict;
    bool test1 = dispResult("Random policy", unitTestCacheOverhead< CRandomEvict >(loop));(void)test1;
    bool test2 = dispResult("LRU policy", unitTestCacheOverhead< CLRUEvict >(loop));(void)test2;
    bool test3 = dispResult("Aging policy", unitTestCacheOverhead< CAgingEvict >(loop));(void)test3;
}
void unitTestCachePerformance(int loop){
    typedef CachedFactory< AbstractProduct, int > CCache;
	std::clock_t start, elapsedNoCache, elapsedCache;
    start = std::clock();
    for(int i=0;i<loop;i++)
        delete createCostlyProductNull();
    elapsedNoCache = std::clock() - start;
    CCache CC;
    CC.Register(nullID, createCostlyProductNull);
    start = std::clock();
    for(int i=0;i<loop;i++){
        AbstractProduct *pProduct(CC.CreateObject(nullID));
        CC.ReleaseObject(pProduct);
    }
    elapsedCache = std::clock() - start;
    cout << "No cache "<<elapsedNoCache<<" ms | Cache "<<elapsedCache<<" ms | Efficiency " << (double(elapsedNoCache)/elapsedCache)-1 << endl;
}

void testCachePerformance()
{
    for(int i=1;i<=5;i++){
        cout << " || => " << i << " iterations" << endl;
        unitTestCachePerformance(i);
    }
}

template< class Cache >
std::clock_t typicalUse( Cache &CC, unsigned objectKind, unsigned maxObjectCount, unsigned maxIteration)
{
    assert(objectKind>0);
    assert(maxIteration>0);
    assert(maxObjectCount>0);
    vector< AbstractProduct* > fetched;
    fetched.reserve(maxObjectCount);
    srand(0); // initialise the pseudo random operator
    std::clock_t start(0);
    std::clock_t end(0);
    try{
        // Registering objects
        for(size_t i=0;i<objectKind;i++)
            CC.Register(i, createProductNull);
        // Simulating real use
        start = std::clock();
        for(unsigned i=0;i<maxIteration;i++)
        {
            const size_t size(fetched.size());
            if( size == maxObjectCount ){
                CC.ReleaseObject(fetched.back());
                fetched.pop_back();
            } else if(size == 0){
                fetched.push_back(CC.CreateObject(int(objectKind*rand()/(RAND_MAX + 1.0))));
            } else if(rand()<RAND_MAX/2){
                CC.ReleaseObject(fetched.back());
                fetched.pop_back();
            } else {
                fetched.push_back(CC.CreateObject(int(objectKind*rand()/(RAND_MAX + 1.0))));
            }
        }
        end = std::clock();
    }catch(std::exception &e)
    {
        cout << "Error in executing typicalUse " << endl << e.what() << endl;
    }
    // Cleaning in use objects
    for(std::vector<AbstractProduct*>::iterator itr = fetched.begin(); itr!=fetched.end(); itr++)
        CC.ReleaseObject(*itr);
    fetched.clear();
    return end-start;
}

template< class Cache >
void displayTypicalUse(Cache &CC, unsigned objectKind, unsigned maxObjectCount, unsigned maxIteration)
{
    CC.displayCacheType();
    cout << "====> " << typicalUse<Cache>(CC, objectKind, maxObjectCount, maxIteration) << " ms" << endl;
}

void testTypicalUse()
{
    const unsigned objectKind(10);
    const unsigned maxObjectCount(300);
    const unsigned maxIteration(1000000);
    cout << "# " << objectKind << " objects registered in the Factory" << endl;
    cout << "# Cache contains max " << maxObjectCount << " objects" << endl;
    cout << "# Test performs "<< maxIteration <<" iterations" << endl;
    {
        typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AlwaysCreate, EvictRandom, SimpleStatisticPolicy > CRandomEvict;
        CRandomEvict cache;
        displayTypicalUse<CRandomEvict>( cache, objectKind, maxObjectCount, maxIteration);
    }
    {
        typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AlwaysCreate, EvictLRU, SimpleStatisticPolicy > CLRUEvict;
        CLRUEvict cache;
        displayTypicalUse( cache, objectKind, maxObjectCount, maxIteration);
    }
    {
        typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AlwaysCreate, EvictAging, SimpleStatisticPolicy > CAgingEvict;
        CAgingEvict cache;
        displayTypicalUse( cache, objectKind, maxObjectCount, maxIteration);
    }
}

template< class Cache >
bool testEvictionError()
{
    bool testPassed = false;
    Cache CC;
    CC.Register(nullID, createProductNull);
    CC.setMaxCreation(1);
    AbstractProduct *pProduct1 = NULL, *pProduct2 = NULL;
    try{
        pProduct1 = CC.CreateObject(nullID); // should be OK
        pProduct2 = CC.CreateObject(nullID); // should cast an exception
    } catch(std::exception &e){
        if(strcmp(e.what(), EvictionException().what())==0)
            testPassed = true;
    }
    if(pProduct1!=NULL)
        CC.ReleaseObject(pProduct1);
    if(pProduct2!=NULL)
        CC.ReleaseObject(pProduct2);
    return testPassed;
}

bool testAllEvictionError()
{
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictRandom > CRandomEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictLRU > CLRUEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictAging > CAgingEvict;
    bool test1 = dispResult("Random policy", testEvictionError< CRandomEvict >());
    bool test2 = dispResult("LRU policy", testEvictionError< CLRUEvict >());
    bool test3 = dispResult("Aging policy", testEvictionError< CAgingEvict >());
    return test1 && test2 && test3;
}

bool testAmountLimitedCreation()
{
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictRandom, SimpleStatisticPolicy > CCache;
    CCache CC;
    CC.Register(nullID, createDebugProductNull);
    CC.Register(intID, createDebugProductNull);
    // CC.setMaxCreation(0); <== would break on assert, such a cache is useless
    CC.setMaxCreation(1);
    AbstractProduct *pProduct1 = NULL, *pProduct2 = NULL;
    pProduct1 = CC.CreateObject(nullID); // should be OK
    CC.ReleaseObject(pProduct1);
    pProduct2 = CC.CreateObject(intID); // should call the evict method
    if(pProduct1!=NULL)
        CC.ReleaseObject(pProduct1);
    if(pProduct2!=NULL)
        CC.ReleaseObject(pProduct2);
    return (CC.getDestroyed()==1);
}

bool testRateLimitedFetchPolicy(bool waitBetweenFetch)
{
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, RateLimitedCreation > CCache;
    CCache CC;
    CC.Register(nullID, createProductNull);
    CC.setRate(2/*max two fetchs*/,100/*within 100 ms*/);

    bool exceptionOccured = false;
    const int number(5);
    const int sleepTime(60);
    AbstractProduct *products[number];
    for(int i=0;i<number;i++) products[i]=NULL; // initializing
    try{
        for(int i=0;i<number;i++){
            products[i] = CC.CreateObject(nullID);
            if(waitBetweenFetch && (i!=(number-1))){
                Sleep(sleepTime);
            }
        }
    } catch (std::exception &e){
        exceptionOccured = true;
        cout << "Exception occured" << endl << e.what() <<endl;
    }

    // Cleaning things by releasing
    for(int i=0;i<number;i++)
        if(products[i]!=NULL)
            CC.ReleaseObject(products[i]);

    return exceptionOccured;
}

bool fullTestRateLimitedFetchPolicy()
{
    cout << " || => Setting rate limit to 2 fetch within 100 ms." << endl;
    cout << " || => generating 5 objects " << endl;
    bool test1 = dispResult("Fast creation", testRateLimitedFetchPolicy(false)==true);
    cout << " || => generating 5 objects with 60ms between each Fetch" << endl;
    bool test2 = dispResult("Slow creation", testRateLimitedFetchPolicy(true)==false);
    return test1 && test2;
}

bool testRelease(){
    typedef CachedFactory< AbstractProduct, int > CCache;
	CCache CC;
    CC.Register(nullID, createProductNull);
    AbstractProduct *pProduct = NULL;
    CC.ReleaseObject(pProduct);
    cout << "Caching failed" << endl;
    return false;
}

bool testCache()
{
    typedef CachedFactory< AbstractProduct, int, Seq< int, int > > CCache2Parm;

	CCache2Parm CC2;
    CC2.Register(intID, createProductInt);
	AbstractProduct * pProduct = CC2.CreateObject(intID,5,3);
	AbstractProduct * pSave(pProduct);
	CC2.ReleaseObject(pProduct);
	pProduct = CC2.CreateObject(intID,5,3);
	if(pSave != pProduct)
    {
	   cout << "Caching failed" << endl;
	   return false;
    }
    else
    {
        CC2.ReleaseObject(pProduct);
        return true;
    }
}

void dispText(char* text)
{
    cout << endl;
    cout << "##========================================"<< endl;
    cout << "## " << text << endl;
    cout << "##========================================"<< endl;
}

void dispText(char* text, char* comment)
{
    cout << endl;
    cout << "##========================================"<< endl;
    cout << "## " << text << endl;
    cout << "## " << comment << endl;
    cout << "##========================================"<< endl;
}

void separator()
{
    cout << endl << endl;
}

void performanceTests()
{
    dispText(" ==> Performance tests <==");
    separator();
    dispText("Test typical use", "tries different Cache strategies in a typical use configuration");
    testTypicalUse();
    separator();
    dispText("Test efficiency","Comparison between generating costly objects (100ms) and using Cache");
    testCachePerformance();
    separator();
    dispText("Test overhead","Intensive use of Cache to determine the cache time overhead");
    testCacheOverhead();
    separator();
}

void reliabilityTests()
{
    dispText(" ==> Reliability tests <==");
    separator();
    dispText("Test caching", "Trying to Create, Release, Create and see if Cache gives the same object");
    bool cacheResult= dispResult("caching result", testCache());
    separator();
    dispText("Test RateLimitedFetch policy",
    "Trying to quickly create objects, then same scenario with pause in between");
    bool rateLimitedResult= dispResult("RateLimitedFetch policy result",fullTestRateLimitedFetchPolicy());
    separator();
    dispText("Test AmountLimitedCreation policy","Trying to create 2 objects with a limit of 1 creation max, you should see a destroyed object (eviction)");
    bool amountLimitedResult = dispResult("AmountLimitedCreation policy result", testAmountLimitedCreation());
    separator();
    dispText("Test eviction error", "An eviction should occur (Creation Policy), but all object are in use");
    bool evictionTest = dispResult("eviction error test result", testAllEvictionError());
    separator();
    if(cacheResult&&rateLimitedResult&&amountLimitedResult&&evictionTest)
        dispText("All tests passed successfully");
    else
        dispText("One or more test have failed");
}

int main(int , char **)
{
    try{
        performanceTests();
        reliabilityTests();
    }catch(std::exception &e){
        cerr << e.what() << endl;
        cerr << "Error while performing tests" << endl;
    }
}

// TODO provide :
// +Efficiency tests
// +Overhead tests
// +Fiability tests
<commit_msg>remove gcc 4.2 warning<commit_after>#define USE_SEQUENCE

#include <cassert>
#include <iostream>
#include <loki/Factory.h>

#ifdef LOKI_DISABLE_TYPELIST_MACROS
	#define USE_WQUENCE
#endif

#ifdef USE_SEQUENCE
	#include <loki/Sequence.h>
#endif

#include <loki/CachedFactory.h>

#if defined(_WIN32) || defined(__CYGWIN__)
#include <windows.h>
#else
#include <unistd.h>
void Sleep(unsigned int t) { usleep(t);}
#endif

using std::cout;
using std::cerr;
using std::endl;
using std::vector;
using namespace Loki;

class AbstractProduct{
public:
    virtual ~AbstractProduct(){};
};

class Product : public AbstractProduct
{
public:
    Product(){}
    Product( int, int ){}
};

class CostlyProduct : public AbstractProduct
{
public:
    CostlyProduct(){Sleep(100);}
    CostlyProduct( int, int ){Sleep(100);}
};

class DebugProduct : public AbstractProduct
{
public:
    DebugProduct()
    { cout << "Product Ctor()" << endl; }
    DebugProduct( int, int )
    { cout << "Product Ctor(int, int)" << endl; }
    ~DebugProduct()
    { cout << "Product Dtor()" << endl; }
};

CostlyProduct* createCostlyProductNull()
{
    return new CostlyProduct;
}

DebugProduct* createDebugProductNull()
{
    return new DebugProduct;
}

Product* createProductNull()
{
    return new Product;
}

Product* createProductInt(int a, int b)
{
    return new Product(a,b);
}

const int nullID(0);
const int intID(1);

bool dispResult(const char* message, bool result)
{
    cout << "## " << message << (result?" ...OK":" ...Failed !") << endl;
    return result;
}

template<class CCache>
bool unitTestCacheOverhead(int loop){
	std::clock_t start, elapsedNoCache, elapsedCache;
    start = std::clock();
    for(int i=0;i<loop;i++)
        delete createProductNull();
    elapsedNoCache = std::clock() - start;
    cout << " " << elapsedNoCache << " ms" ;
    CCache CC;
    CC.Register(nullID, createProductNull);
    start = std::clock();
    for(int i=0;i<loop;i++){
        AbstractProduct *pProduct(CC.CreateObject(nullID));
        CC.ReleaseObject(pProduct);
    }
    elapsedCache = std::clock() - start;
    cout << " " << elapsedCache << " ms";
    cout << " | average overhead per fetch : " <<((static_cast<double>(elapsedCache-elapsedNoCache)) / CLOCKS_PER_SEC * 1000 / loop)  << " ms" << endl;
    return true;
}

void testCacheOverhead(){
    const int loop(1000000);
	cout << "Starting cache overhead test with " << loop << " loops" << endl;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictRandom > CRandomEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictLRU > CLRUEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictAging > CAgingEvict;
    bool test1 = dispResult("Random policy", unitTestCacheOverhead< CRandomEvict >(loop));(void)test1;
    bool test2 = dispResult("LRU policy", unitTestCacheOverhead< CLRUEvict >(loop));(void)test2;
    bool test3 = dispResult("Aging policy", unitTestCacheOverhead< CAgingEvict >(loop));(void)test3;
}
void unitTestCachePerformance(int loop){
    typedef CachedFactory< AbstractProduct, int > CCache;
	std::clock_t start, elapsedNoCache, elapsedCache;
    start = std::clock();
    for(int i=0;i<loop;i++)
        delete createCostlyProductNull();
    elapsedNoCache = std::clock() - start;
    CCache CC;
    CC.Register(nullID, createCostlyProductNull);
    start = std::clock();
    for(int i=0;i<loop;i++){
        AbstractProduct *pProduct(CC.CreateObject(nullID));
        CC.ReleaseObject(pProduct);
    }
    elapsedCache = std::clock() - start;
    cout << "No cache "<<elapsedNoCache<<" ms | Cache "<<elapsedCache<<" ms | Efficiency " << (double(elapsedNoCache)/elapsedCache)-1 << endl;
}

void testCachePerformance()
{
    for(int i=1;i<=5;i++){
        cout << " || => " << i << " iterations" << endl;
        unitTestCachePerformance(i);
    }
}

template< class Cache >
std::clock_t typicalUse( Cache &CC, unsigned objectKind, unsigned maxObjectCount, unsigned maxIteration)
{
    assert(objectKind>0);
    assert(maxIteration>0);
    assert(maxObjectCount>0);
    vector< AbstractProduct* > fetched;
    fetched.reserve(maxObjectCount);
    srand(0); // initialise the pseudo random operator
    std::clock_t start(0);
    std::clock_t end(0);
    try{
        // Registering objects
        for(size_t i=0;i<objectKind;i++)
            CC.Register(i, createProductNull);
        // Simulating real use
        start = std::clock();
        for(unsigned i=0;i<maxIteration;i++)
        {
            const size_t size(fetched.size());
            if( size == maxObjectCount ){
                CC.ReleaseObject(fetched.back());
                fetched.pop_back();
            } else if(size == 0){
                fetched.push_back(CC.CreateObject(int(objectKind*rand()/(RAND_MAX + 1.0))));
            } else if(rand()<RAND_MAX/2){
                CC.ReleaseObject(fetched.back());
                fetched.pop_back();
            } else {
                fetched.push_back(CC.CreateObject(int(objectKind*rand()/(RAND_MAX + 1.0))));
            }
        }
        end = std::clock();
    }catch(std::exception &e)
    {
        cout << "Error in executing typicalUse " << endl << e.what() << endl;
    }
    // Cleaning in use objects
    for(std::vector<AbstractProduct*>::iterator itr = fetched.begin(); itr!=fetched.end(); itr++)
        CC.ReleaseObject(*itr);
    fetched.clear();
    return end-start;
}

template< class Cache >
void displayTypicalUse(Cache &CC, unsigned objectKind, unsigned maxObjectCount, unsigned maxIteration)
{
    CC.displayCacheType();
    cout << "====> " << typicalUse<Cache>(CC, objectKind, maxObjectCount, maxIteration) << " ms" << endl;
}

void testTypicalUse()
{
    const unsigned objectKind(10);
    const unsigned maxObjectCount(300);
    const unsigned maxIteration(1000000);
    cout << "# " << objectKind << " objects registered in the Factory" << endl;
    cout << "# Cache contains max " << maxObjectCount << " objects" << endl;
    cout << "# Test performs "<< maxIteration <<" iterations" << endl;
    {
        typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AlwaysCreate, EvictRandom, SimpleStatisticPolicy > CRandomEvict;
        CRandomEvict cache;
        displayTypicalUse<CRandomEvict>( cache, objectKind, maxObjectCount, maxIteration);
    }
    {
        typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AlwaysCreate, EvictLRU, SimpleStatisticPolicy > CLRUEvict;
        CLRUEvict cache;
        displayTypicalUse( cache, objectKind, maxObjectCount, maxIteration);
    }
    {
        typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AlwaysCreate, EvictAging, SimpleStatisticPolicy > CAgingEvict;
        CAgingEvict cache;
        displayTypicalUse( cache, objectKind, maxObjectCount, maxIteration);
    }
}

template< class Cache >
bool testEvictionError()
{
    bool testPassed = false;
    Cache CC;
    CC.Register(nullID, createProductNull);
    CC.setMaxCreation(1);
    AbstractProduct *pProduct1 = NULL, *pProduct2 = NULL;
    try{
        pProduct1 = CC.CreateObject(nullID); // should be OK
        pProduct2 = CC.CreateObject(nullID); // should cast an exception
    } catch(std::exception &e){
        if(strcmp(e.what(), EvictionException().what())==0)
            testPassed = true;
    }
    if(pProduct1!=NULL)
        CC.ReleaseObject(pProduct1);
    if(pProduct2!=NULL)
        CC.ReleaseObject(pProduct2);
    return testPassed;
}

bool testAllEvictionError()
{
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictRandom > CRandomEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictLRU > CLRUEvict;
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictAging > CAgingEvict;
    bool test1 = dispResult("Random policy", testEvictionError< CRandomEvict >());
    bool test2 = dispResult("LRU policy", testEvictionError< CLRUEvict >());
    bool test3 = dispResult("Aging policy", testEvictionError< CAgingEvict >());
    return test1 && test2 && test3;
}

bool testAmountLimitedCreation()
{
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, AmountLimitedCreation, EvictRandom, SimpleStatisticPolicy > CCache;
    CCache CC;
    CC.Register(nullID, createDebugProductNull);
    CC.Register(intID, createDebugProductNull);
    // CC.setMaxCreation(0); <== would break on assert, such a cache is useless
    CC.setMaxCreation(1);
    AbstractProduct *pProduct1 = NULL, *pProduct2 = NULL;
    pProduct1 = CC.CreateObject(nullID); // should be OK
    CC.ReleaseObject(pProduct1);
    pProduct2 = CC.CreateObject(intID); // should call the evict method
    if(pProduct1!=NULL)
        CC.ReleaseObject(pProduct1);
    if(pProduct2!=NULL)
        CC.ReleaseObject(pProduct2);
    return (CC.getDestroyed()==1);
}

bool testRateLimitedFetchPolicy(bool waitBetweenFetch)
{
    typedef CachedFactory< AbstractProduct, int, NullType, SimplePointer, RateLimitedCreation > CCache;
    CCache CC;
    CC.Register(nullID, createProductNull);
    CC.setRate(2/*max two fetchs*/,100/*within 100 ms*/);

    bool exceptionOccured = false;
    const int number(5);
    const int sleepTime(60);
    AbstractProduct *products[number];
    for(int i=0;i<number;i++) products[i]=NULL; // initializing
    try{
        for(int i=0;i<number;i++){
            products[i] = CC.CreateObject(nullID);
            if(waitBetweenFetch && (i!=(number-1))){
                Sleep(sleepTime);
            }
        }
    } catch (std::exception &e){
        exceptionOccured = true;
        cout << "Exception occured" << endl << e.what() <<endl;
    }

    // Cleaning things by releasing
    for(int i=0;i<number;i++)
        if(products[i]!=NULL)
            CC.ReleaseObject(products[i]);

    return exceptionOccured;
}

bool fullTestRateLimitedFetchPolicy()
{
    cout << " || => Setting rate limit to 2 fetch within 100 ms." << endl;
    cout << " || => generating 5 objects " << endl;
    bool test1 = dispResult("Fast creation", testRateLimitedFetchPolicy(false)==true);
    cout << " || => generating 5 objects with 60ms between each Fetch" << endl;
    bool test2 = dispResult("Slow creation", testRateLimitedFetchPolicy(true)==false);
    return test1 && test2;
}

bool testRelease(){
    typedef CachedFactory< AbstractProduct, int > CCache;
	CCache CC;
    CC.Register(nullID, createProductNull);
    AbstractProduct *pProduct = NULL;
    CC.ReleaseObject(pProduct);
    cout << "Caching failed" << endl;
    return false;
}

bool testCache()
{
    typedef CachedFactory< AbstractProduct, int, Seq< int, int > > CCache2Parm;

	CCache2Parm CC2;
    CC2.Register(intID, createProductInt);
	AbstractProduct * pProduct = CC2.CreateObject(intID,5,3);
	AbstractProduct * pSave(pProduct);
	CC2.ReleaseObject(pProduct);
	pProduct = CC2.CreateObject(intID,5,3);
	if(pSave != pProduct)
    {
	   cout << "Caching failed" << endl;
	   return false;
    }
    else
    {
        CC2.ReleaseObject(pProduct);
        return true;
    }
}

void dispText(const char* text)
{
    cout << endl;
    cout << "##========================================"<< endl;
    cout << "## " << text << endl;
    cout << "##========================================"<< endl;
}

void dispText(const char* text, const char* comment)
{
    cout << endl;
    cout << "##========================================"<< endl;
    cout << "## " << text << endl;
    cout << "## " << comment << endl;
    cout << "##========================================"<< endl;
}

void separator()
{
    cout << endl << endl;
}

void performanceTests()
{
    dispText(" ==> Performance tests <==");
    separator();
    dispText("Test typical use", "tries different Cache strategies in a typical use configuration");
    testTypicalUse();
    separator();
    dispText("Test efficiency","Comparison between generating costly objects (100ms) and using Cache");
    testCachePerformance();
    separator();
    dispText("Test overhead","Intensive use of Cache to determine the cache time overhead");
    testCacheOverhead();
    separator();
}

void reliabilityTests()
{
    dispText(" ==> Reliability tests <==");
    separator();
    dispText("Test caching", "Trying to Create, Release, Create and see if Cache gives the same object");
    bool cacheResult= dispResult("caching result", testCache());
    separator();
    dispText("Test RateLimitedFetch policy",
    "Trying to quickly create objects, then same scenario with pause in between");
    bool rateLimitedResult= dispResult("RateLimitedFetch policy result",fullTestRateLimitedFetchPolicy());
    separator();
    dispText("Test AmountLimitedCreation policy","Trying to create 2 objects with a limit of 1 creation max, you should see a destroyed object (eviction)");
    bool amountLimitedResult = dispResult("AmountLimitedCreation policy result", testAmountLimitedCreation());
    separator();
    dispText("Test eviction error", "An eviction should occur (Creation Policy), but all object are in use");
    bool evictionTest = dispResult("eviction error test result", testAllEvictionError());
    separator();
    if(cacheResult&&rateLimitedResult&&amountLimitedResult&&evictionTest)
        dispText("All tests passed successfully");
    else
        dispText("One or more test have failed");
}

int main(int , char **)
{
    try{
        performanceTests();
        reliabilityTests();
    }catch(std::exception &e){
        cerr << e.what() << endl;
        cerr << "Error while performing tests" << endl;
    }
}

// TODO provide :
// +Efficiency tests
// +Overhead tests
// +Fiability tests
<|endoftext|>


<commit_before>#include "Graphics/RenderSystem.h"
#include "Graphics/VertexDeclarations.h"
#include "Core/Engine.h"

using namespace Blueshift;
using namespace Blueshift::Graphics;
using namespace Blueshift::Platform;

RenderSystem::RenderSystem()
	: render_thread(&RenderSystem::render_thread_func, this) {
	DisplayInfo::EnumerateDisplays(this);
	primary_display_index = 0;
}

RenderSystem::~RenderSystem() {
	for (auto* window : render_windows) {
		if (window != nullptr) {
			window->Close();
			delete window;
		}
	}
	render_windows.clear();
	if (render_thread.joinable()) {
		render_thread.join();
	}
}

void RenderSystem::AddAvailableDisplayInfo(DisplayInfo&& Display) {
	Display.Index = (uint32_t)displays.size();
	displays.push_back(Display);
}

const DisplayInfo& RenderSystem::GetPrimaryDisplay() const {
	return displays[primary_display_index];
}
const DisplayInfo& RenderSystem::GetDisplay(size_t index) const {
	return displays[index];
}
const std::vector<DisplayInfo>& RenderSystem::GetDisplays() const {
	return displays;
}

void RenderSystem::SetPrimaryDisplay(const DisplayInfo& display) {
	primary_display_index = display.Index;
}
void RenderSystem::SetPrimaryDisplay(size_t index) {
	primary_display_index = index;

	if (primary_display_index >= displays.size()) {
		primary_display_index = 0;
	}
}

void RenderSystem::AddRenderWindow(RenderWindow* Window) {
	render_windows.push_back(Window);
}

RenderWindow& RenderSystem::GetPrimaryRenderWindow() const {
	return *render_windows[0];
}

const std::vector<RenderWindow*>& RenderSystem::GetRenderWindows() const {
	return render_windows;
}

void RenderSystem::render_thread_func() {
	while (render_windows.size() == 0) {
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
	}
	bgfx::init();
	bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH,
		0x303030ff, 1.0f, 0);

	bgfx::setDebug(BGFX_DEBUG_TEXT);

	InitializeVertexDeclarations();

	Core::IApplication* application = Core::Engine::Get().GetParameters()->Application;
	while (application->IsRunning()) {

		for (RenderWindow* window : render_windows) {
			window->PreRender();
			window->PostRender();
		}

		bgfx::frame();
	}

	bgfx::shutdown();
}<commit_msg>Added test render code to RenderSystem<commit_after>#include "Graphics/RenderSystem.h"
#include "Graphics/VertexDeclarations.h"
#include "Core/Engine.h"

#include <fstream>

using namespace Blueshift;
using namespace Blueshift::Graphics;
using namespace Blueshift::Platform;

using namespace Blueshift::Core;
using namespace Blueshift::Core::Math;

static SimpleVertex vertices[24] = {
	//+Y Up
	SimpleVertex(Vector3f(-1.0f, 1.0f, -1.0f),
				 Vector3f(0.0f, 1.0f, 0.0f)),
	SimpleVertex(Vector3f( 1.0f, 1.0f, -1.0f),
				 Vector3f(0.0f, 1.0f, 0.0f)),
	SimpleVertex(Vector3f(-1.0f, 1.0f, 1.0f),
				 Vector3f(0.0f, 1.0f, 0.0f)),
	SimpleVertex(Vector3f(1.0f, 1.0f, 1.0f),
				 Vector3f(0.0f, 1.0f, 0.0f)),

	//-Y Down
	SimpleVertex(Vector3f(1.0f, -1.0f, 1.0f),
				 Vector3f(0.0f, -1.0f, 0.0f)),
	SimpleVertex(Vector3f(-1.0f, -1.0f, 1.0f),
				 Vector3f(0.0f, -1.0f, 0.0f)),
	SimpleVertex(Vector3f(1.0f, -1.0f, -1.0f),
				 Vector3f(0.0f, -1.0f, 0.0f)),
	SimpleVertex(Vector3f(-1.0f, -1.0f, -1.0f),
				 Vector3f(0.0f, -1.0f, 0.0f)),

	//+Z Front
	SimpleVertex(Vector3f(-1.0f, -1.0f, 1.0f),
				 Vector3f(0.0f, 0.0f, 1.0f)),
	SimpleVertex(Vector3f(1.0f, -1.0f, 1.0f),
				 Vector3f(0.0f, 0.0f, 1.0f)),
	SimpleVertex(Vector3f(-1.0f, 1.0f, 1.0f),
				 Vector3f(0.0f, 0.0f, 1.0f)),
	SimpleVertex(Vector3f(1.0f, 1.0f, 1.0f),
				 Vector3f(0.0f, 0.0f, 1.0f)),

	//-Z Back
	SimpleVertex(Vector3f(-1.0f, -1.0f, -1.0f),
				 Vector3f(0.0f, 0.0f, -1.0f)),
	SimpleVertex(Vector3f(1.0f, -1.0f, -1.0f),
				 Vector3f(0.0f, 0.0f, -1.0f)),
	SimpleVertex(Vector3f(-1.0f, 1.0f, -1.0f),
				 Vector3f(0.0f, 0.0f, -1.0f)),
	SimpleVertex(Vector3f(1.0f, 1.0f, -1.0f),
				 Vector3f(0.0f, 0.0f, -1.0f)),

	//+X Right
	SimpleVertex(Vector3f(1.0f, -1.0f, -1.0f),
				 Vector3f(1.0f, 0.0f, 0.0f)),
	SimpleVertex(Vector3f(1.0f, -1.0f, 1.0f),
				 Vector3f(1.0f, 0.0f, 0.0f)),
	SimpleVertex(Vector3f(1.0f, 1.0f, -1.0f),
				 Vector3f(1.0f, 0.0f, 0.0f)),
	SimpleVertex(Vector3f(1.0f, 1.0f, 1.0f),
				 Vector3f(1.0f, 0.0f, 0.0f)),

	//-X Left
	SimpleVertex(Vector3f(-1.0f, -1.0f, -1.0f),
				 Vector3f(-1.0f, 0.0f, 0.0f)),
	SimpleVertex(Vector3f(-1.0f, -1.0f, 1.0f),
				 Vector3f(-1.0f, 0.0f, 0.0f)),
	SimpleVertex(Vector3f(-1.0f, 1.0f, -1.0f),
				 Vector3f(-1.0f, 0.0f, 0.0f)),
	SimpleVertex(Vector3f(-1.0f, 1.0f, 1.0f),
				 Vector3f(-1.0f, 0.0f, 0.0f)),
};
static const uint16_t indices[36] = {
	0, 1, 2,
	2, 1, 3,

	6, 5, 4,
	7, 5, 6,
	//4, 5, 6,
	//6, 5, 7,

	10, 9, 8,
	11, 9, 10,
	//8, 9, 10,
	//10, 9, 11,

	12, 13, 14,
	14, 13, 15,

	16, 17, 18,
	18, 17, 19,

	22, 21, 20,
	23, 21, 22
	//20, 21, 22,
	//22, 21, 23
};

RenderSystem::RenderSystem()
	: render_thread(&RenderSystem::render_thread_func, this) {
	DisplayInfo::EnumerateDisplays(this);
	primary_display_index = 0;
}

RenderSystem::~RenderSystem() {
	for (auto* window : render_windows) {
		if (window != nullptr) {
			window->Close();
			delete window;
		}
	}
	render_windows.clear();
	if (render_thread.joinable()) {
		render_thread.join();
	}
}

void RenderSystem::AddAvailableDisplayInfo(DisplayInfo&& Display) {
	Display.Index = (uint32_t)displays.size();
	displays.push_back(Display);
}

const DisplayInfo& RenderSystem::GetPrimaryDisplay() const {
	return displays[primary_display_index];
}
const DisplayInfo& RenderSystem::GetDisplay(size_t index) const {
	return displays[index];
}
const std::vector<DisplayInfo>& RenderSystem::GetDisplays() const {
	return displays;
}

void RenderSystem::SetPrimaryDisplay(const DisplayInfo& display) {
	primary_display_index = display.Index;
}
void RenderSystem::SetPrimaryDisplay(size_t index) {
	primary_display_index = index;

	if (primary_display_index >= displays.size()) {
		primary_display_index = 0;
	}
}

void RenderSystem::AddRenderWindow(RenderWindow* Window) {
	render_windows.push_back(Window);
}

RenderWindow& RenderSystem::GetPrimaryRenderWindow() const {
	return *render_windows[0];
}

const std::vector<RenderWindow*>& RenderSystem::GetRenderWindows() const {
	return render_windows;
}

void RenderSystem::render_thread_func() {
	while (render_windows.size() == 0) {
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
	}
	bgfx::init();
	bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH,
		0x303030ff, 1.0f, 0);

	//bgfx::setDebug(BGFX_DEBUG_TEXT);

	InitializeVertexDeclarations();

	//debug stuff
	bgfx::VertexBufferHandle evil_vbh;
	bgfx::IndexBufferHandle evil_ibh;
	bgfx::ProgramHandle evil_prog;

	size_t size = sizeof(vertices);
	const bgfx::Memory* mem = bgfx::makeRef(vertices, static_cast<uint32_t>(size));
	evil_vbh = bgfx::createVertexBuffer(mem, SimpleVertex::decl);
	evil_ibh = bgfx::createIndexBuffer(bgfx::makeRef(indices, sizeof(indices)));

	uint8_t* vs_code, * fs_code;
	std::ifstream reader("../Assets/Shaders/debug_vs.win.bin", std::ios::binary);
	reader.seekg(0, std::ios::end);
	size_t vs_size = reader.tellg();
	reader.seekg(0, std::ios::beg);
	vs_code = new uint8_t[vs_size];
	reader.read((char*)vs_code, vs_size);
	reader.close();
	reader.open("../Assets/Shaders/debug_fs.win.bin", std::ios::binary);
	reader.seekg(0, std::ios::end);
	size_t fs_size = reader.tellg();
	reader.seekg(0, std::ios::beg);
	fs_code = new uint8_t[fs_size];
	reader.read((char*)fs_code, fs_size);
	reader.close();

	bgfx::ShaderHandle vs = bgfx::createShader(bgfx::makeRef(vs_code, vs_size));
	bgfx::ShaderHandle fs = bgfx::createShader(bgfx::makeRef(fs_code, fs_size));

	evil_prog = bgfx::createProgram(vs, fs, true);

	//delete[] vs_code;
	//delete[] fs_code;

	float theta = 0.0f;

	Core::IApplication* application = Core::Engine::Get().GetParameters()->Application;
	while (application->IsRunning()) {

		for (RenderWindow* window : render_windows) {
			current_view_id = window->GetViewID();
			window->PreRender();

			theta += 0.01f;
			Math::Matrix4f model = Math::RotationMatrix<4, float>(Math::Vector3f(1.0f, 1.0f, 0.0f), theta) * Math::TranslationMatrix<float>(Vector3f(0.0f, 0.0f, 5.0f));
			Math::Matrix4f view = Inverse(Math::TranslationMatrix(Math::Vector3f(0.0f, 0.0f, -10.0f)));
			Math::Matrix4f proj = Math::Downgrade(Scene::CameraComponent::CreatePerspectiveTransform(window->GetAspectRatio(), 70.0, 0.1, 100.0));

			bgfx::setTransform(model.data);
			bgfx::setViewTransform(0, view.data, proj.data);
			bgfx::setVertexBuffer(evil_vbh);
			bgfx::setIndexBuffer(evil_ibh);

			bgfx::submit(0, evil_prog);

			window->PostRender();
		}

		bgfx::frame();
	}

	bgfx::shutdown();
}<|endoftext|>


<commit_before>#include "RenderWindow.h"
#include "Core/Engine.h"
#include "bgfx/bgfx.h"

using namespace Blueshift;
using namespace Blueshift::Core;
using namespace Blueshift::Graphics;

RenderWindow::RenderWindow(uint32_t Width, uint32_t Height)
	: Window(Width, Height, true), view_width(Width), view_height(Height)
{
	view_id = static_cast<uint8_t>(Engine::Get().GetRenderSystem().GetRenderWindows().size());
	if (Engine::Get().GetRenderSystem().GetRenderWindows().size() == 0) {
		is_primary = true;
		this->setup_platform();
	}
}

RenderWindow::~RenderWindow() {

}

void RenderWindow::resize_viewport(uint32_t width, uint32_t height) {
	view_width = width;
	view_height = height;
	dirty_viewport = true;
}

void RenderWindow::PreRender() {
	if (dirty_viewport) {
		dirty_viewport = false;
		if (is_primary) {
			bgfx::setViewFrameBuffer(view_id, BGFX_INVALID_HANDLE);
			bgfx::reset(view_width, view_height,
				BGFX_RESET_VSYNC |
				BGFX_RESET_MSAA_X4 |
				BGFX_RESET_SRGB_BACKBUFFER
				);

		} else {
			//update framebuffer
		}
	}
	bgfx::setViewRect(view_id, 0, 0, view_width, view_height);
	bgfx::touch(view_id);
	bgfx::setState(
		//BGFX_STATE_MSAA |
		BGFX_STATE_ALPHA_WRITE |
		BGFX_STATE_RGB_WRITE |
		BGFX_STATE_CULL_CW |
		BGFX_STATE_DEPTH_WRITE |
		BGFX_STATE_DEPTH_TEST_LESS);
}

void RenderWindow::PostRender() {

}

 <commit_msg>Changed some flags on RenderWindow<commit_after>#include "RenderWindow.h"
#include "Core/Engine.h"
#include "bgfx/bgfx.h"

using namespace Blueshift;
using namespace Blueshift::Core;
using namespace Blueshift::Graphics;

RenderWindow::RenderWindow(uint32_t Width, uint32_t Height)
	: Window(Width, Height, true), view_width(Width), view_height(Height)
{
	view_id = static_cast<uint8_t>(Engine::Get().GetRenderSystem().GetRenderWindows().size());
	if (Engine::Get().GetRenderSystem().GetRenderWindows().size() == 0) {
		is_primary = true;
		this->setup_platform();
	}
}

RenderWindow::~RenderWindow() {

}

void RenderWindow::resize_viewport(uint32_t width, uint32_t height) {
	view_width = width;
	view_height = height;
	dirty_viewport = true;
}

void RenderWindow::PreRender() {
	if (dirty_viewport) {
		dirty_viewport = false;
		if (is_primary) {
			bgfx::setViewFrameBuffer(view_id, BGFX_INVALID_HANDLE);
			bgfx::reset(view_width, view_height,
				BGFX_RESET_VSYNC |
				BGFX_RESET_MSAA_X8 |
				BGFX_RESET_SRGB_BACKBUFFER
				);

		} else {
			//update framebuffer
		}
	}
	bgfx::setViewRect(view_id, 0, 0, view_width, view_height);
	bgfx::touch(view_id);
	bgfx::setState(
		BGFX_STATE_MSAA |
		BGFX_STATE_ALPHA_WRITE |
		BGFX_STATE_RGB_WRITE |
		BGFX_STATE_CULL_CCW |
		BGFX_STATE_DEPTH_WRITE |
		BGFX_STATE_DEPTH_TEST_LESS);
}

void RenderWindow::PostRender() {

}

 <|endoftext|>


<commit_before><commit_msg>Annotate benign race for trace_event category enabled flag.<commit_after><|endoftext|>


<commit_before>#include <array>
#include <future>
#include <iostream>
#include <gtest/gtest.h>
#include "net/acceptor.hpp"
#include "net/connector.hpp"

using namespace std;
using namespace net;

static mutex m;

TEST(AcceptorAndConnectorTest,runTwoThreads)
{
    int s{0};
    array<int,1000> test;
    for(auto& i : test)
        i = ++s;

    auto f1 = async(
        launch::async,
        [&test]()
        {
            acceptor ator{"localhost", "54321"};
            ostream os{ator.accept()};
            for(auto i : test)
            {
                os << i << endl;
                unique_lock<mutex> l{m};
                clog << "ator: " << i << endl;
            }
        }
    );

    auto f2 = async(
        launch::async,
        [&test]()
        {
            connector ctor{"localhost", "54321"};
            istream is{ctor.connect()};
            clog << "Listening..." << endl;
            for(auto i : test)
            {
                int ii;
                is >> ii;
                ASSERT_EQ(i,ii);
                unique_lock<mutex> l{m};
                clog << "ctor: " << ii << endl;
            }
        }
    );

    f1.get();
    f2.get();
}
<commit_msg>Update test_acceptor_and_connector.cpp<commit_after>#include <array>
#include <future>
#include <iostream>
#include <gtest/gtest.h>
#include "net/acceptor.hpp"
#include "net/connector.hpp"

using namespace std;
using namespace net;

static mutex m;

TEST(AcceptorAndConnectorTest,runTwoThreads)
{
    int s{0};
    array<int,1000> test;
    for(auto& i : test)
        i = ++s;

    auto f1 = async(
        launch::async,
        [&test]()
        {
            acceptor ator{"localhost", "54321"};
            ostream os{ator.accept()};
            for(auto i : test)
            {
                os << i << endl;
                unique_lock<mutex> l{m};
                clog << "Acceptor: " << i << endl;
            }
        }
    );

    auto f2 = async(
        launch::async,
        [&test]()
        {
            connector ctor{"localhost", "54321"};
            istream is{ctor.connect()};
            clog << "Listening..." << endl;
            for(auto i : test)
            {
                int ii;
                is >> ii;
                ASSERT_EQ(i,ii);
                unique_lock<mutex> l{m};
                clog << "Connector: " << ii << endl;
            }
        }
    );

    f1.get();
    f2.get();
}
<|endoftext|>


<commit_before>#include <climits>

// PUBLIC API
#include <disir/disir.h>

#include "test_helper.h"

class ConfigKeyvalTest : public testing::DisirTestTestPlugin
{
protected:
    void SetUp()
    {
        DisirTestTestPlugin::SetUp ();

        mold = NULL;
        context_mold = NULL;
        context_config = NULL;
        context_keyval = NULL;

        status = disir_mold_input (instance, "test", "basic_keyval", &mold);
        ASSERT_STATUS (DISIR_STATUS_OK, status);

        status = dc_config_begin (mold, &context_config);
        ASSERT_STATUS (DISIR_STATUS_OK, status);
        ASSERT_TRUE (context_config != NULL);

        status = dc_begin (context_config, DISIR_CONTEXT_KEYVAL, &context_keyval);
        ASSERT_STATUS (DISIR_STATUS_OK, status);
        ASSERT_TRUE (context_keyval != NULL);
    }

    void TearDown()
    {
        if (mold)
        {
            status = disir_mold_finished (&mold);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }
        if (context_mold)
        {
            status = dc_putcontext (&context_mold);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }
        if (context_config)
        {
            status = dc_destroy (&context_config);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }
        if (context_keyval)
        {
            status = dc_destroy (&context_keyval);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }

        DisirTestTestPlugin::TearDown ();
    }

public:
    enum disir_status status;
    struct disir_mold *mold;
    struct disir_context *context_mold;
    struct disir_context *context_config;
    struct disir_context *context_keyval;
};

class ConfigKeyvalIntegerTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_integer", strlen ("key_integer"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

class ConfigKeyvalStringTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_string", strlen ("key_string"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

class ConfigKeyvalFloatTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_float", strlen ("key_float"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

class ConfigKeyvalBooleanTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_boolean", strlen ("key_boolean"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

TEST_F (ConfigKeyvalTest, set_name_doesnt_exist_shall_fail)
{
    const char name[] = "this_name_doesnt_exist";

    status = dc_set_name (context_keyval, name, strlen (name));
    // XXX: Should be a better return status
    ASSERT_STATUS (DISIR_STATUS_INVALID_ARGUMENT, status);

    // XXX Assert error message
}

TEST_F (ConfigKeyvalTest, set_name_that_exists_shall_succeed)
{
    status = dc_set_name (context_keyval, "key_string", strlen ("key_string"));
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalTest, set_integer_value_before_name_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 72);
    ASSERT_STATUS (DISIR_STATUS_MOLD_MISSING, status);
    ASSERT_STREQ ("cannot set value on context without a MOLD",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalTest, set_string_value_before_name_shall_fail)
{
    status = dc_set_value_string (context_keyval, "mys", strlen ("mys"));
    ASSERT_STATUS (DISIR_STATUS_MOLD_MISSING, status);
    ASSERT_STREQ ("cannot set value on context without a MOLD",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalTest, set_float_value_before_name_shall_fail)
{
    status = dc_set_value_float (context_keyval, 3.12);
    ASSERT_STATUS (DISIR_STATUS_MOLD_MISSING, status);
    ASSERT_STREQ ("cannot set value on context without a MOLD",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalIntegerTest, set_value_integer_shall_succeed)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalIntegerTest, get_value_integer_shall_succeed)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);

    ASSERT_EQ (0, value);
}

TEST_F (ConfigKeyvalIntegerTest, set_value_string_shall_fail)
{
    status = dc_set_value_string (context_keyval, "mys", strlen ("mys"));
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set string value on context whose value type is INTEGER",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalIntegerTest, get_value_string_shall_fail)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get string value on context whose value type is INTEGER",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalStringTest, set_value_string_shall_succeed)
{
    status = dc_set_value_string (context_keyval, "hooray", strlen ("hooray"));
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalStringTest, get_value_string_shall_succeed)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalStringTest, set_value_integer_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set integer value on context whose value type is STRING",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalStringTest, get_value_integer_shall_fail)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
}

TEST_F (ConfigKeyvalFloatTest, set_value_float_shall_succeed)
{
    status = dc_set_value_float (context_keyval, 42.123);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalFloatTest, get_value_float_shall_succeed)
{
    double value = LONG_MAX;

    status = dc_get_value_float (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);

    ASSERT_EQ (0.0, value);
}

TEST_F (ConfigKeyvalFloatTest, set_value_string_shall_fail)
{
    status = dc_set_value_string (context_keyval, "hooray", strlen ("hooray"));
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set string value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalFloatTest, get_value_string_shall_fail)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get string value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalFloatTest, set_value_integer_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set integer value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalFloatTest, get_value_integer_shall_fail)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get integer value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

// XX
TEST_F (ConfigKeyvalBooleanTest, set_value_boolean_shall_succeed)
{
    status = dc_set_value_boolean (context_keyval, 1);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalFloatTest, get_value_boolean_shall_succeed)
{
    uint8_t value = 8;

    status = dc_get_value_boolean (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);

    ASSERT_EQ (0, value);
}

TEST_F (ConfigKeyvalBooleanTest, set_value_string_shall_fail)
{
    status = dc_set_value_string (context_keyval, "hooray", strlen ("hooray"));
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set string value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, get_value_string_shall_fail)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get string value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, set_value_integer_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set integer value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, get_value_integer_shall_fail)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get integer value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, set_value_float_shall_fail)
{
    status = dc_set_value_float (context_keyval, 42.123);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set float value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, get_value_float_shall_fail)
{
    double value = LONG_MAX;

    status = dc_get_value_float (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
    ASSERT_STREQ ("cannot get float value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}
<commit_msg>test: update faulty boolean tests<commit_after>#include <climits>

// PUBLIC API
#include <disir/disir.h>

#include "test_helper.h"

class ConfigKeyvalTest : public testing::DisirTestTestPlugin
{
protected:
    void SetUp()
    {
        DisirTestTestPlugin::SetUp ();

        mold = NULL;
        context_mold = NULL;
        context_config = NULL;
        context_keyval = NULL;

        status = disir_mold_input (instance, "test", "basic_keyval", &mold);
        ASSERT_STATUS (DISIR_STATUS_OK, status);

        status = dc_config_begin (mold, &context_config);
        ASSERT_STATUS (DISIR_STATUS_OK, status);
        ASSERT_TRUE (context_config != NULL);

        status = dc_begin (context_config, DISIR_CONTEXT_KEYVAL, &context_keyval);
        ASSERT_STATUS (DISIR_STATUS_OK, status);
        ASSERT_TRUE (context_keyval != NULL);
    }

    void TearDown()
    {
        if (mold)
        {
            status = disir_mold_finished (&mold);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }
        if (context_mold)
        {
            status = dc_putcontext (&context_mold);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }
        if (context_config)
        {
            status = dc_destroy (&context_config);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }
        if (context_keyval)
        {
            status = dc_destroy (&context_keyval);
            EXPECT_STATUS (DISIR_STATUS_OK, status);
        }

        DisirTestTestPlugin::TearDown ();
    }

public:
    enum disir_status status;
    struct disir_mold *mold;
    struct disir_context *context_mold;
    struct disir_context *context_config;
    struct disir_context *context_keyval;
};

class ConfigKeyvalIntegerTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_integer", strlen ("key_integer"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

class ConfigKeyvalStringTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_string", strlen ("key_string"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

class ConfigKeyvalFloatTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_float", strlen ("key_float"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

class ConfigKeyvalBooleanTest : public ConfigKeyvalTest
{
protected:
    void SetUp()
    {
        ConfigKeyvalTest::SetUp ();

        status = dc_set_name (context_keyval, "key_boolean", strlen ("key_boolean"));
        ASSERT_STATUS (DISIR_STATUS_OK, status);
    }
};

TEST_F (ConfigKeyvalTest, set_name_doesnt_exist_shall_fail)
{
    const char name[] = "this_name_doesnt_exist";

    status = dc_set_name (context_keyval, name, strlen (name));
    // XXX: Should be a better return status
    ASSERT_STATUS (DISIR_STATUS_INVALID_ARGUMENT, status);

    // XXX Assert error message
}

TEST_F (ConfigKeyvalTest, set_name_that_exists_shall_succeed)
{
    status = dc_set_name (context_keyval, "key_string", strlen ("key_string"));
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalTest, set_integer_value_before_name_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 72);
    ASSERT_STATUS (DISIR_STATUS_MOLD_MISSING, status);
    ASSERT_STREQ ("cannot set value on context without a MOLD",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalTest, set_string_value_before_name_shall_fail)
{
    status = dc_set_value_string (context_keyval, "mys", strlen ("mys"));
    ASSERT_STATUS (DISIR_STATUS_MOLD_MISSING, status);
    ASSERT_STREQ ("cannot set value on context without a MOLD",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalTest, set_float_value_before_name_shall_fail)
{
    status = dc_set_value_float (context_keyval, 3.12);
    ASSERT_STATUS (DISIR_STATUS_MOLD_MISSING, status);
    ASSERT_STREQ ("cannot set value on context without a MOLD",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalIntegerTest, set_value_integer_shall_succeed)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalIntegerTest, get_value_integer_shall_succeed)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);

    ASSERT_EQ (0, value);
}

TEST_F (ConfigKeyvalIntegerTest, set_value_string_shall_fail)
{
    status = dc_set_value_string (context_keyval, "mys", strlen ("mys"));
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set string value on context whose value type is INTEGER",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalIntegerTest, get_value_string_shall_fail)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get string value on context whose value type is INTEGER",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalStringTest, set_value_string_shall_succeed)
{
    status = dc_set_value_string (context_keyval, "hooray", strlen ("hooray"));
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalStringTest, get_value_string_shall_succeed)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalStringTest, set_value_integer_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set integer value on context whose value type is STRING",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalStringTest, get_value_integer_shall_fail)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
}

TEST_F (ConfigKeyvalFloatTest, set_value_float_shall_succeed)
{
    status = dc_set_value_float (context_keyval, 42.123);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalFloatTest, get_value_float_shall_succeed)
{
    double value = LONG_MAX;

    status = dc_get_value_float (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);

    ASSERT_EQ (0.0, value);
}

TEST_F (ConfigKeyvalFloatTest, set_value_string_shall_fail)
{
    status = dc_set_value_string (context_keyval, "hooray", strlen ("hooray"));
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set string value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalFloatTest, get_value_string_shall_fail)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get string value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalFloatTest, set_value_integer_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set integer value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalFloatTest, get_value_integer_shall_fail)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get integer value on context whose value type is FLOAT",
                  dc_context_error (context_keyval));
}

// XX
TEST_F (ConfigKeyvalBooleanTest, set_value_boolean_shall_succeed)
{
    status = dc_set_value_boolean (context_keyval, 1);
    ASSERT_STATUS (DISIR_STATUS_OK, status);
}

TEST_F (ConfigKeyvalBooleanTest, get_value_boolean_shall_succeed)
{
    uint8_t value = 8;

    status = dc_get_value_boolean (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_OK, status);

    ASSERT_EQ (0, value);
}

TEST_F (ConfigKeyvalBooleanTest, set_value_string_shall_fail)
{
    status = dc_set_value_string (context_keyval, "hooray", strlen ("hooray"));
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set string value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, get_value_string_shall_fail)
{
    const char *output;
    int32_t size;

    status = dc_get_value_string (context_keyval, &output, &size);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get string value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, set_value_integer_shall_fail)
{
    status = dc_set_value_integer (context_keyval, 74);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set integer value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, get_value_integer_shall_fail)
{
    int64_t value = LLONG_MAX;
    status = dc_get_value_integer (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get integer value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, set_value_float_shall_fail)
{
    status = dc_set_value_float (context_keyval, 42.123);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot set float value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}

TEST_F (ConfigKeyvalBooleanTest, get_value_float_shall_fail)
{
    double value = LONG_MAX;

    status = dc_get_value_float (context_keyval, &value);
    ASSERT_STATUS (DISIR_STATUS_WRONG_VALUE_TYPE, status);
    ASSERT_STREQ ("cannot get float value on context whose value type is BOOLEAN",
                  dc_context_error (context_keyval));
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ZipEntry.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-26 14:13:41 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_ENTRY_HXX_
#define _ZIP_ENTRY_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

struct ZipEntry
{
    sal_Int16 nVersion;
    sal_Int16 nFlag;
    sal_Int16 nMethod;
    sal_Int32 nTime;
    sal_Int32 nCrc;
    sal_Int32 nCompressedSize;
    sal_Int32 nSize;
    sal_Int32 nOffset;
    sal_Int16 nNameLen;
    sal_Int16 nExtraLen;
    ::rtl::OUString sName;
};
#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.182); FILE MERGED 2005/09/05 18:49:01 rt 1.3.182.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ZipEntry.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 15:58:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _ZIP_ENTRY_HXX_
#define _ZIP_ENTRY_HXX_

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

struct ZipEntry
{
    sal_Int16 nVersion;
    sal_Int16 nFlag;
    sal_Int16 nMethod;
    sal_Int32 nTime;
    sal_Int32 nCrc;
    sal_Int32 nCompressedSize;
    sal_Int32 nSize;
    sal_Int32 nOffset;
    sal_Int16 nNameLen;
    sal_Int16 nExtraLen;
    ::rtl::OUString sName;
};
#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 "zorbatypes/integer.h"
#include "zorbatypes/decimal.h"
#include "zorbatypes/floatimpl.h"
#include "zorbatypes/numconversions.h"
#include <stdlib.h>

#ifndef ZORBA_NO_BIGNUMBERS
#define IS_ZERO(mapm_obj)                 (mapm_obj.sign() == 0)
#define IS_POSITIVE(mapm_obj)             (mapm_obj.sign() > 0)
#define IS_POSITIVE_OR_ZERO(mapm_obj)     (mapm_obj.sign() >= 0)
#define IS_NEGATIVE(mapm_obj)             (mapm_obj.sign() < 0)
#else
#define IS_ZERO(mapm_obj)                 (mapm_obj == 0)
#define IS_POSITIVE(mapm_obj)             (mapm_obj > 0)
#define IS_POSITIVE_OR_ZERO(mapm_obj)     (mapm_obj >= 0)
#define IS_NEGATIVE(mapm_obj)             (mapm_obj < 0)
#endif

namespace zorba {
SERIALIZABLE_CLASS_VERSIONS(Integer)
END_SERIALIZABLE_CLASS_VERSIONS(Integer)

Integer& Integer::zero() {
  static Integer lValue(IMAPM(0));
  return lValue;
}

#ifdef ZORBA_NUMERIC_OPTIMIZATION
HashCharPtrObjPtrLimited<Integer>   Integer::parsed_integers;
#endif

bool Integer::parseString(const char* aCharStar, Integer& aInteger)
{
#ifdef ZORBA_NUMERIC_OPTIMIZATION
  Integer *hashed_integer;
  if(parsed_integers.get(aCharStar, hashed_integer))
  {
    //found in hash
    aInteger.theInteger = hashed_integer->theInteger;
    return true;
  }
#endif
  // correctness check
  const char* lCur = aCharStar;
  bool lGotSign = false;
  bool lStop = false;
  bool lGotDigit = false;
  bool new_aCharStar = false;

  char ch = *lCur;

  // Skip leading space
  while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
  {
    ++lCur;
    aCharStar++;
    ch = *lCur;
  }

  while (*lCur != '\0' && !lStop)
  {
    ch = *lCur;

    switch(ch)
    {
    case '+':
      if (lGotSign || lGotDigit) {
        lStop = true;
      } else {
        lGotSign = true;
      }
      break;

    case '-':
      if(lGotSign || lGotDigit) {
        lStop = true;
      } else {
        lGotSign = true;
      }
      break;

    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      lGotDigit = true;
      break;

    case ' ':
    case '\t':
    case '\n':
    case '\r':
    {
      const char* firstSpace = lCur;

      // Skip trailing space
      while(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
      {
        ++lCur;
        ch = *lCur;
      }

      if (*lCur != 0)
      {
        lStop = true;
      }
      else
      {
        int len = firstSpace - aCharStar + 1;
        char* copy = new char[len];
        strncpy(copy, aCharStar, len);
        copy[len-1] = 0;
        aCharStar = copy;
        new_aCharStar = true;
        lCur--;
      }

      break;
    }

    default:
      lStop = true;
      break;
    }

    lCur++;
  }

  if (lStop || !lGotDigit)
  {
    if(new_aCharStar)
      delete[] aCharStar;
    return false;
  }
  else
  {
#ifndef ZORBA_NO_BIGNUMBERS
    aInteger.theInteger = aCharStar;
#else
    aInteger.theInteger = atoi(aCharStar);
#endif

#ifdef ZORBA_NUMERIC_OPTIMIZATION
    hashed_integer = new Integer(aInteger);
    const char  *dup_str = _strdup(aCharStar);
    parsed_integers.insert(dup_str, hashed_integer);
#endif
    if(new_aCharStar)
      delete[] aCharStar;
    return true;
  }
}

bool Integer::parseStringUnsigned(const char* aStarChar, Integer& aUInteger) {
  // correctness check
  const char* lCur = aStarChar;
  bool lStop = false;
  while (*lCur != '\0' && !lStop) {
    char lTmp = *lCur++;
    switch(lTmp) {
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        break;
      default:
        lStop = true;
        break;
    }
  }
  if (lStop) {
    return false;
  } else {
#ifndef ZORBA_NO_BIGNUMBERS
    aUInteger.theInteger = aStarChar;
    return true;
#else
    aUInteger.theInteger = (IMAPM)atoi(aStarChar);
    return true;
#endif
  }
}

bool Integer::parseDouble(const Double& aDouble, Integer& aInteger) {
  if (aDouble.isFinite()) {
    aInteger.theInteger = floatingToInteger(aDouble.theFloating);
    return true;
  }
  else {
    return false;
  }
}

bool Integer::parseFloat(const Float& aFloat, Integer& aInteger) {
  if (aFloat.isFinite()) {
    aInteger.theInteger = floatingToInteger(aFloat.theFloating);
    return true;
  }
  else {
    return false;
  }
}

Integer Integer::parseDecimal(const Decimal& aDecimal) {
  Integer lInteger(floatingToInteger(aDecimal.theDecimal));
  return lInteger;
}

Integer Integer::parseLongLong(long long aLong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::longLongToStr(aLong);
  MAPM lMAPM = lStrRep.c_str();
  return Integer(lMAPM);
#else
  return Integer((IMAPM)aLong);
#endif
}

Integer Integer::parseULongLong(unsigned long long aULong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::ulongLongToStr(aULong);
  MAPM lMAPM = lStrRep.c_str();
  return Integer(lMAPM);
#else
  return Integer((IMAPM)aULong);
#endif
}

Integer Integer::parseInt(int32_t aInt) {
  MAPM lMAPM = aInt;
  Integer lInteger(lMAPM);
  return lInteger;
}

Integer Integer::parseUInt(uint32_t aUInt) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::uintToStr(aUInt);
  MAPM lMAPM = lStrRep.c_str();
  return Integer(lMAPM);
#else
  return Integer((IMAPM)aUInt);
#endif
}

Integer Integer::parseLong(long aLong) {
  MAPM lNumber = aLong;
  return Integer(lNumber);
}

Integer Integer::parseULong(unsigned long aULong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::ulongLongToStr(aULong);
  MAPM lNumber = lStrRep.c_str();
  return Integer(lNumber);
#else
  return Integer((IMAPM)aULong);
#endif
}
Integer Integer::parseSizeT(size_t aSizeT) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::sizetToStr(aSizeT);
  MAPM lNumber = lStrRep.c_str();
  return Integer(lNumber);
#else
  return Integer((IMAPM)aSizeT);
#endif
}

Integer& Integer::operator=(const Integer& aInteger) {
  theInteger = aInteger.theInteger;
  return *this;
}

MAPM Integer::longlongToMAPM(long long aLong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::longLongToStr(aLong);
  return MAPM(lStrRep.c_str());
#else
  return (MAPM)aLong;
#endif
}

IMAPM Integer::floatingToInteger(MAPM theFloating)
{
#ifndef ZORBA_NO_BIGNUMBERS
  // TODO inf and nan handling
  if (IS_POSITIVE_OR_ZERO(theFloating))
    return theFloating.floor();
  else
    return theFloating.ceil();
#else
  return (IMAPM)theFloating;
#endif
}

Integer Integer::operator+(const Integer& aInteger) const {
  return Integer(theInteger + aInteger.theInteger);
}

Decimal Integer::operator+(const Decimal& aDecimal) const {
  return Decimal(theInteger + aDecimal.theDecimal);
}

Integer& Integer::operator+=(const Integer& aInteger) {
  theInteger += aInteger.theInteger;
  return *this;
}

Integer Integer::operator-(const Integer& aInteger) const {
  return Integer(theInteger - aInteger.theInteger);
}

Decimal Integer::operator-(const Decimal& aDecimal) const {
  return Decimal(theInteger - aDecimal.theDecimal);
}

Integer& Integer::operator-=(const Integer& aInteger) {
  theInteger -= aInteger.theInteger;
  return *this;
}

Integer Integer::operator*(const Integer& aInteger) const {
  return Integer(theInteger * aInteger.theInteger);
}

Decimal Integer::operator*(const Decimal& aDecimal) const {
  return Decimal(theInteger * aDecimal.theDecimal);
}

Integer& Integer::operator*=(const Integer& aInteger) {
  theInteger *= aInteger.theInteger;
  return *this;
}

Integer Integer::operator/(const Integer& aInteger) const {
  MAPM lRes = (MAPM)theInteger / aInteger.theInteger;
  lRes = floatingToInteger(lRes);
  return Integer(lRes);
}

Decimal Integer::operator/(const Decimal& aDecimal) const {
  MAPM lRes = (MAPM)theInteger / aDecimal.theDecimal;
  return Decimal(lRes);
}

Integer& Integer::operator/=(const Integer& aInteger) {
  theInteger /= (MAPM)aInteger.theInteger;
  theInteger = floatingToInteger(theInteger);
  return *this;
}

Integer Integer::operator%(const Integer& aInteger) const {
  MAPM lRes = theInteger % aInteger.theInteger;
  return Integer(lRes);
}

Decimal Integer::operator%(const Decimal& aDecimal) const {
  MAPM lRes = theInteger % (IMAPM)aDecimal.theDecimal;
  return Decimal(lRes);
}

Integer& Integer::operator%=(const Integer& aInteger) {
  theInteger %= aInteger.theInteger;
  return *this;
}

Integer Integer::operator-() const {
  return Integer(-theInteger);
}

Integer& Integer::operator++() {
  ++theInteger;
  return *this;
}

Integer& Integer::operator--() {
  --theInteger;
  return *this;
}

Integer Integer::operator++(int) {
  Integer lRes(theInteger);
  ++theInteger;
  return lRes;
}

Integer Integer::operator--(int) {
  Integer lRes(theInteger);
  --theInteger;
  return lRes;
}

Integer Integer::round(Integer aPrecision) const {
  return Integer(Decimal::round(theInteger, aPrecision.theInteger));
}

Integer Integer::roundHalfToEven(Integer aPrecision) const {
  return Integer(Decimal::roundHalfToEven(theInteger, aPrecision.theInteger));
}

Integer Integer::sqrt () const {
#ifndef ZORBA_NO_BIGNUMBERS
  return Integer (theInteger.sqrt ());
#else
  return Integer(::sqrt((double)theInteger));
#endif
}

bool Integer::operator==(const Decimal& aDecimal) const {
  return theInteger == aDecimal.theDecimal;
}

bool Integer::operator!=(const Decimal& aDecimal) const {
  return theInteger != aDecimal.theDecimal;
}

bool Integer::operator<(const Decimal& aDecimal) const {
  return theInteger < aDecimal.theDecimal;
}

bool Integer::operator<=(const Decimal& aDecimal) const {
  return theInteger <= aDecimal.theDecimal;
}

bool Integer::operator<=(const Double& aDouble) const {
    return theInteger <= aDouble.theFloating;
}

bool Integer::operator>(const Decimal& aDecimal) const {
  return theInteger > aDecimal.theDecimal;
}

bool Integer::operator>=(const Decimal& aDecimal) const {
  return theInteger >= aDecimal.theDecimal;
}

bool Integer::operator>=(const Double& aDouble) const {
  return theInteger >= aDouble.theFloating;
}

xqpString Integer::toString() const {
#ifndef ZORBA_NO_BIGNUMBERS
  char* lBuffer = new char[theInteger.myDigits()];
  theInteger.toIntegerString(lBuffer);
  xqpString lResult = lBuffer;
  delete lBuffer;
  return lResult;
#else
  char lBuffer[124];
  sprintf(lBuffer, "%d", theInteger);
  return xqpString(lBuffer);
#endif
}

uint32_t Integer::hash() const
{
#ifndef ZORBA_NO_BIGNUMBERS
  Integer lInteger(theInteger % MAPM::get65535());
  if (lInteger < Integer::zero())
    lInteger = -lInteger;
  uint32_t lHash;
  NumConversions::integerToUInt(lInteger, lHash);
  return lHash;
#else
  return (uint32_t)theInteger%65535;
#endif
}

std::ostream& operator<<(std::ostream& os, const Integer& aInteger) {
  os << aInteger.toString();
  return os;
}

} // namespace zorba
<commit_msg>reverted wrong fix<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 "zorbatypes/integer.h"
#include "zorbatypes/decimal.h"
#include "zorbatypes/floatimpl.h"
#include "zorbatypes/numconversions.h"
#include <stdlib.h>

#ifndef ZORBA_NO_BIGNUMBERS
#define IS_ZERO(mapm_obj)                 (mapm_obj.sign() == 0)
#define IS_POSITIVE(mapm_obj)             (mapm_obj.sign() > 0)
#define IS_POSITIVE_OR_ZERO(mapm_obj)     (mapm_obj.sign() >= 0)
#define IS_NEGATIVE(mapm_obj)             (mapm_obj.sign() < 0)
#else
#define IS_ZERO(mapm_obj)                 (mapm_obj == 0)
#define IS_POSITIVE(mapm_obj)             (mapm_obj > 0)
#define IS_POSITIVE_OR_ZERO(mapm_obj)     (mapm_obj >= 0)
#define IS_NEGATIVE(mapm_obj)             (mapm_obj < 0)
#endif

namespace zorba {
SERIALIZABLE_CLASS_VERSIONS(Integer)
END_SERIALIZABLE_CLASS_VERSIONS(Integer)

Integer& Integer::zero() {
  static Integer lValue(IMAPM(0));
  return lValue;
}

#ifdef ZORBA_NUMERIC_OPTIMIZATION
HashCharPtrObjPtrLimited<Integer>   Integer::parsed_integers;
#endif

bool Integer::parseString(const char* aCharStar, Integer& aInteger)
{
#ifdef ZORBA_NUMERIC_OPTIMIZATION
  Integer *hashed_integer;
  if(parsed_integers.get(aCharStar, hashed_integer))
  {
    //found in hash
    aInteger.theInteger = hashed_integer->theInteger;
    return true;
  }
#endif
  // correctness check
  const char* lCur = aCharStar;
  bool lGotSign = false;
  bool lStop = false;
  bool lGotDigit = false;
  bool new_aCharStar = false;

  char ch = *lCur;

  // Skip leading space
  while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
  {
    ++lCur;
    aCharStar++;
    ch = *lCur;
  }

  while (*lCur != '\0' && !lStop)
  {
    ch = *lCur;

    switch(ch)
    {
    case '+':
      if (lGotSign || lGotDigit) {
        lStop = true;
      } else {
        lGotSign = true;
      }
      break;

    case '-':
      if(lGotSign || lGotDigit) {
        lStop = true;
      } else {
        lGotSign = true;
      }
      break;

    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      lGotDigit = true;
      break;

    case ' ':
    case '\t':
    case '\n':
    case '\r':
    {
      const char* firstSpace = lCur;

      // Skip trailing space
      while(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
      {
        ++lCur;
        ch = *lCur;
      }

      if (*lCur != 0)
      {
        lStop = true;
      }
      else
      {
        int len = firstSpace - aCharStar + 1;
        char* copy = new char[len];
        strncpy(copy, aCharStar, len);
        copy[len-1] = 0;
        aCharStar = copy;
        new_aCharStar = true;
        lCur--;
      }

      break;
    }

    default:
      lStop = true;
      break;
    }

    lCur++;
  }

  if (lStop || !lGotDigit)
  {
    if(new_aCharStar)
      delete[] aCharStar;
    return false;
  }
  else
  {
#ifndef ZORBA_NO_BIGNUMBERS
    aInteger.theInteger = aCharStar;
#else
    aInteger.theInteger = atoi(aCharStar);
#endif

#ifdef ZORBA_NUMERIC_OPTIMIZATION
    hashed_integer = new Integer(aInteger);
    const char  *dup_str = _strdup(aCharStar);
    parsed_integers.insert(dup_str, hashed_integer);
#endif
    if(new_aCharStar)
      delete[] aCharStar;
    return true;
  }
}

bool Integer::parseStringUnsigned(const char* aStarChar, Integer& aUInteger) {
  // correctness check
  const char* lCur = aStarChar;
  bool lStop = false;
  while (*lCur != '\0' && !lStop) {
    char lTmp = *lCur++;
    switch(lTmp) {
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        break;
      default:
        lStop = true;
        break;
    }
  }
  if (lStop) {
    return false;
  } else {
#ifndef ZORBA_NO_BIGNUMBERS
    aUInteger.theInteger = aStarChar;
    return true;
#else
    aUInteger.theInteger = (IMAPM)atoi(aStarChar);
    return true;
#endif
  }
}

bool Integer::parseDouble(const Double& aDouble, Integer& aInteger) {
  if (aDouble.isFinite()) {
    aInteger.theInteger = floatingToInteger(aDouble.theFloating);
    return true;
  }
  else {
    return false;
  }
}

bool Integer::parseFloat(const Float& aFloat, Integer& aInteger) {
  if (aFloat.isFinite()) {
    aInteger.theInteger = floatingToInteger(aFloat.theFloating);
    return true;
  }
  else {
    return false;
  }
}

Integer Integer::parseDecimal(const Decimal& aDecimal) {
  Integer lInteger(floatingToInteger(aDecimal.theDecimal));
  return lInteger;
}

Integer Integer::parseLongLong(long long aLong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::longLongToStr(aLong);
  MAPM lMAPM = lStrRep.c_str();
  return Integer(lMAPM);
#else
  return Integer((IMAPM)aLong);
#endif
}

Integer Integer::parseULongLong(unsigned long long aULong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::ulongLongToStr(aULong);
  MAPM lMAPM = lStrRep.c_str();
  return Integer(lMAPM);
#else
  return Integer((IMAPM)aULong);
#endif
}

Integer Integer::parseInt(int32_t aInt) {
  MAPM lMAPM = aInt;
  Integer lInteger(lMAPM);
  return lInteger;
}

Integer Integer::parseUInt(uint32_t aUInt) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::uintToStr(aUInt);
  MAPM lMAPM = lStrRep.c_str();
  return Integer(lMAPM);
#else
  return Integer((IMAPM)aUInt);
#endif
}

Integer Integer::parseLong(long aLong) {
  MAPM lNumber = aLong;
  return Integer(lNumber);
}

Integer Integer::parseULong(unsigned long aULong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::ulongLongToStr(aULong);
  MAPM lNumber = lStrRep.c_str();
  return Integer(lNumber);
#else
  return Integer((IMAPM)aULong);
#endif
}
Integer Integer::parseSizeT(size_t aSizeT) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::sizetToStr(aSizeT);
  MAPM lNumber = lStrRep.c_str();
  return Integer(lNumber);
#else
  return Integer((IMAPM)aSizeT);
#endif
}

Integer& Integer::operator=(const Integer& aInteger) {
  theInteger = aInteger.theInteger;
  return *this;
}

MAPM Integer::longlongToMAPM(long long aLong) {
#ifndef ZORBA_NO_BIGNUMBERS
  xqpString lStrRep = NumConversions::longLongToStr(aLong);
  return MAPM(lStrRep.c_str());
#else
  return (MAPM)aLong;
#endif
}

IMAPM Integer::floatingToInteger(MAPM theFloating)
{
#ifndef ZORBA_NO_BIGNUMBERS
  // TODO inf and nan handling
  if (IS_POSITIVE_OR_ZERO(theFloating))
    return theFloating.floor();
  else
    return theFloating.ceil();
#else
  return (IMAPM)theFloating;
#endif
}

Integer Integer::operator+(const Integer& aInteger) const {
  return Integer(theInteger + aInteger.theInteger);
}

Decimal Integer::operator+(const Decimal& aDecimal) const {
  return Decimal(theInteger + aDecimal.theDecimal);
}

Integer& Integer::operator+=(const Integer& aInteger) {
  theInteger += aInteger.theInteger;
  return *this;
}

Integer Integer::operator-(const Integer& aInteger) const {
  return Integer(theInteger - aInteger.theInteger);
}

Decimal Integer::operator-(const Decimal& aDecimal) const {
  return Decimal(theInteger - aDecimal.theDecimal);
}

Integer& Integer::operator-=(const Integer& aInteger) {
  theInteger -= aInteger.theInteger;
  return *this;
}

Integer Integer::operator*(const Integer& aInteger) const {
  return Integer(theInteger * aInteger.theInteger);
}

Decimal Integer::operator*(const Decimal& aDecimal) const {
  return Decimal(theInteger * aDecimal.theDecimal);
}

Integer& Integer::operator*=(const Integer& aInteger) {
  theInteger *= aInteger.theInteger;
  return *this;
}

Integer Integer::operator/(const Integer& aInteger) const {
  MAPM lRes = (MAPM)theInteger / aInteger.theInteger;
  lRes = floatingToInteger(lRes);
  return Integer(lRes);
}

Decimal Integer::operator/(const Decimal& aDecimal) const {
  MAPM lRes = (MAPM)theInteger / aDecimal.theDecimal;
  return Decimal(lRes);
}

Integer& Integer::operator/=(const Integer& aInteger) {
  theInteger /= (MAPM)aInteger.theInteger;
  theInteger = floatingToInteger(theInteger);
  return *this;
}

Integer Integer::operator%(const Integer& aInteger) const {
  MAPM lRes = theInteger % aInteger.theInteger;
  return Integer(lRes);
}

Decimal Integer::operator%(const Decimal& aDecimal) const {
  MAPM lRes = theInteger % (IMAPM)aDecimal.theDecimal;
  return Decimal(lRes);
}

Integer& Integer::operator%=(const Integer& aInteger) {
  theInteger %= aInteger.theInteger;
  return *this;
}

Integer Integer::operator-() const {
  return Integer(-theInteger);
}

Integer& Integer::operator++() {
  ++theInteger;
  return *this;
}

Integer& Integer::operator--() {
  --theInteger;
  return *this;
}

Integer Integer::operator++(int) {
  Integer lRes(theInteger);
  ++theInteger;
  return lRes;
}

Integer Integer::operator--(int) {
  Integer lRes(theInteger);
  --theInteger;
  return lRes;
}

Integer Integer::round(Integer aPrecision) const {
  return Integer(Decimal::round(theInteger, aPrecision.theInteger));
}

Integer Integer::roundHalfToEven(Integer aPrecision) const {
  return Integer(Decimal::roundHalfToEven(theInteger, aPrecision.theInteger));
}

Integer Integer::sqrt () const {
#ifndef ZORBA_NO_BIGNUMBERS
  return Integer (theInteger.sqrt ());
#else
  return Integer(::sqrt((double)theInteger));
#endif
}

bool Integer::operator==(const Decimal& aDecimal) const {
  return theInteger == aDecimal.theDecimal;
}

bool Integer::operator!=(const Decimal& aDecimal) const {
  return theInteger != aDecimal.theDecimal;
}

bool Integer::operator<(const Decimal& aDecimal) const {
  return theInteger < aDecimal.theDecimal;
}

bool Integer::operator<=(const Decimal& aDecimal) const {
  return theInteger <= aDecimal.theDecimal;
}

bool Integer::operator<=(const Double& aDouble) const {
    return theInteger <= aDouble.theFloating;
}

bool Integer::operator>(const Decimal& aDecimal) const {
  return theInteger > aDecimal.theDecimal;
}

bool Integer::operator>=(const Decimal& aDecimal) const {
  return theInteger >= aDecimal.theDecimal;
}

bool Integer::operator>=(const Double& aDouble) const {
  return theInteger >= aDouble.theFloating;
}

xqpString Integer::toString() const {
#ifndef ZORBA_NO_BIGNUMBERS
  char lBuffer[1024];
  theInteger.toIntegerString(lBuffer);
  xqpString lResult = lBuffer;
  return lResult;
#else
  char lBuffer[124];
  sprintf(lBuffer, "%d", theInteger);
  return xqpString(lBuffer);
#endif
}

uint32_t Integer::hash() const
{
#ifndef ZORBA_NO_BIGNUMBERS
  Integer lInteger(theInteger % MAPM::get65535());
  if (lInteger < Integer::zero())
    lInteger = -lInteger;
  uint32_t lHash;
  NumConversions::integerToUInt(lInteger, lHash);
  return lHash;
#else
  return (uint32_t)theInteger%65535;
#endif
}

std::ostream& operator<<(std::ostream& os, const Integer& aInteger) {
  os << aInteger.toString();
  return os;
}

} // namespace zorba
<|endoftext|>