From 50451ea441280fe193c1c344e299977d8fcbdcc7 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 13 Jan 2010 19:06:23 -0800 Subject: Make onend upb_sink callback take the field as a parameter. --- src/upb_data.c | 5 +++-- src/upb_parse.c | 7 +++++-- src/upb_sink.h | 56 +++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 43 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/upb_data.c b/src/upb_data.c index da72250..dab2d20 100644 --- a/src/upb_data.c +++ b/src/upb_data.c @@ -306,7 +306,7 @@ static void _upb_msgsrc_produceval(union upb_value v, struct upb_fielddef *f, if(upb_issubmsg(f)) { upb_sink_onstart(sink, f); upb_msgsrc_produce(v.msg, upb_downcast_msgdef(f->def), sink); - upb_sink_onend(sink); + upb_sink_onend(sink, f); } else if(upb_isstring(f)) { upb_sink_onstr(sink, f, v.str, 0, upb_strlen(v.str)); } else { @@ -425,8 +425,9 @@ static upb_sink_status _upb_msgsink_startcb(upb_sink *s, struct upb_fielddef *f) return UPB_SINK_CONTINUE; } -static upb_sink_status _upb_msgsink_endcb(upb_sink *s) +static upb_sink_status _upb_msgsink_endcb(upb_sink *s, struct upb_fielddef *f) { + (void)f; // Unused. upb_msgsink *ms = (upb_msgsink*)s; ms->top--; return UPB_SINK_CONTINUE; diff --git a/src/upb_parse.c b/src/upb_parse.c index 577fa5c..be22203 100644 --- a/src/upb_parse.c +++ b/src/upb_parse.c @@ -37,7 +37,8 @@ INLINE const uint8_t *upb_get_v_uint64_t(const uint8_t *buf, const uint8_t *end, } } -// Gets a varint -- called when we only need 32 bits of it. +// Gets a varint -- called when we only need 32 bits of it. Note that a 32-bit +// varint is not a true wire type. INLINE const uint8_t *upb_get_v_uint32_t(const uint8_t *buf, const uint8_t *end, uint32_t *val, struct upb_status *status) @@ -312,6 +313,7 @@ static const uint8_t *upb_parse_value(const uint8_t *buf, const uint8_t *end, struct upb_parser_frame { struct upb_msgdef *msgdef; + struct upb_fielddef *field; size_t end_offset; // For groups, 0. }; @@ -380,6 +382,7 @@ static const uint8_t *push(upb_parser *p, const uint8_t *start, uint32_t submsg_len, struct upb_fielddef *f, struct upb_status *status) { + p->top->field = f; p->top++; if(p->top >= p->limit) { upb_seterr(status, UPB_STATUS_ERROR, @@ -401,8 +404,8 @@ static const uint8_t *push(upb_parser *p, const uint8_t *start, */ static const void *pop(upb_parser *p, const uint8_t *start) { - upb_sink_onend(p->sink); p->top--; + upb_sink_onend(p->sink, p->top->field); return get_msgend(p, start); } diff --git a/src/upb_sink.h b/src/upb_sink.h index 2055688..d864512 100644 --- a/src/upb_sink.h +++ b/src/upb_sink.h @@ -45,11 +45,10 @@ typedef enum { // The normal case, where the consumer wants to continue consuming. UPB_SINK_CONTINUE, - // The consumer has consumed the current value, but it wants to stop for now. - // When the source is next invoked, it should resume at the next value. Note - // that sources are not necessarily resumable; if a source is not resumable, - // returning UPB_SINK_SUSPEND will simply halt it. - UPB_SINK_SUSPEND, + // The sink did not consume this value, and wants to halt further processing. + // If the source is resumable, it should save the current state so that when + // resumed, the value that was just provided will be replayed. + UPB_SINK_STOP, // The consumer wants to skip to the end of the current submessage and // continue consuming. If we are at the top-level, the rest of the @@ -64,18 +63,18 @@ typedef struct { /* upb_sink callbacks *********************************************************/ -// The value callback is called when a regular value (ie. not a string or -// submessage) is pushed. +// The value callback is called for a regular value (ie. not a string or +// submessage). typedef upb_sink_status (*upb_value_cb)(upb_sink *s, struct upb_fielddef *f, union upb_value val); -// The string callback is called when a string is pushed. "str" is the string -// in which the data lives, but it may contain more data than the effective -// string. "start" and "end" indicate the substring of "str" that is the -// effective string. If "start" is <0, this string is a continuation of the -// previous string for this field. If end > upb_strlen(str) then there is more -// data to follow for this string. "end" can also be used as a hint for how -// much data follows, but this is only a hint and is not guaranteed. +// The string callback is called for string data. "str" is the string in which +// the data lives, but it may contain more data than the effective string. +// "start" and "end" indicate the substring of "str" that is the effective +// string. If "start" is <0, this string is a continuation of the previous +// string for this field. If end > upb_strlen(str) then there is more data to +// follow for this string. "end" can also be used as a hint for how much data +// follows, but this is only a hint and is not guaranteed. // // The data is supplied this way to give you the opportunity to reference this // data instead of copying it (perhaps using upb_strslice), or to minimize @@ -87,10 +86,10 @@ typedef upb_sink_status (*upb_str_cb)(upb_sink *s, struct upb_fielddef *f, // The start and end callbacks are called when a submessage begins and ends, // respectively. typedef upb_sink_status (*upb_start_cb)(upb_sink *s, struct upb_fielddef *f); -typedef upb_sink_status (*upb_end_cb)(upb_sink *s); +typedef upb_sink_status (*upb_end_cb)(upb_sink *s, struct upb_fielddef *f); -/* upb_sink implementation *************************************************/ +/* upb_sink implementation ****************************************************/ typedef struct upb_sink_callbacks { upb_value_cb value_cb; @@ -101,19 +100,34 @@ typedef struct upb_sink_callbacks { // We could potentially define these later to also be capable of calling a C++ // virtual method instead of doing the virtual dispatch manually. This would -// make it possible to write C++ sinks in a more natural style. We could have -// a flag in upb_sink defining whether it is a C sink or a C++ one. +// make it possible to write C++ sinks in a more natural style without loss of +// efficiency. We could have a flag in upb_sink defining whether it is a C +// sink or a C++ one. #define upb_sink_onvalue(s, f, val) s->vtbl->value_cb(s, f, val) #define upb_sink_onstr(s, f, str, start, end) s->vtbl->str_cb(s, f, str, start, end) #define upb_sink_onstart(s, f) s->vtbl->start_cb(s, f) -#define upb_sink_onend(s) s->vtbl->end_cb(s) +#define upb_sink_onend(s, f) s->vtbl->end_cb(s, f) -// Initializes a plain C visitor with the given vtbl. The visitor must have -// been allocated separately. +// Initializes a plain C visitor with the given vtbl. The sink must have been +// allocated separately. INLINE void upb_sink_init(upb_sink *s, upb_sink_callbacks *vtbl) { s->vtbl = vtbl; } + +/* upb_bytesink ***************************************************************/ + +// A upb_bytesink is like a upb_sync, but for bytes instead of structured +// protobuf data. Parsers implement upb_bytesink and push to a upb_sink, +// serializers do the opposite (implement upb_sink and push to upb_bytesink). +// +// The two simplest kinds of sinks are "write to string" and "write to FILE*". + +// The single bytesink callback; it takes the bytes to be written and returns +// how many were successfully written. If zero is returned, it indicates that +// no more bytes can be accepted right now. +//typedef size_t (*upb_byte_cb)(upb_bytesink *s, upb_strptr str); + #ifdef __cplusplus } /* extern "C" */ #endif -- cgit v1.2.3