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

STL

开发平台:

Visual C++

  1. /* vim: set tabstop=4 : */
  2. #include "MemStream.h"
  3. #include <sstream>
  4. #include <stdexcept>
  5. #include <typeinfo>
  6. namespace febird {
  7. //void MemIO_Base::seek_cur(ptrdiff_t diff)
  8. void throw_EndOfFile(const char* func, size_t want, size_t available)
  9. {
  10. std::ostringstream oss;
  11. oss << "in " << func << ", want=" << want
  12. << ", available=" << available
  13. // << ", tell=" << tell() << ", size=" << size()
  14. ;
  15. throw EndOfFileException(oss.str().c_str());
  16. }
  17. void throw_OutOfSpace(const char* func, size_t want, size_t available)
  18. {
  19. std::ostringstream oss;
  20. oss << "in " << func << ", want=" << want
  21. << ", available=" << available
  22. // << ", tell=" << tell() << ", size=" << size()
  23. ;
  24. throw OutOfSpaceException(oss.str().c_str());
  25. }
  26. void MemIO::throw_EndOfFile(const char* func, size_t want)
  27. {
  28. febird::throw_EndOfFile(func, want, available());
  29. }
  30. void MemIO::throw_OutOfSpace(const char* func, size_t want)
  31. {
  32. febird::throw_OutOfSpace(func, want, available());
  33. }
  34. //////////////////////////////////////////////////////////////////////////
  35. void SeekableMemIO::swap(SeekableMemIO& that)
  36. {
  37. std::swap(m_beg, that.m_beg);
  38. std::swap(m_end, that.m_end);
  39. std::swap(m_pos, that.m_pos);
  40. }
  41. void SeekableMemIO::seek(long newPos)
  42. {
  43. assert(newPos >= 0);
  44. if (newPos < 0 || newPos > m_end - m_beg) {
  45. std::ostringstream oss;
  46. oss << "in " << BOOST_CURRENT_FUNCTION
  47. << "[newPos=" << newPos << ", size=" << m_end << "]";
  48. throw std::invalid_argument(oss.str());
  49. }
  50. m_pos = m_beg + newPos;
  51. }
  52. void SeekableMemIO::seek(long offset, int origin)
  53. {
  54. size_t pos;
  55. switch (origin)
  56. {
  57. default:
  58. {
  59. std::ostringstream oss;
  60. oss << "in " << BOOST_CURRENT_FUNCTION
  61. << "[offset=" << offset << ", origin=" << origin << "(invalid)]";
  62. throw std::invalid_argument(oss.str().c_str());
  63. }
  64. case 0: pos = (size_t)(0 + offset); break;
  65. case 1: pos = (size_t)(tell() + offset); break;
  66. case 2: pos = (size_t)(size() + offset); break;
  67. }
  68. seek(pos);
  69. }
  70. // rarely used methods....
  71. //
  72. MemIO SeekableMemIO::range(size_t ibeg, size_t iend) const
  73. {
  74. assert(ibeg <= iend);
  75. assert(ibeg <= size());
  76. assert(iend <= size());
  77. if (ibeg <= iend && ibeg <= size() && iend <= size())
  78. {
  79. return MemIO(m_beg + ibeg, m_beg + iend);
  80. }
  81. std::ostringstream oss;
  82. oss << BOOST_CURRENT_FUNCTION
  83. << ": size=" << size()
  84. << ", tell=" << tell()
  85. << ", ibeg=" << ibeg
  86. << ", iend=" << iend
  87. ;
  88. throw std::invalid_argument(oss.str());
  89. }
  90. //////////////////////////////////////////////////////////////////////////
  91. static std::allocator<byte> G_byteAlloc;
  92. AutoGrownMemIO::AutoGrownMemIO(size_t size)
  93. {
  94. // m_beg = 0 == size ? 0 : (byte*)::malloc(size);
  95. try {
  96. m_beg = 0 == size ? 0 : G_byteAlloc.allocate(size);
  97. }
  98. catch (const std::exception& exp)
  99. {
  100. std::ostringstream oss;
  101. oss << "at " << BOOST_CURRENT_FUNCTION << ": size=" << size
  102. << ", nested-exption[, type=" << typeid(exp).name() << ", what=" << exp.what() << "]";
  103. throw std::runtime_error(oss.str());
  104. }
  105. m_end = m_beg + size;
  106. m_pos = m_beg;
  107. }
  108. AutoGrownMemIO::~AutoGrownMemIO()
  109. {
  110. // if (m_beg) ::free(m_beg);
  111. if (m_beg)
  112. G_byteAlloc.deallocate(m_beg, size());
  113. }
  114. void AutoGrownMemIO::clone(const AutoGrownMemIO& src)
  115. {
  116. AutoGrownMemIO t(src.size());
  117. memcpy(t.begin(), src.begin(), src.size());
  118. this->swap(t);
  119. }
  120. void AutoGrownMemIO::swap(AutoGrownMemIO& that)
  121. {
  122. std::swap(m_beg, that.m_beg);
  123. std::swap(m_end, that.m_end);
  124. std::swap(m_pos, that.m_pos);
  125. }
  126. /**
  127.  @brief 改变 buffer 尺寸
  128.   
  129.   不改变 buffer 中的已存内容,不改变 pos
  130.  @note must m_pos <= newsize
  131.  */
  132. void AutoGrownMemIO::resize(size_t newsize)
  133. {
  134. assert(tell() <= newsize);
  135. // byte* newbeg = (byte*)::realloc(m_beg, newsize);
  136. byte* newbeg = 0;
  137. try {
  138. newbeg = G_byteAlloc.allocate(newsize);
  139. }
  140. catch (const std::exception& exp)
  141. {
  142. std::ostringstream oss;
  143. oss << "at " << BOOST_CURRENT_FUNCTION << ": size=" << size() << ", newsize=" << newsize
  144. << ", nested-exption[, type=" << typeid(exp).name() << ", what=" << exp.what() << "]";
  145. throw std::runtime_error(oss.str());
  146. }
  147. if (newbeg)
  148. {
  149. memcpy(newbeg, m_beg, size());
  150. m_pos = newbeg + (m_pos - m_beg);
  151. m_beg = newbeg;
  152. m_end = newbeg + newsize;
  153. }
  154. else
  155. {
  156. #ifdef _MSC_VER
  157. std::ostringstream oss;
  158. oss << "realloc failed in "void AutoGrownMemIO::resize(newsize=" << newsize
  159. << ")", the AutoGrownMemIO object is not mutated!";
  160. throw std::bad_alloc(oss.str().c_str());
  161. #else
  162. throw std::bad_alloc();
  163. #endif
  164. }
  165. }
  166. /**
  167.  @brief 释放原先的空间并重新分配
  168.   
  169.   相当于按新尺寸重新构造一个新 AutoGrownMemIO
  170.   不需要把旧内容拷贝到新地址
  171.  */
  172. void AutoGrownMemIO::init(size_t newsize)
  173. {
  174. // if (m_beg)
  175. // ::free(m_beg);
  176. // m_pos = m_beg = m_end = 0;
  177. // m_beg = (byte*)::malloc(newsize);
  178. size_t oldSize = size();
  179. try {
  180. if (m_beg) {
  181. G_byteAlloc.deallocate(m_beg, oldSize);
  182. m_pos = m_beg = m_end = 0;
  183. }
  184. m_beg = G_byteAlloc.allocate(newsize);
  185. }
  186. catch (const std::exception& exp)
  187. {
  188. std::ostringstream oss;
  189. oss << "at " << BOOST_CURRENT_FUNCTION << ": size=" << oldSize << ", newsize=" << newsize
  190. << ", nested-exption[, type=" << typeid(exp).name() << ", what=" << exp.what() << "]";
  191. throw std::runtime_error(oss.str());
  192. }
  193. if (0 == m_beg)
  194. {
  195. #ifdef _MSC_VER
  196. std::ostringstream oss;
  197. oss << "alloc failed in "" << BOOST_CURRENT_FUNCTION
  198. << "", with capacity=" << newsize
  199. << ", [this=" << (void*)(this)
  200. << "] was partly mutated and is not in consistent state!";
  201. throw std::bad_alloc(oss.str().c_str());
  202. #else
  203. throw std::bad_alloc();
  204. #endif
  205. }
  206. m_pos = m_beg;
  207. m_end = m_beg + newsize;
  208. }
  209. void AutoGrownMemIO::growAndWrite(const void* FEBIRD_RESTRICT data, size_t length)FEBIRD_RESTRICT 
  210. {
  211. using namespace std;
  212. size_t nSize = size();
  213. size_t nGrow = max(length, nSize);
  214. resize(max(nSize + nGrow, (size_t)64u));
  215. memcpy(m_pos, data, length);
  216. m_pos += length;
  217. }
  218. void AutoGrownMemIO::growAndWriteByte(byte b)FEBIRD_RESTRICT 
  219. {
  220. using namespace std;
  221. resize(max(2u * size(), (size_t)64u));
  222. *m_pos++ = b;
  223. }
  224. } // namespace febird