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

@ -7,6 +7,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "upb_data.h" #include "upb_data.h"
#include "upb_def.h" #include "upb_def.h"
#include "upb_parse.h"
static uint32_t round_up_to_pow2(uint32_t v) 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(); 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) { static upb_strlen_t string_get_bytesize(upb_string *s) {
if(upb_data_hasflag(&s->common.base, UPB_DATA_REFCOUNTED)) { if(upb_data_hasflag(&s->common.base, UPB_DATA_REFCOUNTED)) {
return s->refcounted.byte_size; 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) void _upb_string_free(upb_string *s)
{ {
if(string_get_bytesize(s) != 0) free(s->common.ptr); 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); 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 *upb_strslice(upb_string *s, int offset, int len) {
upb_string *slice = upb_string_new(); upb_string *slice = upb_string_new();
len = UPB_MIN((upb_strlen_t)len, upb_strlen(s) - (upb_strlen_t)offset); 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 *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. // ONLY handles refcounted arrays for the moment.
void _upb_array_free(upb_array *a, struct upb_fielddef *f) 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); 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 ********************************************************************/ /* 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 *upb_msg_new(struct upb_msgdef *md) {
upb_msg *msg = malloc(md->size); upb_msg *msg = malloc(md->size);
memset(msg, 0, 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" /* 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 * should be stored, taking into account whether f is an array that may need to
* be allocated or resized. */ * be allocated or resized. */
static union upb_value_ptr get_value_ptr(struct upb_msg *msg, static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f)
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_isarray(f)) {
if(!upb_msg_isset(msg, f)) { if(!upb_msg_has(msg, f)) {
if(!*p.arr || !upb_mmhead_only(&((*p.arr)->mmhead))) { if(!*p.arr || !upb_data_only(*p.data)) {
if(*p.arr) if(*p.arr)
upb_array_unref(*p.arr); upb_array_unref(*p.arr, f);
*p.arr = upb_array_new(f); *p.arr = upb_array_new();
} }
upb_array_truncate(*p.arr); 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; 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, static bool value_cb(void *udata, struct upb_msgdef *msgdef,
struct upb_fielddef *f, union upb_value val) struct upb_fielddef *f, union upb_value val)
{ {
(void)msgdef; (void)msgdef;
struct upb_msgparser *mp = udata; 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); 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); upb_value_write(p, val, f->type);
return true; return true;
} }
static bool str_cb(void *udata, struct upb_msgdef *msgdef, 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) size_t total_len)
{ {
(void)msgdef; (void)msgdef;
struct upb_msgparser *mp = udata; 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); 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(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) if(*p.str)
upb_string_unref(*p.str); upb_string_unref(*p.str);
*p.str = upb_string_new(); *p.str = upb_string_new();
} }
upb_string_resize(*p.str, total_len); upb_strcpylen(*p.str, str, avail_len);
memcpy((*p.str)->ptr, str, avail_len);
(*p.str)->byte_len = avail_len;
return true; return true;
} }
static void start_cb(void *udata, struct upb_fielddef *f) static void start_cb(void *udata, struct upb_fielddef *f)
{ {
struct upb_msgparser *mp = udata; 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); union upb_value_ptr p = get_value_ptr(oldmsg, f);
if(upb_isarray(f) || !upb_msg_isset(oldmsg, f)) { if(upb_isarray(f) || !upb_msg_has(oldmsg, f)) {
if(!*p.msg || !upb_mmhead_only(&((*p.msg)->mmhead))) { struct upb_msgdef *md = upb_downcast_msgdef(f->def);
if(!*p.msg || !upb_data_only(*p.data)) {
if(*p.msg) if(*p.msg)
upb_msg_unref(*p.msg); upb_msg_unref(*p.msg, md);
*p.msg = upb_msg_new(upb_downcast_msgdef(f->def)); *p.msg = upb_msg_new(md);
} }
upb_msg_clear(*p.msg); upb_msg_clear(*p.msg, md);
upb_msg_set(oldmsg, f); upb_msg_sethas(oldmsg, f);
} }
mp->top++; mp->top++;
@ -308,10 +347,9 @@ struct upb_msgparser *upb_msgparser_new(struct upb_msgdef *def)
return mp; 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); upb_cbparser_reset(s->s, s);
s->byref = byref;
s->top = s->stack; s->top = s->stack;
s->top->msg = msg; s->top->msg = msg;
} }
@ -322,13 +360,13 @@ void upb_msgparser_free(struct upb_msgparser *s)
free(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_status *status)
{ {
struct upb_msgparser *mp = upb_msgparser_new(msg->def); struct upb_msgparser *mp = upb_msgparser_new(md);
upb_msgparser_reset(mp, msg, false); upb_msgparser_reset(mp, msg);
upb_msg_clear(msg); upb_msg_clear(msg, md);
upb_msgparser_parse(mp, buf, len, status); upb_msgparser_parse(mp, str, status);
upb_msgparser_free(mp); upb_msgparser_free(mp);
} }

@ -35,7 +35,8 @@ struct upb_fielddef;
// The "base class" of strings, arrays, and messages. Contains a few flags and // 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, // possibly a reference count. None of the functions for upb_data are public,
// but some of the constants are. // 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. // The flags in upb_data.
typedef enum { typedef enum {
@ -196,7 +197,7 @@ typedef struct {
uint32_t byte_size; uint32_t byte_size;
} upb_refcounted_string; } upb_refcounted_string;
union upb_string { union _upb_string {
upb_norefcount_string norefcount; upb_norefcount_string norefcount;
upb_string_common common; upb_string_common common;
upb_refcounted_string refcounted; upb_refcounted_string refcounted;
@ -265,8 +266,22 @@ INLINE bool upb_streql(upb_string *s1, upb_string *s2) {
// Like strcmp(). // Like strcmp().
int upb_strcmp(upb_string *s1, upb_string *s2); 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". // 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. // Returns a new string whose contents are a copy of s.
upb_string *upb_strdup(upb_string *s); upb_string *upb_strdup(upb_string *s);
@ -323,7 +338,7 @@ typedef struct {
upb_arraylen_t size; upb_arraylen_t size;
} upb_refcounted_array; } upb_refcounted_array;
union upb_array { union _upb_array {
upb_norefcount_array norefcount; upb_norefcount_array norefcount;
upb_array_common common; upb_array_common common;
upb_refcounted_array refcounted; upb_refcounted_array refcounted;
@ -395,12 +410,17 @@ INLINE size_t upb_array_len(upb_array *a) {
return a->common.len; return a->common.len;
} }
INLINE void upb_array_truncate(upb_array *a) {
a->common.len = 0;
}
/* upb_msg ********************************************************************/ /* upb_msg ********************************************************************/
// Note that some inline functions for upb_msg are defined in upb_def.h since // Note that some inline functions for upb_msg are defined in upb_def.h since
// they rely on the defs. // they rely on the defs.
struct upb_msg { struct _upb_msg {
upb_data base; upb_data base;
uint8_t data[4]; // We allocate the appropriate amount per message. 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. // 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_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 ********************************************************************/ /* Parsing ********************************************************************/

@ -18,12 +18,14 @@
// generation, because the generated code would want to inline these functions. // generation, because the generated code would want to inline these functions.
// The same applies to the functions to read .proto values below. // 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, const uint8_t *upb_get_v_uint64_t_full(const uint8_t *buf, const uint8_t *end,
struct upb_status *status); uint64_t *val,
struct upb_status *status);
// Gets a varint (wire type: UPB_WIRE_TYPE_VARINT). // 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, INLINE const uint8_t *upb_get_v_uint64_t(const uint8_t *buf, const uint8_t *end,
struct upb_status *status) uint64_t *val,
struct upb_status *status)
{ {
// We inline this common case (1-byte varints), if that fails we dispatch to // We inline this common case (1-byte varints), if that fails we dispatch to
// the full (non-inlined) version. // 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. // 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, INLINE const uint8_t *upb_get_v_uint32_t(const uint8_t *buf, const uint8_t *end,
uint32_t *val, struct upb_status *status) uint32_t *val,
struct upb_status *status)
{ {
uint64_t val64; 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. *val = (uint32_t)val64; // Discard the high bits.
return ret; return ret;
} }
// Gets a fixed-length 32-bit integer (wire type: UPB_WIRE_TYPE_32BIT). // 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, INLINE const uint8_t *upb_get_f_uint32_t(const uint8_t *buf, const uint8_t *end,
uint32_t *val, struct upb_status *status) 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) { if(uint32_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA; status->code = UPB_STATUS_NEED_MORE_DATA;
return end; 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). // 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, INLINE const uint8_t *upb_get_f_uint64_t(const uint8_t *buf, const uint8_t *end,
uint64_t *val, struct upb_status *status) 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) { if(uint64_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA; status->code = UPB_STATUS_NEED_MORE_DATA;
return end; return end;
@ -84,10 +88,11 @@ INLINE uint8_t *upb_get_f_uint64_t(uint8_t *buf, uint8_t *end,
return uint64_end; return uint64_end;
} }
INLINE uint8_t *upb_skip_v_uint64_t(uint8_t *buf, uint8_t *end, INLINE const uint8_t *upb_skip_v_uint64_t(const uint8_t *buf,
struct upb_status *status) 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; uint8_t last = 0x80;
for(; buf < (uint8_t*)end && (last & 0x80); buf++) for(; buf < (uint8_t*)end && (last & 0x80); buf++)
last = *buf; last = *buf;
@ -102,10 +107,11 @@ INLINE uint8_t *upb_skip_v_uint64_t(uint8_t *buf, uint8_t *end,
return buf; return buf;
} }
INLINE uint8_t *upb_skip_f_uint32_t(uint8_t *buf, uint8_t *end, INLINE const uint8_t *upb_skip_f_uint32_t(const uint8_t *buf,
struct upb_status *status) 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) { if(uint32_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA; status->code = UPB_STATUS_NEED_MORE_DATA;
return end; return end;
@ -113,10 +119,11 @@ INLINE uint8_t *upb_skip_f_uint32_t(uint8_t *buf, uint8_t *end,
return uint32_end; return uint32_end;
} }
INLINE uint8_t *upb_skip_f_uint64_t(uint8_t *buf, uint8_t *end, INLINE const uint8_t *upb_skip_f_uint64_t(const uint8_t *buf,
struct upb_status *status) 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) { if(uint64_end > end) {
status->code = UPB_STATUS_NEED_MORE_DATA; status->code = UPB_STATUS_NEED_MORE_DATA;
return end; 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). // // 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 // // On success, a pointer will be returned to the first byte that was
// // not consumed. // // not consumed.
// uint8_t *upb_get_INT32(uint8_t *buf, uint8_t *end, int32_t *d, // const uint8_t *upb_get_INT32(const uint8_t *buf, const uint8_t *end,
// struct upb_status *status); // int32_t *d, struct upb_status *status);
// //
// // Given an already read wire value s (source), convert it to a .proto // // Given an already read wire value s (source), convert it to a .proto
// // value and return it. // // 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) INLINE val_t upb_wvtov_ ## type(wire_t s)
#define GET(type, v_or_f, wire_t, val_t, member_name) \ #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, \ INLINE const uint8_t *upb_get_ ## type(const uint8_t *buf, const uint8_t *end, \
struct upb_status *status) { \ val_t *d, struct upb_status *status) { \
wire_t tmp = 0; \ 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); \ *d = upb_wvtov_ ## type(tmp); \
return ret; \ return ret; \
} }
@ -192,11 +199,11 @@ T(FLOAT, f, uint32_t, float, _float) {
#undef T #undef T
// Parses a tag, places the result in *tag. // Parses a tag, places the result in *tag.
INLINE uint8_t *parse_tag(uint8_t *buf, uint8_t *end, struct upb_tag *tag, INLINE const uint8_t *parse_tag(const uint8_t *buf, const uint8_t *end,
struct upb_status *status) struct upb_tag *tag, struct upb_status *status)
{ {
uint32_t tag_int; 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->wire_type = (upb_wire_type_t)(tag_int & 0x07);
tag->field_number = tag_int >> 3; tag->field_number = tag_int >> 3;
return ret; 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 * Parses a 64-bit varint that is known to be >= 2 bytes (the inline version
* handles 1 and 2 byte varints). * handles 1 and 2 byte varints).
*/ */
uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val, const uint8_t *upb_get_v_uint64_t_full(const uint8_t *buf, const uint8_t *end,
struct upb_status *status) uint64_t *val, struct upb_status *status)
{ {
uint8_t *const maxend = buf + 10; const uint8_t *const maxend = buf + 10;
uint8_t last = 0x80; uint8_t last = 0x80;
*val = 0; *val = 0;
int bitpos; 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; return buf;
} }
uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt, const uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end,
union upb_wire_value *wv, upb_wire_type_t wt,
struct upb_status *status) union upb_wire_value *wv,
struct upb_status *status)
{ {
switch(wt) { switch(wt) {
case UPB_WIRE_TYPE_VARINT: 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 * Advances buf past the current wire value (of type wt), saving the result in
* outbuf. * outbuf.
*/ */
static uint8_t *skip_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt, static const uint8_t *skip_wire_value(const uint8_t *buf, const uint8_t *end,
struct upb_status *status) upb_wire_type_t wt,
struct upb_status *status)
{ {
switch(wt) { switch(wt) {
case UPB_WIRE_TYPE_VARINT: 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, static const uint8_t *upb_parse_value(const uint8_t *buf, const uint8_t *end,
union upb_value_ptr v, struct upb_status *status) upb_field_type_t ft,
union upb_value_ptr v,
struct upb_status *status)
{ {
#define CASE(t, member_name) \ #define CASE(t, member_name) \
case UPB_TYPE(t): return upb_get_ ## t(buf, end, v.member_name, status); 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; 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) if(p->top->end_offset > 0)
return start + (p->top->end_offset - p->completed_offset); 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. return (void*)UINTPTR_MAX; // group.
} }
static bool isgroup(void *submsg_end) static bool isgroup(const void *submsg_end)
{ {
return submsg_end == (void*)UINTPTR_MAX; 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 * Pushes a new stack frame for a submessage with the given len (which will
* be zero if the submessage is a group). * be zero if the submessage is a group).
*/ */
static uint8_t *push(struct upb_cbparser *p, uint8_t *start, static const uint8_t *push(struct upb_cbparser *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++; p->top++;
if(p->top >= p->limit) { 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 * 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). * 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); if(p->end_cb) p->end_cb(p->udata);
p->top--; 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) struct upb_status *status)
{ {
// buf is our current offset, moves from start to end. // buf is our current offset, moves from start to end.
uint8_t *buf = _buf; const uint8_t *buf = (uint8_t*)upb_string_getrobuf(str);
uint8_t *const start = buf; // ptr equivalent of p->completed_offset const uint8_t *const start = buf; // ptr equivalent of p->completed_offset
uint8_t *end = buf + len; const uint8_t *const end = buf + upb_strlen(str);
// When we have fully parsed a tag/value pair, we advance this. // 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; struct upb_msgdef *msgdef = p->top->msgdef;
bool keep_going = true; 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; int32_t delim_len;
buf = upb_get_INT32(buf, end, &delim_len, status); buf = upb_get_INT32(buf, end, &delim_len, status);
CHECK_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)) { if(f && f->type == UPB_TYPE(MESSAGE)) {
submsg_end = push(p, start, delim_end - start, f, status); submsg_end = push(p, start, delim_end - start, f, status);
msgdef = p->top->msgdef; 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 // 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. // the middle of the string, this number could be less than total_len.
typedef bool (*upb_str_cb)(void *udata, struct upb_msgdef *msgdef, 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); size_t avail_len, size_t total_len);
// 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,
@ -80,7 +80,7 @@ void upb_cbparser_reset(struct upb_cbparser *p, void *udata);
// //
// TODO: see if we can provide the following guarantee efficiently: // TODO: see if we can provide the following guarantee efficiently:
// retval will always be >= len. */ // 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); struct upb_status *status);
/* Pick parser interface. ************************************************/ /* Pick parser interface. ************************************************/
@ -117,10 +117,10 @@ struct upb_pickparser *upb_pickparser_new(struct upb_msgdef *msgdef,
char *fields[], char *fields[],
upb_pp_value_cb value_cb, upb_pp_value_cb value_cb,
upb_pp_str_cb str_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); void upb_pickparser_reset(struct upb_pickparser *p, void *udata);
size_t upb_cbparser_parse(struct upb_cbparser *p, void *buf, size_t len, size_t upb_pickparser_parse(struct upb_pickparser *p, upb_string *str,
struct upb_status *status); struct upb_status *status);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

Loading…
Cancel
Save