Usermode/libc - Fixed DIV0 in fread/fopen
[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 EXPORT char *strncat(char *dst, const char *src, size_t n)
104 {
105         char    *to = dst;
106         // Find the end
107         while(*to)      to++;
108         // Copy
109         while(*src && n--)      *to++ = *src++;
110         // End string
111         *to = '\0';
112         return dst;
113 }
114
115 /**
116  * \brief Get the length of a string
117  */
118 EXPORT size_t strlen(const char *str)
119 {
120         size_t  retval;
121         for(retval = 0; *str != '\0'; str++, retval++);
122         return retval;
123 }
124
125 /**
126  * \brief Get the length of a string, with a maximum of \a maxlen
127  * 
128  * Gets the length of a string (excluding the terminating \0 byte)
129  */
130 EXPORT size_t strnlen(const char *str, size_t maxlen)
131 {
132         size_t  len;
133         for( len = 0; maxlen -- && *str; str ++, len ++ );
134         return len;
135 }
136
137 /**
138  * \fn EXPORT char *strdup(const char *str)
139  * \brief Duplicate a string using heap memory
140  * \note Defined in POSIX Spec, not C spec
141  */
142 EXPORT char *strdup(const char *str)
143 {
144         size_t  len = strlen(str);
145         char    *ret = malloc(len+1);
146         if(ret == NULL) return NULL;
147         strcpy(ret, str);
148         return ret;
149 }
150
151 /**
152  * \fn EXPORT char *strndup(const char *str, size_t maxlen)
153  * \brief Duplicate a string into the heap with a maximum length
154  * \param str   Input string buffer
155  * \param maxlen        Maximum valid size of the \a str buffer
156  * \return Heap string with the same value of \a str
157  */
158 EXPORT char *strndup(const char *str, size_t maxlen)
159 {
160         size_t  len;
161         char    *ret;
162         for( len = 0; len < maxlen && str[len]; len ++) ;
163         ret = malloc( len + 1);
164         memcpy( ret, str, len );
165         ret[len] = '\0';
166         return ret;
167 }
168
169 /**
170  * \fn EXPORT char *strchr(char *str, int character)
171  * \brief Locate a character in a string
172  */
173 EXPORT char *strchr(const char *str, int character)
174 {
175         for(;*str;str++)
176         {
177                 if(*str == character)
178                         return (char*)str;
179         }
180         return NULL;
181 }
182
183 /**
184  * \fn EXPORT char *strrchr(char *str, int character)
185  * \brief Locate the last occurance of a character in a string
186  */
187 EXPORT char *strrchr(const char *str, int character)
188 {
189          int    i;
190         i = strlen(str)-1;
191         while(i--)
192         {
193                 if(str[i] == character)
194                         return (void*)&str[i];
195         }
196         return NULL;
197 }
198
199 /**
200  * \fn EXPORT char *strstr(char *str1, const char *str2)
201  * \brief Search a \a str1 for the first occurance of \a str2
202  */
203 EXPORT char *strstr(char *str1, const char *str2)
204 {
205         const char      *test = str2;
206         
207         for(;*str1;str1++)
208         {
209                 if(*test == '\0')       return str1;
210                 if(*str1 == *test)      test++;
211                 else    test = str2;
212         }
213         return NULL;
214 }
215
216 // --- Memory ---
217 /**
218  * \fn EXPORT void *memset(void *dest, int val, size_t num)
219  * \brief Clear memory with the specified value
220  */
221 EXPORT void *memset(void *dest, int val, size_t num)
222 {
223         unsigned char *p = dest;
224         while(num--)    *p++ = val;
225         return dest;
226 }
227
228 /**
229  * \fn EXPORT void *memcpy(void *dest, const void *src, size_t count)
230  * \brief Copy one memory area to another
231  */
232 EXPORT void *memcpy(void *__dest, const void *__src, size_t count)
233 {
234         const int       wordmask = sizeof(void*)-1;
235         uintptr_t       src = (uintptr_t)__src;
236         uintptr_t       dst = (uintptr_t)__dest;
237
238         if( count < sizeof(void*)*2 || (dst & wordmask) != (src & wordmask) )
239         {
240                 char    *dp = __dest;
241                 const char      *sp = __src;
242                 while(count--) *dp++ = *sp ++;
243         }
244         // TODO: Bulk aligned copies
245         #if 0
246         else if(count > 128 && (dst & 15) == (src & 15) )
247         {
248                 // SSE/bulk copy
249                 for( ; dst & 15; count -- )
250                         *(char*)dst++ = *(char*)src++;
251                 memcpy_16byte(dst, src, count / 16);
252                 dst += count & ~15;
253                 src += count & ~15;
254                 count &= 15;
255                 while(count --)
256                         *(char*)dst++ = *(char*)src++;
257         }
258         #endif
259         else
260         {
261                 void    **dp, **sp;
262                 for( ; count && (dst & wordmask) != 0; count -- )
263                         *(char*)dst++ = *(char*)src++;
264
265                 dp = (void*)dst; sp = (void*)src;
266                 while( count >= sizeof(void*) )
267                 {
268                         *dp++ = *sp++;
269                         count -= sizeof(void*);
270                 }
271                 dst = (uintptr_t)dp; src = (uintptr_t)sp;
272                 for( ; count; count -- )
273                         *(char*)dst++ = *(char*)src++;
274         }
275
276         return __dest;
277 }
278
279 /**
280  * \fn EXPORT void *memmove(void *dest, const void *src, size_t count)
281  * \brief Copy data in memory, avoiding overlap problems
282  */
283 EXPORT void *memmove(void *dest, const void *src, size_t count)
284 {
285         char *sp = (char *)src;
286         char *dp = (char *)dest;
287         // Check if the areas overlap
288         if( (uintptr_t)src < (uintptr_t)dest && (uintptr_t)dest < (uintptr_t)src+count )
289                 for(;count--;)
290                         dp[count] = sp[count];
291         else
292                 memcpy(dest, src, count);
293         return dest;
294 }
295
296 /**
297  * \fn EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
298  * \brief Compare two regions of memory
299  * \param mem1  Region 1
300  * \param mem2  Region 2
301  * \param count Number of bytes to check
302  */
303 EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
304 {
305         const unsigned char     *p1 = mem1, *p2 = mem2;
306         while(count--)
307         {
308                 if( *p1 != *p2 )
309                         return *p1 - *p2;
310                 p1 ++;
311                 p2 ++;
312         }
313         return 0;
314 }
315
316 /**
317  * \fn EXPORT void *memchr(void *ptr, int value, size_t num)
318  * \brief Locates the first occurence of \a value starting at \a ptr
319  * \param ptr   Starting memory location
320  * \param value Value to find
321  * \param num   Size of memory area to check
322  */
323 EXPORT void *memchr(const void *ptr, int value, size_t num)
324 {
325         while(num--)
326         {
327                 if( *(const unsigned char*)ptr == (unsigned char)value )
328                         return (void*)ptr;
329                 ptr ++;
330         }
331         return NULL;
332 }
333
334 EXPORT size_t strcspn(const char *haystack, const char *reject)
335 {
336         size_t  ret = 0;
337          int    i;
338         while( *haystack )
339         {
340                 for( i = 0; reject[i] && reject[i] == *haystack; i ++ );
341
342                 if( reject[i] ) return ret;
343                 ret ++;
344         }
345         return ret;
346 }
347
348 EXPORT size_t strspn(const char *haystack, const char *accept)
349 {
350         size_t  ret = 0;
351          int    i;
352         while( *haystack )
353         {
354                 for( i = 0; accept[i] && accept[i] == *haystack; i ++ );
355
356                 if( !accept[i] )        return ret;
357                 ret ++;
358         }
359         return ret;
360 }

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