Ignore:
Timestamp:
2009-04-04T22:04:28Z (15 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b27eb71
Parents:
4527fb5
Message:

Copy printf with Unicode support to userspace.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/io/vsnprintf.c

    r4527fb5 rf2b8cdc  
    3737#include <string.h>
    3838#include <io/printf_core.h>
     39#include <errno.h>
    3940
    40 struct vsnprintf_data {
    41         size_t size;    /* total space for string */
    42         size_t len;     /* count of currently used characters */
    43         char *string;   /* destination string */
    44 };
     41typedef struct {
     42        size_t size;    /* Total size of the buffer (in bytes) */
     43        size_t len;     /* Number of already used bytes */
     44        char *dst;      /* Destination */
     45} vsnprintf_data_t;
    4546
    4647/** Write string to given buffer.
    47  * Write at most data->size characters including trailing zero. According to C99
    48  * has snprintf to return number of characters that would have been written if
    49  * enough space had been available. Hence the return value is not number of
    50  * really printed characters but size of input string. Number of really used
    51  * characters is stored in data->len.
    5248 *
    53  * @param str           Source string to print.
    54  * @param count         Size of the source string.
    55  * @param data          Structure with destination string, counter of used space
    56  *                      and total string size.
    57  * @return              Number of characters to print (not characters really
    58  *                      printed!)
     49 * Write at most data->size plain characters including trailing zero.
     50 * According to C99, snprintf() has to return number of characters that
     51 * would have been written if enough space had been available. Hence
     52 * the return value is not the number of actually printed characters
     53 * but size of the input string.
     54 *
     55 * @param str  Source string to print.
     56 * @param size Number of plain characters in str.
     57 * @param data Structure describing destination string, counter
     58 *             of used space and total string size.
     59 *
     60 * @return Number of characters to print (not characters actually
     61 *         printed).
     62 *
    5963 */
    60 static int
    61 vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
     64static int vsnprintf_str_write(const char *str, size_t size, vsnprintf_data_t *data)
    6265{
    63         size_t i;
    64         i = data->size - data->len;
    65 
    66         if (i == 0) {
    67                 return count;
     66        size_t left = data->size - data->len;
     67       
     68        if (left == 0)
     69                return ((int) size);
     70       
     71        if (left == 1) {
     72                /* We have only one free byte left in buffer
     73                 * -> store trailing zero
     74                 */
     75                data->dst[data->size - 1] = 0;
     76                data->len = data->size;
     77                return ((int) size);
    6878        }
    6979       
    70         if (i == 1) {
    71                 /*
    72                  * We have only one free byte left in buffer => write there
    73                  * trailing zero.
     80        if (left <= size) {
     81                /* We do not have enough space for the whole string
     82                 * with the trailing zero => print only a part
     83                 * of string
    7484                 */
    75                 data->string[data->size - 1] = 0;
    76                 data->len = data->size;
    77                 return count;
     85                index_t index = 0;
     86               
     87                while (index < size) {
     88                        wchar_t uc = str_decode(str, &index, size);
     89                       
     90                        if (chr_encode(uc, data->dst, &data->len, data->size - 1) != EOK)
     91                                break;
     92                }
     93               
     94                /* Put trailing zero at end, but not count it
     95                 * into data->len so it could be rewritten next time
     96                 */
     97                data->dst[data->len] = 0;
     98               
     99                return ((int) size);
    78100        }
    79101       
    80         if (i <= count) {
    81                 /*
    82                  * We have not enought space for whole string with the trailing
    83                  * zero => print only a part of string.
    84                  */
    85                 memcpy((void *)(data->string + data->len), (void *)str, i - 1);
    86                 data->string[data->size - 1] = 0;
    87                 data->len = data->size;
    88                 return count;
     102        /* Buffer is big enought to print the whole string */
     103        memcpy((void *)(data->dst + data->len), (void *) str, size);
     104        data->len += size;
     105       
     106        /* Put trailing zero at end, but not count it
     107         * into data->len so it could be rewritten next time
     108         */
     109        data->dst[data->len] = 0;
     110       
     111        return ((int) size);
     112}
     113
     114/** Write wide string to given buffer.
     115 *
     116 * Write at most data->size plain characters including trailing zero.
     117 * According to C99, snprintf() has to return number of characters that
     118 * would have been written if enough space had been available. Hence
     119 * the return value is not the number of actually printed characters
     120 * but size of the input string.
     121 *
     122 * @param str  Source wide string to print.
     123 * @param size Number of bytes in str.
     124 * @param data Structure describing destination string, counter
     125 *             of used space and total string size.
     126 *
     127 * @return Number of wide characters to print (not characters actually
     128 *         printed).
     129 *
     130 */
     131static int vsnprintf_wstr_write(const wchar_t *str, size_t size, vsnprintf_data_t *data)
     132{
     133        index_t index = 0;
     134       
     135        while (index < (size / sizeof(wchar_t))) {
     136                size_t left = data->size - data->len;
     137               
     138                if (left == 0)
     139                        return ((int) size);
     140               
     141                if (left == 1) {
     142                        /* We have only one free byte left in buffer
     143                         * -> store trailing zero
     144                         */
     145                        data->dst[data->size - 1] = 0;
     146                        data->len = data->size;
     147                        return ((int) size);
     148                }
     149               
     150                if (chr_encode(str[index], data->dst, &data->len, data->size - 1) != EOK)
     151                        break;
     152               
     153                index++;
    89154        }
    90155       
    91         /* Buffer is big enought to print whole string */
    92         memcpy((void *)(data->string + data->len), (void *)str, count);
    93         data->len += count;
    94         /*
    95          * Put trailing zero at end, but not count it into data->len so it could
    96          * be rewritten next time.
     156        /* Put trailing zero at end, but not count it
     157         * into data->len so it could be rewritten next time
    97158         */
    98         data->string[data->len] = 0;
    99 
    100         return count;   
     159        data->dst[data->len] = 0;
     160       
     161        return ((int) size);
    101162}
    102163
    103 /** Print formatted to the given buffer with limited size.
    104  * @param str           Buffer.
    105  * @param size          Bffer size.
    106  * @param fmt           Format string.
    107  * \see For more details about format string see printf_core.
    108  */
    109164int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
    110165{
    111         struct vsnprintf_data data = {size, 0, str};
    112         struct printf_spec ps = {
    113                 (int(*)(void *, size_t, void *)) vsnprintf_write,
     166        vsnprintf_data_t data = {
     167                size,
     168                0,
     169                str
     170        };
     171        printf_spec_t ps = {
     172                (int(*) (const char *, size_t, void *)) vsnprintf_str_write,
     173                (int(*) (const wchar_t *, size_t, void *)) vsnprintf_wstr_write,
    114174                &data
    115175        };
    116 
    117         /*
    118          * Print 0 at end of string - fix the case that nothing will be printed.
    119          */
     176       
     177        /* Print 0 at end of string - fix the case that nothing will be printed */
    120178        if (size > 0)
    121179                str[0] = 0;
Note: See TracChangeset for help on using the changeset viewer.