1 /**
2 * @file lv_xml_utils.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_xml_utils.h"
10 #include "../../stdlib/lv_string.h"
11 #if LV_USE_XML
12
13 #if LV_USE_STDLIB_STRING == LV_STDLIB_CLIB
14 #include <stdlib.h>
15 #endif
16
17 /*********************
18 * DEFINES
19 *********************/
20
21 /**********************
22 * TYPEDEFS
23 **********************/
24
25 /**********************
26 * STATIC PROTOTYPES
27 **********************/
28 static bool is_digit(char c, int base);
29
30 /**********************
31 * STATIC VARIABLES
32 **********************/
33
34 /**********************
35 * MACROS
36 **********************/
37
38 /**********************
39 * GLOBAL FUNCTIONS
40 **********************/
41
42
lv_xml_get_value_of(const char ** attrs,const char * name)43 const char * lv_xml_get_value_of(const char ** attrs, const char * name)
44 {
45 if(attrs == NULL) return NULL;
46 if(name == NULL) return NULL;
47
48 for(int i = 0; attrs[i]; i += 2) {
49 if(lv_streq(attrs[i], name)) return attrs[i + 1];
50 }
51
52 return NULL;
53 }
54
lv_xml_to_color(const char * str)55 lv_color_t lv_xml_to_color(const char * str)
56 {
57 return lv_color_hex(lv_xml_strtol(str, NULL, 16));
58 }
59
lv_xml_to_opa(const char * str)60 lv_opa_t lv_xml_to_opa(const char * str)
61 {
62 int32_t v = lv_xml_atoi(str);
63 size_t len = lv_strlen(str);
64 if(str[len - 1] == '%') {
65 v = v * 255 / 100;
66 }
67
68 v = LV_CLAMP(0, v, 255);
69 return (lv_opa_t)v;
70 }
71
lv_xml_to_bool(const char * str)72 bool lv_xml_to_bool(const char * str)
73 {
74 return lv_streq(str, "false") ? false : true;
75 }
76
lv_xml_atoi_split(const char ** str,char delimiter)77 int32_t lv_xml_atoi_split(const char ** str, char delimiter)
78 {
79 const char * s = *str;
80 int32_t result = 0;
81 int sign = 1;
82
83 /* Skip leading whitespace */
84 while(*s == ' ' || *s == '\t') s++;
85
86 /* Handle optional sign */
87 if(*s == '-') {
88 sign = -1;
89 s++;
90 }
91 else if(*s == '+') {
92 s++;
93 }
94
95 /* Convert the string*/
96 while(*s != delimiter) {
97 if(*s >= '0' && *s <= '9') {
98 int32_t digit = *s - '0';
99
100 result = result * 10 + digit;
101 s++;
102 }
103 else {
104 break; /* Non-digit character */
105 }
106 }
107
108 result = result * sign;
109
110 if(*s != '\0') s++; /*Skip the delimiter*/
111 *str = s;
112 return result;
113
114 }
115
116
lv_xml_atoi(const char * str)117 int32_t lv_xml_atoi(const char * str)
118 {
119
120 return lv_xml_atoi_split(&str, '\0');
121
122 }
123
lv_xml_strtol(const char * str,char ** endptr,int32_t base)124 int32_t lv_xml_strtol(const char * str, char ** endptr, int32_t base)
125 {
126 const char * s = str;
127 int32_t result = 0;
128 int32_t sign = 1;
129
130 /* Skip leading whitespace */
131 while(*s == ' ' || *s == '\t') s++;
132
133 /* Handle optional sign*/
134 if(*s == '-') {
135 sign = -1;
136 s++;
137 }
138 else if(*s == '+') {
139 s++;
140 }
141
142 /* Determine base if 0 is passed as base*/
143 if(base == 0) {
144 if(*s == '0') {
145 if(*(s + 1) == 'x' || *(s + 1) == 'X') {
146 base = 16;
147 s += 2;
148 }
149 else {
150 base = 8;
151 s++;
152 }
153 }
154 else {
155 base = 10;
156 }
157 }
158
159 /* Convert the string*/
160 while(*s) {
161 int32_t digit;
162
163 if(is_digit(*s, base)) {
164 if(*s >= '0' && *s <= '9') {
165 digit = *s - '0';
166 }
167 else if(*s >= 'a' && *s <= 'f') {
168 digit = *s - 'a' + 10;
169 }
170 else if(*s >= 'A' && *s <= 'F') {
171 digit = *s - 'A' + 10;
172 }
173 else {
174 /* This should not happen due to is_digit check*/
175 break;
176 }
177
178 /* Check for overflow */
179 if(result > (INT32_MAX - digit) / base) {
180 result = (sign == 1) ? INT32_MAX : INT32_MIN;
181 if(endptr) *endptr = (char *)s;
182 return result;
183 }
184
185 result = result * base + digit;
186 }
187 s++;
188 }
189
190 /* Set end pointer to the last character processed*/
191 if(endptr) {
192 *endptr = (char *)s;
193 }
194
195 return result * sign;
196 }
197
lv_xml_split_str(char ** src,char delimiter)198 char * lv_xml_split_str(char ** src, char delimiter)
199 {
200 if(*src[0] == '\0') return NULL;
201
202 char * src_first = *src;
203 char * src_next = *src;
204
205 /*Find the delimiter*/
206 while(*src_next != '\0') {
207 if(*src_next == delimiter) {
208 *src_next = '\0'; /*Close the string on the delimiter*/
209 *src = src_next + 1; /*Change the source continue after the found delimiter*/
210 return src_first;
211 }
212 src_next++;
213 }
214
215 /*No delimiter found, return the string as it is*/
216 *src = src_next; /*Move the source point to the end*/
217
218 return src_first;
219 }
220
221 /**********************
222 * STATIC FUNCTIONS
223 **********************/
224
is_digit(char c,int base)225 static bool is_digit(char c, int base)
226 {
227 if(base <= 10) {
228 return (c >= '0' && c < '0' + base);
229 }
230 else {
231 return (c >= '0' && c <= '9') || (c >= 'a' && c < 'a' + (base - 10)) || (c >= 'A' && c < 'A' + (base - 10));
232 }
233 }
234
235
236 #endif /* LV_USE_XML */
237