Add cbprintf(3) and vcbprintf(3).
Thanks to Owen Shepherd of the Public Domain C Library for helping design and formalize these interfaces.
This commit is contained in:
parent
2dffa408ad
commit
ec7e0cc9a6
|
@ -153,7 +153,7 @@ void Print(const char* format, ...)
|
|||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vprintf_callback(PrintCallback, NULL, format, ap);
|
||||
vcbprintf(NULL, PrintCallback, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Sortix {
|
||||
|
@ -95,15 +96,20 @@ inline size_t PrintF(const char* format, ...)
|
|||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
size_t result = vprintf_callback(device_callback, device_pointer, format, list);
|
||||
int result = vcbprintf(device_pointer, device_callback, format, list);
|
||||
va_end(list);
|
||||
return result;
|
||||
if ( result < 0 )
|
||||
return SIZE_MAX;
|
||||
return (size_t) result;
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 1, 0)))
|
||||
inline size_t PrintFV(const char* format, va_list list)
|
||||
{
|
||||
return vprintf_callback(device_callback, device_pointer, format, list);
|
||||
int result = vcbprintf(device_pointer, device_callback, format, list);
|
||||
if ( result < 0 )
|
||||
return SIZE_MAX;
|
||||
return (size_t) result;
|
||||
}
|
||||
|
||||
} // namespace Log
|
||||
|
|
|
@ -67,6 +67,7 @@ signal/sigorset.o \
|
|||
stdio/asprintf.o \
|
||||
stdio/clearerr.o \
|
||||
stdio/clearerr_unlocked.o \
|
||||
stdio/cbprintf.o \
|
||||
stdio/dprintf.o \
|
||||
stdio/fbufsize.o \
|
||||
stdio/fbufsize_unlocked.o \
|
||||
|
@ -142,11 +143,11 @@ stdio/sscanf.o \
|
|||
stdio/ungetc.o \
|
||||
stdio/ungetc_unlocked.o \
|
||||
stdio/vasprintf.o \
|
||||
stdio/vcbprintf.o \
|
||||
stdio/vdprintf.o \
|
||||
stdio/vfprintf_unlocked.o \
|
||||
stdio/vfscanf.o \
|
||||
stdio/vfscanf_unlocked.o \
|
||||
stdio/vprintf_callback.o \
|
||||
stdio/vscanf_callback.o \
|
||||
stdio/vsnprintf.o \
|
||||
stdio/vsprintf.o \
|
||||
|
|
|
@ -320,12 +320,11 @@ void fpurge_unlocked(FILE* fp);
|
|||
size_t fpending_unlocked(FILE* fp);
|
||||
#endif
|
||||
|
||||
/* The Sortix backends for *printf and *scanf. */
|
||||
/* The backends for printf and scanf. */
|
||||
#if __USE_SORTIX
|
||||
size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
||||
void* user,
|
||||
const char* __restrict format,
|
||||
__gnuc_va_list ap)
|
||||
int cbprintf(void*, size_t (*)(void*, const char*, size_t), const char*, ...)
|
||||
__attribute__((__format__ (printf, 3, 4)));
|
||||
int vcbprintf(void*, size_t (*)(void*, const char*, size_t), const char*, __gnuc_va_list ap)
|
||||
__attribute__((__format__ (printf, 3, 0)));
|
||||
int vscanf_callback(void* fp,
|
||||
int (*fgetc)(void*),
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2014.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
stdio/cbprintf.cpp
|
||||
Formats text and outputs it via callback functions.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C"
|
||||
int cbprintf(void* user,
|
||||
size_t (*callback)(void*, const char*, size_t),
|
||||
const char* format,
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int result = vcbprintf(user, callback, format, ap);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
|
@ -72,9 +72,9 @@ int vasprintf(char** restrict result_ptr,
|
|||
state.string_used = 0;
|
||||
if ( !(state.string = (char*) malloc(state.string_length * sizeof(char))) )
|
||||
return *result_ptr = NULL, -1;
|
||||
vprintf_callback(vasprintf_callback, &state, format, list);
|
||||
int result = vcbprintf(&state, vasprintf_callback, format, list);
|
||||
if ( !state.string )
|
||||
return *result_ptr = NULL, -1;
|
||||
state.string[state.string_used] = '\0';
|
||||
return *result_ptr = state.string, (int) state.string_used;
|
||||
return *result_ptr = state.string, result;
|
||||
}
|
||||
|
|
|
@ -17,15 +17,13 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
stdio/vprintf_callback.cpp
|
||||
Provides printf formatting functions that uses callbacks.
|
||||
stdio/vcbprintf.cpp
|
||||
Formats text and outputs it via callback functions.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
// Number of bugs seemingly unrelated bugs that have been traced to here:
|
||||
// Countless + 2
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
@ -51,19 +49,19 @@ static size_t noop_callback(void*, const char*, size_t amount)
|
|||
return amount;
|
||||
}
|
||||
|
||||
static
|
||||
size_t callback_character(size_t (*callback)(void*, const char*, size_t),
|
||||
void* user,
|
||||
static inline
|
||||
size_t callback_character(void* user,
|
||||
size_t (*callback)(void*, const char*, size_t),
|
||||
char c)
|
||||
{
|
||||
return callback(user, &c, 1);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
||||
void* user,
|
||||
const char* restrict format,
|
||||
va_list parameters)
|
||||
int vcbprintf(void* user,
|
||||
size_t (*callback)(void*, const char*, size_t),
|
||||
const char* format,
|
||||
va_list parameters)
|
||||
{
|
||||
if ( !callback )
|
||||
callback = noop_callback;
|
||||
|
@ -80,7 +78,7 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
|||
while ( format[amount] && format[amount] != '%' )
|
||||
amount++;
|
||||
if ( callback(user, format, amount) != amount )
|
||||
return SIZE_MAX;
|
||||
return -1;
|
||||
format += amount;
|
||||
written += amount;
|
||||
continue;
|
||||
|
@ -311,32 +309,32 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
|||
|
||||
if ( use_left_pad )
|
||||
for ( size_t i = length_with_precision; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, ' ') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, ' ') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
if ( callback(user, prefix, prefix_length) != prefix_length )
|
||||
return SIZE_MAX;
|
||||
return -1;
|
||||
written += prefix_length;
|
||||
if ( use_zero_pad )
|
||||
for ( size_t i = normal_length; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, '0') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, '0') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
if ( use_precision )
|
||||
for ( size_t i = digits_length; i < precision; i++ )
|
||||
if ( callback_character(callback, user, '0') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, '0') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
if ( callback(user, output, output_length) != output_length )
|
||||
return SIZE_MAX;
|
||||
return -1;
|
||||
written += output_length;
|
||||
if ( use_right_pad )
|
||||
for ( size_t i = length_with_precision; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, ' ') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, ' ') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
}
|
||||
|
@ -379,19 +377,19 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
|||
|
||||
if ( !field_width_is_negative && 1 < abs_field_width )
|
||||
for ( size_t i = 1; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, ' ') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, ' ') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
|
||||
if ( callback(user, &c, 1) != 1 )
|
||||
return SIZE_MAX;
|
||||
return -1;
|
||||
written++;
|
||||
|
||||
if ( field_width_is_negative && 1 < abs_field_width )
|
||||
for ( size_t i = 1; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, ' ') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, ' ') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
}
|
||||
|
@ -422,19 +420,19 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
|||
|
||||
if ( !field_width_is_negative && string_length < abs_field_width )
|
||||
for ( size_t i = string_length; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, ' ') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, ' ') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
|
||||
if ( callback(user, string, string_length) != string_length )
|
||||
return SIZE_MAX;
|
||||
return -1;
|
||||
written += string_length;
|
||||
|
||||
if ( field_width_is_negative && string_length < abs_field_width )
|
||||
for ( size_t i = string_length; i < abs_field_width; i++ )
|
||||
if ( callback_character(callback, user, ' ') != 1 )
|
||||
return SIZE_MAX;
|
||||
if ( callback_character(user, callback, ' ') != 1 )
|
||||
return -1;
|
||||
else
|
||||
written++;
|
||||
|
||||
|
@ -464,5 +462,8 @@ size_t vprintf_callback(size_t (*callback)(void*, const char*, size_t),
|
|||
goto incomprehensible_conversion;
|
||||
}
|
||||
|
||||
if ( INT_MAX < written )
|
||||
return INT_MAX;
|
||||
|
||||
return written;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
|
@ -30,10 +30,10 @@
|
|||
|
||||
static size_t write_callback(void* user, const char* string, size_t stringlen)
|
||||
{
|
||||
return writeall((int) (uintptr_t) user, string, stringlen * sizeof(char));
|
||||
return writeall((int) (uintptr_t) user, string, stringlen);
|
||||
}
|
||||
|
||||
extern "C" int vdprintf(int fd, const char* restrict format, va_list list)
|
||||
{
|
||||
return vprintf_callback(write_callback, (void*) (uintptr_t) fd, format, list);
|
||||
return vcbprintf((void*) (uintptr_t) fd, write_callback, format, list);
|
||||
}
|
||||
|
|
|
@ -38,8 +38,5 @@ int vfprintf_unlocked(FILE* fp, const char* restrict format, va_list list)
|
|||
if ( !(fp->flags & _FILE_WRITABLE) )
|
||||
return errno = EBADF, fp->flags |= _FILE_STATUS_ERROR, EOF;
|
||||
|
||||
size_t result = vprintf_callback(FileWriteCallback, fp, format, list);
|
||||
if ( result == SIZE_MAX )
|
||||
return -1;
|
||||
return (int) result;
|
||||
return vcbprintf(fp, FileWriteCallback, format, list);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
|
@ -58,8 +58,8 @@ int vsnprintf(char* restrict str, size_t size, const char* restrict format,
|
|||
info.size = size ? size-1 : 0;
|
||||
info.produced = 0;
|
||||
info.written = 0;
|
||||
vprintf_callback(StringPrintCallback, &info, format, list);
|
||||
int result = vcbprintf(&info, StringPrintCallback, format, list);
|
||||
if ( size )
|
||||
info.str[info.written] = '\0';
|
||||
return (int) info.produced;
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue