pw_varint: Add EncodedSize function
This change adds functions to the varint module which return the size of
an integer when encoded as a varint.
Change-Id: I976e33835b1b6bece7ca586cd7f1c4d9ca17cdc8
diff --git a/pw_varint/docs.rst b/pw_varint/docs.rst
index 16c465b..49db88e 100644
--- a/pw_varint/docs.rst
+++ b/pw_varint/docs.rst
@@ -18,6 +18,18 @@
* C
* C++11 (with :doc:`../pw_polyfill/docs`)
+API
+===
+
+.. cpp:function:: size_t EncodedSize(uint64_t integer)
+
+Returns the size of an integer when encoded as a varint. Works on both signed
+and unsigned integers.
+
+.. cpp:function:: size_t ZigZagEncodedSize(int64_t integer)
+
+Returns the size of a signed integer when ZigZag encoded as a varint.
+
Dependencies
============
* ``pw_span``
diff --git a/pw_varint/public/pw_varint/varint.h b/pw_varint/public/pw_varint/varint.h
index 3bef687..b128bc0 100644
--- a/pw_varint/public/pw_varint/varint.h
+++ b/pw_varint/public/pw_varint/varint.h
@@ -32,6 +32,10 @@
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);
+
#ifdef __cplusplus
} // extern "C"
@@ -129,6 +133,16 @@
return pw_VarintDecode(input.data(), input.size(), value);
}
+// Returns a size of an integer when encoded as a varint.
+inline size_t EncodedSize(uint64_t integer) {
+ return pw_VarintEncodedSize(integer);
+}
+
+// Returns a size of an signed integer when ZigZag encoded as a varint.
+inline size_t ZigZagEncodedSize(int64_t integer) {
+ return pw_VarintZigZagEncodedSize(integer);
+}
+
} // namespace varint
} // namespace pw
diff --git a/pw_varint/varint.cc b/pw_varint/varint.cc
index ddfc0ed..9b782c0 100644
--- a/pw_varint/varint.cc
+++ b/pw_varint/varint.cc
@@ -83,5 +83,13 @@
return bytes;
}
+extern "C" size_t pw_VarintEncodedSize(uint64_t integer) {
+ return integer == 0 ? 1 : (64 - __builtin_clzll(integer) + 6) / 7;
+}
+
+extern "C" size_t pw_VarintZigZagEncodedSize(int64_t integer) {
+ return pw_VarintEncodedSize(ZigZagEncode(integer));
+}
+
} // namespace varint
} // namespace pw
diff --git a/pw_varint/varint_test.cc b/pw_varint/varint_test.cc
index 4e2efe2..eceaeb7 100644
--- a/pw_varint/varint_test.cc
+++ b/pw_varint/varint_test.cc
@@ -780,5 +780,50 @@
std::numeric_limits<int64_t>::max());
}
+TEST(Varint, EncodedSize) {
+ EXPECT_EQ(EncodedSize(uint64_t(0u)), 1u);
+ EXPECT_EQ(EncodedSize(uint64_t(1u)), 1u);
+ EXPECT_EQ(EncodedSize(uint64_t(127u)), 1u);
+ EXPECT_EQ(EncodedSize(uint64_t(128u)), 2u);
+ EXPECT_EQ(EncodedSize(uint64_t(16383u)), 2u);
+ EXPECT_EQ(EncodedSize(uint64_t(16384u)), 3u);
+ EXPECT_EQ(EncodedSize(uint64_t(2097151u)), 3u);
+ EXPECT_EQ(EncodedSize(uint64_t(2097152u)), 4u);
+ EXPECT_EQ(EncodedSize(uint64_t(268435455u)), 4u);
+ EXPECT_EQ(EncodedSize(uint64_t(268435456u)), 5u);
+ EXPECT_EQ(EncodedSize(uint64_t(34359738367u)), 5u);
+ EXPECT_EQ(EncodedSize(uint64_t(34359738368u)), 6u);
+ EXPECT_EQ(EncodedSize(uint64_t(4398046511103u)), 6u);
+ EXPECT_EQ(EncodedSize(uint64_t(4398046511104u)), 7u);
+ EXPECT_EQ(EncodedSize(uint64_t(562949953421311u)), 7u);
+ EXPECT_EQ(EncodedSize(uint64_t(562949953421312u)), 8u);
+ EXPECT_EQ(EncodedSize(uint64_t(72057594037927935u)), 8u);
+ EXPECT_EQ(EncodedSize(uint64_t(72057594037927936u)), 9u);
+ EXPECT_EQ(EncodedSize(uint64_t(9223372036854775807u)), 9u);
+ EXPECT_EQ(EncodedSize(uint64_t(9223372036854775808u)), 10u);
+ EXPECT_EQ(EncodedSize(std::numeric_limits<uint64_t>::max()), 10u);
+ EXPECT_EQ(EncodedSize(std::numeric_limits<int64_t>::max()), 9u);
+ EXPECT_EQ(EncodedSize(int64_t(-1)), 10u);
+ EXPECT_EQ(EncodedSize(std::numeric_limits<int64_t>::min()), 10u);
+}
+
+TEST(Varint, ZigZagEncodedSize) {
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(0)), 1u);
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(-1)), 1u);
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(1)), 1u);
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(-64)), 1u);
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(-65)), 2u);
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(63)), 1u);
+ EXPECT_EQ(ZigZagEncodedSize(int64_t(64)), 2u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int8_t>::min()), 2u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int8_t>::max()), 2u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int16_t>::min()), 3u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int16_t>::max()), 3u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int32_t>::min()), 5u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int32_t>::max()), 5u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int64_t>::min()), 10u);
+ EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int64_t>::max()), 10u);
+}
+
} // namespace
} // namespace pw::varint