d61d51dde0d2b742b69c06733c166d6e464b7150
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / string.c
1 /*
2  * AcessOS Basic C Library
3  * string.c
4  */
5 //#include <acess/sys.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <ctype.h>
9 #include "lib.h"
10 #include <string.h>
11
12 /**
13  * \fn EXPORT int strcmp(const char *s1, const char *s2)
14  * \brief Compare two strings
15  */
16 EXPORT int strcmp(const char *_s1, const char *_s2)
17 {
18         return strncmp(_s1, _s2, SIZE_MAX);
19 }
20
21 /**
22  * \fn EXPORT int strncmp(const char *s1, const char *s2, size_t n)
23  * \brief Compare two strings, stopping after n characters
24  */
25 EXPORT int strncmp(const char *_s1, const char *_s2, size_t n)
26 {
27         const unsigned char*    s1 = (const unsigned char*)_s1;
28         const unsigned char*    s2 = (const unsigned char*)_s2;
29         while(n && *s1 && *s1 == *s2)
30         {
31                 s1++; s2++;
32                 n --;
33         }
34         if( n == 0 )
35                 return 0;
36         else
37                 return (int)*s1 - (int)*s2;
38 }
39
40 EXPORT int strcasecmp(const char *_s1, const char *_s2)
41 {
42         return strncasecmp(_s1, _s2, SIZE_MAX);
43 }
44
45 EXPORT int strncasecmp(const char *_s1, const char *_s2, size_t n)
46 {
47         const unsigned char*    s1 = (const unsigned char*)_s1;
48         const unsigned char*    s2 = (const unsigned char*)_s2;
49         while( n-- && *s1 && *s2 )
50         {
51                 if( *s1 != *s2 )
52                 {
53                         int rv;
54                         rv = toupper(*s1) - toupper(*s2);
55                         if(rv != 0)
56                                 return rv;
57                         rv = tolower(*s1) - tolower(*s2);
58                         if(rv != 0)
59                                 return rv;
60                 }
61                 s1 ++;
62                 s2 ++;
63         }
64         return 0;
65 }
66
67 /**
68  * \fn EXPORT char *strcpy(char *dst, const char *src)
69  * \brief Copy a string to another
70  */
71 EXPORT char *strcpy(char *dst, const char *src)
72 {
73         char *_dst = dst;
74         while(*src) {
75                 *dst = *src;
76                 src++; dst++;
77         }
78         *dst = '\0';
79         return _dst;
80 }
81
82 /**
83  * \fn EXPORT char *strncpy(char *dst, const char *src)
84  * \brief Copy at most \a num characters from \a src to \a dst
85  * \return \a dst
86  */
87 EXPORT char *strncpy(char *dst, const char *src, size_t num)
88 {
89         char *to = dst;
90         while(num --)
91         {
92                 if(*src)
93                         *to++ = *src++;
94                 else
95                         *to++ = '\0';
96         }
97         return dst;
98 }
99
100 /**
101  * \fn EXPORT char *strcat(char *dst, const char *src)
102  * \brief Append a string onto another
103  */
104 EXPORT char *strcat(char *dst, const char *src)
105 {
106         char    *to = dst;
107         // Find the end
108         while(*to)      to++;
109         // Copy
110         while(*src)     *to++ = *src++;
111         // End string
112         *to = '\0';
113         return dst;
114 }
115
116 EXPORT char *strncat(char *dst, const char *src, size_t n)
117 {
118         char    *to = dst;
119         // Find the end
120         while(*to)      to++;
121         // Copy
122         while(*src && n--)      *to++ = *src++;
123         // End string
124         *to = '\0';
125         return dst;
126 }
127
128 /**
129  * \brief Get the length of a string
130  */
131 EXPORT size_t strlen(const char *str)
132 {
133         size_t  len = 0;
134         while(str[len] != '\0')
135                 len ++;
136         return len;
137 }
138
139 /**
140  * \brief Get the length of a string, with a maximum of \a maxlen
141  * 
142  * Gets the length of a string (excluding the terminating \0 byte)
143  */
144 EXPORT size_t strnlen(const char *str, size_t maxlen)
145 {
146         size_t  len = 0;
147         while( len < maxlen && str[len] != '\0' )
148                 len ++;
149         return len;
150 }
151
152 /**
153  * \fn EXPORT char *strdup(const char *str)
154  * \brief Duplicate a string using heap memory
155  * \note Defined in POSIX Spec, not C spec
156  */
157 EXPORT char *strdup(const char *str)
158 {
159         size_t  len = strlen(str);
160         char    *ret = malloc(len+1);
161         if(ret == NULL) return NULL;
162         strcpy(ret, str);
163         return ret;
164 }
165
166 /**
167  * \fn EXPORT char *strndup(const char *str, size_t maxlen)
168  * \brief Duplicate a string into the heap with a maximum length
169  * \param str   Input string buffer
170  * \param maxlen        Maximum valid size of the \a str buffer
171  * \return Heap string with the same value of \a str
172  */
173 EXPORT char *strndup(const char *str, size_t maxlen)
174 {
175         size_t  len;
176         char    *ret;
177         for( len = 0; len < maxlen && str[len]; len ++) ;
178         ret = malloc( len + 1);
179         memcpy( ret, str, len );
180         ret[len] = '\0';
181         return ret;
182 }
183
184 /**
185  * \fn EXPORT char *strchr(char *str, int character)
186  * \brief Locate a character in a string
187  */
188 EXPORT char *strchr(const char *_str, int character)
189 {
190         const unsigned char* str = (const unsigned char*)_str;
191         for(;*str;str++)
192         {
193                 if( *str == character )
194                         return (char*)str;
195         }
196         return NULL;
197 }
198
199 /**
200  * \fn EXPORT char *strrchr(char *str, int character)
201  * \brief Locate the last occurance of a character in a string
202  */
203 EXPORT char *strrchr(const char *_str, int character)
204 {
205         const unsigned char* str = (const unsigned char*)_str;
206         for( size_t i = strlen(_str); i--; )
207         {
208                 if(str[i] == character)
209                         return (void*)&str[i];
210         }
211         return NULL;
212 }
213
214 /**
215  * \fn EXPORT char *strstr(char *str1, const char *str2)
216  * \brief Search a \a str1 for the first occurance of \a str2
217  */
218 EXPORT char *strstr(const char *str1, const char *str2)
219 {
220         const char      *test = str2;
221         
222         for(;*str1;str1++)
223         {
224                 if(*test == '\0')       return (char*)str1;
225                 if(*str1 == *test)      test++;
226                 else    test = str2;
227         }
228         return NULL;
229 }
230
231 // --- Memory ---
232 /**
233  * \fn EXPORT void *memset(void *dest, int val, size_t num)
234  * \brief Clear memory with the specified value
235  */
236 EXPORT void *memset(void *dest, int val, size_t num)
237 {
238         unsigned char *p = dest;
239         while(num--)    *p++ = val;
240         return dest;
241 }
242
243 /**
244  * \fn EXPORT void *memcpy(void *dest, const void *src, size_t count)
245  * \brief Copy one memory area to another
246  */
247 EXPORT void *memcpy(void *__dest, const void *__src, size_t count)
248 {
249         const int       wordmask = sizeof(void*)-1;
250         uintptr_t       src = (uintptr_t)__src;
251         uintptr_t       dst = (uintptr_t)__dest;
252
253         if( count < sizeof(void*)*2 || (dst & wordmask) != (src & wordmask) )
254         {
255                 char    *dp = __dest;
256                 const char      *sp = __src;
257                 while(count--) *dp++ = *sp ++;
258         }
259         // TODO: Bulk aligned copies
260         #if 0
261         else if(count > 128 && (dst & 15) == (src & 15) )
262         {
263                 // SSE/bulk copy
264                 for( ; dst & 15; count -- )
265                         *(char*)dst++ = *(char*)src++;
266                 memcpy_16byte(dst, src, count / 16);
267                 dst += count & ~15;
268                 src += count & ~15;
269                 count &= 15;
270                 while(count --)
271                         *(char*)dst++ = *(char*)src++;
272         }
273         #endif
274         else
275         {
276                 void    **dp, **sp;
277                 for( ; count && (dst & wordmask) != 0; count -- )
278                         *(char*)dst++ = *(char*)src++;
279
280                 dp = (void*)dst; sp = (void*)src;
281                 while( count >= sizeof(void*) )
282                 {
283                         *dp++ = *sp++;
284                         count -= sizeof(void*);
285                 }
286                 dst = (uintptr_t)dp; src = (uintptr_t)sp;
287                 for( ; count; count -- )
288                         *(char*)dst++ = *(char*)src++;
289         }
290
291         return __dest;
292 }
293
294 // TODO: memccpy (POSIX defined)
295
296 /**
297  * \fn EXPORT void *memmove(void *dest, const void *src, size_t count)
298  * \brief Copy data in memory, avoiding overlap problems
299  */
300 EXPORT void *memmove(void *dest, const void *src, size_t count)
301 {
302         const char *sp = (const char *)src;
303         char *dp = (char *)dest;
304         // Check if the areas overlap
305         if( sp >= dp+count )
306                 memcpy(dest, src, count);
307         else if( dp >= sp+count )
308                 memcpy(dest, src, count);
309         else {
310                 if( sp < dp ) {
311                         while(count--)
312                                 dp[count] = sp[count];
313                 }
314                 else {
315                         while(count--)
316                                 *dp++ = *sp++;
317                 }
318         }
319         return dest;
320 }
321
322 /**
323  * \fn EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
324  * \brief Compare two regions of memory
325  * \param mem1  Region 1
326  * \param mem2  Region 2
327  * \param count Number of bytes to check
328  */
329 EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
330 {
331         const unsigned char     *p1 = mem1, *p2 = mem2;
332         while(count--)
333         {
334                 if( *p1 != *p2 )
335                         return (int)*p1 - (int)*p2;
336                 p1 ++;
337                 p2 ++;
338         }
339         return 0;
340 }
341
342 /**
343  * \fn EXPORT void *memchr(void *ptr, int value, size_t num)
344  * \brief Locates the first occurence of \a value starting at \a ptr
345  * \param ptr   Starting memory location
346  * \param value Value to find
347  * \param num   Size of memory area to check
348  */
349 EXPORT void *memchr(const void *ptr, int value, size_t num)
350 {
351         const unsigned char* buf = ptr;
352         while(num--)
353         {
354                 if( *buf == (unsigned char)value )
355                         return (void*)buf;
356                 buf ++;
357         }
358         return NULL;
359 }
360
361 EXPORT size_t strcspn(const char *haystack, const char *reject)
362 {
363         size_t  ret = 0;
364         while( *haystack )
365         {
366                 for( int i = 0; reject[i]; i ++ )
367                 {
368                         if( reject[i] == *haystack )
369                                 return ret;
370                 }
371                 ret ++;
372         }
373         return ret;
374 }
375
376 EXPORT size_t strspn(const char *haystack, const char *accept)
377 {
378         size_t  ret = 0;
379         while( *haystack )
380         {
381                 for( int i = 0; accept[i]; i ++ )
382                 {
383                         if( accept[i] != *haystack )
384                                 return ret;
385                 }
386                 ret ++;
387         }
388         return ret;
389 }
390
391 EXPORT char *strpbrk(const char *haystack, const char *accept)
392 {
393         while( *haystack )
394         {
395                 for( int i = 0; accept[i]; i ++ )
396                 {
397                         if( accept[i] == *haystack )
398                                 return (char*)haystack;
399                 }
400                 haystack ++;
401         }
402         return NULL;
403 }
404
405 char *strtok(char *str, const char *delim)
406 {
407         static char *__saveptr;
408         return strtok_r(str, delim, &__saveptr);
409 }
410 char *strtok_r(char *str, const char *delim, char **saveptr)
411 {
412         char *pos = (str ? str : *saveptr);
413         
414         while( strchr(delim, *pos) )
415                 pos ++;
416
417         if( *pos == '\0' )
418                 return NULL;
419
420         char *ret = pos;
421         while( !strchr(delim, *pos) )
422                 pos ++;
423         
424         // Cap the returned string
425         // - If we're at the end of the original string, don't shift pos
426         if( *pos != '\0' ) {
427                 *pos = '\0';
428                 pos ++;
429         }
430         
431         *saveptr = pos;
432         
433         return ret;
434 }
435

UCC git Repository :: git.ucc.asn.au