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.
pull/13171/head
Joshua Haberman 6 years ago committed by GitHub
parent 00f96cb947
commit 928ef7f2c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 70
      BUILD
  2. 37
      CMakeLists.txt
  3. 2
      build_defs.bzl
  4. 2
      upb/bindings/lua/msg.c
  5. 158
      upb/decode.c
  6. 66
      upb/def.c
  7. 6
      upb/encode.c
  8. 1
      upb/generated_util.h
  9. 19
      upb/handlers.c
  10. 6
      upb/handlers.h
  11. 140
      upb/json/parser.c
  12. 2
      upb/json/parser.rl
  13. 401
      upb/legacy_msg_reflection.c
  14. 186
      upb/legacy_msg_reflection.h
  15. 437
      upb/msg.c
  16. 248
      upb/msg.h
  17. 1
      upb/msgfactory.c
  18. 20
      upb/structs.int.h
  19. 28
      upb/upb.h

70
BUILD

@ -34,23 +34,17 @@ config_setting(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
# C/C++ rules ################################################################## # Public C/C++ libraries #######################################################
cc_library( cc_library(
name = "upb", name = "upb",
srcs = [ srcs = [
"google/protobuf/descriptor.upb.c", "google/protobuf/descriptor.upb.c",
"upb/decode.c", "upb/decode.c",
"upb/def.c",
"upb/encode.c", "upb/encode.c",
"upb/handlers.c",
"upb/handlers-inl.h",
"upb/msg.c", "upb/msg.c",
"upb/msgfactory.c",
"upb/port_def.inc", "upb/port_def.inc",
"upb/port_undef.inc", "upb/port_undef.inc",
"upb/sink.c",
"upb/structs.int.h",
"upb/table.c", "upb/table.c",
"upb/table.int.h", "upb/table.int.h",
"upb/upb.c", "upb/upb.c",
@ -58,19 +52,67 @@ cc_library(
hdrs = [ hdrs = [
"google/protobuf/descriptor.upb.h", "google/protobuf/descriptor.upb.h",
"upb/decode.h", "upb/decode.h",
"upb/def.h",
"upb/encode.h", "upb/encode.h",
"upb/generated_util.h", "upb/generated_util.h",
"upb/handlers.h",
"upb/msg.h", "upb/msg.h",
"upb/msgfactory.h",
"upb/sink.h",
"upb/upb.h", "upb/upb.h",
], ],
copts = COPTS, copts = COPTS,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
cc_library(
name = "reflection",
srcs = [
"upb/def.c",
"upb/msgfactory.c",
],
hdrs = [
"upb/def.h",
"upb/msgfactory.h",
],
copts = COPTS,
visibility = ["//visibility:public"],
deps = [":upb"],
)
# Internal C/C++ libraries #####################################################
cc_library(
name = "table",
hdrs = ["upb/table.int.h"],
deps = [":upb"],
)
# Legacy C/C++ Libraries (not recommended for new code) ########################
cc_library(
name = "legacy_msg_reflection",
srcs = [
"upb/legacy_msg_reflection.c",
],
hdrs = ["upb/legacy_msg_reflection.h"],
deps = [":upb"],
)
cc_library(
name = "handlers",
srcs = [
"upb/handlers.c",
"upb/handlers-inl.h",
"upb/sink.c",
],
hdrs = [
"upb/handlers.h",
"upb/sink.h",
],
copts = COPTS,
deps = [
":reflection",
":upb",
],
)
cc_library( cc_library(
name = "upb_pb", name = "upb_pb",
srcs = [ srcs = [
@ -81,7 +123,6 @@ cc_library(
"upb/pb/textprinter.c", "upb/pb/textprinter.c",
"upb/pb/varint.c", "upb/pb/varint.c",
"upb/pb/varint.int.h", "upb/pb/varint.int.h",
"upb/table.int.h",
], ],
hdrs = [ hdrs = [
"upb/pb/decoder.h", "upb/pb/decoder.h",
@ -90,6 +131,8 @@ cc_library(
], ],
copts = COPTS, copts = COPTS,
deps = [ deps = [
":handlers",
":table",
":upb", ":upb",
], ],
) )
@ -327,6 +370,8 @@ upb_amalgamation(
amalgamator = ":amalgamate", amalgamator = ":amalgamate",
libs = [ libs = [
":upb", ":upb",
":reflection",
":handlers",
":upb_pb", ":upb_pb",
":upb_json", ":upb_json",
], ],
@ -352,6 +397,7 @@ lua_cclibrary(
"upb/bindings/lua/upb.h", "upb/bindings/lua/upb.h",
], ],
deps = [ deps = [
"legacy_msg_reflection",
"upb", "upb",
"upb_pb", "upb_pb",
], ],

@ -62,29 +62,43 @@ enable_testing()
add_library(upb add_library(upb
google/protobuf/descriptor.upb.c google/protobuf/descriptor.upb.c
upb/decode.c upb/decode.c
upb/def.c
upb/encode.c upb/encode.c
upb/handlers.c
upb/handlers-inl.h
upb/msg.c upb/msg.c
upb/msgfactory.c
upb/port_def.inc upb/port_def.inc
upb/port_undef.inc upb/port_undef.inc
upb/sink.c
upb/structs.int.h
upb/table.c upb/table.c
upb/table.int.h upb/table.int.h
upb/upb.c upb/upb.c
google/protobuf/descriptor.upb.h google/protobuf/descriptor.upb.h
upb/decode.h upb/decode.h
upb/def.h
upb/encode.h upb/encode.h
upb/generated_util.h upb/generated_util.h
upb/handlers.h
upb/msg.h upb/msg.h
upb/msgfactory.h
upb/sink.h
upb/upb.h) upb/upb.h)
add_library(reflection
upb/def.c
upb/msgfactory.c
upb/def.h
upb/msgfactory.h)
target_link_libraries(reflection
upb)
add_library(table INTERFACE)
target_link_libraries(table INTERFACE
upb)
add_library(legacy_msg_reflection
upb/legacy_msg_reflection.c
upb/legacy_msg_reflection.h)
target_link_libraries(legacy_msg_reflection
upb)
add_library(handlers
upb/handlers.c
upb/handlers-inl.h
upb/sink.c
upb/handlers.h
upb/sink.h)
target_link_libraries(handlers
reflection
upb)
add_library(upb_pb add_library(upb_pb
upb/pb/compile_decoder.c upb/pb/compile_decoder.c
upb/pb/decoder.c upb/pb/decoder.c
@ -93,11 +107,12 @@ add_library(upb_pb
upb/pb/textprinter.c upb/pb/textprinter.c
upb/pb/varint.c upb/pb/varint.c
upb/pb/varint.int.h upb/pb/varint.int.h
upb/table.int.h
upb/pb/decoder.h upb/pb/decoder.h
upb/pb/encoder.h upb/pb/encoder.h
upb/pb/textprinter.h) upb/pb/textprinter.h)
target_link_libraries(upb_pb target_link_libraries(upb_pb
handlers
table
upb) upb)
add_library(upb_json add_library(upb_json
upb/json/parser.c upb/json/parser.c

@ -329,7 +329,7 @@ def upb_proto_reflection_library(name, deps, upbc):
native.cc_library( native.cc_library(
name = name, name = name,
srcs = [":" + srcs_rule], srcs = [":" + srcs_rule],
deps = [":upb"], deps = [":upb", ":reflection"],
copts = ["-Ibazel-out/k8-fastbuild/bin"], copts = ["-Ibazel-out/k8-fastbuild/bin"],
) )

@ -7,9 +7,11 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "lauxlib.h" #include "lauxlib.h"
#include "upb/bindings/lua/upb.h" #include "upb/bindings/lua/upb.h"
#include "upb/handlers.h" #include "upb/handlers.h"
#include "upb/legacy_msg_reflection.h"
#include "upb/msg.h" #include "upb/msg.h"
/* /*

@ -2,7 +2,6 @@
#include <string.h> #include <string.h>
#include "upb/upb.h" #include "upb/upb.h"
#include "upb/decode.h" #include "upb/decode.h"
#include "upb/structs.int.h"
/* Maps descriptor type -> upb field type. */ /* Maps descriptor type -> upb field type. */
const uint8_t upb_desctype_to_fieldtype[] = { const uint8_t upb_desctype_to_fieldtype[] = {
@ -164,7 +163,7 @@ static bool upb_skip_unknownfielddata(upb_decstate *d, upb_decframe *frame,
return false; 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 needed = arr->len + elements;
size_t new_size = UPB_MAX(arr->size, 8); size_t new_size = UPB_MAX(arr->size, 8);
size_t new_bytes; size_t new_bytes;
@ -176,8 +175,8 @@ static bool upb_array_grow(upb_array *arr, size_t elements) {
new_size *= 2; new_size *= 2;
} }
old_bytes = arr->len * arr->element_size; old_bytes = arr->len * elem_size;
new_bytes = new_size * arr->element_size; new_bytes = new_size * elem_size;
new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes); new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes);
CHK(new_data); CHK(new_data);
@ -186,17 +185,23 @@ static bool upb_array_grow(upb_array *arr, size_t elements) {
return true; 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) { 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) { bool upb_array_add(upb_array *arr, size_t elements, size_t elem_size,
void *ret = upb_array_reserve(arr, elements); const void *data) {
void *dest = upb_array_reserve(arr, elements, elem_size);
CHK(dest);
arr->len += elements; arr->len += elements;
return ret; memcpy(dest, data, elements * elem_size);
return true;
} }
static upb_array *upb_getarr(upb_decframe *frame, 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); upb_set32(frame->msg, ~field->presence, field->number);
} }
static char *upb_decode_prepareslot(upb_decframe *frame, static bool upb_decode_addval(upb_decframe *frame,
const upb_msglayout_field *field) { const upb_msglayout_field *field, void *val,
size_t size) {
char *field_mem = frame->msg + field->offset; char *field_mem = frame->msg + field->offset;
upb_array *arr; upb_array *arr;
if (field->label == UPB_LABEL_REPEATED) { if (field->label == UPB_LABEL_REPEATED) {
arr = upb_getorcreatearr(frame, field); 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, 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 char *limit,
const upb_msglayout_field *field, const upb_msglayout_field *field,
int group_number) { int group_number) {
char *submsg_slot = upb_decode_prepareslot(frame, field); upb_msg **submsg = (void*)(frame->msg + field->offset);
char *submsg = *(void **)submsg_slot; const upb_msglayout *subm = frame->m->submsgs[field->submsg_index];
const upb_msglayout *subm;
subm = frame->m->submsgs[field->submsg_index];
UPB_ASSERT(subm);
if (!submsg) { if (!*submsg) {
submsg = upb_msg_new(subm, upb_msg_arena(frame->msg)); *submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
CHK(submsg); CHK(*submsg);
*(void**)submsg_slot = submsg;
} }
upb_decode_message(d, limit, group_number, submsg, subm); upb_decode_message(d, limit, group_number, *submsg, subm);
return true; return true;
} }
@ -286,37 +288,33 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame,
const char *field_start, const char *field_start,
const upb_msglayout_field *field) { const upb_msglayout_field *field) {
uint64_t val; 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)); 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_INT64:
case UPB_DESCRIPTOR_TYPE_UINT64: case UPB_DESCRIPTOR_TYPE_UINT64:
memcpy(field_mem, &val, sizeof(val)); CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break; break;
case UPB_DESCRIPTOR_TYPE_INT32: case UPB_DESCRIPTOR_TYPE_INT32:
case UPB_DESCRIPTOR_TYPE_UINT32: case UPB_DESCRIPTOR_TYPE_UINT32:
case UPB_DESCRIPTOR_TYPE_ENUM: { case UPB_DESCRIPTOR_TYPE_ENUM: {
uint32_t val32 = val; uint32_t val32 = val;
memcpy(field_mem, &val32, sizeof(val32)); CHK(upb_decode_addval(frame, field, &val32, sizeof(val32)));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_BOOL: { case UPB_DESCRIPTOR_TYPE_BOOL: {
bool valbool = val != 0; bool valbool = val != 0;
memcpy(field_mem, &valbool, sizeof(valbool)); CHK(upb_decode_addval(frame, field, &valbool, sizeof(valbool)));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_SINT32: { case UPB_DESCRIPTOR_TYPE_SINT32: {
int32_t decoded = upb_zzdecode_32(val); int32_t decoded = upb_zzdecode_32(val);
memcpy(field_mem, &decoded, sizeof(decoded)); CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded)));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_SINT64: { case UPB_DESCRIPTOR_TYPE_SINT64: {
int64_t decoded = upb_zzdecode_64(val); int64_t decoded = upb_zzdecode_64(val);
memcpy(field_mem, &decoded, sizeof(decoded)); CHK(upb_decode_addval(frame, field, &decoded, sizeof(decoded)));
break; break;
} }
default: 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, static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame,
const char *field_start, const char *field_start,
const upb_msglayout_field *field) { const upb_msglayout_field *field) {
void *field_mem;
uint64_t val; uint64_t val;
field_mem = upb_decode_prepareslot(frame, field);
CHK(field_mem);
CHK(upb_decode_64bit(&d->ptr, frame->limit, &val)); 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_DOUBLE:
case UPB_DESCRIPTOR_TYPE_FIXED64: case UPB_DESCRIPTOR_TYPE_FIXED64:
case UPB_DESCRIPTOR_TYPE_SFIXED64: case UPB_DESCRIPTOR_TYPE_SFIXED64:
memcpy(field_mem, &val, sizeof(val)); CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break; break;
default: default:
return upb_append_unknown(d, frame, field_start); 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, static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame,
const char *field_start, const char *field_start,
const upb_msglayout_field *field) { const upb_msglayout_field *field) {
void *field_mem;
uint32_t val; uint32_t val;
field_mem = upb_decode_prepareslot(frame, field);
CHK(field_mem);
CHK(upb_decode_32bit(&d->ptr, frame->limit, &val)); 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_FLOAT:
case UPB_DESCRIPTOR_TYPE_FIXED32: case UPB_DESCRIPTOR_TYPE_FIXED32:
case UPB_DESCRIPTOR_TYPE_SFIXED32: case UPB_DESCRIPTOR_TYPE_SFIXED32:
memcpy(field_mem, &val, sizeof(val)); CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
break; break;
default: default:
return upb_append_unknown(d, frame, field_start); 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, static bool upb_decode_fixedpacked(upb_array *arr, upb_strview data,
int elem_size) { int elem_size) {
int elements = data.size / elem_size; size_t elements = data.size / elem_size;
void *field_mem;
CHK((size_t)(elements * elem_size) == data.size); CHK((size_t)(elements * elem_size) == data.size);
field_mem = upb_array_add(arr, elements); CHK(upb_array_add(arr, elements, elem_size, data.data));
CHK(field_mem);
memcpy(field_mem, data.data, data.size);
return true; return true;
} }
@ -393,29 +381,24 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
upb_strview val) { upb_strview val) {
upb_array *arr = upb_getorcreatearr(frame, field); upb_array *arr = upb_getorcreatearr(frame, field);
#define VARINT_CASE(ctype, decode) { \ #define VARINT_CASE(ctype, decode) \
const char *ptr = val.data; \ { \
const char *limit = ptr + val.size; \ const char *ptr = val.data; \
while (ptr < limit) { \ const char *limit = ptr + val.size; \
uint64_t val; \ while (ptr < limit) { \
void *field_mem; \ uint64_t val; \
ctype decoded; \ ctype decoded; \
CHK(upb_decode_varint(&ptr, limit, &val)); \ CHK(upb_decode_varint(&ptr, limit, &val)); \
decoded = (decode)(val); \ decoded = (decode)(val); \
field_mem = upb_array_add(arr, 1); \ CHK(upb_array_add(arr, 1, sizeof(decoded), &decoded)); \
CHK(field_mem); \ } \
memcpy(field_mem, &decoded, sizeof(ctype)); \ return true; \
} \ }
return true; \
} switch (field->descriptortype) {
switch ((upb_descriptortype_t)field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: { case UPB_DESCRIPTOR_TYPE_BYTES: {
void *field_mem = upb_array_add(arr, 1); return upb_array_add(arr, 1, sizeof(val), &val);
CHK(field_mem);
memcpy(field_mem, &val, sizeof(val));
return true;
} }
case UPB_DESCRIPTOR_TYPE_FLOAT: case UPB_DESCRIPTOR_TYPE_FLOAT:
case UPB_DESCRIPTOR_TYPE_FIXED32: 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_INT32:
case UPB_DESCRIPTOR_TYPE_UINT32: case UPB_DESCRIPTOR_TYPE_UINT32:
case UPB_DESCRIPTOR_TYPE_ENUM: case UPB_DESCRIPTOR_TYPE_ENUM:
/* TODO: proto2 enum field that isn't in the enum. */
VARINT_CASE(uint32_t, uint32_t); VARINT_CASE(uint32_t, uint32_t);
case UPB_DESCRIPTOR_TYPE_INT64: case UPB_DESCRIPTOR_TYPE_INT64:
case UPB_DESCRIPTOR_TYPE_UINT64: 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: case UPB_DESCRIPTOR_TYPE_SINT64:
VARINT_CASE(int64_t, upb_zzdecode_64); VARINT_CASE(int64_t, upb_zzdecode_64);
case UPB_DESCRIPTOR_TYPE_MESSAGE: { case UPB_DESCRIPTOR_TYPE_MESSAGE: {
const upb_msglayout *subm; const upb_msglayout *subm = frame->m->submsgs[field->submsg_index];
char *submsg; upb_msg *submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
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);
submsg = upb_msg_new(subm, upb_msg_arena(frame->msg));
CHK(submsg); 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); d->ptr -= val.size;
CHK(field_mem);
*(void**)field_mem = submsg;
return upb_decode_message( return upb_decode_message(
d, val.data + val.size, frame->group_number, submsg, subm); 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) { if (field->label == UPB_LABEL_REPEATED) {
return upb_decode_toarray(d, frame, field_start, field, val); return upb_decode_toarray(d, frame, field_start, field, val);
} else { } else {
switch ((upb_descriptortype_t)field->descriptortype) { switch (field->descriptortype) {
case UPB_DESCRIPTOR_TYPE_STRING: case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: { case UPB_DESCRIPTOR_TYPE_BYTES: {
void *field_mem = upb_decode_prepareslot(frame, field); CHK(upb_decode_addval(frame, field, &val, sizeof(val)));
CHK(field_mem);
memcpy(field_mem, &val, sizeof(val));
break; break;
} }
case UPB_DESCRIPTOR_TYPE_MESSAGE: case UPB_DESCRIPTOR_TYPE_MESSAGE:

@ -6,7 +6,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "google/protobuf/descriptor.upb.h" #include "google/protobuf/descriptor.upb.h"
#include "upb/handlers.h"
typedef struct { typedef struct {
size_t len; size_t len;
@ -206,6 +205,30 @@ int cmp_fields(const void *p1, const void *p2) {
return field_rank(f1) - field_rank(f2); 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) { static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
/* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the
* lowest indexes, but we do not publicly guarantee this. */ * 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; 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; for(upb_msg_oneof_begin(&k, m), i = 0;
!upb_msg_oneof_done(&k); !upb_msg_oneof_done(&k);
upb_msg_oneof_next(&k), i++) { upb_msg_oneof_next(&k), i++) {

@ -1,9 +1,11 @@
/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */ /* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
#include "upb/encode.h"
#include <string.h> #include <string.h>
#include "upb/msg.h"
#include "upb/upb.h" #include "upb/upb.h"
#include "upb/encode.h"
#include "upb/structs.int.h"
#define UPB_PB_VARINT_MAX_LEN 10 #define UPB_PB_VARINT_MAX_LEN 10
#define CHK(x) do { if (!(x)) { return false; } } while(0) #define CHK(x) do { if (!(x)) { return false; } } while(0)

@ -8,7 +8,6 @@
#include <stdint.h> #include <stdint.h>
#include "upb/msg.h" #include "upb/msg.h"
#include "upb/structs.int.h"
#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs) #define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)

@ -368,25 +368,6 @@ bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
return true; 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 ***********************************************************/ /* upb_handlercache ***********************************************************/
struct upb_handlercache { struct upb_handlercache {

@ -76,7 +76,7 @@ typedef int32_t upb_selector_t;
#define UPB_STARTMSG_SELECTOR 0 #define UPB_STARTMSG_SELECTOR 0
#define UPB_ENDMSG_SELECTOR 1 #define UPB_ENDMSG_SELECTOR 1
#define UPB_UNKNOWN_SELECTOR 2 #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. */ /* Static selectors for upb::BytesHandler. */
#define UPB_STARTSTR_SELECTOR 0 #define UPB_STARTSTR_SELECTOR 0
@ -233,10 +233,6 @@ UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
return start + 1; 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 #ifdef __cplusplus
} /* extern "C" */ } /* extern "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) { static int parse_timestamp_number(upb_json_parser *p) {
size_t len; size_t len;
const char *buf; const char *buf;
char *end;
int val; int val;
/* atoi() and friends unfortunately do not support specifying the length of /* 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) { static bool start_subobject(upb_json_parser *p) {
if (p->top->is_unknown_field) { if (p->top->is_unknown_field) {
upb_jsonparser_frame *inner;
if (!check_stack(p)) return false; if (!check_stack(p)) return false;
p->top = start_jsonparser_frame(p); 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. */ * 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[] = { static const char _json_actions[] = {
0, 1, 0, 1, 1, 1, 3, 1, 0, 1, 0, 1, 1, 1, 3, 1,
4, 1, 6, 1, 7, 1, 8, 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; 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, size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) { 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); capture_resume(parser, buf);
#line 2830 "upb/json/parser.c" #line 2828 "upb/json/parser.c"
{ {
int _klen; int _klen;
unsigned int _trans; unsigned int _trans;
@ -2901,147 +2899,147 @@ _match:
switch ( *_acts++ ) switch ( *_acts++ )
{ {
case 1: case 1:
#line 2557 "upb/json/parser.rl" #line 2555 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 2: case 2:
#line 2559 "upb/json/parser.rl" #line 2557 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 23;goto _again;} } { p--; {stack[top++] = cs; cs = 23;goto _again;} }
break; break;
case 3: case 3:
#line 2563 "upb/json/parser.rl" #line 2561 "upb/json/parser.rl"
{ start_text(parser, p); } { start_text(parser, p); }
break; break;
case 4: case 4:
#line 2564 "upb/json/parser.rl" #line 2562 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); } { CHECK_RETURN_TOP(end_text(parser, p)); }
break; break;
case 5: case 5:
#line 2570 "upb/json/parser.rl" #line 2568 "upb/json/parser.rl"
{ start_hex(parser); } { start_hex(parser); }
break; break;
case 6: case 6:
#line 2571 "upb/json/parser.rl" #line 2569 "upb/json/parser.rl"
{ hexdigit(parser, p); } { hexdigit(parser, p); }
break; break;
case 7: case 7:
#line 2572 "upb/json/parser.rl" #line 2570 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); } { CHECK_RETURN_TOP(end_hex(parser)); }
break; break;
case 8: case 8:
#line 2578 "upb/json/parser.rl" #line 2576 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); } { CHECK_RETURN_TOP(escape(parser, p)); }
break; break;
case 9: case 9:
#line 2584 "upb/json/parser.rl" #line 2582 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 10: case 10:
#line 2589 "upb/json/parser.rl" #line 2587 "upb/json/parser.rl"
{ start_year(parser, p); } { start_year(parser, p); }
break; break;
case 11: case 11:
#line 2590 "upb/json/parser.rl" #line 2588 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_year(parser, p)); } { CHECK_RETURN_TOP(end_year(parser, p)); }
break; break;
case 12: case 12:
#line 2594 "upb/json/parser.rl" #line 2592 "upb/json/parser.rl"
{ start_month(parser, p); } { start_month(parser, p); }
break; break;
case 13: case 13:
#line 2595 "upb/json/parser.rl" #line 2593 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_month(parser, p)); } { CHECK_RETURN_TOP(end_month(parser, p)); }
break; break;
case 14: case 14:
#line 2599 "upb/json/parser.rl" #line 2597 "upb/json/parser.rl"
{ start_day(parser, p); } { start_day(parser, p); }
break; break;
case 15: case 15:
#line 2600 "upb/json/parser.rl" #line 2598 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_day(parser, p)); } { CHECK_RETURN_TOP(end_day(parser, p)); }
break; break;
case 16: case 16:
#line 2604 "upb/json/parser.rl" #line 2602 "upb/json/parser.rl"
{ start_hour(parser, p); } { start_hour(parser, p); }
break; break;
case 17: case 17:
#line 2605 "upb/json/parser.rl" #line 2603 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hour(parser, p)); } { CHECK_RETURN_TOP(end_hour(parser, p)); }
break; break;
case 18: case 18:
#line 2609 "upb/json/parser.rl" #line 2607 "upb/json/parser.rl"
{ start_minute(parser, p); } { start_minute(parser, p); }
break; break;
case 19: case 19:
#line 2610 "upb/json/parser.rl" #line 2608 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_minute(parser, p)); } { CHECK_RETURN_TOP(end_minute(parser, p)); }
break; break;
case 20: case 20:
#line 2614 "upb/json/parser.rl" #line 2612 "upb/json/parser.rl"
{ start_second(parser, p); } { start_second(parser, p); }
break; break;
case 21: case 21:
#line 2615 "upb/json/parser.rl" #line 2613 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_second(parser, p)); } { CHECK_RETURN_TOP(end_second(parser, p)); }
break; break;
case 22: case 22:
#line 2620 "upb/json/parser.rl" #line 2618 "upb/json/parser.rl"
{ start_duration_base(parser, p); } { start_duration_base(parser, p); }
break; break;
case 23: case 23:
#line 2621 "upb/json/parser.rl" #line 2619 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_duration_base(parser, p)); } { CHECK_RETURN_TOP(end_duration_base(parser, p)); }
break; break;
case 24: case 24:
#line 2623 "upb/json/parser.rl" #line 2621 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 25: case 25:
#line 2628 "upb/json/parser.rl" #line 2626 "upb/json/parser.rl"
{ start_timestamp_base(parser); } { start_timestamp_base(parser); }
break; break;
case 26: case 26:
#line 2630 "upb/json/parser.rl" #line 2628 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); } { start_timestamp_fraction(parser, p); }
break; break;
case 27: case 27:
#line 2631 "upb/json/parser.rl" #line 2629 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
break; break;
case 28: case 28:
#line 2633 "upb/json/parser.rl" #line 2631 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); } { start_timestamp_zone(parser, p); }
break; break;
case 29: case 29:
#line 2634 "upb/json/parser.rl" #line 2632 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
break; break;
case 30: case 30:
#line 2636 "upb/json/parser.rl" #line 2634 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 31: case 31:
#line 2641 "upb/json/parser.rl" #line 2639 "upb/json/parser.rl"
{ start_fieldmask_path_text(parser, p); } { start_fieldmask_path_text(parser, p); }
break; break;
case 32: case 32:
#line 2642 "upb/json/parser.rl" #line 2640 "upb/json/parser.rl"
{ end_fieldmask_path_text(parser, p); } { end_fieldmask_path_text(parser, p); }
break; break;
case 33: case 33:
#line 2647 "upb/json/parser.rl" #line 2645 "upb/json/parser.rl"
{ start_fieldmask_path(parser); } { start_fieldmask_path(parser); }
break; break;
case 34: case 34:
#line 2648 "upb/json/parser.rl" #line 2646 "upb/json/parser.rl"
{ end_fieldmask_path(parser); } { end_fieldmask_path(parser); }
break; break;
case 35: case 35:
#line 2654 "upb/json/parser.rl" #line 2652 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 36: case 36:
#line 2659 "upb/json/parser.rl" #line 2657 "upb/json/parser.rl"
{ {
if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
{stack[top++] = cs; cs = 47;goto _again;} {stack[top++] = cs; cs = 47;goto _again;}
@ -3055,11 +3053,11 @@ _match:
} }
break; break;
case 37: case 37:
#line 2672 "upb/json/parser.rl" #line 2670 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 78;goto _again;} } { p--; {stack[top++] = cs; cs = 78;goto _again;} }
break; break;
case 38: case 38:
#line 2677 "upb/json/parser.rl" #line 2675 "upb/json/parser.rl"
{ {
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_member(parser, p); start_any_member(parser, p);
@ -3069,11 +3067,11 @@ _match:
} }
break; break;
case 39: case 39:
#line 2684 "upb/json/parser.rl" #line 2682 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); } { CHECK_RETURN_TOP(end_membername(parser)); }
break; break;
case 40: case 40:
#line 2687 "upb/json/parser.rl" #line 2685 "upb/json/parser.rl"
{ {
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
end_any_member(parser, p); end_any_member(parser, p);
@ -3083,7 +3081,7 @@ _match:
} }
break; break;
case 41: case 41:
#line 2698 "upb/json/parser.rl" #line 2696 "upb/json/parser.rl"
{ {
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_object(parser, p); start_any_object(parser, p);
@ -3093,7 +3091,7 @@ _match:
} }
break; break;
case 42: case 42:
#line 2707 "upb/json/parser.rl" #line 2705 "upb/json/parser.rl"
{ {
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
CHECK_RETURN_TOP(end_any_object(parser, p)); CHECK_RETURN_TOP(end_any_object(parser, p));
@ -3103,54 +3101,54 @@ _match:
} }
break; break;
case 43: case 43:
#line 2719 "upb/json/parser.rl" #line 2717 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); } { CHECK_RETURN_TOP(start_array(parser)); }
break; break;
case 44: case 44:
#line 2723 "upb/json/parser.rl" #line 2721 "upb/json/parser.rl"
{ end_array(parser); } { end_array(parser); }
break; break;
case 45: case 45:
#line 2728 "upb/json/parser.rl" #line 2726 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_number(parser, p)); } { CHECK_RETURN_TOP(start_number(parser, p)); }
break; break;
case 46: case 46:
#line 2729 "upb/json/parser.rl" #line 2727 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); } { CHECK_RETURN_TOP(end_number(parser, p)); }
break; break;
case 47: case 47:
#line 2731 "upb/json/parser.rl" #line 2729 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); } { CHECK_RETURN_TOP(start_stringval(parser)); }
break; break;
case 48: case 48:
#line 2732 "upb/json/parser.rl" #line 2730 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); } { CHECK_RETURN_TOP(end_stringval(parser)); }
break; break;
case 49: case 49:
#line 2734 "upb/json/parser.rl" #line 2732 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); } { CHECK_RETURN_TOP(end_bool(parser, true)); }
break; break;
case 50: case 50:
#line 2736 "upb/json/parser.rl" #line 2734 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); } { CHECK_RETURN_TOP(end_bool(parser, false)); }
break; break;
case 51: case 51:
#line 2738 "upb/json/parser.rl" #line 2736 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); } { CHECK_RETURN_TOP(end_null(parser)); }
break; break;
case 52: case 52:
#line 2740 "upb/json/parser.rl" #line 2738 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject_full(parser)); } { CHECK_RETURN_TOP(start_subobject_full(parser)); }
break; break;
case 53: case 53:
#line 2741 "upb/json/parser.rl" #line 2739 "upb/json/parser.rl"
{ end_subobject_full(parser); } { end_subobject_full(parser); }
break; break;
case 54: case 54:
#line 2746 "upb/json/parser.rl" #line 2744 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
#line 3154 "upb/json/parser.c" #line 3152 "upb/json/parser.c"
} }
} }
@ -3167,32 +3165,32 @@ _again:
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 0: case 0:
#line 2555 "upb/json/parser.rl" #line 2553 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; if ( p == pe ) { p--; {cs = stack[--top]; if ( p == pe )
goto _test_eof; goto _test_eof;
goto _again;} } goto _again;} }
break; break;
case 46: case 46:
#line 2729 "upb/json/parser.rl" #line 2727 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); } { CHECK_RETURN_TOP(end_number(parser, p)); }
break; break;
case 49: case 49:
#line 2734 "upb/json/parser.rl" #line 2732 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); } { CHECK_RETURN_TOP(end_bool(parser, true)); }
break; break;
case 50: case 50:
#line 2736 "upb/json/parser.rl" #line 2734 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); } { CHECK_RETURN_TOP(end_bool(parser, false)); }
break; break;
case 51: case 51:
#line 2738 "upb/json/parser.rl" #line 2736 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); } { CHECK_RETURN_TOP(end_null(parser)); }
break; break;
case 53: case 53:
#line 2741 "upb/json/parser.rl" #line 2739 "upb/json/parser.rl"
{ end_subobject_full(parser); } { end_subobject_full(parser); }
break; break;
#line 3196 "upb/json/parser.c" #line 3194 "upb/json/parser.c"
} }
} }
} }
@ -3200,7 +3198,7 @@ goto _again;} }
_out: {} _out: {}
} }
#line 2774 "upb/json/parser.rl" #line 2772 "upb/json/parser.rl"
if (p != pe) { if (p != pe) {
upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p); 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. */ /* Emit Ragel initialization of the parser. */
#line 3247 "upb/json/parser.c" #line 3245 "upb/json/parser.c"
{ {
cs = json_start; cs = json_start;
top = 0; top = 0;
} }
#line 2816 "upb/json/parser.rl" #line 2814 "upb/json/parser.rl"
p->current_state = cs; p->current_state = cs;
p->parser_top = top; p->parser_top = top;
accumulate_clear(p); accumulate_clear(p);

@ -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) { static int parse_timestamp_number(upb_json_parser *p) {
size_t len; size_t len;
const char *buf; const char *buf;
char *end;
int val; int val;
/* atoi() and friends unfortunately do not support specifying the length of /* 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) { static bool start_subobject(upb_json_parser *p) {
if (p->top->is_unknown_field) { if (p->top->is_unknown_field) {
upb_jsonparser_frame *inner;
if (!check_stack(p)) return false; if (!check_stack(p)) return false;
p->top = start_jsonparser_frame(p); p->top = start_jsonparser_frame(p);

@ -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);
}

@ -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_

@ -1,111 +1,9 @@
#include <string.h>
#include "upb/table.int.h"
#include "upb/msg.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) { #include "upb/table.int.h"
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 #define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + ofs)
* violate aliasing.
*/
#define DEREF(msg, ofs, type) *PTR_AT(msg, ofs, type)
/* Internal members of a upb_msg. We can change this without breaking binary /* 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* * 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 *); 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) { static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
return VOIDPTR_AT(msg, -sizeof(upb_msg_internal)); 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)); return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext));
} }
void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len) { upb_arena *upb_msg_arena(const upb_msg *msg) {
upb_msg_internal* in = upb_msg_getinternal(msg); return upb_msg_getinternal_const(msg)->arena;
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_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { 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; 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_array *upb_array_new(upb_fieldtype_t type, upb_arena *a) {
upb_alloc *alloc = upb_arena_alloc(a); upb_alloc *alloc = upb_arena_alloc(a);
upb_array *ret = upb_malloc(alloc, sizeof(upb_array)); 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->data = NULL;
ret->len = 0; ret->len = 0;
ret->size = 0; ret->size = 0;
ret->element_size = upb_msgval_sizeof(type);
ret->arena = a; ret->arena = a;
return ret; return ret;
} }
size_t upb_array_size(const upb_array *arr) { void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len) {
return arr->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);
upb_fieldtype_t upb_array_type(const upb_array *arr) { size_t need = in->unknown_size + len;
return arr->type; 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_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;
} }
memcpy(in->unknown + in->unknown_len, data, len);
upb_mapiter_begin(ret, t); in->unknown_len += len;
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) { const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
upb_strtable_iter_setdone(&i->iter); 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) { #undef VOIDPTR_AT
return upb_strtable_iter_isequal(&i1->iter, &i2->iter);
}

@ -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 ** The definitions in this file are internal to upb.
** 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?
**/ **/
#ifndef UPB_MSG_H_ #ifndef UPB_MSG_H_
@ -24,20 +12,6 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "upb/upb.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 #ifdef __cplusplus
extern "C" { extern "C" {
@ -45,15 +19,6 @@ extern "C" {
typedef void upb_msg; 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 *************************************************************/
/* upb_msglayout represents the memory layout of a given upb_msgdef. The /* upb_msglayout represents the memory layout of a given upb_msgdef. The
@ -79,91 +44,18 @@ typedef struct upb_msglayout {
bool extendable; bool extendable;
} upb_msglayout; } upb_msglayout;
/** upb_strview ************************************************************/ /** Message internal representation *******************************************/
/* Our internal representation for repeated fields. */
typedef struct { typedef struct {
const char *data; upb_fieldtype_t type;
size_t size; void *data; /* Each element is element_size. */
} upb_strview; size_t len; /* Measured in elements. */
size_t size; /* Measured in elements. */
UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) { upb_arena *arena;
upb_strview ret; } upb_array;
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) { upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a);
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. */ /* 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); 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); 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_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 #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

@ -1,5 +1,4 @@
#include "upb/handlers.h"
#include "upb/msgfactory.h" #include "upb/msgfactory.h"
static bool is_power_of_two(size_t val) { static bool is_power_of_two(size_t val) {

@ -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_ */

@ -13,6 +13,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#ifdef __cplusplus #ifdef __cplusplus
#include <memory> #include <memory>
@ -170,6 +171,33 @@ class upb::Status {
#endif /* __cplusplus */ #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 *****************************************************************/ /** upb_alloc *****************************************************************/
/* A upb_alloc is a possibly-stateful allocator object. /* A upb_alloc is a possibly-stateful allocator object.

Loading…
Cancel
Save