Added uio_fprintf() and uio_vfprintf().
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2690 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -24,8 +24,10 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "uioutils.h"
|
#include "uioutils.h"
|
||||||
|
#include "utils.h"
|
||||||
#ifdef uio_MEM_DEBUG
|
#ifdef uio_MEM_DEBUG
|
||||||
# include "memdebug.h"
|
# include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -267,6 +269,46 @@ uio_ungetc(int c, uio_Stream *stream) {
|
|||||||
// return c;
|
// return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB. POSIX allows errno to be set for vsprintf(), but does not require it:
|
||||||
|
// "The value of errno may be set to nonzero by a library function call
|
||||||
|
// whether or not there is an error, provided the use of errno is not
|
||||||
|
// documented in the description of the function in this International
|
||||||
|
// Standard." The latter is the case for vsprintf().
|
||||||
|
int
|
||||||
|
uio_vfprintf(uio_Stream *stream, const char *format, va_list args) {
|
||||||
|
// This could be done faster, but going through snprintf() is easiest,
|
||||||
|
// and is fast enough for now.
|
||||||
|
char *buf;
|
||||||
|
int putResult;
|
||||||
|
int savedErrno;
|
||||||
|
|
||||||
|
buf = uio_vasprintf(format, args);
|
||||||
|
if (buf == NULL) {
|
||||||
|
// errno may or may not be set
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
putResult = uio_fputs(buf, stream);
|
||||||
|
savedErrno = errno;
|
||||||
|
|
||||||
|
uio_free(buf);
|
||||||
|
|
||||||
|
errno = savedErrno;
|
||||||
|
return putResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uio_fprintf(uio_Stream *stream, const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
result = uio_vfprintf(stream, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
uio_fputc(int c, uio_Stream *stream) {
|
uio_fputc(int c, uio_Stream *stream) {
|
||||||
assert((stream->openFlags & O_ACCMODE) != O_RDONLY);
|
assert((stream->openFlags & O_ACCMODE) != O_RDONLY);
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ typedef struct uio_Stream uio_Stream;
|
|||||||
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
uio_Stream *uio_fopen(uio_DirHandle *dir, const char *path, const char *mode);
|
uio_Stream *uio_fopen(uio_DirHandle *dir, const char *path, const char *mode);
|
||||||
int uio_fclose(uio_Stream *stream);
|
int uio_fclose(uio_Stream *stream);
|
||||||
@@ -34,6 +36,8 @@ char *uio_fgets(char *buf, int size, uio_Stream *stream);
|
|||||||
int uio_fgetc(uio_Stream *stream);
|
int uio_fgetc(uio_Stream *stream);
|
||||||
#define uio_getc uio_fgetc
|
#define uio_getc uio_fgetc
|
||||||
int uio_ungetc(int c, uio_Stream *stream);
|
int uio_ungetc(int c, uio_Stream *stream);
|
||||||
|
int uio_vfprintf(uio_Stream *stream, const char *format, va_list args);
|
||||||
|
int uio_fprintf(uio_Stream *stream, const char *format, ...);
|
||||||
int uio_fputc(int c, uio_Stream *stream);
|
int uio_fputc(int c, uio_Stream *stream);
|
||||||
#define uio_putc uio_fputc
|
#define uio_putc uio_fputc
|
||||||
int uio_fputs(const char *s, uio_Stream *stream);
|
int uio_fputs(const char *s, uio_Stream *stream);
|
||||||
|
|||||||
@@ -364,3 +364,98 @@ uio_StdioAccessHandle_free(uio_StdioAccessHandle *handle) {
|
|||||||
uio_free(handle);
|
uio_free(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The result should be freed using uio_free().
|
||||||
|
// NB. POSIX allows errno to be set for vsprintf(), but does not require it:
|
||||||
|
// "The value of errno may be set to nonzero by a library function call
|
||||||
|
// whether or not there is an error, provided the use of errno is not
|
||||||
|
// documented in the description of the function in this International
|
||||||
|
// Standard." The latter is the case for vsprintf().
|
||||||
|
char *
|
||||||
|
uio_vasprintf(const char *format, va_list args) {
|
||||||
|
// TODO: If there is a system vasprintf, use that.
|
||||||
|
// XXX: That would mean that the allocation would always go through
|
||||||
|
// malloc() or so, instead of uio_malloc(), which may not be
|
||||||
|
// desirable.
|
||||||
|
|
||||||
|
char *buf;
|
||||||
|
size_t bufSize = 128;
|
||||||
|
// Start with enough for one screen line, and a power of 2,
|
||||||
|
// which might give faster result with allocations.
|
||||||
|
|
||||||
|
buf = uio_malloc(bufSize);
|
||||||
|
if (buf == NULL) {
|
||||||
|
// errno is set.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int printResult = vsnprintf(buf, bufSize, format, args);
|
||||||
|
if (printResult < 0) {
|
||||||
|
// This means the buffer was not small enough, but vsnprintf()
|
||||||
|
// does not give us any clue on how large it should be.
|
||||||
|
// Note that this does not happen with a C'99 compliant
|
||||||
|
// vsnprintf(), but it will happen on MS Windows, and on
|
||||||
|
// glibc before version 2.1.
|
||||||
|
bufSize *= 2;
|
||||||
|
} else if ((unsigned int) printResult >= bufSize) {
|
||||||
|
// The buffer was too small, but printResult contains the size
|
||||||
|
// that the buffer needs to be (excluding the '\0' character).
|
||||||
|
bufSize = printResult + 1;
|
||||||
|
} else {
|
||||||
|
// Success.
|
||||||
|
if ((unsigned int) printResult + 1 != bufSize) {
|
||||||
|
// Shorten the resulting buffer to the size that was
|
||||||
|
// actually needed.
|
||||||
|
char *newBuf = uio_realloc(buf, printResult + 1);
|
||||||
|
if (newBuf == NULL) {
|
||||||
|
// We could have returned the (overly large) original
|
||||||
|
// buffer, but the unused memory might not be
|
||||||
|
// acceptable, and the program would be likely to run
|
||||||
|
// into problems sooner or later anyhow.
|
||||||
|
int savedErrno = errno;
|
||||||
|
uio_free(buf);
|
||||||
|
errno = savedErrno;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return newBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char *newBuf = uio_realloc(buf, bufSize);
|
||||||
|
if (newBuf == NULL)
|
||||||
|
{
|
||||||
|
int savedErrno = errno;
|
||||||
|
uio_free(buf);
|
||||||
|
errno = savedErrno;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = newBuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// As uio_vasprintf(), but with an argument list.
|
||||||
|
char *
|
||||||
|
uio_asprintf(const char *format, ...) {
|
||||||
|
// TODO: If there is a system asprintf, use that.
|
||||||
|
// XXX: That would mean that the allocation would always go through
|
||||||
|
// malloc() or so, instead of uio_malloc(), which may not be
|
||||||
|
// desirable.
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
char *result;
|
||||||
|
int savedErrno;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
result = uio_vasprintf(format, args);
|
||||||
|
savedErrno = errno;
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
errno = savedErrno;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#ifndef _UTILS_H
|
#ifndef _UTILS_H
|
||||||
#define _UTILS_H
|
#define _UTILS_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#ifdef uio_INTERNAL
|
#ifdef uio_INTERNAL
|
||||||
typedef struct uio_StdioAccessHandle uio_StdioAccessHandle;
|
typedef struct uio_StdioAccessHandle uio_StdioAccessHandle;
|
||||||
#else
|
#else
|
||||||
@@ -34,6 +36,8 @@ uio_StdioAccessHandle *uio_getStdioAccess(uio_DirHandle *dir,
|
|||||||
const char *uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle);
|
const char *uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle);
|
||||||
void uio_releaseStdioAccess(uio_StdioAccessHandle *handle);
|
void uio_releaseStdioAccess(uio_StdioAccessHandle *handle);
|
||||||
|
|
||||||
|
char *uio_vasprintf(const char *format, va_list args);
|
||||||
|
char *uio_asprintf(const char *format, ...);
|
||||||
|
|
||||||
#endif /* _UTILS_H */
|
#endif /* _UTILS_H */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user