xo-object2: beginning of DString + utest

This commit is contained in:
Roland Conybeare 2026-01-13 16:43:58 -05:00
commit 56bda48a06
7 changed files with 137 additions and 12 deletions

View file

@ -25,27 +25,20 @@ namespace xo {
DList(xo::obj<AGCObject> h,
DList * r) : head_{h}, rest_{r} {}
/** sentinel for null list **/
/** sentinel for null list.
* Application code may prefer ListOps::nil()
**/
static DList * _nil();
/** list with first element @p car,
* followed by contents of list @p cdr.
* Shares structure with @p cdr
* Application code may prefer ListOps::cons()
**/
static DList * _cons(obj<AAllocator> mm,
obj<AGCObject> car,
DList * cdr);
#ifdef OBSOLETE
/** list with one element @p h1, allocated from @p mm **/
static DList * list(obj<AAllocator> mm,
obj<AGCObject> h1);
/** list with two elements @p h1, @p h2, allocated from @p mm **/
static DList * list(obj<AAllocator> mm,
obj<AGCObject> h1,
obj<AGCObject> h2);
#endif
/** DList length is at least 1 **/
bool is_empty() const noexcept;
/** DList models a finite sequence **/

View file

@ -0,0 +1,58 @@
/** @file DString.hpp
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include <xo/alloc2/Allocator.hpp>
#include <xo/facet/obj.hpp>
#include <cstdint>
namespace xo {
namespace scm {
/** @class DString
* @brief String implementation with gc hooks
*
* String implementation for Schematika.
* Size-prefixed and null-terminated.
* Note however that string length != size for utf-8.
*
* Uses flexible array for chars,
* with string contents in memory immediately
* following the DString itself
**/
struct DString {
public:
using size_type = std::uint32_t;
using AAllocator = xo::mm::AAllocator;
/** create empty string with space for @cap chars
* (including null terminator).
* Use memory from allocator @p mm
**/
static DString * empty(obj<AAllocator> mm,
size_type cap);
/** create string containing a copy of null-terminated @p cstr.
* Use memory from allocator @p mm
**/
static DString * from_cstr(obj<AAllocator> mm,
const char * cstr);
size_type capacity() const noexcept { return capacity_; }
size_type size() const noexcept { return size_; }
const char * chars() const noexcept { return chars_; }
private:
/** extent of @ref chars_ array **/
size_type capacity_ = 0;
/** null terminator at @c chars_[size_] **/
size_type size_ = 0;
/** string contents **/
char chars_[];
};
} /*namespace scm*/
} /*namespace xo*/
/* end DString.hpp */

View file

@ -14,7 +14,6 @@
#pragma once
#include <xo/printable2/Printable.hpp>
#include <xo/printable2/detail/IPrintable_Xfer.hpp>
#include "DInteger.hpp"
namespace xo { namespace scm { class IPrintable_DInteger; } }

View file

@ -13,6 +13,7 @@ set(SELF_SRCS
DList.cpp
DFloat.cpp
DInteger.cpp
DString.cpp
object2_register_types.cpp
object2_register_facets.cpp
)

View file

@ -0,0 +1,37 @@
/** @file DString.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "DString.hpp"
namespace xo {
using xo::facet::typeseq;
namespace scm {
DString *
DString::empty(obj<AAllocator> mm,
size_type cap)
{
assert(cap > 0);
DString * result = nullptr;
if (cap > 0) {
void * mem = mm.alloc(typeseq::id<DString>(),
sizeof(DString) + cap);
result = new (mem) DString();
result->capacity_ = cap;
result->size_ = 0;
if (cap > 0) {
result->chars_[0] = '\0';
}
}
return result;
}
} /*namespace scm*/
} /*namespace xo*/
/* end DString.cpp */

View file

@ -3,6 +3,7 @@
set(UTEST_EXE utest.object2)
set(UTEST_SRCS
object2_utest_main.cpp
DString.test.cpp
X1Collector.test.cpp
Printable.test.cpp
)

View file

@ -0,0 +1,36 @@
/** @file DString.test.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include <xo/object2/DString.hpp>
#include <xo/alloc2/arena/IAllocator_DArena.hpp>
#include <catch2/catch.hpp>
namespace xo {
using xo::scm::DString;
using xo::mm::AAllocator;
using xo::mm::DArena;
using xo::mm::ArenaConfig;
using xo::facet::with_facet;
using xo::facet::obj;
namespace ut {
TEST_CASE("DString-empty", "[object2][DString]")
{
ArenaConfig cfg { .name_ = "testarena",
.size_ = 4*1024 };
DArena arena = DArena::map(cfg);
auto alloc = with_facet<AAllocator>::mkobj(&arena);
DString * s = DString::empty(alloc, 16);
REQUIRE(s != nullptr);
REQUIRE(s->capacity() == 16);
REQUIRE(s->size() == 0);
REQUIRE(s->chars()[0] == '\0');
}
} /*namespace ut*/
} /*namespace xo*/
/* end DString.test.cpp */