summaryrefslogtreecommitdiff
path: root/src/upb_bytestream.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/upb_bytestream.h')
-rw-r--r--src/upb_bytestream.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/upb_bytestream.h b/src/upb_bytestream.h
new file mode 100644
index 0000000..e4b51fd
--- /dev/null
+++ b/src/upb_bytestream.h
@@ -0,0 +1,123 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2010-2011 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * Defines the interfaces upb_bytesrc and upb_bytesink, which are abstractions
+ * of read()/write() with useful buffering/sharing semantics.
+ */
+
+#ifndef UPB_BYTESTREAM_H
+#define UPB_BYTESTREAM_H
+
+#include <stdarg.h>
+#include "upb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* upb_bytesrc ****************************************************************/
+
+// upb_bytesrc is a pull interface for streams of bytes, basically an
+// abstraction of read()/fread(), but it avoids copies where possible.
+
+typedef upb_strlen_t (*upb_bytesrc_read_fptr)(
+ upb_bytesrc *src, void *buf, upb_strlen_t count, upb_status *status);
+typedef bool (*upb_bytesrc_getstr_fptr)(
+ upb_bytesrc *src, upb_string *str, upb_status *status);
+
+typedef struct {
+ upb_bytesrc_read_fptr read;
+ upb_bytesrc_getstr_fptr getstr;
+} upb_bytesrc_vtbl;
+
+struct _upb_bytesrc {
+ upb_bytesrc_vtbl *vtbl;
+};
+
+INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtbl *vtbl) {
+ s->vtbl = vtbl;
+}
+
+// Reads up to "count" bytes into "buf", returning the total number of bytes
+// read. If 0, indicates error and puts details in "status".
+INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf,
+ upb_strlen_t count, upb_status *status) {
+ return src->vtbl->read(src, buf, count, status);
+}
+
+// Like upb_bytesrc_read(), but modifies "str" in-place. Caller must ensure
+// that "str" is created or just recycled. Returns "false" if no data was
+// returned, either due to error or EOF (check status for details).
+//
+// In comparison to upb_bytesrc_read(), this call can possibly alias existing
+// string data (which avoids a copy). On the other hand, if the data was *not*
+// already in an existing string, this copies it into a upb_string, and if the
+// data needs to be put in a specific range of memory (because eg. you need to
+// put it into a different kind of string object) then upb_bytesrc_get() could
+// save you a copy.
+INLINE bool upb_bytesrc_getstr(upb_bytesrc *src, upb_string *str,
+ upb_status *status) {
+ return src->vtbl->getstr(src, str, status);
+}
+
+
+/* upb_bytesink ***************************************************************/
+
+struct _upb_bytesink;
+typedef struct _upb_bytesink upb_bytesink;
+typedef upb_strlen_t (*upb_bytesink_putstr_fptr)(
+ upb_bytesink *bytesink, upb_string *str, upb_status *status);
+typedef upb_strlen_t (*upb_bytesink_vprintf_fptr)(
+ upb_bytesink *bytesink, upb_status *status, const char *fmt, va_list args);
+
+typedef struct {
+ upb_bytesink_putstr_fptr putstr;
+ upb_bytesink_vprintf_fptr vprintf;
+} upb_bytesink_vtbl;
+
+struct _upb_bytesink {
+ upb_bytesink_vtbl *vtbl;
+};
+
+INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtbl *vtbl) {
+ s->vtbl = vtbl;
+}
+
+
+// TODO: Figure out how buffering should be handled. Should the caller buffer
+// data and only call these functions when a buffer is full? Seems most
+// efficient, but then buffering has to be configured in the caller, which
+// could be anything, which makes it hard to have a standard interface for
+// controlling buffering.
+//
+// The downside of having the bytesink buffer is efficiency: the caller is
+// making more (virtual) function calls, and the caller can't arrange to have
+// a big contiguous buffer. The bytesink can do this, but will have to copy
+// to make the data contiguous.
+
+// Returns the number of bytes written.
+INLINE upb_strlen_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status,
+ const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ upb_strlen_t ret = sink->vtbl->vprintf(sink, status, fmt, args);
+ va_end(args);
+ return ret;
+}
+
+// Puts the given string, returning true if the operation was successful, otherwise
+// check "status" for details. Ownership of the string is *not* passed; if
+// the callee wants a reference he must call upb_string_getref() on it.
+INLINE upb_strlen_t upb_bytesink_putstr(upb_bytesink *sink, upb_string *str,
+ upb_status *status) {
+ return sink->vtbl->putstr(sink, str, status);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback