StreamBuffer.cpp
上传用户:kx_jwh
上传日期:2021-09-03
资源大小:76k
文件大小:20k
源码类别:

STL

开发平台:

Visual C++

  1. /* vim: set tabstop=4 : */
  2. #include <sstream>
  3. #include <stdexcept>
  4. #include "StreamBuffer.h"
  5. #include "IStreamWrapper.h"
  6. #include "FileStream.h"
  7. namespace febird {
  8. IOBufferBase::IOBufferBase()
  9. {
  10. m_beg = m_cur = m_end = 0;
  11. m_capacity = 8*1024;
  12. }
  13. IOBufferBase::~IOBufferBase()
  14. {
  15. if (m_beg) free(m_beg);
  16. }
  17. void IOBufferBase::initbuf(size_t capacity)
  18. {
  19. #ifdef _DEBUG
  20. // raise assert when debug
  21. assert(0 == m_beg);
  22. m_beg = (byte*)malloc(capacity);
  23. #else
  24. // when release, free m_beg for avoid memory leak
  25. m_beg = (byte*)realloc(m_beg, capacity);
  26. #endif
  27. m_cur = m_end = m_beg; // set as buffer overflow
  28. m_capacity = capacity;
  29. }
  30. // 在 initbuf 之前,可以调用多次,而不会引发内存分配动作
  31. // 在 initbuf 之后,会重新分配内存
  32. void IOBufferBase::set_bufsize(size_t size)
  33. {
  34. if (0 == m_beg)
  35. {
  36. m_capacity = size;
  37. }
  38. else
  39. {
  40. assert(m_capacity);
  41. byte* pnewbuf = (byte*)realloc(m_beg, size);
  42. if (0 == pnewbuf)
  43. {
  44. throw std::bad_alloc();
  45. }
  46. m_cur = pnewbuf + (m_cur-m_beg);
  47. m_end = pnewbuf + (m_end-m_beg);
  48. m_beg = pnewbuf;
  49. m_capacity = size;
  50. }
  51. }
  52. void IOBufferBase::seek_cur(ptrdiff_t diff)
  53. {
  54. assert(m_beg <= m_cur+diff && m_cur+diff <= m_end);
  55. m_cur += diff;
  56. }
  57. void IOBufferBase::set_bufeof(size_t eofpos)
  58. {
  59. assert(0 != m_beg);
  60. assert(eofpos <= m_capacity);
  61. assert(m_cur <= m_beg + eofpos);
  62. m_end = m_beg + eofpos;
  63. // for compiled with release, avoid error...
  64. if (m_cur > m_end)
  65. m_cur = m_end;
  66. }
  67. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  68. //
  69. //
  70. //! @return retval is 0, or in range[min_length, max_length]
  71. size_t InputBuffer::read_min_max(void* FEBIRD_RESTRICT vbuf, size_t min_length, size_t max_length) FEBIRD_RESTRICT 
  72. {
  73. assert(min_length <= max_length);
  74. if (0 == m_is)
  75. {
  76. std::ostringstream oss;
  77. oss << "in " << BOOST_CURRENT_FUNCTION << "m_is==NULL, regard as eof";
  78. throw EndOfFileException(oss.str().c_str());
  79. }
  80. size_t total = 0;
  81. while (total < min_length)
  82. {
  83. size_t n = m_is->read((unsigned char*)vbuf+total, max_length-total);
  84. if (0 == n) break;
  85. total += n;
  86. }
  87. return total;
  88. }
  89. size_t InputBuffer::fill_and_read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT 
  90. {
  91. return do_fill_and_read(vbuf, length);
  92. }
  93. // this function should not inline
  94. size_t InputBuffer::do_fill_and_read(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT 
  95. {
  96. // assert(length != 0);
  97. // assert(m_cur + length > m_end);
  98. // (0 == length && m_cur == m_end) means prefetch only
  99. assert(0 == length && m_cur == m_end || m_cur + length > m_end);
  100. if (0 == m_is)
  101. {
  102. std::ostringstream oss;
  103. oss << "in " << BOOST_CURRENT_FUNCTION << "m_is==NULL, regard as eof";
  104. throw EndOfFileException(oss.str().c_str());
  105. }
  106. if (0 == m_beg)
  107. {
  108. if (0 == m_capacity) // unbuffered
  109. {
  110. length = read_min_max(vbuf, length, length);
  111. if (0 == length)
  112.     throw EndOfFileException("InputBuffer::fill_and_read: unbuffered");
  113. return length;
  114. }
  115. else
  116. {
  117. initbuf(m_capacity);
  118. }
  119. }
  120. size_t nRead;
  121. size_t n1 = m_end - m_cur; // remain bytes in buffer
  122. size_t n2 = length - n1;   // remain bytes to read
  123. byte*  pb = (byte*)vbuf + n1; // bytes after n1
  124. memcpy(vbuf, m_cur, n1);
  125. if (n2 >= m_capacity) // remain bytes more than buffer capacity
  126. {
  127. m_cur = m_end = m_beg; // set buffer eof
  128. nRead = read_min_max(pb, n2, n2);
  129. if (0 == nRead)
  130. throw EndOfFileException("InputBuffer::do_fill_and_read, read 0 byte");
  131. this->update_pos(nRead);
  132. return n1 + nRead;
  133. }
  134. nRead = read_min_max(m_beg, n2, m_capacity);
  135. if (0 == nRead)
  136. throw EndOfFileException("InputBuffer::do_fill_and_read, read 0 byte");
  137. this->update_pos(nRead);
  138. m_end = m_beg + nRead;
  139. if (nRead < n2)
  140. { // readed bytes too less
  141. memcpy(pb, m_beg, nRead);
  142. m_cur = m_end;
  143. return n1 + nRead;
  144. } else {
  145. memcpy(pb, m_beg, n2);
  146. m_cur = m_beg + n2;
  147. return length;
  148. }
  149. }
  150. // this function should not inline
  151. void InputBuffer::fill_and_ensureRead(void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT 
  152. {
  153. size_t n = do_fill_and_read(vbuf, length);
  154. if (n != length)
  155. {
  156. std::ostringstream oss;
  157. oss << """ << BOOST_CURRENT_FUNCTION << """
  158.     << ", ReadBytes[want=" << length << ", read=" << n << "]";
  159. throw EndOfFileException(oss.str().c_str());
  160. }
  161. }
  162. // this function should not inline
  163. byte InputBuffer::fill_and_read_byte() FEBIRD_RESTRICT 
  164. {
  165. byte b;
  166. if (do_fill_and_read(&b, 1))
  167. return b;
  168. else
  169. throw EndOfFileException(BOOST_CURRENT_FUNCTION);
  170. }
  171. int InputBuffer::fill_and_get_byte() FEBIRD_RESTRICT 
  172. {
  173. byte b;
  174. if (do_fill_and_read(&b, 1))
  175. return b;
  176. else
  177. return -1;
  178. }
  179. void InputBuffer::getline(std::string& line, size_t maxlen)
  180. {
  181. // if (line.capacity() < maxlen)
  182. // line.reserve(maxlen);
  183. line.resize(0);
  184. size_t len = 0;
  185. for (;;)
  186. {
  187. for (byte* p = m_cur; ; ++p, ++len)
  188. {
  189. if (len == maxlen)
  190. {
  191. line.append((char*)m_cur, maxlen-len);
  192. assert(line.size() == len);
  193. m_cur = p;
  194. return;
  195. }
  196. if (p == m_end)
  197. {
  198. if (0 == m_beg)
  199. {
  200. initbuf(m_capacity);
  201. break;
  202. }
  203. line.append((char*)m_cur, (char*)m_end);
  204. assert(line.size() == len);
  205. m_cur = m_end;
  206. size_t nRead = read_min_max(m_beg, m_capacity, m_capacity);
  207. if (0 == nRead)
  208. {
  209. if (line.empty())
  210. throw EndOfFileException("InputBuffer::getline, read 0 byte");
  211. else {
  212. m_cur = m_end = m_beg;
  213. return;
  214. }
  215. }
  216. this->update_pos(nRead);
  217. m_end = m_beg + nRead;
  218. m_cur = m_beg;
  219. break;
  220. }
  221. // 换行有三种,在这里都支持
  222. //  1. "rn"
  223. //  2. "r"
  224. //  3. "n"
  225. if ('r' == *p)
  226. {
  227. line.append((char*)m_cur, (char*)p);
  228. assert(line.size() == len);
  229. // m_cur move to next char point by p, maybe p+1 == m_end
  230. m_cur = p + 1;
  231. // 如果下一个字符是换行,就直接吃掉它
  232. // 如果是文件末尾,直接返回
  233. int nextCh = getByte();
  234. if (-1 == nextCh) // eof
  235. return;
  236. if ('n' != nextCh)
  237. // not line feed, push back the byte
  238. --m_cur;
  239. return;
  240. }
  241. if ('n' == *p)
  242. {
  243. line.append((char*)m_cur, (char*)p);
  244. assert(line.size() == len);
  245. m_cur = p + 1;
  246. return;
  247. }
  248. }
  249. }
  250. }
  251. //////////////////////////////////////////////////////////////////////////////////////////////////////
  252. template<class BaseClass>
  253. OutputBufferBase<BaseClass>::~OutputBufferBase()
  254. {
  255. if (m_os) flush_buffer();
  256. }
  257. // this function should not inline
  258. template<class BaseClass>
  259. void OutputBufferBase<BaseClass>::flush_buffer()
  260. {
  261. if (0 == m_beg) // unbuffered
  262. {
  263. return;
  264. }
  265. if (0 == m_os)
  266. {
  267. std::ostringstream oss;
  268. oss << """ << BOOST_CURRENT_FUNCTION << """
  269. << ", m_os==NULL, regard as DelayedWriteFailException";
  270. throw DelayedWriteFailException(oss.str().c_str());
  271. }
  272. if (m_cur != m_beg)
  273. {
  274. assert(m_beg);
  275. // write [m_beg, m_cur) to stream
  276. //
  277. size_t n1 = m_cur-m_beg;
  278. size_t n2 = m_os->write(m_beg, n1);
  279. this->update_pos(n2);
  280. if (n1 != n2)
  281. {
  282. std::ostringstream oss;
  283. oss << """ << BOOST_CURRENT_FUNCTION << """
  284. << ", WriteBytes[want=" << n1 << ", written=" << n2 << "]";
  285. throw DelayedWriteFailException(oss.str().c_str());
  286. }
  287. }
  288. // set all buffer available
  289. m_cur = m_beg;
  290. m_end = m_beg + m_capacity;
  291. }
  292. template<class BaseClass>
  293. void OutputBufferBase<BaseClass>::flush()
  294. {
  295. flush_buffer();
  296. m_os->flush();
  297. }
  298. // this function should not inline
  299. template<class BaseClass>
  300. size_t OutputBufferBase<BaseClass>::flush_and_write(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT 
  301. {
  302. return do_flush_and_write(vbuf, length);
  303. }
  304. template<class BaseClass>
  305. size_t OutputBufferBase<BaseClass>::do_flush_and_write(const void* FEBIRD_RESTRICT vbuf, size_t length) FEBIRD_RESTRICT 
  306. {
  307. assert(length != 0);
  308. assert(m_cur + length > m_end);
  309. if (0 == m_os)
  310. {
  311. std::ostringstream oss;
  312. oss << """ << BOOST_CURRENT_FUNCTION << """
  313. << ", m_is==NULL, regard as DelayedWriteFailException";
  314. throw DelayedWriteFailException(oss.str().c_str());
  315. }
  316. if (length >= m_capacity) // remain bytes more than capacity, or unbuffered
  317. {
  318. flush_buffer();
  319. size_t n = m_os->write(vbuf, length);
  320. if (0 == n)
  321. {
  322. throw OutOfSpaceException(m_capacity ?
  323.     "flush_and_write" :
  324.    "flush_and_write: unbuffered");
  325. }
  326. this->update_pos(n);
  327. return n;
  328. }
  329. else if (0 == m_beg)
  330. {
  331. BaseClass::initbuf(this->m_capacity);
  332. }
  333. size_t n = m_end-m_cur; // remain free bytes in buffer
  334. memcpy(m_cur, vbuf, n);
  335. m_cur = m_end; // must set as m_end before flush
  336. flush_buffer();
  337. memcpy(m_beg, (byte*)vbuf+n, length-n); 
  338. m_cur = m_beg + (length-n);
  339. return length;
  340. }
  341. // this function should not inline
  342. template<class BaseClass>
  343. void OutputBufferBase<BaseClass>::flush_and_ensureWrite(const void* FEBIRD_RESTRICT vbuf, size_t length)FEBIRD_RESTRICT 
  344. {
  345. size_t n = do_flush_and_write(vbuf, length);
  346. if (n != length)
  347. {
  348. std::ostringstream oss;
  349. oss << """ << BOOST_CURRENT_FUNCTION << """
  350.     << ", WriteBytes[want=" << length << ", written=" << n << "]";
  351. throw OutOfSpaceException(oss.str().c_str());
  352. }
  353. }
  354. // this function should not inline
  355. template<class BaseClass>
  356. void OutputBufferBase<BaseClass>::flush_and_write_byte(byte b)FEBIRD_RESTRICT 
  357. {
  358. assert(m_cur == m_end);
  359. do_flush_and_write(&b, 1);
  360. }
  361. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  362. // this function should not inline
  363. template<class BaseClass>
  364. void SeekableBufferBase<BaseClass>::seek(stream_position_t pos)
  365. {
  366. stream_position_t pos_beg, pos_end;
  367. if (is_prefetched()) {
  368. //! m_stream_pos is mapped to m_end
  369. pos_beg = m_stream_pos - (m_end - m_beg);
  370. pos_end = m_stream_pos;
  371. } else {
  372. //! m_stream_pos is mapped to m_beg
  373. pos_beg = m_stream_pos;
  374. pos_end = m_stream_pos + (m_end - m_beg);
  375. }
  376. if (m_beg!=m_end && pos_beg <= pos && pos <= pos_end)
  377. {
  378. // pos is in [pos_beg, pos_end]
  379. // map m_cur to pos_cur, not need change m_stream_pos and call m_seekable->seek(..)
  380. m_cur = m_beg + (pos - m_stream_pos);
  381. }
  382. else if (m_seekable)
  383. {
  384. invalidate_buffer();
  385. m_seekable->seek(pos);
  386. m_stream_pos = m_seekable->tell();
  387. m_end = m_cur = m_beg; // discard buffer
  388. }
  389. else
  390. {
  391. std::ostringstream oss;
  392. oss << """ << BOOST_CURRENT_FUNCTION << """ << "(pos=" << pos << ")";
  393. throw OutOfSpaceException(oss.str().c_str());
  394. }
  395. }
  396. // this function should not inline
  397. template<class BaseClass>
  398. void SeekableBufferBase<BaseClass>::seek(stream_offset_t offset, int origin)
  399. {
  400. switch (origin)
  401. {
  402. default:
  403. {
  404. std::ostringstream oss;
  405. oss << "in " << BOOST_CURRENT_FUNCTION
  406. << "[offset=" << offset << ", origin=" << origin << "(invalid)]";
  407. throw std::invalid_argument(oss.str().c_str());
  408. }
  409. case 0:
  410. seek(offset);
  411. break;
  412. case 1:
  413. if (m_beg!=m_end)
  414. {
  415. stream_position_t pos_beg, pos_end;
  416. if (is_prefetched()) {
  417. //! m_stream_pos is mapped to m_end
  418. pos_beg = m_stream_pos - (m_end - m_beg);
  419. pos_end = m_stream_pos;
  420. } else {
  421. //! m_stream_pos is mapped to m_beg
  422. pos_beg = m_stream_pos;
  423. pos_end = m_stream_pos + (m_end - m_beg);
  424. }
  425. // pos_cur should map to m_cur
  426. // calculate new pos_cur
  427. stream_position_t pos_cur = pos_beg + (m_cur-m_beg) + offset;
  428. if (pos_beg <= pos_cur && pos_cur <= pos_end)
  429. {
  430. // cur is in [m_stream_pos, end]
  431. // map m_cur to pos_cur, not need change m_stream_pos and call m_seekable->seek(..)
  432. m_cur += offset;
  433. }
  434. else if (m_seekable)
  435. {
  436. invalidate_buffer();
  437. m_seekable->seek(offset, 1);
  438. m_stream_pos = m_seekable->tell();
  439. m_end = m_cur = m_beg; // discard buffer
  440. }
  441. else
  442. {
  443. std::ostringstream oss;
  444. oss << """ << BOOST_CURRENT_FUNCTION << "", no seekable stream, "
  445. << "(offset=" << offset << ", origin=" << origin << ")";
  446. throw OutOfSpaceException(oss.str().c_str());
  447. }
  448. }
  449. else if (m_seekable)
  450. {
  451. m_seekable->seek(offset, 1);
  452. m_stream_pos = m_seekable->tell();
  453. }
  454. else
  455. {
  456. std::ostringstream oss;
  457. oss << """ << BOOST_CURRENT_FUNCTION << "", no seekable stream, "
  458. << "(offset=" << offset << ", origin=" << origin << ")";
  459. throw OutOfSpaceException(oss.str().c_str());
  460. }
  461. break;
  462. case 2:
  463. // --------------------------------------------------------------------
  464. // 这样会丢弃可能仍然有用的 buffer
  465. // 但系统调用的次数少,也不需要 m_seekable->size
  466. // m_end = m_cur = m_beg; // discard buffer
  467. // m_seekable->seek(offset, 2);
  468. //  m_stream_pos = m_seekable->tell();
  469. //  m_last_inc = 0;
  470. // --------------------------------------------------------------------
  471. // 还是这样?这样可能会避免丢弃仍然有用的 buffer,但系统调用次数多
  472. if (0 == m_seekable)
  473. {
  474. std::ostringstream oss;
  475. oss << """ << BOOST_CURRENT_FUNCTION << "", no seekable stream, "
  476. << "(offset=" << offset << ", origin=" << origin << ")";
  477. throw OutOfSpaceException(oss.str().c_str());
  478. }
  479. if (m_end == m_beg) {
  480. m_seekable->seek(offset, 2);
  481. m_stream_pos = m_seekable->tell();
  482. } else
  483. seek(m_seekable->size() + offset);
  484. break;
  485. }
  486. }
  487. template<class BaseClass>
  488. void SeekableBufferBase<BaseClass>::seek_cur(ptrdiff_t diff)
  489. {
  490. seek(diff, 1);
  491. }
  492. template<class BaseClass>
  493. stream_position_t SeekableBufferBase<BaseClass>::size() const
  494. {
  495. using namespace std;
  496. if (m_beg==m_end || is_prefetched())
  497. return m_seekable->size();
  498. else {
  499. assert(!is_prefetched());
  500. stream_position_t cur_size = m_stream_pos + (m_cur-m_beg);
  501. stream_position_t str_size = m_seekable->size();
  502. return max(cur_size, str_size);
  503. }
  504. }
  505. // this function should not inline
  506. template<class BaseClass>
  507. stream_position_t SeekableBufferBase<BaseClass>::tell() const
  508. {
  509. if (m_beg==m_end)
  510. return m_seekable->tell();
  511. else {
  512. if (is_prefetched())
  513. return m_stream_pos - (m_end - m_cur);
  514. else
  515. return m_stream_pos + (m_cur - m_beg);
  516. }
  517. }
  518. template<class BaseClass>
  519. void SeekableBufferBase<BaseClass>::update_pos(size_t inc)
  520. {
  521. m_stream_pos += inc;
  522. }
  523. //------------------------------------------------------------------------
  524. void SeekableInputBuffer::invalidate_buffer()
  525. {
  526. // do nothing...
  527. }
  528. int SeekableInputBuffer::is_prefetched() const
  529. {
  530. return true;
  531. }
  532. void SeekableOutputBuffer::invalidate_buffer()
  533. {
  534. flush_buffer();
  535. }
  536. int SeekableOutputBuffer::is_prefetched() const
  537. {
  538. return false;
  539. }
  540. //////////////////////////////////////////////////////////////////////////
  541. SeekableBuffer::SeekableBuffer()
  542. {
  543. m_dirty = false;
  544. m_prefetched = false;
  545. }
  546. SeekableBuffer::~SeekableBuffer()
  547. {
  548. if (m_os) flush_buffer();
  549. // reset buffer, to avoid super's destructor to flush again...
  550. m_cur = m_end = m_beg;
  551. }
  552. size_t SeekableBuffer::do_fill_and_read(void* FEBIRD_RESTRICT vbuf, size_t length)FEBIRD_RESTRICT 
  553. {
  554. invalidate_buffer();
  555. length = super::do_fill_and_read(vbuf, length);
  556. m_prefetched = true;
  557. return length;
  558. }
  559. size_t SeekableBuffer::do_flush_and_write(const void* FEBIRD_RESTRICT vbuf, size_t length)FEBIRD_RESTRICT 
  560. {
  561. invalidate_buffer();
  562. length = super::do_flush_and_write(vbuf, length);
  563. m_prefetched = false;
  564. m_dirty = true;
  565. return length;
  566. }
  567. void SeekableBuffer::flush_buffer()
  568. {
  569. if (m_dirty) {
  570. super::flush_buffer();
  571. m_prefetched = false;
  572. m_dirty = false;
  573. }
  574. }
  575. void SeekableBuffer::invalidate_buffer()
  576. {
  577. flush_buffer();
  578. m_end = m_cur = m_beg;
  579. }
  580. int SeekableBuffer::is_prefetched() const
  581. {
  582. return m_prefetched;
  583. }
  584. //////////////////////////////////////////////////////////////////////////
  585. FileStreamBuffer::FileStreamBuffer(const char* fname, const char* mode, size_t capacity)
  586. {
  587. this->set_bufsize(capacity);
  588. attach(new SeekableStreamWrapper<FileStream>(fname, mode));
  589. }
  590. FileStreamBuffer::~FileStreamBuffer()
  591. {
  592. flush_buffer();
  593. delete m_os;
  594. m_os = 0;
  595. m_is = 0;
  596. }
  597. //////////////////////////////////////////////////////////////////////////
  598. #if 0 //defined(__GNUC__) && __GNUC__ >= 4
  599. #else
  600. template class OutputBufferBase<InputBuffer>;
  601. template class OutputBufferBase<IOBufferBase>;
  602. template class SeekableBufferBase<InputBuffer>;
  603. template class SeekableBufferBase<OutputBuffer>;
  604. template class SeekableBufferBase<OutputBufferBase<InputBuffer> >;
  605. #endif
  606. //////////////////////////////////////////////////////////////////////////
  607. /*
  608. //! 功能和效率类似于 AutoGrownMemIO
  609. //!
  610. //! 现在 AutoGrownMemIO 更新了,为了效率,也使用指针存储 pos
  611. //! @note
  612. //!  如非必要,请勿使用这个类,最好使用 AutoGrownMemIO
  613. //!
  614. class AutoGrownMemIOBuffer : public SeekableBuffer
  615. {
  616. public:
  617. explicit AutoGrownMemIOBuffer(size_t capacity = 8*1024);
  618. ~AutoGrownMemIOBuffer();
  619. };
  620. //////////////////////////////////////////////////////////////////////////
  621. //! 这个类是个 Stream 的哑实现
  622. //!
  623. //! 只维护一个位置指针来表达 stream 何时结束,并不真正读取或写入数据
  624. //! 只要调用 theAutoGrownMemIOStub.attach(pStreamBuffer), 就构造了一个 AutoGrownMemIO 的等效类,效率可能比 AutoGrownMemIO 还要高一点
  625. //! 为了方便也可以使用 AutoGrownMemIOBuffer 构造一个 SeekableBuffer, 不过 AutoGrownMemIOBuffer 的效率稍低
  626. //! 这是因为 SeekableBuffer 同时支持读和写,本身效率就低一些(比其他四种 StreamBuffer)
  627. //! 如果 attach 其它四种 StreamBuffer, 效率就会很高
  628. //!
  629. //! 经测试比 AutoGrownMemIO 还要高大约 20% ---- 之前 AutoGrownMemIO 的 pos 使用 size_t 存储
  630. //! 应该是因为 AutoGrownMemIO 的 pos 是用 size_t 存储,读写时要多两次加法和两次内存读取操作
  631. //!
  632. //! 现在 AutoGrownMemIO 更新了,为了效率,也使用指针存储 pos
  633. //! @note
  634. //!  如非必要,请勿使用这个类,最好使用 AutoGrownMemIO
  635. //!
  636. class AutoGrownMemIOStub : public ISeekableStream
  637. {
  638. IOBufferBase* m_buf;
  639. size_t m_stub_pos;
  640. public:
  641. template<class StreamBufferT>
  642. explicit AutoGrownMemIOStub(StreamBufferT* buf = 0)
  643. {
  644. attach(buf);
  645. }
  646. template<class StreamBufferT>
  647. void attach(StreamBufferT* buf)
  648. {
  649. m_stub_pos = 0;
  650. m_buf = buf;
  651. buf->attach(this);
  652. }
  653. void seek(stream_position_t pos);
  654. void seek(stream_offset_t offset, int origin);
  655. stream_position_t tell();
  656. size_t read(void* vbuf, size_t length);
  657. size_t write(const void* vbuf, size_t length);
  658. void flush();   
  659. };
  660. void AutoGrownMemIOStub::seek(stream_position_t newPos)
  661. {
  662. if (newPos > m_buf->bufcapacity()) {
  663. std::ostringstream oss;
  664. oss << "in " << BOOST_CURRENT_FUNCTION
  665. << "[newPos=" << newPos << "(too large), size=" << m_buf->bufcapacity() << "]";
  666. throw std::invalid_argument(oss.str());
  667. }
  668. m_stub_pos = newPos;
  669. }
  670. void AutoGrownMemIOStub::seek(stream_offset_t offset, int origin)
  671. {
  672. stream_position_t pos;
  673. switch (origin)
  674. {
  675. default:
  676. {
  677. std::ostringstream oss;
  678. oss << "in " << BOOST_CURRENT_FUNCTION
  679. << "[offset=" << offset << ", origin=" << origin << "(invalid)]";
  680. throw std::invalid_argument(oss.str().c_str());
  681. }
  682. case 0: pos = (size_t)(0 + offset); break;
  683. case 1: pos = (size_t)(m_stub_pos + offset); break;
  684. case 2: pos = (size_t)(m_buf->bufcapacity() + offset); break;
  685. }
  686. seek(pos);
  687. }
  688. stream_position_t AutoGrownMemIOStub::tell()
  689. {
  690. return m_stub_pos;
  691. }
  692. size_t AutoGrownMemIOStub::read(void* vbuf, size_t length)
  693. {
  694. assert(length != 0);
  695. if (m_stub_pos == m_buf->bufcapacity() && length)
  696. throw EndOfFileException(BOOST_CURRENT_FUNCTION);
  697. else
  698. { // 假装读取,实际上不读任何数据
  699. using namespace std;
  700. size_t n = min(length, size_t(m_buf->bufcapacity() - m_stub_pos));
  701. m_stub_pos += n;
  702. return n;
  703. }
  704. }
  705. size_t AutoGrownMemIOStub::write(const void* vbuf, size_t length)
  706. {
  707. assert(length != 0);
  708. if (m_stub_pos >= m_buf->bufcapacity() && length)
  709. throw OutOfSpaceException(BOOST_CURRENT_FUNCTION);
  710. else
  711. {   // 假装写入,实际上不写任何数据
  712. using namespace std;
  713. size_t n = min(length, size_t(m_buf->bufcapacity() - m_stub_pos));
  714. m_stub_pos += n;
  715. return n;
  716. }
  717. }
  718. void AutoGrownMemIOStub::flush()
  719. {
  720. // do nothing...
  721. }
  722. //////////////////////////////////////////////////////////////////////////
  723. AutoGrownMemIOBuffer::AutoGrownMemIOBuffer(size_t capacity)
  724. : SeekableBuffer(capacity)
  725. {
  726. attach(new AutoGrownMemIOStub(this));
  727. m_end = m_beg + m_capacity;
  728. }
  729. AutoGrownMemIOBuffer::~AutoGrownMemIOBuffer()
  730. {
  731. delete m_os;
  732. m_os = 0;
  733. m_is = 0;
  734. }
  735. */
  736. } // febird