author | Olivier Brunel
<jjk@jjacky.com> 2023-02-06 10:12:37 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-02-15 17:45:22 UTC |
parent | 67544a7d435f3ca0ce03d6c15cc92ea325dfa4fa |
doc/u64_pack.3.md | +44 | -0 |
doc/uint64_pack_trim.3.md | +41 | -0 |
include/limb/int.h | +9 | -0 |
include/limb/uint64.h | +11 | -0 |
meta/deps/skalibs/version | +1 | -1 |
meta/libs/limb | +3 | -0 |
src/uint64_pack_trim.c | +28 | -0 |
src/uint64_unpack_trim.c | +23 | -0 |
diff --git a/doc/u64_pack.3.md b/doc/u64_pack.3.md new file mode 100644 index 0000000..1d0652f --- /dev/null +++ b/doc/u64_pack.3.md @@ -0,0 +1,44 @@ +% limb manual +% u64_pack(3) + +# NAME + +u64\_pack, u64\_unpack, u64\_pack\_big, u64\_unpack\_big, u64\_pack\_trim, +u64\_unpack\_trim - pack\/unpack an integer (u64) into\/from a byte array + +# SYNOPSIS + + #include <limb/int.h> + +```pre hl +void u64_pack(u64 <em>val</em>, void *<em>dst</em>) +void u64_unpack(const void *<em>sce</em>, u64 *<em>val</em>) +void u64_pack_big(u64 <em>val</em>, void *<em>dst</em>) +void u64_unpack_big(const void *<em>sce</em>, u64 *<em>val</em>) +int u64_pack_trim(u64 <em>val</em>, void *<em>dst</em>) +int u64_unpack_trim(const void *<em>sce</em>, u64 *<em>val</em>) +``` + +# DESCRIPTION + +All of these aim to either pack the given integer (u64) `val` into the specified +byte array `dst`, or unpack from the specified byte array `sce` the integer +value into the pointed `val`. + +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. +See [uint64_pack_trim](3) for more. + +The `u64_unpack` family does the same, only unpacking from the byte array `sce` +into `val` + +These are actually macros to the relevant functions, offering a 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. diff --git a/doc/uint64_pack_trim.3.md b/doc/uint64_pack_trim.3.md new file mode 100644 index 0000000..40e599d --- /dev/null +++ b/doc/uint64_pack_trim.3.md @@ -0,0 +1,41 @@ +% limb manual +% uint64_pack_trim(3) + +# NAME + +uint64\_pack\_trim, uint64\_unpack\_trim - pack\/unpack an integer (u64) +into\/from a byte array + +# SYNOPSIS + + #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>) +``` + +# 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. + +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. + +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`. + +# RETURN VALUE + +`uint64_pack_trim`() returns the number of bytes written to into `dst` to pack +`val` + +`uint64_unpack_trim`() returns the number of bytes read from `sce` to unpack +`val` diff --git a/include/limb/int.h b/include/limb/int.h index 013981a..df755ab 100644 --- a/include/limb/int.h +++ b/include/limb/int.h @@ -2,6 +2,8 @@ #define LIMB_INT_H #include <stdint.h> +#include <skalibs/uint64.h> +#include "limb/uint64.h" typedef uint8_t u8; typedef uint16_t u16; @@ -10,4 +12,11 @@ typedef uint64_t u64; extern int msb64(u64 val); +#define u64_pack(val,dst) uint64_pack((char *) (dst), val) +#define u64_unpack(sce,val) uint64_unpack((const char *) (sce), val) +#define u64_pack_big(val,dst) uint64_pack_big((char *) (dst), val) +#define u64_unpack_big(sce,val) uint64_unpack_big((const char *) (sce), val) +#define u64_pack_trim(val,dst) uint64_pack_trim((char *) (dst), val) +#define u64_unpack_trim(sce,val) uint64_unpack_trim((const char *) (sce), val) + #endif /* LIMB_INT_H */ diff --git a/include/limb/uint64.h b/include/limb/uint64.h new file mode 100644 index 0000000..1643bd2 --- /dev/null +++ b/include/limb/uint64.h @@ -0,0 +1,11 @@ +#ifndef LIMB_UINT64_H +#define LIMB_UINT64_H + +#include <stdint.h> + +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); + +#endif /* LIMB_UINT64_H */ diff --git a/meta/deps/skalibs/version b/meta/deps/skalibs/version index 0ab9020..ef9d112 100644 --- a/meta/deps/skalibs/version +++ b/meta/deps/skalibs/version @@ -1 +1 @@ -2.8.0.0 +2.12.0.0 diff --git a/meta/libs/limb b/meta/libs/limb index 9f9e3b7..6e979ab 100644 --- a/meta/libs/limb +++ b/meta/libs/limb @@ -7,6 +7,9 @@ obj/openc_exclat.o obj/openc_createat.o # find msb obj/msb64.o +# {,un}pack u64 +obj/uint64_pack_trim.o +obj/uint64_unpack_trim.o # SHA3 obj/sha3/byte_order.o obj/sha3/rhash_sha3_process_block.o diff --git a/src/uint64_pack_trim.c b/src/uint64_pack_trim.c new file mode 100644 index 0000000..7291506 --- /dev/null +++ b/src/uint64_pack_trim.c @@ -0,0 +1,28 @@ +#include <skalibs/uint64.h> +#include "limb/uint64.h" + +int +uint64_pack_trim(char *dst_, uint64_t val) +{ + uint8_t *dst = (uint8_t *) dst_; + int bits = msb64(val); + int b; + + /* ensure little endianness */ + uint64_littlep(&val); + + for (b = 0; b < 8; ++b) { + int n = bits > 7 ? 7 : bits; + /* store the 7 low bits */ + dst[b] = val & 127; + /* and shift them out */ + val >>= 7; + bits -= n; + if (!bits) + break; + /* add our flag: one more byte */ + dst[b] |= 128; + } + return b + 1; + +} diff --git a/src/uint64_unpack_trim.c b/src/uint64_unpack_trim.c new file mode 100644 index 0000000..05ccf93 --- /dev/null +++ b/src/uint64_unpack_trim.c @@ -0,0 +1,23 @@ +#include "limb/uint64.h" + +int +uint64_unpack_trim(const char *sce_, uint64_t *val) +{ + const uint8_t *sce = (const uint8_t *) sce_; + int b; + + *val = 0; + for (b = 0; b < 9; ++b) { + uint8_t byte = sce[b]; + /* extract the last 7 bits from byte and add them into our val */ + *val |= (byte & 127) << (7 * b); + /* is there another byte to read? */ + if (!(byte & 128)) + break; + } + /* if needed, add the last bit from the last byte */ + if (b == 8 && sce[b] & 128) + *val |= 1ULL << 63; + + return b + 1; +}