Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4295 → Rev 4296

/branches/dd/kernel/generic/src/printf/printf_core.c
81,53 → 81,54
static char nullstr[] = "(NULL)";
static char digits_small[] = "0123456789abcdef";
static char digits_big[] = "0123456789ABCDEF";
static char invalch = U_SPECIAL;
 
/** Print one or more UTF-8 characters without adding newline.
/** Print one or more characters without adding newline.
*
* @param buf Buffer holding UTF-8 characters with size of
* @param buf Buffer holding characters with size of
* at least size bytes. NULL is not allowed!
* @param size Size of the buffer in bytes.
* @param ps Output method and its data.
*
* @return Number of UTF-8 characters printed.
* @return Number of characters printed.
*
*/
static int printf_putnchars_utf8(const char *buf, size_t size,
static int printf_putnchars(const char *buf, size_t size,
printf_spec_t *ps)
{
return ps->write_utf8((void *) buf, size, ps->data);
return ps->str_write((void *) buf, size, ps->data);
}
 
/** Print one or more UTF-32 characters without adding newline.
/** Print one or more wide characters without adding newline.
*
* @param buf Buffer holding UTF-32 characters with size of
* @param buf Buffer holding wide characters with size of
* at least size bytes. NULL is not allowed!
* @param size Size of the buffer in bytes.
* @param ps Output method and its data.
*
* @return Number of UTF-32 characters printed.
* @return Number of wide characters printed.
*
*/
static int printf_putnchars_utf32(const wchar_t *buf, size_t size,
static int printf_wputnchars(const wchar_t *buf, size_t size,
printf_spec_t *ps)
{
return ps->write_utf32((void *) buf, size, ps->data);
return ps->wstr_write((void *) buf, size, ps->data);
}
 
/** Print UTF-8 string without adding a newline.
/** Print string without adding a newline.
*
* @param str UTF-8 string to print.
* @param str String to print.
* @param ps Write function specification and support data.
*
* @return Number of UTF-8 characters printed.
* @return Number of characters printed.
*
*/
static int printf_putstr(const char *str, printf_spec_t *ps)
{
if (str == NULL)
return printf_putnchars_utf8(nullstr, strlen(nullstr), ps);
return printf_putnchars(nullstr, str_size(nullstr), ps);
return ps->write_utf8((void *) str, strlen(str), ps->data);
return ps->str_write((void *) str, str_size(str), ps->data);
}
 
/** Print one ASCII character.
141,14 → 142,14
static int printf_putchar(const char ch, printf_spec_t *ps)
{
if (!ascii_check(ch))
return ps->write_utf8((void *) &invalch, 1, ps->data);
return ps->str_write((void *) &invalch, 1, ps->data);
return ps->write_utf8(&ch, 1, ps->data);
return ps->str_write(&ch, 1, ps->data);
}
 
/** Print one UTF-32 character.
/** Print one wide character.
*
* @param c UTF-32 character to be printed.
* @param c Wide character to be printed.
* @param ps Output method.
*
* @return Number of characters printed.
156,10 → 157,10
*/
static int printf_putwchar(const wchar_t ch, printf_spec_t *ps)
{
if (!unicode_check(ch))
return ps->write_utf8((void *) &invalch, 1, ps->data);
if (!chr_check(ch))
return ps->str_write((void *) &invalch, 1, ps->data);
return ps->write_utf32(&ch, sizeof(wchar_t), ps->data);
return ps->wstr_write(&ch, sizeof(wchar_t), ps->data);
}
 
/** Print one formatted ASCII character.
200,7 → 201,7
return (int) (counter + 1);
}
 
/** Print one formatted UTF-32 character.
/** Print one formatted wide character.
*
* @param ch Character to print.
* @param width Width modifier.
238,26 → 239,27
return (int) (counter + 1);
}
 
/** Print UTF-8 string.
/** Print string.
*
* @param str UTF-8 string to be printed.
* @param str String to be printed.
* @param width Width modifier.
* @param precision Precision modifier.
* @param flags Flags that modify the way the string is printed.
*
* @return Number of UTF-8 characters printed, negative value on failure.
* @return Number of characters printed, negative value on failure.
*/
static int print_utf8(char *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
static int print_str(char *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
{
if (str == NULL)
return printf_putstr(nullstr, ps);
/* Print leading spaces */
size_t size = str_length(str);
 
/* Print leading spaces. */
count_t strw = str_length(str);
if (precision == 0)
precision = size;
precision = strw;
 
/* Left padding */
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
267,13 → 269,15
}
}
 
/* Part of @a str fitting into the alloted space. */
int retval;
size_t bytes = str_lsize(str, min(size, precision));
if ((retval = printf_putnchars_utf8(str, bytes, ps)) < 0)
size_t size = str_lsize(str, precision);
if ((retval = printf_putnchars(str, size, ps)) < 0)
return -counter;
 
counter += retval;
 
/* Right padding */
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
280,28 → 284,33
}
 
return ((int) counter);
 
}
 
/** Print UTF-32 string.
/** Print wide string.
*
* @param str UTF-32 string to be printed.
* @param str Wide string to be printed.
* @param width Width modifier.
* @param precision Precision modifier.
* @param flags Flags that modify the way the string is printed.
*
* @return Number of UTF-32 characters printed, negative value on failure.
* @return Number of wide characters printed, negative value on failure.
*/
static int print_utf32(wchar_t *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
static int print_wstr(wchar_t *str, int width, unsigned int precision,
uint32_t flags, printf_spec_t *ps)
{
if (str == NULL)
return printf_putstr(nullstr, ps);
/* Print leading spaces */
size_t size = wstr_length(str);
if (*str == U_BOM)
str++;
/* Print leading spaces. */
size_t strw = wstr_length(str);
if (precision == 0)
precision = size;
precision = strw;
/* Left padding */
count_t counter = 0;
width -= precision;
if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
311,18 → 320,20
}
}
/* Part of @a wstr fitting into the alloted space. */
int retval;
size_t bytes = min(size, precision) * sizeof(wchar_t);
if ((retval = printf_putnchars_utf32(str, bytes, ps)) < 0)
size_t size = wstr_lsize(str, precision);
if ((retval = printf_wputnchars(str, size, ps)) < 0)
return -counter;
counter += retval;
/* Right padding */
while (width-- > 0) {
if (printf_putchar(' ', ps) == 1)
counter++;
}
 
return ((int) counter);
}
 
537,8 → 548,8
* - "h" Signed or unsigned short.@n
* - "" Signed or unsigned int (default value).@n
* - "l" Signed or unsigned long int.@n
* If conversion is "c", the character is wchar_t (UTF-32).@n
* If conversion is "s", the string is wchar_t * (UTF-32).@n
* If conversion is "c", the character is wchar_t (wide character).@n
* If conversion is "s", the string is wchar_t * (wide string).@n
* - "ll" Signed or unsigned long long int.@n
*
* CONVERSION:@n
546,15 → 557,12
*
* - c Print single character. The character is expected to be plain
* ASCII (e.g. only values 0 .. 127 are valid).@n
* If type is "l", then the character is expected to be UTF-32
* If type is "l", then the character is expected to be wide character
* (e.g. values 0 .. 0x10ffff are valid).
*
* - s Print zero terminated string. If a NULL value is passed as
* value, "(NULL)" is printed instead.@n
* The string is expected to be correctly encoded UTF-8 (or plain
* ASCII, which is a subset of UTF-8).@n
* If type is "l", then the string is expected to be correctly
* encoded UTF-32.
* If type is "l", then the string is expected to be wide string.
*
* - P, p Print value of a pointer. Void * value is expected and it is
* printed in hexadecimal notation with prefix (as with \%#X / \%#x
574,35 → 582,35
* - X, x Print hexadecimal number with upper- or lower-case. Prefix is
* not printed by default.
*
* All other characters from fmt except the formatting directives are printed in
* All other characters from fmt except the formatting directives are printed
* verbatim.
*
* @param fmt Formatting NULL terminated string (UTF-8 or plain ASCII).
* @param fmt Format NULL-terminated string.
*
* @return Number of UTF-8 characters printed, negative value on failure.
* @return Number of characters printed, negative value on failure.
*
*/
int printf_core(const char *fmt, printf_spec_t *ps, va_list ap)
{
index_t i = 0; /* Index of the currently processed character from fmt */
index_t nxt = 0;
index_t j = 0; /* Index to the first not printed nonformating character */
size_t i; /* Index of the currently processed character from fmt */
size_t nxt = 0; /* Index of the next character from fmt */
size_t j = 0; /* Index to the first not printed nonformating character */
wchar_t uc; /* Current UTF-32 character decoded from fmt */
count_t counter = 0; /* Number of UTF-8 characters printed */
count_t counter = 0; /* Number of characters printed */
int retval; /* Return values from nested functions */
while (true) {
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
 
if (uc == '\0') break;
 
wchar_t uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 0)
break;
/* Control character */
if (uc == '%') {
/* Print common characters if any processed */
if (i > j) {
if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
/* Error */
counter = -counter;
goto out;
618,7 → 626,7
do {
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
switch (uc) {
case '#':
flags |= __PRINTF_FLAG_PREFIX;
646,10 → 654,10
while (true) {
width *= 10;
width += uc - '0';
 
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
if (uc == '\0')
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 0)
break;
if (!isdigit(uc))
break;
657,7 → 665,7
} else if (uc == '*') {
/* Get width value from argument list */
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
width = (int) va_arg(ap, int);
if (width < 0) {
/* Negative width sets '-' flag */
670,15 → 678,15
int precision = 0;
if (uc == '.') {
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (isdigit(uc)) {
while (true) {
precision *= 10;
precision += uc - '0';
 
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
if (uc == '\0')
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 0)
break;
if (!isdigit(uc))
break;
686,7 → 694,7
} else if (uc == '*') {
/* Get precision value from the argument list */
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
precision = (int) va_arg(ap, int);
if (precision < 0) {
/* Ignore negative precision */
705,10 → 713,10
/* Char or short */
qualifier = PrintfQualifierShort;
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 'h') {
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
qualifier = PrintfQualifierByte;
}
break;
716,10 → 724,10
/* Long or long long */
qualifier = PrintfQualifierLong;
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
if (uc == 'l') {
i = nxt;
uc = chr_decode(fmt, &nxt, UTF8_NO_LIMIT);
uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
qualifier = PrintfQualifierLongLong;
}
break;
736,9 → 744,9
*/
case 's':
if (qualifier == PrintfQualifierLong)
retval = print_utf32(va_arg(ap, wchar_t *), width, precision, flags, ps);
retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps);
else
retval = print_utf8(va_arg(ap, char *), width, precision, flags, ps);
retval = print_str(va_arg(ap, char *), width, precision, flags, ps);
if (retval < 0) {
counter = -counter;
871,7 → 879,7
}
if (i > j) {
if ((retval = printf_putnchars_utf8(&fmt[j], i - j, ps)) < 0) {
if ((retval = printf_putnchars(&fmt[j], i - j, ps)) < 0) {
/* Error */
counter = -counter;
goto out;