basic_binary_iprimitive.ipp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  2. // basic_binary_iprimitive.ipp:
  3. // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
  4. // Use, modification and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org for updates, documentation, and revision history.
  8. #include <boost/assert.hpp>
  9. #include <cstddef> // size_t, NULL
  10. #include <cstring> // memcpy
  11. #include <boost/config.hpp>
  12. #if defined(BOOST_NO_STDC_NAMESPACE)
  13. namespace std{
  14. using ::size_t;
  15. using ::memcpy;
  16. } // namespace std
  17. #endif
  18. #include <boost/detail/workaround.hpp> // fixup for RogueWave
  19. #include <boost/serialization/throw_exception.hpp>
  20. #include <boost/scoped_ptr.hpp>
  21. #include <boost/archive/archive_exception.hpp>
  22. #include <boost/archive/codecvt_null.hpp>
  23. #include <boost/archive/add_facet.hpp>
  24. namespace boost {
  25. namespace archive {
  26. //////////////////////////////////////////////////////////////////////
  27. // implementation of basic_binary_iprimitive
  28. template<class Archive, class Elem, class Tr>
  29. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  30. basic_binary_iprimitive<Archive, Elem, Tr>::init()
  31. {
  32. // Detect attempts to pass native binary archives across
  33. // incompatible platforms. This is not fool proof but its
  34. // better than nothing.
  35. unsigned char size;
  36. this->This()->load(size);
  37. if(sizeof(int) != size)
  38. boost::serialization::throw_exception(
  39. archive_exception(
  40. archive_exception::incompatible_native_format,
  41. "size of int"
  42. )
  43. );
  44. this->This()->load(size);
  45. if(sizeof(long) != size)
  46. boost::serialization::throw_exception(
  47. archive_exception(
  48. archive_exception::incompatible_native_format,
  49. "size of long"
  50. )
  51. );
  52. this->This()->load(size);
  53. if(sizeof(float) != size)
  54. boost::serialization::throw_exception(
  55. archive_exception(
  56. archive_exception::incompatible_native_format,
  57. "size of float"
  58. )
  59. );
  60. this->This()->load(size);
  61. if(sizeof(double) != size)
  62. boost::serialization::throw_exception(
  63. archive_exception(
  64. archive_exception::incompatible_native_format,
  65. "size of double"
  66. )
  67. );
  68. // for checking endian
  69. int i;
  70. this->This()->load(i);
  71. if(1 != i)
  72. boost::serialization::throw_exception(
  73. archive_exception(
  74. archive_exception::incompatible_native_format,
  75. "endian setting"
  76. )
  77. );
  78. }
  79. template<class Archive, class Elem, class Tr>
  80. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  81. basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws)
  82. {
  83. std::size_t l; // number of wchar_t !!!
  84. this->This()->load(l);
  85. load_binary(ws, l * sizeof(wchar_t) / sizeof(char));
  86. ws[l] = L'\0';
  87. }
  88. template<class Archive, class Elem, class Tr>
  89. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  90. basic_binary_iprimitive<Archive, Elem, Tr>::load(std::string & s)
  91. {
  92. std::size_t l;
  93. this->This()->load(l);
  94. // borland de-allocator fixup
  95. #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
  96. if(NULL != s.data())
  97. #endif
  98. s.resize(l);
  99. // note breaking a rule here - could be a problem on some platform
  100. if(0 < l)
  101. load_binary(&(*s.begin()), l);
  102. }
  103. #ifndef BOOST_NO_CWCHAR
  104. template<class Archive, class Elem, class Tr>
  105. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  106. basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s)
  107. {
  108. std::size_t l;
  109. this->This()->load(l);
  110. load_binary(s, l);
  111. s[l] = '\0';
  112. }
  113. #endif
  114. #ifndef BOOST_NO_STD_WSTRING
  115. template<class Archive, class Elem, class Tr>
  116. BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
  117. basic_binary_iprimitive<Archive, Elem, Tr>::load(std::wstring & ws)
  118. {
  119. std::size_t l;
  120. this->This()->load(l);
  121. // borland de-allocator fixup
  122. #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
  123. if(NULL != ws.data())
  124. #endif
  125. ws.resize(l);
  126. // note breaking a rule here - is could be a problem on some platform
  127. load_binary(const_cast<wchar_t *>(ws.data()), l * sizeof(wchar_t) / sizeof(char));
  128. }
  129. #endif
  130. template<class Archive, class Elem, class Tr>
  131. BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
  132. basic_binary_iprimitive<Archive, Elem, Tr>::basic_binary_iprimitive(
  133. std::basic_streambuf<Elem, Tr> & sb,
  134. bool no_codecvt
  135. ) :
  136. #ifndef BOOST_NO_STD_LOCALE
  137. m_sb(sb),
  138. archive_locale(NULL),
  139. locale_saver(m_sb)
  140. {
  141. if(! no_codecvt){
  142. archive_locale.reset(
  143. boost::archive::add_facet(
  144. std::locale::classic(),
  145. new codecvt_null<Elem>
  146. )
  147. );
  148. m_sb.pubimbue(* archive_locale);
  149. }
  150. }
  151. #else
  152. m_sb(sb)
  153. {}
  154. #endif
  155. // some libraries including stl and libcomo fail if the
  156. // buffer isn't flushed before the code_cvt facet is changed.
  157. // I think this is a bug. We explicity invoke sync to when
  158. // we're done with the streambuf to work around this problem.
  159. // Note that sync is a protected member of stream buff so we
  160. // have to invoke it through a contrived derived class.
  161. namespace detail {
  162. // note: use "using" to get past msvc bug
  163. using namespace std;
  164. template<class Elem, class Tr>
  165. class input_streambuf_access : public std::basic_streambuf<Elem, Tr> {
  166. public:
  167. virtual int sync(){
  168. #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
  169. return this->basic_streambuf::sync();
  170. #else
  171. return this->basic_streambuf<Elem, Tr>::sync();
  172. #endif
  173. }
  174. };
  175. } // detail
  176. // scoped_ptr requires that archive_locale be a complete type at time of
  177. // destruction so define destructor here rather than in the header
  178. template<class Archive, class Elem, class Tr>
  179. BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
  180. basic_binary_iprimitive<Archive, Elem, Tr>::~basic_binary_iprimitive(){
  181. // push back unread characters
  182. //destructor can't throw !
  183. try{
  184. static_cast<detail::input_streambuf_access<Elem, Tr> &>(m_sb).sync();
  185. }
  186. catch(...){
  187. }
  188. }
  189. } // namespace archive
  190. } // namespace boost