aboutsummaryrefslogtreecommitdiff
path: root/pw_varint/public/pw_varint/varint.h
diff options
context:
space:
mode:
Diffstat (limited to 'pw_varint/public/pw_varint/varint.h')
-rw-r--r--pw_varint/public/pw_varint/varint.h104
1 files changed, 91 insertions, 13 deletions
diff --git a/pw_varint/public/pw_varint/varint.h b/pw_varint/public/pw_varint/varint.h
index a8db949cc..9d0e0ce49 100644
--- a/pw_varint/public/pw_varint/varint.h
+++ b/pw_varint/public/pw_varint/varint.h
@@ -24,17 +24,47 @@ extern "C" {
// Expose a subset of the varint API for use in C code.
-size_t pw_VarintEncode(uint64_t integer, void* output, size_t output_size);
-size_t pw_VarintZigZagEncode(int64_t integer, void* output, size_t output_size);
+typedef enum {
+ PW_VARINT_ZERO_TERMINATED_LEAST_SIGNIFICANT = 0b00,
+ PW_VARINT_ZERO_TERMINATED_MOST_SIGNIFICANT = 0b01,
+ PW_VARINT_ONE_TERMINATED_LEAST_SIGNIFICANT = 0b10,
+ PW_VARINT_ONE_TERMINATED_MOST_SIGNIFICANT = 0b11,
+} pw_varint_Format;
+
+size_t pw_varint_EncodeCustom(uint64_t integer,
+ void* output,
+ size_t output_size,
+ pw_varint_Format format);
+size_t pw_varint_DecodeCustom(const void* input,
+ size_t input_size,
+ uint64_t* output,
+ pw_varint_Format format);
+
+static inline size_t pw_varint_Encode(uint64_t integer,
+ void* output,
+ size_t output_size) {
+ return pw_varint_EncodeCustom(
+ integer, output, output_size, PW_VARINT_ZERO_TERMINATED_MOST_SIGNIFICANT);
+}
+
+size_t pw_varint_ZigZagEncode(int64_t integer,
+ void* output,
+ size_t output_size);
+
+static inline size_t pw_varint_Decode(const void* input,
+ size_t input_size,
+ uint64_t* output) {
+ return pw_varint_DecodeCustom(
+ input, input_size, output, PW_VARINT_ZERO_TERMINATED_MOST_SIGNIFICANT);
+}
-size_t pw_VarintDecode(const void* input, size_t input_size, uint64_t* output);
-size_t pw_VarintZigZagDecode(const void* input,
- size_t input_size,
- int64_t* output);
+size_t pw_varint_ZigZagDecode(const void* input,
+ size_t input_size,
+ int64_t* output);
// Returns the size of an when encoded as a varint.
-size_t pw_VarintEncodedSize(uint64_t integer);
-size_t pw_VarintZigZagEncodedSize(int64_t integer);
+size_t pw_varint_EncodedSize(uint64_t integer);
+size_t pw_varint_ZigZagEncodedSize(int64_t integer);
#ifdef __cplusplus
@@ -83,7 +113,7 @@ constexpr std::make_signed_t<T> ZigZagDecode(T n)
// Encodes a uint64_t with Little-Endian Base 128 (LEB128) encoding.
inline size_t EncodeLittleEndianBase128(uint64_t integer,
const std::span<std::byte>& output) {
- return pw_VarintEncode(integer, output.data(), output.size());
+ return pw_varint_Encode(integer, output.data(), output.size());
}
// Encodes the provided integer using a variable-length encoding and returns the
@@ -99,9 +129,9 @@ inline size_t EncodeLittleEndianBase128(uint64_t integer,
template <typename T>
size_t Encode(T integer, const std::span<std::byte>& output) {
if (std::is_signed<T>()) {
- return pw_VarintZigZagEncode(integer, output.data(), output.size());
+ return pw_varint_ZigZagEncode(integer, output.data(), output.size());
} else {
- return pw_VarintEncode(integer, output.data(), output.size());
+ return pw_varint_Encode(integer, output.data(), output.size());
}
}
@@ -126,11 +156,36 @@ size_t Encode(T integer, const std::span<std::byte>& output) {
// }
//
inline size_t Decode(const std::span<const std::byte>& input, int64_t* value) {
- return pw_VarintZigZagDecode(input.data(), input.size(), value);
+ return pw_varint_ZigZagDecode(input.data(), input.size(), value);
}
inline size_t Decode(const std::span<const std::byte>& input, uint64_t* value) {
- return pw_VarintDecode(input.data(), input.size(), value);
+ return pw_varint_Decode(input.data(), input.size(), value);
+}
+
+enum class Format {
+ kZeroTerminatedLeastSignificant = PW_VARINT_ZERO_TERMINATED_LEAST_SIGNIFICANT,
+ kZeroTerminatedMostSignificant = PW_VARINT_ZERO_TERMINATED_MOST_SIGNIFICANT,
+ kOneTerminatedLeastSignificant = PW_VARINT_ONE_TERMINATED_LEAST_SIGNIFICANT,
+ kOneTerminatedMostSignificant = PW_VARINT_ONE_TERMINATED_MOST_SIGNIFICANT,
+};
+
+// Encodes a varint in a custom format.
+inline size_t Encode(uint64_t value,
+ std::span<std::byte> output,
+ Format format) {
+ return pw_varint_EncodeCustom(value,
+ output.data(),
+ output.size(),
+ static_cast<pw_varint_Format>(format));
+}
+
+// Decodes a varint from a custom format.
+inline size_t Decode(std::span<const std::byte> input,
+ uint64_t* value,
+ Format format) {
+ return pw_varint_DecodeCustom(
+ input.data(), input.size(), value, static_cast<pw_varint_Format>(format));
}
// Returns a size of an integer when encoded as a varint.
@@ -143,6 +198,29 @@ constexpr size_t ZigZagEncodedSize(int64_t integer) {
return EncodedSize(ZigZagEncode(integer));
}
+// Returns the maximum integer value that can be encoded in a varint of the
+// specified number of bytes.
+//
+// These values are also listed in the table below. Zigzag encoding cuts these
+// in half, as positive and negative integers are alternated.
+//
+// Bytes Max value
+// 1 127
+// 2 16,383
+// 3 2,097,151
+// 4 268,435,455
+// 5 34,359,738,367 -- needed for max uint32 value
+// 6 4,398,046,511,103
+// 7 562,949,953,421,311
+// 8 72,057,594,037,927,935
+// 9 9,223,372,036,854,775,807
+// 10 uint64 max value
+//
+constexpr uint64_t MaxValueInBytes(size_t bytes) {
+ return bytes >= kMaxVarint64SizeBytes ? std::numeric_limits<uint64_t>::max()
+ : (uint64_t(1) << (7 * bytes)) - 1;
+}
+
} // namespace varint
} // namespace pw