Skip to content

Commit 4e875fe

Browse files
committed
backport max_serialized_size feature from develop-v4 branch
1 parent 96443f8 commit 4e875fe

File tree

10 files changed

+197
-43
lines changed

10 files changed

+197
-43
lines changed

generator/EmbeddedProto/Field.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def render(self, filename, jinja_environment):
157157
class FieldBasic(Field):
158158
# A dictionary to convert the wire type into a default value.
159159
type_to_default_value = {FieldDescriptorProto.TYPE_DOUBLE: "0.0",
160-
FieldDescriptorProto.TYPE_FLOAT: "0.0",
160+
FieldDescriptorProto.TYPE_FLOAT: "0.0f",
161161
FieldDescriptorProto.TYPE_INT64: "0",
162162
FieldDescriptorProto.TYPE_UINT64: "0U",
163163
FieldDescriptorProto.TYPE_INT32: "0",
@@ -379,11 +379,18 @@ def get_type_as_defined(self):
379379

380380
return type_name
381381

382+
def get_max_enum_value(self):
383+
# Return the maximum value used by any of the enum items as a string. This is used to calculate the maximum serialized size.
384+
max_number = self.definition.descriptor.value[0].number
385+
for value in self.definition.descriptor.value[1:]:
386+
if max_number < value.number:
387+
max_number = value.number
388+
return str(max_number)
382389
def get_type(self):
383-
return "EmbeddedProto::enumeration<" + self.get_type_as_defined() + ">"
390+
return "EmbeddedProto::enumeration<" + self.get_type_as_defined() + ", EmbeddedProto::WireFormatter::VarintSize(" + self.get_max_enum_value() + ")>"
384391

385392
def get_short_type(self):
386-
return "EmbeddedProto::enumeration<" + self.get_type_as_defined().split("::")[-1] + ">"
393+
return "EmbeddedProto::enumeration<" + self.get_type_as_defined().split("::")[-1] + ", EmbeddedProto::WireFormatter::VarintSize(" + self.get_max_enum_value() + ")>"
387394

388395
def get_default_value(self):
389396
return "static_cast<" + self.get_type_as_defined() + ">(0)"

generator/EmbeddedProto/templates/TypeDefMsg.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,39 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
274274

275275
#endif
276276

277+
//! Calculate the maximum number of bytes required to serialize this type of message.
278+
/*!
279+
This function does not take into account a possible id of this message object is self.
280+
\return The number of bytes required at most to serialize this message type.
281+
*/
282+
static constexpr uint32_t max_serialized_size()
283+
{
284+
using namespace ::EmbeddedProto;
285+
return
286+
{% for field in typedef.fields %}
287+
{{"+ " if not loop.first }}{{field.get_type()}}::max_serialized_size(static_cast<uint32_t>(FieldNumber::{{field.variable_id_name}}))
288+
{% endfor %}
289+
{% for oneof in typedef.oneofs %}
290+
{{"+ " if not loop.first or typedef.fields|length != 0}}max_serialized_size_{{oneof.get_name()}}()
291+
{% endfor %}
292+
{% if typedef.fields|length == 0 and typedef.oneofs|length == 0 %}
293+
0
294+
{% endif %}
295+
;
296+
}
297+
298+
//! Calculate the maximum number of bytes required to serialize this message including the field id number and tag.
299+
/*!
300+
\return The number of bytes required at most to serialize this message type.
301+
*/
302+
static constexpr uint32_t max_serialized_size(const uint32_t field_number)
303+
{
304+
using namespace ::EmbeddedProto;
305+
return WireFormatter::VarintSize(WireFormatter::MakeTag(field_number, WireFormatter::WireType::LENGTH_DELIMITED)) // Size of the tag
306+
+ WireFormatter::VarintSize(max_serialized_size()) // Length delimted value
307+
+ max_serialized_size(); // Length of the serialized content
308+
}
309+
277310
#ifdef MSG_TO_STRING
278311

279312
::EmbeddedProto::string_view to_string(::EmbeddedProto::string_view& str) const
@@ -421,6 +454,7 @@ class {{ typedef.get_name() }} final: public ::EmbeddedProto::MessageInterface
421454
{{ TypeOneof.init(oneof)|indent(6) }}
422455
{{ TypeOneof.clear(oneof)|indent(6) }}
423456
{{ TypeOneof.deserialize(oneof, environment)|indent(6) }}
457+
{{ TypeOneof.max_serialized_size(oneof)|indent(6) }}
424458
#ifdef MSG_TO_STRING
425459
{{ TypeOneof.to_string(oneof)|indent(6) }}
426460
#endif // End of MSG_TO_STRING

generator/EmbeddedProto/templates/TypeOneof.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,27 @@ ::EmbeddedProto::string_view to_string_{{_oneof.get_name()}}(::EmbeddedProto::st
157157

158158
return left_chars;
159159
}
160+
{% endmacro %}
161+
{# #}
162+
{# ------------------------------------------------------------------------------------------------------------------ #}
163+
{# #}
164+
{% macro max_serialized_size(_oneof) %}
165+
static constexpr uint32_t max_serialized_size_{{_oneof.get_name()}}()
166+
{
167+
using namespace EmbeddedProto;
168+
return
169+
{% for field in _oneof.get_fields() %}
170+
{% if not loop.last %}
171+
{{ ' ' * (loop.index0 * 2) }}max({{field.get_type()}}::max_serialized_size(static_cast<uint32_t>(FieldNumber::{{field.variable_id_name}})),
172+
{% else %}
173+
{{ ' ' * (2 + (loop.index0 * 2))}}{{field.get_type()}}::max_serialized_size(static_cast<uint32_t>(FieldNumber::{{field.variable_id_name}}))
174+
{% endif %}
175+
{% endfor %}
176+
{% if _oneof.get_fields() | length > 1 %}
177+
{% for i in range(_oneof.get_fields() | length - 1) %}
178+
{{ ' ' * (5 + (loop.revindex * 2)) }})
179+
{% endfor %}
180+
{% endif %}
181+
;
182+
}
160183
{% endmacro %}

src/Defines.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020-2024 Embedded AMS B.V. - All Rights Reserved
2+
* Copyright (C) 2020-2025 Embedded AMS B.V. - All Rights Reserved
33
*
44
* This file is part of Embedded Proto.
55
*
@@ -16,7 +16,7 @@
1616
* along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
1717
*
1818
* For commercial and closed source application please visit:
19-
* <https://EmbeddedProto.com/license/>.
19+
* <https://embeddedproto.com/pricing/>.
2020
*
2121
* Embedded AMS B.V.
2222
* Info:
@@ -83,6 +83,11 @@ namespace EmbeddedProto
8383
using string_view = array_view<char>;
8484
using bytes_view = array_view<uint8_t>;
8585

86+
//! Simple max function as constexpr
87+
constexpr uint32_t max(const uint32_t a, const uint32_t b)
88+
{
89+
return (a > b) ? a : b;
90+
}
8691
}
8792

8893
#endif //_EMBEDDED_PROTO_DEFINES_H_

src/FieldStringBytes.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,32 @@ namespace EmbeddedProto
263263
void clear() override
264264
{
265265
data_.fill(0);
266-
current_length_ = 0;
266+
current_length_ = 0;
267+
}
268+
269+
//! When serialized with the all elements set, how much bytes are then required.
270+
/*!
271+
This function takes into account the field number and tag combination.
272+
\param[in] field_number We need to include the field number. This because large field numbers require more bytes.
273+
\return The number of bytes required at most.
274+
*/
275+
static constexpr uint32_t max_serialized_size(const uint32_t field_number)
276+
{
277+
return MAX_LENGTH // The number of bytes of the data.
278+
+ WireFormatter::VarintSize(MAX_LENGTH) // The varint indicating the actual number of bytes.
279+
+ WireFormatter::VarintSize(WireFormatter::MakeTag(field_number,
280+
WireFormatter::WireType::LENGTH_DELIMITED)); // The field and tag comby
281+
}
282+
283+
//! When serialized with the all elements set, how much bytes are then required.
284+
/*!
285+
This function is used when the field bytes or string is serialized packed. Think in a repeated field.
286+
\return The number of bytes required at most.
287+
*/
288+
static constexpr uint32_t max_serialized_size()
289+
{
290+
return MAX_LENGTH // The number of bytes of the data.
291+
+ WireFormatter::VarintSize(MAX_LENGTH); // The varint indicating the actual number of bytes.
267292
}
268293

269294
protected:

src/Fields.h

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020-2024 Embedded AMS B.V. - All Rights Reserved
2+
* Copyright (C) 2020-2025 Embedded AMS B.V. - All Rights Reserved
33
*
44
* This file is part of Embedded Proto.
55
*
@@ -16,7 +16,7 @@
1616
* along with Embedded Proto. If not, see <https://www.gnu.org/licenses/>.
1717
*
1818
* For commercial and closed source application please visit:
19-
* <https://EmbeddedProto.com/license/>.
19+
* <https://embeddedproto.com/pricing/>.
2020
*
2121
* Embedded AMS B.V.
2222
* Info:
@@ -119,12 +119,12 @@ namespace EmbeddedProto
119119
#endif // End of MSG_TO_STRING
120120
};
121121

122-
template<Field::FieldTypes FIELDTYPE, class VARIABLE_TYPE, WireFormatter::WireType WIRETYPE>
122+
template<Field::FieldTypes FIELDTYPE, class VARIABLE_TYPE, WireFormatter::WireType WIRETYPE, uint32_t MAX_SER_SIZE>
123123
class FieldTemplate
124124
{
125125
public:
126126
using TYPE = VARIABLE_TYPE;
127-
using CLASS_TYPE = FieldTemplate<FIELDTYPE, VARIABLE_TYPE, WIRETYPE>;
127+
using CLASS_TYPE = FieldTemplate<FIELDTYPE, VARIABLE_TYPE, WIRETYPE, MAX_SER_SIZE>;
128128

129129
FieldTemplate() = default;
130130
FieldTemplate(const VARIABLE_TYPE& v) : value_(v) { };
@@ -209,18 +209,18 @@ namespace EmbeddedProto
209209
bool operator>=(const VARIABLE_TYPE& rhs) { return value_ >= rhs; }
210210
bool operator<=(const VARIABLE_TYPE& rhs) { return value_ <= rhs; }
211211

212-
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS>
213-
bool operator==(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS>& rhs) { return value_ == rhs.get(); }
214-
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS>
215-
bool operator!=(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS>& rhs) { return value_ != rhs.get(); }
216-
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS>
217-
bool operator>(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS>& rhs) { return value_ > rhs.get(); }
218-
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS>
219-
bool operator<(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS>& rhs) { return value_ < rhs.get(); }
220-
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS>
221-
bool operator>=(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS>& rhs) { return value_ >= rhs.get(); }
222-
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS>
223-
bool operator<=(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS>& rhs) { return value_ <= rhs.get(); }
212+
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS, uint32_t SIZE_RHS>
213+
bool operator==(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS, SIZE_RHS>& rhs) { return value_ == rhs.get(); }
214+
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS, uint32_t SIZE_RHS>
215+
bool operator!=(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS, SIZE_RHS>& rhs) { return value_ != rhs.get(); }
216+
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS, uint32_t SIZE_RHS>
217+
bool operator>(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS, SIZE_RHS>& rhs) { return value_ > rhs.get(); }
218+
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS, uint32_t SIZE_RHS>
219+
bool operator<(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS, SIZE_RHS>& rhs) { return value_ < rhs.get(); }
220+
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS, uint32_t SIZE_RHS>
221+
bool operator>=(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS, SIZE_RHS>& rhs) { return value_ >= rhs.get(); }
222+
template<Field::FieldTypes FIELDTYPE_RHS, class TYPE_RHS, WireFormatter::WireType WIRETYPE_RHS, uint32_t SIZE_RHS>
223+
bool operator<=(const FieldTemplate<FIELDTYPE_RHS, TYPE_RHS, WIRETYPE_RHS, SIZE_RHS>& rhs) { return value_ <= rhs.get(); }
224224

225225
void clear() { value_ = static_cast<VARIABLE_TYPE>(0); }
226226

@@ -231,6 +231,22 @@ namespace EmbeddedProto
231231
return calcBuffer.get_size();
232232
}
233233

234+
//! When serialized with the most unfavrouble value how much bytes does this field need.
235+
/*!
236+
This function takes into account the field number and tag combination.
237+
\param[in] field_number We need to include the field number. This because large field numbers require more bytes.
238+
\return The number of bytes required at most.
239+
*/
240+
static constexpr uint32_t max_serialized_size(const uint32_t field_number)
241+
{
242+
return MAX_SER_SIZE + WireFormatter::VarintSize(WireFormatter::MakeTag(field_number, WIRETYPE));
243+
}
244+
245+
static constexpr uint32_t max_serialized_size()
246+
{
247+
return MAX_SER_SIZE;
248+
}
249+
234250
#ifdef MSG_TO_STRING
235251

236252
//! Write all the data in this field to a human readable string.
@@ -438,22 +454,22 @@ namespace EmbeddedProto
438454
};
439455

440456

441-
using int32 = FieldTemplate<Field::FieldTypes::int32, int32_t, WireFormatter::WireType::VARINT>;
442-
using int64 = FieldTemplate<Field::FieldTypes::int64, int64_t, WireFormatter::WireType::VARINT>;
443-
using uint32 = FieldTemplate<Field::FieldTypes::uint32, uint32_t, WireFormatter::WireType::VARINT>;
444-
using uint64 = FieldTemplate<Field::FieldTypes::uint64, uint64_t, WireFormatter::WireType::VARINT>;
445-
using sint32 = FieldTemplate<Field::FieldTypes::sint32, int32_t, WireFormatter::WireType::VARINT>;
446-
using sint64 = FieldTemplate<Field::FieldTypes::sint64, int64_t, WireFormatter::WireType::VARINT>;
447-
using boolean = FieldTemplate<Field::FieldTypes::boolean, bool, WireFormatter::WireType::VARINT>;
448-
using fixed32 = FieldTemplate<Field::FieldTypes::fixed32, uint32_t, WireFormatter::WireType::FIXED32>;
449-
using fixed64 = FieldTemplate<Field::FieldTypes::fixed64, uint64_t, WireFormatter::WireType::FIXED64>;
450-
using sfixed32 = FieldTemplate<Field::FieldTypes::sfixed32, int32_t, WireFormatter::WireType::FIXED32>;
451-
using sfixed64 = FieldTemplate<Field::FieldTypes::sfixed64, int64_t, WireFormatter::WireType::FIXED64>;
452-
using floatfixed = FieldTemplate<Field::FieldTypes::floatfixed, float, WireFormatter::WireType::FIXED32>;
453-
using doublefixed = FieldTemplate<Field::FieldTypes::doublefixed, double, WireFormatter::WireType::FIXED64>;
454-
455-
template<class ENUM_TYPE>
456-
using enumeration = FieldTemplate<Field::FieldTypes::enumeration, ENUM_TYPE, WireFormatter::WireType::VARINT>;
457+
using int32 = FieldTemplate<Field::FieldTypes::int32, int32_t, WireFormatter::WireType::VARINT, 5>;
458+
using int64 = FieldTemplate<Field::FieldTypes::int64, int64_t, WireFormatter::WireType::VARINT, 10>;
459+
using uint32 = FieldTemplate<Field::FieldTypes::uint32, uint32_t, WireFormatter::WireType::VARINT, 5>;
460+
using uint64 = FieldTemplate<Field::FieldTypes::uint64, uint64_t, WireFormatter::WireType::VARINT, 10>;
461+
using sint32 = FieldTemplate<Field::FieldTypes::sint32, int32_t, WireFormatter::WireType::VARINT, 5>;
462+
using sint64 = FieldTemplate<Field::FieldTypes::sint64, int64_t, WireFormatter::WireType::VARINT, 10>;
463+
using boolean = FieldTemplate<Field::FieldTypes::boolean, bool, WireFormatter::WireType::VARINT, 1>;
464+
using fixed32 = FieldTemplate<Field::FieldTypes::fixed32, uint32_t, WireFormatter::WireType::FIXED32, 4>;
465+
using fixed64 = FieldTemplate<Field::FieldTypes::fixed64, uint64_t, WireFormatter::WireType::FIXED64, 8>;
466+
using sfixed32 = FieldTemplate<Field::FieldTypes::sfixed32, int32_t, WireFormatter::WireType::FIXED32, 4>;
467+
using sfixed64 = FieldTemplate<Field::FieldTypes::sfixed64, int64_t, WireFormatter::WireType::FIXED64, 8>;
468+
using floatfixed = FieldTemplate<Field::FieldTypes::floatfixed, float, WireFormatter::WireType::FIXED32, 4>;
469+
using doublefixed = FieldTemplate<Field::FieldTypes::doublefixed, double, WireFormatter::WireType::FIXED64, 8>;
470+
471+
template<class ENUM_TYPE, uint32_t MAX_SER_SIZE>
472+
using enumeration = FieldTemplate<Field::FieldTypes::enumeration, ENUM_TYPE, WireFormatter::WireType::VARINT, MAX_SER_SIZE>;
457473

458474
} // End of namespace EmbeddedProto.
459475
#endif

src/ReadBufferFixedSize.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace EmbeddedProto
5454
//! \see ::EmbeddedProto::ReadBufferInterface::get_size()
5555
uint32_t get_size() const override
5656
{
57-
return write_index_;
57+
return write_index_ - read_index_;
5858
}
5959

6060
//! \see ::EmbeddedProto::ReadBufferInterface::get_max_size()

src/RepeatedField.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,20 @@ namespace EmbeddedProto
5555
struct is_specialization_of_FieldTemplate : std::false_type {};
5656

5757
//! Definition of a trait to check if DATA_TYPE is a specialization of the FieldTemplate.
58-
template<Field::FieldTypes F, typename V, WireFormatter::WireType W>
59-
struct is_specialization_of_FieldTemplate<::EmbeddedProto::FieldTemplate<F,V,W>> : std::true_type {};
58+
template<Field::FieldTypes F, typename V, WireFormatter::WireType W, uint32_t S>
59+
struct is_specialization_of_FieldTemplate<::EmbeddedProto::FieldTemplate<F,V,W,S>> : std::true_type {};
6060

6161
//! This class only supports Field and FieldTemplate classes as template parameter.
6262
static_assert(std::is_base_of<::EmbeddedProto::Field, DATA_TYPE>::value || is_specialization_of_FieldTemplate<DATA_TYPE>::value,
6363
"A Field can only be used as template paramter.");
6464

65+
public:
66+
6567
//! Check how this field shoeld be serialized, packed or not.
6668
static constexpr bool REPEATED_FIELD_IS_PACKED =
6769
!(std::is_base_of<MessageInterface, DATA_TYPE>::value
6870
|| std::is_base_of<internal::BaseStringBytes, DATA_TYPE>::value);
6971

70-
public:
71-
7272
RepeatedField() = default;
7373
~RepeatedField() override = default;
7474

src/RepeatedFieldFixedSize.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,32 @@ namespace EmbeddedProto
193193
//! Return a reference to the internal data storage array.
194194
const std::array<DATA_TYPE, MAX_LENGTH>& get_data_const() const { return data_; }
195195

196+
//! When serialized with the most unfavrouble value how much bytes does this field need.
197+
/*!
198+
This function takes into account the field number and tag combination.
199+
\param[in] field_number We need to include the field number. This because large field numbers require more bytes.
200+
\return The number of bytes required at most.
201+
*/
202+
static constexpr uint32_t max_serialized_size(const uint32_t field_number)
203+
{
204+
return RepeatedField<DATA_TYPE>::REPEATED_FIELD_IS_PACKED
205+
? max_packed_serialized_size(field_number)
206+
: max_unpacked_serialized_size(field_number);
207+
}
208+
209+
static constexpr uint32_t max_packed_serialized_size(const uint32_t field_number)
210+
{
211+
return WireFormatter::VarintSize(WireFormatter::MakeTag(field_number,
212+
WireFormatter::WireType::LENGTH_DELIMITED))
213+
+ WireFormatter::VarintSize(MAX_LENGTH)
214+
+ (MAX_LENGTH * DATA_TYPE::max_serialized_size());
215+
}
216+
217+
static constexpr uint32_t max_unpacked_serialized_size(const uint32_t field_number)
218+
{
219+
return MAX_LENGTH * DATA_TYPE::max_serialized_size(field_number);
220+
}
221+
196222
private:
197223

198224
//! Number of item in the data array.

src/WireFormatter.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@ namespace EmbeddedProto
8181
FIXED32 = 5, //!< fixed32, sfixed32, float
8282
};
8383

84+
//! Calculate the number of bytes a varint value will take.
85+
/*!
86+
\param[in] value The value of which to calculate the size.
87+
\return The number of bytes required for serializing the varint.
88+
*/
89+
static constexpr uint32_t VarintSize(const uint64_t value)
90+
{
91+
return (value < (1ULL << 7)) ? 1 :
92+
(value < (1ULL << 14)) ? 2 :
93+
(value < (1ULL << 21)) ? 3 :
94+
(value < (1ULL << 28)) ? 4 :
95+
(value < (1ULL << 35)) ? 5 :
96+
(value < (1ULL << 42)) ? 6 :
97+
(value < (1ULL << 49)) ? 7 :
98+
(value < (1ULL << 56)) ? 8 :
99+
(value < (1ULL << 63)) ? 9 : 10;
100+
}
101+
84102
//! Encode a signed integer using the zig zag method
85103
/*!
86104
As specified the right-shift must be arithmetic, hence the cast is after the shift. The

0 commit comments

Comments
 (0)