1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/bitops.h>
4 #include <linux/string.h>
5 #include <asm/unaligned.h>
10 * bch2_varint_encode - encode a variable length integer
11 * @out - destination to encode to
12 * @v - unsigned integer to encode
14 * Returns the size in bytes of the encoded integer - at most 9 bytes
16 int bch2_varint_encode(u8 *out, u64 v)
18 unsigned bits = fls64(v|1);
19 unsigned bytes = DIV_ROUND_UP(bits, 7);
21 if (likely(bytes < 9)) {
23 v |= ~(~0 << (bytes - 1));
25 memcpy(out, &v, bytes);
29 put_unaligned_le64(v, out);
36 * bch2_varint_decode - encode a variable length integer
37 * @in - varint to decode
38 * @end - end of buffer to decode from
39 * @out - on success, decoded integer
41 * Returns the size in bytes of the decoded integer - or -1 on failure (would
42 * have read past the end of the buffer)
44 int bch2_varint_decode(const u8 *in, const u8 *end, u64 *out)
46 unsigned bytes = likely(in < end)
51 if (unlikely(in + bytes > end))
54 if (likely(bytes < 9)) {
56 memcpy(&v, in, bytes);
60 v = get_unaligned_le64(++in);
68 * bch2_varint_encode_fast - fast version of bch2_varint_encode
70 * This version assumes it's always safe to write 8 bytes to @out, even if the
71 * encoded integer would be smaller.
73 int bch2_varint_encode_fast(u8 *out, u64 v)
75 unsigned bits = fls64(v|1);
76 unsigned bytes = DIV_ROUND_UP(bits, 7);
78 if (likely(bytes < 9)) {
80 v |= ~(~0 << (bytes - 1));
86 put_unaligned_le64(v, out);
91 * bch2_varint_decode_fast - fast version of bch2_varint_decode
93 * This version assumes that it is safe to read at most 8 bytes past the end of
94 * @end (we still return an error if the varint extends past @end).
96 int bch2_varint_decode_fast(const u8 *in, const u8 *end, u64 *out)
98 u64 v = get_unaligned_le64(in);
99 unsigned bytes = ffz(v & 255) + 1;
101 if (unlikely(in + bytes > end))
104 if (likely(bytes < 9)) {
106 v &= ~(~0ULL << (7 * bytes));
108 v = get_unaligned_le64(++in);