From 8ffc9decbd3a9fedc12c8593005f77a127677b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf-Andr=C3=A9=20Walla?= Date: Thu, 5 Sep 2024 23:42:53 +0200 Subject: [PATCH] Implement String copy to guest std::string, fix Dictionary string bug --- program/cpp/api/string.cpp | 6 ++++++ program/cpp/api/string.hpp | 8 ++++++++ program/cpp/api/syscalls.h | 1 + src/syscalls.cpp | 14 +++++++++++++- 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/program/cpp/api/string.cpp b/program/cpp/api/string.cpp index 273c7b06..1ca35506 100644 --- a/program/cpp/api/string.cpp +++ b/program/cpp/api/string.cpp @@ -59,3 +59,9 @@ String &String::operator=(String &&other) { m_idx = other.m_idx; return *this; } + +String::operator std::string() const { + std::string str; + sys_string_ops(String_Op::TO_STD_STRING, m_idx, 0, (Variant *)&str); + return str; +} diff --git a/program/cpp/api/string.hpp b/program/cpp/api/string.hpp index a1bb2e13..c95592d7 100644 --- a/program/cpp/api/string.hpp +++ b/program/cpp/api/string.hpp @@ -32,6 +32,8 @@ struct String { String operator[](int idx) const; String at(int idx) const { return (*this)[idx]; } + operator std::string() const; + // String size int size() const; @@ -48,10 +50,16 @@ inline Variant::Variant(const String &s) { } inline Variant::operator String() const { + if (m_type != STRING) { + api_throw("std::bad_cast", "Failed to cast Variant to String", this); + } return String::from_variant_index(v.i); } inline String Variant::as_string() const { + if (m_type != STRING) { + api_throw("std::bad_cast", "Failed to cast Variant to String", this); + } return String::from_variant_index(v.i); } diff --git a/program/cpp/api/syscalls.h b/program/cpp/api/syscalls.h index 390ac483..22246096 100644 --- a/program/cpp/api/syscalls.h +++ b/program/cpp/api/syscalls.h @@ -146,4 +146,5 @@ enum class String_Op { INSERT, FIND, ERASE, + TO_STD_STRING, }; diff --git a/src/syscalls.cpp b/src/syscalls.cpp index 18161e15..d59623d9 100644 --- a/src/syscalls.cpp +++ b/src/syscalls.cpp @@ -52,11 +52,16 @@ APICALL(api_print) { auto [array, len] = machine.sysargs(); auto &emu = riscv::emu(machine); + if (len >= 64) { + ERR_PRINT("print(): Too many Variants to print"); + throw std::runtime_error("print(): Too many Variants to print"); + } const GuestVariant *array_ptr = emu.machine().memory.memarray(array, len); // We really want print_internal to be a public function. for (gaddr_t i = 0; i < len; i++) { auto &var = array_ptr[i]; + //printf("Variant[%lu]: type=%d\n", i, var.type); UtilityFunctions::print(var.toVariant(emu)); } } @@ -793,7 +798,7 @@ APICALL(api_dict_ops) { auto *vp = emu.machine().memory.memarray(vaddr, 1); // TODO: Check if the value is already scoped? auto v = dict[key->toVariant(emu)]; - vp->set(emu, v, true); // Implicit trust, as we are returning engine-provided result. + vp->create(emu, std::move(v)); break; } case Dictionary_Op::SET: { @@ -859,6 +864,13 @@ APICALL(api_string_ops) { case String_Op::GET_LENGTH: machine.set_result(str.length()); break; + case String_Op::TO_STD_STRING: { + // Get the string as a std::string. + auto utf8 = str.utf8(); + auto *gstr = emu.machine().memory.memarray(vaddr, 1); + gstr->set_string(emu.machine(), vaddr, utf8.ptr(), utf8.length()); + break; + } default: ERR_PRINT("Invalid String operation"); throw std::runtime_error("Invalid String operation");