iso9660: ~Check signature
[meinos.git] / lib / stdlibc / string.c
blob1a7c113e50eb36b01fb95354b371d8a5b8f3f8b4
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <malloc.h>
23 #include <limits.h>
24 #include <ctype.h>
26 static const char *errno_strings[] = {
27 "No Error",
28 "Argument list too long.",
29 "Permission denied.",
30 "Address in use.",
31 "Address not available.",
32 "Address family not supported.",
33 "Resource unavailable, try again.",
34 "Connection already in progress.",
35 "Bad file descriptor.",
36 "Bad message.",
37 "Device or resource busy.",
38 "Operation canceled.",
39 "No child processes.",
40 "Connection aborted.",
41 "Connection refused.",
42 "Connection reset.",
43 "Resource deadlock would occur.",
44 "Destination address required.",
45 "Mathematics argument out of domain of function.",
46 "Reserved.",
47 "File exists.",
48 "Bad address.",
49 "File too large.",
50 "Host is unreachable.",
51 "Identifier removed.",
52 "Illegal byte sequence.",
53 "Operation in progress.",
54 "Interrupted function.",
55 "Invalid argument.",
56 "I/O error.",
57 "Socket is connected.",
58 "Is a directory.",
59 "Too many levels of symbolic links.",
60 "Too many open files.",
61 "Too many links.",
62 "Message too large.",
63 "Reserved.",
64 "Filename too long.",
65 "Network is down.",
66 "Connection aborted by network.",
67 "Network unreachable.",
68 "Too many files open in system.",
69 "No buffer space available.",
70 "No message is available on the STREAM head read queue.",
71 "No such device.",
72 "No such file or directory.",
73 "Executable file format error.",
74 "No locks available.",
75 "Reserved.",
76 "Not enough space.",
77 "No message of the desired type.",
78 "Protocol not available.",
79 "No space left on device.",
80 "No STREAM resources.",
81 "Not a STREAM.",
82 "Function not supported.",
83 "The socket is not connected.",
84 "Not a directory.",
85 "Directory not empty.",
86 "Not a socket.",
87 "Not supported.",
88 "Inappropriate I/O control operation.",
89 "No such device or address.",
90 "Operation not supported on socket.",
91 "Value too large to be stored in data type.",
92 "Operation not permitted.",
93 "Broken pipe.",
94 "Protocol error.",
95 "Protocol not supported.",
96 "Protocol wrong type for socket.",
97 "Result too large.",
98 "Read-only file system.",
99 "Invalid seek.",
100 "No such process.",
101 "Reserved.",
102 "Stream ioctl() timeout.",
103 "Connection timed out.",
104 "Text file busy.",
105 "Operation would block.",
106 "Cross-device link."
110 * Copies memory
111 * @param dest Destination for memory copy
112 * @param src Source for memory copy
113 * @param c Char which first oncurrence will stop copying
114 * @param n How many bytes to copy
115 * @return dest
117 void *memccpy(void *dest,const void *src,int c,size_t n) {
118 uint8_t *dest8 = (uint8_t*)dest;
119 uint8_t *src8 = (uint8_t*)src;
120 uint32_t i;
122 for (i=0;i<n;i++) {
123 dest8[i] = src8[i];
124 if (src8[i]==((uint8_t)c)) break;
126 return dest;
130 * Searches for c in src
131 * @param src Pointer where to search
132 * @param c Byte to search
133 * @param n How many bytes to search in
134 * @return Pointer to c in src
136 void *memchr(const void *src,int c,size_t n) {
137 uint8_t *src8 = (uint8_t*)src;
138 uint32_t i;
140 for (i=0;i<n;i++) {
141 if (src8[i]==((uint8_t)c)) return (void*)(src8+i);
143 return NULL;
147 * Compares memory
148 * @param srca First source to compare
149 * @param srcb Second source to compare
150 * @param n How many bytes to compare
151 * @return 0 = equal
153 int memcmp(const void *srca,const void *srcb,size_t n) {
154 if (srca==srcb) return 0;
155 size_t fast_count = n/sizeof(int);
156 size_t byte_count = n%sizeof(int);
157 int *fast_srca = (int*)srca;
158 int *fast_srcb = (int*)srcb;
159 uint8_t *byte_srca = ((uint8_t*)srca)+fast_count*sizeof(int);
160 uint8_t *byte_srcb = ((uint8_t*)srcb)+fast_count*sizeof(int);
161 size_t i;
163 for (i=0;i<fast_count;i++) {
164 if (fast_srca[i]!=fast_srcb[i]) return fast_srca[i]-fast_srcb[i];
166 for (i=0;i<byte_count;i++) {
167 if (byte_srca[i]!=byte_srcb[i]) return byte_srca[i]-byte_srcb[i];
169 return 0;
173 * Copies memory
174 * @param dest Destination for memory copy
175 * @param src Source for memory copy
176 * @param n How many bytes to copy
177 * @return dest
179 void *memcpy(void *dest,const void *src,size_t n) {
180 if (dest==src) return dest;
181 size_t fast_count = n/sizeof(int);
182 size_t byte_count = n%sizeof(int);
183 int *fast_dest = (int*)dest;
184 int *fast_src = (int*)src;
185 uint8_t *byte_dest = ((uint8_t*)dest)+fast_count*sizeof(int);
186 uint8_t *byte_src = ((uint8_t*)src)+fast_count*sizeof(int);
187 size_t i;
189 for (i=0;i<fast_count;i++) fast_dest[i] = fast_src[i];
190 for (i=0;i<byte_count;i++) byte_dest[i] = byte_src[i];
191 return dest;
195 * Moves memory
196 * @param dest Destination
197 * @param src Source
198 * @param n How many bytes to move
199 * @todo Please do it the right way
201 void *memmove(void *dest, const void *src, size_t n) {
202 if (dest==src) return dest;
203 size_t fast_count = n/sizeof(int);
204 size_t byte_count = n%sizeof(int);
205 int *fast_dest = (int*)dest;
206 int *fast_src = (int*)src;
207 uint8_t *byte_dest = ((uint8_t*)dest)+fast_count*sizeof(int);
208 uint8_t *byte_src = ((uint8_t*)src)+fast_count*sizeof(int);
209 size_t i;
211 if (src>dest) {
212 for (i=0;i<fast_count;i++) fast_dest[i] = fast_src[i];
213 for (i=0;i<byte_count;i++) byte_dest[i] = byte_src[i];
215 else {
216 for (i=byte_count;i>0;i--) byte_dest[i-1] = byte_src[i-1];
217 for (i=fast_count;i>0;i--) fast_dest[i-1] = fast_src[i-1];
219 return dest;
223 * Writes specified value in memory
224 * @param dest Destination memory
225 * @param val Value to write in memory
226 * @param n How many bytes to write
227 * @return dest
229 void *memset(void *dest,int val,size_t n) {
230 /*size_t fast_count = n/sizeof(int);
231 size_t byte_count = n%sizeof(int);
232 int *fast_dest = (int*)dest;
233 uint8_t *byte_dest = ((uint8_t*)dest)+fast_count*sizeof(int);
234 uint8_t byte_val = (uint8_t)val;
235 int fast_val = 0;
236 size_t i;
238 for (i=0;i<sizeof(int)*8;i+=8) fast_val |= (val&0xFF)<<i;
239 for (i=0;i<fast_count;i++) fast_dest[i] = fast_val;
240 for (i=0;i<byte_count;i++) byte_dest[i] = byte_val;
241 return dest;*/
243 size_t i;
244 uint8_t *byte_dest = (uint8_t*)dest;
245 for (i=0;i<n;i++) byte_dest[i] = val;
246 return dest;
250 * Puts two strings together
251 * @param str1 First string
252 * @param str2 Second string
253 * @return New string
255 char *strcat(char *str1,const char *str2) {
256 return strcpy(str1+strlen(str1),str2);
260 * Locates the first occurrence of a character in a string
261 * @param str String to search in
262 * @param chr Character to search
263 * @return Pointer (String) to character
265 char *strchr(const char *str,int chr) {
266 size_t i;
267 for (i=0;(str[i]!=0 && str[i]!=(char)chr);i++);
268 return str[i]==chr?(char*)str+i:NULL;
272 * Compares two strings
273 * @param str1 First string
274 * @param str2 Second string
275 * @return 0 if strings are equal
277 int strcmp(const char *str1,const char *str2) {
278 if (str1==str2) return 0;
279 size_t i;
281 for (i=0;(str1[i] || str2[i]);i++) {
282 if (str1[i]!=str2[i]) return str1[i]-str2[i];
284 return 0;
288 * Copies a string
289 * @param dest Destination where to store the string
290 * @param src Source string
291 * @return returns dest
293 char *strcpy(char *dest,const char *src) {
294 size_t i;
295 for (i=0;src[i];i++) dest[i] = src[i];
296 dest[i] = 0;
297 return dest;
301 * Duplicates a string
302 * @param src String to duplicate
303 * @return New string
305 char *strdup(const char *src) {
306 size_t len = strlen(src)+1;
307 return memcpy(malloc(len),src,len);
311 * Returns an error string
312 * @param errnum Error number
313 * @return Error string
315 char *strerror(int errnum) {
316 return (char*)errno_strings[errnum];
320 * Gets string length
321 * @param str String
322 * @return length of string
324 size_t strlen(const char *str) {
325 if (str==NULL) return 0;
326 size_t i;
327 for (i=0;str[i];i++);
328 return i;
332 * Appends one string to another with limited size
333 * @param src1 First string
334 * @param src2 Second string, it will be appended to src1
335 * @param n Maximal bytes to append
337 char *strncat(char *src1,const char *src2,size_t n) {
338 size_t src2len = strlen(src2);
339 src2len = n<src2len?n:src2len;
340 size_t src1len = strlen(src1);
341 uint32_t i;
343 for (i=0;i<src2len;i++) {
344 src1[src1len+i] = src2[i];
346 src1[src1len+src2len] = 0;
347 return src1;
351 * Compares to strings until end of string or n bytes
352 * @param str1 String 1
353 * @param str2 String 2
354 * @param n How many bytes to compare maximum
355 * @return 0 if strings are equal
357 int strncmp(const char *str1,const char *str2,size_t n) {
358 if (str1==str2) return 0;
359 size_t i;
361 for (i=0;(str1[i] || str2[i]) && i<n;i++) {
362 if (str1[i]!=str2[i]) return str1[i]-str2[i];
364 return 0;
368 * Copies string, but maximal n bytes
369 * @param dest Destination to copy to
370 * @param src Source to copy from
371 * @param n How many bytes to copy maximal
372 * @return dest
374 char *strncpy(char *dest,const char *src,size_t n) {
375 size_t len = strlen(src)+1;
376 if (n<len) len = n;
377 memcpy(dest,src,len-1);
378 dest[len-1] = 0;
379 return dest;
382 static size_t __strxspn(const char *s, const char *map, int parity)
384 char matchmap[UCHAR_MAX + 1];
385 size_t n = 0;
387 /* Create bitmap */
388 memset(matchmap, 0, sizeof matchmap);
389 while (*map)
390 matchmap[(unsigned char)*map++] = 1;
392 /* Make sure the null character never matches */
393 matchmap[0] = parity;
395 /* Calculate span length */
396 while (matchmap[(unsigned char)*s++] ^ parity)
397 n++;
399 return n;
402 char *strpbrk(const char *s, const char *accept)
404 const char *ss = s + __strxspn(s, accept, 1);
406 return *ss ? (char *)ss : NULL;
409 char *strsep(char **stringp, const char *delim)
411 char *s = *stringp;
412 char *e;
414 if (!s)
415 return NULL;
417 e = strpbrk(s, delim);
418 if (e)
419 *e++ = '\0';
421 *stringp = e;
422 return s;
425 char *strtok(char *s, const char *delim)
427 static char *holder;
429 if (s)
430 holder = s;
432 do {
433 s = strsep(&holder, delim);
434 } while (s && !*s);
436 return s;
439 // in inttypes.h
440 static inline int digitval(int ch) {
441 if (ch>='0' && ch<='9') return ch-'0';
442 else if (ch>='A' && ch<='Z') return ch-'A'+10;
443 else if (ch>='a' && ch<='z') return ch-'a'+10;
444 else return -1;
447 uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
448 int minus = 0;
449 uintmax_t v = 0;
450 int d;
452 while (n && isspace((unsigned char)*nptr)) {
453 nptr++;
454 n--;
457 /* Single optional + or - */
458 if (n) {
459 char c = *nptr;
460 if (c=='-' || c=='+') {
461 minus = (c=='-');
462 nptr++;
463 n--;
467 if (base==0) {
468 if (n>=2 && nptr[0]=='0' && (nptr[1]=='x' || nptr[1]=='X')) {
469 n -= 2;
470 nptr += 2;
471 base = 16;
473 else if (n >= 1 && nptr[0] == '0') {
474 n--;
475 nptr++;
476 base = 8;
478 else base = 10;
480 else if (base==16) {
481 if (n>=2 && nptr[0]=='0' && (nptr[1]=='x' || nptr[1]=='X')) {
482 n -= 2;
483 nptr += 2;
487 while (n && (d = digitval(*nptr))>=0 && d<base) {
488 v = v*base+d;
489 n--;
490 nptr++;
493 if (endptr)
494 *endptr = (char*)nptr;
496 return minus?-v:v;
499 intmax_t strntoimax(const char *nptr,char **endptr,int base,size_t n) {
500 return (intmax_t) strntoumax(nptr,endptr,base,n);
503 uintmax_t strtoumax(const char *nptr,char **endptr,int base) {
504 return (uintmax_t)strntoumax(nptr,endptr,base,~(size_t)0);
507 intmax_t strtoimax(const char *nptr,char **endptr,int base) {
508 return (intmax_t)strntoumax(nptr,endptr,base,~(size_t)0);
511 char *strrchr(const char *s, int c) {
512 char *l = NULL;
513 size_t i;
514 for (i=0;s[i];i++) {
515 if (s[i]==c) l = (char*)s+i;
517 return l;
520 static size_t strxspn(const char *s,const char *map,int parity) {
521 char matchmap[UCHAR_MAX+1];
522 size_t n = 0;
524 /* Create bitmap */
525 memset(matchmap,0,sizeof matchmap);
526 while (*map) matchmap[(unsigned char)*map++] = 1;
528 /* Make sure the null character never matches */
529 matchmap[0] = parity;
531 /* Calculate span length */
532 while (matchmap[(unsigned char)*s++]^parity) n++;
534 return n;
537 size_t strspn(const char *s,const char *accept) {
538 return strxspn(s,accept,0);
541 size_t strcspn(const char *s,const char *reject) {
542 return strxspn(s,reject,1);
545 void *mempcpy(void *dest,const void *src,size_t n) {
546 memcpy(dest,src,n);
547 return dest+n;
550 char *stpcpy(char *dest,const char *src) {
551 size_t i;
552 for (i=0;src[i]!=0;i++) {
553 dest[i] = src[i];
555 return dest+i;
558 void *memmem(const void *haystack,size_t n,const void *needle,size_t m) {
559 const unsigned char *y = (const unsigned char*)haystack;
560 const unsigned char *x = (const unsigned char*)needle;
561 size_t j,k,l;
563 if (m>n || !m || !n) return NULL;
565 if (m!=1) {
566 if (x[0]==x[1]) {
567 k = 2;
568 l = 1;
570 else {
571 k = 1;
572 l = 2;
575 j = 0;
576 while (j<=n-m) {
577 if (x[1] != y[j + 1]) j += k;
578 else {
579 if (!memcmp(x+2,y+j+2,m-2) && x[0]==y[j]) return (void *)&y[j];
580 j += l;
584 else {
585 do {
586 if (*y == *x) return (void *)y;
587 y++;
588 } while (--n);
590 return NULL;
593 char *strstr(const char *haystack,const char *needle) {
594 return (char*)memmem(haystack,strlen(haystack),needle,strlen(needle));
597 void memswap(void *m1,void *m2,size_t n) {
598 char *p = m1;
599 char *q = m2;
600 char tmp;
602 while (n--) {
603 tmp = *p;
604 *p = *q;
605 *q = tmp;
606 p++;
607 q++;