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

STL

开发平台:

Visual C++

  1. /* vim: set tabstop=4 : */
  2. #ifndef __febird_io_AutoGrownMemIO_h__
  3. #define __febird_io_AutoGrownMemIO_h__
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. #include <assert.h>
  8. #include <string.h> // for memcpy
  9. //#include <stdarg.h>
  10. //#include <stdio.h>  // for size_t
  11. #include <stdexcept>
  12. #include <boost/current_function.hpp>
  13. //#include <boost/type_traits/integral_constant.hpp>
  14. #include <boost/mpl/bool.hpp>
  15. #include "../stdtypes.h"
  16. #include "IOException.h"
  17. namespace febird {
  18. FEBIRD_DLL_EXPORT void throw_EndOfFile(const char* func, size_t want, size_t available);
  19. FEBIRD_DLL_EXPORT void throw_OutOfSpace(const char* func, size_t want, size_t available);
  20. //! MinMemIO
  21. //! +--MemIO
  22. //!    +--SeekableMemIO
  23. //!       +--AutoGrownMemIO
  24. /**
  25.  @brief 最有效的MemIO
  26.  
  27.  只用一个指针保存当前位置,没有范围检查,只应该在完全可预测的情况下使用这个类
  28.  @note
  29.   -# 如果无法预测是否会越界,禁止使用该类
  30.  */
  31. class FEBIRD_DLL_EXPORT MinMemIO
  32. {
  33. public:
  34. typedef boost::mpl::false_ is_seekable; //!< 不能 seek
  35. void set(void* FEBIRD_RESTRICT vptr) { m_pos = (unsigned char*)vptr; }
  36. byte readByte() FEBIRD_RESTRICT { return *m_pos++; }
  37. int  getByte() FEBIRD_RESTRICT { return *m_pos++; }
  38. void writeByte(byte b) FEBIRD_RESTRICT { *m_pos++ = b; }
  39. void ensureRead(void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT 
  40. {
  41. memcpy(data, m_pos, length);
  42. m_pos += length;
  43. }
  44. void ensureWrite(const void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT 
  45. {
  46. memcpy(m_pos, data, length);
  47. m_pos += length;
  48. }
  49. size_t read(void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT 
  50. {
  51. memcpy(data, m_pos, length);
  52. m_pos += length;
  53. return length;
  54. }
  55. size_t write(const void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT 
  56. {
  57. memcpy(m_pos, data, length);
  58. m_pos += length;
  59. return length;
  60. }
  61. void flush() {} // do nothing...
  62. byte* current() const { return m_pos; }
  63. //! caller can use this function to determine an offset difference
  64. ptrdiff_t diff(const void* FEBIRD_RESTRICT start) const throw() { return m_pos - (byte*)start; }
  65. void skip(ptrdiff_t diff) throw() { m_pos += diff; }
  66. byte uncheckedReadByte() FEBIRD_RESTRICT { return *m_pos++; }
  67. void uncheckedWriteByte(byte b) FEBIRD_RESTRICT { *m_pos++ = b; }
  68. template<class InputStream>
  69. void from_input(InputStream& input, size_t length) FEBIRD_RESTRICT 
  70. {
  71. input.ensureRead(m_pos, length);
  72. m_pos += length;
  73. }
  74. template<class OutputStream>
  75. void to_output(OutputStream& output, size_t length) FEBIRD_RESTRICT 
  76. {
  77. output.ensureWrite(m_pos, length);
  78. m_pos += length;
  79. }
  80. protected:
  81. byte* FEBIRD_RESTRICT m_pos;
  82. };
  83. /**
  84.  @brief Mem Stream 操作所需的最小集合
  85.   
  86.   这个类的尺寸非常小,在极端情况下效率非常高,在使用外部提供的缓冲时,这个类是最佳的选择
  87.   这个类可以拷贝
  88.  */
  89. class FEBIRD_DLL_EXPORT MemIO : public MinMemIO
  90. {
  91. public:
  92. MemIO() {}
  93. MemIO(void* buf, size_t size) { set(buf, size); }
  94. MemIO(void* beg, void* end) { set(beg, end); }
  95. void set(void* buf, size_t size)
  96. {
  97. m_pos = (byte*)buf;
  98. m_end = (byte*)buf + size;
  99. }
  100. void set(void* beg, void* end)
  101. {
  102. m_pos = (byte*)beg;
  103. m_end = (byte*)end;
  104. }
  105. //! test pos reach end or not
  106. bool eof() const throw()
  107. {
  108. assert(m_pos <= m_end);
  109. return m_pos == m_end;
  110. }
  111. byte readByte() FEBIRD_RESTRICT throw(EndOfFileException);
  112. int  getByte() FEBIRD_RESTRICT throw();
  113. void writeByte(byte b) FEBIRD_RESTRICT throw(OutOfSpaceException);
  114. void ensureRead(void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT ;
  115. void ensureWrite(const void* FEBIRD_RESTRICT data, size_t length)FEBIRD_RESTRICT ;
  116. size_t read(void* FEBIRD_RESTRICT data, size_t length) throw();
  117. size_t write(const void* FEBIRD_RESTRICT data, size_t length) throw();
  118. // rarely used methods....
  119. //
  120. size_t available() const throw() { return m_end - m_pos; }
  121. byte*  end() const throw() { return m_end; }
  122. /**
  123.  @brief 向前跳过 @a diff 个字节
  124.  @a 可以是负数,表示向后跳跃
  125.  */
  126. void skip(ptrdiff_t diff)
  127. {
  128. assert(m_pos + diff <= m_end);
  129. if (m_pos + diff <= m_end)
  130. m_pos += diff;
  131. else
  132. throw std::invalid_argument("diff is too large");
  133. }
  134. template<class InputStream>
  135. void from_input(InputStream& input, size_t length)FEBIRD_RESTRICT 
  136. {
  137. if (m_pos + length > m_end)
  138. throw_OutOfSpace(BOOST_CURRENT_FUNCTION, length);
  139. input.ensureRead(m_pos, length);
  140. m_pos += length;
  141. }
  142. template<class OutputStream>
  143. void to_output(OutputStream& output, size_t length)FEBIRD_RESTRICT 
  144. {
  145. if (m_pos + length > m_end)
  146. throw_EndOfFile(BOOST_CURRENT_FUNCTION, length);
  147. output.ensureWrite(m_pos, length);
  148. m_pos += length;
  149. }
  150. protected:
  151. void throw_EndOfFile(const char* func, size_t want);
  152. void throw_OutOfSpace(const char* func, size_t want);
  153. protected:
  154. byte* FEBIRD_RESTRICT m_end; // only used by set/eof
  155. };
  156. class FEBIRD_DLL_EXPORT AutoGrownMemIO;
  157. class FEBIRD_DLL_EXPORT SeekableMemIO : public MemIO
  158. {
  159. public:
  160. typedef boost::mpl::true_ is_seekable; //!< 可以 seek
  161. SeekableMemIO() { m_pos = m_beg = m_end = 0; }
  162. SeekableMemIO(void* buf, size_t size) { set(buf, size); }
  163. SeekableMemIO(void* beg, void* end) { set(beg, end); }
  164. SeekableMemIO(const MemIO& x) { set(x.current(), x.end()); }
  165. void set(void* buf, size_t size) throw()
  166. {
  167. m_pos = (byte*)buf;
  168. m_beg = (byte*)buf;
  169. m_end = (byte*)buf + size;
  170. }
  171. void set(void* beg, void* end) throw()
  172. {
  173. m_pos = (byte*)beg;
  174. m_beg = (byte*)beg;
  175. m_end = (byte*)end;
  176. }
  177. byte*  begin()const throw() { return m_beg; }
  178. byte*  buf()  const throw() { return m_beg; }
  179. size_t size() const throw() { return m_end-m_beg; }
  180. size_t tell() const throw() { return m_pos-m_beg; }
  181. void rewind() throw() { m_pos = m_beg; }
  182. void seek(long newPos);
  183. void seek(long offset, int origin);
  184. void swap(SeekableMemIO& that);
  185. //@{
  186. //! return part of (*this) as a MemIO
  187. MemIO range(size_t ibeg, size_t iend) const;
  188. MemIO head() const throw() { return MemIO(m_beg, m_pos); }
  189. MemIO tail() const throw() { return MemIO(m_pos, m_end); }
  190. MemIO whole()const throw() { return MemIO(m_beg, m_end); }
  191. //@}
  192. protected:
  193. byte* FEBIRD_RESTRICT m_beg;
  194. private:
  195. SeekableMemIO(AutoGrownMemIO&);
  196. SeekableMemIO(const AutoGrownMemIO&);
  197. };
  198. /**
  199.  @brief AutoGrownMemIO 可以管理自己的 buffer
  200.  @note
  201.   - 如果只需要 Eofmark, 使用 MemIO 就可以了
  202.   - 如果还需要 seekable, 使用 SeekableMemIO
  203.  */
  204. //template<bool Use_c_malloc>
  205. class FEBIRD_DLL_EXPORT AutoGrownMemIO : public SeekableMemIO
  206. {
  207. DECLARE_NONE_COPYABLE_CLASS(AutoGrownMemIO);
  208. void growAndWrite(const void* FEBIRD_RESTRICT data, size_t length)FEBIRD_RESTRICT ;
  209. void growAndWriteByte(byte b)FEBIRD_RESTRICT ;
  210. public:
  211. explicit AutoGrownMemIO(size_t size = 0);
  212. ~AutoGrownMemIO();
  213. void writeByte(byte b) FEBIRD_RESTRICT 
  214. {
  215. assert(m_pos <= m_end);
  216. if (m_pos < m_end)
  217. *m_pos++ = b;
  218. else
  219. growAndWriteByte(b);
  220. }
  221. void ensureWrite(const void* data, size_t length) FEBIRD_RESTRICT 
  222. {
  223. assert(m_pos <= m_end);
  224. if (m_pos + length <= m_end) {
  225. ::memcpy(m_pos, data, length);
  226. m_pos += length;
  227. } else
  228. growAndWrite(data, length);
  229. }
  230. size_t write(const void* data, size_t length) FEBIRD_RESTRICT throw()
  231. {
  232. ensureWrite(data, length);
  233. return length;
  234. }
  235. /*
  236. void printf(const char* format, ...)
  237. #ifdef __GNUC__
  238. __THROW __attribute__ ((__format__ (__printf__, 1, 2)))
  239. #endif
  240. ;
  241. void vprintf(const char* format, av_list ap);
  242. #ifdef __GNUC__
  243. __THROW __attribute__ ((__format__ (__printf__, 1, 0)))
  244. #endif
  245. ;
  246. */
  247. void clone(const AutoGrownMemIO& src);
  248. // rarely used methods....
  249. //
  250. void resize(size_t newsize);
  251. void init(size_t size);
  252. template<class InputStream>
  253. void from_input(InputStream& input, size_t length) FEBIRD_RESTRICT 
  254. {
  255. if (m_pos + length > m_end)
  256. resize(tell() + length);
  257. input.ensureRead(m_pos, length);
  258. m_pos += length;
  259. }
  260. void swap(AutoGrownMemIO& that);
  261. private:
  262. //@{
  263. //! disable MemIO::set
  264. //!
  265. void set(void* buf, size_t size);
  266. void set(void* beg, void* end);
  267. //@}
  268. //@{
  269. //! disable convert-ability to MemIO
  270. //! this cause gcc warning: conversion to a reference to a base class will never use a type conversion operator
  271. //! see SeekableMemIO::SeekableMemIO(const AutoGrownMemIO&)
  272. // operator const SeekableMemIO&() const;
  273. // operator SeekableMemIO&();
  274. //@}
  275. };
  276. //////////////////////////////////////////////////////////////////////////
  277. /**
  278.  * @brief 读取 length 长的数据到 data
  279.  * 
  280.  * 这个函数还是值得 inline 的,可以参考如下手工的汇编代码:
  281.  *
  282.  * inlined in caller, 省略了寄存器保存和回复指令,实际情况下也有可能不用保存和恢复
  283.  *   mov eax, m_end
  284.  *   sub eax, m_pos
  285.  *   mov ecx, length
  286.  *   mov esi, m_pos
  287.  *   mov edi, data
  288.  *   cld
  289.  *   cmp eax, ecx
  290.  *   jl  Overflow
  291.  *   rep movsb
  292.  *   jmp End
  293.  * Overflow:
  294.  *   mov ecx, eax
  295.  *   rep movsb
  296.  * End:
  297.  *   mov m_pos, esi
  298.  * --------------------------------
  299.  * sub routine in caller:
  300.  *   push length
  301.  *   push data
  302.  *   push this
  303.  *   call MemIO::read
  304.  *   add  esp, 12 ; 如果是 stdcall, 则没有这条语句
  305.  */
  306. inline size_t MemIO::read(void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT throw()
  307. {
  308. register int n = m_end - m_pos;
  309. if (n < int(length)) {
  310. ::memcpy(data, m_pos, n);
  311. // m_pos = m_end;
  312. m_pos += n;
  313. return n;
  314. } else {
  315. ::memcpy(data, m_pos, length);
  316. m_pos += length;
  317. return length;
  318. }
  319. }
  320. inline size_t MemIO::write(const void* FEBIRD_RESTRICT data, size_t length) FEBIRD_RESTRICT throw()
  321. {
  322. register int n = m_end - m_pos;
  323. if (n < int(length)) {
  324. ::memcpy(m_pos, data, n);
  325. // m_pos = m_end;
  326. m_pos += n;
  327. return n;
  328. } else {
  329. ::memcpy(m_pos, data, length);
  330. m_pos += length;
  331. return length;
  332. }
  333. }
  334. inline void MemIO::ensureRead(void* FEBIRD_RESTRICT data, size_t length)FEBIRD_RESTRICT 
  335. {
  336. if (m_pos + length <= m_end) {
  337. ::memcpy(data, m_pos, length);
  338. m_pos += length;
  339. } else
  340. throw_EndOfFile(BOOST_CURRENT_FUNCTION, length);
  341. }
  342. inline void MemIO::ensureWrite(const void* FEBIRD_RESTRICT data, size_t length)FEBIRD_RESTRICT 
  343. {
  344. if (m_pos + length <= m_end) {
  345. ::memcpy(m_pos, data, length);
  346. m_pos += length;
  347. } else
  348. throw_OutOfSpace(BOOST_CURRENT_FUNCTION, length);
  349. }
  350. #ifdef _MSC_VER
  351. #pragma warning(push)
  352. #pragma warning(disable: 4715) // not all control paths return a value
  353. #endif
  354. inline byte MemIO::readByte() FEBIRD_RESTRICT throw(EndOfFileException)
  355. {
  356. if (m_pos < m_end)
  357. return *m_pos++;
  358. else
  359. throw_EndOfFile(BOOST_CURRENT_FUNCTION, 1);
  360. }
  361. #ifdef _MSC_VER
  362. #pragma warning(pop)
  363. #endif
  364. inline void MemIO::writeByte(byte b) FEBIRD_RESTRICT throw(OutOfSpaceException)
  365. {
  366. if (m_pos < m_end)
  367. *m_pos++ = b;
  368. else
  369. throw_OutOfSpace(BOOST_CURRENT_FUNCTION, 1);
  370. }
  371. inline int MemIO::getByte() FEBIRD_RESTRICT throw()
  372. {
  373. if (m_pos < m_end)
  374. return *m_pos++;
  375. else
  376. return -1;
  377. }
  378. //////////////////////////////////////////////////////////////////////////
  379. // AutoGrownMemIO can be dumped into DataIO
  380. //////////////////////////////////////////////////////////////////////////
  381. } // namespace febird
  382. #endif