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:
Meep-Eep
2007-02-01 21:45:12 +00:00
parent 433aadf8a9
commit 860b023230
4 changed files with 145 additions and 0 deletions
+42
View File
@@ -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);
+4
View File
@@ -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);
+95
View File
@@ -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;
}
+4
View File
@@ -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 */