libebml_ng
vint.h
Go to the documentation of this file.
1 #ifndef EBML_NG_VINT_H
2 #define EBML_NG_VINT_H
3 
4 #include "exceptions.h"
5 #include "io.h"
6 #include "ebmlID_t.h"
7 #include "struct.h"
8 #include "struct/ull.h"
9 #include <array>
10 #include <stdexcept>
11 #include <string>
12 
13 namespace ebml {
14 
16  extern const size_t UNKNOWN;
17 
28  inline unsigned char vintWidth(char b) {
29  static const std::array<unsigned char, 8> masks = {{
30  0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
31  }};
32  unsigned char k;
33  for (k = 0; k < 8; ++k) {
34  if (b & masks[k]) {
35  return k + 1;
36  }
37  }
38  throw ebmlInvalidVint("Variable-length integer cannot start with null byte.");
39  }
40 
51  inline unsigned char widthAsVint(unsigned long long n) {
52  unsigned char k = 0;
53  if (n == 0xffffffffffffffffULL) {
54  return 8;
55  }
56  while (k <= 8) {
57  if (n < ((1ULL << (7 * k)) - 1ULL)) {
58  return k;
59  }
60  k++;
61  }
62  throw std::overflow_error(
63  std::string("int too big to convert (") + std::to_string(__LINE__)
64  + std::string(":") + std::string(__FILE__) + std::string(")")
65  );
66  }
67 
81  inline unsigned long long unpackVint(const char* data, unsigned char size) {
82  unsigned long long val = unpack<unsigned long long>(data, size);
83  val &= ~(1ULL << (7 * size)); // remove the marker bit
84  if (val == ((1ULL << (7 * size)) - 1ULL)) {
85  return 0xffffffffffffffffULL;
86  }
87  return val;
88  }
89 
99  inline unsigned long long unpackVint(const char* data) {
100  unsigned char size = vintWidth(data[0]);
101  return unpackVint(data, size);
102  }
103 
115  inline void packVint(unsigned long long n, unsigned char size, char* dest) {
116  if ((size == 0) || (size > 8)) {
117  throw std::invalid_argument(
118  std::string("packVint: invalid value for size (") + std::to_string(__LINE__)
119  + std::string(":") + std::string(__FILE__) + std::string(")")
120  );
121  }
122 
123  if (n == 0xffffffffffffffffULL) {
124  pack((1ULL << (7 * size + 1)) - 1ULL, size, dest);
125  return;
126  }
127 
128  if (((1ULL << (7 * size)) - 1ULL) <= n) {
129  throw std::overflow_error(
130  std::string("int too big to convert (") + std::to_string(__LINE__)
131  + std::string(":") + std::string(__FILE__) + std::string(")")
132  );
133  }
134 
135  pack((1ULL << (7 * size)) | n, size, dest);
136  }
137 
148  inline unsigned char packVint(unsigned long long n, char* dest) {
149  unsigned char size = widthAsVint(n);
150  packVint(n, size, dest);
151  return size;
152  }
153 
165  unsigned long long unpackVint(const char* data, size_t dataSize, unsigned char& vintw);
166 
177  unsigned long long unpackVint(ioBase& file, unsigned char& vintw);
178 
191  unsigned long long unpackVint(ioBase& file, off_t offset, unsigned char& vintw);
192 
193 } // namespace ebml
194 
195 #endif
T & data(const ebmlElement_sp &elem)
unsigned char vintWidth(char b)
Determines the width (in bytes) of a variable-length integer (vint) based on its first byte...
Definition: vint.h:28
size_t size(const std::string &value)
Definition: binary.h:8
void packVint(unsigned long long n, unsigned char size, char *dest)
Encodes an unsigned long long as a variable-length integer (vint) with a specified width...
Definition: vint.h:115
Definition: exceptions.h:56
Definition: basictypes.h:40
unsigned char widthAsVint(unsigned long long n)
Computes the minimal width (in bytes) required to encode an unsigned long long as a vint...
Definition: vint.h:51
const size_t UNKNOWN
Special constant representing an unknown or maximum value.
Definition: vint.cpp:15
unsigned long long unpackVint(const char *data, size_t dataSize, unsigned char &vintw)
Decodes a vint from a byte array of known size.
Definition: vint.cpp:20
size_t pack(const std::string &value, size_t size, char *dest)
Definition: binary.h:12