mapped_file.hpp 19 KB

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