llbuffer.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:17k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llbuffer.cpp
  3.  * @author Phoenix
  4.  * @date 2005-09-20
  5.  * @brief Implementation of the segments, buffers, and buffer arrays.
  6.  *
  7.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2005-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #include "linden_common.h"
  35. #include "llbuffer.h"
  36. #include "llmath.h"
  37. #include "llmemtype.h"
  38. #include "llstl.h"
  39. /** 
  40.  * LLSegment
  41.  */
  42. LLSegment::LLSegment() :
  43. mChannel(0),
  44. mData(NULL),
  45. mSize(0)
  46. {
  47. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  48. }
  49. LLSegment::LLSegment(S32 channel, U8* data, S32 data_len) :
  50. mChannel(channel),
  51. mData(data),
  52. mSize(data_len)
  53. {
  54. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  55. }
  56. LLSegment::~LLSegment()
  57. {
  58. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  59. }
  60. bool LLSegment::isOnChannel(S32 channel) const
  61. {
  62. return (mChannel == channel);
  63. }
  64. S32 LLSegment::getChannel() const
  65. {
  66. return mChannel;
  67. }
  68. void LLSegment::setChannel(S32 channel)
  69. {
  70. mChannel = channel;
  71. }
  72. U8* LLSegment::data() const
  73. {
  74. return mData;
  75. }
  76. S32 LLSegment::size() const
  77. {
  78. return mSize;
  79. }
  80. bool LLSegment::operator==(const LLSegment& rhs) const
  81. {
  82. if((mData != rhs.mData)||(mSize != rhs.mSize)||(mChannel != rhs.mChannel))
  83. {
  84. return false;
  85. }
  86. return true;
  87. }
  88. /** 
  89.  * LLHeapBuffer
  90.  */
  91. LLHeapBuffer::LLHeapBuffer() :
  92. mBuffer(NULL),
  93. mSize(0),
  94. mNextFree(NULL),
  95. mReclaimedBytes(0)
  96. {
  97. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  98. const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
  99. allocate(DEFAULT_HEAP_BUFFER_SIZE);
  100. }
  101. LLHeapBuffer::LLHeapBuffer(S32 size) :
  102. mBuffer(NULL),
  103. mSize(0),
  104. mNextFree(NULL),
  105. mReclaimedBytes(0)
  106. {
  107. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  108. allocate(size);
  109. }
  110. LLHeapBuffer::LLHeapBuffer(const U8* src, S32 len) :
  111. mBuffer(NULL),
  112. mSize(0),
  113. mNextFree(NULL),
  114. mReclaimedBytes(0)
  115. {
  116. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  117. if((len > 0) && src)
  118. {
  119. allocate(len);
  120. if(mBuffer)
  121. {
  122. memcpy(mBuffer, src, len); /*Flawfinder: ignore*/
  123. }
  124. }
  125. }
  126. // virtual
  127. LLHeapBuffer::~LLHeapBuffer()
  128. {
  129. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  130. delete[] mBuffer;
  131. mBuffer = NULL;
  132. mSize = 0;
  133. mNextFree = NULL;
  134. }
  135. S32 LLHeapBuffer::bytesLeft() const
  136. {
  137. return (mSize - (mNextFree - mBuffer));
  138. }
  139. // virtual
  140. bool LLHeapBuffer::createSegment(
  141. S32 channel,
  142. S32 size,
  143. LLSegment& segment)
  144. {
  145. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  146. // get actual size of the segment.
  147. S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
  148. // bail if we cannot build a valid segment
  149. if(actual_size <= 0)
  150. {
  151. return false;
  152. }
  153. // Yay, we're done.
  154. segment = LLSegment(channel, mNextFree, actual_size);
  155. mNextFree += actual_size;
  156. return true;
  157. }
  158. // virtual
  159. bool LLHeapBuffer::reclaimSegment(const LLSegment& segment)
  160. {
  161. if(containsSegment(segment))
  162. {
  163. mReclaimedBytes += segment.size();
  164. if(mReclaimedBytes == mSize)
  165. {
  166. // We have reclaimed all of the memory from this
  167. // buffer. Therefore, we can reset the mNextFree to the
  168. // start of the buffer, and reset the reclaimed bytes.
  169. mReclaimedBytes = 0;
  170. mNextFree = mBuffer;
  171. }
  172. else if(mReclaimedBytes > mSize)
  173. {
  174. llwarns << "LLHeapBuffer reclaimed more memory than allocated."
  175. << " This is probably programmer error." << llendl;
  176. }
  177. return true;
  178. }
  179. return false;
  180. }
  181. // virtual
  182. bool LLHeapBuffer::containsSegment(const LLSegment& segment) const
  183. {
  184. // *NOTE: this check is fairly simple because heap buffers are
  185. // simple contiguous chunks of heap memory.
  186. if((mBuffer > segment.data())
  187.    || ((mBuffer + mSize) < (segment.data() + segment.size())))
  188. {
  189. return false;
  190. }
  191. return true;
  192. }
  193. void LLHeapBuffer::allocate(S32 size)
  194. {
  195. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  196. mReclaimedBytes = 0;
  197. mBuffer = new U8[size];
  198. if(mBuffer)
  199. {
  200. mSize = size;
  201. mNextFree = mBuffer;
  202. }
  203. }
  204. /** 
  205.  * LLBufferArray
  206.  */
  207. LLBufferArray::LLBufferArray() :
  208. mNextBaseChannel(0)
  209. {
  210. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  211. }
  212. LLBufferArray::~LLBufferArray()
  213. {
  214. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  215. std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
  216. }
  217. // static
  218. LLChannelDescriptors LLBufferArray::makeChannelConsumer(
  219. const LLChannelDescriptors& channels)
  220. {
  221. LLChannelDescriptors rv(channels.out());
  222. return rv;
  223. }
  224. LLChannelDescriptors LLBufferArray::nextChannel()
  225. {
  226. LLChannelDescriptors rv(mNextBaseChannel++);
  227. return rv;
  228. }
  229. S32 LLBufferArray::capacity() const
  230. {
  231. S32 total = 0;
  232. const_buffer_iterator_t iter = mBuffers.begin();
  233. const_buffer_iterator_t end = mBuffers.end();
  234. for(; iter != end; ++iter)
  235. {
  236. total += (*iter)->capacity();
  237. }
  238. return total;
  239. }
  240. bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
  241. {
  242. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  243. std::vector<LLSegment> segments;
  244. if(copyIntoBuffers(channel, src, len, segments))
  245. {
  246. mSegments.insert(mSegments.end(), segments.begin(), segments.end());
  247. return true;
  248. }
  249. return false;
  250. }
  251. bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)
  252. {
  253. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  254. std::vector<LLSegment> segments;
  255. if(copyIntoBuffers(channel, src, len, segments))
  256. {
  257. mSegments.insert(mSegments.begin(), segments.begin(), segments.end());
  258. return true;
  259. }
  260. return false;
  261. }
  262. bool LLBufferArray::insertAfter(
  263. segment_iterator_t segment,
  264. S32 channel,
  265. const U8* src,
  266. S32 len)
  267. {
  268. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  269. std::vector<LLSegment> segments;
  270. if(mSegments.end() != segment)
  271. {
  272. ++segment;
  273. }
  274. if(copyIntoBuffers(channel, src, len, segments))
  275. {
  276. mSegments.insert(segment, segments.begin(), segments.end());
  277. return true;
  278. }
  279. return false;
  280. }
  281. LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
  282. {
  283. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  284. segment_iterator_t end = mSegments.end();
  285. segment_iterator_t it = getSegment(address);
  286. if(it == end)
  287. {
  288. return end;
  289. }
  290. // We have the location and the segment.
  291. U8* base = (*it).data();
  292. S32 size = (*it).size();
  293. if(address == (base + size))
  294. {
  295. // No need to split, since this is the last byte of the
  296. // segment. We do not want to have zero length segments, since
  297. // that will only incur processing overhead with no advantage.
  298. return it;
  299. }
  300. S32 channel = (*it).getChannel();
  301. LLSegment segment1(channel, base, (address - base) + 1);
  302. *it = segment1;
  303. segment_iterator_t rv = it;
  304. ++it;
  305. LLSegment segment2(channel, address + 1, size - (address - base) - 1);
  306. mSegments.insert(it, segment2);
  307. return rv;
  308. }
  309.    
  310. LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()
  311. {
  312. return mSegments.begin();
  313. }
  314. LLBufferArray::segment_iterator_t LLBufferArray::endSegment()
  315. {
  316. return mSegments.end();
  317. }
  318. LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
  319. U8* address,
  320. LLSegment& segment)
  321. {
  322. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  323. segment_iterator_t rv = mSegments.begin();
  324. segment_iterator_t end = mSegments.end();
  325. if(!address)
  326. {
  327. if(rv != end)
  328. {
  329. segment = (*rv);
  330. }
  331. }
  332. else
  333. {
  334. // we have an address - find the segment it is in.
  335. for( ; rv != end; ++rv)
  336. {
  337. if((address >= (*rv).data())
  338.    && (address < ((*rv).data() + (*rv).size())))
  339. {
  340. if((++address) < ((*rv).data() + (*rv).size()))
  341. {
  342. // it's in this segment - construct an appropriate
  343. // sub-segment.
  344. segment = LLSegment(
  345. (*rv).getChannel(),
  346. address,
  347. (*rv).size() - (address - (*rv).data()));
  348. }
  349. else
  350. {
  351. ++rv;
  352. if(rv != end)
  353. {
  354. segment = (*rv);
  355. }
  356. }
  357. break;
  358. }
  359. }
  360. }
  361. if(rv == end)
  362. {
  363. segment = LLSegment();
  364. }
  365. return rv;
  366. }
  367. LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
  368. {
  369. segment_iterator_t end = mSegments.end();
  370. if(!address)
  371. {
  372. return end;
  373. }
  374. segment_iterator_t it = mSegments.begin();
  375. for( ; it != end; ++it)
  376. {
  377. if((address >= (*it).data())&&(address < (*it).data() + (*it).size()))
  378. {
  379. // found it.
  380. return it;
  381. }
  382. }
  383. return end;
  384. }
  385. LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(
  386. U8* address) const
  387. {
  388. const_segment_iterator_t end = mSegments.end();
  389. if(!address)
  390. {
  391. return end;
  392. }
  393. const_segment_iterator_t it = mSegments.begin();
  394. for( ; it != end; ++it)
  395. {
  396. if((address >= (*it).data())
  397.    && (address < (*it).data() + (*it).size()))
  398. {
  399. // found it.
  400. return it;
  401. }
  402. }
  403. return end;
  404. }
  405. /*
  406. U8* LLBufferArray::getAddressAfter(U8* address) 
  407. {
  408. U8* rv = NULL;
  409. segment_iterator_t it = getSegment(address);
  410. segment_iterator_t end = mSegments.end();
  411. if(it != end)
  412. {
  413. if(++address < ((*it).data() + (*it).size()))
  414. {
  415. // it's in the same segment
  416. rv = address;
  417. }
  418. else
  419. {
  420. // it's in the next segment
  421. if(++it != end)
  422. {
  423. rv = (*it).data();
  424. }
  425. }
  426. }
  427. return rv;
  428. }
  429. */
  430. S32 LLBufferArray::countAfter(S32 channel, U8* start) const
  431. {
  432. S32 count = 0;
  433. S32 offset = 0;
  434. const_segment_iterator_t it;
  435. const_segment_iterator_t end = mSegments.end();
  436. if(start)
  437. {
  438. it = getSegment(start);
  439. if(it == end)
  440. {
  441. return count;
  442. }
  443. if(++start < ((*it).data() + (*it).size()))
  444. {
  445. // it's in the same segment
  446. offset = start - (*it).data();
  447. }
  448. else if(++it == end)
  449. {
  450. // it's in the next segment
  451. return count;
  452. }
  453. }
  454. else
  455. {
  456. it = mSegments.begin();
  457. }
  458. while(it != end)
  459. {
  460. if((*it).isOnChannel(channel))
  461. {
  462. count += (*it).size() - offset;
  463. }
  464. offset = 0;
  465. ++it;
  466. }
  467. return count;
  468. }
  469. U8* LLBufferArray::readAfter(
  470. S32 channel,
  471. U8* start,
  472. U8* dest,
  473. S32& len) const
  474. {
  475. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  476. U8* rv = start;
  477. if(!dest || len <= 0)
  478. {
  479. return rv;
  480. }
  481. S32 bytes_left = len;
  482. len = 0;
  483. S32 bytes_to_copy = 0;
  484. const_segment_iterator_t it;
  485. const_segment_iterator_t end = mSegments.end();
  486. if(start)
  487. {
  488. it = getSegment(start);
  489. if(it == end)
  490. {
  491. return rv;
  492. }
  493. if((++start < ((*it).data() + (*it).size()))
  494.    && (*it).isOnChannel(channel))
  495. {
  496. // copy the data out of this segment
  497. S32 bytes_in_segment = (*it).size() - (start - (*it).data());
  498. bytes_to_copy = llmin(bytes_left, bytes_in_segment);
  499. memcpy(dest, start, bytes_to_copy); /*Flawfinder: ignore*/
  500. len += bytes_to_copy;
  501. bytes_left -= bytes_to_copy;
  502. rv = start + bytes_to_copy - 1;
  503. ++it;
  504. }
  505. else
  506. {
  507. ++it;
  508. }
  509. }
  510. else
  511. {
  512. it = mSegments.begin();
  513. }
  514. while(bytes_left && (it != end))
  515. {
  516. if(!((*it).isOnChannel(channel)))
  517. {
  518. ++it;
  519. continue;
  520. }
  521. bytes_to_copy = llmin(bytes_left, (*it).size());
  522. memcpy(dest + len, (*it).data(), bytes_to_copy); /*Flawfinder: ignore*/
  523. len += bytes_to_copy;
  524. bytes_left -= bytes_to_copy;
  525. rv = (*it).data() + bytes_to_copy - 1;
  526. ++it;
  527. }
  528. return rv;
  529. }
  530. U8* LLBufferArray::seek(
  531. S32 channel,
  532. U8* start,
  533. S32 delta) const
  534. {
  535. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  536. const_segment_iterator_t it;
  537. const_segment_iterator_t end = mSegments.end();
  538. U8* rv = start;
  539. if(0 == delta)
  540. {
  541. if((U8*)npos == start)
  542. {
  543. // someone is looking for end of data. 
  544. segment_list_t::const_reverse_iterator rit = mSegments.rbegin();
  545. segment_list_t::const_reverse_iterator rend = mSegments.rend();
  546. while(rit != rend)
  547. {
  548. if(!((*rit).isOnChannel(channel)))
  549. {
  550. ++rit;
  551. continue;
  552. }
  553. rv = (*rit).data() + (*rit).size();
  554. break;
  555. }
  556. }
  557. else if(start)
  558. {
  559. // This is sort of a weird case - check if zero bytes away
  560. // from current position is on channel and return start if
  561. // that is true. Otherwise, return NULL.
  562. it = getSegment(start);
  563. if((it == end) || !(*it).isOnChannel(channel))
  564. {
  565. rv = NULL;
  566. }
  567. }
  568. else
  569. {
  570. // Start is NULL, so return the very first byte on the
  571. // channel, or NULL.
  572. it = mSegments.begin();
  573. while((it != end) && !(*it).isOnChannel(channel))
  574. {
  575. ++it;
  576. }
  577. if(it != end)
  578. {
  579. rv = (*it).data();
  580. }
  581. }
  582. return rv;
  583. }
  584. if(start)
  585. {
  586. it = getSegment(start);
  587. if((it != end) && (*it).isOnChannel(channel))
  588. {
  589. if(delta > 0)
  590. {
  591. S32 bytes_in_segment = (*it).size() - (start - (*it).data());
  592. S32 local_delta = llmin(delta, bytes_in_segment);
  593. rv += local_delta;
  594. delta -= local_delta;
  595. ++it;
  596. }
  597. else
  598. {
  599. S32 bytes_in_segment = start - (*it).data();
  600. S32 local_delta = llmin(llabs(delta), bytes_in_segment);
  601. rv -= local_delta;
  602. delta += local_delta;
  603. }
  604. }
  605. }
  606. else if(delta < 0)
  607. {
  608. // start is NULL, and delta indicates seeking backwards -
  609. // return NULL.
  610. return NULL;
  611. }
  612. else
  613. {
  614. // start is NULL and delta > 0
  615. it = mSegments.begin();
  616. }
  617. if(delta > 0)
  618. {
  619. // At this point, we have an iterator into the segments, and
  620. // are seeking forward until delta is zero or we run out
  621. while(delta && (it != end))
  622. {
  623. if(!((*it).isOnChannel(channel)))
  624. {
  625. ++it;
  626. continue;
  627. }
  628. if(delta <= (*it).size())
  629. {
  630. // it's in this segment
  631. rv = (*it).data() + delta;
  632. }
  633. delta -= (*it).size();
  634. ++it;
  635. }
  636. if(delta && (it == end))
  637. {
  638. // Whoops - sought past end.
  639. rv = NULL;
  640. }
  641. }
  642. else //if(delta < 0)
  643. {
  644. // We are at the beginning of a segment, and need to search
  645. // backwards.
  646. segment_list_t::const_reverse_iterator rit(it);
  647. segment_list_t::const_reverse_iterator rend = mSegments.rend();
  648. while(delta && (rit != rend))
  649. {
  650. if(!((*rit).isOnChannel(channel)))
  651. {
  652. ++rit;
  653. continue;
  654. }
  655. if(llabs(delta) <= (*rit).size())
  656. {
  657. // it's in this segment.
  658. rv = (*rit).data() + (*rit).size() + delta;
  659. delta = 0;
  660. }
  661. else
  662. {
  663. delta += (*rit).size();
  664. }
  665. ++rit;
  666. }
  667. if(delta && (rit == rend))
  668. {
  669. // sought past the beginning.
  670. rv = NULL;
  671. }
  672. }
  673. return rv;
  674. }
  675. bool LLBufferArray::takeContents(LLBufferArray& source)
  676. {
  677. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  678. std::copy(
  679. source.mBuffers.begin(),
  680. source.mBuffers.end(),
  681. std::back_insert_iterator<buffer_list_t>(mBuffers));
  682. source.mBuffers.clear();
  683. std::copy(
  684. source.mSegments.begin(),
  685. source.mSegments.end(),
  686. std::back_insert_iterator<segment_list_t>(mSegments));
  687. source.mSegments.clear();
  688. source.mNextBaseChannel = 0;
  689. return true;
  690. }
  691. LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
  692. S32 channel,
  693. S32 len)
  694. {
  695. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  696. // start at the end of the buffers, because it is the most likely
  697. // to have free space.
  698. LLSegment segment;
  699. buffer_list_t::reverse_iterator it = mBuffers.rbegin();
  700. buffer_list_t::reverse_iterator end = mBuffers.rend();
  701. bool made_segment = false;
  702. for(; it != end; ++it)
  703. {
  704. if((*it)->createSegment(channel, len, segment))
  705. {
  706. made_segment = true;
  707. break;
  708. }
  709. }
  710. segment_iterator_t send = mSegments.end();
  711. if(!made_segment)
  712. {
  713. LLBuffer* buf = new LLHeapBuffer;
  714. mBuffers.push_back(buf);
  715. if(!buf->createSegment(channel, len, segment))
  716. {
  717. // failed. this should never happen.
  718. return send;
  719. }
  720. }
  721. // store and return the newly made segment
  722. mSegments.insert(send, segment);
  723. std::list<LLSegment>::reverse_iterator rv = mSegments.rbegin();
  724. ++rv;
  725. send = rv.base();
  726. return send;
  727. }
  728. bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
  729. {
  730. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  731. // Find out which buffer contains the segment, and if it is found,
  732. // ask it to reclaim the memory.
  733. bool rv = false;
  734. LLSegment segment(*erase_iter);
  735. buffer_iterator_t iter = mBuffers.begin();
  736. buffer_iterator_t end = mBuffers.end();
  737. for(; iter != end; ++iter)
  738. {
  739. // We can safely call reclaimSegment on every buffer, and once
  740. // it returns true, the segment was found.
  741. if((*iter)->reclaimSegment(segment))
  742. {
  743. rv = true;
  744. break;
  745. }
  746. }
  747. // No need to get the return value since we are not interested in
  748. // the interator retured by the call.
  749. (void)mSegments.erase(erase_iter);
  750. return rv;
  751. }
  752. bool LLBufferArray::copyIntoBuffers(
  753. S32 channel,
  754. const U8* src,
  755. S32 len,
  756. std::vector<LLSegment>& segments)
  757. {
  758. LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
  759. if(!src || !len) return false;
  760. S32 copied = 0;
  761. LLSegment segment;
  762. buffer_iterator_t it = mBuffers.begin();
  763. buffer_iterator_t end = mBuffers.end();
  764. for(; it != end;)
  765. {
  766. if(!(*it)->createSegment(channel, len, segment))
  767. {
  768. ++it;
  769. continue;
  770. }
  771. segments.push_back(segment);
  772. S32 bytes = llmin(segment.size(), len);
  773. memcpy(segment.data(), src + copied, bytes);  /* Flawfinder: Ignore */
  774. copied += bytes;
  775. len -= bytes;
  776. if(0 == len)
  777. {
  778. break;
  779. }
  780. }
  781. while(len)
  782. {
  783. LLBuffer* buf = new LLHeapBuffer;
  784. mBuffers.push_back(buf);
  785. if(!buf->createSegment(channel, len, segment))
  786. {
  787. // this totally failed - bail. This is the weird corner
  788. // case were we 'leak' memory. No worries about an actual
  789. // leak - we will still reclaim the memory later, but this
  790. // particular buffer array is hosed for some reason.
  791. // This should never happen.
  792. return false;
  793. }
  794. segments.push_back(segment);
  795. memcpy(segment.data(), src + copied, segment.size()); /*Flawfinder: ignore*/
  796. copied += segment.size();
  797. len -= segment.size();
  798. }
  799. return true;
  800. }