Make onend upb_sink callback take the field as a parameter.

pull/13171/head
Joshua Haberman 15 years ago
parent d7d1b2a141
commit 50451ea441
  1. 5
      src/upb_data.c
  2. 7
      src/upb_parse.c
  3. 56
      src/upb_sink.h

@ -306,7 +306,7 @@ static void _upb_msgsrc_produceval(union upb_value v, struct upb_fielddef *f,
if(upb_issubmsg(f)) { if(upb_issubmsg(f)) {
upb_sink_onstart(sink, f); upb_sink_onstart(sink, f);
upb_msgsrc_produce(v.msg, upb_downcast_msgdef(f->def), sink); 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)) { } else if(upb_isstring(f)) {
upb_sink_onstr(sink, f, v.str, 0, upb_strlen(v.str)); upb_sink_onstr(sink, f, v.str, 0, upb_strlen(v.str));
} else { } else {
@ -425,8 +425,9 @@ static upb_sink_status _upb_msgsink_startcb(upb_sink *s, struct upb_fielddef *f)
return UPB_SINK_CONTINUE; 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; upb_msgsink *ms = (upb_msgsink*)s;
ms->top--; ms->top--;
return UPB_SINK_CONTINUE; return UPB_SINK_CONTINUE;

@ -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, INLINE const uint8_t *upb_get_v_uint32_t(const uint8_t *buf, const uint8_t *end,
uint32_t *val, uint32_t *val,
struct upb_status *status) 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_parser_frame {
struct upb_msgdef *msgdef; struct upb_msgdef *msgdef;
struct upb_fielddef *field;
size_t end_offset; // For groups, 0. 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, uint32_t submsg_len, struct upb_fielddef *f,
struct upb_status *status) struct upb_status *status)
{ {
p->top->field = f;
p->top++; p->top++;
if(p->top >= p->limit) { if(p->top >= p->limit) {
upb_seterr(status, UPB_STATUS_ERROR, 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) static const void *pop(upb_parser *p, const uint8_t *start)
{ {
upb_sink_onend(p->sink);
p->top--; p->top--;
upb_sink_onend(p->sink, p->top->field);
return get_msgend(p, start); return get_msgend(p, start);
} }

@ -45,11 +45,10 @@ typedef enum {
// The normal case, where the consumer wants to continue consuming. // The normal case, where the consumer wants to continue consuming.
UPB_SINK_CONTINUE, UPB_SINK_CONTINUE,
// The consumer has consumed the current value, but it wants to stop for now. // The sink did not consume this value, and wants to halt further processing.
// When the source is next invoked, it should resume at the next value. Note // If the source is resumable, it should save the current state so that when
// that sources are not necessarily resumable; if a source is not resumable, // resumed, the value that was just provided will be replayed.
// returning UPB_SINK_SUSPEND will simply halt it. UPB_SINK_STOP,
UPB_SINK_SUSPEND,
// The consumer wants to skip to the end of the current submessage and // 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 // continue consuming. If we are at the top-level, the rest of the
@ -64,18 +63,18 @@ typedef struct {
/* upb_sink callbacks *********************************************************/ /* upb_sink callbacks *********************************************************/
// The value callback is called when a regular value (ie. not a string or // The value callback is called for a regular value (ie. not a string or
// submessage) is pushed. // submessage).
typedef upb_sink_status (*upb_value_cb)(upb_sink *s, struct upb_fielddef *f, typedef upb_sink_status (*upb_value_cb)(upb_sink *s, struct upb_fielddef *f,
union upb_value val); union upb_value val);
// The string callback is called when a string is pushed. "str" is the string // The string callback is called for string data. "str" is the string in which
// in which the data lives, but it may contain more data than the effective // the data lives, but it may contain more data than the effective string.
// string. "start" and "end" indicate the substring of "str" that is the // "start" and "end" indicate the substring of "str" that is the effective
// effective string. If "start" is <0, this string is a continuation of the // string. If "start" is <0, this string is a continuation of the previous
// previous string for this field. If end > upb_strlen(str) then there is more // string for this field. If end > upb_strlen(str) then there is more data to
// data to follow for this string. "end" can also be used as a hint for how // follow for this string. "end" can also be used as a hint for how much data
// much data follows, but this is only a hint and is not guaranteed. // 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 // 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 // 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, // The start and end callbacks are called when a submessage begins and ends,
// respectively. // respectively.
typedef upb_sink_status (*upb_start_cb)(upb_sink *s, struct upb_fielddef *f); 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 { typedef struct upb_sink_callbacks {
upb_value_cb value_cb; 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++ // 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 // 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 // make it possible to write C++ sinks in a more natural style without loss of
// a flag in upb_sink defining whether it is a C sink or a C++ one. // 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_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_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_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 // Initializes a plain C visitor with the given vtbl. The sink must have been
// been allocated separately. // allocated separately.
INLINE void upb_sink_init(upb_sink *s, upb_sink_callbacks *vtbl) { INLINE void upb_sink_init(upb_sink *s, upb_sink_callbacks *vtbl) {
s->vtbl = 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 #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

Loading…
Cancel
Save