1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/bitops.h>
4 #include <linux/math.h>
5 #include <linux/string.h>
6 #include <linux/unaligned.h>
9 #include <valgrind/memcheck.h>
15 * bch2_varint_encode - encode a variable length integer
16 * @out: destination to encode to
17 * @v: unsigned integer to encode
18 * Returns: size in bytes of the encoded integer - at most 9 bytes
20 int bch2_varint_encode(u8
*out
, u64 v
)
22 unsigned bits
= fls64(v
|1);
23 unsigned bytes
= DIV_ROUND_UP(bits
, 7);
26 if (likely(bytes
< 9)) {
28 v
|= ~(~0 << (bytes
- 1));
29 v_le
= cpu_to_le64(v
);
30 memcpy(out
, &v_le
, bytes
);
34 put_unaligned_le64(v
, out
);
41 * bch2_varint_decode - encode a variable length integer
42 * @in: varint to decode
43 * @end: end of buffer to decode from
44 * @out: on success, decoded integer
45 * Returns: size in bytes of the decoded integer - or -1 on failure (would
46 * have read past the end of the buffer)
48 int bch2_varint_decode(const u8
*in
, const u8
*end
, u64
*out
)
50 unsigned bytes
= likely(in
< end
)
55 if (unlikely(in
+ bytes
> end
))
58 if (likely(bytes
< 9)) {
61 memcpy(&v_le
, in
, bytes
);
62 v
= le64_to_cpu(v_le
);
65 v
= get_unaligned_le64(++in
);
73 * bch2_varint_encode_fast - fast version of bch2_varint_encode
74 * @out: destination to encode to
75 * @v: unsigned integer to encode
76 * Returns: size in bytes of the encoded integer - at most 9 bytes
78 * This version assumes it's always safe to write 8 bytes to @out, even if the
79 * encoded integer would be smaller.
81 int bch2_varint_encode_fast(u8
*out
, u64 v
)
83 unsigned bits
= fls64(v
|1);
84 unsigned bytes
= DIV_ROUND_UP(bits
, 7);
86 if (likely(bytes
< 9)) {
88 v
|= ~(~0U << (bytes
- 1));
94 put_unaligned_le64(v
, out
);
99 * bch2_varint_decode_fast - fast version of bch2_varint_decode
100 * @in: varint to decode
101 * @end: end of buffer to decode from
102 * @out: on success, decoded integer
103 * Returns: size in bytes of the decoded integer - or -1 on failure (would
104 * have read past the end of the buffer)
106 * This version assumes that it is safe to read at most 8 bytes past the end of
107 * @end (we still return an error if the varint extends past @end).
109 int bch2_varint_decode_fast(const u8
*in
, const u8
*end
, u64
*out
)
111 #ifdef CONFIG_VALGRIND
112 VALGRIND_MAKE_MEM_DEFINED(in
, 8);
114 u64 v
= get_unaligned_le64(in
);
115 unsigned bytes
= ffz(*in
) + 1;
117 if (unlikely(in
+ bytes
> end
))
120 if (likely(bytes
< 9)) {
122 v
&= ~(~0ULL << (7 * bytes
));
124 v
= get_unaligned_le64(++in
);