VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gbititerator.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 ///
18 /// \file gbititerator.h
19 ///
20 
21 #ifndef G_BIT_ITERATOR__H
22 #define G_BIT_ITERATOR__H
23 
24 #include "gdef.h"
25 #include <iterator> // std::distance()
26 
27 namespace G
28 {
29 
30 /// \class G::bit_iterator
31 /// A bit-by-bit input iterator that extracts bits in msb-to-lsb order from
32 /// a sequence of bytes.
33 ///
34 /// Beware of basing bit_iterators on top of istream_iterators because istream
35 /// iterators can extract from the underlying istream when they are advanced.
36 /// This means that if the istream lives longer than the iterator then the
37 /// istream will end up at a poorly-defined position. This bit_iterator
38 /// implementation tries to delay the use of op++() to avoid this effect,
39 /// but cannot do so for op==().
40 ///
41 template <typename T>
43 {
44 public:
45  typedef T byte_iterator_type ;
46 
47  explicit bit_iterator( T bytewise_input_iterator ) ;
48  ///< Constructor. Points to the msb of the given byte.
49 
50  unsigned int operator*() const ;
51  ///< Dereference operator, returning one or zero.
52 
54  ///< Advance operator. Moves from msb to lsb within each byte.
55 
56  bit_iterator operator++( int ) ;
57  ///< Advance operator. Moves from msb to lsb within each byte.
58 
59  bool operator==( const bit_iterator & other ) const ;
60  ///< Comparison operator.
61 
62  bool operator!=( const bit_iterator & other ) const ;
63  ///< Comparison operator.
64 
65  size_t operator-( const bit_iterator & other ) const ;
66  ///< Subtraction operator.
67 
68 private:
69  void normalise() const ;
70 
71 private:
72  mutable unsigned char m_mask ;
73  mutable T m_p ;
74 } ;
75 
76 template <typename T>
78  m_mask(0x80) ,
79  m_p(p)
80 {
81 }
82 
83 template <typename T>
84 unsigned int bit_iterator<T>::operator*() const
85 {
86  normalise() ;
87  unsigned char c = static_cast<unsigned char>( *m_p ) ;
88  return ( c & m_mask ) ? 1U : 0U ;
89 }
90 
91 template <typename T>
92 void bit_iterator<T>::normalise() const
93 {
94  // lazy increment because istream_iterators do an extraction in op++
95  if( m_mask == 0 )
96  {
97  m_mask = 0x80 ;
98  ++m_p ;
99  }
100 }
101 
102 template <typename T>
104 {
105  normalise() ;
106  m_mask >>= 1 ;
107  return *this ;
108 }
109 
110 template <typename T>
112 {
113  normalise() ;
114  bit_iterator old( *this ) ;
115  ++(*this) ;
116  return old ;
117 }
118 
119 template <typename T>
120 bool bit_iterator<T>::operator==( const bit_iterator & other ) const
121 {
122  // this is dodgy because we might be triggering a read of the
123  // underlying stream -- the fix is to implement this method using
124  // op+(1) and have it fail to compile for underlying iterator types
125  // that do not have op+() (eg. istream_iterator) -- template
126  // meta-programming will then be required for any template classes
127  // that are based on G::bit_iterator (such as G::bit_stream)
128  //
129  normalise() ;
130  other.normalise() ;
131 
132  return m_p == other.m_p && m_mask == other.m_mask ;
133 }
134 
135 template <typename T>
136 bool bit_iterator<T>::operator!=( const bit_iterator & other ) const
137 {
138  return ! ( *this == other ) ;
139 }
140 
141 template <typename T>
142 size_t bit_iterator<T>::operator-( const bit_iterator & other ) const
143 {
144  size_t n = std::distance(other.m_p,m_p) * 8 ;
145  unsigned int mask = m_mask ;
146  unsigned int other_mask = other.m_mask ;
147  if( mask == 0 ) mask = 0x80 , n += 8 ;
148  if( other_mask == 0 ) other_mask = 0x80 , n -= 8 ;
149  for( ; mask != 0x80 ; mask <<= 1 ) n++ ;
150  for( ; other_mask != 0x80 ; other_mask <<= 1 ) n-- ;
151  return n ;
152 }
153 
154 }
155 
156 #endif
bit_iterator & operator++()
Advance operator. Moves from msb to lsb within each byte.
Definition: gbititerator.h:103
bool operator==(const bit_iterator &other) const
Comparison operator.
Definition: gbititerator.h:120
unsigned int operator*() const
Dereference operator, returning one or zero.
Definition: gbititerator.h:84
size_t operator-(const bit_iterator &other) const
Subtraction operator.
Definition: gbititerator.h:142
A bit-by-bit input iterator that extracts bits in msb-to-lsb order from a sequence of bytes...
Definition: gbititerator.h:42
bool operator!=(const bit_iterator &other) const
Comparison operator.
Definition: gbititerator.h:136
bit_iterator(T bytewise_input_iterator)
Constructor. Points to the msb of the given byte.
Definition: gbititerator.h:77