summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2010-06-09 20:28:44 -0700
committerJoshua Haberman <joshua@reverberate.org>2010-06-09 20:28:44 -0700
commit5743636ad19eafb11eddeefd29f2803052dadff2 (patch)
tree773a9d0254d8b27f2750ef2bc9ca8803e97082d0 /src
parent992a03be55faf83d794b9ec5e8c4ca7e78c08a9b (diff)
Decoder compiler but doesn't work yet.
Diffstat (limited to 'src')
-rw-r--r--src/upb.c8
-rw-r--r--src/upb.h21
-rw-r--r--src/upb_decoder.c172
-rw-r--r--src/upb_srcsink.h83
-rw-r--r--src/upb_srcsink_vtbl.h93
-rw-r--r--src/upb_string.h5
6 files changed, 235 insertions, 147 deletions
diff --git a/src/upb.c b/src/upb.c
index 938c72d..bd41613 100644
--- a/src/upb.c
+++ b/src/upb.c
@@ -7,6 +7,7 @@
#include <stdarg.h>
#include <stddef.h>
+#include <string.h>
#include "upb.h"
@@ -21,3 +22,10 @@ void upb_seterr(upb_status *status, enum upb_status_code code,
va_end(args);
}
}
+
+void upb_copyerr(upb_status *to, upb_status *from)
+{
+ to->code = from->code;
+ strcpy(to->msg, from->msg);
+}
+
diff --git a/src/upb.h b/src/upb.h
index 4991c50..1681763 100644
--- a/src/upb.h
+++ b/src/upb.h
@@ -71,7 +71,11 @@ enum upb_wire_type {
UPB_WIRE_TYPE_DELIMITED = 2,
UPB_WIRE_TYPE_START_GROUP = 3,
UPB_WIRE_TYPE_END_GROUP = 4,
- UPB_WIRE_TYPE_32BIT = 5
+ UPB_WIRE_TYPE_32BIT = 5,
+
+ // This isn't a real wire type, but we use this constant to describe varints
+ // that are expected to be a maximum of 32 bits.
+ UPB_WIRE_TYPE_32BIT_VARINT = 8
};
typedef uint8_t upb_wire_type_t;
@@ -121,14 +125,8 @@ typedef upb_atomic_refcount_t upb_data;
typedef uint32_t upb_strlen_t;
-struct upb_norefcount_string;
-struct upb_refcounted_string;
-typedef union {
- // Must be first, for the UPB_STATIC_STRING_PTR_INIT() macro.
- struct upb_norefcount_string *norefcount;
- struct upb_refcounted_string *refcounted;
- upb_data *base;
-} upb_strptr;
+struct _upb_string;
+typedef struct _upb_string upb_string;
typedef uint32_t upb_arraylen_t;
@@ -149,7 +147,7 @@ typedef union {
uint32_t uint32;
uint64_t uint64;
bool _bool;
- upb_strptr str;
+ upb_string *str;
upb_arrayptr arr;
upb_msg *msg;
upb_data *data;
@@ -166,7 +164,7 @@ typedef union {
uint32_t *uint32;
uint64_t *uint64;
bool *_bool;
- upb_strptr *str;
+ upb_string **str;
upb_arrayptr *arr;
upb_msg **msg;
upb_data **data;
@@ -290,6 +288,7 @@ INLINE void upb_reset(upb_status *status) {
void upb_seterr(upb_status *status, enum upb_status_code code, const char *msg,
...);
+void upb_copyerr(upb_status *to, upb_status *from);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/upb_decoder.c b/src/upb_decoder.c
index 916f0db..5d352c2 100644
--- a/src/upb_decoder.c
+++ b/src/upb_decoder.c
@@ -10,9 +10,16 @@
#include <stddef.h>
#include <stdlib.h>
+#define UPB_GROUP_END_OFFSET UINT32_MAX
+
+static bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) {
+ // Fake implementation.
+ return ft + wt > 3;
+}
+
/* Functions to read wire values. *********************************************/
-int8_t upb_get_v_uint64_full(const uint8_t *buf, uint64_t *val);
+static uint8_t upb_get_v_uint64_full(const uint8_t *buf, uint64_t *val);
// Gets a varint (wire type: UPB_WIRE_TYPE_VARINT). Caller promises that >=10
// bytes are available at buf. Returns the number of bytes consumed, or 11 if
@@ -66,19 +73,19 @@ INLINE void upb_get_f_uint64(const uint8_t *buf, uint64_t *val)
// Skips a varint (wire type: UPB_WIRE_TYPE_VARINT). Caller promises that 10
// bytes are available at "buf". Returns the number of bytes that were
// skipped.
-INLINE const uint8_t upb_skip_v_uint64(const uint8_t *buf)
+INLINE uint8_t upb_skip_v_uint64(const uint8_t *buf)
{
const uint8_t *const maxend = buf + 10;
uint8_t last = 0x80;
for(; buf < maxend && (last & 0x80); buf++)
last = *buf;
- return
+ return 0; // TODO
}
// Parses remining bytes of a 64-bit varint that has already had its first byte
// parsed.
-const uint8_t upb_get_v_uint64_full(const uint8_t *buf, uint64_t *val)
+static uint8_t upb_get_v_uint64_full(const uint8_t *buf, uint64_t *val)
{
uint8_t bytes = 0;
@@ -101,7 +108,7 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); }
typedef struct {
upb_msgdef *msgdef;
upb_fielddef *field;
- int32_t end_offset; // For groups, -1.
+ upb_strlen_t end_offset; // For groups, -1.
} upb_decoder_frame;
struct upb_decoder {
@@ -132,6 +139,14 @@ struct upb_decoder {
// Wire type of the key we just read.
upb_wire_type_t wire_type;
+
+ // Delimited length of the string field we are reading.
+ upb_strlen_t delimited_len;
+
+ upb_strlen_t packed_end_offset;
+
+ // String we return for string values. We try to recycle it if possible.
+ upb_string *str;
};
@@ -144,6 +159,7 @@ upb_decoder *upb_decoder_new(upb_msgdef *msgdef)
d->limit = &d->stack[UPB_MAX_NESTING];
d->buf = NULL;
d->nextbuf = NULL;
+ d->str = upb_string_new();
return d;
}
@@ -159,8 +175,9 @@ void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc)
d->top = d->stack;
d->top->msgdef = d->toplevel_msgdef;
// The top-level message is not delimited (we can keep receiving data for it
- // indefinitely), so we treat it like a group.
- d->top->end_offset = 0;
+ // indefinitely), so we set the end offset as high as possible, but not equal
+ // to UINT32_MAX so it doesn't equal UPB_GROUP_END_OFFSET.
+ d->top->end_offset = UINT32_MAX - 1;
d->bytesrc = bytesrc;
d->buf = NULL;
d->nextbuf = NULL;
@@ -171,6 +188,11 @@ void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc)
/* upb_decoder buffering. *****************************************************/
+static upb_strlen_t upb_decoder_offset(upb_decoder *d)
+{
+ return d->buf_endoffset - d->buf_bytesleft;
+}
+
// Discards the current buffer if we are done with it, make the next buffer
// current if there is one.
static void upb_decoder_advancebuf(upb_decoder *d)
@@ -186,10 +208,10 @@ static void upb_decoder_advancebuf(upb_decoder *d)
static bool upb_decoder_pullnextbuf(upb_decoder *d)
{
if(!d->nextbuf) {
- d->nextbuf = upb_bytesrc_get(d->bytesrc);
+ d->nextbuf = upb_bytesrc_get(d->bytesrc, UPB_MAX_ENCODED_SIZE);
if(!d->nextbuf && !upb_bytesrc_eof(d->bytesrc)) {
// There was an error in the byte stream, halt the decoder.
- upb_copyerr(&d->status, upb_bytesrc_status(d->bytesrc));
+ upb_copyerr(&d->src.status, upb_bytesrc_status(d->bytesrc));
return false;
}
}
@@ -206,6 +228,9 @@ static bool upb_decoder_skipbytes(upb_decoder *d, int32_t bytes)
return true;
}
+bool upb_decoder_skipval(upb_decoder *d);
+upb_fielddef *upb_decoder_getdef(upb_decoder *d);
+
static bool upb_decoder_skipgroup(upb_decoder *d)
{
// This will be mututally recursive with upb_decoder_skipval() if the group
@@ -217,21 +242,28 @@ static bool upb_decoder_skipgroup(upb_decoder *d)
}
// If we are at the end of the group like we want to be, then
// upb_decoder_getdef() returned NULL because of eof, not error.
- return upb_ok(&d->status);
+ return upb_ok(&d->src.status);
}
-static const uint8_t *upb_decoder_getbuf_full(upb_decoder *d, int32_t *bytes)
+upb_strlen_t upb_decoder_append(uint8_t *buf, upb_string *frombuf,
+ upb_strlen_t len, upb_strlen_t total_len);
+
+static const uint8_t *upb_decoder_getbuf_full(upb_decoder *d, uint32_t *bytes)
{
upb_decoder_pullnextbuf(d);
upb_decoder_advancebuf(d);
if(d->buf_bytesleft >= UPB_MAX_ENCODED_SIZE) {
- return upb_string_getrobuf(d->buf) + upb_string_len(d->buf) -
+ *bytes = d->buf_bytesleft;
+ return (uint8_t*)upb_string_getrobuf(d->buf) + upb_string_len(d->buf) -
d->buf_bytesleft;
} else {
- upb_strlen_t total = 0;
- if(d->buf) total += upb_decoder_append(d->tmpbuf, d->buf, total);
- if(d->nextbuf) total += upb_decoder_append(d->tmpbuf, d->nextbuf, total);
- memset(d->tmpbuf + total, 0x80, UPB_MAX_ENCODED_SIZE - total);
+ upb_strlen_t len = 0;
+ if(d->buf)
+ len += upb_decoder_append(d->tmpbuf, d->buf, len, UPB_MAX_ENCODED_SIZE);
+ if(d->nextbuf)
+ len += upb_decoder_append(d->tmpbuf, d->nextbuf, len, UPB_MAX_ENCODED_SIZE);
+ *bytes = len;
+ memset(d->tmpbuf + len, 0x80, UPB_MAX_ENCODED_SIZE - len);
return d->tmpbuf;
}
}
@@ -241,13 +273,13 @@ static const uint8_t *upb_decoder_getbuf_full(upb_decoder *d, int32_t *bytes)
// those bytes span multiple buffers). *bytes is set to the number of actual
// stream bytes that are available in the returned buffer. If
// *bytes < UPB_MAX_ENCODED_SIZE, the buffer is padded with 0x80 bytes.
-INLINE static const uint8_t *upb_decoder_getbuf(upb_decoder *d, int32_t *bytes)
+INLINE const uint8_t *upb_decoder_getbuf(upb_decoder *d, uint32_t *bytes)
{
if(d->buf_bytesleft >= UPB_MAX_ENCODED_SIZE) {
// The common case; only when we get to the last ten bytes of the buffer
// do we have to do tricky things.
*bytes = d->buf_bytesleft;
- return upb_string_getrobuf(d->buf) + upb_string_len(d->buf) -
+ return (uint8_t*)upb_string_getrobuf(d->buf) + upb_string_len(d->buf) -
d->buf_bytesleft;
} else {
return upb_decoder_getbuf_full(d, bytes);
@@ -256,33 +288,37 @@ INLINE static const uint8_t *upb_decoder_getbuf(upb_decoder *d, int32_t *bytes)
/* upb_src implementation for upb_decoder. ************************************/
+bool upb_decoder_get_v_uint32(upb_decoder *d, uint32_t *key);
+
upb_fielddef *upb_decoder_getdef(upb_decoder *d)
{
+ uint32_t key;
+ upb_wire_type_t wire_type;
+
// Detect end-of-submessage.
if(upb_decoder_offset(d) >= d->top->end_offset) {
- d->eof = true;
+ d->src.eof = true;
return NULL;
}
// Handles the packed field case.
if(d->field) return d->field;
-again:
- uint32_t key;
- upb_wire_type_t wire_type;
+ again:
if(!upb_decoder_get_v_uint32(d, &key)) {
return NULL;
+ }
wire_type = key & 0x7;
if(wire_type == UPB_WIRE_TYPE_DELIMITED) {
// For delimited wire values we parse the length now, since we need it in
// all cases.
- if(!upb_decoder_get_v_uint32(d, &d->delim_len)) return NULL;
+ if(!upb_decoder_get_v_uint32(d, &d->delimited_len)) return NULL;
} else if(wire_type == UPB_WIRE_TYPE_END_GROUP) {
- if(isgroup(d->top->submsg_end)) {
- d->eof = true;
+ if(d->top->end_offset == UPB_GROUP_END_OFFSET) {
+ d->src.eof = true;
} else {
- upb_seterr(d->status, UPB_STATUS_ERROR, "End group seen but current "
+ upb_seterr(&d->src.status, UPB_STATUS_ERROR, "End group seen but current "
"message is not a group, byte offset: %zd",
upb_decoder_offset(d));
}
@@ -302,7 +338,7 @@ again:
// return NULL and report the error.
upb_decoder_skipval(d);
// TODO: better error message.
- upb_seterr(&d->status, UPB_STATUS_ERROR, "Incorrect wire type.\n");
+ upb_seterr(&d->src.status, UPB_STATUS_ERROR, "Incorrect wire type.\n");
return NULL;
}
d->field = f;
@@ -312,30 +348,32 @@ again:
bool upb_decoder_getval(upb_decoder *d, upb_valueptr val)
{
- if(expected_type_for_field == UPB_DELIMITED) {
+ int expected_type_for_field = 0;
+ if(expected_type_for_field == UPB_WIRE_TYPE_DELIMITED) {
// A string, bytes, or a length-delimited submessage. The latter isn't
// technically a string, but can be gotten as one to perform lazy parsing.
d->str = upb_string_tryrecycle(d->str);
const upb_strlen_t total_len = d->delimited_len;
- if (total_len <= d->buf_bytesleft) {
+ if ((int32_t)total_len <= d->buf_bytesleft) {
// The entire string is inside our current buffer, so we can just
// return a substring of the buffer without copying.
upb_string_substr(d->str, d->buf,
upb_string_len(d->buf) - d->buf_bytesleft,
total_len);
- upb_decoder_consume(total_len);
+ d->buf_bytesleft -= total_len;
*val.str = d->str;
} else {
// The string spans buffers, so we must copy from the current buffer,
// the next buffer (if we have one), and finally from the bytesrc.
- char *str = upb_string_getrwbuf(d->str, d->);
+ uint8_t *str = (uint8_t*)upb_string_getrwbuf(d->str, total_len);
upb_strlen_t len = 0;
len += upb_decoder_append(str, d->buf, len, total_len);
upb_decoder_advancebuf(d);
if(d->buf) len += upb_decoder_append(str, d->buf, len, total_len);
+ upb_string_getrwbuf(d->str, len); // Cheap resize.
if(len < total_len) {
- if(!upb_bytesrc_append(d->bytesrc, d->str, len - bytes)) {
- upb_status_copy(&d->error, upb_bytesrc_status(d->bytesrc));
+ if(!upb_bytesrc_append(d->bytesrc, d->str, total_len - len)) {
+ upb_copyerr(&d->src.status, upb_bytesrc_status(d->bytesrc));
return false;
}
}
@@ -346,22 +384,22 @@ bool upb_decoder_getval(upb_decoder *d, upb_valueptr val)
// contiguous buffer.
uint32_t bytes_available;
uint32_t bytes_consumed;
- const uint8_t *buf = upb_decoder_getbuf(d, &bytes_available)
+ const uint8_t *buf = upb_decoder_getbuf(d, &bytes_available);
switch(expected_type_for_field) {
- case UPB_64BIT_VARINT:
+ case UPB_WIRE_TYPE_VARINT:
if((bytes_consumed = upb_get_v_uint32(buf, val.uint32)) > 10) goto err;
- if(f->type == UPB_TYPE(SINT64)) *val.int64 = upb_zzdec_64(*val.int64);
+ if(d->field->type == UPB_TYPE(SINT64)) *val.int64 = upb_zzdec_64(*val.int64);
break;
- case UPB_32BIT_VARINT:
+ case UPB_WIRE_TYPE_32BIT_VARINT:
if((bytes_consumed = upb_get_v_uint64(buf, val.uint64)) > 5) goto err;
- if(f->type == UPB_TYPE(SINT32)) *val.int32 = upb_zzdec_32(*val.int32);
+ if(d->field->type == UPB_TYPE(SINT32)) *val.int32 = upb_zzdec_32(*val.int32);
break;
- case UPB_64BIT_FIXED:
+ case UPB_WIRE_TYPE_64BIT:
bytes_consumed = 8;
if(bytes_available < bytes_consumed) goto err;
upb_get_f_uint64(buf, val.uint64);
break;
- case UPB_32BIT_FIXED:
+ case UPB_WIRE_TYPE_32BIT:
bytes_consumed = 4;
if(bytes_available < bytes_consumed) goto err;
upb_get_f_uint32(buf, val.uint32);
@@ -370,33 +408,40 @@ bool upb_decoder_getval(upb_decoder *d, upb_valueptr val)
// Including start/end group.
goto err;
}
- upb_decoder_consume(bytes_consumed);
- if(wire_type != UPB_WIRE_TYPE_DELIMITED ||
+ d->buf_bytesleft -= bytes_consumed;
+ if(d->wire_type != UPB_WIRE_TYPE_DELIMITED ||
upb_decoder_offset(d) >= d->packed_end_offset) {
d->field = NULL;
}
}
return true;
err:
+ return false;
}
bool upb_decoder_skipval(upb_decoder *d) {
- switch(d->key.wire_type) {
- case UPB_WIRE_TYPE_VARINT:
- return upb_skip_v_uint64(buf, end, status);
+ switch(d->wire_type) {
+ case UPB_WIRE_TYPE_VARINT: {
+ uint32_t bytes_available;
+ const uint8_t *buf = upb_decoder_getbuf(d, &bytes_available);
+ uint8_t bytes = upb_skip_v_uint64(buf);
+ if(bytes > 10) return false;
+ upb_decoder_skipbytes(d, bytes);
+ return true;
+ }
case UPB_WIRE_TYPE_64BIT:
- return upb_decoder_skipbytes(8);
+ return upb_decoder_skipbytes(d, 8);
case UPB_WIRE_TYPE_32BIT:
- return upb_decoder_skipbytes(4);
+ return upb_decoder_skipbytes(d, 4);
case UPB_WIRE_TYPE_START_GROUP:
- return upb_decoder_skipgroup();
+ return upb_decoder_skipgroup(d);
case UPB_WIRE_TYPE_DELIMITED:
// Works for both string/bytes *and* submessages.
- return upb_decoder_skipbytes(d->delimited_len);
+ return upb_decoder_skipbytes(d, d->delimited_len);
default:
// Including UPB_WIRE_TYPE_END_GROUP.
assert(false);
- upb_seterr(&d->status, UPB_STATUS_ERROR, "Tried to skip an end group");
+ upb_seterr(&d->src.status, UPB_STATUS_ERROR, "Tried to skip an end group");
return false;
}
}
@@ -404,26 +449,33 @@ bool upb_decoder_skipval(upb_decoder *d) {
bool upb_decoder_startmsg(upb_decoder *d) {
d->top->field = d->field;
if(++d->top >= d->limit) {
- upb_seterr(d->status, UPB_ERROR_MAX_NESTING_EXCEEDED,
+ upb_seterr(&d->src.status, UPB_ERROR_MAX_NESTING_EXCEEDED,
"Nesting exceeded maximum (%d levels)\n",
UPB_MAX_NESTING);
return false;
}
upb_decoder_frame *frame = d->top;
- frame->end_offset = upb_decoder_offset(d) + d->delimited_len;
- frame->msgdef = upb_downcast_msgdef(f->def);
+ frame->msgdef = upb_downcast_msgdef(d->field->def);
+ if(d->field->type == UPB_TYPE(GROUP)) {
+ frame->end_offset = UPB_GROUP_END_OFFSET;
+ } else {
+ frame->end_offset = upb_decoder_offset(d) + d->delimited_len;
+ }
return true;
}
-bool upb_decoder_endmsg(upb_decoder *src) {
- if(d->top > &d->stack) {
+bool upb_decoder_endmsg(upb_decoder *d) {
+ if(d->top > d->stack) {
--d->top;
- if(!d->eof) {
- if(d->top->f->type == UPB_TYPE(GROUP))
- upb_skip_group();
+ if(!d->src.eof) {
+ if(d->top->field->type == UPB_TYPE(GROUP))
+ upb_decoder_skipgroup(d);
else
- upb_skip_bytes(foo);
+ upb_decoder_skipbytes(d, d->top->end_offset - upb_decoder_offset(d));
}
- d->eof = false;
+ d->src.eof = false;
+ return true;
+ } else {
+ return false;
}
}
diff --git a/src/upb_srcsink.h b/src/upb_srcsink.h
index 4a3d1e3..8e5a09d 100644
--- a/src/upb_srcsink.h
+++ b/src/upb_srcsink.h
@@ -1,8 +1,6 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
- * Copyright (c) 2010 Joshua Haberman. See LICENSE for details.
- *
* This file defines four general-purpose interfaces for pulling/pushing either
* protobuf data or bytes:
*
@@ -13,12 +11,16 @@
*
* These interfaces are used as general-purpose glue in upb. For example, the
* decoder interface works by implementing a upb_src and calling a upb_bytesrc.
+ *
+ * Copyright (c) 2010 Joshua Haberman. See LICENSE for details.
+ *
*/
#ifndef UPB_SRCSINK_H
#define UPB_SRCSINK_H
#include "upb_def.h"
+#include "upb_srcsink_vtbl.h"
#ifdef __cplusplus
extern "C" {
@@ -28,9 +30,6 @@ extern "C" {
// TODO: decide how to handle unknown fields.
-struct upb_src;
-typedef struct upb_src upb_src;
-
// Retrieves the fielddef for the next field in the stream. Returns NULL on
// error or end-of-stream.
upb_fielddef *upb_src_getdef(upb_src *src);
@@ -51,14 +50,12 @@ bool upb_src_startmsg(upb_src *src);
// which case the rest of the submessage is skipped.
bool upb_src_endmsg(upb_src *src);
-// Returns the current error status for the stream.
-upb_status *upb_src_status(upb_src *src);
+// Returns the current error/eof status for the stream.
+INLINE upb_status *upb_src_status(upb_src *src) { return &src->status; }
+INLINE bool upb_src_eof(upb_src *src) { return src->eof; }
/* upb_sink *******************************************************************/
-struct upb_sink;
-typedef struct upb_sink upb_sink;
-
// Puts the given fielddef into the stream.
bool upb_sink_putdef(upb_sink *sink, upb_fielddef *def);
@@ -76,9 +73,6 @@ upb_status *upb_sink_status(upb_sink *sink);
/* upb_bytesrc ****************************************************************/
-struct upb_bytesrc;
-typedef struct upb_bytesrc upb_bytesrc;
-
// Returns the next string in the stream. NULL is returned on error or eof.
// The string must be at least "minlen" bytes long unless the stream is eof.
//
@@ -94,13 +88,11 @@ void upb_bytesrc_recycle(upb_bytesrc *src, upb_string *str);
bool upb_bytesrc_append(upb_bytesrc *src, upb_string *str, upb_strlen_t len);
// Returns the current error status for the stream.
-upb_status *upb_bytesrc_status(upb_src *src);
+INLINE upb_status *upb_bytesrc_status(upb_bytesrc *src) { return &src->status; }
+INLINE bool upb_bytesrc_eof(upb_bytesrc *src) { return src->eof; }
/* upb_bytesink ***************************************************************/
-struct upb_bytesink;
-typedef struct upb_bytesink upb_bytesink;
-
// Puts the given string. Returns the number of bytes that were actually,
// consumed, which may be fewer than were in the string, or <0 on error.
int32_t upb_bytesink_put(upb_bytesink *sink, upb_string *str);
@@ -108,63 +100,6 @@ int32_t upb_bytesink_put(upb_bytesink *sink, upb_string *str);
// Returns the current error status for the stream.
upb_status *upb_bytesink_status(upb_bytesink *sink);
-/* Dynamic Dispatch implementation for src/sink interfaces ********************/
-
-// The rest of this file only concerns components that are implementing any of
-// the above interfaces. To simple clients the code below should be considered
-// private.
-
-// Typedefs for function pointers to all of the above functions.
-typedef upb_fielddef (*upb_src_getdef_fptr)(upb_src *src);
-typedef bool (*upb_src_getval_fptr)(upb_src *src, upb_valueptr val);
-typedef bool (*upb_src_skipval_fptr)(upb_src *src);
-typedef bool (*upb_src_startmsg_fptr)(upb_src *src);
-typedef bool (*upb_src_endmsg_fptr)(upb_src *src);
-typedef upb_status *(*upb_src_status_fptr)(upb_src *src);
-
-typedef bool (*upb_sink_putdef_fptr)(upb_sink *sink, upb_fielddef *def);
-typedef bool (*upb_sink_putval_fptr)(upb_sink *sink, upb_value val);
-typedef bool (*upb_sink_startmsg_fptr)(upb_sink *sink);
-typedef bool (*upb_sink_endmsg_fptr)(upb_sink *sink);
-typedef upb_status *(*upb_sink_status_fptr)(upb_sink *sink);
-
-typedef upb_string *(*upb_bytesrc_get_fptr)(upb_bytesrc *src);
-typedef bool (*upb_bytesrc_append_fptr)(
- upb_bytesrc *src, upb_string *str, upb_strlen_t len);
-typedef upb_status *(*upb_bytesrc_status_fptr)(upb_src *src);
-
-typedef int32_t (*upb_bytesink_put_fptr)(upb_bytesink *sink, upb_string *str);
-typedef upb_status *(*upb_bytesink_status_fptr)(upb_bytesink *sink);
-
-// Vtables for the above interfaces.
-typedef struct {
- upb_src_getdef_fptr getdef;
- upb_src_getval_fptr getval;
- upb_src_skipval_fptr skipval;
- upb_src_startmsg_fptr startmsg;
- upb_src_endmsg_fptr endmsg;
- upb_src_status_fptr status;
-} upb_src_vtable;
-
-// "Base Class" definitions; components that implement these interfaces should
-// contain one of these structures.
-
-struct upb_src {
- upb_src_vtable *vtbl;
- upb_status status;
- bool eof;
-#ifndef NDEBUG
- int state; // For debug-mode checking of API usage.
-#endif
-};
-
-INLINE void upb_sink_init(upb_src *s, upb_src_vtable *vtbl) {
- s->vtbl = vtbl;
-#ifndef DEBUG
- // TODO: initialize debug-mode checking.
-#endif
-}
-
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/src/upb_srcsink_vtbl.h b/src/upb_srcsink_vtbl.h
new file mode 100644
index 0000000..66cd3c2
--- /dev/null
+++ b/src/upb_srcsink_vtbl.h
@@ -0,0 +1,93 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * vtable declarations for types that are implementing any of the src or sink
+ * interfaces. Only components that are implementing these interfaces need
+ * to worry about this file.
+ *
+ * Copyright (c) 2010 Joshua Haberman. See LICENSE for details.
+ */
+
+#ifndef UPB_SRCSINK_VTBL_H_
+#define UPB_SRCSINK_VTBL_H_
+
+#include "upb_def.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct upb_src;
+typedef struct upb_src upb_src;
+struct upb_sink;
+typedef struct upb_sink upb_sink;
+struct upb_bytesrc;
+typedef struct upb_bytesrc upb_bytesrc;
+struct upb_bytesink;
+typedef struct upb_bytesink upb_bytesink;
+
+// Typedefs for function pointers to all of the virtual functions.
+typedef upb_fielddef (*upb_src_getdef_fptr)(upb_src *src);
+typedef bool (*upb_src_getval_fptr)(upb_src *src, upb_valueptr val);
+typedef bool (*upb_src_skipval_fptr)(upb_src *src);
+typedef bool (*upb_src_startmsg_fptr)(upb_src *src);
+typedef bool (*upb_src_endmsg_fptr)(upb_src *src);
+
+typedef bool (*upb_sink_putdef_fptr)(upb_sink *sink, upb_fielddef *def);
+typedef bool (*upb_sink_putval_fptr)(upb_sink *sink, upb_value val);
+typedef bool (*upb_sink_startmsg_fptr)(upb_sink *sink);
+typedef bool (*upb_sink_endmsg_fptr)(upb_sink *sink);
+
+typedef upb_string *(*upb_bytesrc_get_fptr)(upb_bytesrc *src);
+typedef void (*upb_bytesrc_recycle_fptr)(upb_bytesrc *src, upb_string *str);
+typedef bool (*upb_bytesrc_append_fptr)(
+ upb_bytesrc *src, upb_string *str, upb_strlen_t len);
+
+typedef int32_t (*upb_bytesink_put_fptr)(upb_bytesink *sink, upb_string *str);
+
+// Vtables for the above interfaces.
+typedef struct {
+ upb_src_getdef_fptr getdef;
+ upb_src_getval_fptr getval;
+ upb_src_skipval_fptr skipval;
+ upb_src_startmsg_fptr startmsg;
+ upb_src_endmsg_fptr endmsg;
+} upb_src_vtable;
+
+typedef struct {
+ upb_bytesrc_get_fptr get;
+ upb_bytesrc_append_fptr append;
+ upb_bytesrc_recycle_fptr recycle;
+} upb_bytesrc_vtable;
+
+// "Base Class" definitions; components that implement these interfaces should
+// contain one of these structures.
+
+struct upb_src {
+ upb_src_vtable *vtbl;
+ upb_status status;
+ bool eof;
+#ifndef NDEBUG
+ int state; // For debug-mode checking of API usage.
+#endif
+};
+
+struct upb_bytesrc {
+ upb_bytesrc_vtable *vtbl;
+ upb_status status;
+ bool eof;
+};
+
+INLINE void upb_sink_init(upb_src *s, upb_src_vtable *vtbl) {
+ s->vtbl = vtbl;
+ s->eof = false;
+#ifndef DEBUG
+ // TODO: initialize debug-mode checking.
+#endif
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/src/upb_string.h b/src/upb_string.h
index 2c0303d..9a3957c 100644
--- a/src/upb_string.h
+++ b/src/upb_string.h
@@ -28,6 +28,7 @@
#include <assert.h>
#include <string.h>
#include "upb_atomic.h"
+#include "upb.h"
#ifdef __cplusplus
extern "C" {
@@ -35,7 +36,7 @@ extern "C" {
// All members of this struct are private, and may only be read/written through
// the associated functions. Also, strings may *only* be allocated on the heap.
-typedef struct _upb_string {
+struct _upb_string {
char *ptr;
uint32_t len;
uint32_t size;
@@ -46,7 +47,7 @@ typedef struct _upb_string {
// Used if this string is referencing external unowned memory.
upb_atomic_refcount_t reader_count;
} extra;
-} upb_string;
+};
// Returns a newly-created, empty, non-finalized string. When the string is no
// longer needed, it should be unref'd, never freed directly.
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback