<commit_before>#include <ros/ros.h>

#include <geometry_msgs/Twist.h>

#include <tf/transform_broadcaster.h>

#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>

#include <sys/time.h>

#include "Comm.h"

#include <sensor_msgs/Imu.h>
#include <std_srvs/Trigger.h>

#include <stdexcept>

class CheckSumError : public std::logic_error {
public:
    CheckSumError(const std::string &data) :
        std::logic_error("Received the Invalid IMU Data: " + data)
    {
    }
};

float deg_to_rad(float deg) {
    return deg / 180.0f * M_PI;
}

template<class T>
bool isInRange(T value, T max, T min){
    return (value >= min) && (value <= max);
}

struct ImuData {
    double angular_deg[3];
		bool flag;

    ImuData(){
        for(int i=0; i < 2; i++){
            angular_deg[i] = 0;
        }
    }
};

// 角度ごとにURGのデータを送信するためのサービス
// 要求があったときに，URGのデータを別のトピックに送信するだけ
class IMU {
private:
    ros::Publisher imu_pub_;
    ros::ServiceServer reset_service_;
    ros::ServiceServer carivrate_service_;
    CComm* usb;
    double gyro_unit;
    double acc_unit;
    double init_angle;
    std::string port_name;
    int   baudrate;
    ros::Rate loop_rate;
    int  z_axis_dir_;

    ImuData getImuData(){
        ImuData data;
        char command[2] = {0};
        char command2[50] = {0};
        char temp[6];
        unsigned long int sum = 0;

        const float temp_unit = 0.00565;

        sprintf(command, "o");
        usb->Send(command, strlen(command));
        ros::Duration(0.03).sleep();

        usb->Recv(command2, 50);
        ROS_INFO_STREAM("recv = " << command2);

        if (command2[0] == '\0') {
        	data.flag = false;
        	return data;
        }
        data.flag = true;

        memmove(temp,command2,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[0] = ((short)strtol(temp, NULL, 16)) * gyro_unit;
        memmove(temp,command2+4,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[1] = ((short)strtol(temp, NULL, 16)) * gyro_unit;
        memmove(temp,command2+8,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[2] = ((short)strtol(temp, NULL, 16)) * gyro_unit * z_axis_dir_;

        memmove(temp,command2+12,4);

        if(sum != ((short)strtol(temp, NULL, 16))){
            ROS_ERROR_STREAM("Recv Checksum: " << ((short)strtol(temp, NULL, 16)));
            ROS_ERROR_STREAM("Calculate Checksum: " << sum);
            throw CheckSumError(command2);
        }
        //while(data.angular_deg[2] < -180) data.angular_deg[2] += 180;
        //while(data.angular_deg[2] > 180) data.angular_deg[2] -= 180;

        return data;
    }

public:
    bool resetCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        sprintf(command, "0");
        usb->Send(command, strlen(command));
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        res.success = true;
        res.message = "Successful reset angle, gyro angle be zero right now.";

        return true;
    }

    bool caribrateCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb->Send(command, strlen(command));
        std::cout << "Calibrate start ";
        for(int i=0; i<8; ++i) {
            std::cout << ". ";
            sleep(1);
        }
        std::cout << "finish." << std::endl;
        res.success = true;
        res.message = "ADIS driver done with calibration.";

        return true;
    }

    IMU(ros::NodeHandle node) :
        imu_pub_(node.advertise<sensor_msgs::Imu>("imu", 10)),
        reset_service_(node.advertiseService("imu_reset", &IMU::resetCallback, this)),
        carivrate_service_(node.advertiseService("imu_caribrate", &IMU::caribrateCallback, this)),
        gyro_unit(0.00836181640625), acc_unit(0.8), init_angle(0.0),
        port_name("/dev/ttyUSB0"), baudrate(115200), loop_rate(50), z_axis_dir_(-1)
    {
        ros::NodeHandle private_nh("~");
        private_nh.getParam("port_name", port_name);
        private_nh.param<double>("gyro_unit", gyro_unit, gyro_unit);
        private_nh.param<double>("acc_unit", acc_unit, acc_unit);
        private_nh.param<int>("baud_rate", baudrate, baudrate);
        private_nh.param<double>("init_angle", init_angle, init_angle);
        private_nh.param<int>("z_axis_dir", z_axis_dir_, z_axis_dir_);
        usb = new CComm(port_name, baudrate);
    }

    bool init() {
        char command[2] = {0};
        char command2[101] = {0};
        //シリアルポートオープン
        if (!usb->Open()) {
            std::cerr << "open error" << std::endl;
            return false;
        }
        std::cout << "device open success" << std::endl;
        sleep(1);
        //コンフィギュレーション キャリブレーション
        // if(m_calibration == true){
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb->Send(command, strlen(command));
        std::cout << "send = " << command << std::endl;
        for(int i=0; i<8; ++i) {
            printf(". ");
            sleep(1);
        }
        // }
        //コンフィギュレーション リセット
        // if(m_reset == true){
        sprintf(command, "0");
        usb->Send(command, strlen(command));        //送信
        std::cout << "send = " << command << std::endl;
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        // }
        usb->Recv(command2, 100);        //空読み バッファクリアが効かない？
        usb->ClearRecvBuf();                //バッファクリア
        return true;
    }

    void run() {
        double old_angular_z_deg = getImuData().angular_deg[2];
        double angular_z_deg = 0;
        unsigned short abnormal_count = 0;

        while (ros::ok()) {
            tf::Quaternion q;
            sensor_msgs::Imu output_msg;
            try{
                ImuData data = getImuData();
                if (data.flag == false){
                    usb->Close();
                    if(!usb->Open()) {
                        std::cerr << "reconnecting" << std::endl;
                    }
                }else{
                    output_msg.header.stamp = ros::Time::now();

                    ROS_INFO_STREAM("x_deg = " << data.angular_deg[0]);
                    ROS_INFO_STREAM("y_deg = " << data.angular_deg[1]);
                    ROS_INFO_STREAM("z_deg = " << data.angular_deg[2]);

                    if(!isInRange(std::abs(old_angular_z_deg), 180.0, 165.0) && !isInRange(std::abs(data.angular_deg[2]), 180.0, 165.0) &&
                        std::abs(old_angular_z_deg - data.angular_deg[2]) > 40 && abnormal_count < 4){

                        ROS_WARN_STREAM("Angle change too large: z = " << data.angular_deg[2]);
                        ROS_WARN_STREAM("old_z = " << old_angular_z_deg);
                        abnormal_count++;
                        continue;
                    }else{
                        abnormal_count = 0;
                        angular_z_deg = data.angular_deg[2];
                    }

                    q = tf::createQuaternionFromRPY(deg_to_rad(data.angular_deg[0]), deg_to_rad(-data.angular_deg[1]), deg_to_rad(angular_z_deg));
                    tf::quaternionTFToMsg(q, output_msg.orientation);
                    imu_pub_.publish(output_msg);
                    old_angular_z_deg = angular_z_deg;

                }
            }catch(const CheckSumError &e){
                output_msg.header.stamp = ros::Time::now();
                ROS_ERROR_STREAM(e.what());
                continue;
            }

            ros::spinOnce();
            //loop_rate.sleep();
        }
    }
};

int main(int argc, char * argv[])
{
    ros::init(argc, argv, "imu_node");
    ros::NodeHandle node;
    IMU imu(node);
    if(!imu.init()) return 1;
    imu.run();

    return 0;
}
<commit_msg>organize old naming rules<commit_after>#include <ros/ros.h>

#include <geometry_msgs/Twist.h>

#include <tf/transform_broadcaster.h>

#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>

#include <sys/time.h>

#include "Comm.h"

#include <sensor_msgs/Imu.h>
#include <std_srvs/Trigger.h>

#include <stdexcept>

class CheckSumError : public std::logic_error {
public:
    CheckSumError(const std::string &data) :
        std::logic_error("Received the Invalid IMU Data: " + data)
    {
    }
};

float deg_to_rad(float deg) {
    return deg / 180.0f * M_PI;
}

template<class T>
bool isInRange(T value, T max, T min){
    return (value >= min) && (value <= max);
}

struct ImuData {
    double angular_deg[3];
		bool flag;

    ImuData(){
        for(int i=0; i < 2; i++){
            angular_deg[i] = 0;
        }
    }
};

// 角度ごとにURGのデータを送信するためのサービス
class IMU {
private:
    ros::Publisher imu_pub_;
    ros::ServiceServer reset_service_;
    ros::ServiceServer carivrate_service_;
    CComm* usb_;
    double gyro_unit_;
    double acc_unit_;
    std::string port_name_;
    int   baudrate_;
    ros::Rate loop_rate_;
    int  z_axis_dir_;

    ImuData getImuData(){
        ImuData data;
        char command[2] = {0};
        char command2[50] = {0};
        char temp[6];
        unsigned long int sum = 0;

        const float temp_unit = 0.00565;

        sprintf(command, "o");
        usb_->Send(command, strlen(command));
        ros::Duration(0.03).sleep();

        usb_->Recv(command2, 50);
        ROS_INFO_STREAM("recv = " << command2);

        if (command2[0] == '\0') {
        	data.flag = false;
        	return data;
        }
        data.flag = true;

        memmove(temp,command2,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[0] = ((short)strtol(temp, NULL, 16)) * gyro_unit_;
        memmove(temp,command2+4,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[1] = ((short)strtol(temp, NULL, 16)) * gyro_unit_;
        memmove(temp,command2+8,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[2] = ((short)strtol(temp, NULL, 16)) * gyro_unit_ * z_axis_dir_;

        memmove(temp,command2+12,4);

        if(sum != ((short)strtol(temp, NULL, 16))){
            ROS_ERROR_STREAM("Recv Checksum: " << ((short)strtol(temp, NULL, 16)));
            ROS_ERROR_STREAM("Calculate Checksum: " << sum);
            throw CheckSumError(command2);
        }
        //while(data.angular_deg[2] < -180) data.angular_deg[2] += 180;
        //while(data.angular_deg[2] > 180) data.angular_deg[2] -= 180;

        return data;
    }

public:
    bool resetCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        sprintf(command, "0");
        usb_->Send(command, strlen(command));
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        res.success = true;
        res.message = "Successful reset angle, gyro angle be zero right now.";

        return true;
    }

    bool caribrateCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb_->Send(command, strlen(command));
        std::cout << "Calibrate start ";
        for(int i=0; i<8; ++i) {
            std::cout << ". ";
            sleep(1);
        }

        res.success = true;
        res.message = "ADIS driver is done with calibration.";
        ROS_INFO_STREAM(res.message);

        return true;
    }

    IMU(ros::NodeHandle node) :
        imu_pub_(node.advertise<sensor_msgs::Imu>("imu", 10)),
        reset_service_(node.advertiseService("imu_reset", &IMU::resetCallback, this)),
        carivrate_service_(node.advertiseService("imu_caribrate", &IMU::caribrateCallback, this)),
        gyro_unit_(0.00836181640625), acc_unit_(0.8),
        port_name_("/dev/ttyUSB0"), baudrate_(115200), loop_rate_(50), z_axis_dir_(-1)
    {
        ros::NodeHandle private_nh("~");
        private_nh.getParam("port_name", port_name_);
        private_nh.param<double>("gyro_unit", gyro_unit_, gyro_unit_);
        private_nh.param<double>("acc_unit", acc_unit_, acc_unit_);
        private_nh.param<int>("baud_rate", baudrate_, baudrate_);
        private_nh.param<int>("z_axis_dir", z_axis_dir_, z_axis_dir_);
        usb_ = new CComm(port_name_, baudrate_);
    }

    bool init() {
        char command[2] = {0};
        char command2[101] = {0};
        //シリアルポートオープン
        if (!usb_->Open()) {
            std::cerr << "open error" << std::endl;
            return false;
        }
        std::cout << "device open success" << std::endl;
        sleep(1);
        //コンフィギュレーション キャリブレーション
        // if(m_calibration == true){
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb_->Send(command, strlen(command));
        std::cout << "send = " << command << std::endl;
        for(int i=0; i<8; ++i) {
            printf(". ");
            sleep(1);
        }
        // }
        //コンフィギュレーション リセット
        // if(m_reset == true){
        sprintf(command, "0");
        usb_->Send(command, strlen(command));        //送信
        std::cout << "send = " << command << std::endl;
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        // }
        usb_->Recv(command2, 100);        //空読み バッファクリアが効かない？
        usb_->ClearRecvBuf();                //バッファクリア
        return true;
    }

    void run() {
        double old_angular_z_deg = getImuData().angular_deg[2];
        double angular_z_deg = 0;
        unsigned short abnormal_count = 0;

        while (ros::ok()) {
            tf::Quaternion q;
            sensor_msgs::Imu output_msg;
            try{
                ImuData data = getImuData();
                if (data.flag == false){
                    usb_->Close();
                    if(!usb_->Open()) {
                        std::cerr << "reconnecting" << std::endl;
                    }
                }else{
                    output_msg.header.stamp = ros::Time::now();

                    ROS_INFO_STREAM("x_deg = " << data.angular_deg[0]);
                    ROS_INFO_STREAM("y_deg = " << data.angular_deg[1]);
                    ROS_INFO_STREAM("z_deg = " << data.angular_deg[2]);

                    if(!isInRange(std::abs(old_angular_z_deg), 180.0, 165.0) && !isInRange(std::abs(data.angular_deg[2]), 180.0, 165.0) &&
                        std::abs(old_angular_z_deg - data.angular_deg[2]) > 40 && abnormal_count < 4){

                        ROS_WARN_STREAM("Angle change too large: z = " << data.angular_deg[2]);
                        ROS_WARN_STREAM("old_z = " << old_angular_z_deg);
                        abnormal_count++;
                        continue;
                    }else{
                        abnormal_count = 0;
                        angular_z_deg = data.angular_deg[2];
                    }

                    q = tf::createQuaternionFromRPY(deg_to_rad(data.angular_deg[0]), deg_to_rad(-data.angular_deg[1]), deg_to_rad(angular_z_deg));
                    tf::quaternionTFToMsg(q, output_msg.orientation);
                    imu_pub_.publish(output_msg);
                    old_angular_z_deg = angular_z_deg;

                }
            }catch(const CheckSumError &e){
                output_msg.header.stamp = ros::Time::now();
                ROS_ERROR_STREAM(e.what());
                continue;
            }

            ros::spinOnce();
            //loop_rate.sleep();
        }
    }
};

int main(int argc, char * argv[])
{
    ros::init(argc, argv, "imu_node");
    ros::NodeHandle node;
    IMU imu(node);
    if(!imu.init()) return 1;
    imu.run();

    return 0;
}
<|endoftext|>


<commit_before>
#include "../../src/TinyBlock.hpp"

#include "UnitTest.hpp"

#include <cstdlib>

using namespace std;
using namespace memwa;

// ----------------------------------------------------------------------------

void TestTinyBlock( ut::UnitTest * u, const std::size_t objectSize, const std::size_t alignment )
{
	const std::size_t objectsPerPool = UCHAR_MAX;
	const std::size_t blockSize = objectsPerPool * objectSize;
	TinyBlock block( blockSize, objectSize, alignment, objectsPerPool );

	// First do basic tests of empty block.
	UNIT_TEST_WITH_MSG( u, block.IsEmpty(), "new block should be empty." );
	UNIT_TEST_WITH_MSG( u, !block.IsFull(), "new block should not be full." );
	UNIT_TEST_WITH_MSG( u, block.GetInUseCount() == 0, "new block should have no chunks in use." );
	UNIT_TEST( u, !block.IsCorrupt( objectSize ) );

	// Do tests while allocating chunks til block is full.
	void * holder[ objectsPerPool ];
	void * chunk = nullptr;
	for ( unsigned int ii = 0; ii < objectsPerPool; ++ii )
	{
		chunk = block.Allocate( objectSize );
		// This for loop checks that each chunk allocated from the same block has a unique address.
		for ( unsigned int jj = 0; jj < ii; ++jj )
		{
			void * c = holder[ jj ];
			UNIT_TEST( u, chunk != c );
		}
		unsigned char * tooHigh = reinterpret_cast< unsigned char * >( chunk ) + blockSize;
		unsigned char * tooLow = reinterpret_cast< unsigned char * >( chunk ) - blockSize;
		holder[ ii ] = chunk;
		UNIT_TEST( u, chunk != nullptr );
		UNIT_TEST( u, reinterpret_cast< std::size_t >( chunk ) % alignment == 0 );
		UNIT_TEST( u, !block.IsEmpty() );
		UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( tooLow, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( nullptr, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( tooHigh, blockSize ) );
		UNIT_TEST( u, block.IsBelowAddress( tooHigh, blockSize ) );
		UNIT_TEST( u, block.GetInUseCount() == 1 + ii );
	}
	UNIT_TEST( u, !block.IsCorrupt( objectSize ) );
	UNIT_TEST( u, !block.IsEmpty() );
	UNIT_TEST( u, block.IsFull() );
	UNIT_TEST( u, block.GetInUseCount() == objectsPerPool );
	chunk = block.Allocate( objectSize );
	UNIT_TEST( u, chunk == nullptr );

	// Do tests while releasing chunks til block is empty.
	for ( unsigned int ii = 0; ii < objectsPerPool; ++ii )
	{
		chunk = holder[ ii ];
		unsigned char * tooHigh = reinterpret_cast< unsigned char * >( chunk ) + blockSize;
		UNIT_TEST( u, !block.IsEmpty() );
		UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( tooHigh, blockSize ) );
		UNIT_TEST( u, block.IsBelowAddress( tooHigh, blockSize ) );
		block.Release( chunk, objectSize );
		UNIT_TEST( u, block.GetInUseCount() == objectsPerPool - 1 - ii );
		holder[ ii ] = nullptr;
	}
	UNIT_TEST( u, block.IsEmpty() );
	UNIT_TEST( u, !block.IsCorrupt( objectSize ) );

	for ( unsigned int ii = 0; ii < objectsPerPool * 10; ++ii )
	{
		const unsigned int index = rand() % objectsPerPool;
		chunk = holder[ index ];
		if ( chunk == nullptr )
		{
			const unsigned int countBefore = block.GetInUseCount();
			chunk = block.Allocate( objectSize );
			const unsigned int countAfter = block.GetInUseCount();
			UNIT_TEST( u, countAfter - 1 == countBefore );
			UNIT_TEST( u, chunk != nullptr );
			const std::size_t chunkAddress = reinterpret_cast< std::size_t >( chunk );
			UNIT_TEST( u, chunkAddress % alignment == 0 );
/*			if ( chunkAddress % alignment != 0 )
			{
				std::cout << "\t chunk: " << chunkAddress
					<< "  objectSize: " << objectSize
					<< "  alignment: " << alignment
					<< "  offset: " << chunkAddress % alignment << std::endl;
			} */
			UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
			holder[ index ] = chunk;
		}
		else
		{
			UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
			const unsigned int countBefore = block.GetInUseCount();
			block.Release( chunk, objectSize );
			const unsigned int countAfter = block.GetInUseCount();
			UNIT_TEST( u, countAfter + 1 == countBefore );
			holder[ index ] = nullptr;
			chunk = nullptr;
		}
		UNIT_TEST( u, !block.IsCorrupt( objectSize ) );
	}

	block.Destroy();
}

// ----------------------------------------------------------------------------

void TestTinyBlock()
{
	ut::UnitTestSet & uts = ut::UnitTestSet::GetIt();
	ut::UnitTest * u = uts.AddUnitTest( "Test TinyBlock" );

	std::size_t objectSize = 1;
	std::size_t alignment = 1;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 2;
	alignment = 2;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 4;
	alignment = 4;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 4;
	alignment = 2;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 8;
	alignment = 4;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 16;
	alignment = 8;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 12;
	alignment = 4;
	TestTinyBlock( u, objectSize, alignment );

	objectSize = 32;
	alignment = 8;
	TestTinyBlock( u, objectSize, alignment );

/*
	objectSize = 32;
	alignment = 16;
	TestTinyBlock( u, objectSize, alignment );
*/
}

// ----------------------------------------------------------------------------
<commit_msg>Added output lines to show combinations of sizes and alignments.<commit_after>
#include "../../src/TinyBlock.hpp"

#include "UnitTest.hpp"

#include <iostream>

#include <cstdlib>

using namespace std;
using namespace memwa;

// ----------------------------------------------------------------------------

void TestTinyBlock( ut::UnitTest * u, const std::size_t objectSize, const std::size_t alignment )
{
	const std::size_t objectsPerPool = UCHAR_MAX;
	const std::size_t blockSize = objectsPerPool * objectSize;
	TinyBlock block( blockSize, objectSize, alignment, objectsPerPool );

	// First do basic tests of empty block.
	UNIT_TEST_WITH_MSG( u, block.IsEmpty(), "new block should be empty." );
	UNIT_TEST_WITH_MSG( u, !block.IsFull(), "new block should not be full." );
	UNIT_TEST_WITH_MSG( u, block.GetInUseCount() == 0, "new block should have no chunks in use." );
	UNIT_TEST( u, !block.IsCorrupt( objectSize ) );

	// Do tests while allocating chunks til block is full.
	void * holder[ objectsPerPool ];
	void * chunk = nullptr;
	for ( unsigned int ii = 0; ii < objectsPerPool; ++ii )
	{
		chunk = block.Allocate( objectSize );
		// This for loop checks that each chunk allocated from the same block has a unique address.
		for ( unsigned int jj = 0; jj < ii; ++jj )
		{
			void * c = holder[ jj ];
			UNIT_TEST( u, chunk != c );
		}
		unsigned char * tooHigh = reinterpret_cast< unsigned char * >( chunk ) + blockSize;
		unsigned char * tooLow = reinterpret_cast< unsigned char * >( chunk ) - blockSize;
		holder[ ii ] = chunk;
		UNIT_TEST( u, chunk != nullptr );
		UNIT_TEST( u, reinterpret_cast< std::size_t >( chunk ) % alignment == 0 );
		UNIT_TEST( u, !block.IsEmpty() );
		UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( tooLow, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( nullptr, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( tooHigh, blockSize ) );
		UNIT_TEST( u, block.IsBelowAddress( tooHigh, blockSize ) );
		UNIT_TEST( u, block.GetInUseCount() == 1 + ii );
	}
	UNIT_TEST( u, !block.IsCorrupt( objectSize ) );
	UNIT_TEST( u, !block.IsEmpty() );
	UNIT_TEST( u, block.IsFull() );
	UNIT_TEST( u, block.GetInUseCount() == objectsPerPool );
	chunk = block.Allocate( objectSize );
	UNIT_TEST( u, chunk == nullptr );

	// Do tests while releasing chunks til block is empty.
	for ( unsigned int ii = 0; ii < objectsPerPool; ++ii )
	{
		chunk = holder[ ii ];
		unsigned char * tooHigh = reinterpret_cast< unsigned char * >( chunk ) + blockSize;
		UNIT_TEST( u, !block.IsEmpty() );
		UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
		UNIT_TEST( u, !block.HasAddress( tooHigh, blockSize ) );
		UNIT_TEST( u, block.IsBelowAddress( tooHigh, blockSize ) );
		block.Release( chunk, objectSize );
		UNIT_TEST( u, block.GetInUseCount() == objectsPerPool - 1 - ii );
		holder[ ii ] = nullptr;
	}
	UNIT_TEST( u, block.IsEmpty() );
	UNIT_TEST( u, !block.IsCorrupt( objectSize ) );

	for ( unsigned int ii = 0; ii < objectsPerPool * 10; ++ii )
	{
		const unsigned int index = rand() % objectsPerPool;
		chunk = holder[ index ];
		if ( chunk == nullptr )
		{
			const unsigned int countBefore = block.GetInUseCount();
			chunk = block.Allocate( objectSize );
			const unsigned int countAfter = block.GetInUseCount();
			UNIT_TEST( u, countAfter - 1 == countBefore );
			UNIT_TEST( u, chunk != nullptr );
			const std::size_t chunkAddress = reinterpret_cast< std::size_t >( chunk );
			UNIT_TEST( u, chunkAddress % alignment == 0 );
/*			if ( chunkAddress % alignment != 0 )
			{
				std::cout << "\t chunk: " << chunkAddress
					<< "  objectSize: " << objectSize
					<< "  alignment: " << alignment
					<< "  offset: " << chunkAddress % alignment << std::endl;
			} */
			UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
			holder[ index ] = chunk;
		}
		else
		{
			UNIT_TEST( u, block.HasAddress( chunk, blockSize ) );
			const unsigned int countBefore = block.GetInUseCount();
			block.Release( chunk, objectSize );
			const unsigned int countAfter = block.GetInUseCount();
			UNIT_TEST( u, countAfter + 1 == countBefore );
			holder[ index ] = nullptr;
			chunk = nullptr;
		}
		UNIT_TEST( u, !block.IsCorrupt( objectSize ) );
	}

	block.Destroy();
}

// ----------------------------------------------------------------------------

void TestTinyBlock()
{
	ut::UnitTestSet & uts = ut::UnitTestSet::GetIt();
	ut::UnitTest * u = uts.AddUnitTest( "Test TinyBlock" );

	std::cout << std::endl << "Testing Various BlockSizes and Alignments with TinyBlock." << std::endl
		<< "Object Size \t Alignment" << std::endl
		<< "==========================" << std::endl;

	std::size_t objectSize = 1;
	std::size_t alignment = 1;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 2;
	alignment = 2;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 4;
	alignment = 4;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 4;
	alignment = 2;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 8;
	alignment = 4;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 16;
	alignment = 8;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 12;
	alignment = 4;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 32;
	alignment = 8;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;

	objectSize = 32;
	alignment = 16;
	TestTinyBlock( u, objectSize, alignment );
	std::cout << objectSize << "\t\t" << alignment << std::endl;
}

// ----------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include <ctre.hpp>
#include <iostream>
#include <charconv>

static constexpr auto pattern = ctll::fixed_string("(?<first>[0-9])[0-9]++");

int main() {
	using namespace std::string_view_literals;
	auto input = "123,456,768"sv;

	for (auto match: ctre::range<pattern>(input)) {

		if (match == "456") std::cout << "bingo: ";
		if (match != "768") std::cout << "bad: ";

		if ("456" == match) std::cout << "bingo: ";
		if ("768" != match) std::cout << "bad: ";

		auto capture = match.get<1>();

		if (capture == "456") std::cout << "bingo: ";
		if (capture != "768") std::cout << "bad: ";

		if ("456" == capture) std::cout << "bingo: ";
		if ("768" != capture) std::cout << "bad: ";

		int value = 0;
		auto [ptr, err] = std::from_chars(std::data(match), std::data(match)+std::size(match), value);
		if (err == std::errc{}) {
			std::cout << value << "\n";
		} else {
			std::cout << "error\n";
		}
	}
}
<commit_msg>char_conv is not in xcode<commit_after>#include <ctre.hpp>
#include <iostream>
#include <charconv>

static constexpr auto pattern = ctll::fixed_string("(?<first>[0-9])[0-9]++");

int main() {
	using namespace std::string_view_literals;
	auto input = "123,456,768"sv;

	for (auto match: ctre::range<pattern>(input)) {

		if (match == "456") std::cout << "bingo: ";
		if (match != "768") std::cout << "bad: ";

		if ("456" == match) std::cout << "bingo: ";
		if ("768" != match) std::cout << "bad: ";

		auto capture = match.get<1>();

		if (capture == "456") std::cout << "bingo: ";
		if (capture != "768") std::cout << "bad: ";

		if ("456" == capture) std::cout << "bingo: ";
		if ("768" != capture) std::cout << "bad: ";

		[[maybe_unused]] const char * ptr = std::data(match);
		[[maybe_unused]] size_t length = std::size(match);

		[[maybe_unused]] const char * ptr2 = std::data(capture);
		[[maybe_unused]] size_t length2 = std::size(capture);

		//auto [ptr, err] = std::from_chars(std::data(match), std::data(match)+std::size(match), value);
		//if (err == std::errc{}) {
		//	std::cout << value << "\n";
		//} else {
		//	std::cout << "error\n";
		//}
	}
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>
#include <functional>
#include <utility>

#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/get.hpp>

#include "GlobalContext.hpp"
#include "Variable.hpp"
#include "Utils.hpp"

#include "il/IntermediateProgram.hpp"

#include "GetConstantValue.hpp"

using namespace eddic;

GlobalContext::GlobalContext() : Context(NULL) {
    Val zero = 0;

    variables["eddi_remaining"] = std::make_shared<Variable>("eddi_remaining", stringToType("int"), Position(GLOBAL, "eddi_remaining"), zero);
    variables["eddi_current"] = std::make_shared<Variable>("eddi_current", stringToType("int"), Position(GLOBAL, "eddi_current"), zero);
}

void GlobalContext::writeIL(IntermediateProgram& program){
    for(auto it : variables){
        Type type = it.second->type();

        if(type.isArray()){
            program.addInstruction(program.factory().createGlobalArray(it.second->position().name(), type.base(), type.size()));
        } else {
            if (type.base() == BaseType::INT) {
                program.addInstruction(program.factory().createGlobalIntVariable(it.second->position().name(), boost::get<int>(it.second->val())));
            } else if (type.base() == BaseType::STRING) {
                auto value = boost::get<std::pair<std::string, int>>(it.second->val());
                program.addInstruction(program.factory().createGlobalStringVariable(it.second->position().name(), value.first, value.second));
            }
        }
    }
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, Type type){
    //A global variable must have a value
    assert(type.isArray());

    Position position(GLOBAL, variable);

    return variables[variable] = std::make_shared<Variable>(variable, type, position);
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, Type type, ast::Value& value){
    auto val = boost::apply_visitor(GetConstantValue(), value);

    if(type.isConst()){
        Position position(CONST);
        return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
    }

    Position position(GLOBAL, variable);
    return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
}
<commit_msg>Fix global context writing only non-const variables<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <algorithm>
#include <functional>
#include <utility>

#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/get.hpp>

#include "GlobalContext.hpp"
#include "Variable.hpp"
#include "Utils.hpp"

#include "il/IntermediateProgram.hpp"

#include "GetConstantValue.hpp"

using namespace eddic;

GlobalContext::GlobalContext() : Context(NULL) {
    Val zero = 0;

    variables["eddi_remaining"] = std::make_shared<Variable>("eddi_remaining", stringToType("int"), Position(GLOBAL, "eddi_remaining"), zero);
    variables["eddi_current"] = std::make_shared<Variable>("eddi_current", stringToType("int"), Position(GLOBAL, "eddi_current"), zero);
}

void GlobalContext::writeIL(IntermediateProgram& program){
    for(auto it : variables){
        Type type = it.second->type();

        if(!type.isConst()){
            if(type.isArray()){
                program.addInstruction(program.factory().createGlobalArray(it.second->position().name(), type.base(), type.size()));
            } else {
                if (type.base() == BaseType::INT) {
                    program.addInstruction(program.factory().createGlobalIntVariable(it.second->position().name(), boost::get<int>(it.second->val())));
                } else if (type.base() == BaseType::STRING) {
                    auto value = boost::get<std::pair<std::string, int>>(it.second->val());
                    program.addInstruction(program.factory().createGlobalStringVariable(it.second->position().name(), value.first, value.second));
                }
            }
        }
    }
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, Type type){
    //A global variable must have a value
    assert(type.isArray());

    Position position(GLOBAL, variable);

    return variables[variable] = std::make_shared<Variable>(variable, type, position);
}

std::shared_ptr<Variable> GlobalContext::addVariable(const std::string& variable, Type type, ast::Value& value){
    auto val = boost::apply_visitor(GetConstantValue(), value);

    if(type.isConst()){
        Position position(CONST);
        return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
    }

    Position position(GLOBAL, variable);
    return variables[variable] = std::make_shared<Variable>(variable, type, position, val);
}
<|endoftext|>


<commit_before>
#include "IntegrateTFDH.h"

#include "Element.h"
#include "IntegrateOverRadius.h"
#include "PlasmaFunctions.h"
#include "PlasmaState.h"
#include "PhysicalConstants.h"
#include "RadialFunction.h"
#include "TfdhFunctions.h"

#include <cassert>
#include <cmath>
#include <vector>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv2.h>

namespace {

  struct TfdhParams {
    const Element& e;
    const PlasmaState& p;
    TfdhParams(const Element& re, const PlasmaState& rp) : e(re), p(rp) {}
  };

  int tfdhOde(double r, const double f[], double dfdr[], void *params) {
    const double& qe = PhysicalConstantsCGS::ElectronCharge;
    const double phi = qe*f[0]/r;
    const PlasmaState& p = static_cast<TfdhParams*>(params)->p;
    const double ne = Plasma::ne(phi, p);
    const double ionChargeDensity = Plasma::totalIonChargeDensity(phi, p);
    dfdr[0] = f[1];
    dfdr[1] = -4.0*M_PI*qe * r * (ionChargeDensity - ne);
    return GSL_SUCCESS;
  }
}

RadialFunction TFDH::solve(const Element& e, const PlasmaState& p)
{
  // set parameters here:
  // TODO: automatic way of tuning the radii?
  const double ri = 1e-14;
  const double rf = 1e-10;

  const double dv0 = findPotentialRoot(e, p, ri, rf);
  return integrateODE(e, p, ri, rf, dv0);
}

RadialFunction TFDH::integrateODE(const Element& e, const PlasmaState& p,
    const double r_init, const double r_final, const double dv0)
{
  const double dr_start = r_init;
  const double eps_abs = 1e-6;
  const double eps_rel = 0;
  TfdhParams params(e,p);
  gsl_odeiv2_system sys = {tfdhOde, nullptr, 2, &params};
  gsl_odeiv2_driver* d = gsl_odeiv2_driver_alloc_y_new(&sys,
      gsl_odeiv2_step_rk8pd, dr_start, eps_abs, eps_rel);

  // TODO -- clean all this up
  const double& qe = PhysicalConstantsCGS::ElectronCharge;
  double r = r_init;
  double solution[2] = {qe*e.Z + r_init*dv0, dv0};

  // TODO: fix units. too many quanities: solution / chi / xi / ...
  std::vector<double> radii, potentials;
  radii.push_back(r_init);
  potentials.push_back(qe*solution[0]/r_init);

  const int numsteps = 1000;
  for (int i=0; i<numsteps; ++i) {
    const double ri = r_init + (i+1)*(r_final-r_init)/numsteps;
    const int status = gsl_odeiv2_driver_apply(d, &r, ri, solution);
    assert(status==GSL_SUCCESS);
    radii.push_back(ri);
    potentials.push_back(qe*solution[0]/ri);
    if (solution[0] <= 0 or (solution[1]-solution[0])/ri > 0) break;
  }

  gsl_odeiv2_driver_free(d);
  return RadialFunction(radii, potentials);
}

double TFDH::findPotentialRoot(const Element& e, const PlasmaState& p,
    const double r_init, const double r_final)
{
  // find interval that brackets correct potential
  double v_low = 0;
  double v_high = 0;
  {
    bool success = false;
    const double v_step = 100.0;
    const int bracket_attempts = 100;
    for (int i=0; i<bracket_attempts; ++i) {
      const auto& rf = integrateODE(e, p, r_init, r_final, v_low);
      if (rf.data.back() < 0.0) {
        success = true;
        break;
      }
      v_high = v_low;
      v_low -= v_step;
    }
    assert(success and "failed to bracket potential root");
  }

  // find "root" within this bracket
  // we aren't looking for a traditional root, just the boundary between
  // potentials that diverge to +infty or -infty... so do something simple
  double v_mid = 0.0;
  {
    bool success = false;
    const int root_attempts = 100;
    for (int i=0; i<root_attempts; ++i) {
      v_mid = (v_low + v_high)/2.0;
      if (v_mid==v_low or v_mid==v_high) { // underflow
        success = true;
        break;
      }

      const auto& rf = integrateODE(e, p, r_init, r_final, v_mid);
      ((rf.data.back() >= 0.0) ? v_high : v_low) = v_mid;
    }
    assert(success and "failed to find potential root within bracket");
  }

  // TODO: return the corresponding RadialFunction, to avoid computing it
  //       a second time!
  return v_mid;
}

double TFDH::boundElectrons(const Element& e, const PlasmaState& p)
{
  const RadialFunction& tfdh = solve(e, p);
  const RadialFunction& neBound = TFDH::neBound(tfdh, p);
  return integrateOverRadius(neBound);
}
<commit_msg>Tfdh: Use lower-level GSL ODE interface<commit_after>
#include "IntegrateTFDH.h"

#include "Element.h"
#include "IntegrateOverRadius.h"
#include "PlasmaFunctions.h"
#include "PlasmaState.h"
#include "PhysicalConstants.h"
#include "RadialFunction.h"
#include "TfdhFunctions.h"

#include <cassert>
#include <cmath>
#include <vector>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_odeiv2.h>

namespace {

  struct TfdhParams {
    const Element& e;
    const PlasmaState& p;
    TfdhParams(const Element& re, const PlasmaState& rp) : e(re), p(rp) {}
  };

  int tfdhOde(double r, const double f[], double dfdr[], void *params) {
    const double& qe = PhysicalConstantsCGS::ElectronCharge;
    const double phi = qe*f[0]/r;
    const PlasmaState& p = static_cast<TfdhParams*>(params)->p;
    const double ne = Plasma::ne(phi, p);
    const double ionChargeDensity = Plasma::totalIonChargeDensity(phi, p);
    dfdr[0] = f[1];
    dfdr[1] = -4.0*M_PI*qe * r * (ionChargeDensity - ne);
    return GSL_SUCCESS;
  }
}

RadialFunction TFDH::solve(const Element& e, const PlasmaState& p)
{
  // set parameters here:
  // TODO: automatic way of tuning the radii?
  const double ri = 1e-14;
  const double rf = 1e-10;

  const double dv0 = findPotentialRoot(e, p, ri, rf);
  return integrateODE(e, p, ri, rf, dv0);
}

RadialFunction TFDH::integrateODE(const Element& e, const PlasmaState& p,
    const double r_init, const double r_final, const double dv0)
{
  TfdhParams params(e,p);
  const size_t dim = 2;
  const double eps_abs = 1e-6;
  const double eps_rel = 0;
  double r = r_init;
  double dr = r_init;
  const double& qe = PhysicalConstantsCGS::ElectronCharge;
  double solution[dim] = {qe*e.Z + r_init*dv0, dv0};

  gsl_odeiv2_step* step = gsl_odeiv2_step_alloc(gsl_odeiv2_step_rk8pd, dim);
  gsl_odeiv2_control* ctrl = gsl_odeiv2_control_y_new(eps_abs, eps_rel);
  gsl_odeiv2_evolve* ev = gsl_odeiv2_evolve_alloc(dim);
  gsl_odeiv2_system sys = {tfdhOde, nullptr, dim, &params};
  // TODO: use c++11 smart pointers, e.g. as below:
  //std::unique_ptr<gsl_odeiv2_driver, void(*) (gsl_odeiv2_driver*)> dd(
  //    gsl_odeiv2_driver_alloc_y_new(&sys, gsl_odeiv2_step_rk8pd, dr_start,
  //      eps_abs, eps_rel),
  //    gsl_odeiv2_driver_free);

  // TODO: fix units. too many quanities: solution / chi / xi / ...
  std::vector<double> radii, potentials;
  radii.push_back(r_init);
  potentials.push_back(qe*solution[0]/r_init);

  while (r < r_final) {
    const int status = gsl_odeiv2_evolve_apply(ev, ctrl, step, &sys, &r, r_final, &dr, solution);
    assert(status==GSL_SUCCESS);
    radii.push_back(r);
    potentials.push_back(qe*solution[0]/r);
    if (solution[0] <= 0 or (solution[1]-solution[0])/r > 0) break;
  }
  assert(r < r_final and "integrated ODE until final radius without terminating!");

  gsl_odeiv2_evolve_free(ev);
  gsl_odeiv2_control_free(ctrl);
  gsl_odeiv2_step_free(step);
  return RadialFunction(radii, potentials);
}

double TFDH::findPotentialRoot(const Element& e, const PlasmaState& p,
    const double r_init, const double r_final)
{
  // find interval that brackets correct potential
  double v_low = 0;
  double v_high = 0;
  {
    bool success = false;
    const double v_step = 100.0;
    const int bracket_attempts = 100;
    for (int i=0; i<bracket_attempts; ++i) {
      const auto& rf = integrateODE(e, p, r_init, r_final, v_low);
      if (rf.data.back() < 0.0) {
        success = true;
        break;
      }
      v_high = v_low;
      v_low -= v_step;
    }
    assert(success and "failed to bracket potential root");
  }

  // find "root" within this bracket
  // we aren't looking for a traditional root, just the boundary between
  // potentials that diverge to +infty or -infty... so do something simple
  double v_mid = 0.0;
  {
    bool success = false;
    const int root_attempts = 100;
    for (int i=0; i<root_attempts; ++i) {
      v_mid = (v_low + v_high)/2.0;
      if (v_mid==v_low or v_mid==v_high) { // underflow
        success = true;
        break;
      }

      const auto& rf = integrateODE(e, p, r_init, r_final, v_mid);
      ((rf.data.back() >= 0.0) ? v_high : v_low) = v_mid;
    }
    assert(success and "failed to find potential root within bracket");
  }

  // TODO: return the corresponding RadialFunction, to avoid computing it
  //       a second time!
  return v_mid;
}

double TFDH::boundElectrons(const Element& e, const PlasmaState& p)
{
  const RadialFunction& tfdh = solve(e, p);
  const RadialFunction& neBound = TFDH::neBound(tfdh, p);
  return integrateOverRadius(neBound);
}
<|endoftext|>


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

namespace hcc {
namespace jack {

namespace {
const std::map<std::string, TokenType> keywordMap = {
    {"class",       TokenType::CLASS},
    {"method",      TokenType::METHOD},
    {"function",    TokenType::FUNCTION},
    {"constructor", TokenType::CONSTRUCTOR},
    {"int",         TokenType::INT},
    {"boolean",     TokenType::BOOLEAN},
    {"char",        TokenType::CHAR},
    {"void",        TokenType::VOID},
    {"var",         TokenType::VAR},
    {"static",      TokenType::STATIC},
    {"field",       TokenType::FIELD},
    {"let",         TokenType::LET},
    {"do",          TokenType::DO},
    {"if",          TokenType::IF},
    {"else",        TokenType::ELSE},
    {"while",       TokenType::WHILE},
    {"return",      TokenType::RETURN},
    {"true",        TokenType::TRUE},
    {"false",       TokenType::FALSE},
    {"null",        TokenType::NULL_},
    {"this",        TokenType::THIS}
};
const std::map<char, TokenType> punctuationMap = {
    {'&',   TokenType::AMPERSAND},
    {'(',   TokenType::PARENTHESIS_LEFT},
    {')',   TokenType::PARENTHESIS_RIGHT},
    {'*',   TokenType::ASTERISK},
    {'+',   TokenType::PLUS_SIGN},
    {',',   TokenType::COMMA},
    {'-',   TokenType::MINUS_SIGN},
    {'.',   TokenType::DOT},
    // slash is intentionally left out
    {';',   TokenType::SEMICOLON},
    {'<',   TokenType::LESS_THAN_SIGN},
    {'=',   TokenType::EQUALS_SIGN},
    {'>',   TokenType::GREATER_THAN_SIGN},
    {'[',   TokenType::BRACKET_LEFT},
    {']',   TokenType::BRACKET_RIGHT},
    {'{',   TokenType::BRACE_LEFT},
    {'|',   TokenType::VERTICAL_BAR},
    {'}',   TokenType::BRACE_RIGHT},
    {'~',   TokenType::TILDE}
};
const std::map<TokenType, std::string> tokenTypeToString = {
    // keyword
    {TokenType::CLASS,              "keyword 'class'"},
    {TokenType::METHOD,             "keyword 'method'"},
    {TokenType::FUNCTION,           "keyword 'function'"},
    {TokenType::CONSTRUCTOR,        "keyword 'constructor'"},
    {TokenType::INT,                "keyword 'int'"},
    {TokenType::BOOLEAN,            "keyword 'boolean'"},
    {TokenType::CHAR,               "keyword 'char'"},
    {TokenType::VOID,               "keyword 'void'"},
    {TokenType::VAR,                "keyword 'var'"},
    {TokenType::STATIC,             "keyword 'static'"},
    {TokenType::FIELD,              "keyword 'field'"},
    {TokenType::LET,                "keyword 'let'"},
    {TokenType::DO,                 "keyword 'do'"},
    {TokenType::IF,                 "keyword 'if'"},
    {TokenType::ELSE,               "keyword 'else'"},
    {TokenType::WHILE,              "keyword 'while'"},
    {TokenType::RETURN,             "keyword 'return'"},
    {TokenType::TRUE,               "keyword 'true'"},
    {TokenType::FALSE,              "keyword 'false'"},
    {TokenType::NULL_,              "keyword 'null'"},
    {TokenType::THIS,               "keyword 'this'"},
    // punctuation
    {TokenType::AMPERSAND,          "'&'"},
    {TokenType::PARENTHESIS_LEFT,   "'('"},
    {TokenType::PARENTHESIS_RIGHT,  "')'"},
    {TokenType::ASTERISK,           "'*'"},
    {TokenType::PLUS_SIGN,          "'+'"},
    {TokenType::COMMA,              "','"},
    {TokenType::MINUS_SIGN,         "'-'"},
    {TokenType::DOT,                "'.'"},
    {TokenType::SLASH,              "'/'"},
    {TokenType::SEMICOLON,          "';'"},
    {TokenType::LESS_THAN_SIGN,     "'<'"},
    {TokenType::EQUALS_SIGN,        "'='"},
    {TokenType::GREATER_THAN_SIGN,  "'>'"},
    {TokenType::BRACKET_LEFT,       "'['"},
    {TokenType::BRACKET_RIGHT,      "']'"},
    {TokenType::BRACE_LEFT,         "'{'"},
    {TokenType::VERTICAL_BAR,       "'|'"},
    {TokenType::BRACE_RIGHT,        "'}'"},
    {TokenType::TILDE,              "'~'"},
    // rest
    {TokenType::IDENTIFIER,         "identifier"},
    {TokenType::INT_CONST,          "integer constant"},
    {TokenType::STRING_CONST,       "string constant"},
    {TokenType::EOF_,               "end of file"},
    {TokenType::STRAY_CHARACTER,    "stray character"}
};
} // end anonymous namespace

std::ostream& operator<<(std::ostream& os, const TokenType& tt)
{
    auto string = tokenTypeToString.find(tt);
    if (string != tokenTypeToString.end()) {
        os << string->second;
        return os;
    }
    throw std::runtime_error("Assertion failed");
}

Tokenizer::Tokenizer(std::basic_istream<char>& is)
    : current(is)
    , line(1)
    , column(0)
{}

TokenType Tokenizer::_advance()
{
    enum class State {
        START,
        SLASH,
        COMMENT_ONELINE,
        COMMENT_MULTILINE,
        COMMENT_MULTILINE_END,
        STRING,
        NUMBER,
        IDENTIFIER
    };
    State state = State::START;

    string = "";

    while (true) {
        char c;
        if (previousChar) {
            c = *previousChar;
            previousChar.reset();
        } else if (current != last) {
            c = *current++;
        } else {
            return TokenType::EOF_;
        }

        if (c == '\n') {
            column = 0;
            ++line;
        } else {
            ++column;
        }

        switch (state) {
        case State::START:
            if (c == '/') {
                state = State::SLASH;
            } else if (c == '"') {
                state = State::STRING;
            } else if (isdigit(c)) {
                intConstant = c - '0';
                state = State::NUMBER;
            } else if (isalpha(c)) {
                string += c;
                state = State::IDENTIFIER;
            } else if (isspace(c)) {
                // do nothing
            } else {
                auto it = punctuationMap.find(c);
                return (it != punctuationMap.end()) ? it->second : TokenType::STRAY_CHARACTER;
            }
            break;
        case State::SLASH:
            if (c == '/') {
                state = State::COMMENT_ONELINE;
            } else if (c == '*') {
                state = State::COMMENT_MULTILINE;
            } else {
                previousChar = c;

                return TokenType::SLASH;
            }
            break;
        case State::COMMENT_ONELINE:
            state = (c == '\n') ? State::START : State::COMMENT_ONELINE;
            break;
        case State::COMMENT_MULTILINE:
            state = (c == '*') ? State::COMMENT_MULTILINE_END : State::COMMENT_MULTILINE;
            break;
        case State::COMMENT_MULTILINE_END:
            state = (c == '/') ? State::START : State::COMMENT_MULTILINE;
            break;
        case State::STRING:
            if (c == '"') {
                return TokenType::STRING_CONST;
            } else {
                string += c;
            }
            break;
        case State::NUMBER:
            if (isdigit(c)) {
                intConstant = 10*intConstant + (c - '0');
            } else {
                previousChar = c;
                return TokenType::INT_CONST;
            }
            break;
        case State::IDENTIFIER:
            if (isalnum(c)) {
                string += c;
            } else {
                previousChar = c;
                auto kw = keywordMap.find(string);
                return (kw != keywordMap.end()) ? kw->second : TokenType::IDENTIFIER;
            }
            break;
        }
    }
}

} // end namespace jack
} // end namespace hcc
<commit_msg>Jack tokenizer correctly handles '_' character<commit_after>/*
 * Copyright (c) 2012-2013 Dano Pernis
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
#include "JackTokenizer.h"
#include <iostream>
#include <stdexcept>
#include <cctype>

namespace hcc {
namespace jack {

namespace {
const std::map<std::string, TokenType> keywordMap = {
    {"class",       TokenType::CLASS},
    {"method",      TokenType::METHOD},
    {"function",    TokenType::FUNCTION},
    {"constructor", TokenType::CONSTRUCTOR},
    {"int",         TokenType::INT},
    {"boolean",     TokenType::BOOLEAN},
    {"char",        TokenType::CHAR},
    {"void",        TokenType::VOID},
    {"var",         TokenType::VAR},
    {"static",      TokenType::STATIC},
    {"field",       TokenType::FIELD},
    {"let",         TokenType::LET},
    {"do",          TokenType::DO},
    {"if",          TokenType::IF},
    {"else",        TokenType::ELSE},
    {"while",       TokenType::WHILE},
    {"return",      TokenType::RETURN},
    {"true",        TokenType::TRUE},
    {"false",       TokenType::FALSE},
    {"null",        TokenType::NULL_},
    {"this",        TokenType::THIS}
};
const std::map<char, TokenType> punctuationMap = {
    {'&',   TokenType::AMPERSAND},
    {'(',   TokenType::PARENTHESIS_LEFT},
    {')',   TokenType::PARENTHESIS_RIGHT},
    {'*',   TokenType::ASTERISK},
    {'+',   TokenType::PLUS_SIGN},
    {',',   TokenType::COMMA},
    {'-',   TokenType::MINUS_SIGN},
    {'.',   TokenType::DOT},
    // slash is intentionally left out
    {';',   TokenType::SEMICOLON},
    {'<',   TokenType::LESS_THAN_SIGN},
    {'=',   TokenType::EQUALS_SIGN},
    {'>',   TokenType::GREATER_THAN_SIGN},
    {'[',   TokenType::BRACKET_LEFT},
    {']',   TokenType::BRACKET_RIGHT},
    {'{',   TokenType::BRACE_LEFT},
    {'|',   TokenType::VERTICAL_BAR},
    {'}',   TokenType::BRACE_RIGHT},
    {'~',   TokenType::TILDE}
};
const std::map<TokenType, std::string> tokenTypeToString = {
    // keyword
    {TokenType::CLASS,              "keyword 'class'"},
    {TokenType::METHOD,             "keyword 'method'"},
    {TokenType::FUNCTION,           "keyword 'function'"},
    {TokenType::CONSTRUCTOR,        "keyword 'constructor'"},
    {TokenType::INT,                "keyword 'int'"},
    {TokenType::BOOLEAN,            "keyword 'boolean'"},
    {TokenType::CHAR,               "keyword 'char'"},
    {TokenType::VOID,               "keyword 'void'"},
    {TokenType::VAR,                "keyword 'var'"},
    {TokenType::STATIC,             "keyword 'static'"},
    {TokenType::FIELD,              "keyword 'field'"},
    {TokenType::LET,                "keyword 'let'"},
    {TokenType::DO,                 "keyword 'do'"},
    {TokenType::IF,                 "keyword 'if'"},
    {TokenType::ELSE,               "keyword 'else'"},
    {TokenType::WHILE,              "keyword 'while'"},
    {TokenType::RETURN,             "keyword 'return'"},
    {TokenType::TRUE,               "keyword 'true'"},
    {TokenType::FALSE,              "keyword 'false'"},
    {TokenType::NULL_,              "keyword 'null'"},
    {TokenType::THIS,               "keyword 'this'"},
    // punctuation
    {TokenType::AMPERSAND,          "'&'"},
    {TokenType::PARENTHESIS_LEFT,   "'('"},
    {TokenType::PARENTHESIS_RIGHT,  "')'"},
    {TokenType::ASTERISK,           "'*'"},
    {TokenType::PLUS_SIGN,          "'+'"},
    {TokenType::COMMA,              "','"},
    {TokenType::MINUS_SIGN,         "'-'"},
    {TokenType::DOT,                "'.'"},
    {TokenType::SLASH,              "'/'"},
    {TokenType::SEMICOLON,          "';'"},
    {TokenType::LESS_THAN_SIGN,     "'<'"},
    {TokenType::EQUALS_SIGN,        "'='"},
    {TokenType::GREATER_THAN_SIGN,  "'>'"},
    {TokenType::BRACKET_LEFT,       "'['"},
    {TokenType::BRACKET_RIGHT,      "']'"},
    {TokenType::BRACE_LEFT,         "'{'"},
    {TokenType::VERTICAL_BAR,       "'|'"},
    {TokenType::BRACE_RIGHT,        "'}'"},
    {TokenType::TILDE,              "'~'"},
    // rest
    {TokenType::IDENTIFIER,         "identifier"},
    {TokenType::INT_CONST,          "integer constant"},
    {TokenType::STRING_CONST,       "string constant"},
    {TokenType::EOF_,               "end of file"},
    {TokenType::STRAY_CHARACTER,    "stray character"}
};
} // end anonymous namespace

std::ostream& operator<<(std::ostream& os, const TokenType& tt)
{
    auto string = tokenTypeToString.find(tt);
    if (string != tokenTypeToString.end()) {
        os << string->second;
        return os;
    }
    throw std::runtime_error("Assertion failed");
}

Tokenizer::Tokenizer(std::basic_istream<char>& is)
    : current(is)
    , line(1)
    , column(0)
{}

TokenType Tokenizer::_advance()
{
    enum class State {
        START,
        SLASH,
        COMMENT_ONELINE,
        COMMENT_MULTILINE,
        COMMENT_MULTILINE_END,
        STRING,
        NUMBER,
        IDENTIFIER
    };
    State state = State::START;

    string = "";

    while (true) {
        char c;
        if (previousChar) {
            c = *previousChar;
            previousChar.reset();
        } else if (current != last) {
            c = *current++;
        } else {
            return TokenType::EOF_;
        }

        if (c == '\n') {
            column = 0;
            ++line;
        } else {
            ++column;
        }

        switch (state) {
        case State::START:
            if (c == '/') {
                state = State::SLASH;
            } else if (c == '"') {
                state = State::STRING;
            } else if (isdigit(c)) {
                intConstant = c - '0';
                state = State::NUMBER;
            } else if (isalpha(c) || c == '_') {
                string += c;
                state = State::IDENTIFIER;
            } else if (isspace(c)) {
                // do nothing
            } else {
                auto it = punctuationMap.find(c);
                return (it != punctuationMap.end()) ? it->second : TokenType::STRAY_CHARACTER;
            }
            break;
        case State::SLASH:
            if (c == '/') {
                state = State::COMMENT_ONELINE;
            } else if (c == '*') {
                state = State::COMMENT_MULTILINE;
            } else {
                previousChar = c;

                return TokenType::SLASH;
            }
            break;
        case State::COMMENT_ONELINE:
            state = (c == '\n') ? State::START : State::COMMENT_ONELINE;
            break;
        case State::COMMENT_MULTILINE:
            state = (c == '*') ? State::COMMENT_MULTILINE_END : State::COMMENT_MULTILINE;
            break;
        case State::COMMENT_MULTILINE_END:
            state = (c == '/') ? State::START : State::COMMENT_MULTILINE;
            break;
        case State::STRING:
            if (c == '"') {
                return TokenType::STRING_CONST;
            } else {
                string += c;
            }
            break;
        case State::NUMBER:
            if (isdigit(c)) {
                intConstant = 10*intConstant + (c - '0');
            } else {
                previousChar = c;
                return TokenType::INT_CONST;
            }
            break;
        case State::IDENTIFIER:
            if (isalnum(c) || c == '_') {
                string += c;
            } else {
                previousChar = c;
                auto kw = keywordMap.find(string);
                return (kw != keywordMap.end()) ? kw->second : TokenType::IDENTIFIER;
            }
            break;
        }
    }
}

} // end namespace jack
} // end namespace hcc
<|endoftext|>


<commit_before>#include <unicode/strenum.h>
#include <unicode/timezone.h>
#include <unicode/unistr.h>

#include <cppunit/extensions/HelperMacros.h>

#include "cppunit/BetterAssert.h"
#include "l10n/IcuTimeZoneImpl.h"

using namespace std;
using namespace Poco;

namespace BeeeOn {

class IcuTimeZoneImplTest : public CppUnit::TestFixture {
	CPPUNIT_TEST_SUITE(IcuTimeZoneImplTest);
	CPPUNIT_TEST(testPrague);
	CPPUNIT_TEST(testLondon);
	CPPUNIT_TEST(testSpecificID);
	CPPUNIT_TEST(testCETByOffset);
	CPPUNIT_TEST(testEETByOffset);
	CPPUNIT_TEST(testZuluByOffset);
	CPPUNIT_TEST(testUTCm06ByOffset);
	CPPUNIT_TEST_SUITE_END();

public:
	void testPrague();
	void testLondon();
	void testSpecificID();
	void testCETByOffset();
	void testEETByOffset();
	void testZuluByOffset();
	void testUTCm06ByOffset();

private:
	SharedPtr<icu::TimeZone> byID(const string &id);
	SharedPtr<icu::TimeZone> byOffset(const int32_t rawOffset);
};

CPPUNIT_TEST_SUITE_REGISTRATION(IcuTimeZoneImplTest);

SharedPtr<icu::TimeZone> IcuTimeZoneImplTest::byID(const string &id)
{
	icu::UnicodeString unicodeID(id.c_str(), id.size());
	return icu::TimeZone::createTimeZone(unicodeID);
}

void IcuTimeZoneImplTest::testPrague()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	const IcuTimeZoneImpl zone(byID("Europe/Prague"));

	CPPUNIT_ASSERT_EQUAL("Europe/Prague", zone.id());

	CPPUNIT_ASSERT_EQUAL(1, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+02:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"Europe/Prague (GMT+01:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"Europe/Prague (GMT+02:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

void IcuTimeZoneImplTest::testLondon()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	const IcuTimeZoneImpl zone(byID("Europe/London"));

	CPPUNIT_ASSERT_EQUAL("Europe/London", zone.id());

	CPPUNIT_ASSERT_EQUAL(0, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"Europe/London (GMT)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"Europe/London (GMT+01:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

/**
 * Test GMT+01:00 specific time zones. Thowse zones are low-level and the DST
 * does not applies to them.
 */
void IcuTimeZoneImplTest::testSpecificID()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	const IcuTimeZoneImpl zone(byID("GMT+01:00"));

	CPPUNIT_ASSERT_EQUAL("GMT+01:00", zone.id());

	CPPUNIT_ASSERT_EQUAL(1, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

SharedPtr<icu::TimeZone> IcuTimeZoneImplTest::byOffset(const int32_t rawOffset)
{
	UErrorCode error = U_ZERO_ERROR;

	SharedPtr<icu::StringEnumeration> e =
		icu::TimeZone::createTimeZoneIDEnumeration(
			UCAL_ZONE_TYPE_CANONICAL,
			"001", // world
			&rawOffset,
			error
		);

	CPPUNIT_ASSERT_MESSAGE(u_errorName(error), U_SUCCESS(error));

	const UnicodeString *id;

	UnicodeString unknownID;
	icu::TimeZone::getUnknown().getID(unknownID);

	while ((id = e->snext(error)) != NULL) {
		CPPUNIT_ASSERT_MESSAGE(u_errorName(error), U_SUCCESS(error));

		SharedPtr<icu::TimeZone> impl = icu::TimeZone::createTimeZone(*id);
		UnicodeString tmp;

		if (impl->getID(tmp) == unknownID)
			continue; // skip unknown ID, should not happen here

		return impl;
	}

	return nullptr;
}

void IcuTimeZoneImplTest::testCETByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(1 * 60 * 60 * 1000));

	CPPUNIT_ASSERT_EQUAL("CET", zone.id());

	CPPUNIT_ASSERT_EQUAL(1, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+02:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"CET (GMT+01:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"CET (GMT+02:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

void IcuTimeZoneImplTest::testEETByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(2 * 60 * 60 * 1000));

	CPPUNIT_ASSERT_EQUAL("EET", zone.id());

	CPPUNIT_ASSERT_EQUAL(2, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+02:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+03:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"EET (GMT+02:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"EET (GMT+03:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

void IcuTimeZoneImplTest::testZuluByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(0));

	CPPUNIT_ASSERT_EQUAL("Etc/GMT", zone.id());

	CPPUNIT_ASSERT_EQUAL(0, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(0, zone.dstOffset().hours());
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	const string name_12_24 = zone.displayName(Locale::system(), T2017_12_24);
	const string name_06_24 = zone.displayName(Locale::system(), T2017_06_24);

	CPPUNIT_ASSERT(
		"Greenwich Mean Time (GMT)" == name_12_24
		|| "Etc/GMT (GMT)" == name_12_24);
	CPPUNIT_ASSERT(
		"Greenwich Mean Time (GMT)" == name_06_24
		|| "Etc/GMT (GMT)" == name_06_24);
}

void IcuTimeZoneImplTest::testUTCm06ByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(-6 * 60 * 60 * 1000));

	CPPUNIT_ASSERT_EQUAL("CST6CDT", zone.id());

	CPPUNIT_ASSERT_EQUAL(-6, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT-06:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT-05:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"Central Standard Time (GMT-06:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"Central Daylight Time (GMT-05:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

}
<commit_msg>IcuTimeZoneImplTest: refer to UnicodeString with prefix 'icu::'<commit_after>#include <unicode/strenum.h>
#include <unicode/timezone.h>
#include <unicode/unistr.h>

#include <cppunit/extensions/HelperMacros.h>

#include "cppunit/BetterAssert.h"
#include "l10n/IcuTimeZoneImpl.h"

using namespace std;
using namespace Poco;

namespace BeeeOn {

class IcuTimeZoneImplTest : public CppUnit::TestFixture {
	CPPUNIT_TEST_SUITE(IcuTimeZoneImplTest);
	CPPUNIT_TEST(testPrague);
	CPPUNIT_TEST(testLondon);
	CPPUNIT_TEST(testSpecificID);
	CPPUNIT_TEST(testCETByOffset);
	CPPUNIT_TEST(testEETByOffset);
	CPPUNIT_TEST(testZuluByOffset);
	CPPUNIT_TEST(testUTCm06ByOffset);
	CPPUNIT_TEST_SUITE_END();

public:
	void testPrague();
	void testLondon();
	void testSpecificID();
	void testCETByOffset();
	void testEETByOffset();
	void testZuluByOffset();
	void testUTCm06ByOffset();

private:
	SharedPtr<icu::TimeZone> byID(const string &id);
	SharedPtr<icu::TimeZone> byOffset(const int32_t rawOffset);
};

CPPUNIT_TEST_SUITE_REGISTRATION(IcuTimeZoneImplTest);

SharedPtr<icu::TimeZone> IcuTimeZoneImplTest::byID(const string &id)
{
	icu::UnicodeString unicodeID(id.c_str(), id.size());
	return icu::TimeZone::createTimeZone(unicodeID);
}

void IcuTimeZoneImplTest::testPrague()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	const IcuTimeZoneImpl zone(byID("Europe/Prague"));

	CPPUNIT_ASSERT_EQUAL("Europe/Prague", zone.id());

	CPPUNIT_ASSERT_EQUAL(1, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+02:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"Europe/Prague (GMT+01:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"Europe/Prague (GMT+02:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

void IcuTimeZoneImplTest::testLondon()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	const IcuTimeZoneImpl zone(byID("Europe/London"));

	CPPUNIT_ASSERT_EQUAL("Europe/London", zone.id());

	CPPUNIT_ASSERT_EQUAL(0, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"Europe/London (GMT)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"Europe/London (GMT+01:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

/**
 * Test GMT+01:00 specific time zones. Thowse zones are low-level and the DST
 * does not applies to them.
 */
void IcuTimeZoneImplTest::testSpecificID()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	const IcuTimeZoneImpl zone(byID("GMT+01:00"));

	CPPUNIT_ASSERT_EQUAL("GMT+01:00", zone.id());

	CPPUNIT_ASSERT_EQUAL(1, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

SharedPtr<icu::TimeZone> IcuTimeZoneImplTest::byOffset(const int32_t rawOffset)
{
	UErrorCode error = U_ZERO_ERROR;

	SharedPtr<icu::StringEnumeration> e =
		icu::TimeZone::createTimeZoneIDEnumeration(
			UCAL_ZONE_TYPE_CANONICAL,
			"001", // world
			&rawOffset,
			error
		);

	CPPUNIT_ASSERT_MESSAGE(u_errorName(error), U_SUCCESS(error));

	const icu::UnicodeString *id;

	icu::UnicodeString unknownID;
	icu::TimeZone::getUnknown().getID(unknownID);

	while ((id = e->snext(error)) != NULL) {
		CPPUNIT_ASSERT_MESSAGE(u_errorName(error), U_SUCCESS(error));

		SharedPtr<icu::TimeZone> impl = icu::TimeZone::createTimeZone(*id);
		icu::UnicodeString tmp;

		if (impl->getID(tmp) == unknownID)
			continue; // skip unknown ID, should not happen here

		return impl;
	}

	return nullptr;
}

void IcuTimeZoneImplTest::testCETByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(1 * 60 * 60 * 1000));

	CPPUNIT_ASSERT_EQUAL("CET", zone.id());

	CPPUNIT_ASSERT_EQUAL(1, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+01:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+02:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"CET (GMT+01:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"CET (GMT+02:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

void IcuTimeZoneImplTest::testEETByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(2 * 60 * 60 * 1000));

	CPPUNIT_ASSERT_EQUAL("EET", zone.id());

	CPPUNIT_ASSERT_EQUAL(2, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT+02:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT+03:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"EET (GMT+02:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"EET (GMT+03:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

void IcuTimeZoneImplTest::testZuluByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(0));

	CPPUNIT_ASSERT_EQUAL("Etc/GMT", zone.id());

	CPPUNIT_ASSERT_EQUAL(0, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(0, zone.dstOffset().hours());
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	const string name_12_24 = zone.displayName(Locale::system(), T2017_12_24);
	const string name_06_24 = zone.displayName(Locale::system(), T2017_06_24);

	CPPUNIT_ASSERT(
		"Greenwich Mean Time (GMT)" == name_12_24
		|| "Etc/GMT (GMT)" == name_12_24);
	CPPUNIT_ASSERT(
		"Greenwich Mean Time (GMT)" == name_06_24
		|| "Etc/GMT (GMT)" == name_06_24);
}

void IcuTimeZoneImplTest::testUTCm06ByOffset()
{
	static const Timestamp T2017_06_24 = Timestamp::fromEpochTime(1498255200);
	static const Timestamp T2017_12_24 = Timestamp::fromEpochTime(1514070000);

	IcuTimeZoneImpl zone(byOffset(-6 * 60 * 60 * 1000));

	CPPUNIT_ASSERT_EQUAL("CST6CDT", zone.id());

	CPPUNIT_ASSERT_EQUAL(-6, zone.utcOffset().hours());
	CPPUNIT_ASSERT_EQUAL(1, zone.dstOffset().hours());
	CPPUNIT_ASSERT(zone.appliesDST(T2017_06_24));
	CPPUNIT_ASSERT(!zone.appliesDST(T2017_12_24));

	CPPUNIT_ASSERT_EQUAL(
		"GMT-06:00",
		zone.shortName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"GMT-05:00",
		zone.shortName(Locale::system(), T2017_06_24)
	);

	CPPUNIT_ASSERT_EQUAL(
		"Central Standard Time (GMT-06:00)",
		zone.displayName(Locale::system(), T2017_12_24)
	);
	CPPUNIT_ASSERT_EQUAL(
		"Central Daylight Time (GMT-05:00)",
		zone.displayName(Locale::system(), T2017_06_24)
	);
}

}
<|endoftext|>


<commit_before>#include "MissingNumber.hpp"

int MissingNumber::missingNumber(vector<int> &nums) {
    int missing = nums.size();

    for (int i = 0; i < nums.size(); i++) {
        int target = nums[i];

        // place target to the right place
        while (target != i && target != nums.size())
            swap(nums[target], target);

        if (target == nums.size()) {
            missing = i;
            nums[i] = nums.size();
        }
    }

    return missing;
}
<commit_msg>Refine Problem 268. Missing Number<commit_after>#include "MissingNumber.hpp"

int MissingNumber::missingNumber(vector<int> &nums) {
    int n = nums.size();

    for (int i = 0; i < n; i++) {
        int t = nums[i];
        while (t < n && nums[t] != t) {
            int nt = nums[t];
            nums[t] = t;
            t = nt;
        }
    }

    for (int i = 0; i < n; i++)
        if (nums[i] != i)
            return i;

    return n;
}
<|endoftext|>


<commit_before>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "Villager.h"
#include "../World.h"
#include "../BlockArea.h"
#include "../Blocks/BlockHandler.h"
#include "../BlockInServerPluginInterface.h"

cVillager::cVillager(eVillagerType VillagerType) :
	super("Villager", mtVillager, "", "", 0.6, 1.8),
	m_ActionCountDown(-1),
	m_Type(VillagerType),
	m_VillagerAction(false)
{
}

bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
{
	if (!super::DoTakeDamage(a_TDI))
	{
		return false;
	}

	if ((a_TDI.Attacker != NULL) && a_TDI.Attacker->IsPlayer())
	{
		if (m_World->GetTickRandomNumber(5) == 3)
		{
			m_World->BroadcastEntityStatus(*this, esVillagerAngry);
		}
	}
	return true;
}

void cVillager::Tick(float a_Dt, cChunk & a_Chunk)
{
	super::Tick(a_Dt, a_Chunk);

	if (m_ActionCountDown > -1)
	{
		m_ActionCountDown--;
		if (m_ActionCountDown == 0)
		{
			switch (m_Type)
			{
				case vtFarmer:
				{
					HandleFarmerPlaceCrops();
				}
			}
		}
		return;
	}

	if (m_VillagerAction)
	{
		switch (m_Type)
		{
			case vtFarmer:
			{
				HandleFarmerTryHarvestCrops();
			}
		}
		m_VillagerAction = false;
		return;
	}

	// Don't always try to do a special action. Each tick has 1% to do a special action.
	if (m_World->GetTickRandomNumber(99) != 0)
	{
		return;
	}

	switch (m_Type)
	{
		case vtFarmer:
		{
			HandleFarmerPrepareFarmCrops();
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Farmer functions.
void cVillager::HandleFarmerPrepareFarmCrops()
{
	if (!m_World->VillagersShouldHarvestCrops())
	{
		return;
	}

	cBlockArea Surrounding;
	/// Read a 11x7x11 area.
	Surrounding.Read(
		m_World,
		(int) GetPosX() - 5,
		(int) GetPosX() + 5,
		(int) GetPosY() - 3,
		(int) GetPosY() + 3,
		(int) GetPosZ() - 5,
		(int) GetPosZ() + 5
	);

	for (int I = 0; I < 5; I++)
	{
		for (int Y = 0; Y < 6; Y++)
		{
			// Pick random coordinates and check for crops.
			int X = m_World->GetTickRandomNumber(11);
			int Z = m_World->GetTickRandomNumber(11);

			// A villager can't farm this.
			if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z)))
			{
				continue;
			}
			if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7)
			{
				continue;
			}

			m_VillagerAction = true;
			m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5);
			MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5)));
			return;
		}  // for Y loop.
	}  // Repeat the procces 5 times.
}

void cVillager::HandleFarmerTryHarvestCrops()
{
	// Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks.
	if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2)
	{
		// Check if the blocks didn't change while the villager was walking to the coordinates.
		BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z);
		if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7)
		{
			cBlockHandler * Handler = cBlockInfo::GetHandler(CropBlock);
			cChunkInterface ChunkInterface(m_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*m_World);
			Handler->DropBlock(ChunkInterface, *m_World, PluginInterface, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z);
			m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0);
			m_ActionCountDown = 20;
		}
	}
}

void cVillager::HandleFarmerPlaceCrops()
{
	// Check if there is still farmland at the spot where the crops were.
	if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND)
	{
		m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0);
	}
}

bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_CROPS:
		case E_BLOCK_POTATOES:
		case E_BLOCK_CARROTS:
		{
			return true;
		}
	}
	return false;
}

<commit_msg>Fixed wrong Surrounding size<commit_after>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "Villager.h"
#include "../World.h"
#include "../BlockArea.h"
#include "../Blocks/BlockHandler.h"
#include "../BlockInServerPluginInterface.h"

cVillager::cVillager(eVillagerType VillagerType) :
	super("Villager", mtVillager, "", "", 0.6, 1.8),
	m_ActionCountDown(-1),
	m_Type(VillagerType),
	m_VillagerAction(false)
{
}

bool cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
{
	if (!super::DoTakeDamage(a_TDI))
	{
		return false;
	}

	if ((a_TDI.Attacker != NULL) && a_TDI.Attacker->IsPlayer())
	{
		if (m_World->GetTickRandomNumber(5) == 3)
		{
			m_World->BroadcastEntityStatus(*this, esVillagerAngry);
		}
	}
	return true;
}

void cVillager::Tick(float a_Dt, cChunk & a_Chunk)
{
	super::Tick(a_Dt, a_Chunk);

	if (m_ActionCountDown > -1)
	{
		m_ActionCountDown--;
		if (m_ActionCountDown == 0)
		{
			switch (m_Type)
			{
				case vtFarmer:
				{
					HandleFarmerPlaceCrops();
				}
			}
		}
		return;
	}

	if (m_VillagerAction)
	{
		switch (m_Type)
		{
			case vtFarmer:
			{
				HandleFarmerTryHarvestCrops();
			}
		}
		m_VillagerAction = false;
		return;
	}

	// Don't always try to do a special action. Each tick has 1% to do a special action.
	if (m_World->GetTickRandomNumber(99) != 0)
	{
		return;
	}

	switch (m_Type)
	{
		case vtFarmer:
		{
			HandleFarmerPrepareFarmCrops();
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Farmer functions.
void cVillager::HandleFarmerPrepareFarmCrops()
{
	if (!m_World->VillagersShouldHarvestCrops())
	{
		return;
	}

	cBlockArea Surrounding;
	/// Read a 11x7x11 area.
	Surrounding.Read(
		m_World,
		(int) GetPosX() - 5,
		(int) GetPosX() + 6,
		(int) GetPosY() - 3,
		(int) GetPosY() + 4,
		(int) GetPosZ() - 5,
		(int) GetPosZ() + 6
	);

	for (int I = 0; I < 5; I++)
	{
		for (int Y = 0; Y < 6; Y++)
		{
			// Pick random coordinates and check for crops.
			int X = m_World->GetTickRandomNumber(11);
			int Z = m_World->GetTickRandomNumber(11);

			// A villager can't farm this.
			if (!IsBlockFarmable(Surrounding.GetRelBlockType(X, Y, Z)))
			{
				continue;
			}
			if (Surrounding.GetRelBlockMeta(X, Y, Z) != 0x7)
			{
				continue;
			}

			m_VillagerAction = true;
			m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5);
			MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5)));
			return;
		}  // for Y loop.
	}  // Repeat the procces 5 times.
}

void cVillager::HandleFarmerTryHarvestCrops()
{
	// Harvest the crops if the villager isn't moving and if the crops are closer then 2 blocks.
	if (!m_bMovingToDestination && (GetPosition() - m_CropsPos).Length() < 2)
	{
		// Check if the blocks didn't change while the villager was walking to the coordinates.
		BLOCKTYPE CropBlock = m_World->GetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z);
		if (IsBlockFarmable(CropBlock) && m_World->GetBlockMeta(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z) == 0x7)
		{
			cBlockHandler * Handler = cBlockInfo::GetHandler(CropBlock);
			cChunkInterface ChunkInterface(m_World->GetChunkMap());
			cBlockInServerPluginInterface PluginInterface(*m_World);
			Handler->DropBlock(ChunkInterface, *m_World, PluginInterface, this, m_CropsPos.x, m_CropsPos.y, m_CropsPos.z);
			m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_AIR, 0);
			m_ActionCountDown = 20;
		}
	}
}

void cVillager::HandleFarmerPlaceCrops()
{
	// Check if there is still farmland at the spot where the crops were.
	if (m_World->GetBlock(m_CropsPos.x, m_CropsPos.y - 1, m_CropsPos.z) == E_BLOCK_FARMLAND)
	{
		m_World->SetBlock(m_CropsPos.x, m_CropsPos.y, m_CropsPos.z, E_BLOCK_CROPS, 0);
	}
}

bool cVillager::IsBlockFarmable(BLOCKTYPE a_BlockType)
{
	switch (a_BlockType)
	{
		case E_BLOCK_CROPS:
		case E_BLOCK_POTATOES:
		case E_BLOCK_CARROTS:
		{
			return true;
		}
	}
	return false;
}

<|endoftext|>


<commit_before>/*!
 * \file
 * \brief A Module is an abstract concept. Basically, all the objects used in a Simulation are a Module.
 *
 * \section LICENSE
 * This file is under MIT license (https://opensource.org/licenses/MIT).
 */
#ifndef MODULE_HPP_
#define MODULE_HPP_

#include <string>
#include <cassert>

/*!
 * \class Module
 *
 * \brief A Module is an abstract concept. Basically, all the objects used in a Simulation are a Module.
 */
class Module
{
protected:
	int         n_frames; /*!< Number of frames to process in this Module */
	std::string name;     /*!< Name of the Module. */

public:
	/*!
	 * \brief Constructor.
	 *
	 * \param n_frames: number of frames to process in this Module.
	 * \param name    : Module's name.
	 */
	Module(const int n_frames = 1, const std::string name = "Module") : n_frames(n_frames), name(name)
	{ assert(n_frames > 0); }

	/*!
	 * \brief Destructor.
	 */
	virtual ~Module() {}

	/*!
	 * \brief Set the number of frames.
	 *
	 * \param n_frames: number of frames to process in this Module.
	 */
	virtual void set_n_frames(const int n_frames)
	{
		assert(n_frames > 0);
		this->n_frames = n_frames;
	}

	/*!
	 * \brief Get the number of frames.
	 *
	 * \return the number of frames to process in this Module.
	 */
	virtual int get_n_frames() const
	{
		return n_frames;
	}

	/*!
	 * \brief Rename the Module.
	 *
	 * \param name: the new Module name.
	 */
	void rename(const std::string name)
	{
		this->name = name;
	}
};

#endif /* MODULE_HPP_ */
<commit_msg>Add the 'aff3ct::' namespace to the 'Module' class.<commit_after>/*!
 * \file
 * \brief A Module is an abstract concept. Basically, all the objects used in a Simulation are a Module.
 *
 * \section LICENSE
 * This file is under MIT license (https://opensource.org/licenses/MIT).
 */
#ifndef MODULE_HPP_
#define MODULE_HPP_

#include <string>
#include <cassert>

namespace aff3ct
{
/*!
 * \class Module
 *
 * \brief A Module is an abstract concept. Basically, all the objects used in a Simulation are a Module.
 */
class Module
{
protected:
	int         n_frames; /*!< Number of frames to process in this Module */
	std::string name;     /*!< Name of the Module. */

public:
	/*!
	 * \brief Constructor.
	 *
	 * \param n_frames: number of frames to process in this Module.
	 * \param name    : Module's name.
	 */
	Module(const int n_frames = 1, const std::string name = "Module") : n_frames(n_frames), name(name)
	{ assert(n_frames > 0); }

	/*!
	 * \brief Destructor.
	 */
	virtual ~Module() {}

	/*!
	 * \brief Set the number of frames.
	 *
	 * \param n_frames: number of frames to process in this Module.
	 */
	virtual void set_n_frames(const int n_frames)
	{
		assert(n_frames > 0);
		this->n_frames = n_frames;
	}

	/*!
	 * \brief Get the number of frames.
	 *
	 * \return the number of frames to process in this Module.
	 */
	virtual int get_n_frames() const
	{
		return n_frames;
	}

	/*!
	 * \brief Rename the Module.
	 *
	 * \param name: the new Module name.
	 */
	void rename(const std::string name)
	{
		this->name = name;
	}
};
}

#endif /* MODULE_HPP_ */
<|endoftext|>


<commit_before>#include <iostream>

#include "../common/timing.h"

int main(int argc, char *argv[]) {
    if (argc != 3) {
        std::cerr << "Usage: \n\t query-index <index> <query-file>" << std::endl;
        exit(EXIT_FAILURE);
    }

    double startTime = getCurrentTime();
    // TODO
    double endTime = getCurrentTime();
    std::cout << "Took " << (endTime - startTime) << "s to execute the queries." << std::endl;
}
<commit_msg>Do pairwise levenshtein on the indexed strings<commit_after>#include <iostream>
#include <fstream>
#include <vector>

#include <libfuzzymatch/levenshtein.h>
#include <libfuzzymatch/util.h>

#include "../common/timing.h"

int main(int argc, char *argv[]) {
    if (argc != 3) {
        std::cerr << "Usage: \n\t query-index <index> <query-file>" << std::endl;
        exit(EXIT_FAILURE);
    }

    std::vector<std::string> queries;
    std::ifstream file(argv[argc - 1]);
    for (std::string line; std::getline(file, line);) {
        queries.push_back(line);
    }
    file.close();

    std::vector<std::vector<uint32_t>> index;
    std::ifstream indexFile(argv[argc - 2]);
    for (std::string line; std::getline(indexFile, line);) {
        std::vector<uint32_t> indexed;
        utf8to32(line.data(), indexed);
        index.push_back(indexed);
    }
    file.close();

    double startTime = getCurrentTime();
    for (const std::string &_query: queries) {
        std::vector<uint32_t> query;
        utf8to32(_query.data(), query);
        for (const std::vector<uint32_t> &indexed: index) {
            uint32_t distance = levenshtein(query, indexed);
            // TODO: Add to Top20 PQ
        }
    }
    double endTime = getCurrentTime();
    std::cout << "Took " << (endTime - startTime) << "s to execute the queries." << std::endl;
}
<|endoftext|>