/** @file DDictionary.cpp * * @author Roland Conybeare, Mar 2026 **/ #include "DDictionary.hpp" #include "Array.hpp" #include "String.hpp" #include #include namespace xo { using xo::print::APrintable; using xo::facet::FacetRegistry; using xo::mm::AGCObject; namespace scm { DDictionary::DDictionary(DArray * keys, DArray * values) : keys_{keys}, values_{values} {} DDictionary * DDictionary::empty(obj mm, size_type cap) { void * mem = mm.alloc_for(); if (cap <= 0) cap = 1; DArray * keys = DArray::empty(mm, cap); DArray * values = DArray::empty(mm, cap); return new (mem) DDictionary(keys, values); } std::optional> DDictionary::lookup(const DString * key) const noexcept { for (DArray::size_type i = 0, z = keys_->size(); i < z; ++i) { auto i_key = obj::from(keys_->at(i)); assert(i_key); if (DString::compare(*key, *i_key.data()) == 0) return values_->at(i); } return {}; } std::pair> DDictionary::at_index(size_type ix) const { if (ix < keys_->size()) { #ifndef NDEBUG auto key_str = obj::from((*keys_)[ix]); assert(key_str); #endif return pair_type(this->key_at_index(ix), (*values_)[ix]); } return pair_type(); } const DString * DDictionary::key_at_index(size_type ix) const { auto key_str = obj::from((*keys_)[ix]); assert(key_str); return key_str.data(); } obj DDictionary::value_at_index(size_type ix) const { if (ix < keys_->size()) { assert(ix < values_->size()); return (*values_)[ix]; } return obj(); } bool DDictionary::try_update(const pair_type & kv_pair) { for (size_type i = 0, n = keys_->size(); i < n; ++i) { auto key_i = obj::from((*keys_)[i]); assert(key_i); if (*(key_i.data()) == *(kv_pair.first)) { values_->assign_at(i, kv_pair.second); return true; } } return false; } bool DDictionary::try_upsert(const pair_type & kv_pair) { if (this->try_update(kv_pair)) return true; if (keys_->size() == keys_->capacity()) return false; keys_->push_back(obj(const_cast(kv_pair.first))); values_->push_back(kv_pair.second); return true; } bool DDictionary::upsert(obj mm, const pair_type & kv_pair) { if (this->try_update(kv_pair)) return true; if (keys_->size() == keys_->capacity()) { assert(keys_->capacity() > 0); size_type cap_2x = 2 * keys_->capacity(); DArray * keys_2x = DArray::copy(mm, keys_, cap_2x); DArray * values_2x = DArray::copy(mm, values_, cap_2x); if (keys_2x && values_2x) { this->keys_ = keys_2x; this->values_ = values_2x; } else { return false; } } keys_->push_back(obj(const_cast(kv_pair.first))); values_->push_back(kv_pair.second); return true; } void DDictionary::shrink_to_fit() noexcept { keys_->shrink_to_fit(); values_->shrink_to_fit(); } // ----- printable facet ---- bool DDictionary::pretty(const ppindentinfo & ppii) const { using xo::print::ppstate; ppstate * pps = ppii.pps(); if (ppii.upto()) { pps->write("{"); for (size_type i = 0, n = this->size(); i < n; ++i) { if (i > 0) pps->write(" "); obj key = FacetRegistry::instance().variant((*keys_)[i]); obj value = FacetRegistry::instance().variant((*values_)[i]); assert(key.data()); assert(value.data()); if (!pps->print_upto(key)) return false; pps->write(": "); if (!pps->print_upto(value)) return false; } pps->write("}"); return true; } else { pps->write("{...}"); return false; } } // ----- gcobject facet ----- std::size_t DDictionary::shallow_size() const noexcept { return sizeof(DDictionary); } DDictionary * DDictionary::shallow_copy(obj mm) const noexcept { return mm.std_copy_for(this); } std::size_t DDictionary::forward_children(obj gc) noexcept { gc.forward_inplace(&keys_); gc.forward_inplace(&values_); return this->shallow_size(); } } /*namespace scm*/ } /*namespace xo*/ /* end DDictionary.cpp */