#pragma once #include "rapidjson/document.h" #include "rapidjson/writer.h" #include #include namespace rublon { struct RapidJSONPMRAlloc { std::pmr::memory_resource * upstream = std::pmr::get_default_resource(); static constexpr bool kNeedFree = true; static constexpr auto objectOffset = alignof(std::max_align_t); static constexpr auto memPadding = objectOffset * 2; void * Malloc(size_t size) { if(size != 0) { const auto allocated_size = size + memPadding; std::byte * newPtr = static_cast< std::byte * >(upstream->allocate(allocated_size)); auto * ptrToReturn = newPtr + memPadding; // placement new a pointer to ourselves at the first memory location new(newPtr)(RapidJSONPMRAlloc *)(this); // placement new the size in the second location new(newPtr + objectOffset)(std::size_t)(size); return ptrToReturn; } else { return nullptr; } } void freePtr(void * origPtr, size_t originalSize) { if(origPtr == nullptr) { return; } upstream->deallocate(static_cast< std::byte * >(origPtr) - memPadding, originalSize + memPadding); } void * Realloc(void * origPtr, size_t originalSize, size_t newSize) { if(newSize == 0) { freePtr(origPtr, originalSize); return nullptr; } if(newSize <= originalSize) { return origPtr; } void * newPtr = Malloc(newSize); std::memcpy(newPtr, origPtr, originalSize); freePtr(origPtr, originalSize); return newPtr; } // and Free needs to be static, which causes this whole thing // to fall apart. This means that we have to keep our own list of allocated memory // with our own pointers back to ourselves and our own list of sizes // so we can push all of this back to the upstream allocator static void Free(void * ptr) { if(ptr == nullptr) { return; } std::byte * startOfData = static_cast< std::byte * >(ptr) - memPadding; auto * ptrToAllocator = *reinterpret_cast< RapidJSONPMRAlloc ** >(startOfData); auto origAllocatedSize = *reinterpret_cast< std::size_t * >(startOfData + objectOffset); ptrToAllocator->freePtr(ptr, origAllocatedSize); } }; using Document = rapidjson::GenericDocument< rapidjson::UTF8<>, RapidJSONPMRAlloc >; using Value = rapidjson::GenericValue< rapidjson::UTF8<>, RapidJSONPMRAlloc >; using StringBuffer = rapidjson::GenericStringBuffer< rapidjson::UTF8<>, RapidJSONPMRAlloc >; using Writer = rapidjson::Writer< StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, RapidJSONPMRAlloc >; // using value = GenericValue< UTF8<>, RapidJSONPMRAlloc >; // RapidJSONPMRAlloc alloc{&mr}; // GenericDocument< UTF8<>, RapidJSONPMRAlloc > d(&alloc); // d.SetObject(); // GenericDocument< UTF8<>, RapidJSONPMRAlloc >::AllocatorType & allocator = d.GetAllocator(); // d.AddMember("systemToken", "DUPA", allocator); // d.AddMember("username", "$USER", allocator); // d.AddMember("userEmail", "$USER_EMAIL", allocator); } // namespace rublon