summaryrefslogtreecommitdiff
path: root/src/upb_stdio.c
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2011-02-13 12:59:54 -0800
committerJoshua Haberman <joshua@reverberate.org>2011-02-13 12:59:54 -0800
commit6bdbb45e88e7b88b294dfb6e4cb493cbc3c8cf74 (patch)
tree0e00246fb124ebdf6a2210c816704c1d840e2138 /src/upb_stdio.c
parentee84a7da167d2211066c4a663d41febdf9544438 (diff)
Merged core/ and stream/ -> src/. The split wasn't worth it.
Diffstat (limited to 'src/upb_stdio.c')
-rw-r--r--src/upb_stdio.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/upb_stdio.c b/src/upb_stdio.c
new file mode 100644
index 0000000..8857677
--- /dev/null
+++ b/src/upb_stdio.c
@@ -0,0 +1,104 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2010 Joshua Haberman. See LICENSE for details.
+ */
+
+#include "upb_stdio.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include "upb_string.h"
+
+// We can make this configurable if necessary.
+#define BLOCK_SIZE 4096
+
+struct upb_stdio {
+ upb_bytesrc bytesrc;
+ upb_bytesink bytesink;
+ FILE *file;
+};
+
+void upb_stdio_reset(upb_stdio *stdio, FILE* file) {
+ stdio->file = file;
+}
+
+
+/* upb_bytesrc methods ********************************************************/
+
+static upb_strlen_t upb_stdio_read(upb_bytesrc *src, void *buf,
+ upb_strlen_t count, upb_status *status) {
+ upb_stdio *stdio = (upb_stdio*)src;
+ assert(count > 0);
+ size_t read = fread(buf, 1, count, stdio->file);
+ if(read < (size_t)count) {
+ // Error or EOF.
+ if(feof(stdio->file)) {
+ upb_seterr(status, UPB_EOF, "");
+ return read;
+ } else if(ferror(stdio->file)) {
+ upb_seterr(status, UPB_ERROR, "Error reading from stdio stream.");
+ return -1;
+ }
+ }
+ return read;
+}
+
+static bool upb_stdio_getstr(upb_bytesrc *src, upb_string *str,
+ upb_status *status) {
+ upb_strlen_t read = upb_stdio_read(
+ src, upb_string_getrwbuf(str, BLOCK_SIZE), BLOCK_SIZE, status);
+ if (read <= 0) return false;
+ upb_string_getrwbuf(str, read);
+ return true;
+}
+
+
+/* upb_bytesink methods *******************************************************/
+
+upb_strlen_t upb_stdio_putstr(upb_bytesink *sink, upb_string *str, upb_status *status) {
+ upb_stdio *stdio = (upb_stdio*)((char*)sink - offsetof(upb_stdio, bytesink));
+ upb_strlen_t len = upb_string_len(str);
+ upb_strlen_t written = fwrite(upb_string_getrobuf(str), 1, len, stdio->file);
+ if(written < len) {
+ upb_seterr(status, UPB_ERROR, "Error writing to stdio stream.");
+ return -1;
+ }
+ return written;
+}
+
+upb_strlen_t upb_stdio_vprintf(upb_bytesink *sink, upb_status *status,
+ const char *fmt, va_list args) {
+ upb_stdio *stdio = (upb_stdio*)((char*)sink - offsetof(upb_stdio, bytesink));
+ upb_strlen_t written = vfprintf(stdio->file, fmt, args);
+ if (written < 0) {
+ upb_seterr(status, UPB_ERROR, "Error writing to stdio stream.");
+ return -1;
+ }
+ return written;
+}
+
+upb_stdio *upb_stdio_new() {
+ static upb_bytesrc_vtbl bytesrc_vtbl = {
+ upb_stdio_read,
+ upb_stdio_getstr,
+ };
+
+ static upb_bytesink_vtbl bytesink_vtbl = {
+ NULL,
+ upb_stdio_putstr,
+ upb_stdio_vprintf
+ };
+
+ upb_stdio *stdio = malloc(sizeof(*stdio));
+ upb_bytesrc_init(&stdio->bytesrc, &bytesrc_vtbl);
+ upb_bytesink_init(&stdio->bytesink, &bytesink_vtbl);
+ return stdio;
+}
+
+void upb_stdio_free(upb_stdio *stdio) {
+ free(stdio);
+}
+
+upb_bytesrc* upb_stdio_bytesrc(upb_stdio *stdio) { return &stdio->bytesrc; }
+upb_bytesink* upb_stdio_bytesink(upb_stdio *stdio) { return &stdio->bytesink; }
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback