From 6a1f3a66939308668ab8dce0d195afec16e02af9 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 14 Jul 2011 23:15:00 -0700 Subject: Major refactoring: upb_string is gone in favor of upb_strref. --- src/upb_stdio.h | 54 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'src/upb_stdio.h') diff --git a/src/upb_stdio.h b/src/upb_stdio.h index a164821..858830c 100644 --- a/src/upb_stdio.h +++ b/src/upb_stdio.h @@ -5,7 +5,12 @@ * Author: Josh Haberman * * This file provides upb_bytesrc and upb_bytesink implementations for - * ANSI C stdio. + * ANSI C stdio, which is less efficient than posixfd, but more portable. + * + * Specifically, stdio functions acquire locks on every operation (unless you + * use the f{read,write,...}_unlocked variants, which are not standard) and + * performs redundant buffering (unless you disable it with setvbuf(), but we + * can only do this on newly-opened filehandles). */ #include @@ -18,21 +23,44 @@ extern "C" { #endif -struct upb_stdio; -typedef struct upb_stdio upb_stdio; +typedef struct { + uint64_t ofs; + uint32_t refcount; + char data[]; +} upb_stdio_buf; + +// We use a single object for both bytesrc and bytesink for simplicity. +// The object is still not thread-safe, and may only be used by one reader +// and one writer at a time. +typedef struct { + upb_bytesrc src; + upb_bytesink sink; + FILE *file; + bool should_close; + upb_stdio_buf **bufs; + uint32_t nbuf, szbuf; +} upb_stdio; + +void upb_stdio_init(upb_stdio *stdio); +// Caller should call upb_stdio_flush prior to calling this to ensure that +// all data is flushed, otherwise data can be silently dropped if an error +// occurs flushing the remaining buffers. +void upb_stdio_uninit(upb_stdio *stdio); + +// Resets the object to read/write to the given "file." The caller is +// responsible for closing the file, which must outlive this object. +void upb_stdio_reset(upb_stdio *stdio, FILE *file); -// Creation/deletion. -upb_stdio *upb_stdio_new(); -void upb_stdio_free(upb_stdio *stdio); +// As an alternative to upb_stdio_reset(), initializes the object by opening a +// file, and will handle closing it. This may result in more efficient I/O +// than the previous since we can call setvbuf() to disable buffering. +void upb_stdio_open(upb_stdio *stdio, const char *filename, const char *mode, + upb_status *s); -// Reset/initialize the object for use. The src or sink will call -// fread()/fwrite()/etc. on the given FILE*. -void upb_stdio_reset(upb_stdio *stdio, FILE* file); +// Must be called to cleanup after the object, including closing the file if +// it was opened with upb_stdio_open() (which can fail, hence the status). +// -// Gets a bytesrc or bytesink for the given stdio. The returned pointer is -// invalidated by upb_stdio_reset above. It is perfectly valid to get both -// a bytesrc and a bytesink for the same stdio if the FILE* is open for reading -// and writing. upb_bytesrc *upb_stdio_bytesrc(upb_stdio *stdio); upb_bytesink *upb_stdio_bytesink(upb_stdio *stdio); -- cgit v1.2.3