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

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