static inline std::string join(const cstring_span& str, const cstring_span& sep, bool trail_sep) { span_size_t slen = sep.size(); span_size_t len = trail_sep?slen:0; auto get_len = [&len,slen](const element& elem, bool first) { if(!first) len += slen; len += elem.value_size(); }; for_each_elem(str, get_len); std::string res; res.reserve(std_size(len)); auto fill = [&res,sep](const element& elem, bool first) { if(!first) res.append(sep.data(), std_size(sep.size())); res.append(elem.value_data(), std_size(elem.value_size())); }; for_each_elem(str, fill); if(trail_sep) { res.append(sep.data(), std_size(sep.size())); } assert(res.size() == std_size(len)); return std::move(res); }
static inline cstring_span _fit(const cstring_span& s) noexcept { span_size_t hs = element_header_size(s); span_size_t vs = element_value_size(s, hs); assert(s.size() >= hs+vs+hs); return {s.data(), hs+vs+hs}; }
static inline void for_each_elem(const cstring_span& str, Func func) noexcept { span_size_t i = 0; bool first = true; while(i < str.size()) { element elem(str.data()+i, str.size()-i); func(elem, first); i += elem.size(); first = false; } }
void _update(void) const { if(_pos != nullptr && (_tmp.size() == 0)) { span_size_t ll = _len_len(); span_size_t vl = _val_len(ll); _tmp = cstring_span{_pos+ll, span_size_t(vl)}; } }
static inline void rev_for_each_elem(const cstring_span& str, Func func) noexcept { span_size_t i = str.size()-1; bool first = true; while(i > 0) { while(!mbs::is_valid_head_byte(byte(str[i]))) { assert(i > 0); --i; } element elem(str.data()+i, i, str.size()-i); func(elem, first); i -= elem.header_size()+elem.value_size()+1; first = false; } }
static inline cstring_span _rev_fit(const cstring_span& s, span_size_t rev_sz) noexcept { span_size_t hs = element_header_size(s); span_size_t vs = element_value_size(s, hs); assert(rev_sz >= hs+vs); return {s.data()-hs-vs, hs+vs+hs}; }
static inline span_size_t element_value_size(const cstring_span& elem) noexcept { return element_value_size(elem, elem.size()); }
Sym addSymbolMustBeNew(cstring_span<> word) { return addSymbolMustBeNew(std::string(word.data(), word.size())); }