// This file was generated by $generator from $template

#include "anari/anari_cpp.hpp"
#include "$prefixSpecializations.h"

#include <cstdlib>
#include <cstring>
#include <algorithm>

static void managed_deleter(const void*, const void *appMemory) {
   std::free(const_cast<void*>(appMemory));
}

$begin_namespaces

Object<Array1D>::Object(ANARIDevice d, ANARIObject handle, const void* appMemory,
   ANARIMemoryDeleter deleter, const void* userdata, ANARIDataType elementType,
   uint64_t numItems1, uint64_t byteStride1)
: DefaultObject(d, handle), appMemory(appMemory), deleter(deleter), userdata(userdata),
elementType(elementType), numItems1(numItems1), byteStride1(byteStride1)
{
   if(this->byteStride1 == 0) {
      this->byteStride1 = anari::sizeOf(elementType);
   }
   if(appMemory == nullptr) {
      this->appMemory = std::calloc(numItems1, anari::sizeOf(elementType));
      this->deleter = managed_deleter;
   }
   if(anari::isObject(elementType)) {
      objectArray.resize(numItems1);
      const char *basePtr = static_cast<const char*>(this->appMemory);
      for(uint64_t i = 0;i<numItems1;++i) {
         const ANARIObject op = *reinterpret_cast<const ANARIObject*>(basePtr+i*this->byteStride1);
         objectArray[i] = op;
         anariRetainInternal(device, objectArray[i], handle);
      }
   }
}

void* Object<Array1D>::map() {
   return const_cast<void*>(appMemory);
}
void Object<Array1D>::unmap() {
   if(anari::isObject(elementType)) {
      const char *basePtr = static_cast<const char*>(appMemory);
      for(uint64_t i = 0;i<numItems1;++i) {
         const ANARIObject op = *reinterpret_cast<const ANARIObject*>(basePtr+i*byteStride1);
         anariReleaseInternal(device, objectArray[i], handle);
         objectArray[i] = op;
         anariRetainInternal(device, objectArray[i], handle);
      }
   }
}
void Object<Array1D>::releasePublic() {
   // internalize data if necessary
}
Object<Array1D>::~Object() {
   for(auto handle : objectArray) {
      anariReleaseInternal(device, handle, handle);
   }
   if(deleter) {
      deleter(userdata, appMemory);
   }
}


Object<Array2D>::Object(ANARIDevice d, ANARIObject handle, const void* appMemory,
   ANARIMemoryDeleter deleter, const void* userdata, ANARIDataType elementType,
   uint64_t numItems1, uint64_t numItems2,
   uint64_t byteStride1, uint64_t byteStride2)
: DefaultObject(d, handle), appMemory(appMemory), deleter(deleter), userdata(userdata),
elementType(elementType), numItems1(numItems1), numItems2(numItems2),
byteStride1(byteStride1), byteStride2(byteStride2)
{
   if(this->byteStride1 == 0) {
      this->byteStride1 = anari::sizeOf(elementType);
   }
   if(this->byteStride2 == 0) {
      this->byteStride2 = this->byteStride1*numItems1;
   }

   if(appMemory == nullptr) {
      size_t byte_size = anari::sizeOf(elementType)*numItems1*numItems2;
      appMemory = std::malloc(byte_size);
      deleter = managed_deleter;
   }
}

void* Object<Array2D>::map() {
   return const_cast<void*>(appMemory);
}
void Object<Array2D>::unmap() {

}
void Object<Array2D>::releasePublic() {
   // internalize data if necessary
}
Object<Array2D>::~Object() {
   if(deleter) {
      deleter(userdata, appMemory);
   }
}


Object<Array3D>::Object(ANARIDevice d, ANARIObject handle, const void* appMemory,
   ANARIMemoryDeleter deleter, const void* userdata, ANARIDataType elementType,
   uint64_t numItems1, uint64_t numItems2, uint64_t numItems3,
   uint64_t byteStride1, uint64_t byteStride2, uint64_t byteStride3)
: DefaultObject(d, handle), appMemory(appMemory), deleter(deleter), userdata(userdata),
elementType(elementType), numItems1(numItems1), numItems2(numItems2), numItems3(numItems3),
byteStride1(byteStride1), byteStride2(byteStride2), byteStride3(byteStride3)
{
   if(this->byteStride1 == 0) {
      this->byteStride1 = anari::sizeOf(elementType);
   }
   if(this->byteStride2 == 0) {
      this->byteStride2 = this->byteStride1*numItems1;
   }
   if(this->byteStride3 == 0) {
      this->byteStride3 = this->byteStride2*numItems2;
   }

   if(appMemory == nullptr) {
      size_t byte_size = anari::sizeOf(elementType)*numItems1*numItems2*numItems3;
      appMemory = std::malloc(byte_size);
      deleter = managed_deleter;
   }
}

void* Object<Array3D>::map() {
   return const_cast<void*>(appMemory);
}
void Object<Array3D>::unmap() {

}
void Object<Array3D>::releasePublic() {
   // internalize data if necessary
}
Object<Array3D>::~Object() {
   if(deleter) {
      deleter(userdata, appMemory);
   }
}

$end_namespaces
