summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-07-21 01:44:13 -0700
committerJoshua Haberman <joshua@reverberate.org>2009-07-21 01:44:13 -0700
commitbabefc3c66552db4a0b0302324f1280b0faacd82 (patch)
treeb0864240621ef3ea3e59949fc73ecc0f7cd34a31 /src
parentb2a39e50d829a288243dc590997910a1a87f626e (diff)
Bugfixes to parser.
Diffstat (limited to 'src')
-rw-r--r--src/upb_msg.c21
-rw-r--r--src/upb_msg.h13
-rw-r--r--src/upb_parse.c32
-rw-r--r--src/upb_parse.h19
4 files changed, 46 insertions, 39 deletions
diff --git a/src/upb_msg.c b/src/upb_msg.c
index deefb27..a923bb8 100644
--- a/src/upb_msg.c
+++ b/src/upb_msg.c
@@ -1,6 +1,7 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
+ * Copyright (c) 2009 Joshua Haberman. See LICENSE for details.
*/
#include <inttypes.h>
@@ -281,10 +282,13 @@ static void *value_cb(void *udata, void *buf, void *end,
struct upb_msg_parse_state *s = udata;
struct upb_msg_field *f = user_field_desc;
union upb_value_ptr p = get_value_ptr(s->top->data, f);
- return upb_parse_value(buf, end, f->type, p, errjmp);
+ void *ret = upb_parse_value(buf, end, f->type, p, errjmp);
+ google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, s->top->m);
+ //upb_text_printfield(&s->p, *fd->name, f->type, p, stdout);
+ return ret;
}
-static upb_status_t str_cb(void *udata, struct upb_string *str,
+static void str_cb(void *udata, struct upb_string *str,
void *user_field_desc)
{
struct upb_msg_parse_state *s = udata;
@@ -297,7 +301,8 @@ static upb_status_t str_cb(void *udata, struct upb_string *str,
upb_msg_reuse_str(p.str, str->byte_len);
upb_strcpy(*p.str, str);
}
- return UPB_STATUS_OK;
+ google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, s->top->m);
+ //upb_text_printfield(&s->p, *fd->name, f->type, p, stdout);
}
static void submsg_start_cb(void *udata, void *user_field_desc)
@@ -311,12 +316,21 @@ static void submsg_start_cb(void *udata, void *user_field_desc)
s->top->m = f->ref.msg;
s->top->data = *p.msg;
if(!s->merge) upb_msg_clear(s->top->data, s->top->m);
+ //upb_text_push(&s->p, *s->top->m->descriptor->name, stdout);
+}
+
+static void submsg_end_cb(void *udata)
+{
+ struct upb_msg_parse_state *s = udata;
+ s->top--;
+ //upb_text_pop(&s->p, stdout);
}
void upb_msg_parse_reset(struct upb_msg_parse_state *s, void *msg,
struct upb_msg *m, bool merge, bool byref)
{
upb_parse_reset(&s->s, s);
+ //upb_text_printer_init(&s->p, false);
s->merge = merge;
s->byref = byref;
if(!merge && msg == NULL) msg = upb_msgdata_new(m);
@@ -328,6 +342,7 @@ void upb_msg_parse_reset(struct upb_msg_parse_state *s, void *msg,
s->s.value_cb = value_cb;
s->s.str_cb = str_cb;
s->s.submsg_start_cb = submsg_start_cb;
+ s->s.submsg_end_cb = submsg_end_cb;
}
void upb_msg_parse_init(struct upb_msg_parse_state *s, void *msg,
diff --git a/src/upb_msg.h b/src/upb_msg.h
index 0cb3cd5..9eaf6c2 100644
--- a/src/upb_msg.h
+++ b/src/upb_msg.h
@@ -101,7 +101,6 @@
#include "upb.h"
#include "upb_table.h"
#include "upb_parse.h"
-#include "descriptor.h"
#ifdef __cplusplus
extern "C" {
@@ -195,16 +194,6 @@ INLINE struct upb_msg_field *upb_msg_fieldbyname(struct upb_msg *m,
return e ? &e->f : NULL;
}
-INLINE bool upb_issubmsgtype(upb_field_type_t type) {
- return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP ||
- type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE;
-}
-
-INLINE bool upb_isstringtype(upb_field_type_t type) {
- return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING ||
- type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES;
-}
-
INLINE bool upb_issubmsg(struct upb_msg_field *f) {
return upb_issubmsgtype(f->type);
}
@@ -311,12 +300,14 @@ struct upb_msg_parse_frame {
void *data;
};
+//#include "upb_text.h"
struct upb_msg_parse_state {
struct upb_parse_state s;
bool merge;
bool byref;
struct upb_msg *m;
struct upb_msg_parse_frame stack[UPB_MAX_NESTING], *top;
+ //struct upb_text_printer p;
};
/* Initializes/frees a message parser. The parser will write the data to the
diff --git a/src/upb_parse.c b/src/upb_parse.c
index fa37a56..3bbbf4a 100644
--- a/src/upb_parse.c
+++ b/src/upb_parse.c
@@ -10,7 +10,6 @@
#include <stdlib.h>
/* May want to move this to upb.c if enough other things warrant it. */
-#include "descriptor.h"
#define alignof(t) offsetof(struct { char c; t x; }, x)
struct upb_type_info upb_type_info[] = {
[GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE] = {alignof(double), sizeof(double), UPB_WIRE_TYPE_64BIT},
@@ -258,6 +257,7 @@ void upb_parse_reset(struct upb_parse_state *state, void *udata)
/* The top-level message is not delimited (we can keep receiving data for
* it indefinitely), so we treat it like a group. */
*state->top = 0;
+ state->completed_offset = 0;
state->udata = udata;
}
@@ -272,34 +272,23 @@ void upb_parse_free(struct upb_parse_state *state)
free(state->stack);
}
-static void *pop_stack_frame(struct upb_parse_state *s,
- uint8_t *buf, uint8_t *submsg_end)
+static void *pop_stack_frame(struct upb_parse_state *s, uint8_t *buf)
{
if(s->submsg_end_cb) s->submsg_end_cb(s->udata);
- uint32_t final_submsg_len = *s->top - (buf - submsg_end);
s->top--;
- *s->top -= final_submsg_len;
- return (char*)buf + (*s->top > 0 ? *s->top : 0);
+ return (char*)buf + (*s->top > 0 ? (*s->top - s->completed_offset) : 0);
}
/* Returns the next end offset. */
static void *push_stack_frame(struct upb_parse_state *s,
- uint8_t *buf, uint8_t *submsg_end, uint32_t len,
+ uint8_t *buf, uint32_t len,
void *user_field_desc, jmp_buf errjmp)
{
- *s->top -= len;
- if(*s->top < 0) *s->top -= (buf - submsg_end);
s->top++;
if(s->top > s->limit) longjmp(errjmp, UPB_ERROR_STACK_OVERFLOW);
- *s->top = len;
+ *s->top = s->completed_offset + len;
if(s->submsg_start_cb) s->submsg_start_cb(s->udata, user_field_desc);
- return (char*)buf + *s->top;
-}
-
-upb_status_t upb_isstringtype(upb_field_type_t type)
-{
- return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING ||
- type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES;
+ return (char*)buf + (*s->top > 0 ? (*s->top - s->completed_offset) : 0);
}
upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len,
@@ -320,7 +309,7 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len,
struct upb_tag tag;
buf = parse_tag(buf, end, &tag, errjmp);
if(tag.wire_type == UPB_WIRE_TYPE_END_GROUP) {
- submsg_end = pop_stack_frame(s, buf, submsg_end);
+ submsg_end = pop_stack_frame(s, start);
completed = buf;
continue;
}
@@ -344,7 +333,7 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len,
}
if(ft == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE) {
- submsg_end = push_stack_frame(s, buf, submsg_end, delim_len, user_field_desc, errjmp);
+ submsg_end = push_stack_frame(s, start, delim_end - start, user_field_desc, errjmp);
} else { /* Delimited data for which we require (and have) all data. */
if(ft == 0) {
/* Do nothing -- client has elected to skip. */
@@ -361,16 +350,17 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len,
if(ft == 0) /* Client elected to skip. */
buf = skip_wire_value(buf, end, tag.wire_type, errjmp);
else if(ft == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP)
- submsg_end = push_stack_frame(s, buf, submsg_end, 0, user_field_desc, errjmp);
+ submsg_end = push_stack_frame(s, start, 0, user_field_desc, errjmp);
else
buf = s->value_cb(s->udata, buf, end, user_field_desc, errjmp);
}
- while(buf == submsg_end) submsg_end = pop_stack_frame(s, buf, submsg_end);
+ while(buf == submsg_end) submsg_end = pop_stack_frame(s, start);
completed = buf;
}
done:
*read = (char*)completed - (char*)start;
+ s->completed_offset += *read;
return status;
}
diff --git a/src/upb_parse.h b/src/upb_parse.h
index 4a432d8..8975052 100644
--- a/src/upb_parse.h
+++ b/src/upb_parse.h
@@ -16,6 +16,7 @@
#include <stdbool.h>
#include <stdint.h>
#include "upb.h"
+#include "descriptor.h"
#ifdef __cplusplus
extern "C" {
@@ -48,6 +49,16 @@ struct upb_tag {
upb_wire_type_t wire_type;
};
+INLINE bool upb_issubmsgtype(upb_field_type_t type) {
+ return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP ||
+ type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE;
+}
+
+INLINE bool upb_isstringtype(upb_field_type_t type) {
+ return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING ||
+ type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES;
+}
+
/* High-level parsing interface. **********************************************/
/* The general scheme is that the client registers callbacks that will be
@@ -90,9 +101,8 @@ typedef void *(*upb_value_cb)(void *udata, void *buf, void *end,
void *user_field_desc, jmp_buf errjmp);
/* The callback that is called when a string is parsed. */
-typedef upb_status_t (*upb_str_cb)(void *udata,
- struct upb_string *str,
- void *user_field_desc);
+typedef void (*upb_str_cb)(void *udata, struct upb_string *str,
+ void *user_field_desc);
/* Callbacks that are called when a submessage begins and ends, respectively.
* Both are called with the submessage's stack frame at the top of the stack. */
@@ -103,7 +113,8 @@ typedef void (*upb_submsg_end_cb)(void *udata);
struct upb_parse_state {
/* For delimited submsgs, counts from the submsg len down to zero.
* For group submsgs, counts from zero down to the negative len. */
- int32_t stack[UPB_MAX_NESTING], *top, *limit;
+ uint32_t stack[UPB_MAX_NESTING], *top, *limit;
+ size_t completed_offset;
void *udata;
upb_tag_cb tag_cb;
upb_value_cb value_cb;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback