backported fixes from 256boss
[bootcensus] / src / libc / string.c
1 /*
2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018-2019  John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include <string.h>
19 #include <ctype.h>
20 #include <stddef.h>
21
22 void *memmove(void *dest, const void *src, size_t n)
23 {
24         int i;
25         char *dptr;
26         const char *sptr;
27
28         if(dest <= src) {
29                 /* forward copy */
30                 dptr = dest;
31                 sptr = src;
32                 for(i=0; i<n; i++) {
33                         *dptr++ = *sptr++;
34                 }
35         } else {
36                 /* backwards copy */
37                 dptr = (char*)dest + n - 1;
38                 sptr = (const char*)src + n - 1;
39                 for(i=0; i<n; i++) {
40                         *dptr-- = *sptr--;
41                 }
42         }
43
44         return dest;
45 }
46
47 int memcmp(void *aptr, void *bptr, size_t n)
48 {
49         int i, startoffs, diff;
50         uint32_t *a32, *b32;
51         unsigned char *a = aptr;
52         unsigned char *b = bptr;
53
54         a32 = (uint32_t*)((intptr_t)(a + 3) & 0xfffffffc);
55         b32 = (uint32_t*)((intptr_t)(b + 3) & 0xfffffffc);
56
57         /* if both are aligned the same way... */
58         if((startoffs = (unsigned char*)a32 - a) == (unsigned char*)b32 - b) {
59                 /* catch-up to the 32bit alignment */
60                 for(i=0; i<startoffs; i++) {
61                         if((diff = *a++ - *b++) != 0 || --n <= 0) {
62                                 return diff;
63                         }
64                 }
65
66                 /* compare 32bit at once */
67                 while(n >= 4) {
68                         if(*a32 != *b32) break;
69                         a32++;
70                         b32++;
71                         n -= 4;
72                 }
73
74                 /* update byte pointers to contine with the tail */
75                 a = (unsigned char*)a32;
76                 b = (unsigned char*)b32;
77         }
78
79         /* we're here both for the tail-end of same-alignment buffers, or for the
80          * whole length of mis-aligned buffers.
81          */
82         while(n-- > 0) {
83                 if((diff = *a++ - *b++) != 0) {
84                         return diff;
85                 }
86         }
87         return 0;
88 }
89
90 size_t strlen(const char *s)
91 {
92         size_t len = 0;
93         while(*s++) len++;
94         return len;
95 }
96
97 char *strchr(const char *s, int c)
98 {
99         while(*s) {
100                 if(*s == c) {
101                         return (char*)s;
102                 }
103                 s++;
104         }
105         return 0;
106 }
107
108 char *strrchr(const char *s, int c)
109 {
110         const char *ptr = s;
111
112         /* find the end */
113         while(*ptr) ptr++;
114
115         /* go back checking for c */
116         while(--ptr >= s) {
117                 if(*ptr == c) {
118                         return (char*)ptr;
119                 }
120         }
121         return 0;
122 }
123
124 char *strstr(const char *str, const char *substr)
125 {
126         while(*str) {
127                 const char *s1 = str;
128                 const char *s2 = substr;
129
130                 while(*s1 && *s1 == *s2) {
131                         s1++;
132                         s2++;
133                 }
134                 if(!*s2) {
135                         return (char*)str;
136                 }
137                 str++;
138         }
139         return 0;
140 }
141
142 char *strcasestr(const char *str, const char *substr)
143 {
144         while(*str) {
145                 const char *s1 = str;
146                 const char *s2 = substr;
147
148                 while(*s1 && tolower(*s1) == tolower(*s2)) {
149                         s1++;
150                         s2++;
151                 }
152                 if(!*s2) {
153                         return (char*)str;
154                 }
155                 str++;
156         }
157         return 0;
158 }
159
160 int strcmp(const char *s1, const char *s2)
161 {
162         while(*s1 && *s1 == *s2) {
163                 s1++;
164                 s2++;
165         }
166         return *s1 - *s2;
167 }
168
169 int strcasecmp(const char *s1, const char *s2)
170 {
171         while(*s1 && tolower(*s1) == tolower(*s2)) {
172                 s1++;
173                 s2++;
174         }
175         return tolower(*s1) - tolower(*s2);
176 }
177
178 int strncmp(const char *s1, const char *s2, int n)
179 {
180         if(n <= 0) return 0;
181
182         while(n-- > 0 && *s1 && *s2 && *s1 == *s2) {
183                 s1++;
184                 s2++;
185         }
186
187         if(n <= 0) return 0;
188         return *s1 - *s2;
189 }
190
191 int strncasecmp(const char *s1, const char *s2, int n)
192 {
193         if(n <= 0) return 0;
194
195         while(n-- > 0 && *s1 && *s2 && tolower(*s1) == tolower(*s2)) {
196                 s1++;
197                 s2++;
198         }
199
200         if(n <= 0) return 0;
201         return tolower(*s1) - tolower(*s2);
202 }
203
204 char *strcpy(char *dest, const char *src)
205 {
206         char *dptr = dest;
207         while((*dptr++ = *src++));
208         return dest;
209 }
210
211 char *strcat(char *dest, const char *src)
212 {
213         strcpy(dest + strlen(dest), src);
214         return dest;
215 }
216
217 char *strncpy(char *dest, const char *src, int n)
218 {
219         char *dptr = dest;
220         while(n-- > 0 && (*dptr++ = *src++));
221         return dest;
222 }
223
224
225 static const char *errstr[] = {
226         "Success",
227         "Foo",
228         "Interrupted",
229         "Invalid",
230         "Child",
231         "Timeout",
232         "Out of memory",
233         "I/O error",
234         "Not found",
235         "Name too long",
236         "No space left on device",
237         "Permission denied",
238         "Not a directory",
239         "Is a directory",
240         "Does not exist",
241         0,0,0,0,0,
242         0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
243         0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
244         0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
245         0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
246         0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
247         0,0,0,0,0,0,0,
248         "Bug"
249 };
250
251 char *strerror(int err)
252 {
253         if(err < 0 || err > sizeof errstr / sizeof *errstr || !errstr[err]) {
254                 return "Unknown";
255         }
256         return (char*)errstr[err];
257 }