blob: 41d3b75aba8082b51fd77942f36e8f63ed86af75 [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;
Sergii Dmytrukd20cc992024-05-22 20:41:02 +030060 case DATA_TYPE_UINT64:
61 if (data_size != 8) {
62 fprintf(stderr,
63 "warning: expected size of 8, got %zu\n",
64 data_size);
65 }
66
67 if (data_size >= 8)
68 printf("%llu\n", (unsigned long long)*(uint64_t *)data);
69 break;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +020070 case DATA_TYPE_ASCII:
71 for (size_t i = 0; i < data_size; ++i) {
72 char c = data[i];
73 if (isprint(c))
74 printf("%c", c);
75 }
76 printf("\n");
77 break;
78 case DATA_TYPE_UNICODE:
79 char *chars = to_chars((const CHAR16 *)data, data_size);
80 printf("%s\n", chars);
81 free(chars);
82 break;
83 case DATA_TYPE_RAW:
84 fwrite(data, 1, data_size, stdout);
85 break;
86 }
87}
88
89static uint64_t parse_uint(const char source[],
90 const char type[],
Sergii Dmytrukd20cc992024-05-22 20:41:02 +030091 unsigned long long max,
92 bool *failed)
Sergii Dmytruk04bd9652023-11-17 19:31:20 +020093{
94 char *end;
95 unsigned long long uint = strtoull(source, &end, /*base=*/0);
96 if (*end != '\0') {
97 fprintf(stderr, "Trailing characters in \"%s\": %s\n",
98 source, end);
Sergii Dmytrukd20cc992024-05-22 20:41:02 +030099 *failed = true;
100 return 0;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200101 }
102 if (uint > max) {
103 fprintf(stderr, "Invalid %s value: %llu\n", type, uint);
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300104 *failed = true;
105 return 0;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200106 }
107
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300108 *failed = false;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200109 return uint;
110}
111
112void *make_data(const char source[], size_t *data_size, enum data_type type)
113{
114 switch (type) {
115 void *data;
116 bool boolean;
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300117 uint64_t uint;
118 bool failed;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200119
120 case DATA_TYPE_BOOL:
121 if (str_eq(source, "true")) {
122 boolean = true;
123 } else if (str_eq(source, "false")) {
124 boolean = false;
125 } else {
126 fprintf(stderr, "Invalid boolean value: \"%s\"\n",
127 source);
128 return NULL;
129 }
130
131 *data_size = 1;
132 data = xmalloc(*data_size);
133 *(uint8_t *)data = boolean;
134 return data;
135 case DATA_TYPE_UINT8:
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300136 uint = parse_uint(source, "uint8", UINT8_MAX, &failed);
137 if (failed)
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200138 return NULL;
139
140 *data_size = 1;
141 data = xmalloc(*data_size);
142 *(uint8_t *)data = uint;
143 return data;
144 case DATA_TYPE_UINT16:
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300145 uint = parse_uint(source, "uint16", UINT16_MAX, &failed);
146 if (failed)
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200147 return NULL;
148
149 *data_size = 2;
150 data = xmalloc(*data_size);
151 *(uint16_t *)data = uint;
152 return data;
153 case DATA_TYPE_UINT32:
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300154 uint = parse_uint(source, "uint32", UINT32_MAX, &failed);
155 if (failed)
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200156 return NULL;
157
158 *data_size = 4;
159 data = xmalloc(*data_size);
160 *(uint32_t *)data = uint;
161 return data;
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300162 case DATA_TYPE_UINT64:
163 uint = parse_uint(source, "uint64", UINT64_MAX, &failed);
164 if (failed)
165 return NULL;
166
167 *data_size = 8;
168 data = xmalloc(*data_size);
169 *(uint64_t *)data = uint;
170 return data;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200171 case DATA_TYPE_ASCII:
172 *data_size = strlen(source) + 1;
173 return strdup(source);
174 case DATA_TYPE_UNICODE:
175 return to_uchars(source, data_size);
176 case DATA_TYPE_RAW:
177 fprintf(stderr, "Raw data type is output only\n");
178 return NULL;
179 }
180
181 return NULL;
182}
183
184bool parse_data_type(const char str[], enum data_type *type)
185{
186 if (str_eq(str, "bool"))
187 *type = DATA_TYPE_BOOL;
188 else if (str_eq(str, "uint8"))
189 *type = DATA_TYPE_UINT8;
190 else if (str_eq(str, "uint16"))
191 *type = DATA_TYPE_UINT16;
192 else if (str_eq(str, "uint32"))
193 *type = DATA_TYPE_UINT32;
Sergii Dmytrukd20cc992024-05-22 20:41:02 +0300194 else if (str_eq(str, "uint64"))
195 *type = DATA_TYPE_UINT64;
Sergii Dmytruk04bd9652023-11-17 19:31:20 +0200196 else if (str_eq(str, "ascii"))
197 *type = DATA_TYPE_ASCII;
198 else if (str_eq(str, "unicode"))
199 *type = DATA_TYPE_UNICODE;
200 else if (str_eq(str, "raw"))
201 *type = DATA_TYPE_RAW;
202 else
203 return false;
204
205 return true;
206}