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 
30 namespace ZenLib
31 {
32 
33 class 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 {
92 public:
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 
306 private:
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 {
690 public:
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 
705 private:
706  BitStream_Fast* Owner;
707 };
708 
710 {
711  return BitStream_Fast_Local(*this);
712 }
713 
714 #undef ZENLIB_BSF_INLINE
715 #undef ZENLIB_BSF_NOINLINE
716 
717 } //namespace ZenLib
718 #endif
#define MIN(a, b)
Definition: BitStream_Fast.h:36
#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 & operator=(const BitStream_Fast_Local &)=delete
BitStream_Fast_Local(BitStream_Fast_Local &&Other)
Definition: BitStream_Fast.h:693
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