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

STL

开发平台:

Visual C++

  1. /* vim: set tabstop=4 : */
  2. #ifndef __febird_io_MemMapStream_h__
  3. #define __febird_io_MemMapStream_h__
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. //#include <stdio.h>
  8. #include <assert.h>
  9. #include <string.h> // for memcpy
  10. #include "../stdtypes.h"
  11. //#include "../io/MemStream.h"
  12. //#include <boost/type_traits/integral_constant.hpp>
  13. #include <boost/mpl/bool.hpp>
  14. #include <boost/iterator.hpp>
  15. #include <boost/operators.hpp>
  16. #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
  17. # include <io.h>
  18. # include <sys/types.h>
  19. # include <sys/stat.h>
  20. # include <fcntl.h>
  21. #   include <windows.h>
  22. #else
  23. # include <sys/types.h>
  24. # include <sys/stat.h>
  25. #   include <sys/mman.h>
  26. # include <unistd.h>
  27. # include <fcntl.h>
  28. # include <errno.h>
  29. #endif
  30. namespace febird {
  31. class FEBIRD_DLL_EXPORT MemMapStream
  32. {
  33. DECLARE_NONE_COPYABLE_CLASS(MemMapStream)
  34. public:
  35. typedef boost::mpl::true_ is_seekable;
  36. static bool copyFile(const char* srcPath, const char* dstPath);
  37. static void ThrowOpenFileException(const char* fpath, int mode);
  38. public:
  39. MemMapStream(stream_position_t new_file_size, const std::string& fpath, int mode);
  40. MemMapStream();
  41. ~MemMapStream();
  42. bool is_open() const throw();
  43. void open(stream_position_t new_file_size, const std::string& fpath, int mode);
  44. void clone(const MemMapStream& source);
  45. void close();
  46. bool eof() const throw();
  47. int  getByte();
  48. byte readByte();
  49. void writeByte(byte b);
  50. void probe(size_t size);
  51. void skip(size_t size);
  52. //! must call probe(size) before calling this function
  53. void unchecked_skip(size_t size);
  54. size_t read(void* buf, size_t size);
  55. size_t write(const void* buf, size_t size);
  56. void ensureRead(void* buf, size_t size);
  57. void ensureWrite(const void* buf, size_t size);
  58. void flush();
  59. void seek(stream_offset_t offset, int origin);
  60. void seek(stream_position_t pos);
  61. stream_position_t tell() const throw();
  62. stream_position_t size() const throw();
  63. //! 均指当前被 map 的部分
  64. unsigned char* current() const throw() { return m_pos; }
  65. unsigned char* begin() const throw() { return m_beg; }
  66. unsigned char* end() const throw() { return m_end; }
  67. size_t map_size() const throw() { return m_end - m_beg; }
  68. size_t map_tell() const throw() { return m_pos - m_beg; }
  69. size_t map_available() const throw() { return m_end - m_pos; }
  70. void unchecked_write(const void* data, size_t size) throw();
  71. void unchecked_read(void* data, size_t size) throw();
  72. void remap(stream_position_t aligned_fpos, size_t unaligned_size);
  73. bool try_remap(stream_position_t aligned_fpos, size_t unaligned_size);
  74. void unaligned_remap(stream_position_t unaligned_fpos, size_t unaligned_size);
  75. void set_fsize(stream_position_t fsize);
  76. void* map(stream_position_t fpos, size_t size);
  77. void* map(stream_position_t fpos, size_t size, int mode);
  78. void  unmap(void* base, size_t size);
  79. size_t page_size() const { return m_page_size; }
  80. size_t best_block_size() const { return m_best_block_size; }
  81. void set_best_block_size(size_t n) { m_best_block_size = n; }
  82. const std::string& fpath() const { return m_fpath; }
  83. //  int errcode() const throw() { return m_errno; }
  84. //  std::string errmsg() const throw();
  85. int file_handle() const { return (int)m_hFile; }
  86. void align(stream_position_t* fpos, size_t* size)
  87. {
  88. stream_position_t base_off = align_down(*fpos, m_page_size);
  89. *size = align_up(*fpos - base_off + *size, m_page_size);
  90. *fpos = base_off;
  91. }
  92. int BinCompare(MemMapStream& y);
  93. protected:
  94. unsigned char* m_beg;
  95. unsigned char* m_pos;
  96. unsigned char* m_end;
  97. #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
  98. HANDLE m_hFile;
  99. HANDLE m_hMap;
  100. #else
  101. int m_hFile;
  102. #endif
  103. int  m_mode;
  104. // int  m_errno;
  105. stream_position_t m_file_size;
  106. stream_position_t m_file_pos;
  107. size_t m_best_block_size;
  108. size_t m_page_size;
  109. size_t m_AllocationGranularity;
  110. std::string m_fpath;
  111. void init();
  112. void init(stream_position_t new_file_size, const std::string& fpath, int mode);
  113. stream_position_t get_fsize();
  114. bool remap_impl(stream_position_t fpos, size_t size);
  115. void remap_and_skip(size_t size);
  116. void remap_and_probe(size_t size);
  117. size_t remap_and_read(void* buf, size_t size);
  118. size_t remap_and_write(const void* buf, size_t size);
  119. void remap_and_ensureRead(void* buf, size_t size);
  120. void remap_and_ensureWrite(const void* buf, size_t size);
  121. int  remap_and_getByte();
  122. byte remap_and_readByte();
  123. void remap_and_writeByte(unsigned char b);
  124. void cleanup_and_throw(const char* msg);
  125. };
  126. inline void MemMapStream::probe(size_t size)
  127. {
  128. if (m_pos+size <= m_end) {
  129. // do nothing ...
  130. } else
  131. remap_and_probe(size);
  132. }
  133. inline void MemMapStream::skip(size_t size)
  134. {
  135. if (m_pos+size <= m_end) {
  136. m_pos += size;
  137. } else
  138. remap_and_skip(size);
  139. }
  140. inline void MemMapStream::unchecked_skip(size_t size)
  141. {
  142. // if this assert fails, caller maybe not call probe(size) first
  143. assert(m_pos+size <= m_end);
  144. m_pos += size;
  145. }
  146. inline size_t MemMapStream::read(void* buf, size_t size)
  147. {
  148. if (m_pos+size <= m_end) {
  149. memcpy(buf, m_pos, size);
  150. m_pos += size;
  151. return size;
  152. } else
  153. return remap_and_read(buf, size);
  154. }
  155. inline size_t MemMapStream::write(const void* buf, size_t size)
  156. {
  157. if (m_pos+size <= m_end) {
  158. memcpy(m_pos, buf, size);
  159. m_pos += size;
  160. return size;
  161. } else
  162. return remap_and_write(buf, size);
  163. }
  164. inline void MemMapStream::ensureRead(void* buf, size_t size)
  165. {
  166. if (m_pos+size <= m_end) {
  167. memcpy(buf, m_pos, size);
  168. m_pos += size;
  169. } else
  170. remap_and_ensureRead(buf, size);
  171. }
  172. inline void MemMapStream::ensureWrite(const void* buf, size_t size)
  173. {
  174. if (m_pos+size <= m_end) {
  175. memcpy(m_pos, buf, size);
  176. m_pos += size;
  177. } else
  178. remap_and_ensureWrite(buf, size);
  179. }
  180. inline byte MemMapStream::readByte()
  181. {
  182. if (m_pos < m_end)
  183. return *m_pos++;
  184. else
  185. return remap_and_readByte();
  186. }
  187. inline int MemMapStream::getByte()
  188. {
  189. if (m_pos < m_end)
  190. return *m_pos++;
  191. else
  192. return remap_and_getByte();
  193. }
  194. inline void MemMapStream::writeByte(byte b)
  195. {
  196. if (m_pos < m_end)
  197. *m_pos++ = b;
  198. else
  199. remap_and_writeByte(b);
  200. }
  201. inline stream_position_t MemMapStream::tell() const throw()
  202. {
  203. return m_file_pos + (m_pos - m_beg);
  204. }
  205. inline void MemMapStream::unchecked_write(const void* data, size_t size) throw()
  206. {
  207. assert(m_pos <= m_end);
  208. memcpy(m_pos, data, size);
  209. m_pos += size;
  210. }
  211. inline void MemMapStream::unchecked_read(void* data, size_t size) throw()
  212. {
  213. assert(m_pos <= m_end);
  214. memcpy(data, m_pos, size);
  215. m_pos += size;
  216. }
  217. inline bool MemMapStream::eof() const throw()
  218. {
  219. return tell() == m_file_size;
  220. }
  221. template<class T>
  222. class MemMap_Iterator :
  223. public boost::forward_iterator_helper<MemMap_Iterator<T>, T>
  224. {
  225. public:
  226. explicit MemMap_Iterator(MemMapStream* mms = 0) : mms(mms) {}
  227. T& operator*() const
  228. {
  229. mms->probe(sizeof(T));
  230. return *(T*)mms->current();
  231. }
  232. MemMap_Iterator& operator++()
  233. {
  234. mms->skip(sizeof(T));
  235. return *this;
  236. }
  237. private:
  238. MemMapStream* mms;
  239. };
  240. class MMS_MapRegion
  241. {
  242. DECLARE_NONE_COPYABLE_CLASS(MMS_MapRegion)
  243. stream_position_t m_fpos;
  244. size_t            m_size;
  245. MemMapStream*     m_mms;
  246. unsigned char*    m_base;
  247. public:
  248. MMS_MapRegion(MemMapStream& mms, stream_position_t fpos, size_t size)
  249. : m_mms(&mms), m_fpos(fpos), m_size(size)
  250. {
  251. m_base = (unsigned char*)mms.map(fpos, size);
  252. }
  253. MMS_MapRegion(MemMapStream& mms, stream_position_t fpos, size_t size, int flag)
  254. : m_mms(&mms), m_fpos(fpos), m_size(size)
  255. {
  256. m_base = (unsigned char*)mms.map(fpos, size, flag);
  257. }
  258. ~MMS_MapRegion()
  259. {
  260. m_mms->unmap(m_base, m_size);
  261. }
  262. stream_position_t fpos() const { return m_fpos; }
  263. size_t            size() const { return m_size; }
  264. unsigned char*    base() const { return m_base; }
  265. bool cover(stream_position_t pos, size_t length) const
  266. {
  267. return pos >= m_fpos && pos + length <= m_fpos + m_size;
  268. }
  269. void swap(MMS_MapRegion& y)
  270. {
  271. std::swap(m_fpos, y.m_fpos);
  272. std::swap(m_size, y.m_size);
  273. std::swap(m_mms , y.m_mms );
  274. std::swap(m_base, y.m_base);
  275. }
  276. };
  277. //! 可以映射不对齐的内存数据
  278. class FEBIRD_DLL_EXPORT MMS_MapData
  279. {
  280. DECLARE_NONE_COPYABLE_CLASS(MMS_MapData)
  281. stream_position_t m_base_pos;
  282. size_t            m_offset;
  283. size_t            m_size;
  284. MemMapStream*     m_mms;
  285. unsigned char*    m_base_ptr;
  286. public:
  287. MMS_MapData(MemMapStream& mms, stream_position_t fpos, size_t size);
  288. MMS_MapData(MemMapStream& mms, stream_position_t fpos, size_t size, int flag);
  289. ~MMS_MapData();
  290. stream_position_t fpos() const { return m_base_pos + m_offset; }
  291. size_t size() const { return m_size; }
  292. unsigned char* data() const { return m_base_ptr + m_offset; }
  293. void swap(MMS_MapData& y)
  294. {
  295. std::swap(m_base_pos, y.m_base_pos);
  296. std::swap(m_offset  , y.m_offset);
  297. std::swap(m_size    , y.m_size);
  298. std::swap(m_mms     , y.m_mms);
  299. std::swap(m_base_ptr, y.m_base_ptr);
  300. }
  301. };
  302. } // namespace febird
  303. #endif