00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "text.hpp"
00020
00021 namespace
00022 {
00023 const obby::text::size_type CHUNK_INIT =
00024 ~static_cast<obby::text::size_type>(0);
00025
00026 inline obby::text::size_type CHUNK_SIZE(obby::text::size_type size)
00027 {
00028 return size == obby::text::npos ? CHUNK_INIT : size;
00029 }
00030
00031
00032
00033 template<typename List, typename Iter>
00034 Iter find_chunk(List list, obby::text::size_type& pos)
00035 {
00036 for(Iter it = list.begin(); it != list.end(); ++ it)
00037 {
00038 if( (*it)->get_length() > pos)
00039 return it;
00040 else
00041 pos -= (*it)->get_length();
00042 }
00043
00044 if(pos == 0) return list.end();
00045
00046 throw std::logic_error(
00047 "obby::text::find_chunk:\n"
00048 "Requested position exceeds text's size"
00049 );
00050 }
00051 }
00052
00053 obby::text::chunk::chunk(const chunk& other):
00054 m_text(other.m_text), m_author(other.m_author)
00055 {
00056 }
00057
00058 obby::text::chunk::chunk(const string_type& string,
00059 const user* author):
00060 m_text(string),
00061 m_author(author)
00062 {
00063 }
00064
00065 obby::text::chunk::chunk(const net6::packet& pack,
00066 unsigned int& index,
00067 const user_table& table):
00068 m_text(pack.get_param(index + 0).as<std::string>() ),
00069 m_author(
00070 pack.get_param(index + 1).as<const user*>(
00071 ::serialise::hex_context_from<const user*>(table)
00072 )
00073 )
00074 {
00075 index += 2;
00076 }
00077
00078 obby::text::chunk::chunk(const serialise::object& obj,
00079 const user_table& table):
00080 m_text(obj.get_required_attribute("content").as<std::string>() ),
00081 m_author(
00082 obj.get_required_attribute("author").as<const user*>(
00083 ::serialise::default_context_from<const user*>(table)
00084 )
00085 )
00086 {
00087 }
00088
00089 void obby::text::chunk::serialise(serialise::object& obj) const
00090 {
00091 obj.add_attribute("content").set_value(m_text);
00092 obj.add_attribute("author").set_value(m_author);
00093 }
00094
00095 void obby::text::chunk::append_packet(net6::packet& pack) const
00096 {
00097 pack << m_text << m_author;
00098 }
00099
00100 void obby::text::chunk::prepend(const string_type& text)
00101 {
00102 m_text.insert(0, text);
00103 }
00104
00105 void obby::text::chunk::append(const string_type& text)
00106 {
00107 m_text.append(text);
00108 }
00109
00110 void obby::text::chunk::insert(size_type pos, const string_type& text)
00111 {
00112 m_text.insert(pos, text);
00113 }
00114
00115 void obby::text::chunk::erase(size_type pos, size_type len)
00116 {
00117 m_text.erase(pos, len);
00118 }
00119
00120 const obby::text::string_type& obby::text::chunk::get_text() const
00121 {
00122 return m_text;
00123 }
00124
00125 const obby::user* obby::text::chunk::get_author() const
00126 {
00127 return m_author;
00128 }
00129
00130 obby::text::size_type obby::text::chunk::get_length() const
00131 {
00132 return m_text.length();
00133 }
00134
00135 obby::text::text(size_type initial_chunk_size):
00136 m_max_chunk(CHUNK_SIZE(initial_chunk_size) )
00137 {
00138 }
00139
00140 obby::text::text(const text& other):
00141 m_max_chunk(other.m_max_chunk)
00142 {
00143 for(list_type::const_iterator iter = other.m_chunks.begin();
00144 iter != other.m_chunks.end();
00145 ++ iter)
00146 {
00147 m_chunks.push_back(new chunk(**iter) );
00148 }
00149 }
00150
00151 obby::text::text(const string_type& string,
00152 const user* author,
00153 size_type initial_chunk_size):
00154 m_max_chunk(CHUNK_SIZE(initial_chunk_size) )
00155 {
00156 for(size_type n = 0; n < string.length(); ++ n)
00157 {
00158 size_type len = std::min(string.length() - n, m_max_chunk);
00159 m_chunks.push_back(new chunk(string.substr(n, len), author) );
00160 }
00161 }
00162
00163 obby::text::text(const net6::packet& pack,
00164 unsigned int& index,
00165 const user_table& table):
00166 m_max_chunk(CHUNK_INIT)
00167 {
00168 unsigned int count = pack.get_param(index ++).as<unsigned int>();
00169 for(unsigned int i = 0; i < count; ++ i)
00170 m_chunks.push_back(new chunk(pack, index, table) );
00171 }
00172
00173 obby::text::text(const serialise::object& obj,
00174 const user_table& table):
00175 m_max_chunk(CHUNK_INIT)
00176 {
00177 for(serialise::object::child_iterator iter = obj.children_begin();
00178 iter != obj.children_end();
00179 ++ iter)
00180 {
00181 if(iter->get_name() == "chunk")
00182 {
00183 m_chunks.push_back(new chunk(*iter, table) );
00184 }
00185 else
00186 {
00187
00188 format_string str(_("Unexpected child node: '%0%'") );
00189 str << iter->get_name();
00190 throw serialise::error(str.str(), iter->get_line() );
00191 }
00192 }
00193 }
00194
00195 obby::text::~text()
00196 {
00197 clear();
00198 }
00199
00200 obby::text& obby::text::operator=(const text& other)
00201 {
00202 if(&other == this) return *this;
00203
00204 clear();
00205 m_max_chunk = other.m_max_chunk;
00206
00207 for(list_type::const_iterator iter = other.m_chunks.begin();
00208 iter != other.m_chunks.end();
00209 ++ iter)
00210 {
00211 m_chunks.push_back(new chunk(**iter) );
00212 }
00213
00214 return *this;
00215 }
00216
00217 void obby::text::serialise(serialise::object& obj) const
00218 {
00219 for(list_type::const_iterator it = m_chunks.begin();
00220 it != m_chunks.end();
00221 ++ it)
00222 {
00223 serialise::object& part = obj.add_child();
00224 part.set_name("chunk");
00225 (*it)->serialise(part);
00226 }
00227 }
00228
00229 void obby::text::append_packet(net6::packet& pack) const
00230 {
00231 pack << m_chunks.size();
00232 for(list_type::const_iterator it = m_chunks.begin();
00233 it != m_chunks.end();
00234 ++ it)
00235 {
00236 (*it)->append_packet(pack);
00237 }
00238 }
00239
00240 void obby::text::clear()
00241 {
00242 for(list_type::iterator it = m_chunks.begin();
00243 it != m_chunks.end();
00244 ++ it)
00245 {
00246 delete *it;
00247 }
00248
00249 m_chunks.clear();
00250 }
00251
00252 obby::text obby::text::substr(size_type pos, size_type len) const
00253 {
00254 text new_text;
00255 list_type::const_iterator iter = find_chunk(pos);
00256
00257 chunk* prev_chunk = NULL;
00258 while( (len == npos || len > 0) && (iter != m_chunks.end()) )
00259 {
00260 chunk* cur_chunk = *iter;
00261 size_type count = cur_chunk->get_length() - pos;
00262
00263 if(len != npos)
00264 {
00265 count = std::min(count, len);
00266 len -= count;
00267 }
00268
00269 if(prev_chunk != NULL &&
00270 prev_chunk->get_author() == cur_chunk->get_author() &&
00271 prev_chunk->get_length() + cur_chunk->get_length() <=
00272 m_max_chunk)
00273 {
00274 prev_chunk->append(
00275 cur_chunk->get_text().substr(pos, count)
00276 );
00277 }
00278 else
00279 {
00280 prev_chunk = new chunk(
00281 cur_chunk->get_text().substr(pos, count),
00282 cur_chunk->get_author()
00283 );
00284
00285 new_text.m_chunks.push_back(prev_chunk);
00286 }
00287
00288 ++ iter; pos = 0;
00289 }
00290
00291 if(len > 0 && len != npos)
00292 {
00293 throw std::logic_error(
00294 "obby::text::substr:\n"
00295 "len is out or range"
00296 );
00297 }
00298
00299 return new_text;
00300 }
00301
00302 void obby::text::insert(size_type pos,
00303 const string_type& str,
00304 const user* author)
00305 {
00306 list_type::iterator ins_pos = find_chunk(pos);
00307 insert_chunk(ins_pos, pos, str, author);
00308 }
00309
00310 void obby::text::insert(size_type pos,
00311 const text& str)
00312 {
00313 list_type::iterator ins_pos = find_chunk(pos);
00314 for(list_type::const_iterator it = str.m_chunks.begin();
00315 it != str.m_chunks.end();
00316 ++ it)
00317 {
00318 ins_pos = insert_chunk(
00319 ins_pos,
00320 pos,
00321 (*it)->get_text(),
00322 (*it)->get_author()
00323 );
00324 }
00325 }
00326
00327 void obby::text::erase(size_type pos, size_type len)
00328 {
00329 list_type::iterator ers_pos = find_chunk(pos);
00330 list_type::iterator first_chunk = ers_pos;
00331 size_type first_pos = pos;
00332
00333
00334
00335
00336
00337 if(first_pos == 0 && first_chunk != m_chunks.begin() )
00338 {
00339 -- first_chunk;
00340 first_pos = (*first_chunk)->get_length();
00341 }
00342
00343 while( (len == npos || len > 0) && ers_pos != m_chunks.end() )
00344 {
00345 size_type count = (*ers_pos)->get_length() - pos;
00346 if(len != npos)
00347 {
00348 count = std::min(count, len);
00349 len -= count;
00350 }
00351
00352 ers_pos = erase_chunk(ers_pos, pos, count);
00353
00354 if(first_pos > 0 && (*first_chunk)->get_length() > first_pos)
00355 {
00356 ers_pos = first_chunk;
00357 pos = first_pos;
00358 }
00359 else
00360 {
00361 pos = 0;
00362 }
00363 }
00364
00365 if(len != npos && len > 0)
00366 {
00367 throw std::logic_error(
00368 "obby::text::erase:\n"
00369 "len is out of range"
00370 );
00371 }
00372 }
00373
00374 void obby::text::append(const string_type& str,
00375 const user* author)
00376 {
00377 chunk* last_chunk = NULL;
00378 if(!m_chunks.empty() ) last_chunk = *m_chunks.rbegin();
00379 size_type pos = 0;
00380
00381
00382 if(last_chunk != NULL &&
00383 last_chunk->get_author() == author &&
00384 last_chunk->get_length() < m_max_chunk)
00385 {
00386 pos = std::min(
00387 m_max_chunk - last_chunk->get_length(),
00388 str.length()
00389 );
00390
00391 last_chunk->append(str.substr(0, pos) );
00392 }
00393
00394
00395 for(; pos < str.length(); pos += m_max_chunk)
00396 {
00397 size_type count = std::min(str.length() - pos, m_max_chunk);
00398 m_chunks.push_back(new chunk(str.substr(pos, count), author) );
00399 }
00400 }
00401
00402 void obby::text::append(const text& str)
00403 {
00404
00405 for(list_type::const_iterator it = str.m_chunks.begin();
00406 it != str.m_chunks.end();
00407 ++ it)
00408 {
00409 append( (*it)->get_text(), (*it)->get_author() );
00410 }
00411 }
00412
00413 void obby::text::prepend(const string_type& str,
00414 const user* author)
00415 {
00416 chunk* first_chunk = NULL;
00417 if(!m_chunks.empty() ) first_chunk = *m_chunks.begin();
00418
00419 size_type len = str.length();
00420
00421
00422 if(first_chunk != NULL &&
00423 first_chunk->get_author() == author &&
00424 first_chunk->get_length() < m_max_chunk)
00425 {
00426 size_type count = std::min(
00427 m_max_chunk - first_chunk->get_length(),
00428 len
00429 );
00430
00431 len -= count;
00432 first_chunk->prepend(str.substr(len, count) );
00433 }
00434
00435
00436 while(len > 0)
00437 {
00438 size_type count = std::min(
00439 len,
00440 m_max_chunk
00441 );
00442
00443 len -= count;
00444 m_chunks.push_front(new chunk(str.substr(len, count), author));
00445 }
00446 }
00447
00448 void obby::text::prepend(const text& str)
00449 {
00450 for(list_type::const_reverse_iterator it = str.m_chunks.rbegin();
00451 it != str.m_chunks.rend();
00452 ++ it)
00453 {
00454 prepend( (*it)->get_text(), (*it)->get_author() );
00455 }
00456 }
00457
00458 obby::text::size_type obby::text::length() const
00459 {
00460
00461 size_type len = 0;
00462 for(list_type::const_iterator it = m_chunks.begin();
00463 it != m_chunks.end();
00464 ++ it)
00465 {
00466 len += (*it)->get_length();
00467 }
00468
00469 return len;
00470 }
00471
00472 bool obby::text::operator==(const text& other) const
00473 {
00474 return compare(other) == EQUAL_OWNERMATCH;
00475 }
00476
00477 bool obby::text::operator!=(const text& other) const
00478 {
00479 return compare(other) != EQUAL_OWNERMATCH;
00480 }
00481
00482 bool obby::text::operator<(const text& other) const
00483 {
00484 return compare(other) == LESS;
00485 }
00486
00487 bool obby::text::operator>(const text& other) const
00488 {
00489 return compare(other) == GREATER;
00490 }
00491
00492 bool obby::text::operator<=(const text& other) const
00493 {
00494 return compare(other) != GREATER;
00495 }
00496
00497 bool obby::text::operator>=(const text& other) const
00498 {
00499 return compare(other) != LESS;
00500 }
00501
00502 bool obby::text::operator==(const string_type& other) const
00503 {
00504 return compare(other) == EQUAL;
00505 }
00506
00507 bool obby::text::operator!=(const string_type& other) const
00508 {
00509 return compare(other) != EQUAL;
00510 }
00511
00512 bool obby::text::operator<(const string_type& other) const
00513 {
00514 return compare(other) == LESS;
00515 }
00516
00517 bool obby::text::operator>(const string_type& other) const
00518 {
00519 return compare(other) == GREATER;
00520 }
00521
00522 bool obby::text::operator<=(const string_type& other) const
00523 {
00524 return compare(other) != GREATER;
00525 }
00526
00527 bool obby::text::operator>=(const string_type& other) const
00528 {
00529 return compare(other) != LESS;
00530 }
00531
00532 bool obby::text::empty() const
00533 {
00534 return m_chunks.empty();
00535 }
00536
00537 obby::text::chunk_iterator obby::text::chunk_begin() const
00538 {
00539 return chunk_iterator(m_chunks.begin() );
00540 }
00541
00542 obby::text::chunk_iterator obby::text::chunk_end() const
00543 {
00544 return chunk_iterator(m_chunks.end() );
00545 }
00546
00547 void obby::text::set_max_chunk_size(size_type max_chunk)
00548 {
00549 m_max_chunk = max_chunk;
00550 if(m_chunks.empty() ) return;
00551
00552
00553 list_type::iterator next = m_chunks.begin(); ++ next;
00554 for(list_type::iterator it = m_chunks.begin();
00555 it != m_chunks.end();
00556 ++ it, ++ next)
00557 {
00558 chunk* cur_chunk = *it;
00559
00560 chunk* next_chunk = NULL;
00561 if(next != m_chunks.end() ) next_chunk = *next;
00562
00563
00564 if(cur_chunk->get_length() > m_max_chunk)
00565 {
00566 size_type pos = m_max_chunk;
00567 while(cur_chunk->get_length() - pos > 0)
00568 {
00569
00570 if(next_chunk != NULL &&
00571 next_chunk->get_author() ==
00572 cur_chunk->get_author() &&
00573 cur_chunk->get_length() - pos +
00574 next_chunk->get_length() <= m_max_chunk)
00575 {
00576
00577
00578
00579
00580 next_chunk->prepend(
00581 cur_chunk->get_text().substr(
00582 pos
00583 )
00584 );
00585
00586 pos += (cur_chunk->get_length() - pos);
00587 }
00588
00589 else
00590 {
00591 size_type len = std::min(
00592 cur_chunk->get_length() - pos,
00593 m_max_chunk
00594 );
00595
00596 const std::string& text =
00597 cur_chunk->get_text();
00598
00599 it = m_chunks.insert(
00600 next,
00601 new chunk(
00602 text.substr(
00603 pos,
00604 len
00605 ),
00606 cur_chunk->get_author()
00607 )
00608 );
00609
00610 pos += len;
00611 }
00612
00613 }
00614
00615
00616 cur_chunk->erase(m_max_chunk);
00617 cur_chunk = *it;
00618 }
00619
00620 else if(next_chunk != NULL &&
00621 cur_chunk->get_author() == next_chunk->get_author() &&
00622 cur_chunk->get_length() + next_chunk->get_length() <=
00623 m_max_chunk)
00624 {
00625 cur_chunk->append(next_chunk->get_text() );
00626
00627 delete next_chunk;
00628 next = m_chunks.erase(next);
00629 }
00630 }
00631 }
00632
00633 obby::text::operator string_type() const
00634 {
00635 string_type str;
00636 str.reserve(length() );
00637
00638 for(list_type::const_iterator it = m_chunks.begin();
00639 it != m_chunks.end();
00640 ++ it)
00641 {
00642 str.append( (*it)->get_text() );
00643 }
00644
00645 return str;
00646 }
00647
00648 obby::text::list_type::iterator
00649 obby::text::find_chunk(size_type& pos)
00650 {
00651 return ::find_chunk<list_type&, list_type::iterator>(
00652 m_chunks,
00653 pos
00654 );
00655 }
00656
00657 obby::text::list_type::const_iterator
00658 obby::text::find_chunk(size_type& pos) const
00659 {
00660 return ::find_chunk<const list_type&, list_type::const_iterator>(
00661 m_chunks,
00662 pos
00663 );
00664 }
00665
00666 obby::text::list_type::iterator
00667 obby::text::insert_chunk(list_type::iterator chunk_it,
00668 size_type& chunk_pos,
00669 const string_type& str,
00670 const user* author)
00671 {
00672 chunk* cur_chunk = NULL;
00673 if(chunk_it != m_chunks.end() ) cur_chunk = *chunk_it;
00674
00675 list_type::iterator ins_pos = chunk_it;
00676
00677
00678 chunk* prev_chunk = NULL;
00679 list_type::iterator prev_pos = ins_pos;
00680 if(prev_pos != m_chunks.begin() )
00681 {
00682 -- prev_pos;
00683 prev_chunk = *prev_pos;
00684 }
00685
00686
00687 if(prev_chunk != NULL &&
00688 chunk_pos == 0 &&
00689 author == prev_chunk->get_author() &&
00690 str.length() + prev_chunk->get_length() <= m_max_chunk)
00691 {
00692 prev_chunk->append(str);
00693 return chunk_it;
00694 }
00695 else if(cur_chunk == NULL)
00696 {
00697
00698
00699
00700 }
00701
00702 else if(author == cur_chunk->get_author() &&
00703 str.length() + cur_chunk->get_length() <= m_max_chunk)
00704 {
00705 cur_chunk->insert(chunk_pos, str);
00706 chunk_pos += str.length();
00707 return chunk_it;
00708 }
00709
00710
00711 else if(chunk_pos == cur_chunk->get_length() )
00712 {
00713 ++ ins_pos;
00714 }
00715
00716
00717 else if(chunk_pos > 0)
00718 {
00719
00720 chunk* new_chunk = new chunk(
00721 cur_chunk->get_text().substr(chunk_pos),
00722 cur_chunk->get_author()
00723 );
00724
00725 cur_chunk->erase(chunk_pos);
00726 chunk_pos = 0;
00727
00728 ++ ins_pos;
00729 ins_pos = m_chunks.insert(
00730 ins_pos,
00731 new_chunk
00732 );
00733
00734
00735
00736 if(cur_chunk->get_author() == author)
00737 {
00738 if(cur_chunk->get_length() + str.length() <=
00739 m_max_chunk)
00740 {
00741 cur_chunk->append(str);
00742 chunk_pos = cur_chunk->get_length();
00743 -- ins_pos;
00744 return ins_pos;
00745 }
00746 else if(new_chunk->get_length() +
00747 str.length() <= m_max_chunk)
00748 {
00749 new_chunk->prepend(str);
00750 chunk_pos = str.length();
00751 return ins_pos;
00752 }
00753 }
00754
00755
00756
00757
00758 }
00759
00760
00761 if(str.length() <= m_max_chunk)
00762 {
00763 chunk_pos = 0;
00764 m_chunks.insert(ins_pos, new chunk(str, author) );
00765 return ins_pos;
00766 }
00767 else
00768 {
00769
00770
00771
00772 cur_chunk = ( (ins_pos == m_chunks.end()) ? NULL : *ins_pos);
00773 for(size_type n = 0; n < str.length(); n += m_max_chunk)
00774 {
00775 size_type len = std::min(str.length() - n, m_max_chunk);
00776
00777
00778 if(cur_chunk &&
00779 cur_chunk->get_author() == author &&
00780 len + cur_chunk->get_length() <= m_max_chunk)
00781 {
00782
00783
00784
00785 cur_chunk->prepend(str.substr(n, len) );
00786 chunk_pos = len;
00787 return ins_pos;
00788 }
00789 else
00790 {
00791 m_chunks.insert(
00792 ins_pos,
00793 new chunk(str.substr(n, len), author)
00794 );
00795 }
00796 }
00797
00798 chunk_pos = 0;
00799 return ins_pos;
00800 }
00801 }
00802
00803 obby::text::list_type::iterator
00804 obby::text::erase_chunk(list_type::iterator chunk_it,
00805 size_type pos,
00806 size_type len)
00807 {
00808 chunk* prev_chunk = NULL;
00809 chunk* next_chunk = NULL;
00810
00811 list_type::iterator prev_it = chunk_it;
00812 if(prev_it != m_chunks.begin() ) { -- prev_it; prev_chunk = *prev_it; }
00813
00814 list_type::iterator next_it = chunk_it;
00815 ++ next_it;
00816 if(next_it != m_chunks.end() ) { next_chunk = *next_it; }
00817
00818 chunk* cur_chunk = *chunk_it;
00819
00820
00821 if(pos + len > cur_chunk->get_length() )
00822 {
00823 throw std::logic_error(
00824 "obby::text::erase_chunk:\n"
00825 "Chunk len exceeded"
00826 );
00827 }
00828
00829
00830 if(len == cur_chunk->get_length() )
00831 {
00832 delete cur_chunk;
00833 m_chunks.erase(chunk_it);
00834
00835
00836 if(next_chunk != NULL && prev_chunk != NULL &&
00837 next_chunk->get_author() == prev_chunk->get_author() &&
00838 next_chunk->get_length() + prev_chunk->get_length() <
00839 m_max_chunk)
00840 {
00841 prev_chunk->append(next_chunk->get_text() );
00842
00843 delete next_chunk;
00844 next_it = m_chunks.erase(next_it);
00845 }
00846
00847 return next_it;
00848 }
00849
00850
00851 if(prev_chunk != NULL &&
00852 prev_chunk->get_author() == cur_chunk->get_author() &&
00853 cur_chunk->get_length() - len + prev_chunk->get_length() <
00854 m_max_chunk)
00855 {
00856 if(pos > 0)
00857 {
00858 prev_chunk->append(
00859 cur_chunk->get_text().substr(0, pos)
00860 );
00861 }
00862
00863 if(pos + len < cur_chunk->get_length() )
00864 {
00865 prev_chunk->append(
00866 cur_chunk->get_text().substr(pos + len)
00867 );
00868 }
00869
00870 delete cur_chunk;
00871 m_chunks.erase(chunk_it);
00872
00873
00874 if(next_chunk != NULL &&
00875 prev_chunk->get_author() == next_chunk->get_author() &&
00876 prev_chunk->get_length() + next_chunk->get_length() <=
00877 m_max_chunk)
00878 {
00879 prev_chunk->append(next_chunk->get_text() );
00880
00881 delete next_chunk;
00882 next_it = m_chunks.erase(next_it);
00883 }
00884
00885 return next_it;
00886 }
00887
00888
00889 if(next_chunk != NULL &&
00890 next_chunk->get_author() == cur_chunk->get_author() &&
00891 cur_chunk->get_length() - len + next_chunk->get_length() <
00892 m_max_chunk)
00893 {
00894 if(pos + len < cur_chunk->get_length() )
00895 {
00896 next_chunk->prepend(
00897 cur_chunk->get_text().substr(pos)
00898 );
00899 }
00900
00901 if(pos > 0)
00902 {
00903 next_chunk->prepend(
00904 cur_chunk->get_text().substr(0, pos)
00905 );
00906 }
00907
00908 delete cur_chunk;
00909 m_chunks.erase(chunk_it);
00910
00911
00912
00913
00914 ++ next_it;
00915 return next_it;
00916 }
00917
00918
00919 cur_chunk->erase(pos, len);
00920 return next_it;
00921 }
00922
00923 obby::text::compare_result obby::text::compare(const text& other) const
00924 {
00925 list_type::const_iterator it1 = m_chunks.begin();
00926 list_type::const_iterator it2 = other.m_chunks.begin();
00927
00928 size_type pos1 = 0, pos2 = 0;
00929 bool author_match = true;
00930
00931 while(it1 != m_chunks.end() && it2 != other.m_chunks.end() )
00932 {
00933
00934
00935
00936 if( (*it1)->get_author() != (*it2)->get_author() )
00937 author_match = false;
00938
00939 size_type len = std::min(
00940 (*it1)->get_length() - pos1,
00941 (*it2)->get_length() - pos2
00942 );
00943
00944 int res = (*it1)->get_text().compare(
00945 pos1,
00946 len,
00947 (*it2)->get_text(),
00948 pos2,
00949 len
00950 );
00951
00952 if(res != 0) return res < 0 ? LESS : GREATER;
00953
00954 pos1 += len;
00955 pos2 += len;
00956
00957 if(pos1 == (*it1)->get_length() )
00958 { ++ it1; pos1 = 0; }
00959 if(pos2 == (*it2)->get_length() )
00960 { ++ it2; pos2 = 0; }
00961 }
00962
00963
00964 if(it1 != m_chunks.end() )
00965 return GREATER;
00966
00967 else if(it2 != other.m_chunks.end() )
00968 return LESS;
00969
00970 else
00971 return author_match ? EQUAL_OWNERMATCH : EQUAL;
00972 }
00973
00974 obby::text::compare_result obby::text::compare(const string_type& text) const
00975 {
00976 size_type pos = 0;
00977 for(list_type::const_iterator it = m_chunks.begin();
00978 it != m_chunks.end();
00979 ++ it)
00980 {
00981 size_type len = (*it)->get_length();
00982 int res = text.compare(pos, len, (*it)->get_text());
00983 if(res != 0) return res < 0 ? LESS : GREATER;
00984 pos += len;
00985 }
00986
00987 return EQUAL;
00988 }