Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset f2b8cdc in mainline


Ignore:
Timestamp:
2009-04-04T22:04:28Z (12 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master
Children:
b27eb71
Parents:
4527fb5
Message:

Copy printf with Unicode support to userspace.

Files:
17 edited

Legend:

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

    r4527fb5 rf2b8cdc  
    6565
    6666extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
    67 extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
     67extern int chr_encode(wchar_t ch, char *str, size_t *offset, size_t sz);
    6868
    6969extern size_t str_size(const char *str);
     
    7979extern count_t wstr_nlength(const wchar_t *str, size_t size);
    8080
    81 extern bool ascii_check(const wchar_t ch);
    82 extern bool chr_check(const wchar_t ch);
     81extern bool ascii_check(wchar_t ch);
     82extern bool chr_check(wchar_t ch);
    8383
    8484extern int str_cmp(const char *s1, const char *s2);
  • kernel/generic/src/lib/string.c

    r4527fb5 rf2b8cdc  
    207207 *         code was invalid.
    208208 */
    209 int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t size)
     209int chr_encode(wchar_t ch, char *str, size_t *offset, size_t size)
    210210{
    211211        if (*offset >= size)
     
    423423 *
    424424 */
    425 bool ascii_check(const wchar_t ch)
     425bool ascii_check(wchar_t ch)
    426426{
    427427        if ((ch >= 0) && (ch <= 127))
     
    436436 *
    437437 */
    438 bool chr_check(const wchar_t ch)
     438bool chr_check(wchar_t ch)
    439439{
    440440        if ((ch >= 0) && (ch <= 1114111))
  • uspace/lib/libc/arch/amd64/include/types.h

    r4527fb5 rf2b8cdc  
    4848typedef unsigned long long int uint64_t;
    4949
     50typedef int64_t ssize_t;
     51typedef uint64_t size_t;
     52typedef uint64_t count_t;
     53typedef uint64_t index_t;
     54
    5055typedef uint64_t uintptr_t;
    5156
  • uspace/lib/libc/arch/arm32/include/types.h

    r4527fb5 rf2b8cdc  
    4949typedef unsigned long long int uint64_t;
    5050
     51typedef int32_t ssize_t;
     52typedef uint32_t size_t;
     53typedef uint32_t count_t;
     54typedef uint32_t index_t;
     55
    5156typedef uint32_t uintptr_t;
    5257
  • uspace/lib/libc/arch/ia32/include/types.h

    r4527fb5 rf2b8cdc  
    4848typedef unsigned long long int uint64_t;
    4949
     50typedef int32_t ssize_t;
     51typedef uint32_t size_t;
     52typedef uint32_t count_t;
     53typedef uint32_t index_t;
     54
    5055typedef uint32_t uintptr_t;
    5156
  • uspace/lib/libc/arch/ia64/include/types.h

    r4527fb5 rf2b8cdc  
    4848typedef unsigned long int uint64_t;
    4949
     50typedef int64_t ssize_t;
     51typedef uint64_t size_t;
     52typedef uint64_t count_t;
     53typedef uint64_t index_t;
     54
    5055typedef uint64_t uintptr_t;
    5156
  • uspace/lib/libc/arch/mips32/include/types.h

    r4527fb5 rf2b8cdc  
    4949typedef unsigned long long int uint64_t;
    5050
     51typedef int32_t ssize_t;
     52typedef uint32_t size_t;
     53typedef uint32_t count_t;
     54typedef uint32_t index_t;
     55
    5156typedef uint32_t uintptr_t;
    5257
  • uspace/lib/libc/arch/ppc32/include/types.h

    r4527fb5 rf2b8cdc  
    4848typedef unsigned long long int uint64_t;
    4949
     50typedef int32_t ssize_t;
     51typedef uint32_t size_t;
     52typedef uint32_t count_t;
     53typedef uint32_t index_t;
     54
    5055typedef uint32_t uintptr_t;
    5156
  • uspace/lib/libc/arch/sparc64/include/types.h

    r4527fb5 rf2b8cdc  
    4848typedef unsigned long int uint64_t;
    4949
     50typedef int64_t ssize_t;
     51typedef uint64_t size_t;
     52typedef uint64_t count_t;
     53typedef uint64_t index_t;
     54
    5055typedef uint64_t uintptr_t;
    5156
  • uspace/lib/libc/generic/io/fprintf.c

    r4527fb5 rf2b8cdc  
    3939#include <io/printf_core.h>
    4040
    41 static int vfprintf_write(const char *s, size_t count, void *f)
     41static int vfprintf_str_write(const char *s, size_t size, void *f)
    4242{
    43         return fwrite(s, 1, count, (FILE *) f);
     43        /* FIXME: Should return number of characters? */
     44        return fwrite(s, 1, size, (FILE *) f);
     45}
     46
     47static int vfprintf_wstr_write(const char *s, size_t size, void *f)
     48{
     49        /* TODO */
     50        return size;
    4451}
    4552
     
    4754{
    4855        struct printf_spec ps = {
    49                 (int (*)(void *, size_t, void *)) vfprintf_write,
     56                vfprintf_str_write,
     57                vfprintf_wstr_write,
    5058                (void *) f
    5159        };
  • uspace/lib/libc/generic/io/printf_core.c

    r4527fb5 rf2b8cdc  
    22 * Copyright (c) 2001-2004 Jakub Jermar
    33 * Copyright (c) 2006 Josef Cejka
     4 * Copyright (c) 2009 Martin Decky
    45 * All rights reserved.
    56 *
     
    2829 */
    2930
    30 /** @addtogroup libc
     31/** @addtogroup generic
    3132 * @{
    3233 */
    3334/**
    3435 * @file
    35  * @brief       Printing functions.
     36 * @brief Printing functions.
    3637 */
    3738
     
    4243#include <string.h>
    4344
    44 #define __PRINTF_FLAG_PREFIX            0x00000001      /**< show prefixes 0x or 0*/
    45 #define __PRINTF_FLAG_SIGNED            0x00000002      /**< signed / unsigned number */
    46 #define __PRINTF_FLAG_ZEROPADDED        0x00000004      /**< print leading zeroes */
    47 #define __PRINTF_FLAG_LEFTALIGNED       0x00000010      /**< align to left */
    48 #define __PRINTF_FLAG_SHOWPLUS          0x00000020      /**< always show + sign */
    49 #define __PRINTF_FLAG_SPACESIGN         0x00000040      /**< print space instead of plus */
    50 #define __PRINTF_FLAG_BIGCHARS          0x00000080      /**< show big characters */
    51 #define __PRINTF_FLAG_NEGATIVE          0x00000100      /**< number has - sign */
    52 
    53 #define PRINT_NUMBER_BUFFER_SIZE        (64+5)          /**< Buffer big enought for 64 bit number
    54                                                          * printed in base 2, sign, prefix and
    55                                                          * 0 to terminate string.. (last one is only for better testing
    56                                                          * end of buffer by zero-filling subroutine)
    57                                                          */
     45/** show prefixes 0x or 0 */
     46#define __PRINTF_FLAG_PREFIX       0x00000001
     47/** signed / unsigned number */
     48#define __PRINTF_FLAG_SIGNED       0x00000002
     49/** print leading zeroes */
     50#define __PRINTF_FLAG_ZEROPADDED   0x00000004
     51/** align to left */
     52#define __PRINTF_FLAG_LEFTALIGNED  0x00000010
     53/** always show + sign */
     54#define __PRINTF_FLAG_SHOWPLUS     0x00000020
     55/** print space instead of plus */
     56#define __PRINTF_FLAG_SPACESIGN    0x00000040
     57/** show big characters */
     58#define __PRINTF_FLAG_BIGCHARS     0x00000080
     59/** number has - sign */
     60#define __PRINTF_FLAG_NEGATIVE     0x00000100
     61
     62/**
     63 * Buffer big enough for 64-bit number printed in base 2, sign, prefix and 0
     64 * to terminate string... (last one is only for better testing end of buffer by
     65 * zero-filling subroutine)
     66 */
     67#define PRINT_NUMBER_BUFFER_SIZE  (64 + 5)
     68
    5869/** Enumeration of possible arguments types.
    5970 */
     
    6475        PrintfQualifierLong,
    6576        PrintfQualifierLongLong,
    66         PrintfQualifierSizeT,
    6777        PrintfQualifierPointer
    6878} qualifier_t;
    6979
    70 static char digits_small[] = "0123456789abcdef";        /**< Small hexadecimal characters */
    71 static char digits_big[] = "0123456789ABCDEF";          /**< Big hexadecimal characters */
    72 
    73 /** Print count chars from buffer without adding newline
    74  * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
    75  * @param count
    76  * @param ps output method and its data
    77  * @return number of printed characters
    78  */
    79 static int printf_putnchars(const char * buf, size_t count,
    80     struct printf_spec *ps)
    81 {
    82         return ps->write((void *)buf, count, ps->data);
    83 }
    84 
    85 /** Print string without added newline
    86  * @param str string to print
    87  * @param ps write function specification and support data
    88  * @return number of printed characters
    89  */
    90 static int printf_putstr(const char * str, struct printf_spec *ps)
    91 {
    92         size_t count;
    93        
     80static char nullstr[] = "(NULL)";
     81static char digits_small[] = "0123456789abcdef";
     82static char digits_big[] = "0123456789ABCDEF";
     83static char invalch = U_SPECIAL;
     84
     85/** Print one or more characters without adding newline.
     86 *
     87 * @param buf  Buffer holding characters with size of
     88 *             at least size bytes. NULL is not allowed!
     89 * @param size Size of the buffer in bytes.
     90 * @param ps   Output method and its data.
     91 *
     92 * @return Number of characters printed.
     93 *
     94 */
     95static int printf_putnchars(const char *buf, size_t size,
     96    printf_spec_t *ps)
     97{
     98        return ps->str_write((void *) buf, size, ps->data);
     99}
     100
     101/** Print one or more wide characters without adding newline.
     102 *
     103 * @param buf  Buffer holding wide characters with size of
     104 *             at least size bytes. NULL is not allowed!
     105 * @param size Size of the buffer in bytes.
     106 * @param ps   Output method and its data.
     107 *
     108 * @return Number of wide characters printed.
     109 *
     110 */
     111static int printf_wputnchars(const wchar_t *buf, size_t size,
     112    printf_spec_t *ps)
     113{
     114        return ps->wstr_write((void *) buf, size, ps->data);
     115}
     116
     117/** Print string without adding a newline.
     118 *
     119 * @param str String to print.
     120 * @param ps  Write function specification and support data.
     121 *
     122 * @return Number of characters printed.
     123 *
     124 */
     125static int printf_putstr(const char *str, printf_spec_t *ps)
     126{
    94127        if (str == NULL)
    95                 return printf_putnchars("(NULL)", 6, ps);
    96 
    97         count = strlen(str);
    98 
    99         return ps->write((void *) str, count, ps->data);
    100 }
    101 
    102 /** Print one character to output
    103  * @param c one character
    104  * @param ps output method
    105  * @return number of printed characters
    106  */
    107 static int printf_putchar(int c, struct printf_spec *ps)
    108 {
    109         unsigned char ch = c;
    110        
    111         return ps->write((void *) &ch, 1, ps->data);
    112 }
    113 
    114 /** Print one formatted character
    115  * @param c character to print
    116  * @param width
    117  * @param flags
    118  * @return number of printed characters
    119  */
    120 static int print_char(char c, int width, uint64_t flags, struct printf_spec *ps)
    121 {
    122         int counter = 0;
    123        
     128                return printf_putnchars(nullstr, str_size(nullstr), ps);
     129       
     130        return ps->str_write((void *) str, str_size(str), ps->data);
     131}
     132
     133/** Print one ASCII character.
     134 *
     135 * @param c  ASCII character to be printed.
     136 * @param ps Output method.
     137 *
     138 * @return Number of characters printed.
     139 *
     140 */
     141static int printf_putchar(const char ch, printf_spec_t *ps)
     142{
     143        if (!ascii_check(ch))
     144                return ps->str_write((void *) &invalch, 1, ps->data);
     145       
     146        return ps->str_write(&ch, 1, ps->data);
     147}
     148
     149/** Print one wide character.
     150 *
     151 * @param c  Wide character to be printed.
     152 * @param ps Output method.
     153 *
     154 * @return Number of characters printed.
     155 *
     156 */
     157static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
     158{
     159        if (!chr_check(ch))
     160                return ps->str_write((void *) &invalch, 1, ps->data);
     161       
     162        return ps->wstr_write(&ch, sizeof(wchar_t), ps->data);
     163}
     164
     165/** Print one formatted ASCII character.
     166 *
     167 * @param ch    Character to print.
     168 * @param width Width modifier.
     169 * @param flags Flags that change the way the character is printed.
     170 *
     171 * @return Number of characters printed, negative value on failure.
     172 *
     173 */
     174static int print_char(const char ch, int width, uint32_t flags, printf_spec_t *ps)
     175{
     176        count_t counter = 0;
    124177        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     178                while (--width > 0) {
     179                        /*
     180                         * One space is consumed by the character itself, hence
     181                         * the predecrement.
     182                         */
     183                        if (printf_putchar(' ', ps) > 0)
     184                                counter++;
     185                }
     186        }
     187       
     188        if (printf_putchar(ch, ps) > 0)
     189                counter++;
     190       
     191        while (--width > 0) {
    125192                /*
    126                  * One space is consumed by the character itself, hence the
    127                  * predecrement.
     193                 * One space is consumed by the character itself, hence
     194                 * the predecrement.
    128195                 */
     196                if (printf_putchar(' ', ps) > 0)
     197                        counter++;
     198        }
     199       
     200        return (int) (counter + 1);
     201}
     202
     203/** Print one formatted wide character.
     204 *
     205 * @param ch    Character to print.
     206 * @param width Width modifier.
     207 * @param flags Flags that change the way the character is printed.
     208 *
     209 * @return Number of characters printed, negative value on failure.
     210 *
     211 */
     212static int print_wchar(const wchar_t ch, int width, uint32_t flags, printf_spec_t *ps)
     213{
     214        count_t counter = 0;
     215        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    129216                while (--width > 0) {
    130                         if (printf_putchar(' ', ps) > 0)       
    131                                 ++counter;
    132                 }
    133         }
    134        
    135         if (printf_putchar(c, ps) > 0)
     217                        /*
     218                         * One space is consumed by the character itself, hence
     219                         * the predecrement.
     220                         */
     221                        if (printf_putchar(' ', ps) > 0)
     222                                counter++;
     223                }
     224        }
     225       
     226        if (printf_putwchar(ch, ps) > 0)
    136227                counter++;
    137         /*
    138          * One space is consumed by the character itself, hence the
    139          * predecrement.
    140          */
     228       
    141229        while (--width > 0) {
     230                /*
     231                 * One space is consumed by the character itself, hence
     232                 * the predecrement.
     233                 */
    142234                if (printf_putchar(' ', ps) > 0)
    143                         ++counter;
    144         }
    145        
    146         return ++counter;
    147 }
    148 
    149 /** Print one string
    150  * @param s string
    151  * @param width
    152  * @param precision
    153  * @param flags
    154  * @return number of printed characters
    155  */
    156 static int print_string(char *s, int width, int precision, uint64_t flags,
    157     struct printf_spec *ps)
    158 {
    159         int counter = 0;
    160         size_t size;
     235                        counter++;
     236        }
     237       
     238        return (int) (counter + 1);
     239}
     240
     241/** Print string.
     242 *
     243 * @param str       String to be printed.
     244 * @param width     Width modifier.
     245 * @param precision Precision modifier.
     246 * @param flags     Flags that modify the way the string is printed.
     247 *
     248 * @return Number of characters printed, negative value on failure.
     249 */
     250static int print_str(char *str, int width, unsigned int precision,
     251        uint32_t flags, printf_spec_t *ps)
     252{
     253        if (str == NULL)
     254                return printf_putstr(nullstr, ps);
     255
     256        /* Print leading spaces. */
     257        count_t strw = str_length(str);
     258        if (precision == 0)
     259                precision = strw;
     260
     261        /* Left padding */
     262        count_t counter = 0;
     263        width -= precision;
     264        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     265                while (width-- > 0) {
     266                        if (printf_putchar(' ', ps) == 1)
     267                                counter++;
     268                }
     269        }
     270
     271        /* Part of @a str fitting into the alloted space. */
    161272        int retval;
    162 
    163         if (s == NULL) {
    164                 return printf_putstr("(NULL)", ps);
    165         }
    166        
    167         size = strlen(s);
    168 
    169         /* print leading spaces */
    170 
    171         if (precision == 0)
    172                 precision = size;
    173 
     273        size_t size = str_lsize(str, precision);
     274        if ((retval = printf_putnchars(str, size, ps)) < 0)
     275                return -counter;
     276
     277        counter += retval;
     278
     279        /* Right padding */
     280        while (width-- > 0) {
     281                if (printf_putchar(' ', ps) == 1)
     282                        counter++;
     283        }
     284
     285        return ((int) counter);
     286
     287}
     288
     289/** Print wide string.
     290 *
     291 * @param str       Wide string to be printed.
     292 * @param width     Width modifier.
     293 * @param precision Precision modifier.
     294 * @param flags     Flags that modify the way the string is printed.
     295 *
     296 * @return Number of wide characters printed, negative value on failure.
     297 */
     298static int print_wstr(wchar_t *str, int width, unsigned int precision,
     299        uint32_t flags, printf_spec_t *ps)
     300{
     301        if (str == NULL)
     302                return printf_putstr(nullstr, ps);
     303
     304        /* Print leading spaces. */
     305        size_t strw = wstr_length(str);
     306        if (precision == 0)
     307                precision = strw;
     308
     309        /* Left padding */
     310        count_t counter = 0;
    174311        width -= precision;
    175        
    176312        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    177                 while (width-- > 0) {   
    178                         if (printf_putchar(' ', ps) == 1)       
     313                while (width-- > 0) {
     314                        if (printf_putchar(' ', ps) == 1)
    179315                                counter++;
    180316                }
    181317        }
    182318
    183         if ((retval = printf_putnchars(s, size < precision ? size : precision,
    184             ps)) < 0) {
     319        /* Part of @a wstr fitting into the alloted space. */
     320        int retval;
     321        size_t size = wstr_lsize(str, precision);
     322        if ((retval = printf_wputnchars(str, size, ps)) < 0)
    185323                return -counter;
    186         }
    187 
    188         counter += retval;     
    189 
     324
     325        counter += retval;
     326
     327        /* Right padding */
    190328        while (width-- > 0) {
    191                 if (printf_putchar(' ', ps) == 1)       
    192                         ++counter;
    193         }
    194        
    195         return counter;
    196 }
    197 
    198 
    199 /** Print number in given base
    200  *
    201  * Print significant digits of a number in given
    202  * base.
    203  *
    204  * @param num  Number to print.
    205  * @param width
    206  * @param precision
    207  * @param base Base to print the number in (should
    208  *             be in range 2 .. 16).
    209  * @param flags output modifiers
    210  * @return number of printed characters
     329                if (printf_putchar(' ', ps) == 1)
     330                        counter++;
     331        }
     332
     333        return ((int) counter);
     334}
     335
     336/** Print a number in a given base.
     337 *
     338 * Print significant digits of a number in given base.
     339 *
     340 * @param num       Number to print.
     341 * @param width     Width modifier.
     342 * @param precision Precision modifier.
     343 * @param base      Base to print the number in (must be between 2 and 16).
     344 * @param flags     Flags that modify the way the number is printed.
     345 *
     346 * @return Number of characters printed.
    211347 *
    212348 */
    213349static int print_number(uint64_t num, int width, int precision, int base,
    214     uint64_t flags, struct printf_spec *ps)
    215 {
    216         char *digits = digits_small;
    217         char d[PRINT_NUMBER_BUFFER_SIZE];       /* this is good enough even for
    218                                                  * base == 2, prefix and sign */
    219         char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
    220         int size = 0; /* size of number with all prefixes and signs */
    221         int number_size; /* size of plain number */
    222         char sgn;
    223         int retval;
    224         int counter = 0;
    225        
    226         if (flags & __PRINTF_FLAG_BIGCHARS)
    227                 digits = digits_big;   
    228        
    229         *ptr-- = 0; /* Put zero at end of string */
    230 
     350    uint32_t flags, printf_spec_t *ps)
     351{
     352        char *digits;
     353        if (flags & __PRINTF_FLAG_BIGCHARS)
     354                digits = digits_big;
     355        else
     356                digits = digits_small;
     357       
     358        char data[PRINT_NUMBER_BUFFER_SIZE];
     359        char *ptr = &data[PRINT_NUMBER_BUFFER_SIZE - 1];
     360       
     361        /* Size of number with all prefixes and signs */
     362        int size = 0;
     363       
     364        /* Put zero at end of string */
     365        *ptr-- = 0;
     366       
    231367        if (num == 0) {
    232368                *ptr-- = '0';
     
    239375        }
    240376       
    241         number_size = size;
    242 
     377        /* Size of plain number */
     378        int number_size = size;
     379       
    243380        /*
    244          * Collect sum of all prefixes/signs/... to calculate padding and
    245          * leading zeroes
     381         * Collect the sum of all prefixes/signs/etc. to calculate padding and
     382         * leading zeroes.
    246383         */
    247384        if (flags & __PRINTF_FLAG_PREFIX) {
    248385                switch(base) {
    249                 case 2: /* Binary formating is not standard, but usefull */
     386                case 2:
     387                        /* Binary formating is not standard, but usefull */
    250388                        size += 2;
    251389                        break;
     
    258396                }
    259397        }
    260 
    261         sgn = 0;
     398       
     399        char sgn = 0;
    262400        if (flags & __PRINTF_FLAG_SIGNED) {
    263401                if (flags & __PRINTF_FLAG_NEGATIVE) {
     
    272410                }
    273411        }
    274 
    275         if (flags & __PRINTF_FLAG_LEFTALIGNED) {
     412       
     413        if (flags & __PRINTF_FLAG_LEFTALIGNED)
    276414                flags &= ~__PRINTF_FLAG_ZEROPADDED;
    277         }
    278 
     415       
    279416        /*
    280          * If number is leftaligned or precision is specified then zeropadding
    281          * is ignored.
     417         * If the number is left-aligned or precision is specified then
     418         * padding with zeros is ignored.
    282419         */
    283420        if (flags & __PRINTF_FLAG_ZEROPADDED) {
    284                 if ((precision == 0) && (width > size)) {
     421                if ((precision == 0) && (width > size))
    285422                        precision = width - size + number_size;
    286                 }
    287         }
    288 
    289         /* print leading spaces */
    290 
    291         /* We must print whole number not only a part. */
    292         if (number_size > precision)
     423        }
     424       
     425        /* Print leading spaces */
     426        if (number_size > precision) {
     427                /* Print the whole number, not only a part */
    293428                precision = number_size;
    294 
     429        }
     430       
    295431        width -= precision + size - number_size;
     432        count_t counter = 0;
    296433       
    297434        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    298                 while (width-- > 0) {   
    299                         if (printf_putchar(' ', ps) == 1)       
     435                while (width-- > 0) {
     436                        if (printf_putchar(' ', ps) == 1)
    300437                                counter++;
    301438                }
    302439        }
    303440       
    304         /* print sign */
     441        /* Print sign */
    305442        if (sgn) {
    306443                if (printf_putchar(sgn, ps) == 1)
     
    308445        }
    309446       
    310         /* print prefix */
    311        
     447        /* Print prefix */
    312448        if (flags & __PRINTF_FLAG_PREFIX) {
    313449                switch(base) {
    314                 case 2: /* Binary formating is not standard, but usefull */
     450                case 2:
     451                        /* Binary formating is not standard, but usefull */
    315452                        if (printf_putchar('0', ps) == 1)
    316453                                counter++;
     
    340477                }
    341478        }
    342 
    343         /* print leading zeroes */
     479       
     480        /* Print leading zeroes */
    344481        precision -= number_size;
    345         while (precision-- > 0) {       
     482        while (precision-- > 0) {
    346483                if (printf_putchar('0', ps) == 1)
    347484                        counter++;
    348485        }
    349 
    350        
    351         /* print number itself */
    352 
    353         if ((retval = printf_putstr(++ptr, ps)) > 0) {
     486       
     487        /* Print the number itself */
     488        int retval;
     489        if ((retval = printf_putstr(++ptr, ps)) > 0)
    354490                counter += retval;
    355         }
    356        
    357         /* print ending spaces */
    358        
    359         while (width-- > 0) {   
    360                 if (printf_putchar(' ', ps) == 1)       
     491       
     492        /* Print tailing spaces */
     493       
     494        while (width-- > 0) {
     495                if (printf_putchar(' ', ps) == 1)
    361496                        counter++;
    362497        }
    363 
    364         return counter;
    365 }
    366 
     498       
     499        return ((int) counter);
     500}
    367501
    368502/** Print formatted string.
     
    370504 * Print string formatted according to the fmt parameter and variadic arguments.
    371505 * Each formatting directive must have the following form:
    372  * 
    373  *      \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
     506 *
     507 *  \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
    374508 *
    375509 * FLAGS:@n
    376  *      - "#" Force to print prefix.
    377  *      For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and
    378  *      0X and for conversion \%b the prefix is 0b.
    379  *
    380  *      - "-"   Align to left.
    381  *
    382  *      - "+"   Print positive sign just as negative.
    383  *
    384  *      - " "   If the printed number is positive and "+" flag is not set,
    385  *              print space in place of sign.
    386  *
    387  *      - "0"   Print 0 as padding instead of spaces. Zeroes are placed between
    388  *              sign and the rest of the number. This flag is ignored if "-"
    389  *              flag is specified.
    390  * 
     510 *  - "#" Force to print prefix. For \%o conversion, the prefix is 0, for
     511 *        \%x and \%X prefixes are 0x and 0X and for conversion \%b the
     512 *        prefix is 0b.
     513 *
     514 *  - "-" Align to left.
     515 *
     516 *  - "+" Print positive sign just as negative.
     517 *
     518 *  - " " If the printed number is positive and "+" flag is not set,
     519 *        print space in place of sign.
     520 *
     521 *  - "0" Print 0 as padding instead of spaces. Zeroes are placed between
     522 *        sign and the rest of the number. This flag is ignored if "-"
     523 *        flag is specified.
     524 *
    391525 * WIDTH:@n
    392  *      - Specify minimal width of printed argument. If it is bigger, width is
    393  *        ignored. If width is specified with a "*" character instead of number,
    394  *        width is taken from parameter list. And integer parameter is expected
    395  *        before parameter for processed conversion specification. If this value
    396  *        is negative its absolute value is taken and the "-" flag is set.
     526 *  - Specify the minimal width of a printed argument. If it is bigger,
     527 *    width is ignored. If width is specified with a "*" character instead of
     528 *    number, width is taken from parameter list. And integer parameter is
     529 *    expected before parameter for processed conversion specification. If
     530 *    this value is negative its absolute value is taken and the "-" flag is
     531 *    set.
    397532 *
    398533 * PRECISION:@n
    399  *      - Value precision. For numbers it specifies minimum valid numbers.
    400  *        Smaller numbers are printed with leading zeroes. Bigger numbers are
    401  *        not affected. Strings with more than precision characters are cut off.
    402  *        Just as with width, an "*" can be used used instead of a number. An
    403  *        integer value is then expected in parameters. When both width and
    404  *        precision are specified using "*", the first parameter is used for
    405  *        width and the second one for precision.
    406  * 
     534 *  - Value precision. For numbers it specifies minimum valid numbers.
     535 *    Smaller numbers are printed with leading zeroes. Bigger numbers are not
     536 *    affected. Strings with more than precision characters are cut off. Just
     537 *    as with width, an "*" can be used used instead of a number. An integer
     538 *    value is then expected in parameters. When both width and precision are
     539 *    specified using "*", the first parameter is used for width and the
     540 *    second one for precision.
     541 *
    407542 * TYPE:@n
    408  *      - "hh"  Signed or unsigned char.@n
    409  *      - "h"   Signed or usigned short.@n
    410  *      - ""    Signed or usigned int (default value).@n
    411  *      - "l"   Signed or usigned long int.@n
    412  *      - "ll"  Signed or usigned long long int.@n
    413  *      - "z"   Type size_t.@n
    414  *
    415  * 
     543 *  - "hh" Signed or unsigned char.@n
     544 *  - "h"  Signed or unsigned short.@n
     545 *  - ""   Signed or unsigned int (default value).@n
     546 *  - "l"  Signed or unsigned long int.@n
     547 *         If conversion is "c", the character is wchar_t (wide character).@n
     548 *         If conversion is "s", the string is wchar_t * (wide string).@n
     549 *  - "ll" Signed or unsigned long long int.@n
     550 *
    416551 * CONVERSION:@n
    417  *      - %     Print percentile character itself.
    418  *
    419  *      - c     Print single character.
    420  *
    421  *      - s     Print zero terminated string. If a NULL value is passed as
    422  *              value, "(NULL)" is printed instead.
    423  *
    424  *      - P, p  Print value of a pointer. Void * value is expected and it is
    425  *              printed in hexadecimal notation with prefix (as with '\%#X' or
    426  *              '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers).
    427  *
    428  *      - b     Print value as unsigned binary number. Prefix is not printed by
    429  *              default. (Nonstandard extension.)
    430  *
    431  *      - o     Print value as unsigned octal number. Prefix is not printed by
    432  *              default.
    433  *
    434  *      - d, i  Print signed decimal number. There is no difference between d
    435  *              and i conversion.
    436  *
    437  *      - u     Print unsigned decimal number.
    438  *
    439  *      - X, x  Print hexadecimal number with upper- or lower-case. Prefix is
    440  *              not printed by default.
    441  *
    442  * All other characters from fmt except the formatting directives are printed in
     552 *  - % Print percentile character itself.
     553 *
     554 *  - c Print single character. The character is expected to be plain
     555 *      ASCII (e.g. only values 0 .. 127 are valid).@n
     556 *      If type is "l", then the character is expected to be wide character
     557 *      (e.g. values 0 .. 0x10ffff are valid).
     558 *
     559 *  - s Print zero terminated string. If a NULL value is passed as
     560 *      value, "(NULL)" is printed instead.@n
     561 *      If type is "l", then the string is expected to be wide string.
     562 *
     563 *  - P, p Print value of a pointer. Void * value is expected and it is
     564 *         printed in hexadecimal notation with prefix (as with \%#X / \%#x
     565 *         for 32-bit or \%#X / \%#x for 64-bit long pointers).
     566 *
     567 *  - b Print value as unsigned binary number. Prefix is not printed by
     568 *      default. (Nonstandard extension.)
     569 *
     570 *  - o Print value as unsigned octal number. Prefix is not printed by
     571 *      default.
     572 *
     573 *  - d, i Print signed decimal number. There is no difference between d
     574 *         and i conversion.
     575 *
     576 *  - u Print unsigned decimal number.
     577 *
     578 *  - X, x Print hexadecimal number with upper- or lower-case. Prefix is
     579 *         not printed by default.
     580 *
     581 * All other characters from fmt except the formatting directives are printed
    443582 * verbatim.
    444583 *
    445  * @param fmt Formatting NULL terminated string.
    446  * @return Number of printed characters or negative value on failure.
    447  */
    448 int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
    449 {
    450         /* i is the index of the currently processed char from fmt */
    451         int i = 0;
    452         /* j is the index to the first not printed nonformating character */
    453         int j = 0;
    454 
    455         int end;
    456         int counter;    /* counter of printed characters */
    457         int retval;     /* used to store return values from called functions */
    458         char c;
    459         qualifier_t qualifier;  /* type of argument */
    460         int base;       /* base in which will be a numeric parameter printed */
    461         uint64_t number; /* argument value */
    462         size_t  size;   /* byte size of integer parameter */
    463         int width, precision;
    464         uint64_t flags;
    465        
    466         counter = 0;
    467        
    468         while ((c = fmt[i])) {
    469                 /* control character */
    470                 if (c == '%' ) {
    471                         /* print common characters if any processed */ 
     584 * @param fmt Format NULL-terminated string.
     585 *
     586 * @return Number of characters printed, negative value on failure.
     587 *
     588 */
     589int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
     590{
     591        size_t i;        /* Index of the currently processed character from fmt */
     592        size_t nxt = 0;  /* Index of the next character from fmt */
     593        size_t j = 0;    /* Index to the first not printed nonformating character */
     594       
     595        count_t counter = 0;  /* Number of characters printed */
     596        int retval;           /* Return values from nested functions */
     597       
     598        while (true) {
     599                i = nxt;
     600                wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     601               
     602                if (uc == 0)
     603                        break;
     604               
     605                /* Control character */
     606                if (uc == '%') {
     607                        /* Print common characters if any processed */
    472608                        if (i > j) {
    473                                 if ((retval = printf_putnchars(&fmt[j],
    474                                     (size_t)(i - j), ps)) < 0) { /* error */
    475                                         goto minus_out;
     609                                if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
     610                                        /* Error */
     611                                        counter = -counter;
     612                                        goto out;
    476613                                }
    477614                                counter += retval;
    478615                        }
    479                
     616                       
    480617                        j = i;
    481                         /* parse modifiers */
    482                         flags = 0;
    483                         end = 0;
     618                       
     619                        /* Parse modifiers */
     620                        uint32_t flags = 0;
     621                        bool end = false;
    484622                       
    485623                        do {
    486                                 ++i;
    487                                 switch (c = fmt[i]) {
     624                                i = nxt;
     625                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     626                                switch (uc) {
    488627                                case '#':
    489628                                        flags |= __PRINTF_FLAG_PREFIX;
     
    502641                                        break;
    503642                                default:
    504                                         end = 1;
    505                                 };     
    506                                
    507                         } while (end == 0);     
    508                        
    509                         /* width & '*' operator */
    510                         width = 0;
    511                         if (isdigit(fmt[i])) {
    512                                 while (isdigit(fmt[i])) {
     643                                        end = true;
     644                                };
     645                        } while (!end);
     646                       
     647                        /* Width & '*' operator */
     648                        int width = 0;
     649                        if (isdigit(uc)) {
     650                                while (true) {
    513651                                        width *= 10;
    514                                         width += fmt[i++] - '0';
     652                                        width += uc - '0';
     653                                       
     654                                        i = nxt;
     655                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     656                                        if (uc == 0)
     657                                                break;
     658                                        if (!isdigit(uc))
     659                                                break;
    515660                                }
    516                         } else if (fmt[i] == '*') {
    517                                 /* get width value from argument list*/
    518                                 i++;
    519                                 width = (int)va_arg(ap, int);
     661                        } else if (uc == '*') {
     662                                /* Get width value from argument list */
     663                                i = nxt;
     664                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     665                                width = (int) va_arg(ap, int);
    520666                                if (width < 0) {
    521                                         /* negative width sets '-' flag */
     667                                        /* Negative width sets '-' flag */
    522668                                        width *= -1;
    523669                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     
    525671                        }
    526672                       
    527                         /* precision and '*' operator */       
    528                         precision = 0;
    529                         if (fmt[i] == '.') {
    530                                 ++i;
    531                                 if (isdigit(fmt[i])) {
    532                                         while (isdigit(fmt[i])) {
     673                        /* Precision and '*' operator */
     674                        int precision = 0;
     675                        if (uc == '.') {
     676                                i = nxt;
     677                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     678                                if (isdigit(uc)) {
     679                                        while (true) {
    533680                                                precision *= 10;
    534                                                 precision += fmt[i++] - '0';
     681                                                precision += uc - '0';
     682                                               
     683                                                i = nxt;
     684                                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     685                                                if (uc == 0)
     686                                                        break;
     687                                                if (!isdigit(uc))
     688                                                        break;
    535689                                        }
    536                                 } else if (fmt[i] == '*') {
    537                                         /* get precision value from argument */
    538                                         i++;
    539                                         precision = (int)va_arg(ap, int);
     690                                } else if (uc == '*') {
     691                                        /* Get precision value from the argument list */
     692                                        i = nxt;
     693                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     694                                        precision = (int) va_arg(ap, int);
    540695                                        if (precision < 0) {
    541                                                 /* negative precision ignored */
     696                                                /* Ignore negative precision */
    542697                                                precision = 0;
    543698                                        }
    544699                                }
    545700                        }
    546 
    547                         switch (fmt[i++]) {
    548                         /** @todo unimplemented qualifiers:
    549                          * t ptrdiff_t - ISO C 99
     701                       
     702                        qualifier_t qualifier;
     703                       
     704                        switch (uc) {
     705                        /** @todo Unimplemented qualifiers:
     706                         *        t ptrdiff_t - ISO C 99
    550707                         */
    551                         case 'h':       /* char or short */
     708                        case 'h':
     709                                /* Char or short */
    552710                                qualifier = PrintfQualifierShort;
    553                                 if (fmt[i] == 'h') {
    554                                         i++;
     711                                i = nxt;
     712                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     713                                if (uc == 'h') {
     714                                        i = nxt;
     715                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
    555716                                        qualifier = PrintfQualifierByte;
    556717                                }
    557718                                break;
    558                         case 'l':       /* long or long long*/
     719                        case 'l':
     720                                /* Long or long long */
    559721                                qualifier = PrintfQualifierLong;
    560                                 if (fmt[i] == 'l') {
    561                                         i++;
     722                                i = nxt;
     723                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     724                                if (uc == 'l') {
     725                                        i = nxt;
     726                                        uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
    562727                                        qualifier = PrintfQualifierLongLong;
    563728                                }
    564729                                break;
    565                         case 'z':       /* size_t */
    566                                 qualifier = PrintfQualifierSizeT;
    567                                 break;
    568730                        default:
    569                                 /* set default type */
     731                                /* Default type */
    570732                                qualifier = PrintfQualifierInt;
    571                                 --i;
    572                         }       
    573                        
    574                         base = 10;
    575 
    576                         switch (c = fmt[i]) {
    577 
     733                        }
     734                       
     735                        unsigned int base = 10;
     736                       
     737                        switch (uc) {
    578738                        /*
    579739                         * String and character conversions.
    580740                         */
    581741                        case 's':
    582                                 if ((retval = print_string(va_arg(ap, char*),
    583                                     width, precision, flags, ps)) < 0) {
    584                                         goto minus_out;
     742                                if (qualifier == PrintfQualifierLong)
     743                                        retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps);
     744                                else
     745                                        retval = print_str(va_arg(ap, char *), width, precision, flags, ps);
     746                               
     747                                if (retval < 0) {
     748                                        counter = -counter;
     749                                        goto out;
    585750                                }
    586                                        
     751                               
    587752                                counter += retval;
    588                                 j = i + 1;
     753                                j = nxt;
    589754                                goto next_char;
    590755                        case 'c':
    591                                 c = va_arg(ap, unsigned int);
    592                                 retval = print_char(c, width, flags, ps);
     756                                if (qualifier == PrintfQualifierLong)
     757                                        retval = print_wchar(va_arg(ap, wchar_t), width, flags, ps);
     758                                else
     759                                        retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
     760                               
    593761                                if (retval < 0) {
    594                                         goto minus_out;
    595                                 }
    596 
     762                                        counter = -counter;
     763                                        goto out;
     764                                };
     765                               
    597766                                counter += retval;
    598                                 j = i + 1;
     767                                j = nxt;
    599768                                goto next_char;
    600 
    601                         /* 
     769                       
     770                        /*
    602771                         * Integer values
    603772                         */
    604                         case 'P': /* pointer */
    605                                 flags |= __PRINTF_FLAG_BIGCHARS;
     773                        case 'P':
     774                                /* Pointer */
     775                                flags |= __PRINTF_FLAG_BIGCHARS;
    606776                        case 'p':
    607777                                flags |= __PRINTF_FLAG_PREFIX;
    608778                                base = 16;
    609779                                qualifier = PrintfQualifierPointer;
    610                                 break; 
    611                         case 'b': 
     780                                break;
     781                        case 'b':
    612782                                base = 2;
    613783                                break;
     
    617787                        case 'd':
    618788                        case 'i':
    619                                 flags |= __PRINTF_FLAG_SIGNED; 
     789                                flags |= __PRINTF_FLAG_SIGNED;
    620790                        case 'u':
    621791                                break;
     
    625795                                base = 16;
    626796                                break;
    627                         /* percentile itself */
    628                         case '%':
     797                       
     798                        /* Percentile itself */
     799                        case '%':
    629800                                j = i;
    630801                                goto next_char;
     802                       
    631803                        /*
    632804                         * Bad formatting.
     
    634806                        default:
    635807                                /*
    636                                  * Unknown format. Now, j is the index of '%',
    637                                  * so we will print the whole bad format
    638                                  * sequence.
     808                                 * Unknown format. Now, j is the index of '%'
     809                                 * so we will print whole bad format sequence.
    639810                                 */
    640                                 goto next_char;         
    641                         }
    642                
    643                
     811                                goto next_char;
     812                        }
     813                       
    644814                        /* Print integers */
     815                        size_t size;
     816                        uint64_t number;
    645817                        switch (qualifier) {
    646818                        case PrintfQualifierByte:
    647819                                size = sizeof(unsigned char);
    648                                 number = (uint64_t)va_arg(ap, unsigned int);
     820                                number = (uint64_t) va_arg(ap, unsigned int);
    649821                                break;
    650822                        case PrintfQualifierShort:
    651823                                size = sizeof(unsigned short);
    652                                 number = (uint64_t)va_arg(ap, unsigned int);
     824                                number = (uint64_t) va_arg(ap, unsigned int);
    653825                                break;
    654826                        case PrintfQualifierInt:
    655827                                size = sizeof(unsigned int);
    656                                 number = (uint64_t)va_arg(ap, unsigned int);
     828                                number = (uint64_t) va_arg(ap, unsigned int);
    657829                                break;
    658830                        case PrintfQualifierLong:
    659831                                size = sizeof(unsigned long);
    660                                 number = (uint64_t)va_arg(ap, unsigned long);
     832                                number = (uint64_t) va_arg(ap, unsigned long);
    661833                                break;
    662834                        case PrintfQualifierLongLong:
    663835                                size = sizeof(unsigned long long);
    664                                 number = (uint64_t)va_arg(ap,
    665                                     unsigned long long);
     836                                number = (uint64_t) va_arg(ap, unsigned long long);
    666837                                break;
    667838                        case PrintfQualifierPointer:
    668839                                size = sizeof(void *);
    669                                 number = (uint64_t)(unsigned long)va_arg(ap,
    670                                     void *);
    671                                 break;
    672                         case PrintfQualifierSizeT:
    673                                 size = sizeof(size_t);
    674                                 number = (uint64_t)va_arg(ap, size_t);
    675                                 break;
    676                         default: /* Unknown qualifier */
    677                                 goto minus_out;
    678                                        
     840                                number = (uint64_t) (unsigned long) va_arg(ap, void *);
     841                                break;
     842                        default:
     843                                /* Unknown qualifier */
     844                                counter = -counter;
     845                                goto out;
    679846                        }
    680847                       
     
    682849                                if (number & (0x1 << (size * 8 - 1))) {
    683850                                        flags |= __PRINTF_FLAG_NEGATIVE;
    684                                
     851                                       
    685852                                        if (size == sizeof(uint64_t)) {
    686                                                 number = -((int64_t)number);
     853                                                number = -((int64_t) number);
    687854                                        } else {
    688855                                                number = ~number;
     
    694861                                }
    695862                        }
    696 
     863                       
    697864                        if ((retval = print_number(number, width, precision,
    698                             base, flags, ps)) < 0 ) {
    699                                 goto minus_out;
    700                         }
    701 
     865                            base, flags, ps)) < 0) {
     866                                counter = -counter;
     867                                goto out;
     868                        }
     869                       
    702870                        counter += retval;
    703                         j = i + 1;
    704                 }       
     871                        j = nxt;
     872                }
    705873next_char:
    706                        
    707                 ++i;
     874                ;
    708875        }
    709876       
    710877        if (i > j) {
    711                 retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps);
    712                 if (retval < 0) { /* error */
    713                         goto minus_out;
     878                if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
     879                        /* Error */
     880                        counter = -counter;
     881                        goto out;
    714882                }
    715883                counter += retval;
    716884        }
    717885       
    718         return counter;
    719 minus_out:
    720         return -counter;
     886out:
     887        return ((int) counter);
    721888}
    722889
  • uspace/lib/libc/generic/io/vprintf.c

    r4527fb5 rf2b8cdc  
    4242static atomic_t printf_futex = FUTEX_INITIALIZER;
    4343
    44 static int vprintf_write(const char *str, size_t count, void *unused)
     44static int vprintf_str_write(const char *str, size_t size, void *data)
    4545{
    46         return write_stdout(str, count);
     46        size_t offset = 0;
     47        size_t prev;
     48        count_t chars = 0;
     49       
     50        while (offset < size) {
     51                prev = offset;
     52                str_decode(str, &offset, size);
     53                write_stdout(str + prev, offset - prev);
     54                chars++;
     55        }
     56       
     57        return chars;
    4758}
     59
     60static int vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
     61{
     62        size_t offset = 0;
     63        size_t boff;
     64        count_t chars = 0;
     65        char buf[4];
     66       
     67        while (offset < size) {
     68                boff = 0;
     69                chr_encode(str[chars], buf, &boff, 4);
     70                write_stdout(buf, boff);
     71                chars++;
     72                offset += sizeof(wchar_t);
     73        }
     74       
     75        return chars;
     76}
     77
    4878
    4979/** Print formatted text.
     
    5585{
    5686        struct printf_spec ps = {
    57                 (int (*)(void *, size_t, void *)) vprintf_write,
     87                vprintf_str_write,
     88                vprintf_wstr_write,
    5889                 NULL
    5990        };
  • 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;
  • uspace/lib/libc/generic/string.c

    r4527fb5 rf2b8cdc  
    4040#include <malloc.h>
    4141#include <errno.h>
     42#include <align.h>
    4243#include <string.h>
    4344
     
    193194}
    194195
     196/** Get size of string.
     197 *
     198 * Get the number of bytes which are used by the string @a str (excluding the
     199 * NULL-terminator).
     200 *
     201 * @param str String to consider.
     202 *
     203 * @return Number of bytes used by the string
     204 *
     205 */
     206size_t str_size(const char *str)
     207{
     208        size_t size = 0;
     209       
     210        while (*str++ != 0)
     211                size++;
     212       
     213        return size;
     214}
     215
     216/** Get size of wide string.
     217 *
     218 * Get the number of bytes which are used by the wide string @a str (excluding the
     219 * NULL-terminator).
     220 *
     221 * @param str Wide string to consider.
     222 *
     223 * @return Number of bytes used by the wide string
     224 *
     225 */
     226size_t wstr_size(const wchar_t *str)
     227{
     228        return (wstr_length(str) * sizeof(wchar_t));
     229}
     230
     231/** Get size of string with length limit.
     232 *
     233 * Get the number of bytes which are used by up to @a max_len first
     234 * characters in the string @a str. If @a max_len is greater than
     235 * the length of @a str, the entire string is measured (excluding the
     236 * NULL-terminator).
     237 *
     238 * @param str     String to consider.
     239 * @param max_len Maximum number of characters to measure.
     240 *
     241 * @return Number of bytes used by the characters.
     242 *
     243 */
     244size_t str_lsize(const char *str, count_t max_len)
     245{
     246        count_t len = 0;
     247        size_t offset = 0;
     248       
     249        while (len < max_len) {
     250                if (str_decode(str, &offset, STR_NO_LIMIT) == 0)
     251                        break;
     252               
     253                len++;
     254        }
     255       
     256        return offset;
     257}
     258
     259/** Get size of wide string with length limit.
     260 *
     261 * Get the number of bytes which are used by up to @a max_len first
     262 * wide characters in the wide string @a str. If @a max_len is greater than
     263 * the length of @a str, the entire wide string is measured (excluding the
     264 * NULL-terminator).
     265 *
     266 * @param str     Wide string to consider.
     267 * @param max_len Maximum number of wide characters to measure.
     268 *
     269 * @return Number of bytes used by the wide characters.
     270 *
     271 */
     272size_t wstr_lsize(const wchar_t *str, count_t max_len)
     273{
     274        return (wstr_nlength(str, max_len * sizeof(wchar_t)) * sizeof(wchar_t));
     275}
     276
     277/** Get number of characters in a string.
     278 *
     279 * @param str NULL-terminated string.
     280 *
     281 * @return Number of characters in string.
     282 *
     283 */
     284count_t str_length(const char *str)
     285{
     286        count_t len = 0;
     287        size_t offset = 0;
     288       
     289        while (str_decode(str, &offset, STR_NO_LIMIT) != 0)
     290                len++;
     291       
     292        return len;
     293}
     294
     295/** Get number of characters in a wide string.
     296 *
     297 * @param str NULL-terminated wide string.
     298 *
     299 * @return Number of characters in @a str.
     300 *
     301 */
     302count_t wstr_length(const wchar_t *wstr)
     303{
     304        count_t len = 0;
     305       
     306        while (*wstr++ != 0)
     307                len++;
     308       
     309        return len;
     310}
     311
     312/** Get number of characters in a string with size limit.
     313 *
     314 * @param str  NULL-terminated string.
     315 * @param size Maximum number of bytes to consider.
     316 *
     317 * @return Number of characters in string.
     318 *
     319 */
     320count_t str_nlength(const char *str, size_t size)
     321{
     322        count_t len = 0;
     323        size_t offset = 0;
     324       
     325        while (str_decode(str, &offset, size) != 0)
     326                len++;
     327       
     328        return len;
     329}
     330
     331/** Get number of characters in a string with size limit.
     332 *
     333 * @param str  NULL-terminated string.
     334 * @param size Maximum number of bytes to consider.
     335 *
     336 * @return Number of characters in string.
     337 *
     338 */
     339count_t wstr_nlength(const wchar_t *str, size_t size)
     340{
     341        count_t len = 0;
     342        count_t limit = ALIGN_DOWN(size, sizeof(wchar_t));
     343        count_t offset = 0;
     344       
     345        while ((offset < limit) && (*str++ != 0)) {
     346                len++;
     347                offset += sizeof(wchar_t);
     348        }
     349       
     350        return len;
     351}
     352
     353/** Check whether character is plain ASCII.
     354 *
     355 * @return True if character is plain ASCII.
     356 *
     357 */
     358bool ascii_check(wchar_t ch)
     359{
     360        if ((ch >= 0) && (ch <= 127))
     361                return true;
     362       
     363        return false;
     364}
     365
    195366/** Check whether character is valid
    196367 *
     
    198369 *
    199370 */
    200 bool chr_check(const wchar_t ch)
     371bool chr_check(wchar_t ch)
    201372{
    202373        if ((ch >= 0) && (ch <= 1114111))
     
    204375       
    205376        return false;
     377}
     378
     379/** Compare two NULL terminated strings.
     380 *
     381 * Do a char-by-char comparison of two NULL-terminated strings.
     382 * The strings are considered equal iff they consist of the same
     383 * characters on the minimum of their lengths.
     384 *
     385 * @param s1 First string to compare.
     386 * @param s2 Second string to compare.
     387 *
     388 * @return 0 if the strings are equal, -1 if first is smaller,
     389 *         1 if second smaller.
     390 *
     391 */
     392int str_cmp(const char *s1, const char *s2)
     393{
     394        wchar_t c1 = 0;
     395        wchar_t c2 = 0;
     396       
     397        size_t off1 = 0;
     398        size_t off2 = 0;
     399
     400        while (true) {
     401                c1 = str_decode(s1, &off1, STR_NO_LIMIT);
     402                c2 = str_decode(s2, &off2, STR_NO_LIMIT);
     403
     404                if (c1 < c2)
     405                        return -1;
     406               
     407                if (c1 > c2)
     408                        return 1;
     409
     410                if (c1 == 0 || c2 == 0)
     411                        break;         
     412        }
     413
     414        return 0;
     415}
     416
     417/** Compare two NULL terminated strings with length limit.
     418 *
     419 * Do a char-by-char comparison of two NULL-terminated strings.
     420 * The strings are considered equal iff they consist of the same
     421 * characters on the minimum of their lengths and the length limit.
     422 *
     423 * @param s1      First string to compare.
     424 * @param s2      Second string to compare.
     425 * @param max_len Maximum number of characters to consider.
     426 *
     427 * @return 0 if the strings are equal, -1 if first is smaller,
     428 *         1 if second smaller.
     429 *
     430 */
     431int str_lcmp(const char *s1, const char *s2, count_t max_len)
     432{
     433        wchar_t c1 = 0;
     434        wchar_t c2 = 0;
     435       
     436        size_t off1 = 0;
     437        size_t off2 = 0;
     438       
     439        count_t len = 0;
     440
     441        while (true) {
     442                if (len >= max_len)
     443                        break;
     444
     445                c1 = str_decode(s1, &off1, STR_NO_LIMIT);
     446                c2 = str_decode(s2, &off2, STR_NO_LIMIT);
     447
     448                if (c1 < c2)
     449                        return -1;
     450
     451                if (c1 > c2)
     452                        return 1;
     453
     454                if (c1 == 0 || c2 == 0)
     455                        break;
     456
     457                ++len; 
     458        }
     459
     460        return 0;
     461
     462}
     463
     464/** Copy NULL-terminated string.
     465 *
     466 * Copy source string @a src to destination buffer @a dst.
     467 * No more than @a size bytes are written. NULL-terminator is always
     468 * written after the last succesfully copied character (i.e. if the
     469 * destination buffer is has at least 1 byte, it will be always
     470 * NULL-terminated).
     471 *
     472 * @param src   Source string.
     473 * @param dst   Destination buffer.
     474 * @param count Size of the destination buffer.
     475 *
     476 */
     477void str_ncpy(char *dst, const char *src, size_t size)
     478{
     479        /* No space for the NULL-terminator in the buffer */
     480        if (size == 0)
     481                return;
     482       
     483        wchar_t ch;
     484        size_t str_off = 0;
     485        size_t dst_off = 0;
     486       
     487        while ((ch = str_decode(src, &str_off, STR_NO_LIMIT)) != 0) {
     488                if (chr_encode(ch, dst, &dst_off, size) != EOK)
     489                        break;
     490        }
     491       
     492        if (dst_off >= size)
     493                dst[size - 1] = 0;
     494        else
     495                dst[dst_off] = 0;
     496}
     497
     498/** Copy NULL-terminated wide string to string
     499 *
     500 * Copy source wide string @a src to destination buffer @a dst.
     501 * No more than @a size bytes are written. NULL-terminator is always
     502 * written after the last succesfully copied character (i.e. if the
     503 * destination buffer is has at least 1 byte, it will be always
     504 * NULL-terminated).
     505 *
     506 * @param src   Source wide string.
     507 * @param dst   Destination buffer.
     508 * @param count Size of the destination buffer.
     509 *
     510 */
     511void wstr_nstr(char *dst, const wchar_t *src, size_t size)
     512{
     513        /* No space for the NULL-terminator in the buffer */
     514        if (size == 0)
     515                return;
     516       
     517        wchar_t ch;
     518        count_t src_idx = 0;
     519        size_t dst_off = 0;
     520       
     521        while ((ch = src[src_idx++]) != 0) {
     522                if (chr_encode(ch, dst, &dst_off, size) != EOK)
     523                        break;
     524        }
     525       
     526        if (dst_off >= size)
     527                dst[size - 1] = 0;
     528        else
     529                dst[dst_off] = 0;
     530}
     531
     532/** Find first occurence of character in string.
     533 *
     534 * @param str String to search.
     535 * @param ch  Character to look for.
     536 *
     537 * @return Pointer to character in @a str or NULL if not found.
     538 *
     539 */
     540const char *str_chr(const char *str, wchar_t ch)
     541{
     542        wchar_t acc;
     543        size_t off = 0;
     544       
     545        while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
     546                if (acc == ch)
     547                        return (str + off);
     548        }
     549       
     550        return NULL;
     551}
     552
     553/** Insert a wide character into a wide string.
     554 *
     555 * Insert a wide character into a wide string at position
     556 * @a pos. The characters after the position are shifted.
     557 *
     558 * @param str     String to insert to.
     559 * @param ch      Character to insert to.
     560 * @param pos     Character index where to insert.
     561 @ @param max_pos Characters in the buffer.
     562 *
     563 * @return True if the insertion was sucessful, false if the position
     564 *         is out of bounds.
     565 *
     566 */
     567bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos)
     568{
     569        count_t len = wstr_length(str);
     570       
     571        if ((pos > len) || (pos + 1 > max_pos))
     572                return false;
     573       
     574        count_t i;
     575        for (i = len; i + 1 > pos; i--)
     576                str[i + 1] = str[i];
     577       
     578        str[pos] = ch;
     579       
     580        return true;
     581}
     582
     583/** Remove a wide character from a wide string.
     584 *
     585 * Remove a wide character from a wide string at position
     586 * @a pos. The characters after the position are shifted.
     587 *
     588 * @param str String to remove from.
     589 * @param pos Character index to remove.
     590 *
     591 * @return True if the removal was sucessful, false if the position
     592 *         is out of bounds.
     593 *
     594 */
     595bool wstr_remove(wchar_t *str, count_t pos)
     596{
     597        count_t len = wstr_length(str);
     598       
     599        if (pos >= len)
     600                return false;
     601       
     602        count_t i;
     603        for (i = pos + 1; i <= len; i++)
     604                str[i - 1] = str[i];
     605       
     606        return true;
    206607}
    207608
  • uspace/lib/libc/include/io/printf_core.h

    r4527fb5 rf2b8cdc  
    4040
    4141/** Structure for specifying output methods for different printf clones. */
    42 struct printf_spec {
    43         /* Output function, returns count of printed characters or EOF */
    44         int (*write)(void *, size_t, void *);
    45         /* Support data - output stream specification, its state, locks,... */
     42typedef struct printf_spec {
     43        /* String output function, returns number of printed characters or EOF */
     44        int (*str_write)(const char *, size_t, void *);
     45       
     46        /* Wide string output function, returns number of printed characters or EOF */
     47        int (*wstr_write)(const wchar_t *, size_t, void *);
     48       
     49        /* User data - output stream specification, state, locks, etc. */
    4650        void *data;
     51} printf_spec_t;
    4752
    48 };
    49 
    50 int printf_core(const char *fmt, struct printf_spec *ps ,va_list ap);
     53int printf_core(const char *fmt, printf_spec_t *ps, va_list ap);
    5154
    5255#endif
  • uspace/lib/libc/include/string.h

    r4527fb5 rf2b8cdc  
    4242#define U_SPECIAL      '?'
    4343
     44/**< No size limit constant */
     45#define STR_NO_LIMIT  ((size_t) -1)
     46
     47/**< Maximum size of a string containing cnt characters */
     48#define STR_BOUNDS(cnt)  (cnt << 2)
     49
    4450extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
    4551extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
    4652
    47 extern bool chr_check(const wchar_t ch);
     53extern size_t str_size(const char *str);
     54extern size_t wstr_size(const wchar_t *str);
     55
     56extern size_t str_lsize(const char *str, count_t max_len);
     57extern size_t wstr_lsize(const wchar_t *str, count_t max_len);
     58
     59extern count_t str_length(const char *str);
     60extern count_t wstr_length(const wchar_t *wstr);
     61
     62extern count_t str_nlength(const char *str, size_t size);
     63extern count_t wstr_nlength(const wchar_t *str, size_t size);
     64
     65extern bool ascii_check(wchar_t ch);
     66extern bool chr_check(wchar_t ch);
     67
     68extern int str_cmp(const char *s1, const char *s2);
     69extern int str_lcmp(const char *s1, const char *s2, count_t max_len);
     70
     71extern void str_ncpy(char *dst, const char *src, size_t size);
     72extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
     73
     74extern const char *str_chr(const char *str, wchar_t ch);
     75
     76extern bool wstr_linsert(wchar_t *str, wchar_t ch, count_t pos, count_t max_pos);
     77extern bool wstr_remove(wchar_t *str, count_t pos);
     78
     79/*
     80 * TODO: Get rid of this.
     81 */
    4882
    4983extern int strcmp(const char *, const char *);
  • uspace/lib/libc/include/sys/types.h

    r4527fb5 rf2b8cdc  
    3838#include <libarch/types.h>
    3939
    40 typedef unsigned long size_t;
    41 typedef signed long ssize_t;
    4240typedef long off_t;
    4341typedef int mode_t;
Note: See TracChangeset for help on using the changeset viewer.