Project
Loading...
Searching...
No Matches
DataDeflater.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12/* Local Variables: */
13/* mode: c++ */
14/* End: */
15
16#ifndef DATADEFLATER_H
17#define DATADEFLATER_H
18
23
24#include <cstdint>
25#include <cerrno>
26#include <stdexcept>
27#include <cassert>
28
29namespace o2
30{
31namespace data_compression
32{
33
38template <typename CodeType, std::size_t Length = 8 * sizeof(CodeType)>
40{
41 public:
42 using code_type = CodeType;
43 static_assert(Length <= 8 * sizeof(code_type), "CodeType must allow specified bit length");
44 static const std::size_t sMaxLength = Length;
45
46 CodecIdentity() = default;
47 ~CodecIdentity() = default;
48
49 template <typename ValueType, typename WriterType>
50 int write(ValueType v, WriterType writer)
51 {
52 code_type code = v;
53 return writer(code, sMaxLength);
54 }
55};
56
57/* TODO: separate the bare deflater and additional functionality like
58 bounds check and codec by using a mixin approach
59 TODO: error policy, initialization policy
60 TODO: bit order policy: MSB or LSB first to buffer
61 TODO: monitoring policy
62 TODO: bit order: LSB to MSB in every byte or vice versa
63 */
64template <typename TargetType, class Codec = CodecIdentity<TargetType>>
66{
67 public:
68 using target_type = TargetType;
69 static const std::size_t TargetBitWidth = 8 * sizeof(target_type);
70 using Writer = std::function<bool(const target_type&)>;
71
72 DataDeflater() : mCurrent(0), mFilledBits(0), mCodec() {}
74 {
75 // check if the deflater is properly terminated, or pending data will be lost
76 assert(mFilledBits == 0);
77 }
78
83 int reset()
84 {
85 mCurrent = 0;
86 mFilledBits = 0;
87
88 return 0;
89 }
90
96 template <typename WriterT>
97 int close(WriterT& writer)
98 {
99 int nWords = 0;
100 if (mFilledBits > 0) {
101 writer(mCurrent);
102 ++nWords;
103 }
104 reset();
105 return nWords;
106 }
107
117 template <typename ValueType, typename WriterT>
118 int writeRaw(ValueType value, uint16_t bitlength, WriterT writer)
119 {
120 auto bitsToWrite = bitlength;
121 if (bitlength > 8 * sizeof(ValueType)) {
122 // TODO: error policy
123 throw std::runtime_error("bit length exceeds width of the data type");
124 }
125 while (bitsToWrite > 0) {
126 if (mFilledBits == TargetBitWidth) {
127 mFilledBits = 0;
128 writer(mCurrent);
129 mCurrent = 0;
130 }
131 // write at max what is left to be written
132 auto writeNow = bitsToWrite;
133 // write one element of the target buffer at a time
134 if (writeNow > TargetBitWidth) {
135 writeNow = TargetBitWidth;
136 }
137 // write the remaining space in the current element
138 auto capacity = TargetBitWidth - mFilledBits;
139 if (writeNow > capacity) {
140 writeNow = capacity;
141 }
142 auto mask = (((ValueType)1 << writeNow) - 1) << (bitsToWrite - writeNow);
143 auto activebits = (value & mask) >> (bitsToWrite - writeNow);
144 mCurrent |= activebits << (capacity - writeNow);
145 mFilledBits += writeNow;
146 bitsToWrite -= writeNow;
147 assert(mFilledBits <= TargetBitWidth);
148 }
149 return bitlength - bitsToWrite;
150 }
151
152 template <typename T, typename WriterT>
153 int write(T value, WriterT writer)
154 {
155 using RegType = typename Codec::code_type;
156 return mCodec.write(
157 value, [&, this](RegType code, uint16_t codelength) -> int { return this->writeRaw(code, codelength, writer); });
158 }
159
166 int align()
167 {
168 if (mFilledBits == 0 || mFilledBits == TargetBitWidth) {
169 return 0;
170 }
171 // set the number of filled bits to the next target border
172 int nBits = TargetBitWidth - mFilledBits;
173 mFilledBits = TargetBitWidth;
174 return nBits;
175 }
176
177 private:
179 target_type mCurrent;
181 unsigned mFilledBits;
183 Codec mCodec;
184};
185
186} // namespace data_compression
187} // namespace o2
188
189#endif
int write(ValueType v, WriterType writer)
static const std::size_t sMaxLength
int write(T value, WriterT writer)
int writeRaw(ValueType value, uint16_t bitlength, WriterT writer)
std::function< bool(const target_type &)> Writer
static const std::size_t TargetBitWidth
const GLdouble * v
Definition glcorearb.h:832
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLuint mask
Definition glcorearb.h:291
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...