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

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