ATLAS Offline Software
BitUnpacker.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // $Id$
6 /**
7  * @file CxxUtils/BitUnpacker.icc
8  * @author scott snyder <snyder@bnl.gov>
9  * @date Nov, 2014
10  * @brief Helper to unpack a set of values bitwise from a stream.
11  */
12 
13 
14 #include "CxxUtils/ones.h"
15 
16 
17 namespace CxxUtils {
18 
19 
20 /**
21  * @brief Constructor.
22  * @param nbits Number of bits per item to use in the packed representation.
23  * @param stream Input stream object.
24  */
25 template <class STREAM>
26 inline
27 BitUnpacker<STREAM>::BitUnpacker (uint8_t nbits, STREAM& stream)
28  : m_buf(0),
29  m_nbuf(0),
30  m_nbits(nbits),
31  m_stream (stream),
32  m_mask (CxxUtils::ones<uint32_t>(nbits))
33 {
34  assert (m_nbits > 0 && m_nbits <= 32);
35 }
36 
37 
38 /**
39  * @brief Unpack one value from the stream.
40  */
41 template <class STREAM>
42 inline
43 uint32_t BitUnpacker<STREAM>::unpack()
44 {
45  const uint8_t totbits = 8*sizeof(m_buf);
46 
47  if (m_nbuf == 0) {
48  m_stream >> m_buf;
49  m_nbuf = totbits;
50  }
51 
52  uint32_t out = m_buf & m_mask;
53  if (m_nbits > m_nbuf) {
54  uint8_t nleft = m_nbits - m_nbuf;
55  m_stream >> m_buf;
56  out |= (m_buf & CxxUtils::ones<uint32_t>(nleft)) << m_nbuf;
57  m_buf >>= nleft;
58  m_nbuf = totbits - nleft;
59  }
60  else {
61  if (m_nbits >= 32)
62  m_buf = 0;
63  else
64  m_buf >>= m_nbits;
65  m_nbuf -= m_nbits;
66  }
67 
68  return out;
69 }
70 
71 
72 /**
73  * @brief Constructor.
74  * @param stream Input stream object.
75  */
76 template <class STREAM>
77 inline
78 BitUnpacker8<STREAM>::BitUnpacker8 (STREAM& stream)
79  : m_buf(0),
80  m_nbuf(0),
81  m_stream (stream)
82 {
83 }
84 
85 
86 /**
87  * @brief Constructor.
88  * @param nbits Must be 8.
89  * @param stream Input stream object.
90  */
91 template <class STREAM>
92 inline
93 BitUnpacker8<STREAM>::BitUnpacker8 (uint8_t /*nbits*/, STREAM& stream)
94  : m_buf(0),
95  m_nbuf(0),
96  m_stream (stream)
97 {
98 }
99 
100 
101 /**
102  * @brief Unpack one value from the stream.
103  */
104 template <class STREAM>
105 inline
106 uint32_t BitUnpacker8<STREAM>::unpack()
107 {
108  if (m_nbuf == 0) {
109  m_stream >> m_buf;
110  m_nbuf = 4;
111  }
112 
113  uint8_t ret = m_buf & 0xff;
114  m_buf >>= 8;
115  --m_nbuf;
116  return ret;
117 }
118 
119 
120 /**
121  * @brief Constructor.
122  * @param stream Input stream object.
123  */
124 template <class STREAM>
125 inline
126 BitUnpacker16<STREAM>::BitUnpacker16 (STREAM& stream)
127  : m_buf(0),
128  m_nbuf(0),
129  m_stream (stream)
130 {
131 }
132 
133 
134 /**
135  * @brief Constructor.
136  * @param nbits Must be 16.
137  * @param stream Input stream object.
138  */
139 template <class STREAM>
140 inline
141 BitUnpacker16<STREAM>::BitUnpacker16 (uint8_t /*nbits*/, STREAM& stream)
142  : m_buf(0),
143  m_nbuf(0),
144  m_stream (stream)
145 {
146 }
147 
148 
149 /**
150  * @brief Unpack one value from the stream.
151  */
152 template <class STREAM>
153 inline
154 uint32_t BitUnpacker16<STREAM>::unpack()
155 {
156  if (m_nbuf == 0) {
157  m_stream >> m_buf;
158  m_nbuf = 2;
159  }
160 
161  uint16_t ret = m_buf & 0xffff;
162  m_buf >>= 16;
163  --m_nbuf;
164  return ret;
165 }
166 
167 
168 } // namespace CxxUtils
169 
170