author | Olivier Brunel
<jjk@jjacky.com> 2023-04-30 13:51:43 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-05-20 18:06:39 UTC |
parent | 8dbc05d787cb50330dd32cd0267a3ba43d1193f7 |
src/doc/u64.h/u64_pack.3.md | +8 | -5 |
src/doc/uint64.h/uint64_pack_trim.3.md | +15 | -11 |
src/liblimb/include/limb/u64.h | +2 | -2 |
src/liblimb/include/limb/uint64.h | +2 | -2 |
src/liblimb/saencdata.h/saencdata.c | +2 | -2 |
src/liblimb/uint64.h/uint64_pack_trim.c | +8 | -6 |
src/liblimb/uint64.h/uint64_unpack_trim.c | +14 | -8 |
diff --git a/src/doc/u64.h/u64_pack.3.md b/src/doc/u64.h/u64_pack.3.md index 539f84b..a95089e 100644 --- a/src/doc/u64.h/u64_pack.3.md +++ b/src/doc/u64.h/u64_pack.3.md @@ -17,8 +17,8 @@ void u64_pack(void *<em>dst</em>, u64 <em>val</em>) void u64_unpack(u64 *<em>val</em>, const void *<em>sce</em>) void u64_pack_big(void *<em>dst</em>, u64 <em>val</em>) void u64_unpack_big(u64 *<em>val</em>, const void *<em>sce</em>) -int u64_pack_trim(void *<em>dst</em>, u64 <em>val</em>) -int u64_unpack_trim(u64 *<em>val</em>, const void *<em>sce</em>) +int u64_pack_trim(void *<em>dst</em>, size_t <em>dlen</em>, u64 <em>val</em>) +int u64_unpack_trim(u64 *<em>val</em>, const void *<em>sce</em>, size_t <em>slen</em>) ``` # DESCRIPTION @@ -31,11 +31,13 @@ The `u64_pack`() function packs `val` into 8 bytes encoded as little endian, the `u64_pack_big`() function does the same encoded as big endian, and the `u64_pack_trim`() function pack in a little endian mode but /trimming/ the "unneeded" bits, i.e. all most significant bits set to zero need not be -included. It will therefore pack into from 1 to 9 bytes, depending on the value. +included. It will therefore need to pack into from 1 to 9 bytes, depending on +the value. It will never write more than `dlen` bytes though. See [uint64_pack_trim](3) for more. The `u64_unpack` family does the same, only unpacking from the byte array `sce` -into `val` +into `val`. Similarly, the `u64_unpack_trim`() function will never read more +than `slen` bytes. These are actually macros to the relevant `uint64_*` functions, offering a slightly different interface. @@ -43,4 +45,5 @@ slightly different interface. # RETURN VALUE Only `u64_pack_trim`() and `u64_unpack_trim`() have a return value, that of the -number of bytes written to `dst` or read from `sce`, respectively. +number of bytes written to `dst` or read from `sce`, respectively, on success. +Otherwise - not enough byte could be written/read - they will return -1 diff --git a/src/doc/uint64.h/uint64_pack_trim.3.md b/src/doc/uint64.h/uint64_pack_trim.3.md index 380312a..f40c99e 100644 --- a/src/doc/uint64.h/uint64_pack_trim.3.md +++ b/src/doc/uint64.h/uint64_pack_trim.3.md @@ -13,31 +13,35 @@ into\/from a byte array #include <limb/uint64.h> ```pre hl -int uint64_pack_trim(char *<em>dst</em>, uint64_t <em>val</em>) -int uint64_unpack_trim(const char *<em>sce</em>, uint64_t *<em>val</em>) +int uint64_pack_trim(char *<em>dst</em>, size_t <em>dlen</em>, uint64_t <em>val</em>) +int uint64_unpack_trim(const char *<em>sce</em>, size_t <em>slen</em>, uint64_t *<em>val</em>) ``` # DESCRIPTION -The `uint64_pack_trim`() function will store the number `val` into `dst` -/trimming/ the "unneeded" bits, i.e. all most significant bits set to zero need -not be included. +The `uint64_pack_trim`() function will store the number `val` into the byte +array pointed by `dst` of length `dlen`, /trimming/ the "unneeded" bits, i.e. +all most significant bits set to zero need not be included. In other words, it will only use as many bytes as necessary: The value is stored in little-endian mode using only 7 bits per byte, with the last (most significant) bit used as indicator whether or not an additional byte is required. -Therefore the encoded number will take from only 1 up to 9 bytes; As such the -specified buffer `dst` should be able to hold at least 9 bytes. +Therefore the encoded number will take from only 1 up to 9 bytes. -The `uint64_unpack_trim`() function will read at least 1 byte from `sce`, and up -to 9, in order to decode the stored value and place it into `val`. +The `uint64_unpack_trim`() function performs the reverse, reading bytes from the +memory pointed by `sce` to get the encoded value, which will be placed into the +memory pointed by `val`. +It will therefore read from 1 up to 9 bytes, depending on the actual value. +However it will only ever read up to `slen` bytes. # RETURN VALUE `uint64_pack_trim`() returns the number of bytes written to into `dst` to pack -`val` +`val` on success. Otherwise - i.e. more than `dlen` bytes are necessary - it +returns -1. `uint64_unpack_trim`() returns the number of bytes read from `sce` to unpack -`val` +`val` on success. Otherwise - i.e. more than `slen` bytes needed to be read - +it returns -1. diff --git a/src/liblimb/include/limb/u64.h b/src/liblimb/include/limb/u64.h index b220c39..f2d369a 100644 --- a/src/liblimb/include/limb/u64.h +++ b/src/liblimb/include/limb/u64.h @@ -19,8 +19,8 @@ #define u64_unpack(val,sce) uint64_unpack((const char *) (sce), val) #define u64_pack_big(dst,val) uint64_pack_big((char *) (dst), val) #define u64_unpack_big(val,sce) uint64_unpack_big((const char *) (sce), val) -#define u64_pack_trim(dst,val) uint64_pack_trim((char *) (dst), val) -#define u64_unpack_trim(val,sce) uint64_unpack_trim((const char *) (sce), val) +#define u64_pack_trim(dst,dl,val) uint64_pack_trim((char *) (dst), dl, val) +#define u64_unpack_trim(val,sce,sl) uint64_unpack_trim((const char *) (sce), sl, val) extern size_t u64_fmt_generic(char *s, u64 u, u8 base, u8 grp, const char sep); extern size_t u640_fmt_generic(char *s, u64 u, u8 base, size_t min, const char fill, diff --git a/src/liblimb/include/limb/uint64.h b/src/liblimb/include/limb/uint64.h index 77ae892..bb1d8cb 100644 --- a/src/liblimb/include/limb/uint64.h +++ b/src/liblimb/include/limb/uint64.h @@ -9,7 +9,7 @@ extern int msb64(uint64_t val); -extern int uint64_pack_trim(char *dst, uint64_t val); -extern int uint64_unpack_trim(const char *sce, uint64_t *val); +extern int uint64_pack_trim(char *dst, size_t dlen, uint64_t val); +extern int uint64_unpack_trim(const char *sce, size_t slen, uint64_t *val); #endif /* LIMB_UINT64_H */ diff --git a/src/liblimb/saencdata.h/saencdata.c b/src/liblimb/saencdata.h/saencdata.c index 243048c..2e95486 100644 --- a/src/liblimb/saencdata.h/saencdata.c +++ b/src/liblimb/saencdata.h/saencdata.c @@ -18,11 +18,11 @@ saencdata(stralloc *sa, const u16 id, const void *val, const size_t size) sa->len += 2; if (is_blob) { - sa->len += u64_pack_trim(sa->s + sa->len, (u64) size); + sa->len += u64_pack_trim(sa->s + sa->len, 9, (u64) size); if (!stralloc_catb(sa, * (char **) val, size)) goto err; } else { - sa->len += u64_pack_trim(sa->s + sa->len, * (u64 *) val); + sa->len += u64_pack_trim(sa->s + sa->len, 9, * (u64 *) val); } return 1; diff --git a/src/liblimb/uint64.h/uint64_pack_trim.c b/src/liblimb/uint64.h/uint64_pack_trim.c index 995187e..b4252c1 100644 --- a/src/liblimb/uint64.h/uint64_pack_trim.c +++ b/src/liblimb/uint64.h/uint64_pack_trim.c @@ -5,17 +5,19 @@ #include <limb/uint64.h> int -uint64_pack_trim(char *dst_, uint64_t val) +uint64_pack_trim(char *dst_, size_t dlen, uint64_t val) { uint8_t *dst = (uint8_t *) dst_; - int bits = msb64(val); - int b; + unsigned int bits = msb64(val); + unsigned int b = 0; /* ensure little endianness */ uint64_littlep(&val); - for (b = 0; b < 8; ++b) { + for (;;) { int n = bits > 7 ? 7 : bits; + /* enough room? */ + if (b >= dlen) return -1; /* store the 7 low bits */ dst[b] = val & 127; /* and shift them out */ @@ -24,8 +26,8 @@ uint64_pack_trim(char *dst_, uint64_t val) if (!bits) break; /* add our flag: one more byte */ - dst[b] |= 128; + dst[b++] |= 128; } - return b + 1; + return b + 1; } diff --git a/src/liblimb/uint64.h/uint64_unpack_trim.c b/src/liblimb/uint64.h/uint64_unpack_trim.c index a7bd314..dbece48 100644 --- a/src/liblimb/uint64.h/uint64_unpack_trim.c +++ b/src/liblimb/uint64.h/uint64_unpack_trim.c @@ -4,23 +4,29 @@ #include <limb/uint64.h> int -uint64_unpack_trim(const char *sce_, uint64_t *val) +uint64_unpack_trim(const char *sce_, size_t slen, uint64_t *val) { const uint8_t *sce = (const uint8_t *) sce_; - int b; + unsigned int b = 0; *val = 0; - for (b = 0; b < 9; ++b) { + for (;;) { + /* is there a(nother) byte to read? */ + if (b >= slen) return -1; + uint8_t byte = sce[b]; + /* if we're on the last byte, add the last 8 bits and be done */ + if (b == 8) { + *val |= (uint64_t) byte << (7 * 8); + break; + } /* extract the last 7 bits from byte and add them into our val */ - *val |= (byte & 127) << (7 * b); - /* is there another byte to read? */ + *val |= (uint64_t) (byte & 127) << (7 * b); + /* are we done? */ if (!(byte & 128)) break; + ++b; } - /* if needed, add the last bit from the last byte */ - if (b == 8 && sce[b] & 128) - *val |= 1ULL << 63; return b + 1; }