From 8e138c4687bf021d40be5134228940dbfe2fbd45 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 12 Jul 2010 10:21:53 -0700 Subject: Added more comments for upb_src interface. --- Makefile | 1 + core/upb_stream.c | 4 ++-- core/upb_stream.h | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index c37df72..166ca3a 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,7 @@ clean: # The core library (core/libupb.a) SRC=core/upb.c stream/upb_decoder.c core/upb_table.c core/upb_def.c core/upb_string.c \ + core/upb_stream.c \ descriptor/descriptor.c $(SRC): perf-cppflags # Parts of core that are yet to be converted. diff --git a/core/upb_stream.c b/core/upb_stream.c index e0863b8..bda11de 100644 --- a/core/upb_stream.c +++ b/core/upb_stream.c @@ -16,10 +16,10 @@ void upb_streamdata(upb_src *src, upb_sink *sink, upb_status *status) { upb_string *str = NULL; while((f = upb_src_getdef(src)) != NULL) { CHECKSINK(upb_sink_putdef(sink, f)); - if(f->type == UPB_TYPE(GROUP) || f->type == UPB_TYPE(MESSAGE)) { + if(upb_issubmsg(f)) { // We always recurse into submessages, but the putdef above already told // the sink that. - } else if(f->type == UPB_TYPE(STRING) || f->type == UPB_TYPE(BYTES)) { + } else if(upb_isstring(f)) { str = upb_string_tryrecycle(str); CHECKSRC(upb_src_getstr(src, str)); CHECKSINK(upb_sink_putstr(sink, str)); diff --git a/core/upb_stream.h b/core/upb_stream.h index e7b4074..9147e45 100644 --- a/core/upb_stream.h +++ b/core/upb_stream.h @@ -35,29 +35,58 @@ struct _upb_fielddef; /* upb_src ********************************************************************/ +// A upb_src is a pull parser for protobuf data. Sample usage: +// +// #define CHECK(x) if(!x) goto err; +// +// bool parse_msg(upb_src *src, int indent) { +// upb_fielddef *f; +// while ((f = upb_src_getdef(src)) != NULL) { +// for (int i = 0; i < indent; i++) putchar(' '); +// printf("Parsed field; name=" UPB_STRFMT ", num=%d", +// UPB_STRARG(d->name), d->number); +// if (upb_issubmsg(f)) { +// CHECK(upb_src_startmsg(src)); +// CHECK(parse_msg(src, indent + 2)); +// CHECK(upb_src_endmsg(src)); +// } else { +// CHECK(upb_src_skipval(src)); +// } +// } +// // We should be EOF now, otherwise there was an error. +// CHECK(upb_src_eof(src)); +// return true; +// +// err: +// return false; +// } +// // TODO: decide how to handle unknown fields. // Retrieves the fielddef for the next field in the stream. Returns NULL on -// error or end-of-stream. +// error or end-of-stream. End of stream can simply mean end of submessage. struct _upb_fielddef *upb_src_getdef(upb_src *src); -// Retrieves and stores the next value in "val". For string types "val" must -// be a newly-recycled string. Returns false on error. +// Retrieves and stores the next value in "val". upb_src_getval() is for all +// numeric types and upb_src_getstr() is for strings. For string types "str" +// must be a newly-recycled string. Returns false on error. bool upb_src_getval(upb_src *src, upb_valueptr val); bool upb_src_getstr(upb_src *src, upb_string *val); // Like upb_src_getval() but skips the value. bool upb_src_skipval(upb_src *src); -// Descends into a submessage. May only be called after a def has been -// returned that indicates a submessage. +// Descends into a submessage. May only be called when upb_issubmsg(f) is true +// for an f = upb_src_getdef(src) that was just parsed. bool upb_src_startmsg(upb_src *src); // Stops reading a submessage. May be called before the stream is EOF, in // which case the rest of the submessage is skipped. bool upb_src_endmsg(upb_src *src); -// Returns the current error/eof status for the stream. +// Returns the current error/eof status for the stream. If a stream is eof +// but we are inside a submessage, calling upb_src_endmsg(src) will reset +// the eof marker. INLINE upb_status *upb_src_status(upb_src *src) { return &src->status; } INLINE bool upb_src_eof(upb_src *src) { return src->eof; } @@ -80,9 +109,7 @@ bool upb_sink_putdef(upb_sink *sink, struct _upb_fielddef *def); // Puts the given value into the stream. bool upb_sink_putval(upb_sink *sink, upb_value val); - -// Starts a submessage. (needed? the def tells us we're starting a submsg.) -bool upb_sink_startmsg(upb_sink *sink); +bool upb_sink_putstr(upb_sink *sink, upb_string *str); // Ends a submessage. bool upb_sink_endmsg(upb_sink *sink); @@ -114,6 +141,12 @@ 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); +/* Utility functions **********************************************************/ + +// Streams data from src to sink until EOF or error. +void upb_streamdata(upb_src *src, upb_sink *sink, upb_status *status); + + #ifdef __cplusplus } /* extern "C" */ #endif -- cgit v1.2.3