Coverage Report

Created: 2026-09-02 06:38

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
0
#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
16.1k
    : m_length(size)
79
16.1k
{
80
16.1k
  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
16.1k
  else {
87
16.1k
    m_data = data;
88
16.1k
  }
89
16.1k
}
90
91
StreamReader_memory::~StreamReader_memory()
92
16.1k
{
93
16.1k
  if (m_owned_data) {
94
0
    delete[] m_owned_data;
95
0
  }
96
16.1k
}
97
98
uint64_t StreamReader_memory::get_position() const
99
1.05M
{
100
1.05M
  return m_position;
101
1.05M
}
102
103
StreamReader::grow_status StreamReader_memory::wait_for_file_size(uint64_t target_size)
104
930k
{
105
930k
  return (target_size > m_length) ? grow_status::size_beyond_eof : grow_status::size_reached;
106
930k
}
107
108
bool StreamReader_memory::read(void* data, size_t size)
109
56.2M
{
110
56.2M
  uint64_t end_pos = m_position + size;
111
56.2M
  if (end_pos > m_length) {
112
0
    return false;
113
0
  }
114
115
56.2M
  memcpy(data, &m_data[m_position], size);
116
56.2M
  m_position += size;
117
118
56.2M
  return true;
119
56.2M
}
120
121
bool StreamReader_memory::seek(uint64_t position)
122
105k
{
123
105k
  if (position > m_length)
124
0
    return false;
125
126
105k
  m_position = position;
127
105k
  return true;
128
105k
}
129
130
131
StreamReader_CApi::StreamReader_CApi(const heif_reader* func_table, void* userdata)
132
0
    : m_func_table(func_table), m_userdata(userdata)
133
0
{
134
0
}
135
136
StreamReader::grow_status StreamReader_CApi::wait_for_file_size(uint64_t target_size)
137
0
{
138
0
  heif_reader_grow_status status = m_func_table->wait_for_file_size(target_size, m_userdata);
139
0
  switch (status) {
140
0
    case heif_reader_grow_status_size_reached:
141
0
      return grow_status::size_reached;
142
0
    case heif_reader_grow_status_timeout:
143
0
      return grow_status::timeout;
144
0
    case heif_reader_grow_status_size_beyond_eof:
145
0
      return grow_status::size_beyond_eof;
146
0
    default:
147
0
      assert(0);
148
0
      return grow_status::size_beyond_eof;
149
0
  }
150
0
}
151
152
153
BitstreamRange::BitstreamRange(std::shared_ptr<StreamReader> istr,
154
                               size_t length,
155
                               BitstreamRange* parent)
156
480k
    : m_istr(std::move(istr)), m_parent_range(parent), m_remaining(length)
157
480k
{
158
480k
  if (parent) {
159
463k
    m_nesting_level = parent->m_nesting_level + 1;
160
463k
  }
161
480k
}
162
163
164
BitstreamRange::BitstreamRange(std::shared_ptr<StreamReader> istr,
165
                               size_t start,
166
                               size_t end) // one past end
167
0
  : m_istr(std::move(istr)), m_remaining(end - start)
168
0
{
169
0
  assert(end >= start);
170
171
0
  bool success = m_istr->seek(start);
172
0
  assert(success);
173
0
  (void)success; // TODO
174
0
}
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
19.9M
{
185
19.9M
  if (!prepare_read(1)) {
186
168k
    return 0;
187
168k
  }
188
189
19.7M
  uint8_t buf;
190
191
19.7M
  auto istr = get_istream();
192
19.7M
  bool success = istr->read((char*) &buf, 1);
193
194
19.7M
  if (!success) {
195
0
    set_eof_while_reading();
196
0
    return 0;
197
0
  }
198
199
19.7M
  return buf;
200
19.7M
}
201
202
203
uint16_t BitstreamRange::read16()
204
7.90M
{
205
7.90M
  if (!prepare_read(2)) {
206
22.0k
    return 0;
207
22.0k
  }
208
209
7.87M
  uint8_t buf[2];
210
211
7.87M
  auto istr = get_istream();
212
7.87M
  bool success = istr->read((char*) buf, 2);
213
214
7.87M
  if (!success) {
215
0
    set_eof_while_reading();
216
0
    return 0;
217
0
  }
218
219
7.87M
  return static_cast<uint16_t>((buf[0] << 8) | (buf[1]));
220
7.87M
}
221
222
223
int16_t BitstreamRange::read16s()
224
162k
{
225
162k
  uint16_t v = read16();
226
227
162k
  if (v & 0x8000) {
228
10.3k
    auto val = static_cast<int16_t>((~v) & 0x7fff);
229
10.3k
    return static_cast<int16_t>(-val - 1);
230
10.3k
  }
231
152k
  else {
232
152k
    return static_cast<int16_t>(v);
233
152k
  }
234
162k
}
235
236
237
uint32_t BitstreamRange::read24()
238
232
{
239
232
  if (!prepare_read(3)) {
240
0
    return 0;
241
0
  }
242
243
232
  uint8_t buf[3];
244
245
232
  auto istr = get_istream();
246
232
  bool success = istr->read((char*) buf, 3);
247
248
232
  if (!success) {
249
0
    set_eof_while_reading();
250
0
    return 0;
251
0
  }
252
253
232
  return (uint32_t) ((buf[0] << 16) |
254
232
                     (buf[1] << 8) |
255
232
                     (buf[2]));
256
232
}
257
258
uint32_t BitstreamRange::read32()
259
832M
{
260
832M
  if (!prepare_read(4)) {
261
828M
    return 0;
262
828M
  }
263
264
4.02M
  uint8_t buf[4];
265
266
4.02M
  auto istr = get_istream();
267
4.02M
  bool success = istr->read((char*) buf, 4);
268
269
4.02M
  if (!success) {
270
0
    set_eof_while_reading();
271
0
    return 0;
272
0
  }
273
274
4.02M
  return four_bytes_to_uint32(buf[0], buf[1], buf[2], buf[3]);
275
4.02M
}
276
277
278
uint64_t BitstreamRange::read_uint(int len)
279
1.45M
{
280
1.45M
  switch (len)
281
1.45M
  {
282
1.33M
    case 8:
283
1.33M
      return read8();
284
83.0k
    case 16:
285
83.0k
      return read16();
286
232
    case 24:
287
232
      return read24();
288
35.0k
    case 32:
289
35.0k
      return read32();
290
317
    case 64:
291
317
      return read64();
292
0
    default:
293
0
      assert(false);
294
0
      return 0;
295
1.45M
  }
296
1.45M
}
297
298
299
int32_t BitstreamRange::read32s()
300
141k
{
301
141k
  uint32_t v = read32();
302
303
141k
  if (v & 0x80000000) {
304
24.6k
    return -static_cast<int32_t>((~v) & 0x7fffffff) -1;
305
24.6k
  }
306
116k
  else {
307
116k
    return static_cast<int32_t>(v);
308
116k
  }
309
141k
}
310
311
312
uint64_t BitstreamRange::read64()
313
3.91k
{
314
3.91k
  if (!prepare_read(8)) {
315
62
    return 0;
316
62
  }
317
318
3.85k
  uint8_t buf[8];
319
320
3.85k
  auto istr = get_istream();
321
3.85k
  bool success = istr->read((char*) buf, 8);
322
323
3.85k
  if (!success) {
324
0
    set_eof_while_reading();
325
0
    return 0;
326
0
  }
327
328
3.85k
  return ((static_cast<uint64_t>(buf[0]) << 56) |
329
3.85k
          (static_cast<uint64_t>(buf[1]) << 48) |
330
3.85k
          (static_cast<uint64_t>(buf[2]) << 40) |
331
3.85k
          (static_cast<uint64_t>(buf[3]) << 32) |
332
3.85k
          (static_cast<uint64_t>(buf[4]) << 24) |
333
3.85k
          (static_cast<uint64_t>(buf[5]) << 16) |
334
3.85k
          (static_cast<uint64_t>(buf[6]) << 8) |
335
3.85k
          (static_cast<uint64_t>(buf[7])));
336
3.85k
}
337
338
339
int64_t BitstreamRange::read64s()
340
196
{
341
196
  uint64_t v = read64();
342
343
196
  if (v & 0x8000000000000000) {
344
35
    return -static_cast<int64_t >((~v) & 0x7fffffffffffffff) -1;
345
35
  }
346
161
  else {
347
161
    return static_cast<int64_t >(v);
348
161
  }
349
196
}
350
351
352
float BitstreamRange::read_float32()
353
828M
{
354
828M
#if __cpp_lib_bit_cast >= 201806L
355
828M
  uint32_t i = read32();
356
828M
  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
828M
}
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
28.1k
{
390
28.1k
  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
28.1k
  if (eof()) {
395
5.70k
    return std::string();
396
5.70k
  }
397
398
22.4k
  auto istr = get_istream();
399
400
24.3M
  for (;;) {
401
24.3M
    if (!prepare_read(1)) {
402
0
      return std::string();
403
0
    }
404
405
24.3M
    char c;
406
24.3M
    bool success = istr->read(&c, 1);
407
408
24.3M
    if (!success) {
409
0
      set_eof_while_reading();
410
0
      return std::string();
411
0
    }
412
413
24.3M
    if (c == 0 || m_remaining==0) {
414
22.4k
      break;
415
22.4k
    }
416
24.3M
    else {
417
24.3M
      str += (char) c;
418
24.3M
    }
419
24.3M
  }
420
421
22.4k
  return str;
422
22.4k
}
423
424
425
std::string BitstreamRange::read_fixed_string(int len)
426
1.18k
{
427
1.18k
  std::string str;
428
429
1.18k
  if (!prepare_read(len)) {
430
58
    return std::string();
431
58
  }
432
433
1.12k
  auto istr = get_istream();
434
435
1.12k
  uint8_t n;
436
1.12k
  bool success = istr->read(&n, 1);
437
1.12k
  if (!success || n > len - 1) {
438
404
    return {};
439
404
  }
440
441
8.24k
  for (int i = 0; i < n; i++) {
442
7.51k
    char c;
443
7.51k
    success = istr->read(&c, 1);
444
445
7.51k
    if (!success) {
446
0
      set_eof_while_reading();
447
0
      return std::string();
448
0
    }
449
450
7.51k
    str += (char) c;
451
7.51k
  }
452
453
722
  istr->seek_cur(len-n-1);
454
455
722
  return str;
456
722
}
457
458
459
std::string BitstreamRange::read_string_until_eof()
460
1.92k
{
461
1.92k
  size_t n = get_remaining_bytes();
462
463
1.92k
  [[maybe_unused]] bool success = prepare_read(n);
464
1.92k
  assert(success); // we are reading exactly the rest of the box
465
466
1.92k
  std::string str;
467
1.92k
  str.resize(n);
468
1.92k
  get_istream()->read(str.data(), n);
469
470
1.92k
  return str;
471
1.92k
}
472
473
474
bool BitstreamRange::read(uint8_t* data, size_t n)
475
167k
{
476
167k
  if (!prepare_read(n)) {
477
72
    return false;
478
72
  }
479
480
166k
  auto istr = get_istream();
481
166k
  bool success = istr->read(data, n);
482
483
166k
  if (!success) {
484
0
    set_eof_while_reading();
485
0
  }
486
487
166k
  return success;
488
167k
}
489
490
491
bool BitstreamRange::prepare_read(size_t nBytes)
492
1.22G
{
493
  // Note: we do not test for negative nBytes anymore because we now use the unsigned size_t
494
495
1.22G
  if (m_remaining < nBytes) {
496
    // --- not enough data left in box -> move to end of box and set error flag
497
498
828M
    skip_to_end_of_box();
499
500
828M
    m_error = true;
501
828M
    return false;
502
828M
  }
503
394M
  else {
504
    // --- this is the normal case (m_remaining >= nBytes)
505
506
394M
    if (m_parent_range) {
507
338M
      if (!m_parent_range->prepare_read(nBytes)) {
508
0
        return false;
509
0
      }
510
338M
    }
511
512
394M
    m_remaining -= nBytes;
513
514
394M
    return true;
515
394M
  }
516
1.22G
}
517
518
519
StreamReader::grow_status BitstreamRange::wait_for_available_bytes(size_t nBytes)
520
930k
{
521
930k
  int64_t target_size = m_istr->get_position() + nBytes;
522
523
930k
  return m_istr->wait_for_file_size(target_size);
524
930k
}
525
526
527
void BitstreamRange::skip_without_advancing_file_pos(size_t n)
528
845k
{
529
845k
  assert(n <= m_remaining);
530
531
845k
  m_remaining -= n;
532
533
845k
  if (m_parent_range) {
534
742k
    m_parent_range->skip_without_advancing_file_pos(n);
535
742k
  }
536
845k
}
537
538
539
BitReader::BitReader(const uint8_t* buffer, size_t len)
540
13.1k
  : data_start(buffer),
541
13.1k
    data_length(len)
542
13.1k
{
543
13.1k
  data = buffer;
544
13.1k
  bytes_remaining = len;
545
546
13.1k
  nextbits = 0;
547
13.1k
  nextbits_cnt = 0;
548
549
13.1k
  refill();
550
13.1k
}
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
858k
{
567
858k
  assert(n <= 32);
568
569
858k
  if (nextbits_cnt < n) {
570
102k
    refill();
571
102k
  }
572
573
858k
  uint64_t val = nextbits;
574
858k
  val >>= 64 - n;
575
576
858k
#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
858k
  nextbits &= (0xffffffffffffffffULL >> n);
579
858k
#endif
580
581
858k
  nextbits <<= n;
582
858k
  nextbits_cnt -= n;
583
584
858k
  return static_cast<uint32_t>(val);
585
858k
}
586
587
588
uint8_t BitReader::get_bits8(int n)
589
173k
{
590
173k
  assert(n>0 && n <= 8);
591
173k
  return static_cast<uint8_t>(get_bits(n));
592
173k
}
593
594
uint16_t BitReader::get_bits16(int n)
595
64.9k
{
596
64.9k
  assert(n>0 && n <= 16);
597
64.9k
  return static_cast<uint16_t>(get_bits(n));
598
64.9k
}
599
600
uint32_t BitReader::get_bits32(int n)
601
159k
{
602
159k
  assert(n>0 && n <= 32);
603
159k
  return static_cast<uint32_t>(get_bits(n));
604
159k
}
605
606
int32_t BitReader::get_bits32s()
607
6.42k
{
608
6.42k
  uint32_t bits = get_bits(32);
609
6.42k
  return static_cast<int32_t>(bits);
610
6.42k
}
611
612
613
bool BitReader::get_flag()
614
454k
{
615
454k
  return (get_bits(1) == 0x01);
616
454k
}
617
618
std::vector<uint8_t> BitReader::read_bytes(uint32_t n)
619
6.47k
{
620
  // TODO: this implementation isn't very efficient
621
6.47k
  std::vector<uint8_t> bytes;
622
85.4k
  for (uint32_t i = 0; i < n; i++) {
623
79.0k
    bytes.push_back(get_bits8(8));
624
79.0k
  }
625
6.47k
  return bytes;
626
6.47k
}
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
25.1k
{
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
25.1k
  uint64_t nBits = uint64_t{nBytes} * 8;
662
663
  // --- consume the bits that are already buffered in 'nextbits'
664
665
25.1k
  if (nextbits_cnt > 0) {
666
18.3k
    uint64_t from_buffer = std::min(nBits, static_cast<uint64_t>(nextbits_cnt));
667
668
18.3k
    if (from_buffer >= 64) {
669
47
      nextbits = 0;
670
47
    }
671
18.3k
    else {
672
18.3k
#if AVOID_FUZZER_FALSE_POSITIVE
673
18.3k
      nextbits &= (0xffffffffffffffffULL >> from_buffer);
674
18.3k
#endif
675
18.3k
      nextbits <<= from_buffer;
676
18.3k
    }
677
678
18.3k
    nextbits_cnt -= static_cast<int64_t>(from_buffer);
679
18.3k
    nBits -= from_buffer;
680
18.3k
  }
681
682
25.1k
  if (nBits == 0) {
683
17.9k
    return;
684
17.9k
  }
685
686
  // --- skip whole bytes directly in the input buffer, without pushing them
687
  //     through the bit buffer
688
689
7.21k
  uint64_t whole_bytes = nBits / 8;
690
7.21k
  int residual_bits = static_cast<int>(nBits % 8);
691
692
7.21k
  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
72
    uint64_t overshoot_bits = (whole_bytes - bytes_remaining) * 8 + static_cast<uint64_t>(residual_bits);
697
698
72
    data += bytes_remaining;
699
72
    bytes_remaining = 0;
700
72
    nextbits = 0;
701
72
    nextbits_cnt -= static_cast<int64_t>(overshoot_bits);
702
72
    return;
703
72
  }
704
705
7.13k
  data += static_cast<size_t>(whole_bytes);
706
7.13k
  bytes_remaining -= static_cast<size_t>(whole_bytes);
707
7.13k
  nextbits = 0;
708
7.13k
  nextbits_cnt = 0;
709
710
7.13k
  refill();
711
712
7.13k
  if (residual_bits > 0) {
713
0
    skip_bits(residual_bits);
714
0
  }
715
7.13k
}
716
717
void BitReader::skip_bits(int n)
718
47.5k
{
719
47.5k
  if (nextbits_cnt < n) {
720
14.7k
    refill();
721
14.7k
  }
722
723
47.5k
#if AVOID_FUZZER_FALSE_POSITIVE
724
47.5k
  nextbits &= (0xffffffffffffffffULL >> n);
725
47.5k
#endif
726
727
47.5k
  nextbits <<= n;
728
47.5k
  nextbits_cnt -= n;
729
47.5k
}
730
731
void BitReader::skip_bits_fast(int n)
732
0
{
733
0
#if AVOID_FUZZER_FALSE_POSITIVE
734
0
  nextbits &= (0xffffffffffffffffULL >> n);
735
0
#endif
736
737
0
  nextbits <<= n;
738
0
  nextbits_cnt -= n;
739
0
}
740
741
void BitReader::skip_to_byte_boundary()
742
13.1k
{
743
13.1k
  int nskip = static_cast<int>(nextbits_cnt & 7);
744
745
13.1k
#if AVOID_FUZZER_FALSE_POSITIVE
746
13.1k
  nextbits &= (0xffffffffffffffffULL >> nskip);
747
13.1k
#endif
748
749
13.1k
  nextbits <<= nskip;
750
13.1k
  nextbits_cnt -= nskip;
751
13.1k
}
752
753
bool BitReader::get_uvlc(uint32_t* value)
754
0
{
755
0
  int num_zeros = 0;
756
757
0
  while (get_bits(1) == 0) {
758
0
    num_zeros++;
759
760
0
    if (num_zeros > MAX_UVLC_LEADING_ZEROS) { return false; }
761
0
  }
762
763
0
  if (num_zeros != 0) {
764
0
    uint32_t offset = get_bits(num_zeros);
765
0
    *value = offset + (1u << num_zeros) - 1u;
766
0
    assert(*value > 0);
767
0
    return true;
768
0
  }
769
0
  else {
770
0
    *value = 0;
771
0
    return true;
772
0
  }
773
0
}
774
775
bool BitReader::get_svlc(int32_t* value)
776
0
{
777
0
  uint32_t v;
778
0
  if (!get_uvlc(&v)) {
779
0
    return false;
780
0
  }
781
0
  else if (v == 0) {
782
0
    *value = 0;
783
0
    return true;
784
0
  }
785
786
0
  bool negative = ((v & 1u) == 0);
787
0
  *value = negative ? -static_cast<int32_t>(v / 2) : static_cast<int32_t>((v + 1) / 2);
788
0
  return true;
789
0
}
790
791
void BitReader::refill()
792
137k
{
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
137k
  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
4.20k
    return;
808
4.20k
  }
809
810
132k
  int64_t shift = 64 - nextbits_cnt;
811
812
969k
  while (shift >= 8 && bytes_remaining) {
813
836k
    uint64_t newval = *data++;
814
836k
    bytes_remaining--;
815
816
836k
    shift -= 8;
817
836k
    newval <<= shift;
818
836k
    nextbits |= newval;
819
836k
  }
820
821
132k
  nextbits_cnt = 64 - shift;
822
132k
#endif
823
132k
}
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
0
{
879
0
  if (m_position == m_data.size()) {
880
0
    m_data.push_back(v);
881
0
    m_position++;
882
0
  }
883
0
  else {
884
0
    m_data[m_position++] = v;
885
0
  }
886
0
}
887
888
889
void StreamWriter::write16(uint16_t v)
890
0
{
891
0
  size_t required_size = m_position + 2;
892
893
0
  if (required_size > m_data.size()) {
894
0
    m_data.resize(required_size);
895
0
  }
896
897
0
  m_data[m_position++] = uint8_t((v >> 8) & 0xFF);
898
0
  m_data[m_position++] = uint8_t(v & 0xFF);
899
0
}
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
0
{
933
0
  size_t required_size = m_position + 4;
934
935
0
  if (required_size > m_data.size()) {
936
0
    m_data.resize(required_size);
937
0
  }
938
939
0
  m_data[m_position++] = uint8_t((v >> 24) & 0xFF);
940
0
  m_data[m_position++] = uint8_t((v >> 16) & 0xFF);
941
0
  m_data[m_position++] = uint8_t((v >> 8) & 0xFF);
942
0
  m_data[m_position++] = uint8_t(v & 0xFF);
943
0
}
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
0
{
1050
0
  size_t required_size = m_position + vec.size();
1051
1052
0
  if (required_size > m_data.size()) {
1053
0
    m_data.resize(required_size);
1054
0
  }
1055
1056
0
  memcpy(m_data.data() + m_position, vec.data(), vec.size());
1057
0
  m_position += vec.size();
1058
0
}
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
0
{
1079
0
  assert(m_position == m_data.size());
1080
0
  m_data.resize(m_data.size() + n);
1081
0
  m_position += n;
1082
0
}
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
}