common/util/cpp/memory.h (78 lines of code) (raw):
/*
* 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 <folly/FBString.h>
#include <folly/Memory.h>
#include <folly/Range.h>
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 <typename T>
struct malloced_array {
static_assert(
std::is_trivially_destructible<T>::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 <typename U>
void release_to(U** data, size_t* size) noexcept {
*size = n;
*data = release();
}
T* release() noexcept {
n = 0;
return static_cast<T*>(ptr.release());
}
T* get() const noexcept {
return static_cast<T*>(ptr.get());
}
size_t size() const noexcept {
return n;
}
T& operator[](size_t i) const noexcept {
return get()[i];
}
void prune(size_t k) {
assert(k <= n);
n = k;
}
private:
folly::SysBufferUniquePtr ptr;
size_t n;
};
template <typename T>
malloced_array<T> malloc_array(size_t n) {
return malloced_array<T>(n);
}
template <typename T>
malloced_array<T> clone_array(const T* data, size_t size) {
malloced_array<T> arr(size);
if (size != 0) {
std::memcpy(arr.get(), data, size * sizeof(T));
}
return arr;
}
inline malloced_array<uint8_t> clone_bytes(const void* data, size_t size) {
return clone_array<uint8_t>(static_cast<const uint8_t*>(data), size);
}
inline malloced_array<uint8_t> clone_bytes(folly::ByteRange bytes) {
return clone_bytes(bytes.data(), bytes.size());
}
inline malloced_array<uint8_t> clone_bytes(const folly::fbstring& bytes) {
return clone_bytes(bytes.data(), bytes.size());
}
inline malloced_array<uint8_t> clone_bytes(const std::string& bytes) {
return clone_bytes(bytes.data(), bytes.size());
}
inline malloced_array<char> clone_string(const std::string& s) {
auto p = s.c_str();
return clone_array(p, strlen(p) + 1);
}
} // namespace ffi
} // namespace hs
} // namespace facebook