summaryrefslogtreecommitdiff
path: root/upb/msg.c
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2018-09-06 23:16:58 -0700
committerJosh Haberman <jhaberman@gmail.com>2018-09-06 23:16:58 -0700
commita105c015b106b6be31fc45fdd4c568684815801c (patch)
treebbb66457418d6fd20b585bf23b5f2d61ac46a1bc /upb/msg.c
parentea19fa4ed6af171a787990270871e9dc0fd809f0 (diff)
Added support for unknown fields to upb_msg.
After this CL, upb passes all existing proto3 conformance tests. However the conformance suite is missing a lot of cases and should be fleshed out.
Diffstat (limited to 'upb/msg.c')
-rw-r--r--upb/msg.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/upb/msg.c b/upb/msg.c
index b70fe40..4125d4c 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -113,8 +113,12 @@ static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) {
/* Used when a message is not extendable. */
typedef struct {
- /* TODO(haberman): add unknown fields. */
+ /* TODO(haberman): use pointer tagging so we we are slim when known unknown
+ * fields are not present. */
upb_arena *arena;
+ char *unknown;
+ size_t unknown_len;
+ size_t unknown_size;
} upb_msg_internal;
/* Used when a message is extendable. */
@@ -141,6 +145,25 @@ static upb_msg_internal_withext *upb_msg_getinternalwithext(
return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext));
}
+void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len) {
+ upb_msg_internal* in = upb_msg_getinternal(msg);
+ if (len > in->unknown_size - in->unknown_len) {
+ upb_alloc *alloc = upb_arena_alloc(in->arena);
+ size_t need = in->unknown_size + len;
+ size_t newsize = UPB_MAX(in->unknown_size * 2, need);
+ in->unknown = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
+ in->unknown_size = newsize;
+ }
+ memcpy(in->unknown + in->unknown_len, data, len);
+ in->unknown_len += len;
+}
+
+const char *upb_msg_getunknown(upb_msg *msg, size_t *len) {
+ upb_msg_internal* in = upb_msg_getinternal(msg);
+ *len = in->unknown_len;
+ return in->unknown;
+}
+
static const upb_msglayout_field *upb_msg_checkfield(int field_index,
const upb_msglayout *l) {
UPB_ASSERT(field_index >= 0 && field_index < l->field_count);
@@ -165,6 +188,7 @@ static size_t upb_msg_sizeof(const upb_msglayout *l) {
upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
upb_alloc *alloc = upb_arena_alloc(a);
void *mem = upb_malloc(alloc, upb_msg_sizeof(l));
+ upb_msg_internal *in;
upb_msg *msg;
if (!mem) {
@@ -177,7 +201,11 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
memset(msg, 0, l->size);
/* Initialize internal members. */
- upb_msg_getinternal(msg)->arena = a;
+ in = upb_msg_getinternal(msg);
+ in->arena = a;
+ in->unknown = NULL;
+ in->unknown_len = 0;
+ in->unknown_size = 0;
if (l->extendable) {
upb_msg_getinternalwithext(msg, l)->extdict = NULL;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback