42 const std::string& key =
"UNNAMED_BINARY");
54 const std::string& key =
"UNNAMED_BINARY");
72 void decode(T& target)
const;
81 const char* encodedData_;
82 uint32_t encodedDataLength_;
86 initFromData(
const char * str_data,
87 const std::size_t len);
90 void checkLength_(int32_t exp_length)
const;
92 void checkDivisibleBy_(int32_t item_size)
const;
95 void decodeFromBytes_(std::vector<float>& output)
const;
96 void decodeFromBytes_(std::vector<int8_t>& output)
const;
97 void decodeFromBytes_(std::vector<int16_t>& output)
const;
98 void decodeFromBytes_(std::vector<int32_t>& output)
const;
100 void decodeFromBytes_(std::vector<std::string>& output)
const;
105 template<
typename Int,
typename IntOut>
106 void runLengthDecode_(
const std::vector<Int>& input,
107 std::vector<IntOut>& output)
const;
110 template<
typename Int>
111 void deltaDecode_(
const std::vector<Int>& input, std::vector<Int>& output)
const;
113 template<
typename Int>
114 void deltaDecode_(std::vector<Int>& in_out)
const;
117 template<
typename SmallInt,
typename Int>
118 void recursiveIndexDecode_(
const std::vector<SmallInt>& input,
119 std::vector<Int>& output)
const;
122 template<
typename Int>
123 void decodeDivide_(
const std::vector<Int>& input,
float const divisor,
124 std::vector<float>& output)
const;
138#include <arpa/inet.h>
141#ifndef __EMSCRIPTEN__
142void assignBigendian4(
void* dst,
const char* src) {
144 std::memcpy(&tmp, src,
sizeof(uint32_t));
146 std::memcpy(dst, &tmp,
sizeof(uint32_t));
149void assignBigendian2(
void* dst,
const char* src) {
151 std::memcpy(&tmp, src,
sizeof(uint16_t));
153 std::memcpy(dst, &tmp,
sizeof(uint16_t));
161void assignBigendian4(
void* dst,
const char* src) {
162 ((uint8_t*)dst)[0] = src[3];
163 ((uint8_t*)dst)[1] = src[2];
164 ((uint8_t*)dst)[2] = src[1];
165 ((uint8_t*)dst)[3] = src[0];
168void assignBigendian2(
void* dst,
const char* src) {
169 ((uint8_t*)dst)[0] = src[1];
170 ((uint8_t*)dst)[1] = src[0];
174void arrayCopyBigendian4(
void* dst,
const char* src,
size_t n) {
175 for (
size_t i = 0; i < n; i += 4) {
176 assignBigendian4(((
char*)dst) + i, src + i);
180void arrayCopyBigendian2(
void* dst,
const char* src,
size_t n) {
181 for (
size_t i = 0; i < n; i += 2) {
182 assignBigendian2(((
char*)dst) + i, src + i);
190inline void BinaryDecoder::initFromData(
const char * bytes, std::size_t
const len) {
191 assignBigendian4(&strategy_, bytes);
192 assignBigendian4(&length_, bytes + 4);
193 assignBigendian4(¶meter_, bytes + 8);
194 encodedData_ = bytes + 12;
195 encodedDataLength_ = len - 12;
199 const std::string& key)
202 if (obj.type != msgpack::type::BIN) {
203 throw DecodeError(
"The '" + key +
"' entry is not binary data");
205 if (obj.via.bin.size < 12) {
206 std::stringstream err;
207 err <<
"The '" + key +
"' entry is too short " << obj.via.bin.size;
208 throw DecodeError(err.str());
210 this->initFromData(obj.via.bin.ptr, obj.via.bin.size);
214 const std::string& key)
216 this->initFromData(str.data(), str.size());
230 decodeFromBytes_(output);
234 std::vector<int32_t> step1;
235 std::vector<int32_t> step2;
236 decodeFromBytes_(step1);
237 runLengthDecode_(step1, step2);
238 decodeDivide_(step2,
static_cast<float>(parameter_), output);
242 std::vector<int16_t> step1;
243 std::vector<int32_t> step2;
244 decodeFromBytes_(step1);
245 recursiveIndexDecode_(step1, step2);
247 decodeDivide_(step2,
static_cast<float>(parameter_), output);
251 std::vector<int16_t> step1;
252 decodeFromBytes_(step1);
253 decodeDivide_(step1,
static_cast<float>(parameter_), output);
257 std::vector<int16_t> step1;
258 std::vector<int32_t> step2;
259 decodeFromBytes_(step1);
260 recursiveIndexDecode_(step1, step2);
261 decodeDivide_(step2,
static_cast<float>(parameter_), output);
265 std::vector<int8_t> step1;
266 std::vector<int32_t> step2;
267 decodeFromBytes_(step1);
268 recursiveIndexDecode_(step1, step2);
269 decodeDivide_(step2,
static_cast<float>(parameter_), output);
273 std::stringstream err;
274 err <<
"Invalid strategy " << strategy_ <<
" for binary '" + key_
275 <<
"': does not decode to float array";
281 checkLength_(output.size());
290 decodeFromBytes_(output);
294 std::vector<int32_t> step1;
295 decodeFromBytes_(step1);
296 runLengthDecode_(step1, output);
300 std::stringstream err;
301 err <<
"Invalid strategy " << strategy_ <<
" for binary '" + key_
302 <<
"': does not decode to int8 array";
308 checkLength_(output.size());
317 decodeFromBytes_(output);
321 std::stringstream err;
322 err <<
"Invalid strategy " << strategy_ <<
" for binary '" + key_
323 <<
"': does not decode to int16 array";
329 checkLength_(output.size());
338 decodeFromBytes_(output);
342 std::vector<int32_t> step1;
343 decodeFromBytes_(step1);
344 runLengthDecode_(step1, output);
348 std::vector<int32_t> step1;
349 decodeFromBytes_(step1);
350 runLengthDecode_(step1, output);
351 deltaDecode_(output);
355 std::vector<int16_t> step1;
356 decodeFromBytes_(step1);
357 recursiveIndexDecode_(step1, output);
361 std::vector<int8_t> step1;
362 decodeFromBytes_(step1);
363 recursiveIndexDecode_(step1, output);
367 std::stringstream err;
368 err <<
"Invalid strategy " << strategy_ <<
" for binary '" + key_
369 <<
"': does not decode to int32 array";
375 checkLength_(output.size());
384 decodeFromBytes_(output);
388 std::stringstream err;
389 err <<
"Invalid strategy " << strategy_ <<
" for binary '" + key_
390 <<
"': does not decode to string array";
396 checkLength_(output.size());
405 std::vector<int32_t> step1;
406 decodeFromBytes_(step1);
407 runLengthDecode_(step1, output);
411 std::stringstream err;
412 err <<
"Invalid strategy " << strategy_ <<
" for binary '" + key_
413 <<
"': does not decode to string array";
419 checkLength_(output.size());
423inline void BinaryDecoder::checkLength_(int32_t exp_length)
const {
424 if (length_ != exp_length) {
425 std::stringstream err;
426 err <<
"Length mismatch for binary '" + key_ +
"': "
427 << length_ <<
" vs " << exp_length;
432inline void BinaryDecoder::checkDivisibleBy_(int32_t item_size)
const {
433 if (encodedDataLength_ % item_size != 0) {
434 std::stringstream err;
435 err <<
"Binary length of '" + key_ +
"': "
436 << encodedDataLength_ <<
" is not a multiple of " << item_size;
437 throw DecodeError(err.str());
442inline void BinaryDecoder::decodeFromBytes_(std::vector<float>& output)
const {
443 checkDivisibleBy_(4);
445 output.resize(encodedDataLength_ / 4);
447 if(!output.empty()) {
448 arrayCopyBigendian4(&output[0], encodedData_, encodedDataLength_);
451inline void BinaryDecoder::decodeFromBytes_(std::vector<int8_t>& output)
const {
453 output.resize(encodedDataLength_);
455 if (!output.empty()) {
456 memcpy(&output[0], encodedData_, encodedDataLength_);
459inline void BinaryDecoder::decodeFromBytes_(std::vector<int16_t>& output)
const {
460 checkDivisibleBy_(2);
462 output.resize(encodedDataLength_ / 2);
464 if (!output.empty()) {
465 arrayCopyBigendian2(&output[0], encodedData_, encodedDataLength_);
468inline void BinaryDecoder::decodeFromBytes_(std::vector<int32_t>& output)
const {
469 checkDivisibleBy_(4);
471 output.resize(encodedDataLength_ / 4);
473 if (!output.empty()) {
474 arrayCopyBigendian4(&output[0], encodedData_, encodedDataLength_);
478inline void BinaryDecoder::decodeFromBytes_(std::vector<std::string>& output)
const {
479 char NULL_BYTE = 0x00;
481 const int32_t str_len = parameter_;
482 checkDivisibleBy_(str_len);
484 output.resize(encodedDataLength_ / str_len);
486 for (
size_t i = 0; i < output.size(); ++i) {
487 output[i].assign(encodedData_ + i * str_len, str_len);
488 output[i].erase(std::remove(output[i].begin(), output[i].end(), NULL_BYTE), output[i].end());
493template<
typename Int,
typename IntOut>
494void BinaryDecoder::runLengthDecode_(
const std::vector<Int>& input,
495 std::vector<IntOut>& output)
const {
497 checkDivisibleBy_(2);
500 for (
size_t i = 0; i < input.size(); i += 2) {
501 out_size += input[i + 1];
505 output.reserve(out_size);
507 for (
size_t i = 0; i < input.size(); i += 2) {
508 const IntOut value = IntOut(input[i]);
509 const Int number = input[i+1];
510 for (Int j = 0; j < number; ++j) {
511 output.push_back(value);
517template<
typename Int>
518void BinaryDecoder::deltaDecode_(
const std::vector<Int>& input,
519 std::vector<Int>& output)
const {
522 if (input.empty())
return;
523 output.reserve(input.size());
525 output.push_back(input[0]);
526 for (
size_t i = 1; i < input.size(); ++i) {
527 output.push_back(output[i - 1] + input[i]);
530template<
typename Int>
531void BinaryDecoder::deltaDecode_(std::vector<Int>& in_out)
const {
532 for (
size_t i = 1; i < in_out.size(); ++i) {
533 in_out[i] = in_out[i - 1] + in_out[i];
538template<
typename SmallInt,
typename Int>
539void BinaryDecoder::recursiveIndexDecode_(
const std::vector<SmallInt>& input,
540 std::vector<Int>& output)
const {
542 const SmallInt min_int = std::numeric_limits<SmallInt>::min();
543 const SmallInt max_int = std::numeric_limits<SmallInt>::max();
546 for (
size_t i = 0; i < input.size(); ++i) {
547 if (input[i] != min_int && input[i] != max_int) ++out_size;
551 output.reserve(out_size);
554 for (
size_t i = 0; i < input.size(); ++i) {
556 if (input[i] != min_int && input[i] != max_int) {
557 output.push_back(cur_val);
564template<
typename Int>
565void BinaryDecoder::decodeDivide_(
const std::vector<Int>& input,
float const divisor,
566 std::vector<float>& output)
const {
569 output.reserve(input.size());
570 float inv_div = float(1) / divisor;
572 for (
size_t i = 0; i < input.size(); ++i) {
573 output.push_back(
float(input[i]) * inv_div);