diff --git a/src/common.cpp b/src/common.cpp index 8a6fcf5..79cfc51 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -20,6 +20,8 @@ Result Value::create(Arena& arena, PodObject* obj) { return Value(TRY(Float::create(arena, (PodFloat*)obj))); case Tag::Bool: return Value(TRY(Bool::create(arena, (PodBool*)obj))); + case Tag::ByteArray: + return Value(TRY(ByteArray::create(arena, (PodByteArray*)obj))); case Tag::String: return Value(TRY(String::create(arena, (PodString*)obj))); case Tag::Symbol: @@ -59,6 +61,10 @@ Result Float::copy(Arena& arena) { return Value(Float(TRY(_value.copy(arena)))); } +Result ByteArray::copy(Arena& arena) { + return Value(ByteArray(TRY(_value.copy(arena)))); +} + Result String::copy(Arena& arena) { return Value(String(TRY(_value.copy(arena)))); } diff --git a/src/common.hpp b/src/common.hpp index 3438751..0733e39 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -47,6 +47,102 @@ class Nil : public Object { GcRoot _value; }; +class ByteArray : public Object { + public: + ByteArray() {} + ByteArray(ByteArray&& rhs) : _value(std::move(rhs._value)) {} + ByteArray(GcRoot&& val) : _value(std::move(val)) {} + + ByteArray& operator=(ByteArray&& rhs) { + _value = std::move(rhs._value); + return *this; + } + + virtual Tag tag() final { return Tag::String; } + virtual PodObject* pod() final { return _value.get(); } + + static Result create(Arena& arena, PodByteArray* obj) { + return ByteArray(TRY(MkGcRoot(obj, arena))); + } + static Result create(Arena& arena, char* chars, int64_t size) { + auto pod = TRY(arena.alloc(size * sizeof(char))); + + memcpy(pod->data, chars, size * sizeof(char32_t)); + pod->size = size; + + return ByteArray(TRY(MkGcRoot(pod, arena))); + } + + static Result create(Arena& arena, const char* str) { + uint64_t size = strlen(str); + auto pod = TRY(arena.alloc(size * sizeof(char32_t))); + + memcpy(pod->data, str, size); + pod->size = size; + + return ByteArray(TRY(MkGcRoot(pod, arena))); + } + + uint64_t size() { return _value->size; } + virtual Result copy(Arena& arena) final; + + Result operator[](uint64_t idx) { + if (idx >= _value->size) return ErrorCode::IndexOutOfRange; + return _value->data[idx]; + } + + Result concat(Arena& arena, const char* rhs) { + uint64_t rhs_size = strlen(rhs); + uint64_t lhs_size = size(); + uint64_t res_size = lhs_size + rhs_size; + + auto pod = TRY(arena.alloc(res_size * sizeof(char))); + pod->size = res_size; + memcpy(pod->data, _value->data, sizeof(char) * lhs_size); + memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size); + + return ByteArray(TRY(MkGcRoot(pod, arena))); + } + + Result concat(Arena& arena, const char* rhs, uint64_t rhs_size) { + uint64_t lhs_size = size(); + uint64_t res_size = lhs_size + rhs_size; + + auto pod = TRY(arena.alloc(res_size * sizeof(char))); + pod->size = res_size; + memcpy(pod->data, _value->data, sizeof(char) * lhs_size); + memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size); + + return ByteArray(TRY(MkGcRoot(pod, arena))); + } + + Result concat(Arena& arena, ByteArray& rhs) { + uint64_t rhs_size = rhs.size(); + uint64_t lhs_size = size(); + uint64_t res_size = lhs_size + rhs_size; + + auto pod = TRY(arena.alloc(res_size * sizeof(char))); + pod->size = res_size; + memcpy(pod->data, _value->data, sizeof(char) * lhs_size); + memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size); + + return ByteArray(TRY(MkGcRoot(pod, arena))); + } + + Result sub(Arena& arena, uint64_t start, uint64_t end) { + if (start > end) return ErrorCode::IndexOutOfRange; + uint64_t res_size = end - start; + auto pod = TRY(arena.alloc(res_size * sizeof(char))); + pod->size = res_size; + memcpy(pod->data, _value->data + start, sizeof(char) * res_size); + + return ByteArray(TRY(MkGcRoot(pod, arena))); + } + + private: + GcRoot _value; +}; + class String : public Object { public: String() {} diff --git a/src/pod.hpp b/src/pod.hpp index 8e7d109..0b12e24 100644 --- a/src/pod.hpp +++ b/src/pod.hpp @@ -14,6 +14,7 @@ enum class Tag : uint8_t { Symbol, Syntax, Pair, + ByteArray, }; template @@ -74,6 +75,14 @@ class PodBool final : public PodObject { bool value; }; +class PodByteArray final : public PodObject { + public: + PodByteArray() : PodObject(Tag::ByteArray){}; + + uint64_t size; + char data[]; +}; + class PodString final : public PodObject { public: PodString() : PodObject(Tag::String){}; diff --git a/src/reader.hpp b/src/reader.hpp index d4a2229..4d51cee 100644 --- a/src/reader.hpp +++ b/src/reader.hpp @@ -5,7 +5,7 @@ class Reader { public: - Reader(Arena& arena, String&& str) : _arena(arena), _str(std::move(str)) {} + Reader(Arena& arena, String& str) : _arena(arena), _str(str) {} Result read_one(); Result read_multiple(); @@ -39,6 +39,6 @@ class Reader { bool match(char c); Arena& _arena; - String _str; + String& _str; SourcePosition position_{1, 1, 0}; }; diff --git a/src/vli.cpp b/src/vli.cpp index 258fa83..a684972 100644 --- a/src/vli.cpp +++ b/src/vli.cpp @@ -2,6 +2,7 @@ #include "arena.hpp" #include "common.hpp" +#include "reader.hpp" StaticArena<64 * 1024 * 1024> arena; @@ -26,5 +27,9 @@ int main() { } std::cout << "root count: " << arena.root_count() << "\n"; + auto s = DIEIF(String::create(arena, "(1 2 3 \"foo\")")); + auto reader = Reader(arena, s); + + auto r = DIEIF(reader.read_one()); return 0; }