Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/bitstream.cc
Line
Count
Source
1
/*
2
 * HEIF codec.
3
 * Copyright (c) 2017 Dirk Farin <dirk.farin@gmail.com>
4
 *
5
 * This file is part of libheif.
6
 *
7
 * libheif is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libheif is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "bitstream.h"
22
23
#include <utility>
24
#include <cstring>
25
#include <cassert>
26
27
#include "common_utils.h"
28
29
#if !defined(HAVE_BIT)
30
#include <type_traits>
31
#else
32
#include <bit>
33
#endif
34
35
377k
#define MAX_UVLC_LEADING_ZEROS 20
36
37
38
StreamReader_istream::StreamReader_istream(std::unique_ptr<std::istream>&& istr)
39
0
    : m_istr(std::move(istr))
40
0
{
41
0
  m_istr->seekg(0, std::ios_base::end);
42
0
  m_length = m_istr->tellg();
43
0
  m_istr->seekg(0, std::ios_base::beg);
44
0
}
45
46
uint64_t StreamReader_istream::get_position() const
47
0
{
48
0
  return m_istr->tellg();
49
0
}
50
51
StreamReader::grow_status StreamReader_istream::wait_for_file_size(uint64_t target_size)
52
0
{
53
0
  return (target_size > m_length) ? grow_status::size_beyond_eof : grow_status::size_reached;
54
0
}
55
56
bool StreamReader_istream::read(void* data, size_t size)
57
0
{
58
0
  uint64_t end_pos = get_position() + size;
59
0
  if (end_pos > m_length) {
60
0
    return false;
61
0
  }
62
63
0
  m_istr->read((char*) data, size);
64
0
  return true;
65
0
}
66
67
bool StreamReader_istream::seek(uint64_t position)
68
0
{
69
0
  if (position > m_length)
70
0
    return false;
71
72
0
  m_istr->seekg(position, std::ios_base::beg);
73
0
  return true;
74
0
}
75
76
77
StreamReader_memory::StreamReader_memory(const uint8_t* data, size_t size, bool copy)
78
24
    : m_length(size)
79
24
{
80
24
  if (copy) {
81
0
    m_owned_data = new uint8_t[m_length];
82
0
    memcpy(m_owned_data, data, size);
83
84
0
    m_data = m_owned_data;
85
0
  }
86
24
  else {
87
24
    m_data = data;
88
24
  }
89
24
}
90
91
StreamReader_memory::~StreamReader_memory()
92
24
{
93
24
  if (m_owned_data) {
94
0
    delete[] m_owned_data;
95
0
  }
96
24
}
97
98
uint64_t StreamReader_memory::get_position() const
99
54
{
100
54
  return m_position;
101
54
}
102
103
StreamReader::grow_status StreamReader_memory::wait_for_file_size(uint64_t target_size)
104
48
{
105
48
  return (target_size > m_length) ? grow_status::size_beyond_eof : grow_status::size_reached;
106
48
}
107
108
bool StreamReader_memory::read(void* data, size_t size)
109
212
{
110
212
  uint64_t end_pos = m_position + size;
111
212
  if (end_pos > m_length) {
112
0
    return false;
113
0
  }
114
115
212
  memcpy(data, &m_data[m_position], size);
116
212
  m_position += size;
117
118
212
  return true;
119
212
}
120
121
bool StreamReader_memory::seek(uint64_t position)
122
6
{
123
6
  if (position > m_length)
124
0
    return false;
125
126
6
  m_position = position;
127
6
  return true;
128
6
}
129
130
131
StreamReader_CApi::StreamReader_CApi(const heif_reader* func_table, void* userdata)
132
20.5k
    : m_func_table(func_table), m_userdata(userdata)
133
20.5k
{
134
20.5k
}
135
136
StreamReader::grow_status StreamReader_CApi::wait_for_file_size(uint64_t target_size)
137
803k
{
138
803k
  heif_reader_grow_status status = m_func_table->wait_for_file_size(target_size, m_userdata);
139
803k
  switch (status) {
140
790k
    case heif_reader_grow_status_size_reached:
141
790k
      return grow_status::size_reached;
142
0
    case heif_reader_grow_status_timeout:
143
0
      return grow_status::timeout;
144
12.9k
    case heif_reader_grow_status_size_beyond_eof:
145
12.9k
      return grow_status::size_beyond_eof;
146
0
    default:
147
0
      assert(0);
148
0
      return grow_status::size_beyond_eof;
149
803k
  }
150
803k
}
151
152
153
BitstreamRange::BitstreamRange(std::shared_ptr<StreamReader> istr,
154
                               size_t length,
155
                               BitstreamRange* parent)
156
354k
    : m_istr(std::move(istr)), m_parent_range(parent), m_remaining(length)
157
354k
{
158
354k
  if (parent) {
159
334k
    m_nesting_level = parent->m_nesting_level + 1;
160
334k
  }
161
354k
}
162
163
164
BitstreamRange::BitstreamRange(std::shared_ptr<StreamReader> istr,
165
                               size_t start,
166
                               size_t end) // one past end
167
89.7k
  : m_istr(std::move(istr)), m_remaining(end - start)
168
89.7k
{
169
89.7k
  assert(end >= start);
170
171
89.7k
  bool success = m_istr->seek(start);
172
89.7k
  assert(success);
173
89.7k
  (void)success; // TODO
174
89.7k
}
175
176
177
StreamReader::grow_status BitstreamRange::wait_until_range_is_available()
178
0
{
179
0
  return m_istr->wait_for_file_size(m_istr->get_position() + m_remaining);
180
0
}
181
182
183
uint8_t BitstreamRange::read8()
184
2.71M
{
185
2.71M
  if (!prepare_read(1)) {
186
13.0k
    return 0;
187
13.0k
  }
188
189
2.70M
  uint8_t buf;
190
191
2.70M
  auto istr = get_istream();
192
2.70M
  bool success = istr->read((char*) &buf, 1);
193
194
2.70M
  if (!success) {
195
0
    set_eof_while_reading();
196
0
    return 0;
197
0
  }
198
199
2.70M
  return buf;
200
2.70M
}
201
202
203
uint16_t BitstreamRange::read16()
204
625k
{
205
625k
  if (!prepare_read(2)) {
206
4.43k
    return 0;
207
4.43k
  }
208
209
620k
  uint8_t buf[2];
210
211
620k
  auto istr = get_istream();
212
620k
  bool success = istr->read((char*) buf, 2);
213
214
620k
  if (!success) {
215
0
    set_eof_while_reading();
216
0
    return 0;
217
0
  }
218
219
620k
  return static_cast<uint16_t>((buf[0] << 8) | (buf[1]));
220
620k
}
221
222
223
int16_t BitstreamRange::read16s()
224
874
{
225
874
  uint16_t v = read16();
226
227
874
  if (v & 0x8000) {
228
154
    auto val = static_cast<int16_t>((~v) & 0x7fff);
229
154
    return static_cast<int16_t>(-val - 1);
230
154
  }
231
720
  else {
232
720
    return static_cast<int16_t>(v);
233
720
  }
234
874
}
235
236
237
uint32_t BitstreamRange::read24()
238
594
{
239
594
  if (!prepare_read(3)) {
240
0
    return 0;
241
0
  }
242
243
594
  uint8_t buf[3];
244
245
594
  auto istr = get_istream();
246
594
  bool success = istr->read((char*) buf, 3);
247
248
594
  if (!success) {
249
0
    set_eof_while_reading();
250
0
    return 0;
251
0
  }
252
253
594
  return (uint32_t) ((buf[0] << 16) |
254
594
                     (buf[1] << 8) |
255
594
                     (buf[2]));
256
594
}
257
258
uint32_t BitstreamRange::read32()
259
1.51M
{
260
1.51M
  if (!prepare_read(4)) {
261
4.08k
    return 0;
262
4.08k
  }
263
264
1.51M
  uint8_t buf[4];
265
266
1.51M
  auto istr = get_istream();
267
1.51M
  bool success = istr->read((char*) buf, 4);
268
269
1.51M
  if (!success) {
270
0
    set_eof_while_reading();
271
0
    return 0;
272
0
  }
273
274
1.51M
  return four_bytes_to_uint32(buf[0], buf[1], buf[2], buf[3]);
275
1.51M
}
276
277
278
uint64_t BitstreamRange::read_uint(int len)
279
58.0k
{
280
58.0k
  switch (len)
281
58.0k
  {
282
1.31k
    case 8:
283
1.31k
      return read8();
284
55.4k
    case 16:
285
55.4k
      return read16();
286
594
    case 24:
287
594
      return read24();
288
590
    case 32:
289
590
      return read32();
290
135
    case 64:
291
135
      return read64();
292
0
    default:
293
0
      assert(false);
294
0
      return 0;
295
58.0k
  }
296
58.0k
}
297
298
299
int32_t BitstreamRange::read32s()
300
620
{
301
620
  uint32_t v = read32();
302
303
620
  if (v & 0x80000000) {
304
99
    return -static_cast<int32_t>((~v) & 0x7fffffff) -1;
305
99
  }
306
521
  else {
307
521
    return static_cast<int32_t>(v);
308
521
  }
309
620
}
310
311
312
uint64_t BitstreamRange::read64()
313
672
{
314
672
  if (!prepare_read(8)) {
315
28
    return 0;
316
28
  }
317
318
644
  uint8_t buf[8];
319
320
644
  auto istr = get_istream();
321
644
  bool success = istr->read((char*) buf, 8);
322
323
644
  if (!success) {
324
0
    set_eof_while_reading();
325
0
    return 0;
326
0
  }
327
328
644
  return ((static_cast<uint64_t>(buf[0]) << 56) |
329
644
          (static_cast<uint64_t>(buf[1]) << 48) |
330
644
          (static_cast<uint64_t>(buf[2]) << 40) |
331
644
          (static_cast<uint64_t>(buf[3]) << 32) |
332
644
          (static_cast<uint64_t>(buf[4]) << 24) |
333
644
          (static_cast<uint64_t>(buf[5]) << 16) |
334
644
          (static_cast<uint64_t>(buf[6]) << 8) |
335
644
          (static_cast<uint64_t>(buf[7])));
336
644
}
337
338
339
int64_t BitstreamRange::read64s()
340
223
{
341
223
  uint64_t v = read64();
342
343
223
  if (v & 0x8000000000000000) {
344
36
    return -static_cast<int64_t >((~v) & 0x7fffffffffffffff) -1;
345
36
  }
346
187
  else {
347
187
    return static_cast<int64_t >(v);
348
187
  }
349
223
}
350
351
352
float BitstreamRange::read_float32()
353
1.13k
{
354
1.13k
#if __cpp_lib_bit_cast >= 201806L
355
1.13k
  uint32_t i = read32();
356
1.13k
  return std::bit_cast<float>(i); // this works directly on the value layout, thus we do not have to worry about memory layout
357
#else
358
  // compiler too old to support bit_cast
359
360
  // TODO: I am not sure this works everywhere as there seem to be systems where
361
  //       the float byte order is different from the integer endianness
362
  //       https://en.wikipedia.org/wiki/Endianness#Floating_point
363
  uint32_t i = read32();
364
  float f;
365
  memcpy(&f, &i, sizeof(float));
366
  return f;
367
#endif
368
1.13k
}
369
370
371
void StreamWriter::write_float32(float v)
372
0
{
373
0
#if __cpp_lib_bit_cast >= 201806L
374
0
  write32(std::bit_cast<uint32_t>(v)); // this works directly on the value layout, thus we do not have to worry about memory layout
375
#else
376
  // compiler too old to support bit_cast
377
378
  // TODO: I am not sure this works everywhere as there seem to be systems where
379
  //       the float byte order is different from the integer endianness
380
  //       https://en.wikipedia.org/wiki/Endianness#Floating_point
381
  uint32_t i;
382
  memcpy(&i, &v, sizeof(float));
383
  write32(i);
384
#endif
385
0
}
386
387
388
std::string BitstreamRange::read_string()
389
78.0k
{
390
78.0k
  std::string str;
391
392
  // Reading a string when no more data is available, returns an empty string.
393
  // Such a case happens, for example, when reading a 'url' box without content.
394
78.0k
  if (eof()) {
395
779
    return std::string();
396
779
  }
397
398
77.3k
  auto istr = get_istream();
399
400
282k
  for (;;) {
401
282k
    if (!prepare_read(1)) {
402
0
      return std::string();
403
0
    }
404
405
282k
    char c;
406
282k
    bool success = istr->read(&c, 1);
407
408
282k
    if (!success) {
409
0
      set_eof_while_reading();
410
0
      return std::string();
411
0
    }
412
413
282k
    if (c == 0 || m_remaining==0) {
414
77.3k
      break;
415
77.3k
    }
416
204k
    else {
417
204k
      str += (char) c;
418
204k
    }
419
282k
  }
420
421
77.3k
  return str;
422
77.3k
}
423
424
425
std::string BitstreamRange::read_fixed_string(int len)
426
41
{
427
41
  std::string str;
428
429
41
  if (!prepare_read(len)) {
430
7
    return std::string();
431
7
  }
432
433
34
  auto istr = get_istream();
434
435
34
  uint8_t n;
436
34
  bool success = istr->read(&n, 1);
437
34
  if (!success || n > len - 1) {
438
7
    return {};
439
7
  }
440
441
337
  for (int i = 0; i < n; i++) {
442
310
    char c;
443
310
    success = istr->read(&c, 1);
444
445
310
    if (!success) {
446
0
      set_eof_while_reading();
447
0
      return std::string();
448
0
    }
449
450
310
    str += (char) c;
451
310
  }
452
453
27
  istr->seek_cur(len-n-1);
454
455
27
  return str;
456
27
}
457
458
459
std::string BitstreamRange::read_string_until_eof()
460
11
{
461
11
  size_t n = get_remaining_bytes();
462
463
11
  [[maybe_unused]] bool success = prepare_read(n);
464
11
  assert(success); // we are reading exactly the rest of the box
465
466
11
  std::string str;
467
11
  str.resize(n);
468
11
  get_istream()->read(str.data(), n);
469
470
11
  return str;
471
11
}
472
473
474
bool BitstreamRange::read(uint8_t* data, size_t n)
475
37.0k
{
476
37.0k
  if (!prepare_read(n)) {
477
52
    return false;
478
52
  }
479
480
37.0k
  auto istr = get_istream();
481
37.0k
  bool success = istr->read(data, n);
482
483
37.0k
  if (!success) {
484
0
    set_eof_while_reading();
485
0
  }
486
487
37.0k
  return success;
488
37.0k
}
489
490
491
bool BitstreamRange::prepare_read(size_t nBytes)
492
21.3M
{
493
  // Note: we do not test for negative nBytes anymore because we now use the unsigned size_t
494
495
21.3M
  if (m_remaining < nBytes) {
496
    // --- not enough data left in box -> move to end of box and set error flag
497
498
21.7k
    skip_to_end_of_box();
499
500
21.7k
    m_error = true;
501
21.7k
    return false;
502
21.7k
  }
503
21.3M
  else {
504
    // --- this is the normal case (m_remaining >= nBytes)
505
506
21.3M
    if (m_parent_range) {
507
16.1M
      if (!m_parent_range->prepare_read(nBytes)) {
508
0
        return false;
509
0
      }
510
16.1M
    }
511
512
21.3M
    m_remaining -= nBytes;
513
514
21.3M
    return true;
515
21.3M
  }
516
21.3M
}
517
518
519
StreamReader::grow_status BitstreamRange::wait_for_available_bytes(size_t nBytes)
520
761k
{
521
761k
  int64_t target_size = m_istr->get_position() + nBytes;
522
523
761k
  return m_istr->wait_for_file_size(target_size);
524
761k
}
525
526
527
void BitstreamRange::skip_without_advancing_file_pos(size_t n)
528
38.8k
{
529
38.8k
  assert(n <= m_remaining);
530
531
38.8k
  m_remaining -= n;
532
533
38.8k
  if (m_parent_range) {
534
22.3k
    m_parent_range->skip_without_advancing_file_pos(n);
535
22.3k
  }
536
38.8k
}
537
538
539
BitReader::BitReader(const uint8_t* buffer, size_t len)
540
21.3k
  : data_start(buffer),
541
21.3k
    data_length(len)
542
21.3k
{
543
21.3k
  data = buffer;
544
21.3k
  bytes_remaining = len;
545
546
21.3k
  nextbits = 0;
547
21.3k
  nextbits_cnt = 0;
548
549
21.3k
  refill();
550
21.3k
}
551
552
553
void BitReader::reset()
554
0
{
555
0
  data = data_start;
556
0
  bytes_remaining = data_length;
557
558
0
  nextbits = 0;
559
0
  nextbits_cnt = 0;
560
561
0
  refill();
562
0
}
563
564
565
uint32_t BitReader::get_bits(int n)
566
6.68M
{
567
6.68M
  assert(n <= 32);
568
569
6.68M
  if (nextbits_cnt < n) {
570
766k
    refill();
571
766k
  }
572
573
6.68M
  uint64_t val = nextbits;
574
6.68M
  val >>= 64 - n;
575
576
#if AVOID_FUZZER_FALSE_POSITIVE
577
  // Shifting an unsigned integer left such that some MSBs fall out is well defined in C++ despite the fuzzer claiming otherwise.
578
  nextbits &= (0xffffffffffffffffULL >> n);
579
#endif
580
581
6.68M
  nextbits <<= n;
582
6.68M
  nextbits_cnt -= n;
583
584
6.68M
  return static_cast<uint32_t>(val);
585
6.68M
}
586
587
588
uint8_t BitReader::get_bits8(int n)
589
130k
{
590
130k
  assert(n>0 && n <= 8);
591
130k
  return static_cast<uint8_t>(get_bits(n));
592
130k
}
593
594
uint16_t BitReader::get_bits16(int n)
595
8.62k
{
596
8.62k
  assert(n>0 && n <= 16);
597
8.62k
  return static_cast<uint16_t>(get_bits(n));
598
8.62k
}
599
600
uint32_t BitReader::get_bits32(int n)
601
35.0k
{
602
35.0k
  assert(n>0 && n <= 32);
603
35.0k
  return static_cast<uint32_t>(get_bits(n));
604
35.0k
}
605
606
int32_t BitReader::get_bits32s()
607
888
{
608
888
  uint32_t bits = get_bits(32);
609
888
  return static_cast<int32_t>(bits);
610
888
}
611
612
613
bool BitReader::get_flag()
614
37.7k
{
615
37.7k
  return (get_bits(1) == 0x01);
616
37.7k
}
617
618
std::vector<uint8_t> BitReader::read_bytes(uint32_t n)
619
1.33k
{
620
  // TODO: this implementation isn't very efficient
621
1.33k
  std::vector<uint8_t> bytes;
622
5.78k
  for (uint32_t i = 0; i < n; i++) {
623
4.45k
    bytes.push_back(get_bits8(8));
624
4.45k
  }
625
1.33k
  return bytes;
626
1.33k
}
627
628
int BitReader::get_bits_fast(int n)
629
0
{
630
0
  assert(nextbits_cnt >= n);
631
632
0
  uint64_t val = nextbits;
633
0
  val >>= 64 - n;
634
635
0
  nextbits <<= n;
636
0
  nextbits_cnt -= n;
637
638
0
  return (int) val;
639
0
}
640
641
int BitReader::peek_bits(int n)
642
0
{
643
0
  if (nextbits_cnt < n) {
644
0
    refill();
645
0
  }
646
647
0
  uint64_t val = nextbits;
648
0
  val >>= 64 - n;
649
650
0
  return (int) val;
651
0
}
652
653
void BitReader::skip_bytes(uint32_t nBytes)
654
1.89k
{
655
  // This has to run in constant time. The number of bytes to skip is taken directly
656
  // from 32-bit file fields (e.g. the 'uncC' row/tile alignment), so a byte-at-a-time
657
  // loop spins for billions of iterations when a malformed file asks to skip far
658
  // beyond the end of the data. MinimizedImageBox::parse() guards against the same
659
  // failure mode by validating its declared chunk sizes up front.
660
661
1.89k
  uint64_t nBits = uint64_t{nBytes} * 8;
662
663
  // --- consume the bits that are already buffered in 'nextbits'
664
665
1.89k
  if (nextbits_cnt > 0) {
666
1.50k
    uint64_t from_buffer = std::min(nBits, static_cast<uint64_t>(nextbits_cnt));
667
668
1.50k
    if (from_buffer >= 64) {
669
129
      nextbits = 0;
670
129
    }
671
1.37k
    else {
672
#if AVOID_FUZZER_FALSE_POSITIVE
673
      nextbits &= (0xffffffffffffffffULL >> from_buffer);
674
#endif
675
1.37k
      nextbits <<= from_buffer;
676
1.37k
    }
677
678
1.50k
    nextbits_cnt -= static_cast<int64_t>(from_buffer);
679
1.50k
    nBits -= from_buffer;
680
1.50k
  }
681
682
1.89k
  if (nBits == 0) {
683
1.18k
    return;
684
1.18k
  }
685
686
  // --- skip whole bytes directly in the input buffer, without pushing them
687
  //     through the bit buffer
688
689
713
  uint64_t whole_bytes = nBits / 8;
690
713
  int residual_bits = static_cast<int>(nBits % 8);
691
692
713
  if (whole_bytes >= bytes_remaining) {
693
    // Skipping past the end of the data. Record the overshoot in 'nextbits_cnt' (which
694
    // thereby goes negative) so that get_current_byte_index() keeps advancing exactly
695
    // as it did with the previous bit-by-bit implementation.
696
3
    uint64_t overshoot_bits = (whole_bytes - bytes_remaining) * 8 + static_cast<uint64_t>(residual_bits);
697
698
3
    data += bytes_remaining;
699
3
    bytes_remaining = 0;
700
3
    nextbits = 0;
701
3
    nextbits_cnt -= static_cast<int64_t>(overshoot_bits);
702
3
    return;
703
3
  }
704
705
710
  data += static_cast<size_t>(whole_bytes);
706
710
  bytes_remaining -= static_cast<size_t>(whole_bytes);
707
710
  nextbits = 0;
708
710
  nextbits_cnt = 0;
709
710
710
  refill();
711
712
710
  if (residual_bits > 0) {
713
0
    skip_bits(residual_bits);
714
0
  }
715
710
}
716
717
void BitReader::skip_bits(int n)
718
112k
{
719
112k
  if (nextbits_cnt < n) {
720
22.5k
    refill();
721
22.5k
  }
722
723
#if AVOID_FUZZER_FALSE_POSITIVE
724
  nextbits &= (0xffffffffffffffffULL >> n);
725
#endif
726
727
112k
  nextbits <<= n;
728
112k
  nextbits_cnt -= n;
729
112k
}
730
731
void BitReader::skip_bits_fast(int n)
732
0
{
733
#if AVOID_FUZZER_FALSE_POSITIVE
734
  nextbits &= (0xffffffffffffffffULL >> n);
735
#endif
736
737
0
  nextbits <<= n;
738
0
  nextbits_cnt -= n;
739
0
}
740
741
void BitReader::skip_to_byte_boundary()
742
34.8k
{
743
34.8k
  int nskip = static_cast<int>(nextbits_cnt & 7);
744
745
#if AVOID_FUZZER_FALSE_POSITIVE
746
  nextbits &= (0xffffffffffffffffULL >> nskip);
747
#endif
748
749
34.8k
  nextbits <<= nskip;
750
34.8k
  nextbits_cnt -= nskip;
751
34.8k
}
752
753
bool BitReader::get_uvlc(uint32_t* value)
754
133k
{
755
133k
  int num_zeros = 0;
756
757
510k
  while (get_bits(1) == 0) {
758
377k
    num_zeros++;
759
760
377k
    if (num_zeros > MAX_UVLC_LEADING_ZEROS) { return false; }
761
377k
  }
762
763
132k
  if (num_zeros != 0) {
764
68.6k
    uint32_t offset = get_bits(num_zeros);
765
68.6k
    *value = offset + (1u << num_zeros) - 1u;
766
68.6k
    assert(*value > 0);
767
68.6k
    return true;
768
68.6k
  }
769
64.2k
  else {
770
64.2k
    *value = 0;
771
64.2k
    return true;
772
64.2k
  }
773
132k
}
774
775
bool BitReader::get_svlc(int32_t* value)
776
902
{
777
902
  uint32_t v;
778
902
  if (!get_uvlc(&v)) {
779
18
    return false;
780
18
  }
781
884
  else if (v == 0) {
782
559
    *value = 0;
783
559
    return true;
784
559
  }
785
786
325
  bool negative = ((v & 1u) == 0);
787
325
  *value = negative ? -static_cast<int32_t>(v / 2) : static_cast<int32_t>((v + 1) / 2);
788
325
  return true;
789
902
}
790
791
void BitReader::refill()
792
811k
{
793
#if 0
794
  // TODO: activate me once I'm sure this works
795
  while (nextbits_cnt <= 64-8 && bytes_remaining) {
796
    uint64_t newval = *data++;
797
    bytes_remaining--;
798
799
    nextbits_cnt += 8;
800
    newval <<= 64-nextbits_cnt;
801
    nextbits |= newval;
802
  }
803
#else
804
811k
  if (bytes_remaining == 0) {
805
    // Nothing to refill. Returning early also keeps the shift below out of range
806
    // when nextbits_cnt is far negative after skipping past the end of the data.
807
2.65k
    return;
808
2.65k
  }
809
810
808k
  int64_t shift = 64 - nextbits_cnt;
811
812
7.24M
  while (shift >= 8 && bytes_remaining) {
813
6.43M
    uint64_t newval = *data++;
814
6.43M
    bytes_remaining--;
815
816
6.43M
    shift -= 8;
817
6.43M
    newval <<= shift;
818
6.43M
    nextbits |= newval;
819
6.43M
  }
820
821
808k
  nextbits_cnt = 64 - shift;
822
808k
#endif
823
808k
}
824
825
826
// --- BitWriter ---
827
828
void BitWriter::write_bits(uint32_t value, int n)
829
0
{
830
0
  assert(n >= 0 && n <= 32);
831
832
0
  for (int i = n - 1; i >= 0; i--) {
833
0
    uint8_t bit = (value >> i) & 1;
834
0
    m_current_byte |= (bit << (7 - m_bits_in_current_byte));
835
0
    m_bits_in_current_byte++;
836
837
0
    if (m_bits_in_current_byte == 8) {
838
0
      m_data.push_back(m_current_byte);
839
0
      m_current_byte = 0;
840
0
      m_bits_in_current_byte = 0;
841
0
    }
842
0
  }
843
0
}
844
845
void BitWriter::write_bytes(const std::vector<uint8_t>& data)
846
0
{
847
0
  write_bytes(data.data(), data.size());
848
0
}
849
850
void BitWriter::write_bytes(const uint8_t* data, size_t len)
851
0
{
852
0
  assert(m_bits_in_current_byte == 0);
853
0
  m_data.insert(m_data.end(), data, data + len);
854
0
}
855
856
void BitWriter::skip_to_byte_boundary()
857
0
{
858
0
  if (m_bits_in_current_byte > 0) {
859
0
    m_data.push_back(m_current_byte);
860
0
    m_current_byte = 0;
861
0
    m_bits_in_current_byte = 0;
862
0
  }
863
0
}
864
865
std::vector<uint8_t> BitWriter::get_data() const
866
0
{
867
0
  std::vector<uint8_t> result = m_data;
868
0
  if (m_bits_in_current_byte > 0) {
869
0
    result.push_back(m_current_byte);
870
0
  }
871
0
  return result;
872
0
}
873
874
875
// --- StreamWriter ---
876
877
void StreamWriter::write8(uint8_t v)
878
6.95k
{
879
6.95k
  if (m_position == m_data.size()) {
880
6.95k
    m_data.push_back(v);
881
6.95k
    m_position++;
882
6.95k
  }
883
0
  else {
884
0
    m_data[m_position++] = v;
885
0
  }
886
6.95k
}
887
888
889
void StreamWriter::write16(uint16_t v)
890
20.7k
{
891
20.7k
  size_t required_size = m_position + 2;
892
893
20.7k
  if (required_size > m_data.size()) {
894
20.7k
    m_data.resize(required_size);
895
20.7k
  }
896
897
20.7k
  m_data[m_position++] = uint8_t((v >> 8) & 0xFF);
898
20.7k
  m_data[m_position++] = uint8_t(v & 0xFF);
899
20.7k
}
900
901
902
void StreamWriter::write16s(int16_t v16s)
903
0
{
904
0
  uint16_t v;
905
0
  if (v16s >= 0) {
906
0
    v = static_cast<uint16_t>(v16s);
907
0
  }
908
0
  else {
909
0
    auto val = static_cast<uint16_t>((-v16s-1));
910
0
    v = static_cast<uint16_t>(~val);
911
0
  }
912
913
0
  write16(v);
914
0
}
915
916
917
void StreamWriter::write24(uint32_t v)
918
0
{
919
0
  size_t required_size = m_position + 3;
920
921
0
  if (required_size > m_data.size()) {
922
0
    m_data.resize(required_size);
923
0
  }
924
925
0
  m_data[m_position++] = uint8_t((v >> 16) & 0xFF);
926
0
  m_data[m_position++] = uint8_t((v >> 8) & 0xFF);
927
0
  m_data[m_position++] = uint8_t(v & 0xFF);
928
0
}
929
930
931
void StreamWriter::write32(uint32_t v)
932
192k
{
933
192k
  size_t required_size = m_position + 4;
934
935
192k
  if (required_size > m_data.size()) {
936
64.1k
    m_data.resize(required_size);
937
64.1k
  }
938
939
192k
  m_data[m_position++] = uint8_t((v >> 24) & 0xFF);
940
192k
  m_data[m_position++] = uint8_t((v >> 16) & 0xFF);
941
192k
  m_data[m_position++] = uint8_t((v >> 8) & 0xFF);
942
192k
  m_data[m_position++] = uint8_t(v & 0xFF);
943
192k
}
944
945
946
void StreamWriter::write32s(int32_t v32s)
947
0
{
948
0
  uint32_t v;
949
0
  if (v32s >= 0) {
950
0
    v = static_cast<uint32_t>(v32s);
951
0
  }
952
0
  else {
953
0
    v = ~static_cast<uint32_t>((-v32s-1));
954
0
  }
955
956
0
  write32(v);
957
0
}
958
959
960
void StreamWriter::write64(uint64_t v)
961
0
{
962
0
  size_t required_size = m_position + 8;
963
964
0
  if (required_size > m_data.size()) {
965
0
    m_data.resize(required_size);
966
0
  }
967
968
0
  m_data[m_position++] = uint8_t((v >> 56) & 0xFF);
969
0
  m_data[m_position++] = uint8_t((v >> 48) & 0xFF);
970
0
  m_data[m_position++] = uint8_t((v >> 40) & 0xFF);
971
0
  m_data[m_position++] = uint8_t((v >> 32) & 0xFF);
972
0
  m_data[m_position++] = uint8_t((v >> 24) & 0xFF);
973
0
  m_data[m_position++] = uint8_t((v >> 16) & 0xFF);
974
0
  m_data[m_position++] = uint8_t((v >> 8) & 0xFF);
975
0
  m_data[m_position++] = uint8_t(v & 0xFF);
976
0
}
977
978
979
void StreamWriter::write64s(int64_t v)
980
0
{
981
0
  write64(reinterpret_cast<uint64_t&>(v));
982
0
}
983
984
985
void StreamWriter::write(int size, uint64_t value)
986
0
{
987
0
  if (size == 1) {
988
0
    assert(value <= 0xFF);
989
0
    write8((uint8_t) value);
990
0
  }
991
0
  else if (size == 2) {
992
0
    assert(value <= 0xFFFF);
993
0
    write16((uint16_t) value);
994
0
  }
995
0
  else if (size == 4) {
996
0
    assert(value <= 0xFFFFFFFF);
997
0
    write32((uint32_t) value);
998
0
  }
999
0
  else if (size == 8) {
1000
0
    write64((uint64_t) value);
1001
0
  }
1002
0
  else {
1003
0
    assert(false); // unimplemented size
1004
0
  }
1005
0
}
1006
1007
1008
void StreamWriter::write(const std::string& str, bool end_with_null)
1009
0
{
1010
0
  size_t required_size = m_position + str.size() + (end_with_null ? 1 : 0);
1011
1012
0
  if (required_size > m_data.size()) {
1013
0
    m_data.resize(required_size);
1014
0
  }
1015
1016
0
  for (size_t i = 0; i < str.size(); i++) {
1017
0
    m_data[m_position++] = str[i];
1018
0
  }
1019
1020
0
  if (end_with_null) {
1021
0
    m_data[m_position++] = 0;
1022
0
  }
1023
0
}
1024
1025
1026
void StreamWriter::write_fixed_string(std::string s, size_t len)
1027
0
{
1028
0
  size_t required_size = m_position + len;
1029
1030
0
  if (required_size > m_data.size()) {
1031
0
    m_data.resize(required_size);
1032
0
  }
1033
1034
0
  size_t n_chars = std::min(s.length(), len - 1);
1035
0
  assert(n_chars <= 255);
1036
0
  m_data[m_position++] = static_cast<uint8_t>(n_chars);
1037
1038
0
  for (size_t i = 0; i < s.size() && i < len - 1; i++) {
1039
0
    m_data[m_position++] = s[i];
1040
0
  }
1041
1042
0
  for (size_t i = s.size(); i < len - 1; i++) {
1043
0
    m_data[m_position++] = 0;
1044
0
  }
1045
0
}
1046
1047
1048
void StreamWriter::write(const std::vector<uint8_t>& vec)
1049
57.1k
{
1050
57.1k
  size_t required_size = m_position + vec.size();
1051
1052
57.1k
  if (required_size > m_data.size()) {
1053
57.1k
    m_data.resize(required_size);
1054
57.1k
  }
1055
1056
57.1k
  memcpy(m_data.data() + m_position, vec.data(), vec.size());
1057
57.1k
  m_position += vec.size();
1058
57.1k
}
1059
1060
1061
void StreamWriter::write(const StreamWriter& writer)
1062
0
{
1063
0
  size_t required_size = m_position + writer.get_data().size();
1064
1065
0
  if (required_size > m_data.size()) {
1066
0
    m_data.resize(required_size);
1067
0
  }
1068
1069
0
  const auto& data = writer.get_data();
1070
1071
0
  memcpy(m_data.data() + m_position, data.data(), data.size());
1072
1073
0
  m_position += data.size();
1074
0
}
1075
1076
1077
void StreamWriter::skip(int n)
1078
64.1k
{
1079
64.1k
  assert(m_position == m_data.size());
1080
64.1k
  m_data.resize(m_data.size() + n);
1081
64.1k
  m_position += n;
1082
64.1k
}
1083
1084
1085
void StreamWriter::insert(int nBytes)
1086
0
{
1087
0
  assert(nBytes >= 0);
1088
1089
0
  if (nBytes == 0) {
1090
0
    return;
1091
0
  }
1092
1093
0
  m_data.resize(m_data.size() + nBytes);
1094
1095
0
  if (m_position < m_data.size() - nBytes) {
1096
0
    memmove(m_data.data() + m_position + nBytes,
1097
0
            m_data.data() + m_position,
1098
0
            m_data.size() - nBytes - m_position);
1099
0
  }
1100
0
}