Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
5.1 KiB
200 lines
5.1 KiB
/* |
|
* upb - a minimalist implementation of protocol buffers. |
|
* |
|
* vtable declarations for types that are implementing any of the src or sink |
|
* interfaces. Only components that are implementing these interfaces need |
|
* to worry about this file. |
|
* |
|
* Copyright (c) 2010 Joshua Haberman. See LICENSE for details. |
|
*/ |
|
|
|
#ifndef UPB_SRCSINK_VTBL_H_ |
|
#define UPB_SRCSINK_VTBL_H_ |
|
|
|
#include <assert.h> |
|
#include "upb_stream.h" |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
// Typedefs for function pointers to all of the virtual functions. |
|
|
|
// upb_bytesrc. |
|
typedef bool (*upb_bytesrc_get_fptr)( |
|
upb_bytesrc *src, upb_string *str, upb_strlen_t minlen); |
|
typedef bool (*upb_bytesrc_append_fptr)( |
|
upb_bytesrc *src, upb_string *str, upb_strlen_t len); |
|
|
|
// upb_bytesink. |
|
typedef int32_t (*upb_bytesink_put_fptr)(upb_bytesink *sink, upb_string *str); |
|
|
|
// Vtables for the above interfaces. |
|
typedef struct { |
|
upb_bytesrc_get_fptr get; |
|
upb_bytesrc_append_fptr append; |
|
} upb_bytesrc_vtable; |
|
|
|
typedef struct { |
|
upb_bytesink_put_fptr put; |
|
} upb_bytesink_vtable; |
|
|
|
// "Base Class" definitions; components that implement these interfaces should |
|
// contain one of these structures. |
|
|
|
struct _upb_bytesrc { |
|
upb_bytesrc_vtable *vtbl; |
|
upb_status status; |
|
bool eof; |
|
}; |
|
|
|
struct _upb_bytesink { |
|
upb_bytesink_vtable *vtbl; |
|
upb_status status; |
|
bool eof; |
|
}; |
|
|
|
INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtable *vtbl) { |
|
s->vtbl = vtbl; |
|
s->eof = false; |
|
upb_status_init(&s->status); |
|
} |
|
|
|
INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtable *vtbl) { |
|
s->vtbl = vtbl; |
|
s->eof = false; |
|
upb_status_init(&s->status); |
|
} |
|
|
|
// Implementation of virtual function dispatch. |
|
|
|
// upb_bytesrc |
|
INLINE bool upb_bytesrc_get( |
|
upb_bytesrc *bytesrc, upb_string *str, upb_strlen_t minlen) { |
|
return bytesrc->vtbl->get(bytesrc, str, minlen); |
|
} |
|
|
|
INLINE bool upb_bytesrc_append( |
|
upb_bytesrc *bytesrc, upb_string *str, upb_strlen_t len) { |
|
return bytesrc->vtbl->append(bytesrc, str, len); |
|
} |
|
|
|
INLINE upb_status *upb_bytesrc_status(upb_bytesrc *src) { return &src->status; } |
|
INLINE bool upb_bytesrc_eof(upb_bytesrc *src) { return src->eof; } |
|
|
|
// upb_handlers |
|
struct _upb_handlers { |
|
upb_handlerset *set; |
|
void *closure; |
|
}; |
|
|
|
INLINE void upb_handlers_init(upb_handlers *h) { |
|
(void)h; |
|
} |
|
INLINE void upb_handlers_uninit(upb_handlers *h) { |
|
(void)h; |
|
} |
|
|
|
INLINE void upb_handlers_reset(upb_handlers *h) { |
|
h->set = NULL; |
|
h->closure = NULL; |
|
} |
|
|
|
INLINE bool upb_handlers_isempty(upb_handlers *h) { |
|
return !h->set && !h->closure; |
|
} |
|
|
|
INLINE void upb_register_handlerset(upb_handlers *h, upb_handlerset *set) { |
|
h->set = set; |
|
} |
|
|
|
INLINE void upb_set_handler_closure(upb_handlers *h, void *closure) { |
|
h->closure = closure; |
|
} |
|
|
|
// upb_dispatcher |
|
typedef struct { |
|
upb_handlers handlers; |
|
int depth; |
|
} upb_dispatcher_frame; |
|
|
|
struct _upb_dispatcher { |
|
upb_dispatcher_frame stack[UPB_MAX_NESTING], *top, *limit; |
|
}; |
|
|
|
INLINE void upb_dispatcher_init(upb_dispatcher *d) { |
|
d->limit = d->stack + sizeof(d->stack); |
|
} |
|
|
|
INLINE void upb_dispatcher_reset(upb_dispatcher *d, upb_handlers *h) { |
|
d->top = d->stack; |
|
d->top->depth = 1; // Never want to trigger end-of-delegation. |
|
d->top->handlers = *h; |
|
} |
|
|
|
INLINE void upb_dispatch_startmsg(upb_dispatcher *d) { |
|
assert(d->stack == d->top); |
|
d->top->handlers.set->startmsg(d->top->handlers.closure); |
|
} |
|
|
|
INLINE void upb_dispatch_endmsg(upb_dispatcher *d) { |
|
assert(d->stack == d->top); |
|
d->top->handlers.set->endmsg(d->top->handlers.closure); |
|
} |
|
|
|
INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, |
|
struct _upb_fielddef *f) { |
|
upb_handlers handlers; |
|
upb_handlers_init(&handlers); |
|
upb_handlers_reset(&handlers); |
|
upb_flow_t ret = d->top->handlers.set->startsubmsg(d->top->handlers.closure, f, &handlers); |
|
assert((ret == UPB_DELEGATE) == !upb_handlers_isempty(&handlers)); |
|
if (ret == UPB_DELEGATE) { |
|
++d->top; |
|
d->top->handlers = handlers; |
|
d->top->depth = 0; |
|
d->top->handlers.set->startmsg(d->top->handlers.closure); |
|
ret = UPB_CONTINUE; |
|
} |
|
++d->top->depth; |
|
upb_handlers_uninit(&handlers); |
|
return ret; |
|
} |
|
|
|
INLINE upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d) { |
|
if (--d->top->depth == 0) { |
|
d->top->handlers.set->endmsg(d->top->handlers.closure); |
|
--d->top; |
|
} |
|
return d->top->handlers.set->endsubmsg(d->top->handlers.closure); |
|
} |
|
|
|
INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, |
|
struct _upb_fielddef *f, |
|
upb_value val) { |
|
return d->top->handlers.set->value(d->top->handlers.closure, f, val); |
|
} |
|
|
|
INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d, |
|
upb_field_number_t fieldnum, |
|
upb_value val) { |
|
return d->top->handlers.set->unknownval(d->top->handlers.closure, |
|
fieldnum, val); |
|
} |
|
|
|
// upb_bytesink |
|
INLINE int32_t upb_bytesink_put(upb_bytesink *sink, upb_string *str) { |
|
return sink->vtbl->put(sink, str); |
|
} |
|
INLINE upb_status *upb_bytesink_status(upb_bytesink *sink) { |
|
return &sink->status; |
|
} |
|
|
|
// upb_bytesink |
|
|
|
|
|
#ifdef __cplusplus |
|
} /* extern "C" */ |
|
#endif |
|
|
|
#endif
|
|
|