<commit_before>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "common.h"
#include "harness/mt19937.h"

#include <vector>
#include <atomic>

#if !defined(_WIN32)
#include <unistd.h>
#endif

typedef struct
{
  std::atomic<cl_uint> status;
  cl_uint num_svm_pointers;
  std::vector<void *> svm_pointers;
} CallbackData;

void generate_data(std::vector<cl_uchar> &data, size_t size, MTdata seed)
{
  cl_uint randomData = genrand_int32(seed);
  cl_uint bitsLeft = 32;

  for( size_t i = 0; i < size; i++ )
  {
    if( 0 == bitsLeft)
    {
      randomData = genrand_int32(seed);
      bitsLeft = 32;
    }
    data[i] = (cl_uchar)( randomData & 255 );
    randomData >>= 8; randomData -= 8;
  }
}

//callback which will be passed to clEnqueueSVMFree command
void CL_CALLBACK callback_svm_free(cl_command_queue queue, cl_uint num_svm_pointers, void * svm_pointers[], void * user_data)
{
  CallbackData *data = (CallbackData *)user_data;
  data->num_svm_pointers = num_svm_pointers;
  data->svm_pointers.resize(num_svm_pointers, 0);

  cl_context context;
  if(clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, 0) != CL_SUCCESS)
  {
    log_error("clGetCommandQueueInfo failed in the callback\n");
    return;
  }

  for (size_t i = 0; i < num_svm_pointers; ++i)
  {
    data->svm_pointers[i] = svm_pointers[i];
    clSVMFree(context, svm_pointers[i]);
  }

  data->status.store(1, std::memory_order_release);
}

int test_svm_enqueue_api(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
{
  clContextWrapper context = NULL;
  clCommandQueueWrapper queues[MAXQ];
  cl_uint num_devices = 0;
  const size_t elementNum = 1024;
  const size_t numSVMBuffers = 32;
  cl_int error = CL_SUCCESS;
  RandomSeed seed(0);

  error = create_cl_objects(deviceID, NULL, &context, NULL, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
  if(error) return TEST_FAIL;

  queue = queues[0];

  //all possible sizes of vectors and scalars
  size_t typeSizes[] = {
    sizeof(cl_uchar),
    sizeof(cl_uchar2),
    sizeof(cl_uchar3),
    sizeof(cl_uchar4),
    sizeof(cl_uchar8),
    sizeof(cl_uchar16),
    sizeof(cl_ushort),
    sizeof(cl_ushort2),
    sizeof(cl_ushort3),
    sizeof(cl_ushort4),
    sizeof(cl_ushort8),
    sizeof(cl_ushort16),
    sizeof(cl_uint),
    sizeof(cl_uint2),
    sizeof(cl_uint3),
    sizeof(cl_uint4),
    sizeof(cl_uint8),
    sizeof(cl_uint16),
    sizeof(cl_ulong),
    sizeof(cl_ulong2),
    sizeof(cl_ulong3),
    sizeof(cl_ulong4),
    sizeof(cl_ulong8),
    sizeof(cl_ulong16),
  };

  enum allocationTypes {
    host,
    svm
  };

  struct TestType {
    allocationTypes srcAlloc;
    allocationTypes dstAlloc;
    TestType(allocationTypes type1, allocationTypes type2): srcAlloc(type1), dstAlloc(type2){}
  };

 std::vector<TestType> testTypes;

 testTypes.push_back(TestType(host, host));
 testTypes.push_back(TestType(host, svm));
 testTypes.push_back(TestType(svm, host));
 testTypes.push_back(TestType(svm, svm));

  for (const auto test_case : testTypes)
  {
    log_info("clEnqueueSVMMemcpy case: src_alloc = %s, dst_alloc = %s\n", test_case.srcAlloc == svm ? "svm" : "host", test_case.dstAlloc == svm ? "svm" : "host");
    for (size_t i = 0; i < ARRAY_SIZE(typeSizes); ++i)
    {
      //generate initial data
      std::vector<cl_uchar> fillData0(typeSizes[i]), fillData1(typeSizes[i]);
      generate_data(fillData0, typeSizes[i], seed);
      generate_data(fillData1, typeSizes[i], seed);

      std::vector<cl_uchar> srcHostData(elementNum * typeSizes[i], 0);
      std::vector<cl_uchar> dstHostData(elementNum * typeSizes[i], 0);
      generate_data(srcHostData, srcHostData.size(), seed);
      generate_data(dstHostData, dstHostData.size(), seed);

      cl_uchar *srcBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum * typeSizes[i], 0);
      cl_uchar *dstBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum * typeSizes[i], 0);

      clEventWrapper userEvent = clCreateUserEvent(context, &error);
      test_error(error, "clCreateUserEvent failed");
      clEventWrapper eventMemFillList[2];

      error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData0[0], typeSizes[i], elementNum * typeSizes[i], 1, &userEvent, &eventMemFillList[0]);
      test_error(error, "clEnqueueSVMMemFill failed");
      error = clEnqueueSVMMemFill(queue, dstBuffer, &fillData1[0], typeSizes[i], elementNum * typeSizes[i], 1, &userEvent, &eventMemFillList[1]);
      test_error(error, "clEnqueueSVMMemFill failed");

      error = clSetUserEventStatus(userEvent, CL_COMPLETE);
      test_error(error, "clSetUserEventStatus failed");

      cl_uchar * src_ptr;
      cl_uchar * dst_ptr;
      if (test_case.srcAlloc == host) {
        src_ptr = srcHostData.data();
      } else if (test_case.srcAlloc == svm) {
        src_ptr = srcBuffer;
      }
      if (test_case.dstAlloc == host) {
        dst_ptr = dstHostData.data();
      } else if (test_case.dstAlloc == svm) {
        dst_ptr = dstBuffer;
      }
      clEventWrapper eventMemcpy;
      error = clEnqueueSVMMemcpy(queue, CL_FALSE, dst_ptr, src_ptr, elementNum * typeSizes[i], 2, &eventMemFillList[0], &eventMemcpy);
      test_error(error, "clEnqueueSVMMemcpy failed");

      clEventWrapper eventMap;
      error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ | CL_MAP_WRITE, dstBuffer, elementNum * typeSizes[i], 1, &eventMemcpy, &eventMap);
      test_error(error, "clEnqueueSVMMap failed");

      error = clWaitForEvents(1, &eventMap);
      test_error(error, "clWaitForEvents failed");

      //data verification
      for (size_t j = 0; j < elementNum * typeSizes[i]; ++j)
      {
        if (dst_ptr[j] != src_ptr[j]) {
            log_error("Invalid data at index %ld, dst_ptr %d, src_ptr %d\n", j, dst_ptr[j], src_ptr[j]);
            return TEST_FAIL;
        }
      }

      clEventWrapper eventUnmap;
      error = clEnqueueSVMUnmap(queue, dstBuffer, 0, 0, &eventUnmap);
      test_error(error, "clEnqueueSVMUnmap failed");

      error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData1[0], typeSizes[i], elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemFill failed");

      error = clEnqueueSVMMemFill(queue, dstBuffer + elementNum * typeSizes[i] / 2, &fillData1[0], typeSizes[i], elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemFill failed");

      error = clEnqueueSVMMemcpy(queue, CL_FALSE, dstBuffer, srcBuffer, elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemcpy failed");

      error = clEnqueueSVMMemcpy(queue, CL_TRUE, dstBuffer + elementNum * typeSizes[i] / 2, srcBuffer + elementNum * typeSizes[i] / 2, elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemcpy failed");

      void *ptrs[] = { (void *)srcBuffer, (void *)dstBuffer };

      clEventWrapper eventFree;
      error = clEnqueueSVMFree(queue, 2, ptrs, 0, 0, 0, 0, &eventFree);
      test_error(error, "clEnqueueSVMFree failed");

      error = clWaitForEvents(1, &eventFree);
      test_error(error, "clWaitForEvents failed");

      //event info verification for new SVM commands
      cl_command_type commandType;
      for (auto check_event : eventMemFillList) {
          error = clGetEventInfo(check_event, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
          test_error(error, "clGetEventInfo failed");
          if (commandType != CL_COMMAND_SVM_MEMFILL)
          {
              log_error("Invalid command type returned for clEnqueueSVMMemFill\n");
              return TEST_FAIL;
          }
      }

      error = clGetEventInfo(eventMemcpy, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_MEMCPY)
      {
        log_error("Invalid command type returned for clEnqueueSVMMemcpy\n");
        return TEST_FAIL;
      }

      error = clGetEventInfo(eventMap, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_MAP)
      {
        log_error("Invalid command type returned for clEnqueueSVMMap\n");
        return TEST_FAIL;
      }

      error = clGetEventInfo(eventUnmap, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_UNMAP)
      {
        log_error("Invalid command type returned for clEnqueueSVMUnmap\n");
        return TEST_FAIL;
      }

      error = clGetEventInfo(eventFree, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_FREE)
      {
        log_error("Invalid command type returned for clEnqueueSVMFree\n");
        return TEST_FAIL;
      }
    }
  }
  std::vector<void *> buffers(numSVMBuffers, 0);
  for(size_t i = 0; i < numSVMBuffers; ++i) buffers[i] = clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum, 0);

  //verify if callback is triggered correctly
  CallbackData data;
  data.status = 0;

  error = clEnqueueSVMFree(queue, buffers.size(), &buffers[0], callback_svm_free, &data, 0, 0, 0);
  test_error(error, "clEnqueueSVMFree failed");

  error = clFinish(queue);
  test_error(error, "clFinish failed");

  //wait for the callback
  while(data.status.load(std::memory_order_acquire) == 0) {
    usleep(1);
  }

  //check if number of SVM pointers returned in the callback matches with expected
  if (data.num_svm_pointers != buffers.size())
  {
    log_error("Invalid number of SVM pointers returned in the callback, expected: %ld, got: %d\n", buffers.size(), data.num_svm_pointers);
    return TEST_FAIL;
  }

  //check if pointers returned in callback are correct
  for (size_t i = 0; i < buffers.size(); ++i)
  {
    if (data.svm_pointers[i] != buffers[i])
    {
      log_error("Invalid SVM pointer returned in the callback, idx: %ld\n", i);
      return TEST_FAIL;
    }
  }

  return 0;
}
<commit_msg>Fix Issue 462 - test_svm crash (#463)<commit_after>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "common.h"
#include "harness/mt19937.h"

#include <vector>
#include <atomic>

#if !defined(_WIN32)
#include <unistd.h>
#endif

typedef struct
{
  std::atomic<cl_uint> status;
  cl_uint num_svm_pointers;
  std::vector<void *> svm_pointers;
} CallbackData;

void generate_data(std::vector<cl_uchar> &data, size_t size, MTdata seed)
{
  cl_uint randomData = genrand_int32(seed);
  cl_uint bitsLeft = 32;

  for( size_t i = 0; i < size; i++ )
  {
    if( 0 == bitsLeft)
    {
      randomData = genrand_int32(seed);
      bitsLeft = 32;
    }
    data[i] = (cl_uchar)( randomData & 255 );
    randomData >>= 8; randomData -= 8;
  }
}

//callback which will be passed to clEnqueueSVMFree command
void CL_CALLBACK callback_svm_free(cl_command_queue queue, cl_uint num_svm_pointers, void * svm_pointers[], void * user_data)
{
  CallbackData *data = (CallbackData *)user_data;
  data->num_svm_pointers = num_svm_pointers;
  data->svm_pointers.resize(num_svm_pointers, 0);

  cl_context context;
  if(clGetCommandQueueInfo(queue, CL_QUEUE_CONTEXT, sizeof(cl_context), &context, 0) != CL_SUCCESS)
  {
    log_error("clGetCommandQueueInfo failed in the callback\n");
    return;
  }

  for (size_t i = 0; i < num_svm_pointers; ++i)
  {
    data->svm_pointers[i] = svm_pointers[i];
    clSVMFree(context, svm_pointers[i]);
  }

  data->status.store(1, std::memory_order_release);
}

int test_svm_enqueue_api(cl_device_id deviceID, cl_context c, cl_command_queue queue, int num_elements)
{
  clContextWrapper context = NULL;
  clCommandQueueWrapper queues[MAXQ];
  cl_uint num_devices = 0;
  const size_t elementNum = 1024;
  const size_t numSVMBuffers = 32;
  cl_int error = CL_SUCCESS;
  RandomSeed seed(0);

  error = create_cl_objects(deviceID, NULL, &context, NULL, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
  if(error) return TEST_FAIL;

  queue = queues[0];

  //all possible sizes of vectors and scalars
  size_t typeSizes[] = {
    sizeof(cl_uchar),
    sizeof(cl_uchar2),
    sizeof(cl_uchar3),
    sizeof(cl_uchar4),
    sizeof(cl_uchar8),
    sizeof(cl_uchar16),
    sizeof(cl_ushort),
    sizeof(cl_ushort2),
    sizeof(cl_ushort3),
    sizeof(cl_ushort4),
    sizeof(cl_ushort8),
    sizeof(cl_ushort16),
    sizeof(cl_uint),
    sizeof(cl_uint2),
    sizeof(cl_uint3),
    sizeof(cl_uint4),
    sizeof(cl_uint8),
    sizeof(cl_uint16),
    sizeof(cl_ulong),
    sizeof(cl_ulong2),
    sizeof(cl_ulong3),
    sizeof(cl_ulong4),
    sizeof(cl_ulong8),
    sizeof(cl_ulong16),
  };

  enum allocationTypes {
    host,
    svm
  };

  struct TestType {
    allocationTypes srcAlloc;
    allocationTypes dstAlloc;
    TestType(allocationTypes type1, allocationTypes type2): srcAlloc(type1), dstAlloc(type2){}
  };

 std::vector<TestType> testTypes;

 testTypes.push_back(TestType(host, host));
 testTypes.push_back(TestType(host, svm));
 testTypes.push_back(TestType(svm, host));
 testTypes.push_back(TestType(svm, svm));

  for (const auto test_case : testTypes)
  {
    log_info("clEnqueueSVMMemcpy case: src_alloc = %s, dst_alloc = %s\n", test_case.srcAlloc == svm ? "svm" : "host", test_case.dstAlloc == svm ? "svm" : "host");
    for (size_t i = 0; i < ARRAY_SIZE(typeSizes); ++i)
    {
      //generate initial data
      std::vector<cl_uchar> fillData0(typeSizes[i]), fillData1(typeSizes[i]);
      generate_data(fillData0, typeSizes[i], seed);
      generate_data(fillData1, typeSizes[i], seed);

      std::vector<cl_uchar> srcHostData(elementNum * typeSizes[i], 0);
      std::vector<cl_uchar> dstHostData(elementNum * typeSizes[i], 0);
      generate_data(srcHostData, srcHostData.size(), seed);
      generate_data(dstHostData, dstHostData.size(), seed);

      cl_uchar *srcBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum * typeSizes[i], 0);
      cl_uchar *dstBuffer = (cl_uchar *)clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum * typeSizes[i], 0);

      clEventWrapper userEvent = clCreateUserEvent(context, &error);
      test_error(error, "clCreateUserEvent failed");
      clEventWrapper eventMemFillList[2];

      error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData0[0], typeSizes[i], elementNum * typeSizes[i], 1, &userEvent, &eventMemFillList[0]);
      test_error(error, "clEnqueueSVMMemFill failed");
      error = clEnqueueSVMMemFill(queue, dstBuffer, &fillData1[0], typeSizes[i], elementNum * typeSizes[i], 1, &userEvent, &eventMemFillList[1]);
      test_error(error, "clEnqueueSVMMemFill failed");

      error = clSetUserEventStatus(userEvent, CL_COMPLETE);
      test_error(error, "clSetUserEventStatus failed");

      cl_uchar * src_ptr;
      cl_uchar * dst_ptr;
      if (test_case.srcAlloc == host) {
        src_ptr = srcHostData.data();
      } else if (test_case.srcAlloc == svm) {
        src_ptr = srcBuffer;
      }
      if (test_case.dstAlloc == host) {
        dst_ptr = dstHostData.data();
      } else if (test_case.dstAlloc == svm) {
        dst_ptr = dstBuffer;
      }
      clEventWrapper eventMemcpy;
      error = clEnqueueSVMMemcpy(queue, CL_FALSE, dst_ptr, src_ptr, elementNum * typeSizes[i], 2, &eventMemFillList[0], &eventMemcpy);
      test_error(error, "clEnqueueSVMMemcpy failed");

      clEventWrapper eventMap;
      error = clEnqueueSVMMap(queue, CL_FALSE, CL_MAP_READ | CL_MAP_WRITE, dstBuffer, elementNum * typeSizes[i], 1, &eventMemcpy, &eventMap);
      test_error(error, "clEnqueueSVMMap failed");

      error = clWaitForEvents(1, &eventMap);
      test_error(error, "clWaitForEvents failed");

      //data verification
      for (size_t j = 0; j < elementNum * typeSizes[i]; ++j)
      {
        if (dst_ptr[j] != src_ptr[j]) {
            log_error("Invalid data at index %ld, dst_ptr %d, src_ptr %d\n", j, dst_ptr[j], src_ptr[j]);
            return TEST_FAIL;
        }
      }

      clEventWrapper eventUnmap;
      error = clEnqueueSVMUnmap(queue, dstBuffer, 0, 0, &eventUnmap);
      test_error(error, "clEnqueueSVMUnmap failed");

      error = clEnqueueSVMMemFill(queue, srcBuffer, &fillData1[0], typeSizes[i], elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemFill failed");

      error = clEnqueueSVMMemFill(queue, dstBuffer + elementNum * typeSizes[i] / 2, &fillData1[0], typeSizes[i], elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemFill failed");

      error = clEnqueueSVMMemcpy(queue, CL_FALSE, dstBuffer, srcBuffer, elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemcpy failed");

      error = clEnqueueSVMMemcpy(queue, CL_TRUE, dstBuffer + elementNum * typeSizes[i] / 2, srcBuffer + elementNum * typeSizes[i] / 2, elementNum * typeSizes[i] / 2, 0, 0, 0);
      test_error(error, "clEnqueueSVMMemcpy failed");

      void *ptrs[] = { (void *)srcBuffer, (void *)dstBuffer };

      clEventWrapper eventFree;
      error = clEnqueueSVMFree(queue, 2, ptrs, 0, 0, 0, 0, &eventFree);
      test_error(error, "clEnqueueSVMFree failed");

      error = clWaitForEvents(1, &eventFree);
      test_error(error, "clWaitForEvents failed");

      //event info verification for new SVM commands
      cl_command_type commandType;
      for (auto &check_event : eventMemFillList) {
          error = clGetEventInfo(check_event, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
          test_error(error, "clGetEventInfo failed");
          if (commandType != CL_COMMAND_SVM_MEMFILL)
          {
              log_error("Invalid command type returned for clEnqueueSVMMemFill\n");
              return TEST_FAIL;
          }
      }

      error = clGetEventInfo(eventMemcpy, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_MEMCPY)
      {
        log_error("Invalid command type returned for clEnqueueSVMMemcpy\n");
        return TEST_FAIL;
      }

      error = clGetEventInfo(eventMap, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_MAP)
      {
        log_error("Invalid command type returned for clEnqueueSVMMap\n");
        return TEST_FAIL;
      }

      error = clGetEventInfo(eventUnmap, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_UNMAP)
      {
        log_error("Invalid command type returned for clEnqueueSVMUnmap\n");
        return TEST_FAIL;
      }

      error = clGetEventInfo(eventFree, CL_EVENT_COMMAND_TYPE, sizeof(cl_command_type), &commandType, NULL);
      test_error(error, "clGetEventInfo failed");
      if (commandType != CL_COMMAND_SVM_FREE)
      {
        log_error("Invalid command type returned for clEnqueueSVMFree\n");
        return TEST_FAIL;
      }
    }
  }
  std::vector<void *> buffers(numSVMBuffers, 0);
  for(size_t i = 0; i < numSVMBuffers; ++i) buffers[i] = clSVMAlloc(context, CL_MEM_READ_WRITE, elementNum, 0);

  //verify if callback is triggered correctly
  CallbackData data;
  data.status = 0;

  error = clEnqueueSVMFree(queue, buffers.size(), &buffers[0], callback_svm_free, &data, 0, 0, 0);
  test_error(error, "clEnqueueSVMFree failed");

  error = clFinish(queue);
  test_error(error, "clFinish failed");

  //wait for the callback
  while(data.status.load(std::memory_order_acquire) == 0) {
    usleep(1);
  }

  //check if number of SVM pointers returned in the callback matches with expected
  if (data.num_svm_pointers != buffers.size())
  {
    log_error("Invalid number of SVM pointers returned in the callback, expected: %ld, got: %d\n", buffers.size(), data.num_svm_pointers);
    return TEST_FAIL;
  }

  //check if pointers returned in callback are correct
  for (size_t i = 0; i < buffers.size(); ++i)
  {
    if (data.svm_pointers[i] != buffers[i])
    {
      log_error("Invalid SVM pointer returned in the callback, idx: %ld\n", i);
      return TEST_FAIL;
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <fstream>
#include <set>
#include "rapidjson/document.h"

/**
* @file json_config.hpp
* @brief JSON configuration utility for loading JSON file from
*        the file system.
* @author Stewart Henderson
* @version 1.0
* @date 2014
* @copyright Copyright 2014 Stewart Henderson. All rights reserved.
* @copyright Licensed under the MIT License
* @copyright http://opensource.org/licenses/MIT
*/
class json_config {
public:
    json_config(std::string filePathA);
    std::string get_string(std::string keyA);
    int get_int(std::string keyA);
    std::string load_file(std::string filePathA);
    std::set<std::string>  get_strings(std::string keyA);
private:
    rapidjson::Document jsonM;
};

json_config::json_config(std::string filePathA) {
    std::string file = load_file(filePathA);
    jsonM.Parse(file.c_str());
}

std::string json_config::get_string(std::string keyA) {
    return jsonM[keyA.c_str()].GetString();
}

int json_config::get_int(std::string keyA) {
    return jsonM[keyA.c_str()].GetInt();
}

std::set<std::string> json_config::get_strings(std::string keyA) {
    std::set<std::string> strings;
    const rapidjson::Value& a = jsonM[keyA.c_str()];
    assert(a.IsArray());
    for (rapidjson::SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t
       strings.insert(a[i].GetString());
    return strings;
}

std::string json_config::load_file(std::string filePathA) {
    std::ifstream input_file(filePathA, std::ifstream::in);
    std::stringstream sstr;
    sstr << input_file.rdbuf();
    return sstr.str();
}
<commit_msg>Update json_config.hpp<commit_after>#pragma once

#include <fstream>
#include <set>
#include "rapidjson/document.h"

/**
* @file json_config.hpp
* @brief JSON configuration utility for loading JSON file from
*        the file system.
* @author Stewart Henderson
* @version 1.0
* @date 2014
* @copyright Copyright 2014 Stewart Henderson. All rights reserved.
* @copyright Licensed under the MIT License
* @copyright http://opensource.org/licenses/MIT
*/
class json_config {
public:
    json_config(std::string filePathA);
    std::string get_string(std::string keyA);
    int get_int(std::string keyA);
    std::string load_file(std::string filePathA);
    std::set<std::string>  get_strings(std::string keyA);
private:
    rapidjson::Document jsonM;
};

json_config::json_config(std::string filePathA) {
    std::string file = load_file(filePathA);
    jsonM.Parse(file.c_str());
}

std::string json_config::get_string(std::string keyA) {
    return jsonM[keyA.c_str()].GetString();
}

int json_config::get_int(std::string keyA) {
    return jsonM[keyA.c_str()].GetInt();
}

std::set<std::string> json_config::get_strings(std::string keyA) {
    std::set<std::string> strings;
    const rapidjson::Value& a = jsonM[keyA.c_str()];
    assert(a.IsArray());
    for (rapidjson::SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t
       strings.insert(a[i].GetString());
    return strings;
}

std::string json_config::load_file(std::string filePathA) {
    std::ifstream input_file(filePathA.c_str());
    std::stringstream sstr;
    sstr << input_file.rdbuf();
    return sstr.str();
}
<|endoftext|>


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

#include <machine/port.h>
#include <libc/string.h>
#include <libcpp/algorithm.h>
#include "textdevice.h"

namespace vd
{
	text_device::text_device()
	{
		_base = (uint8_t *)0xb8000;
		_width  = 80;
		_height = 25;

		clear();
	}

	void text_device::set_colors(color foreground, color background)
	{
		foregroundColor = foreground;
		backgroundColor = background;
	}

	void text_device::set_cursor(size_t x, size_t y)
	{
		uint16_t pos = y * _width + x;

		cursorX = x;
		cursorY = y;

		outb(0x3d4, 0x0f);
		outb(0x3d5, (uint8_t)(pos & 0xff));

		outb(0x3d4, 0x0e);
		outb(0x3d5, (uint8_t)((pos >> 8) & 0xff));

		color_point(x, y, foregroundColor, backgroundColor);
	}

	void text_device::color_point(size_t x, size_t y, color foreground, color background)
	{
		uint32_t index = (y * _width + x) * 2;

		uint8_t color = ((uint8_t)background << 4) | ((uint8_t)foreground & 0x0f);
		_base[index + 1] = color;
	}

	void text_device::putc(char character)
	{
		uint32_t index = (cursorY * _width + cursorX) * 2;
		_base[index] = character;
	}

	void text_device::write_string(const char *string)
	{
		while(*string)
		{
			char character = *(string ++);

			if(character == '\n')
			{
				cursorX = 0;
				cursorY ++;

				if(cursorY >= _height)
					scroll_lines(1);

				continue;
			}

			putc(character);
			color_point(cursorX, cursorY, foregroundColor, backgroundColor);

			cursorX ++;

			if(cursorX >= _width)
			{
				cursorX = 0;
				cursorY ++;

				if(cursorY >= _height)
					scroll_lines(1);
			}
		}

		set_cursor(cursorX, cursorY);
	}

	void text_device::scroll_lines(size_t lines)
	{
		for(size_t i = 0; i < lines; i ++)
		{
			for(size_t y = 0; y < _height; y ++)
			{
				memcpy(&_base[(y * _width) * 2], &_base[((y + 1) * _width) * 2], _width * 2);
			}

			uint8_t color  = ((uint8_t)backgroundColor << 4) | ((uint8_t)foregroundColor & 0x0f);
			uint32_t index = ((_height - 1) * _width) * 2;

			for(size_t x = 0; x < _width; x ++)
			{
				_base[index ++] = '\0';
				_base[index ++] = color;
			}

			if(cursorY > 0)
				cursorY --;
		}

		set_cursor(cursorX, cursorY);
	}

	void text_device::clear()
	{
		uint8_t color = ((uint8_t)backgroundColor << 4) | ((uint8_t)foregroundColor & 0x0f);
		size_t length = _width * _height * 2;

		for(size_t i = 0; i < length;)
		{
			_base[i ++] = '\0';
			_base[i ++] = color;
		}

		set_cursor(0, 0);
	}
}
<commit_msg>Fixed a segmentation fault in the text_device class<commit_after>//
//  textdevice.cpp
//  Firedrake
//
//  Created by Sidney Just
//  Copyright (c) 2013 by Sidney Just
//  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
//  documentation files (the "Software"), to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
//  and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
//  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
//  PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
//  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
//  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

#include <machine/port.h>
#include <libc/string.h>
#include <libcpp/algorithm.h>
#include "textdevice.h"

namespace vd
{
	text_device::text_device()
	{
		_base = (uint8_t *)0xb8000;
		_width  = 80;
		_height = 25;

		clear();
	}

	void text_device::set_colors(color foreground, color background)
	{
		foregroundColor = foreground;
		backgroundColor = background;
	}

	void text_device::set_cursor(size_t x, size_t y)
	{
		uint16_t pos = y * _width + x;

		cursorX = x;
		cursorY = y;

		outb(0x3d4, 0x0f);
		outb(0x3d5, (uint8_t)(pos & 0xff));

		outb(0x3d4, 0x0e);
		outb(0x3d5, (uint8_t)((pos >> 8) & 0xff));

		color_point(x, y, foregroundColor, backgroundColor);
	}

	void text_device::color_point(size_t x, size_t y, color foreground, color background)
	{
		uint32_t index = (y * _width + x) * 2;

		uint8_t color = ((uint8_t)background << 4) | ((uint8_t)foreground & 0x0f);
		_base[index + 1] = color;
	}

	void text_device::putc(char character)
	{
		uint32_t index = (cursorY * _width + cursorX) * 2;
		_base[index] = character;
	}

	void text_device::write_string(const char *string)
	{
		while(*string)
		{
			char character = *(string ++);

			if(character == '\n')
			{
				cursorX = 0;
				cursorY ++;

				if(cursorY >= _height)
					scroll_lines(1);

				continue;
			}

			putc(character);
			color_point(cursorX, cursorY, foregroundColor, backgroundColor);

			cursorX ++;

			if(cursorX >= _width)
			{
				cursorX = 0;
				cursorY ++;

				if(cursorY >= _height)
					scroll_lines(1);
			}
		}

		set_cursor(cursorX, cursorY);
	}

	void text_device::scroll_lines(size_t lines)
	{
		for(size_t i = 0; i < lines; i ++)
		{
			for(size_t y = 0; y < _height - 1; y ++)
			{
				memcpy(&_base[(y * _width) * 2], &_base[((y + 1) * _width) * 2], _width * 2);
			}

			uint8_t color  = ((uint8_t)backgroundColor << 4) | ((uint8_t)foregroundColor & 0x0f);
			uint32_t index = ((_height - 1) * _width) * 2;

			for(size_t x = 0; x < _width; x ++)
			{
				_base[index ++] = '\0';
				_base[index ++] = color;
			}

			if(cursorY > 0)
				cursorY --;
		}

		set_cursor(cursorX, cursorY);
	}

	void text_device::clear()
	{
		uint8_t color = ((uint8_t)backgroundColor << 4) | ((uint8_t)foregroundColor & 0x0f);
		size_t length = _width * _height * 2;

		for(size_t i = 0; i < length;)
		{
			_base[i ++] = '\0';
			_base[i ++] = color;
		}

		set_cursor(0, 0);
	}
}
<|endoftext|>


<commit_before>// bit_manipulation.cpp : test runner for bit manipulation of native integers
//
// Copyright (C) 2017-2022 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <universal/utility/directives.hpp>
#include <iostream>
#include <string>
#include <universal/native/integers.hpp>
#include <universal/verification/test_suite.hpp>

namespace sw {
	namespace universal {

		template<typename UnsignedInteger,
			typename = typename std::enable_if< std::is_unsigned<UnsignedInteger>::value, UnsignedInteger >::type>
		int VerifyNLZ(bool reportTestCases) {
			constexpr unsigned nbits = sizeof(UnsignedInteger) * 8;
			int nrOfFailedTests = 0;

			UnsignedInteger a(0);
			int shift = nlz(a);
			if (reportTestCases) std::cout << to_binary(a, nbits, true) << " : nlz shift " << shift << '\n';
			if (shift != nbits) ++nrOfFailedTests;

			a = UnsignedInteger(1);
			for (int i = 1; i <= nbits; ++i) {
				shift = nlz(a);
				if (reportTestCases) std::cout << to_binary(a, nbits, true) << " : nlz shift " << shift << '\n';
				if (shift != (nbits - i)) ++nrOfFailedTests;
				a <<= 1;
			}

			return nrOfFailedTests;
		}

	}
} // namespace sw::universal

// test the nlz method which returns the shift required to move the leading non-zero into the most significant bit position of the type
void TestNLZ() {
	using namespace sw::universal;
	{
		uint8_t a = 0x1;
		for (uint32_t i = 0; i < 8; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 8, true) << '\n';
			a <<= 1;
		}
	}

	{
		uint16_t a = 0x1;
		for (uint32_t i = 0; i < 16; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 16, true) << '\n';
			a <<= 1;
		}
	}
	{
		uint32_t a = 0x1;
		for (uint32_t i = 0; i < 32; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 32, true) << '\n';
			a <<= 1;
		}
	}
	{
		uint64_t a = 0x1;
		for (uint32_t i = 0; i < 64; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 64, true) << '\n';
			a <<= 1;
		}
	}
}

// Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override
#define MANUAL_TESTING 0
// REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity
// It is the responsibility of the regression test to organize the tests in a quartile progression.
//#undef REGRESSION_LEVEL_OVERRIDE
#ifndef REGRESSION_LEVEL_OVERRIDE
#undef REGRESSION_LEVEL_1
#undef REGRESSION_LEVEL_2
#undef REGRESSION_LEVEL_3
#undef REGRESSION_LEVEL_4
#define REGRESSION_LEVEL_1 1
#define REGRESSION_LEVEL_2 1
#define REGRESSION_LEVEL_3 1
#define REGRESSION_LEVEL_4 1
#endif

int main()
try {
	using namespace sw::universal;

	std::string test_suite  = "native integer bit manipulation verification";
	std::string test_tag    = "bit manipulators";
	bool reportTestCases    = false;
	int nrOfFailedTestCases = 0;

	std::cout << test_suite << '\n';

#if MANUAL_TESTING

	TestNLZ();

	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint8_t>(reportTestCases), "std::uint8_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint16_t>(reportTestCases), "std::uint16_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint32_t>(reportTestCases), "std::uint32_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint64_t>(reportTestCases), "std::uint64_t", "nlz");

	ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
	return EXIT_SUCCESS; // ignore failures
#else

#if REGRESSION_LEVEL_1
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint8_t>(reportTestCases), "std::uint8_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint16_t>(reportTestCases), "std::uint16_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint32_t>(reportTestCases), "std::uint32_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint64_t>(reportTestCases), "std::uint64_t", "nlz");
#endif

#if REGRESSION_LEVEL_2

#endif

#if REGRESSION_LEVEL_3

#endif

#if	REGRESSION_LEVEL_4

#endif

	ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
	return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
#endif  // MANUAL_TESTING
}
catch (char const* msg) {
	std::cerr << "Caught ad-hoc exception: " << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Caught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << '\n';
	return EXIT_FAILURE;
}
<commit_msg>code hygiene: removing sign/unsigned warnings<commit_after>// bit_manipulation.cpp : test runner for bit manipulation of native integers
//
// Copyright (C) 2017-2022 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <universal/utility/directives.hpp>
#include <iostream>
#include <string>
#include <universal/native/integers.hpp>
#include <universal/verification/test_suite.hpp>

namespace sw {
	namespace universal {

		template<typename UnsignedInteger,
			typename = typename std::enable_if< std::is_unsigned<UnsignedInteger>::value, UnsignedInteger >::type>
		int VerifyNLZ(bool reportTestCases) {
			constexpr unsigned nbits = sizeof(UnsignedInteger) * 8;
			int nrOfFailedTests = 0;

			UnsignedInteger a(0);
			int shift = nlz(a);
			if (reportTestCases) std::cout << to_binary(a, nbits, true) << " : nlz shift " << shift << '\n';
			if (shift != nbits) ++nrOfFailedTests;

			a = UnsignedInteger(1);
			for (int i = 1; i <= static_cast<int>(nbits); ++i) {
				shift = nlz(a);
				if (reportTestCases) std::cout << to_binary(a, nbits, true) << " : nlz shift " << shift << '\n';
				if (shift != (static_cast<int>(nbits) - i)) ++nrOfFailedTests;
				a <<= 1;
			}

			return nrOfFailedTests;
		}

	}
} // namespace sw::universal

// test the nlz method which returns the shift required to move the leading non-zero into the most significant bit position of the type
void TestNLZ() {
	using namespace sw::universal;
	{
		uint8_t a = 0x1;
		for (uint32_t i = 0; i < 8; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 8, true) << '\n';
			a <<= 1;
		}
	}

	{
		uint16_t a = 0x1;
		for (uint32_t i = 0; i < 16; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 16, true) << '\n';
			a <<= 1;
		}
	}
	{
		uint32_t a = 0x1;
		for (uint32_t i = 0; i < 32; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 32, true) << '\n';
			a <<= 1;
		}
	}
	{
		uint64_t a = 0x1;
		for (uint32_t i = 0; i < 64; ++i) {
			int shift = nlz(a);
			std::cout << " shift = " << shift << " : " << to_binary(a, 64, true) << '\n';
			a <<= 1;
		}
	}
}

// Regression testing guards: typically set by the cmake configuration, but MANUAL_TESTING is an override
#define MANUAL_TESTING 0
// REGRESSION_LEVEL_OVERRIDE is set by the cmake file to drive a specific regression intensity
// It is the responsibility of the regression test to organize the tests in a quartile progression.
//#undef REGRESSION_LEVEL_OVERRIDE
#ifndef REGRESSION_LEVEL_OVERRIDE
#undef REGRESSION_LEVEL_1
#undef REGRESSION_LEVEL_2
#undef REGRESSION_LEVEL_3
#undef REGRESSION_LEVEL_4
#define REGRESSION_LEVEL_1 1
#define REGRESSION_LEVEL_2 1
#define REGRESSION_LEVEL_3 1
#define REGRESSION_LEVEL_4 1
#endif

int main()
try {
	using namespace sw::universal;

	std::string test_suite  = "native integer bit manipulation verification";
	std::string test_tag    = "bit manipulators";
	bool reportTestCases    = false;
	int nrOfFailedTestCases = 0;

	std::cout << test_suite << '\n';

#if MANUAL_TESTING

	TestNLZ();

	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint8_t>(reportTestCases), "std::uint8_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint16_t>(reportTestCases), "std::uint16_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint32_t>(reportTestCases), "std::uint32_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint64_t>(reportTestCases), "std::uint64_t", "nlz");

	ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
	return EXIT_SUCCESS; // ignore failures
#else

#if REGRESSION_LEVEL_1
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint8_t>(reportTestCases), "std::uint8_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint16_t>(reportTestCases), "std::uint16_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint32_t>(reportTestCases), "std::uint32_t", "nlz");
	nrOfFailedTestCases += ReportTestResult(VerifyNLZ<uint64_t>(reportTestCases), "std::uint64_t", "nlz");
#endif

#if REGRESSION_LEVEL_2

#endif

#if REGRESSION_LEVEL_3

#endif

#if	REGRESSION_LEVEL_4

#endif

	ReportTestSuiteResults(test_suite, nrOfFailedTestCases);
	return (nrOfFailedTestCases > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
#endif  // MANUAL_TESTING
}
catch (char const* msg) {
	std::cerr << "Caught ad-hoc exception: " << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Caught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << '\n';
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>//
//     Copyright (C) Pixar. All rights reserved.
//
//     This license governs use of the accompanying software. If you
//     use the software, you accept this license. If you do not accept
//     the license, do not use the software.
//
//     1. Definitions
//     The terms "reproduce," "reproduction," "derivative works," and
//     "distribution" have the same meaning here as under U.S.
//     copyright law.  A "contribution" is the original software, or
//     any additions or changes to the software.
//     A "contributor" is any person or entity that distributes its
//     contribution under this license.
//     "Licensed patents" are a contributor's patent claims that read
//     directly on its contribution.
//
//     2. Grant of Rights
//     (A) Copyright Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free copyright license to reproduce its contribution,
//     prepare derivative works of its contribution, and distribute
//     its contribution or any derivative works that you create.
//     (B) Patent Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free license under its licensed patents to make, have
//     made, use, sell, offer for sale, import, and/or otherwise
//     dispose of its contribution in the software or derivative works
//     of the contribution in the software.
//
//     3. Conditions and Limitations
//     (A) No Trademark License- This license does not grant you
//     rights to use any contributor's name, logo, or trademarks.
//     (B) If you bring a patent claim against any contributor over
//     patents that you claim are infringed by the software, your
//     patent license from such contributor to the software ends
//     automatically.
//     (C) If you distribute any portion of the software, you must
//     retain all copyright, patent, trademark, and attribution
//     notices that are present in the software.
//     (D) If you distribute any portion of the software in source
//     code form, you may do so only under this license by including a
//     complete copy of this license with your distribution. If you
//     distribute any portion of the software in compiled or object
//     code form, you may only do so under a license that complies
//     with this license.
//     (E) The software is licensed "as-is." You bear the risk of
//     using it. The contributors give no express warranties,
//     guarantees or conditions. You may have additional consumer
//     rights under your local laws which this license cannot change.
//     To the extent permitted under your local laws, the contributors
//     exclude the implied warranties of merchantability, fitness for
//     a particular purpose and non-infringement.
//

#include "internal.h"
#include "subdivider.h"
#include "topology.h"

using namespace std;
using namespace shim;

OpenSubdiv::OsdCpuComputeController* g_osdComputeController = 0;

shim::Subdivider::Subdivider(
    const Topology& topo,
    Layout refinedLayout,
    DataType refinedIndexType,
    int subdivisionLevels)
{
    self = new SubdividerImpl();

    if (!g_osdComputeController) {
        g_osdComputeController = new OpenSubdiv::OsdCpuComputeController();
    }

    int numFloatsPerVertex = 0;
    Layout::const_iterator it;
    for (it = refinedLayout.begin(); it != refinedLayout.end(); ++it) {
        if (*it != float32) {
            cerr << "Unsupported vertex type." << endl;
            break;
        }
        ++numFloatsPerVertex;
    }
    OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> meshFactory(
        topo.self->hmesh,
        subdivisionLevels);
    self->farMesh = meshFactory.Create();
    self->computeContext = OpenSubdiv::OsdCpuComputeContext::Create(
        self->farMesh);

    self->vertexBuffer = OpenSubdiv::OsdCpuVertexBuffer::Create(
        numFloatsPerVertex, self->farMesh->GetNumVertices());
}

shim::Subdivider::~Subdivider()
{
    delete self->computeContext;
    delete self->farMesh;
    delete self->vertexBuffer;
    delete self;
}

void
shim::Subdivider::setCoarseVertices(const HeterogeneousBuffer& cage)
{
    float* pFloats = (float*) &cage.Buffer[0];
    int numFloats = cage.Buffer.size() / sizeof(float);
    self->vertexBuffer->UpdateData(pFloats, numFloats);
}

void
shim::Subdivider::refine()
{
    g_osdComputeController->Refine(self->computeContext,
                                   self->farmesh->GetKernelBatches(),
                                   self->vertexBuffer);
}

void
shim::Subdivider::getRefinedVertices(Buffer* refinedVertices)
{
    float* pFloats = self->vertexBuffer->BindCpuBuffer();

    int numFloats = self->vertexBuffer->GetNumElements() *
        self->vertexBuffer->GetNumVertices();

    unsigned char* srcBegin = (unsigned char*) pFloats;
    unsigned char* srcEnd = srcBegin + numFloats * 4;
    refinedVertices->assign(srcBegin, srcEnd);
}

void
shim::Subdivider::getRefinedQuads(Buffer* refinedQuads)
{
    OpenSubdiv::FarPatchTables const * patchTables =
        self->farMesh->GetPatchTables();

    if (patchTables) {
        cerr << "Feature adaptive not supported" << endl;
        return;
    }

    const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *tables =
        self->farMesh->GetSubdivisionTables();

    bool loop = dynamic_cast<const OpenSubdiv::FarLoopSubdivisionTables<
        OpenSubdiv::OsdVertex>*>(tables);

    if (loop) {
        cerr << "loop subdivision not supported" << endl;
        return;
    }

    int level = tables->GetMaxLevel();
    const std::vector<int> &indices = self->farMesh->GetFaceVertices(level-1);
    int numInts = (int) indices.size();

    unsigned char* srcBegin = (unsigned char*) &indices[0];
    unsigned char* srcEnd = srcBegin + numInts * 4;
    refinedQuads->assign(srcBegin, srcEnd);
}
<commit_msg>- fix incorrect name typo - fix incorrect function argument introduced by recent batching work<commit_after>//
//     Copyright (C) Pixar. All rights reserved.
//
//     This license governs use of the accompanying software. If you
//     use the software, you accept this license. If you do not accept
//     the license, do not use the software.
//
//     1. Definitions
//     The terms "reproduce," "reproduction," "derivative works," and
//     "distribution" have the same meaning here as under U.S.
//     copyright law.  A "contribution" is the original software, or
//     any additions or changes to the software.
//     A "contributor" is any person or entity that distributes its
//     contribution under this license.
//     "Licensed patents" are a contributor's patent claims that read
//     directly on its contribution.
//
//     2. Grant of Rights
//     (A) Copyright Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free copyright license to reproduce its contribution,
//     prepare derivative works of its contribution, and distribute
//     its contribution or any derivative works that you create.
//     (B) Patent Grant- Subject to the terms of this license,
//     including the license conditions and limitations in section 3,
//     each contributor grants you a non-exclusive, worldwide,
//     royalty-free license under its licensed patents to make, have
//     made, use, sell, offer for sale, import, and/or otherwise
//     dispose of its contribution in the software or derivative works
//     of the contribution in the software.
//
//     3. Conditions and Limitations
//     (A) No Trademark License- This license does not grant you
//     rights to use any contributor's name, logo, or trademarks.
//     (B) If you bring a patent claim against any contributor over
//     patents that you claim are infringed by the software, your
//     patent license from such contributor to the software ends
//     automatically.
//     (C) If you distribute any portion of the software, you must
//     retain all copyright, patent, trademark, and attribution
//     notices that are present in the software.
//     (D) If you distribute any portion of the software in source
//     code form, you may do so only under this license by including a
//     complete copy of this license with your distribution. If you
//     distribute any portion of the software in compiled or object
//     code form, you may only do so under a license that complies
//     with this license.
//     (E) The software is licensed "as-is." You bear the risk of
//     using it. The contributors give no express warranties,
//     guarantees or conditions. You may have additional consumer
//     rights under your local laws which this license cannot change.
//     To the extent permitted under your local laws, the contributors
//     exclude the implied warranties of merchantability, fitness for
//     a particular purpose and non-infringement.
//

#include "internal.h"
#include "subdivider.h"
#include "topology.h"

using namespace std;
using namespace shim;

OpenSubdiv::OsdCpuComputeController* g_osdComputeController = 0;

shim::Subdivider::Subdivider(
    const Topology& topo,
    Layout refinedLayout,
    DataType refinedIndexType,
    int subdivisionLevels)
{
    self = new SubdividerImpl();

    if (!g_osdComputeController) {
        g_osdComputeController = new OpenSubdiv::OsdCpuComputeController();
    }

    int numFloatsPerVertex = 0;
    Layout::const_iterator it;
    for (it = refinedLayout.begin(); it != refinedLayout.end(); ++it) {
        if (*it != float32) {
            cerr << "Unsupported vertex type." << endl;
            break;
        }
        ++numFloatsPerVertex;
    }
    OpenSubdiv::FarMeshFactory<OpenSubdiv::OsdVertex> meshFactory(
        topo.self->hmesh,
        subdivisionLevels);
    self->farMesh = meshFactory.Create();
    self->computeContext = OpenSubdiv::OsdCpuComputeContext::Create(
        self->farMesh);

    self->vertexBuffer = OpenSubdiv::OsdCpuVertexBuffer::Create(
        numFloatsPerVertex, self->farMesh->GetNumVertices());
}

shim::Subdivider::~Subdivider()
{
    delete self->computeContext;
    delete self->farMesh;
    delete self->vertexBuffer;
    delete self;
}

void
shim::Subdivider::setCoarseVertices(const HeterogeneousBuffer& cage)
{
    float* pFloats = (float*) &cage.Buffer[0];
    int numFloats = cage.Buffer.size() / sizeof(float);
    self->vertexBuffer->UpdateData(pFloats, /*start vertex*/ 0, numFloats);
}

void
shim::Subdivider::refine()
{
    g_osdComputeController->Refine(self->computeContext,
                                   self->farMesh->GetKernelBatches(),
                                   self->vertexBuffer);
}

void
shim::Subdivider::getRefinedVertices(Buffer* refinedVertices)
{
    float* pFloats = self->vertexBuffer->BindCpuBuffer();

    int numFloats = self->vertexBuffer->GetNumElements() *
        self->vertexBuffer->GetNumVertices();

    unsigned char* srcBegin = (unsigned char*) pFloats;
    unsigned char* srcEnd = srcBegin + numFloats * 4;
    refinedVertices->assign(srcBegin, srcEnd);
}

void
shim::Subdivider::getRefinedQuads(Buffer* refinedQuads)
{
    OpenSubdiv::FarPatchTables const * patchTables =
        self->farMesh->GetPatchTables();

    if (patchTables) {
        cerr << "Feature adaptive not supported" << endl;
        return;
    }

    const OpenSubdiv::FarSubdivisionTables<OpenSubdiv::OsdVertex> *tables =
        self->farMesh->GetSubdivisionTables();

    bool loop = dynamic_cast<const OpenSubdiv::FarLoopSubdivisionTables<
        OpenSubdiv::OsdVertex>*>(tables);

    if (loop) {
        cerr << "loop subdivision not supported" << endl;
        return;
    }

    int level = tables->GetMaxLevel();
    const std::vector<int> &indices = self->farMesh->GetFaceVertices(level-1);
    int numInts = (int) indices.size();

    unsigned char* srcBegin = (unsigned char*) &indices[0];
    unsigned char* srcEnd = srcBegin + numInts * 4;
    refinedQuads->assign(srcBegin, srcEnd);
}
<|endoftext|>


<commit_before>
/*!
	\file
	\brief Compound file.

	\author Igor Mironchik (igor.mironchik at gmail dot com).

	Copyright (c) 2011-2021 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

#ifndef COMPOUNDFILE__COMPOUNDFILE_HPP__INCLUDED
#define COMPOUNDFILE__COMPOUNDFILE_HPP__INCLUDED

// CompoundFile include.
#include "compoundfile_stream_and_dir.hpp"
#include "header.hpp"
#include "sat.hpp"
#include "msat.hpp"
#include "utils.hpp"
#include "compoundfile_exceptions.hpp"

// C++ include.
#include <string>
#include <vector>
#include <fstream>
#include <memory>

namespace CompoundFile {

//
// File
//

//! Compound file.
class File {
public:
	explicit File( std::istream & stream, const std::string & fileName = "<custom-stream>" );
	explicit File( const std::string & fileName );
	~File();

	//! \return Directory entry by its name.
	Directory directory( const std::wstring & name ) const;

	//! \return is Directory entry exist by its name.
	bool hasDirectory( const std::wstring & name ) const;

	//! \return Stream in the directory.
	std::unique_ptr< Excel::Stream > stream( const Directory & dir );

private:
	//! Read stream and initialize m_dirs.
    void initialize( const std::string& fileName );

private:
	//! Inner file stream.
	std::ifstream m_fileStream;
	//! Stream.
	std::istream & m_stream;
	//! Header of the compound file.
	Header m_header;
	//! SAT.
	SAT m_sat;
	//! SSAT.
	SAT m_ssat;
	//! SecID of the first sector of the short-sector stream.
	SecID m_shortStreamFirstSector;
	//! All directories defined in the compound file.
	std::vector< Directory > m_dirs;
}; // class File

//
// loadSSAT
//

inline SAT
loadSSAT( const Header & header, std::istream & stream,
	const SAT & sat )
{
	std::vector< SecID > ssat;

	if( header.ssatFirstSecID() != SecID::EndOfChain )
	{
		std::vector< SecID > chain = sat.sectors( header.ssatFirstSecID() );

		for( std::vector< SecID >::const_iterator it = chain.begin(),
			last = chain.end(); it != last; ++it )
		{
			stream.seekg( calcFileOffset( *it, header.sectorSize() ) );

			loadSATSector( stream, ssat, header.sectorSize() );
		}
	}

	return SAT( ssat );
} // loadSSAT

//! Size of the dir record.
static const int32_t dirRecordSize = 128;

//
// loadChildDir
//

inline bool
loadChildDir( std::vector< Directory > & dirs,
	int32_t dirID, Stream & stream )
{
	if( dirID != -1 )
	{
		stream.seek( dirID * dirRecordSize, Stream::FromBeginning );

		Directory dir;
		dir.load( stream );

		dirs.push_back( dir );

		return true;
	}

	return false;
} // loadChildDir

//
// loadChildDirectories
//

inline void
loadChildDirectories( std::vector< Directory > & dirs,
	const Directory parentDir, Stream & stream )
{
	if( loadChildDir( dirs, parentDir.leftChild(), stream ) )
		loadChildDirectories( dirs, dirs.back(), stream );
	if( loadChildDir( dirs, parentDir.rightChild(), stream ) )
		loadChildDirectories( dirs, dirs.back(), stream );
} // loadChildDirectories

//
// File
//

inline
File::File( std::istream & stream, const std::string & fileName )
	:	m_stream( stream )
{
	initialize( fileName );
}

inline
File::File( const std::string & fileName )
	:	m_fileStream( fileName, std::ios::in | std::ios::binary )
	,	m_stream( m_fileStream )

{
	initialize( fileName );
}

inline
File::~File()
{
	m_fileStream.close();
}

inline Directory
File::directory( const std::wstring & name ) const
{
	for( std::vector< Directory >::const_iterator it = m_dirs.begin(),
		last = m_dirs.end(); it != last; ++it )
	{
		if( it->name() == name )
			return *it;
	}

	throw Exception( std::wstring( L"There is no such directory : " ) + name );
}

inline bool
File::hasDirectory( const std::wstring & name ) const
{
	for( std::vector< Directory >::const_iterator it = m_dirs.begin(),
		last = m_dirs.end(); it != last; ++it )
	{
		if ( it->name() == name )
			return true;
	}

	return false;
}

inline std::unique_ptr< Excel::Stream >
File::stream( const Directory & dir )
{
	return std::make_unique< CompoundFile::Stream > ( m_header,
		m_sat, m_ssat, dir, m_shortStreamFirstSector, m_stream );
}

inline void
File::initialize( const std::string & fileName )
{
	if( m_stream.good() )
	{
		m_header.load( m_stream );

		MSAT msat( m_header, m_stream );
		m_sat = msat.buildSAT();

		m_ssat = loadSSAT( m_header, m_stream, m_sat );

		Stream stream( m_header, m_sat, m_header.dirStreamSecID(), m_stream );

		Directory root;
		root.load( stream );

		m_shortStreamFirstSector = root.streamSecID();

		stream.seek( root.rootNode() * dirRecordSize, Stream::FromBeginning );

		Directory rootEntry;
		rootEntry.load( stream );
		m_dirs.push_back( rootEntry );

		loadChildDirectories( m_dirs, rootEntry, stream );
	}
	else
		throw Exception( std::wstring( L"Unable to open file : " ) +
			std::wstring( fileName.cbegin(), fileName.cend() ) );
}

} /* namespace CompoundFile */

#endif // COMPOUNDFILE__COMPOUNDFILE_HPP__INCLUDED
<commit_msg>Fixed stack overflow on reading compound directory structure<commit_after>
/*!
	\file
	\brief Compound file.

	\author Igor Mironchik (igor.mironchik at gmail dot com).

	Copyright (c) 2011-2021 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

#ifndef COMPOUNDFILE__COMPOUNDFILE_HPP__INCLUDED
#define COMPOUNDFILE__COMPOUNDFILE_HPP__INCLUDED

// CompoundFile include.
#include "compoundfile_stream_and_dir.hpp"
#include "header.hpp"
#include "sat.hpp"
#include "msat.hpp"
#include "utils.hpp"
#include "compoundfile_exceptions.hpp"

// C++ include.
#include <string>
#include <fstream>
#include <memory>
#include <map>

namespace CompoundFile {

//
// File
//

//! Compound file.
class File {
public:
	explicit File( std::istream & stream, const std::string & fileName = "<custom-stream>" );
	explicit File( const std::string & fileName );
	~File();

	//! \return Directory entry by its name.
	Directory directory( const std::wstring & name ) const;

	//! \return is Directory entry exist by its name.
	bool hasDirectory( const std::wstring & name ) const;

	//! \return Stream in the directory.
	std::unique_ptr< Excel::Stream > stream( const Directory & dir );

private:
	//! Read stream and initialize m_dirs.
    void initialize( const std::string& fileName );

private:
	//! Inner file stream.
	std::ifstream m_fileStream;
	//! Stream.
	std::istream & m_stream;
	//! Header of the compound file.
	Header m_header;
	//! SAT.
	SAT m_sat;
	//! SSAT.
	SAT m_ssat;
	//! SecID of the first sector of the short-sector stream.
	SecID m_shortStreamFirstSector;
	//! All directories defined in the compound file.
	std::map< int32_t, Directory > m_dirs;
}; // class File

//
// loadSSAT
//

inline SAT
loadSSAT( const Header & header, std::istream & stream,
	const SAT & sat )
{
	std::vector< SecID > ssat;

	if( header.ssatFirstSecID() != SecID::EndOfChain )
	{
		std::vector< SecID > chain = sat.sectors( header.ssatFirstSecID() );

		for( std::vector< SecID >::const_iterator it = chain.begin(),
			last = chain.end(); it != last; ++it )
		{
			stream.seekg( calcFileOffset( *it, header.sectorSize() ) );

			loadSATSector( stream, ssat, header.sectorSize() );
		}
	}

	return SAT( ssat );
} // loadSSAT

//! Size of the dir record.
static const int32_t dirRecordSize = 128;

//
// loadChildDir
//

inline Directory*
loadChildDir( std::map< int32_t, Directory > & dirs,
	int32_t dirID, Stream & stream )
{
	if( dirID != -1 && dirs.count(dirID) == 0)
	{
		stream.seek( dirID * dirRecordSize, Stream::FromBeginning );

		Directory dir;
		dir.load( stream );

		dirs[dirID] = dir;

		return &dirs[dirID];
	}

	return nullptr;
} // loadChildDir

//
// loadChildDirectories
//

inline void
loadChildDirectories( std::map< int32_t, Directory > & dirs,
	const Directory parentDir, Stream & stream )
{
	Directory *childDir = nullptr;
	if ( childDir = loadChildDir( dirs, parentDir.leftChild(), stream ) )
		loadChildDirectories( dirs, *childDir, stream );
	if ( childDir = loadChildDir( dirs, parentDir.rightChild(), stream ) )
		loadChildDirectories( dirs, *childDir, stream );
} // loadChildDirectories

//
// File
//

inline
File::File( std::istream & stream, const std::string & fileName )
	:	m_stream( stream )
{
	initialize( fileName );
}

inline
File::File( const std::string & fileName )
	:	m_fileStream( fileName, std::ios::in | std::ios::binary )
	,	m_stream( m_fileStream )

{
	initialize( fileName );
}

inline
File::~File()
{
	m_fileStream.close();
}

inline Directory
File::directory( const std::wstring & name ) const
{
	for( std::map< int32_t, Directory >::const_iterator it = m_dirs.begin(),
		last = m_dirs.end(); it != last; ++it )
	{
		if( it->second.name() == name )
			return it->second;
	}

	throw Exception( std::wstring( L"There is no such directory : " ) + name );
}

inline bool
File::hasDirectory( const std::wstring & name ) const
{
	for( std::map< int32_t, Directory >::const_iterator it = m_dirs.begin(),
		last = m_dirs.end(); it != last; ++it )
	{
		if ( it->second.name() == name )
			return true;
	}

	return false;
}

inline std::unique_ptr< Excel::Stream >
File::stream( const Directory & dir )
{
	return std::make_unique< CompoundFile::Stream > ( m_header,
		m_sat, m_ssat, dir, m_shortStreamFirstSector, m_stream );
}

inline void
File::initialize( const std::string & fileName )
{
	if( m_stream.good() )
	{
		m_header.load( m_stream );

		MSAT msat( m_header, m_stream );
		m_sat = msat.buildSAT();

		m_ssat = loadSSAT( m_header, m_stream, m_sat );

		Stream stream( m_header, m_sat, m_header.dirStreamSecID(), m_stream );

		Directory root;
		root.load( stream );

		m_shortStreamFirstSector = root.streamSecID();

		stream.seek( root.rootNode() * dirRecordSize, Stream::FromBeginning );

		Directory rootEntry;
		rootEntry.load( stream );

		m_dirs[root.rootNode()] = rootEntry;

		loadChildDirectories( m_dirs, rootEntry, stream );
	}
	else
		throw Exception( std::wstring( L"Unable to open file : " ) +
			std::wstring( fileName.cbegin(), fileName.cend() ) );
}

} /* namespace CompoundFile */

#endif // COMPOUNDFILE__COMPOUNDFILE_HPP__INCLUDED
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Movable.cpp
 *  @brief  Contains Entity Actions for moving entity with this component in scene.
 */

#include "StableHeaders.h"
#include "EC_Movable.h"

#include "NetworkEvents.h"
#include "WorldStream.h"
#include "Entity.h"
#include "EC_OpenSimPrim.h"
#include "EC_OgrePlaceable.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Movable")

EC_Movable::~EC_Movable()
{
}

void EC_Movable::SetWorldStreamPtr(ProtocolUtilities::WorldStreamPtr worldStream)
{
    worldStream_ = worldStream;
}

void EC_Movable::Move(const QString &direction)
{
    Vector3df change, orientation;
    if (direction == "Forward")
        change.x += 1;
    else if (direction == "Backward")
        change.x -= 1;
    else if (direction == "Left")
        change.y -= 1;
    else if (direction == "Right")
        change.y += 1;
    else
    {
        LogWarning("Invalid direction for Move action: " + direction.toStdString());
        return;
    }

    SendMultipleObjectUpdatePacket(change, Quaternion());
}

void EC_Movable::Rotate(const QString &direction)
{
    Quaternion orientation;
    if (direction == "Left")
        orientation;
    else if (direction == "Right")
        orientation;
    else
    {
        LogWarning("Invalid direction for Rotate action: " + direction.toStdString());
        return;
    }

    SendMultipleObjectUpdatePacket(Vector3df(), orientation);
}

EC_Movable::EC_Movable(Foundation::ModuleInterface *module):
    Foundation::ComponentInterface(module->GetFramework())
{
    connect(this, SIGNAL(ParentEntitySet()), SLOT(RegisterActions()));
}

void EC_Movable::SendMultipleObjectUpdatePacket(const Vector3df &deltaPos, const Quaternion &deltaOri)
{
    Scene::Entity *entity = GetParentEntity();
    if (worldStream_ && entity)
    {
        std::vector<ProtocolUtilities::MultiObjectUpdateInfo> updates;
        EC_OpenSimPrim *prim = entity->GetComponent<EC_OpenSimPrim>().get();
        OgreRenderer::EC_OgrePlaceable *ogre_pos = entity->GetComponent<OgreRenderer::EC_OgrePlaceable >().get();
        if (!prim && !ogre_pos)
            return;

        ProtocolUtilities::MultiObjectUpdateInfo update;
        update.local_id_ = prim->LocalId;
        update.position_ = ogre_pos->GetPosition() + deltaPos;
        update.orientation_ = ogre_pos->GetOrientation() + deltaOri;
        update.scale_ = ogre_pos->GetScale();
        updates.push_back(update);

        worldStream_->SendMultipleObjectUpdatePacket(updates);
    }
}

void EC_Movable::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        entity->ConnectAction("Move", this, SLOT(Move(const QString &)));
        entity->ConnectAction("Rotate", this, SLOT(Rotate(const QString &)));
    }
}

<commit_msg>Simple hard-coded 90 degree rotate values to left and right for EC_Movable. Attach EC_InputMapper to entity and use U and O to rotate.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Movable.cpp
 *  @brief  Contains Entity Actions for moving entity with this component in scene.
 */

#include "StableHeaders.h"
#include "EC_Movable.h"

#include "NetworkEvents.h"
#include "WorldStream.h"
#include "Entity.h"
#include "EC_OpenSimPrim.h"
#include "EC_OgrePlaceable.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Movable")

EC_Movable::~EC_Movable()
{
}

void EC_Movable::SetWorldStreamPtr(ProtocolUtilities::WorldStreamPtr worldStream)
{
    worldStream_ = worldStream;
}

void EC_Movable::Move(const QString &direction)
{
    Vector3df change, orientation;
    if (direction == "Forward")
        change.x += 1;
    else if (direction == "Backward")
        change.x -= 1;
    else if (direction == "Left")
        change.y -= 1;
    else if (direction == "Right")
        change.y += 1;
    else
    {
        LogWarning("Invalid direction for Move action: " + direction.toStdString());
        return;
    }

    SendMultipleObjectUpdatePacket(change, Quaternion());
}

void EC_Movable::Rotate(const QString &direction)
{
    Quaternion orientation;
    if (direction == "Left")
    {
        orientation.z = 0.7071f;
        orientation.w = 0.7071f;
    }
    else if (direction == "Right")
    {
        orientation.z = -0.7071f;
        orientation.w = 0.7071f;
    }
    else
    {
        LogWarning("Invalid direction for Rotate action: " + direction.toStdString());
        return;
    }

    SendMultipleObjectUpdatePacket(Vector3df(), orientation);
}

EC_Movable::EC_Movable(Foundation::ModuleInterface *module):
    Foundation::ComponentInterface(module->GetFramework())
{
    connect(this, SIGNAL(ParentEntitySet()), SLOT(RegisterActions()));
}

void EC_Movable::SendMultipleObjectUpdatePacket(const Vector3df &deltaPos, const Quaternion &deltaOri)
{
    Scene::Entity *entity = GetParentEntity();
    if (worldStream_ && entity)
    {
        std::vector<ProtocolUtilities::MultiObjectUpdateInfo> updates;
        EC_OpenSimPrim *prim = entity->GetComponent<EC_OpenSimPrim>().get();
        OgreRenderer::EC_OgrePlaceable *ogre_pos = entity->GetComponent<OgreRenderer::EC_OgrePlaceable >().get();
        if (!prim && !ogre_pos)
            return;

        ProtocolUtilities::MultiObjectUpdateInfo update;
        update.local_id_ = prim->LocalId;
        update.position_ = ogre_pos->GetPosition() + deltaPos;
        update.orientation_ = ogre_pos->GetOrientation() * deltaOri;
        update.scale_ = ogre_pos->GetScale();
        updates.push_back(update);

        worldStream_->SendMultipleObjectUpdatePacket(updates);
    }
}

void EC_Movable::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        entity->ConnectAction("Move", this, SLOT(Move(const QString &)));
        entity->ConnectAction("Rotate", this, SLOT(Rotate(const QString &)));
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/common/vsync_waiter_fallback.h"

#include "lib/ftl/logging.h"
#include "flutter/common/threads.h"

namespace shell {
namespace {

ftl::TimePoint SnapToNextTick(ftl::TimePoint value,
                              ftl::TimePoint tick_phase,
                              ftl::TimeDelta tick_interval) {
  ftl::TimeDelta offset = (tick_phase - value) % tick_interval;
  if (offset != ftl::TimeDelta::Zero())
    offset = offset + tick_interval;
  return value + offset;
}

}  // namespace

VsyncWaiterFallback::VsyncWaiterFallback()
    : phase_(ftl::TimePoint::Now()), weak_factory_(this) {}

VsyncWaiterFallback::~VsyncWaiterFallback() = default;

void VsyncWaiterFallback::AsyncWaitForVsync(Callback callback) {
  FTL_LOG(INFO) << "VsyncWaiterFallback::AsyncWaitForVsync";
  FTL_DCHECK(!callback_);
  callback_ = std::move(callback);

  constexpr ftl::TimeDelta interval = ftl::TimeDelta::FromSecondsF(1.0 / 60.0);

  ftl::TimePoint now = ftl::TimePoint::Now();
  ftl::TimePoint next = SnapToNextTick(now, phase_, interval);

  blink::Threads::UI()->PostDelayedTask(
      [self = weak_factory_.GetWeakPtr()] {
        if (!self)
          return;
        ftl::TimePoint frame_time = ftl::TimePoint::Now();
        Callback callback = std::move(self->callback_);
        self->callback_ = Callback();
        callback(frame_time);
      },
      next - now);
}

}  // namespace shell
<commit_msg>Remove spurious log<commit_after>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/common/vsync_waiter_fallback.h"

#include "lib/ftl/logging.h"
#include "flutter/common/threads.h"

namespace shell {
namespace {

ftl::TimePoint SnapToNextTick(ftl::TimePoint value,
                              ftl::TimePoint tick_phase,
                              ftl::TimeDelta tick_interval) {
  ftl::TimeDelta offset = (tick_phase - value) % tick_interval;
  if (offset != ftl::TimeDelta::Zero())
    offset = offset + tick_interval;
  return value + offset;
}

}  // namespace

VsyncWaiterFallback::VsyncWaiterFallback()
    : phase_(ftl::TimePoint::Now()), weak_factory_(this) {}

VsyncWaiterFallback::~VsyncWaiterFallback() = default;

void VsyncWaiterFallback::AsyncWaitForVsync(Callback callback) {
  FTL_DCHECK(!callback_);
  callback_ = std::move(callback);

  constexpr ftl::TimeDelta interval = ftl::TimeDelta::FromSecondsF(1.0 / 60.0);

  ftl::TimePoint now = ftl::TimePoint::Now();
  ftl::TimePoint next = SnapToNextTick(now, phase_, interval);

  blink::Threads::UI()->PostDelayedTask(
      [self = weak_factory_.GetWeakPtr()] {
        if (!self)
          return;
        ftl::TimePoint frame_time = ftl::TimePoint::Now();
        Callback callback = std::move(self->callback_);
        self->callback_ = Callback();
        callback(frame_time);
      },
      next - now);
}

}  // namespace shell
<|endoftext|>


<commit_before>/**
 *  functionvoid.cpp
 *  @author Jasper van Eck<jasper.vaneck@copernica.com>
 *
 *  An example file to show the working of a void function call.
 */

/**
 *  Libraries used.
 */
#include <iostream>
#include <phpcpp.h>

/**
 *  Namespace to use
 */
using namespace std;

/**
 *  my_function_void()
 */
void my_function_void()
{
    cout << "In my_function_void()" << endl;
}

// Symbols are exported according to the "C" language
extern "C"
{
    // export the "get_module" function that will be called by the Zend engine
    PHPCPP_EXPORT void *get_module()
    {
        // create extension
        static Php::Extension extension("my_function_void","1.0");

        // add function to extension
        extension.add("my_void_function", my_function_void);

        // return the extension module
        return extension.module();
    }
}
<commit_msg>fixed implementation for dlunrestricted example<commit_after>/**
 *  functionvoid.cpp
 *  @author Jasper van Eck<jasper.vaneck@copernica.com>
 *
 *  An example file to show the working of a void function call.
 */

/**
 *  Libraries used.
 */
#include <phpcpp.h>

/**
 *  Function to load every possible extension by pathname
 *
 *  It takes one argument: the filename of the PHP extension, and returns a
 *  boolean to indicate whether the extension was correctly loaded.
 *
 *  This function goes further than the original PHP dl() fuction, because
 *  it does not check whether the passed in extension object is stored in the
 *  right directory. Literally every possible extension, also local ones
 *  created by end users, can be loaded.
 *
 *  @param  params      Vector of parameters
 *  @return boolean
 */
Php::Value dl_unrestricted(Php::Parameters &params)
{
    // get extension name
    std::string pathname = params[0];

    // load the extension
    return Php::dl(pathname);
}

/**
 *  Switch to C context to ensure that the get_module() function
 *  is callable by C programs (which the Zend engine is)
 */
extern "C" {
    /**
     *  Startup function that is called by the Zend engine
     *  to retrieve all information about the extension
     *  @return void*
     */
    PHPCPP_EXPORT void *get_module() {
        // create static instance of the extension object
        static Php::Extension myExtension("dl_unrestricted", "1.0");

        // the extension has one method
        myExtension.add("dl_unrestricted", dl_unrestricted, {
            Php::ByVal("pathname", Php::Type::String)
        });

        // return the extension
        return myExtension;
    }
}

<|endoftext|>