00001
00034 #include "linden_common.h"
00035 #include "llbuffer.h"
00036
00037 #include "llmath.h"
00038 #include "llmemtype.h"
00039 #include "llstl.h"
00040
00044 LLSegment::LLSegment() :
00045 mChannel(0),
00046 mData(NULL),
00047 mSize(0)
00048 {
00049 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00050 }
00051
00052 LLSegment::LLSegment(S32 channel, U8* data, S32 data_len) :
00053 mChannel(channel),
00054 mData(data),
00055 mSize(data_len)
00056 {
00057 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00058 }
00059
00060 LLSegment::~LLSegment()
00061 {
00062 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00063 }
00064
00065 bool LLSegment::isOnChannel(S32 channel) const
00066 {
00067 return (mChannel == channel);
00068 }
00069
00070 S32 LLSegment::getChannel() const
00071 {
00072 return mChannel;
00073 }
00074
00075 void LLSegment::setChannel(S32 channel)
00076 {
00077 mChannel = channel;
00078 }
00079
00080
00081 U8* LLSegment::data() const
00082 {
00083 return mData;
00084 }
00085
00086 S32 LLSegment::size() const
00087 {
00088 return mSize;
00089 }
00090
00091 bool LLSegment::operator==(const LLSegment& rhs) const
00092 {
00093 if((mData != rhs.mData)||(mSize != rhs.mSize)||(mChannel != rhs.mChannel))
00094 {
00095 return false;
00096 }
00097 return true;
00098 }
00099
00103 LLHeapBuffer::LLHeapBuffer() :
00104 mBuffer(NULL),
00105 mSize(0),
00106 mNextFree(NULL),
00107 mReclaimedBytes(0)
00108 {
00109 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00110 const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
00111 allocate(DEFAULT_HEAP_BUFFER_SIZE);
00112 }
00113
00114 LLHeapBuffer::LLHeapBuffer(S32 size) :
00115 mBuffer(NULL),
00116 mSize(0),
00117 mNextFree(NULL),
00118 mReclaimedBytes(0)
00119 {
00120 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00121 allocate(size);
00122 }
00123
00124 LLHeapBuffer::LLHeapBuffer(const U8* src, S32 len) :
00125 mBuffer(NULL),
00126 mSize(0),
00127 mNextFree(NULL),
00128 mReclaimedBytes(0)
00129 {
00130 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00131 if((len > 0) && src)
00132 {
00133 allocate(len);
00134 if(mBuffer)
00135 {
00136 memcpy(mBuffer, src, len);
00137 }
00138 }
00139 }
00140
00141
00142 LLHeapBuffer::~LLHeapBuffer()
00143 {
00144 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00145 delete[] mBuffer;
00146 mBuffer = NULL;
00147 mSize = 0;
00148 mNextFree = NULL;
00149 }
00150
00151 S32 LLHeapBuffer::bytesLeft() const
00152 {
00153 return (mSize - (mNextFree - mBuffer));
00154 }
00155
00156
00157 bool LLHeapBuffer::createSegment(
00158 S32 channel,
00159 S32 size,
00160 LLSegment& segment)
00161 {
00162 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00163
00164 S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
00165
00166
00167 if(actual_size <= 0)
00168 {
00169 return false;
00170 }
00171
00172
00173 segment = LLSegment(channel, mNextFree, actual_size);
00174 mNextFree += actual_size;
00175 return true;
00176 }
00177
00178
00179 bool LLHeapBuffer::reclaimSegment(const LLSegment& segment)
00180 {
00181 if(containsSegment(segment))
00182 {
00183 mReclaimedBytes += segment.size();
00184 if(mReclaimedBytes == mSize)
00185 {
00186
00187
00188
00189 mReclaimedBytes = 0;
00190 mNextFree = mBuffer;
00191 }
00192 else if(mReclaimedBytes > mSize)
00193 {
00194 llwarns << "LLHeapBuffer reclaimed more memory than allocated."
00195 << " This is probably programmer error." << llendl;
00196 }
00197 return true;
00198 }
00199 return false;
00200 }
00201
00202
00203 bool LLHeapBuffer::containsSegment(const LLSegment& segment) const
00204 {
00205
00206
00207 if((mBuffer > segment.data())
00208 || ((mBuffer + mSize) < (segment.data() + segment.size())))
00209 {
00210 return false;
00211 }
00212 return true;
00213 }
00214
00215 void LLHeapBuffer::allocate(S32 size)
00216 {
00217 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00218 mReclaimedBytes = 0;
00219 mBuffer = new U8[size];
00220 if(mBuffer)
00221 {
00222 mSize = size;
00223 mNextFree = mBuffer;
00224 }
00225 }
00226
00227
00231 LLBufferArray::LLBufferArray() :
00232 mNextBaseChannel(0)
00233 {
00234 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00235 }
00236
00237 LLBufferArray::~LLBufferArray()
00238 {
00239 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00240 std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
00241 }
00242
00243
00244 LLChannelDescriptors LLBufferArray::makeChannelConsumer(
00245 const LLChannelDescriptors& channels)
00246 {
00247 LLChannelDescriptors rv(channels.out());
00248 return rv;
00249 }
00250
00251 LLChannelDescriptors LLBufferArray::nextChannel()
00252 {
00253 LLChannelDescriptors rv(mNextBaseChannel++);
00254 return rv;
00255 }
00256
00257 S32 LLBufferArray::capacity() const
00258 {
00259 S32 total = 0;
00260 const_buffer_iterator_t iter = mBuffers.begin();
00261 const_buffer_iterator_t end = mBuffers.end();
00262 for(; iter != end; ++iter)
00263 {
00264 total += (*iter)->capacity();
00265 }
00266 return total;
00267 }
00268
00269 bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
00270 {
00271 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00272 std::vector<LLSegment> segments;
00273 if(copyIntoBuffers(channel, src, len, segments))
00274 {
00275 mSegments.insert(mSegments.end(), segments.begin(), segments.end());
00276 return true;
00277 }
00278 return false;
00279 }
00280
00281 bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)
00282 {
00283 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00284 std::vector<LLSegment> segments;
00285 if(copyIntoBuffers(channel, src, len, segments))
00286 {
00287 mSegments.insert(mSegments.begin(), segments.begin(), segments.end());
00288 return true;
00289 }
00290 return false;
00291 }
00292
00293 bool LLBufferArray::insertAfter(
00294 segment_iterator_t segment,
00295 S32 channel,
00296 const U8* src,
00297 S32 len)
00298 {
00299 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00300 std::vector<LLSegment> segments;
00301 if(mSegments.end() != segment)
00302 {
00303 ++segment;
00304 }
00305 if(copyIntoBuffers(channel, src, len, segments))
00306 {
00307 mSegments.insert(segment, segments.begin(), segments.end());
00308 return true;
00309 }
00310 return false;
00311 }
00312
00313 LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
00314 {
00315 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00316 segment_iterator_t end = mSegments.end();
00317 segment_iterator_t it = getSegment(address);
00318 if(it == end)
00319 {
00320 return end;
00321 }
00322
00323
00324 U8* base = (*it).data();
00325 S32 size = (*it).size();
00326 if(address == (base + size))
00327 {
00328
00329
00330
00331 return it;
00332 }
00333 S32 channel = (*it).getChannel();
00334 LLSegment segment1(channel, base, (address - base) + 1);
00335 *it = segment1;
00336 segment_iterator_t rv = it;
00337 ++it;
00338 LLSegment segment2(channel, address + 1, size - (address - base) - 1);
00339 mSegments.insert(it, segment2);
00340 return rv;
00341 }
00342
00343 LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()
00344 {
00345 return mSegments.begin();
00346 }
00347
00348 LLBufferArray::segment_iterator_t LLBufferArray::endSegment()
00349 {
00350 return mSegments.end();
00351 }
00352
00353 LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
00354 U8* address,
00355 LLSegment& segment)
00356 {
00357 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00358 segment_iterator_t rv = mSegments.begin();
00359 segment_iterator_t end = mSegments.end();
00360 if(!address)
00361 {
00362 if(rv != end)
00363 {
00364 segment = (*rv);
00365 }
00366 }
00367 else
00368 {
00369
00370 for( ; rv != end; ++rv)
00371 {
00372 if((address >= (*rv).data())
00373 && (address < ((*rv).data() + (*rv).size())))
00374 {
00375 if((++address) < ((*rv).data() + (*rv).size()))
00376 {
00377
00378
00379 segment = LLSegment(
00380 (*rv).getChannel(),
00381 address,
00382 (*rv).size() - (address - (*rv).data()));
00383 }
00384 else
00385 {
00386 ++rv;
00387 if(rv != end)
00388 {
00389 segment = (*rv);
00390 }
00391 }
00392 break;
00393 }
00394 }
00395 }
00396 if(rv == end)
00397 {
00398 segment = LLSegment();
00399 }
00400 return rv;
00401 }
00402
00403 LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
00404 {
00405 segment_iterator_t end = mSegments.end();
00406 if(!address)
00407 {
00408 return end;
00409 }
00410 segment_iterator_t it = mSegments.begin();
00411 for( ; it != end; ++it)
00412 {
00413 if((address >= (*it).data())&&(address < (*it).data() + (*it).size()))
00414 {
00415
00416 return it;
00417 }
00418 }
00419 return end;
00420 }
00421
00422 LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(
00423 U8* address) const
00424 {
00425 const_segment_iterator_t end = mSegments.end();
00426 if(!address)
00427 {
00428 return end;
00429 }
00430 const_segment_iterator_t it = mSegments.begin();
00431 for( ; it != end; ++it)
00432 {
00433 if((address >= (*it).data())
00434 && (address < (*it).data() + (*it).size()))
00435 {
00436
00437 return it;
00438 }
00439 }
00440 return end;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 S32 LLBufferArray::countAfter(S32 channel, U8* start) const
00470 {
00471 S32 count = 0;
00472 S32 offset = 0;
00473 const_segment_iterator_t it;
00474 const_segment_iterator_t end = mSegments.end();
00475 if(start)
00476 {
00477 it = getSegment(start);
00478 if(it == end)
00479 {
00480 return count;
00481 }
00482 if(++start < ((*it).data() + (*it).size()))
00483 {
00484
00485 offset = start - (*it).data();
00486 }
00487 else if(++it == end)
00488 {
00489
00490 return count;
00491 }
00492 }
00493 else
00494 {
00495 it = mSegments.begin();
00496 }
00497 while(it != end)
00498 {
00499 if((*it).isOnChannel(channel))
00500 {
00501 count += (*it).size() - offset;
00502 }
00503 offset = 0;
00504 ++it;
00505 }
00506 return count;
00507 }
00508
00509 U8* LLBufferArray::readAfter(
00510 S32 channel,
00511 U8* start,
00512 U8* dest,
00513 S32& len) const
00514 {
00515 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00516 U8* rv = start;
00517 if(!dest || len <= 0)
00518 {
00519 return rv;
00520 }
00521 S32 bytes_left = len;
00522 len = 0;
00523 S32 bytes_to_copy = 0;
00524 const_segment_iterator_t it;
00525 const_segment_iterator_t end = mSegments.end();
00526 if(start)
00527 {
00528 it = getSegment(start);
00529 if(it == end)
00530 {
00531 return rv;
00532 }
00533 if((++start < ((*it).data() + (*it).size()))
00534 && (*it).isOnChannel(channel))
00535 {
00536
00537 S32 bytes_in_segment = (*it).size() - (start - (*it).data());
00538 bytes_to_copy = llmin(bytes_left, bytes_in_segment);
00539 memcpy(dest, start, bytes_to_copy);
00540 len += bytes_to_copy;
00541 bytes_left -= bytes_to_copy;
00542 rv = start + bytes_to_copy - 1;
00543 ++it;
00544 }
00545 else
00546 {
00547 ++it;
00548 }
00549 }
00550 else
00551 {
00552 it = mSegments.begin();
00553 }
00554 while(bytes_left && (it != end))
00555 {
00556 if(!((*it).isOnChannel(channel)))
00557 {
00558 ++it;
00559 continue;
00560 }
00561 bytes_to_copy = llmin(bytes_left, (*it).size());
00562 memcpy(dest + len, (*it).data(), bytes_to_copy);
00563 len += bytes_to_copy;
00564 bytes_left -= bytes_to_copy;
00565 rv = (*it).data() + bytes_to_copy - 1;
00566 ++it;
00567 }
00568 return rv;
00569 }
00570
00571 U8* LLBufferArray::seek(
00572 S32 channel,
00573 U8* start,
00574 S32 delta) const
00575 {
00576 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00577 const_segment_iterator_t it;
00578 const_segment_iterator_t end = mSegments.end();
00579 U8* rv = start;
00580 if(0 == delta)
00581 {
00582 if((U8*)npos == start)
00583 {
00584
00585 segment_list_t::const_reverse_iterator rit = mSegments.rbegin();
00586 segment_list_t::const_reverse_iterator rend = mSegments.rend();
00587 while(rit != rend)
00588 {
00589 if(!((*rit).isOnChannel(channel)))
00590 {
00591 ++rit;
00592 continue;
00593 }
00594 rv = (*rit).data() + (*rit).size();
00595 break;
00596 }
00597 }
00598 else if(start)
00599 {
00600
00601
00602
00603 it = getSegment(start);
00604 if((it == end) || !(*it).isOnChannel(channel))
00605 {
00606 rv = NULL;
00607 }
00608 }
00609 else
00610 {
00611
00612
00613 it = mSegments.begin();
00614 while((it != end) && !(*it).isOnChannel(channel))
00615 {
00616 ++it;
00617 }
00618 if(it != end)
00619 {
00620 rv = (*it).data();
00621 }
00622 }
00623 return rv;
00624 }
00625 if(start)
00626 {
00627 it = getSegment(start);
00628 if((it != end) && (*it).isOnChannel(channel))
00629 {
00630 if(delta > 0)
00631 {
00632 S32 bytes_in_segment = (*it).size() - (start - (*it).data());
00633 S32 local_delta = llmin(delta, bytes_in_segment);
00634 rv += local_delta;
00635 delta -= local_delta;
00636 ++it;
00637 }
00638 else
00639 {
00640 S32 bytes_in_segment = start - (*it).data();
00641 S32 local_delta = llmin(llabs(delta), bytes_in_segment);
00642 rv -= local_delta;
00643 delta += local_delta;
00644 }
00645 }
00646 }
00647 else if(delta < 0)
00648 {
00649
00650
00651 return NULL;
00652 }
00653 else
00654 {
00655
00656 it = mSegments.begin();
00657 }
00658 if(delta > 0)
00659 {
00660
00661
00662 while(delta && (it != end))
00663 {
00664 if(!((*it).isOnChannel(channel)))
00665 {
00666 ++it;
00667 continue;
00668 }
00669 if(delta <= (*it).size())
00670 {
00671
00672 rv = (*it).data() + delta;
00673 }
00674 delta -= (*it).size();
00675 ++it;
00676 }
00677 if(delta && (it == end))
00678 {
00679
00680 rv = NULL;
00681 }
00682 }
00683 else
00684 {
00685
00686
00687 segment_list_t::const_reverse_iterator rit(it);
00688 segment_list_t::const_reverse_iterator rend = mSegments.rend();
00689 while(delta && (rit != rend))
00690 {
00691 if(!((*rit).isOnChannel(channel)))
00692 {
00693 ++rit;
00694 continue;
00695 }
00696 if(llabs(delta) <= (*rit).size())
00697 {
00698
00699 rv = (*rit).data() + (*rit).size() + delta;
00700 delta = 0;
00701 }
00702 else
00703 {
00704 delta += (*rit).size();
00705 }
00706 ++rit;
00707 }
00708 if(delta && (rit == rend))
00709 {
00710
00711 rv = NULL;
00712 }
00713 }
00714 return rv;
00715 }
00716
00717 bool LLBufferArray::takeContents(LLBufferArray& source)
00718 {
00719 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00720 std::copy(
00721 source.mBuffers.begin(),
00722 source.mBuffers.end(),
00723 std::back_insert_iterator<buffer_list_t>(mBuffers));
00724 source.mBuffers.clear();
00725 std::copy(
00726 source.mSegments.begin(),
00727 source.mSegments.end(),
00728 std::back_insert_iterator<segment_list_t>(mSegments));
00729 source.mSegments.clear();
00730 source.mNextBaseChannel = 0;
00731 return true;
00732 }
00733
00734 LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
00735 S32 channel,
00736 S32 len)
00737 {
00738 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00739
00740
00741 LLSegment segment;
00742 buffer_list_t::reverse_iterator it = mBuffers.rbegin();
00743 buffer_list_t::reverse_iterator end = mBuffers.rend();
00744 bool made_segment = false;
00745 for(; it != end; ++it)
00746 {
00747 if((*it)->createSegment(channel, len, segment))
00748 {
00749 made_segment = true;
00750 break;
00751 }
00752 }
00753 segment_iterator_t send = mSegments.end();
00754 if(!made_segment)
00755 {
00756 LLBuffer* buf = new LLHeapBuffer;
00757 mBuffers.push_back(buf);
00758 if(!buf->createSegment(channel, len, segment))
00759 {
00760
00761 return send;
00762 }
00763 }
00764
00765
00766 mSegments.insert(send, segment);
00767 std::list<LLSegment>::reverse_iterator rv = mSegments.rbegin();
00768 ++rv;
00769 send = rv.base();
00770 return send;
00771 }
00772
00773 bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
00774 {
00775 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00776
00777
00778
00779 bool rv = false;
00780 LLSegment segment(*erase_iter);
00781 buffer_iterator_t iter = mBuffers.begin();
00782 buffer_iterator_t end = mBuffers.end();
00783 for(; iter != end; ++iter)
00784 {
00785
00786
00787 if((*iter)->reclaimSegment(segment))
00788 {
00789 rv = true;
00790 break;
00791 }
00792 }
00793
00794
00795
00796 (void)mSegments.erase(erase_iter);
00797 return rv;
00798 }
00799
00800
00801 bool LLBufferArray::copyIntoBuffers(
00802 S32 channel,
00803 const U8* src,
00804 S32 len,
00805 std::vector<LLSegment>& segments)
00806 {
00807 LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
00808 if(!src || !len) return false;
00809 S32 copied = 0;
00810 LLSegment segment;
00811 buffer_iterator_t it = mBuffers.begin();
00812 buffer_iterator_t end = mBuffers.end();
00813 for(; it != end;)
00814 {
00815 if(!(*it)->createSegment(channel, len, segment))
00816 {
00817 ++it;
00818 continue;
00819 }
00820 segments.push_back(segment);
00821 S32 bytes = llmin(segment.size(), len);
00822 memcpy(segment.data(), src + copied, bytes);
00823 copied += bytes;
00824 len -= bytes;
00825 if(0 == len)
00826 {
00827 break;
00828 }
00829 }
00830 while(len)
00831 {
00832 LLBuffer* buf = new LLHeapBuffer;
00833 mBuffers.push_back(buf);
00834 if(!buf->createSegment(channel, len, segment))
00835 {
00836
00837
00838
00839
00840
00841 return false;
00842 }
00843 segments.push_back(segment);
00844 memcpy(segment.data(), src + copied, segment.size());
00845 copied += segment.size();
00846 len -= segment.size();
00847 }
00848 return true;
00849 }