transform_width.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #ifndef BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
  2. #define BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  8. // transform_width.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. // iterator which takes elements of x bits and returns elements of y bits.
  15. // used to change streams of 8 bit characters into streams of 6 bit characters.
  16. // and vice-versa for implementing base64 encodeing/decoding. Be very careful
  17. // when using and end iterator. end is only reliable detected when the input
  18. // stream length is some common multiple of x and y. E.G. Base64 6 bit
  19. // character and 8 bit bytes. Lowest common multiple is 24 => 4 6 bit characters
  20. // or 3 8 bit characters
  21. #include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME & PTFO
  22. #include <boost/serialization/pfto.hpp>
  23. #include <boost/iterator/iterator_adaptor.hpp>
  24. #include <boost/iterator/iterator_traits.hpp>
  25. namespace boost {
  26. namespace archive {
  27. namespace iterators {
  28. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  29. // class used by text archives to translate char strings to wchar_t
  30. // strings of the currently selected locale
  31. template<
  32. class Base,
  33. int BitsOut,
  34. int BitsIn,
  35. class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type // output character
  36. >
  37. class transform_width :
  38. public boost::iterator_adaptor<
  39. transform_width<Base, BitsOut, BitsIn, CharType>,
  40. Base,
  41. CharType,
  42. single_pass_traversal_tag,
  43. CharType
  44. >
  45. {
  46. friend class boost::iterator_core_access;
  47. typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
  48. transform_width<Base, BitsOut, BitsIn, CharType>,
  49. Base,
  50. CharType,
  51. single_pass_traversal_tag,
  52. CharType
  53. > super_t;
  54. typedef transform_width<Base, BitsOut, BitsIn, CharType> this_t;
  55. typedef BOOST_DEDUCED_TYPENAME iterator_value<Base>::type base_value_type;
  56. CharType fill();
  57. CharType dereference_impl(){
  58. if(! m_full){
  59. m_current_value = fill();
  60. m_full = true;
  61. }
  62. return m_current_value;
  63. }
  64. CharType dereference() const {
  65. return const_cast<this_t *>(this)->dereference_impl();
  66. }
  67. // test for iterator equality
  68. bool equal(const this_t & rhs) const {
  69. return
  70. this->base_reference() == rhs.base_reference();
  71. ;
  72. }
  73. void increment(){
  74. m_displacement += BitsOut;
  75. while(m_displacement >= BitsIn){
  76. m_displacement -= BitsIn;
  77. if(0 == m_displacement)
  78. m_bufferfull = false;
  79. if(! m_bufferfull){
  80. // note: suspect that this is not invoked for borland
  81. ++(this->base_reference());
  82. }
  83. }
  84. m_full = false;
  85. }
  86. CharType m_current_value;
  87. // number of bits left in current input character buffer
  88. unsigned int m_displacement;
  89. base_value_type m_buffer;
  90. // flag to current output character is ready - just used to save time
  91. bool m_full;
  92. // flag to indicate that m_buffer has data
  93. bool m_bufferfull;
  94. public:
  95. // make composible buy using templated constructor
  96. template<class T>
  97. transform_width(BOOST_PFTO_WRAPPER(T) start) :
  98. super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast<T>(start)))),
  99. m_displacement(0),
  100. m_full(false),
  101. m_bufferfull(false)
  102. {}
  103. // intel 7.1 doesn't like default copy constructor
  104. transform_width(const transform_width & rhs) :
  105. super_t(rhs.base_reference()),
  106. m_current_value(rhs.m_current_value),
  107. m_displacement(rhs.m_displacement),
  108. m_buffer(rhs.m_buffer),
  109. m_full(rhs.m_full),
  110. m_bufferfull(rhs.m_bufferfull)
  111. {}
  112. };
  113. template<class Base, int BitsOut, int BitsIn, class CharType>
  114. CharType transform_width<Base, BitsOut, BitsIn, CharType>::fill(){
  115. CharType retval = 0;
  116. unsigned int missing_bits = BitsOut;
  117. for(;;){
  118. unsigned int bcount;
  119. if(! m_bufferfull){
  120. m_buffer = * this->base_reference();
  121. m_bufferfull = true;
  122. bcount = BitsIn;
  123. }
  124. else
  125. bcount = BitsIn - m_displacement;
  126. unsigned int i = (std::min)(bcount, missing_bits);
  127. // shift interesting bits to least significant position
  128. unsigned int j = m_buffer >> (bcount - i);
  129. // strip off uninteresting bits
  130. // (note presumption of two's complement arithmetic)
  131. j &= ~(-(1 << i));
  132. // append then interesting bits to the output value
  133. retval <<= i;
  134. retval |= j;
  135. missing_bits -= i;
  136. if(0 == missing_bits)
  137. break;
  138. // note: suspect that this is not invoked for borland 5.51
  139. ++(this->base_reference());
  140. m_bufferfull = false;
  141. }
  142. return retval;
  143. }
  144. } // namespace iterators
  145. } // namespace archive
  146. } // namespace boost
  147. #endif // BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP