/* @file String.cpp * * author: Roland Conybeare, Aug 2025 */ #include "String.hpp" #include "GC.hpp" #include #include #include #include namespace xo { namespace obj { String::String(Owner owner, std::size_t z, char * s) : owner_{owner}, z_chars_{z}, chars_{s} {} String::String(gc::IAlloc * mm, Owner owner, std::size_t z, char * s, bool copy) : owner_{owner}, z_chars_{z} { if (copy) { chars_ = reinterpret_cast(mm->alloc(z)); assert(chars_); strlcpy(chars_, s, z); } else { chars_ = s; } } gp String::from(gp x) { return dynamic_cast(x.ptr()); } gp String::copy(const char * s) { return copy(Object::mm, s); } gp String::copy(gc::IAlloc * mm, const char * s) { std::size_t z = 1 + (s ? ::strlen(s) : 0); const char * chars = s ? s : ""; // const-cast ok since chars copied with Owner::unique return new (MMPtr(mm)) String(mm, Owner::unique, z, const_cast(chars), true /*copy*/); } gp String::allocate(std::size_t z) { return new (MMPtr(Object::mm)) String(mm, Owner::unique, z, const_cast(""), true /*copy*/); } gp String::append(gp s1, gp s2) { std::size_t z1 = s1->length(); std::size_t z2 = s2->length(); std::size_t z = z1 + z2; gp retval = allocate(z); strlcpy(retval->chars_, s1->chars_, z1); strlcpy(retval->chars_ + z1, s2->chars_, z2); return retval; } std::size_t String::length() const { return ::strlen(chars_); } // ----- GC support ----- std::size_t String::_shallow_size() const { /* no child Object* pointers to fixup, * but must count for amount of storage used by _shallow_move() */ std::size_t retval = gc::IAlloc::with_padding(sizeof(String)); if (owner_ == Owner::unique) retval += gc::IAlloc::with_padding(z_chars_); return retval; } Object * String::_shallow_copy() const { // Reminder: String must come before secondary allocation, Cpof cpof(this); // might expect to write: // gp copy = new (gcm) String(Object::mm, owner_, z_chars_, chars_); // but this would always put string contents in nursery to-space. // // We need to choose nursery/tenured based on location of this, // achieved by calling GC::alloc_copy() instead of GC::alloc() // gp copy = new (cpof) String(owner_, z_chars_, chars_); if (owner_ == Owner::unique) { std::byte * mem = reinterpret_cast(chars_); copy->chars_ = reinterpret_cast(Object::mm->alloc_gc_copy(z_chars_, mem)); strlcpy(copy->chars_, chars_, z_chars_); } return copy.ptr(); } std::size_t String::_forward_children() { return this->_shallow_size(); } } /*namespace obj*/ } /*namespace xo*/ /* end String.cpp */