blob: 778bf8a6cb21869706393baa1ce8935ef641b971 [file] [log] [blame]
Sergii Dmytruk04bd9652023-11-17 19:31:20 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include "data.h"
4
5#include <ctype.h>
6#include <limits.h>
7#include <stdint.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "utils.h"
13
14void print_data(const uint8_t data[], size_t data_size, enum data_type type)
15{
16 if (data_size == 0)
17 return;
18
19 switch (type) {
20 case DATA_TYPE_BOOL:
21 bool value = false;
22 for (size_t i = 0; i < data_size; ++i) {
23 if (data[i] != 0) {
24 value = true;
25 break;
26 }
27 }
28 printf("%s\n", value ? "true" : "false");
29 break;
30 case DATA_TYPE_UINT8:
31 if (data_size != 1) {
32 fprintf(stderr,
33 "warning: expected size of 1, got %zu\n",
34 data_size);
35 }
36
37 if (data_size >= 1)
38 printf("%u\n", *(uint8_t *)data);
39 break;
40 case DATA_TYPE_UINT16:
41 if (data_size != 2) {
42 fprintf(stderr,
43 "warning: expected size of 2, got %zu\n",
44 data_size);
45 }
46
47 if (data_size >= 2)
48 printf("%u\n", *(uint16_t *)data);
49 break;
50 case DATA_TYPE_UINT32:
51 if (data_size != 4) {
52 fprintf(stderr,
53 "warning: expected size of 4, got %zu\n",
54 data_size);
55 }
56
57 if (data_size >= 4)
58 printf("%u\n", *(uint32_t *)data);
59 break;
60 case DATA_TYPE_ASCII:
61 for (size_t i = 0; i < data_size; ++i) {
62 char c = data[i];
63 if (isprint(c))
64 printf("%c", c);
65 }
66 printf("\n");
67 break;
68 case DATA_TYPE_UNICODE:
69 char *chars = to_chars((const CHAR16 *)data, data_size);
70 printf("%s\n", chars);
71 free(chars);
72 break;
73 case DATA_TYPE_RAW:
74 fwrite(data, 1, data_size, stdout);
75 break;
76 }
77}
78
79static uint64_t parse_uint(const char source[],
80 const char type[],
81 unsigned long long max)
82{
83 char *end;
84 unsigned long long uint = strtoull(source, &end, /*base=*/0);
85 if (*end != '\0') {
86 fprintf(stderr, "Trailing characters in \"%s\": %s\n",
87 source, end);
88 return UINT64_MAX;
89 }
90 if (uint > max) {
91 fprintf(stderr, "Invalid %s value: %llu\n", type, uint);
92 return UINT64_MAX;
93 }
94
95 return uint;
96}
97
98void *make_data(const char source[], size_t *data_size, enum data_type type)
99{
100 switch (type) {
101 void *data;
102 bool boolean;
103 unsigned long long uint;
104
105 case DATA_TYPE_BOOL:
106 if (str_eq(source, "true")) {
107 boolean = true;
108 } else if (str_eq(source, "false")) {
109 boolean = false;
110 } else {
111 fprintf(stderr, "Invalid boolean value: \"%s\"\n",
112 source);
113 return NULL;
114 }
115
116 *data_size = 1;
117 data = xmalloc(*data_size);
118 *(uint8_t *)data = boolean;
119 return data;
120 case DATA_TYPE_UINT8:
121 uint = parse_uint(source, "uint8", UINT8_MAX);
122 if (uint == UINT64_MAX)
123 return NULL;
124
125 *data_size = 1;
126 data = xmalloc(*data_size);
127 *(uint8_t *)data = uint;
128 return data;
129 case DATA_TYPE_UINT16:
130 uint = parse_uint(source, "uint16", UINT16_MAX);
131 if (uint == UINT64_MAX)
132 return NULL;
133
134 *data_size = 2;
135 data = xmalloc(*data_size);
136 *(uint16_t *)data = uint;
137 return data;
138 case DATA_TYPE_UINT32:
139 uint = parse_uint(source, "uint32", UINT32_MAX);
140 if (uint == UINT64_MAX)
141 return NULL;
142
143 *data_size = 4;
144 data = xmalloc(*data_size);
145 *(uint32_t *)data = uint;
146 return data;
147 case DATA_TYPE_ASCII:
148 *data_size = strlen(source) + 1;
149 return strdup(source);
150 case DATA_TYPE_UNICODE:
151 return to_uchars(source, data_size);
152 case DATA_TYPE_RAW:
153 fprintf(stderr, "Raw data type is output only\n");
154 return NULL;
155 }
156
157 return NULL;
158}
159
160bool parse_data_type(const char str[], enum data_type *type)
161{
162 if (str_eq(str, "bool"))
163 *type = DATA_TYPE_BOOL;
164 else if (str_eq(str, "uint8"))
165 *type = DATA_TYPE_UINT8;
166 else if (str_eq(str, "uint16"))
167 *type = DATA_TYPE_UINT16;
168 else if (str_eq(str, "uint32"))
169 *type = DATA_TYPE_UINT32;
170 else if (str_eq(str, "ascii"))
171 *type = DATA_TYPE_ASCII;
172 else if (str_eq(str, "unicode"))
173 *type = DATA_TYPE_UNICODE;
174 else if (str_eq(str, "raw"))
175 *type = DATA_TYPE_RAW;
176 else
177 return false;
178
179 return true;
180}