transform_width.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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)
  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/iterator/iterator_adaptor.hpp>
  22. #include <boost/iterator/iterator_traits.hpp>
  23. #include <algorithm> // std::min
  24. namespace boost {
  25. namespace archive {
  26. namespace iterators {
  27. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  28. // class used by text archives to translate char strings to wchar_t
  29. // strings of the currently selected locale
  30. template<
  31. class Base,
  32. int BitsOut,
  33. int BitsIn,
  34. class CharType = typename boost::iterator_value<Base>::type // output character
  35. >
  36. class transform_width :
  37. public boost::iterator_adaptor<
  38. transform_width<Base, BitsOut, BitsIn, CharType>,
  39. Base,
  40. CharType,
  41. single_pass_traversal_tag,
  42. CharType
  43. >
  44. {
  45. friend class boost::iterator_core_access;
  46. typedef typename boost::iterator_adaptor<
  47. transform_width<Base, BitsOut, BitsIn, CharType>,
  48. Base,
  49. CharType,
  50. single_pass_traversal_tag,
  51. CharType
  52. > super_t;
  53. typedef transform_width<Base, BitsOut, BitsIn, CharType> this_t;
  54. typedef typename iterator_value<Base>::type base_value_type;
  55. void fill();
  56. CharType dereference() const {
  57. if(!m_buffer_out_full)
  58. const_cast<this_t *>(this)->fill();
  59. return m_buffer_out;
  60. }
  61. bool equal_impl(const this_t & rhs){
  62. if(BitsIn < BitsOut) // discard any left over bits
  63. return this->base_reference() == rhs.base_reference();
  64. else{
  65. // BitsIn > BitsOut // zero fill
  66. if(this->base_reference() == rhs.base_reference()){
  67. m_end_of_sequence = true;
  68. return 0 == m_remaining_bits;
  69. }
  70. return false;
  71. }
  72. }
  73. // standard iterator interface
  74. bool equal(const this_t & rhs) const {
  75. return const_cast<this_t *>(this)->equal_impl(rhs);
  76. }
  77. void increment(){
  78. m_buffer_out_full = false;
  79. }
  80. bool m_buffer_out_full;
  81. CharType m_buffer_out;
  82. // last read element from input
  83. base_value_type m_buffer_in;
  84. // number of bits to left in the input buffer.
  85. unsigned int m_remaining_bits;
  86. // flag to indicate we've reached end of data.
  87. bool m_end_of_sequence;
  88. public:
  89. // make composible buy using templated constructor
  90. template<class T>
  91. transform_width(T start) :
  92. super_t(Base(static_cast< T >(start))),
  93. m_buffer_out_full(false),
  94. m_buffer_out(0),
  95. // To disable GCC warning, but not truly necessary
  96. //(m_buffer_in will be initialized later before being
  97. //used because m_remaining_bits == 0)
  98. m_buffer_in(0),
  99. m_remaining_bits(0),
  100. m_end_of_sequence(false)
  101. {}
  102. // intel 7.1 doesn't like default copy constructor
  103. transform_width(const transform_width & rhs) :
  104. super_t(rhs.base_reference()),
  105. m_buffer_out_full(rhs.m_buffer_out_full),
  106. m_buffer_out(rhs.m_buffer_out),
  107. m_buffer_in(rhs.m_buffer_in),
  108. m_remaining_bits(rhs.m_remaining_bits),
  109. m_end_of_sequence(false)
  110. {}
  111. };
  112. template<
  113. class Base,
  114. int BitsOut,
  115. int BitsIn,
  116. class CharType
  117. >
  118. void transform_width<Base, BitsOut, BitsIn, CharType>::fill() {
  119. unsigned int missing_bits = BitsOut;
  120. m_buffer_out = 0;
  121. do{
  122. if(0 == m_remaining_bits){
  123. if(m_end_of_sequence){
  124. m_buffer_in = 0;
  125. m_remaining_bits = missing_bits;
  126. }
  127. else{
  128. m_buffer_in = * this->base_reference()++;
  129. m_remaining_bits = BitsIn;
  130. }
  131. }
  132. // append these bits to the next output
  133. // up to the size of the output
  134. unsigned int i = (std::min)(missing_bits, m_remaining_bits);
  135. // shift interesting bits to least significant position
  136. base_value_type j = m_buffer_in >> (m_remaining_bits - i);
  137. // and mask off the un interesting higher bits
  138. // note presumption of twos complement notation
  139. j &= (1 << i) - 1;
  140. // append then interesting bits to the output value
  141. m_buffer_out <<= i;
  142. m_buffer_out |= j;
  143. // and update counters
  144. missing_bits -= i;
  145. m_remaining_bits -= i;
  146. }while(0 < missing_bits);
  147. m_buffer_out_full = true;
  148. }
  149. } // namespace iterators
  150. } // namespace archive
  151. } // namespace boost
  152. #endif // BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP