Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/str.c

    r933cadf r1737bfb  
    22 * Copyright (c) 2005 Martin Decky
    33 * Copyright (c) 2008 Jiri Svoboda
     4 * Copyright (c) 2011 Martin Sucha
     5 * Copyright (c) 2011 Oleg Romanenko
    46 * All rights reserved.
    57 *
     
    540542
    541543        dstr_size = str_size(dest);
     544        if (dstr_size >= size)
     545                return;
     546       
    542547        str_cpy(dest + dstr_size, size - dstr_size, src);
     548}
     549
     550/** Convert space-padded ASCII to string.
     551 *
     552 * Common legacy text encoding in hardware is 7-bit ASCII fitted into
     553 * a fixed-width byte buffer (bit 7 always zero), right-padded with spaces
     554 * (ASCII 0x20). Convert space-padded ascii to string representation.
     555 *
     556 * If the text does not fit into the destination buffer, the function converts
     557 * as many characters as possible and returns EOVERFLOW.
     558 *
     559 * If the text contains non-ASCII bytes (with bit 7 set), the whole string is
     560 * converted anyway and invalid characters are replaced with question marks
     561 * (U_SPECIAL) and the function returns EIO.
     562 *
     563 * Regardless of return value upon return @a dest will always be well-formed.
     564 *
     565 * @param dest          Destination buffer
     566 * @param size          Size of destination buffer
     567 * @param src           Space-padded ASCII.
     568 * @param n             Size of the source buffer in bytes.
     569 *
     570 * @return              EOK on success, EOVERFLOW if the text does not fit
     571 *                      destination buffer, EIO if the text contains
     572 *                      non-ASCII bytes.
     573 */
     574int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n)
     575{
     576        size_t sidx;
     577        size_t didx;
     578        size_t dlast;
     579        uint8_t byte;
     580        int rc;
     581        int result;
     582
     583        /* There must be space for a null terminator in the buffer. */
     584        assert(size > 0);
     585        result = EOK;
     586
     587        didx = 0;
     588        dlast = 0;
     589        for (sidx = 0; sidx < n; ++sidx) {
     590                byte = src[sidx];
     591                if (!ascii_check(byte)) {
     592                        byte = U_SPECIAL;
     593                        result = EIO;
     594                }
     595
     596                rc = chr_encode(byte, dest, &didx, size - 1);
     597                if (rc != EOK) {
     598                        assert(rc == EOVERFLOW);
     599                        dest[didx] = '\0';
     600                        return rc;
     601                }
     602
     603                /* Remember dest index after last non-empty character */
     604                if (byte != 0x20)
     605                        dlast = didx;
     606        }
     607
     608        /* Terminate string after last non-empty character */
     609        dest[dlast] = '\0';
     610        return result;
    543611}
    544612
     
    572640        dest[dest_off] = '\0';
    573641}
     642
     643/** Convert UTF16 string to string.
     644 *
     645 * Convert utf16 string @a src to string. The output is written to the buffer
     646 * specified by @a dest and @a size. @a size must be non-zero and the string
     647 * written will always be well-formed. Surrogate pairs also supported.
     648 *
     649 * @param dest  Destination buffer.
     650 * @param size  Size of the destination buffer.
     651 * @param src   Source utf16 string.
     652 *
     653 * @return EOK, if success, negative otherwise.
     654 */
     655int utf16_to_str(char *dest, size_t size, const uint16_t *src)
     656{
     657        size_t idx = 0, dest_off = 0;
     658        wchar_t ch;
     659        int rc = EOK;
     660
     661        /* There must be space for a null terminator in the buffer. */
     662        assert(size > 0);
     663
     664        while (src[idx]) {
     665                if ((src[idx] & 0xfc00) == 0xd800) {
     666                        if (src[idx + 1] && (src[idx + 1] & 0xfc00) == 0xdc00) {
     667                                ch = 0x10000;
     668                                ch += (src[idx] & 0x03FF) << 10;
     669                                ch += (src[idx + 1] & 0x03FF);
     670                                idx += 2;
     671                        }
     672                        else
     673                                break;
     674                } else {
     675                        ch = src[idx];
     676                        idx++;
     677                }
     678                rc = chr_encode(ch, dest, &dest_off, size - 1);
     679                if (rc != EOK)
     680                        break;
     681        }
     682        dest[dest_off] = '\0';
     683        return rc;
     684}
     685
     686int str_to_utf16(uint16_t *dest, size_t size, const char *src)
     687{
     688        int rc = EOK;
     689        size_t offset = 0;
     690        size_t idx = 0;
     691        wchar_t c;
     692
     693        assert(size > 0);
     694       
     695        while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
     696                if (c > 0x10000) {
     697                        if (idx + 2 >= size - 1) {
     698                                rc = EOVERFLOW;
     699                                break;
     700                        }
     701                        c = (c - 0x10000);
     702                        dest[idx] = 0xD800 | (c >> 10);
     703                        dest[idx + 1] = 0xDC00 | (c & 0x3FF);
     704                        idx++;
     705                } else {
     706                         dest[idx] = c;
     707                }
     708
     709                idx++;
     710                if (idx >= size - 1) {
     711                        rc = EOVERFLOW;
     712                        break;
     713                }
     714        }
     715
     716        dest[idx] = '\0';
     717        return rc;
     718}
     719
    574720
    575721/** Convert wide string to new string.
     
    654800}
    655801
     802/** Convert string to wide string.
     803 *
     804 * Convert string @a src to wide string. A new wide NULL-terminated
     805 * string will be allocated on the heap.
     806 *
     807 * @param src   Source string.
     808 */
     809wchar_t *str_to_awstr(const char *str)
     810{
     811        size_t len = str_length(str);
     812       
     813        wchar_t *wstr = calloc(len+1, sizeof(wchar_t));
     814        if (wstr == NULL)
     815                return NULL;
     816       
     817        str_to_wstr(wstr, len + 1, str);
     818        return wstr;
     819}
     820
    656821/** Find first occurence of character in string.
    657822 *
     
    674839       
    675840        return NULL;
     841}
     842
     843/** Removes specified trailing characters from a string.
     844 *
     845 * @param str String to remove from.
     846 * @param ch  Character to remove.
     847 */
     848void str_rtrim(char *str, wchar_t ch)
     849{
     850        size_t off = 0;
     851        size_t pos = 0;
     852        wchar_t c;
     853        bool update_last_chunk = true;
     854        char *last_chunk = NULL;
     855
     856        while ((c = str_decode(str, &off, STR_NO_LIMIT))) {
     857                if (c != ch) {
     858                        update_last_chunk = true;
     859                        last_chunk = NULL;
     860                } else if (update_last_chunk) {
     861                        update_last_chunk = false;
     862                        last_chunk = (str + pos);
     863                }
     864                pos = off;
     865        }
     866
     867        if (last_chunk)
     868                *last_chunk = '\0';
     869}
     870
     871/** Removes specified leading characters from a string.
     872 *
     873 * @param str String to remove from.
     874 * @param ch  Character to remove.
     875 */
     876void str_ltrim(char *str, wchar_t ch)
     877{
     878        wchar_t acc;
     879        size_t off = 0;
     880        size_t pos = 0;
     881        size_t str_sz = str_size(str);
     882
     883        while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
     884                if (acc != ch)
     885                        break;
     886                else
     887                        pos = off;
     888        }
     889
     890        if (pos > 0) {
     891                memmove(str, &str[pos], str_sz - pos);
     892                pos = str_sz - pos;
     893                str[str_sz - pos] = '\0';
     894        }
    676895}
    677896
     
    9501169        return dest;
    9511170}
    952 
    9531171
    9541172/** Convert initial part of string to unsigned long according to given base.
     
    11271345}
    11281346
     1347/** Convert string to uint8_t.
     1348 *
     1349 * @param nptr   Pointer to string.
     1350 * @param endptr If not NULL, pointer to the first invalid character
     1351 *               is stored here.
     1352 * @param base   Zero or number between 2 and 36 inclusive.
     1353 * @param strict Do not allow any trailing characters.
     1354 * @param result Result of the conversion.
     1355 *
     1356 * @return EOK if conversion was successful.
     1357 *
     1358 */
     1359int str_uint8_t(const char *nptr, char **endptr, unsigned int base,
     1360    bool strict, uint8_t *result)
     1361{
     1362        assert(result != NULL);
     1363       
     1364        bool neg;
     1365        char *lendptr;
     1366        uint64_t res;
     1367        int ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1368       
     1369        if (endptr != NULL)
     1370                *endptr = (char *) lendptr;
     1371       
     1372        if (ret != EOK)
     1373                return ret;
     1374       
     1375        /* Do not allow negative values */
     1376        if (neg)
     1377                return EINVAL;
     1378       
     1379        /* Check whether we are at the end of
     1380           the string in strict mode */
     1381        if ((strict) && (*lendptr != 0))
     1382                return EINVAL;
     1383       
     1384        /* Check for overflow */
     1385        uint8_t _res = (uint8_t) res;
     1386        if (_res != res)
     1387                return EOVERFLOW;
     1388       
     1389        *result = _res;
     1390       
     1391        return EOK;
     1392}
     1393
     1394/** Convert string to uint16_t.
     1395 *
     1396 * @param nptr   Pointer to string.
     1397 * @param endptr If not NULL, pointer to the first invalid character
     1398 *               is stored here.
     1399 * @param base   Zero or number between 2 and 36 inclusive.
     1400 * @param strict Do not allow any trailing characters.
     1401 * @param result Result of the conversion.
     1402 *
     1403 * @return EOK if conversion was successful.
     1404 *
     1405 */
     1406int str_uint16_t(const char *nptr, char **endptr, unsigned int base,
     1407    bool strict, uint16_t *result)
     1408{
     1409        assert(result != NULL);
     1410       
     1411        bool neg;
     1412        char *lendptr;
     1413        uint64_t res;
     1414        int ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1415       
     1416        if (endptr != NULL)
     1417                *endptr = (char *) lendptr;
     1418       
     1419        if (ret != EOK)
     1420                return ret;
     1421       
     1422        /* Do not allow negative values */
     1423        if (neg)
     1424                return EINVAL;
     1425       
     1426        /* Check whether we are at the end of
     1427           the string in strict mode */
     1428        if ((strict) && (*lendptr != 0))
     1429                return EINVAL;
     1430       
     1431        /* Check for overflow */
     1432        uint16_t _res = (uint16_t) res;
     1433        if (_res != res)
     1434                return EOVERFLOW;
     1435       
     1436        *result = _res;
     1437       
     1438        return EOK;
     1439}
     1440
     1441/** Convert string to uint32_t.
     1442 *
     1443 * @param nptr   Pointer to string.
     1444 * @param endptr If not NULL, pointer to the first invalid character
     1445 *               is stored here.
     1446 * @param base   Zero or number between 2 and 36 inclusive.
     1447 * @param strict Do not allow any trailing characters.
     1448 * @param result Result of the conversion.
     1449 *
     1450 * @return EOK if conversion was successful.
     1451 *
     1452 */
     1453int str_uint32_t(const char *nptr, char **endptr, unsigned int base,
     1454    bool strict, uint32_t *result)
     1455{
     1456        assert(result != NULL);
     1457       
     1458        bool neg;
     1459        char *lendptr;
     1460        uint64_t res;
     1461        int ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1462       
     1463        if (endptr != NULL)
     1464                *endptr = (char *) lendptr;
     1465       
     1466        if (ret != EOK)
     1467                return ret;
     1468       
     1469        /* Do not allow negative values */
     1470        if (neg)
     1471                return EINVAL;
     1472       
     1473        /* Check whether we are at the end of
     1474           the string in strict mode */
     1475        if ((strict) && (*lendptr != 0))
     1476                return EINVAL;
     1477       
     1478        /* Check for overflow */
     1479        uint32_t _res = (uint32_t) res;
     1480        if (_res != res)
     1481                return EOVERFLOW;
     1482       
     1483        *result = _res;
     1484       
     1485        return EOK;
     1486}
     1487
    11291488/** Convert string to uint64_t.
    11301489 *
Note: See TracChangeset for help on using the changeset viewer.