From 4c468d88e34e92e3100de9071f8aaf7e7d0b9c35 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 13 Jan 2026 17:07:03 -0500 Subject: [PATCH] xo-object2: + DString::assign --- xo-object2/include/xo/object2/DString.hpp | 63 +++++++++++++++++++++++ xo-object2/src/object2/DString.cpp | 13 +++++ xo-object2/utest/DString.test.cpp | 32 ++++++++++++ 3 files changed, 108 insertions(+) diff --git a/xo-object2/include/xo/object2/DString.hpp b/xo-object2/include/xo/object2/DString.hpp index 6333f7a4..dbd72ddf 100644 --- a/xo-object2/include/xo/object2/DString.hpp +++ b/xo-object2/include/xo/object2/DString.hpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace xo { @@ -27,6 +28,9 @@ namespace xo { using size_type = std::uint32_t; using AAllocator = xo::mm::AAllocator; + /** @defgroup dstring-ctors constructors **/ + ///@{ + /** create empty string with space for @cap chars * (including null terminator). * Use memory from allocator @p mm @@ -40,10 +44,69 @@ namespace xo { static DString * from_cstr(obj mm, const char * cstr); + ///@} + /** @defgroup dstring-access access methods **/ + ///@{ + size_type capacity() const noexcept { return capacity_; } size_type size() const noexcept { return size_; } const char * chars() const noexcept { return chars_; } + ///@} + /** @defgroup dstring-iterators iterators **/ + ///@{ + + ///@} + /** @defgroup dstring-assign assignment **/ + ///@{ + + /** put string into empty state **/ + void clear() noexcept { size_ = 0; chars_[0] = '\0'; } + + /** replace contents with @p other, or prefix of up to @p capacity - 1 chars **/ + DString & assign(const DString & other); + + // TODO - behave like std::string, to the extent feasible + // insert + // insert_range + // erase + // push_back + // append + // append_range + // operator+= + // replace + // replace_with_range + // copy + // find + // rfind + // find_first_of + // find_first_not_of + // find_last_of + // find_last_not_of + // compare + // starts_with + // end_with + // contains + // substr + + ///@} + /** @defgroup dstring-conversion-operators conversion operators **/ + ///@{ + + operator std::string_view() const noexcept { return std::string_view(chars_); } + + /** @brief conversion oeprator to C-style string. + * + * Example + * @code + * DString s = ...; + * ::strcmp(s, "obey..."); + * @endcode + **/ + operator const char * () const noexcept { return &(chars_[0]); } + + ///@} + private: /** extent of @ref chars_ array **/ size_type capacity_ = 0; diff --git a/xo-object2/src/object2/DString.cpp b/xo-object2/src/object2/DString.cpp index 7f5aee15..53feef8c 100644 --- a/xo-object2/src/object2/DString.cpp +++ b/xo-object2/src/object2/DString.cpp @@ -4,6 +4,7 @@ **/ #include "DString.hpp" +#include #include namespace xo { @@ -50,6 +51,18 @@ namespace xo { return result; } + + DString & + DString::assign(const DString & other) + { + size_type n = std::min(other.size_, capacity_ - 1); + std::memcpy(chars_, other.chars_, n); + chars_[n] = '\0'; + size_ = n; + + return *this; + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-object2/utest/DString.test.cpp b/xo-object2/utest/DString.test.cpp index c3437b6b..0bc3e596 100644 --- a/xo-object2/utest/DString.test.cpp +++ b/xo-object2/utest/DString.test.cpp @@ -47,6 +47,38 @@ namespace xo { REQUIRE(s->size() == 11); REQUIRE(std::strcmp(s->chars(), cstr) == 0); } + + TEST_CASE("DString-assign", "[object2][DString]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DString * src = DString::from_cstr(alloc, "hello"); + DString * dst = DString::empty(alloc, 16); + + dst->assign(*src); + + REQUIRE(dst->size() == 5); + REQUIRE(std::strcmp(dst->chars(), "hello") == 0); + } + + TEST_CASE("DString-assign-truncate", "[object2][DString]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DString * src = DString::from_cstr(alloc, "hello world"); + DString * dst = DString::empty(alloc, 6); + + dst->assign(*src); + + REQUIRE(dst->size() == 5); + REQUIRE(std::strcmp(dst->chars(), "hello") == 0); + } } /*namespace ut*/ } /*namespace xo*/