File indexing completed on 2025-01-18 09:28:29
0001 #ifndef BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
0002 #define BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
0003
0004
0005 #if defined(_MSC_VER)
0006 # pragma once
0007 #endif
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <boost/iterator/iterator_adaptor.hpp>
0028 #include <boost/iterator/iterator_traits.hpp>
0029
0030 #include <algorithm> // std::min
0031
0032 namespace boost {
0033 namespace archive {
0034 namespace iterators {
0035
0036
0037
0038
0039 template<
0040 class Base,
0041 int BitsOut,
0042 int BitsIn,
0043 class CharType = typename boost::iterator_value<Base>::type
0044 >
0045 class transform_width :
0046 public boost::iterator_adaptor<
0047 transform_width<Base, BitsOut, BitsIn, CharType>,
0048 Base,
0049 CharType,
0050 single_pass_traversal_tag,
0051 CharType
0052 >
0053 {
0054 friend class boost::iterator_core_access;
0055 typedef typename boost::iterator_adaptor<
0056 transform_width<Base, BitsOut, BitsIn, CharType>,
0057 Base,
0058 CharType,
0059 single_pass_traversal_tag,
0060 CharType
0061 > super_t;
0062
0063 typedef transform_width<Base, BitsOut, BitsIn, CharType> this_t;
0064 typedef typename iterator_value<Base>::type base_value_type;
0065
0066 void fill();
0067
0068 CharType dereference() const {
0069 if(!m_buffer_out_full)
0070 const_cast<this_t *>(this)->fill();
0071 return m_buffer_out;
0072 }
0073
0074 bool equal_impl(const this_t & rhs){
0075 if(BitsIn < BitsOut)
0076 return this->base_reference() == rhs.base_reference();
0077 else{
0078
0079 if(this->base_reference() == rhs.base_reference()){
0080 m_end_of_sequence = true;
0081 return 0 == m_remaining_bits;
0082 }
0083 return false;
0084 }
0085 }
0086
0087
0088 bool equal(const this_t & rhs) const {
0089 return const_cast<this_t *>(this)->equal_impl(rhs);
0090 }
0091
0092 void increment(){
0093 m_buffer_out_full = false;
0094 }
0095
0096 bool m_buffer_out_full;
0097 CharType m_buffer_out;
0098
0099
0100 base_value_type m_buffer_in;
0101
0102
0103 unsigned int m_remaining_bits;
0104
0105
0106 bool m_end_of_sequence;
0107
0108 public:
0109
0110 template<class T>
0111 transform_width(T start) :
0112 super_t(Base(static_cast< T >(start))),
0113 m_buffer_out_full(false),
0114 m_buffer_out(0),
0115
0116
0117
0118 m_buffer_in(0),
0119 m_remaining_bits(0),
0120 m_end_of_sequence(false)
0121 {}
0122
0123 transform_width(const transform_width & rhs) :
0124 super_t(rhs.base_reference()),
0125 m_buffer_out_full(rhs.m_buffer_out_full),
0126 m_buffer_out(rhs.m_buffer_out),
0127 m_buffer_in(rhs.m_buffer_in),
0128 m_remaining_bits(rhs.m_remaining_bits),
0129 m_end_of_sequence(false)
0130 {}
0131 };
0132
0133 template<
0134 class Base,
0135 int BitsOut,
0136 int BitsIn,
0137 class CharType
0138 >
0139 void transform_width<Base, BitsOut, BitsIn, CharType>::fill() {
0140 unsigned int missing_bits = BitsOut;
0141 m_buffer_out = 0;
0142 do{
0143 if(0 == m_remaining_bits){
0144 if(m_end_of_sequence){
0145 m_buffer_in = 0;
0146 m_remaining_bits = missing_bits;
0147 }
0148 else{
0149 m_buffer_in = * this->base_reference()++;
0150 m_remaining_bits = BitsIn;
0151 }
0152 }
0153
0154
0155
0156 unsigned int i = (std::min)(missing_bits, m_remaining_bits);
0157
0158 base_value_type j = m_buffer_in >> (m_remaining_bits - i);
0159
0160
0161 j &= (1 << i) - 1;
0162
0163 m_buffer_out <<= i;
0164 m_buffer_out |= j;
0165
0166
0167 missing_bits -= i;
0168 m_remaining_bits -= i;
0169 }while(0 < missing_bits);
0170 m_buffer_out_full = true;
0171 }
0172
0173 }
0174 }
0175 }
0176
0177 #endif