void RopeImpl::append_string_impl( string_ptr& dest, string_ptr const& one, string_ptr const& two) { /*trivial cases where one string is empty*/ if(one->length() == 0) { dest = two; return; } else if(two->length() == 0){ dest = one; return; } /*check for catting two short Ascii strings.*/ AsciiImpl* as1 = dynamic_cast<AsciiImpl*>(one.get()); if(as1 && as1->length() < (ASCII_BUFFER_LEVEL / 2)) { AsciiImpl* as2 = dynamic_cast<AsciiImpl*>(two.get()); if(as2 && as2->length() < (ASCII_BUFFER_LEVEL / 2)) { size_t l1 = as1->length(); size_t l2 = as2->length(); /*create a single buffer and concat them*/ boost::shared_array<BYTE> nbp(new BYTE(l1 + l2)); std::copy(as2->start, &as2->start[l2], std::copy(as1->start, &as1->start[l1], &nbp[0] ) ); dest.reset(new AsciiImpl(nbp, &nbp[0], l1 + l2)); return; } } size_t d1 = one->rope_depth(); size_t d2 = two->rope_depth(); if(d1 > d2 + 1) { /*first subtree is pretty heavy, check if: one two /\ | /\ c d a b If so, do this: /\ / \ /\ /\ a b c d */ RopeImpl& r1 = static_cast<RopeImpl&>(*one); size_t d1_2 = r1.two->rope_depth(); if(d1_2 <= d2 + 1) { string_ptr tmp; base_append_string_impl(tmp, r1.two, two, d1_2, d2); append_string_impl(dest, r1.one, tmp); return; } } base_append_string_impl(dest, one, two, d1, d2); }
/*direct construction, only allowed for friends*/ RopeImpl( string_ptr const& n1, string_ptr const& n2, size_t nd, size_t nl1) : one(n1), two(n2), depth(nd), l1(nl1), HlStringImpl(nl1 + n2->length()) { }
void RopeImpl::base_append_string_impl( string_ptr& dest, string_ptr const& one, string_ptr const& two, size_t d1, size_t d2) { size_t nd = d1 > d2 ? d1 + 1 : /*otherwise*/ d2 + 1 ; dest.reset( new RopeImpl(one, two, nd, one->length()) ); }