xo-umbrella2/xo-stringtable2/src/stringtable2/DString.cpp

191 lines
5.1 KiB
C++

/** @file DString.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "DString.hpp"
#include <xo/alloc2/Allocator.hpp>
#include <xo/indentlog/print/pretty.hpp>
#include <algorithm>
#include <cstring>
namespace xo {
using xo::reflect::typeseq;
using xo::print::ppdetail_atomic;
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);
if (mem) {
result = new (mem) DString();
assert(result);
result->capacity_ = cap;
result->size_ = 0;
if (cap > 0) {
result->chars_[0] = '\0';
}
}
}
return result;
}
DString *
DString::from_cstr(obj<AAllocator> mm,
const char * cstr)
{
size_type len = std::strlen(cstr);
size_type cap = len + 1;
void * mem = mm.alloc(typeseq::id<DString>(),
sizeof(DString) + cap);
DString * result = nullptr;
if (mem) {
result = new (mem) DString();
result->capacity_ = cap;
result->size_ = len;
std::memcpy(result->chars_, cstr, cap);
}
return result;
}
DString *
DString::_from_view_aux(obj<AAllocator> mm,
std::string_view sv,
bool suballoc_flag)
{
size_type len = sv.size();
size_type cap = len + 1;
auto tseq = typeseq::id<DString>();
void * mem = nullptr;
size_type mem_z = sizeof(DString) + cap;
if (suballoc_flag)
mem = mm.sub_alloc(mem_z, false /*!complete_flag*/);
else
mem = mm.alloc(tseq, mem_z);
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::from_view(obj<AAllocator> mm,
std::string_view sv)
{
return _from_view_aux(mm, sv, false /*!suballoc_flag*/);
}
DString *
DString::from_str(obj<AAllocator> mm,
const std::string & str)
{
return _from_view_aux(mm,
std::string_view(str),
false /*!suballoc_flag*/);
}
DString *
DString::from_view_suballoc(obj<AAllocator> mm,
std::string_view sv)
{
return _from_view_aux(mm, sv, true /*suballoc_flag*/);
}
DString *
DString::clone(obj<AAllocator> mm, const DString * src)
{
size_type cap = src->capacity_;
void * mem = mm.alloc(typeseq::id<DString>(),
sizeof(DString) + cap);
DString * result = new (mem) DString();
result->capacity_ = cap;
result->size_ = src->size_;
std::memcpy(result->chars_, src->chars_, cap);
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;
}
int
DString::compare(const DString & lhs, const DString & rhs) noexcept
{
return ::strcmp(lhs.chars_, rhs.chars_);
}
auto
DString::fixup_size() noexcept -> size_type
{
this->chars_[capacity_ - 1] = '\0';
this->size_ = ::strlen(chars_);
return this->size_;
}
DString *
DString::gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept
{
// note: not using gc.std_move_for() here
// b/c DString flexible array means not move-constructible
DString * copy = (DString *)gc.alloc_copy_for(this);
if (copy) {
copy->capacity_ = capacity_;
copy->size_ = size_;
::memcpy(copy->chars_, chars_, capacity_);
}
return copy;
}
void
DString::visit_gco_children(VisitReason, obj<AGCObjectVisitor>) noexcept
{
// no-op. no children!
}
bool
DString::pretty(const ppindentinfo & ppii) const
{
return ppdetail_atomic<const char *>::print_pretty(ppii, &(chars_[0]));
}
} /*namespace scm*/
} /*namespace xo*/
/* end DString.cpp */