Ignore:
Timestamp:
2009-03-24T14:43:25Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8f29e336
Parents:
74c8da2c
Message:

Unicode aware printf and family functions
(this breaks some things, but will be fixed soon)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/printf/vsnprintf.c

    r74c8da2c reec616b  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    3535#include <print.h>
    3636#include <printf/printf_core.h>
     37#include <string.h>
    3738#include <memstr.h>
    3839
    39 struct vsnprintf_data {
    40         size_t size; /* total space for string */
    41         size_t len; /* count of currently used characters */
    42         char *string; /* destination string */
    43 };
     40typedef struct {
     41        size_t size;    /* Total size of the buffer (in bytes) */
     42        size_t len;     /* Number of already used bytes */
     43        char *dst;      /* Destination */
     44} vsnprintf_data_t;
    4445
    45 /** Write string to given buffer.
    46  * Write at most data->size characters including trailing zero. According to C99, snprintf() has to return number
    47  * of characters that would have been written if enough space had been available. Hence the return value is not
    48  * number of really printed characters but size of the input string. Number of really used characters
    49  * is stored in data->len.
    50  * @param str source string to print
    51  * @param count size of source string
    52  * @param data structure with destination string, counter of used space and total string size.
    53  * @return number of characters to print (not characters really printed!)
     46/** Write UTF-8 string to given buffer.
     47 *
     48 * Write at most data->size plain characters including trailing zero.
     49 * According to C99, snprintf() has to return number of characters that
     50 * would have been written if enough space had been available. Hence
     51 * the return value is not the number of actually printed characters
     52 * but size of the input string.
     53 *
     54 * @param str  Source UTF-8 string to print.
     55 * @param size Number of plain characters in str.
     56 * @param data Structure describing destination string, counter
     57 *             of used space and total string size.
     58 *
     59 * @return Number of UTF-8 characters to print (not characters actually
     60 *         printed).
     61 *
    5462 */
    55 static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
     63static int vsnprintf_write_utf8(const char *str, size_t size, vsnprintf_data_t *data)
    5664{
    57         size_t i;
    58         i = data->size - data->len;
    59 
    60         if (i == 0) {
    61                 return count;
     65        size_t left = data->size - data->len;
     66       
     67        if (left == 0)
     68                return ((int) size);
     69       
     70        if (left == 1) {
     71                /* We have only one free byte left in buffer
     72                 * -> store trailing zero
     73                 */
     74                data->dst[data->size - 1] = 0;
     75                data->len = data->size;
     76                return ((int) size);
    6277        }
    6378       
    64         if (i == 1) {
    65                 /* We have only one free byte left in buffer => write there trailing zero */
    66                 data->string[data->size - 1] = 0;
    67                 data->len = data->size;
    68                 return count;
     79        if (left <= size) {
     80                /* We have not enought space for whole string
     81                 * with the trailing zero => print only a part
     82                 * of string
     83                 */
     84                index_t index = 0;
     85               
     86                while (index < size) {
     87                        wchar_t uc = utf8_decode(str, &index, size - 1);
     88                       
     89                        if (!utf8_encode(uc, data->dst, &data->len, data->size - 1))
     90                                break;
     91                       
     92                        data->len++;
     93                        index++;
     94                }
     95               
     96                /* Put trailing zero at end, but not count it
     97                 * into data->len so it could be rewritten next time
     98                 */
     99                data->dst[data->len] = 0;
     100               
     101                return ((int) size);
    69102        }
    70103       
    71         if (i <= count) {
    72                 /* We have not enought space for whole string with the trailing zero => print only a part of string */
    73                         memcpy((void *)(data->string + data->len), (void *)str, i - 1);
    74                         data->string[data->size - 1] = 0;
     104        /* Buffer is big enought to print the whole string */
     105        memcpy((void *)(data->dst + data->len), (void *) str, size);
     106        data->len += size;
     107       
     108        /* Put trailing zero at end, but not count it
     109         * into data->len so it could be rewritten next time
     110         */
     111        data->dst[data->len] = 0;
     112       
     113        return ((int) size);
     114}
     115
     116/** Write UTF-32 string to given buffer.
     117 *
     118 * Write at most data->size plain characters including trailing zero.
     119 * According to C99, snprintf() has to return number of characters that
     120 * would have been written if enough space had been available. Hence
     121 * the return value is not the number of actually printed characters
     122 * but size of the input string.
     123 *
     124 * @param str  Source UTF-32 string to print.
     125 * @param size Number of bytes in str.
     126 * @param data Structure describing destination string, counter
     127 *             of used space and total string size.
     128 *
     129 * @return Number of UTF-8 characters to print (not characters actually
     130 *         printed).
     131 *
     132 */
     133static int vsnprintf_write_utf32(const wchar_t *str, size_t size, vsnprintf_data_t *data)
     134{
     135        index_t index = 0;
     136       
     137        while (index < (size / sizeof(wchar_t))) {
     138                size_t left = data->size - data->len;
     139               
     140                if (left == 0)
     141                        return ((int) size);
     142               
     143                if (left == 1) {
     144                        /* We have only one free byte left in buffer
     145                         * -> store trailing zero
     146                         */
     147                        data->dst[data->size - 1] = 0;
    75148                        data->len = data->size;
    76                         return count;
     149                        return ((int) size);
     150                }
     151               
     152                if (!utf8_encode(str[index], data->dst, &data->len, data->size - 1))
     153                        break;
     154               
     155                data->len++;
     156                index++;
    77157        }
    78158       
    79         /* Buffer is big enought to print whole string */
    80         memcpy((void *)(data->string + data->len), (void *)str, count);
    81         data->len += count;
    82         /* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */
    83         data->string[data->len] = 0;
    84 
    85         return count;   
     159        /* Put trailing zero at end, but not count it
     160         * into data->len so it could be rewritten next time
     161         */
     162        data->dst[data->len] = 0;
     163       
     164        return ((int) size);
    86165}
    87166
    88167int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
    89168{
    90         struct vsnprintf_data data = {size, 0, str};
    91         struct printf_spec ps = {(int(*)(void *, size_t, void *))vsnprintf_write, &data};
    92 
     169        vsnprintf_data_t data = {
     170                size,
     171                0,
     172                str
     173        };
     174        printf_spec_t ps = {
     175                (int(*) (const char *, size_t, void *)) vsnprintf_write_utf8,
     176                (int(*) (const wchar_t *, size_t, void *)) vsnprintf_write_utf32,
     177                &data
     178        };
     179       
    93180        /* Print 0 at end of string - fix the case that nothing will be printed */
    94181        if (size > 0)
Note: See TracChangeset for help on using the changeset viewer.