diff options
Diffstat (limited to '')
-rw-r--r-- | util/argconfig.c | 45 | ||||
-rw-r--r-- | util/argconfig.h | 2 | ||||
-rw-r--r-- | util/json.c | 41 | ||||
-rw-r--r-- | util/json.h | 20 | ||||
-rw-r--r-- | util/meson.build | 1 | ||||
-rw-r--r-- | util/types.c | 99 | ||||
-rw-r--r-- | util/types.h | 35 |
7 files changed, 234 insertions, 9 deletions
diff --git a/util/argconfig.c b/util/argconfig.c index d09ba9d..2c328ff 100644 --- a/util/argconfig.c +++ b/util/argconfig.c @@ -488,6 +488,51 @@ int argconfig_parse_comma_sep_array(char *string, int *val, } } +int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val, + unsigned max_length) +{ + int ret = 0; + unsigned long v; + char *tmp; + char *p; + + if (!string || !strlen(string)) + return 0; + + tmp = strtok(string, ","); + if (!tmp) + return 0; + + v = strtoul(tmp, &p, 0); + if (*p != 0) + return -1; + if (v > UINT16_MAX) { + fprintf(stderr, "%s out of range\n", tmp); + return -1; + } + val[ret] = v; + ret++; + + while (1) { + tmp = strtok(NULL, ","); + if (tmp == NULL) + return ret; + + if (ret >= max_length) + return -1; + + v = strtoul(tmp, &p, 0); + if (*p != 0) + return -1; + if (v > UINT16_MAX) { + fprintf(stderr, "%s out of range\n", tmp); + return -1; + } + val[ret] = v; + ret++; + } +} + int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val, unsigned max_length) diff --git a/util/argconfig.h b/util/argconfig.h index de715b1..b66706a 100644 --- a/util/argconfig.h +++ b/util/argconfig.h @@ -126,6 +126,8 @@ int argconfig_parse_subopt_string(char *string, char **options, size_t max_options); int argconfig_parse_comma_sep_array(char *string, int *ret, unsigned max_length); +int argconfig_parse_comma_sep_array_short(char *string, unsigned short *ret, + unsigned max_length); int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *ret, unsigned max_length); diff --git a/util/json.c b/util/json.c index fd52861..84d43e5 100644 --- a/util/json.c +++ b/util/json.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <stdio.h> +#include <errno.h> #include "json.h" +#include "types.h" struct json_object *util_json_object_new_double(long double d) { @@ -17,3 +19,42 @@ struct json_object *util_json_object_new_double(long double d) return obj; } + +struct json_object *util_json_object_new_uint64(uint64_t i) +{ + struct json_object *obj; + char *str; + + if (asprintf(&str, "%" PRIu64, i) < 0) + return NULL; + + obj = json_object_new_string(str); + + free(str); + return obj; + +} + +struct json_object *util_json_object_new_uint128(nvme_uint128_t val) +{ + struct json_object *obj; + obj = json_object_new_string(uint128_t_to_string(val)); + return obj; +} + +uint64_t util_json_object_get_uint64(struct json_object *obj) +{ + uint64_t val = 0; + + if (json_object_is_type(obj, json_type_string)) { + char *end = NULL; + const char *buf; + + buf = json_object_get_string(obj); + val = strtoull(buf, &end, 10); + if ((val == 0 && errno != 0) || (end == buf)) + return 0; + } + + return val; +} diff --git a/util/json.h b/util/json.h index 2b8022a..1312cb8 100644 --- a/util/json.h +++ b/util/json.h @@ -3,6 +3,7 @@ #define __JSON__H #include <json.h> +#include "util/types.h" /* Wrappers around json-c's API */ @@ -14,17 +15,14 @@ json_object_object_add(o, k, json_object_new_int(v)) #define json_object_add_value_int(o, k, v) \ json_object_object_add(o, k, json_object_new_int(v)) -#ifdef CONFIG_JSONC_14 +#ifndef CONFIG_JSONC_14 +#define json_object_new_uint64(v) util_json_object_new_uint64(v) +#define json_object_get_uint64(v) util_json_object_get_uint64(v) +#endif #define json_object_add_value_uint64(o, k, v) \ json_object_object_add(o, k, json_object_new_uint64(v)) -#else -#define json_object_add_value_uint64(o, k, v) \ - if ((v) > UINT_MAX) { \ - fprintf(stderr, "Value overflow in %s", k); \ - json_object_object_add(o, k, json_object_new_int(-1)); \ - } else \ - json_object_object_add(o, k, json_object_new_int(v)) -#endif +#define json_object_add_value_uint128(o, k, v) \ + json_object_object_add(o, k, util_json_object_new_uint128(v)) #define json_object_add_value_double(o, k, v) \ json_object_object_add(o, k, util_json_object_new_double(v)) #define json_object_add_value_float(o, k, v) \ @@ -45,5 +43,9 @@ JSON_C_TO_STRING_NOSLASHESCAPE)) struct json_object *util_json_object_new_double(long double d); +struct json_object *util_json_object_new_uint64(uint64_t i); +struct json_object *util_json_object_new_uint128(nvme_uint128_t val); +struct json_object *util_json_object_new_uint128(nvme_uint128_t val); +uint64_t util_json_object_get_uint64(struct json_object *obj); #endif diff --git a/util/meson.build b/util/meson.build index a999b80..349c70c 100644 --- a/util/meson.build +++ b/util/meson.build @@ -6,4 +6,5 @@ sources += [ 'util/json.c', 'util/suffix.c', 'util/base64.c', + 'util/types.c', ] diff --git a/util/types.c b/util/types.c new file mode 100644 index 0000000..06bb8d4 --- /dev/null +++ b/util/types.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <inttypes.h> +#include <stdio.h> +#include <string.h> + +#include <ccan/endian/endian.h> + +#include "types.h" + +nvme_uint128_t le128_to_cpu(__u8 *data) +{ + nvme_uint128_t u; + nvme_uint128_t tmp; + memcpy(tmp.bytes, data, 16); + u.words[0] = le32_to_cpu(tmp.words[3]); + u.words[1] = le32_to_cpu(tmp.words[2]); + u.words[2] = le32_to_cpu(tmp.words[1]); + u.words[3] = le32_to_cpu(tmp.words[0]); + return u; +} + +long double int128_to_double(__u8 *data) +{ + int i; + long double result = 0; + + for (i = 0; i < 16; i++) { + result *= 256; + result += data[15 - i]; + } + return result; +} + +uint64_t int48_to_long(__u8 *data) +{ + int i; + uint64_t result = 0; + + for (i = 0; i < 6; i++) { + result *= 256; + result += data[5 - i]; + } + return result; +} + +char *uint128_t_to_string(nvme_uint128_t val) +{ + static char str[40]; + int idx = 40; + __u64 div, rem; + + /* terminate at the end, and build up from the ones */ + str[--idx] = '\0'; + + do { + rem = val.words[0]; + + div = rem / 10; + rem = ((rem - div * 10) << 32) + val.words[1]; + val.words[0] = div; + + div = rem / 10; + rem = ((rem - div * 10) << 32) + val.words[2]; + val.words[1] = div; + + div = rem / 10; + rem = ((rem - div * 10) << 32) + val.words[3]; + val.words[2] = div; + + div = rem / 10; + rem = rem - div * 10; + val.words[3] = div; + + str[--idx] = '0' + rem; + } while (val.words[0] || val.words[1] || val.words[2] || val.words[3]); + + return str + idx; +} + +const char *util_uuid_to_string(unsigned char uuid[NVME_UUID_LEN]) +{ + static char uuid_str[NVME_UUID_LEN_STRING]; + + nvme_uuid_to_string(uuid, uuid_str); + + return uuid_str; +} + +const char *util_fw_to_string(char *c) +{ + static char ret[9]; + int i; + + for (i = 0; i < 8; i++) + ret[i] = c[i] >= '!' && c[i] <= '~' ? c[i] : '.'; + ret[i] = '\0'; + return ret; +} diff --git a/util/types.h b/util/types.h new file mode 100644 index 0000000..6d45108 --- /dev/null +++ b/util/types.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _MISC_H +#define _MISC_H + +/* type conversion helpers */ + +#include <stdint.h> +#include <linux/types.h> + +#include <libnvme.h> + +#define ABSOLUTE_ZERO_CELSIUS -273 + +static inline long kelvin_to_celsius(long t) +{ + return t + ABSOLUTE_ZERO_CELSIUS; +} + +/* uint128_t is not always available, define our own. */ +union nvme_uint128 { + __u8 bytes[16]; + __u32 words[4]; /* [0] is most significant word */ +}; + +typedef union nvme_uint128 nvme_uint128_t; + +nvme_uint128_t le128_to_cpu(__u8 *data); +long double int128_to_double(__u8 *data); +uint64_t int48_to_long(__u8 *data); + +char *uint128_t_to_string(nvme_uint128_t val); +const char *util_uuid_to_string(unsigned char uuid[NVME_UUID_LEN]); +const char *util_fw_to_string(char *c); + +#endif /* _MISC_H */ |