<commit_before>#include "program.h"
#include <vector>

namespace opencl {

// /* Program Object APIs  */
// extern CL_API_ENTRY cl_program CL_API_CALL
// clCreateProgramWithSource(cl_context        /* context */,
//                           cl_uint           /* count */,
//                           const char **     /* strings */,
//                           const size_t *    /* lengths */,
//                           cl_int *          /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(CreateProgramWithSource) {
  NanScope();
  REQ_ARGS(2);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_CONTEXT));
  }
  cl_context context=Unwrap<cl_context>(args[0]);
  REQ_STR_ARG(1, str);

  cl_int ret=CL_SUCCESS;
  size_t lengths[]={(size_t) str.length()};
  const char *strings[]={*str};
  cl_program p=::clCreateProgramWithSource(context, 1, strings, lengths, &ret);
  CHECK_ERR(ret);

  NanReturnValue(Wrap(p));
}

// extern CL_API_ENTRY cl_program CL_API_CALL
// clCreateProgramWithBinary(cl_context                     /* context */,
//                           cl_uint                        /* num_devices */,
//                           const cl_device_id *           /* device_list */,
//                           const size_t *                 /* lengths */,
//                           const unsigned char **         /* binaries */,
//                           cl_int *                       /* binary_status */,
//                           cl_int *                       /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(CreateProgramWithBinary) {
  NanScope();
  REQ_ARGS(3);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_CONTEXT));
  }
  cl_context context=Unwrap<cl_context>(args[0]);

  Local<Array> devices = Local<Array>::Cast(args[1]);
  vector<cl_device_id> cl_devices;
  for (uint32_t i=0; i < devices->Length(); i++)
    cl_devices.push_back(Unwrap<cl_device_id>(devices->Get(i)));

  Local<Array> binaries = Local<Array>::Cast(args[2]);
  const size_t n = binaries->Length();
  unique_ptr<size_t[]> lengths(new size_t[n]);
  unique_ptr<const unsigned char*[]> images(new const unsigned char*[n]);

  for (uint32_t i = 0; i < n; ++i) {
    Local<Object> obj=binaries->Get(i)->ToObject();
    images[i] = (const unsigned char*) obj->GetIndexedPropertiesExternalArrayData();
    lengths[i] = obj->GetIndexedPropertiesExternalArrayDataLength();
  }

  cl_int ret=CL_SUCCESS;
  cl_program p=::clCreateProgramWithBinary(
              context, (cl_uint) cl_devices.size(),
              &cl_devices.front(),
              lengths.get(), images.get(),
              NULL, &ret);
  CHECK_ERR(ret);

  NanReturnValue(Wrap(p));
}

// extern CL_API_ENTRY cl_program CL_API_CALL
// clCreateProgramWithBuiltInKernels(cl_context            /* context */,
//                                   cl_uint               /* num_devices */,
//                                   const cl_device_id *  /* device_list */,
//                                   const char *          /* kernel_names */,
//                                   cl_int *              /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(CreateProgramWithBuiltInKernels) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clRetainProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(RetainProgram) {
  NanScope();
  REQ_ARGS(1);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);
  cl_int count=clRetainProgram(p);

  NanReturnValue(JS_INT(count));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(ReleaseProgram) {
  NanScope();
  REQ_ARGS(1);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);
  cl_int count=clReleaseProgram(p);

  NanReturnValue(JS_INT(count));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clBuildProgram(cl_program           /* program */,
//                cl_uint              /* num_devices */,
//                const cl_device_id * /* device_list */,
//                const char *         /* options */,
//                void (CL_CALLBACK *  /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
//                void *               /* user_data */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(BuildProgram) {
  NanScope();
  REQ_ARGS(1);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);
  std::vector<cl_device_id> devices;

  if (!args[1]->IsNull() && !args[1]->IsUndefined()){
    getValuesFromArray(Local<Array>::Cast(args[1]),devices);
  }

  unique_ptr<String::Utf8Value> options = NULL;

  if (!args[2]->IsNull() && !args[2]->IsUndefined()){
    if (!args[2]->IsString())
      NanThrowTypeError("Argument 2 must be a string");
    options = unique_ptr<String::Utf8Value>( new String::Utf8Value(args[2]->ToString()));
  }

  //REQ_STR_ARG(2,options);

  // TODO callback + userdata

  CHECK_ERR(::clBuildProgram(p,
    devices.size(), devices.size() ? &devices.front() : nullptr,
    options != NULL ? **options : nullptr,
    nullptr, nullptr)); // TODO CB

  NanReturnValue(JS_INT(CL_SUCCESS));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clCompileProgram(cl_program           /* program */,
//                  cl_uint              /* num_devices */,
//                  const cl_device_id * /* device_list */,
//                  const char *         /* options */,
//                  cl_uint              /* num_input_headers */,
//                  const cl_program *   /* input_headers */,
//                  const char **        /* header_include_names */,
//                  void (CL_CALLBACK *  /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
//                  void *               /* user_data */) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(CompileProgram) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_program CL_API_CALL
// clLinkProgram(cl_context           /* context */,
//               cl_uint              /* num_devices */,
//               const cl_device_id * /* device_list */,
//               const char *         /* options */,
//               cl_uint              /* num_input_programs */,
//               const cl_program *   /* input_programs */,
//               void (CL_CALLBACK *  /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
//               void *               /* user_data */,
//               cl_int *             /* errcode_ret */ ) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(LinkProgram) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clUnloadPlatformCompiler(cl_platform_id /* platform */) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(UnloadPlatformCompiler) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clGetProgramInfo(cl_program         /* program */,
//                  cl_program_info    /* param_name */,
//                  size_t             /* param_value_size */,
//                  void *             /* param_value */,
//                  size_t *           /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(GetProgramInfo) {
  NanScope();
  REQ_ARGS(2);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_MEM_OBJECT));
  }
  cl_program prog=Unwrap<cl_program>(args[0]);
  cl_program_info param_name = args[1]->Uint32Value();

  switch(param_name) {
    case CL_PROGRAM_REFERENCE_COUNT:
    case CL_PROGRAM_NUM_DEVICES:
    {
      cl_uint val;
      CHECK_ERR(::clGetProgramInfo(prog,param_name,sizeof(cl_uint), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
    case CL_PROGRAM_CONTEXT:
    {
      cl_context val;
      CHECK_ERR(::clGetProgramInfo(prog,param_name,sizeof(cl_context), &val, NULL))
      // TODO NanReturnValue(JS_INT(val));
      break;
    }
    case CL_PROGRAM_DEVICES:
    {
      // TODO
      break;
    }
    case CL_PROGRAM_BINARY_SIZES:
    {
      size_t nsizes;
      CHECK_ERR(::clGetProgramInfo(prog, param_name, 0, NULL, &nsizes));

      // get CL_DEVICE_MAX_WORK_ITEM_SIZES array param
      unique_ptr<size_t[]> sizes(new size_t[nsizes]);
      CHECK_ERR(::clGetProgramInfo(prog, param_name, nsizes*sizeof(size_t), sizes.get(), NULL));
      Local<Array> arr = Array::New(nsizes);
      for(cl_uint i=0;i<nsizes;i++)
        arr->Set(i,JS_INT(sizes[i]));

      NanReturnValue(arr);
    }
    case CL_PROGRAM_BINARIES:
    {
      size_t nbins=0;
      CHECK_ERR(::clGetProgramInfo(prog, param_name, 0, NULL, &nbins));
      nbins /= sizeof(size_t);
      unique_ptr<char*[]> binaries(new char*[nbins]);
      CHECK_ERR(::clGetProgramInfo(prog, param_name, sizeof(char*)*nbins, binaries.get(), NULL));

      // TODO create an array for Uint8Array to return each binary associated to each device
      // Handle<Value> abv = Context::GetCurrent()->Global()->Get(String::NewSymbol("ArrayBuffer"));
      // Handle<Value> argv[] = { Integer::NewFromUnsigned(size) };
      // Handle<Object> arrbuf = Handle<Function>::Cast(abv)->NewInstance(1, argv);
      // void *buffer = arrbuf->GetPointerFromInternalField(0);
      // memcpy(buffer, data, size);

      NanReturnUndefined();
    }
    case CL_PROGRAM_NUM_KERNELS:
    {
      size_t val;
      CHECK_ERR(::clGetProgramInfo(prog,param_name,sizeof(size_t), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
    case CL_PROGRAM_SOURCE:
    case CL_PROGRAM_KERNEL_NAMES:
    {
      size_t nchars;
      CHECK_ERR(::clGetProgramInfo(prog, param_name, 0, NULL, &nchars));
      unique_ptr<char[]> names(new char[nchars]);
      CHECK_ERR(::clGetProgramInfo(prog, param_name, nchars*sizeof(char), names.get(), NULL));
      NanReturnValue(JS_STR(names.get()));
    }
  }
  return NanThrowError(JS_INT(CL_INVALID_VALUE));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clGetProgramBuildInfo(cl_program            /* program */,
//                       cl_device_id          /* device */,
//                       cl_program_build_info /* param_name */,
//                       size_t                /* param_value_size */,
//                       void *                /* param_value */,
//                       size_t *              /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(GetProgramBuildInfo) {
  NanScope();
  REQ_ARGS(3);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_MEM_OBJECT));
  }
  cl_program prog=Unwrap<cl_program>(args[0]);
  if(!isOpenCLObj(args[1])) {
    return NanThrowError(JS_INT(CL_INVALID_DEVICE));
  }
  cl_device_id device=Unwrap<cl_device_id>(args[1]);
  cl_program_build_info param_name = args[2]->Uint32Value();

  switch(param_name) {
    case CL_PROGRAM_BUILD_STATUS:
    {
      cl_build_status val;
      CHECK_ERR(::clGetProgramBuildInfo(prog, device,param_name,sizeof(cl_build_status), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
    case CL_PROGRAM_BUILD_OPTIONS:
    case CL_PROGRAM_BUILD_LOG:
    {
      size_t param_value_size_ret=0;
      CHECK_ERR(::clGetProgramBuildInfo(prog, device, param_name, 0, NULL, &param_value_size_ret));
      unique_ptr<char[]> param_value(new char[param_value_size_ret]);
      CHECK_ERR(::clGetProgramBuildInfo(prog, device, param_name, param_value_size_ret, param_value.get(), NULL));
      NanReturnValue(JS_STR(param_value.get(),(int)param_value_size_ret));
    }
    case CL_PROGRAM_BINARY_TYPE:
    {
      cl_program_binary_type val;
      CHECK_ERR(::clGetProgramBuildInfo(prog, device,param_name,sizeof(cl_program_binary_type), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
  }
  return NanThrowError(JS_INT(CL_INVALID_VALUE));
}

namespace Program {
void init(Handle<Object> exports)
{
  NODE_SET_METHOD(exports, "createProgramWithSource", CreateProgramWithSource);
  NODE_SET_METHOD(exports, "createProgramWithBinary", CreateProgramWithBinary);
  NODE_SET_METHOD(exports, "createProgramWithBuiltInKernels", CreateProgramWithBuiltInKernels);
  NODE_SET_METHOD(exports, "retainProgram", RetainProgram);
  NODE_SET_METHOD(exports, "releaseProgram", ReleaseProgram);
  NODE_SET_METHOD(exports, "buildProgram", BuildProgram);
  NODE_SET_METHOD(exports, "compileProgram", CompileProgram);
  NODE_SET_METHOD(exports, "linkProgram", LinkProgram);
  NODE_SET_METHOD(exports, "unloadPlatformCompiler", UnloadPlatformCompiler);
  NODE_SET_METHOD(exports, "getProgramInfo", GetProgramInfo);
  NODE_SET_METHOD(exports, "getProgramBuildInfo", GetProgramBuildInfo);
}
} // namespace Program

} // namespace opencl
<commit_msg>[Implementation] compileProgram<commit_after>#include "program.h"
#include <vector>
#include <Python/Python.h>

namespace opencl {

// /* Program Object APIs  */
// extern CL_API_ENTRY cl_program CL_API_CALL
// clCreateProgramWithSource(cl_context        /* context */,
//                           cl_uint           /* count */,
//                           const char **     /* strings */,
//                           const size_t *    /* lengths */,
//                           cl_int *          /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(CreateProgramWithSource) {
  NanScope();
  REQ_ARGS(2);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_CONTEXT));
  }
  cl_context context=Unwrap<cl_context>(args[0]);
  REQ_STR_ARG(1, str);

  cl_int ret=CL_SUCCESS;
  size_t lengths[]={(size_t) str.length()};
  const char *strings[]={*str};
  cl_program p=::clCreateProgramWithSource(context, 1, strings, lengths, &ret);
  CHECK_ERR(ret);

  NanReturnValue(Wrap(p));
}

// extern CL_API_ENTRY cl_program CL_API_CALL
// clCreateProgramWithBinary(cl_context                     /* context */,
//                           cl_uint                        /* num_devices */,
//                           const cl_device_id *           /* device_list */,
//                           const size_t *                 /* lengths */,
//                           const unsigned char **         /* binaries */,
//                           cl_int *                       /* binary_status */,
//                           cl_int *                       /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(CreateProgramWithBinary) {
  NanScope();
  REQ_ARGS(3);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_CONTEXT));
  }
  cl_context context=Unwrap<cl_context>(args[0]);

  Local<Array> devices = Local<Array>::Cast(args[1]);
  vector<cl_device_id> cl_devices;
  for (uint32_t i=0; i < devices->Length(); i++)
    cl_devices.push_back(Unwrap<cl_device_id>(devices->Get(i)));

  Local<Array> binaries = Local<Array>::Cast(args[2]);
  const size_t n = binaries->Length();
  unique_ptr<size_t[]> lengths(new size_t[n]);
  unique_ptr<const unsigned char*[]> images(new const unsigned char*[n]);

  for (uint32_t i = 0; i < n; ++i) {
    Local<Object> obj=binaries->Get(i)->ToObject();
    images[i] = (const unsigned char*) obj->GetIndexedPropertiesExternalArrayData();
    lengths[i] = obj->GetIndexedPropertiesExternalArrayDataLength();
  }

  cl_int ret=CL_SUCCESS;
  cl_program p=::clCreateProgramWithBinary(
              context, (cl_uint) cl_devices.size(),
              &cl_devices.front(),
              lengths.get(), images.get(),
              NULL, &ret);
  CHECK_ERR(ret);

  NanReturnValue(Wrap(p));
}

// extern CL_API_ENTRY cl_program CL_API_CALL
// clCreateProgramWithBuiltInKernels(cl_context            /* context */,
//                                   cl_uint               /* num_devices */,
//                                   const cl_device_id *  /* device_list */,
//                                   const char *          /* kernel_names */,
//                                   cl_int *              /* errcode_ret */) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(CreateProgramWithBuiltInKernels) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clRetainProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(RetainProgram) {
  NanScope();
  REQ_ARGS(1);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);
  cl_int count=clRetainProgram(p);

  NanReturnValue(JS_INT(count));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clReleaseProgram(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(ReleaseProgram) {
  NanScope();
  REQ_ARGS(1);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);
  cl_int count=clReleaseProgram(p);

  NanReturnValue(JS_INT(count));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clBuildProgram(cl_program           /* program */,
//                cl_uint              /* num_devices */,
//                const cl_device_id * /* device_list */,
//                const char *         /* options */,
//                void (CL_CALLBACK *  /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
//                void *               /* user_data */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(BuildProgram) {
  NanScope();
  REQ_ARGS(1);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);
  std::vector<cl_device_id> devices;

  if (argExists(args, 1)){
    getValuesFromArray(Local<Array>::Cast(args[1]),devices);
  }

  String::Utf8Value * options = nullptr;

  if (argExists(args, 2)){
    if (!args[2]->IsString())
      NanThrowTypeError("Argument 3 must be a string");
    options = new String::Utf8Value(args[2]);
  }

  //REQ_STR_ARG(2,options);

  // TODO callback + userdata

  int err = ::clBuildProgram(p,
    devices.size(), devices.size() ? &devices.front() : nullptr,
    options != NULL ? **options : nullptr,
    nullptr, nullptr);

  delete options;

  CHECK_ERR(err); // TODO CB

  NanReturnValue(JS_INT(CL_SUCCESS));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clCompileProgram(cl_program           /* program */,
//                  cl_uint              /* num_devices */,
//                  const cl_device_id * /* device_list */,
//                  const char *         /* options */,
//                  cl_uint              /* num_input_headers */,
//                  const cl_program *   /* input_headers */,
//                  const char **        /* header_include_names */,
//                  void (CL_CALLBACK *  /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
//                  void *               /* user_data */) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(CompileProgram) {
  NanScope();
  REQ_ARGS(1);

  // Arg 1 : program
  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_PROGRAM));
  }

  cl_program p = Unwrap<cl_program>(args[0]);

  // Arg 2 : devices
  std::vector<cl_device_id> devices;

  if (argExists(args, 1)){
    getValuesFromArray(Local<Array>::Cast(args[1]),devices);
  }

  // Arg 3 : Options
  String::Utf8Value * options = nullptr;

  if (argExists(args, 2)){
    if (!args[2]->IsString())
      NanThrowTypeError("Argument 3 must be a string");
    options = new String::Utf8Value(args[2]);
  }

  // Arg 4 : programs included
  // Arg 5 : headers names
  std::vector<cl_program> program_headers;
  std::vector<const char *> names;

  // Checking correct mapping
  if (argExists(args, 3)){
    if (!args[3]->IsArray()) {
      NanThrowTypeError("Argument 4 must be an array");
    } else {
      getValuesFromArray(Local<Array>::Cast(args[3]), program_headers);
    }
  }

  if (argExists(args, 4)){
    Local<Array> arr = Local<Array>::Cast(args[4]);
    for (int i = 0; i < arr->Length(); ++ i) {
      String::Utf8Value str(arr->Get(i));
      names.push_back(str.operator*());
    }
  }

  // Arg 4 and 5 mapping
  if (program_headers.size() != names.size()) {
    NanThrowError("Program headers and names should be of the same size");
  }

  // CL CALL
  // TODO Callbacks

  int err = ::clCompileProgram(
    p,
    devices.size(), devices.size() ? &devices.front() : nullptr,
    options != NULL ? **options : nullptr,
    program_headers.size(), program_headers.size() ? &program_headers.front() : nullptr,
    &names.front(),
    nullptr, nullptr);

  delete options;

  CHECK_ERR(err);

  NanReturnValue(JS_INT(CL_SUCCESS));
}

// extern CL_API_ENTRY cl_program CL_API_CALL
// clLinkProgram(cl_context           /* context */,
//               cl_uint              /* num_devices */,
//               const cl_device_id * /* device_list */,
//               const char *         /* options */,
//               cl_uint              /* num_input_programs */,
//               const cl_program *   /* input_programs */,
//               void (CL_CALLBACK *  /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
//               void *               /* user_data */,
//               cl_int *             /* errcode_ret */ ) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(LinkProgram) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clUnloadPlatformCompiler(cl_platform_id /* platform */) CL_API_SUFFIX__VERSION_1_2;
NAN_METHOD(UnloadPlatformCompiler) {
  NanScope();
  // TODO
  NanReturnUndefined();

}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clGetProgramInfo(cl_program         /* program */,
//                  cl_program_info    /* param_name */,
//                  size_t             /* param_value_size */,
//                  void *             /* param_value */,
//                  size_t *           /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(GetProgramInfo) {
  NanScope();
  REQ_ARGS(2);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_MEM_OBJECT));
  }
  cl_program prog=Unwrap<cl_program>(args[0]);
  cl_program_info param_name = args[1]->Uint32Value();

  switch(param_name) {
    case CL_PROGRAM_REFERENCE_COUNT:
    case CL_PROGRAM_NUM_DEVICES:
    {
      cl_uint val;
      CHECK_ERR(::clGetProgramInfo(prog,param_name,sizeof(cl_uint), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
    case CL_PROGRAM_CONTEXT:
    {
      cl_context val;
      CHECK_ERR(::clGetProgramInfo(prog,param_name,sizeof(cl_context), &val, NULL))
      // TODO NanReturnValue(JS_INT(val));
      break;
    }
    case CL_PROGRAM_DEVICES:
    {
      // TODO
      break;
    }
    case CL_PROGRAM_BINARY_SIZES:
    {
      size_t nsizes;
      CHECK_ERR(::clGetProgramInfo(prog, param_name, 0, NULL, &nsizes));

      // get CL_DEVICE_MAX_WORK_ITEM_SIZES array param
      unique_ptr<size_t[]> sizes(new size_t[nsizes]);
      CHECK_ERR(::clGetProgramInfo(prog, param_name, nsizes*sizeof(size_t), sizes.get(), NULL));
      Local<Array> arr = Array::New(nsizes);
      for(cl_uint i=0;i<nsizes;i++)
        arr->Set(i,JS_INT(sizes[i]));

      NanReturnValue(arr);
    }
    case CL_PROGRAM_BINARIES:
    {
      size_t nbins=0;
      CHECK_ERR(::clGetProgramInfo(prog, param_name, 0, NULL, &nbins));
      nbins /= sizeof(size_t);
      unique_ptr<char*[]> binaries(new char*[nbins]);
      CHECK_ERR(::clGetProgramInfo(prog, param_name, sizeof(char*)*nbins, binaries.get(), NULL));

      // TODO create an array for Uint8Array to return each binary associated to each device
      // Handle<Value> abv = Context::GetCurrent()->Global()->Get(String::NewSymbol("ArrayBuffer"));
      // Handle<Value> argv[] = { Integer::NewFromUnsigned(size) };
      // Handle<Object> arrbuf = Handle<Function>::Cast(abv)->NewInstance(1, argv);
      // void *buffer = arrbuf->GetPointerFromInternalField(0);
      // memcpy(buffer, data, size);

      NanReturnUndefined();
    }
    case CL_PROGRAM_NUM_KERNELS:
    {
      size_t val;
      CHECK_ERR(::clGetProgramInfo(prog,param_name,sizeof(size_t), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
    case CL_PROGRAM_SOURCE:
    case CL_PROGRAM_KERNEL_NAMES:
    {
      size_t nchars;
      CHECK_ERR(::clGetProgramInfo(prog, param_name, 0, NULL, &nchars));
      unique_ptr<char[]> names(new char[nchars]);
      CHECK_ERR(::clGetProgramInfo(prog, param_name, nchars*sizeof(char), names.get(), NULL));
      NanReturnValue(JS_STR(names.get()));
    }
  }
  return NanThrowError(JS_INT(CL_INVALID_VALUE));
}

// extern CL_API_ENTRY cl_int CL_API_CALL
// clGetProgramBuildInfo(cl_program            /* program */,
//                       cl_device_id          /* device */,
//                       cl_program_build_info /* param_name */,
//                       size_t                /* param_value_size */,
//                       void *                /* param_value */,
//                       size_t *              /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
NAN_METHOD(GetProgramBuildInfo) {
  NanScope();
  REQ_ARGS(3);

  if(!isOpenCLObj(args[0])) {
    return NanThrowError(JS_INT(CL_INVALID_MEM_OBJECT));
  }
  cl_program prog=Unwrap<cl_program>(args[0]);
  if(!isOpenCLObj(args[1])) {
    return NanThrowError(JS_INT(CL_INVALID_DEVICE));
  }
  cl_device_id device=Unwrap<cl_device_id>(args[1]);
  cl_program_build_info param_name = args[2]->Uint32Value();

  switch(param_name) {
    case CL_PROGRAM_BUILD_STATUS:
    {
      cl_build_status val;
      CHECK_ERR(::clGetProgramBuildInfo(prog, device,param_name,sizeof(cl_build_status), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
    case CL_PROGRAM_BUILD_OPTIONS:
    case CL_PROGRAM_BUILD_LOG:
    {
      size_t param_value_size_ret=0;
      CHECK_ERR(::clGetProgramBuildInfo(prog, device, param_name, 0, NULL, &param_value_size_ret));
      unique_ptr<char[]> param_value(new char[param_value_size_ret]);
      CHECK_ERR(::clGetProgramBuildInfo(prog, device, param_name, param_value_size_ret, param_value.get(), NULL));
      NanReturnValue(JS_STR(param_value.get(),(int)param_value_size_ret));
    }
    case CL_PROGRAM_BINARY_TYPE:
    {
      cl_program_binary_type val;
      CHECK_ERR(::clGetProgramBuildInfo(prog, device,param_name,sizeof(cl_program_binary_type), &val, NULL))
      NanReturnValue(JS_INT(val));
    }
  }
  return NanThrowError(JS_INT(CL_INVALID_VALUE));
}

namespace Program {
void init(Handle<Object> exports)
{
  NODE_SET_METHOD(exports, "createProgramWithSource", CreateProgramWithSource);
  NODE_SET_METHOD(exports, "createProgramWithBinary", CreateProgramWithBinary);
  NODE_SET_METHOD(exports, "createProgramWithBuiltInKernels", CreateProgramWithBuiltInKernels);
  NODE_SET_METHOD(exports, "retainProgram", RetainProgram);
  NODE_SET_METHOD(exports, "releaseProgram", ReleaseProgram);
  NODE_SET_METHOD(exports, "buildProgram", BuildProgram);
  NODE_SET_METHOD(exports, "compileProgram", CompileProgram);
  NODE_SET_METHOD(exports, "linkProgram", LinkProgram);
  NODE_SET_METHOD(exports, "unloadPlatformCompiler", UnloadPlatformCompiler);
  NODE_SET_METHOD(exports, "getProgramInfo", GetProgramInfo);
  NODE_SET_METHOD(exports, "getProgramBuildInfo", GetProgramBuildInfo);
}
} // namespace Program

} // namespace opencl
<|endoftext|>


<commit_before>/**
 * This file implements a command line utility to interact
 * with the d2 library.
 */

#include <d2/analysis.hpp>
#include <d2/event_repository.hpp>
#include <d2/graph_construction.hpp>

#include <boost/assert.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/properties.hpp>
#include <boost/optional.hpp>
#include <boost/phoenix.hpp>
#include <boost/program_options.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <cstddef>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>

static std::string const VERSION = "0.1a";

namespace po = boost::program_options;
namespace phx = boost::phoenix;
using phx::arg_names::_1;

namespace {

// Dot rendering
template <typename LockGraph>
class LockGraphWriter {
    typedef typename boost::graph_traits<LockGraph>::edge_descriptor
                                                            EdgeDescriptor;
    typedef typename boost::graph_traits<LockGraph>::vertex_descriptor
                                                            VertexDescriptor;
    LockGraph const& graph_;

public:
    explicit LockGraphWriter(LockGraph const& lg) : graph_(lg) { }

    template <typename Ostream>
    void operator()(Ostream& os, EdgeDescriptor edge) const {
        os << "[label=\""
           << "from " << graph_[edge].l1_info.call_stack[0].function

           << " to " << graph_[edge].l2_info.call_stack[0].function
           << "\"]";
    }

    template <typename Ostream>
    void operator()(Ostream&, VertexDescriptor) const {

    }
};

template <typename LockGraph>
LockGraphWriter<LockGraph> render_dot(LockGraph const& lg) {
    return LockGraphWriter<LockGraph>(lg);
}

// Statistic gathering
template <typename LockGraph, typename SegmentationGraph>
struct Statistics {
    Statistics(LockGraph const& lg, SegmentationGraph const&)
        : number_of_lock_graph_vertices(num_vertices(lg)),
          number_of_lock_graph_edges(num_edges(lg))
    { }

    std::size_t number_of_lock_graph_vertices;
    std::size_t number_of_lock_graph_edges;
    boost::optional<std::size_t> number_of_distinct_cycles;

    template <typename Ostream>
    friend Ostream& operator<<(Ostream& os, Statistics const& self) {
        os << "number of vertices in the lock graph: " << self.number_of_lock_graph_vertices << '\n'
           << "number of edges in the lock graph: " << self.number_of_lock_graph_edges << '\n'
           << "number of distinct cycles in the lock graph: ";

        if (self.number_of_distinct_cycles)
            os << *self.number_of_distinct_cycles;
        else
            os << "not computed";

        return os;
    }
};

template <typename Stats>
class StatisticGatherer {
    Stats& stats_;

public:
    explicit StatisticGatherer(Stats& stats) : stats_(stats) {
        BOOST_ASSERT_MSG(!stats_.number_of_distinct_cycles,
        "gathering statistics on a statistic object that was already filled");
        stats_.number_of_distinct_cycles = 0;
    }

    template <typename EdgePath, typename LockGraph>
    void operator()(EdgePath const&, LockGraph const&) const {
        ++*stats_.number_of_distinct_cycles;
    }
};

template <typename Stats>
StatisticGatherer<Stats> gather_stats(Stats& stats) {
    return StatisticGatherer<Stats>(stats);
}

// Deadlock analysis
template <typename Ostream>
class CyclePrinter {
    Ostream& os_;

    void format_call_stack(d2::detail::LockDebugInfo const& info,
                           std::string const& indent = "") const {
        BOOST_FOREACH(d2::detail::StackFrame const& frame, info.call_stack) {
            os_ << indent << frame << '\n';
        }
    }

public:
    explicit CyclePrinter(Ostream& os) : os_(os) { }

    template <typename EdgePath, typename LockGraph>
    void operator()(EdgePath const& cycle, LockGraph const& graph) const {
        typedef typename boost::graph_traits<LockGraph>::edge_descriptor
                                                    LockGraphEdgeDescriptor;
        typedef typename boost::edge_property_type<LockGraph>::type
                                                                LockGraphEdge;
        os_ << "----------------------------------------------------";

        BOOST_FOREACH(LockGraphEdgeDescriptor const& edge_desc, cycle) {
            LockGraphEdge const& edge = graph[edge_desc];
            d2::SyncObject const& l1 = graph[source(edge_desc, graph)];
            d2::SyncObject const& l2 = graph[target(edge_desc, graph)];

            os_ << '\n';

            os_ << "Thread " << edge.t << " acquired lock " << l2 << " in\n";
            format_call_stack(edge.l2_info, "    ");

            os_ << "while holding lock " << l1 << " taken in\n";
            format_call_stack(edge.l1_info, "    ");
        }

        os_ << "----------------------------------------------------\n\n";
    }
};

template <typename Ostream>
CyclePrinter<Ostream> print_cycle(Ostream& os) {
    return CyclePrinter<Ostream>(os);
}

} // end anonymous namespace

int main(int argc, char const* argv[]) {
    // Parse command line options.
    po::options_description global("Global options");
    global.add_options()
    (
        "help,h", "produce help message and exit"
    )(
        "version,v", "print version and exit"
    )(
        "output-file,o", po::value<std::string>(), "file to write the output to"
    )(
        "analyze", "perform the analysis for deadlocks"
    )(
        "dot", "produce a dot representation of the lock graph used during the analysis"
    )(
        "stats", "produce statistics about the usage of locks and threads"
    )
    ;

    po::options_description hidden;
    hidden.add_options()
        ("repo-path", po::value<std::string>(), "path of the repository to examine")
    ;
    po::positional_options_description positionals;
    positionals.add("repo-path", 1);

    po::options_description analysis("Analysis options");

    po::options_description dot("Dot rendering options");

    po::options_description statistics("Statistics options");

    po::options_description allowed;
    allowed.add(global).add(analysis).add(dot).add(statistics);

    po::options_description all;
    all.add(allowed).add(hidden);

    po::variables_map args;
    po::command_line_parser parser(argc, argv);
    try {
        po::store(parser.options(all).positional(positionals).run(), args);
        po::notify(args);
    } catch(po::error const& e) {
        std::cerr << e.what() << std::endl
                  << allowed << std::endl;
        return EXIT_FAILURE;
    }

    // Some options make us do something and exit right away. These cases
    // are handled here.
    {
        typedef boost::function<void(po::variable_value)> DieAction;
        std::map<std::string, DieAction> die_actions =
        boost::assign::map_list_of<std::string, DieAction>
            ("help", phx::ref(std::cout) << allowed << '\n')
            ("version", phx::ref(std::cout) << VERSION << '\n')
        ;
        typedef std::pair<std::string, DieAction> DieActionPair;
        BOOST_FOREACH(DieActionPair const& action, die_actions) {
            if (args.count(action.first)) {
                action.second(args[action.first]);
                return EXIT_FAILURE;
            }
        }
    }

    // Open the repository on which we must operate.
    if (!args.count("repo-path")) {
        std::cerr << "missing the path of a repository on which to operate "
                     "from the command line" << std::endl
                  << allowed << std::endl;
        return EXIT_FAILURE;
    }
    d2::EventRepository<> repository(args["repo-path"].as<std::string>());

    // Open the output stream to whatever passed on the command line or to
    // stdout if unspecified.
    std::ofstream output_ofs;
    if (args.count("output-file")) {
        std::string output_file = args["output-file"].as<std::string>();
        output_ofs.open(output_file.c_str());
        if (!output_ofs) {
            std::cerr << "Unable to open output file \"" << output_file <<'"';
            return EXIT_FAILURE;
        }
    }
    std::ostream& output = args.count("output-file") ? output_ofs : std::cout;

    // Build the segmentation and the lock graph. They are required no matter
    // the options we received on the command line.
    d2::SegmentationGraph sg;
    d2::LockGraph lg;
    d2::build_graphs(repository, lg, sg);

    // Main switch dispatching to the right action to perform.
    if (args.count("analyze") || (!args.count("dot") && !args.count("stats"))) {
        d2::analyze(lg, sg, print_cycle(std::cout));
    }
    else if (args.count("dot")) {
        boost::write_graphviz(output, lg, render_dot(lg), render_dot(lg));
    }
    else if (args.count("stats")) {
        Statistics<d2::LockGraph, d2::SegmentationGraph> stats(lg, sg);
        d2::analyze(lg, sg, gather_stats(stats));
        output << stats << std::endl;
    }
    return EXIT_SUCCESS;
}
<commit_msg>Handle errors emitted during graph construction in the command line utility.<commit_after>/**
 * This file implements a command line utility to interact
 * with the d2 library.
 */

#include <d2/analysis.hpp>
#include <d2/event_repository.hpp>
#include <d2/graph_construction.hpp>

#include <boost/assert.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/properties.hpp>
#include <boost/optional.hpp>
#include <boost/phoenix.hpp>
#include <boost/program_options.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <cstddef>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>

static std::string const VERSION = "0.1a";

namespace po = boost::program_options;
namespace phx = boost::phoenix;
using phx::arg_names::_1;

namespace {

// Dot rendering
template <typename LockGraph>
class LockGraphWriter {
    typedef typename boost::graph_traits<LockGraph>::edge_descriptor
                                                            EdgeDescriptor;
    typedef typename boost::graph_traits<LockGraph>::vertex_descriptor
                                                            VertexDescriptor;
    LockGraph const& graph_;

public:
    explicit LockGraphWriter(LockGraph const& lg) : graph_(lg) { }

    template <typename Ostream>
    void operator()(Ostream& os, EdgeDescriptor edge) const {
        os << "[label=\""
           << "from " << graph_[edge].l1_info.call_stack[0].function

           << " to " << graph_[edge].l2_info.call_stack[0].function
           << "\"]";
    }

    template <typename Ostream>
    void operator()(Ostream&, VertexDescriptor) const {

    }
};

template <typename LockGraph>
LockGraphWriter<LockGraph> render_dot(LockGraph const& lg) {
    return LockGraphWriter<LockGraph>(lg);
}

// Statistic gathering
template <typename LockGraph, typename SegmentationGraph>
struct Statistics {
    Statistics(LockGraph const& lg, SegmentationGraph const&)
        : number_of_lock_graph_vertices(num_vertices(lg)),
          number_of_lock_graph_edges(num_edges(lg))
    { }

    std::size_t number_of_lock_graph_vertices;
    std::size_t number_of_lock_graph_edges;
    boost::optional<std::size_t> number_of_distinct_cycles;

    template <typename Ostream>
    friend Ostream& operator<<(Ostream& os, Statistics const& self) {
        os << "number of vertices in the lock graph: " << self.number_of_lock_graph_vertices << '\n'
           << "number of edges in the lock graph: " << self.number_of_lock_graph_edges << '\n'
           << "number of distinct cycles in the lock graph: ";

        if (self.number_of_distinct_cycles)
            os << *self.number_of_distinct_cycles;
        else
            os << "not computed";

        return os;
    }
};

template <typename Stats>
class StatisticGatherer {
    Stats& stats_;

public:
    explicit StatisticGatherer(Stats& stats) : stats_(stats) {
        BOOST_ASSERT_MSG(!stats_.number_of_distinct_cycles,
        "gathering statistics on a statistic object that was already filled");
        stats_.number_of_distinct_cycles = 0;
    }

    template <typename EdgePath, typename LockGraph>
    void operator()(EdgePath const&, LockGraph const&) const {
        ++*stats_.number_of_distinct_cycles;
    }
};

template <typename Stats>
StatisticGatherer<Stats> gather_stats(Stats& stats) {
    return StatisticGatherer<Stats>(stats);
}

// Deadlock analysis
template <typename Ostream>
class CyclePrinter {
    Ostream& os_;

    void format_call_stack(d2::detail::LockDebugInfo const& info,
                           std::string const& indent = "") const {
        BOOST_FOREACH(d2::detail::StackFrame const& frame, info.call_stack) {
            os_ << indent << frame << '\n';
        }
    }

public:
    explicit CyclePrinter(Ostream& os) : os_(os) { }

    template <typename EdgePath, typename LockGraph>
    void operator()(EdgePath const& cycle, LockGraph const& graph) const {
        typedef typename boost::graph_traits<LockGraph>::edge_descriptor
                                                    LockGraphEdgeDescriptor;
        typedef typename boost::edge_property_type<LockGraph>::type
                                                                LockGraphEdge;
        os_ << "----------------------------------------------------";

        BOOST_FOREACH(LockGraphEdgeDescriptor const& edge_desc, cycle) {
            LockGraphEdge const& edge = graph[edge_desc];
            d2::SyncObject const& l1 = graph[source(edge_desc, graph)];
            d2::SyncObject const& l2 = graph[target(edge_desc, graph)];

            os_ << '\n';

            os_ << "Thread " << edge.t << " acquired lock " << l2 << " in\n";
            format_call_stack(edge.l2_info, "    ");

            os_ << "while holding lock " << l1 << " taken in\n";
            format_call_stack(edge.l1_info, "    ");
        }

        os_ << "----------------------------------------------------\n\n";
    }
};

template <typename Ostream>
CyclePrinter<Ostream> print_cycle(Ostream& os) {
    return CyclePrinter<Ostream>(os);
}

} // end anonymous namespace

int main(int argc, char const* argv[]) {
    // Parse command line options.
    po::options_description global("Global options");
    global.add_options()
    (
        "help,h", "produce help message and exit"
    )(
        "version,v", "print version and exit"
    )(
        "output-file,o", po::value<std::string>(), "file to write the output to"
    )(
        "analyze", "perform the analysis for deadlocks"
    )(
        "dot", "produce a dot representation of the lock graph used during the analysis"
    )(
        "stats", "produce statistics about the usage of locks and threads"
    )
    ;

    po::options_description hidden;
    hidden.add_options()
        ("repo-path", po::value<std::string>(), "path of the repository to examine")
    ;
    po::positional_options_description positionals;
    positionals.add("repo-path", 1);

    po::options_description analysis("Analysis options");

    po::options_description dot("Dot rendering options");

    po::options_description statistics("Statistics options");

    po::options_description allowed;
    allowed.add(global).add(analysis).add(dot).add(statistics);

    po::options_description all;
    all.add(allowed).add(hidden);

    po::variables_map args;
    po::command_line_parser parser(argc, argv);
    try {
        po::store(parser.options(all).positional(positionals).run(), args);
        po::notify(args);
    } catch(po::error const& e) {
        std::cerr << e.what() << std::endl
                  << allowed << std::endl;
        return EXIT_FAILURE;
    }

    // Some options make us do something and exit right away. These cases
    // are handled here.
    {
        typedef boost::function<void(po::variable_value)> DieAction;
        std::map<std::string, DieAction> die_actions =
        boost::assign::map_list_of<std::string, DieAction>
            ("help", phx::ref(std::cout) << allowed << '\n')
            ("version", phx::ref(std::cout) << VERSION << '\n')
        ;
        typedef std::pair<std::string, DieAction> DieActionPair;
        BOOST_FOREACH(DieActionPair const& action, die_actions) {
            if (args.count(action.first)) {
                action.second(args[action.first]);
                return EXIT_FAILURE;
            }
        }
    }

    // Open the repository on which we must operate.
    if (!args.count("repo-path")) {
        std::cerr << "missing the path of a repository on which to operate "
                     "from the command line" << std::endl
                  << allowed << std::endl;
        return EXIT_FAILURE;
    }
    d2::EventRepository<> repository(args["repo-path"].as<std::string>());

    // Open the output stream to whatever passed on the command line or to
    // stdout if unspecified.
    std::ofstream output_ofs;
    if (args.count("output-file")) {
        std::string output_file = args["output-file"].as<std::string>();
        output_ofs.open(output_file.c_str());
        if (!output_ofs) {
            std::cerr << "Unable to open output file \"" << output_file <<'"';
            return EXIT_FAILURE;
        }
    }
    std::ostream& output = args.count("output-file") ? output_ofs : std::cout;

    // Build the segmentation and the lock graph. They are required no matter
    // the options we received on the command line.
    d2::SegmentationGraph sg;
    d2::LockGraph lg;
    try {
        d2::build_graphs(repository, lg, sg);
    } catch (d2::EventTypeException const& e) {
        using boost::get_error_info;
        char const* const* actual_type = get_error_info<d2::ActualType>(e);
        char const* const* expected_type = get_error_info<d2::ExpectedType>(e);

        char const* unavailable = "\"unavailable\"";
        if (!actual_type) actual_type = &unavailable;
        if (!expected_type) expected_type = &unavailable;

        std::cerr << "Error while building the graphs:\n"
                     "    encountered an event of type " << *actual_type
                  << " while expecting an event of type " << *expected_type
                  << "." << std::endl;

        return EXIT_FAILURE;
    }

    // Main switch dispatching to the right action to perform.
    if (args.count("analyze") || (!args.count("dot") && !args.count("stats"))) {
        d2::analyze(lg, sg, print_cycle(std::cout));
    }
    else if (args.count("dot")) {
        boost::write_graphviz(output, lg, render_dot(lg), render_dot(lg));
    }
    else if (args.count("stats")) {
        Statistics<d2::LockGraph, d2::SegmentationGraph> stats(lg, sg);
        d2::analyze(lg, sg, gather_stats(stats));
        output << stats << std::endl;
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * project.cpp
 *
 *  Created on: 17/08/2011
 *      Author: bsr
 *
 *  Class to handle prjoect contents and settings
 */

#include "project.h"
#include "dskbuild.h"

project_file::project_file() :
	m_filename(""),
	m_load_address(0x8000),
	m_exec_address(0x8000)
{
}

project_file::project_file(QString filename) :
	m_filename(filename),
	m_load_address(0x8000),
	m_exec_address(0x8000)
{
	// base class
}

project_file::project_file(QString filename, int filetype, unsigned int load, unsigned int exec) :
	m_filename(filename),
	m_filetype(filetype),
	m_load_address(load),
	m_exec_address(exec)
{
}

project_file::~project_file()
{

}

void project_file::set_filename(QString filename)
{
	QStringList ext = filename.split(".");
	if(ext.last() == "asm")
		m_filetype = PROJECT_FILE_SOURCE_ASM;
	else
		m_filetype = PROJECT_FILE_BINARY;
	m_filename = filename;
}

project::project(QString name, QString filename) :
	m_filename(filename),
	m_name(name),
	m_outfilename(m_name+".dsk"),
	m_built(false)
{
}

project::~project()
{
	// remove and free all the project_file objects in this project
	QList<project_file*>::iterator it;

	// find file to remove
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		m_filelist.erase(it);
		//delete(*it);  // TODO: test this
	}
}

bool project::add_file(QString filename)
{
	project_file* pfile = new project_file(filename);
	m_filelist.append(pfile);
	return true;
}

bool project::add_file(project_file* file)
{
	m_filelist.append(file);
	return true;
}

bool project::add_gfx_file(QString filename, int width, int height)
{
	project_file* pfile = new project_file(filename);
	pfile->set_filetype(PROJECT_FILE_GRAPHICS);
	pfile->set_size(width,height);
	m_filelist.append(pfile);
	return true;
}

bool project::remove_file(QString filename)
{
	QList<project_file*>::iterator it;

	// find file to remove
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if((*it)->get_filename() == filename)
		{
			m_filelist.erase(it);
			return true;
		}
	}
	return false;
}

bool project::check_for_file(QString filename)
{
	QList<project_file*>::iterator it;

	// find file
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if((*it)->get_filename() == filename)
		{
			return true;
		}
	}
	return false;
}

void project::xml_filelist(QXmlStreamWriter* stream)
{
	QList<project_file*>::iterator it;

	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		stream->writeStartElement("file");
		stream->writeAttribute("name",(*it)->get_filename());
		if((*it)->get_filetype() == PROJECT_FILE_SOURCE_ASM)
		{
			stream->writeAttribute("type","asm");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
		}
		if((*it)->get_filetype() == PROJECT_FILE_BINARY)
		{
			stream->writeAttribute("type","binary");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
		}
		if((*it)->get_filetype() == PROJECT_FILE_GRAPHICS)
		{
			stream->writeAttribute("type","gfx");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
			stream->writeAttribute("width",QString::number((*it)->get_width(),10));
			stream->writeAttribute("height",QString::number((*it)->get_height(),10));
		}
		if((*it)->get_filetype() == PROJECT_FILE_ASCII)
		{
			stream->writeAttribute("type","ascii");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
		}
		stream->writeEndElement();
	}
}

int project::build(QPlainTextEdit* output)
{
	// TODO: Win32 path separator handling
	bool ret;
	QProcess* pasmo = new QProcess();
	QString pasmo_program = "pasmo";
	QStringList arg;
	// TODO add Z80 C cross-compilers (SDCC, Z88DK)?

	QList<project_file*>::iterator it;
	int exitcode;
	dsk_builder dsk(m_outfilename);

	if(output != 0)
		output->clear();

	// set up working directory
	QDir dir(QDir::temp());
	dir.mkdir("cpc");
	dir.cd("cpc");

	// go through each file in the project, and if it's a source file, compile it
	// or if it's data, then copy it to destination, if necessary
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if(output != 0)
			output->appendPlainText(">>> File: "+(*it)->get_filename()+"\n");
		if((*it)->get_filetype() == PROJECT_FILE_SOURCE_ASM)
		{
			QStringList split_path = (*it)->get_filename().split(QDir::separator());
			QString basefilename = split_path.last();
			QStringList split_base = basefilename.split(".");
			QString basename = split_base.first();

			arg.clear();
			arg += "-v";  // verbose
			arg += (*it)->get_filename();
			arg += (dir.absolutePath()+QDir::separator()+basename+".bin");

			pasmo->setProcessChannelMode(QProcess::MergedChannels);
			pasmo->setReadChannel(QProcess::StandardOutput);
			pasmo->start(pasmo_program,arg);
			if(!pasmo->waitForStarted())
			{
				QMessageBox msg(QMessageBox::Warning,"Build Error","Unable to run Pasmo.  Is it installed and available in your path?",QMessageBox::Ok);
				msg.exec();
				return -1;
			}
			if(output != 0)
			{
				while(pasmo->state() != QProcess::NotRunning)
				{
					char buffer[512];
					qint64 count;
					pasmo->waitForReadyRead();
					while(pasmo->canReadLine())
					{
						count = pasmo->readLine(buffer,512);
						if(count > 0)
							output->insertPlainText(buffer);
					}
				}
			}
			pasmo->waitForFinished();
			exitcode = pasmo->exitCode();
			if(exitcode != 0)
			{
				if(output != 0)
					output->appendPlainText(QString(">>> Pasmo returned an error (%1). Build not successful.\n").arg(exitcode));
				m_built = false;
				return -1;
			}
			// add file to disk image
			dsk.add_file(dir.absolutePath()+QDir::separator()+basename+".bin",
					(*it)->get_load_address(),(*it)->get_exec_address());
			if(output != 0)
			{
				QString l = QString::number((*it)->get_load_address(),16);
				QString e = QString::number((*it)->get_exec_address(),16);
				output->appendPlainText(QString(">>> Adding %1 to virtual disk, Load: 0x%2, Exec: 0x%3\n").arg(dir.absolutePath()+QDir::separator()+basename+".bin").arg(l).arg(e));
			}
		}
		if((*it)->get_filetype() == PROJECT_FILE_BINARY || (*it)->get_filetype() == PROJECT_FILE_GRAPHICS)
		{
			// add file to disk image
			dsk.add_file((*it)->get_filename(), (*it)->get_load_address(),(*it)->get_exec_address());
			if(output != 0)
			{
				QString l = QString::number((*it)->get_load_address(),16);
				QString e = QString::number((*it)->get_exec_address(),16);
				output->appendPlainText(QString(">>> Adding %1 to virtual disk, Load: 0x%2, Exec: 0x%3\n").arg((*it)->get_filename()).arg(l).arg(e));
			}
		}
		if((*it)->get_filetype() == PROJECT_FILE_ASCII)
		{
			// add file to disk image
			dsk.add_ascii_file((*it)->get_filename());
			if(output != 0)
			{
				output->appendPlainText(QString(">>> Adding ASCII file %1 to virtual disk\n").arg((*it)->get_filename()));
			}
		}
	}
	m_built = true;

	if(output != 0)
		output->appendPlainText(QString(">>> Generating DSK image '%1'...").arg(m_outfilename));

	ret = dsk.generate_dsk();

	if(ret == true)
		output->appendPlainText("OK\n");
	else
		output->appendPlainText("Failed\n");

	if(output != 0)
		output->appendPlainText(">>> Finished.\n");
	return 0;
}

project_file* project::find_file(QString file)
{
	QList<project_file*>::iterator it;

	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if((*it)->get_filename() == file)
			return *it;
	}
	return NULL;
}

unsigned int project::get_load_address(QString file)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->get_load_address();
	else
		return 0;
}

unsigned int project::get_exec_address(QString file)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->get_exec_address();
	else
		return 0;
}

int project::get_filetype(QString file)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->get_filetype();
	else
		return 0;
}

void project::set_load_address(QString file, unsigned int addr)
{
	project_file* f = find_file(file);
	if(f != NULL)
		f->set_load_address(addr);
}

void project::set_exec_address(QString file, unsigned int addr)
{
	project_file* f = find_file(file);
	if(f != NULL)
		f->set_exec_address(addr);
}

void project::set_filetype(QString file, int type)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->set_filetype(type);
}
<commit_msg>fix saving of project file when using non-ASM files.<commit_after>/*
 * project.cpp
 *
 *  Created on: 17/08/2011
 *      Author: bsr
 *
 *  Class to handle prjoect contents and settings
 */

#include "project.h"
#include "dskbuild.h"

project_file::project_file() :
	m_filename(""),
	m_load_address(0x8000),
	m_exec_address(0x8000)
{
}

project_file::project_file(QString filename) :
	m_filename(filename),
	m_load_address(0x8000),
	m_exec_address(0x8000)
{
	// base class
}

project_file::project_file(QString filename, int filetype, unsigned int load, unsigned int exec) :
	m_filename(filename),
	m_filetype(filetype),
	m_load_address(load),
	m_exec_address(exec)
{
}

project_file::~project_file()
{

}

void project_file::set_filename(QString filename)
{
	m_filename = filename;
}

project::project(QString name, QString filename) :
	m_filename(filename),
	m_name(name),
	m_outfilename(m_name+".dsk"),
	m_built(false)
{
}

project::~project()
{
	// remove and free all the project_file objects in this project
	QList<project_file*>::iterator it;

	// find file to remove
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		m_filelist.erase(it);
		//delete(*it);  // TODO: test this
	}
}

bool project::add_file(QString filename)
{
	project_file* pfile = new project_file(filename);
	m_filelist.append(pfile);
	return true;
}

bool project::add_file(project_file* file)
{
	m_filelist.append(file);
	return true;
}

bool project::add_gfx_file(QString filename, int width, int height)
{
	project_file* pfile = new project_file(filename);
	pfile->set_filetype(PROJECT_FILE_GRAPHICS);
	pfile->set_size(width,height);
	m_filelist.append(pfile);
	return true;
}

bool project::remove_file(QString filename)
{
	QList<project_file*>::iterator it;

	// find file to remove
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if((*it)->get_filename() == filename)
		{
			m_filelist.erase(it);
			return true;
		}
	}
	return false;
}

bool project::check_for_file(QString filename)
{
	QList<project_file*>::iterator it;

	// find file
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if((*it)->get_filename() == filename)
		{
			return true;
		}
	}
	return false;
}

void project::xml_filelist(QXmlStreamWriter* stream)
{
	QList<project_file*>::iterator it;

	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		stream->writeStartElement("file");
		stream->writeAttribute("name",(*it)->get_filename());
		if((*it)->get_filetype() == PROJECT_FILE_SOURCE_ASM)
		{
			stream->writeAttribute("type","asm");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
		}
		if((*it)->get_filetype() == PROJECT_FILE_BINARY)
		{
			stream->writeAttribute("type","binary");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
		}
		if((*it)->get_filetype() == PROJECT_FILE_GRAPHICS)
		{
			stream->writeAttribute("type","gfx");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
			stream->writeAttribute("width",QString::number((*it)->get_width(),10));
			stream->writeAttribute("height",QString::number((*it)->get_height(),10));
		}
		if((*it)->get_filetype() == PROJECT_FILE_ASCII)
		{
			stream->writeAttribute("type","ascii");
			stream->writeAttribute("load",QString::number((*it)->get_load_address(),16));
			stream->writeAttribute("exec",QString::number((*it)->get_exec_address(),16));
		}
		stream->writeEndElement();
	}
}

int project::build(QPlainTextEdit* output)
{
	// TODO: Win32 path separator handling
	bool ret;
	QProcess* pasmo = new QProcess();
	QString pasmo_program = "pasmo";
	QStringList arg;
	// TODO add Z80 C cross-compilers (SDCC, Z88DK)?

	QList<project_file*>::iterator it;
	int exitcode;
	dsk_builder dsk(m_outfilename);

	if(output != 0)
		output->clear();

	// set up working directory
	QDir dir(QDir::temp());
	dir.mkdir("cpc");
	dir.cd("cpc");

	// go through each file in the project, and if it's a source file, compile it
	// or if it's data, then copy it to destination, if necessary
	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if(output != 0)
			output->appendPlainText(">>> File: "+(*it)->get_filename()+"\n");
		if((*it)->get_filetype() == PROJECT_FILE_SOURCE_ASM)
		{
			QStringList split_path = (*it)->get_filename().split(QDir::separator());
			QString basefilename = split_path.last();
			QStringList split_base = basefilename.split(".");
			QString basename = split_base.first();

			arg.clear();
			arg += "-v";  // verbose
			arg += (*it)->get_filename();
			arg += (dir.absolutePath()+QDir::separator()+basename+".bin");

			pasmo->setProcessChannelMode(QProcess::MergedChannels);
			pasmo->setReadChannel(QProcess::StandardOutput);
			pasmo->start(pasmo_program,arg);
			if(!pasmo->waitForStarted())
			{
				QMessageBox msg(QMessageBox::Warning,"Build Error","Unable to run Pasmo.  Is it installed and available in your path?",QMessageBox::Ok);
				msg.exec();
				return -1;
			}
			if(output != 0)
			{
				while(pasmo->state() != QProcess::NotRunning)
				{
					char buffer[512];
					qint64 count;
					pasmo->waitForReadyRead();
					while(pasmo->canReadLine())
					{
						count = pasmo->readLine(buffer,512);
						if(count > 0)
							output->insertPlainText(buffer);
					}
				}
			}
			pasmo->waitForFinished();
			exitcode = pasmo->exitCode();
			if(exitcode != 0)
			{
				if(output != 0)
					output->appendPlainText(QString(">>> Pasmo returned an error (%1). Build not successful.\n").arg(exitcode));
				m_built = false;
				return -1;
			}
			// add file to disk image
			dsk.add_file(dir.absolutePath()+QDir::separator()+basename+".bin",
					(*it)->get_load_address(),(*it)->get_exec_address());
			if(output != 0)
			{
				QString l = QString::number((*it)->get_load_address(),16);
				QString e = QString::number((*it)->get_exec_address(),16);
				output->appendPlainText(QString(">>> Adding %1 to virtual disk, Load: 0x%2, Exec: 0x%3\n").arg(dir.absolutePath()+QDir::separator()+basename+".bin").arg(l).arg(e));
			}
		}
		if((*it)->get_filetype() == PROJECT_FILE_BINARY || (*it)->get_filetype() == PROJECT_FILE_GRAPHICS)
		{
			// add file to disk image
			dsk.add_file((*it)->get_filename(), (*it)->get_load_address(),(*it)->get_exec_address());
			if(output != 0)
			{
				QString l = QString::number((*it)->get_load_address(),16);
				QString e = QString::number((*it)->get_exec_address(),16);
				output->appendPlainText(QString(">>> Adding %1 to virtual disk, Load: 0x%2, Exec: 0x%3\n").arg((*it)->get_filename()).arg(l).arg(e));
			}
		}
		if((*it)->get_filetype() == PROJECT_FILE_ASCII)
		{
			// add file to disk image
			dsk.add_ascii_file((*it)->get_filename());
			if(output != 0)
			{
				output->appendPlainText(QString(">>> Adding ASCII file %1 to virtual disk\n").arg((*it)->get_filename()));
			}
		}
	}
	m_built = true;

	if(output != 0)
		output->appendPlainText(QString(">>> Generating DSK image '%1'...").arg(m_outfilename));

	ret = dsk.generate_dsk();

	if(ret == true)
		output->appendPlainText("OK\n");
	else
		output->appendPlainText("Failed\n");

	if(output != 0)
		output->appendPlainText(">>> Finished.\n");
	return 0;
}

project_file* project::find_file(QString file)
{
	QList<project_file*>::iterator it;

	for(it=m_filelist.begin();it!=m_filelist.end();it++)
	{
		if((*it)->get_filename() == file)
			return *it;
	}
	return NULL;
}

unsigned int project::get_load_address(QString file)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->get_load_address();
	else
		return 0;
}

unsigned int project::get_exec_address(QString file)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->get_exec_address();
	else
		return 0;
}

int project::get_filetype(QString file)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->get_filetype();
	else
		return 0;
}

void project::set_load_address(QString file, unsigned int addr)
{
	project_file* f = find_file(file);
	if(f != NULL)
		f->set_load_address(addr);
}

void project::set_exec_address(QString file, unsigned int addr)
{
	project_file* f = find_file(file);
	if(f != NULL)
		f->set_exec_address(addr);
}

void project::set_filetype(QString file, int type)
{
	project_file* f = find_file(file);
	if(f != NULL)
		return f->set_filetype(type);
}
<|endoftext|>


<commit_before>//MIT License
//Copyright 2017 Patrick Laughrea
#include "base64.hpp"

#include <cassert>
#include <stdexcept>

#include "constants.hpp"
#include "various/stringBuilder.hpp"

using namespace std;
using namespace various;
using namespace webss;

static void readBytes(SmartIterator& it, char bytes[4]);
static void writeBytes(char bytes[4]);

static const char* ERROR_EXPECTED = "expected character";

#define DECODE_ALL_0 '+'
#define DECODE_ALL_1 '-'
#define DECODE_NUMBER '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
#define DECODE_UPPER 'Q': case 'W': case 'F': case 'R': case 'K': case 'Y': case 'J': case 'I': case 'O': case 'P': \
	case 'A': case 'S': case 'D': case 'T': case 'G': case 'H': case 'E': case 'U': case 'L': \
	case 'Z': case 'X': case 'C': case 'V': case 'B': case 'N': case 'M'
#define DECODE_LOWER 'q': case 'w': case 'f': case 'r': case 'k': case 'y': case 'j': case 'i': case 'o': case 'p': \
	case 'a': case 's': case 'd': case 't': case 'g': case 'h': case 'e': case 'u': case 'l': \
	case 'z': case 'x': case 'c': case 'v': case 'b': case 'n': case 'm'
#define DECODE_CHAR_1 '_'
#define DECODE_CHAR_2 '='
#define DECODE_IGNORED ' ': case '\x7f': \
	case '\x00': case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': case '\x06': case '\x07': case '\x08': case '\x09': case '\x0a': case '\x0b': case '\x0c': case '\x0d': case '\x0e': case '\x0f': \
	case '\x10': case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f'
#define PutThreeBytes(byte) { sb += byte; sb += byte; sb += byte; }

SmartIterator webss::decodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[4];
		int32_t bytesInt;
	};
decodeStart:
	if (!it)
		throw runtime_error(ERROR_EXPECTED);
	switch (*it)
	{
	case CHAR_END_TUPLE:
		return sb.str();
	case DECODE_ALL_0:
		PutThreeBytes('\0')
		goto decodeEnd;
	case DECODE_ALL_1:
		PutThreeBytes('\xff');
		goto decodeEnd;
	case DECODE_IGNORED:
		goto decodeEnd;
	default:
		break;
	}
	readBytes(it, bytes);
	//the 4 bytes: 00111111|00222222|00333333|00112233
	//will become: 11111111|22222222|33333333|00000000
	bytesInt |= (bytesInt & 0x30) << 26;
	bytesInt |= (bytesInt & 0x0c) << 20;
	bytesInt |= (bytesInt & 0x03) << 14;
	bytes[3] = 0;
	sb += bytes;
decodeEnd:
	++it;
	goto decodeStart;
}

static void readBytes(SmartIterator& it, char bytes[4])
{
	int i = 0;
startSwitch:
	switch (*it)
	{
	case DECODE_IGNORED:
		goto restart;
	case DECODE_NUMBER:
		bytes[i] = *it - '0';
		break;
	case DECODE_UPPER:
		bytes[i] = *it - 'A' + 10;
		break;
	case DECODE_LOWER:
		bytes[i] = *it - 'a' + 36;
		break;
	case DECODE_CHAR_1:
		bytes[i] = 62;
		break;
	case DECODE_CHAR_2:
		bytes[i] = 63;
		break;
	default:
		throw runtime_error("forbidden character in encoded binary");
	}
	if (++i == 4)
		return;
restart:
	if (!++it)
		throw runtime_error(ERROR_EXPECTED);
	goto startSwitch;
}

#define ENCODE_NUMBER 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9
#define ENCODE_UPPER 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: \
	case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: \
	case 30: case 31: case 32: case 33: case 34: case 35
#define ENCODE_LOWER 36: case 37: case 38: case 39: \
	case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: \
	case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: \
	case 60: case 61
#define ENCODE_CHAR_1 62
#define ENCODE_CHAR_2 63

#ifdef BASE64_ENCODE_ALL_ZEROS
#ifdef BASE64_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } }
#endif
#else //BASE64_ENCODE_ALL_ZEROS
#ifdef BASE64_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) ;
#endif
#endif //BASE64_ENCODE_ALL_ZEROS

string webss::encodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[5];
		int32_t bytesInt;
	};
	bytes[4] = 0;
encodeStart:
	if (!it)
		return sb;
	bytesInt = 0;
	bytes[0] = *it;
	if (!++it)
	{
		SpecialCheck(0xff000000, return sb)
		goto encodeBytes;
	}
	bytes[1] = *it;
	if (!++it)
	{
		SpecialCheck(0xffff0000, return sb)
		goto encodeBytes;
	}
	bytes[2] = *it;
	SpecialCheck(0xffffff00, ++it; goto encodeStart)
encodeBytes:
	//the 4 bytes: 11111111|22222222|33333333|00000000
	//will become: 00111111|00222222|00333333|00112233
	bytesInt |= (bytesInt & (0xc0 << 24)) >> 26;
	bytesInt |= (bytesInt & (0xc0 << 16)) >> 20;
	bytesInt |= (bytesInt & (0xc0 << 8)) >> 14;
	writeBytes(bytes);
	sb += bytes;
	++it;
	goto encodeStart;
}

static void writeBytes(char bytes[4])
{
	for (int i = 0; i < 4; ++i)
		switch (bytes[i])
		{
		case ENCODE_NUMBER:
			bytes[i] += '0';
			break;
		case ENCODE_UPPER:
			bytes[i] += 'A' - 10;
			break;
		case ENCODE_LOWER:
			bytes[i] += 'a' - 36;
			break;
		case ENCODE_CHAR_1:
			bytes[i] = DECODE_CHAR_1;
			break;
		case ENCODE_CHAR_2:
			bytes[i] = DECODE_CHAR_2;
			break;
		default:
			assert(false); throw domain_error("");
		}
}<commit_msg>Make Base64 encode all 0 and -1 by default<commit_after>//MIT License
//Copyright 2017 Patrick Laughrea
#include "base64.hpp"

#include <cassert>
#include <stdexcept>

#include "constants.hpp"
#include "various/stringBuilder.hpp"

using namespace std;
using namespace various;
using namespace webss;

static void readBytes(SmartIterator& it, char bytes[4]);
static void writeBytes(char bytes[4]);

static const char* ERROR_EXPECTED = "expected character";

#define DECODE_ALL_0 '+'
#define DECODE_ALL_1 '-'
#define DECODE_NUMBER '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
#define DECODE_UPPER 'Q': case 'W': case 'F': case 'R': case 'K': case 'Y': case 'J': case 'I': case 'O': case 'P': \
	case 'A': case 'S': case 'D': case 'T': case 'G': case 'H': case 'E': case 'U': case 'L': \
	case 'Z': case 'X': case 'C': case 'V': case 'B': case 'N': case 'M'
#define DECODE_LOWER 'q': case 'w': case 'f': case 'r': case 'k': case 'y': case 'j': case 'i': case 'o': case 'p': \
	case 'a': case 's': case 'd': case 't': case 'g': case 'h': case 'e': case 'u': case 'l': \
	case 'z': case 'x': case 'c': case 'v': case 'b': case 'n': case 'm'
#define DECODE_CHAR_1 '_'
#define DECODE_CHAR_2 '='
#define DECODE_IGNORED ' ': case '\x7f': \
	case '\x00': case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': case '\x06': case '\x07': case '\x08': case '\x09': case '\x0a': case '\x0b': case '\x0c': case '\x0d': case '\x0e': case '\x0f': \
	case '\x10': case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f'
#define PutThreeBytes(byte) { sb += byte; sb += byte; sb += byte; }

SmartIterator webss::decodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[4];
		int32_t bytesInt;
	};
decodeStart:
	if (!it)
		throw runtime_error(ERROR_EXPECTED);
	switch (*it)
	{
	case CHAR_END_TUPLE:
		return sb.str();
	case DECODE_ALL_0:
		PutThreeBytes('\0')
		goto decodeEnd;
	case DECODE_ALL_1:
		PutThreeBytes('\xff');
		goto decodeEnd;
	case DECODE_IGNORED:
		goto decodeEnd;
	default:
		break;
	}
	readBytes(it, bytes);
	//the 4 bytes: 00111111|00222222|00333333|00112233
	//will become: 11111111|22222222|33333333|00000000
	bytesInt |= (bytesInt & 0x30) << 26;
	bytesInt |= (bytesInt & 0x0c) << 20;
	bytesInt |= (bytesInt & 0x03) << 14;
	bytes[3] = 0;
	sb += bytes;
decodeEnd:
	++it;
	goto decodeStart;
}

static void readBytes(SmartIterator& it, char bytes[4])
{
	int i = 0;
startSwitch:
	switch (*it)
	{
	case DECODE_IGNORED:
		goto restart;
	case DECODE_NUMBER:
		bytes[i] = *it - '0';
		break;
	case DECODE_UPPER:
		bytes[i] = *it - 'A' + 10;
		break;
	case DECODE_LOWER:
		bytes[i] = *it - 'a' + 36;
		break;
	case DECODE_CHAR_1:
		bytes[i] = 62;
		break;
	case DECODE_CHAR_2:
		bytes[i] = 63;
		break;
	default:
		throw runtime_error("forbidden character in encoded binary");
	}
	if (++i == 4)
		return;
restart:
	if (!++it)
		throw runtime_error(ERROR_EXPECTED);
	goto startSwitch;
}

#define ENCODE_NUMBER 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9
#define ENCODE_UPPER 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: \
	case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: \
	case 30: case 31: case 32: case 33: case 34: case 35
#define ENCODE_LOWER 36: case 37: case 38: case 39: \
	case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: \
	case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: \
	case 60: case 61
#define ENCODE_CHAR_1 62
#define ENCODE_CHAR_2 63

#ifndef BASE64_DISABLE_ENCODE_ALL_ZEROS
#ifndef BASE64_DISABLE_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == 0) { sb += DECODE_ALL_0; Cmd; } }
#endif
#else //BASE64_DISABLE_ENCODE_ALL_ZEROS
#ifdef BASE64_DISABLE_ENCODE_ALL_ONES
#define SpecialCheck(Ones, Cmd) { \
	if (bytesInt == Ones) { sb += DECODE_ALL_1; Cmd; } }
#else
#define SpecialCheck(Ones, Cmd) ;
#endif
#endif //BASE64_DISABLE_ENCODE_ALL_ZEROS

string webss::encodeBase64(SmartIterator& it)
{
	StringBuilder sb;
	union
	{
		char bytes[5];
		int32_t bytesInt;
	};
	bytes[4] = 0;
encodeStart:
	if (!it)
		return sb;
	bytesInt = 0;
	bytes[0] = *it;
	if (!++it)
	{
		SpecialCheck(0xff000000, return sb)
		goto encodeBytes;
	}
	bytes[1] = *it;
	if (!++it)
	{
		SpecialCheck(0xffff0000, return sb)
		goto encodeBytes;
	}
	bytes[2] = *it;
	SpecialCheck(0xffffff00, ++it; goto encodeStart)
encodeBytes:
	//the 4 bytes: 11111111|22222222|33333333|00000000
	//will become: 00111111|00222222|00333333|00112233
	bytesInt |= (bytesInt & (0xc0 << 24)) >> 26;
	bytesInt |= (bytesInt & (0xc0 << 16)) >> 20;
	bytesInt |= (bytesInt & (0xc0 << 8)) >> 14;
	writeBytes(bytes);
	sb += bytes;
	++it;
	goto encodeStart;
}

static void writeBytes(char bytes[4])
{
	for (int i = 0; i < 4; ++i)
		switch (bytes[i])
		{
		case ENCODE_NUMBER:
			bytes[i] += '0';
			break;
		case ENCODE_UPPER:
			bytes[i] += 'A' - 10;
			break;
		case ENCODE_LOWER:
			bytes[i] += 'a' - 36;
			break;
		case ENCODE_CHAR_1:
			bytes[i] = DECODE_CHAR_1;
			break;
		case ENCODE_CHAR_2:
			bytes[i] = DECODE_CHAR_2;
			break;
		default:
			assert(false); throw domain_error("");
		}
}<|endoftext|>


<commit_before>#include "weights.h"

#include <sstream>

#include "fdict.h"
#include "filelib.h"
#include "verbose.h"

using namespace std;

void Weights::InitFromFile(const string& filename,
                           vector<weight_t>* pweights,
                           vector<string>* feature_list) {
  vector<weight_t>& weights = *pweights;
  if (!SILENT) cerr << "Reading weights from " << filename << endl;
  ReadFile in_file(filename);
  istream& in = *in_file.stream();
  assert(in);

  bool read_text = true;
  if (1) {
    ReadFile hdrrf(filename);
    istream& hi = *hdrrf.stream();
    assert(hi);
    char buf[10];
    hi.get(buf, 6);
    assert(hi.good());
    if (strncmp(buf, "_PHWf", 5) == 0) {
      read_text = false;
    }
  }

  if (read_text) {
    int weight_count = 0;
    bool fl = false;
    string buf;
    weight_t val = 0;
    while (in) {
      getline(in, buf);
      if (buf.size() == 0) continue;
      if (buf[0] == '#') continue;
      if (buf[0] == ' ') {
        cerr << "Weights file lines may not start with whitespace.\n" << buf << endl;
        abort();
      }
      for (int i = buf.size() - 1; i > 0; --i)
        if (buf[i] == '=' || buf[i] == '\t') { buf[i] = ' '; break; }
      int start = 0;
      while(start < buf.size() && buf[start] == ' ') ++start;
      int end = 0;
      while(end < buf.size() && buf[end] != ' ') ++end;
      const int fid = FD::Convert(buf.substr(start, end - start));
      if (feature_list) { feature_list->push_back(buf.substr(start, end - start)); }
      while(end < buf.size() && buf[end] == ' ') ++end;
      val = strtod(&buf.c_str()[end], NULL);
      if (isnan(val)) {
        cerr << FD::Convert(fid) << " has weight NaN!\n";
        abort();
      }
      if (weights.size() <= fid)
        weights.resize(fid + 1);
      weights[fid] = val;
      ++weight_count;
      if (!SILENT) {
        if (weight_count %   50000 == 0) { cerr << '.' << flush; fl = true; }
        if (weight_count % 2000000 == 0) { cerr << " [" << weight_count << "]\n"; fl = false; }
      }
    }
    if (!SILENT) {
      if (fl) { cerr << endl; }
      cerr << "Loaded " << weight_count << " feature weights\n";
    }
  } else {   // !read_text
    char buf[6];
    in.get(buf, 6);
    size_t num_keys[2];
    in.get(reinterpret_cast<char*>(&num_keys[0]), sizeof(size_t) + 1);
    if (num_keys[0] != FD::NumFeats()) {
      cerr << "Hash function reports " << FD::NumFeats() << " keys but weights file contains " << num_keys[0] << endl;
      abort();
    }
    weights.resize(num_keys[0]);
    in.get(reinterpret_cast<char*>(&weights[0]), num_keys[0] * sizeof(weight_t));
    if (!in.good()) {
      cerr << "Error loading weights!\n";
      abort();
    }
  }
}

void Weights::WriteToFile(const string& fname,
                          const vector<weight_t>& weights,
                          bool hide_zero_value_features,
                          const string* extra) {
  WriteFile out(fname);
  ostream& o = *out.stream();
  assert(o);
  bool write_text = !FD::UsingPerfectHashFunction();

  if (write_text) {
    if (extra) { o << "# " << *extra << endl; }
    o.precision(17);
    const int num_feats = FD::NumFeats();
    for (int i = 1; i < num_feats; ++i) {
      const weight_t val = (i < weights.size() ? weights[i] : 0.0);
      if (hide_zero_value_features && val == 0.0) continue;
      o << FD::Convert(i) << ' ' << val << endl;
    }
  } else {
    o.write("_PHWf", 5);
    const size_t keys = FD::NumFeats();
    assert(keys <= weights.size());
    o.write(reinterpret_cast<const char*>(&keys), sizeof(keys));
    o.write(reinterpret_cast<const char*>(&weights[0]), keys * sizeof(weight_t));
  }
}

void Weights::InitSparseVector(const vector<weight_t>& dv,
                               SparseVector<weight_t>* sv) {
  sv->clear();
  for (unsigned i = 1; i < dv.size(); ++i) {
    if (dv[i]) sv->set_value(i, dv[i]);
  }
}

void Weights::SanityCheck(const vector<weight_t>& w) {
  for (int i = 0; i < w.size(); ++i) {
    assert(!isnan(w[i]));
    assert(!isinf(w[i]));
  }
}

struct FComp {
  const vector<weight_t>& w_;
  FComp(const vector<weight_t>& w) : w_(w) {}
  bool operator()(int a, int b) const {
    return fabs(w_[a]) > fabs(w_[b]);
  }
};

void Weights::ShowLargestFeatures(const vector<weight_t>& w) {
  vector<int> fnums(w.size());
  for (int i = 0; i < w.size(); ++i)
    fnums[i] = i;
  vector<int>::iterator mid = fnums.begin();
  mid += (w.size() > 10 ? 10 : w.size());
  partial_sort(fnums.begin(), mid, fnums.end(), FComp(w));
  cerr << "TOP FEATURES:";
  for (vector<int>::iterator i = fnums.begin(); i != mid; ++i) {
    cerr << ' ' << FD::Convert(*i) << '=' << w[*i];
  }
  cerr << endl;
}

<commit_msg>fix weight serialization bug<commit_after>#include "weights.h"

#include <sstream>

#include "fdict.h"
#include "filelib.h"
#include "verbose.h"

using namespace std;

void Weights::InitFromFile(const string& filename,
                           vector<weight_t>* pweights,
                           vector<string>* feature_list) {
  vector<weight_t>& weights = *pweights;
  if (!SILENT) cerr << "Reading weights from " << filename << endl;
  ReadFile in_file(filename);
  istream& in = *in_file.stream();
  assert(in);

  bool read_text = true;
  if (1) {
    ReadFile hdrrf(filename);
    istream& hi = *hdrrf.stream();
    assert(hi);
    char buf[10];
    hi.read(buf, 5);
    assert(hi.good());
    if (strncmp(buf, "_PHWf", 5) == 0) {
      read_text = false;
    }
  }

  if (read_text) {
    int weight_count = 0;
    bool fl = false;
    string buf;
    weight_t val = 0;
    while (in) {
      getline(in, buf);
      if (buf.size() == 0) continue;
      if (buf[0] == '#') continue;
      if (buf[0] == ' ') {
        cerr << "Weights file lines may not start with whitespace.\n" << buf << endl;
        abort();
      }
      for (int i = buf.size() - 1; i > 0; --i)
        if (buf[i] == '=' || buf[i] == '\t') { buf[i] = ' '; break; }
      int start = 0;
      while(start < buf.size() && buf[start] == ' ') ++start;
      int end = 0;
      while(end < buf.size() && buf[end] != ' ') ++end;
      const int fid = FD::Convert(buf.substr(start, end - start));
      if (feature_list) { feature_list->push_back(buf.substr(start, end - start)); }
      while(end < buf.size() && buf[end] == ' ') ++end;
      val = strtod(&buf.c_str()[end], NULL);
      if (isnan(val)) {
        cerr << FD::Convert(fid) << " has weight NaN!\n";
        abort();
      }
      if (weights.size() <= fid)
        weights.resize(fid + 1);
      weights[fid] = val;
      ++weight_count;
      if (!SILENT) {
        if (weight_count %   50000 == 0) { cerr << '.' << flush; fl = true; }
        if (weight_count % 2000000 == 0) { cerr << " [" << weight_count << "]\n"; fl = false; }
      }
    }
    if (!SILENT) {
      if (fl) { cerr << endl; }
      cerr << "Loaded " << weight_count << " feature weights\n";
    }
  } else {   // !read_text
    char buf[6];
    in.read(buf, 5);
    size_t num_keys;
    in.read(reinterpret_cast<char*>(&num_keys), sizeof(size_t));
    if (num_keys != FD::NumFeats()) {
      cerr << "Hash function reports " << FD::NumFeats() << " keys but weights file contains " << num_keys << endl;
      abort();
    }
    weights.resize(num_keys);
    in.read(reinterpret_cast<char*>(&weights.front()), num_keys * sizeof(weight_t));
    if (!in.good()) {
      cerr << "Error loading weights!\n";
      abort();
    } else {
      cerr << "  Successfully loaded " << (num_keys * sizeof(weight_t)) << " bytes\n";
    }
  }
}

void Weights::WriteToFile(const string& fname,
                          const vector<weight_t>& weights,
                          bool hide_zero_value_features,
                          const string* extra) {
  WriteFile out(fname);
  ostream& o = *out.stream();
  assert(o);
  bool write_text = !FD::UsingPerfectHashFunction();

  if (write_text) {
    if (extra) { o << "# " << *extra << endl; }
    o.precision(17);
    const int num_feats = FD::NumFeats();
    for (int i = 1; i < num_feats; ++i) {
      const weight_t val = (i < weights.size() ? weights[i] : 0.0);
      if (hide_zero_value_features && val == 0.0) continue;
      o << FD::Convert(i) << ' ' << val << endl;
    }
  } else {
    o.write("_PHWf", 5);
    const size_t keys = FD::NumFeats();
    assert(keys <= weights.size());
    o.write(reinterpret_cast<const char*>(&keys), sizeof(keys));
    o.write(reinterpret_cast<const char*>(&weights[0]), keys * sizeof(weight_t));
  }
}

void Weights::InitSparseVector(const vector<weight_t>& dv,
                               SparseVector<weight_t>* sv) {
  sv->clear();
  for (unsigned i = 1; i < dv.size(); ++i) {
    if (dv[i]) sv->set_value(i, dv[i]);
  }
}

void Weights::SanityCheck(const vector<weight_t>& w) {
  for (int i = 0; i < w.size(); ++i) {
    assert(!isnan(w[i]));
    assert(!isinf(w[i]));
  }
}

struct FComp {
  const vector<weight_t>& w_;
  FComp(const vector<weight_t>& w) : w_(w) {}
  bool operator()(int a, int b) const {
    return fabs(w_[a]) > fabs(w_[b]);
  }
};

void Weights::ShowLargestFeatures(const vector<weight_t>& w) {
  vector<int> fnums(w.size());
  for (int i = 0; i < w.size(); ++i)
    fnums[i] = i;
  vector<int>::iterator mid = fnums.begin();
  mid += (w.size() > 10 ? 10 : w.size());
  partial_sort(fnums.begin(), mid, fnums.end(), FComp(w));
  cerr << "TOP FEATURES:";
  for (vector<int>::iterator i = fnums.begin(); i != mid; ++i) {
    cerr << ' ' << FD::Convert(*i) << '=' << w[*i];
  }
  cerr << endl;
}

<|endoftext|>


<commit_before>#include "internal.hpp"

#include "macros.hpp"
#include "message.hpp"

namespace CaDiCaL {

bool Internal::restarting () {
  if (!opts.restart) return false;
  if (level < 2) return false;
  if (stats.conflicts <= lim.restart) return false;
  if (fast_glue_avg < 5) return true;
  double s = slow_glue_avg, f = fast_glue_avg, l = opts.restartmargin * s;
  LOG ("EMA learned glue slow %.2f fast %.2f limit %.2f", s, f, l);
  return l <= f;
}

int Internal::reuse_trail () {
  if (!opts.reusetrail) return 0;
  long limit = bumped (next_decision_variable ());
  int res = 0;
  while (res < level && bumped (control[res + 1].decision) > limit)
    res++;
  if (res) stats.reused++;
  return res;
}

void Internal::restart () {
  START (restart);
  stats.restarts++;
  LOG ("restart %ld", stats.restarts);
  lim.lastlevel = level;
  backtrack (reuse_trail ());
  int delta = opts.restartint * stable;
  if (delta < 1) delta = 1;
  if (delta > 200) delta = 200;
  lim.restart = stats.conflicts + delta;
  report ('r', 1);
  STOP (restart);
}

};

<commit_msg>fixed<commit_after>#include "internal.hpp"

#include "macros.hpp"
#include "message.hpp"

namespace CaDiCaL {

bool Internal::restarting () {
  if (!opts.restart) return false;
  if (level < 2) return false;
  if (stats.conflicts <= lim.restart) return false;
  double s = slow_glue_avg, f = fast_glue_avg, l = opts.restartmargin * s;
  LOG ("EMA learned glue slow %.2f fast %.2f limit %.2f", s, f, l);
  return l <= f;
}

int Internal::reuse_trail () {
  if (!opts.reusetrail) return 0;
  long limit = bumped (next_decision_variable ());
  int res = 0;
  while (res < level && bumped (control[res + 1].decision) > limit)
    res++;
  if (res) stats.reused++;
  return res;
}

void Internal::restart () {
  START (restart);
  stats.restarts++;
  LOG ("restart %ld", stats.restarts);
  lim.lastlevel = level;
  backtrack (reuse_trail ());
  int delta = opts.restartint * stable;
  if (delta < 1) delta = 1;
  if (delta > 200) delta = 200;
  lim.restart = stats.conflicts + delta;
  report ('r', 1);
  STOP (restart);
}

};

<|endoftext|>


<commit_before>#include <iostream>
#include "scenary.hpp"
#include "inputHandler.hpp"
#include "structs.hpp"

Scenary::Scenary( std::unique_ptr<ObjectData> objectData ) : Sprite( std::move( objectData ) ) {
  ignoreScale_    = true;
}

void Scenary::update( float dt, Uint32 msFrameDiff ) {
  Sprite::update( dt, msFrameDiff );

  //std::cout << "scenary zIndex is " << zIndex_ << std::endl;

}

void Scenary::render() {
  Sprite::render();
}

void Scenary::clean() {

}
<commit_msg>Adding damage stuff<commit_after>#include <iostream>
#include "scenary.hpp"
#include "inputHandler.hpp"
#include "structs.hpp"

Scenary::Scenary( std::unique_ptr<ObjectData> objectData ) : Sprite( std::move( objectData ) ) {
  ignoreScale_    = true;
}

void Scenary::update( float dt, Uint32 msFrameDiff ) {

  if( health_.getCurrentHp() < health_.getMaxHp() ) {
    if( health_.getCurrentHp() < 260 ) {
      spriteState_ = DAMAGED3;
    } else if( health_.getCurrentHp() < 510 ) {
      spriteState_ = DAMAGED2;
    } else if( m_health.getCurrentHp() < 760 ) {
      spriteState_ = DAMAGED1;
    }
  }

  Sprite::update( dt, msFrameDiff );

  //std::cout << "scenary zIndex is " << zIndex_ << std::endl;

}

void Scenary::render() {
  Sprite::render();
}

void Scenary::clean() {

}
<|endoftext|>