summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--util/argconfig.c45
-rw-r--r--util/argconfig.h2
-rw-r--r--util/json.c41
-rw-r--r--util/json.h20
-rw-r--r--util/meson.build1
-rw-r--r--util/types.c99
-rw-r--r--util/types.h35
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 */