summaryrefslogtreecommitdiff
path: root/src/upb_decoder.c
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2011-02-17 19:14:53 -0800
committerJoshua Haberman <joshua@reverberate.org>2011-02-17 19:14:53 -0800
commitf1e1cc4695b34b292454e903adbf09e66cf2e9d5 (patch)
tree4536fa1613c054c83b91a0ac1e76759815ceab80 /src/upb_decoder.c
parentf9a6f67e275dd6d379ae9428e1c40f43d8d17386 (diff)
Split inttable into a hash part and an array part.
upb_inttable() now supports a "compact" operation that will decide on an array size and put all entries with small enough keys into the array part for faster lookup. Also exposed the upb_itof_ent structure and put a few useful values there, so they are one fewer pointer chase away.
Diffstat (limited to 'src/upb_decoder.c')
-rw-r--r--src/upb_decoder.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/src/upb_decoder.c b/src/upb_decoder.c
index 9c216d5..4467440 100644
--- a/src/upb_decoder.c
+++ b/src/upb_decoder.c
@@ -11,6 +11,12 @@
#include <stdlib.h>
#include "upb_def.h"
+// If the return value is other than UPB_CONTINUE, that is what the last
+// callback returned.
+extern upb_flow_t upb_fastdecode(const char **p, const char *end,
+ upb_value_handler_t *value_cb, void *closure,
+ void *table, int table_size);
+
/* Pure Decoding **************************************************************/
// The key fast-path varint-decoding routine. Here we can assume we have at
@@ -329,6 +335,12 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
CHECK_FLOW(upb_pop(d));
}
+ // Decodes as many fields as possible, updating d->ptr appropriately,
+ // before falling through to the slow(er) path.
+ //CHECK_FLOW(upb_fastdecode(&d->ptr, d->end,
+ // d->dispatcher->top->handlers.set->value,
+ // d->top->handlers.closure));
+
// Parse/handle tag.
upb_tag tag;
if (!upb_decode_tag(d, &tag)) {
@@ -373,15 +385,19 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
}
// Look up field by tag number.
- upb_fielddef *f = upb_msgdef_itof(d->top->msgdef, tag.field_number);
+ upb_itof_ent *e = upb_msgdef_itofent(d->top->msgdef, tag.field_number);
- if (!f) {
+ if (!e) {
if (tag.wire_type == UPB_WIRE_TYPE_DELIMITED)
CHECK(upb_decode_string(d, &val, &d->tmp));
CHECK_FLOW(upb_dispatch_unknownval(&d->dispatcher, tag.field_number, val));
continue;
- } else if (!upb_check_type(tag.wire_type, f->type)) {
- // TODO: put more details in this error msg.
+ }
+
+ upb_fielddef *f = e->f;
+
+ if (tag.wire_type != e->native_wire_type) {
+ // TODO: Support packed fields.
upb_seterr(status, UPB_ERROR, "Field had incorrect type, name: " UPB_STRFMT
", field type: %d, expected wire type %d, actual wire type: %d",
UPB_STRARG(f->name), f->type, upb_types[f->type].native_wire_type,
@@ -398,10 +414,10 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
// that the top 32 bits all match the highest bit of the low 32 bits.
// If this is not true we are losing data. But the main protobuf library
// doesn't check this, and it would slow us down, so pass for now.
- switch (f->type) {
+ switch (e->field_type) {
case UPB_TYPE(MESSAGE):
case UPB_TYPE(GROUP):
- CHECK_FLOW(upb_push(d, f, val, f->type));
+ CHECK_FLOW(upb_push(d, f, val, e->field_type));
continue; // We have no value to dispatch.
case UPB_TYPE(STRING):
case UPB_TYPE(BYTES):
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback