Skip to content

Commit

Permalink
Implement 32-byte std::string fetch with fallback for Zig toolchain
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Dec 11, 2024
1 parent 686b10c commit e2af33d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 18 deletions.
38 changes: 22 additions & 16 deletions program/cpp/docker/api/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "syscalls.h"

MAKE_SYSCALL(ECALL_STRING_CREATE, unsigned, sys_string_create, const char *, size_t);
MAKE_SYSCALL(ECALL_STRING_OPS, int, sys_string_ops, String_Op, unsigned, int, Variant *);
MAKE_SYSCALL(ECALL_STRING_OPS, int, sys_string_ops, String_Op, unsigned, int, ...);
MAKE_SYSCALL(ECALL_STRING_AT, unsigned, sys_string_at, unsigned, int);
MAKE_SYSCALL(ECALL_STRING_SIZE, int, sys_string_size, unsigned);
MAKE_SYSCALL(ECALL_STRING_APPEND, void, sys_string_append, unsigned, const char *, size_t);
Expand All @@ -15,23 +15,23 @@ String &String::operator=(const String &value) {
}

void String::append(const String &value) {
(void)sys_string_ops(String_Op::APPEND, m_idx, 0, (Variant *)&value);
(void)sys_string_ops(String_Op::APPEND, m_idx, 0, &value);
}

void String::insert(int idx, const String &value) {
(void)sys_string_ops(String_Op::INSERT, m_idx, 0, (Variant *)&value);
(void)sys_string_ops(String_Op::INSERT, m_idx, 0, &value);
}

void String::append(std::string_view value) {
(void)sys_string_append(m_idx, value.data(), value.size());
}

void String::erase(int idx, int count) {
sys_string_ops(String_Op::ERASE, m_idx, idx, (Variant *)(uintptr_t)count);
sys_string_ops(String_Op::ERASE, m_idx, idx, count);
}

int String::find(const String &value) const {
return sys_string_ops(String_Op::FIND, m_idx, 0, (Variant *)&value);
return sys_string_ops(String_Op::FIND, m_idx, 0, &value);
}

String String::operator[](int idx) const {
Expand All @@ -50,29 +50,35 @@ unsigned String::Create(const char *data, size_t size) {
std::string String::utf8() const {
std::string str;
if constexpr (sizeof(std::string) == 32) {
sys_string_ops(String_Op::TO_STD_STRING, m_idx, 0, (Variant *)&str);
sys_string_ops(String_Op::TO_STD_STRING, m_idx, 0, &str);
} else {
struct Buffer {
char *data;
size_t size;
} buffer;
sys_string_ops(String_Op::TO_STD_STRING, m_idx, 1, (Variant *)&buffer);
str.assign(buffer.data, buffer.data + buffer.size);
std::free(buffer.data);
// Guesstimate that the string is less than 32 bytes.
str.resize_and_overwrite(32, [idx = m_idx](char *data, size_t size) -> std::size_t {
struct Buffer {
char *data;
size_t size;
} buffer;
buffer.data = data;
buffer.size = size;
// This syscall will either copy to the existing buffer or allocate a new one,
// and then update the buffer struct with the new data, freeing the old buffer.
sys_string_ops(String_Op::TO_STD_STRING, idx, 1, &buffer);
return buffer.size;
});
}
return str;
}

std::u32string String::utf32() const {
std::u32string str;
sys_string_ops(String_Op::TO_STD_STRING, m_idx, 2, (Variant *)&str);
sys_string_ops(String_Op::TO_STD_STRING, m_idx, 2, &str);
return str;
}

bool String::operator==(const String &other) const {
return sys_string_ops(String_Op::COMPARE, m_idx, 0, (Variant *)&other);
return sys_string_ops(String_Op::COMPARE, m_idx, 0, &other);
}

bool String::operator==(const char *other) const {
return sys_string_ops(String_Op::COMPARE_CSTR, m_idx, 0, (Variant *)other);
return sys_string_ops(String_Op::COMPARE_CSTR, m_idx, 0, other);
}
9 changes: 7 additions & 2 deletions src/sandbox_syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1653,9 +1653,14 @@ APICALL(api_string_ops) {
gaddr_t size;
} *buffer = machine.memory.memarray<Buffer>(vaddr, 1);
CharString utf8 = str.utf8();
const size_t size = utf8.length();
// Allocate memory for the string in the guest memory.
buffer->size = utf8.length();
buffer->ptr = machine.arena().malloc(buffer->size);
if (buffer->size < size) {
buffer->size = size;
if (buffer->ptr)
machine.arena().free(buffer->ptr);
buffer->ptr = machine.arena().malloc(buffer->size);
}
// Copy the string to the guest memory.
machine.memory.memcpy(buffer->ptr, utf8.ptr(), buffer->size);
} else if (index == 2) { // Get the string as a std::u32string.
Expand Down

0 comments on commit e2af33d

Please sign in to comment.