summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2019-03-27 12:52:33 -0700
committerGitHub <noreply@github.com>2019-03-27 12:52:33 -0700
commit928ef7f2c02f18d9945dd750884dffbdebef1b98 (patch)
treed3b71619bfa0b8a91854045c01ce8b5cd15ae403 /upb
parent00f96cb9475228ecacd9be1660f4f8d9d7b24038 (diff)
Removed reflection and other extraneous things from the core library. (#158)
* Removed reflection and other extraneous things from the core library. * Added missing files and ran buildifier. * New CMakeLists.txt. * Made table its own cc_library() for internal usage.
Diffstat (limited to 'upb')
-rw-r--r--upb/bindings/lua/msg.c2
-rw-r--r--upb/decode.c158
-rw-r--r--upb/def.c66
-rw-r--r--upb/encode.c6
-rw-r--r--upb/generated_util.h1
-rw-r--r--upb/handlers.c19
-rw-r--r--upb/handlers.h6
-rw-r--r--upb/json/parser.c140
-rw-r--r--upb/json/parser.rl2
-rw-r--r--upb/legacy_msg_reflection.c401
-rw-r--r--upb/legacy_msg_reflection.h186
-rw-r--r--upb/msg.c437
-rw-r--r--upb/msg.h248
-rw-r--r--upb/msgfactory.c1
-rw-r--r--upb/structs.int.h20
-rw-r--r--upb/upb.h28
16 files changed, 815 insertions, 906 deletions
diff --git a/upb/bindings/lua/msg.c b/upb/bindings/lua/msg.c
index df5a143..1e5e47c 100644
--- a/upb/bindings/lua/msg.c
+++ b/upb/bindings/lua/msg.c
@@ -7,9 +7,11 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
+
#include "lauxlib.h"
#include "upb/bindings/lua/upb.h"
#include "upb/handlers.h"
+#include "upb/legacy_msg_reflection.h"
#include "upb/msg.h"
/*
diff --git a/upb/decode.c b/upb/decode.c
index 8ea0573..996f36a 100644
--- a/upb/decode.c
+++ b/upb/decode.c
@@ -2,7 +2,6 @@
#include <string.h>
#include "upb/upb.h"
#include "upb/decode.h"
-#include "upb/structs.int.h"
/* Maps descriptor type -> upb field type. */
const uint8_t upb_desctype_to_fieldtype[] = {
@@ -164,7 +163,7 @@ static bool upb_skip_unknownfielddata(upb_decstate *d, upb_decframe *frame,
return false;
}
-static bool upb_array_grow(upb_array *arr, size_t elements) {
+static bool upb_array_grow(upb_array *arr, size_t elements, size_t elem_size) {
size_t needed = arr->len + elements;
size_t new_size = UPB_MAX(arr->size, 8);
size_t new_bytes;
@@ -176,8 +175,8 @@ static bool upb_array_grow(upb_array *arr, size_t elements) {
new_size *= 2;
}
- old_bytes = arr->len * arr->element_size;
- new_bytes = new_size * arr->element_size;
+ old_bytes = arr->len * elem_size;
+ new_bytes = new_size * elem_size;
new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes);
CHK(new_data);
@@ -186,17 +185,23 @@ static bool upb_array_grow(upb_array *arr, size_t elements) {
return true;
}
-static void *upb_array_reserve(upb_array *arr, size_t elements) {
+static void *upb_array_reserve(upb_array *arr, size_t elements,
+ size_t elem_size) {
if (arr->size - arr->len < elements) {
- CHK(upb_array_grow(arr, elements));
+ if (!upb_array_grow(arr, elements, elem_size)) return NULL;
}
- return (char*)arr->data + (arr->len * arr->element_size);
+ return (char*)arr->data + (arr->len * elem_size);
}
-static void *upb_array_add(upb_array *arr, size_t elements) {
- void *ret = upb_array_reserve(arr, elements);
+bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size,
+ const void *data) {
+ void *dest = upb_array_reserve(arr, elements, elem_size);
+
+ CHK(dest);
arr->len += elements;
- return ret;
+ memcpy(dest, data, elements * elem_size);
+
+ return true;
}
static upb_array *upb_getarr(upb_decframe *frame,
@@ -234,17 +239,20 @@ static void upb_setoneofcase(upb_decframe *frame,
upb_set32(frame->msg, ~field->presence, field->number);
}
-static char *upb_decode_prepareslot(upb_decframe *frame,
- const upb_msglayout_field *field) {
+static bool upb_decode_addval(upb_decframe *frame,
+ const upb_msglayout_field *field, void *val,
+ size_t size) {
char *field_mem = frame->msg + field->offset;
upb_array *arr;
if (field->label == UPB_LABEL_REPEATED) {
arr = upb_getorcreatearr(frame, field);
- field_mem = upb_array_reserve(arr, 1);
+ field_mem = upb_array_reserve(arr, 1, size);
+ CHK(field_mem);
}
- return field_mem;
+ memcpy(field_mem, val, size);
+ return true;
}
static void upb_decode_setpresent(upb_decframe *frame,
@@ -264,21 +272,15 @@ static bool upb_decode_submsg(upb_decstate *d, upb_decframe *frame,
const char *limit,
const upb_msglayout_field *field,
int group_number) {
- char *submsg_slot = upb_decode_prepareslot(frame, field);
- char *submsg = *(void **)submsg_slot;
- const upb_msglayout *subm;
-
- subm = frame->m->submsgs[field->submsg_index];
- UPB_ASSERT(subm);
+ upb_msg **submsg = (void*)(frame->msg + field->offset);
+ const upb_msglayout *subm = frame->m->submsgs[field->submsg_index];
- if (!submsg) {
- submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
- CHK(submsg);
- *(void**)submsg_slot = submsg;
+ if (!*submsg) {
+ *submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
+ CHK(*submsg);
}
- upb_decode_message(d, limit, group_number, submsg, subm);
-
+ upb_decode_message(d, limit, group_number, *submsg, subm);
return true;
}
@@ -286,37 +288,33 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
const upb_msglayout_field *field) {
uint64_t val;
- void *field_mem;
-
- field_mem = upb_decode_prepareslot(frame, field);
- CHK(field_mem);
CHK(upb_decode_varint(&d->ptr, frame->limit, &val));
- switch ((upb_descriptortype_t)field->descriptortype) {
+ switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_INT64:
case UPB_DESCRIPTOR_TYPE_UINT64:
- memcpy(field_mem, &val, sizeof(val));
+ CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break;
case UPB_DESCRIPTOR_TYPE_INT32:
case UPB_DESCRIPTOR_TYPE_UINT32:
case UPB_DESCRIPTOR_TYPE_ENUM: {
uint32_t val32 = val;
- memcpy(field_mem, &val32, sizeof(val32));
+ CHK(upb_decode_addval(frame, field, &val32, sizeof(val32)));
break;
}
case UPB_DESCRIPTOR_TYPE_BOOL: {
bool valbool = val != 0;
- memcpy(field_mem, &valbool, sizeof(valbool));
+ CHK(upb_decode_addval(frame, field, &valbool, sizeof(valbool)));
break;
}
case UPB_DESCRIPTOR_TYPE_SINT32: {
int32_t decoded = upb_zzdecode_32(val);
- memcpy(field_mem, &decoded, sizeof(decoded));
+ CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded)));
break;
}
case UPB_DESCRIPTOR_TYPE_SINT64: {
int64_t decoded = upb_zzdecode_64(val);
- memcpy(field_mem, &decoded, sizeof(decoded));
+ CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded)));
break;
}
default:
@@ -330,18 +328,14 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame,
static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
const upb_msglayout_field *field) {
- void *field_mem;
uint64_t val;
-
- field_mem = upb_decode_prepareslot(frame, field);
- CHK(field_mem);
CHK(upb_decode_64bit(&d->ptr, frame->limit, &val));
- switch ((upb_descriptortype_t)field->descriptortype) {
+ switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_DOUBLE:
case UPB_DESCRIPTOR_TYPE_FIXED64:
case UPB_DESCRIPTOR_TYPE_SFIXED64:
- memcpy(field_mem, &val, sizeof(val));
+ CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break;
default:
return upb_append_unknown(d, frame, field_start);
@@ -354,18 +348,14 @@ static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame,
static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
const upb_msglayout_field *field) {
- void *field_mem;
uint32_t val;
-
- field_mem = upb_decode_prepareslot(frame, field);
- CHK(field_mem);
CHK(upb_decode_32bit(&d->ptr, frame->limit, &val));
- switch ((upb_descriptortype_t)field->descriptortype) {
+ switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_FLOAT:
case UPB_DESCRIPTOR_TYPE_FIXED32:
case UPB_DESCRIPTOR_TYPE_SFIXED32:
- memcpy(field_mem, &val, sizeof(val));
+ CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break;
default:
return upb_append_unknown(d, frame, field_start);
@@ -377,13 +367,11 @@ static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame,
static bool upb_decode_fixedpacked(upb_array *arr, upb_strview data,
int elem_size) {
- int elements = data.size / elem_size;
- void *field_mem;
+ size_t elements = data.size / elem_size;
CHK((size_t)(elements * elem_size) == data.size);
- field_mem = upb_array_add(arr, elements);
- CHK(field_mem);
- memcpy(field_mem, data.data, data.size);
+ CHK(upb_array_add(arr, elements, elem_size, data.data));
+
return true;
}
@@ -393,29 +381,24 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
upb_strview val) {
upb_array *arr = upb_getorcreatearr(frame, field);
-#define VARINT_CASE(ctype, decode) { \
- const char *ptr = val.data; \
- const char *limit = ptr + val.size; \
- while (ptr < limit) { \
- uint64_t val; \
- void *field_mem; \
- ctype decoded; \
- CHK(upb_decode_varint(&ptr, limit, &val)); \
- decoded = (decode)(val); \
- field_mem = upb_array_add(arr, 1); \
- CHK(field_mem); \
- memcpy(field_mem, &decoded, sizeof(ctype)); \
- } \
- return true; \
-}
-
- switch ((upb_descriptortype_t)field->descriptortype) {
+#define VARINT_CASE(ctype, decode) \
+ { \
+ const char *ptr = val.data; \
+ const char *limit = ptr + val.size; \
+ while (ptr < limit) { \
+ uint64_t val; \
+ ctype decoded; \
+ CHK(upb_decode_varint(&ptr, limit, &val)); \
+ decoded = (decode)(val); \
+ CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded)); \
+ } \
+ return true; \
+ }
+
+ switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: {
- void *field_mem = upb_array_add(arr, 1);
- CHK(field_mem);
- memcpy(field_mem, &val, sizeof(val));
- return true;
+ return upb_array_add(arr, 1, sizeof(val), &val);
}
case UPB_DESCRIPTOR_TYPE_FLOAT:
case UPB_DESCRIPTOR_TYPE_FIXED32:
@@ -428,7 +411,6 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
case UPB_DESCRIPTOR_TYPE_INT32:
case UPB_DESCRIPTOR_TYPE_UINT32:
case UPB_DESCRIPTOR_TYPE_ENUM:
- /* TODO: proto2 enum field that isn't in the enum. */
VARINT_CASE(uint32_t, uint32_t);
case UPB_DESCRIPTOR_TYPE_INT64:
case UPB_DESCRIPTOR_TYPE_UINT64:
@@ -440,24 +422,14 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
case UPB_DESCRIPTOR_TYPE_SINT64:
VARINT_CASE(int64_t, upb_zzdecode_64);
case UPB_DESCRIPTOR_TYPE_MESSAGE: {
- const upb_msglayout *subm;
- char *submsg;
- void *field_mem;
-
- CHK(val.size <= (size_t)(frame->limit - val.data));
- d->ptr -= val.size;
-
- /* Create elemente message. */
- subm = frame->m->submsgs[field->submsg_index];
- UPB_ASSERT(subm);
+ const upb_msglayout *subm = frame->m->submsgs[field->submsg_index];
+ upb_msg *submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
- submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
CHK(submsg);
+ CHK(val.size <= (size_t)(frame->limit - val.data));
+ upb_array_add(arr, 1, sizeof(submsg), &submsg);
- field_mem = upb_array_add(arr, 1);
- CHK(field_mem);
- *(void**)field_mem = submsg;
-
+ d->ptr -= val.size;
return upb_decode_message(
d, val.data + val.size, frame->group_number, submsg, subm);
}
@@ -478,12 +450,10 @@ static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame,
if (field->label == UPB_LABEL_REPEATED) {
return upb_decode_toarray(d, frame, field_start, field, val);
} else {
- switch ((upb_descriptortype_t)field->descriptortype) {
+ switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: {
- void *field_mem = upb_decode_prepareslot(frame, field);
- CHK(field_mem);
- memcpy(field_mem, &val, sizeof(val));
+ CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break;
}
case UPB_DESCRIPTOR_TYPE_MESSAGE:
diff --git a/upb/def.c b/upb/def.c
index 8d40b8e..6721bcb 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -6,7 +6,6 @@
#include <stdlib.h>
#include <string.h>
#include "google/protobuf/descriptor.upb.h"
-#include "upb/handlers.h"
typedef struct {
size_t len;
@@ -206,6 +205,30 @@ int cmp_fields(const void *p1, const void *p2) {
return field_rank(f1) - field_rank(f2);
}
+/* A few implementation details of handlers. We put these here to avoid
+ * a def -> handlers dependency. */
+
+#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/handlers.h. */
+
+static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
+ return upb_fielddef_isseq(f) ? 2 : 0;
+}
+
+static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
+ uint32_t ret = 1;
+ if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */
+ if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
+ if (upb_fielddef_issubmsg(f)) {
+ /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
+ ret += 0;
+ if (upb_fielddef_lazy(f)) {
+ /* STARTSTR/ENDSTR/STRING (for lazy) */
+ ret += 3;
+ }
+ }
+ return ret;
+}
+
static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
/* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the
* lowest indexes, but we do not publicly guarantee this. */
@@ -251,47 +274,6 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
}
m->selector_count = selector;
-#ifndef NDEBUG
- {
- /* Verify that all selectors for the message are distinct. */
-#define TRY(type) \
- if (upb_handlers_getselector(f, type, &sel)) { upb_inttable_insert(&t, sel, v); }
-
- upb_inttable t;
- upb_value v;
- upb_selector_t sel;
-
- upb_inttable_init(&t, UPB_CTYPE_BOOL);
- v = upb_value_bool(true);
- upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
- upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v);
- upb_inttable_insert(&t, UPB_UNKNOWN_SELECTOR, v);
- for(upb_msg_field_begin(&j, m);
- !upb_msg_field_done(&j);
- upb_msg_field_next(&j)) {
- upb_fielddef *f = upb_msg_iter_field(&j);
- /* These calls will assert-fail in upb_table if the value already
- * exists. */
- TRY(UPB_HANDLER_INT32);
- TRY(UPB_HANDLER_INT64)
- TRY(UPB_HANDLER_UINT32)
- TRY(UPB_HANDLER_UINT64)
- TRY(UPB_HANDLER_FLOAT)
- TRY(UPB_HANDLER_DOUBLE)
- TRY(UPB_HANDLER_BOOL)
- TRY(UPB_HANDLER_STARTSTR)
- TRY(UPB_HANDLER_STRING)
- TRY(UPB_HANDLER_ENDSTR)
- TRY(UPB_HANDLER_STARTSUBMSG)
- TRY(UPB_HANDLER_ENDSUBMSG)
- TRY(UPB_HANDLER_STARTSEQ)
- TRY(UPB_HANDLER_ENDSEQ)
- }
- upb_inttable_uninit(&t);
- }
-#undef TRY
-#endif
-
for(upb_msg_oneof_begin(&k, m), i = 0;
!upb_msg_oneof_done(&k);
upb_msg_oneof_next(&k), i++) {
diff --git a/upb/encode.c b/upb/encode.c
index 18b35d9..2bcf550 100644
--- a/upb/encode.c
+++ b/upb/encode.c
@@ -1,9 +1,11 @@
/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
+#include "upb/encode.h"
+
#include <string.h>
+
+#include "upb/msg.h"
#include "upb/upb.h"
-#include "upb/encode.h"
-#include "upb/structs.int.h"
#define UPB_PB_VARINT_MAX_LEN 10
#define CHK(x) do { if (!(x)) { return false; } } while(0)
diff --git a/upb/generated_util.h b/upb/generated_util.h
index 657280f..0d5e6ba 100644
--- a/upb/generated_util.h
+++ b/upb/generated_util.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include "upb/msg.h"
-#include "upb/structs.int.h"
#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
diff --git a/upb/handlers.c b/upb/handlers.c
index 7abf948..a452663 100644
--- a/upb/handlers.c
+++ b/upb/handlers.c
@@ -368,25 +368,6 @@ bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
return true;
}
-uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
- return upb_fielddef_isseq(f) ? 2 : 0;
-}
-
-uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
- uint32_t ret = 1;
- if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */
- if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
- if (upb_fielddef_issubmsg(f)) {
- /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
- ret += 0;
- if (upb_fielddef_lazy(f)) {
- /* STARTSTR/ENDSTR/STRING (for lazy) */
- ret += 3;
- }
- }
- return ret;
-}
-
/* upb_handlercache ***********************************************************/
struct upb_handlercache {
diff --git a/upb/handlers.h b/upb/handlers.h
index e267f12..cedd977 100644
--- a/upb/handlers.h
+++ b/upb/handlers.h
@@ -76,7 +76,7 @@ typedef int32_t upb_selector_t;
#define UPB_STARTMSG_SELECTOR 0
#define UPB_ENDMSG_SELECTOR 1
#define UPB_UNKNOWN_SELECTOR 2
-#define UPB_STATIC_SELECTOR_COUNT 3
+#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/def.c. */
/* Static selectors for upb::BytesHandler. */
#define UPB_STARTSTR_SELECTOR 0
@@ -233,10 +233,6 @@ UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
return start + 1;
}
-/* Internal-only. */
-uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
-uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
-
#ifdef __cplusplus
} /* extern "C" */
diff --git a/upb/json/parser.c b/upb/json/parser.c
index db7f14f..4040370 100644
--- a/upb/json/parser.c
+++ b/upb/json/parser.c
@@ -1533,7 +1533,6 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
static int parse_timestamp_number(upb_json_parser *p) {
size_t len;
const char *buf;
- char *end;
int val;
/* atoi() and friends unfortunately do not support specifying the length of
@@ -2009,7 +2008,6 @@ static void end_any_member(upb_json_parser *p, const char *ptr) {
static bool start_subobject(upb_json_parser *p) {
if (p->top->is_unknown_field) {
- upb_jsonparser_frame *inner;
if (!check_stack(p)) return false;
p->top = start_jsonparser_frame(p);
@@ -2544,11 +2542,11 @@ static bool does_fieldmask_end(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */
-#line 2749 "upb/json/parser.rl"
+#line 2747 "upb/json/parser.rl"
-#line 2552 "upb/json/parser.c"
+#line 2550 "upb/json/parser.c"
static const char _json_actions[] = {
0, 1, 0, 1, 1, 1, 3, 1,
4, 1, 6, 1, 7, 1, 8, 1,
@@ -2803,7 +2801,7 @@ static const int json_en_value_machine = 78;
static const int json_en_main = 1;
-#line 2752 "upb/json/parser.rl"
+#line 2750 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
@@ -2826,7 +2824,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf);
-#line 2830 "upb/json/parser.c"
+#line 2828 "upb/json/parser.c"
{
int _klen;
unsigned int _trans;
@@ -2901,147 +2899,147 @@ _match:
switch ( *_acts++ )
{
case 1:
-#line 2557 "upb/json/parser.rl"
+#line 2555 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 2:
-#line 2559 "upb/json/parser.rl"
+#line 2557 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
break;
case 3:
-#line 2563 "upb/json/parser.rl"
+#line 2561 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 4:
-#line 2564 "upb/json/parser.rl"
+#line 2562 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 5:
-#line 2570 "upb/json/parser.rl"
+#line 2568 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 6:
-#line 2571 "upb/json/parser.rl"
+#line 2569 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 7:
-#line 2572 "upb/json/parser.rl"
+#line 2570 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 8:
-#line 2578 "upb/json/parser.rl"
+#line 2576 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 9:
-#line 2584 "upb/json/parser.rl"
+#line 2582 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 10:
-#line 2589 "upb/json/parser.rl"
+#line 2587 "upb/json/parser.rl"
{ start_year(parser, p); }
break;
case 11:
-#line 2590 "upb/json/parser.rl"
+#line 2588 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_year(parser, p)); }
break;
case 12:
-#line 2594 "upb/json/parser.rl"
+#line 2592 "upb/json/parser.rl"
{ start_month(parser, p); }
break;
case 13:
-#line 2595 "upb/json/parser.rl"
+#line 2593 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_month(parser, p)); }
break;
case 14:
-#line 2599 "upb/json/parser.rl"
+#line 2597 "upb/json/parser.rl"
{ start_day(parser, p); }
break;
case 15:
-#line 2600 "upb/json/parser.rl"
+#line 2598 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_day(parser, p)); }
break;
case 16:
-#line 2604 "upb/json/parser.rl"
+#line 2602 "upb/json/parser.rl"
{ start_hour(parser, p); }
break;
case 17:
-#line 2605 "upb/json/parser.rl"
+#line 2603 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hour(parser, p)); }
break;
case 18:
-#line 2609 "upb/json/parser.rl"
+#line 2607 "upb/json/parser.rl"
{ start_minute(parser, p); }
break;
case 19:
-#line 2610 "upb/json/parser.rl"
+#line 2608 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_minute(parser, p)); }
break;
case 20:
-#line 2614 "upb/json/parser.rl"
+#line 2612 "upb/json/parser.rl"
{ start_second(parser, p); }
break;
case 21:
-#line 2615 "upb/json/parser.rl"
+#line 2613 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_second(parser, p)); }
break;
case 22:
-#line 2620 "upb/json/parser.rl"
+#line 2618 "upb/json/parser.rl"
{ start_duration_base(parser, p); }
break;
case 23:
-#line 2621 "upb/json/parser.rl"
+#line 2619 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
break;
case 24:
-#line 2623 "upb/json/parser.rl"
+#line 2621 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 25:
-#line 2628 "upb/json/parser.rl"
+#line 2626 "upb/json/parser.rl"
{ start_timestamp_base(parser); }
break;
case 26:
-#line 2630 "upb/json/parser.rl"
+#line 2628 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); }
break;
case 27:
-#line 2631 "upb/json/parser.rl"
+#line 2629 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
break;
case 28:
-#line 2633 "upb/json/parser.rl"
+#line 2631 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); }
break;
case 29:
-#line 2634 "upb/json/parser.rl"
+#line 2632 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
break;
case 30:
-#line 2636 "upb/json/parser.rl"
+#line 2634 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 31:
-#line 2641 "upb/json/parser.rl"
+#line 2639 "upb/json/parser.rl"
{ start_fieldmask_path_text(parser, p); }
break;
case 32:
-#line 2642 "upb/json/parser.rl"
+#line 2640 "upb/json/parser.rl"
{ end_fieldmask_path_text(parser, p); }
break;
case 33:
-#line 2647 "upb/json/parser.rl"
+#line 2645 "upb/json/parser.rl"
{ start_fieldmask_path(parser); }
break;
case 34:
-#line 2648 "upb/json/parser.rl"
+#line 2646 "upb/json/parser.rl"
{ end_fieldmask_path(parser); }
break;
case 35:
-#line 2654 "upb/json/parser.rl"
+#line 2652 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 36:
-#line 2659 "upb/json/parser.rl"
+#line 2657 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
{stack[top++] = cs; cs = 47;goto _again;}
@@ -3055,11 +3053,11 @@ _match:
}
break;
case 37:
-#line 2672 "upb/json/parser.rl"
+#line 2670 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
break;
case 38:
-#line 2677 "upb/json/parser.rl"
+#line 2675 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_member(parser, p);
@@ -3069,11 +3067,11 @@ _match:
}
break;
case 39:
-#line 2684 "upb/json/parser.rl"
+#line 2682 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 40:
-#line 2687 "upb/json/parser.rl"
+#line 2685 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
end_any_member(parser, p);
@@ -3083,7 +3081,7 @@ _match:
}
break;
case 41:
-#line 2698 "upb/json/parser.rl"
+#line 2696 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_object(parser, p);
@@ -3093,7 +3091,7 @@ _match:
}
break;
case 42:
-#line 2707 "upb/json/parser.rl"
+#line 2705 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
CHECK_RETURN_TOP(end_any_object(parser, p));
@@ -3103,54 +3101,54 @@ _match:
}
break;
case 43:
-#line 2719 "upb/json/parser.rl"
+#line 2717 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 44:
-#line 2723 "upb/json/parser.rl"
+#line 2721 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 45:
-#line 2728 "upb/json/parser.rl"
+#line 2726 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_number(parser, p)); }
break;
case 46:
-#line 2729 "upb/json/parser.rl"
+#line 2727 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 47:
-#line 2731 "upb/json/parser.rl"
+#line 2729 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 48:
-#line 2732 "upb/json/parser.rl"
+#line 2730 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 49:
-#line 2734 "upb/json/parser.rl"
+#line 2732 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 50:
-#line 2736 "upb/json/parser.rl"
+#line 2734 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 51:
-#line 2738 "upb/json/parser.rl"
+#line 2736 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 52:
-#line 2740 "upb/json/parser.rl"
+#line 2738 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
break;
case 53:
-#line 2741 "upb/json/parser.rl"
+#line 2739 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
case 54:
-#line 2746 "upb/json/parser.rl"
+#line 2744 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
-#line 3154 "upb/json/parser.c"
+#line 3152 "upb/json/parser.c"
}
}
@@ -3167,32 +3165,32 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 0:
-#line 2555 "upb/json/parser.rl"
+#line 2553 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; if ( p == pe )
goto _test_eof;
goto _again;} }
break;
case 46:
-#line 2729 "upb/json/parser.rl"
+#line 2727 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 49:
-#line 2734 "upb/json/parser.rl"
+#line 2732 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 50:
-#line 2736 "upb/json/parser.rl"
+#line 2734 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 51:
-#line 2738 "upb/json/parser.rl"
+#line 2736 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 53:
-#line 2741 "upb/json/parser.rl"
+#line 2739 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
-#line 3196 "upb/json/parser.c"
+#line 3194 "upb/json/parser.c"
}
}
}
@@ -3200,7 +3198,7 @@ goto _again;} }
_out: {}
}
-#line 2774 "upb/json/parser.rl"
+#line 2772 "upb/json/parser.rl"
if (p != pe) {
upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
@@ -3243,13 +3241,13 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */
-#line 3247 "upb/json/parser.c"
+#line 3245 "upb/json/parser.c"
{
cs = json_start;
top = 0;
}
-#line 2816 "upb/json/parser.rl"
+#line 2814 "upb/json/parser.rl"
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);
diff --git a/upb/json/parser.rl b/upb/json/parser.rl
index e7c456a..a48a47d 100644
--- a/upb/json/parser.rl
+++ b/upb/json/parser.rl
@@ -1531,7 +1531,6 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
static int parse_timestamp_number(upb_json_parser *p) {
size_t len;
const char *buf;
- char *end;
int val;
/* atoi() and friends unfortunately do not support specifying the length of
@@ -2007,7 +2006,6 @@ static void end_any_member(upb_json_parser *p, const char *ptr) {
static bool start_subobject(upb_json_parser *p) {
if (p->top->is_unknown_field) {
- upb_jsonparser_frame *inner;
if (!check_stack(p)) return false;
p->top = start_jsonparser_frame(p);
diff --git a/upb/legacy_msg_reflection.c b/upb/legacy_msg_reflection.c
new file mode 100644
index 0000000..0140533
--- /dev/null
+++ b/upb/legacy_msg_reflection.c
@@ -0,0 +1,401 @@
+
+#include "upb/legacy_msg_reflection.h"
+
+#include <string.h>
+#include "upb/table.int.h"
+#include "upb/msg.h"
+
+bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) {
+ return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 ||
+ type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 ||
+ type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING;
+}
+
+#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs)
+#define VOIDPTR_AT(msg, ofs) PTR_AT(msg, ofs, void)
+#define ENCODE_MAX_NESTING 64
+#define CHECK_TRUE(x) if (!(x)) { return false; }
+
+/** upb_msgval ****************************************************************/
+
+/* These functions will generate real memcpy() calls on ARM sadly, because
+ * the compiler assumes they might not be aligned. */
+
+static upb_msgval upb_msgval_read(const void *p, size_t ofs,
+ uint8_t size) {
+ upb_msgval val;
+ p = (char*)p + ofs;
+ memcpy(&val, p, size);
+ return val;
+}
+
+static void upb_msgval_write(void *p, size_t ofs, upb_msgval val,
+ uint8_t size) {
+ p = (char*)p + ofs;
+ memcpy(p, &val, size);
+}
+
+static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ return 8;
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_FLOAT:
+ return 4;
+ case UPB_TYPE_BOOL:
+ return 1;
+ case UPB_TYPE_MESSAGE:
+ return sizeof(void*);
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_STRING:
+ return sizeof(upb_strview);
+ }
+ UPB_UNREACHABLE();
+}
+
+static uint8_t upb_msg_fieldsize(const upb_msglayout_field *field) {
+ if (field->label == UPB_LABEL_REPEATED) {
+ return sizeof(void*);
+ } else {
+ return upb_msgval_sizeof(upb_desctype_to_fieldtype[field->descriptortype]);
+ }
+}
+
+/* TODO(haberman): this is broken right now because upb_msgval can contain
+ * a char* / size_t pair, which is too big for a upb_value. To fix this
+ * we'll probably need to dynamically allocate a upb_msgval and store a
+ * pointer to that in the tables for extensions/maps. */
+static upb_value upb_toval(upb_msgval val) {
+ upb_value ret;
+ UPB_UNUSED(val);
+ memset(&ret, 0, sizeof(upb_value)); /* XXX */
+ return ret;
+}
+
+static upb_msgval upb_msgval_fromval(upb_value val) {
+ upb_msgval ret;
+ UPB_UNUSED(val);
+ memset(&ret, 0, sizeof(upb_msgval)); /* XXX */
+ return ret;
+}
+
+static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT;
+ case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE;
+ case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL;
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR;
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_INT32: return UPB_CTYPE_INT32;
+ case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32;
+ case UPB_TYPE_INT64: return UPB_CTYPE_INT64;
+ case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64;
+ default: UPB_ASSERT(false); return 0;
+ }
+}
+
+
+/** upb_msg *******************************************************************/
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define DEREF(msg, ofs, type) *PTR_AT(msg, ofs, type)
+
+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);
+ return &l->fields[field_index];
+}
+
+static bool upb_msg_inoneof(const upb_msglayout_field *field) {
+ return field->presence < 0;
+}
+
+static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index,
+ const upb_msglayout *l) {
+ const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
+ UPB_ASSERT(upb_msg_inoneof(field));
+ return PTR_AT(msg, ~field->presence, uint32_t);
+}
+
+bool upb_msg_has(const upb_msg *msg,
+ int field_index,
+ const upb_msglayout *l) {
+ const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
+
+ UPB_ASSERT(field->presence);
+
+ if (upb_msg_inoneof(field)) {
+ /* Oneofs are set when the oneof number is set to this field. */
+ return *upb_msg_oneofcase(msg, field_index, l) == field->number;
+ } else {
+ /* Other fields are set when their hasbit is set. */
+ uint32_t hasbit = field->presence;
+ return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8));
+ }
+}
+
+upb_msgval upb_msg_get(const upb_msg *msg, int field_index,
+ const upb_msglayout *l) {
+ const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
+ int size = upb_msg_fieldsize(field);
+ return upb_msgval_read(msg, field->offset, size);
+}
+
+void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val,
+ const upb_msglayout *l) {
+ const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
+ int size = upb_msg_fieldsize(field);
+ upb_msgval_write(msg, field->offset, val, size);
+}
+
+
+/** upb_array *****************************************************************/
+
+#define DEREF_ARR(arr, i, type) ((type*)arr->data)[i]
+
+size_t upb_array_size(const upb_array *arr) {
+ return arr->len;
+}
+
+upb_fieldtype_t upb_array_type(const upb_array *arr) {
+ return arr->type;
+}
+
+upb_msgval upb_array_get(const upb_array *arr, size_t i) {
+ size_t element_size = upb_msgval_sizeof(arr->type);
+ UPB_ASSERT(i < arr->len);
+ return upb_msgval_read(arr->data, i * element_size, element_size);
+}
+
+bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
+ size_t element_size = upb_msgval_sizeof(arr->type);
+ UPB_ASSERT(i <= arr->len);
+
+ if (i == arr->len) {
+ /* Extending the array. */
+
+ if (i == arr->size) {
+ /* Need to reallocate. */
+ size_t new_size = UPB_MAX(arr->size * 2, 8);
+ size_t new_bytes = new_size * element_size;
+ size_t old_bytes = arr->size * element_size;
+ upb_alloc *alloc = upb_arena_alloc(arr->arena);
+ upb_msgval *new_data =
+ upb_realloc(alloc, arr->data, old_bytes, new_bytes);
+
+ if (!new_data) {
+ return false;
+ }
+
+ arr->data = new_data;
+ arr->size = new_size;
+ }
+
+ arr->len = i + 1;
+ }
+
+ upb_msgval_write(arr->data, i * element_size, val, element_size);
+ return true;
+}
+
+
+/** upb_map *******************************************************************/
+
+struct upb_map {
+ upb_fieldtype_t key_type;
+ upb_fieldtype_t val_type;
+ /* We may want to optimize this to use inttable where possible, for greater
+ * efficiency and lower memory footprint. */
+ upb_strtable strtab;
+ upb_arena *arena;
+};
+
+static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key,
+ const char **out_key, size_t *out_len) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ /* Point to string data of the input key. */
+ *out_key = key->str.data;
+ *out_len = key->str.size;
+ return;
+ case UPB_TYPE_BOOL:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ /* Point to the key itself. XXX: big-endian. */
+ *out_key = (const char*)key;
+ *out_len = upb_msgval_sizeof(type);
+ return;
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_FLOAT:
+ case UPB_TYPE_MESSAGE:
+ break; /* Cannot be a map key. */
+ }
+ UPB_UNREACHABLE();
+}
+
+static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key,
+ size_t len) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ return upb_msgval_makestr(key, len);
+ case UPB_TYPE_BOOL:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ return upb_msgval_read(key, 0, upb_msgval_sizeof(type));
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_FLOAT:
+ case UPB_TYPE_MESSAGE:
+ break; /* Cannot be a map key. */
+ }
+ UPB_UNREACHABLE();
+}
+
+upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype,
+ upb_arena *a) {
+ upb_ctype_t vtabtype = upb_fieldtotabtype(vtype);
+ upb_alloc *alloc = upb_arena_alloc(a);
+ upb_map *map = upb_malloc(alloc, sizeof(upb_map));
+
+ if (!map) {
+ return NULL;
+ }
+
+ UPB_ASSERT(upb_fieldtype_mapkeyok(ktype));
+ map->key_type = ktype;
+ map->val_type = vtype;
+ map->arena = a;
+
+ if (!upb_strtable_init2(&map->strtab, vtabtype, alloc)) {
+ return NULL;
+ }
+
+ return map;
+}
+
+size_t upb_map_size(const upb_map *map) {
+ return upb_strtable_count(&map->strtab);
+}
+
+upb_fieldtype_t upb_map_keytype(const upb_map *map) {
+ return map->key_type;
+}
+
+upb_fieldtype_t upb_map_valuetype(const upb_map *map) {
+ return map->val_type;
+}
+
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
+ upb_value tabval;
+ const char *key_str;
+ size_t key_len;
+ bool ret;
+
+ upb_map_tokey(map->key_type, &key, &key_str, &key_len);
+ ret = upb_strtable_lookup2(&map->strtab, key_str, key_len, &tabval);
+ if (ret) {
+ memcpy(val, &tabval, sizeof(tabval));
+ }
+
+ return ret;
+}
+
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+ upb_msgval *removed) {
+ const char *key_str;
+ size_t key_len;
+ upb_value tabval = upb_toval(val);
+ upb_value removedtabval;
+ upb_alloc *a = upb_arena_alloc(map->arena);
+
+ upb_map_tokey(map->key_type, &key, &key_str, &key_len);
+
+ /* TODO(haberman): add overwrite operation to minimize number of lookups. */
+ if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) {
+ upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a);
+ memcpy(&removed, &removedtabval, sizeof(removed));
+ }
+
+ return upb_strtable_insert3(&map->strtab, key_str, key_len, tabval, a);
+}
+
+bool upb_map_del(upb_map *map, upb_msgval key) {
+ const char *key_str;
+ size_t key_len;
+ upb_alloc *a = upb_arena_alloc(map->arena);
+
+ upb_map_tokey(map->key_type, &key, &key_str, &key_len);
+ return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a);
+}
+
+
+/** upb_mapiter ***************************************************************/
+
+struct upb_mapiter {
+ upb_strtable_iter iter;
+ upb_fieldtype_t key_type;
+};
+
+size_t upb_mapiter_sizeof() {
+ return sizeof(upb_mapiter);
+}
+
+void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) {
+ upb_strtable_begin(&i->iter, &map->strtab);
+ i->key_type = map->key_type;
+}
+
+upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) {
+ upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof());
+
+ if (!ret) {
+ return NULL;
+ }
+
+ upb_mapiter_begin(ret, t);
+ return ret;
+}
+
+void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) {
+ upb_free(a, i);
+}
+
+void upb_mapiter_next(upb_mapiter *i) {
+ upb_strtable_next(&i->iter);
+}
+
+bool upb_mapiter_done(const upb_mapiter *i) {
+ return upb_strtable_done(&i->iter);
+}
+
+upb_msgval upb_mapiter_key(const upb_mapiter *i) {
+ return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter),
+ upb_strtable_iter_keylength(&i->iter));
+}
+
+upb_msgval upb_mapiter_value(const upb_mapiter *i) {
+ return upb_msgval_fromval(upb_strtable_iter_value(&i->iter));
+}
+
+void upb_mapiter_setdone(upb_mapiter *i) {
+ upb_strtable_iter_setdone(&i->iter);
+}
+
+bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) {
+ return upb_strtable_iter_isequal(&i1->iter, &i2->iter);
+}
diff --git a/upb/legacy_msg_reflection.h b/upb/legacy_msg_reflection.h
new file mode 100644
index 0000000..66d3fba
--- /dev/null
+++ b/upb/legacy_msg_reflection.h
@@ -0,0 +1,186 @@
+
+#ifndef UPB_LEGACY_MSG_REFLECTION_H_
+#define UPB_LEGACY_MSG_REFLECTION_H_
+
+#include "upb/upb.h"
+#include "upb/msg.h"
+
+struct upb_map;
+typedef struct upb_map upb_map;
+
+struct upb_mapiter;
+typedef struct upb_mapiter upb_mapiter;
+
+/** upb_msgval ****************************************************************/
+
+/* A union representing all possible protobuf values. Used for generic get/set
+ * operations. */
+
+typedef union {
+ bool b;
+ float flt;
+ double dbl;
+ int32_t i32;
+ int64_t i64;
+ uint32_t u32;
+ uint64_t u64;
+ const upb_map* map;
+ const upb_msg* msg;
+ const upb_array* arr;
+ const void* ptr;
+ upb_strview str;
+} upb_msgval;
+
+#define ACCESSORS(name, membername, ctype) \
+ UPB_INLINE ctype upb_msgval_get ## name(upb_msgval v) { \
+ return v.membername; \
+ } \
+ UPB_INLINE void upb_msgval_set ## name(upb_msgval *v, ctype cval) { \
+ v->membername = cval; \
+ } \
+ UPB_INLINE upb_msgval upb_msgval_ ## name(ctype v) { \
+ upb_msgval ret; \
+ ret.membername = v; \
+ return ret; \
+ }
+
+ACCESSORS(bool, b, bool)
+ACCESSORS(float, flt, float)
+ACCESSORS(double, dbl, double)
+ACCESSORS(int32, i32, int32_t)
+ACCESSORS(int64, i64, int64_t)
+ACCESSORS(uint32, u32, uint32_t)
+ACCESSORS(uint64, u64, uint64_t)
+ACCESSORS(map, map, const upb_map*)
+ACCESSORS(msg, msg, const upb_msg*)
+ACCESSORS(ptr, ptr, const void*)
+ACCESSORS(arr, arr, const upb_array*)
+ACCESSORS(str, str, upb_strview)
+
+#undef ACCESSORS
+
+UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) {
+ return upb_msgval_str(upb_strview_make(data, size));
+}
+
+/** upb_msg *******************************************************************/
+
+/* A upb_msg represents a protobuf message. It always corresponds to a specific
+ * upb_msglayout, which describes how it is laid out in memory. */
+
+/* Read-only message API. Can be safely called by anyone. */
+
+/* Returns the value associated with this field:
+ * - for scalar fields (including strings), the value directly.
+ * - return upb_msg*, or upb_map* for msg/map.
+ * If the field is unset for these field types, returns NULL.
+ *
+ * TODO(haberman): should we let users store cached array/map/msg
+ * pointers here for fields that are unset? Could be useful for the
+ * strongly-owned submessage model (ie. generated C API that doesn't use
+ * arenas).
+ */
+upb_msgval upb_msg_get(const upb_msg *msg,
+ int field_index,
+ const upb_msglayout *l);
+
+/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
+bool upb_msg_has(const upb_msg *msg,
+ int field_index,
+ const upb_msglayout *l);
+
+/* Mutable message API. May only be called by the owner of the message who
+ * knows its ownership scheme and how to keep it consistent. */
+
+/* Sets the given field to the given value. Does not perform any memory
+ * management: if you overwrite a pointer to a msg/array/map/string without
+ * cleaning it up (or using an arena) it will leak.
+ */
+void upb_msg_set(upb_msg *msg,
+ int field_index,
+ upb_msgval val,
+ const upb_msglayout *l);
+
+/* For a primitive field, set it back to its default. For repeated, string, and
+ * submessage fields set it back to NULL. This could involve releasing some
+ * internal memory (for example, from an extension dictionary), but it is not
+ * recursive in any way and will not recover any memory that may be used by
+ * arrays/maps/strings/msgs that this field may have pointed to.
+ */
+bool upb_msg_clearfield(upb_msg *msg,
+ int field_index,
+ const upb_msglayout *l);
+
+/* TODO(haberman): copyfrom()/mergefrom()? */
+
+/** upb_array *****************************************************************/
+
+/* A upb_array stores data for a repeated field. The memory management
+ * semantics are the same as upb_msg. A upb_array allocates dynamic
+ * memory internally for the array elements. */
+
+upb_fieldtype_t upb_array_type(const upb_array *arr);
+
+/* Read-only interface. Safe for anyone to call. */
+
+size_t upb_array_size(const upb_array *arr);
+upb_msgval upb_array_get(const upb_array *arr, size_t i);
+
+/* Write interface. May only be called by the message's owner who can enforce
+ * its memory management invariants. */
+
+bool upb_array_set(upb_array *arr, size_t i, upb_msgval val);
+
+/** upb_map *******************************************************************/
+
+/* A upb_map stores data for a map field. The memory management semantics are
+ * the same as upb_msg, with one notable exception. upb_map will internally
+ * store a copy of all string keys, but *not* any string values or submessages.
+ * So you must ensure that any string or message values outlive the map, and you
+ * must delete them manually when they are no longer required. */
+
+upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype,
+ upb_arena *a);
+
+/* Read-only interface. Safe for anyone to call. */
+
+size_t upb_map_size(const upb_map *map);
+upb_fieldtype_t upb_map_keytype(const upb_map *map);
+upb_fieldtype_t upb_map_valuetype(const upb_map *map);
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
+
+/* Write interface. May only be called by the message's owner who can enforce
+ * its memory management invariants. */
+
+/* Sets or overwrites an entry in the map. Return value indicates whether
+ * the operation succeeded or failed with OOM, and also whether an existing
+ * key was replaced or not. */
+bool upb_map_set(upb_map *map,
+ upb_msgval key, upb_msgval val,
+ upb_msgval *valremoved);
+
+/* Deletes an entry in the map. Returns true if the key was present. */
+bool upb_map_del(upb_map *map, upb_msgval key);
+
+/** upb_mapiter ***************************************************************/
+
+/* For iterating over a map. Map iterators are invalidated by mutations to the
+ * map, but an invalidated iterator will never return junk or crash the process.
+ * An invalidated iterator may return entries that were already returned though,
+ * and if you keep invalidating the iterator during iteration, the program may
+ * enter an infinite loop. */
+
+size_t upb_mapiter_sizeof();
+
+void upb_mapiter_begin(upb_mapiter *i, const upb_map *t);
+upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a);
+void upb_mapiter_free(upb_mapiter *i, upb_alloc *a);
+void upb_mapiter_next(upb_mapiter *i);
+bool upb_mapiter_done(const upb_mapiter *i);
+
+upb_msgval upb_mapiter_key(const upb_mapiter *i);
+upb_msgval upb_mapiter_value(const upb_mapiter *i);
+void upb_mapiter_setdone(upb_mapiter *i);
+bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2);
+
+#endif // UPB_LEGACY_MSG_REFLECTION_H_
diff --git a/upb/msg.c b/upb/msg.c
index b46d41c..d6ad8df 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -1,111 +1,9 @@
-#include <string.h>
-#include "upb/table.int.h"
#include "upb/msg.h"
-#include "upb/structs.int.h"
-
-bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) {
- return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 ||
- type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 ||
- type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING;
-}
-
-#define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs)
-#define VOIDPTR_AT(msg, ofs) PTR_AT(msg, ofs, void)
-#define ENCODE_MAX_NESTING 64
-#define CHECK_TRUE(x) if (!(x)) { return false; }
-
-/** upb_msgval ****************************************************************/
-
-/* These functions will generate real memcpy() calls on ARM sadly, because
- * the compiler assumes they might not be aligned. */
-
-static upb_msgval upb_msgval_read(const void *p, size_t ofs,
- uint8_t size) {
- upb_msgval val;
- p = (char*)p + ofs;
- memcpy(&val, p, size);
- return val;
-}
-
-static void upb_msgval_write(void *p, size_t ofs, upb_msgval val,
- uint8_t size) {
- p = (char*)p + ofs;
- memcpy(p, &val, size);
-}
-
-static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
- switch (type) {
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT64:
- return 8;
- case UPB_TYPE_ENUM:
- case UPB_TYPE_INT32:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_FLOAT:
- return 4;
- case UPB_TYPE_BOOL:
- return 1;
- case UPB_TYPE_MESSAGE:
- return sizeof(void*);
- case UPB_TYPE_BYTES:
- case UPB_TYPE_STRING:
- return sizeof(upb_strview);
- }
- UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fieldsize(const upb_msglayout_field *field) {
- if (field->label == UPB_LABEL_REPEATED) {
- return sizeof(void*);
- } else {
- return upb_msgval_sizeof(upb_desctype_to_fieldtype[field->descriptortype]);
- }
-}
-
-/* TODO(haberman): this is broken right now because upb_msgval can contain
- * a char* / size_t pair, which is too big for a upb_value. To fix this
- * we'll probably need to dynamically allocate a upb_msgval and store a
- * pointer to that in the tables for extensions/maps. */
-static upb_value upb_toval(upb_msgval val) {
- upb_value ret;
- UPB_UNUSED(val);
- memset(&ret, 0, sizeof(upb_value)); /* XXX */
- return ret;
-}
-
-static upb_msgval upb_msgval_fromval(upb_value val) {
- upb_msgval ret;
- UPB_UNUSED(val);
- memset(&ret, 0, sizeof(upb_msgval)); /* XXX */
- return ret;
-}
-static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) {
- switch (type) {
- case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT;
- case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE;
- case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL;
- case UPB_TYPE_BYTES:
- case UPB_TYPE_MESSAGE:
- case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR;
- case UPB_TYPE_ENUM:
- case UPB_TYPE_INT32: return UPB_CTYPE_INT32;
- case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32;
- case UPB_TYPE_INT64: return UPB_CTYPE_INT64;
- case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64;
- default: UPB_ASSERT(false); return 0;
- }
-}
-
-
-/** upb_msg *******************************************************************/
+#include "upb/table.int.h"
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define DEREF(msg, ofs, type) *PTR_AT(msg, ofs, type)
+#define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + ofs)
/* Internal members of a upb_msg. We can change this without breaking binary
* compatibility. We put these before the user's data. The user's upb_msg*
@@ -131,6 +29,10 @@ static int upb_msg_internalsize(const upb_msglayout *l) {
return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
}
+static size_t upb_msg_sizeof(const upb_msglayout *l) {
+ return l->size + upb_msg_internalsize(l);
+}
+
static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
return VOIDPTR_AT(msg, -sizeof(upb_msg_internal));
}
@@ -145,44 +47,8 @@ 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(const upb_msg *msg, size_t *len) {
- const upb_msg_internal* in = upb_msg_getinternal_const(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);
- return &l->fields[field_index];
-}
-
-static bool upb_msg_inoneof(const upb_msglayout_field *field) {
- return field->presence < 0;
-}
-
-static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index,
- const upb_msglayout *l) {
- const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
- UPB_ASSERT(upb_msg_inoneof(field));
- return PTR_AT(msg, ~field->presence, uint32_t);
-}
-
-static size_t upb_msg_sizeof(const upb_msglayout *l) {
- return l->size + upb_msg_internalsize(l);
+upb_arena *upb_msg_arena(const upb_msg *msg) {
+ return upb_msg_getinternal_const(msg)->arena;
}
upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
@@ -214,46 +80,6 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
return msg;
}
-upb_arena *upb_msg_arena(const upb_msg *msg) {
- return upb_msg_getinternal_const(msg)->arena;
-}
-
-bool upb_msg_has(const upb_msg *msg,
- int field_index,
- const upb_msglayout *l) {
- const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
-
- UPB_ASSERT(field->presence);
-
- if (upb_msg_inoneof(field)) {
- /* Oneofs are set when the oneof number is set to this field. */
- return *upb_msg_oneofcase(msg, field_index, l) == field->number;
- } else {
- /* Other fields are set when their hasbit is set. */
- uint32_t hasbit = field->presence;
- return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8));
- }
-}
-
-upb_msgval upb_msg_get(const upb_msg *msg, int field_index,
- const upb_msglayout *l) {
- const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
- int size = upb_msg_fieldsize(field);
- return upb_msgval_read(msg, field->offset, size);
-}
-
-void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val,
- const upb_msglayout *l) {
- const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
- int size = upb_msg_fieldsize(field);
- upb_msgval_write(msg, field->offset, val, size);
-}
-
-
-/** upb_array *****************************************************************/
-
-#define DEREF_ARR(arr, i, type) ((type*)arr->data)[i]
-
upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a) {
upb_alloc *alloc = upb_arena_alloc(a);
upb_array *ret = upb_malloc(alloc, sizeof(upb_array));
@@ -266,245 +92,28 @@ upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a) {
ret->data = NULL;
ret->len = 0;
ret->size = 0;
- ret->element_size = upb_msgval_sizeof(type);
ret->arena = a;
return ret;
}
-size_t upb_array_size(const upb_array *arr) {
- return arr->len;
-}
-
-upb_fieldtype_t upb_array_type(const upb_array *arr) {
- return arr->type;
-}
-
-upb_msgval upb_array_get(const upb_array *arr, size_t i) {
- UPB_ASSERT(i < arr->len);
- return upb_msgval_read(arr->data, i * arr->element_size, arr->element_size);
-}
-
-bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
- UPB_ASSERT(i <= arr->len);
-
- if (i == arr->len) {
- /* Extending the array. */
-
- if (i == arr->size) {
- /* Need to reallocate. */
- size_t new_size = UPB_MAX(arr->size * 2, 8);
- size_t new_bytes = new_size * arr->element_size;
- size_t old_bytes = arr->size * arr->element_size;
- upb_alloc *alloc = upb_arena_alloc(arr->arena);
- upb_msgval *new_data =
- upb_realloc(alloc, arr->data, old_bytes, new_bytes);
-
- if (!new_data) {
- return false;
- }
-
- arr->data = new_data;
- arr->size = new_size;
- }
-
- arr->len = i + 1;
- }
-
- upb_msgval_write(arr->data, i * arr->element_size, val, arr->element_size);
- return true;
-}
-
-
-/** upb_map *******************************************************************/
-
-struct upb_map {
- upb_fieldtype_t key_type;
- upb_fieldtype_t val_type;
- /* We may want to optimize this to use inttable where possible, for greater
- * efficiency and lower memory footprint. */
- upb_strtable strtab;
- upb_arena *arena;
-};
-
-static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key,
- const char **out_key, size_t *out_len) {
- switch (type) {
- case UPB_TYPE_STRING:
- /* Point to string data of the input key. */
- *out_key = key->str.data;
- *out_len = key->str.size;
- return;
- case UPB_TYPE_BOOL:
- case UPB_TYPE_INT32:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT64:
- /* Point to the key itself. XXX: big-endian. */
- *out_key = (const char*)key;
- *out_len = upb_msgval_sizeof(type);
- return;
- case UPB_TYPE_BYTES:
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_ENUM:
- case UPB_TYPE_FLOAT:
- case UPB_TYPE_MESSAGE:
- break; /* Cannot be a map key. */
- }
- UPB_UNREACHABLE();
-}
-
-static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key,
- size_t len) {
- switch (type) {
- case UPB_TYPE_STRING:
- return upb_msgval_makestr(key, len);
- case UPB_TYPE_BOOL:
- case UPB_TYPE_INT32:
- case UPB_TYPE_UINT32:
- case UPB_TYPE_INT64:
- case UPB_TYPE_UINT64:
- return upb_msgval_read(key, 0, upb_msgval_sizeof(type));
- case UPB_TYPE_BYTES:
- case UPB_TYPE_DOUBLE:
- case UPB_TYPE_ENUM:
- case UPB_TYPE_FLOAT:
- case UPB_TYPE_MESSAGE:
- break; /* Cannot be a map key. */
- }
- UPB_UNREACHABLE();
-}
-
-upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype,
- upb_arena *a) {
- upb_ctype_t vtabtype = upb_fieldtotabtype(vtype);
- upb_alloc *alloc = upb_arena_alloc(a);
- upb_map *map = upb_malloc(alloc, sizeof(upb_map));
-
- if (!map) {
- return NULL;
- }
-
- UPB_ASSERT(upb_fieldtype_mapkeyok(ktype));
- map->key_type = ktype;
- map->val_type = vtype;
- map->arena = a;
-
- if (!upb_strtable_init2(&map->strtab, vtabtype, alloc)) {
- return NULL;
- }
-
- return map;
-}
-
-size_t upb_map_size(const upb_map *map) {
- return upb_strtable_count(&map->strtab);
-}
-
-upb_fieldtype_t upb_map_keytype(const upb_map *map) {
- return map->key_type;
-}
-
-upb_fieldtype_t upb_map_valuetype(const upb_map *map) {
- return map->val_type;
-}
-
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
- upb_value tabval;
- const char *key_str;
- size_t key_len;
- bool ret;
-
- upb_map_tokey(map->key_type, &key, &key_str, &key_len);
- ret = upb_strtable_lookup2(&map->strtab, key_str, key_len, &tabval);
- if (ret) {
- memcpy(val, &tabval, sizeof(tabval));
- }
-
- return ret;
-}
-
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
- upb_msgval *removed) {
- const char *key_str;
- size_t key_len;
- upb_value tabval = upb_toval(val);
- upb_value removedtabval;
- upb_alloc *a = upb_arena_alloc(map->arena);
-
- upb_map_tokey(map->key_type, &key, &key_str, &key_len);
-
- /* TODO(haberman): add overwrite operation to minimize number of lookups. */
- if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) {
- upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a);
- memcpy(&removed, &removedtabval, sizeof(removed));
- }
-
- return upb_strtable_insert3(&map->strtab, key_str, key_len, tabval, a);
-}
-
-bool upb_map_del(upb_map *map, upb_msgval key) {
- const char *key_str;
- size_t key_len;
- upb_alloc *a = upb_arena_alloc(map->arena);
-
- upb_map_tokey(map->key_type, &key, &key_str, &key_len);
- return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a);
-}
-
-
-/** upb_mapiter ***************************************************************/
-
-struct upb_mapiter {
- upb_strtable_iter iter;
- upb_fieldtype_t key_type;
-};
-
-size_t upb_mapiter_sizeof() {
- return sizeof(upb_mapiter);
-}
-
-void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) {
- upb_strtable_begin(&i->iter, &map->strtab);
- i->key_type = map->key_type;
-}
-
-upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) {
- upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof());
-
- if (!ret) {
- return NULL;
+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;
}
-
- upb_mapiter_begin(ret, t);
- return ret;
-}
-
-void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) {
- upb_free(a, i);
-}
-
-void upb_mapiter_next(upb_mapiter *i) {
- upb_strtable_next(&i->iter);
-}
-
-bool upb_mapiter_done(const upb_mapiter *i) {
- return upb_strtable_done(&i->iter);
-}
-
-upb_msgval upb_mapiter_key(const upb_mapiter *i) {
- return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter),
- upb_strtable_iter_keylength(&i->iter));
-}
-
-upb_msgval upb_mapiter_value(const upb_mapiter *i) {
- return upb_msgval_fromval(upb_strtable_iter_value(&i->iter));
+ memcpy(in->unknown + in->unknown_len, data, len);
+ in->unknown_len += len;
}
-void upb_mapiter_setdone(upb_mapiter *i) {
- upb_strtable_iter_setdone(&i->iter);
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
+ const upb_msg_internal* in = upb_msg_getinternal_const(msg);
+ *len = in->unknown_len;
+ return in->unknown;
}
-bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) {
- return upb_strtable_iter_isequal(&i1->iter, &i2->iter);
-}
+#undef VOIDPTR_AT
diff --git a/upb/msg.h b/upb/msg.h
index 78c3633..e46733f 100644
--- a/upb/msg.h
+++ b/upb/msg.h
@@ -1,21 +1,9 @@
/*
-** upb::Message is a representation for protobuf messages.
+** Data structures for message tables, used for parsing and serialization.
+** This are much lighter-weight than full reflection, but they are do not
+** have enough information to convert to text format, JSON, etc.
**
-** However it differs from other common representations like
-** google::protobuf::Message in one key way: it does not prescribe any
-** ownership between messages and submessages, and it relies on the
-** client to ensure that each submessage/array/map outlives its parent.
-**
-** All messages, arrays, and maps live in an Arena. If the entire message
-** tree is in the same arena, ensuring proper lifetimes is simple. However
-** the client can mix arenas as long as they ensure that there are no
-** dangling pointers.
-**
-** A client can access a upb::Message without knowing anything about
-** ownership semantics, but to create or mutate a message a user needs
-** to implement the memory management themselves.
-**
-** TODO: UTF-8 checking?
+** The definitions in this file are internal to upb.
**/
#ifndef UPB_MSG_H_
@@ -24,20 +12,6 @@
#include <stdint.h>
#include <string.h>
#include "upb/upb.h"
-#include "upb/structs.int.h"
-
-#ifdef __cplusplus
-
-namespace upb {
-class Array;
-class Map;
-class MapIterator;
-class MessageLayout;
-}
-
-#endif
-
-/* TODO(haberman): C++ accessors */
#ifdef __cplusplus
extern "C" {
@@ -45,15 +19,6 @@ extern "C" {
typedef void upb_msg;
-struct upb_array;
-typedef struct upb_array upb_array;
-
-struct upb_map;
-typedef struct upb_map upb_map;
-
-struct upb_mapiter;
-typedef struct upb_mapiter upb_mapiter;
-
/** upb_msglayout *************************************************************/
/* upb_msglayout represents the memory layout of a given upb_msgdef. The
@@ -79,91 +44,18 @@ typedef struct upb_msglayout {
bool extendable;
} upb_msglayout;
-/** upb_strview ************************************************************/
+/** Message internal representation *******************************************/
+/* Our internal representation for repeated fields. */
typedef struct {
- const char *data;
- size_t size;
-} upb_strview;
-
-UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
- upb_strview ret;
- ret.data = data;
- ret.size = size;
- return ret;
-}
-
-UPB_INLINE upb_strview upb_strview_makez(const char *data) {
- return upb_strview_make(data, strlen(data));
-}
+ upb_fieldtype_t type;
+ void *data; /* Each element is element_size. */
+ size_t len; /* Measured in elements. */
+ size_t size; /* Measured in elements. */
+ upb_arena *arena;
+} upb_array;
-UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
- return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
-
-#define UPB_STRVIEW_FORMAT "%.*s"
-#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
-
-/** upb_msgval ****************************************************************/
-
-/* A union representing all possible protobuf values. Used for generic get/set
- * operations. */
-
-typedef union {
- bool b;
- float flt;
- double dbl;
- int32_t i32;
- int64_t i64;
- uint32_t u32;
- uint64_t u64;
- const upb_map* map;
- const upb_msg* msg;
- const upb_array* arr;
- const void* ptr;
- upb_strview str;
-} upb_msgval;
-
-#define ACCESSORS(name, membername, ctype) \
- UPB_INLINE ctype upb_msgval_get ## name(upb_msgval v) { \
- return v.membername; \
- } \
- UPB_INLINE void upb_msgval_set ## name(upb_msgval *v, ctype cval) { \
- v->membername = cval; \
- } \
- UPB_INLINE upb_msgval upb_msgval_ ## name(ctype v) { \
- upb_msgval ret; \
- ret.membername = v; \
- return ret; \
- }
-
-ACCESSORS(bool, b, bool)
-ACCESSORS(float, flt, float)
-ACCESSORS(double, dbl, double)
-ACCESSORS(int32, i32, int32_t)
-ACCESSORS(int64, i64, int64_t)
-ACCESSORS(uint32, u32, uint32_t)
-ACCESSORS(uint64, u64, uint64_t)
-ACCESSORS(map, map, const upb_map*)
-ACCESSORS(msg, msg, const upb_msg*)
-ACCESSORS(ptr, ptr, const void*)
-ACCESSORS(arr, arr, const upb_array*)
-ACCESSORS(str, str, upb_strview)
-
-#undef ACCESSORS
-
-UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) {
- return upb_msgval_str(upb_strview_make(data, size));
-}
-
-/** upb_msg *******************************************************************/
-
-/* A upb_msg represents a protobuf message. It always corresponds to a specific
- * upb_msglayout, which describes how it is laid out in memory. */
-
-/* Creates a new message of the given type/layout in this arena. */
+upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
/* Returns the arena for the given message. */
@@ -172,121 +64,7 @@ upb_arena *upb_msg_arena(const upb_msg *msg);
void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len);
const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-/* Read-only message API. Can be safely called by anyone. */
-
-/* Returns the value associated with this field:
- * - for scalar fields (including strings), the value directly.
- * - return upb_msg*, or upb_map* for msg/map.
- * If the field is unset for these field types, returns NULL.
- *
- * TODO(haberman): should we let users store cached array/map/msg
- * pointers here for fields that are unset? Could be useful for the
- * strongly-owned submessage model (ie. generated C API that doesn't use
- * arenas).
- */
-upb_msgval upb_msg_get(const upb_msg *msg,
- int field_index,
- const upb_msglayout *l);
-
-/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
-bool upb_msg_has(const upb_msg *msg,
- int field_index,
- const upb_msglayout *l);
-
-/* Mutable message API. May only be called by the owner of the message who
- * knows its ownership scheme and how to keep it consistent. */
-
-/* Sets the given field to the given value. Does not perform any memory
- * management: if you overwrite a pointer to a msg/array/map/string without
- * cleaning it up (or using an arena) it will leak.
- */
-void upb_msg_set(upb_msg *msg,
- int field_index,
- upb_msgval val,
- const upb_msglayout *l);
-
-/* For a primitive field, set it back to its default. For repeated, string, and
- * submessage fields set it back to NULL. This could involve releasing some
- * internal memory (for example, from an extension dictionary), but it is not
- * recursive in any way and will not recover any memory that may be used by
- * arrays/maps/strings/msgs that this field may have pointed to.
- */
-bool upb_msg_clearfield(upb_msg *msg,
- int field_index,
- const upb_msglayout *l);
-
-/* TODO(haberman): copyfrom()/mergefrom()? */
-
-/** upb_array *****************************************************************/
-
-/* A upb_array stores data for a repeated field. The memory management
- * semantics are the same as upb_msg. A upb_array allocates dynamic
- * memory internally for the array elements. */
-
upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a);
-upb_fieldtype_t upb_array_type(const upb_array *arr);
-
-/* Read-only interface. Safe for anyone to call. */
-
-size_t upb_array_size(const upb_array *arr);
-upb_msgval upb_array_get(const upb_array *arr, size_t i);
-
-/* Write interface. May only be called by the message's owner who can enforce
- * its memory management invariants. */
-
-bool upb_array_set(upb_array *arr, size_t i, upb_msgval val);
-
-/** upb_map *******************************************************************/
-
-/* A upb_map stores data for a map field. The memory management semantics are
- * the same as upb_msg, with one notable exception. upb_map will internally
- * store a copy of all string keys, but *not* any string values or submessages.
- * So you must ensure that any string or message values outlive the map, and you
- * must delete them manually when they are no longer required. */
-
-upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype,
- upb_arena *a);
-
-/* Read-only interface. Safe for anyone to call. */
-
-size_t upb_map_size(const upb_map *map);
-upb_fieldtype_t upb_map_keytype(const upb_map *map);
-upb_fieldtype_t upb_map_valuetype(const upb_map *map);
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
-
-/* Write interface. May only be called by the message's owner who can enforce
- * its memory management invariants. */
-
-/* Sets or overwrites an entry in the map. Return value indicates whether
- * the operation succeeded or failed with OOM, and also whether an existing
- * key was replaced or not. */
-bool upb_map_set(upb_map *map,
- upb_msgval key, upb_msgval val,
- upb_msgval *valremoved);
-
-/* Deletes an entry in the map. Returns true if the key was present. */
-bool upb_map_del(upb_map *map, upb_msgval key);
-
-/** upb_mapiter ***************************************************************/
-
-/* For iterating over a map. Map iterators are invalidated by mutations to the
- * map, but an invalidated iterator will never return junk or crash the process.
- * An invalidated iterator may return entries that were already returned though,
- * and if you keep invalidating the iterator during iteration, the program may
- * enter an infinite loop. */
-
-size_t upb_mapiter_sizeof();
-
-void upb_mapiter_begin(upb_mapiter *i, const upb_map *t);
-upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a);
-void upb_mapiter_free(upb_mapiter *i, upb_alloc *a);
-void upb_mapiter_next(upb_mapiter *i);
-bool upb_mapiter_done(const upb_mapiter *i);
-
-upb_msgval upb_mapiter_key(const upb_mapiter *i);
-upb_msgval upb_mapiter_value(const upb_mapiter *i);
-void upb_mapiter_setdone(upb_mapiter *i);
-bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/upb/msgfactory.c b/upb/msgfactory.c
index f082042..2e13199 100644
--- a/upb/msgfactory.c
+++ b/upb/msgfactory.c
@@ -1,5 +1,4 @@
-#include "upb/handlers.h"
#include "upb/msgfactory.h"
static bool is_power_of_two(size_t val) {
diff --git a/upb/structs.int.h b/upb/structs.int.h
deleted file mode 100644
index ec7a4ae..0000000
--- a/upb/structs.int.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-** structs.int.h: structures definitions that are internal to upb.
-*/
-
-#ifndef UPB_STRUCTS_H_
-#define UPB_STRUCTS_H_
-
-#include "upb/upb.h"
-
-struct upb_array {
- upb_fieldtype_t type;
- uint8_t element_size;
- void *data; /* Each element is element_size. */
- size_t len; /* Measured in elements. */
- size_t size; /* Measured in elements. */
- upb_arena *arena;
-};
-
-#endif /* UPB_STRUCTS_H_ */
-
diff --git a/upb/upb.h b/upb/upb.h
index 92db893..49bb757 100644
--- a/upb/upb.h
+++ b/upb/upb.h
@@ -13,6 +13,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <string.h>
#ifdef __cplusplus
#include <memory>
@@ -170,6 +171,33 @@ class upb::Status {
#endif /* __cplusplus */
+/** upb_strview ************************************************************/
+
+typedef struct {
+ const char *data;
+ size_t size;
+} upb_strview;
+
+UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
+ upb_strview ret;
+ ret.data = data;
+ ret.size = size;
+ return ret;
+}
+
+UPB_INLINE upb_strview upb_strview_makez(const char *data) {
+ return upb_strview_make(data, strlen(data));
+}
+
+UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
+ return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
+}
+
+#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
+
+#define UPB_STRVIEW_FORMAT "%.*s"
+#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
+
/** upb_alloc *****************************************************************/
/* A upb_alloc is a possibly-stateful allocator object.
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback