mapped_file.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. // (C) Copyright Jorge Lodos 2008.
  2. // (C) Copyright Jonathan Turkanis 2003.
  3. // (C) Copyright Craig Henderson 2002. 'boost/memmap.hpp' from sandbox
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
  6. #ifndef BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED
  7. #define BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED
  8. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  9. # pragma once
  10. #endif
  11. #include <boost/config.hpp> // make sure size_t is in std.
  12. #include <cstddef> // size_t.
  13. #include <string> // pathnames.
  14. #include <utility> // pair.
  15. #include <boost/config.hpp> // BOOST_MSVC.
  16. #include <boost/detail/workaround.hpp>
  17. #include <boost/iostreams/close.hpp>
  18. #include <boost/iostreams/concepts.hpp>
  19. #include <boost/iostreams/detail/config/auto_link.hpp>
  20. #include <boost/iostreams/detail/config/dyn_link.hpp>
  21. #include <boost/iostreams/detail/config/wide_streams.hpp>
  22. #include <boost/iostreams/detail/ios.hpp> // openmode, failure
  23. #include <boost/iostreams/detail/path.hpp>
  24. #include <boost/iostreams/operations_fwd.hpp>
  25. #include <boost/iostreams/positioning.hpp>
  26. #include <boost/shared_ptr.hpp>
  27. #include <boost/static_assert.hpp>
  28. #include <boost/throw_exception.hpp>
  29. #include <boost/type_traits/is_same.hpp>
  30. // Must come last.
  31. #include <boost/config/abi_prefix.hpp>
  32. namespace boost { namespace iostreams {
  33. //------------------Definition of mapped_file_base and mapped_file_params-----//
  34. // Forward declarations
  35. class mapped_file_source;
  36. class mapped_file_sink;
  37. class mapped_file;
  38. namespace detail { class mapped_file_impl; }
  39. class mapped_file_base {
  40. public:
  41. enum mapmode {
  42. readonly = 1,
  43. readwrite = 2,
  44. priv = 4
  45. };
  46. };
  47. // Bitmask operations for mapped_file_base::mapmode
  48. mapped_file_base::mapmode
  49. operator|(mapped_file_base::mapmode a, mapped_file_base::mapmode b);
  50. mapped_file_base::mapmode
  51. operator&(mapped_file_base::mapmode a, mapped_file_base::mapmode b);
  52. mapped_file_base::mapmode
  53. operator^(mapped_file_base::mapmode a, mapped_file_base::mapmode b);
  54. mapped_file_base::mapmode
  55. operator~(mapped_file_base::mapmode a);
  56. mapped_file_base::mapmode
  57. operator|=(mapped_file_base::mapmode& a, mapped_file_base::mapmode b);
  58. mapped_file_base::mapmode
  59. operator&=(mapped_file_base::mapmode& a, mapped_file_base::mapmode b);
  60. mapped_file_base::mapmode
  61. operator^=(mapped_file_base::mapmode& a, mapped_file_base::mapmode b);
  62. //------------------Definition of mapped_file_params--------------------------//
  63. namespace detail {
  64. struct mapped_file_params_base {
  65. mapped_file_params_base()
  66. : flags(static_cast<mapped_file_base::mapmode>(0)),
  67. mode(), offset(0), length(static_cast<std::size_t>(-1)),
  68. new_file_size(0), hint(0)
  69. { }
  70. private:
  71. friend class mapped_file_impl;
  72. void normalize();
  73. public:
  74. mapped_file_base::mapmode flags;
  75. BOOST_IOS::openmode mode; // Deprecated
  76. stream_offset offset;
  77. std::size_t length;
  78. stream_offset new_file_size;
  79. const char* hint;
  80. };
  81. } // End namespace detail.
  82. // This template allows Boost.Filesystem paths to be specified when creating or
  83. // reopening a memory mapped file, without creating a dependence on
  84. // Boost.Filesystem. Possible values of Path include std::string,
  85. // boost::filesystem::path, boost::filesystem::wpath,
  86. // and boost::iostreams::detail::path (used to store either a std::string or a
  87. // std::wstring).
  88. template<typename Path>
  89. struct basic_mapped_file_params
  90. : detail::mapped_file_params_base
  91. {
  92. typedef detail::mapped_file_params_base base_type;
  93. // For wide paths, instantiate basic_mapped_file_params
  94. // with boost::filesystem::wpath
  95. #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
  96. BOOST_STATIC_ASSERT((!is_same<Path, std::wstring>::value));
  97. #endif
  98. // Default constructor
  99. basic_mapped_file_params() { }
  100. // Construction from a Path
  101. explicit basic_mapped_file_params(const Path& p) : path(p) { }
  102. // Construction from a path of a different type
  103. template<typename PathT>
  104. explicit basic_mapped_file_params(const PathT& p) : path(p) { }
  105. // Copy constructor
  106. basic_mapped_file_params(const basic_mapped_file_params& other)
  107. : base_type(other), path(other.path)
  108. { }
  109. // Templated copy constructor
  110. template<typename PathT>
  111. basic_mapped_file_params(const basic_mapped_file_params<PathT>& other)
  112. : base_type(other), path(other.path)
  113. { }
  114. typedef Path path_type;
  115. Path path;
  116. };
  117. typedef basic_mapped_file_params<std::string> mapped_file_params;
  118. //------------------Definition of mapped_file_source--------------------------//
  119. class BOOST_IOSTREAMS_DECL mapped_file_source : public mapped_file_base {
  120. private:
  121. struct safe_bool_helper { int x; };
  122. typedef int safe_bool_helper::* safe_bool;
  123. typedef detail::mapped_file_impl impl_type;
  124. typedef basic_mapped_file_params<detail::path> param_type;
  125. friend class mapped_file;
  126. friend class detail::mapped_file_impl;
  127. friend struct boost::iostreams::operations<mapped_file_source>;
  128. public:
  129. typedef char char_type;
  130. struct category
  131. : public source_tag,
  132. public direct_tag,
  133. public closable_tag
  134. { };
  135. typedef std::size_t size_type;
  136. typedef const char* iterator;
  137. BOOST_STATIC_CONSTANT(size_type, max_length = static_cast<size_type>(-1));
  138. // Default constructor
  139. mapped_file_source();
  140. // Constructor taking a parameters object
  141. template<typename Path>
  142. explicit mapped_file_source(const basic_mapped_file_params<Path>& p);
  143. // Constructor taking a list of parameters
  144. template<typename Path>
  145. explicit mapped_file_source( const Path& path,
  146. size_type length = max_length,
  147. boost::intmax_t offset = 0 );
  148. // Copy Constructor
  149. mapped_file_source(const mapped_file_source& other);
  150. //--------------Stream interface------------------------------------------//
  151. template<typename Path>
  152. void open(const basic_mapped_file_params<Path>& p);
  153. template<typename Path>
  154. void open( const Path& path,
  155. size_type length = max_length,
  156. boost::intmax_t offset = 0 );
  157. bool is_open() const;
  158. void close();
  159. operator safe_bool() const;
  160. bool operator!() const;
  161. mapmode flags() const;
  162. //--------------Container interface---------------------------------------//
  163. size_type size() const;
  164. const char* data() const;
  165. iterator begin() const;
  166. iterator end() const;
  167. //--------------Query admissible offsets----------------------------------//
  168. // Returns the allocation granularity for virtual memory. Values passed
  169. // as offsets must be multiples of this value.
  170. static int alignment();
  171. private:
  172. void init();
  173. void open_impl(const param_type& p);
  174. boost::shared_ptr<impl_type> pimpl_;
  175. };
  176. //------------------Definition of mapped_file---------------------------------//
  177. class BOOST_IOSTREAMS_DECL mapped_file : public mapped_file_base {
  178. private:
  179. typedef mapped_file_source delegate_type;
  180. typedef delegate_type::safe_bool safe_bool;
  181. typedef basic_mapped_file_params<detail::path> param_type;
  182. friend struct boost::iostreams::operations<mapped_file >;
  183. friend class mapped_file_sink;
  184. public:
  185. typedef char char_type;
  186. struct category
  187. : public seekable_device_tag,
  188. public direct_tag,
  189. public closable_tag
  190. { };
  191. typedef mapped_file_source::size_type size_type;
  192. typedef char* iterator;
  193. typedef const char* const_iterator;
  194. BOOST_STATIC_CONSTANT(size_type, max_length = delegate_type::max_length);
  195. // Default constructor
  196. mapped_file() { }
  197. // Construstor taking a parameters object
  198. template<typename Path>
  199. explicit mapped_file(const basic_mapped_file_params<Path>& p);
  200. // Constructor taking a list of parameters
  201. template<typename Path>
  202. mapped_file( const Path& path,
  203. mapmode flags,
  204. size_type length = max_length,
  205. stream_offset offset = 0 );
  206. // Constructor taking a list of parameters, including a
  207. // std::ios_base::openmode (deprecated)
  208. template<typename Path>
  209. explicit mapped_file( const Path& path,
  210. BOOST_IOS::openmode mode =
  211. BOOST_IOS::in | BOOST_IOS::out,
  212. size_type length = max_length,
  213. stream_offset offset = 0 );
  214. // Copy Constructor
  215. mapped_file(const mapped_file& other);
  216. //--------------Conversion to mapped_file_source (deprecated)-------------//
  217. operator mapped_file_source&() { return delegate_; }
  218. operator const mapped_file_source&() const { return delegate_; }
  219. //--------------Stream interface------------------------------------------//
  220. // open overload taking a parameters object
  221. template<typename Path>
  222. void open(const basic_mapped_file_params<Path>& p);
  223. // open overload taking a list of parameters
  224. template<typename Path>
  225. void open( const Path& path,
  226. mapmode mode,
  227. size_type length = max_length,
  228. stream_offset offset = 0 );
  229. // open overload taking a list of parameters, including a
  230. // std::ios_base::openmode (deprecated)
  231. template<typename Path>
  232. void open( const Path& path,
  233. BOOST_IOS::openmode mode =
  234. BOOST_IOS::in | BOOST_IOS::out,
  235. size_type length = max_length,
  236. stream_offset offset = 0 );
  237. bool is_open() const { return delegate_.is_open(); }
  238. void close() { delegate_.close(); }
  239. operator safe_bool() const { return delegate_; }
  240. bool operator!() const { return !delegate_; }
  241. mapmode flags() const { return delegate_.flags(); }
  242. //--------------Container interface---------------------------------------//
  243. size_type size() const { return delegate_.size(); }
  244. char* data() const;
  245. const char* const_data() const { return delegate_.data(); }
  246. iterator begin() const { return data(); }
  247. const_iterator const_begin() const { return const_data(); }
  248. iterator end() const { return data() + size(); }
  249. const_iterator const_end() const { return const_data() + size(); }
  250. //--------------Query admissible offsets----------------------------------//
  251. // Returns the allocation granularity for virtual memory. Values passed
  252. // as offsets must be multiples of this value.
  253. static int alignment() { return mapped_file_source::alignment(); }
  254. //--------------File access----------------------------------------------//
  255. void resize(stream_offset new_size);
  256. private:
  257. delegate_type delegate_;
  258. };
  259. //------------------Definition of mapped_file_sink----------------------------//
  260. class BOOST_IOSTREAMS_DECL mapped_file_sink : private mapped_file {
  261. public:
  262. friend struct boost::iostreams::operations<mapped_file_sink>;
  263. using mapped_file::mapmode;
  264. using mapped_file::readonly;
  265. using mapped_file::readwrite;
  266. using mapped_file::priv;
  267. using mapped_file::char_type;
  268. struct category
  269. : public sink_tag,
  270. public direct_tag,
  271. public closable_tag
  272. { };
  273. using mapped_file::size_type;
  274. using mapped_file::iterator;
  275. using mapped_file::max_length;
  276. using mapped_file::is_open;
  277. using mapped_file::close;
  278. using mapped_file::operator safe_bool;
  279. using mapped_file::operator !;
  280. using mapped_file::flags;
  281. using mapped_file::size;
  282. using mapped_file::data;
  283. using mapped_file::begin;
  284. using mapped_file::end;
  285. using mapped_file::alignment;
  286. using mapped_file::resize;
  287. // Default constructor
  288. mapped_file_sink() { }
  289. // Constructor taking a parameters object
  290. template<typename Path>
  291. explicit mapped_file_sink(const basic_mapped_file_params<Path>& p);
  292. // Constructor taking a list of parameters
  293. template<typename Path>
  294. explicit mapped_file_sink( const Path& path,
  295. size_type length = max_length,
  296. boost::intmax_t offset = 0,
  297. mapmode flags = readwrite );
  298. // Copy Constructor
  299. mapped_file_sink(const mapped_file_sink& other);
  300. // open overload taking a parameters object
  301. template<typename Path>
  302. void open(const basic_mapped_file_params<Path>& p);
  303. // open overload taking a list of parameters
  304. template<typename Path>
  305. void open( const Path& path,
  306. size_type length = max_length,
  307. boost::intmax_t offset = 0,
  308. mapmode flags = readwrite );
  309. };
  310. //------------------Implementation of mapped_file_source----------------------//
  311. template<typename Path>
  312. mapped_file_source::mapped_file_source(const basic_mapped_file_params<Path>& p)
  313. { init(); open(p); }
  314. template<typename Path>
  315. mapped_file_source::mapped_file_source(
  316. const Path& path, size_type length, boost::intmax_t offset)
  317. { init(); open(path, length, offset); }
  318. template<typename Path>
  319. void mapped_file_source::open(const basic_mapped_file_params<Path>& p)
  320. {
  321. param_type params(p);
  322. if (params.flags) {
  323. if (params.flags != mapped_file::readonly)
  324. boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid flags"));
  325. } else {
  326. if (params.mode & BOOST_IOS::out)
  327. boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode"));
  328. params.mode |= BOOST_IOS::in;
  329. }
  330. open_impl(params);
  331. }
  332. template<typename Path>
  333. void mapped_file_source::open(
  334. const Path& path, size_type length, boost::intmax_t offset)
  335. {
  336. param_type p(path);
  337. p.length = length;
  338. p.offset = offset;
  339. open(p);
  340. }
  341. //------------------Implementation of mapped_file-----------------------------//
  342. template<typename Path>
  343. mapped_file::mapped_file(const basic_mapped_file_params<Path>& p)
  344. { open(p); }
  345. template<typename Path>
  346. mapped_file::mapped_file(
  347. const Path& path, mapmode flags,
  348. size_type length, stream_offset offset )
  349. { open(path, flags, length, offset); }
  350. template<typename Path>
  351. mapped_file::mapped_file(
  352. const Path& path, BOOST_IOS::openmode mode,
  353. size_type length, stream_offset offset )
  354. { open(path, mode, length, offset); }
  355. template<typename Path>
  356. void mapped_file::open(const basic_mapped_file_params<Path>& p)
  357. { delegate_.open_impl(p); }
  358. template<typename Path>
  359. void mapped_file::open(
  360. const Path& path, mapmode flags,
  361. size_type length, stream_offset offset )
  362. {
  363. param_type p(path);
  364. p.flags = flags;
  365. p.length = length;
  366. p.offset = offset;
  367. open(p);
  368. }
  369. template<typename Path>
  370. void mapped_file::open(
  371. const Path& path, BOOST_IOS::openmode mode,
  372. size_type length, stream_offset offset )
  373. {
  374. param_type p(path);
  375. p.mode = mode;
  376. p.length = length;
  377. p.offset = offset;
  378. open(p);
  379. }
  380. inline char* mapped_file::data() const
  381. { return (flags() != readonly) ? const_cast<char*>(delegate_.data()) : 0; }
  382. //------------------Implementation of mapped_file_sink------------------------//
  383. template<typename Path>
  384. mapped_file_sink::mapped_file_sink(const basic_mapped_file_params<Path>& p)
  385. { open(p); }
  386. template<typename Path>
  387. mapped_file_sink::mapped_file_sink(
  388. const Path& path, size_type length,
  389. boost::intmax_t offset, mapmode flags )
  390. { open(path, length, offset, flags); }
  391. template<typename Path>
  392. void mapped_file_sink::open(const basic_mapped_file_params<Path>& p)
  393. {
  394. param_type params(p);
  395. if (params.flags) {
  396. if (params.flags & mapped_file::readonly)
  397. boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid flags"));
  398. } else {
  399. if (params.mode & BOOST_IOS::in)
  400. boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode"));
  401. params.mode |= BOOST_IOS::out;
  402. }
  403. mapped_file::open(params);
  404. }
  405. template<typename Path>
  406. void mapped_file_sink::open(
  407. const Path& path, size_type length,
  408. boost::intmax_t offset, mapmode flags )
  409. {
  410. param_type p(path);
  411. p.flags = flags;
  412. p.length = length;
  413. p.offset = offset;
  414. open(p);
  415. }
  416. //------------------Specialization of direct_impl-----------------------------//
  417. template<>
  418. struct operations<mapped_file_source>
  419. : boost::iostreams::detail::close_impl<closable_tag>
  420. {
  421. static std::pair<char*, char*>
  422. input_sequence(mapped_file_source& src)
  423. {
  424. return std::make_pair( const_cast<char*>(src.begin()),
  425. const_cast<char*>(src.end()) );
  426. }
  427. };
  428. template<>
  429. struct operations<mapped_file>
  430. : boost::iostreams::detail::close_impl<closable_tag>
  431. {
  432. static std::pair<char*, char*>
  433. input_sequence(mapped_file& file)
  434. {
  435. return std::make_pair(file.begin(), file.end());
  436. }
  437. static std::pair<char*, char*>
  438. output_sequence(mapped_file& file)
  439. {
  440. return std::make_pair(file.begin(), file.end());
  441. }
  442. };
  443. template<>
  444. struct operations<mapped_file_sink>
  445. : boost::iostreams::detail::close_impl<closable_tag>
  446. {
  447. static std::pair<char*, char*>
  448. output_sequence(mapped_file_sink& sink)
  449. {
  450. return std::make_pair(sink.begin(), sink.end());
  451. }
  452. };
  453. //------------------Definition of mapmode operators---------------------------//
  454. inline mapped_file::mapmode
  455. operator|(mapped_file::mapmode a, mapped_file::mapmode b)
  456. {
  457. return static_cast<mapped_file::mapmode>
  458. (static_cast<int>(a) | static_cast<int>(b));
  459. }
  460. inline mapped_file::mapmode
  461. operator&(mapped_file::mapmode a, mapped_file::mapmode b)
  462. {
  463. return static_cast<mapped_file::mapmode>
  464. (static_cast<int>(a) & static_cast<int>(b));
  465. }
  466. inline mapped_file::mapmode
  467. operator^(mapped_file::mapmode a, mapped_file::mapmode b)
  468. {
  469. return static_cast<mapped_file::mapmode>
  470. (static_cast<int>(a) ^ static_cast<int>(b));
  471. }
  472. inline mapped_file::mapmode
  473. operator~(mapped_file::mapmode a)
  474. {
  475. return static_cast<mapped_file::mapmode>(~static_cast<int>(a));
  476. }
  477. inline mapped_file::mapmode
  478. operator|=(mapped_file::mapmode& a, mapped_file::mapmode b)
  479. {
  480. return a = a | b;
  481. }
  482. inline mapped_file::mapmode
  483. operator&=(mapped_file::mapmode& a, mapped_file::mapmode b)
  484. {
  485. return a = a & b;
  486. }
  487. inline mapped_file::mapmode
  488. operator^=(mapped_file::mapmode& a, mapped_file::mapmode b)
  489. {
  490. return a = a ^ b;
  491. }
  492. } } // End namespaces iostreams, boost.
  493. #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
  494. #endif // #ifndef BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED