1 /**
2 * @file lv_string.c
3 */
4
5 /*********************
6 * INCLUDES
7 *********************/
8 #include "../../lv_conf_internal.h"
9 #if LV_USE_STDLIB_STRING == LV_STDLIB_BUILTIN
10 #include "../../misc/lv_assert.h"
11 #include "../../misc/lv_log.h"
12 #include "../../misc/lv_math.h"
13 #include "../../stdlib/lv_string.h"
14 #include "../../stdlib/lv_mem.h"
15
16 /*********************
17 * DEFINES
18 *********************/
19 #ifdef LV_ARCH_64
20 #define MEM_UNIT uint64_t
21 #define ALIGN_MASK 0x7
22 #else
23 #define MEM_UNIT uint32_t
24 #define ALIGN_MASK 0x3
25 #endif
26
27 /**********************
28 * TYPEDEFS
29 **********************/
30
31 /**********************
32 * STATIC PROTOTYPES
33 **********************/
34
35 /**********************
36 * STATIC VARIABLES
37 **********************/
38
39 /**********************
40 * MACROS
41 **********************/
42 #if LV_USE_LOG && LV_LOG_TRACE_MEM
43 #define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__)
44 #else
45 #define LV_TRACE_MEM(...)
46 #endif
47
48 #define _COPY(d, s) *d = *s; d++; s++;
49 #define _SET(d, v) *d = v; d++;
50 #define _REPEAT8(expr) expr expr expr expr expr expr expr expr
51
52 /**********************
53 * GLOBAL FUNCTIONS
54 **********************/
55
lv_memcpy(void * dst,const void * src,size_t len)56 void * LV_ATTRIBUTE_FAST_MEM lv_memcpy(void * dst, const void * src, size_t len)
57 {
58 uint8_t * d8 = dst;
59 const uint8_t * s8 = src;
60
61 /*Simplify for small memories*/
62 if(len < 16) {
63 while(len) {
64 *d8 = *s8;
65 d8++;
66 s8++;
67 len--;
68 }
69 return dst;
70 }
71
72 lv_uintptr_t d_align = (lv_uintptr_t)d8 & ALIGN_MASK;
73 lv_uintptr_t s_align = (lv_uintptr_t)s8 & ALIGN_MASK;
74
75 /*Byte copy for unaligned memories*/
76 if(s_align != d_align) {
77 while(len > 32) {
78 _REPEAT8(_COPY(d8, s8));
79 _REPEAT8(_COPY(d8, s8));
80 _REPEAT8(_COPY(d8, s8));
81 _REPEAT8(_COPY(d8, s8));
82 len -= 32;
83 }
84 while(len) {
85 _COPY(d8, s8)
86 len--;
87 }
88 return dst;
89 }
90
91 /*Make the memories aligned*/
92 if(d_align) {
93 d_align = ALIGN_MASK + 1 - d_align;
94 while(d_align && len) {
95 _COPY(d8, s8);
96 d_align--;
97 len--;
98 }
99 }
100
101 uint32_t * d32 = (uint32_t *)d8;
102 const uint32_t * s32 = (uint32_t *)s8;
103 while(len > 32) {
104 _REPEAT8(_COPY(d32, s32))
105 len -= 32;
106 }
107
108 d8 = (uint8_t *)d32;
109 s8 = (const uint8_t *)s32;
110 while(len) {
111 _COPY(d8, s8)
112 len--;
113 }
114
115 return dst;
116 }
117
lv_memset(void * dst,uint8_t v,size_t len)118 void LV_ATTRIBUTE_FAST_MEM lv_memset(void * dst, uint8_t v, size_t len)
119 {
120 uint8_t * d8 = (uint8_t *)dst;
121 uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;
122
123 /*Make the address aligned*/
124 if(d_align) {
125 d_align = ALIGN_MASK + 1 - d_align;
126 while(d_align && len) {
127 _SET(d8, v);
128 len--;
129 d_align--;
130 }
131 }
132
133 uint32_t v32 = (uint32_t)v + ((uint32_t)v << 8) + ((uint32_t)v << 16) + ((uint32_t)v << 24);
134 uint32_t * d32 = (uint32_t *)d8;
135
136 while(len > 32) {
137 _REPEAT8(_SET(d32, v32));
138 len -= 32;
139 }
140
141 d8 = (uint8_t *)d32;
142 while(len) {
143 _SET(d8, v);
144 len--;
145 }
146 }
147
lv_memmove(void * dst,const void * src,size_t len)148 void * LV_ATTRIBUTE_FAST_MEM lv_memmove(void * dst, const void * src, size_t len)
149 {
150 if(dst < src || (char *)dst > ((char *)src + len)) {
151 return lv_memcpy(dst, src, len);
152 }
153
154 if(dst > src) {
155 char * tmp = (char *)dst + len - 1;
156 char * s = (char *)src + len - 1;
157
158 while(len--) {
159 *tmp-- = *s--;
160 }
161 }
162 else {
163 char * tmp = (char *)dst;
164 char * s = (char *)src;
165
166 while(len--) {
167 *tmp++ = *s++;
168 }
169 }
170
171 return dst;
172 }
173
lv_memcmp(const void * p1,const void * p2,size_t len)174 int lv_memcmp(const void * p1, const void * p2, size_t len)
175 {
176 const char * s1 = (const char *) p1;
177 const char * s2 = (const char *) p2;
178 while(--len > 0 && (*s1 == *s2)) {
179 s1++;
180 s2++;
181 }
182 return *s1 - *s2;
183 }
184
185 /* See https://en.cppreference.com/w/c/string/byte/strlen for reference */
lv_strlen(const char * str)186 size_t lv_strlen(const char * str)
187 {
188 size_t i = 0;
189 while(str[i]) i++;
190
191 return i;
192 }
193
lv_strlcpy(char * dst,const char * src,size_t dst_size)194 size_t lv_strlcpy(char * dst, const char * src, size_t dst_size)
195 {
196 size_t i = 0;
197 if(dst_size > 0) {
198 for(; i < dst_size - 1 && src[i]; i++) {
199 dst[i] = src[i];
200 }
201 dst[i] = '\0';
202 }
203 while(src[i]) i++;
204 return i;
205 }
206
lv_strncpy(char * dst,const char * src,size_t dst_size)207 char * lv_strncpy(char * dst, const char * src, size_t dst_size)
208 {
209 size_t i;
210 for(i = 0; i < dst_size && src[i]; i++) {
211 dst[i] = src[i];
212 }
213 for(; i < dst_size; i++) {
214 dst[i] = '\0';
215 }
216 return dst;
217 }
218
lv_strcpy(char * dst,const char * src)219 char * lv_strcpy(char * dst, const char * src)
220 {
221 char * tmp = dst;
222 while((*dst++ = *src++) != '\0');
223 return tmp;
224 }
225
lv_strcmp(const char * s1,const char * s2)226 int lv_strcmp(const char * s1, const char * s2)
227 {
228 while(*s1 && (*s1 == *s2)) {
229 s1++;
230 s2++;
231 }
232 return *(const unsigned char *)s1 - *(const unsigned char *)s2;
233 }
234
lv_strncmp(const char * s1,const char * s2,size_t len)235 int lv_strncmp(const char * s1, const char * s2, size_t len)
236 {
237 if(len == 0) {
238 return 0;
239 }
240
241 while(len > 0 && *s1 && (*s1 == *s2)) {
242 if(--len == 0) {
243 return 0;
244 }
245 s1++;
246 s2++;
247 }
248 return *(const unsigned char *)s1 - *(const unsigned char *)s2;
249 }
250
lv_strdup(const char * src)251 char * lv_strdup(const char * src)
252 {
253 size_t len = lv_strlen(src) + 1;
254 char * dst = lv_malloc(len);
255 if(dst == NULL) return NULL;
256
257 lv_memcpy(dst, src, len); /*memcpy is faster than strncpy when length is known*/
258 return dst;
259 }
260
lv_strcat(char * dst,const char * src)261 char * lv_strcat(char * dst, const char * src)
262 {
263 lv_strcpy(dst + lv_strlen(dst), src);
264 return dst;
265 }
266
lv_strncat(char * dst,const char * src,size_t src_len)267 char * lv_strncat(char * dst, const char * src, size_t src_len)
268 {
269 char * tmp = dst;
270 while(*dst != '\0') {
271 dst++;
272 }
273 while(src_len != 0 && *src != '\0') {
274 src_len--;
275 *dst++ = *src++;
276 }
277 *dst = '\0';
278 return tmp;
279 }
280
lv_strchr(const char * s,int c)281 char * lv_strchr(const char * s, int c)
282 {
283 for(; ; s++) {
284 if(*s == c) {
285 return (char *)s;
286 }
287
288 if(*s == '\0') {
289 break;
290 }
291 }
292
293 return NULL;
294 }
295
296 /**********************
297 * STATIC FUNCTIONS
298 **********************/
299
300 #endif /*LV_STDLIB_BUILTIN*/
301