diff options
author | Alexei Frolov <frolv@google.com> | 2021-03-30 13:19:40 -0700 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2021-04-02 01:46:17 +0000 |
commit | 6fe8ccf0ff7e3a13ca4abfdd7c6c452b4d7b8f60 (patch) | |
tree | b7f996f72c2f62e212acbb35bc2cedc294ecc8c8 | |
parent | b7902c03b282855a2fba07c16871097145d7a8af (diff) | |
download | pigweed-6fe8ccf0ff7e3a13ca4abfdd7c6c452b4d7b8f60.tar.gz |
pw_varint: MaxValueInBytes function
This adds a function to the varint API that returns the maximum value
that can be encoded into a given number of bytes.
Change-Id: I6be36117623e3cb9ec90fc4c5eb88b42196385aa
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/39581
Commit-Queue: Alexei Frolov <frolv@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
-rw-r--r-- | pw_varint/docs.rst | 5 | ||||
-rw-r--r-- | pw_varint/public/pw_varint/varint.h | 23 | ||||
-rw-r--r-- | pw_varint/varint_test.cc | 24 |
3 files changed, 52 insertions, 0 deletions
diff --git a/pw_varint/docs.rst b/pw_varint/docs.rst index 3327ccdba..58c90f959 100644 --- a/pw_varint/docs.rst +++ b/pw_varint/docs.rst @@ -28,6 +28,11 @@ and unsigned integers. Returns the size of a signed integer when ZigZag encoded as a varint. +.. cpp:function:: uint64_t MaxValueInBytes(size_t bytes) + +Returns the maximum integer value that can be encoded as a varint into the +specified number of bytes. + Dependencies ============ * ``pw_span`` diff --git a/pw_varint/public/pw_varint/varint.h b/pw_varint/public/pw_varint/varint.h index 4432e1934..9d0e0ce49 100644 --- a/pw_varint/public/pw_varint/varint.h +++ b/pw_varint/public/pw_varint/varint.h @@ -198,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 diff --git a/pw_varint/varint_test.cc b/pw_varint/varint_test.cc index 2d373d217..27282c4f2 100644 --- a/pw_varint/varint_test.cc +++ b/pw_varint/varint_test.cc @@ -1054,5 +1054,29 @@ TEST(Varint, ZigZagEncodedSize) { EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int64_t>::max()), 10u); } +constexpr uint64_t CalculateMaxValueInBytes(size_t bytes) { + uint64_t value = 0; + for (size_t i = 0; i < bytes; ++i) { + value |= uint64_t(0x7f) << (7 * i); + } + return value; +} + +TEST(Varint, MaxValueInBytes) { + static_assert(MaxValueInBytes(0) == 0); + static_assert(MaxValueInBytes(1) == 0x7f); + static_assert(MaxValueInBytes(2) == 0x3fff); + static_assert(MaxValueInBytes(3) == 0x1fffff); + static_assert(MaxValueInBytes(4) == 0x0fffffff); + static_assert(MaxValueInBytes(5) == CalculateMaxValueInBytes(5)); + static_assert(MaxValueInBytes(6) == CalculateMaxValueInBytes(6)); + static_assert(MaxValueInBytes(7) == CalculateMaxValueInBytes(7)); + static_assert(MaxValueInBytes(8) == CalculateMaxValueInBytes(8)); + static_assert(MaxValueInBytes(9) == CalculateMaxValueInBytes(9)); + static_assert(MaxValueInBytes(10) == std::numeric_limits<uint64_t>::max()); + static_assert(MaxValueInBytes(11) == std::numeric_limits<uint64_t>::max()); + static_assert(MaxValueInBytes(100) == std::numeric_limits<uint64_t>::max()); +} + } // namespace } // namespace pw::varint |