aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexei Frolov <frolv@google.com>2021-03-30 13:19:40 -0700
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2021-04-02 01:46:17 +0000
commit6fe8ccf0ff7e3a13ca4abfdd7c6c452b4d7b8f60 (patch)
treeb7f996f72c2f62e212acbb35bc2cedc294ecc8c8
parentb7902c03b282855a2fba07c16871097145d7a8af (diff)
downloadpigweed-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.rst5
-rw-r--r--pw_varint/public/pw_varint/varint.h23
-rw-r--r--pw_varint/varint_test.cc24
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