/** @file DUniqueString.cpp * * @author Roland Conybeare, Jan 2026 **/ #include "DUniqueString.hpp" #include "DString.hpp" #include #include #include namespace xo { using xo::mm::padding; using xo::facet::typeseq; namespace scm { int DUniqueString::compare(const DUniqueString & lhs, const DUniqueString & rhs) { if (&lhs == &rhs) return 0; return DString::compare(*(lhs._text()), *(rhs._text())); } DString * DUniqueString::_text() const noexcept { // location of paired DString is chosen // by allocator (DArena, probably). // // In general allocator alignment more conservative // than C++ alignment // // Remmebr also: although DUniqueString has zero members, // C++ requires it to behave asif size at least 1 byte // for iterator consistency // (e.g. because c++ would support iterating over // std::vector) // size_t offset = padding::with_padding(sizeof(*this)); assert(offset > 0); return (DString *)(((std::byte *)this) + offset); } bool DUniqueString::pretty(const ppindentinfo & ppii) const { return _text()->pretty(ppii); } DUniqueString * DUniqueString::from_view(obj mm, std::string_view sv) { scope log(XO_DEBUG(false)); /** fine point: choosing to allocate DUniqueString ahead of DString, * so it comes first in bump allocator **/ void * mem = mm.super_alloc(typeseq::id(), sizeof(DUniqueString)); DUniqueString * result = new (mem) DUniqueString(); /** allocated in memory immediate following @p result. * This optimization saves us one pointer (8 bytes) in DUniqueString * itself, plus one allocation header (8 bytes) for 16 bytes total **/ DString * text = DString::from_view_suballoc(mm, sv); log && log(xtag("result", result), xtag("result.text", result->_text()), xtag("text", text)); assert(text); assert(text == result->_text()); /** must finish super-allocation before next alloc **/ mm.sub_alloc(0, true); return result; } DUniqueString * DUniqueString::gco_shallow_move(obj gc) noexcept { // well-posed, but not expected to be used. // // Not using gc.std_move_for() here because compiler doesn't know // actual alloc size of a DUniqueString instance assert(false); DUniqueString * copy = (DUniqueString *)gc.alloc_copy((std::byte *)this); if (copy) { // Copy assignment not implemented in general // *copy = *this; // in this case *copy already has the same size as *this assert(size() <= capacity()); strncpy(copy->_text()->data(), this->_text()->chars(), this->size()); } return copy; } void DUniqueString::visit_gco_children(VisitReason, obj) noexcept { // no-op -- childless! } } /*namespace scm*/ } /*namespace xo*/ /* end DUniqueString.cpp */