wchar_from_mb.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
  2. #define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER)
  5. # pragma once
  6. #endif
  7. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  8. // wchar_from_mb.hpp
  9. // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
  10. // Use, modification and distribution is subject to the Boost Software
  11. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  12. // http://www.boost.org/LICENSE_1_0.txt)
  13. // See http://www.boost.org for updates, documentation, and revision history.
  14. #include <cctype>
  15. #include <cstddef> // size_t
  16. #ifndef BOOST_NO_CWCHAR
  17. #include <cwchar> // mbstate_t
  18. #endif
  19. #include <algorithm> // copy
  20. #include <boost/config.hpp>
  21. #if defined(BOOST_NO_STDC_NAMESPACE)
  22. namespace std{
  23. using ::mbstate_t;
  24. } // namespace std
  25. #endif
  26. #include <boost/assert.hpp>
  27. #include <boost/core/ignore_unused.hpp>
  28. #include <boost/array.hpp>
  29. #include <boost/iterator/iterator_adaptor.hpp>
  30. #include <boost/archive/detail/utf8_codecvt_facet.hpp>
  31. #include <boost/archive/iterators/dataflow_exception.hpp>
  32. #include <boost/serialization/throw_exception.hpp>
  33. #include <iostream>
  34. namespace boost {
  35. namespace archive {
  36. namespace iterators {
  37. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  38. // class used by text archives to translate char strings to wchar_t
  39. // strings of the currently selected locale
  40. template<class Base>
  41. class wchar_from_mb
  42. : public boost::iterator_adaptor<
  43. wchar_from_mb<Base>,
  44. Base,
  45. wchar_t,
  46. single_pass_traversal_tag,
  47. wchar_t
  48. >
  49. {
  50. friend class boost::iterator_core_access;
  51. typedef typename boost::iterator_adaptor<
  52. wchar_from_mb<Base>,
  53. Base,
  54. wchar_t,
  55. single_pass_traversal_tag,
  56. wchar_t
  57. > super_t;
  58. typedef wchar_from_mb<Base> this_t;
  59. void drain();
  60. wchar_t dereference() const {
  61. if(m_output.m_next == m_output.m_next_available)
  62. return static_cast<wchar_t>(0);
  63. return * m_output.m_next;
  64. }
  65. void increment(){
  66. if(m_output.m_next == m_output.m_next_available)
  67. return;
  68. if(++m_output.m_next == m_output.m_next_available){
  69. if(m_input.m_done)
  70. return;
  71. drain();
  72. }
  73. }
  74. bool equal(this_t const & rhs) const {
  75. return dereference() == rhs.dereference();
  76. }
  77. boost::archive::detail::utf8_codecvt_facet m_codecvt_facet;
  78. std::mbstate_t m_mbs;
  79. template<typename T>
  80. struct sliding_buffer {
  81. boost::array<T, 32> m_buffer;
  82. typename boost::array<T, 32>::const_iterator m_next_available;
  83. typename boost::array<T, 32>::iterator m_next;
  84. bool m_done;
  85. // default ctor
  86. sliding_buffer() :
  87. m_next_available(m_buffer.begin()),
  88. m_next(m_buffer.begin()),
  89. m_done(false)
  90. {}
  91. // copy ctor
  92. sliding_buffer(const sliding_buffer & rhs) :
  93. m_next_available(
  94. std::copy(
  95. rhs.m_buffer.begin(),
  96. rhs.m_next_available,
  97. m_buffer.begin()
  98. )
  99. ),
  100. m_next(
  101. m_buffer.begin() + (rhs.m_next - rhs.m_buffer.begin())
  102. ),
  103. m_done(rhs.m_done)
  104. {}
  105. };
  106. sliding_buffer<typename iterator_value<Base>::type> m_input;
  107. sliding_buffer<typename iterator_value<this_t>::type> m_output;
  108. public:
  109. // make composible buy using templated constructor
  110. template<class T>
  111. wchar_from_mb(T start) :
  112. super_t(Base(static_cast< T >(start))),
  113. m_mbs(std::mbstate_t())
  114. {
  115. BOOST_ASSERT(std::mbsinit(&m_mbs));
  116. drain();
  117. }
  118. // default constructor used as an end iterator
  119. wchar_from_mb(){}
  120. // copy ctor
  121. wchar_from_mb(const wchar_from_mb & rhs) :
  122. super_t(rhs.base_reference()),
  123. m_mbs(rhs.m_mbs),
  124. m_input(rhs.m_input),
  125. m_output(rhs.m_output)
  126. {}
  127. };
  128. template<class Base>
  129. void wchar_from_mb<Base>::drain(){
  130. BOOST_ASSERT(! m_input.m_done);
  131. for(;;){
  132. typename boost::iterators::iterator_reference<Base>::type c = *(this->base_reference());
  133. // a null character in a multibyte stream is takes as end of string
  134. if(0 == c){
  135. m_input.m_done = true;
  136. break;
  137. }
  138. ++(this->base_reference());
  139. * const_cast<typename iterator_value<Base>::type *>(
  140. (m_input.m_next_available++)
  141. ) = c;
  142. // if input buffer is full - we're done for now
  143. if(m_input.m_buffer.end() == m_input.m_next_available)
  144. break;
  145. }
  146. const typename boost::iterators::iterator_value<Base>::type * input_new_start;
  147. typename iterator_value<this_t>::type * next_available;
  148. BOOST_ATTRIBUTE_UNUSED // redundant with ignore_unused below but clarifies intention
  149. std::codecvt_base::result r = m_codecvt_facet.in(
  150. m_mbs,
  151. m_input.m_buffer.begin(),
  152. m_input.m_next_available,
  153. input_new_start,
  154. m_output.m_buffer.begin(),
  155. m_output.m_buffer.end(),
  156. next_available
  157. );
  158. BOOST_ASSERT(std::codecvt_base::ok == r);
  159. m_output.m_next_available = next_available;
  160. m_output.m_next = m_output.m_buffer.begin();
  161. // we're done with some of the input so shift left.
  162. m_input.m_next_available = std::copy(
  163. input_new_start,
  164. m_input.m_next_available,
  165. m_input.m_buffer.begin()
  166. );
  167. m_input.m_next = m_input.m_buffer.begin();
  168. }
  169. } // namespace iterators
  170. } // namespace archive
  171. } // namespace boost
  172. #endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP