ZenLib
BitStream_Fast.h
Go to the documentation of this file.
1/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
2 *
3 * Use of this source code is governed by a zlib-style license that can
4 * be found in the License.txt file in the root of the source tree.
5 */
6
7//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8//
9// Read a stream bit per bit
10// Can read up to 32 bits at once (64 bits with Get8 and Peek8)
11//
12//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13
14//---------------------------------------------------------------------------
15#ifndef ZenBitStream_FastH
16#define ZenBitStream_FastH
17//---------------------------------------------------------------------------
18
19//---------------------------------------------------------------------------
20#include "ZenLib/Conf.h"
21//---------------------------------------------------------------------------
22
23#include <cstddef>
24#include <cstring>
25#if defined(_MSC_VER)
26 #include <stdlib.h>
27 #include <intrin.h>
28#endif
29
30namespace ZenLib
31{
32
33class BitStream_Fast_Local;
34
35#ifndef MIN
36 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
37#endif
38
39#if defined(_MSC_VER)
40 #define ZENLIB_BSF_INLINE __forceinline
41 #define ZENLIB_BSF_NOINLINE __declspec(noinline)
42#elif defined(__GNUC__) || defined(__clang__)
43 #define ZENLIB_BSF_INLINE inline __attribute__((always_inline))
44 #define ZENLIB_BSF_NOINLINE __attribute__((noinline))
45#else
46 #define ZENLIB_BSF_INLINE inline
47 #define ZENLIB_BSF_NOINLINE
48#endif
49
50//***************************************************************************
51// BitStream_Fast
52//***************************************************************************
53//
54// Design: the position is the count of remaining bits, Buffer_Size. Window
55// holds one native big-endian word of the stream, loaded by Attach(),
56// Resize() and Refresh(), then when a read goes past its usable bits. A read
57// checks that its bits are in Window, decrements Buffer_Size and extracts
58// them with one rotation and a mask: the position is the only state written
59// by reads, and Skip() is a subtraction.
60//
61// Window is rotated at load time so that the bit read when Buffer_Size is B
62// is its bit (B-1)%WordBits: after a read of n bits decremented Buffer_Size,
63// the bits are the n low bits of Window rotated right by Buffer_Size. Reads
64// only need, in addition to Buffer_Size:
65// - WindowEnd: Buffer_Size value after the last usable bit of Window, never
66// beyond the logical end. A read of n bits can use Window iff
67// n+WindowEnd<=Buffer_Size, which also implies n<=Remain().
68// - The position is never before Window: Window is loaded at or before the
69// position, so the usable bits never wrap around. A position beyond Window
70// (after Skip()) just fails the usability check.
71// A reload at byte Position/8 gives at least WordBits-7 usable bits, or all
72// the remaining bits when the word is moved back to end at the last readable
73// byte. While Buffer_Size is 0, every read fails the usability check.
74// Get8(), Get8_Unchecked() and Peek8() parts not in Window, and peeks wider
75// than a fresh Window (32-bit words), use their own word load at the position,
76// Window unchanged.
77//
78// Underrun: Remain() becomes 0 and the logical end moves to the position,
79// which is preserved for a growing Resize(); BufferUnderRun() thus implies
80// Remain()==0.
81//
82// Memory safety: loads never go before Buffer or beyond the logical end plus
83// the declared ExtraBytesAvailable_ reserve, the reserve keeping its Attach()
84// time end. Near the end, the word is loaded so that it ends at the last
85// readable byte. If fewer bytes than a word are
86// readable (logical size plus reserve), they are copied entirely into Window,
87// zero padded, and never need another load: WindowEnd is then 0 and Reload()
88// is never called.
89//
91{
92public:
94 // ExtraBytesAvailable_ is the number of initialized, readable bytes after
95 // Buffer_+Size_, excluded from Size_ and Remain(); readable bytes must not
96 // be modified while attached, except bytes not read yet followed by a call
97 // to Refresh(). Zero requires no extra storage beyond the
98 // logical buffer. The reserve is not moved by Resize(): loads stay before
99 // Buffer_+Size_+ExtraBytesAvailable_, or before the logical end if a
100 // growing Resize() moved it further.
101 BitStream_Fast (const int8u* Buffer_, size_t Size_, size_t ExtraBytesAvailable_=0) { Attach(Buffer_, Size_, ExtraBytesAvailable_); }
103
104 // Same extra-byte contract as the constructor; omitted means zero.
105 ZENLIB_BSF_INLINE void Attach(const int8u* Buffer_, size_t Size_, size_t ExtraBytesAvailable_=0)
106 {
107 Buffer=Buffer_;
108 Buffer_Size=Buffer_Size_Init=BitEnd=Size_*8;
109 // A reserve of one word minus one byte is enough for any load
110 ExtraBytes=(int8u)MIN(ExtraBytesAvailable_, sizeof(Word)-1);
111 BufferUnderRun_=false;
112 Fill();
113 }
114
115 //***********************************************************************
116 // Reads
117 //***********************************************************************
118
120 {
121 if (Buffer_Size<=WindowEnd)
122 {
123 if (!Buffer_Size)
124 {
125 UnderRun();
126 return false;
127 }
128 Reload();
129 }
130 Buffer_Size--;
131 return TestBit(Window, Buffer_Size);
132 }
133
134 ZENLIB_BSF_INLINE int8u Get1(int8u HowMany)
135 {
136 return (int8u)Get<8>(HowMany);
137 }
138
139 ZENLIB_BSF_INLINE int16u Get2(int8u HowMany)
140 {
141 return (int16u)Get<16>(HowMany);
142 }
143
144 ZENLIB_BSF_INLINE int32u Get4(int8u HowMany)
145 {
146 return (int32u)Get<32>(HowMany);
147 }
148
149 ZENLIB_BSF_INLINE int64u Get8(int8u HowMany)
150 {
151 if (HowMany<=32)
152 return Get<32>(HowMany);
153 if (HowMany>64)
154 return 0;
155 if (HowMany>Buffer_Size)
156 {
157 // Historical behavior: the high part is consumed if it is available
158 if ((size_t)(HowMany-32)<=Buffer_Size)
159 Buffer_Size-=HowMany-32;
160 UnderRun();
161 return 0;
162 }
163 return Read64(HowMany);
164 }
165
166 // Preconditions: 1 <= HowMany <= 32 and Remain() >= HowMany.
167 ZENLIB_BSF_INLINE int32u Get4_Unchecked(int8u HowMany)
168 {
169 return (int32u)Read<32>(HowMany);
170 }
171
172 // Preconditions: 1 <= HowMany <= 64 and Remain() >= HowMany.
173 ZENLIB_BSF_INLINE int64u Get8_Unchecked(int8u HowMany)
174 {
175 return Read64(HowMany);
176 }
177
178 // Exp-Golomb ue(v), up to 31 leading zero bits (values up to 2^32-2).
179 // Returns 0 if the code is longer or truncated; the buffer is then
180 // considered as exhausted (Remain() is 0 and BufferUnderRun() is set), so
181 // BufferUnderRun() right after the call tells an error from a valid 0.
183 {
184 Word Bits;
185 unsigned Size;
186 if (!PeekUE(Bits, Size))
187 return GetUE_Slow();
188 Buffer_Size-=Size;
189 return (int32u)(Bits>>(WordBits-Size))-1;
190 }
191
192 // Exp-Golomb se(v). Returns 0 on error, see GetUE().
194 {
195 const int32u CodeNum=GetUE();
196 return (int32s)((CodeNum&1)?(CodeNum>>1)+1:0u-(CodeNum>>1));
197 }
198
199 // Sticky error state; cleared by Attach() or by growing Resize().
200 bool BufferUnderRun() const { return BufferUnderRun_; }
201
203
204 ZENLIB_BSF_INLINE void Skip(size_t HowMany)
205 {
206 if (HowMany>Buffer_Size)
207 {
208 UnderRun();
209 return;
210 }
211 Buffer_Size-=HowMany;
212 }
213
215 {
216 if (Buffer_Size<=WindowEnd)
217 {
218 if (!Buffer_Size)
219 {
220 UnderRun();
221 return false;
222 }
223 Reload();
224 }
225 return TestBit(Window, Buffer_Size-1);
226 }
227
228 ZENLIB_BSF_INLINE int8u Peek1(int8u HowMany)
229 {
230 return (int8u)Peek<8>(HowMany);
231 }
232
233 ZENLIB_BSF_INLINE int16u Peek2(int8u HowMany)
234 {
235 return (int16u)Peek<16>(HowMany);
236 }
237
238 ZENLIB_BSF_INLINE int32u Peek4(int8u HowMany)
239 {
240 return (int32u)Peek<32>(HowMany);
241 }
242
243 int64u Peek8(int8u HowMany)
244 {
245 if (HowMany<=32)
246 return Peek<32>(HowMany);
247 if (HowMany>64)
248 return 0;
249 if (HowMany>Buffer_Size)
250 {
251 UnderRun();
252 return 0;
253 }
254 if (HowMany<=WordBits)
255 return PeekWide(Buffer_Size, HowMany);
256 // 32-bit words: high part, then the 32 bits after it
257 const int64u High=PeekWide(Buffer_Size, HowMany-32);
258 return (High<<32)|PeekWide(Buffer_Size-(HowMany-32), 32);
259 }
260
261 inline size_t Remain() const
262 {
263 return Buffer_Size;
264 }
265
266 inline void Byte_Align()
267 {
268 Buffer_Size&=~(size_t)7;
269 }
270
271 inline size_t Offset_Get() const
272 {
273 return (Buffer_Size_Init-Buffer_Size)/8;
274 }
275
276 inline size_t BitOffset_Get() const
277 {
278 return Buffer_Size%8;
279 }
280
281 inline size_t OffsetBeforeLastCall_Get() const //No more valid
282 {
283 return Buffer_Size%8;
284 }
285
286 // Size_ is the new count of remaining bits: the position is kept, only the logical end
287 // moves, to the position plus Size_ bits (this sum must fit in a size_t). Beyond the
288 // attached size, the bytes up to the new logical end must be readable, see Attach().
289 inline void Resize(size_t Size_)
290 {
291 if (BufferUnderRun_ && Size_>Buffer_Size)
292 BufferUnderRun_=false;
293 BitEnd=BitEnd-Buffer_Size+Size_;
294 Buffer_Size=Size_;
295 Fill();
296 }
297
298 // Loads Window again from the attached bytes at the position: needed after
299 // modifying bytes not read yet (for example a descrambling in place), as
300 // Window may already contain them. The position and the state are kept.
301 inline void Refresh()
302 {
303 Fill();
304 }
305
306private:
307 typedef size_t Word;
308 enum { WordBits=sizeof(Word)*8 };
309
310 //***********************************************************************
311 // Word helpers
312 //***********************************************************************
313
314 static ZENLIB_BSF_INLINE Word LoadWord(const int8u* Source)
315 {
316 Word Value;
317 std::memcpy(&Value, Source, sizeof(Value));
318 #if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
319 return Value;
320 #elif defined(_MSC_VER)
321 #if defined(_WIN64)
322 return _byteswap_uint64(Value);
323 #else
324 return _byteswap_ulong(Value);
325 #endif
326 #elif (defined(__GNUC__) || defined(__clang__)) && defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
327 return sizeof(Word)==8?(Word)__builtin_bswap64((int64u)Value):(Word)__builtin_bswap32((int32u)Value);
328 #else
329 // Unknown byte order
330 Word Result=0;
331 for (size_t i=0; i<sizeof(Word); i++)
332 Result=(Result<<8)|Source[i];
333 return Result;
334 #endif
335 }
336
337 // Big-endian value of Size bytes (Size<sizeof(Word)), left aligned, zero padded
338 static ZENLIB_BSF_NOINLINE Word LoadPartial(const int8u* Source, size_t Size)
339 {
340 Word Value=0;
341 for (size_t i=0; i<Size; i++)
342 Value|=(Word)Source[i]<<(WordBits-8-8*i);
343 return Value;
344 }
345
346 static ZENLIB_BSF_INLINE unsigned CountLeadingZeros(Word Value) //Value!=0
347 {
348 #if defined(_MSC_VER)
349 unsigned long Index;
350 #if defined(_WIN64)
351 _BitScanReverse64(&Index, Value);
352 #else
353 _BitScanReverse(&Index, Value);
354 #endif
355 return (unsigned)(WordBits-1-Index);
356 #elif defined(__GNUC__) || defined(__clang__)
357 return sizeof(Word)==8?(unsigned)__builtin_clzll((unsigned long long)Value):(unsigned)__builtin_clz((unsigned)Value);
358 #else
359 unsigned Count=0;
360 while (!(Value>>(WordBits-1))) { Value<<=1; Count++; }
361 return Count;
362 #endif
363 }
364
365 // Mask of the HowMany low bits, 0 <= HowMany <= WordBits
366 static ZENLIB_BSF_INLINE Word Mask(unsigned HowMany)
367 {
368 // A table avoids a variable shift when HowMany is not a constant.
369 // 64-bit entries for any word size: with 32-bit words, only the first 33 are used.
370 #define ZENLIB_BSF_MASK4(N) ((int64u)1<<(N))-1, ((int64u)2<<(N))-1, ((int64u)4<<(N))-1, ((int64u)8<<(N))-1
371 static const int64u Masks[65]=
372 {
377 (int64u)-1,
378 };
379 #undef ZENLIB_BSF_MASK4
380 return (Word)Masks[HowMany];
381 }
382
383 // Value rotated right by Count%WordBits bits
384 static ZENLIB_BSF_INLINE Word RotateRight(Word Value, size_t Count)
385 {
386 #if defined(_MSC_VER) && !defined(__clang__)
387 // The instruction masks the count
388 #if defined(_WIN64)
389 return _rotr64(Value, (int)Count);
390 #else
391 return _rotr(Value, (int)Count);
392 #endif
393 #else
394 const unsigned Shift=(unsigned)(Count&(WordBits-1));
395 return (Value>>Shift)|(Value<<((WordBits-Shift)&(WordBits-1))); // Recognized as a rotation
396 #endif
397 }
398
399 // Bit Index%WordBits of Value, 0 being the least significant bit
400 static ZENLIB_BSF_INLINE bool TestBit(Word Value, size_t Index)
401 {
402 // Both forms let the instruction mask the index: a rotation with MSVC,
403 // a bit test or a shift with GCC and Clang
404 #if defined(_MSC_VER) && !defined(__clang__)
405 return (RotateRight(Value, Index)&1)!=0;
406 #else
407 return ((Value>>(Index&(WordBits-1)))&1)!=0;
408 #endif
409 }
410
411 //***********************************************************************
412 // Window management
413 //***********************************************************************
414
415 // Loads Window at byte Position/8, or at the last loadable byte offset.
416 // Precondition: a full word is readable (LastLoad is valid), which is the case if WindowEnd>0.
417 ZENLIB_BSF_INLINE void Reload()
418 {
419 size_t Load=(BitEnd-Buffer_Size)/8;
420 if (Load>LastLoad)
421 Load=LastLoad; // Near the end, the word ends at the last readable byte
422 // Bits from the word start to the logical end, then Buffer_Size value at the least
423 // significant bit of the word (wraps around if the word ends after the logical end).
424 // Unsigned comparison: with 32-bit words, Avail may be 2^31 or more.
425 const size_t Avail=BitEnd-Load*8;
426 const size_t WindowLow=Avail-WordBits;
427 Window=RotateRight(LoadWord(Buffer+Load), 0-WindowLow);
428 WindowEnd=Avail>WordBits?WindowLow:0;
429 }
430
431 // Computes the load limit for the current logical end then loads Window, any buffer size
432 ZENLIB_BSF_INLINE void Fill()
433 {
434 // Readable bytes since Buffer: the logical ones, then the reserve, trusted
435 // only up to its end at Attach() time, as a growing Resize() may move the
436 // logical end beyond the attached size
437 const size_t Logical=BitEnd/8+(BitEnd%8!=0); // No overflow after any Resize()
438 const size_t Attached=Buffer_Size_Init/8+ExtraBytes;
439 size_t Readable=Logical+ExtraBytes;
440 if (Readable>Attached)
441 Readable=Logical>Attached?Logical:Attached;
442 if (Readable>=sizeof(Word))
443 {
444 LastLoad=Readable-sizeof(Word);
445 if (Buffer_Size)
446 {
447 Reload();
448 return;
449 }
450 }
451 else
452 {
453 LastLoad=0; // Never used: Window contains the whole buffer
454 if (Buffer_Size)
455 {
456 Window=RotateRight(LoadPartial(Buffer, Readable), WordBits-BitEnd);
457 WindowEnd=0;
458 return;
459 }
460 }
461
462 // Nothing to read, nothing to load: every read fails the usability check
463 Window=0;
464 WindowEnd=0;
465 }
466
467 ZENLIB_BSF_INLINE void UnderRun()
468 {
469 // The logical end moves to the position, which is kept for a growing Resize()
470 BitEnd-=Buffer_Size;
471 Buffer_Size=0;
472 WindowEnd=0;
473 BufferUnderRun_=true;
474 }
475
476 //***********************************************************************
477 // Reads
478 //***********************************************************************
479
480 template <int Max>
481 ZENLIB_BSF_INLINE Word Get(int8u HowMany)
482 {
483 // Rejects 0 and HowMany>Max with a single comparison
484 if ((unsigned)(HowMany-1)>=(unsigned)Max)
485 return 0;
486 return Read<Max>(HowMany);
487 }
488
489 template <int Max>
490 ZENLIB_BSF_INLINE Word Peek(int8u HowMany)
491 {
492 if ((unsigned)(HowMany-1)>=(unsigned)Max)
493 return 0;
494 if (HowMany+WindowEnd>Buffer_Size)
495 {
496 if (HowMany>Buffer_Size)
497 {
498 UnderRun();
499 return 0;
500 }
501 Reload();
502 // A fresh Window has at least WordBits-7 usable bits
503 if (Max>WordBits-7 && HowMany+WindowEnd>Buffer_Size)
504 return PeekDirect(Buffer_Size, HowMany);
505 }
506 return RotateRight(Window, Buffer_Size-HowMany)&Mask(HowMany);
507 }
508
509 // Preconditions: 1 <= HowMany <= Max <= WordBits (if HowMany>Remain(): underrun)
510 template <int Max>
511 ZENLIB_BSF_INLINE Word Read(unsigned HowMany)
512 {
513 if (HowMany+WindowEnd>Buffer_Size)
514 {
515 if (HowMany>Buffer_Size)
516 {
517 UnderRun();
518 return 0;
519 }
520 Reload();
521 // A fresh Window has at least WordBits-7 usable bits
522 if (Max>WordBits-7 && HowMany+WindowEnd>Buffer_Size)
523 return Read_Split(HowMany);
524 }
525 Buffer_Size-=HowMany;
526 return RotateRight(Window, Buffer_Size)&Mask(HowMany);
527 }
528
529 // Read wider than the usable bits of a fresh Window (32-bit words only): the high
530 // part from Window, which is then reloaded at the position of the low part
531 ZENLIB_BSF_NOINLINE Word Read_Split(unsigned HowMany)
532 {
533 const unsigned High_Size=(unsigned)(Buffer_Size-WindowEnd);
534 Buffer_Size-=High_Size;
535 const Word High=RotateRight(Window, Buffer_Size)&Mask(High_Size);
536 Reload();
537 const unsigned Low_Size=HowMany-High_Size;
538 Buffer_Size-=Low_Size;
539 return (High<<Low_Size)|(RotateRight(Window, Buffer_Size)&Mask(Low_Size));
540 }
541
542 // Preconditions: 1 <= HowMany <= 64 (if HowMany>Remain(): underrun)
543 ZENLIB_BSF_INLINE int64u Read64(unsigned HowMany)
544 {
545 if (HowMany<=WordBits)
546 return ReadWide(HowMany);
547 const int64u High=ReadWide(HowMany-32);
548 return (High<<32)|ReadWide(32);
549 }
550
551 // A wide read would consume most of a reloaded Window: it uses its own load instead.
552 // Preconditions: 1 <= HowMany <= WordBits (if HowMany>Remain(): underrun)
553 ZENLIB_BSF_INLINE Word ReadWide(unsigned HowMany)
554 {
555 Word Value;
556 if (HowMany+WindowEnd<=Buffer_Size)
557 Value=RotateRight(Window, Buffer_Size-HowMany)&Mask(HowMany);
558 else if (HowMany<=Buffer_Size)
559 Value=PeekDirect(Buffer_Size, HowMany);
560 else
561 {
562 UnderRun();
563 return 0;
564 }
565 Buffer_Size-=HowMany;
566 return Value;
567 }
568
569 // HowMany bits at the position where Remain() would be Remaining, no state change.
570 // Preconditions: 1 <= HowMany <= WordBits and HowMany <= Remaining <= Remain(),
571 // so that the position is not before Window.
572 ZENLIB_BSF_INLINE Word PeekWide(size_t Remaining, unsigned HowMany) const
573 {
574 if (HowMany+WindowEnd<=Remaining)
575 return RotateRight(Window, Remaining-HowMany)&Mask(HowMany);
576 return PeekDirect(Remaining, HowMany);
577 }
578
579 // HowMany bits at the position where Remain() would be Remaining, from their own
580 // word load, Window unchanged.
581 // Preconditions: 1 <= HowMany <= WordBits, HowMany <= Remaining <= Remain() and the
582 // bits are not all in Window (so a full word is readable).
583 ZENLIB_BSF_INLINE Word PeekDirect(size_t Remaining, unsigned HowMany) const
584 {
585 const size_t BitPos=BitEnd-Remaining;
586 size_t Load=BitPos/8;
587 if (Load>LastLoad)
588 Load=LastLoad; // The word then contains all the remaining bits
589 const unsigned Shift=(unsigned)(BitPos-Load*8);
590 Word Value=LoadWord(Buffer+Load)<<Shift;
591 if (Shift+HowMany>WordBits)
592 Value|=(Word)(Buffer[Load+sizeof(Word)]>>(8-Shift)); // Not clamped, before the logical end
593 return Value>>(WordBits-HowMany);
594 }
595
596 //***********************************************************************
597 // Exp-Golomb
598 //***********************************************************************
599
600 // Exp-Golomb code inside Window: bits from the position, left aligned, and code size
601 ZENLIB_BSF_INLINE bool PeekUE(Word& Bits, unsigned& Size) const
602 {
603 if (Buffer_Size<=WindowEnd)
604 return false;
605 Bits=RotateRight(Window, Buffer_Size); // Next bit at the top, then the usable bits
606 if (!Bits)
607 return false;
608 // The whole code must be in the usable bits, so it is valid even if the
609 // leading one was found in the bits wrapped around after them.
610 // Size<=WordBits-1, so at most 31 leading zero bits on 64-bit.
611 Size=CountLeadingZeros(Bits)*2+1;
612 return Size<=Buffer_Size-WindowEnd; // Size+WindowEnd could overflow
613 }
614
615 // Exp-Golomb code not inside Window
616 ZENLIB_BSF_NOINLINE int32u GetUE_Slow()
617 {
618 // Reload if bits after Window are readable, else the code is long, truncated or invalid
619 Word Bits;
620 unsigned Size;
621 if (WindowEnd)
622 {
623 Reload();
624 if (PeekUE(Bits, Size))
625 {
626 Buffer_Size-=Size;
627 return (int32u)(Bits>>(WordBits-Size))-1;
628 }
629 }
630 if (Buffer_Size)
631 {
632 const int64u Result=GetUE_Bytes(Buffer, BitEnd-Buffer_Size, Buffer_Size);
633 const size_t Code_Size=(size_t)(Result>>32);
634 if (Code_Size)
635 {
636 Buffer_Size-=Code_Size; // The next read reloads Window if needed
637 return (int32u)Result;
638 }
639 }
640 UnderRun();
641 return 0;
642 }
643
644 // Exp-Golomb code read byte per byte, for codes not fitting in a fresh Window.
645 // Returns the code size (0 on error) in the high 32 bits, the value in the low 32 bits.
646 static ZENLIB_BSF_NOINLINE int64u GetUE_Bytes(const int8u* Buffer, size_t BitPos, size_t Remain)
647 {
648 const unsigned Peeked=(unsigned)MIN(Remain, (size_t)32);
649 const int32u Prefix=ReadBytes(Buffer, BitPos, Peeked)<<(32-Peeked);
650 if (!Prefix)
651 return 0; // More than 31 leading zero bits, or truncated
652 unsigned LeadingZeroBits=0;
653 while (!(Prefix>>(31-LeadingZeroBits)))
654 LeadingZeroBits++;
655 if (LeadingZeroBits*2+1>Remain)
656 return 0; // Truncated
657 const int32u Info=LeadingZeroBits?ReadBytes(Buffer, BitPos+LeadingZeroBits+1, LeadingZeroBits):0;
658 return ((int64u)(LeadingZeroBits*2+1)<<32)|((((int32u)1<<LeadingZeroBits)|Info)-1);
659 }
660
661 // HowMany bits (1 to 32) at BitPos, reading only the bytes containing them
662 static int32u ReadBytes(const int8u* Buffer, size_t BitPos, unsigned HowMany)
663 {
664 const int8u* Source=Buffer+BitPos/8;
665 const unsigned Skipped=(unsigned)(BitPos%8);
666 const unsigned Bytes=(Skipped+HowMany+7)/8;
667 int64u Value=0;
668 for (unsigned i=0; i<Bytes; i++)
669 Value=(Value<<8)|Source[i];
670 return (int32u)((Value>>(Bytes*8-Skipped-HowMany))&(((int64u)1<<HowMany)-1));
671 }
672
673 // Hot state, see the class comment
674 Word Window;
675 size_t Buffer_Size; // Remaining bits
676 size_t WindowEnd;
677 // Cold state, used when Window is (re)loaded
678 const int8u* Buffer;
679 size_t BitEnd; // Logical end, in bits since Buffer
680 size_t LastLoad; // Last byte offset where a full word can be loaded
681 size_t Buffer_Size_Init;
682 int8u ExtraBytes;
683 bool BufferUnderRun_;
684};
685
686// Independent parsing state: changes become visible in the owner only at Commit().
687// The owner must outlive the session and must not be modified before Commit().
689{
690public:
692 : BitStream_Fast(Owner_), Owner(&Owner_) {}
694 : BitStream_Fast(Other), Owner(Other.Owner) { Other.Owner=NULL; }
697
698 // Explicit commit permits speculative parsing; destruction discards changes.
699 void Commit()
700 {
701 if (Owner)
702 *Owner=static_cast<const BitStream_Fast&>(*this);
703 }
704
705private:
706 BitStream_Fast* Owner;
707};
708
713
714#undef ZENLIB_BSF_INLINE
715#undef ZENLIB_BSF_NOINLINE
716
717} //namespace ZenLib
718#endif
#define MIN(a, b)
Definition BitStream.h:27
#define ZENLIB_BSF_MASK4(N)
#define ZENLIB_BSF_INLINE
Definition BitStream_Fast.h:46
#define ZENLIB_BSF_NOINLINE
Definition BitStream_Fast.h:47
#define NULL
Definition HTTPClientWrapper.h:98
Definition BitStream_Fast.h:689
void Commit()
Definition BitStream_Fast.h:699
BitStream_Fast_Local(BitStream_Fast_Local &&Other)
Definition BitStream_Fast.h:693
BitStream_Fast_Local & operator=(const BitStream_Fast_Local &)=delete
BitStream_Fast_Local(const BitStream_Fast_Local &)=delete
BitStream_Fast_Local(BitStream_Fast &Owner_)
Definition BitStream_Fast.h:691
Definition BitStream_Fast.h:91
ZENLIB_BSF_INLINE int32u GetUE()
Definition BitStream_Fast.h:182
ZENLIB_BSF_INLINE int32u Get4_Unchecked(int8u HowMany)
Definition BitStream_Fast.h:167
ZENLIB_BSF_INLINE int32s GetSE()
Definition BitStream_Fast.h:193
ZENLIB_BSF_INLINE void Skip(size_t HowMany)
Definition BitStream_Fast.h:204
ZENLIB_BSF_INLINE bool GetB()
Definition BitStream_Fast.h:119
BitStream_Fast(const int8u *Buffer_, size_t Size_, size_t ExtraBytesAvailable_=0)
Definition BitStream_Fast.h:101
ZENLIB_BSF_INLINE int8u Get1(int8u HowMany)
Definition BitStream_Fast.h:134
ZENLIB_BSF_INLINE int64u Get8(int8u HowMany)
Definition BitStream_Fast.h:149
void Refresh()
Definition BitStream_Fast.h:301
size_t OffsetBeforeLastCall_Get() const
Definition BitStream_Fast.h:281
ZENLIB_BSF_INLINE void Attach(const int8u *Buffer_, size_t Size_, size_t ExtraBytesAvailable_=0)
Definition BitStream_Fast.h:105
bool BufferUnderRun() const
Definition BitStream_Fast.h:200
size_t BitOffset_Get() const
Definition BitStream_Fast.h:276
ZENLIB_BSF_INLINE int64u Get8_Unchecked(int8u HowMany)
Definition BitStream_Fast.h:173
void Resize(size_t Size_)
Definition BitStream_Fast.h:289
ZENLIB_BSF_INLINE int16u Get2(int8u HowMany)
Definition BitStream_Fast.h:139
BitStream_Fast_Local LocalReader()
Definition BitStream_Fast.h:709
~BitStream_Fast()
Definition BitStream_Fast.h:102
size_t Offset_Get() const
Definition BitStream_Fast.h:271
int64u Peek8(int8u HowMany)
Definition BitStream_Fast.h:243
ZENLIB_BSF_INLINE bool PeekB()
Definition BitStream_Fast.h:214
ZENLIB_BSF_INLINE int32u Peek4(int8u HowMany)
Definition BitStream_Fast.h:238
void Byte_Align()
Definition BitStream_Fast.h:266
ZENLIB_BSF_INLINE int32u Get4(int8u HowMany)
Definition BitStream_Fast.h:144
BitStream_Fast()
Definition BitStream_Fast.h:93
ZENLIB_BSF_INLINE int8u Peek1(int8u HowMany)
Definition BitStream_Fast.h:228
size_t Remain() const
Definition BitStream_Fast.h:261
ZENLIB_BSF_INLINE int16u Peek2(int8u HowMany)
Definition BitStream_Fast.h:233
Definition BitStream.h:24