Compare commits
1 Commits
5a56871ae5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fac013d63f |
@ -28,7 +28,7 @@ auto AsyncOps::run_task(Mut<std::function<void()>> task) -> void {
|
|||||||
|
|
||||||
auto AsyncOps::initialize_scheduler(Mut<u8> worker_count) -> Result<void> {
|
auto AsyncOps::initialize_scheduler(Mut<u8> worker_count) -> Result<void> {
|
||||||
if (worker_count == 0) {
|
if (worker_count == 0) {
|
||||||
Const<u32> hw_concurrency = std::thread::hardware_concurrency();
|
const u32 hw_concurrency = std::thread::hardware_concurrency();
|
||||||
Mut<u32> threads = 2;
|
Mut<u32> threads = 2;
|
||||||
if (hw_concurrency > 2) {
|
if (hw_concurrency > 2) {
|
||||||
threads = hw_concurrency - 2;
|
threads = hw_concurrency - 2;
|
||||||
@ -65,14 +65,14 @@ auto AsyncOps::terminate_scheduler() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto AsyncOps::schedule_task(Mut<std::function<void(WorkerId worker_id)>> task,
|
auto AsyncOps::schedule_task(Mut<std::function<void(WorkerId worker_id)>> task,
|
||||||
Const<TaskTag> tag, Const<Schedule *> schedule,
|
const TaskTag tag, Schedule *schedule,
|
||||||
Const<Priority> priority) -> void {
|
const Priority priority) -> void {
|
||||||
ensure(!s_schedule_workers.empty(),
|
ensure(!s_schedule_workers.empty(),
|
||||||
"Scheduler must be initialized before calling schedule_task");
|
"Scheduler must be initialized before calling schedule_task");
|
||||||
|
|
||||||
schedule->counter.fetch_add(1);
|
schedule->counter.fetch_add(1);
|
||||||
{
|
{
|
||||||
Const<std::lock_guard<std::mutex>> lock(s_queue_mutex);
|
const std::lock_guard<std::mutex> lock(s_queue_mutex);
|
||||||
if (priority == Priority::High) {
|
if (priority == Priority::High) {
|
||||||
s_high_priority_queue.emplace_back(
|
s_high_priority_queue.emplace_back(
|
||||||
ScheduledTask{tag, schedule, std::move(task)});
|
ScheduledTask{tag, schedule, std::move(task)});
|
||||||
@ -84,8 +84,8 @@ auto AsyncOps::schedule_task(Mut<std::function<void(WorkerId worker_id)>> task,
|
|||||||
s_wake_condition.notify_one();
|
s_wake_condition.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AsyncOps::cancel_tasks_of_tag(Const<TaskTag> tag) -> void {
|
auto AsyncOps::cancel_tasks_of_tag(const TaskTag tag) -> void {
|
||||||
Const<std::lock_guard<std::mutex>> lock(s_queue_mutex);
|
const std::lock_guard<std::mutex> lock(s_queue_mutex);
|
||||||
|
|
||||||
{
|
{
|
||||||
MutRef<std::deque<ScheduledTask>> queue = s_high_priority_queue;
|
MutRef<std::deque<ScheduledTask>> queue = s_high_priority_queue;
|
||||||
@ -120,8 +120,7 @@ auto AsyncOps::cancel_tasks_of_tag(Const<TaskTag> tag) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AsyncOps::wait_for_schedule_completion(Const<Schedule *> schedule)
|
auto AsyncOps::wait_for_schedule_completion(Schedule *schedule) -> void {
|
||||||
-> void {
|
|
||||||
ensure(!s_schedule_workers.empty(), "Scheduler must be initialized before "
|
ensure(!s_schedule_workers.empty(), "Scheduler must be initialized before "
|
||||||
"calling wait_for_schedule_completion");
|
"calling wait_for_schedule_completion");
|
||||||
|
|
||||||
@ -147,7 +146,7 @@ auto AsyncOps::wait_for_schedule_completion(Const<Schedule *> schedule)
|
|||||||
task.schedule_handle->counter.notify_all();
|
task.schedule_handle->counter.notify_all();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Const<u32> current_val = schedule->counter.load();
|
const u32 current_val = schedule->counter.load();
|
||||||
if (current_val > 0) {
|
if (current_val > 0) {
|
||||||
schedule->counter.wait(current_val);
|
schedule->counter.wait(current_val);
|
||||||
}
|
}
|
||||||
@ -159,8 +158,8 @@ auto AsyncOps::get_worker_count() -> WorkerId {
|
|||||||
return static_cast<WorkerId>(s_schedule_workers.size());
|
return static_cast<WorkerId>(s_schedule_workers.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AsyncOps::schedule_worker_loop(Const<std::stop_token> stop_token,
|
auto AsyncOps::schedule_worker_loop(const std::stop_token stop_token,
|
||||||
Const<WorkerId> worker_id) -> void {
|
const WorkerId worker_id) -> void {
|
||||||
while (!stop_token.stop_requested()) {
|
while (!stop_token.stop_requested()) {
|
||||||
Mut<ScheduledTask> task;
|
Mut<ScheduledTask> task;
|
||||||
Mut<bool> found_task = false;
|
Mut<bool> found_task = false;
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
#include <IACore/CLI.hpp>
|
#include <IACore/CLI.hpp>
|
||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
CLIParser::CLIParser(Const<Span<Const<String>>> args) : m_arg_list(args) {
|
CLIParser::CLIParser(const Span<const String> args) : m_arg_list(args) {
|
||||||
m_current_arg = m_arg_list.begin();
|
m_current_arg = m_arg_list.begin();
|
||||||
|
|
||||||
// Skip executable path
|
// Skip executable path
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] inline auto read_unaligned(Const<Const<u8> *> ptr) -> T {
|
[[nodiscard]] inline auto read_unaligned(const u8 *ptr) -> T {
|
||||||
Mut<T> v;
|
Mut<T> v;
|
||||||
std::memcpy(&v, ptr, sizeof(T));
|
std::memcpy(&v, ptr, sizeof(T));
|
||||||
return v;
|
return v;
|
||||||
@ -41,7 +41,7 @@ struct Crc32Tables {
|
|||||||
Mut<u32> table[8][256] = {};
|
Mut<u32> table[8][256] = {};
|
||||||
|
|
||||||
consteval Crc32Tables() {
|
consteval Crc32Tables() {
|
||||||
constexpr Const<u32> T = 0x82F63B78;
|
constexpr const u32 T = 0x82F63B78;
|
||||||
|
|
||||||
for (Mut<u32> i = 0; i < 256; i++) {
|
for (Mut<u32> i = 0; i < 256; i++) {
|
||||||
Mut<u32> crc = i;
|
Mut<u32> crc = i;
|
||||||
@ -53,24 +53,24 @@ struct Crc32Tables {
|
|||||||
|
|
||||||
for (Mut<i32> i = 0; i < 256; i++) {
|
for (Mut<i32> i = 0; i < 256; i++) {
|
||||||
for (Mut<i32> slice = 1; slice < 8; slice++) {
|
for (Mut<i32> slice = 1; slice < 8; slice++) {
|
||||||
Const<u32> prev = table[slice - 1][i];
|
const u32 prev = table[slice - 1][i];
|
||||||
table[slice][i] = (prev >> 8) ^ table[0][prev & 0xFF];
|
table[slice][i] = (prev >> 8) ^ table[0][prev & 0xFF];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Const<Crc32Tables> CRC32_TABLES{};
|
static constexpr const Crc32Tables CRC32_TABLES{};
|
||||||
|
|
||||||
#if IA_ARCH_X64
|
#if IA_ARCH_X64
|
||||||
inline auto crc32_x64_hw(Ref<Span<Const<u8>>> data) -> u32 {
|
inline auto crc32_x64_hw(Ref<Span<const u8>> data) -> u32 {
|
||||||
Mut<const u8 *> p = data.data();
|
Mut<const u8 *> p = data.data();
|
||||||
|
|
||||||
Mut<u32> crc = 0xFFFFFFFF;
|
Mut<u32> crc = 0xFFFFFFFF;
|
||||||
Mut<usize> len = data.size();
|
Mut<usize> len = data.size();
|
||||||
|
|
||||||
while (len >= 8) {
|
while (len >= 8) {
|
||||||
Const<u64> chunk = read_unaligned<u64>(p);
|
const u64 chunk = read_unaligned<u64>(p);
|
||||||
crc = static_cast<u32>(_mm_crc32_u64(static_cast<u64>(crc), chunk));
|
crc = static_cast<u32>(_mm_crc32_u64(static_cast<u64>(crc), chunk));
|
||||||
p += 8;
|
p += 8;
|
||||||
len -= 8;
|
len -= 8;
|
||||||
@ -86,14 +86,14 @@ inline auto crc32_x64_hw(Ref<Span<Const<u8>>> data) -> u32 {
|
|||||||
|
|
||||||
#if IA_ARCH_ARM64
|
#if IA_ARCH_ARM64
|
||||||
__attribute__((target("+crc"))) inline auto
|
__attribute__((target("+crc"))) inline auto
|
||||||
crc32_arm64_hw(Ref<Span<Const<u8>>> data) -> u32 {
|
crc32_arm64_hw(Ref<Span<const u8>> data) -> u32 {
|
||||||
Mut<const u8 *> p = data.data();
|
Mut<const u8 *> p = data.data();
|
||||||
|
|
||||||
Mut<u32> crc = 0xFFFFFFFF;
|
Mut<u32> crc = 0xFFFFFFFF;
|
||||||
Mut<usize> len = data.size();
|
Mut<usize> len = data.size();
|
||||||
|
|
||||||
while (len >= 8) {
|
while (len >= 8) {
|
||||||
Const<u64> chunk = read_unaligned<u64>(p);
|
const u64 chunk = read_unaligned<u64>(p);
|
||||||
crc = __crc32cd(crc, chunk);
|
crc = __crc32cd(crc, chunk);
|
||||||
p += 8;
|
p += 8;
|
||||||
len -= 8;
|
len -= 8;
|
||||||
@ -107,14 +107,14 @@ crc32_arm64_hw(Ref<Span<Const<u8>>> data) -> u32 {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline auto crc32_software_slice8(Ref<Span<Const<u8>>> data) -> u32 {
|
inline auto crc32_software_slice8(Ref<Span<const u8>> data) -> u32 {
|
||||||
Mut<const u8 *> p = data.data();
|
Mut<const u8 *> p = data.data();
|
||||||
Mut<u32> crc = 0xFFFFFFFF;
|
Mut<u32> crc = 0xFFFFFFFF;
|
||||||
Mut<usize> len = data.size();
|
Mut<usize> len = data.size();
|
||||||
|
|
||||||
while (len >= 8) {
|
while (len >= 8) {
|
||||||
Const<u32> term1 = crc ^ read_unaligned<u32>(p);
|
const u32 term1 = crc ^ read_unaligned<u32>(p);
|
||||||
Const<u32> term2 = read_unaligned<u32>(p + 4);
|
const u32 term2 = read_unaligned<u32>(p + 4);
|
||||||
|
|
||||||
crc = CRC32_TABLES.table[7][term1 & 0xFF] ^
|
crc = CRC32_TABLES.table[7][term1 & 0xFF] ^
|
||||||
CRC32_TABLES.table[6][(term1 >> 8) & 0xFF] ^
|
CRC32_TABLES.table[6][(term1 >> 8) & 0xFF] ^
|
||||||
@ -136,7 +136,7 @@ inline auto crc32_software_slice8(Ref<Span<Const<u8>>> data) -> u32 {
|
|||||||
return ~crc;
|
return ~crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::crc32(Ref<Span<Const<u8>>> data) -> u32 {
|
auto DataOps::crc32(Ref<Span<const u8>> data) -> u32 {
|
||||||
#if IA_ARCH_X64
|
#if IA_ARCH_X64
|
||||||
// IACore mandates AVX2 so no need to check
|
// IACore mandates AVX2 so no need to check
|
||||||
return crc32_x64_hw(data);
|
return crc32_x64_hw(data);
|
||||||
@ -148,33 +148,32 @@ auto DataOps::crc32(Ref<Span<Const<u8>>> data) -> u32 {
|
|||||||
return crc32_software_slice8(data);
|
return crc32_software_slice8(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Const<u32> XXH_PRIME32_1 = 0x9E3779B1U;
|
constexpr const u32 XXH_PRIME32_1 = 0x9E3779B1U;
|
||||||
constexpr Const<u32> XXH_PRIME32_2 = 0x85EBCA77U;
|
constexpr const u32 XXH_PRIME32_2 = 0x85EBCA77U;
|
||||||
constexpr Const<u32> XXH_PRIME32_3 = 0xC2B2AE3DU;
|
constexpr const u32 XXH_PRIME32_3 = 0xC2B2AE3DU;
|
||||||
constexpr Const<u32> XXH_PRIME32_4 = 0x27D4EB2FU;
|
constexpr const u32 XXH_PRIME32_4 = 0x27D4EB2FU;
|
||||||
constexpr Const<u32> XXH_PRIME32_5 = 0x165667B1U;
|
constexpr const u32 XXH_PRIME32_5 = 0x165667B1U;
|
||||||
|
|
||||||
inline auto xxh32_round(Mut<u32> seed, Const<u32> input) -> u32 {
|
inline auto xxh32_round(Mut<u32> seed, const u32 input) -> u32 {
|
||||||
seed += input * XXH_PRIME32_2;
|
seed += input * XXH_PRIME32_2;
|
||||||
seed = std::rotl(seed, 13);
|
seed = std::rotl(seed, 13);
|
||||||
seed *= XXH_PRIME32_1;
|
seed *= XXH_PRIME32_1;
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::hash_xxhash(Ref<String> string, Const<u32> seed) -> u32 {
|
auto DataOps::hash_xxhash(Ref<String> string, const u32 seed) -> u32 {
|
||||||
return hash_xxhash(
|
return hash_xxhash(Span<const u8>(reinterpret_cast<const u8 *>(string.data()),
|
||||||
Span<Const<u8>>(reinterpret_cast<const u8 *>(string.data()),
|
|
||||||
string.length()),
|
string.length()),
|
||||||
seed);
|
seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::hash_xxhash(Ref<Span<Const<u8>>> data, Const<u32> seed) -> u32 {
|
auto DataOps::hash_xxhash(Ref<Span<const u8>> data, const u32 seed) -> u32 {
|
||||||
Mut<const u8 *> p = data.data();
|
Mut<const u8 *> p = data.data();
|
||||||
Const<const u8 *> b_end = p + data.size();
|
const u8 *b_end = p + data.size();
|
||||||
Mut<u32> h32{};
|
Mut<u32> h32{};
|
||||||
|
|
||||||
if (data.size() >= 16) {
|
if (data.size() >= 16) {
|
||||||
Const<const u8 *> limit = b_end - 16;
|
const u8 *limit = b_end - 16;
|
||||||
|
|
||||||
Mut<u32> v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
Mut<u32> v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
|
||||||
Mut<u32> v2 = seed + XXH_PRIME32_2;
|
Mut<u32> v2 = seed + XXH_PRIME32_2;
|
||||||
@ -201,7 +200,7 @@ auto DataOps::hash_xxhash(Ref<Span<Const<u8>>> data, Const<u32> seed) -> u32 {
|
|||||||
h32 += static_cast<u32>(data.size());
|
h32 += static_cast<u32>(data.size());
|
||||||
|
|
||||||
while (p + 4 <= b_end) {
|
while (p + 4 <= b_end) {
|
||||||
Const<u32> t = read_unaligned<u32>(p) * XXH_PRIME32_3;
|
const u32 t = read_unaligned<u32>(p) * XXH_PRIME32_3;
|
||||||
h32 += t;
|
h32 += t;
|
||||||
h32 = std::rotl(h32, 17) * XXH_PRIME32_4;
|
h32 = std::rotl(h32, 17) * XXH_PRIME32_4;
|
||||||
p += 4;
|
p += 4;
|
||||||
@ -221,21 +220,21 @@ auto DataOps::hash_xxhash(Ref<Span<Const<u8>>> data, Const<u32> seed) -> u32 {
|
|||||||
return h32;
|
return h32;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Const<u32> FNV1A_32_PRIME = 0x01000193;
|
constexpr const u32 FNV1A_32_PRIME = 0x01000193;
|
||||||
constexpr Const<u32> FNV1A_32_OFFSET = 0x811c9dc5;
|
constexpr const u32 FNV1A_32_OFFSET = 0x811c9dc5;
|
||||||
|
|
||||||
auto DataOps::hash_fnv1a(Ref<String> string) -> u32 {
|
auto DataOps::hash_fnv1a(Ref<String> string) -> u32 {
|
||||||
Mut<u32> hash = FNV1A_32_OFFSET;
|
Mut<u32> hash = FNV1A_32_OFFSET;
|
||||||
for (Const<char> c : string) {
|
for (const char c : string) {
|
||||||
hash ^= static_cast<u8>(c);
|
hash ^= static_cast<u8>(c);
|
||||||
hash *= FNV1A_32_PRIME;
|
hash *= FNV1A_32_PRIME;
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::hash_fnv1a(Ref<Span<Const<u8>>> data) -> u32 {
|
auto DataOps::hash_fnv1a(Ref<Span<const u8>> data) -> u32 {
|
||||||
Mut<u32> hash = FNV1A_32_OFFSET;
|
Mut<u32> hash = FNV1A_32_OFFSET;
|
||||||
Const<const u8 *> ptr = data.data();
|
const u8 *ptr = data.data();
|
||||||
|
|
||||||
for (Mut<usize> i = 0; i < data.size(); ++i) {
|
for (Mut<usize> i = 0; i < data.size(); ++i) {
|
||||||
hash ^= ptr[i];
|
hash ^= ptr[i];
|
||||||
@ -244,8 +243,7 @@ auto DataOps::hash_fnv1a(Ref<Span<Const<u8>>> data) -> u32 {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::detect_compression(Const<Span<Const<u8>>> data)
|
auto DataOps::detect_compression(const Span<const u8> data) -> CompressionType {
|
||||||
-> CompressionType {
|
|
||||||
if (data.size() < 2) {
|
if (data.size() < 2) {
|
||||||
return CompressionType::None;
|
return CompressionType::None;
|
||||||
}
|
}
|
||||||
@ -262,7 +260,7 @@ auto DataOps::detect_compression(Const<Span<Const<u8>>> data)
|
|||||||
return CompressionType::None;
|
return CompressionType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::zlib_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
auto DataOps::zlib_inflate(Ref<Span<const u8>> data) -> Result<Vec<u8>> {
|
||||||
Mut<z_stream> zs{};
|
Mut<z_stream> zs{};
|
||||||
zs.zalloc = Z_NULL;
|
zs.zalloc = Z_NULL;
|
||||||
zs.zfree = Z_NULL;
|
zs.zfree = Z_NULL;
|
||||||
@ -276,7 +274,7 @@ auto DataOps::zlib_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
zs.avail_in = static_cast<uInt>(data.size());
|
zs.avail_in = static_cast<uInt>(data.size());
|
||||||
|
|
||||||
Mut<Vec<u8>> out_buffer;
|
Mut<Vec<u8>> out_buffer;
|
||||||
Const<usize> guess_size =
|
const usize guess_size =
|
||||||
data.size() < 1024 ? data.size() * 4 : data.size() * 2;
|
data.size() < 1024 ? data.size() * 4 : data.size() * 2;
|
||||||
out_buffer.resize(guess_size);
|
out_buffer.resize(guess_size);
|
||||||
|
|
||||||
@ -286,8 +284,8 @@ auto DataOps::zlib_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
Mut<int> ret;
|
Mut<int> ret;
|
||||||
do {
|
do {
|
||||||
if (zs.avail_out == 0) {
|
if (zs.avail_out == 0) {
|
||||||
Const<usize> current_pos = zs.total_out;
|
const usize current_pos = zs.total_out;
|
||||||
Const<usize> new_size = out_buffer.size() * 2;
|
const usize new_size = out_buffer.size() * 2;
|
||||||
out_buffer.resize(new_size);
|
out_buffer.resize(new_size);
|
||||||
|
|
||||||
zs.next_out = reinterpret_cast<Bytef *>(out_buffer.data() + current_pos);
|
zs.next_out = reinterpret_cast<Bytef *>(out_buffer.data() + current_pos);
|
||||||
@ -309,7 +307,7 @@ auto DataOps::zlib_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
return out_buffer;
|
return out_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::zlib_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
auto DataOps::zlib_deflate(Ref<Span<const u8>> data) -> Result<Vec<u8>> {
|
||||||
Mut<z_stream> zs{};
|
Mut<z_stream> zs{};
|
||||||
zs.zalloc = Z_NULL;
|
zs.zalloc = Z_NULL;
|
||||||
zs.zfree = Z_NULL;
|
zs.zfree = Z_NULL;
|
||||||
@ -328,7 +326,7 @@ auto DataOps::zlib_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
zs.next_out = reinterpret_cast<Bytef *>(out_buffer.data());
|
zs.next_out = reinterpret_cast<Bytef *>(out_buffer.data());
|
||||||
zs.avail_out = static_cast<uInt>(out_buffer.size());
|
zs.avail_out = static_cast<uInt>(out_buffer.size());
|
||||||
|
|
||||||
Const<int> ret = deflate(&zs, Z_FINISH);
|
const int ret = deflate(&zs, Z_FINISH);
|
||||||
|
|
||||||
if (ret != Z_STREAM_END) {
|
if (ret != Z_STREAM_END) {
|
||||||
deflateEnd(&zs);
|
deflateEnd(&zs);
|
||||||
@ -341,8 +339,8 @@ auto DataOps::zlib_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
return out_buffer;
|
return out_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::zstd_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
auto DataOps::zstd_inflate(Ref<Span<const u8>> data) -> Result<Vec<u8>> {
|
||||||
Const<unsigned long long> content_size =
|
const unsigned long long content_size =
|
||||||
ZSTD_getFrameContentSize(data.data(), data.size());
|
ZSTD_getFrameContentSize(data.data(), data.size());
|
||||||
|
|
||||||
if (content_size == ZSTD_CONTENTSIZE_ERROR) {
|
if (content_size == ZSTD_CONTENTSIZE_ERROR) {
|
||||||
@ -353,7 +351,7 @@ auto DataOps::zstd_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
Mut<Vec<u8>> out_buffer;
|
Mut<Vec<u8>> out_buffer;
|
||||||
out_buffer.resize(static_cast<usize>(content_size));
|
out_buffer.resize(static_cast<usize>(content_size));
|
||||||
|
|
||||||
Const<usize> d_size = ZSTD_decompress(out_buffer.data(), out_buffer.size(),
|
const usize d_size = ZSTD_decompress(out_buffer.data(), out_buffer.size(),
|
||||||
data.data(), data.size());
|
data.data(), data.size());
|
||||||
|
|
||||||
if (ZSTD_isError(d_size)) {
|
if (ZSTD_isError(d_size)) {
|
||||||
@ -380,7 +378,7 @@ auto DataOps::zstd_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (output.pos == output.size) {
|
if (output.pos == output.size) {
|
||||||
Const<usize> new_size = out_buffer.size() * 2;
|
const usize new_size = out_buffer.size() * 2;
|
||||||
out_buffer.resize(new_size);
|
out_buffer.resize(new_size);
|
||||||
output.dst = out_buffer.data();
|
output.dst = out_buffer.data();
|
||||||
output.size = new_size;
|
output.size = new_size;
|
||||||
@ -394,13 +392,13 @@ auto DataOps::zstd_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
return out_buffer;
|
return out_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::zstd_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
auto DataOps::zstd_deflate(Ref<Span<const u8>> data) -> Result<Vec<u8>> {
|
||||||
Const<usize> max_dst_size = ZSTD_compressBound(data.size());
|
const usize max_dst_size = ZSTD_compressBound(data.size());
|
||||||
|
|
||||||
Mut<Vec<u8>> out_buffer;
|
Mut<Vec<u8>> out_buffer;
|
||||||
out_buffer.resize(max_dst_size);
|
out_buffer.resize(max_dst_size);
|
||||||
|
|
||||||
Const<usize> compressed_size = ZSTD_compress(out_buffer.data(), max_dst_size,
|
const usize compressed_size = ZSTD_compress(out_buffer.data(), max_dst_size,
|
||||||
data.data(), data.size(), 3);
|
data.data(), data.size(), 3);
|
||||||
|
|
||||||
if (ZSTD_isError(compressed_size)) {
|
if (ZSTD_isError(compressed_size)) {
|
||||||
@ -411,7 +409,7 @@ auto DataOps::zstd_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
return out_buffer;
|
return out_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::gzip_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
auto DataOps::gzip_deflate(Ref<Span<const u8>> data) -> Result<Vec<u8>> {
|
||||||
Mut<z_stream> zs{};
|
Mut<z_stream> zs{};
|
||||||
zs.zalloc = Z_NULL;
|
zs.zalloc = Z_NULL;
|
||||||
zs.zfree = Z_NULL;
|
zs.zfree = Z_NULL;
|
||||||
@ -432,7 +430,7 @@ auto DataOps::gzip_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
zs.next_out = reinterpret_cast<Bytef *>(out_buffer.data());
|
zs.next_out = reinterpret_cast<Bytef *>(out_buffer.data());
|
||||||
zs.avail_out = static_cast<uInt>(out_buffer.size());
|
zs.avail_out = static_cast<uInt>(out_buffer.size());
|
||||||
|
|
||||||
Const<int> ret = deflate(&zs, Z_FINISH);
|
const int ret = deflate(&zs, Z_FINISH);
|
||||||
|
|
||||||
if (ret != Z_STREAM_END) {
|
if (ret != Z_STREAM_END) {
|
||||||
deflateEnd(&zs);
|
deflateEnd(&zs);
|
||||||
@ -445,7 +443,7 @@ auto DataOps::gzip_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
|||||||
return out_buffer;
|
return out_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DataOps::gzip_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>> {
|
auto DataOps::gzip_inflate(Ref<Span<const u8>> data) -> Result<Vec<u8>> {
|
||||||
return zlib_inflate(data);
|
return zlib_inflate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,36 +29,36 @@ namespace IACore {
|
|||||||
Mut<HashMap<const u8 *, std::tuple<void *, void *, void *>>>
|
Mut<HashMap<const u8 *, std::tuple<void *, void *, void *>>>
|
||||||
FileOps::s_mapped_files;
|
FileOps::s_mapped_files;
|
||||||
|
|
||||||
auto FileOps::unmap_file(Const<Const<u8> *> mapped_ptr) -> void {
|
auto FileOps::unmap_file(const u8 *mapped_ptr) -> void {
|
||||||
if (!s_mapped_files.contains(mapped_ptr)) {
|
if (!s_mapped_files.contains(mapped_ptr)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mut<decltype(s_mapped_files)::iterator> it = s_mapped_files.find(mapped_ptr);
|
Mut<decltype(s_mapped_files)::iterator> it = s_mapped_files.find(mapped_ptr);
|
||||||
Const<std::tuple<void *, void *, void *>> handles = it->second;
|
const std::tuple<void *, void *, void *> handles = it->second;
|
||||||
s_mapped_files.erase(it);
|
s_mapped_files.erase(it);
|
||||||
|
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
::UnmapViewOfFile(std::get<1>(handles));
|
::UnmapViewOfFile(std::get<1>(handles));
|
||||||
::CloseHandle(static_cast<HANDLE>(std::get<2>(handles)));
|
::CloseHandle(static_cast<HANDLE>(std::get<2>(handles)));
|
||||||
|
|
||||||
Const<HANDLE> handle = static_cast<HANDLE>(std::get<0>(handles));
|
const HANDLE handle = static_cast<HANDLE>(std::get<0>(handles));
|
||||||
if (handle != INVALID_HANDLE_VALUE) {
|
if (handle != INVALID_HANDLE_VALUE) {
|
||||||
::CloseHandle(handle);
|
::CloseHandle(handle);
|
||||||
}
|
}
|
||||||
#elif IA_PLATFORM_UNIX
|
#elif IA_PLATFORM_UNIX
|
||||||
::munmap(std::get<1>(handles), (usize)std::get<2>(handles));
|
::munmap(std::get<1>(handles), (usize)std::get<2>(handles));
|
||||||
Const<i32> fd = (i32)((u64)std::get<0>(handles));
|
const i32 fd = (i32)((u64)std::get<0>(handles));
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
::close(fd);
|
::close(fd);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::map_shared_memory(Ref<String> name, Const<usize> size,
|
auto FileOps::map_shared_memory(Ref<String> name, const usize size,
|
||||||
Const<bool> is_owner) -> Result<u8 *> {
|
const bool is_owner) -> Result<u8 *> {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Const<int> wchars_num =
|
const int wchars_num =
|
||||||
MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, NULL, 0);
|
MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, NULL, 0);
|
||||||
Mut<std::wstring> w_name(wchars_num, 0);
|
Mut<std::wstring> w_name(wchars_num, 0);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, &w_name[0], wchars_num);
|
MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, &w_name[0], wchars_num);
|
||||||
@ -135,7 +135,7 @@ auto FileOps::unlink_shared_memory(Ref<String> name) -> void {
|
|||||||
auto FileOps::map_file(Ref<Path> path, MutRef<usize> size)
|
auto FileOps::map_file(Ref<Path> path, MutRef<usize> size)
|
||||||
-> Result<const u8 *> {
|
-> Result<const u8 *> {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Const<HANDLE> handle = CreateFileA(
|
const HANDLE handle = CreateFileA(
|
||||||
path.string().c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
path.string().c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ auto FileOps::map_file(Ref<Path> path, MutRef<usize> size)
|
|||||||
return fail("Failed to memory map {}", path.string());
|
return fail("Failed to memory map {}", path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u8> *result =
|
const u8 *result =
|
||||||
static_cast<const u8 *>(MapViewOfFile(h_map, FILE_MAP_READ, 0, 0, 0));
|
static_cast<const u8 *>(MapViewOfFile(h_map, FILE_MAP_READ, 0, 0, 0));
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
@ -173,7 +173,7 @@ auto FileOps::map_file(Ref<Path> path, MutRef<usize> size)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
#elif IA_PLATFORM_UNIX
|
#elif IA_PLATFORM_UNIX
|
||||||
Const<int> handle = open(path.string().c_str(), O_RDONLY);
|
const int handle = open(path.string().c_str(), O_RDONLY);
|
||||||
if (handle == -1) {
|
if (handle == -1) {
|
||||||
return fail("Failed to open {} for memory mapping", path.string());
|
return fail("Failed to open {} for memory mapping", path.string());
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ auto FileOps::map_file(Ref<Path> path, MutRef<usize> size)
|
|||||||
close(handle);
|
close(handle);
|
||||||
return fail("Failed to memory map {}", path.string());
|
return fail("Failed to memory map {}", path.string());
|
||||||
}
|
}
|
||||||
Const<Const<u8> *> result = static_cast<const u8 *>(addr);
|
const u8 *result = static_cast<const u8 *>(addr);
|
||||||
madvise(addr, size, MADV_SEQUENTIAL);
|
madvise(addr, size, MADV_SEQUENTIAL);
|
||||||
s_mapped_files[result] =
|
s_mapped_files[result] =
|
||||||
std::make_tuple((void *)((u64)handle), (void *)addr, (void *)size);
|
std::make_tuple((void *)((u64)handle), (void *)addr, (void *)size);
|
||||||
@ -200,7 +200,7 @@ auto FileOps::map_file(Ref<Path> path, MutRef<usize> size)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::stream_to_file(Ref<Path> path, Const<bool> overwrite)
|
auto FileOps::stream_to_file(Ref<Path> path, const bool overwrite)
|
||||||
-> Result<StreamWriter> {
|
-> Result<StreamWriter> {
|
||||||
if (!overwrite && std::filesystem::exists(path)) {
|
if (!overwrite && std::filesystem::exists(path)) {
|
||||||
return fail("File already exists: {}", path.string());
|
return fail("File already exists: {}", path.string());
|
||||||
@ -222,7 +222,7 @@ auto FileOps::read_text_file(Ref<Path> path) -> Result<String> {
|
|||||||
}
|
}
|
||||||
Mut<String> result;
|
Mut<String> result;
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
Const<long> len = ftell(f);
|
const long len = ftell(f);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
result.resize(static_cast<usize>(len));
|
result.resize(static_cast<usize>(len));
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
@ -239,7 +239,7 @@ auto FileOps::read_binary_file(Ref<Path> path) -> Result<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
Mut<Vec<u8>> result;
|
Mut<Vec<u8>> result;
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
Const<long> len = ftell(f);
|
const long len = ftell(f);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
result.resize(static_cast<usize>(len));
|
result.resize(static_cast<usize>(len));
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
@ -250,8 +250,8 @@ auto FileOps::read_binary_file(Ref<Path> path) -> Result<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::write_text_file(Ref<Path> path, Ref<String> contents,
|
auto FileOps::write_text_file(Ref<Path> path, Ref<String> contents,
|
||||||
Const<bool> overwrite) -> Result<usize> {
|
const bool overwrite) -> Result<usize> {
|
||||||
Const<Const<char> *> mode = overwrite ? "w" : "wx";
|
const char *mode = overwrite ? "w" : "wx";
|
||||||
Mut<FILE *> f = fopen(path.string().c_str(), mode);
|
Mut<FILE *> f = fopen(path.string().c_str(), mode);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
if (!overwrite && errno == EEXIST) {
|
if (!overwrite && errno == EEXIST) {
|
||||||
@ -259,14 +259,14 @@ auto FileOps::write_text_file(Ref<Path> path, Ref<String> contents,
|
|||||||
}
|
}
|
||||||
return fail("Failed to write to file: {}", path.string());
|
return fail("Failed to write to file: {}", path.string());
|
||||||
}
|
}
|
||||||
Const<usize> result = fwrite(contents.data(), 1, contents.size(), f);
|
const usize result = fwrite(contents.data(), 1, contents.size(), f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::write_binary_file(Ref<Path> path, Const<Span<Const<u8>>> contents,
|
auto FileOps::write_binary_file(Ref<Path> path, const Span<const u8> contents,
|
||||||
Const<bool> overwrite) -> Result<usize> {
|
const bool overwrite) -> Result<usize> {
|
||||||
Const<Const<char> *> mode = overwrite ? "w" : "wx";
|
const char *mode = overwrite ? "w" : "wx";
|
||||||
Mut<FILE *> f = fopen(path.string().c_str(), mode);
|
Mut<FILE *> f = fopen(path.string().c_str(), mode);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
if (!overwrite && errno == EEXIST) {
|
if (!overwrite && errno == EEXIST) {
|
||||||
@ -274,7 +274,7 @@ auto FileOps::write_binary_file(Ref<Path> path, Const<Span<Const<u8>>> contents,
|
|||||||
}
|
}
|
||||||
return fail("Failed to write to file: {}", path.string());
|
return fail("Failed to write to file: {}", path.string());
|
||||||
}
|
}
|
||||||
Const<usize> result = fwrite(contents.data(), 1, contents.size(), f);
|
const usize result = fwrite(contents.data(), 1, contents.size(), f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -301,8 +301,8 @@ auto FileOps::normalize_executable_path(Ref<Path> path) -> Path {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::native_open_file(Ref<Path> path, Const<FileAccess> access,
|
auto FileOps::native_open_file(Ref<Path> path, const FileAccess access,
|
||||||
Const<FileMode> mode, Const<u32> permissions)
|
const FileMode mode, const u32 permissions)
|
||||||
-> Result<NativeFileHandle> {
|
-> Result<NativeFileHandle> {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Mut<DWORD> dw_access = 0;
|
Mut<DWORD> dw_access = 0;
|
||||||
@ -392,7 +392,7 @@ auto FileOps::native_open_file(Ref<Path> path, Const<FileAccess> access,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::native_close_file(Const<NativeFileHandle> handle) -> void {
|
auto FileOps::native_close_file(const NativeFileHandle handle) -> void {
|
||||||
if (handle == INVALID_FILE_HANDLE) {
|
if (handle == INVALID_FILE_HANDLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -428,8 +428,8 @@ auto FileOps::MemoryMappedRegion::operator=(
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FileOps::MemoryMappedRegion::map(Const<NativeFileHandle> handle,
|
auto FileOps::MemoryMappedRegion::map(const NativeFileHandle handle,
|
||||||
Const<u64> offset, Const<usize> size)
|
const u64 offset, const usize size)
|
||||||
-> Result<void> {
|
-> Result<void> {
|
||||||
unmap();
|
unmap();
|
||||||
|
|
||||||
@ -447,7 +447,7 @@ auto FileOps::MemoryMappedRegion::map(Const<NativeFileHandle> handle,
|
|||||||
return fail("Failed to get file size");
|
return fail("Failed to get file size");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u64> end_offset = offset + size;
|
const u64 end_offset = offset + size;
|
||||||
if (static_cast<u64>(file_size.QuadPart) < end_offset) {
|
if (static_cast<u64>(file_size.QuadPart) < end_offset) {
|
||||||
Mut<LARGE_INTEGER> new_size;
|
Mut<LARGE_INTEGER> new_size;
|
||||||
new_size.QuadPart = static_cast<LONGLONG>(end_offset);
|
new_size.QuadPart = static_cast<LONGLONG>(end_offset);
|
||||||
@ -465,8 +465,8 @@ auto FileOps::MemoryMappedRegion::map(Const<NativeFileHandle> handle,
|
|||||||
return fail("CreateFileMapping failed: {}", GetLastError());
|
return fail("CreateFileMapping failed: {}", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<DWORD> offset_high = static_cast<DWORD>(offset >> 32);
|
const DWORD offset_high = static_cast<DWORD>(offset >> 32);
|
||||||
Const<DWORD> offset_low = static_cast<DWORD>(offset & 0xFFFFFFFF);
|
const DWORD offset_low = static_cast<DWORD>(offset & 0xFFFFFFFF);
|
||||||
|
|
||||||
m_ptr = static_cast<u8 *>(MapViewOfFile(m_map_handle, FILE_MAP_WRITE,
|
m_ptr = static_cast<u8 *>(MapViewOfFile(m_map_handle, FILE_MAP_WRITE,
|
||||||
offset_high, offset_low, size));
|
offset_high, offset_low, size));
|
||||||
@ -484,7 +484,7 @@ auto FileOps::MemoryMappedRegion::map(Const<NativeFileHandle> handle,
|
|||||||
return fail("Failed to fstat file");
|
return fail("Failed to fstat file");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u64> end_offset = offset + size;
|
const u64 end_offset = offset + size;
|
||||||
if (static_cast<u64>(sb.st_size) < end_offset) {
|
if (static_cast<u64>(sb.st_size) < end_offset) {
|
||||||
if (ftruncate(handle, static_cast<off_t>(end_offset)) == -1) {
|
if (ftruncate(handle, static_cast<off_t>(end_offset)) == -1) {
|
||||||
return fail("Failed to ftruncate (extend) file");
|
return fail("Failed to ftruncate (extend) file");
|
||||||
|
|||||||
@ -21,8 +21,8 @@ auto HttpClient::create(Ref<String> host) -> Result<Box<HttpClient>> {
|
|||||||
return make_box_protected<HttpClient>(httplib::Client(host));
|
return make_box_protected<HttpClient>(httplib::Client(host));
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto build_headers(Span<Const<HttpClient::Header>> headers,
|
static auto build_headers(Span<const HttpClient::Header> headers,
|
||||||
Const<Const<char> *> default_content_type)
|
const char *default_content_type)
|
||||||
-> httplib::Headers {
|
-> httplib::Headers {
|
||||||
Mut<httplib::Headers> out;
|
Mut<httplib::Headers> out;
|
||||||
Mut<bool> has_content_type = false;
|
Mut<bool> has_content_type = false;
|
||||||
@ -59,26 +59,26 @@ auto HttpClient::disable_certificate_verification() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto HttpClient::preprocess_response(Ref<String> response) -> String {
|
auto HttpClient::preprocess_response(Ref<String> response) -> String {
|
||||||
Const<Span<Const<u8>>> response_bytes = {
|
const Span<const u8> response_bytes = {
|
||||||
reinterpret_cast<Const<u8> *>(response.data()), response.size()};
|
reinterpret_cast<const u8 *>(response.data()), response.size()};
|
||||||
Const<DataOps::CompressionType> compression =
|
const DataOps::CompressionType compression =
|
||||||
DataOps::detect_compression(response_bytes);
|
DataOps::detect_compression(response_bytes);
|
||||||
|
|
||||||
switch (compression) {
|
switch (compression) {
|
||||||
case DataOps::CompressionType::Gzip: {
|
case DataOps::CompressionType::Gzip: {
|
||||||
Const<Result<Vec<u8>>> data = DataOps::gzip_inflate(response_bytes);
|
const Result<Vec<u8>> data = DataOps::gzip_inflate(response_bytes);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
return String(reinterpret_cast<Const<char> *>(data->data()), data->size());
|
return String(reinterpret_cast<const char *>(data->data()), data->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
case DataOps::CompressionType::Zlib: {
|
case DataOps::CompressionType::Zlib: {
|
||||||
Const<Result<Vec<u8>>> data = DataOps::zlib_inflate(response_bytes);
|
const Result<Vec<u8>> data = DataOps::zlib_inflate(response_bytes);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
return String(reinterpret_cast<Const<char> *>(data->data()), data->size());
|
return String(reinterpret_cast<const char *>(data->data()), data->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
case DataOps::CompressionType::None:
|
case DataOps::CompressionType::None:
|
||||||
@ -88,10 +88,9 @@ auto HttpClient::preprocess_response(Ref<String> response) -> String {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpClient::raw_get(Ref<String> path, Span<Const<Header>> headers,
|
auto HttpClient::raw_get(Ref<String> path, Span<const Header> headers,
|
||||||
Const<Const<char> *> default_content_type)
|
const char *default_content_type) -> Result<String> {
|
||||||
-> Result<String> {
|
const httplib::Headers http_headers =
|
||||||
Const<httplib::Headers> http_headers =
|
|
||||||
build_headers(headers, default_content_type);
|
build_headers(headers, default_content_type);
|
||||||
|
|
||||||
Mut<String> adjusted_path = path;
|
Mut<String> adjusted_path = path;
|
||||||
@ -99,8 +98,7 @@ auto HttpClient::raw_get(Ref<String> path, Span<Const<Header>> headers,
|
|||||||
adjusted_path = "/" + path;
|
adjusted_path = "/" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<httplib::Result> res =
|
const httplib::Result res = m_client.Get(adjusted_path.c_str(), http_headers);
|
||||||
m_client.Get(adjusted_path.c_str(), http_headers);
|
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
m_last_response_code = static_cast<EResponseCode>(res->status);
|
m_last_response_code = static_cast<EResponseCode>(res->status);
|
||||||
@ -113,16 +111,15 @@ auto HttpClient::raw_get(Ref<String> path, Span<Const<Header>> headers,
|
|||||||
return fail("Network Error: {}", httplib::to_string(res.error()));
|
return fail("Network Error: {}", httplib::to_string(res.error()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpClient::raw_post(Ref<String> path, Span<Const<Header>> headers,
|
auto HttpClient::raw_post(Ref<String> path, Span<const Header> headers,
|
||||||
Ref<String> body,
|
Ref<String> body, const char *default_content_type)
|
||||||
Const<Const<char> *> default_content_type)
|
|
||||||
-> Result<String> {
|
-> Result<String> {
|
||||||
Mut<httplib::Headers> http_headers =
|
Mut<httplib::Headers> http_headers =
|
||||||
build_headers(headers, default_content_type);
|
build_headers(headers, default_content_type);
|
||||||
|
|
||||||
Mut<String> content_type = default_content_type;
|
Mut<String> content_type = default_content_type;
|
||||||
if (http_headers.count("Content-Type")) {
|
if (http_headers.count("Content-Type")) {
|
||||||
Const<httplib::Headers::iterator> t = http_headers.find("Content-Type");
|
const httplib::Headers::iterator t = http_headers.find("Content-Type");
|
||||||
content_type = t->second;
|
content_type = t->second;
|
||||||
http_headers.erase(t);
|
http_headers.erase(t);
|
||||||
}
|
}
|
||||||
@ -134,8 +131,8 @@ auto HttpClient::raw_post(Ref<String> path, Span<Const<Header>> headers,
|
|||||||
adjusted_path = "/" + path;
|
adjusted_path = "/" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<httplib::Result> res = m_client.Post(
|
const httplib::Result res = m_client.Post(adjusted_path.c_str(), http_headers,
|
||||||
adjusted_path.c_str(), http_headers, body, content_type.c_str());
|
body, content_type.c_str());
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
m_last_response_code = static_cast<EResponseCode>(res->status);
|
m_last_response_code = static_cast<EResponseCode>(res->status);
|
||||||
|
|||||||
@ -21,7 +21,7 @@ auto HttpCommon::url_encode(Ref<String> value) -> String {
|
|||||||
escaped.fill('0');
|
escaped.fill('0');
|
||||||
escaped << std::hex << std::uppercase;
|
escaped << std::hex << std::uppercase;
|
||||||
|
|
||||||
for (Const<char> c : value) {
|
for (const char c : value) {
|
||||||
if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' ||
|
if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' ||
|
||||||
c == '.' || c == '~')
|
c == '.' || c == '~')
|
||||||
escaped << c;
|
escaped << c;
|
||||||
@ -39,8 +39,8 @@ auto HttpCommon::url_decode(Ref<String> value) -> String {
|
|||||||
|
|
||||||
for (Mut<size_t> i = 0; i < value.length(); ++i) {
|
for (Mut<size_t> i = 0; i < value.length(); ++i) {
|
||||||
if (value[i] == '%' && i + 2 < value.length()) {
|
if (value[i] == '%' && i + 2 < value.length()) {
|
||||||
Const<std::string> hex_str = value.substr(i + 1, 2);
|
const std::string hex_str = value.substr(i + 1, 2);
|
||||||
Const<char> decoded_char =
|
const char decoded_char =
|
||||||
static_cast<char>(std::strtol(hex_str.c_str(), nullptr, 16));
|
static_cast<char>(std::strtol(hex_str.c_str(), nullptr, 16));
|
||||||
result += decoded_char;
|
result += decoded_char;
|
||||||
i += 2;
|
i += 2;
|
||||||
@ -53,7 +53,7 @@ auto HttpCommon::url_decode(Ref<String> value) -> String {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpCommon::header_type_to_string(Const<EHeaderType> type) -> String {
|
auto HttpCommon::header_type_to_string(const EHeaderType type) -> String {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EHeaderType::ACCEPT:
|
case EHeaderType::ACCEPT:
|
||||||
return "Accept";
|
return "Accept";
|
||||||
@ -111,7 +111,7 @@ auto HttpCommon::header_type_to_string(Const<EHeaderType> type) -> String {
|
|||||||
return "<Unknown>";
|
return "<Unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpCommon::is_success_response_code(Const<EResponseCode> code) -> bool {
|
auto HttpCommon::is_success_response_code(const EResponseCode code) -> bool {
|
||||||
return (i32)code >= 200 && (i32)code < 300;
|
return (i32)code >= 200 && (i32)code < 300;
|
||||||
}
|
}
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
@ -18,24 +18,21 @@
|
|||||||
namespace IACore {
|
namespace IACore {
|
||||||
|
|
||||||
auto HttpServer::Request::get_header(Ref<String> key) const -> String {
|
auto HttpServer::Request::get_header(Ref<String> key) const -> String {
|
||||||
if (Const<HashMap<String, String>::const_iterator> it = headers.find(key);
|
if (auto it = headers.find(key); it != headers.end()) {
|
||||||
it != headers.end()) {
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpServer::Request::get_param(Ref<String> key) const -> String {
|
auto HttpServer::Request::get_param(Ref<String> key) const -> String {
|
||||||
if (Const<HashMap<String, String>::const_iterator> it = params.find(key);
|
if (auto it = params.find(key); it != params.end()) {
|
||||||
it != params.end()) {
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpServer::Request::get_path_param(Ref<String> key) const -> String {
|
auto HttpServer::Request::get_path_param(Ref<String> key) const -> String {
|
||||||
if (Const<HashMap<String, String>::const_iterator> it = path_params.find(key);
|
if (auto it = path_params.find(key); it != path_params.end()) {
|
||||||
it != path_params.end()) {
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
@ -58,7 +55,7 @@ void HttpServer::Response::set_content(Ref<String> content, Ref<String> type) {
|
|||||||
content_type = type;
|
content_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::Response::set_status(Const<EResponseCode> status_code) {
|
void HttpServer::Response::set_status(const EResponseCode status_code) {
|
||||||
code = status_code;
|
code = status_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +75,7 @@ auto HttpServer::create() -> Result<Box<HttpServer>> {
|
|||||||
return make_box<PublicHttpServer>();
|
return make_box<PublicHttpServer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HttpServer::listen(Ref<String> host, Const<u32> port) -> Result<void> {
|
auto HttpServer::listen(Ref<String> host, const u32 port) -> Result<void> {
|
||||||
if (!m_server.listen(host.c_str(), static_cast<int>(port))) {
|
if (!m_server.listen(host.c_str(), static_cast<int>(port))) {
|
||||||
return fail("Failed to start HTTP server on {}:{}", host, port);
|
return fail("Failed to start HTTP server on {}:{}", host, port);
|
||||||
}
|
}
|
||||||
@ -94,8 +91,8 @@ void HttpServer::stop() {
|
|||||||
auto HttpServer::is_running() const -> bool { return m_server.is_running(); }
|
auto HttpServer::is_running() const -> bool { return m_server.is_running(); }
|
||||||
|
|
||||||
void HttpServer::register_handler(Ref<String> method, Ref<String> pattern,
|
void HttpServer::register_handler(Ref<String> method, Ref<String> pattern,
|
||||||
Const<Handler> handler) {
|
const Handler handler) {
|
||||||
Const<httplib::Server::Handler> wrapper =
|
const httplib::Server::Handler wrapper =
|
||||||
[handler](Ref<httplib::Request> req, MutRef<httplib::Response> res) {
|
[handler](Ref<httplib::Request> req, MutRef<httplib::Response> res) {
|
||||||
Mut<Request> ia_req;
|
Mut<Request> ia_req;
|
||||||
ia_req.path = req.path;
|
ia_req.path = req.path;
|
||||||
@ -138,23 +135,23 @@ void HttpServer::register_handler(Ref<String> method, Ref<String> pattern,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::get(Ref<String> pattern, Const<Handler> handler) {
|
void HttpServer::get(Ref<String> pattern, const Handler handler) {
|
||||||
register_handler("GET", pattern, handler);
|
register_handler("GET", pattern, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::post(Ref<String> pattern, Const<Handler> handler) {
|
void HttpServer::post(Ref<String> pattern, const Handler handler) {
|
||||||
register_handler("POST", pattern, handler);
|
register_handler("POST", pattern, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::put(Ref<String> pattern, Const<Handler> handler) {
|
void HttpServer::put(Ref<String> pattern, const Handler handler) {
|
||||||
register_handler("PUT", pattern, handler);
|
register_handler("PUT", pattern, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::del(Ref<String> pattern, Const<Handler> handler) {
|
void HttpServer::del(Ref<String> pattern, const Handler handler) {
|
||||||
register_handler("DELETE", pattern, handler);
|
register_handler("DELETE", pattern, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpServer::options(Ref<String> pattern, Const<Handler> handler) {
|
void HttpServer::options(Ref<String> pattern, const Handler handler) {
|
||||||
register_handler("OPTIONS", pattern, handler);
|
register_handler("OPTIONS", pattern, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ struct IpcConnectionDescriptor {
|
|||||||
shared_mem_size);
|
shared_mem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto deserialize(Const<StringView> data)
|
static auto deserialize(const StringView data)
|
||||||
-> Option<IpcConnectionDescriptor> {
|
-> Option<IpcConnectionDescriptor> {
|
||||||
enum class ParseState { SocketPath, SharedMemPath, SharedMemSize };
|
enum class ParseState { SocketPath, SharedMemPath, SharedMemSize };
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ struct IpcConnectionDescriptor {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ParseState::SharedMemSize: {
|
case ParseState::SharedMemSize: {
|
||||||
Const<const char *> start = data.data() + t;
|
const char *start = data.data() + t;
|
||||||
Const<const char *> end = data.data() + i;
|
const char *end = data.data() + i;
|
||||||
if (std::from_chars(start, end, result.shared_mem_size).ec !=
|
if (std::from_chars(start, end, result.shared_mem_size).ec !=
|
||||||
std::errc{}) {
|
std::errc{}) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@ -77,8 +77,8 @@ IpcNode::~IpcNode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IpcNode::connect(Const<const char *> connection_string) -> Result<void> {
|
auto IpcNode::connect(const char *connection_string) -> Result<void> {
|
||||||
Const<Option<IpcConnectionDescriptor>> desc_opt =
|
const Option<IpcConnectionDescriptor> desc_opt =
|
||||||
IpcConnectionDescriptor::deserialize(connection_string);
|
IpcConnectionDescriptor::deserialize(connection_string);
|
||||||
if (!desc_opt) {
|
if (!desc_opt) {
|
||||||
return fail("Failed to parse connection string");
|
return fail("Failed to parse connection string");
|
||||||
@ -141,7 +141,7 @@ void IpcNode::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mut<u8> signal = 0;
|
Mut<u8> signal = 0;
|
||||||
Const<isize> res = recv(m_socket, reinterpret_cast<char *>(&signal), 1, 0);
|
const isize res = recv(m_socket, reinterpret_cast<char *>(&signal), 1, 0);
|
||||||
if (res == 1) {
|
if (res == 1) {
|
||||||
on_signal(signal);
|
on_signal(signal);
|
||||||
} else if (res == 0 || (res < 0 && !SocketOps::is_would_block())) {
|
} else if (res == 0 || (res < 0 && !SocketOps::is_would_block())) {
|
||||||
@ -152,30 +152,30 @@ void IpcNode::update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcNode::send_signal(Const<u8> signal) {
|
void IpcNode::send_signal(const u8 signal) {
|
||||||
if (m_socket != INVALID_SOCKET) {
|
if (m_socket != INVALID_SOCKET) {
|
||||||
send(m_socket, reinterpret_cast<const char *>(&signal), sizeof(signal), 0);
|
send(m_socket, reinterpret_cast<const char *>(&signal), sizeof(signal), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IpcNode::send_packet(Const<u16> packet_id, Const<Span<Const<u8>>> payload)
|
auto IpcNode::send_packet(const u16 packet_id, const Span<const u8> payload)
|
||||||
-> Result<void> {
|
-> Result<void> {
|
||||||
if (!m_mino.is_valid())
|
if (!m_mino.is_valid())
|
||||||
return fail("invalid MINO");
|
return fail("invalid MINO");
|
||||||
return m_mino.push(packet_id, payload);
|
return m_mino.push(packet_id, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcManager::NodeSession::send_signal(Const<u8> signal) {
|
void IpcManager::NodeSession::send_signal(const u8 signal) {
|
||||||
if (data_socket != INVALID_SOCKET) {
|
if (data_socket != INVALID_SOCKET) {
|
||||||
send(data_socket, reinterpret_cast<const char *>(&signal), sizeof(signal),
|
send(data_socket, reinterpret_cast<const char *>(&signal), sizeof(signal),
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IpcManager::NodeSession::send_packet(Const<u16> packet_id,
|
auto IpcManager::NodeSession::send_packet(const u16 packet_id,
|
||||||
Const<Span<Const<u8>>> payload)
|
const Span<const u8> payload)
|
||||||
-> Result<void> {
|
-> Result<void> {
|
||||||
Const<std::scoped_lock<std::mutex>> lock(send_mutex);
|
const std::scoped_lock<std::mutex> lock(send_mutex);
|
||||||
if (!moni.is_valid())
|
if (!moni.is_valid())
|
||||||
return fail("invalid MONI");
|
return fail("invalid MONI");
|
||||||
return moni.push(packet_id, payload);
|
return moni.push(packet_id, payload);
|
||||||
@ -207,7 +207,7 @@ IpcManager::~IpcManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IpcManager::update() {
|
void IpcManager::update() {
|
||||||
Const<std::chrono::system_clock::time_point> now =
|
const std::chrono::system_clock::time_point now =
|
||||||
std::chrono::system_clock::now();
|
std::chrono::system_clock::now();
|
||||||
|
|
||||||
for (Mut<isize> i = static_cast<isize>(m_pending_sessions.size()) - 1; i >= 0;
|
for (Mut<isize> i = static_cast<isize>(m_pending_sessions.size()) - 1; i >= 0;
|
||||||
@ -246,7 +246,7 @@ void IpcManager::update() {
|
|||||||
SocketOps::close(session->listener_socket);
|
SocketOps::close(session->listener_socket);
|
||||||
session->listener_socket = INVALID_SOCKET;
|
session->listener_socket = INVALID_SOCKET;
|
||||||
|
|
||||||
Const<NativeProcessID> session_id = session->node_process->id.load();
|
const NativeProcessID session_id = session->node_process->id.load();
|
||||||
Mut<NodeSession *> session_ptr = session.get();
|
Mut<NodeSession *> session_ptr = session.get();
|
||||||
m_active_sessions.push_back(std::move(session));
|
m_active_sessions.push_back(std::move(session));
|
||||||
m_pending_sessions.erase(m_pending_sessions.begin() + i);
|
m_pending_sessions.erase(m_pending_sessions.begin() + i);
|
||||||
@ -269,7 +269,7 @@ void IpcManager::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mut<u8> signal = 0;
|
Mut<u8> signal = 0;
|
||||||
Const<isize> res =
|
const isize res =
|
||||||
recv(node->data_socket, reinterpret_cast<char *>(&signal), 1, 0);
|
recv(node->data_socket, reinterpret_cast<char *>(&signal), 1, 0);
|
||||||
|
|
||||||
if (res == 1) {
|
if (res == 1) {
|
||||||
@ -288,12 +288,12 @@ void IpcManager::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto IpcManager::spawn_node(Ref<Path> executable_path,
|
auto IpcManager::spawn_node(Ref<Path> executable_path,
|
||||||
Const<u32> shared_memory_size)
|
const u32 shared_memory_size)
|
||||||
-> Result<NativeProcessID> {
|
-> Result<NativeProcessID> {
|
||||||
Mut<Box<NodeSession>> session = make_box<NodeSession>();
|
Mut<Box<NodeSession>> session = make_box<NodeSession>();
|
||||||
|
|
||||||
static Mut<std::atomic<u32>> s_id_gen{0};
|
static Mut<std::atomic<u32>> s_id_gen{0};
|
||||||
Const<u32> sid = ++s_id_gen;
|
const u32 sid = ++s_id_gen;
|
||||||
|
|
||||||
Mut<String> sock_path;
|
Mut<String> sock_path;
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
@ -316,7 +316,7 @@ auto IpcManager::spawn_node(Ref<Path> executable_path,
|
|||||||
fcntl(session->listener_socket, F_SETFL, O_NONBLOCK);
|
fcntl(session->listener_socket, F_SETFL, O_NONBLOCK);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Const<String> shm_name = std::format("ia_shm_{}", sid);
|
const String shm_name = std::format("ia_shm_{}", sid);
|
||||||
session->mapped_ptr =
|
session->mapped_ptr =
|
||||||
AU_TRY(FileOps::map_shared_memory(shm_name, shared_memory_size, true));
|
AU_TRY(FileOps::map_shared_memory(shm_name, shared_memory_size, true));
|
||||||
|
|
||||||
@ -327,8 +327,8 @@ auto IpcManager::spawn_node(Ref<Path> executable_path,
|
|||||||
layout->meta.version = 1;
|
layout->meta.version = 1;
|
||||||
layout->meta.total_size = shared_memory_size;
|
layout->meta.total_size = shared_memory_size;
|
||||||
|
|
||||||
Const<u64> header_size = IpcSharedMemoryLayout::get_header_size();
|
const u64 header_size = IpcSharedMemoryLayout::get_header_size();
|
||||||
Const<u64> usable_bytes = shared_memory_size - header_size;
|
const u64 usable_bytes = shared_memory_size - header_size;
|
||||||
|
|
||||||
Mut<u64> half_size = (usable_bytes / 2);
|
Mut<u64> half_size = (usable_bytes / 2);
|
||||||
half_size -= (half_size % 64);
|
half_size -= (half_size % 64);
|
||||||
@ -356,17 +356,17 @@ auto IpcManager::spawn_node(Ref<Path> executable_path,
|
|||||||
desc.shared_mem_path = shm_name;
|
desc.shared_mem_path = shm_name;
|
||||||
desc.shared_mem_size = shared_memory_size;
|
desc.shared_mem_size = shared_memory_size;
|
||||||
|
|
||||||
Const<String> args = std::format("\"{}\"", desc.serialize());
|
const String args = std::format("\"{}\"", desc.serialize());
|
||||||
|
|
||||||
session->node_process = AU_TRY(ProcessOps::spawn_process_async(
|
session->node_process = AU_TRY(ProcessOps::spawn_process_async(
|
||||||
FileOps::normalize_executable_path(executable_path).string(), args,
|
FileOps::normalize_executable_path(executable_path).string(), args,
|
||||||
[sid](Const<StringView> line) {
|
[sid](StringView line) {
|
||||||
if (Env::IS_DEBUG) {
|
if (Env::IS_DEBUG) {
|
||||||
std::cout << std::format("{}[Node:{}:STDOUT|STDERR]: {}{}\n",
|
std::cout << std::format("{}[Node:{}:STDOUT|STDERR]: {}{}\n",
|
||||||
console::MAGENTA, sid, line, console::RESET);
|
console::MAGENTA, sid, line, console::RESET);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[sid](Const<Result<i32>> result) {
|
[sid](Result<i32> result) {
|
||||||
if (Env::IS_DEBUG) {
|
if (Env::IS_DEBUG) {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
std::cout << std::format(
|
std::cout << std::format(
|
||||||
@ -386,7 +386,7 @@ auto IpcManager::spawn_node(Ref<Path> executable_path,
|
|||||||
executable_path.string());
|
executable_path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<NativeProcessID> process_id = session->node_process->id.load();
|
const NativeProcessID process_id = session->node_process->id.load();
|
||||||
|
|
||||||
session->shared_mem_name = shm_name;
|
session->shared_mem_name = shm_name;
|
||||||
session->creation_time = std::chrono::system_clock::now();
|
session->creation_time = std::chrono::system_clock::now();
|
||||||
@ -395,12 +395,12 @@ auto IpcManager::spawn_node(Ref<Path> executable_path,
|
|||||||
return process_id;
|
return process_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IpcManager::wait_till_node_is_online(Const<NativeProcessID> node_id)
|
auto IpcManager::wait_till_node_is_online(const NativeProcessID node_id)
|
||||||
-> bool {
|
-> bool {
|
||||||
Mut<bool> is_pending = true;
|
Mut<bool> is_pending = true;
|
||||||
while (is_pending) {
|
while (is_pending) {
|
||||||
is_pending = false;
|
is_pending = false;
|
||||||
for (Const<Box<NodeSession>> &session : m_pending_sessions) {
|
for (const Box<NodeSession> &session : m_pending_sessions) {
|
||||||
if (session->node_process->id.load() == node_id) {
|
if (session->node_process->id.load() == node_id) {
|
||||||
is_pending = true;
|
is_pending = true;
|
||||||
break;
|
break;
|
||||||
@ -412,8 +412,8 @@ auto IpcManager::wait_till_node_is_online(Const<NativeProcessID> node_id)
|
|||||||
return m_active_session_map.contains(node_id);
|
return m_active_session_map.contains(node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcManager::shutdown_node(Const<NativeProcessID> node_id) {
|
void IpcManager::shutdown_node(const NativeProcessID node_id) {
|
||||||
Const<HashMap<NativeProcessID, NodeSession *>::iterator> it_node =
|
const HashMap<NativeProcessID, NodeSession *>::iterator it_node =
|
||||||
m_active_session_map.find(node_id);
|
m_active_session_map.find(node_id);
|
||||||
if (it_node == m_active_session_map.end()) {
|
if (it_node == m_active_session_map.end()) {
|
||||||
return;
|
return;
|
||||||
@ -431,8 +431,8 @@ void IpcManager::shutdown_node(Const<NativeProcessID> node_id) {
|
|||||||
m_active_session_map.erase(it_node);
|
m_active_session_map.erase(it_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcManager::send_signal(Const<NativeProcessID> node, Const<u8> signal) {
|
void IpcManager::send_signal(const NativeProcessID node, const u8 signal) {
|
||||||
Const<HashMap<NativeProcessID, NodeSession *>::iterator> it_node =
|
const HashMap<NativeProcessID, NodeSession *>::iterator it_node =
|
||||||
m_active_session_map.find(node);
|
m_active_session_map.find(node);
|
||||||
if (it_node == m_active_session_map.end()) {
|
if (it_node == m_active_session_map.end()) {
|
||||||
return;
|
return;
|
||||||
@ -440,9 +440,9 @@ void IpcManager::send_signal(Const<NativeProcessID> node, Const<u8> signal) {
|
|||||||
it_node->second->send_signal(signal);
|
it_node->second->send_signal(signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IpcManager::send_packet(Const<NativeProcessID> node, Const<u16> packet_id,
|
auto IpcManager::send_packet(const NativeProcessID node, const u16 packet_id,
|
||||||
Const<Span<Const<u8>>> payload) -> Result<void> {
|
const Span<const u8> payload) -> Result<void> {
|
||||||
Const<HashMap<NativeProcessID, NodeSession *>::iterator> it_node =
|
const HashMap<NativeProcessID, NodeSession *>::iterator it_node =
|
||||||
m_active_session_map.find(node);
|
m_active_session_map.find(node);
|
||||||
if (it_node == m_active_session_map.end())
|
if (it_node == m_active_session_map.end())
|
||||||
return fail("no such node");
|
return fail("no such node");
|
||||||
|
|||||||
@ -24,11 +24,11 @@ Mut<Logger::LogLevel> Logger::m_log_level = Logger::LogLevel::Info;
|
|||||||
Mut<std::ofstream> Logger::m_log_file;
|
Mut<std::ofstream> Logger::m_log_file;
|
||||||
|
|
||||||
static auto get_seconds_count() -> f64 {
|
static auto get_seconds_count() -> f64 {
|
||||||
static Const<std::chrono::time_point<std::chrono::steady_clock>> start_time =
|
static const std::chrono::time_point<std::chrono::steady_clock> start_time =
|
||||||
std::chrono::steady_clock::now();
|
std::chrono::steady_clock::now();
|
||||||
Const<std::chrono::time_point<std::chrono::steady_clock>> now =
|
const std::chrono::time_point<std::chrono::steady_clock> now =
|
||||||
std::chrono::steady_clock::now();
|
std::chrono::steady_clock::now();
|
||||||
Const<std::chrono::duration<f64>> duration = now - start_time;
|
const std::chrono::duration<f64> duration = now - start_time;
|
||||||
return duration.count();
|
return duration.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,8 +41,7 @@ auto Logger::terminate() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Logger::enable_logging_to_disk(Const<Const<char> *> file_path)
|
auto Logger::enable_logging_to_disk(const char *file_path) -> Result<void> {
|
||||||
-> Result<void> {
|
|
||||||
if (m_log_file.is_open()) {
|
if (m_log_file.is_open()) {
|
||||||
m_log_file.flush();
|
m_log_file.flush();
|
||||||
m_log_file.close();
|
m_log_file.close();
|
||||||
@ -57,7 +56,7 @@ auto Logger::enable_logging_to_disk(Const<Const<char> *> file_path)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Logger::set_log_level(Const<LogLevel> log_level) -> void {
|
auto Logger::set_log_level(const LogLevel log_level) -> void {
|
||||||
m_log_level = log_level;
|
m_log_level = log_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +67,10 @@ auto Logger::flush_logs() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Logger::log_internal(Const<Const<char> *> prefix, Const<Const<char> *> tag,
|
auto Logger::log_internal(const char *prefix, const char *tag,
|
||||||
ForwardRef<String> msg) -> void {
|
ForwardRef<String> msg) -> void {
|
||||||
Const<f64> seconds = get_seconds_count();
|
const f64 seconds = get_seconds_count();
|
||||||
Const<String> out_line =
|
const String out_line =
|
||||||
std::format("[{:>8.3f}]: [{}]: {}", seconds, tag, msg);
|
std::format("[{:>8.3f}]: [{}]: {}", seconds, tag, msg);
|
||||||
|
|
||||||
std::cout << prefix << out_line << console::RESET << '\n';
|
std::cout << prefix << out_line << console::RESET << '\n';
|
||||||
|
|||||||
@ -30,7 +30,7 @@ namespace IACore {
|
|||||||
Mut<Platform::Capabilities> Platform::s_capabilities{};
|
Mut<Platform::Capabilities> Platform::s_capabilities{};
|
||||||
|
|
||||||
#if defined(IA_ARCH_X64)
|
#if defined(IA_ARCH_X64)
|
||||||
auto Platform::cpuid(Const<i32> function, Const<i32> sub_function,
|
auto Platform::cpuid(const i32 function, const i32 sub_function,
|
||||||
Mut<i32> out[4]) -> void {
|
Mut<i32> out[4]) -> void {
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__cpuidex(reinterpret_cast<i32 *>(out), static_cast<i32>(function),
|
__cpuidex(reinterpret_cast<i32 *>(out), static_cast<i32>(function),
|
||||||
@ -59,21 +59,21 @@ auto Platform::check_cpu() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpuid(1, 0, cpu_info);
|
cpuid(1, 0, cpu_info);
|
||||||
Const<bool> osxsave = (cpu_info[2] & (1 << 27)) != 0;
|
const bool osxsave = (cpu_info[2] & (1 << 27)) != 0;
|
||||||
Const<bool> avx = (cpu_info[2] & (1 << 28)) != 0;
|
const bool avx = (cpu_info[2] & (1 << 28)) != 0;
|
||||||
Const<bool> fma = (cpu_info[2] & (1 << 12)) != 0;
|
const bool fma = (cpu_info[2] & (1 << 12)) != 0;
|
||||||
|
|
||||||
if (!osxsave || !avx || !fma) {
|
if (!osxsave || !avx || !fma) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u64> xcr_feature_mask = _xgetbv(0);
|
const u64 xcr_feature_mask = _xgetbv(0);
|
||||||
if ((xcr_feature_mask & 0x6) != 0x6) {
|
if ((xcr_feature_mask & 0x6) != 0x6) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpuid(7, 0, cpu_info);
|
cpuid(7, 0, cpu_info);
|
||||||
Const<bool> avx2 = (cpu_info[1] & (1 << 5)) != 0;
|
const bool avx2 = (cpu_info[1] & (1 << 5)) != 0;
|
||||||
if (!avx2) {
|
if (!avx2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ auto Platform::check_cpu() -> bool {
|
|||||||
|
|
||||||
#elif defined(IA_ARCH_ARM64)
|
#elif defined(IA_ARCH_ARM64)
|
||||||
#if defined(__linux__) || defined(__ANDROID__)
|
#if defined(__linux__) || defined(__ANDROID__)
|
||||||
Const<usize> hw_caps = getauxval(AT_HWCAP);
|
const usize hw_caps = getauxval(AT_HWCAP);
|
||||||
|
|
||||||
#ifndef HWCAP_CRC32
|
#ifndef HWCAP_CRC32
|
||||||
#define HWCAP_CRC32 (1 << 7)
|
#define HWCAP_CRC32 (1 << 7)
|
||||||
|
|||||||
@ -18,13 +18,13 @@
|
|||||||
namespace IACore {
|
namespace IACore {
|
||||||
struct LineBuffer {
|
struct LineBuffer {
|
||||||
Mut<String> m_accumulator;
|
Mut<String> m_accumulator;
|
||||||
Const<std::function<void(Const<StringView>)>> m_callback;
|
const std::function<void(StringView)> m_callback;
|
||||||
|
|
||||||
auto append(Const<char *> data, Const<usize> size) -> void;
|
auto append(const char *data, const usize size) -> void;
|
||||||
auto flush() -> void;
|
auto flush() -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto LineBuffer::append(Const<char *> data, Const<usize> size) -> void {
|
auto LineBuffer::append(const char *data, const usize size) -> void {
|
||||||
Mut<usize> start = 0;
|
Mut<usize> start = 0;
|
||||||
for (Mut<usize> i = 0; i < size; ++i) {
|
for (Mut<usize> i = 0; i < size; ++i) {
|
||||||
if (data[i] == '\n' || data[i] == '\r') {
|
if (data[i] == '\n' || data[i] == '\r') {
|
||||||
@ -68,7 +68,7 @@ auto ProcessOps::get_current_process_id() -> NativeProcessID {
|
|||||||
|
|
||||||
auto ProcessOps::spawn_process_sync(
|
auto ProcessOps::spawn_process_sync(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback)
|
const std::function<void(StringView)> on_output_line_callback)
|
||||||
-> Result<i32> {
|
-> Result<i32> {
|
||||||
Mut<std::atomic<NativeProcessID>> id = 0;
|
Mut<std::atomic<NativeProcessID>> id = 0;
|
||||||
if constexpr (Env::IS_WINDOWS) {
|
if constexpr (Env::IS_WINDOWS) {
|
||||||
@ -80,8 +80,8 @@ auto ProcessOps::spawn_process_sync(
|
|||||||
|
|
||||||
auto ProcessOps::spawn_process_async(
|
auto ProcessOps::spawn_process_async(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback,
|
const std::function<void(StringView)> on_output_line_callback,
|
||||||
Const<std::function<void(Const<Result<i32>>)>> on_finish_callback)
|
const std::function<void(Result<i32>)> on_finish_callback)
|
||||||
-> Result<Box<ProcessHandle>> {
|
-> Result<Box<ProcessHandle>> {
|
||||||
Mut<Box<ProcessHandle>> handle = make_box<ProcessHandle>();
|
Mut<Box<ProcessHandle>> handle = make_box<ProcessHandle>();
|
||||||
handle->is_running = true;
|
handle->is_running = true;
|
||||||
@ -118,7 +118,7 @@ auto ProcessOps::terminate_process(Ref<Box<ProcessHandle>> handle) -> void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<NativeProcessID> pid = handle->id.load();
|
const NativeProcessID pid = handle->id.load();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ auto ProcessOps::terminate_process(Ref<Box<ProcessHandle>> handle) -> void {
|
|||||||
|
|
||||||
auto ProcessOps::spawn_process_windows(
|
auto ProcessOps::spawn_process_windows(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback,
|
const std::function<void(StringView)> on_output_line_callback,
|
||||||
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32> {
|
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32> {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Mut<SECURITY_ATTRIBUTES> sa_attr = {sizeof(SECURITY_ATTRIBUTES), NULL, true};
|
Mut<SECURITY_ATTRIBUTES> sa_attr = {sizeof(SECURITY_ATTRIBUTES), NULL, true};
|
||||||
@ -162,7 +162,7 @@ auto ProcessOps::spawn_process_windows(
|
|||||||
|
|
||||||
Mut<String> command_line = std::format("\"{}\" {}", command, args);
|
Mut<String> command_line = std::format("\"{}\" {}", command, args);
|
||||||
|
|
||||||
Const<BOOL> success = CreateProcessA(NULL, command_line.data(), NULL, NULL,
|
const BOOL success = CreateProcessA(NULL, command_line.data(), NULL, NULL,
|
||||||
true, 0, NULL, NULL, &si, &pi);
|
true, 0, NULL, NULL, &si, &pi);
|
||||||
|
|
||||||
CloseHandle(h_write);
|
CloseHandle(h_write);
|
||||||
@ -206,7 +206,7 @@ auto ProcessOps::spawn_process_windows(
|
|||||||
|
|
||||||
auto ProcessOps::spawn_process_posix(
|
auto ProcessOps::spawn_process_posix(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback,
|
const std::function<void(StringView)> on_output_line_callback,
|
||||||
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32> {
|
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32> {
|
||||||
#if IA_PLATFORM_UNIX
|
#if IA_PLATFORM_UNIX
|
||||||
Mut<Array<i32, 2>> pipefd;
|
Mut<Array<i32, 2>> pipefd;
|
||||||
@ -214,7 +214,7 @@ auto ProcessOps::spawn_process_posix(
|
|||||||
return fail("Failed to create pipe");
|
return fail("Failed to create pipe");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<pid_t> pid = fork();
|
const pid_t pid = fork();
|
||||||
|
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
return fail("Failed to fork process");
|
return fail("Failed to fork process");
|
||||||
@ -235,7 +235,7 @@ auto ProcessOps::spawn_process_posix(
|
|||||||
Mut<bool> in_quotes = false;
|
Mut<bool> in_quotes = false;
|
||||||
Mut<bool> is_escaped = false;
|
Mut<bool> is_escaped = false;
|
||||||
|
|
||||||
for (Const<char> c : args) {
|
for (const char c : args) {
|
||||||
if (is_escaped) {
|
if (is_escaped) {
|
||||||
current_token += c;
|
current_token += c;
|
||||||
is_escaped = false;
|
is_escaped = false;
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
namespace IACore {
|
namespace IACore {
|
||||||
Mut<i32> SocketOps::s_init_count = 0;
|
Mut<i32> SocketOps::s_init_count = 0;
|
||||||
|
|
||||||
auto SocketOps::close(Const<SocketHandle> sock) -> void {
|
auto SocketOps::close(const SocketHandle sock) -> void {
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ auto SocketOps::close(Const<SocketHandle> sock) -> void {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SocketOps::listen(Const<SocketHandle> sock, Const<i32> queue_size)
|
auto SocketOps::listen(const SocketHandle sock, const i32 queue_size)
|
||||||
-> Result<void> {
|
-> Result<void> {
|
||||||
if (::listen(sock, queue_size) == 0) {
|
if (::listen(sock, queue_size) == 0) {
|
||||||
return {};
|
return {};
|
||||||
@ -44,7 +44,7 @@ auto SocketOps::listen(Const<SocketHandle> sock, Const<i32> queue_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto SocketOps::create_unix_socket() -> Result<SocketHandle> {
|
auto SocketOps::create_unix_socket() -> Result<SocketHandle> {
|
||||||
Const<SocketHandle> sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
const SocketHandle sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
return fail("socket(AF_UNIX) failed: {}", WSAGetLastError());
|
return fail("socket(AF_UNIX) failed: {}", WSAGetLastError());
|
||||||
@ -55,8 +55,8 @@ auto SocketOps::create_unix_socket() -> Result<SocketHandle> {
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SocketOps::bind_unix_socket(Const<SocketHandle> sock,
|
auto SocketOps::bind_unix_socket(const SocketHandle sock, const char *path)
|
||||||
Const<const char *> path) -> Result<void> {
|
-> Result<void> {
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
return fail("Invalid socket handle");
|
return fail("Invalid socket handle");
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ auto SocketOps::bind_unix_socket(Const<SocketHandle> sock,
|
|||||||
Mut<sockaddr_un> addr{};
|
Mut<sockaddr_un> addr{};
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
Const<usize> max_len = sizeof(addr.sun_path) - 1;
|
const usize max_len = sizeof(addr.sun_path) - 1;
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
strncpy_s(addr.sun_path, sizeof(addr.sun_path), path, max_len);
|
strncpy_s(addr.sun_path, sizeof(addr.sun_path), path, max_len);
|
||||||
#else
|
#else
|
||||||
@ -85,8 +85,8 @@ auto SocketOps::bind_unix_socket(Const<SocketHandle> sock,
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SocketOps::connect_unix_socket(Const<SocketHandle> sock,
|
auto SocketOps::connect_unix_socket(const SocketHandle sock, const char *path)
|
||||||
Const<const char *> path) -> Result<void> {
|
-> Result<void> {
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
return fail("Invalid socket handle");
|
return fail("Invalid socket handle");
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ auto SocketOps::connect_unix_socket(Const<SocketHandle> sock,
|
|||||||
Mut<sockaddr_un> addr{};
|
Mut<sockaddr_un> addr{};
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
Const<usize> max_len = sizeof(addr.sun_path) - 1;
|
const usize max_len = sizeof(addr.sun_path) - 1;
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
strncpy_s(addr.sun_path, sizeof(addr.sun_path), path, max_len);
|
strncpy_s(addr.sun_path, sizeof(addr.sun_path), path, max_len);
|
||||||
#else
|
#else
|
||||||
@ -113,8 +113,8 @@ auto SocketOps::connect_unix_socket(Const<SocketHandle> sock,
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SocketOps::is_port_available(Const<u16> port, Const<i32> type) -> bool {
|
auto SocketOps::is_port_available(const u16 port, const i32 type) -> bool {
|
||||||
Const<SocketHandle> sock = socket(AF_INET, type, 0);
|
const SocketHandle sock = socket(AF_INET, type, 0);
|
||||||
if (sock == INVALID_SOCKET) {
|
if (sock == INVALID_SOCKET) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ namespace IACore {
|
|||||||
auto StreamReader::create_from_file(Ref<Path> path) -> Result<StreamReader> {
|
auto StreamReader::create_from_file(Ref<Path> path) -> Result<StreamReader> {
|
||||||
Mut<usize> size = 0;
|
Mut<usize> size = 0;
|
||||||
|
|
||||||
Const<const u8 *> ptr = AU_TRY(FileOps::map_file(path, size));
|
const u8 *ptr = AU_TRY(FileOps::map_file(path, size));
|
||||||
|
|
||||||
Mut<StreamReader> reader(Span<const u8>(ptr, size));
|
Mut<StreamReader> reader(Span<const u8>(ptr, size));
|
||||||
reader.m_storage_type = StorageType::OwningMmap;
|
reader.m_storage_type = StorageType::OwningMmap;
|
||||||
@ -35,7 +35,7 @@ StreamReader::StreamReader(ForwardRef<Vec<u8>> data)
|
|||||||
m_data_size = m_owning_vector.size();
|
m_data_size = m_owning_vector.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamReader::StreamReader(Const<Span<const u8>> data)
|
StreamReader::StreamReader(const Span<const u8> data)
|
||||||
: m_data(data.data()), m_data_size(data.size()),
|
: m_data(data.data()), m_data_size(data.size()),
|
||||||
m_storage_type(StorageType::NonOwning) {}
|
m_storage_type(StorageType::NonOwning) {}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ StreamWriter::StreamWriter() : m_storage_type(StorageType::OwningVector) {
|
|||||||
m_buffer = m_owning_vector.data();
|
m_buffer = m_owning_vector.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamWriter::StreamWriter(Const<Span<u8>> data)
|
StreamWriter::StreamWriter(const Span<u8> data)
|
||||||
: m_buffer(data.data()), m_cursor(0), m_capacity(data.size()),
|
: m_buffer(data.data()), m_cursor(0), m_capacity(data.size()),
|
||||||
m_storage_type(StorageType::NonOwning) {}
|
m_storage_type(StorageType::NonOwning) {}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ auto StreamWriter::operator=(ForwardRef<StreamWriter> other)
|
|||||||
-> MutRef<StreamWriter> {
|
-> MutRef<StreamWriter> {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
if (m_storage_type == StorageType::OwningFile) {
|
if (m_storage_type == StorageType::OwningFile) {
|
||||||
if (Const<Result<void>> res = flush_to_disk(); !res) {
|
if (const Result<void> res = flush_to_disk(); !res) {
|
||||||
std::fprintf(stderr, "[IACore] Data loss in StreamWriter move: %s\n",
|
std::fprintf(stderr, "[IACore] Data loss in StreamWriter move: %s\n",
|
||||||
res.error().c_str());
|
res.error().c_str());
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ auto StreamWriter::operator=(ForwardRef<StreamWriter> other)
|
|||||||
|
|
||||||
StreamWriter::~StreamWriter() {
|
StreamWriter::~StreamWriter() {
|
||||||
if (m_storage_type == StorageType::OwningFile) {
|
if (m_storage_type == StorageType::OwningFile) {
|
||||||
if (Const<Result<void>> res = flush_to_disk(); !res) {
|
if (const Result<void> res = flush_to_disk(); !res) {
|
||||||
std::fprintf(stderr, "[IACore] LOST DATA in ~StreamWriter: %s\n",
|
std::fprintf(stderr, "[IACore] LOST DATA in ~StreamWriter: %s\n",
|
||||||
res.error().c_str());
|
res.error().c_str());
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ auto StreamWriter::flush_to_disk() -> Result<void> {
|
|||||||
return fail("Failed to open file for writing: {}", m_file_path.string());
|
return fail("Failed to open file for writing: {}", m_file_path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<usize> written = std::fwrite(m_buffer, 1, m_cursor, f);
|
const usize written = std::fwrite(m_buffer, 1, m_cursor, f);
|
||||||
std::fclose(f);
|
std::fclose(f);
|
||||||
|
|
||||||
if (written != m_cursor) {
|
if (written != m_cursor) {
|
||||||
@ -118,15 +118,15 @@ auto StreamWriter::flush_to_disk() -> Result<void> {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto StreamWriter::write(Const<u8> byte, Const<usize> count) -> Result<void> {
|
auto StreamWriter::write(const u8 byte, const usize count) -> Result<void> {
|
||||||
if (m_cursor + count > m_capacity) {
|
if (m_cursor + count > m_capacity) {
|
||||||
if (m_storage_type == StorageType::NonOwning) {
|
if (m_storage_type == StorageType::NonOwning) {
|
||||||
return fail("StreamWriter buffer overflow (NonOwning)");
|
return fail("StreamWriter buffer overflow (NonOwning)");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<usize> required = m_cursor + count;
|
const usize required = m_cursor + count;
|
||||||
Const<usize> double_cap = m_capacity * 2;
|
const usize double_cap = m_capacity * 2;
|
||||||
Const<usize> new_capacity = (double_cap > required) ? double_cap : required;
|
const usize new_capacity = (double_cap > required) ? double_cap : required;
|
||||||
|
|
||||||
m_owning_vector.resize(new_capacity);
|
m_owning_vector.resize(new_capacity);
|
||||||
m_capacity = m_owning_vector.size();
|
m_capacity = m_owning_vector.size();
|
||||||
@ -138,16 +138,15 @@ auto StreamWriter::write(Const<u8> byte, Const<usize> count) -> Result<void> {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto StreamWriter::write(Const<const void *> buffer, Const<usize> size)
|
auto StreamWriter::write(const void *buffer, const usize size) -> Result<void> {
|
||||||
-> Result<void> {
|
|
||||||
if (m_cursor + size > m_capacity) {
|
if (m_cursor + size > m_capacity) {
|
||||||
if (m_storage_type == StorageType::NonOwning) {
|
if (m_storage_type == StorageType::NonOwning) {
|
||||||
return fail("StreamWriter buffer overflow (NonOwning)");
|
return fail("StreamWriter buffer overflow (NonOwning)");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<usize> required = m_cursor + size;
|
const usize required = m_cursor + size;
|
||||||
Const<usize> double_cap = m_capacity * 2;
|
const usize double_cap = m_capacity * 2;
|
||||||
Const<usize> new_capacity = (double_cap > required) ? double_cap : required;
|
const usize new_capacity = (double_cap > required) ? double_cap : required;
|
||||||
|
|
||||||
m_owning_vector.resize(new_capacity);
|
m_owning_vector.resize(new_capacity);
|
||||||
m_capacity = m_owning_vector.size();
|
m_capacity = m_owning_vector.size();
|
||||||
|
|||||||
@ -17,15 +17,15 @@
|
|||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
|
|
||||||
static Const<String> BASE64_CHAR_TABLE =
|
static const String BASE64_CHAR_TABLE =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
static auto is_base64(Const<u8> c) -> bool {
|
static auto is_base64(const u8 c) -> bool {
|
||||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
||||||
(c >= '0' && c <= '9') || (c == '+') || (c == '/');
|
(c >= '0' && c <= '9') || (c == '+') || (c == '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto get_base64_index(Const<u8> c) -> u8 {
|
static auto get_base64_index(const u8 c) -> u8 {
|
||||||
if (c >= 'A' && c <= 'Z')
|
if (c >= 'A' && c <= 'Z')
|
||||||
return c - 'A';
|
return c - 'A';
|
||||||
if (c >= 'a' && c <= 'z')
|
if (c >= 'a' && c <= 'z')
|
||||||
@ -39,16 +39,16 @@ static auto get_base64_index(Const<u8> c) -> u8 {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto StringOps::encode_base64(Const<Span<Const<u8>>> data) -> String {
|
auto StringOps::encode_base64(const Span<const u8> data) -> String {
|
||||||
Mut<String> result;
|
Mut<String> result;
|
||||||
result.reserve(((data.size() + 2) / 3) * 4);
|
result.reserve(((data.size() + 2) / 3) * 4);
|
||||||
|
|
||||||
for (Mut<usize> i = 0; i < data.size(); i += 3) {
|
for (Mut<usize> i = 0; i < data.size(); i += 3) {
|
||||||
Const<u32> b0 = data[i];
|
const u32 b0 = data[i];
|
||||||
Const<u32> b1 = (i + 1 < data.size()) ? data[i + 1] : 0;
|
const u32 b1 = (i + 1 < data.size()) ? data[i + 1] : 0;
|
||||||
Const<u32> b2 = (i + 2 < data.size()) ? data[i + 2] : 0;
|
const u32 b2 = (i + 2 < data.size()) ? data[i + 2] : 0;
|
||||||
|
|
||||||
Const<u32> triple = (b0 << 16) | (b1 << 8) | b2;
|
const u32 triple = (b0 << 16) | (b1 << 8) | b2;
|
||||||
|
|
||||||
result += BASE64_CHAR_TABLE[(triple >> 18) & 0x3F];
|
result += BASE64_CHAR_TABLE[(triple >> 18) & 0x3F];
|
||||||
result += BASE64_CHAR_TABLE[(triple >> 12) & 0x3F];
|
result += BASE64_CHAR_TABLE[(triple >> 12) & 0x3F];
|
||||||
@ -75,8 +75,8 @@ auto StringOps::decode_base64(Ref<String> data) -> Vec<u8> {
|
|||||||
Mut<i32> i = 0;
|
Mut<i32> i = 0;
|
||||||
Mut<Array<u8, 4>> tmp_buf = {};
|
Mut<Array<u8, 4>> tmp_buf = {};
|
||||||
|
|
||||||
for (Const<char> c_char : data) {
|
for (const char c_char : data) {
|
||||||
Const<u8> c = static_cast<u8>(c_char);
|
const u8 c = static_cast<u8>(c_char);
|
||||||
if (c == '=') {
|
if (c == '=') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -86,10 +86,10 @@ auto StringOps::decode_base64(Ref<String> data) -> Vec<u8> {
|
|||||||
|
|
||||||
tmp_buf[i++] = c;
|
tmp_buf[i++] = c;
|
||||||
if (i == 4) {
|
if (i == 4) {
|
||||||
Const<u8> n0 = get_base64_index(tmp_buf[0]);
|
const u8 n0 = get_base64_index(tmp_buf[0]);
|
||||||
Const<u8> n1 = get_base64_index(tmp_buf[1]);
|
const u8 n1 = get_base64_index(tmp_buf[1]);
|
||||||
Const<u8> n2 = get_base64_index(tmp_buf[2]);
|
const u8 n2 = get_base64_index(tmp_buf[2]);
|
||||||
Const<u8> n3 = get_base64_index(tmp_buf[3]);
|
const u8 n3 = get_base64_index(tmp_buf[3]);
|
||||||
|
|
||||||
result.push_back((n0 << 2) | ((n1 & 0x30) >> 4));
|
result.push_back((n0 << 2) | ((n1 & 0x30) >> 4));
|
||||||
result.push_back(((n1 & 0x0F) << 4) | ((n2 & 0x3C) >> 2));
|
result.push_back(((n1 & 0x0F) << 4) | ((n2 & 0x3C) >> 2));
|
||||||
@ -104,9 +104,9 @@ auto StringOps::decode_base64(Ref<String> data) -> Vec<u8> {
|
|||||||
tmp_buf[j] = 'A';
|
tmp_buf[j] = 'A';
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u8> n0 = get_base64_index(tmp_buf[0]);
|
const u8 n0 = get_base64_index(tmp_buf[0]);
|
||||||
Const<u8> n1 = get_base64_index(tmp_buf[1]);
|
const u8 n1 = get_base64_index(tmp_buf[1]);
|
||||||
Const<u8> n2 = get_base64_index(tmp_buf[2]);
|
const u8 n2 = get_base64_index(tmp_buf[2]);
|
||||||
|
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
result.push_back((n0 << 2) | ((n1 & 0x30) >> 4));
|
result.push_back((n0 << 2) | ((n1 & 0x30) >> 4));
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
namespace {
|
namespace {
|
||||||
auto from_hex_char(Const<char> c) -> i32 {
|
auto from_hex_char(const char c) -> i32 {
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
return c - '0';
|
return c - '0';
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ auto from_hex_char(Const<char> c) -> i32 {
|
|||||||
extern Mut<std::chrono::high_resolution_clock::time_point> g_start_time;
|
extern Mut<std::chrono::high_resolution_clock::time_point> g_start_time;
|
||||||
|
|
||||||
auto Utils::get_unix_time() -> u64 {
|
auto Utils::get_unix_time() -> u64 {
|
||||||
Const<std::chrono::system_clock::time_point> now =
|
const std::chrono::system_clock::time_point now =
|
||||||
std::chrono::system_clock::now();
|
std::chrono::system_clock::now();
|
||||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
now.time_since_epoch())
|
now.time_since_epoch())
|
||||||
@ -44,14 +44,14 @@ auto Utils::get_unix_time() -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::get_ticks_count() -> u64 {
|
auto Utils::get_ticks_count() -> u64 {
|
||||||
Const<std::chrono::high_resolution_clock::duration> duration =
|
const std::chrono::high_resolution_clock::duration duration =
|
||||||
std::chrono::high_resolution_clock::now() - g_start_time;
|
std::chrono::high_resolution_clock::now() - g_start_time;
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(duration)
|
return std::chrono::duration_cast<std::chrono::milliseconds>(duration)
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::get_seconds_count() -> f64 {
|
auto Utils::get_seconds_count() -> f64 {
|
||||||
Const<std::chrono::high_resolution_clock::duration> duration =
|
const std::chrono::high_resolution_clock::duration duration =
|
||||||
std::chrono::high_resolution_clock::now() - g_start_time;
|
std::chrono::high_resolution_clock::now() - g_start_time;
|
||||||
return static_cast<f64>(
|
return static_cast<f64>(
|
||||||
std::chrono::duration_cast<std::chrono::seconds>(duration).count());
|
std::chrono::duration_cast<std::chrono::seconds>(duration).count());
|
||||||
@ -61,31 +61,31 @@ auto Utils::get_random() -> f32 {
|
|||||||
return static_cast<f32>(std::rand()) / static_cast<f32>(RAND_MAX);
|
return static_cast<f32>(std::rand()) / static_cast<f32>(RAND_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::get_random(Const<u64> max) -> u64 {
|
auto Utils::get_random(const u64 max) -> u64 {
|
||||||
return static_cast<u64>(static_cast<f32>(max) * get_random());
|
return static_cast<u64>(static_cast<f32>(max) * get_random());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::get_random(Const<i64> min, Const<i64> max) -> i64 {
|
auto Utils::get_random(const i64 min, const i64 max) -> i64 {
|
||||||
return min + static_cast<i64>(static_cast<f32>(max - min) * get_random());
|
return min + static_cast<i64>(static_cast<f32>(max - min) * get_random());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::sleep(Const<u64> milliseconds) -> void {
|
auto Utils::sleep(const u64 milliseconds) -> void {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
|
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::binary_to_hex_string(Const<Span<Const<u8>>> data) -> String {
|
auto Utils::binary_to_hex_string(const Span<const u8> data) -> String {
|
||||||
static constexpr Const<char[17]> lut = "0123456789ABCDEF";
|
static constexpr const char LUT[17] = "0123456789ABCDEF";
|
||||||
Mut<String> res = String();
|
Mut<String> res = String();
|
||||||
res.reserve(data.size() * 2);
|
res.reserve(data.size() * 2);
|
||||||
|
|
||||||
for (Const<u8> b : data) {
|
for (u8 b : data) {
|
||||||
res.push_back(lut[(b >> 4) & 0x0F]);
|
res.push_back(LUT[(b >> 4) & 0x0F]);
|
||||||
res.push_back(lut[b & 0x0F]);
|
res.push_back(LUT[b & 0x0F]);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Utils::hex_string_to_binary(Const<StringView> hex) -> Result<Vec<u8>> {
|
auto Utils::hex_string_to_binary(const StringView hex) -> Result<Vec<u8>> {
|
||||||
if (hex.size() % 2 != 0) {
|
if (hex.size() % 2 != 0) {
|
||||||
return fail("Hex string must have even length");
|
return fail("Hex string must have even length");
|
||||||
}
|
}
|
||||||
@ -94,11 +94,11 @@ auto Utils::hex_string_to_binary(Const<StringView> hex) -> Result<Vec<u8>> {
|
|||||||
out.reserve(hex.size() / 2);
|
out.reserve(hex.size() / 2);
|
||||||
|
|
||||||
for (Mut<usize> i = 0; i < hex.size(); i += 2) {
|
for (Mut<usize> i = 0; i < hex.size(); i += 2) {
|
||||||
Const<char> high = hex[i];
|
const char high = hex[i];
|
||||||
Const<char> low = hex[i + 1];
|
const char low = hex[i + 1];
|
||||||
|
|
||||||
Const<i32> h = from_hex_char(high);
|
const i32 h = from_hex_char(high);
|
||||||
Const<i32> l = from_hex_char(low);
|
const i32 l = from_hex_char(low);
|
||||||
|
|
||||||
if (h == -1 || l == -1) {
|
if (h == -1 || l == -1) {
|
||||||
return fail("Invalid hex character found");
|
return fail("Invalid hex character found");
|
||||||
|
|||||||
@ -20,7 +20,7 @@ namespace IACore {
|
|||||||
|
|
||||||
auto XML::parse_from_string(Ref<String> data) -> Result<Document> {
|
auto XML::parse_from_string(Ref<String> data) -> Result<Document> {
|
||||||
Mut<Document> doc;
|
Mut<Document> doc;
|
||||||
Const<pugi::xml_parse_result> parse_result = doc.load_string(data.c_str());
|
const pugi::xml_parse_result parse_result = doc.load_string(data.c_str());
|
||||||
if (!parse_result) {
|
if (!parse_result) {
|
||||||
return fail("Failed to parse XML {}", parse_result.description());
|
return fail("Failed to parse XML {}", parse_result.description());
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ auto XML::parse_from_string(Ref<String> data) -> Result<Document> {
|
|||||||
|
|
||||||
auto XML::parse_from_file(Ref<Path> path) -> Result<Document> {
|
auto XML::parse_from_file(Ref<Path> path) -> Result<Document> {
|
||||||
Mut<Document> doc;
|
Mut<Document> doc;
|
||||||
Const<pugi::xml_parse_result> parse_result =
|
const pugi::xml_parse_result parse_result =
|
||||||
doc.load_file(path.string().c_str());
|
doc.load_file(path.string().c_str());
|
||||||
if (!parse_result) {
|
if (!parse_result) {
|
||||||
return fail("Failed to parse XML {}", parse_result.description());
|
return fail("Failed to parse XML {}", parse_result.description());
|
||||||
@ -37,13 +37,13 @@ auto XML::parse_from_file(Ref<Path> path) -> Result<Document> {
|
|||||||
return std::move(doc);
|
return std::move(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto XML::serialize_to_string(Ref<Node> node, Const<bool> escape) -> String {
|
auto XML::serialize_to_string(Ref<Node> node, const bool escape) -> String {
|
||||||
Mut<std::ostringstream> oss;
|
Mut<std::ostringstream> oss;
|
||||||
node.print(oss);
|
node.print(oss);
|
||||||
return escape ? escape_xml_string(oss.str()) : oss.str();
|
return escape ? escape_xml_string(oss.str()) : oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto XML::serialize_to_string(Ref<Document> doc, Const<bool> escape) -> String {
|
auto XML::serialize_to_string(Ref<Document> doc, const bool escape) -> String {
|
||||||
Mut<std::ostringstream> oss;
|
Mut<std::ostringstream> oss;
|
||||||
doc.save(oss);
|
doc.save(oss);
|
||||||
return escape ? escape_xml_string(oss.str()) : oss.str();
|
return escape ? escape_xml_string(oss.str()) : oss.str();
|
||||||
@ -53,7 +53,7 @@ auto XML::escape_xml_string(Ref<String> xml) -> String {
|
|||||||
Mut<String> buffer;
|
Mut<String> buffer;
|
||||||
buffer.reserve(xml.size() + (xml.size() / 10));
|
buffer.reserve(xml.size() + (xml.size() / 10));
|
||||||
|
|
||||||
for (Const<char> c : xml) {
|
for (const char c : xml) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '&':
|
case '&':
|
||||||
buffer.append("&");
|
buffer.append("&");
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
namespace IACore {
|
namespace IACore {
|
||||||
class RingBufferView {
|
class RingBufferView {
|
||||||
public:
|
public:
|
||||||
static constexpr Const<u16> PACKET_ID_SKIP = 0;
|
static constexpr const u16 PACKET_ID_SKIP = 0;
|
||||||
|
|
||||||
struct ControlBlock {
|
struct ControlBlock {
|
||||||
struct alignas(64) {
|
struct alignas(64) {
|
||||||
@ -39,9 +39,9 @@ public:
|
|||||||
struct PacketHeader {
|
struct PacketHeader {
|
||||||
PacketHeader() : id(0), payload_size(0) {}
|
PacketHeader() : id(0), payload_size(0) {}
|
||||||
|
|
||||||
PacketHeader(Const<u16> id) : id(id), payload_size(0) {}
|
PacketHeader(const u16 id) : id(id), payload_size(0) {}
|
||||||
|
|
||||||
PacketHeader(Const<u16> id, Const<u16> payload_size)
|
PacketHeader(const u16 id, const u16 payload_size)
|
||||||
: id(id), payload_size(payload_size) {}
|
: id(id), payload_size(payload_size) {}
|
||||||
|
|
||||||
Mut<u16> id{};
|
Mut<u16> id{};
|
||||||
@ -51,10 +51,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
static auto default_instance() -> RingBufferView;
|
static auto default_instance() -> RingBufferView;
|
||||||
|
|
||||||
static auto create(Ref<Span<u8>> buffer, Const<bool> is_owner)
|
static auto create(Ref<Span<u8>> buffer, const bool is_owner)
|
||||||
-> Result<RingBufferView>;
|
-> Result<RingBufferView>;
|
||||||
static auto create(Const<ControlBlock *> control_block, Ref<Span<u8>> buffer,
|
static auto create(ControlBlock *control_block, Ref<Span<u8>> buffer,
|
||||||
Const<bool> is_owner) -> Result<RingBufferView>;
|
const bool is_owner) -> Result<RingBufferView>;
|
||||||
|
|
||||||
// Returns:
|
// Returns:
|
||||||
// - nullopt if empty
|
// - nullopt if empty
|
||||||
@ -63,16 +63,16 @@ public:
|
|||||||
auto pop(MutRef<PacketHeader> out_header, Ref<Span<u8>> out_buffer)
|
auto pop(MutRef<PacketHeader> out_header, Ref<Span<u8>> out_buffer)
|
||||||
-> Result<Option<usize>>;
|
-> Result<Option<usize>>;
|
||||||
|
|
||||||
auto push(Const<u16> packet_id, Ref<Span<const u8>> data) -> Result<void>;
|
auto push(const u16 packet_id, Ref<Span<const u8>> data) -> Result<void>;
|
||||||
|
|
||||||
auto get_control_block() -> ControlBlock *;
|
auto get_control_block() -> ControlBlock *;
|
||||||
|
|
||||||
[[nodiscard]] auto is_valid() const -> bool;
|
[[nodiscard]] auto is_valid() const -> bool;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RingBufferView(Ref<Span<u8>> buffer, Const<bool> is_owner);
|
RingBufferView(Ref<Span<u8>> buffer, const bool is_owner);
|
||||||
RingBufferView(Const<ControlBlock *> control_block, Ref<Span<u8>> buffer,
|
RingBufferView(ControlBlock *control_block, Ref<Span<u8>> buffer,
|
||||||
Const<bool> is_owner);
|
const bool is_owner);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mut<u8 *> m_data_ptr{};
|
Mut<u8 *> m_data_ptr{};
|
||||||
@ -80,26 +80,24 @@ private:
|
|||||||
Mut<ControlBlock *> m_control_block{};
|
Mut<ControlBlock *> m_control_block{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto write_wrapped(Const<u32> offset, Const<const void *> data,
|
auto write_wrapped(const u32 offset, const void *data, const u32 size)
|
||||||
Const<u32> size) -> void;
|
|
||||||
auto read_wrapped(Const<u32> offset, Const<void *> out_data, Const<u32> size)
|
|
||||||
-> void;
|
-> void;
|
||||||
|
auto read_wrapped(const u32 offset, void *out_data, const u32 size) -> void;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline auto RingBufferView::default_instance() -> RingBufferView {
|
inline auto RingBufferView::default_instance() -> RingBufferView {
|
||||||
return RingBufferView(nullptr, {}, false);
|
return RingBufferView(nullptr, {}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto RingBufferView::create(Ref<Span<u8>> buffer, Const<bool> is_owner)
|
inline auto RingBufferView::create(Ref<Span<u8>> buffer, const bool is_owner)
|
||||||
-> Result<RingBufferView> {
|
-> Result<RingBufferView> {
|
||||||
if (buffer.size() <= sizeof(ControlBlock)) {
|
if (buffer.size() <= sizeof(ControlBlock)) {
|
||||||
return fail("Buffer too small for ControlBlock");
|
return fail("Buffer too small for ControlBlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_owner) {
|
if (!is_owner) {
|
||||||
Const<ControlBlock *> cb = reinterpret_cast<ControlBlock *>(buffer.data());
|
const ControlBlock *cb = reinterpret_cast<ControlBlock *>(buffer.data());
|
||||||
Const<u32> capacity =
|
const u32 capacity = static_cast<u32>(buffer.size()) - sizeof(ControlBlock);
|
||||||
static_cast<u32>(buffer.size()) - sizeof(ControlBlock);
|
|
||||||
if (cb->consumer.capacity != capacity) {
|
if (cb->consumer.capacity != capacity) {
|
||||||
return fail("Capacity mismatch");
|
return fail("Capacity mismatch");
|
||||||
}
|
}
|
||||||
@ -108,8 +106,8 @@ inline auto RingBufferView::create(Ref<Span<u8>> buffer, Const<bool> is_owner)
|
|||||||
return RingBufferView(buffer, is_owner);
|
return RingBufferView(buffer, is_owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto RingBufferView::create(Const<ControlBlock *> control_block,
|
inline auto RingBufferView::create(ControlBlock *control_block,
|
||||||
Ref<Span<u8>> buffer, Const<bool> is_owner)
|
Ref<Span<u8>> buffer, const bool is_owner)
|
||||||
-> Result<RingBufferView> {
|
-> Result<RingBufferView> {
|
||||||
if (control_block == nullptr) {
|
if (control_block == nullptr) {
|
||||||
return fail("ControlBlock is null");
|
return fail("ControlBlock is null");
|
||||||
@ -122,7 +120,7 @@ inline auto RingBufferView::create(Const<ControlBlock *> control_block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline RingBufferView::RingBufferView(Ref<Span<u8>> buffer,
|
inline RingBufferView::RingBufferView(Ref<Span<u8>> buffer,
|
||||||
Const<bool> is_owner) {
|
const bool is_owner) {
|
||||||
m_control_block = reinterpret_cast<ControlBlock *>(buffer.data());
|
m_control_block = reinterpret_cast<ControlBlock *>(buffer.data());
|
||||||
m_data_ptr = buffer.data() + sizeof(ControlBlock);
|
m_data_ptr = buffer.data() + sizeof(ControlBlock);
|
||||||
|
|
||||||
@ -135,9 +133,9 @@ inline RingBufferView::RingBufferView(Ref<Span<u8>> buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RingBufferView::RingBufferView(Const<ControlBlock *> control_block,
|
inline RingBufferView::RingBufferView(ControlBlock *control_block,
|
||||||
Ref<Span<u8>> buffer,
|
Ref<Span<u8>> buffer,
|
||||||
Const<bool> is_owner) {
|
const bool is_owner) {
|
||||||
m_control_block = control_block;
|
m_control_block = control_block;
|
||||||
m_data_ptr = buffer.data();
|
m_data_ptr = buffer.data();
|
||||||
m_capacity = static_cast<u32>(buffer.size());
|
m_capacity = static_cast<u32>(buffer.size());
|
||||||
@ -152,11 +150,11 @@ inline RingBufferView::RingBufferView(Const<ControlBlock *> control_block,
|
|||||||
inline auto RingBufferView::pop(MutRef<PacketHeader> out_header,
|
inline auto RingBufferView::pop(MutRef<PacketHeader> out_header,
|
||||||
Ref<Span<u8>> out_buffer)
|
Ref<Span<u8>> out_buffer)
|
||||||
-> Result<Option<usize>> {
|
-> Result<Option<usize>> {
|
||||||
Const<u32> write =
|
const u32 write =
|
||||||
m_control_block->producer.write_offset.load(std::memory_order_acquire);
|
m_control_block->producer.write_offset.load(std::memory_order_acquire);
|
||||||
Const<u32> read =
|
const u32 read =
|
||||||
m_control_block->consumer.read_offset.load(std::memory_order_relaxed);
|
m_control_block->consumer.read_offset.load(std::memory_order_relaxed);
|
||||||
Const<u32> cap = m_capacity;
|
const u32 cap = m_capacity;
|
||||||
|
|
||||||
if (read == write) {
|
if (read == write) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@ -170,11 +168,11 @@ inline auto RingBufferView::pop(MutRef<PacketHeader> out_header,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (out_header.payload_size > 0) {
|
if (out_header.payload_size > 0) {
|
||||||
Const<u32> data_read_offset = (read + sizeof(PacketHeader)) % cap;
|
const u32 data_read_offset = (read + sizeof(PacketHeader)) % cap;
|
||||||
read_wrapped(data_read_offset, out_buffer.data(), out_header.payload_size);
|
read_wrapped(data_read_offset, out_buffer.data(), out_header.payload_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u32> new_read_offset =
|
const u32 new_read_offset =
|
||||||
(read + sizeof(PacketHeader) + out_header.payload_size) % cap;
|
(read + sizeof(PacketHeader) + out_header.payload_size) % cap;
|
||||||
m_control_block->consumer.read_offset.store(new_read_offset,
|
m_control_block->consumer.read_offset.store(new_read_offset,
|
||||||
std::memory_order_release);
|
std::memory_order_release);
|
||||||
@ -182,21 +180,21 @@ inline auto RingBufferView::pop(MutRef<PacketHeader> out_header,
|
|||||||
return std::make_optional(static_cast<usize>(out_header.payload_size));
|
return std::make_optional(static_cast<usize>(out_header.payload_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto RingBufferView::push(Const<u16> packet_id, Ref<Span<const u8>> data)
|
inline auto RingBufferView::push(const u16 packet_id, Ref<Span<const u8>> data)
|
||||||
-> Result<void> {
|
-> Result<void> {
|
||||||
if (data.size() > std::numeric_limits<u16>::max()) {
|
if (data.size() > std::numeric_limits<u16>::max()) {
|
||||||
return fail("Data size exceeds u16 limit");
|
return fail("Data size exceeds u16 limit");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u32> total_size = sizeof(PacketHeader) + static_cast<u32>(data.size());
|
const u32 total_size = sizeof(PacketHeader) + static_cast<u32>(data.size());
|
||||||
|
|
||||||
Const<u32> read =
|
const u32 read =
|
||||||
m_control_block->consumer.read_offset.load(std::memory_order_acquire);
|
m_control_block->consumer.read_offset.load(std::memory_order_acquire);
|
||||||
Const<u32> write =
|
const u32 write =
|
||||||
m_control_block->producer.write_offset.load(std::memory_order_relaxed);
|
m_control_block->producer.write_offset.load(std::memory_order_relaxed);
|
||||||
Const<u32> cap = m_capacity;
|
const u32 cap = m_capacity;
|
||||||
|
|
||||||
Const<u32> free_space =
|
const u32 free_space =
|
||||||
(read <= write) ? (m_capacity - write) + read : (read - write);
|
(read <= write) ? (m_capacity - write) + read : (read - write);
|
||||||
|
|
||||||
// Leave 1 byte empty (prevent ambiguities)
|
// Leave 1 byte empty (prevent ambiguities)
|
||||||
@ -204,17 +202,17 @@ inline auto RingBufferView::push(Const<u16> packet_id, Ref<Span<const u8>> data)
|
|||||||
return fail("RingBuffer full");
|
return fail("RingBuffer full");
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<PacketHeader> header{packet_id, static_cast<u16>(data.size())};
|
const PacketHeader header{packet_id, static_cast<u16>(data.size())};
|
||||||
write_wrapped(write, &header, sizeof(PacketHeader));
|
write_wrapped(write, &header, sizeof(PacketHeader));
|
||||||
|
|
||||||
Const<u32> data_write_offset = (write + sizeof(PacketHeader)) % cap;
|
const u32 data_write_offset = (write + sizeof(PacketHeader)) % cap;
|
||||||
|
|
||||||
if (!data.empty()) {
|
if (!data.empty()) {
|
||||||
write_wrapped(data_write_offset, data.data(),
|
write_wrapped(data_write_offset, data.data(),
|
||||||
static_cast<u32>(data.size()));
|
static_cast<u32>(data.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<u32> new_write_offset = (data_write_offset + data.size()) % cap;
|
const u32 new_write_offset = (data_write_offset + data.size()) % cap;
|
||||||
m_control_block->producer.write_offset.store(new_write_offset,
|
m_control_block->producer.write_offset.store(new_write_offset,
|
||||||
std::memory_order_release);
|
std::memory_order_release);
|
||||||
|
|
||||||
@ -225,32 +223,30 @@ inline auto RingBufferView::get_control_block() -> ControlBlock * {
|
|||||||
return m_control_block;
|
return m_control_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto RingBufferView::write_wrapped(Const<u32> offset,
|
inline auto RingBufferView::write_wrapped(const u32 offset, const void *data,
|
||||||
Const<const void *> data,
|
const u32 size) -> void {
|
||||||
Const<u32> size) -> void {
|
|
||||||
if (offset + size <= m_capacity) {
|
if (offset + size <= m_capacity) {
|
||||||
std::memcpy(m_data_ptr + offset, data, size);
|
std::memcpy(m_data_ptr + offset, data, size);
|
||||||
} else {
|
} else {
|
||||||
Const<u32> first_chunk = m_capacity - offset;
|
const u32 first_chunk = m_capacity - offset;
|
||||||
Const<u32> second_chunk = size - first_chunk;
|
const u32 second_chunk = size - first_chunk;
|
||||||
|
|
||||||
Const<const u8 *> src = static_cast<const u8 *>(data);
|
const u8 *src = static_cast<const u8 *>(data);
|
||||||
|
|
||||||
std::memcpy(m_data_ptr + offset, src, first_chunk);
|
std::memcpy(m_data_ptr + offset, src, first_chunk);
|
||||||
std::memcpy(m_data_ptr, src + first_chunk, second_chunk);
|
std::memcpy(m_data_ptr, src + first_chunk, second_chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto RingBufferView::read_wrapped(Const<u32> offset,
|
inline auto RingBufferView::read_wrapped(const u32 offset, void *out_data,
|
||||||
Const<void *> out_data,
|
const u32 size) -> void {
|
||||||
Const<u32> size) -> void {
|
|
||||||
if (offset + size <= m_capacity) {
|
if (offset + size <= m_capacity) {
|
||||||
std::memcpy(out_data, m_data_ptr + offset, size);
|
std::memcpy(out_data, m_data_ptr + offset, size);
|
||||||
} else {
|
} else {
|
||||||
Const<u32> first_chunk = m_capacity - offset;
|
const u32 first_chunk = m_capacity - offset;
|
||||||
Const<u32> second_chunk = size - first_chunk;
|
const u32 second_chunk = size - first_chunk;
|
||||||
|
|
||||||
Const<u8 *> dst = static_cast<u8 *>(out_data);
|
u8 *dst = static_cast<u8 *>(out_data);
|
||||||
|
|
||||||
std::memcpy(dst, m_data_ptr + offset, first_chunk);
|
std::memcpy(dst, m_data_ptr + offset, first_chunk);
|
||||||
std::memcpy(dst + first_chunk, m_data_ptr, second_chunk);
|
std::memcpy(dst + first_chunk, m_data_ptr, second_chunk);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ public:
|
|||||||
using TaskTag = u64;
|
using TaskTag = u64;
|
||||||
using WorkerId = u16;
|
using WorkerId = u16;
|
||||||
|
|
||||||
static constexpr Const<WorkerId> MAIN_THREAD_WORKER_ID = 0;
|
static constexpr const WorkerId MAIN_THREAD_WORKER_ID = 0;
|
||||||
|
|
||||||
enum class Priority : u8 { High, Normal };
|
enum class Priority : u8 { High, Normal };
|
||||||
|
|
||||||
@ -35,15 +35,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static auto initialize_scheduler(Const<u8> worker_count = 0) -> Result<void>;
|
static auto initialize_scheduler(const u8 worker_count = 0) -> Result<void>;
|
||||||
static auto terminate_scheduler() -> void;
|
static auto terminate_scheduler() -> void;
|
||||||
|
|
||||||
static auto schedule_task(Mut<std::function<void(Const<WorkerId>)>> task,
|
static auto schedule_task(Mut<std::function<void(const WorkerId)>> task,
|
||||||
Const<TaskTag> tag, Mut<Schedule *> schedule,
|
const TaskTag tag, Mut<Schedule *> schedule,
|
||||||
Const<Priority> priority = Priority::Normal)
|
const Priority priority = Priority::Normal) -> void;
|
||||||
-> void;
|
|
||||||
|
|
||||||
static auto cancel_tasks_of_tag(Const<TaskTag> tag) -> void;
|
static auto cancel_tasks_of_tag(const TaskTag tag) -> void;
|
||||||
|
|
||||||
static auto wait_for_schedule_completion(Mut<Schedule *> schedule) -> void;
|
static auto wait_for_schedule_completion(Mut<Schedule *> schedule) -> void;
|
||||||
|
|
||||||
@ -55,11 +54,11 @@ private:
|
|||||||
struct ScheduledTask {
|
struct ScheduledTask {
|
||||||
Mut<TaskTag> tag{};
|
Mut<TaskTag> tag{};
|
||||||
Mut<Schedule *> schedule_handle{};
|
Mut<Schedule *> schedule_handle{};
|
||||||
Mut<std::function<void(Const<WorkerId>)>> task{};
|
Mut<std::function<void(const WorkerId)>> task{};
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto schedule_worker_loop(Mut<std::stop_token> stop_token,
|
static auto schedule_worker_loop(Mut<std::stop_token> stop_token,
|
||||||
Const<WorkerId> worker_id) -> void;
|
const WorkerId worker_id) -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Mut<std::mutex> s_queue_mutex;
|
static Mut<std::mutex> s_queue_mutex;
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class CLIParser {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CLIParser(Const<Span<Const<String>>> args);
|
CLIParser(const Span<const String> args);
|
||||||
~CLIParser() = default;
|
~CLIParser() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -57,7 +57,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Const<Span<Const<String>>> m_arg_list;
|
const Span<const String> m_arg_list;
|
||||||
Mut<Span<Const<String>>::const_iterator> m_current_arg;
|
Mut<Span<const String>::const_iterator> m_current_arg;
|
||||||
};
|
};
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
@ -24,24 +24,22 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static auto hash_fnv1a(Ref<String> string) -> u32;
|
static auto hash_fnv1a(Ref<String> string) -> u32;
|
||||||
static auto hash_fnv1a(Ref<Span<Const<u8>>> data) -> u32;
|
static auto hash_fnv1a(Ref<Span<const u8>> data) -> u32;
|
||||||
|
|
||||||
static auto hash_xxhash(Ref<String> string, Const<u32> seed = 0) -> u32;
|
static auto hash_xxhash(Ref<String> string, const u32 seed = 0) -> u32;
|
||||||
static auto hash_xxhash(Ref<Span<Const<u8>>> data, Const<u32> seed = 0)
|
static auto hash_xxhash(Ref<Span<const u8>> data, const u32 seed = 0) -> u32;
|
||||||
-> u32;
|
|
||||||
|
|
||||||
static auto crc32(Ref<Span<Const<u8>>> data) -> u32;
|
static auto crc32(Ref<Span<const u8>> data) -> u32;
|
||||||
|
|
||||||
static auto detect_compression(Const<Span<Const<u8>>> data)
|
static auto detect_compression(const Span<const u8> data) -> CompressionType;
|
||||||
-> CompressionType;
|
|
||||||
|
|
||||||
static auto gzip_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>>;
|
static auto gzip_inflate(Ref<Span<const u8>> data) -> Result<Vec<u8>>;
|
||||||
static auto gzip_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>>;
|
static auto gzip_deflate(Ref<Span<const u8>> data) -> Result<Vec<u8>>;
|
||||||
|
|
||||||
static auto zlib_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>>;
|
static auto zlib_inflate(Ref<Span<const u8>> data) -> Result<Vec<u8>>;
|
||||||
static auto zlib_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>>;
|
static auto zlib_deflate(Ref<Span<const u8>> data) -> Result<Vec<u8>>;
|
||||||
|
|
||||||
static auto zstd_inflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>>;
|
static auto zstd_inflate(Ref<Span<const u8>> data) -> Result<Vec<u8>>;
|
||||||
static auto zstd_deflate(Ref<Span<Const<u8>>> data) -> Result<Vec<u8>>;
|
static auto zstd_deflate(Ref<Span<const u8>> data) -> Result<Vec<u8>>;
|
||||||
};
|
};
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
@ -43,7 +43,7 @@ public:
|
|||||||
Mut<DynamicLib> lib;
|
Mut<DynamicLib> lib;
|
||||||
|
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Const<HMODULE> h = LoadLibraryA(full_path.string().c_str());
|
const HMODULE h = LoadLibraryA(full_path.string().c_str());
|
||||||
if (!h) {
|
if (!h) {
|
||||||
return fail(get_windows_error());
|
return fail(get_windows_error());
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ public:
|
|||||||
#else
|
#else
|
||||||
Mut<void *> h = dlopen(full_path.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
Mut<void *> h = dlopen(full_path.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||||
if (!h) {
|
if (!h) {
|
||||||
Const<char *> err = dlerror();
|
const char *err = dlerror();
|
||||||
return fail(err ? err : "Unknown dlopen error");
|
return fail(err ? err : "Unknown dlopen error");
|
||||||
}
|
}
|
||||||
lib.m_handle = h;
|
lib.m_handle = h;
|
||||||
@ -96,7 +96,7 @@ public:
|
|||||||
#else
|
#else
|
||||||
dlerror(); // Clear prev errors
|
dlerror(); // Clear prev errors
|
||||||
sym = dlsym(m_handle, name.c_str());
|
sym = dlsym(m_handle, name.c_str());
|
||||||
if (Const<char *> err = dlerror()) {
|
if (const char *err = dlerror()) {
|
||||||
return fail(err);
|
return fail(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -129,19 +129,19 @@ private:
|
|||||||
|
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
static auto get_windows_error() -> String {
|
static auto get_windows_error() -> String {
|
||||||
Const<DWORD> error_id = ::GetLastError();
|
const DWORD error_id = ::GetLastError();
|
||||||
if (error_id == 0) {
|
if (error_id == 0) {
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
Mut<LPSTR> message_buffer = nullptr;
|
Mut<LPSTR> message_buffer = nullptr;
|
||||||
Const<usize> size = FormatMessageA(
|
const usize size = FormatMessageA(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
nullptr, error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
nullptr, error_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
reinterpret_cast<LPSTR>(&message_buffer), 0, nullptr);
|
reinterpret_cast<LPSTR>(&message_buffer), 0, nullptr);
|
||||||
|
|
||||||
Const<String> message(message_buffer, size);
|
const String message(message_buffer, size);
|
||||||
LocalFree(message_buffer);
|
LocalFree(message_buffer);
|
||||||
return "Win32 Error: " + message;
|
return "Win32 Error: " + message;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class Environment {
|
|||||||
public:
|
public:
|
||||||
static auto find(Ref<String> name) -> Option<String> {
|
static auto find(Ref<String> name) -> Option<String> {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Const<u32> buffer_size =
|
const u32 buffer_size =
|
||||||
static_cast<u32>(GetEnvironmentVariableA(name.c_str(), nullptr, 0));
|
static_cast<u32>(GetEnvironmentVariableA(name.c_str(), nullptr, 0));
|
||||||
|
|
||||||
if (buffer_size == 0) {
|
if (buffer_size == 0) {
|
||||||
@ -34,7 +34,7 @@ public:
|
|||||||
Mut<String> result;
|
Mut<String> result;
|
||||||
result.resize(buffer_size);
|
result.resize(buffer_size);
|
||||||
|
|
||||||
Const<u32> actual_size = static_cast<u32>(
|
const u32 actual_size = static_cast<u32>(
|
||||||
GetEnvironmentVariableA(name.c_str(), result.data(), buffer_size));
|
GetEnvironmentVariableA(name.c_str(), result.data(), buffer_size));
|
||||||
|
|
||||||
if (actual_size == 0 || actual_size > buffer_size) {
|
if (actual_size == 0 || actual_size > buffer_size) {
|
||||||
@ -45,7 +45,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
Const<char *> val = std::getenv(name.c_str());
|
const char *val = std::getenv(name.c_str());
|
||||||
if (val == nullptr) {
|
if (val == nullptr) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,11 +22,10 @@
|
|||||||
|
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
using NativeFileHandle = HANDLE;
|
using NativeFileHandle = HANDLE;
|
||||||
static constexpr au::Const<NativeFileHandle> INVALID_FILE_HANDLE =
|
static constexpr NativeFileHandle INVALID_FILE_HANDLE = INVALID_HANDLE_VALUE;
|
||||||
INVALID_HANDLE_VALUE;
|
|
||||||
#else
|
#else
|
||||||
using NativeFileHandle = int;
|
using NativeFileHandle = int;
|
||||||
static constexpr au::Const<NativeFileHandle> INVALID_FILE_HANDLE = -1;
|
static constexpr NativeFileHandle INVALID_FILE_HANDLE = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
@ -49,31 +48,31 @@ public:
|
|||||||
TruncateExisting // Opens existing and clears it
|
TruncateExisting // Opens existing and clears it
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto native_open_file(Ref<Path> path, Const<FileAccess> access,
|
static auto native_open_file(Ref<Path> path, const FileAccess access,
|
||||||
Const<FileMode> mode,
|
const FileMode mode,
|
||||||
Const<u32> permissions = 0644)
|
const u32 permissions = 0644)
|
||||||
-> Result<NativeFileHandle>;
|
-> Result<NativeFileHandle>;
|
||||||
|
|
||||||
static auto native_close_file(Const<NativeFileHandle> handle) -> void;
|
static auto native_close_file(const NativeFileHandle handle) -> void;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static auto normalize_executable_path(Ref<Path> path) -> Path;
|
static auto normalize_executable_path(Ref<Path> path) -> Path;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static auto unmap_file(Const<const u8 *> mapped_ptr) -> void;
|
static auto unmap_file(const u8 *mapped_ptr) -> void;
|
||||||
|
|
||||||
static auto map_file(Ref<Path> path, MutRef<usize> size)
|
static auto map_file(Ref<Path> path, MutRef<usize> size)
|
||||||
-> Result<const u8 *>;
|
-> Result<const u8 *>;
|
||||||
|
|
||||||
// @param `is_owner` true to allocate/truncate. false to just open.
|
// @param `is_owner` true to allocate/truncate. false to just open.
|
||||||
static auto map_shared_memory(Ref<String> name, Const<usize> size,
|
static auto map_shared_memory(Ref<String> name, const usize size,
|
||||||
Const<bool> is_owner) -> Result<u8 *>;
|
const bool is_owner) -> Result<u8 *>;
|
||||||
|
|
||||||
static auto unlink_shared_memory(Ref<String> name) -> void;
|
static auto unlink_shared_memory(Ref<String> name) -> void;
|
||||||
|
|
||||||
static auto stream_from_file(Ref<Path> path) -> Result<StreamReader>;
|
static auto stream_from_file(Ref<Path> path) -> Result<StreamReader>;
|
||||||
|
|
||||||
static auto stream_to_file(Ref<Path> path, Const<bool> overwrite = false)
|
static auto stream_to_file(Ref<Path> path, const bool overwrite = false)
|
||||||
-> Result<StreamWriter>;
|
-> Result<StreamWriter>;
|
||||||
|
|
||||||
static auto read_text_file(Ref<Path> path) -> Result<String>;
|
static auto read_text_file(Ref<Path> path) -> Result<String>;
|
||||||
@ -81,10 +80,10 @@ public:
|
|||||||
static auto read_binary_file(Ref<Path> path) -> Result<Vec<u8>>;
|
static auto read_binary_file(Ref<Path> path) -> Result<Vec<u8>>;
|
||||||
|
|
||||||
static auto write_text_file(Ref<Path> path, Ref<String> contents,
|
static auto write_text_file(Ref<Path> path, Ref<String> contents,
|
||||||
Const<bool> overwrite = false) -> Result<usize>;
|
const bool overwrite = false) -> Result<usize>;
|
||||||
|
|
||||||
static auto write_binary_file(Ref<Path> path, Const<Span<const u8>> contents,
|
static auto write_binary_file(Ref<Path> path, const Span<const u8> contents,
|
||||||
Const<bool> overwrite = false) -> Result<usize>;
|
const bool overwrite = false) -> Result<usize>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Mut<HashMap<const u8 *, std::tuple<void *, void *, void *>>>
|
static Mut<HashMap<const u8 *, std::tuple<void *, void *, void *>>>
|
||||||
@ -103,7 +102,7 @@ public:
|
|||||||
auto operator=(ForwardRef<MemoryMappedRegion> other) noexcept
|
auto operator=(ForwardRef<MemoryMappedRegion> other) noexcept
|
||||||
-> MemoryMappedRegion &;
|
-> MemoryMappedRegion &;
|
||||||
|
|
||||||
auto map(Const<NativeFileHandle> handle, Const<u64> offset, Const<usize> size)
|
auto map(const NativeFileHandle handle, const u64 offset, const usize size)
|
||||||
-> Result<void>;
|
-> Result<void>;
|
||||||
|
|
||||||
auto unmap() -> void;
|
auto unmap() -> void;
|
||||||
|
|||||||
@ -31,20 +31,20 @@ public:
|
|||||||
auto operator=(Ref<HttpClient>) -> MutRef<HttpClient> = delete;
|
auto operator=(Ref<HttpClient>) -> MutRef<HttpClient> = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto raw_get(Ref<String> path, Span<Const<Header>> headers,
|
auto raw_get(Ref<String> path, Span<const Header> headers,
|
||||||
Const<char> *default_content_type =
|
const char *default_content_type =
|
||||||
"application/x-www-form-urlencoded") -> Result<String>;
|
"application/x-www-form-urlencoded") -> Result<String>;
|
||||||
|
|
||||||
auto raw_post(Ref<String> path, Span<Const<Header>> headers, Ref<String> body,
|
auto raw_post(Ref<String> path, Span<const Header> headers, Ref<String> body,
|
||||||
Const<char> *default_content_type =
|
const char *default_content_type =
|
||||||
"application/x-www-form-urlencoded") -> Result<String>;
|
"application/x-www-form-urlencoded") -> Result<String>;
|
||||||
|
|
||||||
template <typename ResponseType>
|
template <typename ResponseType>
|
||||||
auto json_get(Ref<String> path, Span<Const<Header>> headers)
|
auto json_get(Ref<String> path, Span<const Header> headers)
|
||||||
-> Result<ResponseType>;
|
-> Result<ResponseType>;
|
||||||
|
|
||||||
template <typename PayloadType, typename ResponseType>
|
template <typename PayloadType, typename ResponseType>
|
||||||
auto json_post(Ref<String> path, Span<Const<Header>> headers,
|
auto json_post(Ref<String> path, Span<const Header> headers,
|
||||||
Ref<PayloadType> body) -> Result<ResponseType>;
|
Ref<PayloadType> body) -> Result<ResponseType>;
|
||||||
|
|
||||||
// Certificate verification is enabled by default
|
// Certificate verification is enabled by default
|
||||||
@ -66,9 +66,9 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename ResponseType>
|
template <typename ResponseType>
|
||||||
auto HttpClient::json_get(Ref<String> path, Span<Const<Header>> headers)
|
auto HttpClient::json_get(Ref<String> path, Span<const Header> headers)
|
||||||
-> Result<ResponseType> {
|
-> Result<ResponseType> {
|
||||||
Const<String> raw_response =
|
const String raw_response =
|
||||||
AU_TRY(raw_get(path, headers, "application/json"));
|
AU_TRY(raw_get(path, headers, "application/json"));
|
||||||
|
|
||||||
if (last_response_code() != EResponseCode::OK) {
|
if (last_response_code() != EResponseCode::OK) {
|
||||||
@ -79,11 +79,11 @@ auto HttpClient::json_get(Ref<String> path, Span<Const<Header>> headers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename PayloadType, typename ResponseType>
|
template <typename PayloadType, typename ResponseType>
|
||||||
auto HttpClient::json_post(Ref<String> path, Span<Const<Header>> headers,
|
auto HttpClient::json_post(Ref<String> path, Span<const Header> headers,
|
||||||
Ref<PayloadType> body) -> Result<ResponseType> {
|
Ref<PayloadType> body) -> Result<ResponseType> {
|
||||||
Const<String> encoded_body = AU_TRY(Json::encode_struct(body));
|
const String encoded_body = AU_TRY(Json::encode_struct(body));
|
||||||
|
|
||||||
Const<String> raw_response =
|
const String raw_response =
|
||||||
AU_TRY(raw_post(path, headers, encoded_body, "application/json"));
|
AU_TRY(raw_post(path, headers, encoded_body, "application/json"));
|
||||||
|
|
||||||
if (last_response_code() != EResponseCode::OK) {
|
if (last_response_code() != EResponseCode::OK) {
|
||||||
|
|||||||
@ -130,20 +130,20 @@ public:
|
|||||||
static auto url_encode(Ref<String> value) -> String;
|
static auto url_encode(Ref<String> value) -> String;
|
||||||
static auto url_decode(Ref<String> value) -> String;
|
static auto url_decode(Ref<String> value) -> String;
|
||||||
|
|
||||||
static auto header_type_to_string(Const<EHeaderType> type) -> String;
|
static auto header_type_to_string(const EHeaderType type) -> String;
|
||||||
|
|
||||||
static inline auto create_header(Const<EHeaderType> key, Ref<String> value)
|
static inline auto create_header(const EHeaderType key, Ref<String> value)
|
||||||
-> Header;
|
-> Header;
|
||||||
static inline auto create_header(Ref<String> key, Ref<String> value)
|
static inline auto create_header(Ref<String> key, Ref<String> value)
|
||||||
-> Header;
|
-> Header;
|
||||||
|
|
||||||
static auto is_success_response_code(Const<EResponseCode> code) -> bool;
|
static auto is_success_response_code(const EResponseCode code) -> bool;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HttpCommon() = default;
|
HttpCommon() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto HttpCommon::create_header(Const<EHeaderType> key, Ref<String> value)
|
auto HttpCommon::create_header(const EHeaderType key, Ref<String> value)
|
||||||
-> HttpCommon::Header {
|
-> HttpCommon::Header {
|
||||||
return Header{header_type_to_string(key), value};
|
return Header{header_type_to_string(key), value};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ public:
|
|||||||
Mut<String> content_type = "text/plain";
|
Mut<String> content_type = "text/plain";
|
||||||
|
|
||||||
void set_content(Ref<String> content, Ref<String> type);
|
void set_content(Ref<String> content, Ref<String> type);
|
||||||
void set_status(Const<EResponseCode> status_code);
|
void set_status(const EResponseCode status_code);
|
||||||
void add_header(Ref<String> key, Ref<String> value);
|
void add_header(Ref<String> key, Ref<String> value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,25 +62,25 @@ public:
|
|||||||
auto operator=(HttpServer &&) -> HttpServer & = delete;
|
auto operator=(HttpServer &&) -> HttpServer & = delete;
|
||||||
auto operator=(const HttpServer &) -> HttpServer & = delete;
|
auto operator=(const HttpServer &) -> HttpServer & = delete;
|
||||||
|
|
||||||
auto listen(Ref<String> host, Const<u32> port) -> Result<void>;
|
auto listen(Ref<String> host, const u32 port) -> Result<void>;
|
||||||
void stop();
|
void stop();
|
||||||
auto is_running() const -> bool;
|
auto is_running() const -> bool;
|
||||||
|
|
||||||
void get(Ref<String> pattern, Const<Handler> handler);
|
void get(Ref<String> pattern, const Handler handler);
|
||||||
void post(Ref<String> pattern, Const<Handler> handler);
|
void post(Ref<String> pattern, const Handler handler);
|
||||||
void put(Ref<String> pattern, Const<Handler> handler);
|
void put(Ref<String> pattern, const Handler handler);
|
||||||
void del(Ref<String> pattern, Const<Handler> handler);
|
void del(Ref<String> pattern, const Handler handler);
|
||||||
void options(Ref<String> pattern, Const<Handler> handler);
|
void options(Ref<String> pattern, const Handler handler);
|
||||||
|
|
||||||
template <typename ResponseType>
|
template <typename ResponseType>
|
||||||
void
|
void
|
||||||
json_get(Ref<String> pattern,
|
json_get(Ref<String> pattern,
|
||||||
Const<std::function<Result<ResponseType>(Ref<Request>)>> handler);
|
const std::function<Result<ResponseType(Ref<Request>)>> handler);
|
||||||
|
|
||||||
template <typename PayloadType, typename ResponseType>
|
template <typename PayloadType, typename ResponseType>
|
||||||
void json_post(
|
void json_post(
|
||||||
Ref<String> pattern,
|
Ref<String> pattern,
|
||||||
Const<std::function<Result<ResponseType>(Ref<PayloadType>)>> handler);
|
const std::function<Result<ResponseType(Ref<PayloadType>)>> handler);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HttpServer();
|
HttpServer();
|
||||||
@ -89,22 +89,22 @@ private:
|
|||||||
Mut<httplib::Server> m_server;
|
Mut<httplib::Server> m_server;
|
||||||
|
|
||||||
void register_handler(Ref<String> method, Ref<String> pattern,
|
void register_handler(Ref<String> method, Ref<String> pattern,
|
||||||
Const<Handler> handler);
|
const Handler handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ResponseType>
|
template <typename ResponseType>
|
||||||
void HttpServer::json_get(
|
void HttpServer::json_get(
|
||||||
Ref<String> pattern,
|
Ref<String> pattern,
|
||||||
Const<std::function<Result<ResponseType>(Ref<Request>)>> handler) {
|
const std::function<Result<ResponseType(Ref<Request>)>> handler) {
|
||||||
get(pattern, [handler](Ref<Request> req, MutRef<Response> res) {
|
get(pattern, [handler](Ref<Request> req, MutRef<Response> res) {
|
||||||
Const<Result<ResponseType>> result = handler(req);
|
const Result<ResponseType> result = handler(req);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
||||||
res.set_content(result.error(), "text/plain");
|
res.set_content(result.error(), "text/plain");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<Result<String>> json_res = Json::encode_struct(*result);
|
const Result<String> json_res = Json::encode_struct(*result);
|
||||||
if (!json_res) {
|
if (!json_res) {
|
||||||
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
||||||
res.set_content("Failed to encode JSON response", "text/plain");
|
res.set_content("Failed to encode JSON response", "text/plain");
|
||||||
@ -119,9 +119,9 @@ void HttpServer::json_get(
|
|||||||
template <typename PayloadType, typename ResponseType>
|
template <typename PayloadType, typename ResponseType>
|
||||||
void HttpServer::json_post(
|
void HttpServer::json_post(
|
||||||
Ref<String> pattern,
|
Ref<String> pattern,
|
||||||
Const<std::function<Result<ResponseType>(Ref<PayloadType>)>> handler) {
|
const std::function<Result<ResponseType(Ref<PayloadType>)>> handler) {
|
||||||
post(pattern, [handler](Ref<Request> req, MutRef<Response> res) {
|
post(pattern, [handler](Ref<Request> req, MutRef<Response> res) {
|
||||||
Const<Result<PayloadType>> payload =
|
const Result<PayloadType> payload =
|
||||||
Json::parse_to_struct<PayloadType>(req.body);
|
Json::parse_to_struct<PayloadType>(req.body);
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
res.set_status(EResponseCode::BAD_REQUEST);
|
res.set_status(EResponseCode::BAD_REQUEST);
|
||||||
@ -129,14 +129,14 @@ void HttpServer::json_post(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<Result<ResponseType>> result = handler(*payload);
|
const Result<ResponseType> result = handler(*payload);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
||||||
res.set_content(result.error(), "text/plain");
|
res.set_content(result.error(), "text/plain");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<Result<String>> json_res = Json::encode_struct(*result);
|
const Result<String> json_res = Json::encode_struct(*result);
|
||||||
if (!json_res) {
|
if (!json_res) {
|
||||||
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
res.set_status(EResponseCode::INTERNAL_SERVER_ERROR);
|
||||||
res.set_content("Failed to encode JSON response", "text/plain");
|
res.set_content("Failed to encode JSON response", "text/plain");
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
#define IACORE_MAIN() \
|
#define IACORE_MAIN() \
|
||||||
auto _app_entry(IACore::Ref<IACore::Vec<IACore::String>> args) \
|
auto _app_entry(IACore::Ref<IACore::Vec<IACore::String>> args) \
|
||||||
-> IACore::Result<IACore::i32>; \
|
-> IACore::Result<IACore::i32>; \
|
||||||
auto main(Const<int> argc, Mut<char *> argv[]) -> int { \
|
auto main(int argc, Mut<char *> argv[]) -> int { \
|
||||||
IACore::Mut<IACore::i32> exit_code = 0; \
|
IACore::Mut<IACore::i32> exit_code = 0; \
|
||||||
IACore::initialize(); \
|
IACore::initialize(); \
|
||||||
IACore::Mut<IACore::Vec<IACore::String>> args; \
|
IACore::Mut<IACore::Vec<IACore::String>> args; \
|
||||||
@ -29,7 +29,7 @@
|
|||||||
for (IACore::Mut<IACore::i32> i = 0; i < argc; ++i) { \
|
for (IACore::Mut<IACore::i32> i = 0; i < argc; ++i) { \
|
||||||
args.push_back(argv[i]); \
|
args.push_back(argv[i]); \
|
||||||
} \
|
} \
|
||||||
IACore::Const<IACore::Result<IACore::i32>> result = _app_entry(args); \
|
IACore::Result<IACore::i32> result = _app_entry(args); \
|
||||||
if (!result) { \
|
if (!result) { \
|
||||||
IACore::Logger::error("Application exited with an error: '{}'.", \
|
IACore::Logger::error("Application exited with an error: '{}'.", \
|
||||||
result.error()); \
|
result.error()); \
|
||||||
|
|||||||
@ -105,8 +105,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
auto _test_eq(Ref<T1> lhs, Ref<T2> rhs, Const<const char *> description)
|
auto _test_eq(Ref<T1> lhs, Ref<T2> rhs, const char *description) -> bool {
|
||||||
-> bool {
|
|
||||||
if (lhs != rhs) {
|
if (lhs != rhs) {
|
||||||
print_fail(description, to_string(lhs), to_string(rhs));
|
print_fail(description, to_string(lhs), to_string(rhs));
|
||||||
return false;
|
return false;
|
||||||
@ -115,8 +114,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
auto _test_neq(Ref<T1> lhs, Ref<T2> rhs, Const<const char *> description)
|
auto _test_neq(Ref<T1> lhs, Ref<T2> rhs, const char *description) -> bool {
|
||||||
-> bool {
|
|
||||||
if (lhs == rhs) {
|
if (lhs == rhs) {
|
||||||
print_fail(description, to_string(lhs), "NOT " + to_string(rhs));
|
print_fail(description, to_string(lhs), "NOT " + to_string(rhs));
|
||||||
return false;
|
return false;
|
||||||
@ -125,11 +123,10 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto _test_approx(Const<T> lhs, Const<T> rhs, Const<const char *> description)
|
auto _test_approx(const T lhs, const T rhs, const char *description) -> bool {
|
||||||
-> bool {
|
|
||||||
static_assert(std::is_floating_point_v<T>,
|
static_assert(std::is_floating_point_v<T>,
|
||||||
"Approx only works for floats/doubles");
|
"Approx only works for floats/doubles");
|
||||||
Const<T> diff = std::abs(lhs - rhs);
|
const T diff = std::abs(lhs - rhs);
|
||||||
if (diff > static_cast<T>(0.0001)) {
|
if (diff > static_cast<T>(0.0001)) {
|
||||||
print_fail(description, to_string(lhs), to_string(rhs));
|
print_fail(description, to_string(lhs), to_string(rhs));
|
||||||
return false;
|
return false;
|
||||||
@ -137,7 +134,7 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _test(Const<bool> value, Const<const char *> description) -> bool {
|
auto _test(const bool value, const char *description) -> bool {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
std::cout << console::BLUE << " " << description << "... "
|
std::cout << console::BLUE << " " << description << "... "
|
||||||
<< console::RED << "FAILED" << console::RESET << "\n";
|
<< console::RED << "FAILED" << console::RESET << "\n";
|
||||||
@ -146,7 +143,7 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _test_not(Const<bool> value, Const<const char *> description) -> bool {
|
auto _test_not(const bool value, const char *description) -> bool {
|
||||||
if (value) {
|
if (value) {
|
||||||
std::cout << console::BLUE << " " << description << "... "
|
std::cout << console::BLUE << " " << description << "... "
|
||||||
<< console::RED << "FAILED" << console::RESET << "\n";
|
<< console::RED << "FAILED" << console::RESET << "\n";
|
||||||
@ -155,13 +152,12 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _test_unit(Mut<TestFunctor> functor, Const<const char *> name) -> void {
|
auto _test_unit(Mut<TestFunctor> functor, const char *name) -> void {
|
||||||
m_units.push_back({name, std::move(functor)});
|
m_units.push_back({name, std::move(functor)});
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto print_fail(Const<const char *> desc, Ref<String> v1, Ref<String> v2)
|
auto print_fail(const char *desc, Ref<String> v1, Ref<String> v2) -> void {
|
||||||
-> void {
|
|
||||||
std::cout << console::BLUE << " " << desc << "... " << console::RED
|
std::cout << console::BLUE << " " << desc << "... " << console::RED
|
||||||
<< "FAILED" << console::RESET << "\n";
|
<< "FAILED" << console::RESET << "\n";
|
||||||
std::cout << console::RED << " Expected: " << v2 << console::RESET
|
std::cout << console::RED << " Expected: " << v2 << console::RESET
|
||||||
@ -215,7 +211,7 @@ auto Runner<StopOnFail, IsVerbose>::test_block() -> void {
|
|||||||
<< console::RESET;
|
<< console::RESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
Const<bool> result = v.functor();
|
const bool result = v.functor();
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
m_fail_count++;
|
m_fail_count++;
|
||||||
@ -237,7 +233,7 @@ auto Runner<StopOnFail, IsVerbose>::summarize() -> void {
|
|||||||
if (m_fail_count == 0) {
|
if (m_fail_count == 0) {
|
||||||
std::cout << "\n\tALL TESTS PASSED!\n\n";
|
std::cout << "\n\tALL TESTS PASSED!\n\n";
|
||||||
} else {
|
} else {
|
||||||
Const<f64> success_rate =
|
const f64 success_rate =
|
||||||
(100.0 * static_cast<f64>(m_test_count - m_fail_count) /
|
(100.0 * static_cast<f64>(m_test_count - m_fail_count) /
|
||||||
static_cast<f64>(m_test_count));
|
static_cast<f64>(m_test_count));
|
||||||
std::cout << console::RED << m_fail_count << " OF " << m_test_count
|
std::cout << console::RED << m_fail_count << " OF " << m_test_count
|
||||||
|
|||||||
@ -35,7 +35,7 @@ struct alignas(64) IpcSharedMemoryLayout {
|
|||||||
Mut<Header> meta;
|
Mut<Header> meta;
|
||||||
|
|
||||||
// Pad to ensure MONI starts on a fresh cache line (64 bytes)
|
// Pad to ensure MONI starts on a fresh cache line (64 bytes)
|
||||||
Const<Array<u8, 64 - sizeof(Header)>> _pad0;
|
const Array<u8, 64 - sizeof(Header)> _pad0;
|
||||||
|
|
||||||
// =========================================================
|
// =========================================================
|
||||||
// RING BUFFER CONTROL BLOCKS
|
// RING BUFFER CONTROL BLOCKS
|
||||||
@ -56,7 +56,7 @@ struct alignas(64) IpcSharedMemoryLayout {
|
|||||||
Mut<u64> mino_data_size;
|
Mut<u64> mino_data_size;
|
||||||
|
|
||||||
// Pad to ensure the actual Data Buffer starts on a fresh cache line
|
// Pad to ensure the actual Data Buffer starts on a fresh cache line
|
||||||
Const<Array<u8, 64 - (sizeof(u64) * 4)>> _pad1;
|
const Array<u8, 64 - (sizeof(u64) * 4)> _pad1;
|
||||||
|
|
||||||
static constexpr auto get_header_size() -> usize {
|
static constexpr auto get_header_size() -> usize {
|
||||||
return sizeof(IpcSharedMemoryLayout);
|
return sizeof(IpcSharedMemoryLayout);
|
||||||
@ -73,17 +73,17 @@ public:
|
|||||||
|
|
||||||
// When Manager spawns a node, `connection_string` is passed
|
// When Manager spawns a node, `connection_string` is passed
|
||||||
// as the first command line argument
|
// as the first command line argument
|
||||||
auto connect(Const<const char *> connection_string) -> Result<void>;
|
auto connect(const char *connection_string) -> Result<void>;
|
||||||
|
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
auto send_signal(Const<u8> signal) -> void;
|
auto send_signal(const u8 signal) -> void;
|
||||||
auto send_packet(Const<u16> packet_id, Const<Span<Const<u8>>> payload)
|
auto send_packet(const u16 packet_id, const Span<const u8> payload)
|
||||||
-> Result<void>;
|
-> Result<void>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual auto on_signal(Const<u8> signal) -> void = 0;
|
virtual auto on_signal(const u8 signal) -> void = 0;
|
||||||
virtual auto on_packet(Const<u16> packet_id, Const<Span<Const<u8>>> payload)
|
virtual auto on_packet(const u16 packet_id, const Span<const u8> payload)
|
||||||
-> void = 0;
|
-> void = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -116,13 +116,13 @@ class IpcManager {
|
|||||||
|
|
||||||
Mut<bool> is_ready{false};
|
Mut<bool> is_ready{false};
|
||||||
|
|
||||||
auto send_signal(Const<u8> signal) -> void;
|
auto send_signal(const u8 signal) -> void;
|
||||||
auto send_packet(Const<u16> packet_id, Const<Span<Const<u8>>> payload)
|
auto send_packet(const u16 packet_id, const Span<const u8> payload)
|
||||||
-> Result<void>;
|
-> Result<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr Const<u32> DEFAULT_NODE_SHARED_MEMORY_SIZE = 4 * 1024 * 1024;
|
static constexpr const u32 DEFAULT_NODE_SHARED_MEMORY_SIZE = 4 * 1024 * 1024;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~IpcManager();
|
virtual ~IpcManager();
|
||||||
@ -131,22 +131,22 @@ public:
|
|||||||
|
|
||||||
auto
|
auto
|
||||||
spawn_node(Ref<Path> executable_path,
|
spawn_node(Ref<Path> executable_path,
|
||||||
Const<u32> shared_memory_size = DEFAULT_NODE_SHARED_MEMORY_SIZE)
|
const u32 shared_memory_size = DEFAULT_NODE_SHARED_MEMORY_SIZE)
|
||||||
-> Result<NativeProcessID>;
|
-> Result<NativeProcessID>;
|
||||||
|
|
||||||
auto wait_till_node_is_online(Const<NativeProcessID> node) -> bool;
|
auto wait_till_node_is_online(const NativeProcessID node) -> bool;
|
||||||
|
|
||||||
auto shutdown_node(Const<NativeProcessID> node) -> void;
|
auto shutdown_node(const NativeProcessID node) -> void;
|
||||||
|
|
||||||
auto send_signal(Const<NativeProcessID> node, Const<u8> signal) -> void;
|
auto send_signal(const NativeProcessID node, const u8 signal) -> void;
|
||||||
auto send_packet(Const<NativeProcessID> node, Const<u16> packet_id,
|
auto send_packet(const NativeProcessID node, const u16 packet_id,
|
||||||
Const<Span<Const<u8>>> payload) -> Result<void>;
|
const Span<const u8> payload) -> Result<void>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual auto on_signal(Const<NativeProcessID> node, Const<u8> signal)
|
virtual auto on_signal(const NativeProcessID node, const u8 signal)
|
||||||
-> void = 0;
|
-> void = 0;
|
||||||
virtual auto on_packet(Const<NativeProcessID> node, Const<u16> packet_id,
|
virtual auto on_packet(const NativeProcessID node, const u16 packet_id,
|
||||||
Const<Span<Const<u8>>> payload) -> void = 0;
|
const Span<const u8> payload) -> void = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mut<Vec<u8>> m_receive_buffer;
|
Mut<Vec<u8>> m_receive_buffer;
|
||||||
|
|||||||
@ -48,7 +48,7 @@ private:
|
|||||||
|
|
||||||
class Json {
|
class Json {
|
||||||
private:
|
private:
|
||||||
static constexpr Const<glz::opts> GLAZE_OPTS =
|
static constexpr const glz::opts GLAZE_OPTS =
|
||||||
glz::opts{.error_on_unknown_keys = false};
|
glz::opts{.error_on_unknown_keys = false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -65,7 +65,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline auto Json::parse(Ref<String> json_str) -> Result<nlohmann::json> {
|
inline auto Json::parse(Ref<String> json_str) -> Result<nlohmann::json> {
|
||||||
Const<nlohmann::json> res =
|
const nlohmann::json res =
|
||||||
nlohmann::json::parse(json_str, nullptr, false, true);
|
nlohmann::json::parse(json_str, nullptr, false, true);
|
||||||
|
|
||||||
if (res.is_discarded()) {
|
if (res.is_discarded()) {
|
||||||
@ -80,7 +80,7 @@ inline auto Json::parse_read_only(Ref<String> json_str)
|
|||||||
|
|
||||||
Mut<simdjson::dom::element> root;
|
Mut<simdjson::dom::element> root;
|
||||||
|
|
||||||
Const<simdjson::error_code> error = parser->parse(json_str).get(root);
|
const simdjson::error_code error = parser->parse(json_str).get(root);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return fail("JSON Error: {}", simdjson::error_message(error));
|
return fail("JSON Error: {}", simdjson::error_message(error));
|
||||||
@ -97,7 +97,7 @@ template <typename T>
|
|||||||
inline auto Json::parse_to_struct(Ref<String> json_str) -> Result<T> {
|
inline auto Json::parse_to_struct(Ref<String> json_str) -> Result<T> {
|
||||||
Mut<T> result{};
|
Mut<T> result{};
|
||||||
|
|
||||||
Const<glz::error_ctx> err = glz::read<GLAZE_OPTS>(result, json_str);
|
const glz::error_ctx err = glz::read<GLAZE_OPTS>(result, json_str);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return fail("JSON Struct Parse Error: {}",
|
return fail("JSON Struct Parse Error: {}",
|
||||||
@ -109,7 +109,7 @@ inline auto Json::parse_to_struct(Ref<String> json_str) -> Result<T> {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline auto Json::encode_struct(Ref<T> data) -> Result<String> {
|
inline auto Json::encode_struct(Ref<T> data) -> Result<String> {
|
||||||
Mut<String> result;
|
Mut<String> result;
|
||||||
Const<glz::error_ctx> err = glz::write_json(data, result);
|
const glz::error_ctx err = glz::write_json(data, result);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return fail("JSON Struct Encode Error");
|
return fail("JSON Struct Encode Error");
|
||||||
|
|||||||
@ -33,36 +33,35 @@ public:
|
|||||||
enum class LogLevel { Trace, Debug, Info, Warn, Error };
|
enum class LogLevel { Trace, Debug, Info, Warn, Error };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static auto enable_logging_to_disk(Const<const char *> file_path)
|
static auto enable_logging_to_disk(const char *file_path) -> Result<void>;
|
||||||
-> Result<void>;
|
static auto set_log_level(const LogLevel log_level) -> void;
|
||||||
static auto set_log_level(Const<LogLevel> log_level) -> void;
|
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static auto trace(Const<std::format_string<Args...>> fmt,
|
static auto trace(const std::format_string<Args...> fmt,
|
||||||
ForwardRef<Args>... args) -> void {
|
ForwardRef<Args>... args) -> void {
|
||||||
log_trace(std::vformat(fmt.get(), std::make_format_args(args...)));
|
log_trace(std::vformat(fmt.get(), std::make_format_args(args...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static auto debug(Const<std::format_string<Args...>> fmt,
|
static auto debug(const std::format_string<Args...> fmt,
|
||||||
ForwardRef<Args>... args) -> void {
|
ForwardRef<Args>... args) -> void {
|
||||||
log_debug(std::vformat(fmt.get(), std::make_format_args(args...)));
|
log_debug(std::vformat(fmt.get(), std::make_format_args(args...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static auto info(Const<std::format_string<Args...>> fmt,
|
static auto info(const std::format_string<Args...> fmt,
|
||||||
ForwardRef<Args>... args) -> void {
|
ForwardRef<Args>... args) -> void {
|
||||||
log_info(std::vformat(fmt.get(), std::make_format_args(args...)));
|
log_info(std::vformat(fmt.get(), std::make_format_args(args...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static auto warn(Const<std::format_string<Args...>> fmt,
|
static auto warn(const std::format_string<Args...> fmt,
|
||||||
ForwardRef<Args>... args) -> void {
|
ForwardRef<Args>... args) -> void {
|
||||||
log_warn(std::vformat(fmt.get(), std::make_format_args(args...)));
|
log_warn(std::vformat(fmt.get(), std::make_format_args(args...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static auto error(Const<std::format_string<Args...>> fmt,
|
static auto error(const std::format_string<Args...> fmt,
|
||||||
ForwardRef<Args>... args) -> void {
|
ForwardRef<Args>... args) -> void {
|
||||||
log_error(std::vformat(fmt.get(), std::make_format_args(args...)));
|
log_error(std::vformat(fmt.get(), std::make_format_args(args...)));
|
||||||
}
|
}
|
||||||
@ -107,7 +106,7 @@ private:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static auto log_internal(Const<const char *> prefix, Const<const char *> tag,
|
static auto log_internal(const char *prefix, const char *tag,
|
||||||
ForwardRef<String> msg) -> void;
|
ForwardRef<String> msg) -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -82,14 +82,14 @@ namespace Env {
|
|||||||
using namespace Auxid::Env;
|
using namespace Auxid::Env;
|
||||||
|
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
constexpr Const<bool> IS_WINDOWS = true;
|
constexpr const bool IS_WINDOWS = true;
|
||||||
constexpr Const<bool> IS_UNIX = false;
|
constexpr const bool IS_UNIX = false;
|
||||||
#else
|
#else
|
||||||
constexpr Const<bool> IS_WINDOWS = false;
|
constexpr const bool IS_WINDOWS = false;
|
||||||
constexpr Const<bool> IS_UNIX = true;
|
constexpr const bool IS_UNIX = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr Const<usize> MAX_PATH_LEN = 4096;
|
constexpr const usize MAX_PATH_LEN = 4096;
|
||||||
|
|
||||||
} // namespace Env
|
} // namespace Env
|
||||||
|
|
||||||
@ -120,13 +120,13 @@ struct Version {
|
|||||||
// Console Colors
|
// Console Colors
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
namespace console {
|
namespace console {
|
||||||
constexpr Const<const char *> RESET = "\033[0m";
|
constexpr const char *RESET = "\033[0m";
|
||||||
constexpr Const<const char *> RED = "\033[31m";
|
constexpr const char *RED = "\033[31m";
|
||||||
constexpr Const<const char *> GREEN = "\033[32m";
|
constexpr const char *GREEN = "\033[32m";
|
||||||
constexpr Const<const char *> YELLOW = "\033[33m";
|
constexpr const char *YELLOW = "\033[33m";
|
||||||
constexpr Const<const char *> BLUE = "\033[34m";
|
constexpr const char *BLUE = "\033[34m";
|
||||||
constexpr Const<const char *> MAGENTA = "\033[35m";
|
constexpr const char *MAGENTA = "\033[35m";
|
||||||
constexpr Const<const char *> CYAN = "\033[36m";
|
constexpr const char *CYAN = "\033[36m";
|
||||||
} // namespace console
|
} // namespace console
|
||||||
|
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
|
|||||||
@ -37,8 +37,8 @@ public:
|
|||||||
static auto check_cpu() -> bool;
|
static auto check_cpu() -> bool;
|
||||||
|
|
||||||
#if IA_ARCH_X64
|
#if IA_ARCH_X64
|
||||||
static auto cpuid(Const<i32> function, Const<i32> sub_function,
|
static auto cpuid(const i32 function, const i32 sub_function, Mut<i32 *> out)
|
||||||
Mut<i32 *> out) -> void;
|
-> void;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static auto get_architecture_name() -> const char *;
|
static auto get_architecture_name() -> const char *;
|
||||||
|
|||||||
@ -44,13 +44,13 @@ public:
|
|||||||
|
|
||||||
static auto spawn_process_sync(
|
static auto spawn_process_sync(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback)
|
const std::function<void(StringView)> on_output_line_callback)
|
||||||
-> Result<i32>;
|
-> Result<i32>;
|
||||||
|
|
||||||
static auto spawn_process_async(
|
static auto spawn_process_async(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback,
|
const std::function<void(StringView)> on_output_line_callback,
|
||||||
Const<std::function<void(Const<Result<i32>>)>> on_finish_callback)
|
const std::function<void(Result<i32>)> on_finish_callback)
|
||||||
-> Result<Box<ProcessHandle>>;
|
-> Result<Box<ProcessHandle>>;
|
||||||
|
|
||||||
static auto terminate_process(Ref<Box<ProcessHandle>> handle) -> void;
|
static auto terminate_process(Ref<Box<ProcessHandle>> handle) -> void;
|
||||||
@ -58,12 +58,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
static auto spawn_process_windows(
|
static auto spawn_process_windows(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback,
|
const std::function<void(StringView)> on_output_line_callback,
|
||||||
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32>;
|
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32>;
|
||||||
|
|
||||||
static auto spawn_process_posix(
|
static auto spawn_process_posix(
|
||||||
Ref<String> command, Ref<String> args,
|
Ref<String> command, Ref<String> args,
|
||||||
Const<std::function<void(Const<StringView>)>> on_output_line_callback,
|
const std::function<void(StringView)> on_output_line_callback,
|
||||||
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32>;
|
MutRef<std::atomic<NativeProcessID>> id) -> Result<i32>;
|
||||||
};
|
};
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
@ -41,10 +41,9 @@ class alignas(16) IntVec4 {
|
|||||||
public:
|
public:
|
||||||
IntVec4() = default;
|
IntVec4() = default;
|
||||||
|
|
||||||
inline explicit IntVec4(Const<u32> s);
|
inline explicit IntVec4(const u32 s);
|
||||||
inline explicit IntVec4(Const<const u32 *> values);
|
inline explicit IntVec4(const u32 *values);
|
||||||
inline explicit IntVec4(Const<u32> a, Const<u32> b, Const<u32> c,
|
inline explicit IntVec4(const u32 a, const u32 b, const u32 c, const u32 d);
|
||||||
Const<u32> d);
|
|
||||||
|
|
||||||
inline auto operator+(Ref<IntVec4> other) const -> IntVec4;
|
inline auto operator+(Ref<IntVec4> other) const -> IntVec4;
|
||||||
inline auto operator-(Ref<IntVec4> other) const -> IntVec4;
|
inline auto operator-(Ref<IntVec4> other) const -> IntVec4;
|
||||||
@ -55,44 +54,43 @@ public:
|
|||||||
inline auto operator^(Ref<IntVec4> other) const -> IntVec4;
|
inline auto operator^(Ref<IntVec4> other) const -> IntVec4;
|
||||||
inline auto operator~() const -> IntVec4;
|
inline auto operator~() const -> IntVec4;
|
||||||
|
|
||||||
inline auto operator<<(Const<u32> amount) const -> IntVec4;
|
inline auto operator<<(const u32 amount) const -> IntVec4;
|
||||||
inline auto operator>>(Const<u32> amount) const -> IntVec4;
|
inline auto operator>>(const u32 amount) const -> IntVec4;
|
||||||
|
|
||||||
[[nodiscard]] inline auto sat_add(Ref<IntVec4> other) const -> IntVec4;
|
[[nodiscard]] inline auto sat_add(Ref<IntVec4> other) const -> IntVec4;
|
||||||
[[nodiscard]] inline auto sat_sub(Ref<IntVec4> other) const -> IntVec4;
|
[[nodiscard]] inline auto sat_sub(Ref<IntVec4> other) const -> IntVec4;
|
||||||
|
|
||||||
[[nodiscard]] inline auto clamp(Const<u32> min, Const<u32> max) const
|
[[nodiscard]] inline auto clamp(const u32 min, const u32 max) const
|
||||||
-> IntVec4;
|
-> IntVec4;
|
||||||
|
|
||||||
[[nodiscard]] inline auto mult_add(Ref<IntVec4> multiplier,
|
[[nodiscard]] inline auto mult_add(Ref<IntVec4> multiplier,
|
||||||
Ref<IntVec4> addend) const -> IntVec4;
|
Ref<IntVec4> addend) const -> IntVec4;
|
||||||
|
|
||||||
inline auto store(Mut<u32 *> values) -> void;
|
inline auto store(Mut<u32 *> values) -> void;
|
||||||
static inline auto load(Const<const u32 *> values) -> IntVec4;
|
static inline auto load(const u32 *values) -> IntVec4;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Tag = hn::FixedTag<u32, 4>;
|
using Tag = hn::FixedTag<u32, 4>;
|
||||||
|
|
||||||
Mut<hn::Vec<Tag>> m_data;
|
Mut<hn::Vec<Tag>> m_data;
|
||||||
|
|
||||||
inline explicit IntVec4(Const<hn::Vec<Tag>> v) : m_data(v) {}
|
inline explicit IntVec4(const hn::Vec<Tag> v) : m_data(v) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class alignas(16) FloatVec4 {
|
class alignas(16) FloatVec4 {
|
||||||
public:
|
public:
|
||||||
FloatVec4() = default;
|
FloatVec4() = default;
|
||||||
|
|
||||||
inline explicit FloatVec4(Const<f32> s);
|
inline explicit FloatVec4(const f32 s);
|
||||||
inline explicit FloatVec4(Const<const f32 *> values);
|
inline explicit FloatVec4(const f32 *values);
|
||||||
inline explicit FloatVec4(Const<f32> a, Const<f32> b, Const<f32> c,
|
inline explicit FloatVec4(const f32 a, const f32 b, const f32 c, const f32 d);
|
||||||
Const<f32> d);
|
|
||||||
|
|
||||||
inline auto operator+(Ref<FloatVec4> other) const -> FloatVec4;
|
inline auto operator+(Ref<FloatVec4> other) const -> FloatVec4;
|
||||||
inline auto operator-(Ref<FloatVec4> other) const -> FloatVec4;
|
inline auto operator-(Ref<FloatVec4> other) const -> FloatVec4;
|
||||||
inline auto operator*(Ref<FloatVec4> other) const -> FloatVec4;
|
inline auto operator*(Ref<FloatVec4> other) const -> FloatVec4;
|
||||||
inline auto operator/(Ref<FloatVec4> other) const -> FloatVec4;
|
inline auto operator/(Ref<FloatVec4> other) const -> FloatVec4;
|
||||||
|
|
||||||
[[nodiscard]] inline auto clamp(Const<f32> min, Const<f32> max) const
|
[[nodiscard]] inline auto clamp(const f32 min, const f32 max) const
|
||||||
-> FloatVec4;
|
-> FloatVec4;
|
||||||
|
|
||||||
[[nodiscard]] inline auto abs() const -> FloatVec4;
|
[[nodiscard]] inline auto abs() const -> FloatVec4;
|
||||||
@ -106,30 +104,30 @@ public:
|
|||||||
Ref<FloatVec4> addend) const -> FloatVec4;
|
Ref<FloatVec4> addend) const -> FloatVec4;
|
||||||
|
|
||||||
inline auto store(Mut<f32 *> values) -> void;
|
inline auto store(Mut<f32 *> values) -> void;
|
||||||
static inline auto load(Const<const f32 *> values) -> FloatVec4;
|
static inline auto load(const f32 *values) -> FloatVec4;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Tag = hn::FixedTag<f32, 4>;
|
using Tag = hn::FixedTag<f32, 4>;
|
||||||
|
|
||||||
Mut<hn::Vec<Tag>> m_data;
|
Mut<hn::Vec<Tag>> m_data;
|
||||||
|
|
||||||
inline explicit FloatVec4(Const<hn::Vec<Tag>> v) : m_data(v) {}
|
inline explicit FloatVec4(const hn::Vec<Tag> v) : m_data(v) {}
|
||||||
};
|
};
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
IntVec4::IntVec4(Const<u32> s) {
|
IntVec4::IntVec4(const u32 s) {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
m_data = hn::Set(d, s);
|
m_data = hn::Set(d, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntVec4::IntVec4(Const<const u32 *> values) {
|
IntVec4::IntVec4(const u32 *values) {
|
||||||
Const<Tag> data;
|
const Tag data;
|
||||||
m_data = hn::Load(data, values);
|
m_data = hn::Load(data, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
IntVec4::IntVec4(Const<u32> a, Const<u32> b, Const<u32> c, Const<u32> d) {
|
IntVec4::IntVec4(const u32 a, const u32 b, const u32 c, const u32 d) {
|
||||||
Const<Tag> data;
|
const Tag data;
|
||||||
alignas(16) Mut<Array<u32, 4>> values = {a, b, c, d};
|
alignas(16) Mut<Array<u32, 4>> values = {a, b, c, d};
|
||||||
m_data = hn::Load(data, values.data());
|
m_data = hn::Load(data, values.data());
|
||||||
}
|
}
|
||||||
@ -160,11 +158,11 @@ auto IntVec4::operator^(Ref<IntVec4> other) const -> IntVec4 {
|
|||||||
|
|
||||||
auto IntVec4::operator~() const -> IntVec4 { return IntVec4(hn::Not(m_data)); }
|
auto IntVec4::operator~() const -> IntVec4 { return IntVec4(hn::Not(m_data)); }
|
||||||
|
|
||||||
auto IntVec4::operator<<(Const<u32> amount) const -> IntVec4 {
|
auto IntVec4::operator<<(const u32 amount) const -> IntVec4 {
|
||||||
return IntVec4(hn::ShiftLeftSame(m_data, amount));
|
return IntVec4(hn::ShiftLeftSame(m_data, amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IntVec4::operator>>(Const<u32> amount) const -> IntVec4 {
|
auto IntVec4::operator>>(const u32 amount) const -> IntVec4 {
|
||||||
return IntVec4(hn::ShiftRightSame(m_data, amount));
|
return IntVec4(hn::ShiftRightSame(m_data, amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,37 +179,37 @@ auto IntVec4::sat_sub(Ref<IntVec4> other) const -> IntVec4 {
|
|||||||
return IntVec4(hn::SaturatedSub(m_data, other.m_data));
|
return IntVec4(hn::SaturatedSub(m_data, other.m_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IntVec4::clamp(Const<u32> min, Const<u32> max) const -> IntVec4 {
|
auto IntVec4::clamp(const u32 min, const u32 max) const -> IntVec4 {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
Const<hn::Vec<Tag>> v_min = hn::Set(d, min);
|
const hn::Vec<Tag> v_min = hn::Set(d, min);
|
||||||
Const<hn::Vec<Tag>> v_max = hn::Set(d, max);
|
const hn::Vec<Tag> v_max = hn::Set(d, max);
|
||||||
return IntVec4(hn::Min(hn::Max(m_data, v_min), v_max));
|
return IntVec4(hn::Min(hn::Max(m_data, v_min), v_max));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IntVec4::store(Mut<u32 *> values) -> void {
|
auto IntVec4::store(Mut<u32 *> values) -> void {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
hn::Store(m_data, d, values);
|
hn::Store(m_data, d, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IntVec4::load(Const<const u32 *> values) -> IntVec4 {
|
auto IntVec4::load(const u32 *values) -> IntVec4 {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
return IntVec4(hn::Load(d, values));
|
return IntVec4(hn::Load(d, values));
|
||||||
}
|
}
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
|
|
||||||
namespace IACore {
|
namespace IACore {
|
||||||
FloatVec4::FloatVec4(Const<f32> s) {
|
FloatVec4::FloatVec4(const f32 s) {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
m_data = hn::Set(d, s);
|
m_data = hn::Set(d, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatVec4::FloatVec4(Const<const f32 *> values) {
|
FloatVec4::FloatVec4(const f32 *values) {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
m_data = hn::Load(d, values);
|
m_data = hn::Load(d, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatVec4::FloatVec4(Const<f32> a, Const<f32> b, Const<f32> c, Const<f32> d) {
|
FloatVec4::FloatVec4(const f32 a, const f32 b, const f32 c, const f32 d) {
|
||||||
Const<Tag> data;
|
const Tag data;
|
||||||
alignas(16) Mut<Array<f32, 4>> temp = {a, b, c, d};
|
alignas(16) Mut<Array<f32, 4>> temp = {a, b, c, d};
|
||||||
m_data = hn::Load(data, temp.data());
|
m_data = hn::Load(data, temp.data());
|
||||||
}
|
}
|
||||||
@ -237,10 +235,10 @@ auto FloatVec4::mult_add(Ref<FloatVec4> multiplier, Ref<FloatVec4> addend) const
|
|||||||
return FloatVec4(hn::MulAdd(m_data, multiplier.m_data, addend.m_data));
|
return FloatVec4(hn::MulAdd(m_data, multiplier.m_data, addend.m_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FloatVec4::clamp(Const<f32> min, Const<f32> max) const -> FloatVec4 {
|
auto FloatVec4::clamp(const f32 min, const f32 max) const -> FloatVec4 {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
Const<hn::Vec<Tag>> v_min = hn::Set(d, min);
|
const hn::Vec<Tag> v_min = hn::Set(d, min);
|
||||||
Const<hn::Vec<Tag>> v_max = hn::Set(d, max);
|
const hn::Vec<Tag> v_max = hn::Set(d, max);
|
||||||
return FloatVec4(hn::Min(hn::Max(m_data, v_min), v_max));
|
return FloatVec4(hn::Min(hn::Max(m_data, v_min), v_max));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,26 +253,26 @@ auto FloatVec4::rsqrt() const -> FloatVec4 {
|
|||||||
auto FloatVec4::abs() const -> FloatVec4 { return FloatVec4(hn::Abs(m_data)); }
|
auto FloatVec4::abs() const -> FloatVec4 { return FloatVec4(hn::Abs(m_data)); }
|
||||||
|
|
||||||
auto FloatVec4::dot(Ref<FloatVec4> other) const -> f32 {
|
auto FloatVec4::dot(Ref<FloatVec4> other) const -> f32 {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
Const<hn::Vec<Tag>> v_mul = hn::Mul(m_data, other.m_data);
|
const hn::Vec<Tag> v_mul = hn::Mul(m_data, other.m_data);
|
||||||
return hn::ReduceSum(d, v_mul);
|
return hn::ReduceSum(d, v_mul);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FloatVec4::normalize() const -> FloatVec4 {
|
auto FloatVec4::normalize() const -> FloatVec4 {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
Const<hn::Vec<Tag>> v_mul = hn::Mul(m_data, m_data);
|
const hn::Vec<Tag> v_mul = hn::Mul(m_data, m_data);
|
||||||
Const<hn::Vec<Tag>> v_len_sq = hn::SumOfLanes(d, v_mul);
|
const hn::Vec<Tag> v_len_sq = hn::SumOfLanes(d, v_mul);
|
||||||
Const<hn::Vec<Tag>> v_inv_len = hn::ApproximateReciprocalSqrt(v_len_sq);
|
const hn::Vec<Tag> v_inv_len = hn::ApproximateReciprocalSqrt(v_len_sq);
|
||||||
return FloatVec4(hn::Mul(m_data, v_inv_len));
|
return FloatVec4(hn::Mul(m_data, v_inv_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FloatVec4::store(Mut<f32 *> values) -> void {
|
auto FloatVec4::store(Mut<f32 *> values) -> void {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
hn::Store(m_data, d, values);
|
hn::Store(m_data, d, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto FloatVec4::load(Const<const f32 *> values) -> FloatVec4 {
|
auto FloatVec4::load(const f32 *values) -> FloatVec4 {
|
||||||
Const<Tag> d;
|
const Tag d;
|
||||||
return FloatVec4(hn::Load(d, values));
|
return FloatVec4(hn::Load(d, values));
|
||||||
}
|
}
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
}
|
}
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
Mut<WSADATA> wsa_data;
|
Mut<WSADATA> wsa_data;
|
||||||
Const<i32> res = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
const i32 res = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
s_init_count--;
|
s_init_count--;
|
||||||
return fail("WSAStartup failed with error: {}", res);
|
return fail("WSAStartup failed with error: {}", res);
|
||||||
@ -77,29 +77,29 @@ public:
|
|||||||
|
|
||||||
static auto is_initialized() -> bool { return s_init_count > 0; }
|
static auto is_initialized() -> bool { return s_init_count > 0; }
|
||||||
|
|
||||||
static auto is_port_available_tcp(Const<u16> port) -> bool {
|
static auto is_port_available_tcp(const u16 port) -> bool {
|
||||||
return is_port_available(port, SOCK_STREAM);
|
return is_port_available(port, SOCK_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto is_port_available_udp(Const<u16> port) -> bool {
|
static auto is_port_available_udp(const u16 port) -> bool {
|
||||||
return is_port_available(port, SOCK_DGRAM);
|
return is_port_available(port, SOCK_DGRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto is_would_block() -> bool;
|
static auto is_would_block() -> bool;
|
||||||
|
|
||||||
static auto close(Const<SocketHandle> sock) -> void;
|
static auto close(const SocketHandle sock) -> void;
|
||||||
|
|
||||||
static auto listen(Const<SocketHandle> sock, Const<i32> queue_size = 5)
|
static auto listen(const SocketHandle sock, const i32 queue_size = 5)
|
||||||
-> Result<void>;
|
-> Result<void>;
|
||||||
|
|
||||||
static auto create_unix_socket() -> Result<SocketHandle>;
|
static auto create_unix_socket() -> Result<SocketHandle>;
|
||||||
|
|
||||||
static auto bind_unix_socket(Const<SocketHandle> sock,
|
static auto bind_unix_socket(const SocketHandle sock, const char *path)
|
||||||
Const<const char *> path) -> Result<void>;
|
-> Result<void>;
|
||||||
static auto connect_unix_socket(Const<SocketHandle> sock,
|
static auto connect_unix_socket(const SocketHandle sock, const char *path)
|
||||||
Const<const char *> path) -> Result<void>;
|
-> Result<void>;
|
||||||
|
|
||||||
static auto unlink_file(Const<const char *> path) -> void {
|
static auto unlink_file(const char *path) -> void {
|
||||||
#if IA_PLATFORM_WINDOWS
|
#if IA_PLATFORM_WINDOWS
|
||||||
DeleteFileA(path);
|
DeleteFileA(path);
|
||||||
#elif IA_PLATFORM_UNIX
|
#elif IA_PLATFORM_UNIX
|
||||||
@ -108,7 +108,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto is_port_available(Const<u16> port, Const<i32> type) -> bool;
|
static auto is_port_available(const u16 port, const i32 type) -> bool;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Mut<i32> s_init_count;
|
static Mut<i32> s_init_count;
|
||||||
|
|||||||
@ -31,7 +31,7 @@ public:
|
|||||||
static auto create_from_file(Ref<Path> path) -> Result<StreamReader>;
|
static auto create_from_file(Ref<Path> path) -> Result<StreamReader>;
|
||||||
|
|
||||||
explicit StreamReader(ForwardRef<Vec<u8>> data);
|
explicit StreamReader(ForwardRef<Vec<u8>> data);
|
||||||
explicit StreamReader(Const<Span<const u8>> data);
|
explicit StreamReader(const Span<const u8> data);
|
||||||
~StreamReader();
|
~StreamReader();
|
||||||
|
|
||||||
StreamReader(ForwardRef<StreamReader> other);
|
StreamReader(ForwardRef<StreamReader> other);
|
||||||
@ -40,17 +40,17 @@ public:
|
|||||||
StreamReader(Ref<StreamReader>) = delete;
|
StreamReader(Ref<StreamReader>) = delete;
|
||||||
auto operator=(Ref<StreamReader>) -> MutRef<StreamReader> = delete;
|
auto operator=(Ref<StreamReader>) -> MutRef<StreamReader> = delete;
|
||||||
|
|
||||||
auto read(Mut<void *> buffer, Const<usize> size) -> Result<void>;
|
auto read(Mut<void *> buffer, const usize size) -> Result<void>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard("Check for EOF")]]
|
[[nodiscard("Check for EOF")]]
|
||||||
auto read() -> Result<T>;
|
auto read() -> Result<T>;
|
||||||
|
|
||||||
auto skip(Const<usize> amount) -> void {
|
auto skip(const usize amount) -> void {
|
||||||
m_cursor = std::min(m_cursor + amount, m_data_size);
|
m_cursor = std::min(m_cursor + amount, m_data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto seek(Const<usize> pos) -> void {
|
auto seek(const usize pos) -> void {
|
||||||
m_cursor = (pos > m_data_size) ? m_data_size : pos;
|
m_cursor = (pos > m_data_size) ? m_data_size : pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ private:
|
|||||||
Mut<StorageType> m_storage_type = StorageType::NonOwning;
|
Mut<StorageType> m_storage_type = StorageType::NonOwning;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline auto StreamReader::read(Mut<void *> buffer, Const<usize> size)
|
inline auto StreamReader::read(Mut<void *> buffer, const usize size)
|
||||||
-> Result<void> {
|
-> Result<void> {
|
||||||
if (m_cursor + size > m_data_size) [[unlikely]] {
|
if (m_cursor + size > m_data_size) [[unlikely]] {
|
||||||
return fail("Unexpected EOF while reading");
|
return fail("Unexpected EOF while reading");
|
||||||
@ -90,7 +90,7 @@ inline auto StreamReader::read() -> Result<T> {
|
|||||||
static_assert(std::is_trivially_copyable_v<T>,
|
static_assert(std::is_trivially_copyable_v<T>,
|
||||||
"T must be trivially copyable to read via memcpy");
|
"T must be trivially copyable to read via memcpy");
|
||||||
|
|
||||||
constexpr Const<usize> SIZE = sizeof(T);
|
constexpr const usize SIZE = sizeof(T);
|
||||||
|
|
||||||
if (m_cursor + SIZE > m_data_size) [[unlikely]] {
|
if (m_cursor + SIZE > m_data_size) [[unlikely]] {
|
||||||
return fail("Unexpected EOF while reading");
|
return fail("Unexpected EOF while reading");
|
||||||
|
|||||||
@ -30,7 +30,7 @@ public:
|
|||||||
static auto create_from_file(Ref<Path> path) -> Result<StreamWriter>;
|
static auto create_from_file(Ref<Path> path) -> Result<StreamWriter>;
|
||||||
|
|
||||||
StreamWriter();
|
StreamWriter();
|
||||||
explicit StreamWriter(Const<Span<u8>> data);
|
explicit StreamWriter(const Span<u8> data);
|
||||||
|
|
||||||
StreamWriter(ForwardRef<StreamWriter> other);
|
StreamWriter(ForwardRef<StreamWriter> other);
|
||||||
auto operator=(ForwardRef<StreamWriter> other) -> MutRef<StreamWriter>;
|
auto operator=(ForwardRef<StreamWriter> other) -> MutRef<StreamWriter>;
|
||||||
@ -40,8 +40,8 @@ public:
|
|||||||
|
|
||||||
~StreamWriter();
|
~StreamWriter();
|
||||||
|
|
||||||
auto write(Const<u8> byte, Const<usize> count) -> Result<void>;
|
auto write(const u8 byte, const usize count) -> Result<void>;
|
||||||
auto write(Const<const void *> buffer, Const<usize> size) -> Result<void>;
|
auto write(const void *buffer, const usize size) -> Result<void>;
|
||||||
|
|
||||||
template <typename T> auto write(Ref<T> value) -> Result<void>;
|
template <typename T> auto write(Ref<T> value) -> Result<void>;
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
namespace IACore {
|
namespace IACore {
|
||||||
class StringOps {
|
class StringOps {
|
||||||
public:
|
public:
|
||||||
static auto encode_base64(Const<Span<Const<u8>>> data) -> String;
|
static auto encode_base64(const Span<const u8> data) -> String;
|
||||||
static auto decode_base64(Ref<String> data) -> Vec<u8>;
|
static auto decode_base64(Ref<String> data) -> Vec<u8>;
|
||||||
};
|
};
|
||||||
} // namespace IACore
|
} // namespace IACore
|
||||||
@ -29,14 +29,14 @@ public:
|
|||||||
static auto get_seconds_count() -> f64;
|
static auto get_seconds_count() -> f64;
|
||||||
|
|
||||||
static auto get_random() -> f32;
|
static auto get_random() -> f32;
|
||||||
static auto get_random(Const<u64> max) -> u64;
|
static auto get_random(const u64 max) -> u64;
|
||||||
static auto get_random(Const<i64> min, Const<i64> max) -> i64;
|
static auto get_random(const i64 min, const i64 max) -> i64;
|
||||||
|
|
||||||
static auto sleep(Const<u64> milliseconds) -> void;
|
static auto sleep(const u64 milliseconds) -> void;
|
||||||
|
|
||||||
static auto binary_to_hex_string(Const<Span<Const<u8>>> data) -> String;
|
static auto binary_to_hex_string(const Span<const u8> data) -> String;
|
||||||
|
|
||||||
static auto hex_string_to_binary(Const<StringView> hex) -> Result<Vec<u8>>;
|
static auto hex_string_to_binary(const StringView hex) -> Result<Vec<u8>>;
|
||||||
|
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
inline static auto sort(ForwardRef<Range> range) -> void {
|
inline static auto sort(ForwardRef<Range> range) -> void {
|
||||||
@ -60,11 +60,11 @@ public:
|
|||||||
Mut<u64> h = 0;
|
Mut<u64> h = 0;
|
||||||
|
|
||||||
if constexpr (std::is_constructible_v<StringView, T>) {
|
if constexpr (std::is_constructible_v<StringView, T>) {
|
||||||
Const<StringView> sv(v);
|
const StringView sv(v);
|
||||||
Const<ankerl::unordered_dense::hash<StringView>> hasher;
|
const ankerl::unordered_dense::hash<StringView> hasher;
|
||||||
h = hasher(sv);
|
h = hasher(sv);
|
||||||
} else {
|
} else {
|
||||||
Const<ankerl::unordered_dense::hash<T>> hasher;
|
const ankerl::unordered_dense::hash<T> hasher;
|
||||||
h = hasher(v);
|
h = hasher(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... MemberPtrs>
|
template <typename T, typename... MemberPtrs>
|
||||||
inline static auto compute_hash_flat(Ref<T> obj, Const<MemberPtrs>... members)
|
inline static auto compute_hash_flat(Ref<T> obj, const MemberPtrs... members)
|
||||||
-> u64 {
|
-> u64 {
|
||||||
Mut<u64> seed = 0;
|
Mut<u64> seed = 0;
|
||||||
(hash_combine(seed, obj.*members), ...);
|
(hash_combine(seed, obj.*members), ...);
|
||||||
|
|||||||
@ -29,9 +29,9 @@ public:
|
|||||||
static auto parse_from_string(Ref<String> data) -> Result<Document>;
|
static auto parse_from_string(Ref<String> data) -> Result<Document>;
|
||||||
static auto parse_from_file(Ref<Path> path) -> Result<Document>;
|
static auto parse_from_file(Ref<Path> path) -> Result<Document>;
|
||||||
|
|
||||||
static auto serialize_to_string(Ref<Node> node, Const<bool> escape = false)
|
static auto serialize_to_string(Ref<Node> node, const bool escape = false)
|
||||||
-> String;
|
-> String;
|
||||||
static auto serialize_to_string(Ref<Document> doc, Const<bool> escape = false)
|
static auto serialize_to_string(Ref<Document> doc, const bool escape = false)
|
||||||
-> String;
|
-> String;
|
||||||
|
|
||||||
static auto escape_xml_string(Ref<String> xml) -> String;
|
static auto escape_xml_string(Ref<String> xml) -> String;
|
||||||
|
|||||||
@ -33,7 +33,7 @@ IACORE_MAIN() {
|
|||||||
<< "===============================================================\n"
|
<< "===============================================================\n"
|
||||||
<< console::RESET << "\n";
|
<< console::RESET << "\n";
|
||||||
|
|
||||||
Const<i32> result = Test::TestRegistry::run_all();
|
const i32 result = Test::TestRegistry::run_all();
|
||||||
|
|
||||||
SocketOps::terminate();
|
SocketOps::terminate();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user