<commit_before>#include <stdlib.h>

#include "ftdi_driver.h"
#include "ftdi_constants.h"

using namespace v8;
using namespace node;

/**********************************
 * Local typedefs
 **********************************/
struct DeviceListBaton
{
    Persistent<Value> callback;
    FT_DEVICE_LIST_INFO_NODE *devInfo;
    DWORD listLength;
    FT_STATUS status;
    int vid;
    int pid;

    DeviceListBaton()
    {
        devInfo = NULL;
    }
};

/**********************************
 * Local Helper Functions protoypes
 **********************************/
bool DeviceMatchesFilterCriteria(FT_DEVICE_LIST_INFO_NODE *devInfo, int filterVid, int filterPid);

/**********************************
 * Local Variables
 **********************************/
uv_mutex_t libraryMutex;
uv_mutex_t vidPidMutex;

/**********************************
 * Functions
 **********************************/
void InitializeList(Handle<Object> target)
{
    Persistent<FunctionTemplate> constructor_template;
    Local<FunctionTemplate> t = FunctionTemplate::New();
    constructor_template = Persistent<FunctionTemplate>::New(t);
    constructor_template->SetClassName(String::NewSymbol("FtdiDriver"));
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

    NODE_SET_METHOD(constructor_template, "findAll", FindAll);
    target->Set(String::NewSymbol("FtdiDriver"), constructor_template->GetFunction());

    uv_mutex_init(&vidPidMutex);
}

void FindAllAsync(uv_work_t* req)
{
    DeviceListBaton* listBaton = static_cast<DeviceListBaton*>(req->data);

    FT_STATUS ftStatus;
    DWORD numDevs = 0;

    // Lock Readout
    uv_mutex_lock(&vidPidMutex);

#ifndef WIN32
    if(listBaton->vid != 0 && listBaton->pid != 0)
    {
        uv_mutex_lock(&libraryMutex);
        ftStatus = FT_SetVIDPID(listBaton->vid, listBaton->pid);
        uv_mutex_unlock(&libraryMutex);
    }
#endif
    // create the device information list
    uv_mutex_lock(&libraryMutex);
    ftStatus = FT_CreateDeviceInfoList(&numDevs);
    uv_mutex_unlock(&libraryMutex);
    if (ftStatus == FT_OK)
    {
        if (numDevs > 0)
        {
            // allocate storage for list based on numDevs
            listBaton->devInfo =  (FT_DEVICE_LIST_INFO_NODE*) malloc(sizeof(FT_DEVICE_LIST_INFO_NODE) * numDevs);

            // get the device information list
            uv_mutex_lock(&libraryMutex);
            ftStatus = FT_GetDeviceInfoList(listBaton->devInfo, &numDevs);
            uv_mutex_unlock(&libraryMutex);
        }
    }
    uv_mutex_unlock(&vidPidMutex);

    listBaton->listLength = numDevs;
    listBaton->status = ftStatus;
}

void FindAllFinished(uv_work_t* req)
{
    DeviceListBaton* listBaton = static_cast<DeviceListBaton*>(req->data);

    //printf("Num DevFound: %d, status: %d\r\n", listBaton->listLength, listBaton->status);

    Handle<Value> argv[2];

    if(listBaton->status == FT_OK)
    {
        // Determine the length of the resulting list
        int resultListLength = 0;
        for (DWORD i = 0; i < listBaton->listLength; i++)
        {
            if(DeviceMatchesFilterCriteria(&listBaton->devInfo[i], listBaton->vid, listBaton->pid))
            {
                resultListLength++;
            }
        }

        // Create Java Script Array for the resulting devices
        Local<Array> array= Array::New(resultListLength);

        int index = 0;
        for (DWORD i = 0; i < listBaton->listLength; i++)
        {
            // Add device to the array in case it matches the criteria
            if(DeviceMatchesFilterCriteria(&listBaton->devInfo[i], listBaton->vid, listBaton->pid))
            {
                Local<Object> obj = Object::New();
                obj->Set(String::New(DEVICE_DESCRIPTION_TAG), String::New(listBaton->devInfo[i].Description));
                obj->Set(String::New(DEVICE_SERIAL_NR_TAG), String::New(listBaton->devInfo[i].SerialNumber));
                obj->Set(String::New(DEVICE_LOCATION_ID_TAG), Number::New(listBaton->devInfo[i].LocId));
                obj->Set(String::New(DEVICE_INDEX_TAG), Number::New(i));
                obj->Set(String::New(DEVICE_VENDOR_ID_TAG), Number::New( (listBaton->devInfo[i].ID >> 16) & (0xFFFF)));
                obj->Set(String::New(DEVICE_PRODUCT_ID_TAG), Number::New( (listBaton->devInfo[i].ID) & (0xFFFF)));
                array->Set(index++, obj);
            }
        }

        argv[1] = array;
    }
    else
    {
        argv[1] = Undefined();
    }
    argv[0] = Number::New(listBaton->status);

    Function::Cast(*listBaton->callback)->Call(Context::GetCurrent()->Global(), 2, argv);

    if(listBaton->devInfo != NULL)
    {
        free(listBaton->devInfo);
    }
}

Handle<Value> FindAll(const Arguments& args)
{
    HandleScope scope;

    int vid = 0;
    int pid = 0;

    if (args.Length() != 3)
    {
        ThrowException(Exception::TypeError(String::New("Wrong number of Arguments")));
    }
    if (args[0]->IsNumber() && args[1]->IsNumber())
    {
        vid = (int) args[0]->NumberValue();
        pid = (int) args[1]->NumberValue();
    }

    // callback
    if(!args[2]->IsFunction())
    {
        return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("Third argument must be a function"))));
    }
    Local<Value> callback = args[2];

    DeviceListBaton* listBaton = new DeviceListBaton();
    listBaton->callback = Persistent<Value>::New(callback);
    listBaton->vid = vid;
    listBaton->pid = pid;

    uv_work_t* req = new uv_work_t();
    req->data = listBaton;
    uv_queue_work(uv_default_loop(), req, FindAllAsync, (uv_after_work_cb)FindAllFinished);

    return scope.Close(v8::Undefined());
}

bool DeviceMatchesFilterCriteria(FT_DEVICE_LIST_INFO_NODE *devInfo, int filterVid, int filterPid)
{
    int devVid = (devInfo->ID >> 16) & (0xFFFF);
    int devPid = (devInfo->ID) & (0xFFFF);

    if(filterVid == 0 && filterPid == 0)
    {
        return true;
    }
    if(filterVid != 0 && filterVid != devVid)
    {
        return false;
    }
    if(filterPid != 0 && filterPid != devPid)
    {
        return false;
    }
    return true;
}

<commit_msg>Fallback for empty fields in find function<commit_after>#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "ftdi_driver.h"
#include "ftdi_constants.h"

using namespace v8;
using namespace node;

/**********************************
 * Local typedefs
 **********************************/
struct DeviceListBaton
{
    Persistent<Value> callback;
    FT_DEVICE_LIST_INFO_NODE *devInfo;
    DWORD listLength;
    FT_STATUS status;
    int vid;
    int pid;

    DeviceListBaton()
    {
        devInfo = NULL;
    }
};

/**********************************
 * Local Helper Functions protoypes
 **********************************/
bool DeviceMatchesFilterCriteria(FT_DEVICE_LIST_INFO_NODE *devInfo, int filterVid, int filterPid);

/**********************************
 * Local Variables
 **********************************/
uv_mutex_t libraryMutex;
uv_mutex_t vidPidMutex;

/**********************************
 * Functions
 **********************************/
void InitializeList(Handle<Object> target)
{
    Persistent<FunctionTemplate> constructor_template;
    Local<FunctionTemplate> t = FunctionTemplate::New();
    constructor_template = Persistent<FunctionTemplate>::New(t);
    constructor_template->SetClassName(String::NewSymbol("FtdiDriver"));
    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

    NODE_SET_METHOD(constructor_template, "findAll", FindAll);
    target->Set(String::NewSymbol("FtdiDriver"), constructor_template->GetFunction());

    uv_mutex_init(&vidPidMutex);
}

void FindAllAsync(uv_work_t* req)
{
    DeviceListBaton* listBaton = static_cast<DeviceListBaton*>(req->data);

    FT_STATUS ftStatus;
    DWORD numDevs = 0;

    // Lock Readout
    uv_mutex_lock(&vidPidMutex);

#ifndef WIN32
    if(listBaton->vid != 0 && listBaton->pid != 0)
    {
        uv_mutex_lock(&libraryMutex);
        ftStatus = FT_SetVIDPID(listBaton->vid, listBaton->pid);
        uv_mutex_unlock(&libraryMutex);
    }
#endif
    // create the device information list
    uv_mutex_lock(&libraryMutex);
    ftStatus = FT_CreateDeviceInfoList(&numDevs);
    uv_mutex_unlock(&libraryMutex);
    if (ftStatus == FT_OK)
    {
        if (numDevs > 0)
        {
            // allocate storage for list based on numDevs
            listBaton->devInfo =  (FT_DEVICE_LIST_INFO_NODE*) malloc(sizeof(FT_DEVICE_LIST_INFO_NODE) * numDevs);
            memset(listBaton->devInfo, 0, sizeof(FT_DEVICE_LIST_INFO_NODE) * numDevs);

            // get the device information list
            uv_mutex_lock(&libraryMutex);
            ftStatus = FT_GetDeviceInfoList(listBaton->devInfo, &numDevs);
            uv_mutex_unlock(&libraryMutex);

            for(DWORD i = 0; i < numDevs; i++)
            {
                if(strlen(listBaton->devInfo[i].SerialNumber) == 0)
                {
                    FT_ListDevices((PVOID)i, listBaton->devInfo[i].SerialNumber, FT_LIST_BY_INDEX | FT_OPEN_BY_SERIAL_NUMBER);
                }
                if(strlen(listBaton->devInfo[i].Description) == 0)
                {
                    FT_ListDevices((PVOID)i, listBaton->devInfo[i].Description, FT_LIST_BY_INDEX | FT_OPEN_BY_DESCRIPTION);
                }
                if(listBaton->devInfo[i].LocId == 0)
                {
                    FT_ListDevices((PVOID)i, &listBaton->devInfo[i].LocId, FT_LIST_BY_INDEX | FT_OPEN_BY_LOCATION);
                }
            }
        }
    }
    uv_mutex_unlock(&vidPidMutex);

    listBaton->listLength = numDevs;
    listBaton->status = ftStatus;
}

void FindAllFinished(uv_work_t* req)
{
    DeviceListBaton* listBaton = static_cast<DeviceListBaton*>(req->data);

    //printf("Num DevFound: %d, status: %d\r\n", listBaton->listLength, listBaton->status);

    Handle<Value> argv[2];

    if(listBaton->status == FT_OK)
    {
        // Determine the length of the resulting list
        int resultListLength = 0;
        for (DWORD i = 0; i < listBaton->listLength; i++)
        {
            if(DeviceMatchesFilterCriteria(&listBaton->devInfo[i], listBaton->vid, listBaton->pid))
            {
                resultListLength++;
            }
        }

        // Create Java Script Array for the resulting devices
        Local<Array> array= Array::New(resultListLength);

        int index = 0;
        for (DWORD i = 0; i < listBaton->listLength; i++)
        {
            // Add device to the array in case it matches the criteria
            if(DeviceMatchesFilterCriteria(&listBaton->devInfo[i], listBaton->vid, listBaton->pid))
            {
                Local<Object> obj = Object::New();
                obj->Set(String::New(DEVICE_DESCRIPTION_TAG), String::New(listBaton->devInfo[i].Description));
                obj->Set(String::New(DEVICE_SERIAL_NR_TAG), String::New(listBaton->devInfo[i].SerialNumber));
                obj->Set(String::New(DEVICE_LOCATION_ID_TAG), Number::New(listBaton->devInfo[i].LocId));
                obj->Set(String::New(DEVICE_INDEX_TAG), Number::New(i));
                obj->Set(String::New(DEVICE_VENDOR_ID_TAG), Number::New( (listBaton->devInfo[i].ID >> 16) & (0xFFFF)));
                obj->Set(String::New(DEVICE_PRODUCT_ID_TAG), Number::New( (listBaton->devInfo[i].ID) & (0xFFFF)));
                array->Set(index++, obj);
            }
        }

        argv[1] = array;
    }
    else
    {
        argv[1] = Undefined();
    }
    argv[0] = Number::New(listBaton->status);

    Function::Cast(*listBaton->callback)->Call(Context::GetCurrent()->Global(), 2, argv);

    if(listBaton->devInfo != NULL)
    {
        free(listBaton->devInfo);
    }
}

Handle<Value> FindAll(const Arguments& args)
{
    HandleScope scope;

    int vid = 0;
    int pid = 0;

    if (args.Length() != 3)
    {
        ThrowException(Exception::TypeError(String::New("Wrong number of Arguments")));
    }
    if (args[0]->IsNumber() && args[1]->IsNumber())
    {
        vid = (int) args[0]->NumberValue();
        pid = (int) args[1]->NumberValue();
    }

    // callback
    if(!args[2]->IsFunction())
    {
        return scope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("Third argument must be a function"))));
    }
    Local<Value> callback = args[2];

    DeviceListBaton* listBaton = new DeviceListBaton();
    listBaton->callback = Persistent<Value>::New(callback);
    listBaton->vid = vid;
    listBaton->pid = pid;

    uv_work_t* req = new uv_work_t();
    req->data = listBaton;
    uv_queue_work(uv_default_loop(), req, FindAllAsync, (uv_after_work_cb)FindAllFinished);

    return scope.Close(v8::Undefined());
}

bool DeviceMatchesFilterCriteria(FT_DEVICE_LIST_INFO_NODE *devInfo, int filterVid, int filterPid)
{
    int devVid = (devInfo->ID >> 16) & (0xFFFF);
    int devPid = (devInfo->ID) & (0xFFFF);

    if(filterVid == 0 && filterPid == 0)
    {
        return true;
    }
    if(filterVid != 0 && filterVid != devVid)
    {
        return false;
    }
    if(filterPid != 0 && filterPid != devPid)
    {
        return false;
    }
    return true;
}

<|endoftext|>


<commit_before><commit_msg>pbroadcast4/2 assume aligned memory<commit_after><|endoftext|>


<commit_before><commit_msg>test: new unit test for callbacks<commit_after><|endoftext|>


<commit_before>///
/// @file   pod_vector.cpp
/// @brief  Plain old data vector, like std::vector but does not
///         default initialize memory.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <pod_vector.hpp>

#include <cstdlib>
#include <iostream>
#include <random>
#include <numeric>
#include <utility>

using std::size_t;
using primecount::pod_vector;

void check(bool OK)
{
  std::cout << "   " << (OK ? "OK" : "ERROR") << "\n";
  if (!OK)
    std::exit(1);
}

int main()
{
  // The pod_vector class uses std::vector internally. For
  // performance reasons we want vector::resize() not to
  // free memory when resizing to a smaller size. The C++
  // standard seems to indirectly guarantee this behavior,
  // but it is not 100% clear. So this tests verifies this
  // behavior.

  // Allocate from 1 KiB to 128 MiB
  for (size_t i = 10; i <= 27; i++)
  {
    pod_vector<char> vect;
    vect.resize(size_t(1) << i);
    auto capacity1 = vect.capacity();
    vect.resize(100);
    auto capacity2 = vect.capacity();

    std::cout << "vect.resize(100).capacity = " << capacity1;
    check(capacity1 == capacity2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t n = dist(gen);
    pod_vector<size_t> vect;

    for (size_t i = 0; i <= n; i++)
      vect.push_back(i);

    for (size_t i = 0; i <= n; i++)
    {
      std::cout << "vect.push_back(" << i << ") = " << i;
      check(vect[i] == i);
    }
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t size = dist(gen);

    // pod_vector does not default initialize POD types
    // but it does initialize classes and structs with constructors.
    struct pod_t
    {
      pod_t() = default;
      pod_t(int i, int j) : a(i), b(j) { }
      int a = 100;
      int b = 200;
    };

    pod_vector<pod_t> vect(size);

    for (size_t i = 0; i < size; i++)
    {
      std::cout << "vect[i].a = " << vect[i].a;
      check(vect[i].a == 100);
      std::cout << "vect[i].b = " << vect[i].b;
      check(vect[i].b == 200);
    }

    vect.emplace_back(7, 8);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().a;
    check(vect.back().a == 7);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().b;
    check(vect.back().b == 8);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(10000, 20000);

    std::size_t n = dist(gen);
    pod_vector<int> vect;
    vect.reserve(n);

    std::cout << "Vect size after reserve: " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve: " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve: " << vect.capacity();
    check(vect.capacity() == n);

    vect.reserve(n / 2);
    std::cout << "Vect size after reserve/2: " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve/2: " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve/2: " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n);
    std::cout << "Vect size after resize: " << vect.size();
    check(vect.size() == n);
    std::cout << "Vect capacity after resize: " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n / 2);
    std::cout << "Vect size after resize/2: " << vect.size();
    check(vect.size() == n / 2);
    std::cout << "Vect capacity after resize/2: " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n * 2);
    std::cout << "Vect size after resize*2: " << vect.size();
    check(vect.size() == n * 2);
    std::cout << "Vect capacity after resize*2: " << vect.capacity();
    check(vect.capacity() >= n * 2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    // Test if resize does not default initilize
    vect.resize(0);
    vect.resize(size);
    int sum = std::accumulate(&vect[0], &vect[0] + vect.size(), 0);
    std::cout << "Vect sum after resize: " << sum;
    check(sum == 123 * size);
    std::cout << "Vect.end(): " << vect.end();
    check(vect.end() == vect.begin() + vect.size());

    // Test reallocation (old content must be copied into new vector)
    vect.resize(vect.size() * 2);
    sum = std::accumulate(&vect[0], &vect[0] + size, 0);
    std::cout << "Vect sum after reallocation: " << sum;
    check(sum == 123 * size);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    pod_vector<int> vect2 = std::move(vect);
    std::cout << "Vect1 empty after std::move: " << vect.empty();
    check(vect.empty() == true);
    int sum = std::accumulate(vect2.begin(), vect2.end(), 0);
    std::cout << "Vect2 sum after std::move: " << sum;
    check(sum == 123 * size);
  }

  std::cout << std::endl;
  std::cout << "All tests passed successfully!" << std::endl;

  return 0;
}
<commit_msg>Add more tests<commit_after>///
/// @file   pod_vector.cpp
/// @brief  Plain old data vector, like std::vector but does not
///         default initialize memory.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <pod_vector.hpp>

#include <cstdlib>
#include <iostream>
#include <random>
#include <numeric>
#include <utility>

using std::size_t;
using primecount::pod_vector;

void check(bool OK)
{
  std::cout << "   " << (OK ? "OK" : "ERROR") << "\n";
  if (!OK)
    std::exit(1);
}

int main()
{
  // The pod_vector class uses std::vector internally. For
  // performance reasons we want vector::resize() not to
  // free memory when resizing to a smaller size. The C++
  // standard seems to indirectly guarantee this behavior,
  // but it is not 100% clear. So this tests verifies this
  // behavior.

  // Allocate from 1 KiB to 128 MiB
  for (size_t i = 10; i <= 27; i++)
  {
    pod_vector<char> vect;
    vect.resize(size_t(1) << i);
    auto capacity1 = vect.capacity();
    vect.resize(100);
    auto capacity2 = vect.capacity();

    std::cout << "vect.resize(100).capacity = " << capacity1;
    check(capacity1 == capacity2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t n = dist(gen);
    pod_vector<size_t> vect;

    for (size_t i = 0; i <= n; i++)
      vect.push_back(i);

    for (size_t i = 0; i <= n; i++)
    {
      std::cout << "vect.push_back(" << i << ") = " << i;
      check(vect[i] == i);
    }
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(100, 200);

    std::size_t size = dist(gen);

    // pod_vector does not default initialize POD types
    // but it does initialize classes and structs with constructors.
    struct pod_t
    {
      pod_t() = default;
      pod_t(int i, int j) : a(i), b(j) { }
      int a = 100;
      int b = 200;
    };

    pod_vector<pod_t> vect(size);

    for (size_t i = 0; i < size; i++)
    {
      std::cout << "vect[i].a = " << vect[i].a;
      check(vect[i].a == 100);
      std::cout << "vect[i].b = " << vect[i].b;
      check(vect[i].b == 200);
    }

    vect.emplace_back(7, 8);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().a;
    check(vect.back().a == 7);
    std::cout << "vect.emplace_back(7, 8) = " << vect.back().b;
    check(vect.back().b == 8);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<std::size_t> dist(10000, 20000);

    std::size_t n = dist(gen);
    pod_vector<int> vect;
    vect.resize(0);

    std::cout << "Vect size after resize(0): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect capacity after resize(0): " << vect.capacity();
    check(vect.capacity() == 0);

    vect.reserve(n);

    std::cout << "Vect size after reserve(n): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve(n): " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve(n): " << vect.capacity();
    check(vect.capacity() == n);

    vect.reserve(n / 2);
    std::cout << "Vect size after reserve(n/2): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect empty after reserve(n/2): " << vect.empty();
    check(vect.empty() == true);
    std::cout << "Vect capacity after reserve(n/2): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n);
    std::cout << "Vect size after resize(n): " << vect.size();
    check(vect.size() == n);
    std::cout << "Vect capacity after resize(n): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n);
    std::cout << "Vect size after 2nd resize(n): " << vect.size();
    check(vect.size() == n);
    std::cout << "Vect capacity after 2nd resize(n): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n / 2);
    std::cout << "Vect size after resize(n/2): " << vect.size();
    check(vect.size() == n / 2);
    std::cout << "Vect capacity after resize(n/2): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(0);
    std::cout << "Vect size after resize(0): " << vect.size();
    check(vect.size() == 0);
    std::cout << "Vect capacity after resize(0): " << vect.capacity();
    check(vect.capacity() == n);

    vect.resize(n * 2);
    std::cout << "Vect size after resize(n*2): " << vect.size();
    check(vect.size() == n * 2);
    std::cout << "Vect capacity after resize(n*2): " << vect.capacity();
    check(vect.capacity() >= n * 2);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    // Test if resize does not default initilize
    vect.resize(0);
    vect.resize(size);
    int sum = std::accumulate(&vect[0], &vect[0] + vect.size(), 0);
    std::cout << "Vect sum after resize: " << sum;
    check(sum == 123 * size);
    std::cout << "Vect.end(): " << vect.end();
    check(vect.end() == vect.begin() + vect.size());

    // Test reallocation (old content must be copied into new vector)
    vect.resize(vect.size() * 2);
    sum = std::accumulate(&vect[0], &vect[0] + size, 0);
    std::cout << "Vect sum after reallocation: " << sum;
    check(sum == 123 * size);
  }

  {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(10000, 20000);

    int size = dist(gen);
    pod_vector<int> vect(size);
    std::fill_n(&vect[0], size, 123);

    pod_vector<int> vect2 = std::move(vect);
    std::cout << "Vect1 empty after std::move: " << vect.empty();
    check(vect.empty() == true);
    int sum = std::accumulate(vect2.begin(), vect2.end(), 0);
    std::cout << "Vect2 sum after std::move: " << sum;
    check(sum == 123 * size);
  }

  std::cout << std::endl;
  std::cout << "All tests passed successfully!" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>#include "../../../vendor/gc/include/gc.h"
#include "../../../vendor/gc/include/gc_cpp.h"
#include "../../../vendor/gc/include/gc_allocator.h"

#include "try_catch_block.h"
#include "../../scope.h"

namespace fancy {
  namespace parser {
    namespace nodes {

      // ExceptionHandler

      ExceptionHandler::ExceptionHandler(Identifier* exception_class_name,
                                         Identifier* local_name,
                                         Expression* body) :
        _exception_class_name(exception_class_name),
        _exception_class(0),
        _local_name(local_name),
        _body(body)
      {
      }

      bool ExceptionHandler::can_handle(Class* the_class, Scope *scope)
      {
        _exception_class = dynamic_cast<Class*>(scope->get(_exception_class_name->name()));
        if(_exception_class) {
          return the_class->subclass_of(_exception_class);
        }
        return false;
      }

      FancyObject* ExceptionHandler::handle(FancyException* exception, Scope *scope)
      {
        Scope *catch_scope = new Scope(scope);
        if(_local_name->name() != "") {
          scope->define(_local_name->name(), exception);
        }
        return _body->eval(catch_scope);
      }

      // TryCatchBlock

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   except_handler_list* except_handlers) :
        _body(body),
        _finally_block(NULL)
      {
        init_except_handlers(except_handlers);
      }

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   except_handler_list* except_handlers,
                                   ExpressionList* finally_block) :
        _body(body),
        _finally_block(finally_block)
      {
        init_except_handlers(except_handlers);
      }

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   list<ExceptionHandler*> except_handlers) :
        _body(body),
        _except_handlers(except_handlers),
        _finally_block(NULL)
      {
      }

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   list<ExceptionHandler*> except_handlers,
                                   ExpressionList* finally_block) :
        _body(body),
        _except_handlers(except_handlers),
        _finally_block(finally_block)
      {
      }

      FancyObject* TryCatchBlock::eval(Scope *scope)
      {
        // OK, I admit this code looks kinda ugly. But it's pretty
        // simple actually:
        // Try to simply eval the body.
        // If there's a finally block defined, run it afterwars, then
        // return its last value.
        // If the body evaluation raises an exception:
        // -> check for an exception handler.
        // Again, always make sure that a finally block gets run, if
        // defined.

        try {
          if(!_finally_block) {
            return _body->eval(scope);
          } else {
            _body->eval(scope);
            return _finally_block->eval(scope);
          }
        } catch(FancyException* ex) {
          for(list<ExceptionHandler*>::iterator it = _except_handlers.begin();
              it != _except_handlers.end();
              it++) {
            if((*it)->can_handle(ex->exception_class(), scope)) {
              FancyObject* retval = (*it)->handle(ex, scope);
              // eval finally block if any given
              if(_finally_block) {
                retval = _finally_block->eval(scope);
              }
              return retval;
            }
          }
          // always eval finally block!
          if(_finally_block) {
            _finally_block->eval(scope);
          }
          throw ex; // no handler defined
        }
      }

      void TryCatchBlock::init_except_handlers(except_handler_list* except_handlers)
      {
        for(except_handler_list *tmp = except_handlers; tmp != NULL; tmp = tmp->next) {
          _except_handlers.push_front(tmp->handler);
        }
      }
    }
  }
}
<commit_msg>use local stack-allocated Scope object in ExceptionHandler#handle() and define the exception's local name within the catch_scope.<commit_after>#include "../../../vendor/gc/include/gc.h"
#include "../../../vendor/gc/include/gc_cpp.h"
#include "../../../vendor/gc/include/gc_allocator.h"

#include "try_catch_block.h"
#include "../../scope.h"

namespace fancy {
  namespace parser {
    namespace nodes {

      // ExceptionHandler

      ExceptionHandler::ExceptionHandler(Identifier* exception_class_name,
                                         Identifier* local_name,
                                         Expression* body) :
        _exception_class_name(exception_class_name),
        _exception_class(0),
        _local_name(local_name),
        _body(body)
      {
      }

      bool ExceptionHandler::can_handle(Class* the_class, Scope *scope)
      {
        _exception_class = dynamic_cast<Class*>(scope->get(_exception_class_name->name()));
        if(_exception_class) {
          return the_class->subclass_of(_exception_class);
        }
        return false;
      }

      FancyObject* ExceptionHandler::handle(FancyException* exception, Scope *scope)
      {
        // Scope *catch_scope = new Scope(scope);
        Scope catch_scope(scope);
        if(_local_name->name() != "") {
          catch_scope.define(_local_name->name(), exception);
        }
        return _body->eval(&catch_scope);
      }

      // TryCatchBlock

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   except_handler_list* except_handlers) :
        _body(body),
        _finally_block(NULL)
      {
        init_except_handlers(except_handlers);
      }

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   except_handler_list* except_handlers,
                                   ExpressionList* finally_block) :
        _body(body),
        _finally_block(finally_block)
      {
        init_except_handlers(except_handlers);
      }

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   list<ExceptionHandler*> except_handlers) :
        _body(body),
        _except_handlers(except_handlers),
        _finally_block(NULL)
      {
      }

      TryCatchBlock::TryCatchBlock(ExpressionList* body,
                                   list<ExceptionHandler*> except_handlers,
                                   ExpressionList* finally_block) :
        _body(body),
        _except_handlers(except_handlers),
        _finally_block(finally_block)
      {
      }

      FancyObject* TryCatchBlock::eval(Scope *scope)
      {
        // OK, I admit this code looks kinda ugly. But it's pretty
        // simple actually:
        // Try to simply eval the body.
        // If there's a finally block defined, run it afterwars, then
        // return its last value.
        // If the body evaluation raises an exception:
        // -> check for an exception handler.
        // Again, always make sure that a finally block gets run, if
        // defined.

        try {
          if(!_finally_block) {
            return _body->eval(scope);
          } else {
            _body->eval(scope);
            return _finally_block->eval(scope);
          }
        } catch(FancyException* ex) {
          for(list<ExceptionHandler*>::iterator it = _except_handlers.begin();
              it != _except_handlers.end();
              it++) {
            if((*it)->can_handle(ex->exception_class(), scope)) {
              FancyObject* retval = (*it)->handle(ex, scope);
              // eval finally block if any given
              if(_finally_block) {
                retval = _finally_block->eval(scope);
              }
              return retval;
            }
          }
          // always eval finally block!
          if(_finally_block) {
            _finally_block->eval(scope);
          }
          throw ex; // no handler defined
        }
      }

      void TryCatchBlock::init_except_handlers(except_handler_list* except_handlers)
      {
        for(except_handler_list *tmp = except_handlers; tmp != NULL; tmp = tmp->next) {
          _except_handlers.push_front(tmp->handler);
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>#ifndef _PITO_INTERCEPTOR_SYSTEM_CALL_HPP_
#define _PITO_INTERCEPTOR_SYSTEM_CALL_HPP_

#include <pito/interceptor/Library.hpp>
#include <sys/types.h>

namespace pito { namespace interceptor {

namespace system_call {
    struct open {};
};

template <class Tag>
struct SystemCall;

template <class LibraryTag, class Ret, class... Args>
struct SystemCallHelper {
    typedef Ret (*call_t)(Args...);

    SystemCallHelper(std::string const& name) : call_(0), name_(name) {}

    Ret operator()(Args... args) {
        if (! call_) {
            call_ = dlsym(library::instance<LibraryTag>().handle(), name_.c_str());
        }
        return call_(args...);
    }

  private:
    call_t call_;
    std::string name_;
};

template <>
struct SystemCall<system_call::open>
  : SystemCallHelper<library::c, int, const char *, int, mode_t>
{
    SystemCall() : SystemCallHelper<library::c, int, const char *, int, mode_t>("open") {}
};

} }

#endif
<commit_msg>instance for system call<commit_after>#ifndef _PITO_INTERCEPTOR_SYSTEM_CALL_HPP_
#define _PITO_INTERCEPTOR_SYSTEM_CALL_HPP_

#include <pito/interceptor/Library.hpp>
#include <sys/types.h>

namespace pito { namespace interceptor {

namespace system_call {
    struct open {};
};

template <class Tag>
struct SystemCall;

template <class LibraryTag, class Ret, class... Args>
struct SystemCallHelper {
    typedef Ret (*call_t)(Args...);

    SystemCallHelper(std::string const& name) : call_(0), name_(name) {}

    Ret operator()(Args... args) {
        if (! call_) {
            call_ = dlsym(library::instance<LibraryTag>().handle(), name_.c_str());
        }
        return call_(args...);
    }

  private:
    call_t call_;
    std::string name_;
};

template <>
struct SystemCall<system_call::open>
  : SystemCallHelper<library::c, int, const char *, int, mode_t>
{
    SystemCall() : SystemCallHelper<library::c, int, const char *, int, mode_t>("open") {}
};

namespace library {
    template <class Tag>
    SystemCall<Tag>& instance() {
        return singleton_default< SystemCall<Tag> >::instance();
    }
}

} }

#endif
<|endoftext|>


<commit_before>// mapnik
#include <mapnik/feature_factory.hpp>
#include <mapnik/geometry.hpp>

// yajl
#include "yajl/yajl_parse.h"

#include "jit_featureset.hpp"

mapnik::transcoder* tr = new mapnik::transcoder("utf-8");

static int gj_start_map(void * ctx)
{
    return 1;
}

static int gj_map_key(void * ctx, const unsigned char* key, size_t t)
{
    std::string key_ = std::string((const char*) key, t);
    if (((fm *) ctx)->state == parser_in_properties)
    {
        ((fm *) ctx)->property_name = key_;
    }
    else
    {
        if (key_ == "features")
        {
            ((fm *) ctx)->state = parser_in_features;
        }
        else if (key_ == "geometry")
        {
            ((fm *) ctx)->state = parser_in_geometry;
        }
        else if ((((fm *) ctx)->state == parser_in_geometry) && (key_ == "type"))
        {
            ((fm *) ctx)->state = parser_in_type;
        }
        else if (key_ == "properties")
        {
            ((fm *) ctx)->state = parser_in_properties;
        }
        else if (key_ == "coordinates")
        {
            ((fm *) ctx)->state = parser_in_coordinates;
        }
    }
    return 1;
}

static int gj_end_map(void * ctx)
{
    if ((((fm *) ctx)->state == parser_in_properties) ||
        (((fm *) ctx)->state == parser_in_geometry))
    {
        ((fm *) ctx)->state = parser_in_feature;
    }
    else if (((fm *) ctx)->state == parser_in_feature)
    {
        if (((fm *) ctx)->geometry_type == "Point")
        {
            mapnik::geometry_type * pt;
            pt = new mapnik::geometry_type(mapnik::Point);
            pt->move_to(
                ((fm *) ctx)->point_cache.at(0),
                ((fm *) ctx)->point_cache.at(1));
            ((fm *) ctx)->feature->add_geometry(pt);
        }
        if (((fm *) ctx)->geometry_type == "LineString")
        {
            mapnik::geometry_type * pt;
            pt = new mapnik::geometry_type(mapnik::LineString);

            pt->set_capacity(((fm *) ctx)->point_cache.size() / 2);
            pt->move_to(
                ((fm *) ctx)->point_cache.at(0),
                ((fm *) ctx)->point_cache.at(1));

            for (int i = 2; i < ((fm *) ctx)->point_cache.size(); i += 2) {
                pt->line_to(
                    ((fm *) ctx)->point_cache.at(i),
                    ((fm *) ctx)->point_cache.at(i + 1));
            }
            ((fm *) ctx)->feature->add_geometry(pt);
        }
        ((fm *) ctx)->state = parser_in_features;
        ((fm *) ctx)->done = 1;
    }
    return 1;
}

static int gj_null(void * ctx)
{
    if (((fm *) ctx)->state == parser_in_properties)
    {
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, mapnik::value_null());
    }
    return 1;
}

static int gj_boolean(void * ctx, int x)
{
    if (((fm *) ctx)->state == parser_in_properties)
    {
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, x);
    }
    return 1;
}

static int gj_number(void * ctx, const char* str, size_t t)
{
    std::string str_ = std::string((const char*) str, t);
    double x = boost::lexical_cast<double>(str_);

    if (((fm *) ctx)->state == parser_in_coordinates)
    {
        ((fm *) ctx)->point_cache.push_back(x);
    }
    if (((fm *) ctx)->state == parser_in_properties)
    {
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, x);
    }
    return 1;
}

static int gj_string(void * ctx, const unsigned char* str, size_t t)
{
    std::string str_ = std::string((const char*) str, t);
    if (((fm *) ctx)->state == parser_in_type)
    {
        ((fm *) ctx)->geometry_type = str_;
    }
    else if (((fm *) ctx)->state == parser_in_properties)
    {
        UnicodeString ustr = tr->transcode(str_.c_str());
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, ustr);
    }
    return 1;
}

static int gj_start_array(void * ctx)
{
    if (((fm *) ctx)->state == parser_in_coordinates)
    {
        ((fm *) ctx)->coord_dimensions++;
    }
    return 1;
}

static int gj_end_array(void * ctx)
{
    if (((fm *) ctx)->state == parser_in_coordinates)
    {
        ((fm *) ctx)->coord_dimensions--;
        if (((fm *) ctx)->coord_dimensions < 1)
        {
            ((fm *) ctx)->state = parser_in_geometry;
        }
    }
    else if (((fm *) ctx)->state == parser_in_features)
    {
        ((fm *) ctx)->state = parser_outside;
    }
    return 1;
}

static yajl_callbacks callbacks = {
    gj_null,
    gj_boolean,
    NULL,
    NULL,
    gj_number,
    gj_string,
    gj_start_map,
    gj_map_key,
    gj_end_map,
    gj_start_array,
    gj_end_array
};

jit_featureset::jit_featureset(
    mapnik::box2d<double> const& box,
    std::string input_string,
    std::string const& encoding)
    : box_(box),
      feature_id_(1),
      input_string_(input_string),
      tr_(new mapnik::transcoder(encoding)) {

    state_bundle.state = parser_outside;
    state_bundle.done = 0;

    // FIXME: manually free
    hand = yajl_alloc(
        &callbacks, NULL,
        &state_bundle);

    yajl_config(hand, yajl_allow_comments, 1);

    mapnik::feature_ptr feature(mapnik::feature_factory::create(feature_id_));
    state_bundle.feature = feature;

    for (itt_ = 0; itt_ < input_string_.length(); itt_++) {

        int parse_result;

        parse_result = yajl_parse(hand,
                (const unsigned char*) &input_string_[itt_], 1);

        if (parse_result == yajl_status_error)
        {
            unsigned char *str = yajl_get_error(hand, 1,  (const unsigned char*) input_string_.c_str(), input_string_.length());
            std::ostringstream errmsg;
            errmsg << "GeoJSON Plugin: invalid GeoJSON detected: " << (const char*) str << "\n";
            yajl_free_error(hand, str);
            throw mapnik::datasource_exception(errmsg.str());
        }
        else if (state_bundle.done == 1)
        {
            features_.push_back(state_bundle.feature);

            feature_id_++;
            mapnik::feature_ptr feature(mapnik::feature_factory::create(feature_id_));

            // reset
            state_bundle.point_cache.clear();
            state_bundle.done = 0;
            state_bundle.geometry_type = "";
            state_bundle.feature = feature;

        }

    }
}

jit_featureset::~jit_featureset() { }

mapnik::feature_ptr jit_featureset::next()
{
    feature_id_++;
    if (feature_id_ <= features_.size())
    {
        return features_.at(feature_id_ - 1);
    }
    else
    {
        return mapnik::feature_ptr();
    }
}
<commit_msg>Featureset returning features from HTTP<commit_after>// mapnik
#include <mapnik/feature_factory.hpp>
#include <mapnik/geometry.hpp>

// yajl
#include "yajl/yajl_parse.h"

#include "jit_featureset.hpp"

mapnik::transcoder* tr = new mapnik::transcoder("utf-8");

static int gj_start_map(void * ctx)
{
    return 1;
}

static int gj_map_key(void * ctx, const unsigned char* key, size_t t)
{
    std::string key_ = std::string((const char*) key, t);
    if (((fm *) ctx)->state == parser_in_properties)
    {
        ((fm *) ctx)->property_name = key_;
    }
    else
    {
        if (key_ == "features")
        {
            ((fm *) ctx)->state = parser_in_features;
        }
        else if (key_ == "geometry")
        {
            ((fm *) ctx)->state = parser_in_geometry;
        }
        else if ((((fm *) ctx)->state == parser_in_geometry) && (key_ == "type"))
        {
            ((fm *) ctx)->state = parser_in_type;
        }
        else if (key_ == "properties")
        {
            ((fm *) ctx)->state = parser_in_properties;
        }
        else if (key_ == "coordinates")
        {
            ((fm *) ctx)->state = parser_in_coordinates;
        }
    }
    return 1;
}

static int gj_end_map(void * ctx)
{
    if ((((fm *) ctx)->state == parser_in_properties) ||
        (((fm *) ctx)->state == parser_in_geometry))
    {
        ((fm *) ctx)->state = parser_in_feature;
    }
    else if (((fm *) ctx)->state == parser_in_feature)
    {
        if (((fm *) ctx)->geometry_type == "Point")
        {
            mapnik::geometry_type * pt;
            pt = new mapnik::geometry_type(mapnik::Point);
            pt->move_to(
                ((fm *) ctx)->point_cache.at(0),
                ((fm *) ctx)->point_cache.at(1));
            ((fm *) ctx)->feature->add_geometry(pt);
        }
        if (((fm *) ctx)->geometry_type == "LineString")
        {
            mapnik::geometry_type * pt;
            pt = new mapnik::geometry_type(mapnik::LineString);

            pt->set_capacity(((fm *) ctx)->point_cache.size() / 2);
            pt->move_to(
                ((fm *) ctx)->point_cache.at(0),
                ((fm *) ctx)->point_cache.at(1));

            for (int i = 2; i < ((fm *) ctx)->point_cache.size(); i += 2) {
                pt->line_to(
                    ((fm *) ctx)->point_cache.at(i),
                    ((fm *) ctx)->point_cache.at(i + 1));
            }
            ((fm *) ctx)->feature->add_geometry(pt);
        }
        ((fm *) ctx)->state = parser_in_features;
        ((fm *) ctx)->done = 1;
    }
    return 1;
}

static int gj_null(void * ctx)
{
    if (((fm *) ctx)->state == parser_in_properties)
    {
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, mapnik::value_null());
    }
    return 1;
}

static int gj_boolean(void * ctx, int x)
{
    if (((fm *) ctx)->state == parser_in_properties)
    {
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, x);
    }
    return 1;
}

static int gj_number(void * ctx, const char* str, size_t t)
{
    std::string str_ = std::string((const char*) str, t);
    double x = boost::lexical_cast<double>(str_);

    if (((fm *) ctx)->state == parser_in_coordinates)
    {
        ((fm *) ctx)->point_cache.push_back(x);
    }
    if (((fm *) ctx)->state == parser_in_properties)
    {
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, x);
    }
    return 1;
}

static int gj_string(void * ctx, const unsigned char* str, size_t t)
{
    std::string str_ = std::string((const char*) str, t);
    if (((fm *) ctx)->state == parser_in_type)
    {
        ((fm *) ctx)->geometry_type = str_;
    }
    else if (((fm *) ctx)->state == parser_in_properties)
    {
        UnicodeString ustr = tr->transcode(str_.c_str());
        boost::put(*((fm *) ctx)->feature, ((fm *) ctx)->property_name, ustr);
    }
    return 1;
}

static int gj_start_array(void * ctx)
{
    if (((fm *) ctx)->state == parser_in_coordinates)
    {
        ((fm *) ctx)->coord_dimensions++;
    }
    return 1;
}

static int gj_end_array(void * ctx)
{
    if (((fm *) ctx)->state == parser_in_coordinates)
    {
        ((fm *) ctx)->coord_dimensions--;
        if (((fm *) ctx)->coord_dimensions < 1)
        {
            ((fm *) ctx)->state = parser_in_geometry;
        }
    }
    else if (((fm *) ctx)->state == parser_in_features)
    {
        ((fm *) ctx)->state = parser_outside;
    }
    return 1;
}

static yajl_callbacks callbacks = {
    gj_null,
    gj_boolean,
    NULL,
    NULL,
    gj_number,
    gj_string,
    gj_start_map,
    gj_map_key,
    gj_end_map,
    gj_start_array,
    gj_end_array
};

jit_featureset::jit_featureset(
    mapnik::box2d<double> const& box,
    std::string input_string,
    std::string const& encoding)
    : box_(box),
      feature_id_(1),
      input_string_(input_string),
      tr_(new mapnik::transcoder(encoding)) {

    state_bundle.state = parser_outside;
    state_bundle.done = 0;

    // FIXME: manually free
    hand = yajl_alloc(
        &callbacks, NULL,
        &state_bundle);

    yajl_config(hand, yajl_allow_comments, 1);
    yajl_config(hand, yajl_allow_trailing_garbage, 1);

    mapnik::feature_ptr feature(mapnik::feature_factory::create(feature_id_));
    state_bundle.feature = feature;

    for (itt_ = 0; itt_ < input_string_.length(); itt_++) {

        int parse_result;

        parse_result = yajl_parse(hand,
                (const unsigned char*) &input_string_[itt_], 1);

        if (parse_result == yajl_status_error)
        {
            unsigned char *str = yajl_get_error(hand, 1,  (const unsigned char*) input_string_.c_str(), input_string_.length());
            std::ostringstream errmsg;
            errmsg << "GeoJSON Plugin: invalid GeoJSON detected: " << (const char*) str << "\n";
            yajl_free_error(hand, str);
            throw mapnik::datasource_exception(errmsg.str());
        }
        else if (state_bundle.done == 1)
        {
            features_.push_back(state_bundle.feature);

            feature_id_++;
            mapnik::feature_ptr feature(mapnik::feature_factory::create(feature_id_));

            // reset
            state_bundle.point_cache.clear();
            state_bundle.done = 0;
            state_bundle.geometry_type = "";
            state_bundle.feature = feature;

        }
    }
    feature_id_ = 0;
}

jit_featureset::~jit_featureset() { }

mapnik::feature_ptr jit_featureset::next()
{
    feature_id_++;
    if (feature_id_ <= features_.size())
    {
        return features_.at(feature_id_ - 1);
    }
    else
    {
        return mapnik::feature_ptr();
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>
#include <limits>
#include <type_traits>

namespace const_expr_string
{
    // Definition
    template<typename CharT>
    class const_expr_string
    {
        public:
            using value_type = CharT;
            using traits_type = std::char_traits<value_type>;
            using size_type = size_t;
            using difference_type = std::ptrdiff_t;
            using const_pointer = const CharT *;
            using pointer = const_pointer;
            using const_reference = const CharT&;
            using reference = const_reference;
            using const_iterator = const CharT*;
            using iterator = const_iterator;
            using const_reverse_iterator = std::reverse_iterator<const_iterator>;
            using reverse_iterator = const_reverse_iterator;
            static constexpr size_type npos = size_type(-1);

            // Constructors
            constexpr const_expr_string(const_pointer data) noexcept;
            constexpr const_expr_string(const const_expr_string<CharT>& other) = default;

            // Size based
            constexpr size_t length() const noexcept;
            constexpr size_t size() const noexcept;
            constexpr size_type max_size() const noexcept;
            constexpr bool empty() const noexcept;

            // Conversion operator
            constexpr operator const_pointer() const noexcept;

            // Iterators
            constexpr iterator begin() const noexcept;
            constexpr const_iterator cbegin() const noexcept;
            constexpr iterator end() const noexcept;
            constexpr const_iterator cend() const noexcept;

            // TODO: Fix reverse_iterator functions!
            //Can't be constexpr without a reverse_iterator type
            //constexpr const_reverse_iterator rbegin() const noexcept;
            //constexpr const_reverse_iterator crbegin() const noexcept;
            //constexpr const_reverse_iterator rend() const noexcept;
            //constexpr const_reverse_iterator crend() const noexcept;

            // Indexing
            constexpr const_reference operator[](size_type pos) const;
            constexpr const_reference at(size_type pos) const;

            // ref positions
            constexpr const_reference front() const;
            constexpr const_reference back() const;

            // Data member
            constexpr const_pointer data() const noexcept;

            // Compares
            constexpr int compare (const_expr_string v) const;
            constexpr int compare (size_type pos1, size_type count1, const_expr_string v) const;
            constexpr int compare (size_type pos1, size_type count1, const_expr_string v,
                    size_type pos2, size_type count2) const;
            constexpr int compare (const_pointer s) const; // TODO: not implemented
            constexpr int compare (size_type pos1, size_type count1, const_pointer s) const; // TODO: not implemented
            constexpr int compare (size_type pos1, size_type count1, const_pointer s, size_type count2) const; // TODO: not implemented

            // Finds
            constexpr size_type find(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type rfind(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type rfind(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type rfind(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type rfind(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_first_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_last_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_first_not_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_not_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_not_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_not_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_last_not_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_not_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_not_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_not_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
        private:
            const_pointer _data;
            static constexpr size_type str_len(const char* str)
            {
                size_type i = 0;
                while (str[i] != '\0') ++i;
                return i;
            }
    };

    // Implementation
    template <typename CharT>
    constexpr const_expr_string<CharT>::const_expr_string(
            const_expr_string<CharT>::const_pointer data) noexcept
    : _data(data)
    {
    }

    template <typename CharT>
    constexpr const_expr_string<CharT>::operator
            const_expr_string<CharT>::const_pointer() const noexcept
    {
        return _data;
    }

    template <typename CharT>
    constexpr size_t const_expr_string<CharT>::length() const noexcept
    {
        return const_expr_string<CharT>::str_len(_data);
    }

    template <typename CharT>
    constexpr size_t const_expr_string<CharT>::size() const noexcept
    {
        return length();
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::iterator const_expr_string<CharT>::begin() const noexcept
    {
        return &*_data;
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::const_iterator const_expr_string<CharT>::cbegin() const noexcept
    {
        return begin();
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::iterator const_expr_string<CharT>::end() const noexcept
    {
        return _data + size();
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::const_iterator const_expr_string<CharT>::cend() const noexcept
    {
        return end();
    }

    //Can't be constexpr without a reverse_iterator type
    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::reverse_iterator const_expr_string<CharT>::rbegin() const noexcept
    //{
    //    return const_reverse_iterator(end());
    //}

    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::const_reverse_iterator const_expr_string<CharT>::crbegin() const noexcept
    //{
    //    return rbegin();
    //}

    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::reverse_iterator const_expr_string<CharT>::rend() const noexcept
    //{
    //    return const_reverse_iterator(begin());
    //}

    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::const_reverse_iterator const_expr_string<CharT>::crend() const noexcept
    //{
    //    return rend();
    //}

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::operator[](const_expr_string<CharT>::size_type pos) const
    {
        return _data[pos];
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::at(const_expr_string<CharT>::size_type pos) const
    {
        return pos >= size() ?
            throw std::out_of_range("call to at with too large index") :
            operator[](pos);
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_pointer const_expr_string<CharT>::data() const noexcept
    {
        return _data;
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::front() const
    {
        return operator[](0);
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::back() const
    {
        return operator[](size() - 1);
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::size_type const_expr_string<CharT>::max_size() const noexcept
    {
        // reserves npos to be an illegal index
        return std::numeric_limits<size_type>::max() - 1;
    }

    template<typename CharT>
    constexpr bool const_expr_string<CharT>::empty() const noexcept
    {
        return _data[0] == '\0';
    }

    // Compare functions
    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (const_expr_string<CharT> v) const
    {
        return compare(0, size(), v, 0, size());
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_expr_string v) const
    {
        return compare (pos1, count1, v, 0, v.size());
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_expr_string v,
            const_expr_string<CharT>::size_type pos2,
            const_expr_string<CharT>::size_type count2) const
    {
        typename const_expr_string<CharT>::size_type lhsSize = count1;
        typename const_expr_string<CharT>::size_type rhsSize = count2;

        if (lhsSize < rhsSize) return -1;
        if (lhsSize > rhsSize) return 1;

        for (const_expr_string<CharT>::size_type i = 0; i < lhsSize; ++i)
        {
            if (_data[i + pos1] < v._data[i + pos2]) return -1;
            if (_data[i + pos1] > v._data[i + pos2]) return 1;
        }

        return 0;
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (
            typename const_expr_string<CharT>::const_pointer s) const
    {
        return compare(0, size(), s, str_len(s));
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (
            typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_pointer s) const
    {
        return compare(pos1, count1, s, str_len(s));
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (
            typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_pointer s,
            typename const_expr_string<CharT>::size_type count2) const
    {
        return compare(pos1, count1, const_expr_string<CharT>(s), 0, count2);
    }

    // compare operators
    template<typename CharT>
    constexpr bool operator==(const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) == 0;
    }

    template<typename CharT>
    constexpr bool operator!=(const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return !(lhs == rhs);
    }

    template<typename CharT>
    constexpr bool operator < (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) < 0;
    }

    template<typename CharT>
    constexpr bool operator <= (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) <= 0;
    }

    template<typename CharT>
    constexpr bool operator > (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) > 0;
    }

    template<typename CharT>
    constexpr bool operator >= (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) >= 0;
    }

    // OStream conversion
    template <typename CharT, typename Traits>
    std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
        const_expr_string<CharT> v)
    {
        return os << v.data();
    }
} // namespace const_expr_string
<commit_msg>Updated TODO comments on the Compare functions<commit_after>#include <iostream>
#include <stdexcept>
#include <limits>
#include <type_traits>

namespace const_expr_string
{
    // Definition
    template<typename CharT>
    class const_expr_string
    {
        public:
            using value_type = CharT;
            using traits_type = std::char_traits<value_type>;
            using size_type = size_t;
            using difference_type = std::ptrdiff_t;
            using const_pointer = const CharT *;
            using pointer = const_pointer;
            using const_reference = const CharT&;
            using reference = const_reference;
            using const_iterator = const CharT*;
            using iterator = const_iterator;
            using const_reverse_iterator = std::reverse_iterator<const_iterator>;
            using reverse_iterator = const_reverse_iterator;
            static constexpr size_type npos = size_type(-1);

            // Constructors
            constexpr const_expr_string(const_pointer data) noexcept;
            constexpr const_expr_string(const const_expr_string<CharT>& other) = default;

            // Size based
            constexpr size_t length() const noexcept;
            constexpr size_t size() const noexcept;
            constexpr size_type max_size() const noexcept;
            constexpr bool empty() const noexcept;

            // Conversion operator
            constexpr operator const_pointer() const noexcept;

            // Iterators
            constexpr iterator begin() const noexcept;
            constexpr const_iterator cbegin() const noexcept;
            constexpr iterator end() const noexcept;
            constexpr const_iterator cend() const noexcept;

            // TODO: Fix reverse_iterator functions!
            //Can't be constexpr without a reverse_iterator type
            //constexpr const_reverse_iterator rbegin() const noexcept;
            //constexpr const_reverse_iterator crbegin() const noexcept;
            //constexpr const_reverse_iterator rend() const noexcept;
            //constexpr const_reverse_iterator crend() const noexcept;

            // Indexing
            constexpr const_reference operator[](size_type pos) const;
            constexpr const_reference at(size_type pos) const;

            // ref positions
            constexpr const_reference front() const;
            constexpr const_reference back() const;

            // Data member
            constexpr const_pointer data() const noexcept;

            // Compares
            constexpr int compare (const_expr_string v) const;
            constexpr int compare (size_type pos1, size_type count1, const_expr_string v) const;
            constexpr int compare (size_type pos1, size_type count1, const_expr_string v,
                    size_type pos2, size_type count2) const;
            constexpr int compare (const_pointer s) const;
            constexpr int compare (size_type pos1, size_type count1, const_pointer s) const;
            constexpr int compare (size_type pos1, size_type count1, const_pointer s, size_type count2) const;

            // Finds
            constexpr size_type find(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type rfind(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type rfind(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type rfind(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type rfind(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_first_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_last_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_first_not_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_not_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_not_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_first_not_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
            constexpr size_type find_last_not_of(const_expr_string v, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_not_of(value_type c, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_not_of(const_pointer, size_type pos = 0) const;// TODO: not implemented
            constexpr size_type find_last_not_of(const_pointer, size_type pos, size_type count) const;// TODO: not implemented
        private:
            const_pointer _data;
            static constexpr size_type str_len(const char* str)
            {
                size_type i = 0;
                while (str[i] != '\0') ++i;
                return i;
            }
    };

    // Implementation
    template <typename CharT>
    constexpr const_expr_string<CharT>::const_expr_string(
            const_expr_string<CharT>::const_pointer data) noexcept
    : _data(data)
    {
    }

    template <typename CharT>
    constexpr const_expr_string<CharT>::operator
            const_expr_string<CharT>::const_pointer() const noexcept
    {
        return _data;
    }

    template <typename CharT>
    constexpr size_t const_expr_string<CharT>::length() const noexcept
    {
        return const_expr_string<CharT>::str_len(_data);
    }

    template <typename CharT>
    constexpr size_t const_expr_string<CharT>::size() const noexcept
    {
        return length();
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::iterator const_expr_string<CharT>::begin() const noexcept
    {
        return &*_data;
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::const_iterator const_expr_string<CharT>::cbegin() const noexcept
    {
        return begin();
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::iterator const_expr_string<CharT>::end() const noexcept
    {
        return _data + size();
    }

    template <typename CharT>
    constexpr typename const_expr_string<CharT>::const_iterator const_expr_string<CharT>::cend() const noexcept
    {
        return end();
    }

    //Can't be constexpr without a reverse_iterator type
    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::reverse_iterator const_expr_string<CharT>::rbegin() const noexcept
    //{
    //    return const_reverse_iterator(end());
    //}

    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::const_reverse_iterator const_expr_string<CharT>::crbegin() const noexcept
    //{
    //    return rbegin();
    //}

    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::reverse_iterator const_expr_string<CharT>::rend() const noexcept
    //{
    //    return const_reverse_iterator(begin());
    //}

    //template <typename CharT>
    //constexpr typename const_expr_string<CharT>::const_reverse_iterator const_expr_string<CharT>::crend() const noexcept
    //{
    //    return rend();
    //}

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::operator[](const_expr_string<CharT>::size_type pos) const
    {
        return _data[pos];
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::at(const_expr_string<CharT>::size_type pos) const
    {
        return pos >= size() ?
            throw std::out_of_range("call to at with too large index") :
            operator[](pos);
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_pointer const_expr_string<CharT>::data() const noexcept
    {
        return _data;
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::front() const
    {
        return operator[](0);
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::const_reference const_expr_string<CharT>::back() const
    {
        return operator[](size() - 1);
    }

    template<typename CharT>
    constexpr typename const_expr_string<CharT>::size_type const_expr_string<CharT>::max_size() const noexcept
    {
        // reserves npos to be an illegal index
        return std::numeric_limits<size_type>::max() - 1;
    }

    template<typename CharT>
    constexpr bool const_expr_string<CharT>::empty() const noexcept
    {
        return _data[0] == '\0';
    }

    // Compare functions
    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (const_expr_string<CharT> v) const
    {
        return compare(0, size(), v, 0, size());
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_expr_string v) const
    {
        return compare (pos1, count1, v, 0, v.size());
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_expr_string v,
            const_expr_string<CharT>::size_type pos2,
            const_expr_string<CharT>::size_type count2) const
    {
        typename const_expr_string<CharT>::size_type lhsSize = count1;
        typename const_expr_string<CharT>::size_type rhsSize = count2;

        if (lhsSize < rhsSize) return -1;
        if (lhsSize > rhsSize) return 1;

        for (const_expr_string<CharT>::size_type i = 0; i < lhsSize; ++i)
        {
            if (_data[i + pos1] < v._data[i + pos2]) return -1;
            if (_data[i + pos1] > v._data[i + pos2]) return 1;
        }

        return 0;
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (
            typename const_expr_string<CharT>::const_pointer s) const
    {
        return compare(0, size(), s, str_len(s));
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (
            typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_pointer s) const
    {
        return compare(pos1, count1, s, str_len(s));
    }

    template<typename CharT>
    constexpr int const_expr_string<CharT>::compare (
            typename const_expr_string<CharT>::size_type pos1,
            typename const_expr_string<CharT>::size_type count1,
            typename const_expr_string<CharT>::const_pointer s,
            typename const_expr_string<CharT>::size_type count2) const
    {
        return compare(pos1, count1, const_expr_string<CharT>(s), 0, count2);
    }

    // compare operators
    template<typename CharT>
    constexpr bool operator==(const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) == 0;
    }

    template<typename CharT>
    constexpr bool operator!=(const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return !(lhs == rhs);
    }

    template<typename CharT>
    constexpr bool operator < (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) < 0;
    }

    template<typename CharT>
    constexpr bool operator <= (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) <= 0;
    }

    template<typename CharT>
    constexpr bool operator > (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) > 0;
    }

    template<typename CharT>
    constexpr bool operator >= (const_expr_string<CharT> lhs, const_expr_string<CharT> rhs)
    {
        return lhs.compare(rhs) >= 0;
    }

    // OStream conversion
    template <typename CharT, typename Traits>
    std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
        const_expr_string<CharT> v)
    {
        return os << v.data();
    }
} // namespace const_expr_string
<|endoftext|>


<commit_before>//
// Copyright (c) 2020 INRIA
//

#ifndef __eigenpy_user_type_hpp__
#define __eigenpy_user_type_hpp__

#include "eigenpy/fwd.hpp"
#include "eigenpy/numpy-type.hpp"
#include "eigenpy/register.hpp"

namespace eigenpy
{
  namespace internal
  {
    template<typename T, int type_code = NumpyEquivalentType<T>::type_code>
    struct SpecialMethods
    {
      inline static void copyswap(void * /*dst*/, void * /*src*/, int /*swap*/, void * /*arr*/) /*{}*/;
      inline static PyObject * getitem(void * /*ip*/, void * /*ap*/) /*{ return NULL; }*/;
      inline static int setitem(PyObject * /*op*/, void * /*ov*/, void * /*ap*/) /*{ return -1; }*/;
      inline static void copyswapn(void * /*dest*/, long /*dstride*/, void * /*src*/,
                            long /*sstride*/, long /*n*/, int /*swap*/, void * /*arr*/) /*{}*/;
      inline static npy_bool nonzero(void * /*ip*/, void * /*array*/) /*{ return (npy_bool)false; }*/;
      inline static void dotfunc(void * /*ip0_*/, npy_intp /*is0*/, void * /*ip1_*/, npy_intp /*is1*/,
                          void * /*op*/, npy_intp /*n*/, void * /*arr*/);
      inline static int fillwithscalar(void* buffer_, npy_intp length,
                                       void* value, void* arr);
//      static void cast(void * /*from*/, void * /*to*/, npy_intp /*n*/, void * /*fromarr*/, void * /*toarr*/) {};
    };

    template<typename T>
    struct OffsetOf
    {
      struct Data
      {
        char c;
        T v;
      };

      enum { value = offsetof(Data, v) };
    };

    template<typename T>
    struct SpecialMethods<T,NPY_USERDEF>
    {
      inline static void copyswap(void * dst, void * src, int swap, void * /*arr*/)
      {
//        std::cout << "copyswap" << std::endl;
        if (src != NULL)
        {
          T & t1 = *static_cast<T*>(dst);
          T & t2 = *static_cast<T*>(src);
          t1 = t2;
        }

        if(swap)
        {
          T & t1 = *static_cast<T*>(dst);
          T & t2 = *static_cast<T*>(src);
          std::swap(t1,t2);
        }
      }

      inline static PyObject * getitem(void * ip, void * ap)
      {
//        std::cout << "getitem" << std::endl;
        PyArrayObject * py_array = static_cast<PyArrayObject *>(ap);
        if((py_array==NULL) || PyArray_ISBEHAVED_RO(py_array))
        {
          T * elt_ptr = static_cast<T*>(ip);
          bp::object m(boost::ref(*elt_ptr));
          Py_INCREF(m.ptr());
          return m.ptr();
        }
        else
        {
          T * elt_ptr = static_cast<T*>(ip);
          bp::object m(boost::ref(*elt_ptr));
          Py_INCREF(m.ptr());
          return m.ptr();
        }
      }

      inline static int setitem(PyObject * src_obj, void * dest_ptr, void * array)
      {
//        std::cout << "setitem" << std::endl;
        if(array == NULL)
        {
          eigenpy::Exception("Cannot retrieve the type stored in the array.");
          return -1;
        }
        PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
        PyArray_Descr * descr = PyArray_DTYPE(py_array);
        PyTypeObject * array_scalar_type = descr->typeobj;
        PyTypeObject * src_obj_type = Py_TYPE(src_obj);

        if(array_scalar_type != src_obj_type)
        {
          return -1;
        }

        bp::extract<T&> extract_src_obj(src_obj);
        if(!extract_src_obj.check())
        {
          std::stringstream ss;
          ss << "The input type is of wrong type. ";
          ss << "The expected type is " << bp::type_info(typeid(T)).name() << std::endl;
          eigenpy::Exception(ss.str());
          return -1;
        }

        const T & src = extract_src_obj();
        T & dest = *static_cast<T*>(dest_ptr);
        dest = src;

        return 0;
      }

      inline static void copyswapn(void * dst, long dstride, void * src, long sstride,
                                   long n, int swap, void * array)
      {
//        std::cout << "copyswapn" << std::endl;

        char *dstptr = static_cast<char*>(dst);
        char *srcptr = static_cast<char*>(src);

        PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
        PyArray_CopySwapFunc * copyswap = PyArray_DESCR(py_array)->f->copyswap;

        for (npy_intp i = 0; i < n; i++)
        {
          copyswap(dstptr, srcptr, swap, array);
          dstptr += dstride;
          srcptr += sstride;
        }
      }

      inline static npy_bool nonzero(void * ip, void * array)
      {
//        std::cout << "nonzero" << std::endl;
        static const T ZeroValue = T(0);
        PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
        if(py_array == NULL || PyArray_ISBEHAVED_RO(py_array))
        {
          const T & value = *static_cast<T*>(ip);
          return (npy_bool)(value != ZeroValue);
        }
        else
        {
          T tmp_value;
          PyArray_DESCR(py_array)->f->copyswap(&tmp_value, ip, PyArray_ISBYTESWAPPED(py_array),
                                               array);
          return (npy_bool)(tmp_value != ZeroValue);
        }
      }

      inline static void dotfunc(void * ip0_, npy_intp is0, void * ip1_, npy_intp is1,
                                 void * op, npy_intp n, void * /*arr*/)
      {
          T res = T(0);
          char *ip0 = (char*)ip0_, *ip1 = (char*)ip1_;
          npy_intp i;
          for(i = 0; i < n; i++)
          {

            res += *static_cast<T*>(static_cast<void*>(ip0))
            * *static_cast<T*>(static_cast<void*>(ip1));
            ip0 += is0;
            ip1 += is1;
          }
          *static_cast<T*>(op) = res;
      }

      inline static int fillwithscalar(void* buffer_, npy_intp length,
                                       void* value, void* /*arr*/)
      {
        T r = *(T*)value;
        T* buffer = (T*)buffer_;
        npy_intp i;
        for (i = 0; i < length; i++) {
          buffer[i] = r;
        }
        return 0;
      }

//      static void cast(void * from, void * to, npy_intp n, void * fromarr, void * toarr)
//      {
//      }

    };

  } // namespace internal

  template<typename Scalar>
  int registerNewType(PyTypeObject * py_type_ptr = NULL)
  {
    // Check whether the type is a Numpy native type.
    // In this case, the registration is not required.
    if(isNumpyNativeType<Scalar>())
      return NumpyEquivalentType<Scalar>::type_code;

    // Retrieve the registered type for the current Scalar
    if(py_type_ptr == NULL)
    { // retrive the type from Boost.Python
      py_type_ptr = Register::getPyType<Scalar>();
    }

    if(Register::isRegistered(py_type_ptr))
      return Register::getTypeCode(py_type_ptr); // the type is already registered

    PyArray_GetItemFunc * getitem = &internal::SpecialMethods<Scalar>::getitem;
    PyArray_SetItemFunc * setitem = &internal::SpecialMethods<Scalar>::setitem;
    PyArray_NonzeroFunc * nonzero = &internal::SpecialMethods<Scalar>::nonzero;
    PyArray_CopySwapFunc * copyswap = &internal::SpecialMethods<Scalar>::copyswap;
    PyArray_CopySwapNFunc * copyswapn = reinterpret_cast<PyArray_CopySwapNFunc*>(&internal::SpecialMethods<Scalar>::copyswapn);
    PyArray_DotFunc * dotfunc = &internal::SpecialMethods<Scalar>::dotfunc;
    PyArray_FillWithScalarFunc * fillwithscalar = &internal::SpecialMethods<Scalar>::fillwithscalar;
//    PyArray_CastFunc * cast = &internal::SpecialMethods<Scalar>::cast;

    int code = Register::registerNewType(py_type_ptr,
                                         &typeid(Scalar),
                                         sizeof(Scalar),
                                         internal::OffsetOf<Scalar>::value,
                                         getitem, setitem, nonzero,
                                         copyswap, copyswapn,
                                         dotfunc,
                                         fillwithscalar);

    call_PyArray_RegisterCanCast(call_PyArray_DescrFromType(NPY_OBJECT),
                                 code, NPY_NOSCALAR);

    return code;
  }

} // namespace eigenpy

#endif // __eigenpy_user_type_hpp__
<commit_msg>user-type.hpp: add doc for setitem and getitem + minor changes<commit_after>//
// Copyright (c) 2020 INRIA
//

#ifndef __eigenpy_user_type_hpp__
#define __eigenpy_user_type_hpp__

#include "eigenpy/fwd.hpp"
#include "eigenpy/numpy-type.hpp"
#include "eigenpy/register.hpp"

namespace eigenpy
{
  namespace internal
  {
    template<typename T, int type_code = NumpyEquivalentType<T>::type_code>
    struct SpecialMethods
    {
      inline static void copyswap(void * /*dst*/, void * /*src*/, int /*swap*/, void * /*arr*/) /*{}*/;
      inline static PyObject * getitem(void * /*ip*/, void * /*ap*/) /*{ return NULL; }*/;
      inline static int setitem(PyObject * /*op*/, void * /*ov*/, void * /*ap*/) /*{ return -1; }*/;
      inline static void copyswapn(void * /*dest*/, long /*dstride*/, void * /*src*/,
                            long /*sstride*/, long /*n*/, int /*swap*/, void * /*arr*/) /*{}*/;
      inline static npy_bool nonzero(void * /*ip*/, void * /*array*/) /*{ return (npy_bool)false; }*/;
      inline static void dotfunc(void * /*ip0_*/, npy_intp /*is0*/, void * /*ip1_*/, npy_intp /*is1*/,
                          void * /*op*/, npy_intp /*n*/, void * /*arr*/);
      inline static int fillwithscalar(void* buffer_, npy_intp length,
                                       void* value, void* arr);
//      static void cast(void * /*from*/, void * /*to*/, npy_intp /*n*/, void * /*fromarr*/, void * /*toarr*/) {};
    };

    template<typename T>
    struct OffsetOf
    {
      struct Data
      {
        char c;
        T v;
      };

      enum { value = offsetof(Data, v) };
    };

    template<typename T>
    struct SpecialMethods<T,NPY_USERDEF>
    {
      inline static void copyswap(void * dst, void * src, int swap, void * /*arr*/)
      {
//        std::cout << "copyswap" << std::endl;
        if (src != NULL)
        {
          T & t1 = *static_cast<T*>(dst);
          T & t2 = *static_cast<T*>(src);
          t1 = t2;
        }

        if(swap)
        {
          T & t1 = *static_cast<T*>(dst);
          T & t2 = *static_cast<T*>(src);
          std::swap(t1,t2);
        }
      }

      ///
      /// \brief Get a python object from an array
      ///        It returns a standard Python object from
      ///        a single element of the array object arr pointed to by data.
      /// \param[in] data Pointer to the first element of the C++ data stream
      /// \param[in] arr  Pointer to the first element of the Python object data stream
      ///
      /// \returns PyObject corresponding to the python datastream.
      ///
      inline static PyObject * getitem(void * ip, void * ap)
      {
//      std::cout << "getitem" << std::endl;
        PyArrayObject * py_array = static_cast<PyArrayObject *>(ap);
        T * elt_ptr = static_cast<T*>(ip);
        bp::object m(boost::ref(*elt_ptr));
        Py_INCREF(m.ptr());
        return m.ptr();
      }

      ///
      /// \brief Set a python object in an array.
      ///        It sets the Python object "item" into the array, arr, at the position
      ///        pointed to by data. This function deals with “misbehaved” arrays.
      ///        If successful, a zero is returned, otherwise, a negative one is returned
      ///        (and a Python error set).

      /// \param[in] src_obj  Pointer to the location of the python object
      /// \param[in] dest_ptr Pointer to the location in the array where the source object should be saved.
      /// \param[in] array Pointer to the location of the array
      ///
      /// \returns int Success(0) or Failure(-1)
      ///

      inline static int setitem(PyObject * src_obj, void * dest_ptr, void * array)
      {
//        std::cout << "setitem" << std::endl;
        if(array == NULL)
        {
          eigenpy::Exception("Cannot retrieve the type stored in the array.");
          return -1;
        }
        PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
        PyArray_Descr * descr = PyArray_DTYPE(py_array);
        PyTypeObject * array_scalar_type = descr->typeobj;
        PyTypeObject * src_obj_type = Py_TYPE(src_obj);

        if(array_scalar_type != src_obj_type)
        {
          return -1;
        }

        bp::extract<T&> extract_src_obj(src_obj);
        if(!extract_src_obj.check())
        {
          std::stringstream ss;
          ss << "The input type is of wrong type. ";
          ss << "The expected type is " << bp::type_info(typeid(T)).name() << std::endl;
          eigenpy::Exception(ss.str());
          return -1;
        }

        const T & src = extract_src_obj();
        T & dest = *static_cast<T*>(dest_ptr);
        dest = src;

        return 0;
      }

      inline static void copyswapn(void * dst, long dstride, void * src, long sstride,
                                   long n, int swap, void * array)
      {
//        std::cout << "copyswapn" << std::endl;

        char *dstptr = static_cast<char*>(dst);
        char *srcptr = static_cast<char*>(src);

        PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
        PyArray_CopySwapFunc * copyswap = PyArray_DESCR(py_array)->f->copyswap;

        for (npy_intp i = 0; i < n; i++)
        {
          copyswap(dstptr, srcptr, swap, array);
          dstptr += dstride;
          srcptr += sstride;
        }
      }

      inline static npy_bool nonzero(void * ip, void * array)
      {
//        std::cout << "nonzero" << std::endl;
        static const T ZeroValue = T(0);
        PyArrayObject * py_array = static_cast<PyArrayObject *>(array);
        if(py_array == NULL || PyArray_ISBEHAVED_RO(py_array))
        {
          const T & value = *static_cast<T*>(ip);
          return (npy_bool)(value != ZeroValue);
        }
        else
        {
          T tmp_value;
          PyArray_DESCR(py_array)->f->copyswap(&tmp_value, ip, PyArray_ISBYTESWAPPED(py_array),
                                               array);
          return (npy_bool)(tmp_value != ZeroValue);
        }
      }

      inline static void dotfunc(void * ip0_, npy_intp is0, void * ip1_, npy_intp is1,
                                 void * op, npy_intp n, void * /*arr*/)
      {
          T res = T(0);
          char *ip0 = (char*)ip0_, *ip1 = (char*)ip1_;
          npy_intp i;
          for(i = 0; i < n; i++)
          {

            res += *static_cast<T*>(static_cast<void*>(ip0))
            * *static_cast<T*>(static_cast<void*>(ip1));
            ip0 += is0;
            ip1 += is1;
          }
          *static_cast<T*>(op) = res;
      }

      inline static int fillwithscalar(void* buffer_, npy_intp length,
                                       void* value, void* /*arr*/)
      {
        T r = *(T*)value;
        T* buffer = (T*)buffer_;
        npy_intp i;
        for (i = 0; i < length; i++) {
          buffer[i] = r;
        }
        return 0;
      }

//      static void cast(void * from, void * to, npy_intp n, void * fromarr, void * toarr)
//      {
//      }

    };  //     struct SpecialMethods<T,NPY_USERDEF>

  } // namespace internal

  template<typename Scalar>
  int registerNewType(PyTypeObject * py_type_ptr = NULL)
  {
    // Check whether the type is a Numpy native type.
    // In this case, the registration is not required.
    if(isNumpyNativeType<Scalar>())
      return NumpyEquivalentType<Scalar>::type_code;

    // Retrieve the registered type for the current Scalar
    if(py_type_ptr == NULL)
    { // retrive the type from Boost.Python
      py_type_ptr = Register::getPyType<Scalar>();
    }

    if(Register::isRegistered(py_type_ptr))
      return Register::getTypeCode(py_type_ptr); // the type is already registered

    PyArray_GetItemFunc * getitem = &internal::SpecialMethods<Scalar>::getitem;
    PyArray_SetItemFunc * setitem = &internal::SpecialMethods<Scalar>::setitem;
    PyArray_NonzeroFunc * nonzero = &internal::SpecialMethods<Scalar>::nonzero;
    PyArray_CopySwapFunc * copyswap = &internal::SpecialMethods<Scalar>::copyswap;
    PyArray_CopySwapNFunc * copyswapn = reinterpret_cast<PyArray_CopySwapNFunc*>(&internal::SpecialMethods<Scalar>::copyswapn);
    PyArray_DotFunc * dotfunc = &internal::SpecialMethods<Scalar>::dotfunc;
    PyArray_FillWithScalarFunc * fillwithscalar = &internal::SpecialMethods<Scalar>::fillwithscalar;
//    PyArray_CastFunc * cast = &internal::SpecialMethods<Scalar>::cast;

    int code = Register::registerNewType(py_type_ptr,
                                         &typeid(Scalar),
                                         sizeof(Scalar),
                                         internal::OffsetOf<Scalar>::value,
                                         getitem, setitem, nonzero,
                                         copyswap, copyswapn,
                                         dotfunc,
                                         fillwithscalar);

    call_PyArray_RegisterCanCast(call_PyArray_DescrFromType(NPY_OBJECT),
                                 code, NPY_NOSCALAR);

    return code;
  }

} // namespace eigenpy

#endif // __eigenpy_user_type_hpp__
<|endoftext|>