Changeset ef6dd3f in mainline


Ignore:
Timestamp:
2011-06-08T11:51:03Z (13 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1eee1283
Parents:
acc3f82c
Message:

Almost complete implementation of string.h

Location:
uspace/lib/posix
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/string.c

    racc3f82c ref6dd3f  
    3838#include "string.h"
    3939
    40 #include <libc/assert.h>
    41 
     40#include <assert.h>
    4241#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 */
     47static 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 */
     57static 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 */
     71static 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
    4985 */
    5086char *posix_strcpy(char *dest, const char *src)
    5187{
    52         // TODO
    53         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
    6298 */
    6399char *posix_strncpy(char *dest, const char *src, size_t n)
    64100{
    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 */
     111char *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 */
     136char *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
    74164 */
    75165char *posix_strcat(char *dest, const char *src)
    76166{
    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
    87180 */
    88181char *posix_strncat(char *dest, const char *src, size_t n)
    89182{
    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 */
     200void *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 *
    109222 * @param s
    110  * @return
     223 * @return Newly allocated string
    111224 */
    112225char *posix_strdup(const char *s)
    113226{
    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 */
     237char *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;
    116251}
    117252
     
    121256 * @param mem2
    122257 * @param n
    123  * @return
     258 * @return Difference of the first pair of inequal bytes,
     259 *          or 0 if areas have the same content
    124260 */
    125261int posix_memcmp(const void *mem1, const void *mem2, size_t n)
    126262{
    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       
    128275        return 0;
    129276}
     
    137284int posix_strcmp(const char *s1, const char *s2)
    138285{
    139         // TODO
    140         return 0;
     286        assert(s1 != NULL);
     287        assert(s2 != NULL);
     288
     289        return posix_strncmp(s1, s2, STR_NO_LIMIT);
    141290}
    142291
     
    150299int posix_strncmp(const char *s1, const char *s2, size_t n)
    151300{
    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
    178313        return 0;
    179314}
     
    188323void *posix_memchr(const void *mem, int c, size_t n)
    189324{
    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;
    204335}
    205336
     
    212343char *posix_strchr(const char *s, int c)
    213344{
    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;
    216360}
    217361
     
    224368char *posix_strrchr(const char *s, int c)
    225369{
    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 */
     391char *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 */
     406size_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 */
     421size_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 */
     440char *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 */
     468int 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 */
     484size_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 */
     502char *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 */
     516int 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
    227529        return 0;
    228530}
     
    230532/**
    231533 *
    232  * @param s1
    233  * @param s2
    234  * @return
    235  */
    236 char *posix_strpbrk(const char *s1, const char *s2)
    237 {
    238         // TODO
    239         return 0;
    240 }
    241 
    242 /**
    243  *
    244  * @param s1
    245  * @param s2
    246  * @return
    247  */
    248 size_t posix_strcspn(const char *s1, const char *s2)
    249 {
    250         // TODO
    251         return 0;
    252 }
    253 
    254 /**
    255  *
    256  * @param s1
    257  * @param s2
    258  * @return
    259  */
    260 size_t posix_strspn(const char *s1, const char *s2)
    261 {
    262         // TODO
    263         return 0;
    264 }
    265 
    266 /**
    267  *
    268  * @param s1
    269  * @param s2
    270  * @return
    271  */
    272 char *posix_strstr(const char *s1, const char *s2)
    273 {
    274         // TODO
    275         return 0;
    276 }
    277 
    278 /**
    279  *
    280  * @param s1
    281  * @param s2
    282  * @return
    283  */
    284 int posix_strcoll(const char *s1, const char *s2)
    285 {
    286         // TODO
    287         return 0;
    288 }
    289 
    290 /**
    291  *
    292  * @param s1
    293  * @param s2
    294  * @param n
    295  * @return
    296  */
    297 size_t posix_strxfrm(char *s1, const char *s2, size_t n)
    298 {
    299         // TODO
    300         return 0;
    301 }
    302 
    303 /**
    304  *
    305  * @param errnum
    306  * @return
    307  */
    308 char *posix_strerror(int errnum)
    309 {
    310         // TODO
    311         return 0;
    312 }
    313 
    314 /**
    315  *
    316534 * @param s
    317535 * @return
     
    319537size_t posix_strlen(const char *s)
    320538{
    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 */
     550size_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;
    323562}
    324563
  • uspace/lib/posix/string.h

    racc3f82c ref6dd3f  
    4040#include <str.h>
    4141
     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
    4263#ifndef NULL
    4364        #define NULL  ((void *) 0)
     
    4768extern char *posix_strcpy(char *restrict dest, const char *restrict src);
    4869extern char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n);
     70extern char *posix_stpcpy(char *restrict dest, const char *restrict src);
     71extern char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n);
    4972extern char *posix_strcat(char *restrict dest, const char *restrict src);
    5073extern char *posix_strncat(char *restrict dest, const char *restrict src, size_t n);
    51 extern void *posix_mempcpy(void *restrict dest, const void *restrict src, size_t n);
     74extern void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n);
    5275extern char *posix_strdup(const char *s);
     76extern char *posix_strndup(const char *s, size_t n);
    5377
    5478/* String/Array Comparison */
     
    5680extern int posix_strcmp(const char *s1, const char *s2);
    5781extern 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);
    6082
    6183/* Search Functions */
    6284extern void *posix_memchr(const void *mem, int c, size_t n);
    63 extern void *posix_rawmemchr(const void *mem, int c);
    6485extern char *posix_strchr(const char *s, int c);
    6586extern char *posix_strrchr(const char *s, int c);
     
    7596/* Error Messages */
    7697extern char *posix_strerror(int errnum);
     98extern int posix_strerror_r(int errnum, char *buf, size_t bufsz);
    7799
    78100/* String Length */
    79101extern size_t posix_strlen(const char *s);
     102extern size_t posix_strnlen(const char *s, size_t n);
    80103
    81104#ifndef LIBPOSIX_INTERNAL
    82105        #define strcpy posix_strcpy
    83106        #define strncpy posix_strncpy
     107        #define stpcpy posix_stpcpy
     108        #define stpncpy posix_stpncpy
    84109        #define strcat posix_strcat
    85110        #define strncat posix_strncat
    86         #define mempcpy posix_mempcpy
     111        #define memccpy posix_memccpy
    87112        #define strdup posix_strdup
     113        #define strndup posix_strndup
    88114
    89115        #define memcmp posix_memcmp
    90116        #define strcmp posix_strcmp
    91117        #define strncmp posix_strncmp
    92         #define strcasecmp posix_strcasecmp
    93         #define strncasecmp posix_strncasecmp
    94118
    95119        #define memchr posix_memchr
    96         #define rawmemchr posix_rawmemchr
    97120        #define strchr posix_strchr
    98121        #define strrchr posix_strrchr
     
    106129
    107130        #define strerror posix_strerror
     131        #define strerror_r posix_strerror_r
     132        #define strsignal(i) ((char*) "SIGNonSense: There are no signals in HelenOS.")
    108133
    109134        #define strlen posix_strlen
     135        #define strnlen posix_strnlen
    110136#endif
    111137
Note: See TracChangeset for help on using the changeset viewer.