From 5c79b8140ce5fb6686c3ced3d8d08940a66e3ea5 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 4 Feb 2025 12:52:37 +0000 Subject: [PATCH] implement converting container/tag identifiers to/from strings --- src/misc.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/misc.h | 18 ++++++++-- 2 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 src/misc.c diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..a8f02c4 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,104 @@ +#include "misc.h" + +#include +#include +#include +#include +#include +#include + +static enum ec3_status identifier_from_int_string( + const char *s, + uint64_t *out, + int base) +{ + /* skip leading '0x' */ + s += 2; + char *ep = NULL; + uint64_t v = strtoull(s, &ep, base); + + if (!ep || *ep != '\0') { + return EC3_ERR_INVALID_VALUE; + } + + *out = v; + return EC3_SUCCESS; +} + +static bool is_base10_string(const char *s) +{ + for (unsigned int i = 0; s[i]; i++) { + if (!isdigit(s[i])) { + return false; + } + } + + return true; +} + +enum ec3_status ec3_identifier_from_string(const char *s, uint64_t *out) +{ + if (s[0] == '0' && s[1] == 'x') { + return identifier_from_int_string(s, out, 16); + } + + if (is_base10_string(s)) { + return identifier_from_int_string(s, out, 10); + } + + b_i64 v = {0}; + + for (unsigned int i = 0; s[i]; i++) { + if (i > sizeof *out) { + return EC3_ERR_INVALID_VALUE; + } + + v.i_bytes[i] = s[i]; + } + + *out = b_i64_btoh(v); + return EC3_SUCCESS; +} + +enum ec3_status ec3_identifier_to_string(uint64_t id, char *out, size_t max) +{ + if (id == 0) { + snprintf(out, max, "%016llx", id); + return EC3_SUCCESS; + } + + bool is_ascii = true; + bool zero_only = false; + + b_i64 v = b_i64_htob(id); + + for (unsigned int i = 0; i < sizeof v; i++) { + int c = v.i_bytes[i]; + + if (c != 0 && zero_only) { + is_ascii = false; + } + + if (c == 0) { + zero_only = true; + continue; + } + + if (c < 32 || c > 126) { + is_ascii = false; + } + } + + if (is_ascii) { + char str[9]; + memcpy(str, v.i_bytes, sizeof v); + str[8] = 0; + + strncpy(out, str, max - 1); + out[max - 1] = 0; + } else { + snprintf(out, max, "%016llx", id); + } + + return EC3_SUCCESS; +} diff --git a/src/misc.h b/src/misc.h index 49eb2e2..79a6cf4 100644 --- a/src/misc.h +++ b/src/misc.h @@ -1,12 +1,24 @@ #ifndef MISC_H_ #define MISC_H_ +#include "status.h" + +#include +#include + #ifdef __GNUC__ -#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#define PACK(__Declaration__) __Declaration__ __attribute__((__packed__)) #endif #ifdef _MSC_VER -#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +#define PACK(__Declaration__) \ + __pragma(pack(push, 1)) __Declaration__ __pragma(pack(pop)) #endif -#endif \ No newline at end of file +extern enum ec3_status ec3_identifier_from_string(const char *s, uint64_t *out); +extern enum ec3_status ec3_identifier_to_string( + uint64_t id, + char *out, + size_t max); + +#endif