upbc compiles and links! But probably doesn't work yet.

pull/13171/head
Joshua Haberman 15 years ago
parent f6cc21bc2d
commit c33d51581a
  1. 28
      src/upb.h
  2. 138
      src/upb_data.c
  3. 34
      src/upb_data.h
  4. 117
      src/upb_parse.c
  5. 10
      src/upb_parse.h

@ -13,6 +13,7 @@
#include <stdint.h>
#include <stdio.h> // only for size_t.
#include "descriptor_const.h"
#include "upb_atomic.h"
#ifdef __cplusplus
extern "C" {
@ -124,13 +125,14 @@ struct upb_tag {
// INTERNAL-ONLY: never refer to these types with a tag ("union", "struct").
// Always use the typedefs.
union upb_string;
union upb_array;
struct upb_msg;
union _upb_string;
union _upb_array;
struct _upb_msg;
typedef union upb_string upb_string;
typedef union upb_array upb_array;
typedef struct upb_msg upb_msg;
typedef union _upb_string upb_string;
typedef union _upb_array upb_array;
typedef struct _upb_msg upb_msg;
typedef upb_atomic_refcount_t upb_data;
// A single .proto value. The owner must have an out-of-band way of knowing
// the type, so that it knows which union member to use.
@ -142,9 +144,10 @@ union upb_value {
uint32_t uint32;
uint64_t uint64;
bool _bool;
union upb_string *str;
union upb_array *arr;
struct upb_msg *msg;
upb_string *str;
upb_array *arr;
upb_msg *msg;
upb_data *data;
};
// A pointer to a .proto value. The owner must have an out-of-band way of
@ -158,9 +161,10 @@ union upb_value_ptr {
uint32_t *uint32;
uint64_t *uint64;
bool *_bool;
union upb_string **str;
union upb_array **arr;
struct upb_msg **msg;
upb_string **str;
upb_array **arr;
upb_msg **msg;
upb_data **data;
void *_void;
};

@ -7,6 +7,7 @@
#include <stdlib.h>
#include "upb_data.h"
#include "upb_def.h"
#include "upb_parse.h"
static uint32_t round_up_to_pow2(uint32_t v)
{
@ -51,6 +52,18 @@ static void check_not_frozen(upb_data *d) {
if(upb_data_hasflag(d, UPB_DATA_FROZEN)) abort();
}
/* upb_string *******************************************************************/
upb_string *upb_string_new() {
upb_string *s = malloc(sizeof(upb_refcounted_string));
data_init(&s->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
s->refcounted.byte_size = 0;
s->common.byte_len = 0;
s->common.ptr = NULL;
return s;
}
static upb_strlen_t string_get_bytesize(upb_string *s) {
if(upb_data_hasflag(&s->common.base, UPB_DATA_REFCOUNTED)) {
return s->refcounted.byte_size;
@ -68,18 +81,6 @@ static void string_set_bytesize(upb_string *s, upb_strlen_t newsize) {
}
}
/* upb_string *******************************************************************/
upb_string *upb_string_new() {
upb_string *s = malloc(sizeof(upb_refcounted_string));
data_init(&s->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
s->refcounted.byte_size = 0;
s->common.byte_len = 0;
s->common.ptr = NULL;
return s;
}
void _upb_string_free(upb_string *s)
{
if(string_get_bytesize(s) != 0) free(s->common.ptr);
@ -136,11 +137,6 @@ void upb_strcat(upb_string *s, upb_string *append) {
upb_string_getrobuf(append), append_len);
}
void upb_strcpy(upb_string *dest, upb_string *src) {
upb_strlen_t src_len = upb_strlen(src);
memcpy(upb_string_getrwbuf(dest, src_len), upb_string_getrobuf(src), src_len);
}
upb_string *upb_strslice(upb_string *s, int offset, int len) {
upb_string *slice = upb_string_new();
len = UPB_MIN((upb_strlen_t)len, upb_strlen(s) - (upb_strlen_t)offset);
@ -165,6 +161,15 @@ int upb_strcmp(upb_string *s1, upb_string *s2) {
/* upb_array ******************************************************************/
upb_array *upb_array_new() {
upb_array *a = malloc(sizeof(upb_refcounted_array));
data_init(&a->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
a->refcounted.size = 0;
a->common.len = 0;
a->common.elements._void = NULL;
return a;
}
// ONLY handles refcounted arrays for the moment.
void _upb_array_free(upb_array *a, struct upb_fielddef *f)
{
@ -178,9 +183,42 @@ void _upb_array_free(upb_array *a, struct upb_fielddef *f)
free(a);
}
static upb_arraylen_t array_get_size(upb_array *a) {
if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) {
return a->refcounted.size;
} else {
return (a->norefcount.size_and_flags & 0xFFFFFFF8) >> 3;
}
}
static void array_set_size(upb_array *a, upb_arraylen_t newsize) {
if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) {
a->refcounted.size = newsize;
} else {
a->norefcount.size_and_flags &= 0x7;
a->norefcount.size_and_flags |= (newsize << 3);
}
}
void upb_array_resize(upb_array *a, upb_strlen_t len) {
check_not_frozen(&a->common.base);
if(array_get_size(a) < len) {
// Need to resize.
size_t new_size = round_up_to_pow2(len);
a->common.elements._void = realloc(a->common.elements._void, new_size);
array_set_size(a, new_size);
}
a->common.len = len;
}
/* upb_msg ********************************************************************/
static void upb_msg_sethas(upb_msg *msg, struct upb_fielddef *f) {
msg->data[f->field_index/8] |= (1 << (f->field_index % 8));
}
upb_msg *upb_msg_new(struct upb_msgdef *md) {
upb_msg *msg = malloc(md->size);
memset(msg, 0, md->size);
@ -219,74 +257,75 @@ struct upb_msgparser {
/* Helper function that returns a pointer to where the next value for field "f"
* should be stored, taking into account whether f is an array that may need to
* be allocated or resized. */
static union upb_value_ptr get_value_ptr(struct upb_msg *msg,
struct upb_fielddef *f)
static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f)
{
union upb_value_ptr p = upb_msg_getptr(msg, f);
union upb_value_ptr p = _upb_msg_getptr(msg, f);
if(upb_isarray(f)) {
if(!upb_msg_isset(msg, f)) {
if(!*p.arr || !upb_mmhead_only(&((*p.arr)->mmhead))) {
if(!upb_msg_has(msg, f)) {
if(!*p.arr || !upb_data_only(*p.data)) {
if(*p.arr)
upb_array_unref(*p.arr);
*p.arr = upb_array_new(f);
upb_array_unref(*p.arr, f);
*p.arr = upb_array_new();
}
upb_array_truncate(*p.arr);
upb_msg_set(msg, f);
upb_msg_sethas(msg, f);
}
p = upb_array_append(*p.arr);
upb_arraylen_t oldlen = upb_array_len(*p.arr);
upb_array_resize(*p.arr, oldlen + 1);
p = _upb_array_getptr(*p.arr, f, oldlen);
}
return p;
}
/* Callbacks for the stream parser. */
// Callbacks for the stream parser.
// TODO: implement these in terms of public interfaces.
static bool value_cb(void *udata, struct upb_msgdef *msgdef,
struct upb_fielddef *f, union upb_value val)
{
(void)msgdef;
struct upb_msgparser *mp = udata;
struct upb_msg *msg = mp->top->msg;
upb_msg *msg = mp->top->msg;
union upb_value_ptr p = get_value_ptr(msg, f);
upb_msg_set(msg, f);
upb_msg_sethas(msg, f);
upb_value_write(p, val, f->type);
return true;
}
static bool str_cb(void *udata, struct upb_msgdef *msgdef,
struct upb_fielddef *f, uint8_t *str, size_t avail_len,
struct upb_fielddef *f, const uint8_t *str, size_t avail_len,
size_t total_len)
{
(void)msgdef;
struct upb_msgparser *mp = udata;
struct upb_msg *msg = mp->top->msg;
upb_msg *msg = mp->top->msg;
union upb_value_ptr p = get_value_ptr(msg, f);
upb_msg_set(msg, f);
upb_msg_sethas(msg, f);
if(avail_len != total_len) abort(); /* TODO: support streaming. */
if(!*p.str || !upb_mmhead_only(&((*p.str)->mmhead))) {
if(!*p.str || !upb_data_only(*p.data)) {
if(*p.str)
upb_string_unref(*p.str);
*p.str = upb_string_new();
}
upb_string_resize(*p.str, total_len);
memcpy((*p.str)->ptr, str, avail_len);
(*p.str)->byte_len = avail_len;
upb_strcpylen(*p.str, str, avail_len);
return true;
}
static void start_cb(void *udata, struct upb_fielddef *f)
{
struct upb_msgparser *mp = udata;
struct upb_msg *oldmsg = mp->top->msg;
upb_msg *oldmsg = mp->top->msg;
union upb_value_ptr p = get_value_ptr(oldmsg, f);
if(upb_isarray(f) || !upb_msg_isset(oldmsg, f)) {
if(!*p.msg || !upb_mmhead_only(&((*p.msg)->mmhead))) {
if(upb_isarray(f) || !upb_msg_has(oldmsg, f)) {
struct upb_msgdef *md = upb_downcast_msgdef(f->def);
if(!*p.msg || !upb_data_only(*p.data)) {
if(*p.msg)
upb_msg_unref(*p.msg);
*p.msg = upb_msg_new(upb_downcast_msgdef(f->def));
upb_msg_unref(*p.msg, md);
*p.msg = upb_msg_new(md);
}
upb_msg_clear(*p.msg);
upb_msg_set(oldmsg, f);
upb_msg_clear(*p.msg, md);
upb_msg_sethas(oldmsg, f);
}
mp->top++;
@ -308,10 +347,9 @@ struct upb_msgparser *upb_msgparser_new(struct upb_msgdef *def)
return mp;
}
void upb_msgparser_reset(struct upb_msgparser *s, struct upb_msg *msg, bool byref)
void upb_msgparser_reset(struct upb_msgparser *s, upb_msg *msg)
{
upb_cbparser_reset(s->s, s);
s->byref = byref;
s->top = s->stack;
s->top->msg = msg;
}
@ -322,13 +360,13 @@ void upb_msgparser_free(struct upb_msgparser *s)
free(s);
}
void upb_msg_parsestr(struct upb_msg *msg, void *buf, size_t len,
void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_string *str,
struct upb_status *status)
{
struct upb_msgparser *mp = upb_msgparser_new(msg->def);
upb_msgparser_reset(mp, msg, false);
upb_msg_clear(msg);
upb_msgparser_parse(mp, buf, len, status);
struct upb_msgparser *mp = upb_msgparser_new(md);
upb_msgparser_reset(mp, msg);
upb_msg_clear(msg, md);
upb_msgparser_parse(mp, str, status);
upb_msgparser_free(mp);
}

@ -35,7 +35,8 @@ struct upb_fielddef;
// The "base class" of strings, arrays, and messages. Contains a few flags and
// possibly a reference count. None of the functions for upb_data are public,
// but some of the constants are.
typedef upb_atomic_refcount_t upb_data;
// typedef upb_atomic_refcount_t upb_data;
// The flags in upb_data.
typedef enum {
@ -196,7 +197,7 @@ typedef struct {
uint32_t byte_size;
} upb_refcounted_string;
union upb_string {
union _upb_string {
upb_norefcount_string norefcount;
upb_string_common common;
upb_refcounted_string refcounted;
@ -265,8 +266,22 @@ INLINE bool upb_streql(upb_string *s1, upb_string *s2) {
// Like strcmp().
int upb_strcmp(upb_string *s1, upb_string *s2);
// Like upb_strcpy, but copies from a buffer and length.
INLINE void upb_strcpylen(upb_string *dest, const void *src, upb_strlen_t len) {
memcpy(upb_string_getrwbuf(dest, len), src, len);
}
// Replaces the contents of "dest" with the contents of "src".
void upb_strcpy(upb_string *dest, upb_string *src);
INLINE void upb_strcpy(upb_string *dest, upb_string *src) {
upb_strcpylen(dest, upb_string_getrobuf(src), upb_strlen(src));
}
// Like upb_strcpy, but copies from a NULL-terminated string.
INLINE void upb_strcpyc(upb_string *dest, const char *src) {
// This does two passes over src, but that is necessary unless we want to
// repeatedly re-allocate dst, which seems worse.
upb_strcpylen(dest, src, strlen(src));
}
// Returns a new string whose contents are a copy of s.
upb_string *upb_strdup(upb_string *s);
@ -323,7 +338,7 @@ typedef struct {
upb_arraylen_t size;
} upb_refcounted_array;
union upb_array {
union _upb_array {
upb_norefcount_array norefcount;
upb_array_common common;
upb_refcounted_array refcounted;
@ -395,12 +410,17 @@ INLINE size_t upb_array_len(upb_array *a) {
return a->common.len;
}
INLINE void upb_array_truncate(upb_array *a) {
a->common.len = 0;
}
/* upb_msg ********************************************************************/
// Note that some inline functions for upb_msg are defined in upb_def.h since
// they rely on the defs.
struct upb_msg {
struct _upb_msg {
upb_data base;
uint8_t data[4]; // We allocate the appropriate amount per message.
};
@ -444,7 +464,9 @@ INLINE union upb_value upb_msg_get(upb_msg *msg, struct upb_fielddef *f) {
// and will drop a ref on whatever was there before.
void upb_msg_set(upb_msg *msg, struct upb_fielddef *f, union upb_value val);
void upb_msg_clear(upb_msg *msg, struct upb_msgdef *md);
INLINE void upb_msg_clear(upb_msg *msg, struct upb_msgdef *md) {
memset(msg->data, 0, md->set_flags_bytes);
}
/* Parsing ********************************************************************/

@ -18,12 +18,14 @@
// generation, because the generated code would want to inline these functions.
// The same applies to the functions to read .proto values below.
uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val,
struct upb_status *status);
const uint8_t *upb_get_v_uint64_t_full(const uint8_t *buf, const uint8_t *end,
uint64_t *val,
struct upb_status *status);
// Gets a varint (wire type: UPB_WIRE_TYPE_VARINT).
INLINE uint8_t *upb_get_v_uint64_t(uint8_t *buf, uint8_t *end, uint64_t *val,
struct upb_status *status)
INLINE const uint8_t *upb_get_v_uint64_t(const uint8_t *buf, const uint8_t *end,
uint64_t *val,
struct upb_status *status)
{
// We inline this common case (1-byte varints), if that fails we dispatch to
// the full (non-inlined) version.
@ -36,20 +38,21 @@ INLINE uint8_t *upb_get_v_uint64_t(uint8_t *buf, uint8_t *end, uint64_t *val,
}
// Gets a varint -- called when we only need 32 bits of it.
INLINE uint8_t *upb_get_v_uint32_t(uint8_t *buf, uint8_t *end,
uint32_t *val, struct upb_status *status)
INLINE const uint8_t *upb_get_v_uint32_t(const uint8_t *buf, const uint8_t *end,
uint32_t *val,
struct upb_status *status)
{
uint64_t val64;
uint8_t *ret = upb_get_v_uint64_t(buf, end, &val64, status);
const uint8_t *ret = upb_get_v_uint64_t(buf, end, &val64, status);
*val = (uint32_t)val64; // Discard the high bits.
return ret;
}
// Gets a fixed-length 32-bit integer (wire type: UPB_WIRE_TYPE_32BIT).
INLINE uint8_t *upb_get_f_uint32_t(uint8_t *buf, uint8_t *end,
uint32_t *val, struct upb_status *status)
INLINE const uint8_t *upb_get_f_uint32_t(const uint8_t *buf, const uint8_t *end,
uint32_t *val, struct upb_status *status)
{
uint8_t *uint32_end = buf + sizeof(uint32_t);
const uint8_t *uint32_end = buf + sizeof(uint32_t);
if(uint32_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA;
return end;
@ -65,10 +68,11 @@ INLINE uint8_t *upb_get_f_uint32_t(uint8_t *buf, uint8_t *end,
}
// Gets a fixed-length 64-bit integer (wire type: UPB_WIRE_TYPE_64BIT).
INLINE uint8_t *upb_get_f_uint64_t(uint8_t *buf, uint8_t *end,
uint64_t *val, struct upb_status *status)
INLINE const uint8_t *upb_get_f_uint64_t(const uint8_t *buf, const uint8_t *end,
uint64_t *val,
struct upb_status *status)
{
uint8_t *uint64_end = buf + sizeof(uint64_t);
const uint8_t *uint64_end = buf + sizeof(uint64_t);
if(uint64_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA;
return end;
@ -84,10 +88,11 @@ INLINE uint8_t *upb_get_f_uint64_t(uint8_t *buf, uint8_t *end,
return uint64_end;
}
INLINE uint8_t *upb_skip_v_uint64_t(uint8_t *buf, uint8_t *end,
struct upb_status *status)
INLINE const uint8_t *upb_skip_v_uint64_t(const uint8_t *buf,
const uint8_t *end,
struct upb_status *status)
{
uint8_t *const maxend = buf + 10;
const uint8_t *const maxend = buf + 10;
uint8_t last = 0x80;
for(; buf < (uint8_t*)end && (last & 0x80); buf++)
last = *buf;
@ -102,10 +107,11 @@ INLINE uint8_t *upb_skip_v_uint64_t(uint8_t *buf, uint8_t *end,
return buf;
}
INLINE uint8_t *upb_skip_f_uint32_t(uint8_t *buf, uint8_t *end,
struct upb_status *status)
INLINE const uint8_t *upb_skip_f_uint32_t(const uint8_t *buf,
const uint8_t *end,
struct upb_status *status)
{
uint8_t *uint32_end = buf + sizeof(uint32_t);
const uint8_t *uint32_end = buf + sizeof(uint32_t);
if(uint32_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA;
return end;
@ -113,10 +119,11 @@ INLINE uint8_t *upb_skip_f_uint32_t(uint8_t *buf, uint8_t *end,
return uint32_end;
}
INLINE uint8_t *upb_skip_f_uint64_t(uint8_t *buf, uint8_t *end,
struct upb_status *status)
INLINE const uint8_t *upb_skip_f_uint64_t(const uint8_t *buf,
const uint8_t *end,
struct upb_status *status)
{
uint8_t *uint64_end = buf + sizeof(uint64_t);
const uint8_t *uint64_end = buf + sizeof(uint64_t);
if(uint64_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA;
return end;
@ -137,8 +144,8 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); }
// // not contain the entire value UPB_STATUS_NEED_MORE_DATA is returned).
// // On success, a pointer will be returned to the first byte that was
// // not consumed.
// uint8_t *upb_get_INT32(uint8_t *buf, uint8_t *end, int32_t *d,
// struct upb_status *status);
// const uint8_t *upb_get_INT32(const uint8_t *buf, const uint8_t *end,
// int32_t *d, struct upb_status *status);
//
// // Given an already read wire value s (source), convert it to a .proto
// // value and return it.
@ -151,10 +158,10 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); }
INLINE val_t upb_wvtov_ ## type(wire_t s)
#define GET(type, v_or_f, wire_t, val_t, member_name) \
INLINE uint8_t *upb_get_ ## type(uint8_t *buf, uint8_t *end, val_t *d, \
struct upb_status *status) { \
INLINE const uint8_t *upb_get_ ## type(const uint8_t *buf, const uint8_t *end, \
val_t *d, struct upb_status *status) { \
wire_t tmp = 0; \
uint8_t *ret = upb_get_ ## v_or_f ## _ ## wire_t(buf, end, &tmp, status); \
const uint8_t *ret = upb_get_ ## v_or_f ## _ ## wire_t(buf, end, &tmp, status); \
*d = upb_wvtov_ ## type(tmp); \
return ret; \
}
@ -192,11 +199,11 @@ T(FLOAT, f, uint32_t, float, _float) {
#undef T
// Parses a tag, places the result in *tag.
INLINE uint8_t *parse_tag(uint8_t *buf, uint8_t *end, struct upb_tag *tag,
struct upb_status *status)
INLINE const uint8_t *parse_tag(const uint8_t *buf, const uint8_t *end,
struct upb_tag *tag, struct upb_status *status)
{
uint32_t tag_int;
uint8_t *ret = upb_get_v_uint32_t(buf, end, &tag_int, status);
const uint8_t *ret = upb_get_v_uint32_t(buf, end, &tag_int, status);
tag->wire_type = (upb_wire_type_t)(tag_int & 0x07);
tag->field_number = tag_int >> 3;
return ret;
@ -207,10 +214,10 @@ INLINE uint8_t *parse_tag(uint8_t *buf, uint8_t *end, struct upb_tag *tag,
* Parses a 64-bit varint that is known to be >= 2 bytes (the inline version
* handles 1 and 2 byte varints).
*/
uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val,
struct upb_status *status)
const uint8_t *upb_get_v_uint64_t_full(const uint8_t *buf, const uint8_t *end,
uint64_t *val, struct upb_status *status)
{
uint8_t *const maxend = buf + 10;
const uint8_t *const maxend = buf + 10;
uint8_t last = 0x80;
*val = 0;
int bitpos;
@ -231,9 +238,10 @@ uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val,
return buf;
}
uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt,
union upb_wire_value *wv,
struct upb_status *status)
const uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end,
upb_wire_type_t wt,
union upb_wire_value *wv,
struct upb_status *status)
{
switch(wt) {
case UPB_WIRE_TYPE_VARINT:
@ -252,8 +260,9 @@ uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt,
* Advances buf past the current wire value (of type wt), saving the result in
* outbuf.
*/
static uint8_t *skip_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt,
struct upb_status *status)
static const uint8_t *skip_wire_value(const uint8_t *buf, const uint8_t *end,
upb_wire_type_t wt,
struct upb_status *status)
{
switch(wt) {
case UPB_WIRE_TYPE_VARINT:
@ -272,8 +281,10 @@ static uint8_t *skip_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt,
}
}
static uint8_t *upb_parse_value(uint8_t *buf, uint8_t *end, upb_field_type_t ft,
union upb_value_ptr v, struct upb_status *status)
static const uint8_t *upb_parse_value(const uint8_t *buf, const uint8_t *end,
upb_field_type_t ft,
union upb_value_ptr v,
struct upb_status *status)
{
#define CASE(t, member_name) \
case UPB_TYPE(t): return upb_get_ ## t(buf, end, v.member_name, status);
@ -349,7 +360,7 @@ void upb_cbparser_reset(struct upb_cbparser *p, void *udata)
p->top->end_offset = 0;
}
static void *get_msgend(struct upb_cbparser *p, uint8_t *start)
static const void *get_msgend(struct upb_cbparser *p, const uint8_t *start)
{
if(p->top->end_offset > 0)
return start + (p->top->end_offset - p->completed_offset);
@ -357,7 +368,7 @@ static void *get_msgend(struct upb_cbparser *p, uint8_t *start)
return (void*)UINTPTR_MAX; // group.
}
static bool isgroup(void *submsg_end)
static bool isgroup(const void *submsg_end)
{
return submsg_end == (void*)UINTPTR_MAX;
}
@ -374,9 +385,9 @@ INLINE bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) {
* Pushes a new stack frame for a submessage with the given len (which will
* be zero if the submessage is a group).
*/
static uint8_t *push(struct upb_cbparser *p, uint8_t *start,
uint32_t submsg_len, struct upb_fielddef *f,
struct upb_status *status)
static const uint8_t *push(struct upb_cbparser *p, const uint8_t *start,
uint32_t submsg_len, struct upb_fielddef *f,
struct upb_status *status)
{
p->top++;
if(p->top >= p->limit) {
@ -397,7 +408,7 @@ static uint8_t *push(struct upb_cbparser *p, uint8_t *start,
* Pops a stack frame, returning a pointer for where the next submsg should
* end (or a pointer that is out of range for a group).
*/
static void *pop(struct upb_cbparser *p, uint8_t *start)
static const void *pop(struct upb_cbparser *p, const uint8_t *start)
{
if(p->end_cb) p->end_cb(p->udata);
p->top--;
@ -405,18 +416,18 @@ static void *pop(struct upb_cbparser *p, uint8_t *start)
}
size_t upb_cbparser_parse(struct upb_cbparser *p, void *_buf, size_t len,
size_t upb_cbparser_parse(struct upb_cbparser *p, upb_string *str,
struct upb_status *status)
{
// buf is our current offset, moves from start to end.
uint8_t *buf = _buf;
uint8_t *const start = buf; // ptr equivalent of p->completed_offset
uint8_t *end = buf + len;
const uint8_t *buf = (uint8_t*)upb_string_getrobuf(str);
const uint8_t *const start = buf; // ptr equivalent of p->completed_offset
const uint8_t *const end = buf + upb_strlen(str);
// When we have fully parsed a tag/value pair, we advance this.
uint8_t *completed = buf;
const uint8_t *completed = buf;
uint8_t *submsg_end = get_msgend(p, start);
const uint8_t *submsg_end = get_msgend(p, start);
struct upb_msgdef *msgdef = p->top->msgdef;
bool keep_going = true;
@ -453,7 +464,7 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, void *_buf, size_t len,
int32_t delim_len;
buf = upb_get_INT32(buf, end, &delim_len, status);
CHECK_STATUS();
uint8_t *delim_end = buf + delim_len;
const uint8_t *delim_end = buf + delim_len;
if(f && f->type == UPB_TYPE(MESSAGE)) {
submsg_end = push(p, start, delim_end - start, f, status);
msgdef = p->top->msgdef;

@ -40,7 +40,7 @@ typedef bool (*upb_value_cb)(void *udata, struct upb_msgdef *msgdef,
// available at str. If the client is streaming and the current buffer ends in
// the middle of the string, this number could be less than total_len.
typedef bool (*upb_str_cb)(void *udata, struct upb_msgdef *msgdef,
struct upb_fielddef *f, uint8_t *str,
struct upb_fielddef *f, const uint8_t *str,
size_t avail_len, size_t total_len);
// The start and end callbacks are called when a submessage begins and ends,
@ -80,7 +80,7 @@ void upb_cbparser_reset(struct upb_cbparser *p, void *udata);
//
// TODO: see if we can provide the following guarantee efficiently:
// retval will always be >= len. */
size_t upb_cbparser_parse(struct upb_cbparser *p, void *buf, size_t len,
size_t upb_cbparser_parse(struct upb_cbparser *p, upb_string *str,
struct upb_status *status);
/* Pick parser interface. ************************************************/
@ -117,10 +117,10 @@ struct upb_pickparser *upb_pickparser_new(struct upb_msgdef *msgdef,
char *fields[],
upb_pp_value_cb value_cb,
upb_pp_str_cb str_cb);
void upb_pickparser_free(struct upb_cbparser *p);
void upb_pickparser_free(struct upb_pickparser *p);
void upb_pickparser_reset(struct upb_pickparser *p, void *udata);
size_t upb_cbparser_parse(struct upb_cbparser *p, void *buf, size_t len,
struct upb_status *status);
size_t upb_pickparser_parse(struct upb_pickparser *p, upb_string *str,
struct upb_status *status);
#ifdef __cplusplus
} /* extern "C" */

Loading…
Cancel
Save