/* SPDX-License-Identifier: GPL-2.0-or-later */ #include "data.h" #include #include #include #include #include #include #include "utils.h" void print_data(const uint8_t data[], size_t data_size, enum data_type type) { if (data_size == 0) return; switch (type) { case DATA_TYPE_BOOL: bool value = false; for (size_t i = 0; i < data_size; ++i) { if (data[i] != 0) { value = true; break; } } printf("%s\n", value ? "true" : "false"); break; case DATA_TYPE_UINT8: if (data_size != 1) { fprintf(stderr, "warning: expected size of 1, got %zu\n", data_size); } if (data_size >= 1) printf("%u\n", *(uint8_t *)data); break; case DATA_TYPE_UINT16: if (data_size != 2) { fprintf(stderr, "warning: expected size of 2, got %zu\n", data_size); } if (data_size >= 2) printf("%u\n", *(uint16_t *)data); break; case DATA_TYPE_UINT32: if (data_size != 4) { fprintf(stderr, "warning: expected size of 4, got %zu\n", data_size); } if (data_size >= 4) printf("%u\n", *(uint32_t *)data); break; case DATA_TYPE_ASCII: for (size_t i = 0; i < data_size; ++i) { char c = data[i]; if (isprint(c)) printf("%c", c); } printf("\n"); break; case DATA_TYPE_UNICODE: char *chars = to_chars((const CHAR16 *)data, data_size); printf("%s\n", chars); free(chars); break; case DATA_TYPE_RAW: fwrite(data, 1, data_size, stdout); break; } } static uint64_t parse_uint(const char source[], const char type[], unsigned long long max) { char *end; unsigned long long uint = strtoull(source, &end, /*base=*/0); if (*end != '\0') { fprintf(stderr, "Trailing characters in \"%s\": %s\n", source, end); return UINT64_MAX; } if (uint > max) { fprintf(stderr, "Invalid %s value: %llu\n", type, uint); return UINT64_MAX; } return uint; } void *make_data(const char source[], size_t *data_size, enum data_type type) { switch (type) { void *data; bool boolean; unsigned long long uint; case DATA_TYPE_BOOL: if (str_eq(source, "true")) { boolean = true; } else if (str_eq(source, "false")) { boolean = false; } else { fprintf(stderr, "Invalid boolean value: \"%s\"\n", source); return NULL; } *data_size = 1; data = xmalloc(*data_size); *(uint8_t *)data = boolean; return data; case DATA_TYPE_UINT8: uint = parse_uint(source, "uint8", UINT8_MAX); if (uint == UINT64_MAX) return NULL; *data_size = 1; data = xmalloc(*data_size); *(uint8_t *)data = uint; return data; case DATA_TYPE_UINT16: uint = parse_uint(source, "uint16", UINT16_MAX); if (uint == UINT64_MAX) return NULL; *data_size = 2; data = xmalloc(*data_size); *(uint16_t *)data = uint; return data; case DATA_TYPE_UINT32: uint = parse_uint(source, "uint32", UINT32_MAX); if (uint == UINT64_MAX) return NULL; *data_size = 4; data = xmalloc(*data_size); *(uint32_t *)data = uint; return data; case DATA_TYPE_ASCII: *data_size = strlen(source) + 1; return strdup(source); case DATA_TYPE_UNICODE: return to_uchars(source, data_size); case DATA_TYPE_RAW: fprintf(stderr, "Raw data type is output only\n"); return NULL; } return NULL; } bool parse_data_type(const char str[], enum data_type *type) { if (str_eq(str, "bool")) *type = DATA_TYPE_BOOL; else if (str_eq(str, "uint8")) *type = DATA_TYPE_UINT8; else if (str_eq(str, "uint16")) *type = DATA_TYPE_UINT16; else if (str_eq(str, "uint32")) *type = DATA_TYPE_UINT32; else if (str_eq(str, "ascii")) *type = DATA_TYPE_ASCII; else if (str_eq(str, "unicode")) *type = DATA_TYPE_UNICODE; else if (str_eq(str, "raw")) *type = DATA_TYPE_RAW; else return false; return true; }