-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathcompositecodec.h
110 lines (97 loc) · 3.29 KB
/
compositecodec.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* This code is released under the
* Apache License Version 2.0 http://www.apache.org/licenses/.
*
* (c) Daniel Lemire, http://lemire.me/en/
*/
#ifndef COMPOSITECODEC_H_
#define COMPOSITECODEC_H_
#include "codecs.h"
#include "common.h"
#include "util.h"
namespace FastPForLib {
/**
* This is a useful class for CODEC that only compress
* data having length a multiple of some unit length.
*/
template <class Codec1, class Codec2>
class CompositeCodec : public IntegerCODEC {
public:
CompositeCodec() : codec1(), codec2() {}
Codec1 codec1;
Codec2 codec2;
void encodeArray(const uint32_t *in, const size_t length, uint32_t *out,
size_t &nvalue) override {
_encodeArray<uint32_t>(in, length, out, nvalue);
}
void encodeArray(const uint64_t *in, const size_t length, uint32_t *out,
size_t &nvalue) override {
_encodeArray<uint64_t>(in, length, out, nvalue);
}
const uint32_t *decodeArray(const uint32_t *in, const size_t length,
uint32_t *out, size_t &nvalue) override {
return _decodeArray<uint32_t>(in, length, out, nvalue);
}
const uint32_t *decodeArray(const uint32_t *in, const size_t length,
uint64_t *out, size_t &nvalue) override {
return _decodeArray<uint64_t>(in, length, out, nvalue);
}
std::string name() const override {
return codec1.name() + "+" + codec2.name();
}
private:
template <typename IntType>
void _encodeArray(const IntType *in, const size_t length, uint32_t *out,
size_t &nvalue) {
if (nvalue == 0) {
return;
}
const size_t roundedlength = length / Codec1::BlockSize * Codec1::BlockSize;
size_t nvalue1 = nvalue;
codec1.encodeArray(in, roundedlength, out, nvalue1);
if (roundedlength < length) {
if (nvalue1 > nvalue) {
throw std::logic_error(
"Encode run over output buffer. Potential buffer overflow!");
}
size_t nvalue2 = nvalue - nvalue1;
codec2.encodeArray(in + roundedlength, length - roundedlength,
out + nvalue1, nvalue2);
nvalue = nvalue1 + nvalue2;
} else {
nvalue = nvalue1;
}
}
template <typename IntType>
const uint32_t *_decodeArray(const uint32_t *in, const size_t length,
IntType *out, size_t &nvalue) {
if (nvalue == 0) {
return in;
}
const uint32_t *const initin(in);
size_t mynvalue1 = nvalue;
const uint32_t *in2 = codec1.decodeArray(in, length, out, mynvalue1);
if (length + in > in2) {
if (nvalue <= mynvalue1) {
throw std::logic_error("Buffer contains more data than requested!");
}
size_t nvalue2 = nvalue - mynvalue1;
const uint32_t *in3 = codec2.decodeArray(in2, length - (in2 - in),
out + mynvalue1, nvalue2);
nvalue = mynvalue1 + nvalue2;
if (initin + length < in3) {
throw std::logic_error(
"Decode run over output buffer. Potential buffer overflow!");
}
return in3;
}
nvalue = mynvalue1;
if (initin + length < in2) {
throw std::logic_error(
"Decode run over output buffer. Potential buffer overflow!");
}
return in2;
}
};
} // namespace FastPForLib
#endif /* COMPOSITECODEC_H_ */