added license
[rpikern] / src / libc / string.c
1 #include <string.h>
2 #include <ctype.h>
3 #include <stddef.h>
4
5 void *memset(void *ptr, int val, size_t size)
6 {
7         unsigned char *p = ptr;
8         while(size--) {
9                 *p++ = val;
10         }
11         return ptr;
12 }
13
14 void *memcpy(void *dest, const void *src, size_t n)
15 {
16         unsigned char *d = dest;
17         const unsigned char *s = src;
18         while(n--) {
19                 *d++ = *s++;
20         }
21         return dest;
22 }
23
24 void *memmove(void *dest, const void *src, size_t n)
25 {
26         int i;
27         char *dptr;
28         const char *sptr;
29
30         if(dest <= src) {
31                 /* forward copy */
32                 dptr = dest;
33                 sptr = src;
34                 for(i=0; i<n; i++) {
35                         *dptr++ = *sptr++;
36                 }
37         } else {
38                 /* backwards copy */
39                 dptr = (char*)dest + n - 1;
40                 sptr = (const char*)src + n - 1;
41                 for(i=0; i<n; i++) {
42                         *dptr-- = *sptr--;
43                 }
44         }
45
46         return dest;
47 }
48
49 int memcmp(void *aptr, void *bptr, size_t n)
50 {
51         int i, startoffs, diff;
52         uint32_t *a32, *b32;
53         unsigned char *a = aptr;
54         unsigned char *b = bptr;
55
56         a32 = (uint32_t*)((intptr_t)(a + 3) & 0xfffffffc);
57         b32 = (uint32_t*)((intptr_t)(b + 3) & 0xfffffffc);
58
59         /* if both are aligned the same way... */
60         if((startoffs = (unsigned char*)a32 - a) == (unsigned char*)b32 - b) {
61                 /* catch-up to the 32bit alignment */
62                 for(i=0; i<startoffs; i++) {
63                         if((diff = *a++ - *b++) != 0 || --n <= 0) {
64                                 return diff;
65                         }
66                 }
67
68                 /* compare 32bit at once */
69                 while(n >= 4) {
70                         if(*a32 != *b32) break;
71                         a32++;
72                         b32++;
73                         n -= 4;
74                 }
75
76                 /* update byte pointers to contine with the tail */
77                 a = (unsigned char*)a32;
78                 b = (unsigned char*)b32;
79         }
80
81         /* we're here both for the tail-end of same-alignment buffers, or for the
82          * whole length of mis-aligned buffers.
83          */
84         while(n-- > 0) {
85                 if((diff = *a++ - *b++) != 0) {
86                         return diff;
87                 }
88         }
89         return 0;
90 }
91
92 size_t strlen(const char *s)
93 {
94         size_t len = 0;
95         while(*s++) len++;
96         return len;
97 }
98
99 char *strchr(const char *s, int c)
100 {
101         while(*s) {
102                 if(*s == c) {
103                         return (char*)s;
104                 }
105                 s++;
106         }
107         return 0;
108 }
109
110 char *strrchr(const char *s, int c)
111 {
112         const char *ptr = s;
113
114         /* find the end */
115         while(*ptr) ptr++;
116
117         /* go back checking for c */
118         while(--ptr >= s) {
119                 if(*ptr == c) {
120                         return (char*)ptr;
121                 }
122         }
123         return 0;
124 }
125
126 char *strstr(const char *str, const char *substr)
127 {
128         while(*str) {
129                 const char *s1 = str;
130                 const char *s2 = substr;
131
132                 while(*s1 && *s1 == *s2) {
133                         s1++;
134                         s2++;
135                 }
136                 if(!*s2) {
137                         return (char*)str;
138                 }
139                 str++;
140         }
141         return 0;
142 }
143
144 char *strcasestr(const char *str, const char *substr)
145 {
146         while(*str) {
147                 const char *s1 = str;
148                 const char *s2 = substr;
149
150                 while(*s1 && tolower(*s1) == tolower(*s2)) {
151                         s1++;
152                         s2++;
153                 }
154                 if(!*s2) {
155                         return (char*)str;
156                 }
157                 str++;
158         }
159         return 0;
160 }
161
162 int strcmp(const char *s1, const char *s2)
163 {
164         while(*s1 && *s1 == *s2) {
165                 s1++;
166                 s2++;
167         }
168         return *s1 - *s2;
169 }
170
171 int strcasecmp(const char *s1, const char *s2)
172 {
173         while(*s1 && tolower(*s1) == tolower(*s2)) {
174                 s1++;
175                 s2++;
176         }
177         return tolower(*s1) - tolower(*s2);
178 }
179
180 int strncmp(const char *s1, const char *s2, int n)
181 {
182         if(n <= 0) return 0;
183
184         while(n-- > 0 && *s1 && *s2 && *s1 == *s2) {
185                 s1++;
186                 s2++;
187         }
188
189         if(n <= 0) return 0;
190         return *s1 - *s2;
191 }
192
193 int strncasecmp(const char *s1, const char *s2, int n)
194 {
195         if(n <= 0) return 0;
196
197         while(n-- > 0 && *s1 && *s2 && tolower(*s1) == tolower(*s2)) {
198                 s1++;
199                 s2++;
200         }
201
202         if(n <= 0) return 0;
203         return tolower(*s1) - tolower(*s2);
204 }
205
206 char *strcpy(char *dest, const char *src)
207 {
208         char *dptr = dest;
209         while((*dptr++ = *src++));
210         return dest;
211 }
212
213 char *strcat(char *dest, const char *src)
214 {
215         strcpy(dest + strlen(dest), src);
216         return dest;
217 }
218
219 char *strncpy(char *dest, const char *src, int n)
220 {
221         char *dptr = dest;
222         while(n-- > 0 && (*dptr++ = *src++));
223         return dest;
224 }
225
226
227 static const char *errstr[] = {
228         "Success",
229         "Foo",
230         "Interrupted",
231         "Invalid",
232         "Child",
233         "Timeout",
234         "Out of memory",
235         "I/O error",
236         "Not found",
237         "Name too long",
238         "No space left on device",
239         "Permission denied",
240         "Not a directory",
241         "Is a directory",
242         "Does not exist",
243         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,0,0,0,  0,0,0,0,0,0,0,0,0,0,
248         0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
249         0,0,0,0,0,0,0,
250         "Bug"
251 };
252
253 char *strerror(int err)
254 {
255         if(err < 0 || err > sizeof errstr / sizeof *errstr || !errstr[err]) {
256                 return "Unknown";
257         }
258         return (char*)errstr[err];
259 }