summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
Diffstat (limited to 'upb')
-rwxr-xr-xupb/descriptor/descriptor.upb.c80
-rwxr-xr-xupb/descriptor/descriptor.upb.h122
-rw-r--r--upb/descriptor/reader.c166
-rw-r--r--upb/descriptor/reader.h4
-rw-r--r--upb/google/proto1.cc147
-rw-r--r--upb/google/proto2.cc249
-rw-r--r--upb/handlers-inl.h470
-rw-r--r--upb/handlers.c563
-rw-r--r--upb/handlers.h1007
-rw-r--r--upb/pb/decoder.c54
-rw-r--r--upb/pb/decoder.h4
-rw-r--r--upb/pb/decoder_x64.dasc201
-rw-r--r--upb/pb/glue.c4
-rw-r--r--upb/pb/textprinter.c51
-rw-r--r--upb/shim/shim.c69
-rw-r--r--upb/shim/shim.h74
-rw-r--r--upb/sink.c179
-rw-r--r--upb/sink.h172
-rw-r--r--upb/table.h1
-rw-r--r--upb/upb.h35
20 files changed, 1877 insertions, 1775 deletions
diff --git a/upb/descriptor/descriptor.upb.c b/upb/descriptor/descriptor.upb.c
index 80d5f59..61a5449 100755
--- a/upb/descriptor/descriptor.upb.c
+++ b/upb/descriptor/descriptor.upb.c
@@ -12,53 +12,53 @@ const upb_tabent google_protobuf_intentries[66];
const _upb_value google_protobuf_arrays[97];
const upb_msgdef google_protobuf_msgs[20] = {
- UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[0], &google_protobuf_arrays[0], 6, 5), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[0]), 25),
+ UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[0], &google_protobuf_arrays[0], 6, 5), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[0]), 31),
UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[6], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[16]), 2),
- UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[10], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[20]), 9),
- UPB_MSGDEF_INIT("google.protobuf.EnumOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[14], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[24]), 4),
- UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[15], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[28]), 6),
- UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[19], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[32]), 4),
- UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[8], &google_protobuf_arrays[20], 6, 5), UPB_STRTABLE_INIT(8, 15, 9, 4, &google_protobuf_strentries[36]), 17),
- UPB_MSGDEF_INIT("google.protobuf.FieldOptions", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[12], &google_protobuf_arrays[26], 5, 3), UPB_STRTABLE_INIT(5, 7, 9, 3, &google_protobuf_strentries[52]), 10),
- UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", UPB_INTTABLE_INIT(4, 7, 9, 3, &google_protobuf_intentries[16], &google_protobuf_arrays[31], 6, 5), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[60]), 31),
- UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[37], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[76]), 4),
- UPB_MSGDEF_INIT("google.protobuf.FileOptions", UPB_INTTABLE_INIT(8, 15, 9, 4, &google_protobuf_intentries[24], &google_protobuf_arrays[40], 6, 1), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[80]), 16),
- UPB_MSGDEF_INIT("google.protobuf.MessageOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[40], &google_protobuf_arrays[46], 4, 2), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[96]), 6),
- UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[50], 5, 4), UPB_STRTABLE_INIT(4, 7, 9, 3, &google_protobuf_strentries[100]), 11),
- UPB_MSGDEF_INIT("google.protobuf.MethodOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[42], &google_protobuf_arrays[55], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[108]), 4),
- UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[56], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[112]), 9),
- UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[44], &google_protobuf_arrays[60], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[116]), 4),
- UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[61], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[120]), 4),
+ UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[10], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[20]), 11),
+ UPB_MSGDEF_INIT("google.protobuf.EnumOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[14], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[24]), 5),
+ UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[15], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[28]), 7),
+ UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[19], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[32]), 5),
+ UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[8], &google_protobuf_arrays[20], 6, 5), UPB_STRTABLE_INIT(8, 15, 9, 4, &google_protobuf_strentries[36]), 18),
+ UPB_MSGDEF_INIT("google.protobuf.FieldOptions", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[12], &google_protobuf_arrays[26], 5, 3), UPB_STRTABLE_INIT(5, 7, 9, 3, &google_protobuf_strentries[52]), 11),
+ UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", UPB_INTTABLE_INIT(4, 7, 9, 3, &google_protobuf_intentries[16], &google_protobuf_arrays[31], 6, 5), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[60]), 37),
+ UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[37], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[76]), 5),
+ UPB_MSGDEF_INIT("google.protobuf.FileOptions", UPB_INTTABLE_INIT(8, 15, 9, 4, &google_protobuf_intentries[24], &google_protobuf_arrays[40], 6, 1), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[80]), 17),
+ UPB_MSGDEF_INIT("google.protobuf.MessageOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[40], &google_protobuf_arrays[46], 4, 2), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[96]), 7),
+ UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[50], 5, 4), UPB_STRTABLE_INIT(4, 7, 9, 3, &google_protobuf_strentries[100]), 12),
+ UPB_MSGDEF_INIT("google.protobuf.MethodOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[42], &google_protobuf_arrays[55], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[108]), 5),
+ UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[56], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[112]), 11),
+ UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[44], &google_protobuf_arrays[60], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[116]), 5),
+ UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[61], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[120]), 5),
UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[64], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[124]), 6),
- UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[46], &google_protobuf_arrays[68], 6, 4), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[128]), 16),
+ UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[46], &google_protobuf_arrays[68], 6, 4), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[128]), 17),
UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[74], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[144]), 4),
};
const upb_fielddef google_protobuf_fields[73] = {
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 9, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "ctype", 1, &google_protobuf_msgs[7], upb_upcast(&google_protobuf_enums[2]), 0, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 14, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 15, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 8, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 2, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 12, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 13, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "end", 2, &google_protobuf_msgs[1], NULL, 1, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[2]), 13, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[2]), 17, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[2]), 15, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[2]), 18, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 3, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[6]), 29, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 21, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[1]), 17, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[6]), 34, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 25, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[1]), 20, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "field", 2, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "file", 1, &google_protobuf_msgs[9], upb_upcast(&google_protobuf_msgs[8]), 2, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 4, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 6, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 4, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 15, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 11, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 16, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 12, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 0, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "label", 4, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_enums[0]), 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "location", 1, &google_protobuf_msgs[16], upb_upcast(&google_protobuf_msgs[17]), 2, UPB_VALUE_INIT_NONE),
@@ -74,32 +74,32 @@ const upb_fielddef google_protobuf_fields[73] = {
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[0], NULL, 0, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[8], NULL, 0, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 0, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 8, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[0]), 9, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 9, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[0]), 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 1, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 2, &google_protobuf_msgs[4], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 3, &google_protobuf_msgs[6], NULL, 6, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], upb_upcast(&google_protobuf_enums[3]), 14, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], upb_upcast(&google_protobuf_enums[3]), 15, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 4, &google_protobuf_msgs[12], upb_upcast(&google_protobuf_msgs[13]), 9, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], upb_upcast(&google_protobuf_msgs[15]), 7, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[10]), 19, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], upb_upcast(&google_protobuf_msgs[3]), 7, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[11]), 23, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], upb_upcast(&google_protobuf_msgs[15]), 8, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[10]), 21, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], upb_upcast(&google_protobuf_msgs[3]), 8, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[11]), 28, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_msgs[7]), 9, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[4], upb_upcast(&google_protobuf_msgs[5]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 6, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "package", 2, &google_protobuf_msgs[8], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "packed", 2, &google_protobuf_msgs[7], NULL, 1, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "path", 1, &google_protobuf_msgs[17], NULL, 2, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 7, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 8, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 5, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[14]), 25, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[16]), 21, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[14]), 29, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[16]), 24, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "span", 2, &google_protobuf_msgs[17], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "start", 1, &google_protobuf_msgs[1], NULL, 0, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 13, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 14, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "type", 5, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_enums[1]), 8, UPB_VALUE_INIT_NONE),
- UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 11, UPB_VALUE_INIT_NONE),
+ UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 12, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], upb_upcast(&google_protobuf_msgs[18]), 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], upb_upcast(&google_protobuf_msgs[18]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], upb_upcast(&google_protobuf_msgs[18]), 2, UPB_VALUE_INIT_NONE),
diff --git a/upb/descriptor/descriptor.upb.h b/upb/descriptor/descriptor.upb.h
index 23c42a0..e3291a3 100755
--- a/upb/descriptor/descriptor.upb.h
+++ b/upb/descriptor/descriptor.upb.h
@@ -84,48 +84,48 @@ extern const upb_enumdef google_protobuf_enums[4];
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART &google_protobuf_msgs[19]
// Selector definitions.
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 11
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 9
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 10
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 12
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 10
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 11
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 3
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 0
-#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 16
-#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 14
-#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 15
+#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 17
+#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 15
+#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 16
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 10
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 7
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 8
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 6
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 2
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 12
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 13
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 1
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 13
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 14
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 17
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 16
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 15
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 18
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 15
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 14
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 13
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 18
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 17
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 16
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 19
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 5
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 3
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 4
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 3
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 4
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 29
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 28
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 27
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 30
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 21
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 20
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 19
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 17
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 16
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 15
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 18
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 34
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 33
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 32
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 35
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 25
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 24
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 23
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 26
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 20
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 19
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 18
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 21
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 4
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 3
@@ -134,19 +134,19 @@ extern const upb_enumdef google_protobuf_enums[4];
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 1
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 0
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 3
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 6
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 4
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 5
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 7
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 5
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 6
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 5
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 3
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 3
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 6
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 4
-#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 15
-#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 13
-#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 11
-#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 12
+#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 16
+#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 14
+#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 12
+#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 13
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 2
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 0
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 1
@@ -192,25 +192,25 @@ extern const upb_enumdef google_protobuf_enums[4];
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 0
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 1
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 8
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 9
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 8
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 7
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 10
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 9
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 10
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 9
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 8
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 1
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 3
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 6
-#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 14
+#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 15
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 9
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 10
-#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7
-#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 8
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 19
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20
-#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7
-#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 8
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 23
-#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 24
+#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 8
+#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 9
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 21
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 22
+#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 8
+#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 9
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 28
+#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 29
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 9
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 10
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 4
@@ -225,25 +225,25 @@ extern const upb_enumdef google_protobuf_enums[4];
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 1
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 2
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 0
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 7
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 5
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 25
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 24
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 23
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 26
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 21
-#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 22
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 29
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 28
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 27
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 30
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 24
+#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 25
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 4
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 5
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 0
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 15
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 13
-#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 14
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 16
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 14
+#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 15
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 8
-#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 13
-#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 11
-#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 12
+#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 14
+#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 12
+#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 13
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 1
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 0
diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c
index 529d5ef..5fe334f 100644
--- a/upb/descriptor/reader.c
+++ b/upb/descriptor/reader.c
@@ -52,13 +52,15 @@ static char *upb_join(const char *base, const char *name) {
// upb_deflist is an internal-only dynamic array for storing a growing list of
// upb_defs.
typedef struct {
+ upb_pipeline *pipeline;
upb_def **defs;
size_t len;
size_t size;
bool owned;
} upb_deflist;
-void upb_deflist_init(upb_deflist *l) {
+void upb_deflist_init(upb_deflist *l, upb_pipeline *pipeline) {
+ l->pipeline = pipeline;
l->size = 0;
l->defs = NULL;
l->len = 0;
@@ -68,15 +70,16 @@ void upb_deflist_init(upb_deflist *l) {
void upb_deflist_uninit(upb_deflist *l) {
if (l->owned)
for(size_t i = 0; i < l->len; i++)
- upb_def_unref(l->defs[i], &l->defs);
+ upb_def_unref(l->defs[i], l);
}
-bool upb_deflist_push(upb_deflist *l, upb_def *d, upb_pipeline *p) {
+bool upb_deflist_push(upb_deflist *l, upb_def *d) {
if(++l->len >= l->size) {
size_t new_size = UPB_MAX(l->size, 4);
new_size *= 2;
l->defs = upb_pipeline_realloc(
- p, l->defs, l->size * sizeof(void*), new_size * sizeof(void*));
+ l->pipeline, l->defs,
+ l->size * sizeof(void*), new_size * sizeof(void*));
if (!l->defs) return false;
l->size = new_size;
}
@@ -87,7 +90,7 @@ bool upb_deflist_push(upb_deflist *l, upb_def *d, upb_pipeline *p) {
void upb_deflist_donaterefs(upb_deflist *l, void *owner) {
assert(l->owned);
for (size_t i = 0; i < l->len; i++)
- upb_def_donateref(l->defs[i], &l->defs, owner);
+ upb_def_donateref(l->defs[i], l, owner);
l->owned = false;
}
@@ -134,8 +137,8 @@ struct upb_descreader {
upb_fielddef *f;
};
-void upb_descreader_init(void *r);
-void upb_descreader_uninit(void *r);
+void upb_descreader_init(void *self, upb_pipeline *p);
+void upb_descreader_uninit(void *self);
const upb_frametype upb_descreader_frametype = {
sizeof(upb_descreader),
@@ -155,16 +158,16 @@ const upb_handlers *upb_descreader_gethandlers(const void *owner);
/* upb_descreader ************************************************************/
-void upb_descreader_init(void *_r) {
- upb_descreader *r = _r;
- upb_deflist_init(&r->defs);
+void upb_descreader_init(void *self, upb_pipeline *pipeline) {
+ upb_descreader *r = self;
+ upb_deflist_init(&r->defs, pipeline);
r->stack_len = 0;
r->name = NULL;
r->default_string = NULL;
}
-void upb_descreader_uninit(void *_r) {
- upb_descreader *r = _r;
+void upb_descreader_uninit(void *self) {
+ upb_descreader *r = self;
free(r->name);
upb_deflist_uninit(&r->defs);
free(r->default_string);
@@ -213,37 +216,39 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) {
}
// Handlers for google.protobuf.FileDescriptorProto.
-static bool file_startmsg(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool file_startmsg(void *r) {
upb_descreader_startcontainer(r);
return true;
}
-static void file_endmsg(const upb_sinkframe *frame, upb_status *status) {
+static bool file_endmsg(void *closure, upb_status *status) {
UPB_UNUSED(status);
- upb_descreader *r = upb_sinkframe_userdata(frame);
+ upb_descreader *r = closure;
upb_descreader_endcontainer(r);
+ return true;
}
-static size_t file_onpackage(const upb_sinkframe *frame,
- const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static size_t file_onpackage(void *closure, const void *hd, const char *buf,
+ size_t n) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// XXX: see comment at the top of the file.
upb_descreader_setscopename(r, upb_strndup(buf, n));
return n;
}
// Handlers for google.protobuf.EnumValueDescriptorProto.
-static bool enumval_startmsg(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool enumval_startmsg(void *closure) {
+ upb_descreader *r = closure;
r->saw_number = false;
r->saw_name = false;
return true;
}
-static size_t enumval_onname(const upb_sinkframe *frame,
- const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static size_t enumval_onname(void *closure, const void *hd, const char *buf,
+ size_t n) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// XXX: see comment at the top of the file.
free(r->name);
r->name = upb_strndup(buf, n);
@@ -251,18 +256,19 @@ static size_t enumval_onname(const upb_sinkframe *frame,
return n;
}
-static bool enumval_onnumber(const upb_sinkframe *frame, int32_t val) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool enumval_onnumber(void *closure, const void *hd, int32_t val) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
r->number = val;
r->saw_number = true;
return true;
}
-static void enumval_endmsg(const upb_sinkframe *frame, upb_status *status) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool enumval_endmsg(void *closure, upb_status *status) {
+ upb_descreader *r = closure;
if(!r->saw_number || !r->saw_name) {
upb_status_seterrliteral(status, "Enum value missing name or number.");
- return;
+ return false;
}
upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
if (upb_enumdef_numvals(e) == 0) {
@@ -273,33 +279,35 @@ static void enumval_endmsg(const upb_sinkframe *frame, upb_status *status) {
upb_enumdef_addval(e, r->name, r->number, status);
free(r->name);
r->name = NULL;
+ return true;
}
// Handlers for google.protobuf.EnumDescriptorProto.
-static bool enum_startmsg(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
- upb_pipeline *p = upb_sinkframe_pipeline(frame);
- upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs)), p);
+static bool enum_startmsg(void *closure) {
+ upb_descreader *r = closure;
+ upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs)));
return true;
}
-static void enum_endmsg(const upb_sinkframe *frame, upb_status *status) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool enum_endmsg(void *closure, upb_status *status) {
+ upb_descreader *r = closure;
upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
if (upb_def_fullname(upb_descreader_last(r)) == NULL) {
upb_status_seterrliteral(status, "Enum had no name.");
- return;
+ return false;
}
if (upb_enumdef_numvals(e) == 0) {
upb_status_seterrliteral(status, "Enum had no values.");
- return;
+ return false;
}
+ return true;
}
-static size_t enum_onname(const upb_sinkframe *frame,
- const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static size_t enum_onname(void *closure, const void *hd, const char *buf,
+ size_t n) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// XXX: see comment at the top of the file.
char *fullname = upb_strndup(buf, n);
upb_def_setfullname(upb_descreader_last(r), fullname);
@@ -308,8 +316,8 @@ static size_t enum_onname(const upb_sinkframe *frame,
}
// Handlers for google.protobuf.FieldDescriptorProto
-static bool field_startmsg(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool field_startmsg(void *closure) {
+ upb_descreader *r = closure;
r->f = upb_fielddef_new(&r->defs);
free(r->default_string);
r->default_string = NULL;
@@ -380,8 +388,8 @@ static bool parse_default(char *str, upb_value *d, int type) {
return success;
}
-static void field_endmsg(const upb_sinkframe *frame, upb_status *status) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool field_endmsg(void *closure, upb_status *status) {
+ upb_descreader *r = closure;
upb_fielddef *f = r->f;
// TODO: verify that all required fields were present.
assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL);
@@ -390,7 +398,7 @@ static void field_endmsg(const upb_sinkframe *frame, upb_status *status) {
if (r->default_string) {
if (upb_fielddef_issubmsg(f)) {
upb_status_seterrliteral(status, "Submessages cannot have defaults.");
- return;
+ return false;
}
if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
upb_fielddef_setdefaultcstr(f, r->default_string);
@@ -401,34 +409,39 @@ static void field_endmsg(const upb_sinkframe *frame, upb_status *status) {
// We don't worry too much about giving a great error message since the
// compiler should have ensured this was correct.
upb_status_seterrliteral(status, "Error converting default value.");
- return;
+ return false;
}
upb_fielddef_setdefault(f, val);
}
}
+ return true;
}
-static bool field_ontype(const upb_sinkframe *frame, int32_t val) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool field_ontype(void *closure, const void *hd, int32_t val) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
upb_fielddef_setdescriptortype(r->f, val);
return true;
}
-static bool field_onlabel(const upb_sinkframe *frame, int32_t val) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool field_onlabel(void *closure, const void *hd, int32_t val) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
upb_fielddef_setlabel(r->f, val);
return true;
}
-static bool field_onnumber(const upb_sinkframe *frame, int32_t val) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool field_onnumber(void *closure, const void *hd, int32_t val) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
upb_fielddef_setnumber(r->f, val);
return true;
}
-static size_t field_onname(const upb_sinkframe *frame,
- const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static size_t field_onname(void *closure, const void *hd, const char *buf,
+ size_t n) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
upb_fielddef_setname(r->f, name);
@@ -436,9 +449,10 @@ static size_t field_onname(const upb_sinkframe *frame,
return n;
}
-static size_t field_ontypename(const upb_sinkframe *frame,
- const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static size_t field_ontypename(void *closure, const void *hd, const char *buf,
+ size_t n) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
upb_fielddef_setsubdefname(r->f, name);
@@ -446,9 +460,10 @@ static size_t field_ontypename(const upb_sinkframe *frame,
return n;
}
-static size_t field_ondefaultval(const upb_sinkframe *frame,
+static size_t field_ondefaultval(void *closure, const void *hd,
const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// Have to convert from string to the correct type, but we might not know the
// type yet, so we save it as a string until the end of the field.
// XXX: see comment at the top of the file.
@@ -458,27 +473,28 @@ static size_t field_ondefaultval(const upb_sinkframe *frame,
}
// Handlers for google.protobuf.DescriptorProto (representing a message).
-static bool msg_startmsg(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
- upb_pipeline *p = upb_sinkframe_pipeline(frame);
- upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs)), p);
+static bool msg_startmsg(void *closure) {
+ upb_descreader *r = closure;
+ upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs)));
upb_descreader_startcontainer(r);
return true;
}
-static void msg_endmsg(const upb_sinkframe *frame, upb_status *status) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool msg_endmsg(void *closure, upb_status *status) {
+ upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
if(!upb_def_fullname(upb_upcast(m))) {
upb_status_seterrliteral(status, "Encountered message with no name.");
- return;
+ return false;
}
upb_descreader_endcontainer(r);
+ return true;
}
-static size_t msg_onname(const upb_sinkframe *frame,
- const char *buf, size_t n) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static size_t msg_onname(void *closure, const void *hd, const char *buf,
+ size_t n) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
@@ -487,16 +503,18 @@ static size_t msg_onname(const upb_sinkframe *frame,
return n;
}
-static bool msg_onendfield(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool msg_onendfield(void *closure, const void *hd) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
upb_msgdef_addfield(m, r->f, &r->defs);
r->f = NULL;
return true;
}
-static bool discardfield(const upb_sinkframe *frame) {
- upb_descreader *r = upb_sinkframe_userdata(frame);
+static bool discardfield(void *closure, const void *hd) {
+ UPB_UNUSED(hd);
+ upb_descreader *r = closure;
// Discard extension field so we don't leak it.
upb_fielddef_unref(r->f, &r->defs);
r->f = NULL;
diff --git a/upb/descriptor/reader.h b/upb/descriptor/reader.h
index 87f5f86..b7c7d8b 100644
--- a/upb/descriptor/reader.h
+++ b/upb/descriptor/reader.h
@@ -57,10 +57,6 @@ const upb_handlers *upb_descreader_gethandlers(const void *owner);
namespace upb {
-template<> inline const FrameType* GetFrameType<upb::descriptor::Reader>() {
- return upb_descreader_getframetype();
-}
-
namespace descriptor {
inline upb::Def** GetDefs(Reader* r, void* owner, int* n) {
return upb_descreader_getdefs(r, owner, n);
diff --git a/upb/google/proto1.cc b/upb/google/proto1.cc
index 3967723..51b221a 100644
--- a/upb/google/proto1.cc
+++ b/upb/google/proto1.cc
@@ -23,6 +23,7 @@
#include "net/proto/proto2_reflection.h"
#include "upb/def.h"
#include "upb/handlers.h"
+#include "upb/shim/shim.h"
#include "upb/sink.h"
template <class T> static T* GetPointer(void* message, size_t offset) {
@@ -202,14 +203,12 @@ class P2R_Handlers {
const proto2::FieldDescriptor* proto2_f, const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(f->IsSequence());
- h->SetStartSequenceHandler(f, &PushOffset, new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset>);
+ h->SetStartSequenceHandler(
+ f, UpbBind(PushOffset, new FieldOffset(proto2_f, r)));
}
- static void* PushOffset(const upb::SinkFrame* frame) {
- const FieldOffset* offset =
- static_cast<FieldOffset*>(frame->handler_data());
- return offset->GetFieldPointer<void>(frame->userdata());
+ static void* PushOffset(void* m, const FieldOffset* offset) {
+ return offset->GetFieldPointer<void>(m);
}
// Primitive Value (numeric, enum, bool) /////////////////////////////////////
@@ -220,18 +219,15 @@ class P2R_Handlers {
const upb::FieldDef* f, upb::Handlers* h) {
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetValueHandler<T>(f, &Append<T>, NULL, NULL);
+ h->SetValueHandler<T>(f, UpbMakeHandlerT(Append<T>));
} else {
- upb::SetStoreValueHandler<T>(f, GetOffset(proto2_f, r),
- GetHasbit(proto2_f, r), h);
+ upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r));
}
}
template <typename T>
- static bool Append(const upb::SinkFrame* frame, T val) {
+ static bool Append(proto2::RepeatedField<T>* r, T val) {
// Proto1's ProtoArray class derives from proto2::RepeatedField.
- proto2::RepeatedField<T>* r =
- static_cast<proto2::RepeatedField<T>*>(frame->userdata());
r->Add(val);
return true;
}
@@ -241,21 +237,18 @@ class P2R_Handlers {
static void SetStringHandlers(const proto2::FieldDescriptor* proto2_f,
const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
- h->SetStringHandler(f, &OnStringBuf, NULL, NULL);
+ h->SetStringHandler(f, UpbMakeHandler(OnStringBuf));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, &StartRepeatedString, NULL, NULL);
+ h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedString));
} else {
- h->SetStartStringHandler(f, &StartString, new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset>);
+ h->SetStartStringHandler(
+ f, UpbBind(StartString, new FieldOffset(proto2_f, r)));
}
}
- static void* StartString(const upb::SinkFrame* frame, size_t size_hint) {
- UPB_UNUSED(size_hint);
- void* m = frame->userdata();
- const FieldOffset* info =
- static_cast<const FieldOffset*>(frame->handler_data());
+ static string* StartString(proto2::Message* m, const FieldOffset* info,
+ size_t size_hint) {
info->SetHasbit(m);
string* str = info->GetFieldPointer<string>(m);
str->clear();
@@ -263,18 +256,13 @@ class P2R_Handlers {
return str;
}
- static size_t OnStringBuf(const upb::SinkFrame* frame,
- const char* buf,
- size_t n) {
- string* s = static_cast<string*>(frame->userdata());
+ static size_t OnStringBuf(string* s, const char* buf, size_t n) {
s->append(buf, n);
return n;
}
- static void* StartRepeatedString(const upb::SinkFrame* frame,
- size_t size_hint) {
- proto2::RepeatedPtrField<string>* r =
- static_cast<proto2::RepeatedPtrField<string>*>(frame->userdata());
+ static string* StartRepeatedString(proto2::RepeatedPtrField<string>* r,
+ size_t size_hint) {
string* str = r->Add();
// reserve() here appears to hurt performance rather than help.
return str;
@@ -287,17 +275,14 @@ class P2R_Handlers {
const upb::FieldDef* f, upb::Handlers* h) {
// This type is only used for non-repeated string fields.
assert(!f->IsSequence());
- h->SetStartStringHandler(f, &StartOutOfLineString,
- new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset>);
- h->SetStringHandler(f, &OnStringBuf, NULL, NULL);
+ h->SetStartStringHandler(
+ f, UpbBind(StartOutOfLineString, new FieldOffset(proto2_f, r)));
+ h->SetStringHandler(f, UpbMakeHandler(OnStringBuf));
}
- static void* StartOutOfLineString(const upb::SinkFrame* frame,
- size_t size_hint) {
- const FieldOffset* info =
- static_cast<const FieldOffset*>(frame->handler_data());
- void* m = frame->userdata();
+ static string* StartOutOfLineString(proto2::Message* m,
+ const FieldOffset* info,
+ size_t size_hint) {
info->SetHasbit(m);
string** str = info->GetFieldPointer<string*>(m);
if (*str == &::proto2::internal::GetEmptyString())
@@ -312,40 +297,33 @@ class P2R_Handlers {
static void SetCordHandlers(const proto2::FieldDescriptor* proto2_f,
const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
- h->SetStringHandler(f, &OnCordBuf, NULL, NULL);
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, &StartRepeatedCord, NULL, NULL);
+ h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord));
} else {
- h->SetStartStringHandler(f, &StartCord, new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset*>);
+ h->SetStartStringHandler(
+ f, UpbBind(StartCord, new FieldOffset(proto2_f, r)));
}
+ h->SetStringHandler(f, UpbMakeHandler(OnCordBuf));
}
- static void* StartCord(const upb::SinkFrame* frame, size_t size_hint) {
+ static Cord* StartCord(proto2::Message* m, const FieldOffset* offset,
+ size_t size_hint) {
UPB_UNUSED(size_hint);
- void* m = frame->userdata();
- const FieldOffset* offset =
- static_cast<const FieldOffset*>(frame->handler_data());
offset->SetHasbit(m);
Cord* field = offset->GetFieldPointer<Cord>(m);
field->Clear();
return field;
}
- static size_t OnCordBuf(const upb::SinkFrame* frame,
- const char* buf,
- size_t n) {
- Cord* c = static_cast<Cord*>(frame->userdata());
+ static size_t OnCordBuf(Cord* c, const char* buf, size_t n) {
c->Append(StringPiece(buf, n));
return true;
}
- static void* StartRepeatedCord(const upb::SinkFrame* frame,
+ static Cord* StartRepeatedCord(proto2::RepeatedField<Cord>* r,
size_t size_hint) {
UPB_UNUSED(size_hint);
- proto2::RepeatedField<Cord>* r =
- static_cast<proto2::RepeatedField<Cord>*>(frame->userdata());
return r->Add();
}
@@ -367,46 +345,39 @@ class P2R_Handlers {
const proto2::Message* prototype_;
};
- static void SetStartSubMessageHandler(
- const proto2::FieldDescriptor* proto2_f, const proto2::Message& m,
- const _pi::Proto2Reflection* r, upb::Handlers::StartFieldHandler* handler,
- const upb::FieldDef* f, upb::Handlers* h) {
- h->SetStartSubMessageHandler(f, handler,
- new SubMessageHandlerData(m, proto2_f, r),
- &upb::DeletePointer<SubMessageHandlerData>);
- }
-
static void SetRequiredMessageHandlers(
const proto2::FieldDescriptor* proto2_f, const proto2::Message& m,
const _pi::Proto2Reflection* r, const upb::FieldDef* f,
upb::Handlers* h) {
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage,
+ new SubMessageHandlerData(m, proto2_f, r)));
} else {
- h->SetStartSubMessageHandler(f, &StartRequiredSubMessage,
- new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset>);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartRequiredSubMessage, new FieldOffset(proto2_f, r)));
}
}
- static void* StartRequiredSubMessage(const upb::SinkFrame* frame) {
- const FieldOffset* offset =
- static_cast<FieldOffset*>(frame->handler_data());
- void* m = frame->userdata();
+ static proto2::Message* StartRequiredSubMessage(proto2::Message* m,
+ const FieldOffset* offset) {
offset->SetHasbit(m);
- return offset->GetFieldPointer<void>(m);
+ return offset->GetFieldPointer<proto2::Message>(m);
}
static void SetMessageHandlers(const proto2::FieldDescriptor* proto2_f,
const proto2::Message& m,
const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
+ scoped_ptr<SubMessageHandlerData> data(
+ new SubMessageHandlerData(m, proto2_f, r));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage, data.release()));
} else {
- SetStartSubMessageHandler(proto2_f, m, r, &StartSubMessage, f, h);
+ h->SetStartSubMessageHandler(f, UpbBind(StartSubMessage, data.release()));
}
}
@@ -414,28 +385,26 @@ class P2R_Handlers {
const proto2::Message& m,
const _pi::Proto2Reflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
+ scoped_ptr<SubMessageHandlerData> data(
+ new SubMessageHandlerData(m, proto2_f, r));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- SetStartSubMessageHandler(proto2_f, m, r, &StartRepeatedSubMessage, f, h);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage, data.release()));
} else {
- SetStartSubMessageHandler(proto2_f, m, r, &StartWeakSubMessage, f, h);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartWeakSubMessage, data.release()));
}
}
- static void* StartSubMessage(const upb::SinkFrame* frame) {
- void* m = frame->userdata();
- const SubMessageHandlerData* info =
- static_cast<const SubMessageHandlerData*>(frame->handler_data());
+ static void* StartSubMessage(void *m, const SubMessageHandlerData* info) {
info->SetHasbit(m);
proto2::Message** subm = info->GetFieldPointer<proto2::Message*>(m);
if (*subm == info->prototype()) *subm = (*subm)->New();
return *subm;
}
- static void* StartWeakSubMessage(const upb::SinkFrame* frame) {
- void* m = frame->userdata();
- const SubMessageHandlerData* info =
- static_cast<const SubMessageHandlerData*>(frame->handler_data());
+ static void* StartWeakSubMessage(void* m, const SubMessageHandlerData* info) {
info->SetHasbit(m);
proto2::Message** subm = info->GetFieldPointer<proto2::Message*>(m);
if (*subm == NULL) {
@@ -446,7 +415,7 @@ class P2R_Handlers {
class RepeatedMessageTypeHandler {
public:
- typedef void Type;
+ typedef proto2::Message Type;
// AddAllocated() calls this, but only if other objects are sitting
// around waiting for reuse, which we will not do.
static void Delete(Type* t) {
@@ -457,12 +426,10 @@ class P2R_Handlers {
// Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
// its base class RepeatedPtrFieldBase*.
- static void* StartRepeatedSubMessage(const upb::SinkFrame* frame) {
- const SubMessageHandlerData* info =
- static_cast<const SubMessageHandlerData*>(frame->handler_data());
- proto2::internal::RepeatedPtrFieldBase* r =
- static_cast<proto2::internal::RepeatedPtrFieldBase*>(frame->userdata());
- void* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
+ static proto2::Message* StartRepeatedSubMessage(
+ proto2::internal::RepeatedPtrFieldBase* r,
+ const SubMessageHandlerData* info) {
+ proto2::Message* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
if (!submsg) {
submsg = info->prototype()->New();
r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
diff --git a/upb/google/proto2.cc b/upb/google/proto2.cc
index 8f9bcd8..e878a65 100644
--- a/upb/google/proto2.cc
+++ b/upb/google/proto2.cc
@@ -18,6 +18,7 @@
#include "upb/def.h"
#include "upb/google/proto1.h"
#include "upb/handlers.h"
+#include "upb/shim/shim.h"
#include "upb/sink.h"
namespace upb {
@@ -65,6 +66,7 @@ using goog::int32;
using goog::int64;
using goog::uint32;
using goog::uint64;
+using goog::scoped_ptr;
#endif // ifdef UPB_GOOGLE3
@@ -260,7 +262,7 @@ case goog::FieldDescriptor::cpptype: \
int number() const { return number_; }
goog::internal::FieldType type() const { return type_; }
- goog::internal::ExtensionSet* GetExtensionSet(goog::Message* m) const {
+ goog::internal::ExtensionSet* GetExtensionSet(goog::MessageLite* m) const {
return GetPointer<goog::internal::ExtensionSet>(m, offset_);
}
@@ -277,14 +279,13 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(f->IsSequence());
- h->SetStartSequenceHandler(f, &PushOffset, new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset>);
+ h->SetStartSequenceHandler(
+ f, UpbBind(PushOffset, new FieldOffset(proto2_f, r)));
}
- static void* PushOffset(const upb::SinkFrame* frame) {
- const FieldOffset* offset =
- static_cast<FieldOffset*>(frame->handler_data());
- return offset->GetFieldPointer<void>(frame->userdata());
+ // TODO(haberman): make more type-safe?
+ static void* PushOffset(void* message, const FieldOffset* offset) {
+ return offset->GetFieldPointer<void>(message);
}
// Primitive Value (numeric, bool) ///////////////////////////////////////////
@@ -294,37 +295,33 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
if (proto2_f->is_extension()) {
- ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r);
- upb::Handlers::Free* free = &upb::DeletePointer<ExtensionFieldData>;
+ scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
if (f->IsSequence()) {
- h->SetValueHandler<T>(f, &AppendPrimitiveExtension<T>, data, free);
+ h->SetValueHandler<T>(
+ f, UpbBindT(AppendPrimitiveExtension<T>, data.release()));
} else {
- h->SetValueHandler<T>(f, &SetPrimitiveExtension<T>, data, free);
+ h->SetValueHandler<T>(
+ f, UpbBindT(SetPrimitiveExtension<T>, data.release()));
}
} else {
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetValueHandler<T>(f, &AppendPrimitive<T>, NULL, NULL);
+ h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>));
} else {
- upb::SetStoreValueHandler<T>(f, GetOffset(proto2_f, r),
- GetHasbit(proto2_f, r), h);
+ upb::Shim::Set(h, f, GetOffset(proto2_f, r), GetHasbit(proto2_f, r));
}
}
}
template <typename T>
- static bool AppendPrimitive(const upb::SinkFrame* frame, T val) {
- goog::RepeatedField<T>* r =
- static_cast<goog::RepeatedField<T>*>(frame->userdata());
+ static bool AppendPrimitive(goog::RepeatedField<T>* r, T val) {
r->Add(val);
return true;
}
template <typename T>
- static bool AppendPrimitiveExtension(const upb::SinkFrame* frame, T val) {
- goog::Message* m = frame->GetUserdata<goog::Message>();
- ExtensionFieldData* data =
- static_cast<ExtensionFieldData*>(frame->handler_data());
+ static bool AppendPrimitiveExtension(goog::Message* m,
+ const ExtensionFieldData* data, T val) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
// TODO(haberman): give an accurate value for "packed"
goog::internal::RepeatedPrimitiveTypeTraits<T>::Add(
@@ -333,10 +330,8 @@ case goog::FieldDescriptor::cpptype: \
}
template <typename T>
- static bool SetPrimitiveExtension(const upb::SinkFrame* frame, T val) {
- goog::Message* m = frame->GetUserdata<goog::Message>();
- ExtensionFieldData* data =
- static_cast<ExtensionFieldData*>(frame->handler_data());
+ static bool SetPrimitiveExtension(goog::Message* m,
+ const ExtensionFieldData* data, T val) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
goog::internal::PrimitiveTypeTraits<T>::Set(data->number(), data->type(),
val, set);
@@ -376,20 +371,16 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(!proto2_f->is_extension());
- EnumHandlerData* data = new EnumHandlerData(proto2_f, r, f);
+ scoped_ptr<EnumHandlerData> data(new EnumHandlerData(proto2_f, r, f));
if (f->IsSequence()) {
- h->SetInt32Handler(f, &AppendEnum, data,
- &upb::DeletePointer<EnumHandlerData>);
+ h->SetInt32Handler(f, UpbBind(AppendEnum, data.release()));
} else {
- h->SetInt32Handler(f, &SetEnum, data,
- &upb::DeletePointer<EnumHandlerData>);
+ h->SetInt32Handler(f, UpbBind(SetEnum, data.release()));
}
}
- static bool SetEnum(const upb::SinkFrame* frame, int32_t val) {
- goog::Message* m = static_cast<goog::Message*>(frame->userdata());
- const EnumHandlerData* data =
- static_cast<const EnumHandlerData*>(frame->handler_data());
+ static bool SetEnum(goog::Message* m, const EnumHandlerData* data,
+ int32_t val) {
if (data->IsValidValue(val)) {
int32_t* message_val = data->GetFieldPointer<int32_t>(m);
*message_val = val;
@@ -400,13 +391,11 @@ case goog::FieldDescriptor::cpptype: \
return true;
}
- static bool AppendEnum(const upb::SinkFrame* frame, int32_t val) {
+ static bool AppendEnum(goog::Message* m, const EnumHandlerData* data,
+ int32_t val) {
// Closure is the enclosing message. We can't use the RepeatedField<> as
// the closure because we need to go back to the message for unrecognized
// enum values, which go into the unknown field set.
- goog::Message* m = static_cast<goog::Message*>(frame->userdata());
- const EnumHandlerData* data =
- static_cast<const EnumHandlerData*>(frame->handler_data());
if (data->IsValidValue(val)) {
goog::RepeatedField<int32_t>* r =
data->GetFieldPointer<goog::RepeatedField<int32_t> >(m);
@@ -424,29 +413,23 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(proto2_f->is_extension());
- ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r);
+ scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
if (f->IsSequence()) {
- h->SetInt32Handler(f, &AppendEnumExtension, data,
- upb::DeletePointer<ExtensionFieldData>);
+ h->SetInt32Handler(f, UpbBind(AppendEnumExtension, data.release()));
} else {
- h->SetInt32Handler(f, &SetEnumExtension, data,
- upb::DeletePointer<ExtensionFieldData>);
+ h->SetInt32Handler(f, UpbBind(SetEnumExtension, data.release()));
}
}
- static bool SetEnumExtension(const upb::SinkFrame* frame, int32_t val) {
- goog::Message* m = frame->GetUserdata<goog::Message>();
- const ExtensionFieldData* data =
- static_cast<const ExtensionFieldData*>(frame->handler_data());
+ static bool SetEnumExtension(goog::Message* m, const ExtensionFieldData* data,
+ int32_t val) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
set->SetEnum(data->number(), data->type(), val, NULL);
return true;
}
- static bool AppendEnumExtension(const upb::SinkFrame* frame, int32_t val) {
- goog::Message* m = frame->GetUserdata<goog::Message>();
- const ExtensionFieldData* data =
- static_cast<const ExtensionFieldData*>(frame->handler_data());
+ static bool AppendEnumExtension(goog::Message* m,
+ const ExtensionFieldData* data, int32_t val) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
// TODO(haberman): give an accurate value for "packed"
set->AddEnum(data->number(), data->type(), true, val, NULL);
@@ -480,24 +463,21 @@ case goog::FieldDescriptor::cpptype: \
const upb::FieldDef* f,
upb::Handlers* h) {
assert(!proto2_f->is_extension());
- h->SetStringHandler(f, &OnStringBuf<T>, NULL, NULL);
+ h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, &StartRepeatedString<T>, NULL, NULL);
+ h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>));
} else {
- StringHandlerData<T>* data = new StringHandlerData<T>(proto2_f, r);
- h->SetStartStringHandler(f, &StartString<T>, data,
- &upb::DeletePointer<StringHandlerData<T> >);
+ h->SetStartStringHandler(
+ f, UpbBindT(StartString<T>, new StringHandlerData<T>(proto2_f, r)));
}
}
// This needs to be templated because google3 string is not std::string.
template <typename T>
- static void* StartString(const upb::SinkFrame* frame, size_t size_hint) {
+ static T* StartString(goog::Message* m, const StringHandlerData<T>* data,
+ size_t size_hint) {
UPB_UNUSED(size_hint);
- goog::Message* m = static_cast<goog::Message*>(frame->userdata());
- const StringHandlerData<T>* data =
- static_cast<const StringHandlerData<T>*>(frame->handler_data());
T** str = data->GetStringPointer(m);
data->SetHasbit(m);
// If it points to the default instance, we must create a new instance.
@@ -508,19 +488,15 @@ case goog::FieldDescriptor::cpptype: \
}
template <typename T>
- static size_t OnStringBuf(const upb::SinkFrame* frame,
- const char* buf, size_t n) {
- T* str = static_cast<T*>(frame->userdata());
+ static size_t OnStringBuf(T* str, const char* buf, size_t n) {
str->append(buf, n);
return n;
}
template <typename T>
- static void* StartRepeatedString(const upb::SinkFrame* frame,
+ static T* StartRepeatedString(goog::RepeatedPtrField<T>* r,
size_t size_hint) {
UPB_UNUSED(size_hint);
- goog::RepeatedPtrField<T>* r =
- static_cast<goog::RepeatedPtrField<T>*>(frame->userdata());
T* str = r->Add();
str->clear();
// reserve() here appears to hurt performance rather than help.
@@ -535,35 +511,32 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(proto2_f->is_extension());
- h->SetStringHandler(f, &OnStringBuf<T>, NULL, NULL);
- ExtensionFieldData* data = new ExtensionFieldData(proto2_f, r);
+ h->SetStringHandler(f, UpbMakeHandlerT(OnStringBuf<T>));
+ scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
if (f->IsSequence()) {
- h->SetStartStringHandler(f, &StartRepeatedStringExtension, data,
- upb::DeletePointer<ExtensionFieldData>);
+ h->SetStartStringHandler(
+ f, UpbBindT(StartRepeatedStringExtension<T>, data.release()));
} else {
- h->SetStartStringHandler(f, &StartStringExtension, data,
- upb::DeletePointer<ExtensionFieldData>);
+ h->SetStartStringHandler(
+ f, UpbBindT(StartStringExtension<T>, data.release()));
}
}
- // google3 string is not std::string, but we avoid needing to template
- // because we do not actually have to declare the string type.
- static void* StartStringExtension(const upb::SinkFrame* frame,
- size_t size_hint) {
+ // Templated because google3 is not std::string.
+ template <class T>
+ static T* StartStringExtension(goog::Message* m,
+ const ExtensionFieldData* data,
+ size_t size_hint) {
UPB_UNUSED(size_hint);
- goog::Message* m = frame->GetUserdata<goog::Message>();
- const ExtensionFieldData* data =
- static_cast<const ExtensionFieldData*>(frame->handler_data());
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
return set->MutableString(data->number(), data->type(), NULL);
}
- static void* StartRepeatedStringExtension(const upb::SinkFrame* frame,
- size_t size_hint) {
+ template <class T>
+ static T* StartRepeatedStringExtension(goog::Message* m,
+ const ExtensionFieldData* data,
+ size_t size_hint) {
UPB_UNUSED(size_hint);
- goog::Message* m = frame->GetUserdata<goog::Message>();
- const ExtensionFieldData* data =
- static_cast<const ExtensionFieldData*>(frame->handler_data());
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
return set->AddString(data->number(), data->type(), NULL);
}
@@ -588,24 +561,21 @@ case goog::FieldDescriptor::cpptype: \
const goog::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f);
- SubMessageHandlerData* data =
- new SubMessageHandlerData(proto2_f, r, field_prototype);
- upb::Handlers::Free* free = &upb::DeletePointer<SubMessageHandlerData>;
+ scoped_ptr<SubMessageHandlerData> data(
+ new SubMessageHandlerData(proto2_f, r, field_prototype));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartSubMessageHandler(f, &StartRepeatedSubMessage, data, free);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessage, data.release()));
} else {
- h->SetStartSubMessageHandler(f, &StartSubMessage, data, free);
+ h->SetStartSubMessageHandler(f, UpbBind(StartSubMessage, data.release()));
}
}
- static void* StartSubMessage(const upb::SinkFrame* frame) {
- void* m = frame->userdata();
- const SubMessageHandlerData* data =
- static_cast<const SubMessageHandlerData*>(frame->handler_data());
+ static goog::Message* StartSubMessage(goog::Message* m,
+ const SubMessageHandlerData* data) {
data->SetHasbit(m);
- goog::Message** subm =
- data->GetFieldPointer<goog::Message*>(frame->userdata());
+ goog::Message** subm = data->GetFieldPointer<goog::Message*>(m);
if (*subm == NULL || *subm == data->prototype()) {
*subm = data->prototype()->New();
}
@@ -614,7 +584,7 @@ case goog::FieldDescriptor::cpptype: \
class RepeatedMessageTypeHandler {
public:
- typedef void Type;
+ typedef goog::Message Type;
// AddAllocated() calls this, but only if other objects are sitting
// around waiting for reuse, which we will not do.
static void Delete(Type* t) {
@@ -625,12 +595,10 @@ case goog::FieldDescriptor::cpptype: \
// Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
// its base class RepeatedPtrFieldBase*.
- static void* StartRepeatedSubMessage(const upb::SinkFrame* frame) {
- const SubMessageHandlerData* data =
- static_cast<const SubMessageHandlerData*>(frame->handler_data());
- goog::internal::RepeatedPtrFieldBase* r =
- static_cast<goog::internal::RepeatedPtrFieldBase*>(frame->userdata());
- void* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
+ static goog::Message* StartRepeatedSubMessage(
+ goog::internal::RepeatedPtrFieldBase* r,
+ const SubMessageHandlerData* data) {
+ goog::Message* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
if (!submsg) {
submsg = data->prototype()->New();
r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
@@ -663,32 +631,26 @@ case goog::FieldDescriptor::cpptype: \
const upb::FieldDef* f,
upb::Handlers* h) {
const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f);
- SubMessageExtensionHandlerData* data =
- new SubMessageExtensionHandlerData(proto2_f, r, field_prototype);
- upb::Handlers::Free* free = &upb::DeletePointer<SubMessageHandlerData>;
+ scoped_ptr<SubMessageExtensionHandlerData> data(
+ new SubMessageExtensionHandlerData(proto2_f, r, field_prototype));
if (f->IsSequence()) {
- h->SetStartSubMessageHandler(f, &StartRepeatedSubMessageExtension, data,
- free);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartRepeatedSubMessageExtension, data.release()));
} else {
- h->SetStartSubMessageHandler(f, &StartSubMessageExtension, data, free);
+ h->SetStartSubMessageHandler(
+ f, UpbBind(StartSubMessageExtension, data.release()));
}
}
- static void* StartRepeatedSubMessageExtension(const upb::SinkFrame* frame) {
- goog::Message* m = frame->GetUserdata<goog::Message>();
- const SubMessageExtensionHandlerData* data =
- static_cast<const SubMessageExtensionHandlerData*>(
- frame->handler_data());
+ static goog::MessageLite* StartRepeatedSubMessageExtension(
+ goog::MessageLite* m, const SubMessageExtensionHandlerData* data) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
return set->AddMessage(data->number(), data->type(), *data->prototype(),
NULL);
}
- static void* StartSubMessageExtension(const upb::SinkFrame* frame) {
- goog::Message* m = frame->GetUserdata<goog::Message>();
- const SubMessageExtensionHandlerData* data =
- static_cast<const SubMessageExtensionHandlerData*>(
- frame->handler_data());
+ static goog::MessageLite* StartSubMessageExtension(
+ goog::MessageLite* m, const SubMessageExtensionHandlerData* data) {
goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
return set->MutableMessage(data->number(), data->type(), *data->prototype(),
NULL);
@@ -708,39 +670,33 @@ case goog::FieldDescriptor::cpptype: \
const proto2::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(!proto2_f->is_extension());
- h->SetStringHandler(f, &OnCordBuf, NULL, NULL);
+ h->SetStringHandler(f, UpbMakeHandler(&OnCordBuf));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, &StartRepeatedCord, NULL, NULL);
+ h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord));
} else {
- h->SetStartStringHandler(f, &StartCord, new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset*>);
+ h->SetStartStringHandler(
+ f, UpbBind(StartCord, new FieldOffset(proto2_f, r)));
}
}
- static void* StartCord(const upb::SinkFrame* frame, size_t size_hint) {
+ static Cord* StartCord(goog::Message* m, const FieldOffset* offset,
+ size_t size_hint) {
UPB_UNUSED(size_hint);
- void* m = frame->userdata();
- const FieldOffset* offset =
- static_cast<const FieldOffset*>(frame->handler_data());
offset->SetHasbit(m);
Cord* field = offset->GetFieldPointer<Cord>(m);
field->Clear();
return field;
}
- static size_t OnCordBuf(const upb::SinkFrame* frame,
- const char* buf, size_t n) {
- Cord* c = static_cast<Cord*>(frame->userdata());
+ static size_t OnCordBuf(Cord* c, const char* buf, size_t n) {
c->Append(StringPiece(buf, n));
return n;
}
- static void* StartRepeatedCord(const upb::SinkFrame* frame,
+ static Cord* StartRepeatedCord(proto2::RepeatedField<Cord>* r,
size_t size_hint) {
UPB_UNUSED(size_hint);
- proto2::RepeatedField<Cord>* r =
- static_cast<proto2::RepeatedField<Cord>*>(frame->userdata());
return r->Add();
}
@@ -751,24 +707,21 @@ case goog::FieldDescriptor::cpptype: \
const proto2::internal::GeneratedMessageReflection* r,
const upb::FieldDef* f, upb::Handlers* h) {
assert(!proto2_f->is_extension());
- h->SetStringHandler(f, &OnStringPieceBuf, NULL, NULL);
+ h->SetStringHandler(f, UpbMakeHandler(OnStringPieceBuf));
if (f->IsSequence()) {
SetStartSequenceHandler(proto2_f, r, f, h);
- h->SetStartStringHandler(f, &StartRepeatedStringPiece, NULL, NULL);
+ h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedStringPiece));
} else {
- h->SetStartStringHandler(f, &StartStringPiece,
- new FieldOffset(proto2_f, r),
- &upb::DeletePointer<FieldOffset*>);
+ h->SetStartStringHandler(
+ f, UpbBind(StartStringPiece, new FieldOffset(proto2_f, r)));
}
}
- static size_t OnStringPieceBuf(const upb::SinkFrame* frame,
+ static size_t OnStringPieceBuf(proto2::internal::StringPieceField* field,
const char* buf, size_t len) {
// TODO(haberman): alias if possible and enabled on the input stream.
// TODO(haberman): add a method to StringPieceField that lets us avoid
// this copy/malloc/free.
- proto2::internal::StringPieceField* field =
- static_cast<proto2::internal::StringPieceField*>(frame->userdata());
size_t new_len = field->size() + len;
char* data = new char[new_len];
memcpy(data, field->data(), field->size());
@@ -778,12 +731,9 @@ case goog::FieldDescriptor::cpptype: \
return len;
}
- static void* StartStringPiece(const upb::SinkFrame* frame,
- size_t size_hint) {
+ static proto2::internal::StringPieceField* StartStringPiece(
+ goog::Message* m, const FieldOffset* offset, size_t size_hint) {
UPB_UNUSED(size_hint);
- void* m = frame->userdata();
- const FieldOffset* offset =
- static_cast<const FieldOffset*>(frame->handler_data());
offset->SetHasbit(m);
proto2::internal::StringPieceField* field =
offset->GetFieldPointer<proto2::internal::StringPieceField>(m);
@@ -791,13 +741,10 @@ case goog::FieldDescriptor::cpptype: \
return field;
}
- static void* StartRepeatedStringPiece(const upb::SinkFrame* frame,
- size_t size_hint) {
+ static proto2::internal::StringPieceField* StartRepeatedStringPiece(
+ proto2::RepeatedPtrField<proto2::internal::StringPieceField>* r,
+ size_t size_hint) {
UPB_UNUSED(size_hint);
- typedef proto2::RepeatedPtrField<
- proto2::internal::StringPieceField> RepeatedStringPiece;
- RepeatedStringPiece* r =
- static_cast<RepeatedStringPiece*>(frame->userdata());
proto2::internal::StringPieceField* field = r->Add();
field->Clear();
return field;
diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h
new file mode 100644
index 0000000..4a2800c
--- /dev/null
+++ b/upb/handlers-inl.h
@@ -0,0 +1,470 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * Inline definitions for handlers.h, which are particularly long and a bit
+ * tricky.
+ */
+
+#ifndef UPB_HANDLERS_INL_H_
+#define UPB_HANDLERS_INL_H_
+
+#ifdef __cplusplus
+
+namespace upb {
+
+// Deleter: class for constructing a function that deletes a pointer type.
+template <class T> struct Deleter {
+ static void Delete(void* p) { delete static_cast<T*>(p); }
+};
+
+template <class T> Deleter<T> MatchDeleter(T* data) {
+ UPB_UNUSED(data);
+ return Deleter<T>();
+}
+
+// Template magic for creating type-safe wrappers around the user's actual
+// function. These convert between the void*'s of the C API and the C++
+// user's types. These also handle conversion between multiple types with
+// the same witdh; ie "long long" and "long" are both 64 bits on LP64.
+
+// ValueHandler
+template <class C, class T1, class T2 = typename CanonicalType<T1>::Type>
+struct ValueHandlerWrapper2 {
+ template <bool F(C *, T1)>
+ inline static bool Wrapper(void *closure, const void *hd, T2 val) {
+ UPB_UNUSED(hd);
+ return F(static_cast<C *>(closure), val);
+ }
+};
+
+template <class C, class D, class T1,
+ class T2 = typename CanonicalType<T1>::Type>
+struct ValueHandlerWrapper3 {
+ template <bool F(C *, const D *, T1)>
+ inline static bool Wrapper(void *closure, const void *hd, T2 val) {
+ return F(static_cast<C *>(closure), static_cast<const D *>(hd), val);
+ }
+};
+
+template <class C, class T>
+inline ValueHandlerWrapper2<C, T> MatchWrapper(bool (*f)(C *, T)) {
+ UPB_UNUSED(f);
+ return ValueHandlerWrapper2<C, T>();
+}
+
+template <class C, class D, class T>
+inline ValueHandlerWrapper3<C, D, T> MatchWrapper(bool (*f)(C *, const D *,
+ T)) {
+ UPB_UNUSED(f);
+ return ValueHandlerWrapper3<C, D, T>();
+}
+
+template <class T>
+inline typename ValueHandler<T>::H MakeHandler(bool (*wrapper)(void *,
+ const void *,
+ T)) {
+ return ValueHandler<T>::H::Make(wrapper, NULL, NULL);
+}
+
+template <class C, class D, class T1, class T2>
+inline typename ValueHandler<T1>::H BindHandler(
+ bool (*wrapper)(void *, const void *, T1), bool (*h)(C *, const D *, T2),
+ D *data) {
+ UPB_UNUSED(h); // Only for making sure function matches "D".
+ return ValueHandler<T1>::H::Make(wrapper, data, MatchDeleter(data).Delete);
+}
+
+// StartFieldHandler
+template <class R, class C> struct StartFieldHandlerWrapper2 {
+ template <R *F(C *)> static void *Wrapper(void *closure, const void *hd) {
+ UPB_UNUSED(hd);
+ return F(static_cast<C *>(closure));
+ }
+};
+
+template <class R, class C, class D> struct StartFieldHandlerWrapper3 {
+ template <R *F(C *, const D *)>
+ inline static void *Wrapper(void *closure, const void *hd) {
+ return F(static_cast<C *>(closure), static_cast<const D *>(hd));
+ }
+};
+
+template <class R, class C>
+inline StartFieldHandlerWrapper2<R, C> MatchWrapper(R *(*f)(C *)) {
+ UPB_UNUSED(f);
+ return StartFieldHandlerWrapper2<R, C>();
+}
+
+template <class R, class C, class D>
+inline StartFieldHandlerWrapper3<R, C, D> MatchWrapper(R *(*f)(C *,
+ const D *)) {
+ UPB_UNUSED(f);
+ return StartFieldHandlerWrapper3<R, C, D>();
+}
+
+inline StartFieldHandler MakeHandler(void *(*wrapper)(void *, const void *)) {
+ return StartFieldHandler::Make(wrapper, NULL, NULL);
+}
+
+template <class R, class C, class D>
+inline StartFieldHandler BindHandler(void *(*wrapper)(void *, const void *),
+ R *(*h)(C *, const D *), D *data) {
+ UPB_UNUSED(h); // Only for making sure function matches "D".
+ return StartFieldHandler::Make(wrapper, data, MatchDeleter(data).Delete);
+}
+
+// EndFieldHandler
+template <class C> struct EndFieldHandlerWrapper2 {
+ template <bool F(C *)>
+ inline static bool Wrapper(void *closure, const void *hd) {
+ UPB_UNUSED(hd);
+ return F(static_cast<C *>(closure));
+ }
+};
+
+template <class C, class D> struct EndFieldHandlerWrapper3 {
+ template <bool F(C *, const D *)>
+ inline static bool Wrapper(void *closure, const void *hd) {
+ return F(static_cast<C *>(closure), static_cast<const D *>(hd));
+ }
+};
+
+template <class C>
+inline EndFieldHandlerWrapper2<C> MatchWrapper(bool (*f)(C *)) {
+ UPB_UNUSED(f);
+ return EndFieldHandlerWrapper2<C>();
+}
+
+template <class C, class D>
+inline EndFieldHandlerWrapper3<C, D> MatchWrapper(bool (*f)(C *, const D *)) {
+ UPB_UNUSED(f);
+ return EndFieldHandlerWrapper3<C, D>();
+}
+
+inline EndFieldHandler MakeHandler(bool (*wrapper)(void *, const void *)) {
+ return EndFieldHandler::Make(wrapper, NULL, NULL);
+}
+
+template <class C, class D>
+inline EndFieldHandler BindHandler(bool (*wrapper)(void *, const void *),
+ bool (*h)(C *, const D *), D *data) {
+ UPB_UNUSED(h); // Only for making sure function matches "D".
+ return EndFieldHandler::Make(wrapper, data, MatchDeleter(data).Delete);
+}
+
+// StartStringHandler
+template <class R, class C> struct StartStringHandlerWrapper2 {
+ template <R *F(C *, size_t)>
+ inline static void *Wrapper(void *closure, const void *hd, size_t hint) {
+ UPB_UNUSED(hd);
+ return F(static_cast<C *>(closure), hint);
+ }
+};
+
+template <class R, class C, class D> struct StartStringHandlerWrapper3 {
+ template <R *F(C *, const D *, size_t)>
+ inline static void *Wrapper(void *closure, const void *hd, size_t hint) {
+ return F(static_cast<C *>(closure), static_cast<const D *>(hd), hint);
+ }
+};
+
+template <class R, class C>
+inline StartStringHandlerWrapper2<R, C> MatchWrapper(R *(*f)(C *, size_t)) {
+ UPB_UNUSED(f);
+ return StartStringHandlerWrapper2<R, C>();
+}
+
+template <class R, class C, class D>
+inline StartStringHandlerWrapper3<R, C, D> MatchWrapper(R *(*f)(C *, const D *,
+ size_t)) {
+ UPB_UNUSED(f);
+ return StartStringHandlerWrapper3<R, C, D>();
+}
+
+inline StartStringHandler MakeHandler(void *(*wrapper)(void *, const void *,
+ size_t)) {
+ return StartStringHandler::Make(wrapper, NULL, NULL);
+}
+
+template <class R, class C, class D>
+inline StartStringHandler BindHandler(void *(*wrapper)(void *, const void *,
+ size_t),
+ R *(*h)(C *, const D *, size_t),
+ D *data) {
+ UPB_UNUSED(h); // Only for making sure function matches "D".
+ return StartStringHandler::Make(wrapper, data, MatchDeleter(data).Delete);
+}
+
+// StringHandler
+template <class C> struct StringHandlerWrapper2 {
+ template <size_t F(C *, const char *buf, size_t len)>
+ inline static size_t Wrapper(void *closure, const void *hd, const char *buf,
+ size_t len) {
+ UPB_UNUSED(hd);
+ return F(static_cast<C *>(closure), buf, len);
+ }
+};
+
+template <class C, class D> struct StringHandlerWrapper3 {
+ template <size_t F(C *, const D *, const char *buf, size_t len)>
+ inline static size_t Wrapper(void *closure, const void *hd, const char *buf,
+ size_t len) {
+ return F(static_cast<C *>(closure), static_cast<const D *>(hd), buf, len);
+ }
+};
+
+template <class C>
+inline StringHandlerWrapper2<C> MatchWrapper(size_t (*f)(C *, const char *,
+ size_t)) {
+ UPB_UNUSED(f);
+ return StringHandlerWrapper2<C>();
+}
+
+template <class C, class D>
+inline StringHandlerWrapper3<C, D> MatchWrapper(size_t (*f)(C *, const D *,
+ const char *,
+ size_t)) {
+ UPB_UNUSED(f);
+ return StringHandlerWrapper3<C, D>();
+}
+
+inline StringHandler MakeHandler(size_t (*wrapper)(void *, const void *,
+ const char *, size_t)) {
+ return StringHandler::Make(wrapper, NULL, NULL);
+}
+
+template <class C, class D>
+inline StringHandler BindHandler(
+ size_t (*wrapper)(void *, const void *, const char *, size_t),
+ size_t (*h)(C *, const D *, const char *, size_t), D *data) {
+ UPB_UNUSED(h); // Only for making sure function matches "D".
+ return StringHandler::Make(wrapper, data, MatchDeleter(data).Delete);
+}
+
+// utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
+// variant C type.
+#define TYPE_METHODS(utype, ltype, ctype, vtype) \
+ template <> struct CanonicalType<vtype> { \
+ typedef ctype Type; \
+ }; \
+ template <> \
+ inline bool Handlers::SetValueHandler<vtype>( \
+ const FieldDef *f, \
+ const typename ValueHandler<typename CanonicalType<vtype>::Type>::H & \
+ handler) { \
+ handler.registered_ = true; \
+ return upb_handlers_set##ltype(this, f, handler.handler_, handler.data_, \
+ handler.cleanup_); \
+ } \
+ template <> \
+ inline bool Handlers::SetValueHandler<vtype>( \
+ const char *f, const typename ValueHandler< \
+ typename CanonicalType<vtype>::Type>::H &handler) { \
+ handler.registered_ = true; \
+ return upb_handlers_set##ltype##_n(this, f, handler.handler_, \
+ handler.data_, handler.cleanup_); \
+ }
+
+TYPE_METHODS(Double, double, double, double);
+TYPE_METHODS(Float, float, float, float);
+TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64_t);
+TYPE_METHODS(UInt32, uint32, uint32_t, upb_uint32_t);
+TYPE_METHODS(Int64, int64, int64_t, upb_int64_t);
+TYPE_METHODS(Int32, int32, int32_t, upb_int32_t);
+TYPE_METHODS(Bool, bool, bool, bool);
+
+#ifdef UPB_TWO_32BIT_TYPES
+TYPE_METHODS(Int32, int32, int32_t, upb_int32alt_t);
+TYPE_METHODS(Uint32, uint32, uint32_t, upb_uint32alt_t);
+#endif
+
+#ifdef UPB_TWO_64BIT_TYPES
+TYPE_METHODS(Int64, int64, int64_t, upb_int64alt_t);
+TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64alt_t);
+#endif
+#undef TYPE_METHODS
+
+// Type methods that are only one-per-canonical-type and not one-per-cvariant.
+
+#define TYPE_METHODS(utype, ctype) \
+ inline bool Handlers::Set##utype##Handler(const FieldDef *f, \
+ const utype##Handler &h) { \
+ return SetValueHandler<ctype>(f, h); \
+ } \
+ inline bool Handlers::Set##utype##Handler(const char *f, \
+ const utype##Handler &h) { \
+ return SetValueHandler<ctype>(f, h); \
+ }
+
+TYPE_METHODS(Double, double);
+TYPE_METHODS(Float, float);
+TYPE_METHODS(UInt64, uint64_t);
+TYPE_METHODS(UInt32, uint32_t);
+TYPE_METHODS(Int64, int64_t);
+TYPE_METHODS(Int32, int32_t);
+TYPE_METHODS(Bool, bool);
+#undef TYPE_METHODS
+
+template <class T1, bool F(T1*)> bool Wrapper1(void *p1) {
+ return F(static_cast<T1*>(p1));
+}
+template <class T1, bool F(T1 *, upb::Status *)>
+bool EndMessageWrapper(void *p1, upb::Status *s) {
+ return F(static_cast<T1 *>(p1), s);
+}
+inline Handlers *Handlers::New(const MessageDef *m, const FrameType *ft,
+ const void *owner) {
+ return upb_handlers_new(m, ft, owner);
+}
+inline const Handlers *Handlers::NewFrozen(const MessageDef *m,
+ const FrameType *ft,
+ const void *owner,
+ upb_handlers_callback *callback,
+ void *closure) {
+ return upb_handlers_newfrozen(m, ft, owner, callback, closure);
+}
+inline bool Handlers::IsFrozen() const { return upb_handlers_isfrozen(this); }
+inline void Handlers::Ref(const void *owner) const {
+ upb_handlers_ref(this, owner);
+}
+inline void Handlers::Unref(const void *owner) const {
+ upb_handlers_unref(this, owner);
+}
+inline void Handlers::DonateRef(const void *from, const void *to) const {
+ upb_handlers_donateref(this, from, to);
+}
+inline void Handlers::CheckRef(const void *owner) const {
+ upb_handlers_checkref(this, owner);
+}
+inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) {
+ return upb_handlers_freeze(handlers, n, s);
+}
+inline const FrameType *Handlers::frame_type() const {
+ return upb_handlers_frametype(this);
+}
+inline const MessageDef *Handlers::message_def() const {
+ return upb_handlers_msgdef(this);
+}
+template <class T, bool F(T *)> void Handlers::SetStartMessageHandler() {
+ upb_handlers_setstartmsg(this, &Wrapper1<T, F>);
+}
+template <class T, bool F(T *, upb::Status *)>
+void Handlers::SetEndMessageHandler() {
+ upb_handlers_setendmsg(this, &EndMessageWrapper<T, F>);
+}
+inline bool Handlers::SetStartStringHandler(const FieldDef *f,
+ const StartStringHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstartstr(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetEndStringHandler(const FieldDef *f,
+ const EndFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setendstr(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetStringHandler(const FieldDef *f,
+ const StringHandler& handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstring(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetStartSequenceHandler(
+ const FieldDef *f, const StartFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstartseq(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetStartSubMessageHandler(
+ const FieldDef *f, const StartFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstartsubmsg(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f,
+ const EndFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setendsubmsg(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetEndSequenceHandler(const FieldDef *f,
+ const EndFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setendseq(this, f, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) {
+ return upb_handlers_setsubhandlers(this, f, sub);
+}
+inline bool Handlers::SetStartStringHandler(const char *name,
+ const StartStringHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstartstr_n(this, name, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetEndStringHandler(const char *name,
+ const EndFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setendstr_n(this, name, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetStringHandler(const char *name,
+ const StringHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstring_n(this, name, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetStartSequenceHandler(
+ const char *name, const StartFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstartseq_n(this, name, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline bool Handlers::SetStartSubMessageHandler(
+ const char *name, const StartFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setstartsubmsg_n(this, name, handler.handler_,
+ handler.data_, handler.cleanup_);
+}
+inline bool Handlers::SetEndSubMessageHandler(const char *name,
+ const EndFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setendsubmsg_n(this, name, handler.handler_,
+ handler.data_, handler.cleanup_);
+}
+inline bool Handlers::SetEndSequenceHandler(const char *name,
+ const EndFieldHandler &handler) {
+ handler.registered_ = true;
+ return upb_handlers_setendseq_n(this, name, handler.handler_, handler.data_,
+ handler.cleanup_);
+}
+inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const {
+ return upb_handlers_getsubhandlers(this, f);
+}
+inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const {
+ return upb_handlers_getsubhandlers_sel(this, sel);
+}
+inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type,
+ Handlers::Selector *s) {
+ return upb_handlers_getselector(f, type, s);
+}
+inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) {
+ return upb_handlers_getendselector(start);
+}
+inline Handlers::GenericFunction *Handlers::GetHandler(
+ Handlers::Selector selector) {
+ return upb_handlers_gethandler(this, selector);
+}
+inline const void *Handlers::GetHandlerData(Handlers::Selector selector) {
+ return upb_handlers_gethandlerdata(this, selector);
+}
+
+} // namespace upb
+
+#endif // __cplusplus
+
+#endif // UPB_HANDLERS_INL_H_
diff --git a/upb/handlers.c b/upb/handlers.c
index b7458f2..6cbe6dc 100644
--- a/upb/handlers.c
+++ b/upb/handlers.c
@@ -3,6 +3,9 @@
*
* Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * TODO(haberman): it's unclear whether a lot of the consistency checks should
+ * assert() or return false.
*/
#include "upb/handlers.h"
@@ -16,106 +19,114 @@
// UPB_NO_CLOSURE.
char _upb_noclosure;
-static const upb_fieldhandler *getfh(
- const upb_handlers *h, upb_selector_t selector) {
- assert(selector < upb_handlers_msgdef(h)->selector_count);
- upb_fieldhandler* fhbase = (void*)&h->fh_base;
- return &fhbase[selector];
-}
+typedef struct {
+ void (*func)();
+ void *data;
+} tabent;
-static upb_fieldhandler *getfh_mutable(upb_handlers *h,
- upb_selector_t selector) {
- return (upb_fieldhandler*)getfh(h, selector);
+static void freehandlers(upb_refcounted *r) {
+ upb_handlers *h = (upb_handlers*)r;
+ upb_msgdef_unref(h->msg, h);
+ for (size_t i = 0; i < h->cleanup_len; i++) {
+ h->cleanup[i].cleanup(h->cleanup[i].ptr);
+ }
+ free(h->cleanup);
+ free(h);
}
-bool upb_handlers_isfrozen(const upb_handlers *h) {
- return upb_refcounted_isfrozen(upb_upcast(h));
+static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
+ void *closure) {
+ const upb_handlers *h = (const upb_handlers*)r;
+ upb_msg_iter i;
+ for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) {
+ upb_fielddef *f = upb_msg_iter_field(&i);
+ if (!upb_fielddef_issubmsg(f)) continue;
+ const upb_handlers *sub = upb_handlers_getsubhandlers(h, f);
+ if (sub) visit(r, upb_upcast(sub), closure);
+ }
}
-uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
- return upb_fielddef_isseq(f) ? 2 : 0;
-}
+static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
-uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
- uint32_t ret = 1;
- if (upb_fielddef_isstring(f)) ret += 2; // [STARTSTR]/STRING/ENDSTR
- if (upb_fielddef_isseq(f)) ret += 2; // STARTSEQ/ENDSEQ
- if (upb_fielddef_issubmsg(f)) ret += 1; // [STARTSUBMSG]/ENDSUBMSG
- return ret;
-}
+typedef struct {
+ upb_inttable tab; // maps upb_msgdef* -> upb_handlers*.
+ upb_handlers_callback *callback;
+ void *closure;
+} dfs_state;
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_INT32:
- case UPB_TYPE_ENUM:
- return UPB_HANDLER_INT32;
- case UPB_TYPE_INT64:
- return UPB_HANDLER_INT64;
- case UPB_TYPE_UINT32:
- return UPB_HANDLER_UINT32;
- case UPB_TYPE_UINT64:
- return UPB_HANDLER_UINT64;
- case UPB_TYPE_FLOAT:
- return UPB_HANDLER_FLOAT;
- case UPB_TYPE_DOUBLE:
- return UPB_HANDLER_DOUBLE;
- case UPB_TYPE_BOOL:
- return UPB_HANDLER_BOOL;
- default: assert(false); return -1; // Invalid input.
+static upb_handlers *newformsg(const upb_msgdef *m, const upb_frametype *ft,
+ const void *owner,
+ dfs_state *s) {
+ upb_handlers *h = upb_handlers_new(m, ft, owner);
+ if (!h) return NULL;
+ if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;
+
+ s->callback(s->closure, h);
+
+ // For each submessage field, get or create a handlers object and set it as
+ // the subhandlers.
+ upb_msg_iter i;
+ for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
+ upb_fielddef *f = upb_msg_iter_field(&i);
+ if (!upb_fielddef_issubmsg(f)) continue;
+
+ const upb_msgdef *subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
+ upb_value subm_ent;
+ if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
+ upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
+ } else {
+ upb_handlers *sub_mh = newformsg(subdef, ft, &sub_mh, s);
+ if (!sub_mh) goto oom;
+ upb_handlers_setsubhandlers(h, f, sub_mh);
+ upb_handlers_unref(sub_mh, &sub_mh);
+ }
}
+ return h;
+
+oom:
+ upb_handlers_unref(h, owner);
+ return NULL;
}
-bool upb_getselector(
- const upb_fielddef *f, upb_handlertype_t type, upb_selector_t *s) {
- // If the type checks in this function are a hot-spot, we can introduce a
- // separate function that calculates the selector assuming that the type
- // is correct (may even want to make it inline for the upb_sink fast-path.
- switch (type) {
- case UPB_HANDLER_INT32:
- case UPB_HANDLER_INT64:
- case UPB_HANDLER_UINT32:
- case UPB_HANDLER_UINT64:
- case UPB_HANDLER_FLOAT:
- case UPB_HANDLER_DOUBLE:
- case UPB_HANDLER_BOOL:
- if (!upb_fielddef_isprimitive(f) ||
- upb_handlers_getprimitivehandlertype(f) != type)
- return false;
- *s = f->selector_base;
- break;
- case UPB_HANDLER_STRING:
- if (!upb_fielddef_isstring(f)) return false;
- *s = f->selector_base;
- break;
- case UPB_HANDLER_STARTSTR:
- if (!upb_fielddef_isstring(f)) return false;
- *s = f->selector_base + 1;
- break;
- case UPB_HANDLER_ENDSTR:
- if (!upb_fielddef_isstring(f)) return false;
- *s = f->selector_base + 2;
- break;
- case UPB_HANDLER_STARTSEQ:
- if (!upb_fielddef_isseq(f)) return false;
- *s = f->selector_base - 2;
- break;
- case UPB_HANDLER_ENDSEQ:
- if (!upb_fielddef_isseq(f)) return false;
- *s = f->selector_base - 1;
- break;
- case UPB_HANDLER_STARTSUBMSG:
- if (!upb_fielddef_issubmsg(f)) return false;
- *s = f->selector_base;
- break;
- case UPB_HANDLER_ENDSUBMSG:
- if (!upb_fielddef_issubmsg(f)) return false;
- *s = f->selector_base + 1;
- break;
+// This wastes a bit of space since the "func" member of this slot is unused,
+// but the code is simpler. Worst-case overhead is 20% (messages with only
+// non-repeated submessage fields). Can change later if necessary.
+#define SUBH(h, field_base) h->table[field_base + 2].data
+
+static int32_t chkset(upb_handlers *h, const upb_fielddef *f,
+ upb_handlertype_t type) {
+ upb_selector_t sel;
+ assert(!upb_handlers_isfrozen(h));
+ if (upb_handlers_msgdef(h) != upb_fielddef_msgdef(f)) return -1;
+ if (!upb_handlers_getselector(f, type, &sel)) return -1;
+ if (h->table[sel].func) return -1;
+ return sel;
+}
+
+static bool addcleanup(upb_handlers *h, void *ptr, void (*cleanup)(void*)) {
+ if (h->cleanup_len == h->cleanup_size) {
+ h->cleanup_size = UPB_MAX(4, h->cleanup_size * 2);
+ void *resized = realloc(h->cleanup, sizeof(*h->cleanup) * h->cleanup_size);
+ if (!resized) {
+ h->cleanup_size = h->cleanup_len;
+ cleanup(ptr);
+ return false;
+ }
+ h->cleanup = resized;
}
- assert(*s < upb_fielddef_msgdef(f)->selector_count);
+ h->cleanup[h->cleanup_len].ptr = ptr;
+ h->cleanup[h->cleanup_len].cleanup = cleanup;
+ h->cleanup_len++;
return true;
}
+
+/* Public interface ***********************************************************/
+
+bool upb_handlers_isfrozen(const upb_handlers *h) {
+ return upb_refcounted_isfrozen(upb_upcast(h));
+}
+
void upb_handlers_ref(const upb_handlers *h, const void *owner) {
upb_refcounted_ref(upb_upcast(h), owner);
}
@@ -133,49 +144,20 @@ void upb_handlers_checkref(const upb_handlers *h, const void *owner) {
upb_refcounted_checkref(upb_upcast(h), owner);
}
-static void do_cleanup(upb_handlers* h, const upb_fielddef *f,
- upb_handlertype_t type) {
- upb_selector_t selector;
- if (!upb_getselector(f, type, &selector)) return;
- upb_fieldhandler *fh = getfh_mutable(h, selector);
- if (fh->cleanup) fh->cleanup(fh->data);
- fh->cleanup = NULL;
- fh->data = NULL;
-}
-
-static void freehandlers(upb_refcounted *r) {
- upb_handlers *h = (upb_handlers*)r;
- upb_msg_iter i;
- for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) {
- upb_fielddef *f = upb_msg_iter_field(&i);
- for (upb_handlertype_t type = 0; type < UPB_HANDLER_MAX; type++)
- do_cleanup(h, f, type);
- }
- upb_msgdef_unref(h->msg, h);
- free(h);
-}
-
-static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
- void *closure) {
- const upb_handlers *h = (const upb_handlers*)r;
- upb_msg_iter i;
- for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) {
- upb_fielddef *f = upb_msg_iter_field(&i);
- if (!upb_fielddef_issubmsg(f)) continue;
- const upb_handlers *sub = upb_handlers_getsubhandlers(h, f);
- if (sub) visit(r, upb_upcast(sub), closure);
- }
-}
upb_handlers *upb_handlers_new(const upb_msgdef *md, const upb_frametype *ft,
const void *owner) {
assert(upb_msgdef_isfrozen(md));
- static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
- size_t fhandlers_size = sizeof(upb_fieldhandler) * md->selector_count;
- upb_handlers *h = calloc(sizeof(*h) - sizeof(void*) + fhandlers_size, 1);
+
+ int extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1);
+ upb_handlers *h = calloc(sizeof(*h) + extra, 1);
if (!h) return NULL;
+
h->msg = md;
h->ft = ft;
+ h->cleanup = NULL;
+ h->cleanup_size = 0;
+ h->cleanup_len = 0;
upb_msgdef_ref(h->msg, h);
if (!upb_refcounted_init(upb_upcast(h), &vtbl, owner)) goto oom;
@@ -187,95 +169,38 @@ oom:
return NULL;
}
-bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
- // TODO: verify we have a transitive closure.
- return upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s);
-}
-
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
-
-const upb_frametype *upb_handlers_frametype(const upb_handlers *h) {
- return h->ft;
-}
-
-void upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handler *handler) {
- assert(!upb_handlers_isfrozen(h));
- h->startmsg = handler;
-}
-
-upb_startmsg_handler *upb_handlers_getstartmsg(const upb_handlers *h) {
- return h->startmsg;
-}
-
-void upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handler *handler) {
- assert(!upb_handlers_isfrozen(h));
- h->endmsg = handler;
-}
+const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
+ const upb_frametype *ft,
+ const void *owner,
+ upb_handlers_callback *callback,
+ void *closure) {
+ dfs_state state;
+ state.callback = callback;
+ state.closure = closure;
+ if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL;
-upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h) {
- return h->endmsg;
-}
+ upb_handlers *ret = newformsg(m, ft, owner, &state);
-// For now we stuff the subhandlers pointer into the fieldhandlers*
-// corresponding to the UPB_HANDLER_STARTSUBMSG handler.
-static const upb_handlers **subhandlersptr_sel(upb_handlers *h,
- upb_selector_t startsubmsg) {
- return &getfh_mutable(h, startsubmsg)->subhandlers;
-}
+ upb_inttable_uninit(&state.tab);
+ if (!ret) return NULL;
-static const upb_handlers **subhandlersptr(upb_handlers *h,
- const upb_fielddef *f) {
- assert(upb_fielddef_issubmsg(f));
- upb_selector_t selector;
- bool ok = upb_getselector(f, UPB_HANDLER_STARTSUBMSG, &selector);
+ upb_refcounted *r = upb_upcast(ret);
+ bool ok = upb_refcounted_freeze(&r, 1, NULL);
UPB_ASSERT_VAR(ok, ok);
- return subhandlersptr_sel(h, selector);
-}
-
-bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
- const upb_handlers *sub) {
- assert(!upb_handlers_isfrozen(h));
- if (!upb_fielddef_issubmsg(f)) return false;
- if (sub != NULL &&
- upb_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
- return false;
- }
- const upb_handlers **stored = subhandlersptr(h, f);
- const upb_handlers *old = *stored;
- if (old) upb_unref2(old, h);
- *stored = sub;
- if (sub) upb_ref2(sub, h);
- return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
- const upb_fielddef *f) {
- const upb_handlers **stored = subhandlersptr((upb_handlers*)h, f);
- return *stored;
-}
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
- upb_selector_t sel) {
- const upb_handlers **stored = subhandlersptr_sel((upb_handlers*)h, sel);
- return *stored;
+ return ret;
}
#define SETTER(name, handlerctype, handlertype) \
bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \
- handlerctype val, void *data, \
+ handlerctype func, void *data, \
upb_handlerfree *cleanup) { \
- assert(!upb_handlers_isfrozen(h)); \
- if (upb_handlers_msgdef(h) != upb_fielddef_msgdef(f)) return false; \
- upb_selector_t selector; \
- bool ok = upb_getselector(f, handlertype, &selector); \
- if (!ok) return false; \
- do_cleanup(h, f, handlertype); \
- upb_fieldhandler *fh = getfh_mutable(h, selector); \
- fh->handler = (upb_func*)val; \
- fh->data = (upb_func*)data; \
- fh->cleanup = (upb_func*)cleanup; \
+ int32_t sel = chkset(h, f, handlertype); \
+ if (sel < 0 || (cleanup && !addcleanup(h, data, cleanup))) return false; \
+ h->table[sel].func = (upb_func*)func; \
+ h->table[sel].data = data; \
return true; \
- } \
+ }
SETTER(int32, upb_int32_handler*, UPB_HANDLER_INT32);
SETTER(int64, upb_int64_handler*, UPB_HANDLER_INT64);
@@ -292,133 +217,145 @@ SETTER(startsubmsg, upb_startfield_handler*, UPB_HANDLER_STARTSUBMSG);
SETTER(endsubmsg, upb_endfield_handler*, UPB_HANDLER_ENDSUBMSG);
SETTER(endseq, upb_endfield_handler*, UPB_HANDLER_ENDSEQ);
-// Our current implementation of these "alt" functions is, according to the
-// letter of the standard, undefined behavior, because we store the
-// upb_int32_handler2* to memory and then read it back (and call it) as a
-// upb_int32_handler*. Even though both function pointer types take 32-bit
-// integer arguments, they are still technically different types (because one
-// takes an "int" argument and one takes a "long" argument), and calling a
-// function through a pointer to an incompatible type is undefined behavior.
-//
-// I think it is exceedingly unlikely that "int" and "long" would ever have
-// incompatible calling conventions when both are known to be 32 bit signed
-// two's complement integers. But if absolute standards-compliance is ever
-// required, either due to a practical problem with the undefined behavior or a
-// tool that notices the incongruity, we have an available option for being
-// perfectly standard-compliant; we can store a bool for every function pointer
-// indicating whether it is an "alt" pointer or not. Then at the call site
-// (inside upb_sink) we can do:
-//
-// if (is_alt) {
-// upb_int32_handler2 *func = fp;
-// func(...);
-// } else {
-// upb_int32_handler *func = fp;
-// func(...);
-// }
-//
-// We could do this now, but it adds complexity and wastes the memory to store
-// these useless bools. The bools are useless because the compiler will almost
-// certainly optimize away this branch and elide the two calls into a single
-// call with the 32-bit parameter calling convention.
-
-#ifdef UPB_TWO_32BIT_TYPES
-SETTER(int32alt, upb_int32_handler2*, UPB_HANDLER_INT32);
-SETTER(uint32alt, upb_uint32_handler2*, UPB_HANDLER_UINT32);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-SETTER(int64alt, upb_int64_handler2*, UPB_HANDLER_INT64);
-SETTER(uint64alt, upb_uint64_handler2*, UPB_HANDLER_UINT64);
-#endif
-
#undef SETTER
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s) {
- return getfh(h, s)->handler;
+bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
+ const upb_handlers *sub) {
+ assert(sub);
+ assert(!upb_handlers_isfrozen(h));
+ assert(upb_fielddef_issubmsg(f));
+ if (SUBH(h, f->selector_base)) return false; // Can't reset.
+ if (upb_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
+ return false;
+ }
+ SUBH(h, f->selector_base) = sub;
+ upb_ref2(sub, h);
+ return true;
}
-void *upb_handlers_gethandlerdata(const upb_handlers *h, upb_selector_t s) {
- return getfh(h, s)->data;
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+ const upb_fielddef *f) {
+ assert(upb_fielddef_issubmsg(f));
+ return SUBH(h, f->selector_base);
}
-typedef struct {
- upb_inttable tab; // maps upb_msgdef* -> upb_handlers*.
- upb_handlers_callback *callback;
- void *closure;
-} dfs_state;
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+ upb_selector_t sel) {
+ // STARTSUBMSG selector in sel is the field's selector base.
+ return SUBH(h, sel);
+}
-static upb_handlers *newformsg(const upb_msgdef *m, const upb_frametype *ft,
- const void *owner,
- dfs_state *s) {
- upb_handlers *h = upb_handlers_new(m, ft, owner);
- if (!h) return NULL;
- if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;
+const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
- s->callback(s->closure, h);
+const upb_frametype *upb_handlers_frametype(const upb_handlers *h) {
+ return h->ft;
+}
- // For each submessage field, get or create a handlers object and set it as
- // the subhandlers.
- upb_msg_iter i;
- for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
- upb_fielddef *f = upb_msg_iter_field(&i);
- if (!upb_fielddef_issubmsg(f)) continue;
+void upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handler *handler) {
+ assert(!upb_handlers_isfrozen(h));
+ h->startmsg = handler;
+}
- const upb_msgdef *subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
- upb_value subm_ent;
- if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
- upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
- } else {
- upb_handlers *sub_mh = newformsg(subdef, ft, &sub_mh, s);
- if (!sub_mh) goto oom;
- upb_handlers_setsubhandlers(h, f, sub_mh);
- upb_handlers_unref(sub_mh, &sub_mh);
- }
- }
- return h;
+upb_startmsg_handler *upb_handlers_getstartmsg(const upb_handlers *h) {
+ return h->startmsg;
+}
-oom:
- upb_handlers_unref(h, owner);
- return NULL;
+void upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handler *handler) {
+ assert(!upb_handlers_isfrozen(h));
+ h->endmsg = handler;
}
-const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
- const upb_frametype *ft,
- const void *owner,
- upb_handlers_callback *callback,
- void *closure) {
- dfs_state state;
- state.callback = callback;
- state.closure = closure;
- if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL;
+upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h) {
+ return h->endmsg;
+}
- upb_handlers *ret = newformsg(m, ft, owner, &state);
- if (!ret) return NULL;
- upb_refcounted *r = upb_upcast(ret);
- upb_status status = UPB_STATUS_INIT;
- bool ok = upb_refcounted_freeze(&r, 1, &status);
- UPB_ASSERT_VAR(ok, ok);
- upb_status_uninit(&status);
+upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s) {
+ return (upb_func *)h->table[s].func;
+}
- upb_inttable_uninit(&state.tab);
- return ret;
+const void *upb_handlers_gethandlerdata(const upb_handlers *h,
+ upb_selector_t s) {
+ return h->table[s].data;
+}
+
+/* "Static" methods ***********************************************************/
+
+bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
+ // TODO: verify we have a transitive closure.
+ return upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s);
+}
+
+upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
+ case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
+ case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
+ case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
+ case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
+ case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
+ case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
+ default: assert(false); return -1; // Invalid input.
+ }
+}
+
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+ upb_selector_t *s) {
+ switch (type) {
+ case UPB_HANDLER_INT32:
+ case UPB_HANDLER_INT64:
+ case UPB_HANDLER_UINT32:
+ case UPB_HANDLER_UINT64:
+ case UPB_HANDLER_FLOAT:
+ case UPB_HANDLER_DOUBLE:
+ case UPB_HANDLER_BOOL:
+ if (!upb_fielddef_isprimitive(f) ||
+ upb_handlers_getprimitivehandlertype(f) != type)
+ return false;
+ *s = f->selector_base;
+ break;
+ case UPB_HANDLER_STRING:
+ if (!upb_fielddef_isstring(f)) return false;
+ *s = f->selector_base;
+ break;
+ case UPB_HANDLER_STARTSTR:
+ if (!upb_fielddef_isstring(f)) return false;
+ *s = f->selector_base + 1;
+ break;
+ case UPB_HANDLER_ENDSTR:
+ if (!upb_fielddef_isstring(f)) return false;
+ *s = f->selector_base + 2;
+ break;
+ case UPB_HANDLER_STARTSEQ:
+ if (!upb_fielddef_isseq(f)) return false;
+ *s = f->selector_base - 2;
+ break;
+ case UPB_HANDLER_ENDSEQ:
+ if (!upb_fielddef_isseq(f)) return false;
+ *s = f->selector_base - 1;
+ break;
+ case UPB_HANDLER_STARTSUBMSG:
+ if (!upb_fielddef_issubmsg(f)) return false;
+ *s = f->selector_base;
+ break;
+ case UPB_HANDLER_ENDSUBMSG:
+ if (!upb_fielddef_issubmsg(f)) return false;
+ *s = f->selector_base + 1;
+ break;
+ // Subhandler slot is selector_base + 2.
+ }
+ assert(*s < upb_fielddef_msgdef(f)->selector_count);
+ return true;
}
-#define STDMSG_WRITER(type, ctype) \
- bool upb_stdmsg_set ## type (const upb_sinkframe *frame, ctype val) { \
- const upb_stdmsg_fval *f = upb_sinkframe_handlerdata(frame); \
- uint8_t *m = upb_sinkframe_userdata(frame); \
- if (f->hasbit > 0) \
- *(uint8_t*)&m[f->hasbit / 8] |= 1 << (f->hasbit % 8); \
- *(ctype*)&m[f->offset] = val; \
- return true; \
- } \
-
-STDMSG_WRITER(double, double)
-STDMSG_WRITER(float, float)
-STDMSG_WRITER(int32, int32_t)
-STDMSG_WRITER(int64, int64_t)
-STDMSG_WRITER(uint32, uint32_t)
-STDMSG_WRITER(uint64, uint64_t)
-STDMSG_WRITER(bool, bool)
-#undef STDMSG_WRITER
+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; // [STARTSTR]/STRING/ENDSTR
+ if (upb_fielddef_issubmsg(f)) ret += 2; // [STARTSUBMSG]/ENDSUBMSG/SUBH
+ return ret;
+}
diff --git a/upb/handlers.h b/upb/handlers.h
index 79ca0d8..09743ff 100644
--- a/upb/handlers.h
+++ b/upb/handlers.h
@@ -25,24 +25,54 @@
#include "upb/def.h"
#ifdef __cplusplus
+
struct upb_frametype;
+
namespace upb {
+
typedef upb_frametype FrameType;
class Handlers;
-class SinkFrame;
-}
+
+template <class T> class Handler;
+typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
+typedef Handler<bool(*)(void *, const void *)> EndFieldHandler;
+typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
+typedef Handler<size_t(*)(void *, const void *, const char *, size_t)>
+ StringHandler;
+
+template <class T> struct ValueHandler {
+ typedef Handler<bool(*)(void *, const void *, T)> H;
+};
+
+typedef ValueHandler<upb_int32_t>::H Int32Handler;
+typedef ValueHandler<upb_int64_t>::H Int64Handler;
+typedef ValueHandler<upb_uint32_t>::H UInt32Handler;
+typedef ValueHandler<upb_uint64_t>::H UInt64Handler;
+typedef ValueHandler<float>::H FloatHandler;
+typedef ValueHandler<double>::H DoubleHandler;
+typedef ValueHandler<bool>::H BoolHandler;
+template <class T> struct CanonicalType;
+
+} // namespace upb
+
typedef upb::FrameType upb_frametype;
typedef upb::Handlers upb_handlers;
-typedef upb::SinkFrame upb_sinkframe;
-UPB_INLINE void *upb_sinkframe_handlerdata(const upb_sinkframe* frame);
-#else
+
+#else // #ifdef __cplusplus
+
struct upb_frametype;
struct upb_handlers;
struct upb_sinkframe;
typedef struct upb_frametype upb_frametype;
typedef struct upb_handlers upb_handlers;
typedef struct upb_sinkframe upb_sinkframe;
-#endif
+
+#endif // #ifdef __cplusplus
+
+typedef struct {
+ void (*func)();
+ const void *data;
+} upb_handlers_tabent;
// All the different types of handlers that can be registered.
// Only needed for the advanced functions in upb::Handlers.
@@ -83,49 +113,20 @@ typedef int32_t upb_selector_t;
// parsing or visiting a message of a specific type.
//
// Any handlers that are not set behave as if they had successfully consumed
-// the value. For start* handlers that return a void* closure, an unset handler
-// will propagate the existing closure.
+// the value. Any unset Start* handlers will propagate their closure to the
+// inner frame.
+//
+// The easiest way to create the *Handler objects needed by the Set* methods is
+// with the UpbBind() and UpbMakeHandler() macros; see below.
class upb::Handlers {
public:
typedef upb_selector_t Selector;
typedef upb_handlertype_t Type;
- typedef bool StartMessageHandler(const SinkFrame*);
- typedef void EndMessageHandler(const SinkFrame*, Status* status);
- typedef void* StartFieldHandler(const SinkFrame*);
- typedef bool EndFieldHandler(const SinkFrame*);
- typedef void* StartStringHandler(const SinkFrame* c, size_t size_hint);
- typedef size_t StringHandler(const SinkFrame* c, const char* buf, size_t len);
-
- template <class T> struct Value {
- typedef bool Handler(const SinkFrame*, T val);
- };
-
- typedef Value<upb_int32_t>::Handler Int32Handler;
- typedef Value<upb_int64_t>::Handler Int64Handler;
- typedef Value<upb_uint32_t>::Handler UInt32Handler;
- typedef Value<upb_uint64_t>::Handler UInt64Handler;
- typedef Value<float>::Handler FloatHandler;
- typedef Value<double>::Handler DoubleHandler;
- typedef Value<bool>::Handler BoolHandler;
-
-#ifdef UPB_TWO_32BIT_TYPES
- typedef Value<upb_int32alt_t>::Handler Int32Handler2;
- typedef Value<upb_uint32alt_t>::Handler UInt32Handler2;
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
- typedef Value<upb_int64alt_t>::Handler Int64Handler2;
- typedef Value<upb_uint64alt_t>::Handler UInt64Handler2;
-#endif
-
// Any function pointer can be converted to this and converted back to its
// correct type.
typedef void GenericFunction();
- // For freeing handler data.
- typedef void Free(void *data);
-
typedef void HandlersCallback(void *closure, upb_handlers *h);
// Returns a new handlers object for the given frozen msgdef that will use
@@ -168,103 +169,83 @@ class upb::Handlers {
// Sets the startmsg handler for the message, which is defined as follows:
//
- // bool startmsg(const upb::SinkFrame* frame) {
+ // bool startmsg(MyType* closure) {
// // Called when the message begins. Returns true if processing should
// // continue.
// return true;
// }
- void SetStartMessageHandler(StartMessageHandler *handler);
- StartMessageHandler *GetStartMessageHandler() const;
+ //
+ // TODO(haberman): change this to work with UpbMakeHandler and auto-deduce,
+ // like all of the field handlers.
+ template<class T, bool F(T*)> void SetStartMessageHandler();
// Sets the endmsg handler for the message, which is defined as follows:
//
- // void endmsg(const upb::SinkFrame* frame, upb_status *status) {
+ // bool endmsg(MyType* closure, upb_status *status) {
// // Called when processing of this message ends, whether in success or
// // failure. "status" indicates the final status of processing, and
// // can also be modified in-place to update the final status.
// }
- void SetEndMessageHandler(EndMessageHandler *handler);
- EndMessageHandler *GetEndMessageHandler() const;
+ //
+ // TODO(haberman): change this to work with UpbMakeHandler and auto-deduce,
+ // like all of the field handlers.
+ template<class T, bool F(T*, upb::Status*)> void SetEndMessageHandler();
// Sets the value handler for the given field, which is defined as follows
// (this is for an int32 field; other field types will pass their native
// C/C++ type for "val"):
//
- // bool value(const upb::SinkFrame *frame, upb_int32_t val) {
+ // bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
// // Called when the field's value is encountered. "d" contains
// // whatever data was bound to this field when it was registered.
// // Returns true if processing should continue.
// return true;
// }
//
- // The value type must exactly match f->type().
- // For example, SetInt32Handler() may only be used for fields of type
- // UPB_TYPE_INT32 and UPB_TYPE_ENUM.
- //
- // "d" is the data that will be bound to this callback and passed to it.
- // If "fr" is non-NULL it will be run when the data is no longer needed.
+ // handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
//
- // Returns "false" if "f" does not belong to this message or has the wrong
- // type for this handler.
+ // The value type must exactly match f->type().
+ // For example, a handler that takes an int32_t parameter may only be used for
+ // fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
//
- // NOTE: the prototype above uses "upb_int32_t" and not "int32_t" from
- // stdint.h. For C++ any int32 typedef will work correctly thanks to
- // function overloading on the function pointer type. But in C things are
- // more complicated; "int" and "long" could both be 32-bit types, but the
- // two are incompatible with each other when it comes to function pointers.
- // Since we don't know what the underlying type of int32_t is, we have to
- // define our own which we *do* know the underlying type of. The easiest
- // and most portable choice is to define handlers in C with the upb_intXX_t
- // types.
- bool SetInt32Handler (const FieldDef* f, Int32Handler* h, void* d, Free* fr);
- bool SetInt64Handler (const FieldDef* f, Int64Handler* h, void* d, Free* fr);
- bool SetUInt32Handler(const FieldDef* f, UInt32Handler* h, void* d, Free* fr);
- bool SetUInt64Handler(const FieldDef* f, UInt64Handler* h, void* d, Free* fr);
- bool SetFloatHandler (const FieldDef* f, FloatHandler* h, void* d, Free* fr);
- bool SetDoubleHandler(const FieldDef* f, DoubleHandler* h, void* d, Free* fr);
- bool SetBoolHandler (const FieldDef* f, BoolHandler* h, void* d, Free* fr);
+ // Returns false if the handler failed to register; in this case the cleanup
+ // handler (if any) will be called immediately.
+ bool SetInt32Handler (const FieldDef* f, const Int32Handler& h);
+ bool SetInt64Handler (const FieldDef* f, const Int64Handler& h);
+ bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h);
+ bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h);
+ bool SetFloatHandler (const FieldDef* f, const FloatHandler& h);
+ bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h);
+ bool SetBoolHandler (const FieldDef* f, const BoolHandler& h);
// Convenience versions that look up the field by name first. These return
// false if no field with this name exists, or for any of the other reasons
// that the FieldDef* version returns false.
- bool SetInt32Handler (const char *name, Int32Handler* h, void* d, Free* fr);
- bool SetInt64Handler (const char *name, Int64Handler* h, void* d, Free* fr);
- bool SetUInt32Handler(const char *name, UInt32Handler* h, void* d, Free* fr);
- bool SetUInt64Handler(const char *name, UInt64Handler* h, void* d, Free* fr);
- bool SetFloatHandler (const char *name, FloatHandler* h, void* d, Free* fr);
- bool SetDoubleHandler(const char *name, DoubleHandler* h, void* d, Free* fr);
- bool SetBoolHandler (const char *name, BoolHandler* h, void* d, Free* fr);
-
- // On platforms where there are two 32-bit or 64-bit integer types, provide
- // registration functions for both. Function overloading should make this
- // all transparent to the user.
-#ifdef UPB_TWO_32BIT_TYPES
- bool SetInt32Handler (const FieldDef* f, Int32Handler2* h, void* d, Free* x);
- bool SetUInt32Handler(const FieldDef* f, UInt32Handler2* h, void* d, Free* x);
- bool SetInt32Handler (const char *name, Int32Handler2* h, void* d, Free* x);
- bool SetUInt32Handler(const char *name, UInt32Handler2* h, void* d, Free* x);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
- bool SetInt64Handler (const FieldDef* f, Int64Handler2* h, void* d, Free* x);
- bool SetUInt64Handler(const FieldDef* f, UInt64Handler2* h, void* d, Free* x);
- bool SetInt64Handler (const char *name, Int64Handler2* h, void* d, Free* x);
- bool SetUInt64Handler(const char *name, UInt64Handler2* h, void* d, Free* x);
-#endif
-
- // Like the above, but these are templated on the type of the value. For
- // example, templating on int64_t is equivalent to calling SetInt64Handler.
- // Attempts to template on a type that does not map to a UPB_TYPE_* type
- // (like int8_t, since protobufs have no 8-bit type) will get an "undefined
- // function" compilation error.
- template<class T> bool SetValueHandler(
- const FieldDef* f, typename Value<T>::Handler* h, void* d, Free* fr);
- template<class T> bool SetValueHandler(
- const char* name, typename Value<T>::Handler* h, void* d, Free* fr);
+ bool SetInt32Handler (const char *name, const Int32Handler& h);
+ bool SetInt64Handler (const char *name, const Int64Handler& h);
+ bool SetUInt32Handler(const char *name, const UInt32Handler& h);
+ bool SetUInt64Handler(const char *name, const UInt64Handler& h);
+ bool SetFloatHandler (const char *name, const FloatHandler& h);
+ bool SetDoubleHandler(const char *name, const DoubleHandler& h);
+ bool SetBoolHandler (const char *name, const BoolHandler& h);
+
+ // Like the previous, but templated on the type on the value (ie. int32).
+ // This is mostly useful to call from other templates. To call this you must
+ // specify the template parameter explicitly, ie:
+ // h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData));
+ template <class T>
+ bool SetValueHandler(
+ const FieldDef *f,
+ const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler);
+ template <class T>
+ bool SetValueHandler(
+ const char *name,
+ const typename ValueHandler<typename CanonicalType<T>::Type>::H& handler);
// Sets handlers for a string field, which are defined as follows:
//
- // void* startstr(const upb::SinkFrame *frame, size_t size_hint) {
+ // MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
+ // size_t size_hint) {
// // Called when a string value begins. The return value indicates the
// // closure for the string. "size_hint" indicates the size of the
// // string if it is known, however if the string is length-delimited
@@ -279,7 +260,8 @@ class upb::Handlers {
// return closure;
// }
//
- // size_t str(const upb::SinkFrame* frame, const char *str, size_t len) {
+ // size_t str(MyClosure* closure, const MyHandlerData* d,
+ // const char *str, size_t len) {
// // Called for each buffer of string data; the multiple physical buffers
// // are all part of the same logical string. The return value indicates
// // how many bytes were consumed. If this number is less than "len",
@@ -290,98 +272,80 @@ class upb::Handlers {
// return len;
// }
//
- // bool endstr(const upb::SinkFrame* frame) {
- // // Called when a string value ends.
+ // bool endstr(MyClosure* c, const MyHandlerData* d) {
+ // // Called when a string value ends. Return value indicates whether
+ // // processing should continue.
// return true;
// }
- bool SetStartStringHandler(const FieldDef* f, StartStringHandler* h,
- void* d, Free* fr);
- bool SetStringHandler(const FieldDef* f, StringHandler* h, void* d, Free* fr);
- bool SetEndStringHandler(const FieldDef* f, EndFieldHandler* h,
- void* d, Free* fr);
+ bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h);
+ bool SetStringHandler(const FieldDef* f, const StringHandler& h);
+ bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h);
// Convenience versions that look up the field by name first. These return
// false if no field with this name exists, or for any of the other reasons
// that the FieldDef* version returns false.
- bool SetStartStringHandler(const char* name, StartStringHandler* h,
- void* d, Free* fr);
- bool SetStringHandler(const char* name, StringHandler* h, void* d, Free* fr);
- bool SetEndStringHandler(const char* name, EndFieldHandler* h,
- void* d, Free* fr);
+ bool SetStartStringHandler(const char* name, const StartStringHandler& h);
+ bool SetStringHandler(const char* name, const StringHandler& h);
+ bool SetEndStringHandler(const char* name, const EndFieldHandler& h);
// Sets the startseq handler, which is defined as follows:
//
- // void *startseq(const upb::SinkFrame* frame) {
+ // MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
// // Called when a sequence (repeated field) begins. The returned
// // pointer indicates the closure for the sequence (or UPB_BREAK
// // to interrupt processing).
// return closure;
// }
//
+ // h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
+ //
// Returns "false" if "f" does not belong to this message or is not a
// repeated field.
- //
- // "data" is the data that will be bound to this callback and passed to it.
- // If "cleanup" is non-NULL it will be run when the data is no longer needed.
- bool SetStartSequenceHandler(const FieldDef* f, StartFieldHandler *handler,
- void* data, Free* cleanup);
- bool SetStartSequenceHandler(const char* name, StartFieldHandler *handler,
- void* data, Free* cleanup);
+ bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h);
+ bool SetStartSequenceHandler(const char* name, const StartFieldHandler& h);
// Sets the startsubmsg handler for the given field, which is defined as
// follows:
//
- // void *startsubmsg(const upb::SinkFrame *frame) {
+ // MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
// // Called when a submessage begins. The returned pointer indicates the
// // closure for the sequence (or UPB_BREAK to interrupt processing).
// return closure;
// }
//
- // "data" is the data that will be bound to this callback and passed to it.
- // If "cleanup" is non-NULL it will be run when the data is no longer needed.
+ // h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
+ // new MyHandlerData(...)));
//
// Returns "false" if "f" does not belong to this message or is not a
// submessage/group field.
- bool SetStartSubMessageHandler(const FieldDef* f, StartFieldHandler *handler,
- void* data, Free* cleanup);
- bool SetStartSubMessageHandler(const char* name, StartFieldHandler *handler,
- void* data, Free* cleanup);
+ bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h);
+ bool SetStartSubMessageHandler(const char* name, const StartFieldHandler& h);
// Sets the endsubmsg handler for the given field, which is defined as
// follows:
//
- // bool endsubmsg(const upb::SinkFrame *frame) {
+ // bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
// // Called when a submessage ends. Returns true to continue processing.
// return true;
// }
//
- // "data" is the data that will be bound to this callback and passed to it.
- // If "cleanup" is non-NULL it will be run when the data is no longer needed.
- //
// Returns "false" if "f" does not belong to this message or is not a
// submessage/group field.
- bool SetEndSubMessageHandler(const FieldDef* f, EndFieldHandler *handler,
- void* data, Free* cleanup);
- bool SetEndSubMessageHandler(const char* name, EndFieldHandler *handler,
- void* data, Free* cleanup);
+ bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h);
+ bool SetEndSubMessageHandler(const char *name, const EndFieldHandler &h);
// Starts the endsubseq handler for the given field, which is defined as
// follows:
//
- // bool endseq(const upb::SinkFrame *frame) {
+ // bool endseq(MyClosure* c, const MyHandlerData* d) {
// // Called when a sequence ends. Returns true continue processing.
// return true;
// }
//
- // "data" is the data that will be bound to this callback and passed to it.
- // If "cleanup" is non-NULL it will be run when the data is no longer needed.
- //
// Returns "false" if "f" does not belong to this message or is not a
// repeated field.
- bool SetEndSequenceHandler(const FieldDef* f, EndFieldHandler *handler,
- void* data, Free* cleanup);
- bool SetEndSequenceHandler(const char* name, EndFieldHandler *handler,
- void* data, Free* cleanup);
+ bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h);
+ bool SetEndSequenceHandler(const char* name, const EndFieldHandler& h);
// Sets or gets the object that specifies handlers for the given field, which
// must be a submessage or group. Returns NULL if no handlers are set.
@@ -408,11 +372,7 @@ class upb::Handlers {
GenericFunction* GetHandler(Selector selector);
// Returns the handler data that was registered with this handler.
- void* GetHandlerData(Selector selector);
-
- // Gets the byte offset from a Handlers* where the given handler can be found.
- // Useful for JITs that want to read the pointer in their fast path.
- static size_t GetHandlerOffset(Selector selector);
+ const void* GetHandlerData(Selector selector);
// Could add any of the following functions as-needed, with some minor
// implementation changes:
@@ -422,7 +382,6 @@ class upb::Handlers {
private:
UPB_DISALLOW_POD_OPS(Handlers);
- friend void* ::upb_sinkframe_handlerdata(const upb_sinkframe* frame);
#else
struct upb_handlers {
@@ -430,43 +389,175 @@ struct upb_handlers {
upb_refcounted base;
const upb_msgdef *msg;
const upb_frametype *ft;
- bool (*startmsg)(const upb_sinkframe*);
- void (*endmsg)(const upb_sinkframe*, upb_status*);
- void *fh_base[1]; // Start of dynamically-sized field handler array.
+ bool (*startmsg)(void*);
+ bool (*endmsg)(void*, upb_status*);
+ struct {
+ void *ptr;
+ void (*cleanup)(void*);
+ } *cleanup;
+ size_t cleanup_len, cleanup_size;
+ upb_handlers_tabent table[1]; // Dynamically-sized field handler array.
};
-// Native C API.
#ifdef __cplusplus
+
+namespace upb {
+
+// Convenience macros for creating a Handler object that is wrapped with a
+// type-safe wrapper function that converts the "void*" parameters/returns
+// of the underlying C API into nice C++ function.
+//
+// Sample usage:
+// bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
+// // do stuff ...
+// return true;
+// }
+//
+// // Handler that doesn't need any data bound to it.
+// bool OnValue(MyClosure* c, int32_t val) {
+// // do stuff ...
+// return true;
+// }
+//
+// // Takes ownership of the MyHandlerData.
+// handlers->SetInt32Handler(f1, UpbBind(OnValue, new MyHandlerData(...)));
+// handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue));
+
+#ifdef UPB_CXX11
+
+// In C++11, the "template" disambiguator can appear even outside templates,
+// so all calls can safely use this pair of macros.
+
+#define UpbMakeHandler(f) \
+ upb::MakeHandler(upb::MatchWrapper(f).template Wrapper<f>)
+
+// We have to be careful to only evaluate "d" once.
+#define UpbBind(f, d) \
+ upb::BindHandler(upb::MatchWrapper(f).template Wrapper<f>, f, (d))
+
+#else
+
+// Prior to C++11, the "template" disambiguator may only appear inside a
+// template, so the regular macro must not use "template"
+
+#define UpbMakeHandler(f) \
+ upb::MakeHandler(upb::MatchWrapper(f).Wrapper<f>)
+
+#define UpbBind(f, d) \
+ upb::BindHandler(upb::MatchWrapper(f).Wrapper<f>, f, (d))
+
+#endif // UPB_CXX11
+
+// This macro must be used in C++98 for calls from inside a template. But we
+// define this variant in all cases; code that wants to be compatible with both
+// C++98 and C++11 should always use this macro when calling from a template.
+#define UpbMakeHandlerT(f) \
+ upb::MakeHandler(upb::MatchWrapper(f).template Wrapper<f>)
+
+#define UpbBindT(f, d) \
+ upb::BindHandler(upb::MatchWrapper(f).template Wrapper<f>, f, (d))
+
+
+// FieldHandler: a struct that contains the (handler, data, deleter) tuple that
+// is used by all field-level handlers. Users could Make() these directly but
+// it's more convenient to use the Upb{Bind,Make}ValueHandler macros.
+//
+// This class is intentionally not copyable or assignable; it can only be
+// constructed as a temporary object with Make() and then must be registered as
+// a handler (this is enforced with the assert() in the destructor).
+template <class T> class Handler {
+ public:
+ // The underlying, non-type-safe handler function signature that upb uses
+ // internally.
+ typedef T FuncPtr;
+
+ ~Handler() { assert(registered_); }
+
+ static Handler<T> Make(FuncPtr h, void* hd, void (*fr)(void*)) {
+ return Handler<T>(h, hd, fr);
+ }
+
+ private:
+ friend class Handlers;
+
+ Handler(FuncPtr h, void *d, void (*c)(void *))
+ : handler_(h), data_(d), cleanup_(c), registered_(false) {}
+ Handler(const Handler&);
+ void operator=(const Handler&);
+
+ FuncPtr handler_;
+ void *data_;
+ void (*cleanup_)(void*);
+ mutable bool registered_;
+
+ // Noisy friend declarations; these are all of the "Bind" functions,
+ // two for each type of handler. They need to be friends so that
+ // they can call the copy constructor to return a temporary.
+
+ template <class T1>
+ friend typename ValueHandler<T1>::H MakeHandler(bool (*wrapper)(void *,
+ const void *,
+ T1));
+
+ template <class C, class D, class T1, class T2>
+ friend typename ValueHandler<T1>::H BindHandler(
+ bool (*wrapper)(void *, const void *, T1), bool (*h)(C *, const D *, T2),
+ D *data);
+
+ friend StartFieldHandler MakeHandler(void* (*wrapper)(void *, const void *));
+
+ template <class R, class C, class D>
+ friend StartFieldHandler BindHandler(void *(*wrapper)(void *, const void *),
+ R *(*h)(C *, const D *), D *data);
+
+ friend EndFieldHandler MakeHandler(bool (*wrapper)(void *, const void *));
+
+ template <class C, class D>
+ friend EndFieldHandler BindHandler(bool (*wrapper)(void *, const void *),
+ bool (*h)(C *, const D *), D *data);
+
+ friend StringHandler MakeHandler(size_t (*wrapper)(void *, const void *,
+ const char *, size_t));
+
+ template <class C, class D>
+ friend StringHandler BindHandler(
+ size_t (*wrapper)(void *, const void *, const char *, size_t),
+ size_t (*h)(C *, const D *, const char *, size_t), D *data);
+
+ friend StartStringHandler MakeHandler(void *(*wrapper)(void *, const void *,
+ size_t));
+
+ template <class R, class C, class D>
+ friend StartStringHandler BindHandler(void *(*wrapper)(void *, const void *,
+ size_t),
+ R *(*h)(C *, const D *, size_t),
+ D *data);
+};
+
+} // namespace upb
+
extern "C" {
-#endif
-typedef bool upb_startmsg_handler(const upb_sinkframe *frame);
-typedef void upb_endmsg_handler(const upb_sinkframe *frame, upb_status *status);
-typedef void* upb_startfield_handler(const upb_sinkframe *frame);
-typedef bool upb_endfield_handler(const upb_sinkframe *frame);
+#endif // __cplusplus
+
+// Native C API.
typedef void upb_handlers_callback(void *closure, upb_handlers *h);
typedef void upb_handlerfree(void *d);
typedef void upb_func();
-typedef bool upb_int32_handler(const upb_sinkframe *f, upb_int32_t val);
-typedef bool upb_int64_handler(const upb_sinkframe *f, upb_int64_t val);
-typedef bool upb_uint32_handler(const upb_sinkframe *f, upb_uint32_t val);
-typedef bool upb_uint64_handler(const upb_sinkframe *f, upb_uint64_t val);
-typedef bool upb_float_handler(const upb_sinkframe *f, float val);
-typedef bool upb_double_handler(const upb_sinkframe *f, double val);
-typedef bool upb_bool_handler(const upb_sinkframe *f, bool val);
-typedef void* upb_startstr_handler(const upb_sinkframe *f, size_t size_hint);
-typedef size_t upb_string_handler(
- const upb_sinkframe *f, const char *buf, size_t n);
-
-#ifdef UPB_TWO_32BIT_TYPES
-typedef bool upb_int32_handler2(const upb_sinkframe *f, upb_int32alt_t val);
-typedef bool upb_uint32_handler2(const upb_sinkframe *f, upb_uint32alt_t val);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-typedef bool upb_int64_handler2(const upb_sinkframe *f, upb_int64alt_t val);
-typedef bool upb_uint64_handler2(const upb_sinkframe *f, upb_uint64alt_t val);
-#endif
+typedef bool upb_startmsg_handler(void *c);
+typedef bool upb_endmsg_handler(void *c, upb_status *status);
+typedef void* upb_startfield_handler(void *c, const void *hd);
+typedef bool upb_endfield_handler(void *c, const void *hd);
+typedef bool upb_int32_handler(void *c, const void *hd, int32_t val);
+typedef bool upb_int64_handler(void *c, const void *hd, int64_t val);
+typedef bool upb_uint32_handler(void *c, const void *hd, uint32_t val);
+typedef bool upb_uint64_handler(void *c, const void *hd, uint64_t val);
+typedef bool upb_float_handler(void *c, const void *hd, float val);
+typedef bool upb_double_handler(void *c, const void *hd, double val);
+typedef bool upb_bool_handler(void *c, const void *hd, bool val);
+typedef void* upb_startstr_handler(void *c, const void *hd, size_t size_hint);
+typedef size_t upb_string_handler(void *c, const void *hd, const char *buf,
+ size_t n);
upb_handlers *upb_handlers_new(const upb_msgdef *m,
const upb_frametype *ft,
@@ -478,95 +569,79 @@ const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
void *closure);
// From upb_refcounted.
-void upb_handlers_unref(const upb_handlers *h, const void *owner);
bool upb_handlers_isfrozen(const upb_handlers *h);
void upb_handlers_ref(const upb_handlers *h, const void *owner);
-void upb_handlers_donateref(
- const upb_handlers *h, const void *from, const void *to);
+void upb_handlers_unref(const upb_handlers *h, const void *owner);
+void upb_handlers_donateref(const upb_handlers *h, const void *from,
+ const void *to);
void upb_handlers_checkref(const upb_handlers *h, const void *owner);
-bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s);
const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
const upb_frametype *upb_handlers_frametype(const upb_handlers *h);
void upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handler *handler);
upb_startmsg_handler *upb_handlers_getstartmsg(const upb_handlers *h);
void upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handler *handler);
upb_endmsg_handler *upb_handlers_getendmsg(const upb_handlers *h);
-bool upb_handlers_setint32(
- upb_handlers *h, const upb_fielddef *f, upb_int32_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setint64(
- upb_handlers *h, const upb_fielddef *f, upb_int64_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setuint32(
- upb_handlers *h, const upb_fielddef *f, upb_uint32_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setuint64(
- upb_handlers *h, const upb_fielddef *f, upb_uint64_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setfloat(
- upb_handlers *h, const upb_fielddef *f, upb_float_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setdouble(
- upb_handlers *h, const upb_fielddef *f, upb_double_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setbool(
- upb_handlers *h, const upb_fielddef *f, upb_bool_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setstartstr(
- upb_handlers *h, const upb_fielddef *f, upb_startstr_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setstring(
- upb_handlers *h, const upb_fielddef *f, upb_string_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setendstr(
- upb_handlers *h, const upb_fielddef *f, upb_endfield_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setstartseq(
- upb_handlers *h, const upb_fielddef *f, upb_startfield_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setstartsubmsg(
- upb_handlers *h, const upb_fielddef *f, upb_startfield_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setendsubmsg(
- upb_handlers *h, const upb_fielddef *f, upb_endfield_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setendseq(
- upb_handlers *h, const upb_fielddef *f, upb_endfield_handler *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setsubhandlers(
- upb_handlers *h, const upb_fielddef *f, const upb_handlers *sub);
-const upb_handlers *upb_handlers_getsubhandlers(
- const upb_handlers *h, const upb_fielddef *f);
-const upb_handlers *upb_handlers_getsubhandlers_sel(
- const upb_handlers *h, upb_selector_t sel);
+bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
+ upb_int32_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
+ upb_int64_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
+ upb_uint32_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
+ upb_uint64_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
+ upb_float_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
+ upb_double_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
+ upb_bool_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
+ upb_startstr_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
+ upb_string_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
+ upb_endfield_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
+ upb_startfield_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
+ upb_startfield_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
+ upb_endfield_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
+ upb_endfield_handler *handler, void *d,
+ upb_handlerfree *fr);
+bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
+ const upb_handlers *sub);
+const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
+ const upb_fielddef *f);
+const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
+ upb_selector_t sel);
+upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s);
+const void *upb_handlers_gethandlerdata(const upb_handlers *h,
+ upb_selector_t s);
+
+// "Static" methods
+bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s);
upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
-bool upb_getselector(
- const upb_fielddef *f, upb_handlertype_t type, upb_selector_t *s);
-UPB_INLINE upb_selector_t upb_getendselector(upb_selector_t start) {
+bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
+ upb_selector_t *s);
+UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
return start + 1;
}
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s);
-void *upb_handlers_gethandlerdata(const upb_handlers *h, upb_selector_t s);
-size_t upb_gethandleroffset(upb_selector_t s);
-
-#ifdef UPB_TWO_32BIT_TYPES
-bool upb_handlers_setint32alt(
- upb_handlers *h, const upb_fielddef *f, upb_int32_handler2 *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setuint32alt(
- upb_handlers *h, const upb_fielddef *f, upb_uint32_handler2 *handler,
- void *d, upb_handlerfree *fr);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-bool upb_handlers_setint64alt(
- upb_handlers *h, const upb_fielddef *f, upb_int64_handler2 *handler,
- void *d, upb_handlerfree *fr);
-bool upb_handlers_setuint64alt(
- upb_handlers *h, const upb_fielddef *f, upb_uint64_handler2 *handler,
- void *d, upb_handlerfree *fr);
-#endif
// Internal-only.
uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
@@ -599,414 +674,8 @@ DEFINE_NAME_SETTER(startsubmsg, upb_startfield_handler*);
DEFINE_NAME_SETTER(endsubmsg, upb_endfield_handler*);
DEFINE_NAME_SETTER(endseq, upb_endfield_handler*);
-#ifdef UPB_TWO_32BIT_TYPES
-DEFINE_NAME_SETTER(int32alt, upb_int32_handler2*);
-DEFINE_NAME_SETTER(uint32alt, upb_uint32_handler2*);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-DEFINE_NAME_SETTER(int64alt, upb_int64_handler2*);
-DEFINE_NAME_SETTER(uint64alt, upb_uint64_handler2*);
-#endif
-
#undef DEFINE_NAME_SETTER
-// Value writers for every in-memory type: write the data to a known offset
-// from the closure "c." These depend on the fval being a pointer to a
-// structure that is (or begins with) the upb_stdmsg_fval type.
-//
-// TODO(haberman): These are hacky; remove them and replace with an API that
-// lets you set a simple "writer" handler in a way that can generate
-// specialized code right then.
-
-typedef struct upb_stdmsg_fval {
-#ifdef __cplusplus
- upb_stdmsg_fval(size_t offset_, int32_t hasbit_)
- : offset(offset_),
- hasbit(hasbit_) {
- }
-#endif
- size_t offset;
- int32_t hasbit;
-} upb_stdmsg_fval;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-bool upb_stdmsg_setint32(const upb_sinkframe *frame, int32_t val);
-bool upb_stdmsg_setint64(const upb_sinkframe *frame, int64_t val);
-bool upb_stdmsg_setuint32(const upb_sinkframe *frame, uint32_t val);
-bool upb_stdmsg_setuint64(const upb_sinkframe *frame, uint64_t val);
-bool upb_stdmsg_setfloat(const upb_sinkframe *frame, float val);
-bool upb_stdmsg_setdouble(const upb_sinkframe *frame, double val);
-bool upb_stdmsg_setbool(const upb_sinkframe *frame, bool val);
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#ifdef __cplusplus
-
-namespace upb {
-
-// This function should be specialized by types that have a FrameType.
-template<class T> inline const FrameType* GetFrameType() { return NULL; }
-
-// C++ Wrappers
-inline Handlers* Handlers::New(const MessageDef* m, const FrameType* ft,
- const void *owner) {
- return upb_handlers_new(m, ft, owner);
-}
-inline const Handlers* Handlers::NewFrozen(
- const MessageDef *m, const FrameType* ft, const void *owner,
- upb_handlers_callback *callback, void *closure) {
- return upb_handlers_newfrozen(m, ft, owner, callback, closure);
-}
-inline bool Handlers::IsFrozen() const {
- return upb_handlers_isfrozen(this);
-}
-inline void Handlers::Ref(const void* owner) const {
- upb_handlers_ref(this, owner);
-}
-inline void Handlers::Unref(const void* owner) const {
- upb_handlers_unref(this, owner);
-}
-inline void Handlers::DonateRef(const void *from, const void *to) const {
- upb_handlers_donateref(this, from, to);
-}
-inline void Handlers::CheckRef(const void *owner) const {
- upb_handlers_checkref(this, owner);
-}
-inline bool Handlers::Freeze(Handlers*const* handlers, int n, Status* s) {
- return upb_handlers_freeze(handlers, n, s);
-}
-inline const FrameType* Handlers::frame_type() const {
- return upb_handlers_frametype(this);
-}
-inline const MessageDef* Handlers::message_def() const {
- return upb_handlers_msgdef(this);
-}
-inline void Handlers::SetStartMessageHandler(
- Handlers::StartMessageHandler *handler) {
- upb_handlers_setstartmsg(this, handler);
-}
-inline void Handlers::SetEndMessageHandler(
- Handlers::EndMessageHandler *handler) {
- upb_handlers_setendmsg(this, handler);
-}
-inline bool Handlers::SetInt32Handler(
- const FieldDef *f, Handlers::Int32Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint32(this, f, handler, d, fr);
-}
-inline bool Handlers::SetInt64Handler(
- const FieldDef *f, Handlers::Int64Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint64(this, f, handler, d, fr);
-}
-inline bool Handlers::SetUInt32Handler(
- const FieldDef *f, Handlers::UInt32Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint32(this, f, handler, d, fr);
-}
-inline bool Handlers::SetUInt64Handler(
- const FieldDef *f, Handlers::UInt64Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint64(this, f, handler, d, fr);
-}
-inline bool Handlers::SetFloatHandler(
- const FieldDef *f, Handlers::FloatHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setfloat(this, f, handler, d, fr);
-}
-inline bool Handlers::SetDoubleHandler(
- const FieldDef *f, Handlers::DoubleHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setdouble(this, f, handler, d, fr);
-}
-inline bool Handlers::SetBoolHandler(
- const FieldDef *f, Handlers::BoolHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setbool(this, f, handler, d, fr);
-}
-inline bool Handlers::SetStartStringHandler(
- const FieldDef* f, Handlers::StartStringHandler* handler,
- void* d, Handlers::Free* fr) {
- return upb_handlers_setstartstr(this, f, handler, d, fr);
-}
-inline bool Handlers::SetEndStringHandler(
- const FieldDef* f, Handlers::EndFieldHandler* handler,
- void* d, Handlers::Free* fr) {
- return upb_handlers_setendstr(this, f, handler, d, fr);
-}
-inline bool Handlers::SetStringHandler(
- const FieldDef *f, Handlers::StringHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setstring(this, f, handler, d, fr);
-}
-inline bool Handlers::SetStartSequenceHandler(
- const FieldDef* f, Handlers::StartFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setstartseq(this, f, handler, d, fr);
-}
-inline bool Handlers::SetStartSubMessageHandler(
- const FieldDef* f, Handlers::StartFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setstartsubmsg(this, f, handler, d, fr);
-}
-inline bool Handlers::SetEndSubMessageHandler(
- const FieldDef* f, Handlers::EndFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setendsubmsg(this, f, handler, d, fr);
-}
-inline bool Handlers::SetEndSequenceHandler(
- const FieldDef* f, Handlers::EndFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setendseq(this, f, handler, d, fr);
-}
-inline bool Handlers::SetSubHandlers(
- const FieldDef* f, const Handlers* sub) {
- return upb_handlers_setsubhandlers(this, f, sub);
-}
-inline bool Handlers::SetInt32Handler(
- const char* name, Handlers::Int32Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint32_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetInt64Handler(
- const char* name, Handlers::Int64Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint64_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetUInt32Handler(
- const char* name, Handlers::UInt32Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint32_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetUInt64Handler(
- const char* name, Handlers::UInt64Handler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint64_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetFloatHandler(
- const char* name, Handlers::FloatHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setfloat_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetDoubleHandler(
- const char* name, Handlers::DoubleHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setdouble_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetBoolHandler(
- const char* name, Handlers::BoolHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setbool_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetStartStringHandler(
- const char* name, Handlers::StartStringHandler* handler,
- void* d, Handlers::Free* fr) {
- return upb_handlers_setstartstr_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetEndStringHandler(
- const char* name, Handlers::EndFieldHandler* handler,
- void* d, Handlers::Free* fr) {
- return upb_handlers_setendstr_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetStringHandler(
- const char* name, Handlers::StringHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setstring_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetStartSequenceHandler(
- const char* name, Handlers::StartFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setstartseq_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetStartSubMessageHandler(
- const char* name, Handlers::StartFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setstartsubmsg_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetEndSubMessageHandler(
- const char* name, Handlers::EndFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setendsubmsg_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetEndSequenceHandler(
- const char* name, Handlers::EndFieldHandler *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setendseq_n(this, name, handler, d, fr);
-}
-inline Handlers::StartMessageHandler *Handlers::GetStartMessageHandler() const {
- return upb_handlers_getstartmsg(this);
-}
-inline Handlers::EndMessageHandler *Handlers::GetEndMessageHandler() const {
- return upb_handlers_getendmsg(this);
-}
-inline const Handlers* Handlers::GetSubHandlers(
- const FieldDef* f) const {
- return upb_handlers_getsubhandlers(this, f);
-}
-inline const Handlers* Handlers::GetSubHandlers(
- Handlers::Selector sel) const {
- return upb_handlers_getsubhandlers_sel(this, sel);
-}
-inline bool Handlers::GetSelector(
- const FieldDef* f, Handlers::Type type, Handlers::Selector* s) {
- return upb_getselector(f, type, s);
-}
-inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) {
- return upb_getendselector(start);
-}
-inline Handlers::GenericFunction* Handlers::GetHandler(
- Handlers::Selector selector) {
- return upb_handlers_gethandler(this, selector);
-}
-inline void* Handlers::GetHandlerData(Handlers::Selector selector) {
- return upb_handlers_gethandlerdata(this, selector);
-}
-inline size_t Handlers::GetHandlerOffset(Handlers::Selector selector) {
- return upb_gethandleroffset(selector);
-}
-
-#ifdef UPB_TWO_32BIT_TYPES
-inline bool Handlers::SetInt32Handler(
- const FieldDef *f, Handlers::Int32Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint32alt(this, f, handler, d, fr);
-}
-inline bool Handlers::SetUInt32Handler(
- const FieldDef *f, Handlers::UInt32Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint32alt(this, f, handler, d, fr);
-}
-inline bool Handlers::SetInt32Handler(
- const char* name, Handlers::Int32Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint32alt_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetUInt32Handler(
- const char* name, Handlers::UInt32Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint32alt_n(this, name, handler, d, fr);
-}
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-inline bool Handlers::SetInt64Handler(
- const FieldDef *f, Handlers::Int64Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint64alt(this, f, handler, d, fr);
-}
-inline bool Handlers::SetUInt64Handler(
- const FieldDef *f, Handlers::UInt64Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint64alt(this, f, handler, d, fr);
-}
-inline bool Handlers::SetInt64Handler(
- const char* name, Handlers::Int64Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setint64alt_n(this, name, handler, d, fr);
-}
-inline bool Handlers::SetUInt64Handler(
- const char* name, Handlers::UInt64Handler2 *handler,
- void *d, Handlers::Free *fr) {
- return upb_handlers_setuint64alt_n(this, name, handler, d, fr);
-}
-#endif
-
-#define SET_VALUE_HANDLER(type, ctype, handlertype) \
- template<> \
- inline bool Handlers::SetValueHandler<ctype>( \
- const FieldDef* f, \
- handlertype* handler, \
- void* data, Handlers::Free* cleanup) { \
- return upb_handlers_set ## type(this, f, handler, data, cleanup); \
- } \
- template<> \
- inline bool Handlers::SetValueHandler<ctype>( \
- const char* f, \
- handlertype* handler, \
- void* data, Handlers::Free* cleanup) { \
- return upb_handlers_set ## type ## _n(this, f, handler, data, cleanup); \
- }
-SET_VALUE_HANDLER(double, double, DoubleHandler);
-SET_VALUE_HANDLER(float, float, FloatHandler);
-SET_VALUE_HANDLER(uint64, upb_uint64_t, UInt64Handler);
-SET_VALUE_HANDLER(uint32, upb_uint32_t, UInt32Handler);
-SET_VALUE_HANDLER(int64, upb_int64_t, Int64Handler);
-SET_VALUE_HANDLER(int32, upb_int32_t, Int32Handler);
-SET_VALUE_HANDLER(bool, bool, BoolHandler);
-
-#ifdef UPB_TWO_32BIT_TYPES
-SET_VALUE_HANDLER(int32alt, upb_int32alt_t, Int32Handler2);
-SET_VALUE_HANDLER(uint32alt, upb_uint32alt_t, UInt32Handler2);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-SET_VALUE_HANDLER(int64alt, upb_int64alt_t, Int64Handler2);
-SET_VALUE_HANDLER(uint64alt, upb_uint64alt_t, UInt64Handler2);
-#endif
-
-#undef SET_VALUE_HANDLER
-
-template <class T> void DeletePointer(void *p) { delete static_cast<T*>(p); }
-
-template <class T>
-void SetStoreValueHandler(
- const FieldDef* f, size_t offset, int32_t hasbit, Handlers* h);
-
-// A handy templated function that will retrieve a value handler for a given
-// C++ type.
-#define SET_STORE_VALUE_HANDLER(type, ctype, handlerctype) \
- template <> \
- inline void SetStoreValueHandler<ctype>(const FieldDef* f, size_t offset, \
- int32_t hasbit, Handlers* h) { \
- h->SetValueHandler<handlerctype>( \
- f, upb_stdmsg_set ## type, new upb_stdmsg_fval(offset, hasbit), \
- &upb::DeletePointer<upb_stdmsg_fval>); \
- }
-
-SET_STORE_VALUE_HANDLER(double, double, double);
-SET_STORE_VALUE_HANDLER(float, float, float);
-SET_STORE_VALUE_HANDLER(uint64, upb_uint64_t, uint64_t);
-SET_STORE_VALUE_HANDLER(uint32, upb_uint32_t, uint32_t);
-SET_STORE_VALUE_HANDLER(int64, upb_int64_t, int64_t);
-SET_STORE_VALUE_HANDLER(int32, upb_int32_t, int32_t);
-SET_STORE_VALUE_HANDLER(bool, bool, bool);
-
-#ifdef UPB_TWO_32BIT_TYPES
-SET_STORE_VALUE_HANDLER(int32, upb_int32alt_t, int32_t);
-SET_STORE_VALUE_HANDLER(uint32, upb_uint32alt_t, uint32_t);
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-SET_STORE_VALUE_HANDLER(int64, upb_int64alt_t, int64_t);
-SET_STORE_VALUE_HANDLER(uint64, upb_uint64alt_t, uint64_t);
-#endif
-
-#undef SET_STORE_VALUE_HANDLER
+#include "upb/handlers-inl.h"
-} // namespace upb
-#endif
-
-// Implementation detail, put in the header file only so
-// upb_sinkframe_handlerdata() can be inlined.
-typedef struct {
- upb_func *handler;
-
- // Could put either or both of these in a separate table to save memory when
- // they are sparse.
- void *data;
- upb_handlerfree *cleanup;
-
- // TODO(haberman): this is wasteful; only the first "fieldhandler" of a
- // submessage field needs this. To reduce memory footprint we should either:
- // - put the subhandlers in a separate "fieldhandler", stored as part of
- // a union with one of the above fields.
- // - count selector offsets by individual pointers instead of by whole
- // fieldhandlers.
- const upb_handlers *subhandlers;
-} upb_fieldhandler;
-
-#endif
+#endif // UPB_HANDLERS_H
diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c
index da4c48d..18bb430 100644
--- a/upb/pb/decoder.c
+++ b/upb/pb/decoder.c
@@ -95,6 +95,10 @@ typedef struct {
// Maps (upb_handlers* or upb_fielddef*) -> int32 pclabel_base
upb_inttable pclabels;
+ // For marking labels that should go into the generated code.
+ // Maps pclabel -> owned char* label.
+ upb_inttable asmlabels;
+
// This is not the same as len(pclabels) because the table only contains base
// offsets for each def, but each def can have many pclabels.
uint32_t pclabel_count;
@@ -131,7 +135,7 @@ static const upb_decoder_typeinfo upb_decoder_types[] = {
static upb_selector_t getselector(const upb_fielddef *f,
upb_handlertype_t type) {
upb_selector_t selector;
- bool ok = upb_getselector(f, type, &selector);
+ bool ok = upb_handlers_getselector(f, type, &selector);
UPB_ASSERT_VAR(ok, ok);
return selector;
}
@@ -165,11 +169,11 @@ void freeplan(void *_p) {
free(p);
}
-static decoderplan *getdecoderplan(const upb_handlers *h) {
+static const decoderplan *getdecoderplan(const upb_handlers *h) {
if (upb_handlers_frametype(h) != upb_pbdecoder_getframetype())
return NULL;
upb_selector_t sel;
- if (!upb_getselector(UPB_BYTESTREAM_BYTES, UPB_HANDLER_STRING, &sel))
+ if (!upb_handlers_getselector(UPB_BYTESTREAM_BYTES, UPB_HANDLER_STRING, &sel))
return NULL;
return upb_handlers_gethandlerdata(h, sel);
}
@@ -180,7 +184,7 @@ bool upb_pbdecoder_isdecoder(const upb_handlers *h) {
bool upb_pbdecoder_hasjitcode(const upb_handlers *h) {
#ifdef UPB_USE_JIT_X64
- decoderplan *p = getdecoderplan(h);
+ const decoderplan *p = getdecoderplan(h);
if (!p) return false;
return p->jit_code != NULL;
#else
@@ -190,7 +194,7 @@ bool upb_pbdecoder_hasjitcode(const upb_handlers *h) {
}
const upb_handlers *upb_pbdecoder_getdesthandlers(const upb_handlers *h) {
- decoderplan *p = getdecoderplan(h);
+ const decoderplan *p = getdecoderplan(h);
if (!p) return NULL;
return p->dest_handlers;
}
@@ -582,7 +586,7 @@ static const upb_fielddef *decode_tag(upb_pbdecoder *d) {
uint32_t tag = decode_v32(d);
uint8_t wire_type = tag & 0x7;
uint32_t fieldnum = tag >> 3; const upb_fielddef *f = NULL;
- const upb_handlers *h = upb_sinkframe_handlers(upb_sink_top(d->sink));
+ const upb_handlers *h = d->sink->top->h; // TODO(haberman): rm
f = upb_msgdef_itof(upb_handlers_msgdef(h), fieldnum);
bool packed = false;
@@ -645,17 +649,19 @@ static const upb_fielddef *decode_tag(upb_pbdecoder *d) {
}
}
-void *start(const upb_sinkframe *fr, size_t size_hint) {
+void *start(void *closure, const void *handler_data, size_t size_hint) {
+ UPB_UNUSED(handler_data);
UPB_UNUSED(size_hint);
- upb_pbdecoder *d = upb_sinkframe_userdata(fr);
+ upb_pbdecoder *d = closure;
assert(d);
assert(d->sink);
upb_sink_startmsg(d->sink);
return d;
}
-bool end(const upb_sinkframe *fr) {
- upb_pbdecoder *d = upb_sinkframe_userdata(fr);
+bool end(void *closure, const void *handler_data) {
+ UPB_UNUSED(handler_data);
+ upb_pbdecoder *d = closure;
if (d->residual_end > d->residual) {
// We have preserved bytes.
@@ -667,7 +673,6 @@ bool end(const upb_sinkframe *fr) {
if (d->top == d->stack + 1 &&
d->top->is_sequence &&
!d->top->is_packed) {
- assert(upb_sinkframe_depth(upb_sink_top(d->sink)) == 1);
pop_seq(d);
}
if (d->top != d->stack) {
@@ -679,47 +684,47 @@ bool end(const upb_sinkframe *fr) {
return true;
}
-size_t decode(const upb_sinkframe *fr, const char *buf, size_t size) {
- upb_pbdecoder *d = upb_sinkframe_userdata(fr);
- decoderplan *plan = upb_sinkframe_handlerdata(fr);
+size_t decode(void *closure, const void *hd, const char *buf, size_t size) {
+ upb_pbdecoder *d = closure;
+ const decoderplan *plan = hd;
UPB_UNUSED(plan);
- assert(upb_sinkframe_handlers(upb_sink_top(d->sink)) == plan->dest_handlers);
+ assert(d->sink->top->h == plan->dest_handlers);
if (size == 0) return 0;
// Assume we'll consume the whole buffer unless this is overwritten.
d->ret = size;
+ d->buf_param = buf;
+ d->size_param = size;
if (_setjmp(d->exitjmp)) {
// Hit end-of-buffer or error.
return d->ret;
}
- d->buf_param = buf;
- d->size_param = size;
if (d->residual_end > d->residual) {
// We have residual bytes from the last buffer.
- d->userbuf_remaining = size;
+ d->userbuf_remaining = d->size_param;
} else {
d->userbuf_remaining = 0;
- advancetobuf(d, buf, size);
+ advancetobuf(d, buf, d->size_param);
if (d->top != d->stack &&
upb_fielddef_isstring(d->top->f) &&
!d->top->is_sequence) {
// Last buffer ended in the middle of a string; deliver more of it.
size_t len = d->top->end_ofs - offset(d);
- if (size >= len) {
+ if (d->size_param >= len) {
upb_sink_putstring(d->sink, getselector(d->top->f, UPB_HANDLER_STRING),
d->ptr, len);
advance(d, len);
pop_string(d);
} else {
upb_sink_putstring(d->sink, getselector(d->top->f, UPB_HANDLER_STRING),
- d->ptr, size);
- advance(d, size);
+ d->ptr, d->size_param);
+ advance(d, d->size_param);
d->residual_end = d->residual;
advancetobuf(d, d->residual, 0);
- return size;
+ return d->size_param;
}
}
}
@@ -761,7 +766,8 @@ size_t decode(const upb_sinkframe *fr, const char *buf, size_t size) {
}
}
-void init(void *_d) {
+void init(void *_d, upb_pipeline *p) {
+ UPB_UNUSED(p);
upb_pbdecoder *d = _d;
d->limit = &d->stack[UPB_MAX_NESTING];
d->sink = NULL;
diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h
index 4307434..c1b6cb3 100644
--- a/upb/pb/decoder.h
+++ b/upb/pb/decoder.h
@@ -70,10 +70,6 @@ const upb_handlers *upb_pbdecoder_getdesthandlers(const upb_handlers *h);
namespace upb {
-template<> inline const FrameType* GetFrameType<upb::pb::Decoder>() {
- return upb_pbdecoder_getframetype();
-}
-
namespace pb {
inline bool ResetDecoderSink(Decoder* r, Sink* sink) {
return upb_pbdecoder_resetsink(r, sink);
diff --git a/upb/pb/decoder_x64.dasc b/upb/pb/decoder_x64.dasc
index 7d4c537..154fee3 100644
--- a/upb/pb/decoder_x64.dasc
+++ b/upb/pb/decoder_x64.dasc
@@ -12,9 +12,11 @@
|// function) we must respect alignment rules. All x86-64 systems require
|// 16-byte stack alignment.
+#define _GNU_SOURCE
#include <stdio.h>
#include <sys/mman.h>
#include "dynasm/dasm_x86.h"
+#include "upb/shim/shim.h"
#ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS MAP_ANON
@@ -61,7 +63,7 @@ static uint32_t upb_getpclabel(decoderplan *plan, const void *obj, int n) {
return upb_value_getuint32(v) + n;
}
-static upb_jitmsginfo *upb_getmsginfo(decoderplan *plan,
+static upb_jitmsginfo *upb_getmsginfo(const decoderplan *plan,
const upb_handlers *h) {
upb_value v;
bool found = upb_inttable_lookupptr(&plan->msginfo, h, &v);
@@ -161,6 +163,7 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; }
|.define ARG2_64, rsi
|.define ARG3_32, edx
|.define ARG3_64, rdx
+|.define ARG4_32, ecx
|.define ARG4_64, rcx
|.define XMMARG1, xmm0
@@ -193,13 +196,11 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; }
||{
|| uintptr_t data = (uintptr_t)gethandlerdata(h, f, type);
|| if (data > 0xffffffff) {
-| mov64 rax, data
-| mov SINKFRAME->u.handler_data, rax
-|| } else if (data > 0x7fffffff) {
-| mov eax, data
-| mov SINKFRAME->u.handler_data, rax
+| mov64 ARG2_64, data
+|| } else if (data) {
+| mov ARG2_32, data
|| } else {
-| mov qword SINKFRAME->u.handler_data, data
+| xor ARG2_32, ARG2_32
|| }
|| }
|.endmacro
@@ -269,6 +270,8 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; }
|// table on the raw (length-masked) varint to save 3-4 cycles of latency.
|// Currently only support tables where all entries are in the array part.
|.macro dyndispatch_, h
+|| asmlabel(plan, "_UPB_MCODE_DISPATCH_%s.%d",
+|| upb_msgdef_fullname(upb_handlers_msgdef(h)), rand());
|=>upb_getpclabel(plan, h, DYNDISPATCH):
| decode_loaded_varint, 0
| mov ecx, esi
@@ -310,22 +313,21 @@ static void upb_assert_notnull(void *addr) { assert(addr != NULL); (void)addr; }
|
|.macro pushsinkframe, handlers, field, endtype
| mov rax, DECODER->sink
-| mov dword SINKFRAME->u.selector, getselector(field, endtype)
+| mov dword SINKFRAME->selector, getselector(field, endtype)
| lea rcx, [SINKFRAME + sizeof(upb_sinkframe)] // rcx for short addressing
| cmp rcx, SINK:rax->limit
| jae ->exit_jit // Frame stack overflow.
| mov64 r9, (uintptr_t)handlers
| mov SINKFRAME:rcx->h, r9
| mov SINKFRAME:rcx->closure, CLOSURE
-| mov SINK:rax->top_, rcx
-| mov SINKFRAME:rcx->sink_, rax
+| mov SINK:rax->top, rcx
| mov SINKFRAME, rcx
|.endmacro
|
|.macro popsinkframe
| sub SINKFRAME, sizeof(upb_sinkframe)
| mov rax, DECODER->sink
-| mov SINK:rax->top_, SINKFRAME
+| mov SINK:rax->top, SINKFRAME
| mov CLOSURE, SINKFRAME->closure
|.endmacro
|
@@ -415,12 +417,28 @@ static uintptr_t gethandlerdata(const upb_handlers *h, const upb_fielddef *f,
return (uintptr_t)upb_handlers_gethandlerdata(h, getselector(f, type));
}
+static void asmlabel(decoderplan *plan, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ char *str = NULL;
+ size_t size = 0;
+ upb_vrprintf(&str, &size, 0, fmt, ap);
+ va_end(ap);
+ uint32_t label = plan->pclabel_count++;
+ dasm_growpc(plan, plan->pclabel_count);
+ |=>label:
+ upb_inttable_insert(&plan->asmlabels, label, upb_value_ptr(str));
+}
+
// Decodes the next val into ARG2, advances PTR.
static void upb_decoderplan_jit_decodefield(decoderplan *plan,
size_t tag_size,
const upb_handlers *h,
const upb_fielddef *f) {
// Decode the value into arg 3 for the callback.
+ asmlabel(plan, "UPB_MCODE_DECODE_FIELD_%s.%s",
+ upb_msgdef_fullname(upb_handlers_msgdef(h)),
+ upb_fielddef_name(f));
switch (upb_fielddef_descriptortype(f)) {
case UPB_DESCRIPTOR_TYPE_DOUBLE:
| movsd XMMARG1, qword [PTR + tag_size]
@@ -496,39 +514,36 @@ static void upb_decoderplan_jit_decodefield(decoderplan *plan,
upb_func *handler = gethandler(h, f, UPB_HANDLER_STARTSTR);
if (handler) {
+ // void* startstr(void *c, const void *hd, size_t hint)
| mov DECODER->tmp_len, ARG2_32
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
+ | mov ARG3_64, ARG2_64
| load_handler_data h, f, UPB_HANDLER_STARTSTR
| callp handler
| check_ptr_ret
- | mov CLOSURE, rax
- | mov ARG3_32, DECODER->tmp_len
+ | mov ARG1_64, rax // sub-closure
+ | mov ARG4_32, DECODER->tmp_len
} else {
- | mov ARG3_64, ARG2_64
+ | mov ARG1_64, CLOSURE
+ | mov ARG4_64, ARG2_64
}
handler = gethandler(h, f, UPB_HANDLER_STRING);
if (handler) {
- // TODO: push a real frame so we can resume into the string.
- // (but maybe do this only if the string breaks).
- | pushsinkframe h, f, UPB_HANDLER_ENDSTR
-
- // size_t str(const upb_sinkframe *frame, const char *buf, size_t len)
- | mov ARG1_64, SINKFRAME
+ // size_t str(void *c, const void *hd, const char *buf, size_t len)
| load_handler_data h, f, UPB_HANDLER_STRING
- | mov ARG2_64, PTR
+ | mov ARG3_64, PTR
| callp handler
// TODO: properly handle returns other than "n" (the whole string).
| add PTR, rax
- | popsinkframe
} else {
- | add PTR, ARG3_64
+ | add PTR, ARG4_64
}
handler = gethandler(h, f, UPB_HANDLER_ENDSTR);
if (handler) {
// bool endstr(const upb_sinkframe *frame);
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| load_handler_data h, f, UPB_HANDLER_ENDSTR
| callp handler
| check_bool_ret
@@ -553,13 +568,16 @@ static void upb_decoderplan_jit_callcb(decoderplan *plan,
const upb_fielddef *f) {
// Call callbacks. Specializing the append accessors didn't yield a speed
// increase in benchmarks.
+ asmlabel(plan, "UPB_MCODE_CALLCB_%s.%s",
+ upb_msgdef_fullname(upb_handlers_msgdef(h)),
+ upb_fielddef_name(f));
if (upb_fielddef_issubmsg(f)) {
// Call startsubmsg handler (if any).
upb_func *startsubmsg = gethandler(h, f, UPB_HANDLER_STARTSUBMSG);
if (startsubmsg) {
// upb_sflow_t startsubmsg(const upb_sinkframe *frame)
| mov DECODER->tmp_len, ARG2_32
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| load_handler_data h, f, UPB_HANDLER_STARTSUBMSG
| callp startsubmsg
| check_ptr_ret
@@ -594,37 +612,46 @@ static void upb_decoderplan_jit_callcb(decoderplan *plan,
upb_func *endsubmsg = gethandler(h, f, UPB_HANDLER_ENDSUBMSG);
if (endsubmsg) {
// upb_flow_t endsubmsg(void *closure, upb_value fval);
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| load_handler_data h, f, UPB_HANDLER_ENDSUBMSG
| callp endsubmsg
| check_bool_ret
}
} else if (!upb_fielddef_isstring(f)) {
upb_handlertype_t handlertype = upb_handlers_getprimitivehandlertype(f);
+ upb_selector_t sel = getselector(f, handlertype);
upb_func *handler = gethandler(h, f, handlertype);
- const upb_stdmsg_fval *fv = (void*)gethandlerdata(h, f, handlertype);
- // Test for callbacks we can specialize.
- // Can't switch() on function pointers.
- if (handler == (void*)&upb_stdmsg_setint64 ||
- handler == (void*)&upb_stdmsg_setuint64) {
- | mov [CLOSURE + fv->offset], ARG2_64
- | sethas CLOSURE, fv->hasbit
- } else if (handler == (void*)&upb_stdmsg_setdouble) {
- | movsd qword [CLOSURE + fv->offset], XMMARG1
- | sethas CLOSURE, fv->hasbit
- } else if (handler == (void*)&upb_stdmsg_setint32 ||
- handler == (void*)&upb_stdmsg_setuint32) {
- | mov [CLOSURE + fv->offset], ARG2_32
- | sethas CLOSURE, fv->hasbit
- } else if (handler == (void*)&upb_stdmsg_setfloat) {
- | movss dword [CLOSURE + fv->offset], XMMARG1
- | sethas CLOSURE, fv->hasbit
- } else if (handler == (void*)&upb_stdmsg_setbool) {
- | mov [CLOSURE + fv->offset], ARG2_8
- | sethas CLOSURE, fv->hasbit
+ const upb_shim_data *data = upb_shim_getdata(h, sel);
+ if (data) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ | mov [CLOSURE + data->offset], ARG2_64
+ break;
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_ENUM:
+ | mov [CLOSURE + data->offset], ARG2_32
+ break;
+ case UPB_TYPE_DOUBLE:
+ | movsd qword [CLOSURE + data->offset], XMMARG1
+ break;
+ case UPB_TYPE_FLOAT:
+ | movss dword [CLOSURE + data->offset], XMMARG1
+ break;
+ case UPB_TYPE_BOOL:
+ | mov [CLOSURE + data->offset], ARG2_8
+ break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ assert(false); break;
+ }
+ | sethas CLOSURE, data->hasbit
} else if (handler) {
// bool value(const upb_sinkframe* frame, ctype val)
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
+ | mov ARG3_64, ARG2_64
| load_handler_data h, f, handlertype
| callp handler
| check_bool_ret
@@ -647,7 +674,7 @@ static void upb_decoderplan_jit_endseq(decoderplan *plan,
| popframe
upb_func *endseq = gethandler(h, f, UPB_HANDLER_ENDSEQ);
if (endseq) {
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| load_handler_data h, f, UPB_HANDLER_ENDSEQ
| callp endseq
}
@@ -658,6 +685,9 @@ static void upb_decoderplan_jit_field(decoderplan *plan,
const upb_handlers *h,
const upb_fielddef *f,
const upb_fielddef *next_f) {
+ asmlabel(plan, "UPB_MCODE_FIELD_%s.%s",
+ upb_msgdef_fullname(upb_handlers_msgdef(h)),
+ upb_fielddef_name(f));
uint64_t tag = upb_get_encoded_tag(f);
uint64_t next_tag = next_f ? upb_get_encoded_tag(next_f) : 0;
int tag_size = upb_value_size(tag);
@@ -672,7 +702,7 @@ static void upb_decoderplan_jit_field(decoderplan *plan,
if (upb_fielddef_isseq(f)) {
upb_func *startseq = gethandler(h, f, UPB_HANDLER_STARTSEQ);
if (startseq) {
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| load_handler_data h, f, UPB_HANDLER_STARTSEQ
| callp startseq
| check_ptr_ret
@@ -726,6 +756,8 @@ static int upb_compare_uint32(const void *a, const void *b) {
static void upb_decoderplan_jit_msg(decoderplan *plan,
const upb_handlers *h) {
+ asmlabel(plan, "UPB_MCODE_DECODEMSG_%s",
+ upb_msgdef_fullname(upb_handlers_msgdef(h)));
|=>upb_getpclabel(plan, h, AFTER_STARTMSG):
| push rbp
| mov rbp, rsp
@@ -739,7 +771,7 @@ static void upb_decoderplan_jit_msg(decoderplan *plan,
upb_startmsg_handler *startmsg = upb_handlers_getstartmsg(h);
if (startmsg) {
// upb_flow_t startmsg(void *closure);
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| callp startmsg
| check_bool_ret
}
@@ -792,7 +824,7 @@ static void upb_decoderplan_jit_msg(decoderplan *plan,
upb_endmsg_handler *endmsg = upb_handlers_getendmsg(h);
if (endmsg) {
// void endmsg(void *closure, upb_status *status) {
- | mov ARG1_64, SINKFRAME
+ | mov ARG1_64, CLOSURE
| mov ARG2_64, DECODER->sink
| mov ARG2_64, SINK:ARG2_64->pipeline_
| add ARG2_64, offsetof(upb_pipeline, status_)
@@ -815,6 +847,7 @@ static void upb_decoderplan_jit(decoderplan *plan) {
// calculate the structure offsets ourself instead of symbolically
// (ie. [r15 + 0xcd] instead of DECODER->ptr). So we tolerate a bit of
// unnecessary duplication/redundancy.
+ asmlabel(plan, "upb_jit_trampoline");
| push rbp
| mov rbp, rsp
| push r15
@@ -828,13 +861,14 @@ static void upb_decoderplan_jit(decoderplan *plan) {
| mov DECODER->saved_rbp, rbp
| mov FRAME, DECODER:ARG1_64->top
| mov rax, DECODER:ARG1_64->sink
- | mov SINKFRAME, SINK:rax->top_
+ | mov SINKFRAME, SINK:rax->top
| mov CLOSURE, SINKFRAME->closure
| mov PTR, DECODER->ptr
// TODO: push return addresses for re-entry (will be necessary for multiple
// buffer support).
| call ARG2_64
+ asmlabel(plan, "exitjit");
|->exit_jit:
| mov rbp, DECODER->saved_rbp
| lea rsp, [rbp - 48]
@@ -903,6 +937,8 @@ static void upb_decoderplan_makejit(decoderplan *plan) {
upb_inttable_init(&plan->pclabels, UPB_CTYPE_UINT32);
upb_decoderplan_jit_assignpclabels(plan, plan->dest_handlers);
+ upb_inttable_init(&plan->asmlabels, UPB_CTYPE_PTR);
+
void **globals = malloc(UPB_JIT_GLOBAL__MAX * sizeof(*globals));
dasm_init(plan, 1);
dasm_setupglobal(plan, globals, UPB_JIT_GLOBAL__MAX);
@@ -947,18 +983,57 @@ static void upb_decoderplan_makejit(decoderplan *plan) {
upb_inttable_uninit(&plan->pclabels);
- dasm_free(plan);
- free(globals);
-
mprotect(plan->jit_code, plan->jit_size, PROT_EXEC | PROT_READ);
#ifndef NDEBUG
- // View with: objdump -M intel -D -b binary -mi386 -Mx86-64 /tmp/machine-code
- // Or: ndisasm -b 64 /tmp/machine-code
- FILE *f = fopen("/tmp/machine-code", "wb");
- fwrite(plan->jit_code, plan->jit_size, 1, f);
- fclose(f);
+ // Dump to a .o file in /tmp, for easy inspection.
+
+ // Convert all asm labels from pclabel offsets to machine code offsets.
+ upb_inttable mclabels;
+ upb_inttable_init(&mclabels, UPB_CTYPE_PTR);
+ upb_inttable_begin(&i, &plan->asmlabels);
+ for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ upb_inttable_insert(
+ &mclabels,
+ dasm_getpclabel(plan, upb_inttable_iter_key(&i)),
+ upb_inttable_iter_value(&i));
+ }
+
+ FILE *f = fopen("/tmp/upb-jit-code.s", "w");
+ if (f) {
+ fputs(" .text", f);
+ size_t linelen = 0;
+ for (size_t i = 0; i < plan->jit_size; i++) {
+ upb_value v;
+ if (upb_inttable_lookup(&mclabels, i, &v)) {
+ const char *label = upb_value_getptr(v);
+ fprintf(f, "\n\n_%s:\n", label);
+ fprintf(f, " .globl _%s", label);
+ linelen = 1000;
+ }
+ if (linelen >= 77) {
+ linelen = fprintf(f, "\n .byte %u", plan->jit_code[i]);
+ } else {
+ linelen += fprintf(f, ",%u", plan->jit_code[i]);
+ }
+ }
+ fputs("\n", f);
+ fclose(f);
+ } else {
+ fprintf(stderr, "Couldn't open /tmp/upb-jit-code.s for writing/\n");
+ }
+
+ upb_inttable_uninit(&mclabels);
#endif
+
+ upb_inttable_begin(&i, &plan->asmlabels);
+ for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ free(upb_value_getptr(upb_inttable_iter_value(&i)));
+ }
+ upb_inttable_uninit(&plan->asmlabels);
+
+ dasm_free(plan);
+ free(globals);
}
static void upb_decoderplan_freejit(decoderplan *plan) {
@@ -975,10 +1050,10 @@ static void upb_decoderplan_freejit(decoderplan *plan) {
// TODO: unregister
}
-static void upb_decoder_enterjit(upb_pbdecoder *d, decoderplan *plan) {
+static void upb_decoder_enterjit(upb_pbdecoder *d, const decoderplan *plan) {
if (plan->jit_code &&
d->top == d->stack &&
- d->sink->top_ == d->sink->stack &&
+ d->sink->top == d->sink->stack &&
d->ptr && d->ptr < d->jit_end) {
#ifndef NDEBUG
register uint64_t rbx asm ("rbx") = 11;
diff --git a/upb/pb/glue.c b/upb/pb/glue.c
index bcde039..2c621f4 100644
--- a/upb/pb/glue.c
+++ b/upb/pb/glue.c
@@ -30,7 +30,7 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
// Create sinks.
upb_sink *reader_sink = upb_pipeline_newsink(&pipeline, reader_h);
upb_sink *decoder_sink = upb_pipeline_newsink(&pipeline, decoder_h);
- upb_pbdecoder *d = upb_sinkframe_userdata(upb_sink_base(decoder_sink));
+ upb_pbdecoder *d = upb_sink_getobj(decoder_sink);
upb_pbdecoder_resetsink(d, reader_sink);
// Push input data.
@@ -42,7 +42,7 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
return NULL;
}
- upb_descreader *r = upb_sinkframe_userdata(upb_sink_base(reader_sink));
+ upb_descreader *r = upb_sink_getobj(reader_sink);
upb_def **defs = upb_descreader_getdefs(r, owner, n);
upb_def **defscopy = malloc(sizeof(upb_def*) * (*n));
memcpy(defscopy, defs, sizeof(upb_def*) * (*n));
diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c
index 91c1e2d..08eda15 100644
--- a/upb/pb/textprinter.c
+++ b/upb/pb/textprinter.c
@@ -38,8 +38,7 @@ static int endfield(upb_textprinter *p) {
return 0;
}
-static int putescaped(upb_textprinter *p, const char *buf, size_t len,
- bool preserve_utf8) {
+static int putescaped(const char* buf, size_t len, bool preserve_utf8) {
// Based on CEscapeInternal() from Google's protobuf release.
char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
const char *end = buf + len;
@@ -84,9 +83,9 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len,
}
#define TYPE(name, ctype, fmt) \
- static bool put ## name(const upb_sinkframe *frame, ctype val) { \
- upb_textprinter *p = upb_sinkframe_userdata(frame); \
- const upb_fielddef *f = upb_sinkframe_handlerdata(frame); \
+ static bool put ## name(void *closure, const void *handler_data, ctype val) {\
+ upb_textprinter *p = closure; \
+ const upb_fielddef *f = handler_data; \
CHECK(indent(p)); \
puts(upb_fielddef_name(f)); \
puts(": "); \
@@ -97,9 +96,9 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len,
return false; \
}
-static bool putbool(const upb_sinkframe *frame, bool val) {
- upb_textprinter *p = upb_sinkframe_userdata(frame);
- const upb_fielddef *f = upb_sinkframe_handlerdata(frame);
+static bool putbool(void *closure, const void *handler_data, bool val) {
+ upb_textprinter *p = closure;
+ const upb_fielddef *f = handler_data;
CHECK(indent(p));
puts(upb_fielddef_name(f));
puts(": ");
@@ -121,44 +120,49 @@ TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
// Output a symbolic value from the enum if found, else just print as int32.
-static bool putenum(const upb_sinkframe *frame, int32_t val) {
- const upb_fielddef *f = upb_sinkframe_handlerdata(frame);
+static bool putenum(void *closure, const void *handler_data, int32_t val) {
+ const upb_fielddef *f = handler_data;
const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f));
const char *label = upb_enumdef_iton(enum_def, val);
if (label) {
puts(label);
} else {
- CHECK(putint32(frame, val));
+ CHECK(putint32(closure, handler_data, val));
}
return true;
err:
return false;
}
-static void *startstr(const upb_sinkframe *frame, size_t size_hint) {
+static void *startstr(void *closure, const void *handler_data,
+ size_t size_hint) {
+ UPB_UNUSED(handler_data);
UPB_UNUSED(size_hint);
- upb_textprinter *p = upb_sinkframe_userdata(frame);
+ upb_textprinter *p = closure;
putchar('"');
return p;
}
-static bool endstr(const upb_sinkframe *frame) {
+static bool endstr(void *closure, const void *handler_data) {
+ UPB_UNUSED(closure);
+ UPB_UNUSED(handler_data);
putchar('"');
return true;
}
-static size_t putstr(const upb_sinkframe *frame, const char *buf, size_t len) {
- upb_textprinter *p = upb_sinkframe_userdata(frame);
- const upb_fielddef *f = upb_sinkframe_handlerdata(frame);
- CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
+static size_t putstr(void *closure, const void *hd, const char *buf,
+ size_t len) {
+ UPB_UNUSED(closure);
+ const upb_fielddef *f = hd;
+ CHECK(putescaped(buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
return len;
err:
return 0;
}
-static void *startsubmsg(const upb_sinkframe *frame) {
- upb_textprinter *p = upb_sinkframe_userdata(frame);
- const upb_fielddef *f = upb_sinkframe_handlerdata(frame);
+static void *startsubmsg(void *closure, const void *handler_data) {
+ upb_textprinter *p = closure;
+ const upb_fielddef *f = handler_data;
CHECK(indent(p));
printf("%s {", upb_fielddef_name(f));
if (!p->single_line)
@@ -169,8 +173,9 @@ err:
return UPB_BREAK;
}
-static bool endsubmsg(const upb_sinkframe *frame) {
- upb_textprinter *p = upb_sinkframe_userdata(frame);
+static bool endsubmsg(void *closure, const void *handler_data) {
+ UPB_UNUSED(handler_data);
+ upb_textprinter *p = closure;
p->indent_depth--;
CHECK(indent(p));
putchar('}');
diff --git a/upb/shim/shim.c b/upb/shim/shim.c
new file mode 100644
index 0000000..6a79ac0
--- /dev/null
+++ b/upb/shim/shim.c
@@ -0,0 +1,69 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2013 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ */
+
+#include "upb/shim/shim.h"
+
+#include <stdlib.h>
+
+// Fallback implementation if the shim is not specialized by the JIT.
+#define SHIM_WRITER(type, ctype) \
+ bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \
+ uint8_t *m = c; \
+ const upb_shim_data *d = hd; \
+ if (d->hasbit > 0) \
+ *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \
+ *(ctype*)&m[d->offset] = val; \
+ return true; \
+ } \
+
+SHIM_WRITER(double, double)
+SHIM_WRITER(float, float)
+SHIM_WRITER(int32, int32_t)
+SHIM_WRITER(int64, int64_t)
+SHIM_WRITER(uint32, uint32_t)
+SHIM_WRITER(uint64, uint64_t)
+SHIM_WRITER(bool, bool)
+#undef SHIM_WRITER
+
+bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
+ int32_t hasbit) {
+ upb_shim_data *d = malloc(sizeof(*d));
+ if (!d) return false;
+ d->offset = offset;
+ d->hasbit = hasbit;
+
+#define TYPE(u, l) \
+ case UPB_TYPE_##u: return upb_handlers_set##l(h, f, upb_shim_set##l, d, free)
+
+ switch (upb_fielddef_type(f)) {
+ TYPE(INT64, int64);
+ TYPE(INT32, int32);
+ TYPE(ENUM, int32);
+ TYPE(UINT64, uint64);
+ TYPE(UINT32, uint32);
+ TYPE(DOUBLE, double);
+ TYPE(FLOAT, float);
+ TYPE(BOOL, bool);
+ default: assert(false); return false;
+ }
+#undef TYPE
+}
+
+const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s) {
+ upb_func *f = upb_handlers_gethandler(h, s);
+ if ((upb_int64_handler*)f == upb_shim_setint64 ||
+ (upb_int32_handler*)f == upb_shim_setint32 ||
+ (upb_uint64_handler*)f == upb_shim_setuint64 ||
+ (upb_uint32_handler*)f == upb_shim_setuint32 ||
+ (upb_double_handler*)f == upb_shim_setdouble ||
+ (upb_float_handler*)f == upb_shim_setfloat ||
+ (upb_bool_handler*)f == upb_shim_setbool) {
+ return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
+ } else {
+ return NULL;
+ }
+}
diff --git a/upb/shim/shim.h b/upb/shim/shim.h
new file mode 100644
index 0000000..98310d7
--- /dev/null
+++ b/upb/shim/shim.h
@@ -0,0 +1,74 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2013 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * For handlers that do very tiny, very simple operations, the function call
+ * overhead of calling a handler can be significant. This file allows the
+ * user to define handlers that do something very simple like store the value
+ * to memory and/or set a hasbit. JIT compilers can then special-case these
+ * handlers and emit specialized code for them instead of actually calling the
+ * handler.
+ *
+ * The functionality is very simple/limited right now but may expand to be able
+ * to call another function.
+ */
+
+#ifndef UPB_SHIM_H
+#define UPB_SHIM_H
+
+#include "upb/handlers.h"
+
+typedef struct {
+ size_t offset;
+ int32_t hasbit;
+} upb_shim_data;
+
+#ifdef __cplusplus
+
+namespace upb {
+
+struct Shim {
+ typedef upb_shim_data Data;
+
+ // Sets a handler for the given field that writes the value to the given
+ // offset and, if hasbit >= 0, sets a bit at the given bit offset. Returns
+ // true if the handler was set successfully.
+ static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit);
+
+ // If this handler is a shim, returns the corresponding upb::Shim::Data.
+ // Otherwise returns NULL.
+ static const Data* GetData(const Handlers* h, Handlers::Selector s);
+};
+
+} // namespace upb
+
+extern "C" {
+#endif
+
+// C API.
+bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
+ int32_t hasbit);
+const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s);
+
+#ifdef __cplusplus
+} // extern "C"
+
+namespace upb {
+
+// C++ Wrappers.
+inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs,
+ int32_t hasbit) {
+ return upb_shim_set(h, f, ofs, hasbit);
+}
+inline const Shim::Data* Shim::GetData(const Handlers* h,
+ Handlers::Selector s) {
+ return upb_shim_getdata(h, s);
+}
+
+} // namespace
+
+#endif
+
+#endif // UPB_SHIM_H
diff --git a/upb/sink.c b/upb/sink.c
index f3af23d..0ffb63a 100644
--- a/upb/sink.c
+++ b/upb/sink.c
@@ -15,7 +15,7 @@ static void upb_sink_resetobj(void *obj);
static const upb_frametype upb_sink_frametype;
static bool chkstack(upb_sink *s) {
- if (s->top_ + 1 >= s->limit) {
+ if (s->top + 1 >= s->limit) {
upb_status_seterrliteral(&s->pipeline_->status_, "Nesting too deep.");
return false;
} else {
@@ -134,7 +134,7 @@ void *upb_pipeline_allocobj(upb_pipeline *p, const upb_frametype *ft) {
obj->prev = p->obj_head;
obj->ft = ft;
p->obj_head = obj;
- if (ft->init) ft->init(&obj->data);
+ if (ft->init) ft->init(&obj->data, p);
return &obj->data;
}
@@ -180,21 +180,6 @@ void upb_pipeline_donateref(
}
-/* upb_sinkframe **************************************************************/
-
-int upb_sinkframe_depth(const upb_sinkframe* frame) {
- return frame - frame->sink_->stack;
-}
-
-const upb_handlers* upb_sinkframe_handlers(const upb_sinkframe* frame) {
- return frame->h;
-}
-
-upb_pipeline *upb_sinkframe_pipeline(const upb_sinkframe* frame) {
- return frame->sink_->pipeline_;
-}
-
-
/* upb_sink *******************************************************************/
static const upb_frametype upb_sink_frametype = {
@@ -205,82 +190,79 @@ static const upb_frametype upb_sink_frametype = {
};
void upb_sink_reset(upb_sink *s, void *closure) {
- s->top_ = s->stack;
- s->top_->closure = closure;
+ s->top = s->stack;
+ s->top->closure = closure;
}
static void upb_sink_resetobj(void *obj) {
upb_sink *s = obj;
- s->top_ = s->stack;
+ s->top = s->stack;
}
static void upb_sink_init(upb_sink *s, const upb_handlers *h, upb_pipeline *p) {
s->pipeline_ = p;
- s->limit = &s->stack[UPB_MAX_NESTING];
- s->stack[0].h = h;
- s->top_ = s->stack;
+ s->stack = upb_pipeline_alloc(p, sizeof(*s->stack) * UPB_MAX_NESTING);
+ s->top = s->stack;
+ s->limit = s->stack + UPB_MAX_NESTING;
+ s->top->h = h;
if (h->ft) {
- s->stack[0].closure = upb_pipeline_allocobj(p, h->ft);
+ s->top->closure = upb_pipeline_allocobj(p, h->ft);
}
}
-const upb_sinkframe *upb_sink_top(const upb_sink *s) {
- return s->top_;
-}
-
-const upb_sinkframe *upb_sink_base(const upb_sink *s) {
- return s->stack;
-}
-
upb_pipeline *upb_sink_pipeline(const upb_sink *s) {
return s->pipeline_;
}
+void *upb_sink_getobj(const upb_sink *s) {
+ return s->stack[0].closure;
+}
+
bool upb_sink_startmsg(upb_sink *s) {
- const upb_handlers *h = s->top_->h;
+ const upb_handlers *h = s->top->h;
upb_startmsg_handler *startmsg = upb_handlers_getstartmsg(h);
- return startmsg ? startmsg(s->top_) : true;
+ return startmsg ? startmsg(s->top->closure) : true;
}
void upb_sink_endmsg(upb_sink *s) {
- assert(s->top_ == s->stack);
- upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top_->h);
+ assert(s->top == s->stack);
+ upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top->h);
if (endmsg) {
- endmsg(s->top_, &s->pipeline_->status_);
+ endmsg(s->top->closure, &s->pipeline_->status_);
}
}
-#define PUTVAL(type, ctype, htype) \
+#define PUTVAL(type, ctype) \
bool upb_sink_put ## type(upb_sink *s, upb_selector_t sel, ctype val) { \
- const upb_handlers *h = s->top_->h; \
+ const upb_handlers *h = s->top->h; \
upb_ ## type ## _handler *handler = (upb_ ## type ## _handler*) \
upb_handlers_gethandler(h, sel); \
if (handler) { \
- s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel); \
- bool ok = handler(s->top_, val); \
+ const void *hd = upb_handlers_gethandlerdata(h, sel); \
+ bool ok = handler(s->top->closure, hd, val); \
if (!ok) return false; \
} \
return true; \
}
-PUTVAL(int32, int32_t, INT32);
-PUTVAL(int64, int64_t, INT64);
-PUTVAL(uint32, uint32_t, UINT32);
-PUTVAL(uint64, uint64_t, UINT64);
-PUTVAL(float, float, FLOAT);
-PUTVAL(double, double, DOUBLE);
-PUTVAL(bool, bool, BOOL);
+PUTVAL(int32, int32_t);
+PUTVAL(int64, int64_t);
+PUTVAL(uint32, uint32_t);
+PUTVAL(uint64, uint64_t);
+PUTVAL(float, float);
+PUTVAL(double, double);
+PUTVAL(bool, bool);
#undef PUTVAL
size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel,
const char *buf, size_t n) {
- const upb_handlers *h = s->top_->h;
+ const upb_handlers *h = s->top->h;
upb_string_handler *handler =
(upb_string_handler*)upb_handlers_gethandler(h, sel);
if (handler) {
- s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel);;
- n = handler(s->top_, buf, n);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);;
+ n = handler(s->top->closure, hd, buf, n);
}
return n;
@@ -289,39 +271,39 @@ size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel,
bool upb_sink_startseq(upb_sink *s, upb_selector_t sel) {
if (!chkstack(s)) return false;
- void *subc = s->top_->closure;
- const upb_handlers *h = s->top_->h;
+ void *subc = s->top->closure;
+ const upb_handlers *h = s->top->h;
upb_startfield_handler *startseq =
(upb_startfield_handler*)upb_handlers_gethandler(h, sel);
if (startseq) {
- s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel);
- subc = startseq(s->top_);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);
+ subc = startseq(s->top->closure, hd);
if (subc == UPB_BREAK) {
return false;
}
}
- s->top_->u.selector = upb_getendselector(sel);
- ++s->top_;
- s->top_->h = h;
- s->top_->closure = subc;
- s->top_->sink_ = s;
+ s->top->selector = upb_handlers_getendselector(sel);
+ ++s->top;
+ s->top->h = h;
+ s->top->closure = subc;
return true;
}
bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) {
- --s->top_;
- assert(sel == s->top_->u.selector);
+ --s->top;
+ assert(sel == s->top->selector);
- const upb_handlers *h = s->top_->h;
+ const upb_handlers *h = s->top->h;
upb_endfield_handler *endseq =
(upb_endfield_handler*)upb_handlers_gethandler(h, sel);
if (endseq) {
- bool ok = endseq(s->top_);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);
+ bool ok = endseq(s->top->closure, hd);
if (!ok) {
- ++s->top_;
+ ++s->top;
return false;
}
}
@@ -332,38 +314,38 @@ bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) {
bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, size_t size_hint) {
if (!chkstack(s)) return false;
- void *subc = s->top_->closure;
- const upb_handlers *h = s->top_->h;
+ void *subc = s->top->closure;
+ const upb_handlers *h = s->top->h;
upb_startstr_handler *startstr =
(upb_startstr_handler*)upb_handlers_gethandler(h, sel);
if (startstr) {
- s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel);
- subc = startstr(s->top_, size_hint);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);
+ subc = startstr(s->top->closure, hd, size_hint);
if (subc == UPB_BREAK) {
return false;
}
}
- s->top_->u.selector = upb_getendselector(sel);
- ++s->top_;
- s->top_->h = h;
- s->top_->closure = subc;
- s->top_->sink_ = s;
+ s->top->selector = upb_handlers_getendselector(sel);
+ ++s->top;
+ s->top->h = h;
+ s->top->closure = subc;
return true;
}
bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) {
- --s->top_;
- assert(sel == s->top_->u.selector);
- const upb_handlers *h = s->top_->h;
+ --s->top;
+ assert(sel == s->top->selector);
+ const upb_handlers *h = s->top->h;
upb_endfield_handler *endstr =
(upb_endfield_handler*)upb_handlers_gethandler(h, sel);
if (endstr) {
- bool ok = endstr(s->top_);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);
+ bool ok = endstr(s->top->closure, hd);
if (!ok) {
- ++s->top_;
+ ++s->top;
return false;
}
}
@@ -374,44 +356,47 @@ bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) {
bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel) {
if (!chkstack(s)) return false;
- void *subc = s->top_->closure;
- const upb_handlers *h = s->top_->h;
+ void *subc = s->top->closure;
+ const upb_handlers *h = s->top->h;
upb_startfield_handler *startsubmsg =
(upb_startfield_handler*)upb_handlers_gethandler(h, sel);
if (startsubmsg) {
- s->top_->u.handler_data = upb_handlers_gethandlerdata(h, sel);
- subc = startsubmsg(s->top_);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);
+ subc = startsubmsg(s->top->closure, hd);
if (subc == UPB_BREAK) {
return false;
}
}
- s->top_->u.selector= upb_getendselector(sel);
- ++s->top_;
- s->top_->h = upb_handlers_getsubhandlers_sel(h, sel);
+ s->top->selector= upb_handlers_getendselector(sel);
+ ++s->top;
+ s->top->h = upb_handlers_getsubhandlers_sel(h, sel);
// TODO: should add support for submessages without any handlers
- assert(s->top_->h);
- s->top_->closure = subc;
- s->top_->sink_ = s;
+ assert(s->top->h);
+ s->top->closure = subc;
upb_sink_startmsg(s);
return true;
}
bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
- upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top_->h);
- if (endmsg) endmsg(s->top_, &s->pipeline_->status_);
- --s->top_;
+ upb_endmsg_handler *endmsg = upb_handlers_getendmsg(s->top->h);
+ if (endmsg) {
+ // TODO(haberman): check return value.
+ endmsg(s->top->closure, &s->pipeline_->status_);
+ }
+ --s->top;
- assert(sel == s->top_->u.selector);
- const upb_handlers *h = s->top_->h;
+ assert(sel == s->top->selector);
+ const upb_handlers *h = s->top->h;
upb_endfield_handler *endsubmsg =
(upb_endfield_handler*)upb_handlers_gethandler(h, sel);
if (endsubmsg) {
- bool ok = endsubmsg(s->top_);
+ const void *hd = upb_handlers_gethandlerdata(h, sel);
+ bool ok = endsubmsg(s->top->closure, hd);
if (!ok) {
- ++s->top_;
+ ++s->top;
return false;
}
}
@@ -420,5 +405,5 @@ bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
}
const upb_handlers *upb_sink_tophandlers(upb_sink *s) {
- return s->top_->h;
+ return s->top->h;
}
diff --git a/upb/sink.h b/upb/sink.h
index 333575f..dcc2b4f 100644
--- a/upb/sink.h
+++ b/upb/sink.h
@@ -30,22 +30,13 @@ template <int size> class SeededPipeline;
}
typedef upb::Pipeline upb_pipeline;
typedef upb::Sink upb_sink;
-UPB_INLINE upb_sink* upb_sinkframe_sink(const upb_sinkframe* frame);
-UPB_INLINE void* upb_sinkframe_userdata(const upb_sinkframe* frame);
-UPB_INLINE void* upb_sinkframe_handlerdata(const upb_sinkframe* frame);
#else
struct upb_pipeline;
struct upb_sink;
typedef struct upb_pipeline upb_pipeline;
typedef struct upb_sink upb_sink;
#endif
-
-struct upb_frametype {
- size_t size;
- void (*init)(void* obj);
- void (*uninit)(void* obj);
- void (*reset)(void* obj);
-};
+struct upb_sinkframe;
#ifdef __cplusplus
@@ -122,6 +113,13 @@ struct upb_pipeline {
upb_status status_;
};
+struct upb_frametype {
+ size_t size;
+ void (*init)(void* obj, upb_pipeline *p);
+ void (*uninit)(void* obj);
+ void (*reset)(void* obj);
+};
+
#ifdef __cplusplus
// For convenience, a template for a pipeline with an array of initial memory.
@@ -136,84 +134,6 @@ class upb::SeededPipeline : public upb::Pipeline {
char mem_[initial_size];
};
-class upb::SinkFrame {
- public:
- // Returns the sink that this frame belongs to.
- Sink* sink() const;
-
- // Returns the pipeline that this sink and frame belong to.
- Pipeline* pipeline() const;
-
- // The depth of this frame (counts all kind of frames (sequence, submessage,
- // and string frames).
- int depth() const;
-
- // The Handlers object for this frame.
- const Handlers* handlers() const;
-
- // Returns the user data that is bound to this sink frame (as returned
- // by the Start{SubMessage,String,Sequence} handler, or passed to
- // Sink::Reset()).
- void* userdata() const;
-
- // A templated version of userdata() that type-checks the templated return
- // type.
- //
- // TODO(haberman): this isn't truly robust until sequence and string frames
- // have distinct FrameTypes in the Handlers.
- template<class T>
- T* GetUserdata() const {
-#ifdef NDEBUG
- return static_cast<T*>(userdata());
-#else
- const FrameType* type = handlers()->frame_type();
- if (!type || type == GetFrameType<T>()) {
- return static_cast<T*>(userdata());
- } else {
- assert(false);
- return NULL;
- }
-#endif
- }
-
- // Returns the data that was bound to the currently-executing callback in the
- // Handlers object. If not currently in a handler, the results are undefined.
- void* handler_data() const;
-
- private:
- UPB_DISALLOW_POD_OPS(SinkFrame);
- friend class upb::Sink;
- friend upb_sink* ::upb_sinkframe_sink(const upb_sinkframe* frame);
- friend void* ::upb_sinkframe_userdata(const upb_sinkframe* frame);
- friend void* ::upb_sinkframe_handlerdata(const upb_sinkframe* frame);
-
-#else
-struct upb_sinkframe {
-#endif
- upb_sink *sink_;
- const upb_handlers *h;
- void *closure;
-
- union {
- // For the top frame (sink->top), the handler_data for the
- // currently-executing callback, otherwise undefined.
- // TODO(haberman): have a special pointer value to indicate "not in a
- // callback"; this will be a way to enforce non-reentrancy of a sink.
- void *handler_data;
-
- // For other frames, the END* callback that will run when the subframe is
- // popped (for example, for a "sequence" frame the frame above it will be a
- // UPB_HANDLER_ENDSEQ handler). But this is only necessary for assertion
- // checking inside upb_sink and can be omitted if the sink has only one
- // caller.
- // TODO(haberman): have a mechanism for ensuring that a sink only has one
- // caller.
- upb_selector_t selector;
- } u;
-};
-
-#ifdef __cplusplus
-
// A upb::Sink is an object that binds a upb::Handlers object to some runtime
// state. It is the object that can actually call a set of handlers.
//
@@ -234,13 +154,12 @@ class upb::Sink {
// used as the top-level closure.
void Reset(void *closure);
- // Returns the top-most and base (lowest) frame of the stack, respectively.
- const SinkFrame* top() const;
- const SinkFrame* base() const;
-
// Returns the pipeline that this sink comes from.
Pipeline* pipeline() const;
+ // Returns the top-level object that is bound to this sink.
+ template <class T> T* GetObject() const;
+
// Functions for pushing data into the sink.
//
// These return false if processing should stop (either due to error or just
@@ -285,23 +204,9 @@ class upb::Sink {
struct upb_sink {
#endif
upb_pipeline *pipeline_;
- upb_sinkframe *top_, *limit;
- upb_sinkframe stack[UPB_MAX_NESTING];
+ struct upb_sinkframe *top, *limit, *stack;
};
-// C API.
-UPB_INLINE upb_sink *upb_sinkframe_sink(const upb_sinkframe* frame) {
- return frame->sink_;
-}
-
-UPB_INLINE void *upb_sinkframe_userdata(const upb_sinkframe* frame) {
- return frame->closure;
-}
-
-UPB_INLINE void *upb_sinkframe_handlerdata(const upb_sinkframe* frame) {
- return frame->u.handler_data;
-}
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -321,14 +226,9 @@ void upb_pipeline_donateref(
upb_sink *upb_pipeline_newsink(upb_pipeline *p, const upb_handlers *h);
const upb_status *upb_pipeline_status(const upb_pipeline *p);
-int upb_sinkframe_depth(const upb_sinkframe* frame);
-const upb_handlers* upb_sinkframe_handlers(const upb_sinkframe* frame);
-upb_pipeline* upb_sinkframe_pipeline(const upb_sinkframe* frame);
-
void upb_sink_reset(upb_sink *s, void *closure);
upb_pipeline *upb_sink_pipeline(const upb_sink *s);
-const upb_sinkframe *upb_sink_top(const upb_sink *s);
-const upb_sinkframe *upb_sink_base(const upb_sink *s);
+void *upb_sink_getobj(const upb_sink *s);
bool upb_sink_startmsg(upb_sink *s);
void upb_sink_endmsg(upb_sink *s);
bool upb_sink_putint32(upb_sink *s, upb_selector_t sel, int32_t val);
@@ -386,36 +286,15 @@ inline void Pipeline::DonateRef(const upb::Handlers* h, const void *owner) {
return upb_pipeline_donateref(this, h, owner);
}
-inline Sink* SinkFrame::sink() const {
- return upb_sinkframe_sink(this);
-}
-inline Pipeline* SinkFrame::pipeline() const {
- return upb_sinkframe_pipeline(this);
-}
-inline void* SinkFrame::userdata() const {
- return upb_sinkframe_userdata(this);
-}
-inline void* SinkFrame::handler_data() const {
- return upb_sinkframe_handlerdata(this);
-}
-inline int SinkFrame::depth() const {
- return upb_sinkframe_depth(this);
-}
-inline const Handlers* SinkFrame::handlers() const {
- return upb_sinkframe_handlers(this);
-}
-
inline void Sink::Reset(void *closure) {
upb_sink_reset(this, closure);
}
inline Pipeline* Sink::pipeline() const {
return upb_sink_pipeline(this);
}
-inline const SinkFrame* Sink::top() const {
- return upb_sink_top(this);
-}
-inline const SinkFrame* Sink::base() const {
- return upb_sink_base(this);
+template <class T>
+inline T* Sink::GetObject() const {
+ return static_cast<T*>(upb_sink_getobj(this));
}
inline bool Sink::StartMessage() {
return upb_sink_startmsg(this);
@@ -470,4 +349,23 @@ inline bool Sink::EndSequence(Handlers::Selector sel) {
} // namespace upb
#endif
+// TODO(haberman): move this to sink.c. We keep it here now only because the
+// JIT needs to modify it directly, which it only needs to do because it makes
+// the interpreter handle fallback cases. When the JIT is self-sufficient, it
+// will no longer need to touch the sink's stack at all.
+struct upb_sinkframe {
+ const upb_handlers *h;
+ void *closure;
+
+ // For any frames besides the top, this is the END* callback that will run
+ // when the subframe is popped (for example, for a "sequence" frame the frame
+ // above it will be a UPB_HANDLER_ENDSEQ handler). But this is only
+ // necessary for assertion checking inside upb_sink and can be omitted if the
+ // sink has only one caller.
+ //
+ // TODO(haberman): have a mechanism for ensuring that a sink only has one
+ // caller.
+ upb_selector_t selector;
+};
+
#endif
diff --git a/upb/table.h b/upb/table.h
index 2b4c80c..f96dee9 100644
--- a/upb/table.h
+++ b/upb/table.h
@@ -164,6 +164,7 @@ void upb_inttable_compact(upb_inttable *t);
// A special-case inlinable version of the lookup routine for 32-bit integers.
UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
upb_value *v) {
+ *v = upb_value_int32(0); // Silence compiler warnings.
if (key < t->array_size) {
_upb_value arrval = t->array[key];
if (upb_arrhas(arrval)) {
diff --git a/upb/upb.h b/upb/upb.h
index cf221dc..86cae88 100644
--- a/upb/upb.h
+++ b/upb/upb.h
@@ -35,11 +35,12 @@ extern "C" {
#define UPB_C99
#endif
-#if (defined(__cplusplus) && __cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X__)
+#if ((defined(__cplusplus) && __cplusplus >= 201103L) || \
+ defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11)
#define UPB_CXX11
#endif
-#if defined(__GXX_EXPERIMENTAL_CXX0X__) && !defined(UPB_NO_CXX11)
+#ifdef UPB_CXX11
#define UPB_DISALLOW_POD_OPS(class_name) \
class_name() = delete; \
~class_name() = delete; \
@@ -70,27 +71,15 @@ extern "C" {
#endif
// Type detection and typedefs for integer types.
+// For platforms where there are multiple 32-bit or 64-bit types, we need to be
+// able to enumerate them so we can properly create overloads for all variants.
//
-// We unfortunately cannot just use stdint.h types in all cases, because some
-// platforms have more than one 32-bit type (or 64-bit type). For example, on
-// x86-64, both "long" and "long long" are 64-bit types, but they are
-// unfortunately incompatible with each other despite being the same size.
-// Since the types are incompatible, functions pointers between them are
-// incompatible also, which leads to trouble since handlers are declared in
-// terms of function pointers. Since we don't know which of these types
-// stdint.h will use (and we have no way of inspecting the typedefs, either at
-// preprocessing or compilation time), we are forced to declare our own
-// typedefs that we *do* know the real underlying type of.
-//
-// If any platform existed where there three integer types were the same size,
-// this would have to become more complicated. For example, short, int, and
-// long could all be 32-bits. Even more diabolically, short, int, long, and
-// long long could all be 64 bits and still be standard-compliant. However,
-// few platforms are this strange, and it's unlikely that upb will be used on
-// the strangest ones.
-//
-// For more information, see:
-// http://blog.reverberate.org/2013/03/cc-gripe-1-integer-types.html
+// If any platform existed where there were three integer types with the same
+// size, this would have to become more complicated. For example, short, int,
+// and long could all be 32-bits. Even more diabolically, short, int, long,
+// and long long could all be 64 bits and still be standard-compliant.
+// However, few platforms are this strange, and it's unlikely that upb will be
+// used on the strangest ones.
// Can't count on stdint.h limits like INT32_MAX, because in C++ these are
// only defined when __STDC_LIMIT_MACROS are defined before the *first* include
@@ -348,7 +337,7 @@ typedef struct {
#define UPB__VALUE_INIT_NONE UPB_VALUE_INIT(NULL, ptr)
#ifdef NDEBUG
-#define SET_TYPE(dest, val)
+#define SET_TYPE(dest, val) UPB_UNUSED(val)
#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE}
#else
#define SET_TYPE(dest, val) dest = val
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback