/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include #include namespace facebook { namespace hs { namespace ffi { /// A wrapper for a malloc'ed block of memory. Ownership can be release via /// 'release' and 'release_to'; the memory must then be released manually via /// 'free'. This makes it suitable for passing to Haskell. template struct malloced_array { static_assert( std::is_trivially_destructible::value, "malloced_array requires a trivially destructible type"); malloced_array() noexcept : n(0) {} explicit malloced_array(size_t k) : ptr(folly::allocate_sys_buffer(k * sizeof(T))), n(k) {} malloced_array(folly::SysBufferUniquePtr&& p, size_t k) noexcept : ptr(std::move(p)), n(k) {} malloced_array(malloced_array&&) noexcept = default; malloced_array(const malloced_array&) = delete; malloced_array& operator=(malloced_array&& other) noexcept = default; malloced_array& operator=(const malloced_array&) = delete; template void release_to(U** data, size_t* size) noexcept { *size = n; *data = release(); } T* release() noexcept { n = 0; return static_cast(ptr.release()); } T* get() const noexcept { return static_cast(ptr.get()); } size_t size() const noexcept { return n; } T& operator[](size_t i) const noexcept { return get()[i]; } void prune(size_t k) noexcept { assert(k <= n); n = k; } private: folly::SysBufferUniquePtr ptr; size_t n; }; template malloced_array malloc_array(size_t n) { return malloced_array(n); } template malloced_array clone_array(const T* data, size_t size, size_t pad = 0) { malloced_array arr(size + pad); if (size != 0) { std::memcpy(arr.get(), data, size * sizeof(T)); } return arr; } inline malloced_array clone_bytes(const void* data, size_t size, size_t pad = 0) { return clone_array(static_cast(data), size, pad); } inline malloced_array clone_bytes( folly::ByteRange bytes, size_t pad = 0) { return clone_bytes(bytes.data(), bytes.size(), pad); } inline malloced_array clone_bytes( const folly::fbstring& bytes, size_t pad = 0) { return clone_bytes(bytes.data(), bytes.size(), pad); } inline malloced_array clone_bytes( const std::string& bytes, size_t pad = 0) { return clone_bytes(bytes.data(), bytes.size(), pad); } inline malloced_array clone_string(const std::string& s, size_t pad = 0) { auto p = s.c_str(); return clone_array(p, strlen(p) + 1, pad); } } // namespace ffi } // namespace hs } // namespace facebook