Changeset 240b2e4 in mainline


Ignore:
Timestamp:
2025-04-13T19:05:55Z (5 days ago)
Author:
GitHub <noreply@…>
Children:
c7c6afd
Parents:
62e3411 (diff), 28c39f3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Wayne Thornton <wmthornton-dev@…> (2025-04-13 19:05:55)
git-committer:
GitHub <noreply@…> (2025-04-13 19:05:55)
Message:

Merge branch 'HelenOS:master' into master

Files:
3 added
6 edited
3 moved

Legend:

Unmodified
Added
Removed
  • abi/include/_bits/mbstate_t.h

    r62e3411 r240b2e4  
    11/*
    2  * Copyright (c) 2020 Martin Decky
     2 * Copyright (c) 2025 Jiří Zárevúcky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup kernel_generic
     29/** @addtogroup bits
    3030 * @{
    3131 */
     
    3333 */
    3434
    35 #ifndef _KERN_UCHAR_H_
    36 #define _KERN_UCHAR_H_
     35#ifndef _BITS_MBSTATE_T_H_
     36#define _BITS_MBSTATE_T_H_
    3737
    38 #include <_bits/uchar.h>
     38typedef struct {
     39        unsigned short continuation;
     40} mbstate_t;
    3941
    4042#endif
  • abi/include/_bits/uchar.h

    r62e3411 r240b2e4  
    4646#endif
    4747
    48 typedef uint32_t char32_t;
     48typedef uint_least16_t char16_t;
     49typedef uint_least32_t char32_t;
    4950
    5051#endif
  • common/include/uchar.h

    r62e3411 r240b2e4  
    11/*
    2  * Copyright (c) 2020 Martin Decky
     2 * Copyright (c) 2025 Jiří Zárevúcky
    33 * All rights reserved.
    44 *
     
    3636#define _LIBC_UCHAR_H_
    3737
     38#include <_bits/mbstate_t.h>
     39#include <_bits/size_t.h>
    3840#include <_bits/uchar.h>
     41#include <stdint.h>
     42
     43size_t mbrtoc8(char8_t *__restrict pc8, const char *__restrict s, size_t n,
     44    mbstate_t *__restrict ps);
     45size_t c8rtomb(char *__restrict s, char8_t c8, mbstate_t *__restrict ps);
     46size_t mbrtoc16(char16_t *__restrict pc16, const char *__restrict s, size_t n,
     47    mbstate_t *__restrict ps);
     48size_t c16rtomb(char *__restrict s, char16_t c16, mbstate_t *__restrict ps);
     49size_t mbrtoc32(char32_t *__restrict pc32, const char *__restrict s, size_t n,
     50    mbstate_t *__restrict ps);
     51size_t c32rtomb(char *__restrict s, char32_t c32, mbstate_t *__restrict ps);
     52
     53#ifdef _HELENOS_SOURCE
     54#define UCHAR_ILSEQ      ((size_t) -1)
     55#define UCHAR_INCOMPLETE ((size_t) -2)
     56#define UCHAR_CONTINUED  ((size_t) -3)
     57#endif
    3958
    4059#endif
  • common/stdc/wchar.c

    r62e3411 r240b2e4  
    11/*
    2  * Copyright (c) 2017 CZ.NIC, z.s.p.o.
     2 * Copyright (c) 2025 Jiří Zárevúcky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /*
    30  * Authors:
    31  *      Jiří Zárevúcky (jzr) <zarevucky.jiri@gmail.com>
    32  */
     29#include <uchar.h>
     30#include <wchar.h>
    3331
    34 /** @addtogroup libc
    35  * @{
    36  */
    37 /** @file
    38  */
    39 
    40 #ifndef _LIBC_WCHAR_H_
    41 #define _LIBC_WCHAR_H_
    42 
    43 #include <_bits/size_t.h>
    44 #include <_bits/wchar_t.h>
    45 #include <_bits/wchar_limits.h>
    46 #include <_bits/wint_t.h>
    47 #include <_bits/NULL.h>
    48 #include <_bits/WEOF.h>
    49 
     32#if __STDC_HOSTED__
     33#include <fibril.h>
    5034#endif
    5135
    52 /** @}
    53  */
     36wint_t btowc(int c)
     37{
     38        return (c < 0x80) ? c : WEOF;
     39}
     40
     41int wctob(wint_t c)
     42{
     43        return c;
     44}
     45
     46int mbsinit(const mbstate_t *ps)
     47{
     48        return ps == NULL || ps->continuation == 0;
     49}
     50
     51size_t mbrlen(const char *s, size_t n, mbstate_t *ps)
     52{
     53#if __STDC_HOSTED__
     54        static fibril_local mbstate_t global_state;
     55        if (!ps)
     56                ps = &global_state;
     57#endif
     58
     59        return mbrtowc(NULL, s, n, ps);
     60}
     61
     62_Static_assert(sizeof(wchar_t) == sizeof(char16_t) || sizeof(wchar_t) == sizeof(char32_t));
     63
     64size_t mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
     65{
     66#if __STDC_HOSTED__
     67        static fibril_local mbstate_t global_state;
     68        if (!ps)
     69                ps = &global_state;
     70#endif
     71
     72        if (sizeof(wchar_t) == sizeof(char16_t))
     73                return mbrtoc16((char16_t *) pwc, s, n, ps);
     74        else
     75                return mbrtoc32((char32_t *) pwc, s, n, ps);
     76}
     77
     78size_t wcrtomb(char *s, wchar_t wc, mbstate_t * ps)
     79{
     80#if __STDC_HOSTED__
     81        static fibril_local mbstate_t global_state;
     82        if (!ps)
     83                ps = &global_state;
     84#endif
     85
     86        if (sizeof(wchar_t) == sizeof(char16_t))
     87                return c16rtomb(s, (char16_t) wc, ps);
     88        else
     89                return c32rtomb(s, (char32_t) wc, ps);
     90}
  • common/str.c

    r62e3411 r240b2e4  
    5454 *                        are valid
    5555 *
     56 *                        Note that Unicode characters do not match
     57 *                        one-to-one with displayed characters or glyphs on
     58 *                        screen. For that level of precision, look up
     59 *                        Grapheme Clusters.
     60 *
    5661 *  ASCII character       7 bit encoded ASCII character, stored in char
    5762 *                        (usually signed 8 bit integer), code points 0 .. 127
     
    7176 *  [wide] string width   number of display cells on a monospace display taken
    7277 *                        by a [wide] string, size_t
     78 *
     79 *                        This is virtually impossible to determine exactly for
     80 *                        all strings without knowing specifics of the display
     81 *                        device, due to various factors affecting text output.
     82 *                        If you have the option to query the terminal for
     83 *                        position change caused by outputting the string,
     84 *                        it is preferrable to determine width that way.
    7385 *
    7486 *
     
    108120#include <str.h>
    109121
     122#include <align.h>
    110123#include <assert.h>
    111124#include <ctype.h>
    112125#include <errno.h>
     126#include <macros.h>
     127#include <mem.h>
    113128#include <stdbool.h>
    114129#include <stddef.h>
    115130#include <stdint.h>
    116131#include <stdlib.h>
    117 
    118 #include <align.h>
    119 #include <mem.h>
     132#include <uchar.h>
    120133
    121134/** Byte mask consisting of lowest @n bits (out of 8) */
     
    130143/** Number of data bits in a UTF-8 continuation byte */
    131144#define CONT_BITS  6
     145
     146static inline bool _is_ascii(uint8_t b)
     147{
     148        return b < 0x80;
     149}
     150
     151static inline bool _is_continuation_byte(uint8_t b)
     152{
     153        return (b & 0xc0) == 0x80;
     154}
     155
     156static inline int _char_continuation_bytes(char32_t c)
     157{
     158        if ((c & ~LO_MASK_32(11)) == 0)
     159                return 1;
     160
     161        if ((c & ~LO_MASK_32(16)) == 0)
     162                return 2;
     163
     164        if ((c & ~LO_MASK_32(21)) == 0)
     165                return 3;
     166
     167        /* Codes longer than 21 bits are not supported */
     168        return -1;
     169}
     170
     171static inline int _continuation_bytes(uint8_t b)
     172{
     173        /* 0xxxxxxx */
     174        if (_is_ascii(b))
     175                return 0;
     176
     177        /* 110xxxxx 10xxxxxx */
     178        if ((b & 0xe0) == 0xc0)
     179                return 1;
     180
     181        /* 1110xxxx 10xxxxxx 10xxxxxx */
     182        if ((b & 0xf0) == 0xe0)
     183                return 2;
     184
     185        /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
     186        if ((b & 0xf8) == 0xf0)
     187                return 3;
     188
     189        return -1;
     190}
    132191
    133192/** Decode a single character from a string.
     
    154213        uint8_t b0 = (uint8_t) str[(*offset)++];
    155214
     215        /* Fast exit for the most common case. */
     216        if (_is_ascii(b0))
     217                return b0;
     218
     219        /* 10xxxxxx -- unexpected continuation byte */
     220        if (_is_continuation_byte(b0))
     221                return U_SPECIAL;
     222
    156223        /* Determine code length */
    157224
    158         unsigned int b0_bits;  /* Data bits in first byte */
    159         unsigned int cbytes;   /* Number of continuation bytes */
    160 
    161         if ((b0 & 0x80) == 0) {
    162                 /* 0xxxxxxx (Plain ASCII) */
    163                 b0_bits = 7;
    164                 cbytes = 0;
    165         } else if ((b0 & 0xe0) == 0xc0) {
    166                 /* 110xxxxx 10xxxxxx */
    167                 b0_bits = 5;
    168                 cbytes = 1;
    169         } else if ((b0 & 0xf0) == 0xe0) {
    170                 /* 1110xxxx 10xxxxxx 10xxxxxx */
    171                 b0_bits = 4;
    172                 cbytes = 2;
    173         } else if ((b0 & 0xf8) == 0xf0) {
    174                 /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
    175                 b0_bits = 3;
    176                 cbytes = 3;
    177         } else {
    178                 /* 10xxxxxx -- unexpected continuation byte */
    179                 return U_SPECIAL;
    180         }
     225        unsigned int cbytes = _continuation_bytes(b0);
     226        unsigned int b0_bits = 6 - cbytes;  /* Data bits in first byte */
    181227
    182228        if (*offset + cbytes > size)
     
    189235                uint8_t b = (uint8_t) str[(*offset)++];
    190236
    191                 /* Must be 10xxxxxx */
    192                 if ((b & 0xc0) != 0x80)
     237                if (!_is_continuation_byte(b))
    193238                        return U_SPECIAL;
    194239
     
    221266                return 0;
    222267
    223         size_t processed = 0;
     268        int cbytes = 0;
    224269        /* Continue while continuation bytes found */
    225         while (*offset > 0 && processed < 4) {
     270        while (*offset > 0 && cbytes < 4) {
    226271                uint8_t b = (uint8_t) str[--(*offset)];
    227272
    228                 if (processed == 0 && (b & 0x80) == 0) {
    229                         /* 0xxxxxxx (Plain ASCII) */
    230                         return b & 0x7f;
    231                 } else if ((b & 0xe0) == 0xc0 || (b & 0xf0) == 0xe0 ||
    232                     (b & 0xf8) == 0xf0) {
    233                         /* Start byte */
    234                         size_t start_offset = *offset;
    235                         return str_decode(str, &start_offset, size);
    236                 } else if ((b & 0xc0) != 0x80) {
    237                         /* Not a continuation byte */
     273                if (_is_continuation_byte(b)) {
     274                        cbytes++;
     275                        continue;
     276                }
     277
     278                /* Invalid byte. */
     279                if (cbytes != _continuation_bytes(b))
    238280                        return U_SPECIAL;
    239                 }
    240                 processed++;
    241         }
     281
     282                /* Start byte */
     283                size_t start_offset = *offset;
     284                return str_decode(str, &start_offset, size);
     285        }
     286
    242287        /* Too many continuation bytes */
    243288        return U_SPECIAL;
     
    259304 *         code was invalid.
    260305 */
    261 errno_t chr_encode(const char32_t ch, char *str, size_t *offset, size_t size)
     306errno_t chr_encode(char32_t ch, char *str, size_t *offset, size_t size)
    262307{
    263308        if (*offset >= size)
    264309                return EOVERFLOW;
    265310
     311        /* Fast exit for the most common case. */
     312        if (ch < 0x80) {
     313                str[(*offset)++] = (char) ch;
     314                return EOK;
     315        }
     316
     317        /* Codes longer than 21 bits are not supported */
    266318        if (!chr_check(ch))
    267319                return EINVAL;
    268320
    269         /*
    270          * Unsigned version of ch (bit operations should only be done
    271          * on unsigned types).
    272          */
    273         uint32_t cc = (uint32_t) ch;
    274 
    275321        /* Determine how many continuation bytes are needed */
    276322
    277         unsigned int b0_bits;  /* Data bits in first byte */
    278         unsigned int cbytes;   /* Number of continuation bytes */
    279 
    280         if ((cc & ~LO_MASK_32(7)) == 0) {
    281                 b0_bits = 7;
    282                 cbytes = 0;
    283         } else if ((cc & ~LO_MASK_32(11)) == 0) {
    284                 b0_bits = 5;
    285                 cbytes = 1;
    286         } else if ((cc & ~LO_MASK_32(16)) == 0) {
    287                 b0_bits = 4;
    288                 cbytes = 2;
    289         } else if ((cc & ~LO_MASK_32(21)) == 0) {
    290                 b0_bits = 3;
    291                 cbytes = 3;
    292         } else {
    293                 /* Codes longer than 21 bits are not supported */
    294                 return EINVAL;
    295         }
     323        unsigned int cbytes = _char_continuation_bytes(ch);
     324        unsigned int b0_bits = 6 - cbytes;  /* Data bits in first byte */
    296325
    297326        /* Check for available space in buffer */
     
    302331        unsigned int i;
    303332        for (i = cbytes; i > 0; i--) {
    304                 str[*offset + i] = 0x80 | (cc & LO_MASK_32(CONT_BITS));
    305                 cc = cc >> CONT_BITS;
     333                str[*offset + i] = 0x80 | (ch & LO_MASK_32(CONT_BITS));
     334                ch >>= CONT_BITS;
    306335        }
    307336
    308337        /* Encode first byte */
    309         str[*offset] = (cc & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
     338        str[*offset] = (ch & LO_MASK_32(b0_bits)) | HI_MASK_8(8 - b0_bits - 1);
    310339
    311340        /* Advance offset */
     
    315344}
    316345
     346/* Convert in place any bytes that don't form a valid character into U_SPECIAL. */
     347static void _repair_string(char *str, size_t n)
     348{
     349        for (; *str && n > 0; str++, n--) {
     350                int cont = _continuation_bytes(*str);
     351                if (cont == 0)
     352                        continue;
     353
     354                if (cont < 0 || n <= (size_t) cont) {
     355                        *str = U_SPECIAL;
     356                        continue;
     357                }
     358
     359                for (int i = 1; i <= cont; i++) {
     360                        if (!_is_continuation_byte(str[i])) {
     361                                *str = U_SPECIAL;
     362                                continue;
     363                        }
     364                }
     365        }
     366}
     367
     368static size_t _str_size(const char *str)
     369{
     370        size_t size = 0;
     371
     372        while (*str++ != 0)
     373                size++;
     374
     375        return size;
     376}
     377
    317378/** Get size of string.
    318379 *
     
    327388size_t str_size(const char *str)
    328389{
    329         size_t size = 0;
    330 
    331         while (*str++ != 0)
    332                 size++;
    333 
    334         return size;
     390        return _str_size(str);
    335391}
    336392
     
    378434}
    379435
     436static size_t _str_nsize(const char *str, size_t max_size)
     437{
     438        size_t size = 0;
     439
     440        while ((*str++ != 0) && (size < max_size))
     441                size++;
     442
     443        return size;
     444}
     445
    380446/** Get size of string with size limit.
    381447 *
     
    391457size_t str_nsize(const char *str, size_t max_size)
    392458{
    393         size_t size = 0;
    394 
    395         while ((*str++ != 0) && (size < max_size))
    396                 size++;
    397 
    398         return size;
     459        return _str_nsize(str, max_size);
    399460}
    400461
     
    582643int str_cmp(const char *s1, const char *s2)
    583644{
    584         char32_t c1 = 0;
    585         char32_t c2 = 0;
    586 
    587         size_t off1 = 0;
    588         size_t off2 = 0;
    589 
    590         while (true) {
    591                 c1 = str_decode(s1, &off1, STR_NO_LIMIT);
    592                 c2 = str_decode(s2, &off2, STR_NO_LIMIT);
    593 
    594                 if (c1 < c2)
    595                         return -1;
    596 
    597                 if (c1 > c2)
    598                         return 1;
    599 
    600                 if (c1 == 0 || c2 == 0)
    601                         break;
    602         }
    603 
    604         return 0;
     645        /*
     646         * UTF-8 has the nice property that lexicographic ordering on bytes is
     647         * the same as the lexicographic ordering of the character sequences.
     648         */
     649        while (*s1 == *s2 && *s1 != 0) {
     650                s1++;
     651                s2++;
     652        }
     653
     654        if (*s1 == *s2)
     655                return 0;
     656
     657        return (*s1 < *s2) ? -1 : 1;
    605658}
    606659
     
    681734int str_casecmp(const char *s1, const char *s2)
    682735{
     736        // FIXME: doesn't work for non-ASCII caseful characters
     737
    683738        char32_t c1 = 0;
    684739        char32_t c2 = 0;
     
    729784int str_lcasecmp(const char *s1, const char *s2, size_t max_len)
    730785{
     786        // FIXME: doesn't work for non-ASCII caseful characters
     787
    731788        char32_t c1 = 0;
    732789        char32_t c2 = 0;
     
    760817}
    761818
     819static bool _test_prefix(const char *s, const char *p)
     820{
     821        while (*s == *p && *s != 0) {
     822                s++;
     823                p++;
     824        }
     825
     826        return *p == 0;
     827}
     828
    762829/** Test whether p is a prefix of s.
    763830 *
     
    773840bool str_test_prefix(const char *s, const char *p)
    774841{
    775         char32_t c1 = 0;
    776         char32_t c2 = 0;
    777 
    778         size_t off1 = 0;
    779         size_t off2 = 0;
    780 
    781         while (true) {
    782                 c1 = str_decode(s, &off1, STR_NO_LIMIT);
    783                 c2 = str_decode(p, &off2, STR_NO_LIMIT);
    784 
    785                 if (c2 == 0)
    786                         return true;
    787 
    788                 if (c1 != c2)
    789                         return false;
    790 
    791                 if (c1 == 0)
    792                         break;
    793         }
    794 
    795         return false;
     842        return _test_prefix(s, p);
    796843}
    797844
     
    820867
    821868        return s + off;
     869}
     870
     871/** Copy string as a sequence of bytes. */
     872static void _str_cpy(char *dest, const char *src)
     873{
     874        while (*src)
     875                *(dest++) = *(src++);
     876
     877        *dest = 0;
     878}
     879
     880/** Copy string as a sequence of bytes. */
     881static void _str_cpyn(char *dest, size_t size, const char *src)
     882{
     883        char *dest_top = dest + size - 1;
     884
     885        while (*src && dest < dest_top)
     886                *(dest++) = *(src++);
     887
     888        *dest = 0;
    822889}
    823890
     
    839906        assert(size > 0);
    840907        assert(src != NULL);
    841 
    842         size_t src_off = 0;
    843         size_t dest_off = 0;
    844 
    845         char32_t ch;
    846         while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
    847                 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    848                         break;
    849         }
    850 
    851         dest[dest_off] = '\0';
     908        assert(dest != NULL);
     909
     910        /* Copy data. */
     911        _str_cpyn(dest, size, src);
     912
     913        /* In-place translate invalid bytes to U_SPECIAL. */
     914        _repair_string(dest, size);
    852915}
    853916
     
    872935        /* There must be space for a null terminator in the buffer. */
    873936        assert(size > 0);
    874 
    875         size_t src_off = 0;
    876         size_t dest_off = 0;
    877 
    878         char32_t ch;
    879         while ((ch = str_decode(src, &src_off, n)) != 0) {
    880                 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    881                         break;
    882         }
    883 
    884         dest[dest_off] = '\0';
     937        assert(src != NULL);
     938
     939        /* Copy data. */
     940        _str_cpyn(dest, min(size, n + 1), src);
     941
     942        /* In-place translate invalid bytes to U_SPECIAL. */
     943        _repair_string(dest, size);
    885944}
    886945
     
    898957void str_append(char *dest, size_t size, const char *src)
    899958{
    900         size_t dstr_size;
    901 
    902         dstr_size = str_size(dest);
    903         if (dstr_size >= size)
    904                 return;
    905 
    906         str_cpy(dest + dstr_size, size - dstr_size, src);
     959        assert(src != NULL);
     960        assert(dest != NULL);
     961        assert(size > 0);
     962
     963        size_t dstr_size = _str_nsize(dest, size);
     964        _str_cpyn(dest + dstr_size, size - dstr_size, src);
     965        _repair_string(dest + dstr_size, size - dstr_size);
    907966}
    908967
     
    933992errno_t spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n)
    934993{
    935         size_t sidx;
    936         size_t didx;
    937         size_t dlast;
    938         uint8_t byte;
    939         errno_t rc;
    940         errno_t result;
    941 
    942         /* There must be space for a null terminator in the buffer. */
    943         assert(size > 0);
    944         result = EOK;
    945 
    946         didx = 0;
    947         dlast = 0;
    948         for (sidx = 0; sidx < n; ++sidx) {
    949                 byte = src[sidx];
    950                 if (!ascii_check(byte)) {
    951                         byte = U_SPECIAL;
     994        size_t len = 0;
     995
     996        /* Determine the length of the source string. */
     997        for (size_t i = 0; i < n; i++) {
     998                if (src[i] == 0)
     999                        break;
     1000
     1001                if (src[i] != ' ')
     1002                        len = i + 1;
     1003        }
     1004
     1005        errno_t result = EOK;
     1006        size_t out_len = min(len, size - 1);
     1007
     1008        /* Copy characters */
     1009        for (size_t i = 0; i < out_len; i++) {
     1010                dest[i] = src[i];
     1011
     1012                if (dest[i] < 0) {
     1013                        dest[i] = U_SPECIAL;
    9521014                        result = EIO;
    9531015                }
    954 
    955                 rc = chr_encode(byte, dest, &didx, size - 1);
    956                 if (rc != EOK) {
    957                         assert(rc == EOVERFLOW);
    958                         dest[didx] = '\0';
    959                         return rc;
    960                 }
    961 
    962                 /* Remember dest index after last non-empty character */
    963                 if (byte != 0x20)
    964                         dlast = didx;
    965         }
    966 
    967         /* Terminate string after last non-empty character */
    968         dest[dlast] = '\0';
     1016        }
     1017
     1018        dest[out_len] = 0;
     1019
     1020        if (out_len < len)
     1021                return EOVERFLOW;
     1022
    9691023        return result;
    9701024}
     
    12071261}
    12081262
     1263static char *_strchr(const char *str, char c)
     1264{
     1265        while (*str != 0 && *str != c)
     1266                str++;
     1267
     1268        return (*str == c) ? (char *) str : NULL;
     1269}
     1270
    12091271/** Find first occurence of character in string.
    12101272 *
     
    12161278char *str_chr(const char *str, char32_t ch)
    12171279{
    1218         char32_t acc;
    1219         size_t off = 0;
    1220         size_t last = 0;
    1221 
    1222         while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
    1223                 if (acc == ch)
    1224                         return (char *) (str + last);
    1225                 last = off;
     1280        /* Fast path for an ASCII character. */
     1281        if (ascii_check(ch))
     1282                return _strchr(str, ch);
     1283
     1284        /* Convert character to UTF-8. */
     1285        char utf8[STR_BOUNDS(1) + 1];
     1286        size_t offset = 0;
     1287
     1288        if (chr_encode(ch, utf8, &offset, sizeof(utf8)) != EOK || offset == 0)
     1289                return NULL;
     1290
     1291        utf8[offset] = '\0';
     1292
     1293        /* Find the first byte, then check if all of them are correct. */
     1294        while (*str != 0) {
     1295                str = _strchr(str, utf8[0]);
     1296                if (!str)
     1297                        return NULL;
     1298
     1299                if (_test_prefix(str, utf8))
     1300                        return (char *) str;
     1301
     1302                str++;
    12261303        }
    12271304
     
    12381315char *str_str(const char *hs, const char *n)
    12391316{
    1240         size_t off = 0;
    1241 
    1242         if (str_lcmp(hs, n, str_length(n)) == 0)
    1243                 return (char *)hs;
    1244 
    1245         while (str_decode(hs, &off, STR_NO_LIMIT) != 0) {
    1246                 if (str_lcmp(hs + off, n, str_length(n)) == 0)
    1247                         return (char *)(hs + off);
     1317        size_t hsize = _str_size(hs);
     1318        size_t nsize = _str_size(n);
     1319
     1320        while (hsize >= nsize) {
     1321                if (_test_prefix(hs, n))
     1322                        return (char *) hs;
     1323
     1324                hs++;
     1325                hsize--;
    12481326        }
    12491327
    12501328        return NULL;
     1329}
     1330
     1331static void _str_rtrim(char *str, char c)
     1332{
     1333        char *last = str;
     1334
     1335        while (*str) {
     1336                if (*str != c)
     1337                        last = str;
     1338
     1339                str++;
     1340        }
     1341
     1342        /* Truncate string. */
     1343        last[1] = 0;
    12511344}
    12521345
     
    12581351void str_rtrim(char *str, char32_t ch)
    12591352{
     1353        /* Fast path for the ASCII case. */
     1354        if (ascii_check(ch)) {
     1355                _str_rtrim(str, ch);
     1356                return;
     1357        }
     1358
    12601359        size_t off = 0;
    12611360        size_t pos = 0;
     
    12791378}
    12801379
     1380static void _str_ltrim(char *str, char c)
     1381{
     1382        char *p = str;
     1383
     1384        while (*p == c)
     1385                p++;
     1386
     1387        if (str != p)
     1388                _str_cpy(str, p);
     1389}
     1390
    12811391/** Removes specified leading characters from a string.
    12821392 *
     
    12861396void str_ltrim(char *str, char32_t ch)
    12871397{
     1398        /* Fast path for the ASCII case. */
     1399        if (ascii_check(ch)) {
     1400                _str_ltrim(str, ch);
     1401                return;
     1402        }
     1403
    12881404        char32_t acc;
    12891405        size_t off = 0;
     
    13051421}
    13061422
     1423static char *_str_rchr(const char *str, char c)
     1424{
     1425        const char *last = NULL;
     1426
     1427        while (*str) {
     1428                if (*str == c)
     1429                        last = str;
     1430
     1431                str++;
     1432        }
     1433
     1434        return (char *) last;
     1435}
     1436
    13071437/** Find last occurence of character in string.
    13081438 *
     
    13141444char *str_rchr(const char *str, char32_t ch)
    13151445{
     1446        if (ascii_check(ch))
     1447                return _str_rchr(str, ch);
     1448
    13161449        char32_t acc;
    13171450        size_t off = 0;
     
    14021535char *str_dup(const char *src)
    14031536{
    1404         size_t size = str_size(src) + 1;
     1537        size_t size = _str_size(src) + 1;
    14051538        char *dest = malloc(size);
    14061539        if (!dest)
    14071540                return NULL;
    14081541
    1409         str_cpy(dest, size, src);
     1542        _str_cpy(dest, src);
     1543        _repair_string(dest, size);
    14101544        return dest;
    14111545}
     
    14331567char *str_ndup(const char *src, size_t n)
    14341568{
    1435         size_t size = str_size(src);
    1436         if (size > n)
    1437                 size = n;
    1438 
    1439         char *dest = malloc(size + 1);
     1569        size_t size = _str_nsize(src, n) + 1;
     1570
     1571        char *dest = malloc(size);
    14401572        if (!dest)
    14411573                return NULL;
    14421574
    1443         str_ncpy(dest, size + 1, src, size);
     1575        _str_cpyn(dest, size, src);
     1576        _repair_string(dest, size);
    14441577        return dest;
    14451578}
  • kernel/generic/include/assert.h

    r62e3411 r240b2e4  
    8282#else /* CONFIG_DEBUG */
    8383
    84 #define assert(expr)
    85 #define assert_verbose(expr, msg)
    86 #define static_assert(expr, msg)
     84#define assert(expr) ((void) 0)
     85#define assert_verbose(expr, msg) ((void) 0)
     86#define static_assert(expr, msg) ((void) 0)
    8787
    8888#endif /* CONFIG_DEBUG */
  • uspace/lib/c/meson.build

    r62e3411 r240b2e4  
    6262        'common/adt/checksum.c',
    6363        'common/adt/circ_buf.c',
     64        'common/adt/hash_table.c',
    6465        'common/adt/list.c',
    65         'common/adt/hash_table.c',
    6666        'common/adt/odict.c',
     67        'common/gsort.c',
    6768        'common/printf/printf_core.c',
     69        'common/stdc/bsearch.c',
     70        'common/stdc/calloc.c',
    6871        'common/stdc/ctype.c',
    6972        'common/stdc/mem.c',
    70         'common/stdc/bsearch.c',
    7173        'common/stdc/qsort.c',
    72         'common/stdc/calloc.c',
    73         'common/gsort.c',
     74        'common/stdc/uchar.c',
     75        'common/stdc/wchar.c',
    7476        'common/str.c',
    7577        'common/str_error.c',
    7678        'common/strtol.c',
    7779
    78         'generic/libc.c',
    7980        'generic/adt/prodcons.c',
     81        'generic/arg_parse.c',
    8082        'generic/as.c',
    81         'generic/ddi.c',
    82         'generic/perm.c',
     83        'generic/assert.c',
     84        'generic/async/client.c',
     85        'generic/async/ports.c',
     86        'generic/async/server.c',
    8387        'generic/capa.c',
    8488        'generic/config.c',
    8589        'generic/context.c',
    8690        'generic/dbgcon.c',
     91        'generic/ddi.c',
    8792        'generic/device/clock_dev.c',
    8893        'generic/device/hw_res.c',
     
    9196        'generic/dirent.c',
    9297        'generic/dlfcn.c',
     98        'generic/double_to_str.c',
    9399        'generic/elf/elf.c',
    94100        'generic/elf/elf_load.c',
    95101        'generic/elf/elf_mod.c',
     102        'generic/errno.c',
    96103        'generic/event.c',
    97         'generic/errno.c',
     104        'generic/getopt.c',
     105        'generic/ieee_double.c',
     106        'generic/imath.c',
    98107        'generic/inttypes.c',
    99         'generic/loc.c',
    100         'generic/string.c',
    101         'generic/l18n/langs.c',
    102         'generic/pcb.c',
    103         'generic/pio_trace.c',
    104         'generic/smc.c',
    105         'generic/task.c',
    106         'generic/imath.c',
    107108        'generic/io/asprintf.c',
    108109        'generic/io/io.c',
    109         'generic/io/printf.c',
     110        'generic/io/kio.c',
     111        'generic/io/klog.c',
    110112        'generic/io/log.c',
    111113        'generic/io/logctl.c',
    112         'generic/io/kio.c',
    113         'generic/io/klog.c',
     114        'generic/io/printf.c',
    114115        'generic/io/snprintf.c',
     116        'generic/io/table.c',
    115117        'generic/io/vprintf.c',
    116118        'generic/io/vsnprintf.c',
    117         'generic/io/table.c',
     119        'generic/ipc.c',
    118120        'generic/irq.c',
    119         'generic/ieee_double.c',
     121        'generic/l18n/langs.c',
     122        'generic/libc.c',
     123        'generic/loader.c',
     124        'generic/loc.c',
     125        'generic/malloc.c',
     126        'generic/ns.c',
     127        'generic/pcb.c',
     128        'generic/perm.c',
     129        'generic/pio_trace.c',
    120130        'generic/power_of_ten.c',
    121         'generic/double_to_str.c',
    122         'generic/malloc.c',
    123131        'generic/rndgen.c',
     132        'generic/setjmp.c',
    124133        'generic/shutdown.c',
     134        'generic/smc.c',
     135        'generic/stack.c',
     136        'generic/stacktrace.c',
     137        'generic/stats.c',
     138        'generic/stdio.c',
    125139        'generic/stdio/scanf.c',
    126140        'generic/stdio/sprintf.c',
     
    128142        'generic/stdio/sstream.c',
    129143        'generic/stdio/vsprintf.c',
     144        'generic/stdlib.c',
     145        'generic/string.c',
     146        'generic/sysinfo.c',
     147        'generic/task.c',
    130148        'generic/thread/fibril.c',
    131149        'generic/thread/fibril_synch.c',
     150        'generic/thread/futex.c',
     151        'generic/thread/mpsc.c',
    132152        'generic/thread/thread.c',
    133153        'generic/thread/tls.c',
    134         'generic/thread/futex.c',
    135         'generic/thread/mpsc.c',
    136         'generic/sysinfo.c',
    137         'generic/ipc.c',
    138         'generic/ns.c',
    139         'generic/async/client.c',
    140         'generic/async/server.c',
    141         'generic/async/ports.c',
    142         'generic/loader.c',
    143         'generic/getopt.c',
    144154        'generic/time.c',
    145155        'generic/tmpfile.c',
    146         'generic/stdio.c',
    147         'generic/stdlib.c',
     156        'generic/ubsan.c',
    148157        'generic/udebug.c',
     158        'generic/uuid.c',
    149159        'generic/vfs/canonify.c',
    150160        'generic/vfs/inbox.c',
    151161        'generic/vfs/mtab.c',
    152162        'generic/vfs/vfs.c',
    153         'generic/setjmp.c',
    154         'generic/stack.c',
    155         'generic/stacktrace.c',
    156         'generic/arg_parse.c',
    157         'generic/stats.c',
    158         'generic/assert.c',
    159         'generic/ubsan.c',
    160         'generic/uuid.c',
    161163)
    162164
    163165if CONFIG_RTLD
    164166        src += files(
    165                 'generic/rtld/rtld.c',
    166167                'generic/rtld/dynamic.c',
    167168                'generic/rtld/module.c',
     169                'generic/rtld/rtld.c',
    168170                'generic/rtld/symbol.c',
    169171        )
     
    190192        'test/qsort.c',
    191193        'test/sprintf.c',
     194        'test/stdio.c',
    192195        'test/stdio/scanf.c',
    193         'test/stdio.c',
    194196        'test/stdlib.c',
    195197        'test/str.c',
    196198        'test/string.c',
    197199        'test/strtol.c',
     200        'test/uchar.c',
    198201        'test/uuid.c',
    199202)
  • uspace/lib/c/test/main.c

    r62e3411 r240b2e4  
    5757PCUT_IMPORT(strtol);
    5858PCUT_IMPORT(table);
     59PCUT_IMPORT(uchar);
    5960PCUT_IMPORT(uuid);
    6061
  • uspace/lib/ext4/src/extent.c

    r62e3411 r240b2e4  
    888888                ext4_extent_path_t *old_root = path + 1;
    889889
    890                 size_t nbytes = sizeof(ext4_extent_path_t) * (path->depth + 1);
    891                 memmove(old_root, new_root, nbytes);
     890                for (int i = path->depth; i >= 0; i--)
     891                        path[i + 1] = path[i];
     892
    892893                memset(new_root, 0, sizeof(ext4_extent_path_t));
    893894
Note: See TracChangeset for help on using the changeset viewer.