LibC: Implement {,v}asprintf
These were added in POSIX issue 8
This commit is contained in:
parent
a9f58e96d2
commit
ff289b25b6
|
@ -56,6 +56,7 @@ extern FILE* __stderr;
|
|||
extern FILE* __stddbg;
|
||||
#define stddbg __stddbg
|
||||
|
||||
int asprintf(char** __restrict ptr, const char* __restrict format, ...);
|
||||
void clearerr(FILE* stream);
|
||||
char* ctermid(char* s);
|
||||
int dprintf(int fildes, const char* __restrict format, ...);
|
||||
|
@ -116,6 +117,7 @@ char* tempnam(const char* dir, const char* pfx);
|
|||
FILE* tmpfile(void);
|
||||
char* tmpnam(char* s);
|
||||
int ungetc(int c, FILE* stream);
|
||||
int vasprintf(char** __restrict ptr, const char* __restrict format, va_list ap);
|
||||
int vdprintf(int fildes, const char* __restrict format, va_list ap);
|
||||
int vfprintf(FILE* __restrict stream, const char* __restrict format, va_list ap);
|
||||
int vfscanf(FILE* __restrict stream, const char* __restrict format, va_list arg);
|
||||
|
|
|
@ -120,6 +120,15 @@ static void _init_stdio()
|
|||
s_files[STDDBG_FILENO].buffer_type = _IOLBF;
|
||||
}
|
||||
|
||||
int asprintf(char** __restrict ptr, const char* __restrict format, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
int ret = vasprintf(ptr, format, arguments);
|
||||
va_end(arguments);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void clearerr(FILE* file)
|
||||
{
|
||||
ScopeLock _(file);
|
||||
|
@ -1023,6 +1032,62 @@ int ungetc(int c, FILE* stream)
|
|||
return ungetc_unlocked(c, stream);
|
||||
}
|
||||
|
||||
|
||||
int vasprintf(char** __restrict ptr, const char* __restrict format, va_list ap)
|
||||
{
|
||||
struct print_info
|
||||
{
|
||||
char* buffer;
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
};
|
||||
print_info info {
|
||||
.buffer = nullptr,
|
||||
.capacity = 0,
|
||||
.length = 0,
|
||||
};
|
||||
|
||||
info.buffer = static_cast<char*>(malloc(16));
|
||||
if (info.buffer == nullptr)
|
||||
return -1;
|
||||
info.capacity = 16;
|
||||
|
||||
const int ret = printf_impl(format, ap,
|
||||
[](int c, void* _info) -> int
|
||||
{
|
||||
auto& info = *static_cast<print_info*>(_info);
|
||||
|
||||
if (info.length + 1 >= info.capacity)
|
||||
{
|
||||
const size_t new_capacity = info.capacity * 2;
|
||||
void* new_buffer = realloc(info.buffer, new_capacity);
|
||||
if (new_buffer == nullptr)
|
||||
{
|
||||
free(info.buffer);
|
||||
info.buffer = nullptr;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
info.buffer = static_cast<char*>(new_buffer);
|
||||
info.capacity = new_capacity;
|
||||
}
|
||||
|
||||
info.buffer[info.length++] = c;
|
||||
return 0;
|
||||
}, &info
|
||||
);
|
||||
|
||||
if (info.buffer == nullptr)
|
||||
return -1;
|
||||
|
||||
ASSERT(info.length < info.capacity);
|
||||
info.buffer[info.length] = '\0';
|
||||
|
||||
*ptr = info.buffer;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vdprintf(int fildes, const char* __restrict format, va_list arguments)
|
||||
{
|
||||
struct print_info
|
||||
|
|
Loading…
Reference in New Issue