Helps streamline DX1Collector in xo-gc/. Want both forward and verify entry points for the same representation.
119 lines
3.6 KiB
C++
119 lines
3.6 KiB
C++
/** @file DUniqueString.cpp
|
|
*
|
|
* @author Roland Conybeare, Jan 2026
|
|
**/
|
|
|
|
#include "DUniqueString.hpp"
|
|
#include "DString.hpp"
|
|
#include <xo/arena/padding.hpp>
|
|
#include <xo/indentlog/scope.hpp>
|
|
#include <cstring>
|
|
|
|
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<EmptyStruct>)
|
|
//
|
|
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<AAllocator> 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<DUniqueString>(),
|
|
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<AGCObjectVisitor> 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<AGCObjectVisitor>) noexcept
|
|
{
|
|
// no-op -- childless!
|
|
}
|
|
} /*namespace scm*/
|
|
} /*namespace xo*/
|
|
|
|
/* end DUniqueString.cpp */
|