Changeset b888d5f in mainline


Ignore:
Timestamp:
2009-04-03T07:52:29Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
043eca0
Parents:
7ce3cb2
Message:

cleanup and extend string functions according to agreed conventions

Location:
kernel/generic
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/string.h

    r7ce3cb2 rb888d5f  
    3838#include <typedefs.h>
    3939
    40 #define UTF8_NO_LIMIT  ((size_t) -1)
     40#define STR_NO_LIMIT  ((size_t) -1)
     41
     42/**< Maximum size of a string containing cnt characters */
     43#define STR_BOUNDS(cnt)  (cnt << 2)
    4144
    4245extern char invalch;
    4346
    44 extern wchar_t chr_decode(const char *, size_t *, size_t);
    45 extern int chr_encode(wchar_t, char *, size_t *, size_t);
    46 extern count_t chr_width(wchar_t);
     47extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
     48extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
    4749
    48 extern size_t str_size(const char *);
    49 extern size_t str_lsize(const char *, count_t);
    50 extern size_t str_wsize(const char *, count_t);
     50extern size_t str_size(const char *str);
     51extern size_t wstr_size(const wchar_t *str);
    5152
    52 extern count_t str_length(const char *);
    53 extern count_t wstr_length(const wchar_t *);
    54 extern count_t wstr_wlength(const wchar_t *, count_t);
     53extern size_t str_lsize(const char *str, count_t max_len);
     54extern size_t wstr_lsize(const wchar_t *str, count_t max_len);
     55
     56extern count_t str_length(const char *str);
     57extern count_t wstr_length(const wchar_t *wstr);
     58
     59extern count_t str_nlength(const char *str, size_t size);
     60extern count_t wstr_nlength(const wchar_t *str, size_t size);
    5561
    5662extern bool ascii_check(const wchar_t ch);
    57 extern bool unicode_check(const wchar_t ch);
     63extern bool chr_check(const wchar_t ch);
    5864
    59 extern int strcmp(const char *src, const char *dst);
    60 extern int strncmp(const char *src, const char *dst, size_t len);
    61 extern void strncpy(char *dest, const char *src, size_t len);
     65extern int str_cmp(const char *s1, const char *s2);
     66extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
    6267
    63 extern char *strchr(const char *s, int i);
     68extern void str_ncpy(char *dst, const char *src, size_t size);
     69extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
     70
     71extern const char *str_chr(const char *str, wchar_t ch);
     72
     73extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
     74extern bool wstr_remove(wchar_t *str, count_t pos);
    6475
    6576#endif
  • kernel/generic/src/lib/string.c

    r7ce3cb2 rb888d5f  
    3838 * strings, called just strings are encoded in UTF-8. Wide strings (encoded
    3939 * in UTF-32) are supported to a limited degree. A single character is
    40  * represented as wchar_t.
    41  *
    42  * Strings have the following metrics:
    43  *
    44  *      Metric  Abbrev. Meaning
    45  *      ------  ------  -------
    46  *      size    n       Number of bytes the string is encoded into, excluding
    47  *                      the null terminator.
    48  *      length  l       The number of characters in the string, excluding
    49  *                      the null terminator.
    50  *      width   w       The number of character cells the string takes up on a
    51  *                      monospace display.
    52  *
    53  * Naming scheme:
    54  *
    55  *      chr_xxx         operate on characters
    56  *      str_xxx         operate on strings
    57  *      wstr_xxx        operate on wide strings
    58  *
    59  *      [w]str_[n|l|w]xxx       operate on a prefix limited by size, length
    60  *                              or width.
     40 * represented as wchar_t.@n
     41 *
     42 * Overview of the terminology:@n
     43 *
     44 *  Term                  Meaning
     45 *  --------------------  ----------------------------------------------------
     46 *  byte                  8 bits stored in uint8_t (unsigned 8 bit integer)
     47 *
     48 *  character             UTF-32 encoded Unicode character, stored in wchar_t
     49 *                        (signed 32 bit integer), code points 0 .. 1114111
     50 *                        are valid
     51 *
     52 *  ASCII character       7 bit encoded ASCII character, stored in char
     53 *                        (usually signed 8 bit integer), code points 0 .. 127
     54 *                        are valid
     55 *
     56 *  string                UTF-8 encoded NULL-terminated Unicode string, char *
     57 *
     58 *  wide string           UTF-32 encoded NULL-terminated Unicode string,
     59 *                        wchar_t *
     60 *
     61 *  [wide] string size    number of BYTES in a [wide] string (excluding
     62 *                        the NULL-terminator), size_t
     63 *
     64 *  [wide] string length  number of CHARACTERS in a [wide] string (excluding
     65 *                        the NULL-terminator), count_t
     66 *
     67 *  [wide] string width   number of display cells on a monospace display taken
     68 *                        by a [wide] string, count_t
     69 *
     70 *
     71 * Overview of string metrics:@n
     72 *
     73 *  Metric  Abbrev.  Type     Meaning
     74 *  ------  ------   ------   -------------------------------------------------
     75 *  size    n        size_t   number of BYTES in a string (excluding the
     76 *                            NULL-terminator)
     77 *
     78 *  length  l        count_t  number of CHARACTERS in a string (excluding the
     79 *                            null terminator)
     80 *
     81 *  width  w         count_t  number of display cells on a monospace display
     82 *                            taken by a string
     83 *
     84 *
     85 * Function naming prefixes:@n
     86 *
     87 *  chr_    operate on characters
     88 *  ascii_  operate on ASCII characters
     89 *  str_    operate on strings
     90 *  wstr_   operate on wide strings
     91 *
     92 *  [w]str_[n|l|w]  operate on a prefix limited by size, length
     93 *                  or width
     94 *
     95 *
     96 * A specific character inside a [wide] string can be referred to by:@n
     97 *
     98 *  pointer (char *, wchar_t *)
     99 *  byte offset (size_t)
     100 *  character index (count_t)
     101 *
    61102 */
    62103
     
    67108#include <arch.h>
    68109#include <errno.h>
    69 #include <console/kconsole.h>
     110#include <align.h>
    70111
    71112char invalch = '?';
    72113
    73 /** Byte mask consisting of lowest @n bits (out of eight). */
    74 #define LO_MASK_8(n) ((uint8_t)((1 << (n)) - 1))
    75 
    76 /** Byte mask consisting of lowest @n bits (out of 32). */
    77 #define LO_MASK_32(n) ((uint32_t)((1 << (n)) - 1))
    78 
    79 /** Byte mask consisting of highest @n bits (out of eight). */
    80 #define HI_MASK_8(n) (~LO_MASK_8(8 - (n)))
    81 
    82 /** Number of data bits in a UTF-8 continuation byte. */
    83 #define CONT_BITS 6
    84 
    85 /** Decode a single character from a substring.
    86  *
    87  * Decode a single character from a substring of size @a sz. Decoding starts
     114/** Byte mask consisting of lowest @n bits (out of 8) */
     115#define LO_MASK_8(n)  ((uint8_t) ((1 << (n)) - 1))
     116
     117/** Byte mask consisting of lowest @n bits (out of 32) */
     118#define LO_MASK_32(n)  ((uint32_t) ((1 << (n)) - 1))
     119
     120/** Byte mask consisting of highest @n bits (out of 8) */
     121#define HI_MASK_8(n)  (~LO_MASK_8(8 - (n)))
     122
     123/** Number of data bits in a UTF-8 continuation byte */
     124#define CONT_BITS  6
     125
     126/** Decode a single character from a string.
     127 *
     128 * Decode a single character from a string of size @a size. Decoding starts
    88129 * at @a offset and this offset is moved to the beginning of the next
    89130 * character. In case of decoding error, offset generally advances at least
    90  * by one. However, offset is never moved beyond (str + sz).
    91  *
    92  * @param str   String (not necessarily NULL-terminated).
    93  * @param index Index (counted in plain characters) where to start
    94  *              the decoding.
    95  * @param limit Size of the substring.
    96  *
    97  * @return      Value of decoded character or '?' on decoding error.
    98  */
    99 wchar_t chr_decode(const char *str, size_t *offset, size_t sz)
    100 {
    101         uint8_t b0, b;          /* Bytes read from str. */
    102         wchar_t ch;
    103 
    104         int b0_bits;            /* Data bits in first byte. */
    105         int cbytes;             /* Number of continuation bytes. */
    106 
    107         if (*offset + 1 > sz)
    108                 return invalch;
    109 
    110         b0 = (uint8_t) str[(*offset)++];
    111 
    112         /* Determine code length. */
    113 
     131 * by one. However, offset is never moved beyond size.
     132 *
     133 * @param str    String (not necessarily NULL-terminated).
     134 * @param offset Byte offset in string where to start decoding.
     135 * @param size   Size of the string (in bytes).
     136 *
     137 * @return Value of decoded character, invalch on decoding error or
     138 *         NULL if attempt to decode beyond @a size.
     139 *
     140 */
     141wchar_t str_decode(const char *str, size_t *offset, size_t size)
     142{
     143        if (*offset + 1 > size)
     144                return 0;
     145       
     146        /* First byte read from string */
     147        uint8_t b0 = (uint8_t) str[(*offset)++];
     148       
     149        /* Determine code length */
     150       
     151        unsigned int b0_bits;  /* Data bits in first byte */
     152        unsigned int cbytes;   /* Number of continuation bytes */
     153       
    114154        if ((b0 & 0x80) == 0) {
    115155                /* 0xxxxxxx (Plain ASCII) */
     
    129169                cbytes = 3;
    130170        } else {
    131                 /* 10xxxxxx -- unexpected continuation byte. */
     171                /* 10xxxxxx -- unexpected continuation byte */
    132172                return invalch;
    133173        }
    134 
    135         if (*offset + cbytes > sz) {
     174       
     175        if (*offset + cbytes > size)
    136176                return invalch;
    137         }
    138 
    139         ch = b0 & LO_MASK_8(b0_bits);
    140 
    141         /* Decode continuation bytes. */
     177       
     178        wchar_t ch = b0 & LO_MASK_8(b0_bits);
     179       
     180        /* Decode continuation bytes */
    142181        while (cbytes > 0) {
    143                 b = (uint8_t) str[(*offset)++];
    144 
    145                 /* Must be 10xxxxxx. */
    146                 if ((b & 0xc0) != 0x80) {
     182                uint8_t b = (uint8_t) str[(*offset)++];
     183               
     184                /* Must be 10xxxxxx */
     185                if ((b & 0xc0) != 0x80)
    147186                        return invalch;
    148                 }
    149 
    150                 /* Shift data bits to ch. */
     187               
     188                /* Shift data bits to ch */
    151189                ch = (ch << CONT_BITS) | (wchar_t) (b & LO_MASK_8(CONT_BITS));
    152                 --cbytes;
    153         }
    154 
     190                cbytes--;
     191        }
     192       
    155193        return ch;
    156194}
     
    162200 * is moved to the position where the next character can be written to.
    163201 *
    164  * @param ch            Input character.
    165  * @param str           Output buffer.
    166  * @param offset        Offset (in bytes) where to start writing.
    167  * @param sz            Size of the output buffer.
     202 * @param ch     Input character.
     203 * @param str    Output buffer.
     204 * @param offset Byte offset where to start writing.
     205 * @param size   Size of the output buffer (in bytes).
    168206 *
    169207 * @return EOK if the character was encoded successfully, EOVERFLOW if there
     
    171209 *         code was invalid.
    172210 */
    173 int chr_encode(wchar_t ch, char *str, size_t *offset, size_t sz)
    174 {
    175         uint32_t cc;            /* Unsigned version of ch. */
    176 
    177         int cbytes;             /* Number of continuation bytes. */
    178         int b0_bits;            /* Number of data bits in first byte. */
    179         int i;
    180 
    181         if (*offset >= sz)
     211int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
     212{
     213        if (*offset >= size)
    182214                return EOVERFLOW;
    183 
    184         if (ch < 0)
     215       
     216        if (!chr_check(ch))
    185217                return EINVAL;
    186 
    187         /* Bit operations should only be done on unsigned numbers. */
    188         cc = (uint32_t) ch;
    189 
    190         /* Determine how many continuation bytes are needed. */
     218       
     219        /* Unsigned version of ch (bit operations should only be done
     220           on unsigned types). */
     221        uint32_t cc = (uint32_t) ch;
     222       
     223        /* Determine how many continuation bytes are needed */
     224       
     225        unsigned int b0_bits;  /* Data bits in first byte */
     226        unsigned int cbytes;   /* Number of continuation bytes */
     227       
    191228        if ((cc & ~LO_MASK_32(7)) == 0) {
    192229                b0_bits = 7;
     
    202239                cbytes = 3;
    203240        } else {
    204                 /* Codes longer than 21 bits are not supported. */
     241                /* Codes longer than 21 bits are not supported */
    205242                return EINVAL;
    206243        }
    207 
    208         /* Check for available space in buffer. */
    209         if (*offset + cbytes >= sz)
     244       
     245        /* Check for available space in buffer */
     246        if (*offset + cbytes >= size)
    210247                return EOVERFLOW;
    211 
    212         /* Encode continuation bytes. */
    213         for (i = cbytes; i > 0; --i) {
     248       
     249        /* Encode continuation bytes */
     250        unsigned int i;
     251        for (i = cbytes; i > 0; i--) {
    214252                str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
    215253                cc = cc >> CONT_BITS;
    216254        }
    217 
    218         /* Encode first byte. */
     255       
     256        /* Encode first byte */
    219257        str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
    220 
    221         /* Advance offset. */
    222         *offset += (1 + cbytes);
     258       
     259        /* Advance offset */
     260        *offset += cbytes + 1;
    223261       
    224262        return EOK;
    225263}
    226264
    227 /** Get display width of character.
    228  *
    229  * @param ch    The character.
    230  * @return      Character width in display cells.
    231  */
    232 count_t chr_width(wchar_t ch)
    233 {
    234         return 1;
    235 }
    236 
    237 /** Get size of string, with length limit.
     265/** Get size of string.
     266 *
     267 * Get the number of bytes which are used by the string @a str (excluding the
     268 * NULL-terminator).
     269 *
     270 * @param str String to consider.
     271 *
     272 * @return Number of bytes used by the string
     273 *
     274 */
     275size_t str_size(const char *str)
     276{
     277        size_t size = 0;
     278       
     279        while (*str++ != 0)
     280                size++;
     281       
     282        return size;
     283}
     284
     285/** Get size of wide string.
     286 *
     287 * Get the number of bytes which are used by the wide string @a str (excluding the
     288 * NULL-terminator).
     289 *
     290 * @param str Wide string to consider.
     291 *
     292 * @return Number of bytes used by the wide string
     293 *
     294 */
     295size_t wstr_size(const wchar_t *str)
     296{
     297        return (wstr_length(str) * sizeof(wchar_t));
     298}
     299
     300/** Get size of string with length limit.
    238301 *
    239302 * Get the number of bytes which are used by up to @a max_len first
    240303 * characters in the string @a str. If @a max_len is greater than
    241  * the length of @a str, the entire string is measured.
    242  *
    243  * @param str   String to consider.
    244  * @param count Maximum number of characters to measure.
    245  *
    246  * @return      Number of bytes used by the characters.
     304 * the length of @a str, the entire string is measured (excluding the
     305 * NULL-terminator).
     306 *
     307 * @param str     String to consider.
     308 * @param max_len Maximum number of characters to measure.
     309 *
     310 * @return Number of bytes used by the characters.
     311 *
    247312 */
    248313size_t str_lsize(const char *str, count_t max_len)
    249314{
    250315        count_t len = 0;
    251         size_t cur = 0;
    252         size_t prev;
    253         wchar_t ch;
    254 
    255         while (true) {
    256                 prev = cur;
    257                 if (len >= max_len)
     316        size_t offset = 0;
     317       
     318        while (len < max_len) {
     319                if (str_decode(str, &offset, STR_NO_LIMIT) == 0)
    258320                        break;
    259                 ch = chr_decode(str, &cur, UTF8_NO_LIMIT);
    260                 if (ch == '\0') break;
    261 
     321               
    262322                len++;
    263323        }
    264 
    265         return prev;
    266 }
    267 
    268 /** Get size of string, with width limit.
    269  *
    270  * Get the number of bytes which are used by the longest prefix of @a str
    271  * that can fit into @a max_width display cells.
    272  *
    273  * @param str   String to consider.
    274  * @param count Maximum number of display cells.
    275  *
    276  * @return      Number of bytes used by the characters that fit.
    277  */
    278 size_t str_wsize(const char *str, count_t max_width)
    279 {
    280         count_t width = 0;
    281         size_t cur = 0;
    282         size_t prev;
    283         wchar_t ch;
    284 
    285         while (true) {
    286                 prev = cur;
    287                 if (width >= max_width)
    288                         break;
    289                 ch = chr_decode(str, &cur, UTF8_NO_LIMIT);
    290                 if (ch == '\0') break;
    291 
    292                 width += chr_width(ch);
    293         }
    294 
    295         return prev;
    296 }
    297 
    298 
    299 /** Get length of wide string, with width limit.
    300  *
    301  * Get the number of characters in a wide string that can fit into @a max_width
    302  * display cells.
    303  *
    304  * @param wstr   Wide string to consider.
    305  * @param count Maximum number of display cells.
    306  *
    307  * @return      Number of bytes used by the characters that fit.
    308  */
    309 count_t wstr_wlength(const wchar_t *wstr, count_t max_width)
    310 {
    311         count_t width = 0;
    312         index_t cur = 0;
    313 
    314         while (true) {
    315                 if (width >= max_width)
    316                         break;
    317                 if (wstr[cur] == '\0') break;
    318 
    319                 width += chr_width(wstr[cur]);
    320                 ++cur;
    321         }
    322 
    323         return (count_t) cur;
     324       
     325        return offset;
     326}
     327
     328/** Get size of wide string with length limit.
     329 *
     330 * Get the number of bytes which are used by up to @a max_len first
     331 * wide characters in the wide string @a str. If @a max_len is greater than
     332 * the length of @a str, the entire wide string is measured (excluding the
     333 * NULL-terminator).
     334 *
     335 * @param str     Wide string to consider.
     336 * @param max_len Maximum number of wide characters to measure.
     337 *
     338 * @return Number of bytes used by the wide characters.
     339 *
     340 */
     341size_t wstr_lsize(const wchar_t *str, count_t max_len)
     342{
     343        return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
     344}
     345
     346/** Get number of characters in a string.
     347 *
     348 * @param str NULL-terminated string.
     349 *
     350 * @return Number of characters in string.
     351 *
     352 */
     353count_t str_length(const char *str)
     354{
     355        count_t len = 0;
     356        size_t offset = 0;
     357       
     358        while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
     359                len++;
     360       
     361        return len;
     362}
     363
     364/** Get number of characters in a wide string.
     365 *
     366 * @param str NULL-terminated wide string.
     367 *
     368 * @return Number of characters in @a str.
     369 *
     370 */
     371count_t wstr_length(const wchar_t *wstr)
     372{
     373        count_t len = 0;
     374       
     375        while (*wstr++ != 0)
     376                len++;
     377       
     378        return len;
     379}
     380
     381/** Get number of characters in a string with size limit.
     382 *
     383 * @param str  NULL-terminated string.
     384 * @param size Maximum number of bytes to consider.
     385 *
     386 * @return Number of characters in string.
     387 *
     388 */
     389count_t str_nlength(const char *str, size_t size)
     390{
     391        count_t len = 0;
     392        size_t offset = 0;
     393       
     394        while (str_decode(str, &offset, size) != 0)
     395                len++;
     396       
     397        return len;
     398}
     399
     400/** Get number of characters in a string with size limit.
     401 *
     402 * @param str  NULL-terminated string.
     403 * @param size Maximum number of bytes to consider.
     404 *
     405 * @return Number of characters in string.
     406 *
     407 */
     408count_t wstr_nlength(const wchar_t *str, size_t size)
     409{
     410        count_t len = 0;
     411        count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
     412        count_t offset = 0;
     413       
     414        while ((offset < limit) && (*str++ != 0)) {
     415                len++;
     416                offset += sizeof(wchar_t);
     417        }
     418       
     419        return len;
    324420}
    325421
     
    337433}
    338434
    339 /** Check whether character is Unicode.
    340  *
    341  * @return True if character is valid Unicode code point.
    342  */
    343 bool unicode_check(const wchar_t ch)
     435/** Check whether character is valid
     436 *
     437 * @return True if character is a valid Unicode code point.
     438 *
     439 */
     440bool chr_check(const wchar_t ch)
    344441{
    345442        if ((ch >= 0) && (ch <= 1114111))
     
    349446}
    350447
    351 /** Return number of bytes the string occupies.
    352  *
    353  * @param str A string.
    354  * @return Number of bytes in @a str excluding the null terminator.
    355  */
    356 size_t str_size(const char *str)
    357 {
    358         size_t size;
    359 
    360         size = 0;
    361         while (*str++ != '\0')
    362                 ++size;
    363 
    364         return size;
    365 }
    366 
    367 /** Return number of characters in a string.
    368  *
    369  * @param str NULL-terminated string.
    370  * @return Number of characters in string.
    371  */
    372 count_t str_length(const char *str)
    373 {
    374         count_t len = 0;
    375         size_t offset = 0;
    376 
    377         while (chr_decode(str, &offset, UTF8_NO_LIMIT) != 0) {
    378                 len++;
    379         }
    380 
    381         return len;
    382 }
    383 
    384 /** Return number of characters in a wide string.
    385  *
    386  * @param       str NULL-terminated wide string.
    387  * @return      Number of characters in @a str.
    388  */
    389 count_t wstr_length(const wchar_t *wstr)
    390 {
    391         count_t len;
    392 
    393         len = 0;
    394         while (*wstr++ != '\0')
    395                 ++len;
    396 
    397         return len;
    398 }
    399 
    400 /** Compare two NULL terminated strings
    401  *
    402  * Do a char-by-char comparison of two NULL terminated strings.
     448/** Compare two NULL terminated strings.
     449 *
     450 * Do a char-by-char comparison of two NULL-terminated strings.
    403451 * The strings are considered equal iff they consist of the same
    404452 * characters on the minimum of their lengths.
    405453 *
    406  * @param src First string to compare.
    407  * @param dst Second string to compare.
    408  *
    409  * @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
    410  *
    411  */
    412 int strcmp(const char *src, const char *dst)
    413 {
    414         for (; *src && *dst; src++, dst++) {
    415                 if (*src < *dst)
     454 * @param s1 First string to compare.
     455 * @param s2 Second string to compare.
     456 *
     457 * @return 0 if the strings are equal, -1 if first is smaller,
     458 *         1 if second smaller.
     459 *
     460 */
     461int str_cmp(const char *s1, const char *s2)
     462{
     463        wchar_t c1;
     464        wchar_t c2;
     465       
     466        size_t off1 = 0;
     467        size_t off2 = 0;
     468       
     469        while ((c1 = str_decode(s1, &off1, STR_NO_LIMIT) != 0)
     470            && (c2 = str_decode(s2, &off2, STR_NO_LIMIT) != 0)) {
     471               
     472                if (off1 != off2)
     473                        break;
     474               
     475                if (c1 < c2)
    416476                        return -1;
    417                 if (*src > *dst)
     477               
     478                if (c1 > c2)
    418479                        return 1;
    419480        }
    420         if (*src == *dst)
     481       
     482        if ((off1 == off2) && (c1 == c2))
    421483                return 0;
    422484       
    423         if (!*src)
     485        if ((c1 == 0) || (off1 < off2))
    424486                return -1;
    425487       
     
    427489}
    428490
    429 
    430 /** Compare two NULL terminated strings
    431  *
    432  * Do a char-by-char comparison of two NULL terminated strings.
     491/** Compare two NULL terminated strings with length limit.
     492 *
     493 * Do a char-by-char comparison of two NULL-terminated strings.
    433494 * The strings are considered equal iff they consist of the same
    434  * characters on the minimum of their lengths and specified maximal
    435  * length.
    436  *
    437  * @param src First string to compare.
    438  * @param dst Second string to compare.
    439  * @param len Maximal length for comparison.
    440  *
    441  * @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
    442  */
    443 int strncmp(const char *src, const char *dst, size_t len)
    444 {
    445         unsigned int i;
    446        
    447         for (i = 0; (*src) && (*dst) && (i < len); src++, dst++, i++) {
    448                 if (*src < *dst)
     495 * characters on the minimum of their lengths and the length limit.
     496 *
     497 * @param s1      First string to compare.
     498 * @param s2      Second string to compare.
     499 * @param max_len Maximum number of characters to consider.
     500 *
     501 * @return 0 if the strings are equal, -1 if first is smaller,
     502 *         1 if second smaller.
     503 *
     504 */
     505int str_lcmp(const char *s1, const char *s2, count_t max_len)
     506{
     507        wchar_t c1 = 0;
     508        wchar_t c2 = 0;
     509       
     510        size_t off1 = 0;
     511        size_t off2 = 0;
     512       
     513        count_t len = 0;
     514       
     515        while ((len < max_len)
     516            && ((c1 = str_decode(s1, &off1, STR_NO_LIMIT)) != 0)
     517            && ((c2 = str_decode(s2, &off2, STR_NO_LIMIT)) != 0)) {
     518               
     519                if (off1 != off2)
     520                        break;
     521               
     522                if (c1 < c2)
    449523                        return -1;
    450524               
    451                 if (*src > *dst)
     525                if (c1 > c2)
    452526                        return 1;
    453         }
    454        
    455         if (i == len || *src == *dst)
     527               
     528                len++;
     529        }
     530       
     531        if ((off1 == off2) && (len == max_len) && (c1 == c2))
    456532                return 0;
    457533       
    458         if (!*src)
     534        if ((c1 == 0) || (off1 < off2))
    459535                return -1;
    460536       
     
    462538}
    463539
    464 
    465 
    466 /** Copy NULL terminated string.
    467  *
    468  * Copy at most 'len' characters from string 'src' to 'dest'.
    469  * If 'src' is shorter than 'len', '\0' is inserted behind the
    470  * last copied character.
    471  *
    472  * @param src  Source string.
    473  * @param dest Destination buffer.
    474  * @param len  Size of destination buffer.
    475  */
    476 void strncpy(char *dest, const char *src, size_t len)
    477 {
    478         unsigned int i;
    479        
    480         for (i = 0; i < len; i++) {
    481                 if (!(dest[i] = src[i]))
    482                         return;
    483         }
    484        
    485         dest[i - 1] = '\0';
     540/** Copy NULL-terminated string.
     541 *
     542 * Copy source string @a src to destination buffer @a dst.
     543 * No more than @a size bytes are written. NULL-terminator is always
     544 * written after the last succesfully copied character (i.e. if the
     545 * destination buffer is has at least 1 byte, it will be always
     546 * NULL-terminated).
     547 *
     548 * @param src   Source string.
     549 * @param dst   Destination buffer.
     550 * @param count Size of the destination buffer.
     551 *
     552 */
     553void str_ncpy(char *dst, const char *src, size_t size)
     554{
     555        /* No space for the NULL-terminator in the buffer */
     556        if (size == 0)
     557                return;
     558       
     559        wchar_t ch;
     560        size_t str_off = 0;
     561        size_t dst_off = 0;
     562       
     563        while ((ch = str_decode(src, &str_off, STR_NO_LIMIT) != 0)) {
     564                if (chr_encode(ch, dst, &dst_off, size) != EOK)
     565                        break;
     566        }
     567       
     568        if (dst_off >= size)
     569                dst[size - 1] = 0;
     570        else
     571                dst[dst_off] = 0;
     572}
     573
     574/** Copy NULL-terminated wide string to string
     575 *
     576 * Copy source wide string @a src to destination buffer @a dst.
     577 * No more than @a size bytes are written. NULL-terminator is always
     578 * written after the last succesfully copied character (i.e. if the
     579 * destination buffer is has at least 1 byte, it will be always
     580 * NULL-terminated).
     581 *
     582 * @param src   Source wide string.
     583 * @param dst   Destination buffer.
     584 * @param count Size of the destination buffer.
     585 *
     586 */
     587void wstr_nstr(char *dst, const wchar_t *src, size_t size)
     588{
     589        /* No space for the NULL-terminator in the buffer */
     590        if (size == 0)
     591                return;
     592       
     593        wchar_t ch;
     594        count_t src_idx = 0;
     595        size_t dst_off = 0;
     596       
     597        while ((ch = src[src_idx++]) != 0) {
     598                if (chr_encode(ch, dst, &dst_off, size) != EOK)
     599                        break;
     600        }
     601       
     602        if (dst_off >= size)
     603                dst[size - 1] = 0;
     604        else
     605                dst[dst_off] = 0;
    486606}
    487607
    488608/** Find first occurence of character in string.
    489609 *
    490  * @param s String to search.
    491  * @param i Character to look for.
    492  *
    493  * @return Pointer to character in @a s or NULL if not found.
    494  */
    495 extern char *strchr(const char *s, int i)
    496 {
    497         while (*s != '\0') {
    498                 if (*s == i)
    499                         return (char *) s;
    500                 ++s;
     610 * @param str String to search.
     611 * @param ch  Character to look for.
     612 *
     613 * @return Pointer to character in @a str or NULL if not found.
     614 *
     615 */
     616const char *str_chr(const char *str, wchar_t ch)
     617{
     618        wchar_t acc;
     619        size_t off = 0;
     620       
     621        while ((acc = str_decode(str, &off, STR_NO_LIMIT) != 0)) {
     622                if (acc == ch)
     623                        return (str + off);
    501624        }
    502625       
     
    504627}
    505628
     629/** Insert a wide character into a wide string.
     630 *
     631 * Insert a wide character into a wide string at position
     632 * @a pos. The characters after the position are shifted.
     633 *
     634 * @param str     String to insert to.
     635 * @param ch      Character to insert to.
     636 * @param pos     Character index where to insert.
     637 @ @param max_pos Characters in the buffer.
     638 *
     639 * @return True if the insertion was sucessful, false if the position
     640 *         is out of bounds.
     641 *
     642 */
     643bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
     644{
     645        count_t len = wstr_length(str);
     646       
     647        if ((pos > len) || (pos + 1 > max_pos))
     648                return false;
     649       
     650        count_t i;
     651        for (i = len; i + 1 > pos; i--)
     652                str[i + 1] = str[i];
     653       
     654        str[pos] = ch;
     655       
     656        return true;
     657}
     658
     659/** Remove a wide character from a wide string.
     660 *
     661 * Remove a wide character from a wide string at position
     662 * @a pos. The characters after the position are shifted.
     663 *
     664 * @param str String to remove from.
     665 * @param pos Character index to remove.
     666 *
     667 * @return True if the removal was sucessful, false if the position
     668 *         is out of bounds.
     669 *
     670 */
     671bool wstr_remove(wchar_t *str, count_t pos)
     672{
     673        count_t len = wstr_length(str);
     674       
     675        if (pos >= len)
     676                return false;
     677       
     678        count_t i;
     679        for (i = pos + 1; i <= len; i++)
     680                str[i - 1] = str[i];
     681       
     682        return true;
     683}
     684
    506685/** @}
    507686 */
Note: See TracChangeset for help on using the changeset viewer.