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