@@ -169,52 +169,56 @@ inline void write_little_endian(std::ostream& stream, const IntType* values, std
169169 write_little_endian<IntType>(stream, values[i]);
170170}
171171
172-
173172// Read N signed integers from the stream s, putting them in the array out.
174173// The stream is assumed to be compressed using the signed LEB128 format.
175174// See https://en.wikipedia.org/wiki/LEB128 for a description of the compression scheme.
176- template <typename IntType, std::size_t Count>
177- inline void read_leb_128 (std::istream& stream, std::array<IntType, Count>& out) {
178-
179- // Check the presence of our LEB128 magic string
180- char leb128MagicString[Leb128MagicStringSize];
181- stream.read (leb128MagicString, Leb128MagicStringSize);
182- assert (strncmp (Leb128MagicString, leb128MagicString, Leb128MagicStringSize) == 0 );
175+ template <typename BufType, typename IntType, std::size_t Count>
176+ inline void read_leb_128_detail (std::istream& stream,
177+ std::array<IntType, Count>& out,
178+ std::uint32_t & bytes_left,
179+ BufType& buf,
180+ std::uint32_t & buf_pos) {
183181
184182 static_assert (std::is_signed_v<IntType>, " Not implemented for unsigned types" );
183+ static_assert (sizeof (IntType) <= 4 , " Not implemented for types larger than 32 bit" );
185184
186- const std::uint32_t BUF_SIZE = 4096 ;
187- std::uint8_t buf[BUF_SIZE];
188-
189- auto bytes_left = read_little_endian<std::uint32_t >(stream);
190-
191- std::uint32_t buf_pos = BUF_SIZE;
192- for (std::size_t i = 0 ; i < Count; ++i)
185+ IntType result = 0 ;
186+ size_t shift = 0 , i = 0 ;
187+ while (i < Count)
193188 {
194- IntType result = 0 ;
195- size_t shift = 0 ;
196- do
189+ if (buf_pos == buf.size ())
197190 {
198- if (buf_pos == BUF_SIZE)
199- {
200- stream.read (reinterpret_cast <char *>(buf), std::min (bytes_left, BUF_SIZE));
201- buf_pos = 0 ;
202- }
191+ stream.read (reinterpret_cast <char *>(buf.data ()),
192+ std::min (std::size_t (bytes_left), buf.size ()));
193+ buf_pos = 0 ;
194+ }
203195
204- std::uint8_t byte = buf[buf_pos++];
205- --bytes_left;
206- result |= (byte & 0x7f ) << shift;
207- shift += 7 ;
196+ std::uint8_t byte = buf[buf_pos++];
197+ --bytes_left;
198+ result |= (byte & 0x7f ) << ( shift % 32 ) ;
199+ shift += 7 ;
208200
209- if ((byte & 0x80 ) == 0 )
210- {
211- out[i] = (sizeof (IntType) * 8 <= shift || (byte & 0x40 ) == 0 )
212- ? result
213- : result | ~((1 << shift) - 1 );
214- break ;
215- }
216- } while (shift < sizeof (IntType) * 8 );
201+ if ((byte & 0x80 ) == 0 )
202+ {
203+ out[i++] = (shift >= 32 || (byte & 0x40 ) == 0 ) ? result : result | ~((1 << shift) - 1 );
204+ result = 0 ;
205+ shift = 0 ;
206+ }
217207 }
208+ }
209+
210+ template <typename ... Arrays>
211+ inline void read_leb_128 (std::istream& stream, Arrays&... outs) {
212+ // Check the presence of our LEB128 magic string
213+ char leb128MagicString[Leb128MagicStringSize];
214+ stream.read (leb128MagicString, Leb128MagicStringSize);
215+ assert (strncmp (Leb128MagicString, leb128MagicString, Leb128MagicStringSize) == 0 );
216+
217+ auto bytes_left = read_little_endian<std::uint32_t >(stream);
218+ std::array<std::uint8_t , 8192 > buf;
219+ std::uint32_t buf_pos = buf.size ();
220+
221+ (read_leb_128_detail (stream, outs, bytes_left, buf, buf_pos), ...);
218222
219223 assert (bytes_left == 0 );
220224}
0 commit comments