176ae659e54019d480a6be6fb7745cdfd5c9e891
[monolithium.git] / libraries / mlcrt / src / string.c
1 /*
2  * string.c
3  *
4  * Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23
24 char *strcpy(char *destination, const char *source)
25 {
26     while (*source != 0) *(destination++) = *(source++);
27     *destination = 0;
28     return destination;
29 }
30
31 char *strncpy(char *destination, const char *source, uint32_t num)
32 {
33     char *ptr = destination;
34     while ((num--) && (*source)) *(ptr++) = *(source++);
35     *ptr = 0;
36     return destination;
37 }
38
39 int strcmp(const char *str1, const char *str2)
40 {
41     while (*str1 || *str2)
42     {
43         if (*str1 != *str2) break;
44         str1++;
45         str2++;
46     }
47
48     if (*str1 < *str2) return -1;
49     else if (*str1 > *str2) return 1;
50     else return 0;
51 }
52
53 int stricmp(const char *str1, const char *str2)
54 {
55     while (*str1 || *str2)
56     {
57         if (tolower(*str1) != tolower(*str2)) break;
58         str1++;
59         str2++;
60     }
61     if (*str1 < *str2) return -1;
62     else if (*str1 > *str2) return 1;
63     else return 0;
64 }
65
66 int strncmp(const char *str1, const char *str2, size_t n)
67 {
68     int i;
69
70     for (i = 0; i < n; i++)
71     {
72         if (str1[i] < str2[i]) return -1;
73         else if (str1[i] > str2[i]) return 1;
74         if (str1[i] == 0 || str2[i] == 0) break;
75     }
76
77     return 0;
78 }
79
80 char *strstr(const char *haystack, const char *needle)
81 {
82     while (*haystack)
83     {
84         const char *s1 = haystack;
85         const char *s2 = needle;
86         int found = 1;
87
88         while (*s2)
89         {
90             if (*s1++ != *s2++)
91             {
92                 found = 0;
93                 break;
94             }
95         }
96
97         if (found) return (char*)haystack;
98         haystack++;
99     }
100
101     return NULL;
102 }
103
104 char *strchr(const char *str, char c)
105 {
106     while ((*str != 0) && (*str != c)) str++;
107     if (*str == c) return (char*)str;
108     else return NULL;
109 }
110
111 char *strrchr(const char *str, char c)
112 {
113     char *ret = NULL;
114
115     while (*str != 0)
116     {
117         if (*str == c) ret = (char*)str;
118         str++;
119     }
120
121     return ret;
122 }
123
124 char *strcat(char *destination, const char *source)
125 {
126     strcpy(strchr(destination, '\0'), source);
127     return destination;
128 }
129
130 char *strncat(char *destination, const char *source, size_t n)
131 {
132     char *ptr = strchr(destination, 0);
133     while ((n--) && (*source)) *(ptr++) = *(source++);
134     *ptr = 0;
135     return destination;
136 }
137
138 char *strdup(const char *source)
139 {
140     char *destination = (char*)malloc(strlen(source) + 1);
141     if (destination) strcpy(destination, source);
142     return destination;
143 }
144
145 char *strtok_r(char *str, const char *delimiters, char **endptr)
146 {
147     if (str == NULL) str = *endptr;
148     char *start = str;
149
150     while (*str != 0)
151     {
152         if (strchr(delimiters, *str) != NULL)
153         {
154             *str = 0;
155             *endptr = str + 1;
156             return start;
157         }
158
159         str++;
160     }
161
162     *endptr = str;
163     return start != str ? start : NULL;
164 }
165
166 char *strtok(char *str, const char *delimiters)
167 {
168     static char *endptr;
169     return strtok_r(str, delimiters, &endptr);
170 }
171
172 size_t strlen(const char *str)
173 {
174     int ret = 0;
175     while (str[ret] != 0) ret++;
176     return ret;
177 }
178
179 void strrev(char *str)
180 {
181     size_t i, j = strlen(str) - 1;
182
183     while (i < j)
184     {
185         int t = str[i];
186         str[i] = str[j];
187         str[j] = t;
188
189         i++;
190         j--;
191     }
192 }
193
194 void memset(void *ptr, int value, size_t n)
195 {
196     uint8_t *ptr_byte = (uint8_t*)ptr;
197     value &= 0xFF;
198     uint32_t tile = value | (value << 8) | (value << 16) | (value << 24);
199
200     if (n >> 2)
201     {
202         asm volatile ("cld\n"
203                       "rep stosl\n"
204                       : "=D"(ptr_byte)
205                       : "D"(ptr_byte), "a"(tile), "c"(n >> 2)
206                       : "cc");
207     }
208
209     switch (n & 3)
210     {
211     case 3:
212         *ptr_byte++ = value;
213     case 2:
214         *ptr_byte++ = value;
215     case 1:
216         *ptr_byte++ = value;
217     }
218 }
219
220 void memcpy(void *destination, const void *source, size_t n)
221 {
222     uint8_t *src_byte = (uint8_t*)source;
223     uint8_t *dest_byte = (uint8_t*)destination;
224     if (!n) return;
225
226     if (n >> 2)
227     {
228         asm volatile ("cld\n"
229                       "rep movsl\n"
230                       : "=D"(dest_byte), "=S"(src_byte)
231                       : "D"(destination), "S"(source), "c"(n >> 2)
232                       : "cc", "memory");
233     }
234
235     switch (n & 3)
236     {
237     case 3:
238         *dest_byte++ = *src_byte++;
239     case 2:
240         *dest_byte++ = *src_byte++;
241     case 1:
242         *dest_byte++ = *src_byte++;
243     }
244 }
245
246 void memmove(void *destination, const void *source, size_t n)
247 {
248     if (!n) return;
249
250     if (destination < source)
251     {
252         uint8_t *src_byte = (uint8_t*)source;
253         uint8_t *dest_byte = (uint8_t*)destination;
254
255         if (n >> 2)
256         {
257             asm volatile ("cld\n"
258                           "rep movsl\n"
259                           : "=D"(dest_byte), "=S"(src_byte)
260                           : "D"(destination), "S"(source), "c"(n >> 2)
261                           : "cc", "memory");
262         }
263
264         switch (n & 3)
265         {
266         case 3:
267             *dest_byte++ = *src_byte++;
268         case 2:
269             *dest_byte++ = *src_byte++;
270         case 1:
271             *dest_byte++ = *src_byte++;
272         }
273     }
274     else if (destination > source)
275     {
276         uint8_t *src_byte = (uint8_t*)source + n;
277         uint8_t *dest_byte = (uint8_t*)destination + n;
278
279         switch (n & 3)
280         {
281         case 3:
282             *--dest_byte = *--src_byte;
283         case 2:
284             *--dest_byte = *--src_byte;
285         case 1:
286             *--dest_byte = *--src_byte;
287         }
288
289         if (n >> 2)
290         {
291             asm volatile ("std\n"
292                           "rep movsl\n"
293                           :
294                           : "D"(dest_byte - 4), "S"(src_byte - 4), "c"(n >> 2)
295                           : "cc", "memory");
296         }
297     }
298 }
299
300 int memcmp(const void *mem1, const void *mem2, size_t n)
301 {
302     uint32_t flags;
303
304     asm volatile ("cld\n"
305                   "repz cmpsb\n"
306                   "pushfl\n"
307                   "popl %0\n"
308                   : "=r"(flags)
309                   : "S"(mem1), "D"(mem2), "c"(n)
310                   : "cc");
311
312     if (flags & 0x40) return 0;
313     else return (flags & 1) ? 1 : -1;
314 }