Changeset ef6dd3f in mainline
- Timestamp:
- 2011-06-08T11:51:03Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1eee1283
- Parents:
- acc3f82c
- Location:
- uspace/lib/posix
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/string.c
racc3f82c ref6dd3f 38 38 #include "string.h" 39 39 40 #include <libc/assert.h> 41 40 #include <assert.h> 42 41 #include <str_error.h> 43 44 /** 45 * 46 * @param dest 47 * @param src 48 * @return 42 #include <stdlib.h> 43 #include <errno.h> 44 45 /* Defined for convenience. Returns pointer to the terminating nul character. 46 */ 47 static char *strzero(const char *s) 48 { 49 while (*s != '\0') 50 s ++; 51 52 return (char*) s; 53 } 54 55 /* Returns true if s2 is a prefix of s1. 56 */ 57 static bool begins_with(const char *s1, const char *s2) 58 { 59 while (*s1 == *s2 && *s2 != '\0') { 60 s1 ++; 61 s2 ++; 62 } 63 64 /* true if the end was reached */ 65 return *s2 == '\0'; 66 } 67 68 /* The same as strpbrk, except it returns pointer to the nul terminator 69 * if no occurence is found. 70 */ 71 static char *strpbrk_null(const char *s1, const char *s2) 72 { 73 while (!posix_strchr(s2, *s1)) { 74 ++ s1; 75 } 76 77 return (char *) s1; 78 } 79 80 /** 81 * 82 * @param dest 83 * @param src 84 * @return dest 49 85 */ 50 86 char *posix_strcpy(char *dest, const char *src) 51 87 { 52 // TODO53 return 0;54 } 55 56 /** 57 * 58 * @param dest 59 * @param src 60 * @param n 61 * @return 88 posix_stpcpy(dest, src); 89 return dest; 90 } 91 92 /** 93 * 94 * @param dest 95 * @param src 96 * @param n 97 * @return dest 62 98 */ 63 99 char *posix_strncpy(char *dest, const char *src, size_t n) 64 100 { 65 // TODO 66 return 0; 67 } 68 69 /** 70 * 71 * @param dest 72 * @param src 73 * @return 101 posix_stpncpy(dest, src, n); 102 return dest; 103 } 104 105 /** 106 * 107 * @param dest 108 * @param src 109 * @return Pointer to the nul character in the dest string 110 */ 111 char *posix_stpcpy(char *restrict dest, const char *restrict src) 112 { 113 assert(dest != NULL); 114 assert(src != NULL); 115 116 for (size_t i = 0; ; ++ i) { 117 dest[i] = src[i]; 118 119 if (src[i] == '\0') { 120 /* pointer to the terminating nul character */ 121 return &dest[i]; 122 } 123 } 124 125 /* unreachable */ 126 return NULL; 127 } 128 129 /** 130 * 131 * @param dest 132 * @param src 133 * @param n 134 * @return Pointer to the first written nul character or &dest[n] 135 */ 136 char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n) 137 { 138 assert(dest != NULL); 139 assert(src != NULL); 140 141 for (size_t i = 0; i < n; ++ i) { 142 dest[i] = src[i]; 143 144 /* the standard requires that nul characters 145 * are appended to the length of n, in case src is shorter 146 */ 147 if (src[i] == '\0') { 148 char *result = &dest[i]; 149 for (++ i; i < n; ++ i) { 150 dest[i] = '\0'; 151 } 152 return result; 153 } 154 } 155 156 return &dest[n]; 157 } 158 159 /** 160 * 161 * @param dest 162 * @param src 163 * @return dest 74 164 */ 75 165 char *posix_strcat(char *dest, const char *src) 76 166 { 77 // TODO 78 return 0; 79 } 80 81 /** 82 * 83 * @param dest 84 * @param src 85 * @param n 86 * @return 167 assert(dest != NULL); 168 assert(src != NULL); 169 170 posix_strcpy(strzero(dest), src); 171 return dest; 172 } 173 174 /** 175 * 176 * @param dest 177 * @param src 178 * @param n 179 * @return dest 87 180 */ 88 181 char *posix_strncat(char *dest, const char *src, size_t n) 89 182 { 90 // TODO 91 return 0; 92 } 93 94 /** 95 * 96 * @param dest 97 * @param src 98 * @param n 99 * @return 100 */ 101 void *posix_mempcpy(void *dest, const void *src, size_t n) 102 { 103 // TODO 104 return 0; 105 } 106 107 /** 108 * 183 assert(dest != NULL); 184 assert(src != NULL); 185 186 char *zeroptr = posix_strncpy(strzero(dest), src, n); 187 /* strncpy doesn't append the nul terminator, so we do it here */ 188 zeroptr[n] = '\0'; 189 return dest; 190 } 191 192 /** 193 * 194 * @param dest 195 * @param src 196 * @param c 197 * @param n 198 * @return Pointer to the first byte after c in dest if found, NULL otherwise. 199 */ 200 void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n) 201 { 202 assert(dest != NULL); 203 assert(src != NULL); 204 205 unsigned char* bdest = dest; 206 const unsigned char* bsrc = src; 207 208 for (size_t i = 0; i < n; ++ i) { 209 bdest[i] = bsrc[i]; 210 211 if (bsrc[i] == (unsigned char) c) { 212 /* pointer to the next byte */ 213 return &bdest[i + 1]; 214 } 215 } 216 217 return NULL; 218 } 219 220 /** 221 * 109 222 * @param s 110 * @return 223 * @return Newly allocated string 111 224 */ 112 225 char *posix_strdup(const char *s) 113 226 { 114 // TODO 115 return 0; 227 // FIXME: SIZE_MAX doesn't work 228 return posix_strndup(s, STR_NO_LIMIT); 229 } 230 231 /** 232 * 233 * @param s 234 * @param n 235 * @return Newly allocated string of length at most n 236 */ 237 char *posix_strndup(const char *s, size_t n) 238 { 239 assert(s != NULL); 240 241 size_t len = posix_strnlen(s, n); 242 char *dup = malloc(len + 1); 243 if (dup == NULL) { 244 return NULL; 245 } 246 247 memcpy(dup, s, len); 248 dup[len] = '\0'; 249 250 return dup; 116 251 } 117 252 … … 121 256 * @param mem2 122 257 * @param n 123 * @return 258 * @return Difference of the first pair of inequal bytes, 259 * or 0 if areas have the same content 124 260 */ 125 261 int posix_memcmp(const void *mem1, const void *mem2, size_t n) 126 262 { 127 // TODO 263 assert(mem1 != NULL); 264 assert(mem2 != NULL); 265 266 const unsigned char *s1 = mem1; 267 const unsigned char *s2 = mem2; 268 269 for (size_t i = 0; i < n; ++ i) { 270 if (s1[i] != s2[i]) { 271 return s2[i] - s1[i]; 272 } 273 } 274 128 275 return 0; 129 276 } … … 137 284 int posix_strcmp(const char *s1, const char *s2) 138 285 { 139 // TODO 140 return 0; 286 assert(s1 != NULL); 287 assert(s2 != NULL); 288 289 return posix_strncmp(s1, s2, STR_NO_LIMIT); 141 290 } 142 291 … … 150 299 int posix_strncmp(const char *s1, const char *s2, size_t n) 151 300 { 152 // TODO 153 return 0; 154 } 155 156 /** 157 * 158 * @param s1 159 * @param s2 160 * @return 161 */ 162 int posix_strcasecmp(const char *s1, const char *s2) 163 { 164 // TODO 165 return 0; 166 } 167 168 /** 169 * 170 * @param s1 171 * @param s2 172 * @param n 173 * @return 174 */ 175 int posix_strncasecmp(const char *s1, const char *s2, size_t n) 176 { 177 // TODO 301 assert(s1 != NULL); 302 assert(s2 != NULL); 303 304 for (size_t i = 0; i < n; ++ i) { 305 if (s1[i] != s2[i]) { 306 return s2[i] - s1[i]; 307 } 308 if (s1[i] == '\0') { 309 break; 310 } 311 } 312 178 313 return 0; 179 314 } … … 188 323 void *posix_memchr(const void *mem, int c, size_t n) 189 324 { 190 // TODO 191 return 0; 192 } 193 194 /** 195 * 196 * @param mem 197 * @param c 198 * @return 199 */ 200 void *posix_rawmemchr(const void *mem, int c) 201 { 202 // TODO 203 return 0; 325 assert(mem != NULL); 326 327 const unsigned char *s = mem; 328 329 for (size_t i = 0; i < n; ++ i) { 330 if (s[i] == (unsigned char) c) { 331 return (void *) &s[i]; 332 } 333 } 334 return NULL; 204 335 } 205 336 … … 212 343 char *posix_strchr(const char *s, int c) 213 344 { 214 // TODO 215 return 0; 345 assert(s != NULL); 346 347 /* special handling for the case that zero is searched for */ 348 if (c == '\0') 349 return strzero(s); 350 351 /* otherwise just loop through the string until found */ 352 while (*s != (char) c) { 353 if (*s == '\0') 354 return NULL; 355 356 s ++; 357 } 358 359 return (char *) s; 216 360 } 217 361 … … 224 368 char *posix_strrchr(const char *s, int c) 225 369 { 226 // TODO 370 assert(s != NULL); 371 372 const char *ptr = strzero(s); 373 374 /* the same as in strchr, except it loops in reverse direction */ 375 while (*ptr != (char) c) { 376 if (ptr == s) 377 return NULL; 378 379 ptr ++; 380 } 381 382 return (char *) ptr; 383 } 384 385 /** 386 * 387 * @param s1 388 * @param s2 389 * @return 390 */ 391 char *posix_strpbrk(const char *s1, const char *s2) 392 { 393 assert(s1 != NULL); 394 assert(s2 != NULL); 395 396 char *ptr = strpbrk_null(s1, s2); 397 return (*ptr == '\0') ? NULL : ptr; 398 } 399 400 /** 401 * 402 * @param s1 403 * @param s2 404 * @return 405 */ 406 size_t posix_strcspn(const char *s1, const char *s2) 407 { 408 assert(s1 != NULL); 409 assert(s2 != NULL); 410 411 char *ptr = strpbrk_null(s1, s2); 412 return (size_t) (ptr - s1); 413 } 414 415 /** 416 * 417 * @param s1 418 * @param s2 419 * @return 420 */ 421 size_t posix_strspn(const char *s1, const char *s2) 422 { 423 assert(s1 != NULL); 424 assert(s2 != NULL); 425 426 const char *ptr; 427 for (ptr = s1; *ptr != '\0'; ++ ptr) { 428 if (!posix_strchr(s2, *ptr)) 429 break; 430 } 431 return ptr - s1; 432 } 433 434 /** 435 * 436 * @param s1 437 * @param s2 438 * @return 439 */ 440 char *posix_strstr(const char *s1, const char *s2) 441 { 442 assert(s1 != NULL); 443 assert(s2 != NULL); 444 445 /* special case - needle is an empty string */ 446 if (*s2 == '\0') 447 return (char *) s1; 448 449 // TODO: use faster algorithm 450 /* check for prefix from every position - quadratic complexity */ 451 while (*s1 != '\0') { 452 if (begins_with(s1, s2)) 453 return (char *) s1; 454 455 s1 ++; 456 } 457 458 return NULL; 459 } 460 461 /** 462 * Currently ignores locale and just calls strcmp. 463 * 464 * @param s1 465 * @param s2 466 * @return 467 */ 468 int posix_strcoll(const char *s1, const char *s2) 469 { 470 assert(s1 != NULL); 471 assert(s2 != NULL); 472 473 return posix_strcmp(s1, s2); 474 } 475 476 /** 477 * strcoll is equal to strcmp here, so this just makes a copy. 478 * 479 * @param s1 480 * @param s2 481 * @param n 482 * @return 483 */ 484 size_t posix_strxfrm(char *s1, const char *s2, size_t n) 485 { 486 assert(s1 != NULL || n == 0); 487 assert(s2 != NULL); 488 489 size_t len = posix_strlen(s2); 490 491 if (n > len) 492 posix_strcpy(s1, s2); 493 494 return len; 495 } 496 497 /** 498 * 499 * @param errnum 500 * @return 501 */ 502 char *posix_strerror(int errnum) 503 { 504 /* uses function from libc, we just have to negate errno 505 (POSIX uses positive errorcodes, HelenOS has negative) */ 506 return (char *) str_error (-errnum); 507 } 508 509 /** 510 * 511 * @param errnum Error code 512 * @param buf Buffer to store a human readable string to 513 * @param bufsz Size of buffer pointed to by buf 514 * @return 515 */ 516 int posix_strerror_r(int errnum, char *buf, size_t bufsz) 517 { 518 assert(buf != NULL); 519 520 char *errstr = posix_strerror(errnum); 521 /* HelenOS str_error can't fail */ 522 523 if (posix_strlen(errstr) + 1 > bufsz) { 524 return -ERANGE; 525 } else { 526 posix_strcpy(buf, errstr); 527 } 528 227 529 return 0; 228 530 } … … 230 532 /** 231 533 * 232 * @param s1233 * @param s2234 * @return235 */236 char *posix_strpbrk(const char *s1, const char *s2)237 {238 // TODO239 return 0;240 }241 242 /**243 *244 * @param s1245 * @param s2246 * @return247 */248 size_t posix_strcspn(const char *s1, const char *s2)249 {250 // TODO251 return 0;252 }253 254 /**255 *256 * @param s1257 * @param s2258 * @return259 */260 size_t posix_strspn(const char *s1, const char *s2)261 {262 // TODO263 return 0;264 }265 266 /**267 *268 * @param s1269 * @param s2270 * @return271 */272 char *posix_strstr(const char *s1, const char *s2)273 {274 // TODO275 return 0;276 }277 278 /**279 *280 * @param s1281 * @param s2282 * @return283 */284 int posix_strcoll(const char *s1, const char *s2)285 {286 // TODO287 return 0;288 }289 290 /**291 *292 * @param s1293 * @param s2294 * @param n295 * @return296 */297 size_t posix_strxfrm(char *s1, const char *s2, size_t n)298 {299 // TODO300 return 0;301 }302 303 /**304 *305 * @param errnum306 * @return307 */308 char *posix_strerror(int errnum)309 {310 // TODO311 return 0;312 }313 314 /**315 *316 534 * @param s 317 535 * @return … … 319 537 size_t posix_strlen(const char *s) 320 538 { 321 // TODO 322 return 0; 539 assert(s != NULL); 540 541 return (size_t) (strzero(s) - s); 542 } 543 544 /** 545 * 546 * @param s 547 * @param n 548 * @return 549 */ 550 size_t posix_strnlen(const char *s, size_t n) 551 { 552 assert(s != NULL); 553 554 for (size_t sz = 0; sz < n; ++ sz) { 555 556 if (s[sz] == '\0') { 557 return sz; 558 } 559 } 560 561 return n; 323 562 } 324 563 -
uspace/lib/posix/string.h
racc3f82c ref6dd3f 40 40 #include <str.h> 41 41 42 /* available in str.h 43 * 44 * char *strtok(char *restrict, const char *restrict); 45 * char *strtok_r(char *restrict, const char *restrict, char **restrict); 46 * 47 * available in mem.h 48 * 49 * void *memset(void *, int, size_t); 50 * void *memcpy(void *, const void *, size_t); 51 * void *memmove(void *, const void *, size_t); 52 * 53 * unimplemented due to missing locales 54 * 55 * int strcoll_l(const char *, const char *, locale_t); 56 * char *strerror_l(int, locale_t); 57 * size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t); 58 * 59 */ 60 61 // TODO: provide *_l once there is locale.h 62 42 63 #ifndef NULL 43 64 #define NULL ((void *) 0) … … 47 68 extern char *posix_strcpy(char *restrict dest, const char *restrict src); 48 69 extern char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n); 70 extern char *posix_stpcpy(char *restrict dest, const char *restrict src); 71 extern char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n); 49 72 extern char *posix_strcat(char *restrict dest, const char *restrict src); 50 73 extern char *posix_strncat(char *restrict dest, const char *restrict src, size_t n); 51 extern void *posix_mem pcpy(void *restrict dest, const void *restrict src, size_t n);74 extern void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n); 52 75 extern char *posix_strdup(const char *s); 76 extern char *posix_strndup(const char *s, size_t n); 53 77 54 78 /* String/Array Comparison */ … … 56 80 extern int posix_strcmp(const char *s1, const char *s2); 57 81 extern int posix_strncmp(const char *s1, const char *s2, size_t n); 58 extern int posix_strcasecmp(const char *s1, const char *s2);59 extern int posix_strncasecmp(const char *s1, const char *s2, size_t n);60 82 61 83 /* Search Functions */ 62 84 extern void *posix_memchr(const void *mem, int c, size_t n); 63 extern void *posix_rawmemchr(const void *mem, int c);64 85 extern char *posix_strchr(const char *s, int c); 65 86 extern char *posix_strrchr(const char *s, int c); … … 75 96 /* Error Messages */ 76 97 extern char *posix_strerror(int errnum); 98 extern int posix_strerror_r(int errnum, char *buf, size_t bufsz); 77 99 78 100 /* String Length */ 79 101 extern size_t posix_strlen(const char *s); 102 extern size_t posix_strnlen(const char *s, size_t n); 80 103 81 104 #ifndef LIBPOSIX_INTERNAL 82 105 #define strcpy posix_strcpy 83 106 #define strncpy posix_strncpy 107 #define stpcpy posix_stpcpy 108 #define stpncpy posix_stpncpy 84 109 #define strcat posix_strcat 85 110 #define strncat posix_strncat 86 #define mem pcpy posix_mempcpy111 #define memccpy posix_memccpy 87 112 #define strdup posix_strdup 113 #define strndup posix_strndup 88 114 89 115 #define memcmp posix_memcmp 90 116 #define strcmp posix_strcmp 91 117 #define strncmp posix_strncmp 92 #define strcasecmp posix_strcasecmp93 #define strncasecmp posix_strncasecmp94 118 95 119 #define memchr posix_memchr 96 #define rawmemchr posix_rawmemchr97 120 #define strchr posix_strchr 98 121 #define strrchr posix_strrchr … … 106 129 107 130 #define strerror posix_strerror 131 #define strerror_r posix_strerror_r 132 #define strsignal(i) ((char*) "SIGNonSense: There are no signals in HelenOS.") 108 133 109 134 #define strlen posix_strlen 135 #define strnlen posix_strnlen 110 136 #endif 111 137
Note:
See TracChangeset
for help on using the changeset viewer.