diff --git a/include/xo/object2/DString.hpp b/include/xo/object2/DString.hpp index fb23672..2092f7d 100644 --- a/include/xo/object2/DString.hpp +++ b/include/xo/object2/DString.hpp @@ -72,6 +72,12 @@ namespace xo { static DString * from_cstr(obj mm, const char * cstr); + /** create string containing a copy of @p sv. + * Use memory from allocator @p mm + **/ + static DString * from_view(obj mm, + std::string_view sv); + /** clone existing string **/ static DString * clone(obj mm, const DString * src); diff --git a/src/object2/DString.cpp b/src/object2/DString.cpp index d96f712..93bdf5b 100644 --- a/src/object2/DString.cpp +++ b/src/object2/DString.cpp @@ -57,6 +57,25 @@ namespace xo { return result; } + DString * + DString::from_view(obj mm, + std::string_view sv) + { + size_type len = sv.size(); + size_type cap = len + 1; + + void * mem = mm.alloc(typeseq::id(), + sizeof(DString) + cap); + + DString * result = new (mem) DString(); + result->capacity_ = cap; + result->size_ = len; + std::memcpy(result->chars_, sv.data(), len); + result->chars_[len] = '\0'; + + return result; + } + DString * DString::clone(obj mm, const DString * src) { diff --git a/utest/DString.test.cpp b/utest/DString.test.cpp index 21f33bd..124cebb 100644 --- a/utest/DString.test.cpp +++ b/utest/DString.test.cpp @@ -50,6 +50,31 @@ namespace xo { REQUIRE(std::strcmp(s->chars(), cstr) == 0); } + TEST_CASE("DString-from_view", "[object2][DString]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + std::string_view sv = "hello world"; + DString * s = DString::from_view(alloc, sv); + + REQUIRE(s != nullptr); + REQUIRE(s->capacity() == 12); + REQUIRE(s->size() == 11); + REQUIRE(std::strcmp(s->chars(), "hello world") == 0); + + // test with substring (not null-terminated) + std::string_view sub = sv.substr(0, 5); + DString * s2 = DString::from_view(alloc, sub); + + REQUIRE(s2 != nullptr); + REQUIRE(s2->capacity() == 6); + REQUIRE(s2->size() == 5); + REQUIRE(std::strcmp(s2->chars(), "hello") == 0); + } + TEST_CASE("DString-assign", "[object2][DString]") { ArenaConfig cfg { .name_ = "testarena",