<commit_before>#include "i2c.h"
#include <ppltasks.h>
#include <vector>
#include <iostream>

using v8::FunctionTemplate;
using namespace concurrency;
using namespace Platform;
using namespace Windows::Devices::Enumeration;

Nan::Persistent<v8::Function> WinI2c::constructor;

NAN_MODULE_INIT(WinI2c::Init) {
  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("WinI2c").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(6);

  Nan::SetPrototypeMethod(tpl, "openSync", OpenSync);
  Nan::SetPrototypeMethod(tpl, "closeSync", CloseSync);
  Nan::SetPrototypeMethod(tpl, "read", Read);
  Nan::SetPrototypeMethod(tpl, "readPartial", ReadPartial);
  Nan::SetPrototypeMethod(tpl, "write", Write);
  Nan::SetPrototypeMethod(tpl, "writePartial", WritePartial);
  Nan::SetPrototypeMethod(tpl, "writeRead", WriteRead);
  Nan::SetPrototypeMethod(tpl, "writeReadPartial", WriteReadPartial);
  Nan::SetPrototypeMethod(tpl, "setDevice", SetDevice);

  constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
  Nan::Set(target, Nan::New("WinI2c").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
}

WinI2c::WinI2c() {
  RoInitialize(RO_INIT_MULTITHREADED);
}

WinI2c::~WinI2c() {
  RoUninitialize();
}

NAN_METHOD(WinI2c::New) {
  if (info.IsConstructCall()) {
    WinI2c *obj = new WinI2c();
    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }
  else {
    const int argc = 1;
    v8::Local<v8::Value> argv[argc] = { info[0] };
    v8::Local<v8::Function> cons = Nan::New(constructor);
    info.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

NAN_METHOD(WinI2c::OpenSync) {
  if (info.Length() < 1 ||
      !info[0]->IsString()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::OpenSync",
      "incorrect arguments passed to WinI2c::OpenSync"
      "(string i2cControllerName)"));
  }

  Nan::HandleScope scope;
  v8::String::Utf8Value str(info[0]->ToString());
  std::string stdStr = std::string(*str);
  std::wstring stdWStr;
  stdWStr.assign(stdStr.begin(), stdStr.end());

  String^ deviceSelector = I2cDevice::GetDeviceSelector(ref new Platform::String(stdWStr.c_str()));
  DeviceInformationCollection^ i2cDeviceControllers = create_task(DeviceInformation::FindAllAsync(deviceSelector)).get();

  if (nullptr == i2cDeviceControllers) {
    Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::OpenSync", "DeviceInformation::FindAllAsync failed to return controller(s)"));
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  obj->_i2cDeviceId = i2cDeviceControllers->GetAt(0)->Id;
}

NAN_METHOD(WinI2c::SetDevice) {
  if (info.Length() < 1 ||
      !info[0]->IsInt32()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::SetDevice",
      "incorrect arguments passed to WinI2c::SetDevice"
      "(int deviceAddress)"));
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());

  if(nullptr == obj->_i2cDevice) {
    I2cConnectionSettings^ settings = ref new I2cConnectionSettings(info[0]->Int32Value());

    //TODO: Expose as properties for the user to change
    settings->BusSpeed = I2cBusSpeed::FastMode;
    settings->SharingMode = I2cSharingMode::Exclusive;

    obj->_i2cDevice = create_task(I2cDevice::FromIdAsync(obj->_i2cDeviceId, settings)).get();
    if (nullptr == obj->_i2cDevice) {
      Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::SetDevice", "I2cDevice::FromIdAsync failed to return an i2c device"));
    }
  }
}

NAN_METHOD(WinI2c::CloseSync) {
  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());

  //From https://msdn.microsoft.com/en-us/library/windows.devices.i2c.i2cdevice.close.aspx
  // You cannot call Close methods through Visual C++ component extensions(C++ / CX) on
  // Windows Runtime class instances where the class implemented IClosable.Instead, C++ / CX code
  // for runtime classes should call the destructor or set the last reference to null.
  obj->_i2cDevice = nullptr;
}

NAN_METHOD(WinI2c::Read) {
  Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::Read", "Not Implemented"));
}

NAN_METHOD(WinI2c::ReadPartial) {
  if (info.Length() < 2 ||
      !info[0]->IsInt32() ||
      !info[1]->IsObject()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::ReadPartial",
      "incorrect arguments passed to WinI2c::ReadPartial"
      "(int length, Buffer buffer)"));
  }

  Nan::HandleScope scope;
  uint32 length = info[0]->Uint32Value();
  v8::Local<v8::Object> bufferHandle = info[1].As<v8::Object>();
  int bytesRead = -1;
  byte* bufferData = (byte*)node::Buffer::Data(bufferHandle);
  size_t bufferLength = node::Buffer::Length(bufferHandle);

  if (length > bufferLength) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::ReadPartial",
      "buffer passed to WinI2c::Read contains less than 'length' bytes"));
  }

  auto readBuf = ref new Platform::Array<BYTE>(length);
  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    I2cTransferResult result = obj->_i2cDevice->ReadPartial(readBuf);

    switch (result.Status) {
      case I2cTransferStatus::FullTransfer:
        bytesRead = result.BytesTransferred;
        break;
      case I2cTransferStatus::PartialTransfer:
        bytesRead = result.BytesTransferred;
        wprintf(L"%d bytes partially transferred\n", bytesRead);
        break;
      case I2cTransferStatus::SlaveAddressNotAcknowledged:
        wprintf(L"Slave address was not acknowledged\n");
        break;
      default:
        wprintf(L"Invalid transfer status value\n");
    }
  }
  catch (Exception^ e) {
    Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::ReadPartial", ""));
  }

  for (int i = 0; i < readBuf->Length; i++) {
    bufferData[i] = readBuf[i];
  }

  if (bytesRead == -1) {
    return Nan::ThrowError(Nan::ErrnoException(errno, "WinI2c::ReadPartial", ""));
  }

  info.GetReturnValue().Set(Nan::New<v8::Integer>(bytesRead));
}

NAN_METHOD(WinI2c::Write) {
  if (info.Length() < 1 || !info[0]->IsArray()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::Write",
      "incorrect arguments passed to WinI2c::Write"));
  }

  Nan::HandleScope scope;
  std::vector<BYTE> bytes;
  v8::Handle<v8::Value> val;
  v8::Local<v8::Array> arr = Nan::New<v8::Array>();

  v8::Handle<v8::Array> jsArray = v8::Handle<v8::Array>::Cast(info[0]);
  for (unsigned int i = 0; i < jsArray->Length(); i++) {
    val = jsArray->Get(i);
    bytes.push_back(static_cast<BYTE>(val->Uint32Value()));
    Nan::Set(arr, i, val);
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    obj->_i2cDevice->Write(ArrayReference<BYTE>(bytes.data(), static_cast<unsigned int>(bytes.size())));
  } catch (Exception^ e) {
    Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::Write", ""));
  }
}

NAN_METHOD(WinI2c::WritePartial) {
  if (info.Length() < 2 ||
      !info[0]->IsInt32() ||
      !info[1]->IsObject()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WritePartial",
      "incorrect arguments passed to WinI2c::WritePartial"
      "(int length, Buffer buffer)"));
  }

  Nan::HandleScope scope;
  uint32 length = info[0]->Uint32Value();
  v8::Local<v8::Object> bufferHandle = info[1].As<v8::Object>();
  int bytesWritten = -1;
  byte* bufferData = (byte*)node::Buffer::Data(bufferHandle);
  size_t bufferLength = node::Buffer::Length(bufferHandle);

  if (length > bufferLength) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WritePartial",
      "buffer passed to WinI2c::WritePartial contains less than 'length' bytes"));
  }

  auto writeBuf = ref new Platform::Array<BYTE>(length);

  for (int i = 0; i < writeBuf->Length; i++) {
    writeBuf->set(i, bufferData[i]);
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    I2cTransferResult result = obj->_i2cDevice->WritePartial(writeBuf);
    switch (result.Status) {
      case I2cTransferStatus::FullTransfer:
        bytesWritten = result.BytesTransferred;
        break;
      case I2cTransferStatus::PartialTransfer:
        bytesWritten = result.BytesTransferred;
        wprintf(L"%d bytes partially transferred\n", bytesWritten);
        break;
      case I2cTransferStatus::SlaveAddressNotAcknowledged:
        wprintf(L"Slave address was not acknowledged\n");
        break;
      default:
        wprintf(L"Invalid transfer status value\n");
    }
  }
  catch (Exception^ e) {
    Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::WritePartial", ""));
  }

  if (bytesWritten == -1) {
    return Nan::ThrowError(Nan::ErrnoException(errno, "WinI2c::WritePartial", ""));
  }

  info.GetReturnValue().Set(Nan::New<v8::Integer>(bytesWritten));
}

NAN_METHOD(WinI2c::WriteRead) {
  Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::WriteRead", "Not Implemented"));
}

NAN_METHOD(WinI2c::WriteReadPartial) {
  if (info.Length() < 3 ||
      !info[0]->IsInt32() ||
      !info[1]->IsInt32() ||
      !info[2]->IsObject()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WriteReadPartial",
      "incorrect arguments passed to WinI2c::WriteReadPartial"
      "(int cmd, int length, Buffer buffer)"));
  }

  Nan::HandleScope scope;
  uint32 length = info[1]->Uint32Value();
  v8::Local<v8::Object> bufferHandle = info[2].As<v8::Object>();
  int bytesRead = -1;
  byte* bufferData = (byte*)node::Buffer::Data(bufferHandle);
  size_t bufferLength = node::Buffer::Length(bufferHandle);

  if (length > bufferLength) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WriteReadPartial",
      "buffer passed to WinI2c::WriteReadPartial contains less than 'length' bytes"));
  }

  auto readBuf = ref new Platform::Array<BYTE>(length);
  auto writeBuf = ref new Platform::Array<BYTE>(1);
  writeBuf->set(0, info[0]->Int32Value());

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    I2cTransferResult result = obj->_i2cDevice->WriteReadPartial(writeBuf, readBuf);
    switch (result.Status) {
      case I2cTransferStatus::FullTransfer:
        bytesRead = result.BytesTransferred;
        break;
      case I2cTransferStatus::PartialTransfer:
        bytesRead = result.BytesTransferred;
        wprintf(L"%d bytes partially transferred\n", bytesRead);
        break;
      case I2cTransferStatus::SlaveAddressNotAcknowledged:
        wprintf(L"Slave address was not acknowledged\n");
        break;
      default:
        wprintf(L"Invalid transfer status value\n");
    }
  }
  catch (Exception^ e) {
    Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::WriteReadPartial", ""));
  }

  for (int i = 0; i < readBuf->Length; i++) {
    bufferData[i] = readBuf[i];
  }

  if (bytesRead == -1) {
    return Nan::ThrowError(Nan::ErrnoException(errno, "WinI2c::WriteReadPartial", ""));
  }

  info.GetReturnValue().Set(Nan::New<v8::Integer>(bytesRead));
}

NODE_MODULE(i2c, WinI2c::Init)
<commit_msg>Removing unnecessary handlescopes<commit_after>#include "i2c.h"
#include <ppltasks.h>
#include <vector>
#include <iostream>

using v8::FunctionTemplate;
using namespace concurrency;
using namespace Platform;
using namespace Windows::Devices::Enumeration;

Nan::Persistent<v8::Function> WinI2c::constructor;

NAN_MODULE_INIT(WinI2c::Init) {
  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("WinI2c").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(6);

  Nan::SetPrototypeMethod(tpl, "openSync", OpenSync);
  Nan::SetPrototypeMethod(tpl, "closeSync", CloseSync);
  Nan::SetPrototypeMethod(tpl, "read", Read);
  Nan::SetPrototypeMethod(tpl, "readPartial", ReadPartial);
  Nan::SetPrototypeMethod(tpl, "write", Write);
  Nan::SetPrototypeMethod(tpl, "writePartial", WritePartial);
  Nan::SetPrototypeMethod(tpl, "writeRead", WriteRead);
  Nan::SetPrototypeMethod(tpl, "writeReadPartial", WriteReadPartial);
  Nan::SetPrototypeMethod(tpl, "setDevice", SetDevice);

  constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
  Nan::Set(target, Nan::New("WinI2c").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
}

WinI2c::WinI2c() {
  RoInitialize(RO_INIT_MULTITHREADED);
}

WinI2c::~WinI2c() {
  RoUninitialize();
}

NAN_METHOD(WinI2c::New) {
  if (info.IsConstructCall()) {
    WinI2c *obj = new WinI2c();
    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }
  else {
    const int argc = 1;
    v8::Local<v8::Value> argv[argc] = { info[0] };
    v8::Local<v8::Function> cons = Nan::New(constructor);
    info.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

NAN_METHOD(WinI2c::OpenSync) {
  if (info.Length() < 1 ||
      !info[0]->IsString()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::OpenSync",
      "incorrect arguments passed to WinI2c::OpenSync"
      "(string i2cControllerName)"));
  }

  v8::String::Utf8Value str(info[0]->ToString());
  std::string stdStr = std::string(*str);
  std::wstring stdWStr;
  stdWStr.assign(stdStr.begin(), stdStr.end());

  String^ deviceSelector = I2cDevice::GetDeviceSelector(ref new Platform::String(stdWStr.c_str()));
  DeviceInformationCollection^ i2cDeviceControllers = create_task(DeviceInformation::FindAllAsync(deviceSelector)).get();

  if (nullptr == i2cDeviceControllers) {
    return Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::OpenSync", "DeviceInformation::FindAllAsync failed to return controller(s)"));
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  obj->_i2cDeviceId = i2cDeviceControllers->GetAt(0)->Id;
}

NAN_METHOD(WinI2c::SetDevice) {
  if (info.Length() < 1 ||
      !info[0]->IsInt32()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::SetDevice",
      "incorrect arguments passed to WinI2c::SetDevice"
      "(int deviceAddress)"));
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());

  if(nullptr == obj->_i2cDevice) {
    I2cConnectionSettings^ settings = ref new I2cConnectionSettings(info[0]->Int32Value());

    //TODO: Expose as properties for the user to change
    settings->BusSpeed = I2cBusSpeed::FastMode;
    settings->SharingMode = I2cSharingMode::Exclusive;

    obj->_i2cDevice = create_task(I2cDevice::FromIdAsync(obj->_i2cDeviceId, settings)).get();
    if (nullptr == obj->_i2cDevice) {
      return Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::SetDevice", "I2cDevice::FromIdAsync failed to return an i2c device"));
    }
  }
}

NAN_METHOD(WinI2c::CloseSync) {
  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());

  //From https://msdn.microsoft.com/en-us/library/windows.devices.i2c.i2cdevice.close.aspx
  // You cannot call Close methods through Visual C++ component extensions(C++ / CX) on
  // Windows Runtime class instances where the class implemented IClosable.Instead, C++ / CX code
  // for runtime classes should call the destructor or set the last reference to null.
  obj->_i2cDevice = nullptr;
}

NAN_METHOD(WinI2c::Read) {
  return Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::Read", "Not Implemented"));
}

NAN_METHOD(WinI2c::ReadPartial) {
  if (info.Length() < 2 ||
      !info[0]->IsInt32() ||
      !info[1]->IsObject()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::ReadPartial",
      "incorrect arguments passed to WinI2c::ReadPartial"
      "(int length, Buffer buffer)"));
  }

  uint32 length = info[0]->Uint32Value();
  v8::Local<v8::Object> bufferHandle = info[1].As<v8::Object>();
  int bytesRead = -1;
  byte* bufferData = (byte*)node::Buffer::Data(bufferHandle);
  size_t bufferLength = node::Buffer::Length(bufferHandle);

  if (length > bufferLength) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::ReadPartial",
      "buffer passed to WinI2c::Read contains less than 'length' bytes"));
  }

  auto readBuf = ref new Platform::Array<BYTE>(length);
  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    I2cTransferResult result = obj->_i2cDevice->ReadPartial(readBuf);

    switch (result.Status) {
      case I2cTransferStatus::FullTransfer:
        bytesRead = result.BytesTransferred;
        break;
      case I2cTransferStatus::PartialTransfer:
        bytesRead = result.BytesTransferred;
        wprintf(L"%d bytes partially transferred\n", bytesRead);
        break;
      case I2cTransferStatus::SlaveAddressNotAcknowledged:
        wprintf(L"Slave address was not acknowledged\n");
        break;
      default:
        wprintf(L"Invalid transfer status value\n");
    }
  }
  catch (Exception^ e) {
    return Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::ReadPartial", ""));
  }

  for (int i = 0; i < readBuf->Length; i++) {
    bufferData[i] = readBuf[i];
  }

  if (bytesRead == -1) {
    return Nan::ThrowError(Nan::ErrnoException(errno, "WinI2c::ReadPartial", ""));
  }

  info.GetReturnValue().Set(Nan::New<v8::Integer>(bytesRead));
}

NAN_METHOD(WinI2c::Write) {
  if (info.Length() < 1 || !info[0]->IsArray()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::Write",
      "incorrect arguments passed to WinI2c::Write"));
  }

  std::vector<BYTE> bytes;
  v8::Handle<v8::Value> val;
  v8::Local<v8::Array> arr = Nan::New<v8::Array>();

  v8::Handle<v8::Array> jsArray = v8::Handle<v8::Array>::Cast(info[0]);
  for (unsigned int i = 0; i < jsArray->Length(); i++) {
    val = jsArray->Get(i);
    bytes.push_back(static_cast<BYTE>(val->Uint32Value()));
    Nan::Set(arr, i, val);
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    obj->_i2cDevice->Write(ArrayReference<BYTE>(bytes.data(), static_cast<unsigned int>(bytes.size())));
  } catch (Exception^ e) {
    return Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::Write", ""));
  }
}

NAN_METHOD(WinI2c::WritePartial) {
  if (info.Length() < 2 ||
      !info[0]->IsInt32() ||
      !info[1]->IsObject()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WritePartial",
      "incorrect arguments passed to WinI2c::WritePartial"
      "(int length, Buffer buffer)"));
  }

  uint32 length = info[0]->Uint32Value();
  v8::Local<v8::Object> bufferHandle = info[1].As<v8::Object>();
  int bytesWritten = -1;
  byte* bufferData = (byte*)node::Buffer::Data(bufferHandle);
  size_t bufferLength = node::Buffer::Length(bufferHandle);

  if (length > bufferLength) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WritePartial",
      "buffer passed to WinI2c::WritePartial contains less than 'length' bytes"));
  }

  auto writeBuf = ref new Platform::Array<BYTE>(length);

  for (int i = 0; i < writeBuf->Length; i++) {
    writeBuf->set(i, bufferData[i]);
  }

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    I2cTransferResult result = obj->_i2cDevice->WritePartial(writeBuf);
    switch (result.Status) {
      case I2cTransferStatus::FullTransfer:
        bytesWritten = result.BytesTransferred;
        break;
      case I2cTransferStatus::PartialTransfer:
        bytesWritten = result.BytesTransferred;
        wprintf(L"%d bytes partially transferred\n", bytesWritten);
        break;
      case I2cTransferStatus::SlaveAddressNotAcknowledged:
        wprintf(L"Slave address was not acknowledged\n");
        break;
      default:
        wprintf(L"Invalid transfer status value\n");
    }
  }
  catch (Exception^ e) {
    return Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::WritePartial", ""));
  }

  if (bytesWritten == -1) {
    return Nan::ThrowError(Nan::ErrnoException(errno, "WinI2c::WritePartial", ""));
  }

  info.GetReturnValue().Set(Nan::New<v8::Integer>(bytesWritten));
}

NAN_METHOD(WinI2c::WriteRead) {
  return Nan::ThrowError(Nan::ErrnoException(EPERM, "WinI2c::WriteRead", "Not Implemented"));
}

NAN_METHOD(WinI2c::WriteReadPartial) {
  if (info.Length() < 3 ||
      !info[0]->IsInt32() ||
      !info[1]->IsInt32() ||
      !info[2]->IsObject()) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WriteReadPartial",
      "incorrect arguments passed to WinI2c::WriteReadPartial"
      "(int cmd, int length, Buffer buffer)"));
  }

  uint32 length = info[1]->Uint32Value();
  v8::Local<v8::Object> bufferHandle = info[2].As<v8::Object>();
  int bytesRead = -1;
  byte* bufferData = (byte*)node::Buffer::Data(bufferHandle);
  size_t bufferLength = node::Buffer::Length(bufferHandle);

  if (length > bufferLength) {
    return Nan::ThrowError(Nan::ErrnoException(EINVAL, "WinI2c::WriteReadPartial",
      "buffer passed to WinI2c::WriteReadPartial contains less than 'length' bytes"));
  }

  auto readBuf = ref new Platform::Array<BYTE>(length);
  auto writeBuf = ref new Platform::Array<BYTE>(1);
  writeBuf->set(0, info[0]->Int32Value());

  WinI2c* obj = Nan::ObjectWrap::Unwrap<WinI2c>(info.This());
  try {
    I2cTransferResult result = obj->_i2cDevice->WriteReadPartial(writeBuf, readBuf);
    switch (result.Status) {
      case I2cTransferStatus::FullTransfer:
        bytesRead = result.BytesTransferred;
        break;
      case I2cTransferStatus::PartialTransfer:
        bytesRead = result.BytesTransferred;
        wprintf(L"%d bytes partially transferred\n", bytesRead);
        break;
      case I2cTransferStatus::SlaveAddressNotAcknowledged:
        wprintf(L"Slave address was not acknowledged\n");
        break;
      default:
        wprintf(L"Invalid transfer status value\n");
    }
  }
  catch (Exception^ e) {
    return Nan::ThrowError(Nan::ErrnoException(e->HResult, "WinI2c::WriteReadPartial", ""));
  }

  for (int i = 0; i < readBuf->Length; i++) {
    bufferData[i] = readBuf[i];
  }

  if (bytesRead == -1) {
    return Nan::ThrowError(Nan::ErrnoException(errno, "WinI2c::WriteReadPartial", ""));
  }

  info.GetReturnValue().Set(Nan::New<v8::Integer>(bytesRead));
}

NODE_MODULE(i2c, WinI2c::Init)
<|endoftext|>


<commit_before>// window.cpp

#ifndef SAMPLES_DIR
#define SAMPLES_DIR ""
#endif

#include <QComboBox>
#include <QDialog>
#include <QFileDialog>
#include <QLabel>
#include <QLineEdit>
#include <QList>
#include <QtMultimedia/QCameraInfo>

#include "window.h"

Window::Window (QWidget* parent)
: QWidget (parent)
, _acquisition ()
, _frame_timer ()
, _holder_layout_img (this)
, _holder_layout_btn (this)
, _layout_app (QBoxLayout::TopToBottom, this)
, _layout_img (&_holder_layout_img)
, _layout_btn (QBoxLayout::LeftToRight, &_holder_layout_btn)
, _btn_pause ("Pause", this)
, _btn_reference ("Set Reference", this)
, _btn_input ("Select Input", this)
, _statusbar (this)
, _augmentation (this) {
    _layout_app.addWidget (&_holder_layout_img);
    _layout_app.addWidget (&_holder_layout_btn);
    _layout_app.addWidget (&_statusbar);

    _layout_img.addWidget (&_augmentation, 0, 0);
    _layout_btn.addWidget (&_btn_pause);
    _layout_btn.addWidget (&_btn_reference);
    _layout_btn.addWidget (&_btn_input);
    _statusbar.setSizeGripEnabled (false);

    connect (&_frame_timer, SIGNAL (timeout ()), this, SLOT (timeout ()));
    connect (&_btn_pause, SIGNAL (clicked ()), this, SLOT (btn_pause_clicked ()));
    connect (&_btn_reference, SIGNAL (clicked ()), this, SLOT (btn_reference_clicked ()));
    connect (&_btn_input, SIGNAL (clicked ()), this, SLOT (btn_input_clicked ()));

    _frame_timer.setInterval (1000 / _framerate);
    _frame_timer.start ();
}

Window::~Window () {
}

QSize Window::minimumSizeHint () const {
    return _layout_app.minimumSize ();
}

QSize Window::sizeHint () const {
    return _layout_app.sizeHint ();
}

void Window::keyPressEvent (QKeyEvent* e) {
    if (e->key () == Qt::Key_Escape)
        close ();
    else
        QWidget::keyPressEvent (e);
}

void Window::timeout () {
    cv::Mat frame;
    try {
        frame = _acquisition.capture ();
        // call vision here
    } catch (const std::runtime_error& e) {
        _statusbar.showMessage ("Select Input");
        frame = cv::Mat (1000, 1000, CV_8UC3, cv::Scalar (0, 0, 0));
    }
    _augmentation.setBackground (frame.ptr (), frame.cols, frame.rows);
    _augmentation.update ();
}

void Window::btn_pause_clicked () {
    if (_frame_timer.isActive ()) {
        _frame_timer.stop ();
        _btn_pause.setText ("Resume");
    } else {
        _frame_timer.start ();
        _btn_pause.setText ("Pause");
    }
}

void Window::btn_reference_clicked () {
    // call vision here
    ;
}

void Window::btn_input_clicked () {
    // create dialog ui elements
    QDialog dialog (this);
    QBoxLayout layout_dialog (QBoxLayout::TopToBottom, &dialog);
    QPushButton btn_open_filebrowser ("Open File Browser");
    QComboBox box_camid;
    QLabel label1 ("Select camera:");
    QLabel label2 ("Or choose a file:");

    // order the ui elements
    dialog.setWindowTitle ("Select Input");
    layout_dialog.addWidget (&label1);
    layout_dialog.addWidget (&box_camid);
    layout_dialog.addWidget (&label2);
    layout_dialog.addWidget (&btn_open_filebrowser);

    // fill list of cameras
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras ();
    if (cameras.size () > 0) {
        foreach (const QCameraInfo& cameraInfo, cameras) {
            box_camid.addItem (cameraInfo.description ());
        }
    } else {
        box_camid.setEnabled (false);
        box_camid.addItem ("No Cameras Found");
    }

    connect (&box_camid, SIGNAL (currentIndexChanged (int)), &dialog, SLOT (close ()));
    connect (&box_camid, SIGNAL (currentIndexChanged (int)), this,
    SLOT (dialog_box_camid_indexchanged (int)));
    connect (&btn_open_filebrowser, SIGNAL (clicked ()), &dialog, SLOT (close ()));
    connect (&btn_open_filebrowser, SIGNAL (clicked ()), this,
    SLOT (dialog_btn_filebrowser_clicked ()));

    dialog.exec ();
}

void Window::dialog_btn_filebrowser_clicked () {
    // test file
    QString file_name = QFileDialog::getOpenFileName (
    this, tr ("Open Video"), SAMPLES_DIR, tr ("Videos (*.webm)"));

    if (!file_name.isEmpty ()) {
        _acquisition.source (file_name.toStdString ());
        _statusbar.showMessage (QString ("Set source: ") + file_name, 2000);
    }
}

void Window::dialog_box_camid_indexchanged (int idx) {
    _acquisition.source (idx);
    _statusbar.showMessage (QString ("Selected camera #") + QString (idx), 2000);
}
<commit_msg>add default selection option<commit_after>// window.cpp

#ifndef SAMPLES_DIR
#define SAMPLES_DIR ""
#endif

#include <QComboBox>
#include <QDialog>
#include <QFileDialog>
#include <QLabel>
#include <QLineEdit>
#include <QList>
#include <QtMultimedia/QCameraInfo>

#include "window.h"

Window::Window (QWidget* parent)
: QWidget (parent)
, _acquisition ()
, _frame_timer ()
, _holder_layout_img (this)
, _holder_layout_btn (this)
, _layout_app (QBoxLayout::TopToBottom, this)
, _layout_img (&_holder_layout_img)
, _layout_btn (QBoxLayout::LeftToRight, &_holder_layout_btn)
, _btn_pause ("Pause", this)
, _btn_reference ("Set Reference", this)
, _btn_input ("Select Input", this)
, _statusbar (this)
, _augmentation (this) {
    _layout_app.addWidget (&_holder_layout_img);
    _layout_app.addWidget (&_holder_layout_btn);
    _layout_app.addWidget (&_statusbar);

    _layout_img.addWidget (&_augmentation, 0, 0);
    _layout_btn.addWidget (&_btn_pause);
    _layout_btn.addWidget (&_btn_reference);
    _layout_btn.addWidget (&_btn_input);
    _statusbar.setSizeGripEnabled (false);

    connect (&_frame_timer, SIGNAL (timeout ()), this, SLOT (timeout ()));
    connect (&_btn_pause, SIGNAL (clicked ()), this, SLOT (btn_pause_clicked ()));
    connect (&_btn_reference, SIGNAL (clicked ()), this, SLOT (btn_reference_clicked ()));
    connect (&_btn_input, SIGNAL (clicked ()), this, SLOT (btn_input_clicked ()));

    _frame_timer.setInterval (1000 / _framerate);
    _frame_timer.start ();
}

Window::~Window () {
}

QSize Window::minimumSizeHint () const {
    return _layout_app.minimumSize ();
}

QSize Window::sizeHint () const {
    return _layout_app.sizeHint ();
}

void Window::keyPressEvent (QKeyEvent* e) {
    if (e->key () == Qt::Key_Escape)
        close ();
    else
        QWidget::keyPressEvent (e);
}

void Window::timeout () {
    cv::Mat frame;
    try {
        frame = _acquisition.capture ();
        // call vision here
    } catch (const std::runtime_error& e) {
        _statusbar.showMessage ("Select Input");
        frame = cv::Mat (1000, 1000, CV_8UC3, cv::Scalar (0, 0, 0));
    }
    _augmentation.setBackground (frame.ptr (), frame.cols, frame.rows);
    _augmentation.update ();
}

void Window::btn_pause_clicked () {
    if (_frame_timer.isActive ()) {
        _frame_timer.stop ();
        _btn_pause.setText ("Resume");
    } else {
        _frame_timer.start ();
        _btn_pause.setText ("Pause");
    }
}

void Window::btn_reference_clicked () {
    // call vision here
    ;
}

void Window::btn_input_clicked () {
    // create dialog ui elements
    QDialog dialog (this);
    QBoxLayout layout_dialog (QBoxLayout::TopToBottom, &dialog);
    QPushButton btn_open_filebrowser ("Open File Browser");
    QComboBox box_camid;
    QLabel label1 ("Select camera:");
    QLabel label2 ("Or choose a file:");

    // order the ui elements
    dialog.setWindowTitle ("Select Input");
    layout_dialog.addWidget (&label1);
    layout_dialog.addWidget (&box_camid);
    layout_dialog.addWidget (&label2);
    layout_dialog.addWidget (&btn_open_filebrowser);

    // fill list of cameras
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras ();
    if (cameras.size () > 0) {
        box_camid.addItem ("Select Camera");
        foreach (const QCameraInfo& cameraInfo, cameras) {
            box_camid.addItem (cameraInfo.description ());
        }
    } else {
        box_camid.setEnabled (false);
        box_camid.addItem ("No Cameras Found");
    }

    connect (&box_camid, SIGNAL (currentIndexChanged (int)), &dialog, SLOT (close ()));
    connect (&box_camid, SIGNAL (currentIndexChanged (int)), this,
    SLOT (dialog_box_camid_indexchanged (int)));
    connect (&btn_open_filebrowser, SIGNAL (clicked ()), &dialog, SLOT (close ()));
    connect (&btn_open_filebrowser, SIGNAL (clicked ()), this,
    SLOT (dialog_btn_filebrowser_clicked ()));

    dialog.exec ();
}

void Window::dialog_btn_filebrowser_clicked () {
    // test file
    QString file_name = QFileDialog::getOpenFileName (
    this, tr ("Open Video"), SAMPLES_DIR, tr ("Videos (*.webm)"));

    if (!file_name.isEmpty ()) {
        _acquisition.source (file_name.toStdString ());
        _statusbar.showMessage (QString ("Set source: ") + file_name, 2000);
    }
}

void Window::dialog_box_camid_indexchanged (int idx) {
    _acquisition.source (idx);
    _statusbar.showMessage (QString ("Selected camera #") + QString (idx), 2000);
}
<|endoftext|>


<commit_before>#include <unittest.hpp>
#include <mmm.hpp>

namespace {

  auto constructors_1 = UnitTest("vector constructors 1", +[] {
    vec4 v;
    vec4 u(0);
    vec4 t{0};
    vec4 s = vec4();
    vec4 r = vec4(0);

    if (v != u) return false;
    if (u != t) return false;
    if (t != s) return false;
    if (s != r) return false;
    if (r != 0) return false;

    return true;
  });
  auto constructors_2 = UnitTest("vector constructors 2", +[] {
    vec2 v = vec2(3, 4);
    vec3 u = vec3(2, v);
    vec4 t = vec4(1, u);

    if (t != vec4(1, 2, 3, 4)) return false;

    return true;
  });
  auto constructors_3 = UnitTest("vector constructors 3", +[] {
    vec2 v = vec2(1, 2);
    vec2 u = vec2(3, 4);
    vec4 t = vec4(v, u);

    vec<10> s = vec<10>(0, t, u + 2, v + 6, 9);

    if (s != vec<10>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) return false;

    return true;
  });
  auto constructors_4 = UnitTest("vector constructors 4", +[] {
    vec4 v = vec4(8, 7, 6, 1);
    vec4 u = vec4(2, 3, 5, 4);
    vec4 t = vec4(12, 10, 11, 13);
    vec4 s = vec4(0);

    vec<15> r = vec<15>(s.x, v.w, u.xywz, v.zyx, 9, t.yzxw, 14);

    if (r != vec<15>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14))
      return false;

    return true;
  });

  auto index = UnitTest("vector index", +[] {
    vec4 v = vec4(1, 2, 3, 4);

    float& x = v[0];
    x = 0;
    if (v[0] != 0) return false;

    float y = v[1];
    y = 73;
    if (v[1] != 2) return false;

    v[2] = 12;
    if (v[2] != 12) return false;

    v.data[3] = -1;
    if (v[3] != -1) return false;

    return true;
  });

  auto array_cast = UnitTest("vector array_cast", +[] {
    ivec4 v = ivec4(8, 7, 6, 5);
    int* i = v;

    if (i[0] != 8 and i[1] != 7 and i[2] != 6 and i[3] != 5) return false;

    return true;
  });

  auto swiz_func = UnitTest("vector swizzleElems", +[] {
    ivec<9> v = ivec<9>(0, 1, 2, 10, 11, 12, 20, 21, 22);

    ivec3 u = v.swizzleElems<3, 4, 5>() += 100;
    if (u != ivec3(110, 111, 112)) return false;
    if (v != ivec<9>(0, 1, 2, 110, 111, 112, 20, 21, 22)) return false;

    return true;
  });
}
<commit_msg>added test for swizzle ranges<commit_after>#include <unittest.hpp>
#include <mmm.hpp>

namespace {

  auto constructors_1 = UnitTest("vector constructors 1", +[] {
    vec4 v;
    vec4 u(0);
    vec4 t{0};
    vec4 s = vec4();
    vec4 r = vec4(0);

    if (v != u) return false;
    if (u != t) return false;
    if (t != s) return false;
    if (s != r) return false;
    if (r != 0) return false;

    return true;
  });
  auto constructors_2 = UnitTest("vector constructors 2", +[] {
    vec2 v = vec2(3, 4);
    vec3 u = vec3(2, v);
    vec4 t = vec4(1, u);

    if (t != vec4(1, 2, 3, 4)) return false;

    return true;
  });
  auto constructors_3 = UnitTest("vector constructors 3", +[] {
    vec2 v = vec2(1, 2);
    vec2 u = vec2(3, 4);
    vec4 t = vec4(v, u);

    vec<10> s = vec<10>(0, t, u + 2, v + 6, 9);

    if (s != vec<10>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) return false;

    return true;
  });
  auto constructors_4 = UnitTest("vector constructors 4", +[] {
    vec4 v = vec4(8, 7, 6, 1);
    vec4 u = vec4(2, 3, 5, 4);
    vec4 t = vec4(12, 10, 11, 13);
    vec4 s = vec4(0);

    vec<15> r = vec<15>(s.x, v.w, u.xywz, v.zyx, 9, t.yzxw, 14);

    if (r != vec<15>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14))
      return false;

    return true;
  });

  auto index = UnitTest("vector index", +[] {
    vec4 v = vec4(1, 2, 3, 4);

    float& x = v[0];
    x = 0;
    if (v[0] != 0) return false;

    float y = v[1];
    y = 73;
    if (v[1] != 2) return false;

    v[2] = 12;
    if (v[2] != 12) return false;

    v.data[3] = -1;
    if (v[3] != -1) return false;

    return true;
  });

  auto array_cast = UnitTest("vector array_cast", +[] {
    ivec4 v = ivec4(8, 7, 6, 5);
    int* i = v;

    if (i[0] != 8 and i[1] != 7 and i[2] != 6 and i[3] != 5) return false;

    return true;
  });

  auto swiz_elems = UnitTest("vector swizzleElems", +[] {
    ivec<9> v = ivec<9>(0, 1, 2, 10, 11, 12, 20, 21, 22);

    ivec3 u = v.swizzleElems<3, 4, 5>() += 100;
    if (u != ivec3(110, 111, 112)) return false;
    if (v != ivec<9>(0, 1, 2, 110, 111, 112, 20, 21, 22)) return false;

    return true;
  });
  auto swiz_range1 = UnitTest("vector swizzleRange positive", +[] {
    ivec<9> v = ivec<9>(0, 1, 2, 10, 11, 12, 20, 21, 22);

    auto& u = v.swizzleRange<3, 5>();
    if (u != ivec3(10, 11, 12)) return false;

    u += 100;
    if (u != ivec3(110, 111, 112)) return false;

    if (v != ivec<9>(0, 1, 2, 110, 111, 112, 20, 21, 22)) return false;

    return true;
  });
  auto swiz_range2 = UnitTest("vector swizzleRange negative", +[] {
    ivec<9> v = ivec<9>(0, 1, 2, 10, 11, 12, 20, 21, 22);

    auto& u = v.swizzleRange<5, 3>();
    if (u != ivec3(12, 11, 10)) return false;

    u += 100;
    if (u != ivec3(112, 111, 110)) return false;

    if (v != ivec<9>(0, 1, 2, 110, 111, 112, 20, 21, 22)) return false;

    return true;
  });
}
<|endoftext|>


<commit_before>#pragma once

#include <cstdlib>
#include <type_traits>
#include <initializer_list>
#include <utility>
#include <new>
#include "types.hh"
#include "_utils.hh"

namespace zbs {

// Hashmap.
//
// K - type of the key
// V - type of the value
// Hash - takes (const K&, int) and returns int, a hash functor with seed
// KeyEqual - checks if one key is equal to another, returns bool

template <typename T>
struct hash;

template <>
struct hash<const char*> {
	int operator()(const char *s, int seed);
};

// TODO: more hash implementations

template <typename K, typename V>
struct key_and_value {
	K key;
	V value;
};

template <typename K, typename V, typename Hash>
class map_iter;

template <typename K, typename V, typename Hash = hash<K>>
class map {
	friend class map_iter<K, V, Hash>;

	static constexpr float _load = 6.5;
	static constexpr int _bucket_size = 8;
	static constexpr int _max_key_size = 128;
	static constexpr int _max_value_size = 128;
	static constexpr bool _indirect_key() {	return sizeof(K) > _max_key_size; }
	static constexpr bool _indirect_value() { return sizeof(V) > _max_value_size; }

	typedef typename std::conditional<_indirect_key(), K*, K>::type KK;
	typedef typename std::conditional<_indirect_value(), V*, V>::type VV;

	template <bool Indirect, typename T>
	struct _indirect;

	// when T is indirectly stored, all functions take T*
	template <typename T>
	struct _indirect<true, T> {
		static T &get(T *a) {
			return *a;
		}

		static void destroy(T *a) {
			a->~T();
			detail::free(a);
		}

		static T *insert(T *a) {
			*a = detail::malloc<T>(1);
			return *a;
		}
	};

	// when T is directly stored, all functions take T&
	template <typename T>
	struct _indirect<false, T> {
		static T &get(T &a) {
			return a;
		}

		static void destroy(T &a) {
			a.~T();
		}

		static T *insert(T &a) {
			return &a;
		}
	};

	struct _bucket {
		uint8 top_hash[_bucket_size];
		_bucket *overflow;
		KK keys[_bucket_size];
		VV values[_bucket_size];

		K &key(int i) {
			return _indirect<_indirect_key(), K>::get(keys[i]);
		}

		V &value(int i) {
			return _indirect<_indirect_value(), V>::get(values[i]);
		}

		void clear() {
			static_assert(_bucket_size == 8, "bucket_size != 8");
			*(uint64*)top_hash = 0;
			overflow = nullptr;
		}

		void free() {
			for (int i = 0; i < _bucket_size; i++) {
				if (top_hash[i] == 0)
					continue;

				_indirect<_indirect_key(), K>::destroy(keys[i]);
				_indirect<_indirect_value(), V>::destroy(values[i]);
			}
		}
	};

	int _hash0 = 0;
	int _count = 0;
	uint8 _B = 0;
	_bucket *_buckets = nullptr;

	void _split_bucket(_bucket *b, int i) {
		int newbit = 1 << (_B - 1);
		_bucket *x = _buckets + i;
		_bucket *y = _buckets + i + newbit;
		x->clear();
		y->clear();
		int xi = 0;
		int yi = 0;

		do {
			for (int i = 0; i < _bucket_size; i++) {
				if (b->top_hash[i] == 0)
					continue;

				int hash = Hash()(b->key(i), _hash0);
				if ((hash & newbit) == 0) {
					if (xi == _bucket_size) {
						_bucket *newx = detail::malloc<_bucket>(1);
						newx->clear();
						x->overflow = newx;
						x = newx;
						xi = 0;
					}
					x->top_hash[xi] = b->top_hash[i];
					new (&x->keys[xi]) KK(std::move(b->keys[i]));
					new (&x->values[xi]) VV(std::move(b->values[i]));
					xi++;
				} else {
					if (yi == _bucket_size) {
						_bucket *newy = detail::malloc<_bucket>(1);
						newy->clear();
						y->overflow = newy;
						y = newy;
						yi = 0;
					}
					y->top_hash[yi] = b->top_hash[i];
					new (&y->keys[yi]) KK(std::move(b->keys[i]));
					new (&y->values[yi]) VV(std::move(b->values[i]));
					yi++;
				}
			}
			b = b->overflow;
		} while (b);
	}

	void _grow() {
		_bucket *old_buckets = _buckets;
		int old_buckets_n = 1 << _B;

		_B++;
		_buckets = detail::malloc<_bucket>(1 << _B);

		for (int i = 0; i < old_buckets_n; i++) {
			_bucket *b = old_buckets + i;
			_split_bucket(b, i);

			// free old bucket contents and overflow buckets
			_bucket *next = b->overflow;
			while (next) {
				_bucket *cur = next;
				next = cur->overflow;

				cur->free();
				detail::free(cur);
			}
			b->free();
		}
		detail::free(old_buckets);
	}

	V &_find_or_insert(K key) {
		int hash = Hash()(key, _hash0);
		if (_buckets == nullptr) {
			_buckets = detail::malloc<_bucket>(1);
			_buckets->clear();
		}

again:
		int bi = hash & ((1 << _B) - 1);
		_bucket *b = _buckets + bi;
		uint8 top = hash >> (sizeof(int) * 8 - 8);
		if (top == 0)
			top = 1;

		uint8 *insert_top = nullptr;
		KK *insert_key = nullptr;
		VV *insert_value = nullptr;

		for (;;) {
			for (int i = 0; i < _bucket_size; i++) {
				if (b->top_hash[i] != top) {
					if (b->top_hash[i] == 0 && insert_top == nullptr) {
						insert_top = b->top_hash + i;
						insert_key = b->keys + i;
						insert_value = b->values + i;
					}
					continue;
				}

				if (!(key == b->key(i)))
					continue;

				return b->value(i);
			}

			if (b->overflow == nullptr)
				break;
			b = b->overflow;
		}

		if (_count >= _load * (1 << _B) && _count >= _bucket_size) {
			_grow();
			goto again;
		}

		if (insert_top == nullptr) {
			_bucket *newb = detail::malloc<_bucket>(1);
			newb->clear();
			b->overflow = newb;
			insert_top = newb->top_hash;
			insert_key = &newb->key(0);
			insert_value = &newb->value(0);
		}

		*insert_top = top;
		K *newk = _indirect<_indirect_key(), K>::insert(*insert_key);
		V *newv = _indirect<_indirect_value(), V>::insert(*insert_value);
		new (newk) K(std::move(key));
		new (newv) V;
		_count++;

		return *newv;
	}

public:
	explicit map(int hint = 0) {
		while (hint > _bucket_size && hint > _load * (1 << _B))
			_B++;

		if (_B != 0) {
			_buckets = detail::malloc<_bucket>(1 << _B);
			for (int i = 0, n = 1 << _B; i < n; i++) {
				_buckets[i].clear();
			}
		}
		_hash0 = detail::fastrand();
	}

	map(std::initializer_list<key_and_value<K, V>> r): map(r.size()) {
		for (const auto &kv : r) {
			operator[](kv.key) = kv.value;
		}
	}

	~map() {
		if (_buckets == nullptr)
			return;

		for (int i = 0, n = 1 << _B; i < n; i++) {
			_bucket &b = _buckets[i];
			_bucket *next = b.overflow;
			while (next) {
				_bucket *cur = next;
				next = cur->overflow;

				cur->free();
				detail::free(cur);
			}
			b.free();
		}
		detail::free(_buckets);
	}

	int len() const { return _count; }

	V &operator[](K k) {
		return _find_or_insert(std::move(k));
	}
};

template <typename K, typename V, typename Hash>
class map_iter {
	typename map<K, V, Hash>::_bucket *_buckets;
	typename map<K, V, Hash>::_bucket *_bucket;
	int _buckets_n;
	int _bucket_i;
	int _i;

	void _find_next_valid() {
		if (_bucket_i == _buckets_n) {
			return;
		}

		for (;;) {
			_i++;
			if (_i == map<K, V, Hash>::_bucket_size) {
				// done with current bucket, try next overflow
				_bucket = _bucket->overflow;
				_i = 0;
				if (_bucket == nullptr) {
					// oops, no overflow bucket, try next
					// one in the table
					_bucket_i++;
					if (_bucket_i == _buckets_n) {
						// no buckets left, we're done
						return;
					}
					_bucket = _buckets + _bucket_i;
				}
			}

			// check if it's a valid entry
			if (_bucket->top_hash[_i] != 0) {
				return;
			}
		}
	}
public:
	map_iter() = default;

	explicit map_iter(map<K, V, Hash> &m):
		_buckets(m._buckets), _bucket(m._buckets),
		_buckets_n(1 << m._B), _bucket_i(0), _i(0)
	{
		if (m.len() == 0) {
			_buckets_n = 0;
			return;
		}

		if (_bucket->top_hash[_i] == 0)
			_find_next_valid();
	}

	map_iter &operator++() {
		_find_next_valid();
		return *this;
	}

	bool operator==(const map_iter&) const { return _bucket_i == _buckets_n; }
	bool operator!=(const map_iter&) const { return _bucket_i != _buckets_n; }
	key_and_value<const K&, V&> operator*() {
		return {
			map<K, V, Hash>::template _indirect<
				map<K, V, Hash>::_indirect_key(), K
			>::get(_bucket->keys[_i]),
			map<K, V, Hash>::template _indirect<
				map<K, V, Hash>::_indirect_value(), V
			>::get(_bucket->values[_i]),
		};
	}
};

template <typename K, typename V, typename Hash>
map_iter<K, V, Hash> begin(map<K, V, Hash> &m) {
	return map_iter<K, V, Hash>(m);
}

template <typename K, typename V, typename Hash>
map_iter<K, V, Hash> end(map<K, V, Hash>&) {
	return map_iter<K, V, Hash>();
}

} // namespace zbs
<commit_msg>Split map constructors into two, causes issues on clang.<commit_after>#pragma once

#include <cstdlib>
#include <type_traits>
#include <initializer_list>
#include <utility>
#include <new>
#include "types.hh"
#include "_utils.hh"

namespace zbs {

// Hashmap.
//
// K - type of the key
// V - type of the value
// Hash - takes (const K&, int) and returns int, a hash functor with seed
// KeyEqual - checks if one key is equal to another, returns bool

template <typename T>
struct hash;

template <>
struct hash<const char*> {
	int operator()(const char *s, int seed);
};

// TODO: more hash implementations

template <typename K, typename V>
struct key_and_value {
	K key;
	V value;
};

template <typename K, typename V, typename Hash>
class map_iter;

template <typename K, typename V, typename Hash = hash<K>>
class map {
	friend class map_iter<K, V, Hash>;

	static constexpr float _load = 6.5;
	static constexpr int _bucket_size = 8;
	static constexpr int _max_key_size = 128;
	static constexpr int _max_value_size = 128;
	static constexpr bool _indirect_key() {	return sizeof(K) > _max_key_size; }
	static constexpr bool _indirect_value() { return sizeof(V) > _max_value_size; }

	typedef typename std::conditional<_indirect_key(), K*, K>::type KK;
	typedef typename std::conditional<_indirect_value(), V*, V>::type VV;

	template <bool Indirect, typename T>
	struct _indirect;

	// when T is indirectly stored, all functions take T*
	template <typename T>
	struct _indirect<true, T> {
		static T &get(T *a) {
			return *a;
		}

		static void destroy(T *a) {
			a->~T();
			detail::free(a);
		}

		static T *insert(T *a) {
			*a = detail::malloc<T>(1);
			return *a;
		}
	};

	// when T is directly stored, all functions take T&
	template <typename T>
	struct _indirect<false, T> {
		static T &get(T &a) {
			return a;
		}

		static void destroy(T &a) {
			a.~T();
		}

		static T *insert(T &a) {
			return &a;
		}
	};

	struct _bucket {
		uint8 top_hash[_bucket_size];
		_bucket *overflow;
		KK keys[_bucket_size];
		VV values[_bucket_size];

		K &key(int i) {
			return _indirect<_indirect_key(), K>::get(keys[i]);
		}

		V &value(int i) {
			return _indirect<_indirect_value(), V>::get(values[i]);
		}

		void clear() {
			static_assert(_bucket_size == 8, "bucket_size != 8");
			*(uint64*)top_hash = 0;
			overflow = nullptr;
		}

		void free() {
			for (int i = 0; i < _bucket_size; i++) {
				if (top_hash[i] == 0)
					continue;

				_indirect<_indirect_key(), K>::destroy(keys[i]);
				_indirect<_indirect_value(), V>::destroy(values[i]);
			}
		}
	};

	int _hash0 = 0;
	int _count = 0;
	uint8 _B = 0;
	_bucket *_buckets = nullptr;

	void _split_bucket(_bucket *b, int i) {
		int newbit = 1 << (_B - 1);
		_bucket *x = _buckets + i;
		_bucket *y = _buckets + i + newbit;
		x->clear();
		y->clear();
		int xi = 0;
		int yi = 0;

		do {
			for (int i = 0; i < _bucket_size; i++) {
				if (b->top_hash[i] == 0)
					continue;

				int hash = Hash()(b->key(i), _hash0);
				if ((hash & newbit) == 0) {
					if (xi == _bucket_size) {
						_bucket *newx = detail::malloc<_bucket>(1);
						newx->clear();
						x->overflow = newx;
						x = newx;
						xi = 0;
					}
					x->top_hash[xi] = b->top_hash[i];
					new (&x->keys[xi]) KK(std::move(b->keys[i]));
					new (&x->values[xi]) VV(std::move(b->values[i]));
					xi++;
				} else {
					if (yi == _bucket_size) {
						_bucket *newy = detail::malloc<_bucket>(1);
						newy->clear();
						y->overflow = newy;
						y = newy;
						yi = 0;
					}
					y->top_hash[yi] = b->top_hash[i];
					new (&y->keys[yi]) KK(std::move(b->keys[i]));
					new (&y->values[yi]) VV(std::move(b->values[i]));
					yi++;
				}
			}
			b = b->overflow;
		} while (b);
	}

	void _grow() {
		_bucket *old_buckets = _buckets;
		int old_buckets_n = 1 << _B;

		_B++;
		_buckets = detail::malloc<_bucket>(1 << _B);

		for (int i = 0; i < old_buckets_n; i++) {
			_bucket *b = old_buckets + i;
			_split_bucket(b, i);

			// free old bucket contents and overflow buckets
			_bucket *next = b->overflow;
			while (next) {
				_bucket *cur = next;
				next = cur->overflow;

				cur->free();
				detail::free(cur);
			}
			b->free();
		}
		detail::free(old_buckets);
	}

	V &_find_or_insert(K key) {
		int hash = Hash()(key, _hash0);
		if (_buckets == nullptr) {
			_buckets = detail::malloc<_bucket>(1);
			_buckets->clear();
		}

again:
		int bi = hash & ((1 << _B) - 1);
		_bucket *b = _buckets + bi;
		uint8 top = hash >> (sizeof(int) * 8 - 8);
		if (top == 0)
			top = 1;

		uint8 *insert_top = nullptr;
		KK *insert_key = nullptr;
		VV *insert_value = nullptr;

		for (;;) {
			for (int i = 0; i < _bucket_size; i++) {
				if (b->top_hash[i] != top) {
					if (b->top_hash[i] == 0 && insert_top == nullptr) {
						insert_top = b->top_hash + i;
						insert_key = b->keys + i;
						insert_value = b->values + i;
					}
					continue;
				}

				if (!(key == b->key(i)))
					continue;

				return b->value(i);
			}

			if (b->overflow == nullptr)
				break;
			b = b->overflow;
		}

		if (_count >= _load * (1 << _B) && _count >= _bucket_size) {
			_grow();
			goto again;
		}

		if (insert_top == nullptr) {
			_bucket *newb = detail::malloc<_bucket>(1);
			newb->clear();
			b->overflow = newb;
			insert_top = newb->top_hash;
			insert_key = &newb->key(0);
			insert_value = &newb->value(0);
		}

		*insert_top = top;
		K *newk = _indirect<_indirect_key(), K>::insert(*insert_key);
		V *newv = _indirect<_indirect_value(), V>::insert(*insert_value);
		new (newk) K(std::move(key));
		new (newv) V;
		_count++;

		return *newv;
	}

public:
	explicit map(int hint) {
		while (hint > _bucket_size && hint > _load * (1 << _B))
			_B++;

		if (_B != 0) {
			_buckets = detail::malloc<_bucket>(1 << _B);
			for (int i = 0, n = 1 << _B; i < n; i++) {
				_buckets[i].clear();
			}
		}
		_hash0 = detail::fastrand();
	}

	map(): map(0) {}

	map(std::initializer_list<key_and_value<K, V>> r): map(r.size()) {
		for (const auto &kv : r) {
			operator[](kv.key) = kv.value;
		}
	}

	~map() {
		if (_buckets == nullptr)
			return;

		for (int i = 0, n = 1 << _B; i < n; i++) {
			_bucket &b = _buckets[i];
			_bucket *next = b.overflow;
			while (next) {
				_bucket *cur = next;
				next = cur->overflow;

				cur->free();
				detail::free(cur);
			}
			b.free();
		}
		detail::free(_buckets);
	}

	int len() const { return _count; }

	V &operator[](K k) {
		return _find_or_insert(std::move(k));
	}
};

template <typename K, typename V, typename Hash>
class map_iter {
	typename map<K, V, Hash>::_bucket *_buckets;
	typename map<K, V, Hash>::_bucket *_bucket;
	int _buckets_n;
	int _bucket_i;
	int _i;

	void _find_next_valid() {
		if (_bucket_i == _buckets_n) {
			return;
		}

		for (;;) {
			_i++;
			if (_i == map<K, V, Hash>::_bucket_size) {
				// done with current bucket, try next overflow
				_bucket = _bucket->overflow;
				_i = 0;
				if (_bucket == nullptr) {
					// oops, no overflow bucket, try next
					// one in the table
					_bucket_i++;
					if (_bucket_i == _buckets_n) {
						// no buckets left, we're done
						return;
					}
					_bucket = _buckets + _bucket_i;
				}
			}

			// check if it's a valid entry
			if (_bucket->top_hash[_i] != 0) {
				return;
			}
		}
	}
public:
	map_iter() = default;

	explicit map_iter(map<K, V, Hash> &m):
		_buckets(m._buckets), _bucket(m._buckets),
		_buckets_n(1 << m._B), _bucket_i(0), _i(0)
	{
		if (m.len() == 0) {
			_buckets_n = 0;
			return;
		}

		if (_bucket->top_hash[_i] == 0)
			_find_next_valid();
	}

	map_iter &operator++() {
		_find_next_valid();
		return *this;
	}

	bool operator==(const map_iter&) const { return _bucket_i == _buckets_n; }
	bool operator!=(const map_iter&) const { return _bucket_i != _buckets_n; }
	key_and_value<const K&, V&> operator*() {
		return {
			map<K, V, Hash>::template _indirect<
				map<K, V, Hash>::_indirect_key(), K
			>::get(_bucket->keys[_i]),
			map<K, V, Hash>::template _indirect<
				map<K, V, Hash>::_indirect_value(), V
			>::get(_bucket->values[_i]),
		};
	}
};

template <typename K, typename V, typename Hash>
map_iter<K, V, Hash> begin(map<K, V, Hash> &m) {
	return map_iter<K, V, Hash>(m);
}

template <typename K, typename V, typename Hash>
map_iter<K, V, Hash> end(map<K, V, Hash>&) {
	return map_iter<K, V, Hash>();
}

} // namespace zbs
<|endoftext|>


<commit_before>/*
    SWARM

    Copyright (C) 2012-2022 Torbjorn Rognes and Frederic Mahe

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: Torbjorn Rognes <torognes@ifi.uio.no>,
    Department of Informatics, University of Oslo,
    PO Box 1080 Blindern, NO-0316 Oslo, Norway
*/

#include "swarm.h"
#include "pseudo_rng.h"
#include "util.h"
#include "zobrist.h"

uint64_t * zobrist_tab_base = nullptr;
uint64_t * zobrist_tab_byte_base = nullptr;

void zobrist_init(unsigned int n)
{
  /*
    Generate 4n random 64-bit numbers. They will represent the four
    different bases in any position (1 to n) of a sequence.
    They will be XOR'ed together to form the hash of that sequence.
    The number n should be the length of the longest sequence to be
    hashed including potential additional insertions.

    The number is generated by xor'ing together four shifted
    31-bit random numbers.
  */
  constexpr unsigned int byte_range {256};
  constexpr unsigned int multiplier {16};

  /* allocate memory for tables */

  zobrist_tab_base = static_cast<uint64_t *>
    (xmalloc(4 * n * sizeof(uint64_t)));

  zobrist_tab_byte_base = static_cast<uint64_t *>
    (xmalloc(byte_range * (n / 4) * sizeof(uint64_t)));

  /* fill table with random 64 bit numbers */

  for(auto i = 0U; i < 4 * n; i++)
    {
      auto z = 0ULL;
      z = rand_64();
      z <<= multiplier;
      z ^= rand_64();
      z <<= multiplier;
      z ^= rand_64();
      z <<= multiplier;
      z ^= rand_64();
      zobrist_tab_base[i] = z;
    }

  /* combine into bytes for faster computations */

  for(auto i = 0U; i < n / 4; i++) {
    for(auto j = 0U; j < byte_range; j++) {
      auto z = 0ULL;
      auto x = j;
      z ^= zobrist_value(4 * i + 0, x & 3);
      x >>= 2;
      z ^= zobrist_value(4 * i + 1, x & 3);
      x >>= 2;
      z ^= zobrist_value(4 * i + 2, x & 3);
      x >>= 2;
      z ^= zobrist_value(4 * i + 3, x & 3);
      zobrist_tab_byte_base[byte_range * i + j] = z;
    }
  }
}

void zobrist_exit()
{
  xfree(zobrist_tab_byte_base);
  xfree(zobrist_tab_base);
}

auto zobrist_hash(unsigned char * s, unsigned int len) -> uint64_t
{
  /* compute the Zobrist hash function of sequence s of length len. */
  /* len is the actual number of bases in the sequence */
  /* it is encoded in (len+3)/4 bytes */

  constexpr unsigned int offset {64};
  constexpr unsigned int nt_per_uint64 {32};  // 32 nucleotides can fit in a uint64
  auto * q = reinterpret_cast<uint64_t *>(s);
  uint64_t z = 0;
  unsigned int p = 0;
  auto * qb = reinterpret_cast<unsigned char *>(q);

  while (p + nt_per_uint64 < len)
    {
      for(auto i = 0U; i < nt_per_uint64; i += 4) {
        // i = {0, 4, 8, 12, 16, 20, 24, 28}
        z ^= zobrist_tab_byte_base[offset * (p + i) + *qb++];
      }
      p += nt_per_uint64;
    }

  while (p + 4 < len)
    {
      z ^= zobrist_tab_byte_base[offset * p + *qb++];
      p += 4;
    }

  if (p < len)
    {
      uint64_t x = *qb++;
      while (p < len)
        {
          z ^= zobrist_value(p, x & 3);
          x >>= 2;
          p++;
        }
    }

  return z;
}

auto zobrist_hash_delete_first(unsigned char * s, unsigned int len) -> uint64_t
{
  /* compute the Zobrist hash function of sequence s,
     but delete the first base */

  constexpr unsigned int nt_per_uint64 {32};  // 32 nucleotides can fit in a uint64
  auto * q = reinterpret_cast<uint64_t *>(s);
  uint64_t x = q[0];
  uint64_t z = 0;
  for(auto p = 1U; p < len; p++)
    {
      if ((p & (nt_per_uint64 - 1)) == 0) {
        x = q[p / nt_per_uint64];
      }
      else {
        x >>= 2;
      }
      z ^= zobrist_value(p - 1, x & 3);
    }
  return z;
}

auto zobrist_hash_insert_first(unsigned char * s, unsigned int len) -> uint64_t
{
  /* compute the Zobrist hash function of sequence s,
     but insert a gap (no value) before the first base */

  constexpr unsigned int nt_per_uint64 {32};  // 32 nucleotides can fit in a uint64
  auto * q = reinterpret_cast<uint64_t *>(s);
  uint64_t x = 0;
  uint64_t z = 0;
  for(auto p = 0U; p < len; p++)
    {
      if ((p & (nt_per_uint64 - 1)) == 0) {
        x = q[p / nt_per_uint64];
      }
      else {
        x >>= 2;
      }
      z ^= zobrist_value(p + 1, x & 3);
    }
  return z;
}
<commit_msg>longer names for parameters, fix spacing<commit_after>/*
    SWARM

    Copyright (C) 2012-2022 Torbjorn Rognes and Frederic Mahe

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Contact: Torbjorn Rognes <torognes@ifi.uio.no>,
    Department of Informatics, University of Oslo,
    PO Box 1080 Blindern, NO-0316 Oslo, Norway
*/

#include "swarm.h"
#include "pseudo_rng.h"
#include "util.h"
#include "zobrist.h"

uint64_t * zobrist_tab_base = nullptr;
uint64_t * zobrist_tab_byte_base = nullptr;

void zobrist_init(unsigned int n)
{
  /*
    Generate 4n random 64-bit numbers. They will represent the four
    different bases in any position (1 to n) of a sequence.
    They will be XOR'ed together to form the hash of that sequence.
    The number n should be the length of the longest sequence to be
    hashed including potential additional insertions.

    The number is generated by xor'ing together four shifted
    31-bit random numbers.
  */
  constexpr unsigned int byte_range {256};
  constexpr unsigned int multiplier {16};

  /* allocate memory for tables */

  zobrist_tab_base = static_cast<uint64_t *>
    (xmalloc(4 * n * sizeof(uint64_t)));

  zobrist_tab_byte_base = static_cast<uint64_t *>
    (xmalloc(byte_range * (n / 4) * sizeof(uint64_t)));

  /* fill table with random 64 bit numbers */

  for(auto i = 0U; i < 4 * n; i++)
    {
      auto z = 0ULL;
      z = rand_64();
      z <<= multiplier;
      z ^= rand_64();
      z <<= multiplier;
      z ^= rand_64();
      z <<= multiplier;
      z ^= rand_64();
      zobrist_tab_base[i] = z;
    }

  /* combine into bytes for faster computations */

  for(auto i = 0U; i < n / 4; i++) {
    for(auto j = 0U; j < byte_range; j++) {
      auto z = 0ULL;
      auto x = j;
      z ^= zobrist_value(4 * i + 0, x & 3);
      x >>= 2;
      z ^= zobrist_value(4 * i + 1, x & 3);
      x >>= 2;
      z ^= zobrist_value(4 * i + 2, x & 3);
      x >>= 2;
      z ^= zobrist_value(4 * i + 3, x & 3);
      zobrist_tab_byte_base[byte_range * i + j] = z;
    }
  }
}

void zobrist_exit()
{
  xfree(zobrist_tab_byte_base);
  xfree(zobrist_tab_base);
}

auto zobrist_hash(unsigned char * seq, unsigned int len) -> uint64_t
{
  /* compute the Zobrist hash function of sequence seq of length len. */
  /* len is the actual number of bases in the sequence */
  /* it is encoded in (len + 3 ) / 4 bytes */

  constexpr unsigned int offset {64};
  constexpr unsigned int nt_per_uint64 {32};  // 32 nucleotides can fit in a uint64
  auto * q = reinterpret_cast<uint64_t *>(seq);
  uint64_t z = 0;
  unsigned int p = 0;
  auto * qb = reinterpret_cast<unsigned char *>(q);

  while (p + nt_per_uint64 < len)
    {
      for(auto i = 0U; i < nt_per_uint64; i += 4) {
        // i = {0, 4, 8, 12, 16, 20, 24, 28}
        z ^= zobrist_tab_byte_base[offset * (p + i) + *qb++];
      }
      p += nt_per_uint64;
    }

  while (p + 4 < len)
    {
      z ^= zobrist_tab_byte_base[offset * p + *qb++];
      p += 4;
    }

  if (p < len)
    {
      uint64_t x = *qb++;
      while (p < len)
        {
          z ^= zobrist_value(p, x & 3);
          x >>= 2;
          p++;
        }
    }

  return z;
}

auto zobrist_hash_delete_first(unsigned char * seq, unsigned int len) -> uint64_t
{
  /* compute the Zobrist hash function of sequence seq,
     but delete the first base */

  constexpr unsigned int nt_per_uint64 {32};  // 32 nucleotides can fit in a uint64
  auto * q = reinterpret_cast<uint64_t *>(seq);
  uint64_t x = q[0];
  uint64_t z = 0;
  for(auto p = 1U; p < len; p++)
    {
      if ((p & (nt_per_uint64 - 1)) == 0) {
        x = q[p / nt_per_uint64];
      }
      else {
        x >>= 2;
      }
      z ^= zobrist_value(p - 1, x & 3);
    }
  return z;
}

auto zobrist_hash_insert_first(unsigned char * seq, unsigned int len) -> uint64_t
{
  /* compute the Zobrist hash function of sequence seq,
     but insert a gap (no value) before the first base */

  constexpr unsigned int nt_per_uint64 {32};  // 32 nucleotides can fit in a uint64
  auto * q = reinterpret_cast<uint64_t *>(seq);
  uint64_t x = 0;
  uint64_t z = 0;
  for(auto p = 0U; p < len; p++)
    {
      if ((p & (nt_per_uint64 - 1)) == 0) {
        x = q[p / nt_per_uint64];
      }
      else {
        x >>= 2;
      }
      z ^= zobrist_value(p + 1, x & 3);
    }
  return z;
}
<|endoftext|>


<commit_before>#include "Configuration.hpp"

#include <memory>
#include <string>
#include <vector>

#include "tclap/CmdLine.h"

#include "SequentialEventDispatcher.hpp"

namespace warped {

Configuration::Configuration(const std::string& config_file_name, unsigned int max_sim_time)
    : config_file_name_(config_file_name), max_sim_time_(max_sim_time) {}

Configuration::Configuration(const std::string& model_description, int argc,
                             const char* const* argv,
                             const std::vector<TCLAP::Arg*>& cmd_line_args)
    : config_file_name_(""), max_sim_time_(0) { init(model_description, argc, argv, cmd_line_args); }

Configuration::Configuration(const std::string& model_description, int argc,
                             const char* const* argv)
    : config_file_name_(""), max_sim_time_(0) {
    std::vector<TCLAP::Arg*> v;
    init(model_description, argc, argv, v);
}

void Configuration::init(const std::string& model_description, int argc, const char* const* argv,
                         const std::vector<TCLAP::Arg*>& cmd_line_args) {
    TCLAP::CmdLine cmd_line(model_description);

    TCLAP::ValueArg<std::string> config_arg("c", "config", "Warped configuration file",
                                            false, config_file_name_, "file", cmd_line);
    TCLAP::ValueArg<unsigned int> max_sim_time_arg("t", "max-sim-time",
                                                   "specify a simulation end time",
                                                   false, max_sim_time_, "time", cmd_line);
    for (auto arg : cmd_line_args) {
        cmd_line.add(arg);
    }

    cmd_line.parse(argc, argv);

    max_sim_time_ = max_sim_time_arg.getValue();
    config_file_name_ = config_arg.getValue();

}

std::unique_ptr<EventDispatcher> Configuration::make_dispatcher() {
    return std::unique_ptr<EventDispatcher> {new SequentialEventDispatcher{max_sim_time_}};
}

} // namespace warped<commit_msg>Changed local variable into rvalue<commit_after>#include "Configuration.hpp"

#include <memory>
#include <string>
#include <vector>

#include "tclap/CmdLine.h"

#include "SequentialEventDispatcher.hpp"

namespace warped {

Configuration::Configuration(const std::string& config_file_name, unsigned int max_sim_time)
    : config_file_name_(config_file_name), max_sim_time_(max_sim_time) {}

Configuration::Configuration(const std::string& model_description, int argc,
                             const char* const* argv,
                             const std::vector<TCLAP::Arg*>& cmd_line_args)
    : config_file_name_(""), max_sim_time_(0) { init(model_description, argc, argv, cmd_line_args); }

Configuration::Configuration(const std::string& model_description, int argc,
                             const char* const* argv)
    : config_file_name_(""), max_sim_time_(0) { init(model_description, argc, argv, {}); }

void Configuration::init(const std::string& model_description, int argc, const char* const* argv,
                         const std::vector<TCLAP::Arg*>& cmd_line_args) {
    TCLAP::CmdLine cmd_line(model_description);

    TCLAP::ValueArg<std::string> config_arg("c", "config", "Warped configuration file",
                                            false, config_file_name_, "file", cmd_line);
    TCLAP::ValueArg<unsigned int> max_sim_time_arg("t", "max-sim-time",
                                                   "specify a simulation end time",
                                                   false, max_sim_time_, "time", cmd_line);
    for (auto arg : cmd_line_args) {
        cmd_line.add(arg);
    }

    cmd_line.parse(argc, argv);

    max_sim_time_ = max_sim_time_arg.getValue();
    config_file_name_ = config_arg.getValue();

}

std::unique_ptr<EventDispatcher> Configuration::make_dispatcher() {
    return std::unique_ptr<EventDispatcher> {new SequentialEventDispatcher{max_sim_time_}};
}

} // namespace warped<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: UnoNamespaceMap.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#include <set>

#include "UnoNamespaceMap.hxx"
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase2.hxx>
#endif
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <comphelper/stl_types.hxx>
#include <svtools/itempool.hxx>
#include "unoapi.hxx"
#include "xmlcnitm.hxx"

using namespace ::comphelper;
using namespace ::osl;
using namespace ::rtl;
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;

namespace svx
{
    /** implements a component to export namespaces of all SvXMLAttrContainerItem inside
        one or two pools with a variable count of which ids.
    */
    class NamespaceMap : public WeakImplHelper2< XNameAccess, XServiceInfo >
    {
    private:
        sal_uInt16* mpWhichIds;
        SfxItemPool* mpPool;

    public:
        NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool );
        virtual ~NamespaceMap();

        // XNameAccess
        virtual Any SAL_CALL getByName( const OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
        virtual Sequence< OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (RuntimeException);

        // XElementAccess
        virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);

        // XServiceInfo
        virtual OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
        virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
        virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
    };

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool1, SfxItemPool* )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool1 );
    }

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool );
    }

    Sequence< OUString > SAL_CALL NamespaceMap_getSupportedServiceNames()
        throw()
    {
        Sequence< OUString > aSupportedServiceNames( 1 );
        aSupportedServiceNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.NamespaceMap" ) );
        return aSupportedServiceNames;
    }

    OUString SAL_CALL NamespaceMap_getImplementationName()
        throw()
    {
        return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.NamespaceMap" ) );
    }

    class NamespaceIteratorImpl
    {
    private:
        SfxItemPool* mpPool;

        sal_uInt16* mpWhichId;

        sal_uInt16 mnItemCount;
        sal_uInt16 mnItem;

        const SvXMLAttrContainerItem* mpCurrentAttr;
        sal_uInt16 mnCurrentAttr;

    public:

        NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool );

        sal_Bool next( OUString& rPrefix, OUString& rURL );
    };
}

using namespace ::svx;

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

NamespaceIteratorImpl::NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool )
{
    mpPool = pPool;
    mpCurrentAttr = NULL;
    mnCurrentAttr = 0;

    mpWhichId = pWhichIds;

    mnItem = 0;
    mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
}

sal_Bool NamespaceIteratorImpl::next( OUString& rPrefix, OUString& rURL )
{
    // we still need to process the current attribute
    if( mpCurrentAttr && (mnCurrentAttr != USHRT_MAX) )
    {
        rPrefix = mpCurrentAttr->GetPrefix( mnCurrentAttr );
        rURL = mpCurrentAttr->GetNamespace( mnCurrentAttr );

        mnCurrentAttr = mpCurrentAttr->GetNextNamespaceIndex( mnCurrentAttr );
        return sal_True;
    }

    // we need the next namespace item
    mpCurrentAttr = NULL;

    const SfxPoolItem* pItem = 0;
    // look for the next available item in the current pool
    while( (mnItem < mnItemCount) && ( NULL == (pItem = mpPool->GetItem( *mpWhichId, mnItem ) ) ) )
        mnItem++;

    // are we finished with the current whichid?
    if( mnItem == mnItemCount )
    {
        mpWhichId++;

        // are we finished with the current pool?
        if( 0 != *mpWhichId )
        {
            mnItem = 0;
            mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
            return next( rPrefix, rURL );
        }

        pItem = NULL;
    }

    if( pItem )
    {
        mnItem++;

        // get that item and see if there namespaces inside
        const SvXMLAttrContainerItem *pUnknown = (const SvXMLAttrContainerItem *)pItem;
        if( (pUnknown->GetAttrCount() > 0) )
        {
            mpCurrentAttr = pUnknown;
            mnCurrentAttr = pUnknown->GetFirstNamespaceIndex();
        }
        return next( rPrefix, rURL );
    }

    return false;
}

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

NamespaceMap::NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool )
: mpWhichIds( pWhichIds ), mpPool( pPool )
{
}

NamespaceMap::~NamespaceMap()
{
}

// XNameAccess
Any SAL_CALL NamespaceMap::getByName( const OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    if( !bFound )
        throw NoSuchElementException();

    return makeAny( aURL );
}

Sequence< OUString > SAL_CALL NamespaceMap::getElementNames() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    std::set< OUString, comphelper::UStringLess > aPrefixSet;

    while( aIter.next( aPrefix, aURL ) )
        aPrefixSet.insert( aPrefix );

    Sequence< OUString > aSeq( aPrefixSet.size() );
    OUString* pPrefixes = aSeq.getArray();

    std::set< OUString, comphelper::UStringLess >::iterator aPrefixIter( aPrefixSet.begin() );
    const std::set< OUString, comphelper::UStringLess >::iterator aEnd( aPrefixSet.end() );

    while( aPrefixIter != aEnd )
    {
        *pPrefixes++ = *aPrefixIter++;
    }

    return aSeq;
}

sal_Bool SAL_CALL NamespaceMap::hasByName( const OUString& aName ) throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    return bFound;
}

// XElementAccess
Type SAL_CALL NamespaceMap::getElementType() throw (RuntimeException)
{
    return ::getCppuType( (const OUString*) 0 );
}

sal_Bool SAL_CALL NamespaceMap::hasElements() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    OUString aPrefix;
    OUString aURL;

    return aIter.next( aPrefix, aURL );
}

// XServiceInfo
OUString SAL_CALL NamespaceMap::getImplementationName(  )
    throw(RuntimeException)
{
    return NamespaceMap_getImplementationName();
}

sal_Bool SAL_CALL NamespaceMap::supportsService( const OUString& )
    throw(RuntimeException)
{
    return sal_True;
}

Sequence< OUString > SAL_CALL NamespaceMap::getSupportedServiceNames(  )
    throw(RuntimeException)
{
    return NamespaceMap_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS obo30 (1.8.90); FILE MERGED 2008/06/02 12:27:51 obo 1.8.90.1: #i90100# ambigous Reference during ENABLE_PCH build<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: UnoNamespaceMap.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#include <set>

#include "UnoNamespaceMap.hxx"
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase2.hxx>
#endif
#include <osl/diagnose.h>
#include <osl/mutex.hxx>
#include <comphelper/stl_types.hxx>
#include <svtools/itempool.hxx>
#include "unoapi.hxx"
#include "xmlcnitm.hxx"

using namespace ::comphelper;
using namespace ::osl;
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;

namespace svx
{
    /** implements a component to export namespaces of all SvXMLAttrContainerItem inside
        one or two pools with a variable count of which ids.
    */
    class NamespaceMap : public WeakImplHelper2< XNameAccess, XServiceInfo >
    {
    private:
        sal_uInt16* mpWhichIds;
        SfxItemPool* mpPool;

    public:
        NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool );
        virtual ~NamespaceMap();

        // XNameAccess
        virtual Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (RuntimeException);

        // XElementAccess
        virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
        virtual sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);

        // XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
        virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(RuntimeException);
        virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
    };

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool1, SfxItemPool* )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool1 );
    }

    Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool )
    {
        return (XWeak*)new NamespaceMap( pWhichIds, pPool );
    }

    Sequence< ::rtl::OUString > SAL_CALL NamespaceMap_getSupportedServiceNames()
        throw()
    {
        Sequence< ::rtl::OUString > aSupportedServiceNames( 1 );
        aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.NamespaceMap" ) );
        return aSupportedServiceNames;
    }

    ::rtl::OUString SAL_CALL NamespaceMap_getImplementationName()
        throw()
    {
        return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.NamespaceMap" ) );
    }

    class NamespaceIteratorImpl
    {
    private:
        SfxItemPool* mpPool;

        sal_uInt16* mpWhichId;

        sal_uInt16 mnItemCount;
        sal_uInt16 mnItem;

        const SvXMLAttrContainerItem* mpCurrentAttr;
        sal_uInt16 mnCurrentAttr;

    public:

        NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool );

        sal_Bool next( ::rtl::OUString& rPrefix, ::rtl::OUString& rURL );
    };
}

using namespace ::svx;

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

NamespaceIteratorImpl::NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool )
{
    mpPool = pPool;
    mpCurrentAttr = NULL;
    mnCurrentAttr = 0;

    mpWhichId = pWhichIds;

    mnItem = 0;
    mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
}

sal_Bool NamespaceIteratorImpl::next( ::rtl::OUString& rPrefix, ::rtl::OUString& rURL )
{
    // we still need to process the current attribute
    if( mpCurrentAttr && (mnCurrentAttr != USHRT_MAX) )
    {
        rPrefix = mpCurrentAttr->GetPrefix( mnCurrentAttr );
        rURL = mpCurrentAttr->GetNamespace( mnCurrentAttr );

        mnCurrentAttr = mpCurrentAttr->GetNextNamespaceIndex( mnCurrentAttr );
        return sal_True;
    }

    // we need the next namespace item
    mpCurrentAttr = NULL;

    const SfxPoolItem* pItem = 0;
    // look for the next available item in the current pool
    while( (mnItem < mnItemCount) && ( NULL == (pItem = mpPool->GetItem( *mpWhichId, mnItem ) ) ) )
        mnItem++;

    // are we finished with the current whichid?
    if( mnItem == mnItemCount )
    {
        mpWhichId++;

        // are we finished with the current pool?
        if( 0 != *mpWhichId )
        {
            mnItem = 0;
            mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount( *mpWhichId ) : 0;
            return next( rPrefix, rURL );
        }

        pItem = NULL;
    }

    if( pItem )
    {
        mnItem++;

        // get that item and see if there namespaces inside
        const SvXMLAttrContainerItem *pUnknown = (const SvXMLAttrContainerItem *)pItem;
        if( (pUnknown->GetAttrCount() > 0) )
        {
            mpCurrentAttr = pUnknown;
            mnCurrentAttr = pUnknown->GetFirstNamespaceIndex();
        }
        return next( rPrefix, rURL );
    }

    return false;
}

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

NamespaceMap::NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool )
: mpWhichIds( pWhichIds ), mpPool( pPool )
{
}

NamespaceMap::~NamespaceMap()
{
}

// XNameAccess
Any SAL_CALL NamespaceMap::getByName( const ::rtl::OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    ::rtl::OUString aPrefix;
    ::rtl::OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    if( !bFound )
        throw NoSuchElementException();

    return makeAny( aURL );
}

Sequence< ::rtl::OUString > SAL_CALL NamespaceMap::getElementNames() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    ::rtl::OUString aPrefix;
    ::rtl::OUString aURL;

    std::set< ::rtl::OUString, comphelper::UStringLess > aPrefixSet;

    while( aIter.next( aPrefix, aURL ) )
        aPrefixSet.insert( aPrefix );

    Sequence< ::rtl::OUString > aSeq( aPrefixSet.size() );
    ::rtl::OUString* pPrefixes = aSeq.getArray();

    std::set< ::rtl::OUString, comphelper::UStringLess >::iterator aPrefixIter( aPrefixSet.begin() );
    const std::set< ::rtl::OUString, comphelper::UStringLess >::iterator aEnd( aPrefixSet.end() );

    while( aPrefixIter != aEnd )
    {
        *pPrefixes++ = *aPrefixIter++;
    }

    return aSeq;
}

sal_Bool SAL_CALL NamespaceMap::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    ::rtl::OUString aPrefix;
    ::rtl::OUString aURL;

    sal_Bool bFound;

    do
    {
        bFound = aIter.next( aPrefix, aURL );
    }
    while( bFound && (aPrefix != aName ) );

    return bFound;
}

// XElementAccess
Type SAL_CALL NamespaceMap::getElementType() throw (RuntimeException)
{
    return ::getCppuType( (const ::rtl::OUString*) 0 );
}

sal_Bool SAL_CALL NamespaceMap::hasElements() throw (RuntimeException)
{
    NamespaceIteratorImpl aIter( mpWhichIds, mpPool );

    ::rtl::OUString aPrefix;
    ::rtl::OUString aURL;

    return aIter.next( aPrefix, aURL );
}

// XServiceInfo
::rtl::OUString SAL_CALL NamespaceMap::getImplementationName(  )
    throw(RuntimeException)
{
    return NamespaceMap_getImplementationName();
}

sal_Bool SAL_CALL NamespaceMap::supportsService( const ::rtl::OUString& )
    throw(RuntimeException)
{
    return sal_True;
}

Sequence< ::rtl::OUString > SAL_CALL NamespaceMap::getSupportedServiceNames(  )
    throw(RuntimeException)
{
    return NamespaceMap_getSupportedServiceNames();
}
<|endoftext|>