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

Function ParseLeadingLEB128

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

Source from the content-addressed store, hash-verified

346/// \see MaxLEB128ByteLenFor
347template <typename Int>
348constexpr int32_t ParseLeadingLEB128(const uint8_t* data, int32_t max_data_size,
349 Int* out) {
350 constexpr auto kMaxBytes = kMaxLEB128ByteLenFor<Int>;
351 static_assert(kMaxBytes >= 1);
352 constexpr uint8_t kLow7Mask = 0x7F;
353 constexpr uint8_t kContinuationBit = 0x80;
354 constexpr int32_t kSignBitCount = std::is_signed_v<Int> ? 1 : 0;
355 // Number of bits allowed for encoding data on the last byte to avoid overflow
356 constexpr uint8_t kHighBitCount = (8 * sizeof(Int) - kSignBitCount) % 7;
357 // kHighBitCount least significant `0` bits and the rest with `1`
358 constexpr uint8_t kHighForbiddenMask = ~((1 << kHighBitCount) - 1);
359
360 // Iteratively building the value
361 std::make_unsigned_t<Int> value = 0;
362
363 // Read as many bytes as we could be for the given output.
364 for (int32_t i = 0; i < kMaxBytes - 1; i++) {
365 // We have not finished reading a valid LEB128, yet we run out of data
366 if (ARROW_PREDICT_FALSE(i >= max_data_size)) {
367 return 0;
368 }
369
370 // Read the byte and set its 7 LSB to in the final value
371 const uint8_t byte = data[i];
372 value |= static_cast<Int>(byte & kLow7Mask) << (7 * i);
373
374 // Check for lack of continuation flag in MSB
375 if ((byte & kContinuationBit) == 0) {
376 *out = value;
377 return i + 1;
378 }
379 }
380
381 // Process the last index avoiding overflowing
382 constexpr int32_t last = kMaxBytes - 1;
383
384 // We have not finished reading a valid LEB128, yet we run out of data
385 if (ARROW_PREDICT_FALSE(last >= max_data_size)) {
386 return 0;
387 }
388
389 const uint8_t byte = data[last];
390
391 // Need to check if there are bits that would overflow the output.
392 // Also checks that there is no continuation.
393 if (ARROW_PREDICT_FALSE((byte & kHighForbiddenMask) != 0)) {
394 return 0;
395 }
396
397 // No longer need to mask since we ensured
398 value |= static_cast<Int>(byte) << (7 * last);
399 *out = value;
400 return last + 1;
401}
402} // namespace bit_util
403} // namespace arrow

Callers 3

GetVlqIntMethod · 0.85
PeekImplMethod · 0.85
TestLEB128DecodeFunction · 0.85

Calls

no outgoing calls

Tested by 1

TestLEB128DecodeFunction · 0.68