MCPcopy Create free account
hub / github.com/apache/arrow / ParseLeadingLEB128

Function ParseLeadingLEB128

cpp/src/arrow/util/bit_util.h:312–365  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

310/// \see MaxLEB128ByteLenFor
311template <typename Int>
312constexpr int32_t ParseLeadingLEB128(const uint8_t* data, int32_t max_data_size,
313 Int* out) {
314 constexpr auto kMaxBytes = kMaxLEB128ByteLenFor<Int>;
315 static_assert(kMaxBytes >= 1);
316 constexpr uint8_t kLow7Mask = 0x7F;
317 constexpr uint8_t kContinuationBit = 0x80;
318 constexpr int32_t kSignBitCount = std::is_signed_v<Int> ? 1 : 0;
319 // Number of bits allowed for encoding data on the last byte to avoid overflow
320 constexpr uint8_t kHighBitCount = (8 * sizeof(Int) - kSignBitCount) % 7;
321 // kHighBitCount least significant `0` bits and the rest with `1`
322 constexpr uint8_t kHighForbiddenMask = ~((1 << kHighBitCount) - 1);
323
324 // Iteratively building the value
325 std::make_unsigned_t<Int> value = 0;
326
327 // Read as many bytes as we could be for the given output.
328 for (int32_t i = 0; i < kMaxBytes - 1; i++) {
329 // We have not finished reading a valid LEB128, yet we run out of data
330 if (ARROW_PREDICT_FALSE(i >= max_data_size)) {
331 return 0;
332 }
333
334 // Read the byte and set its 7 LSB to in the final value
335 const uint8_t byte = data[i];
336 value |= static_cast<Int>(byte & kLow7Mask) << (7 * i);
337
338 // Check for lack of continuation flag in MSB
339 if ((byte & kContinuationBit) == 0) {
340 *out = value;
341 return i + 1;
342 }
343 }
344
345 // Process the last index avoiding overflowing
346 constexpr int32_t last = kMaxBytes - 1;
347
348 // We have not finished reading a valid LEB128, yet we run out of data
349 if (ARROW_PREDICT_FALSE(last >= max_data_size)) {
350 return 0;
351 }
352
353 const uint8_t byte = data[last];
354
355 // Need to check if there are bits that would overflow the output.
356 // Also checks that there is no continuation.
357 if (ARROW_PREDICT_FALSE((byte & kHighForbiddenMask) != 0)) {
358 return 0;
359 }
360
361 // No longer need to mask since we ensured
362 value |= static_cast<Int>(byte) << (7 * last);
363 *out = value;
364 return last + 1;
365}
366} // namespace bit_util
367} // namespace arrow

Callers 3

GetVlqIntMethod · 0.85
PeekImplMethod · 0.85
TestLEB128DecodeFunction · 0.85

Calls

no outgoing calls

Tested by 1

TestLEB128DecodeFunction · 0.68