upb_stream: all callbacks registered ahead-of-time.

This is a significant change to the upb_stream
protocol, and should hopefully be the last
significant change.

All callbacks are now registered ahead-of-time
instead of having delegated callbacks registered
at runtime, which makes it much easier to
aggressively optimize ahead-of-time (like with a
JIT).

Other impacts of this change:

- You no longer need to have loaded descriptor.proto
  as a upb_def to load other descriptors!  This means
  the special-case code we used for bootstrapping is
  no longer necessary, and we no longer need to link
  the descriptor for descriptor.proto into upb.

- A client can now register any upb_value as what
  will be delivered to their value callback, not
  just a upb_fielddef*.  This should allow for other
  clients to get more bang out of the streaming
  decoder.

This change unfortunately causes a bit of a performance
regression -- I think largely due to highly
suboptimal code that GCC generates when structs
are returned by value.  See:
  http://blog.reverberate.org/2011/03/19/when-a-compilers-slow-code-actually-bites-you/

On the other hand, once we have a JIT this should
no longer matter.

Performance numbers:

plain.parsestream_googlemessage1.upb_table: 374 -> 396 (5.88)
plain.parsestream_googlemessage2.upb_table: 616 -> 449 (-27.11)
plain.parsetostruct_googlemessage1.upb_table_byref: 268 -> 269 (0.37)
plain.parsetostruct_googlemessage1.upb_table_byval: 215 -> 204 (-5.12)
plain.parsetostruct_googlemessage2.upb_table_byref: 307 -> 281 (-8.47)
plain.parsetostruct_googlemessage2.upb_table_byval: 297 -> 272 (-8.42)
omitfp.parsestream_googlemessage1.upb_table: 423 -> 410 (-3.07)
omitfp.parsestream_googlemessage2.upb_table: 679 -> 483 (-28.87)
omitfp.parsetostruct_googlemessage1.upb_table_byref: 287 -> 282 (-1.74)
omitfp.parsetostruct_googlemessage1.upb_table_byval: 226 -> 219 (-3.10)
omitfp.parsetostruct_googlemessage2.upb_table_byref: 315 -> 298 (-5.40)
omitfp.parsetostruct_googlemessage2.upb_table_byval: 297 -> 287 (-3.37)
pull/13171/head
Josh Haberman 14 years ago
parent 37e1c3102b
commit 8ef6873e0e
  1. 18
      Makefile
  2. 16
      benchmarks/parsestream.upb_table.c
  3. 19
      benchmarks/parsetostruct.upb_table.c
  4. 331
      src/descriptor.c
  5. 438
      src/descriptor_const.h
  6. 8
      src/upb.c
  7. 19
      src/upb.h
  8. 156
      src/upb_decoder.c
  9. 38
      src/upb_decoder.h
  10. 10
      src/upb_decoder_x64.asm
  11. 705
      src/upb_def.c
  12. 54
      src/upb_def.h
  13. 2
      src/upb_encoder.h
  14. 43
      src/upb_glue.c
  15. 122
      src/upb_msg.c
  16. 31
      src/upb_msg.h
  17. 1
      src/upb_stdio.c
  18. 328
      src/upb_stream.c
  19. 508
      src/upb_stream.h
  20. 303
      src/upb_stream_vtbl.h
  21. 2
      src/upb_strstream.c
  22. 1
      src/upb_table.c
  23. 38
      src/upb_textprinter.c
  24. 6
      src/upb_textprinter.h
  25. 3
      tests/test_def.c

@ -40,7 +40,7 @@ CC=gcc
CXX=g++
CFLAGS=-std=c99
INCLUDE=-Isrc -Itests -I.
CPPFLAGS=$(INCLUDE) -Wall -Wextra -Wno-missing-field-initializers $(USER_CFLAGS)
CPPFLAGS=$(INCLUDE) -Wall -Wextra $(USER_CFLAGS)
LDLIBS=-lpthread src/libupb.a
# Build with "make Q=" to see all commands that are being executed.
@ -69,28 +69,28 @@ $(ALLSRC): perf-cppflags
# Every source file used in upb should appear here.
# The core library -- the absolute minimum you must compile in to successfully
# bootstrap.
# The core library.
CORE= \
src/upb.c \
src/upb_stream.c \
src/upb_table.c \
src/upb_string.c \
src/upb_def.c \
src/upb_msg.c \
# Common encoders/decoders and upb_msg -- you're almost certain to want these.
# Common encoders/decoders -- you're almost certain to want these.
STREAM= \
src/upb_decoder.c \
src/upb_stdio.c \
src/upb_textprinter.c \
src/upb_strstream.c \
src/upb_msg.c \
src/upb_glue.c \
ASMCORE= \
src/upb_decoder_x64.asm
# Parts of core that are yet to be converted.
OTHERSRC=src/upb_encoder.c src/upb_text.c
OTHERSRC=src/upb_encoder.c
BENCHMARKS_SRC= \
benchmarks/main.c \
@ -100,12 +100,13 @@ BENCHMARKS_SRC= \
TESTS_SRC= \
tests/test_decoder.c \
tests/test_def.c \
tests/test_stream.c \
tests/test_string.c \
tests/tests.c \
tests/tests_varint.c \
tests/test_vs_proto2.cc
#tests/test_stream.c \
ALLSRC=$(CORE) $(STREAM) $(BENCHMARKS_SRC) $(TESTS_SRC)
@ -184,7 +185,6 @@ src/descriptor.pb: src/descriptor.proto
descriptorgen: src/descriptor.pb src/upbc
@# Regenerate descriptor_const.h
./src/upbc -o src/descriptor src/descriptor.pb
cd src && xxd -i descriptor.pb > descriptor.c
src/upbc: src/upbc.c $(LIBUPB)
@ -201,10 +201,10 @@ tests/test.proto.pb: tests/test.proto
SIMPLE_TESTS= \
tests/test_string \
tests/test_def \
tests/test_stream \
tests/test_varint \
tests/tests
# tests/test_decoder \
tests/test_stream \
SIMPLE_CXX_TESTS= \
tests/test_table

@ -47,11 +47,12 @@ static bool initialize()
fprintf(stderr, "Error reading " MESSAGE_FILE "\n");
return false;
}
upb_decoder_init(&decoder, def);
upb_handlers_init(&handlers, def);
// Cause all messages to be read, but do nothing when they are.
upb_register_all(&handlers, NULL, NULL, NULL, NULL, NULL, NULL);
upb_decoder_init(&decoder, &handlers);
upb_stringsrc_init(&stringsrc);
upb_handlers_init(&handlers);
static upb_handlerset handlerset = {}; // Empty handlers.
upb_register_handlerset(&handlers, &handlerset);
return true;
}
@ -61,6 +62,7 @@ static void cleanup()
upb_def_unref(UPB_UPCAST(def));
upb_decoder_uninit(&decoder);
upb_stringsrc_uninit(&stringsrc);
upb_handlers_uninit(&handlers);
}
static size_t run(int i)
@ -68,10 +70,8 @@ static size_t run(int i)
(void)i;
upb_status status = UPB_STATUS_INIT;
upb_stringsrc_reset(&stringsrc, input_str);
upb_decoder_reset(&decoder, upb_stringsrc_bytesrc(&stringsrc));
upb_src *src = upb_decoder_src(&decoder);
upb_src_sethandlers(src, &handlers);
upb_src_run(src, &status);
upb_decoder_reset(&decoder, upb_stringsrc_bytesrc(&stringsrc), NULL);
upb_decoder_decode(&decoder, &status);
if(!upb_ok(&status)) goto err;
return upb_string_len(input_str);

@ -13,7 +13,6 @@ static upb_msg *msg;
static upb_stringsrc strsrc;
static upb_decoder d;
static upb_handlers h;
static upb_msgpopulator p;
static bool initialize()
{
@ -54,9 +53,9 @@ static bool initialize()
msg = upb_msg_new(def);
upb_stringsrc_init(&strsrc);
upb_decoder_init(&d, def);
upb_msgpopulator_init(&p);
upb_handlers_init(&h);
upb_handlers_init(&h, def);
upb_msg_regdhandlers(&h);
upb_decoder_init(&d, &h);
if (!BYREF) {
// Pretend the input string is stack-allocated, which will force its data
@ -79,7 +78,6 @@ static void cleanup()
upb_def_unref(UPB_UPCAST(def));
upb_stringsrc_uninit(&strsrc);
upb_decoder_uninit(&d);
upb_msgpopulator_uninit(&p);
upb_handlers_uninit(&h);
}
@ -89,16 +87,9 @@ static size_t run(int i)
upb_status status = UPB_STATUS_INIT;
upb_msg_clear(msg, def);
upb_stringsrc_reset(&strsrc, input_str);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc));
upb_msgpopulator_reset(&p, msg, def);
upb_handlers_init(&h);
upb_msgpopulator_register_handlers(&p, &h);
upb_src *src = upb_decoder_src(&d);
upb_src_sethandlers(src, &h);
upb_src_run(src, &status);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), msg);
upb_decoder_decode(&d, &status);
if(!upb_ok(&status)) goto err;
upb_status_uninit(&status);
return upb_string_len(input_str);
err:

@ -1,331 +0,0 @@
unsigned char descriptor_pb[] = {
0x0a, 0xd8, 0x1e, 0x0a, 0x14, 0x73, 0x72, 0x63, 0x2f, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x47, 0x0a, 0x11, 0x46, 0x69,
0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x97, 0x03, 0x0a, 0x13,
0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x0f, 0x0a,
0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x12, 0x12, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x12, 0x36,
0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x6e,
0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x12, 0x38, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x2d, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39,
0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64,
0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa9, 0x03,
0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x34, 0x0a, 0x05, 0x66,
0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x35, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x6e,
0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x12, 0x48, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e,
0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x2c, 0x0a, 0x0e, 0x45,
0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67,
0x65, 0x12, 0x0d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01,
0x20, 0x01, 0x28, 0x05, 0x12, 0x0b, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x22, 0x94, 0x05, 0x0a, 0x14, 0x46, 0x69,
0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x0e, 0x0a, 0x06,
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
0x12, 0x3a, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c,
0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11,
0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x09, 0x12, 0x10, 0x0a, 0x08, 0x65, 0x78, 0x74,
0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x12,
0x15, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x12, 0x2e,
0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xb6,
0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01,
0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f,
0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e,
0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50,
0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, 0x12,
0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45,
0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50,
0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10,
0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52,
0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50,
0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12,
0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45,
0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12,
0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10,
0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49,
0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22,
0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e,
0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e,
0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45,
0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02,
0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45,
0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x8c, 0x01, 0x0a,
0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12, 0x38,
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2d, 0x0a, 0x07,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x6c, 0x0a, 0x18, 0x45,
0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63,
0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x12, 0x0e, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x12, 0x32, 0x0a, 0x07, 0x6f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x90, 0x01,
0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x12, 0x36, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x30,
0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x22, 0x7f, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x12, 0x12, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x12,
0x13, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x12, 0x2f, 0x0a, 0x07,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xd5, 0x03,
0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x14, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61,
0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x12,
0x1c, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65,
0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x08, 0x20, 0x01, 0x28, 0x09, 0x12, 0x22, 0x0a, 0x13, 0x6a, 0x61, 0x76,
0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x1d, 0x6a, 0x61, 0x76,
0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65,
0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61,
0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
0x6c, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d,
0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69,
0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50,
0x45, 0x45, 0x44, 0x12, 0x22, 0x0a, 0x13, 0x63, 0x63, 0x5f, 0x67, 0x65,
0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
0x6c, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f,
0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x13, 0x70, 0x79, 0x5f,
0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69,
0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50,
0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44,
0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c,
0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45,
0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
0x02, 0x22, 0xb8, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x17,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f,
0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18,
0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
0x12, 0x2e, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64,
0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08,
0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x94, 0x02, 0x0a,
0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x3a, 0x0a, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e,
0x47, 0x12, 0x0e, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x12, 0x19, 0x0a, 0x0a, 0x64, 0x65, 0x70,
0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x14,
0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c,
0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x09, 0x20, 0x01,
0x28, 0x09, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22,
0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06,
0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04,
0x43, 0x4f, 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54,
0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x49, 0x45, 0x43, 0x45, 0x10, 0x02,
0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
0x5d, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x62,
0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x14, 0x75, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
0x80, 0x02, 0x22, 0x60, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x14,
0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80,
0x80, 0x80, 0x80, 0x02, 0x22, 0x5f, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a,
0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10,
0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9e, 0x02, 0x0a, 0x13, 0x55, 0x6e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61,
0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x10, 0x69, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x12, 0x1a, 0x0a, 0x12,
0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74,
0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04,
0x12, 0x1a, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65,
0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05,
0x20, 0x01, 0x28, 0x03, 0x12, 0x14, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62,
0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01,
0x28, 0x01, 0x12, 0x14, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c,
0x12, 0x17, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74,
0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
0x09, 0x1a, 0x33, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72,
0x74, 0x12, 0x11, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61,
0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x12, 0x14, 0x0a, 0x0c,
0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x22, 0x7c, 0x0a, 0x0e, 0x53, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x3a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49,
0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x1a, 0x2e, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x10, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03,
0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x04, 0x73, 0x70,
0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01,
0x42, 0x29, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42,
0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01
};
unsigned int descriptor_pb_len = 3931;

@ -50,152 +50,298 @@ typedef enum google_protobuf_FileOptions_OptimizeMode {
/* Constants for field names and numbers. */
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNUM 1
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNAME "file"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNUM 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNAME "field"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNUM 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNAME "nested_type"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNUM 4
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNAME "enum_type"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_FIELDNUM 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_FIELDNAME "extension_range"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_FIELDNUM 6
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_FIELDNAME "extension"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_FIELDNUM 7
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_FIELDNUM 1
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_FIELDNAME "path"
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_FIELDNUM 2
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_FIELDNAME "span"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_FIELDNUM 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_FIELDNUM 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_FIELDNAME "identifier_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_FIELDNUM 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_FIELDNAME "positive_int_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_FIELDNUM 5
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_FIELDNAME "negative_int_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_FIELDNUM 6
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_FIELDNAME "double_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_FIELDNUM 7
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_FIELDNAME "string_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_FIELDNUM 8
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_FIELDNAME "aggregate_value"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_FIELDNUM 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_FIELDNAME "package"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_FIELDNUM 3
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_FIELDNAME "dependency"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNUM 4
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNAME "message_type"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNUM 5
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNAME "enum_type"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_FIELDNUM 6
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_FIELDNAME "service"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_FIELDNUM 7
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_FIELDNAME "extension"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_FIELDNUM 8
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_FIELDNUM 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_FIELDNAME "source_code_info"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_FIELDNUM 2
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_FIELDNAME "input_type"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_FIELDNUM 3
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_FIELDNAME "output_type"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_FIELDNUM 4
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNUM 2
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNAME "value"
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_FIELDNUM 3
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_FIELDNUM 2
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_FIELDNAME "number"
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_FIELDNUM 3
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_FIELDNUM 2
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_FIELDNAME "method"
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_FIELDNUM 3
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_FIELDNUM 1
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_FIELDNAME "name_part"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_FIELDNUM 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_FIELDNAME "is_extension"
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_FIELDNUM 1
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_FIELDNAME "location"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_FIELDNUM 1
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_FIELDNAME "start"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_FIELDNUM 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_FIELDNAME "end"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_FIELDNUM 1
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_FIELDNAME "ctype"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_FIELDNUM 2
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_FIELDNAME "packed"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_FIELDNUM 3
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_FIELDNAME "deprecated"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_FIELDNUM 9
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_FIELDNAME "experimental_map_key"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_FIELDNUM 1
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_FIELDNAME "java_package"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_FIELDNUM 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_FIELDNAME "java_outer_classname"
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_FIELDNUM 9
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_FIELDNAME "optimize_for"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_FIELDNUM 10
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_FIELDNAME "java_multiple_files"
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_FIELDNUM 16
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_FIELDNAME "cc_generic_services"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_FIELDNUM 17
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_FIELDNAME "java_generic_services"
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_FIELDNUM 18
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_FIELDNAME "py_generic_services"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_FIELDNUM 20
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_FIELDNAME "java_generate_equals_and_hash"
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_FIELDNUM 1
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_FIELDNAME "message_set_wire_format"
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_FIELDNUM 2
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_FIELDNAME "no_standard_descriptor_accessor"
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_FIELDNUM 1
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_FIELDNAME "name"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_FIELDNUM 2
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_FIELDNAME "extendee"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNUM 3
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNAME "number"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNUM 4
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNAME "label"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNUM 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNAME "type"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_FIELDNUM 6
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_FIELDNAME "type_name"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_FIELDNUM 7
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_FIELDNAME "default_value"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_FIELDNUM 8
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_FIELDNAME "options"
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_FIELDNUM 999
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNUM 1
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNAME "file"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNUM 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNAME "field"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNUM 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNAME "nested_type"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNUM 4
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNAME "enum_type"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDNUM 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDNAME "extension_range"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDNUM 6
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDNAME "extension"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDNUM 7
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDNUM 1
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDNAME "path"
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH__FIELDTYPE 5
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDNUM 2
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDNAME "span"
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN__FIELDTYPE 5
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDNUM 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME__FIELDTYPE 11
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDNUM 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDNAME "identifier_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDNUM 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDNAME "positive_int_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE__FIELDTYPE 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDNUM 5
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDNAME "negative_int_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE__FIELDTYPE 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDNUM 6
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDNAME "double_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE__FIELDTYPE 1
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDNUM 7
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDNAME "string_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE__FIELDTYPE 12
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDNUM 8
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDNAME "aggregate_value"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNUM 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNAME "package"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDNUM 3
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDNAME "dependency"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNUM 4
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNAME "message_type"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNUM 5
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNAME "enum_type"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDNUM 6
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDNAME "service"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDNUM 7
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDNAME "extension"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDNUM 8
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDNUM 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDNAME "source_code_info"
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO__FIELDTYPE 11
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDNUM 2
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDNAME "input_type"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDNUM 3
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDNAME "output_type"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDNUM 4
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNUM 2
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNAME "value"
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDTYPE 11
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDNUM 3
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNUM 2
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNAME "number"
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDTYPE 5
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDNUM 3
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDNUM 2
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDNAME "method"
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD__FIELDTYPE 11
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDNUM 3
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDNUM 1
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDNAME "name_part"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART__FIELDTYPE 9
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDNUM 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDNAME "is_extension"
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION__FIELDTYPE 8
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDNUM 1
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDNAME "location"
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDNUM 1
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDNAME "start"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START__FIELDTYPE 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDNUM 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDNAME "end"
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END__FIELDTYPE 5
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDNUM 1
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDNAME "ctype"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE__FIELDTYPE 14
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDNUM 2
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDNAME "packed"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDNUM 3
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDNAME "deprecated"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDNUM 9
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDNAME "experimental_map_key"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDNUM 1
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDNAME "java_package"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDNUM 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDNAME "java_outer_classname"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDNUM 9
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDNAME "optimize_for"
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR__FIELDTYPE 14
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDNUM 10
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDNAME "java_multiple_files"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDNUM 16
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDNAME "cc_generic_services"
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDNUM 17
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDNAME "java_generic_services"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDNUM 18
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDNAME "py_generic_services"
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDNUM 20
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDNAME "java_generate_equals_and_hash"
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH__FIELDTYPE 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDNUM 1
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDNAME "message_set_wire_format"
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT__FIELDTYPE 8
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDNUM 2
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDNAME "no_standard_descriptor_accessor"
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR__FIELDTYPE 8
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNUM 1
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNAME "name"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDNUM 2
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDNAME "extendee"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNUM 3
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNAME "number"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDTYPE 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNUM 4
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNAME "label"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDTYPE 14
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNUM 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNAME "type"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDTYPE 14
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNUM 6
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNAME "type_name"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNUM 7
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNAME "default_value"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDTYPE 9
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDNUM 8
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDNAME "options"
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS__FIELDTYPE 11
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDNUM 999
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDNAME "uninterpreted_option"
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION__FIELDTYPE 11
#ifdef __cplusplus
} /* extern "C" */
#endif

@ -8,7 +8,7 @@
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include "descriptor_const.h"
#include "upb.h"
#include "upb_string.h"
@ -40,6 +40,12 @@ const upb_type_info upb_types[] = {
TYPE_INFO(UPB_WIRE_TYPE_VARINT, int64_t, 1, INT64) // SINT64
};
#ifdef NDEBUG
upb_value UPB_NO_VALUE = {{0}};
#else
upb_value UPB_NO_VALUE = {{0}, UPB_VALUETYPE_RAW};
#endif
void upb_seterr(upb_status *status, enum upb_status_code code,
const char *msg, ...) {
status->code = code;

@ -46,11 +46,15 @@ INLINE size_t upb_align_up(size_t val, size_t align) {
// The maximum that any submessages can be nested. Matches proto2's limit.
// At the moment this specifies the size of several statically-sized arrays
// and therefore setting it high will cause more memory to be used. Will
// be replaced by a runtime-configurable limit and dynamically-resizing arrays.
#define UPB_MAX_NESTING 64
// The maximum number of fields that any one .proto type can have. Note that
// this is very different than the max field number. It is hard to imagine a
// scenario where more than 32k fields makes sense.
// scenario where more than 32k fields (each with its own name and field number)
// makes sense.
#define UPB_MAX_FIELDS (1<<15)
typedef int16_t upb_field_count_t;
@ -72,7 +76,9 @@ typedef int16_t upb_field_count_t;
// The maximum depth that the type graph can have. Note that this setting does
// not automatically constrain UPB_MAX_NESTING, because type cycles allow for
// unlimited nesting if we do not limit it.
// unlimited nesting if we do not limit it. Many algorithms in upb call
// recursive functions that traverse the type graph, so we must limit this to
// avoid blowing the C stack.
#define UPB_MAX_TYPE_DEPTH 64
// The biggest possible single value is a 10-byte varint.
@ -145,6 +151,8 @@ struct _upb_msg;
typedef struct _upb_msg upb_msg;
struct _upb_bytesrc;
typedef struct _upb_bytesrc upb_bytesrc;
struct _upb_fielddef;
typedef struct _upb_fielddef upb_fielddef;
typedef int32_t upb_strlen_t;
#define UPB_STRLEN_MAX INT32_MAX
@ -155,23 +163,25 @@ typedef uint8_t upb_valuetype_t;
#define UPB_VALUETYPE_ARRAY 32
#define UPB_VALUETYPE_BYTESRC 32
#define UPB_VALUETYPE_RAW 33
#define UPB_VALUETYPE_FIELDDEF 34
// A single .proto value. The owner must have an out-of-band way of knowing
// the type, so that it knows which union member to use.
typedef struct {
union {
uint64_t uint64;
double _double;
float _float;
int32_t int32;
int64_t int64;
uint32_t uint32;
uint64_t uint64;
bool _bool;
upb_string *str;
upb_bytesrc *bytesrc;
upb_msg *msg;
upb_array *arr;
upb_atomic_refcount_t *refcount;
upb_fielddef *fielddef;
void *_void;
} val;
@ -208,6 +218,9 @@ UPB_VALUE_ACCESSORS(str, str, upb_string*, UPB_TYPE(STRING));
UPB_VALUE_ACCESSORS(msg, msg, upb_msg*, UPB_TYPE(MESSAGE));
UPB_VALUE_ACCESSORS(arr, arr, upb_array*, UPB_VALUETYPE_ARRAY);
UPB_VALUE_ACCESSORS(bytesrc, bytesrc, upb_bytesrc*, UPB_VALUETYPE_BYTESRC);
UPB_VALUE_ACCESSORS(fielddef, fielddef, upb_fielddef*, UPB_VALUETYPE_FIELDDEF);
extern upb_value UPB_NO_VALUE;
INLINE void upb_value_setraw(upb_value *val, uint64_t cval) {
SET_TYPE(val->type, UPB_VALUETYPE_RAW);

@ -4,13 +4,11 @@
* Copyright (c) 2008-2011 Joshua Haberman. See LICENSE for details.
*/
#include "upb_decoder.h"
#include "upb_varint_decoder.h"
#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
#include "upb_def.h"
#include "upb_decoder.h"
#include "upb_varint_decoder.h"
// If the return value is other than UPB_CONTINUE, that is what the last
// callback returned.
@ -37,7 +35,12 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); }
INLINE void upb_decoder_advance(upb_decoder *d, size_t len) {
d->ptr += len;
//d->bytes_parsed_slow += len;
}
INLINE size_t upb_decoder_offset(upb_decoder *d) {
size_t offset = d->buf_stream_offset;
if (d->buf) offset += (d->ptr - upb_string_getrobuf(d->buf));
return offset;
}
INLINE size_t upb_decoder_bufleft(upb_decoder *d) {
@ -45,13 +48,11 @@ INLINE size_t upb_decoder_bufleft(upb_decoder *d) {
}
INLINE void upb_dstate_setmsgend(upb_decoder *d) {
d->submsg_end = (d->top->end_offset == UPB_GROUP_END_OFFSET) ?
(void*)UINTPTR_MAX :
upb_string_getrobuf(d->buf) + (d->top->end_offset - d->buf_stream_offset);
size_t end_offset = d->dispatcher.top->end_offset;
d->submsg_end = (end_offset == UPB_GROUP_END_OFFSET) ? (void*)UINTPTR_MAX :
d->ptr + (end_offset - upb_decoder_offset(d));
}
static upb_flow_t upb_pop(upb_decoder *d);
// Called only from the slow path, this function copies the next "len" bytes
// from the stream to "data", adjusting the dstate appropriately.
static bool upb_getbuf(upb_decoder *d, void *data, size_t bytes_wanted) {
@ -186,54 +187,44 @@ INLINE bool upb_check_type(upb_wire_type_t wt, upb_fieldtype_t ft) {
return upb_types[ft].native_wire_type == wt;
}
static upb_flow_t upb_push(upb_decoder *d, upb_fielddef *f,
upb_value submsg_len, upb_fieldtype_t type) {
++d->top;
if(d->top >= d->limit) {
upb_seterr(d->status, UPB_ERROR, "Nesting too deep.");
return UPB_ERROR;
}
d->top->end_offset = (type == UPB_TYPE(GROUP)) ?
UPB_GROUP_END_OFFSET :
d->buf_stream_offset + (d->ptr - upb_string_getrobuf(d->buf)) +
upb_value_getint32(submsg_len);
d->top->f = f;
d->msgdef = upb_downcast_msgdef(f->def);
static upb_flow_t upb_pop(upb_decoder *d) {
upb_flow_t ret = upb_dispatch_endsubmsg(&d->dispatcher);
upb_dstate_setmsgend(d);
upb_flow_t ret = upb_dispatch_startsubmsg(&d->dispatcher, f);
if (ret == UPB_SKIPSUBMSG) {
if (type == UPB_TYPE(GROUP)) {
fprintf(stderr, "upb_decoder: Can't skip groups yet.\n");
abort();
}
upb_decoder_advance(d, upb_value_getint32(submsg_len));
--d->top;
upb_dstate_setmsgend(d);
ret = UPB_CONTINUE;
}
return ret;
}
static upb_flow_t upb_pop(upb_decoder *d) {
--d->top;
d->msgdef = upb_downcast_msgdef(d->top->f->def);
static upb_flow_t upb_decoder_skipsubmsg(upb_decoder *d) {
if (d->dispatcher.top->f->type == UPB_TYPE(GROUP)) {
fprintf(stderr, "upb_decoder: Can't skip groups yet.\n");
abort();
}
upb_decoder_advance(d, d->dispatcher.top->end_offset - d->buf_stream_offset -
(d->ptr - upb_string_getrobuf(d->buf)));
upb_pop(d);
return UPB_CONTINUE;
}
static upb_flow_t upb_push(upb_decoder *d, upb_handlers_fieldent *f,
upb_value submsg_len) {
upb_flow_t flow = upb_dispatch_startsubmsg(&d->dispatcher, f,
(f->type == UPB_TYPE(GROUP)) ? UPB_GROUP_END_OFFSET :
upb_decoder_offset(d) + upb_value_getint32(submsg_len));
upb_dstate_setmsgend(d);
return upb_dispatch_endsubmsg(&d->dispatcher, d->top->f);
return flow;
}
void upb_decoder_run(upb_src *src, upb_status *status) {
upb_decoder *d = (upb_decoder*)src;
void upb_decoder_decode(upb_decoder *d, upb_status *status) {
d->status = status;
d->ptr = NULL;
d->end = NULL; // Force a buffer pull.
d->submsg_end = (void*)0x1; // But don't let end-of-message get triggered.
d->msgdef = upb_downcast_msgdef(d->top->f->def);
// TODO: handle UPB_SKIPSUBMSG
#define CHECK_FLOW(expr) if ((expr) == UPB_BREAK) { /*assert(!upb_ok(status));*/ goto callback_err; }
#define CHECK_FLOW(expr) \
switch (expr) { \
case UPB_BREAK: goto callback_err; \
case UPB_SKIPSUBMSG: upb_decoder_skipsubmsg(d); continue; \
default: break; /* continue normally. */ \
}
#define CHECK(expr) if (!expr) { assert(!upb_ok(status)); goto err; }
CHECK_FLOW(upb_dispatch_startmsg(&d->dispatcher));
if (upb_dispatch_startmsg(&d->dispatcher, d->closure) != UPB_CONTINUE) goto err;
// Main loop: executed once per tag/field pair.
while(1) {
@ -261,10 +252,10 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
// Parse/handle tag.
upb_tag tag;
if (!upb_decode_tag(d, &tag)) {
if (status->code == UPB_EOF && d->top == d->stack) {
if (status->code == UPB_EOF && upb_dispatcher_stackempty(&d->dispatcher)) {
// Normal end-of-file.
upb_clearerr(status);
CHECK_FLOW(upb_dispatch_endmsg(&d->dispatcher));
upb_dispatch_endmsg(&d->dispatcher, status);
return;
} else {
if (status->code == UPB_EOF) {
@ -282,7 +273,7 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
case UPB_WIRE_TYPE_START_GROUP:
break; // Nothing to do now, below we will push appropriately.
case UPB_WIRE_TYPE_END_GROUP:
if(d->top->end_offset != UPB_GROUP_END_OFFSET) {
if(d->dispatcher.top->end_offset != UPB_GROUP_END_OFFSET) {
upb_seterr(status, UPB_ERROR, "Unexpected END_GROUP tag.");
goto err;
}
@ -302,41 +293,38 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
}
// Look up field by tag number.
upb_itof_ent *e = upb_msgdef_itofent(d->msgdef, tag.field_number);
upb_dispatcher_field *f =
upb_dispatcher_lookup(&d->dispatcher, tag.field_number);
if (!e) {
if (!f) {
if (tag.wire_type == UPB_WIRE_TYPE_DELIMITED)
CHECK(upb_decode_string(d, &val, &d->tmp));
CHECK_FLOW(upb_dispatch_unknownval(&d->dispatcher, tag.field_number, val));
continue;
}
upb_fielddef *f = e->f;
assert(e->field_type == f->type);
assert(e->native_wire_type == upb_types[f->type].native_wire_type);
if (tag.wire_type != e->native_wire_type) {
if (tag.wire_type != f->native_wire_type) {
// TODO: Support packed fields.
upb_seterr(status, UPB_ERROR, "Field had incorrect type, name: " UPB_STRFMT
", field type: %d, expected wire type %d, actual wire type: %d",
UPB_STRARG(f->name), f->type, upb_types[f->type].native_wire_type,
tag.wire_type);
upb_printerr(status);
upb_seterr(status, UPB_ERROR, "Field had incorrect type, field number: %d"
", field type: %d, expected wire type: %d, "
"actual wire type: %d, offset: %d",
tag.field_number, f->type, upb_types[f->type].native_wire_type,
tag.wire_type, upb_decoder_offset(d));
goto err;
}
// Perform any further massaging of the data now that we have the fielddef.
// Now we can distinguish strings from submessages, and we know about
// zig-zag-encoded types.
// Perform any further massaging of the data now that we have the field's
// type. Now we can distinguish strings from submessages, and we know
// about zig-zag-encoded types.
// TODO: handle packed encoding.
// TODO: if we were being paranoid, we could check for 32-bit-varint types
// that the top 32 bits all match the highest bit of the low 32 bits.
// If this is not true we are losing data. But the main protobuf library
// doesn't check this, and it would slow us down, so pass for now.
switch (e->field_type) {
switch (f->type) {
case UPB_TYPE(MESSAGE):
case UPB_TYPE(GROUP):
CHECK_FLOW(upb_push(d, f, val, e->field_type));
CHECK_FLOW(upb_push(d, f, val));
continue; // We have no value to dispatch.
case UPB_TYPE(STRING):
case UPB_TYPE(BYTES):
@ -358,7 +346,6 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
}
callback_err:
upb_copyerr(status, d->dispatcher.top->handlers.status);
if (upb_ok(status)) {
upb_seterr(status, UPB_ERROR, "Callback returned UPB_BREAK");
}
@ -366,37 +353,24 @@ err:
assert(!upb_ok(status));
}
void upb_decoder_sethandlers(upb_src *src, upb_handlers *handlers) {
upb_decoder *d = (upb_decoder*)src;
upb_dispatcher_reset(&d->dispatcher, handlers, true);
d->top = d->stack;
d->buf_stream_offset = 0;
}
void upb_decoder_init(upb_decoder *d, upb_msgdef *msgdef) {
static upb_src_vtbl vtbl = {
&upb_decoder_sethandlers,
&upb_decoder_run,
};
upb_src_init(&d->src, &vtbl);
upb_dispatcher_init(&d->dispatcher);
d->f.def = UPB_UPCAST(msgdef);
d->stack[0].f = &d->f;
// Never want to end top-level message, so treat it like a group.
d->stack[0].end_offset = UPB_GROUP_END_OFFSET;
d->limit = &d->stack[UPB_MAX_NESTING];
void upb_decoder_init(upb_decoder *d, upb_handlers *handlers) {
upb_dispatcher_init(&d->dispatcher, handlers, UPB_GROUP_END_OFFSET);
d->buf = NULL;
d->tmp = NULL;
}
void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc) {
void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, void *closure) {
d->bytesrc = bytesrc;
d->top = &d->stack[0];
d->closure = closure;
upb_dispatcher_reset(&d->dispatcher);
d->ptr = NULL;
d->end = NULL; // Force a buffer pull.
d->submsg_end = (void*)0x1; // But don't let end-of-message get triggered.
d->buf_stream_offset = 0;
}
void upb_decoder_uninit(upb_decoder *d) {
upb_dispatcher_uninit(&d->dispatcher);
upb_string_unref(d->buf);
upb_string_unref(d->tmp);
}
upb_src *upb_decoder_src(upb_decoder *d) { return &d->src; }

@ -18,7 +18,6 @@
#include <stdbool.h>
#include <stdint.h>
#include "upb_def.h"
#include "upb_stream.h"
#ifdef __cplusplus
@ -27,31 +26,17 @@ extern "C" {
/* upb_decoder *****************************************************************/
// The decoder keeps a stack with one entry per level of recursion.
// upb_decoder_frame is one frame of that stack.
typedef struct {
upb_fielddef *f;
size_t end_offset; // For groups, 0.
} upb_decoder_frame;
struct _upb_decoder {
// Immutable state of the decoder.
upb_src src;
upb_dispatcher dispatcher;
// Bytesrc from which we pull serialized data.
upb_bytesrc *bytesrc;
// Mutable state of the decoder.
// Msgdef for the current level.
upb_msgdef *msgdef;
// Stack entries store the offset where the submsg ends (for groups, 0).
upb_decoder_frame *top, *limit;
// Dispatcher to which we push parsed data.
upb_dispatcher dispatcher;
// Current input buffer.
upb_string *buf;
// Temporary string for passing to callbacks.
// Temporary string for passing string data to callbacks.
upb_string *tmp;
// The offset within the overall stream represented by the *beginning* of buf.
@ -66,12 +51,11 @@ struct _upb_decoder {
// End of this submessage, relative to *ptr.
const char *submsg_end;
// The closure that was passed by the caller for the top-level message.
void *closure;
// Where we will store any errors that occur.
upb_status *status;
// A fake fielddef for storing the msgdef for the top-level message.
upb_fielddef f;
upb_decoder_frame stack[UPB_MAX_NESTING];
};
// A upb_decoder decodes the binary protocol buffer format, writing the data it
@ -80,18 +64,16 @@ struct _upb_decoder;
typedef struct _upb_decoder upb_decoder;
// Allocates and frees a upb_decoder, respectively.
void upb_decoder_init(upb_decoder *d, upb_msgdef *md);
void upb_decoder_init(upb_decoder *d, upb_handlers *handlers);
void upb_decoder_uninit(upb_decoder *d);
// Resets the internal state of an already-allocated decoder. This puts it in a
// state where it has not seen any data, and expects the next data to be from
// the beginning of a new protobuf. Parsers must be reset before they can be
// used. A decoder can be reset multiple times.
void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc);
void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc, void *closure);
// Returns a upb_src pointer by which the decoder can be used. The returned
// upb_src is invalidated by upb_decoder_reset() or upb_decoder_free().
upb_src *upb_decoder_src(upb_decoder *d);
void upb_decoder_decode(upb_decoder *d, upb_status *status);
#ifdef __cplusplus
} /* extern "C" */

@ -34,8 +34,8 @@ SECTION .text
%define BUF rbx ; const char *p, current buf position.
%define END rbp ; const char *end, where the buf ends (either submsg end or buf end)
%define STRING r12 ; unused
%define FIELDDEF r13 ; upb_fielddef *f, needs to be preserved across varint decoding call.
%define CALLBACK r14
%define FVAL r13 ; upb_value fval, needs to be preserved across varint decoding call.
%define UNUSED r14
%define CLOSURE r15
; Stack layout: *tableptr, uint32_t maxfield_times_8
@ -57,10 +57,10 @@ SECTION .text
; path that goes into a tight loop if the encoding was packed).
; - check_6: the field is not a group or a message (or string, TODO)
; (this could be relaxed, but due to delegation it's a bit tricky).
; - if the value is a string, the entire string is available in
; - check_7: if the value is a string, the entire string is available in
; the buffer, and our cached string object can be recycled, and
; our string object already references the source buffer, so
; absolutely no refcount twiddling is required. (check_7)
; absolutely no refcount twiddling is required.
%macro decode_and_dispatch_ 0
@ -78,7 +78,7 @@ align 16
; Decode a 1 or 2-byte varint -> eax.
mov cl, byte [BUF]
lea rdi, [BUF+1]
movzx rax, cl ; Need all of rax since we're doing a 64-bit lea later.
movzx eax, cl
and eax, 0x7f
test cl, cl
jns .one_byte_tag ; Should be predictable if fields are in order.

@ -7,8 +7,6 @@
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "descriptor.c"
#include "descriptor_const.h"
#include "upb_def.h"
#include "upb_msg.h"
@ -190,16 +188,11 @@ static void upb_def_uninit(upb_def *def) {
// We use a separate object (upb_defbuilder) instead of having the defs handle
// the parse themselves because we need to store state that is only necessary
// during the building process itself.
// When we are bootstrapping descriptor.proto, we must help the bare decoder out
// by telling it when to descend into a submessage, because with the wire format
// alone we cannot tell the difference between a submessage and a string.
//
// TODO: In the long-term, we should bootstrap from a serialization format that
// contains this information, so we can remove this special-case code. This
// would involve defining a serialization format very similar to the existing
// protobuf format, but that contains more information about the wire type.
#define BEGIN_SUBMSG 100
// All of the handlers registration in this file must be done using the
// low-level upb_register_typed_* interface, since we might not have a msgdef
// yet (in the case of bootstrapping). This makes it more laborious than it
// will be for real users.
// upb_deflist: A little dynamic array for storing a growing list of upb_defs.
typedef struct {
@ -257,6 +250,7 @@ struct _upb_defbuilder {
upb_defbuilder_frame stack[UPB_MAX_TYPE_DEPTH];
int stack_len;
upb_status status;
upb_symtab *symtab;
uint32_t number;
upb_string *name;
@ -267,23 +261,23 @@ struct _upb_defbuilder {
upb_fielddef *f;
};
typedef struct _upb_defbuilder upb_defbuilder;
// Forward declares for top-level file descriptors.
static void upb_msgdef_register_DescriptorProto(upb_defbuilder *b, upb_handlers *h);
static void upb_enumdef_register_EnumDescriptorProto(upb_defbuilder *b,
upb_handlers *h);
static void upb_msgdef_register_DescriptorProto(upb_handlers *h);
static void upb_enumdef_register_EnumDescriptorProto(upb_handlers *h);
static void upb_defbuilder_init(upb_defbuilder *b) {
upb_defbuilder *upb_defbuilder_new(upb_symtab *s) {
upb_defbuilder *b = malloc(sizeof(*b));
upb_deflist_init(&b->defs);
upb_status_init(&b->status);
b->symtab = s;
b->stack_len = 0;
b->name = NULL;
b->default_string = NULL;
return b;
}
static void upb_defbuilder_uninit(upb_defbuilder *b) {
static void upb_defbuilder_free(upb_defbuilder *b) {
upb_string_unref(b->name);
upb_status_uninit(&b->status);
upb_deflist_uninit(&b->defs);
@ -292,6 +286,7 @@ static void upb_defbuilder_uninit(upb_defbuilder *b) {
upb_defbuilder_frame *f = &b->stack[--b->stack_len];
upb_string_unref(f->name);
}
free(b);
}
static upb_msgdef *upb_defbuilder_top(upb_defbuilder *b) {
@ -332,89 +327,67 @@ static upb_flow_t upb_defbuilder_FileDescriptorProto_startmsg(void *_b) {
return UPB_CONTINUE;
}
static upb_flow_t upb_defbuilder_FileDescriptorProto_endmsg(void *_b) {
static void upb_defbuilder_FileDescriptorProto_endmsg(void *_b,
upb_status *status) {
(void)status;
upb_defbuilder *b = _b;
upb_defbuilder_endcontainer(b);
return UPB_CONTINUE;
}
static upb_flow_t upb_defbuilder_FileDescriptorProto_value(void *_b,
upb_fielddef *f,
upb_value val) {
static upb_flow_t upb_defbuilder_FileDescriptorProto_package(void *_b,
upb_value fval,
upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_FIELDNUM:
upb_defbuilder_setscopename(b, upb_value_getstr(val));
break;
case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNUM:
case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNUM:
return BEGIN_SUBMSG;
}
upb_defbuilder_setscopename(b, upb_value_getstr(val));
return UPB_CONTINUE;
}
static upb_flow_t upb_defbuilder_FileDescriptorProto_startsubmsg(
void *_b, upb_fielddef *f, upb_handlers *h) {
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_FIELDNUM:
upb_msgdef_register_DescriptorProto(b, h);
return UPB_DELEGATE;
case GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_FIELDNUM:
upb_enumdef_register_EnumDescriptorProto(b, h);
return UPB_DELEGATE;
default:
// TODO: services and extensions.
return UPB_SKIPSUBMSG;
}
}
static void upb_defbuilder_register_FileDescriptorProto(upb_handlers *h) {
upb_register_startend(h, upb_defbuilder_FileDescriptorProto_startmsg,
upb_defbuilder_FileDescriptorProto_endmsg);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNUM,
GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDTYPE,
&upb_defbuilder_FileDescriptorProto_package, UPB_NO_VALUE);
upb_handlers_typed_push(h,
GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNUM,
GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDTYPE);
upb_msgdef_register_DescriptorProto(h);
upb_handlers_typed_pop(h);
static void upb_defbuilder_register_FileDescriptorProto(upb_defbuilder *b,
upb_handlers *h) {
static upb_handlerset handlers = {
&upb_defbuilder_FileDescriptorProto_startmsg,
&upb_defbuilder_FileDescriptorProto_endmsg,
&upb_defbuilder_FileDescriptorProto_value,
&upb_defbuilder_FileDescriptorProto_startsubmsg,
};
upb_register_handlerset(h, &handlers);
upb_set_handler_closure(h, b, &b->status);
upb_handlers_typed_push(h,
GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNUM,
GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE);
upb_enumdef_register_EnumDescriptorProto(h);
upb_handlers_typed_pop(h);
// TODO: services and extensions.
}
// Handlers for google.protobuf.FileDescriptorSet.
static upb_flow_t upb_defbuilder_FileDescriptorSet_value(void *b,
upb_fielddef *f,
upb_value val) {
(void)b;
(void)val;
switch(f->number) {
case GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNUM:
return BEGIN_SUBMSG;
}
return UPB_CONTINUE;
}
static bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs,
bool allow_redef, upb_status *status);
static upb_flow_t upb_defbuilder_FileDescriptorSet_startsubmsg(
void *_b, upb_fielddef *f, upb_handlers *h) {
static void upb_defbuilder_FileDescriptorSet_onendmsg(void *_b,
upb_status *status) {
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_FIELDNUM:
upb_defbuilder_register_FileDescriptorProto(b, h);
return UPB_DELEGATE;
}
return UPB_SKIPSUBMSG;
if (upb_ok(status))
upb_symtab_add_defs(b->symtab, b->defs.defs, b->defs.len, false, status);
upb_defbuilder_free(b);
}
static void upb_defbuilder_register_FileDescriptorSet(
upb_defbuilder *b, upb_handlers *h) {
static upb_handlerset handlers = {
NULL, // startmsg
NULL, // endmsg
&upb_defbuilder_FileDescriptorSet_value,
&upb_defbuilder_FileDescriptorSet_startsubmsg,
};
upb_register_handlerset(h, &handlers);
upb_set_handler_closure(h, b, &b->status);
static void upb_defbuilder_register_FileDescriptorSet(upb_handlers *h) {
upb_register_startend(h, NULL, upb_defbuilder_FileDescriptorSet_onendmsg);
upb_handlers_typed_push(h,
GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNUM,
GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDTYPE);
upb_defbuilder_register_FileDescriptorProto(h);
upb_handlers_typed_pop(h);
}
void upb_defbuilder_reghandlers(upb_handlers *h) {
upb_defbuilder_register_FileDescriptorSet(h);
}
@ -469,31 +442,33 @@ static upb_flow_t upb_enumdef_EnumValueDescriptorProto_startmsg(void *_b) {
return UPB_CONTINUE;
}
static upb_flow_t upb_enumdef_EnumValueDescriptorProto_value(void *_b,
upb_fielddef *f,
upb_value val) {
static upb_flow_t upb_enumdef_EnumValueDescriptorProto_name(void *_b,
upb_value fval,
upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_FIELDNUM:
upb_string_unref(b->name);
b->name = upb_string_getref(upb_value_getstr(val));
b->saw_name = true;
break;
case GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_FIELDNUM:
b->number = upb_value_getint32(val);
b->saw_number = true;
break;
default:
break;
}
upb_string_unref(b->name);
b->name = upb_string_getref(upb_value_getstr(val));
b->saw_name = true;
return UPB_CONTINUE;
}
static upb_flow_t upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b) {
static upb_flow_t upb_enumdef_EnumValueDescriptorProto_number(void *_b,
upb_value fval,
upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
b->number = upb_value_getint32(val);
b->saw_number = true;
return UPB_CONTINUE;
}
static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b,
upb_status *status) {
upb_defbuilder *b = _b;
if(!b->saw_number || !b->saw_name) {
upb_seterr(&b->status, UPB_ERROR, "Enum value missing name or number.");
return UPB_BREAK;
upb_seterr(status, UPB_ERROR, "Enum value missing name or number.");
return;
}
upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
if (upb_inttable_count(&e->iton) == 0) {
@ -509,18 +484,19 @@ static upb_flow_t upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b) {
// table. strtables can ref their keys, but the inttable doesn't know that
// the value is a string.
b->name = NULL;
return UPB_CONTINUE;
}
static void upb_enumdef_register_EnumValueDescriptorProto(upb_defbuilder *b,
upb_handlers *h) {
static upb_handlerset handlers = {
&upb_enumdef_EnumValueDescriptorProto_startmsg,
&upb_enumdef_EnumValueDescriptorProto_endmsg,
&upb_enumdef_EnumValueDescriptorProto_value,
};
upb_register_handlerset(h, &handlers);
upb_set_handler_closure(h, b, &b->status);
static void upb_enumdef_register_EnumValueDescriptorProto(upb_handlers *h) {
upb_register_startend(h, upb_enumdef_EnumValueDescriptorProto_startmsg,
upb_enumdef_EnumValueDescriptorProto_endmsg);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNUM,
GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDTYPE,
&upb_enumdef_EnumValueDescriptorProto_name, UPB_NO_VALUE);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNUM,
GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDTYPE,
&upb_enumdef_EnumValueDescriptorProto_number, UPB_NO_VALUE);
}
// google.protobuf.EnumDescriptorProto.
@ -534,61 +510,43 @@ static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_b) {
return UPB_CONTINUE;
}
static upb_flow_t upb_enumdef_EnumDescriptorProto_endmsg(void *_b) {
static void upb_enumdef_EnumDescriptorProto_endmsg(void *_b, upb_status *status) {
upb_defbuilder *b = _b;
upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
if (upb_defbuilder_last((upb_defbuilder*)_b)->fqname == NULL) {
upb_seterr(&b->status, UPB_ERROR, "Enum had no name.");
return UPB_BREAK;
upb_seterr(status, UPB_ERROR, "Enum had no name.");
return;
}
if (upb_inttable_count(&e->iton) == 0) {
upb_seterr(&b->status, UPB_ERROR, "Enum had no values.");
return UPB_BREAK;
upb_seterr(status, UPB_ERROR, "Enum had no values.");
return;
}
return UPB_CONTINUE;
}
static upb_flow_t upb_enumdef_EnumDescriptorProto_value(void *_b,
upb_fielddef *f,
upb_value val) {
static upb_flow_t upb_enumdef_EnumDescriptorProto_name(void *_b,
upb_value fval,
upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_FIELDNUM: {
upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
upb_string_unref(e->base.fqname);
e->base.fqname = upb_string_getref(upb_value_getstr(val));
return UPB_CONTINUE;
}
case GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNUM:
return BEGIN_SUBMSG;
default:
return UPB_CONTINUE;
}
upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
upb_string_unref(e->base.fqname);
e->base.fqname = upb_string_getref(upb_value_getstr(val));
return UPB_CONTINUE;
}
static upb_flow_t upb_enumdef_EnumDescriptorProto_startsubmsg(void *_b,
upb_fielddef *f,
upb_handlers *h) {
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_FIELDNUM:
upb_enumdef_register_EnumValueDescriptorProto(b, h);
return UPB_DELEGATE;
default:
return UPB_SKIPSUBMSG;
}
}
static void upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) {
upb_register_startend(h, &upb_enumdef_EnumDescriptorProto_startmsg,
&upb_enumdef_EnumDescriptorProto_endmsg);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNUM,
GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDTYPE,
&upb_enumdef_EnumDescriptorProto_name, UPB_NO_VALUE);
static void upb_enumdef_register_EnumDescriptorProto(upb_defbuilder *b,
upb_handlers *h) {
static upb_handlerset handlers = {
&upb_enumdef_EnumDescriptorProto_startmsg,
&upb_enumdef_EnumDescriptorProto_endmsg,
&upb_enumdef_EnumDescriptorProto_value,
&upb_enumdef_EnumDescriptorProto_startsubmsg,
};
upb_register_handlerset(h, &handlers);
upb_set_handler_closure(h, b, &b->status);
upb_handlers_typed_push(h,
GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNUM,
GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDTYPE);
upb_enumdef_register_EnumValueDescriptorProto(h);
upb_handlers_typed_pop(h);
}
upb_enum_iter upb_enum_begin(upb_enumdef *e) {
@ -650,7 +608,7 @@ static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) {
upb_string *str = upb_value_getstr(f->default_value);
assert(str); // Should point to either a real default or the empty string.
upb_enumdef *e = upb_downcast_enumdef(f->def);
upb_enumval_t val;
upb_enumval_t val = 0;
if (str == upb_emptystring()) {
upb_value_setint32(&f->default_value, e->default_value);
} else {
@ -776,7 +734,7 @@ static bool upb_fielddef_setdefault(upb_string *dstr, upb_value *d, int type) {
return success;
}
static upb_flow_t upb_fielddef_endmsg(void *_b) {
static void upb_fielddef_endmsg(void *_b, upb_status *status) {
upb_defbuilder *b = _b;
upb_fielddef *f = b->f;
// TODO: verify that all required fields were present.
@ -795,53 +753,87 @@ static upb_flow_t upb_fielddef_endmsg(void *_b) {
if (!upb_fielddef_setdefault(dstr, &f->default_value, f->type)) {
// We don't worry too much about giving a great error message since the
// compiler should have ensured this was correct.
upb_seterr(&b->status, UPB_ERROR, "Error converting default value.");
return UPB_BREAK;
upb_seterr(status, UPB_ERROR, "Error converting default value.");
return;
}
}
static upb_flow_t upb_fielddef_ontype(void *_b, upb_value fval, upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
b->f->type = upb_value_getint32(val);
return UPB_CONTINUE;
}
static upb_flow_t upb_fielddef_value(void *_b, upb_fielddef *f, upb_value val) {
static upb_flow_t upb_fielddef_onlabel(void *_b, upb_value fval, upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNUM:
b->f->type = upb_value_getint32(val);
break;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNUM:
b->f->label = upb_value_getint32(val);
break;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNUM:
b->f->number = upb_value_getint32(val);
break;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_FIELDNUM:
upb_string_unref(b->f->name);
b->f->name = upb_string_getref(upb_value_getstr(val));
break;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_FIELDNUM: {
upb_def_unref(b->f->def);
b->f->def = UPB_UPCAST(upb_unresolveddef_new(upb_value_getstr(val)));
b->f->owned = true;
break;
}
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_FIELDNUM:
// Have to convert from string to the correct type, but we might not know
// the type yet.
upb_string_unref(b->default_string);
b->default_string = upb_string_getref(upb_value_getstr(val));
break;
}
b->f->label = upb_value_getint32(val);
return UPB_CONTINUE;
}
static upb_flow_t upb_fielddef_onnumber(void *_b, upb_value fval, upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
b->f->number = upb_value_getint32(val);
return UPB_CONTINUE;
}
static upb_flow_t upb_fielddef_onname(void *_b, upb_value fval, upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
upb_string_unref(b->f->name);
b->f->name = upb_string_getref(upb_value_getstr(val));
return UPB_CONTINUE;
}
static upb_flow_t upb_fielddef_ontypename(void *_b, upb_value fval,
upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
upb_def_unref(b->f->def);
b->f->def = UPB_UPCAST(upb_unresolveddef_new(upb_value_getstr(val)));
b->f->owned = true;
return UPB_CONTINUE;
}
static upb_flow_t upb_fielddef_ondefaultval(void *_b, upb_value fval,
upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
// Have to convert from string to the correct type, but we might not know the
// type yet.
upb_string_unref(b->default_string);
b->default_string = upb_string_getref(upb_value_getstr(val));
return UPB_CONTINUE;
}
static void upb_fielddef_register_FieldDescriptorProto(upb_defbuilder *b,
upb_handlers *h) {
static upb_handlerset handlers = {
&upb_fielddef_startmsg,
&upb_fielddef_endmsg,
&upb_fielddef_value,
};
upb_register_handlerset(h, &handlers);
upb_set_handler_closure(h, b, &b->status);
static void upb_fielddef_register_FieldDescriptorProto(upb_handlers *h) {
upb_register_startend(h, upb_fielddef_startmsg, upb_fielddef_endmsg);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNUM,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDTYPE,
&upb_fielddef_ontype, UPB_NO_VALUE);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNUM,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDTYPE,
&upb_fielddef_onlabel, UPB_NO_VALUE);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNUM,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDTYPE,
&upb_fielddef_onnumber, UPB_NO_VALUE);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNUM,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDTYPE,
&upb_fielddef_onname, UPB_NO_VALUE);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNUM,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDTYPE,
&upb_fielddef_ontypename, UPB_NO_VALUE);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNUM,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDTYPE,
&upb_fielddef_ondefaultval, UPB_NO_VALUE);
}
@ -874,12 +866,12 @@ static upb_flow_t upb_msgdef_startmsg(void *_b) {
return UPB_CONTINUE;
}
static upb_flow_t upb_msgdef_endmsg(void *_b) {
static void upb_msgdef_endmsg(void *_b, upb_status *status) {
upb_defbuilder *b = _b;
upb_msgdef *m = upb_defbuilder_top(b);
if(!m->base.fqname) {
upb_seterr(&b->status, UPB_ERROR, "Encountered message with no name.");
return UPB_BREAK;
upb_seterr(status, UPB_ERROR, "Encountered message with no name.");
return;
}
upb_inttable_compact(&m->itof);
@ -944,58 +936,44 @@ static upb_flow_t upb_msgdef_endmsg(void *_b) {
}
upb_defbuilder_endcontainer(b);
return UPB_CONTINUE;
}
static upb_flow_t upb_msgdef_value(void *_b, upb_fielddef *f, upb_value val) {
static upb_flow_t upb_msgdef_onname(void *_b, upb_value fval, upb_value val) {
(void)fval;
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_FIELDNUM: {
assert(val.type == UPB_TYPE(STRING));
upb_msgdef *m = upb_defbuilder_top(b);
upb_string_unref(m->base.fqname);
m->base.fqname = upb_string_getref(upb_value_getstr(val));
upb_defbuilder_setscopename(b, upb_value_getstr(val));
return UPB_CONTINUE;
}
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNUM:
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNUM:
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNUM:
return BEGIN_SUBMSG;
default:
// TODO: extensions.
return UPB_CONTINUE;
}
assert(val.type == UPB_TYPE(STRING));
upb_msgdef *m = upb_defbuilder_top(b);
upb_string_unref(m->base.fqname);
m->base.fqname = upb_string_getref(upb_value_getstr(val));
upb_defbuilder_setscopename(b, upb_value_getstr(val));
return UPB_CONTINUE;
}
static upb_flow_t upb_msgdef_startsubmsg(void *_b, upb_fielddef *f,
upb_handlers *h) {
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_FIELDNUM:
upb_fielddef_register_FieldDescriptorProto(b, h);
return UPB_DELEGATE;
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_FIELDNUM:
upb_msgdef_register_DescriptorProto(b, h);
return UPB_DELEGATE;
case GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_FIELDNUM:
upb_enumdef_register_EnumDescriptorProto(b, h);
return UPB_DELEGATE;
default:
return UPB_SKIPSUBMSG;
}
}
static void upb_msgdef_register_DescriptorProto(upb_handlers *h) {
upb_register_startend(h, &upb_msgdef_startmsg, &upb_msgdef_endmsg);
upb_register_typed_value(h,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNUM,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDTYPE,
&upb_msgdef_onname, UPB_NO_VALUE);
upb_handlers_typed_push(h,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNUM,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDTYPE);
upb_fielddef_register_FieldDescriptorProto(h);
upb_handlers_typed_pop(h);
// DescriptorProto is self-recursive, so we must link the definition.
upb_handlers_typed_link(h,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNUM,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDTYPE, 0);
static void upb_msgdef_register_DescriptorProto(upb_defbuilder *b,
upb_handlers *h) {
static upb_handlerset handlers = {
&upb_msgdef_startmsg,
&upb_msgdef_endmsg,
&upb_msgdef_value,
&upb_msgdef_startsubmsg,
};
upb_register_handlerset(h, &handlers);
upb_set_handler_closure(h, b, &b->status);
upb_handlers_typed_push(h,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNUM,
GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE);
upb_enumdef_register_EnumDescriptorProto(h);
upb_handlers_typed_pop(h);
// TODO: extensions.
}
static void upb_msgdef_free(upb_msgdef *m)
@ -1185,8 +1163,8 @@ bool upb_resolverefs(upb_strtable *tmptab, upb_strtable *symtab,
// indicating whether the new defs can overwrite existing defs in the symtab,
// attempts to add the given defs to the symtab. The whole operation either
// succeeds or fails. Ownership of "defs" and "exts" is taken.
bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs,
bool allow_redef, upb_status *status)
static bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs,
bool allow_redef, upb_status *status)
{
upb_rwlock_wrlock(&s->lock);
@ -1325,232 +1303,3 @@ upb_def *upb_symtab_resolve(upb_symtab *s, upb_string *base, upb_string *symbol)
upb_rwlock_unlock(&s->lock);
return ret;
}
void upb_symtab_addfds(upb_symtab *s, upb_src *src, upb_status *status)
{
upb_defbuilder b;
upb_defbuilder_init(&b);
upb_handlers handlers;
upb_handlers_init(&handlers);
upb_defbuilder_register_FileDescriptorSet(&b, &handlers);
upb_src_sethandlers(src, &handlers);
upb_src_run(src, status);
if (upb_ok(status))
upb_symtab_add_defs(s, b.defs.defs, b.defs.len, false, status);
upb_defbuilder_uninit(&b);
upb_handlers_uninit(&handlers);
}
/* upb_baredecoder ************************************************************/
// upb_baredecoder is a upb_src that can parse a subset of the protocol buffer
// binary format. It is only used for bootstrapping. It can parse without
// having a upb_msgdef, which is why it is useful for bootstrapping the first
// msgdef. On the downside, it does not support:
//
// * having its input span multiple upb_strings.
// * reading any field of the returned upb_fielddef's except f->number.
// * keeping a pointer to the upb_fielddef* and reading it later (the same
// upb_fielddef is reused over and over).
// * detecting errors in the input (we trust that our input is known-good).
// * skipping the rest of the submessage (UPB_SKIPSUBMSG).
//
// It also does not support any of the follow protobuf features:
// * packed fields.
// * groups.
// * zig-zag-encoded types like sint32 and sint64.
//
// Since it cannot tell the difference between submessages and strings, it
// always reports them as strings first, but if the value callback returns
// UPB_TREAT_AS_SUBMSG this signals to the baredecoder that it should be
// treated like a submessage instead.
//
// TODO: for bootstrapping we should define a slightly different wire format
// that includes enough information to know the precise integer types and
// that distinguishes between strings and submessages. This will allow
// us to get rid of the UPB_TREAT_AS_SUBMSG hack. It will also allow us
// to get rid of the upb_value_setraw() scheme, which would be more
// complicated to support on big-endian machines.
typedef struct {
upb_src src;
upb_string *input;
upb_strlen_t offset;
upb_dispatcher dispatcher;
} upb_baredecoder;
static uint64_t upb_baredecoder_readv64(upb_baredecoder *d)
{
const uint8_t *start = (uint8_t*)upb_string_getrobuf(d->input) + d->offset;
const uint8_t *buf = start;
uint8_t last = 0x80;
uint64_t val = 0;
for(int bitpos = 0; (last & 0x80); buf++, bitpos += 7)
val |= ((uint64_t)((last = *buf) & 0x7F)) << bitpos;
d->offset += buf - start;
return val;
}
static uint32_t upb_baredecoder_readv32(upb_baredecoder *d)
{
return (uint32_t)upb_baredecoder_readv64(d); // Truncate.
}
static uint64_t upb_baredecoder_readf64(upb_baredecoder *d)
{
uint64_t val;
memcpy(&val, upb_string_getrobuf(d->input) + d->offset, 8);
d->offset += 8;
return val;
}
static uint32_t upb_baredecoder_readf32(upb_baredecoder *d)
{
uint32_t val;
memcpy(&val, upb_string_getrobuf(d->input) + d->offset, 4);
d->offset += 4;
return val;
}
static void upb_baredecoder_sethandlers(upb_src *src, upb_handlers *handlers) {
upb_baredecoder *d = (upb_baredecoder*)src;
upb_dispatcher_reset(&d->dispatcher, handlers, false);
}
static void upb_baredecoder_run(upb_src *src, upb_status *status) {
upb_baredecoder *d = (upb_baredecoder*)src;
assert(!upb_handlers_isempty(&d->dispatcher.top->handlers));
upb_string *str = NULL;
upb_strlen_t stack[UPB_MAX_NESTING] = {UPB_STRLEN_MAX};
upb_strlen_t *top = &stack[0];
d->offset = 0;
#define CHECK(x) if (x != UPB_CONTINUE && x != BEGIN_SUBMSG) goto err;
CHECK(upb_dispatch_startmsg(&d->dispatcher));
while(d->offset < upb_string_len(d->input)) {
uint32_t key = upb_baredecoder_readv64(d);
upb_fielddef f;
f.number = key >> 3;
upb_wire_type_t wt = key & 0x7;
if(wt == UPB_WIRE_TYPE_DELIMITED) {
uint32_t delim_len = upb_baredecoder_readv32(d);
// We don't know if it's a string or a submessage; deliver first as
// string.
upb_string_recycle(&str);
upb_string_substr(str, d->input, d->offset, delim_len);
upb_value v;
upb_value_setstr(&v, str);
upb_flow_t ret = upb_dispatch_value(&d->dispatcher, &f, v);
CHECK(ret);
if(ret == BEGIN_SUBMSG) {
// Should deliver as a submessage instead.
CHECK(upb_dispatch_startsubmsg(&d->dispatcher, &f));
*(++top) = d->offset + delim_len;
} else {
d->offset += delim_len;
}
} else {
upb_value v;
switch(wt) {
case UPB_WIRE_TYPE_VARINT:
upb_value_setraw(&v, upb_baredecoder_readv64(d));
break;
case UPB_WIRE_TYPE_64BIT:
upb_value_setraw(&v, upb_baredecoder_readf64(d));
break;
case UPB_WIRE_TYPE_32BIT:
upb_value_setraw(&v, upb_baredecoder_readf32(d));
break;
default:
assert(false);
abort();
}
CHECK(upb_dispatch_value(&d->dispatcher, &f, v));
}
// Detect end-of-submessage.
while(d->offset >= *top) {
CHECK(upb_dispatch_endsubmsg(&d->dispatcher, &f));
d->offset = *(top--);
}
}
CHECK(upb_dispatch_endmsg(&d->dispatcher));
upb_string_unref(str);
return;
err:
upb_copyerr(status, d->dispatcher.top->handlers.status);
upb_string_unref(str);
}
static upb_baredecoder *upb_baredecoder_new(upb_string *str) {
static upb_src_vtbl vtbl = {
&upb_baredecoder_sethandlers,
&upb_baredecoder_run,
};
upb_baredecoder *d = malloc(sizeof(*d));
upb_src_init(&d->src, &vtbl);
d->input = upb_string_getref(str);
d->offset = 0;
upb_dispatcher_init(&d->dispatcher);
return d;
}
static void upb_baredecoder_free(upb_baredecoder *d) {
upb_string_unref(d->input);
free(d);
}
static upb_src *upb_baredecoder_src(upb_baredecoder *d) {
return &d->src;
}
static upb_symtab *descriptor_symtab = NULL;
static void upb_free_descriptor_symtab() {
if (descriptor_symtab) {
// There should be no way for anyone to acquire a ref on this symtab.
assert(upb_atomic_only(&descriptor_symtab->refcount));
_upb_symtab_free(descriptor_symtab);
descriptor_symtab = NULL;
}
}
upb_def *upb_getdescriptordef(upb_string *str) {
// TODO: add locking.
if (descriptor_symtab == NULL) {
descriptor_symtab = upb_symtab_new();
static upb_string descriptor_str =
UPB_STATIC_STRING_ARRAY(descriptor_pb);
upb_baredecoder *decoder = upb_baredecoder_new(&descriptor_str);
upb_status status = UPB_STATUS_INIT;
upb_symtab_addfds(descriptor_symtab, upb_baredecoder_src(decoder), &status);
upb_baredecoder_free(decoder);
if(!upb_ok(&status)) {
// upb itself is corrupt.
upb_printerr(&status);
upb_clearerr(&status);
abort();
}
upb_status_uninit(&status);
// As a sanity check, make sure that FileDescriptorSet was loaded.
upb_msgdef *def = upb_getfdsdef();
if (!def) {
// upb itself is corrupt.
abort();
}
upb_msgdef_unref(def); // The symtab already holds a ref on it.
atexit(upb_free_descriptor_symtab);
}
return upb_symtab_resolve(
descriptor_symtab, UPB_STRLIT("google.protobuf"), str);
}
upb_msgdef *upb_getfdsdef() {
return upb_downcast_msgdef(
upb_getdescriptordef(UPB_STRLIT("FileDescriptorSet")));
}

@ -28,7 +28,6 @@
#define UPB_DEF_H_
#include "upb_atomic.h"
#include "upb_stream.h"
#include "upb_table.h"
#ifdef __cplusplus
@ -90,7 +89,7 @@ INLINE void upb_def_unref(upb_def *def) {
// in the sense that it derives from upb_def. It cannot stand on its own; it
// is either a field of a upb_msgdef or contained inside a upb_extensiondef.
// It is also reference-counted.
typedef struct _upb_fielddef {
struct _upb_fielddef {
uint8_t type;
uint8_t label;
// True if we own a ref on "def" (above). This is true unless this edge is
@ -111,11 +110,14 @@ typedef struct _upb_fielddef {
// For the case of an enum or a submessage, points to the def for that type.
upb_def *def;
upb_atomic_refcount_t refcount;
} upb_fielddef;
};
// A variety of tests about the type of a field.
INLINE bool upb_issubmsgtype(upb_fieldtype_t type) {
return type == UPB_TYPE(GROUP) || type == UPB_TYPE(MESSAGE);
}
INLINE bool upb_issubmsg(upb_fielddef *f) {
return f->type == UPB_TYPE(GROUP) || f->type == UPB_TYPE(MESSAGE);
return upb_issubmsgtype(f->type);
}
INLINE bool upb_isstring(upb_fielddef *f) {
return f->type == UPB_TYPE(STRING) || f->type == UPB_TYPE(BYTES);
@ -225,6 +227,7 @@ INLINE upb_fielddef *upb_msg_iter_field(upb_msg_iter iter) {
return ent->f;
}
/* upb_enumdef ****************************************************************/
typedef int32_t upb_enumval_t;
@ -274,8 +277,8 @@ INLINE int32_t upb_enum_iter_number(upb_enum_iter iter) {
/* upb_symtab *****************************************************************/
// A SymbolTable is where upb_defs live. It is empty when first constructed.
// Clients add definitions to the symtab by supplying unserialized or
// serialized descriptors (as defined in descriptor.proto).
// Clients add definitions to the symtab by supplying descriptors (as defined
// in descriptor.proto) via the upb_stream interface.
struct _upb_symtab {
upb_atomic_refcount_t refcount;
upb_rwlock_t lock; // Protects all members except the refcount.
@ -284,7 +287,7 @@ struct _upb_symtab {
};
typedef struct _upb_symtab upb_symtab;
// Initializes a upb_symtab. Contexts are not freed explicitly, but unref'd
// Initializes a upb_symtab. Symtabs are not freed explicitly, but unref'd
// when the caller is done with them.
upb_symtab *upb_symtab_new(void);
void _upb_symtab_free(upb_symtab *s); // Must not be called directly!
@ -316,33 +319,22 @@ upb_def *upb_symtab_lookup(upb_symtab *s, upb_string *sym);
// returned, otherwise only defs of the required type are returned.
upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type);
// "fds" is a upb_src that will yield data from the
// google.protobuf.FileDescriptorSet message type. It is not necessary that
// the upb_def for FileDescriptorSet came from this symtab, but it must be
// compatible with the official descriptor.proto, as published by Google.
//
// upb_symtab_addfds() adds all the definitions from the given
// FileDescriptorSet and adds them to the symtab. status indicates whether the
// operation was successful or not, and the error message (if any).
// upb_defbuilder: For adding defs to the symtab.
// You allocate the defbuilder, which can handle a single descriptor.
// It will be freed automatically when the parse completes.
struct _upb_defbuilder;
typedef struct _upb_defbuilder upb_defbuilder;
struct _upb_handlers;
// Allocates a new defbuilder that will add defs to the given symtab.
upb_defbuilder *upb_defbuilder_new(upb_symtab *s);
// Registers handlers that will operate on a defbuilder to add the defs
// to the defbuilder's symtab. Will free itself when the parse finishes.
//
// TODO: should this allow redefinition? Either is possible, but which is
// more useful? Maybe it should be an option.
void upb_symtab_addfds(upb_symtab *s, upb_src *desc, upb_status *status);
// Returns a def corresponding to the given name, from descriptor.proto.
// upb internally bootstraps the defs in descriptor.proto, since they are
// necessary for loading other descriptors. The caller owns a ref on the
// returned def (which is NULL if no such def exists in descriptor.proto).
//
// The name should *not* be qualified by the package, to promote
// interoperability between the internal and external releases of Protocol
// Buffers (inside Google, these are in the "proto2" package, externally they
// are in "google.protobuf".
upb_def *upb_getdescriptordef(upb_string *str);
// A convenience method for getting the upb_def for FileDescriptorProto.
// Return should never be NULL.
upb_msgdef *upb_getfdsdef();
void upb_defbuilder_reghandlers(struct _upb_handlers *h);
/* upb_def casts **************************************************************/

@ -14,7 +14,7 @@
#define UPB_ENCODER_H_
#include "upb.h"
#include "upb_srcsink.h"
#include "upb_stream.h"
#ifdef __cplusplus
extern "C" {

@ -16,25 +16,18 @@ void upb_strtomsg(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str);
upb_decoder d;
upb_decoder_init(&d, md);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc));
upb_src *src = upb_decoder_src(&d);
upb_msgpopulator p;
upb_msgpopulator_init(&p);
upb_msgpopulator_reset(&p, msg, md);
upb_handlers h;
upb_handlers_init(&h);
upb_msgpopulator_register_handlers(&p, &h);
upb_src_sethandlers(src, &h);
upb_handlers_init(&h, md);
upb_msg_regdhandlers(&h);
upb_decoder d;
upb_decoder_init(&d, &h);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), msg);
upb_src_run(src, status);
upb_decoder_decode(&d, status);
upb_stringsrc_uninit(&strsrc);
upb_decoder_uninit(&d);
upb_msgpopulator_uninit(&p);
upb_handlers_uninit(&h);
}
@ -46,11 +39,12 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_textprinter *p = upb_textprinter_new();
upb_handlers h;
upb_handlers_init(&h);
upb_textprinter_reset(p, &h, upb_stringsink_bytesink(&strsink), single_line);
upb_handlers_init(&h, md);
upb_textprinter_reghandlers(&h);
upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line);
upb_status status = UPB_STATUS_INIT;
upb_msg_runhandlers(msg, md, &h, &status);
upb_msg_runhandlers(msg, md, &h, p, &status);
// None of {upb_msg_runhandlers, upb_textprinter, upb_stringsink} should be
// capable of returning an error.
assert(upb_ok(&status));
@ -66,13 +60,18 @@ void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) {
upb_stringsrc_init(&strsrc);
upb_stringsrc_reset(&strsrc, str);
upb_handlers h;
upb_handlers_init(&h, NULL);
upb_defbuilder_reghandlers(&h);
upb_decoder d;
upb_msgdef *fds_msgdef = upb_getfdsdef();
upb_decoder_init(&d, fds_msgdef);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc));
upb_decoder_init(&d, &h);
upb_defbuilder *b = upb_defbuilder_new(symtab);
upb_decoder_reset(&d, upb_stringsrc_bytesrc(&strsrc), b);
upb_symtab_addfds(symtab, upb_decoder_src(&d), status);
upb_decoder_decode(&d, status);
upb_handlers_uninit(&h);
upb_stringsrc_uninit(&strsrc);
upb_decoder_uninit(&d);
upb_def_unref(UPB_UPCAST(fds_msgdef));
}

@ -7,8 +7,6 @@
*/
#include "upb_msg.h"
#include "upb_decoder.h"
#include "upb_strstream.h"
static uint32_t upb_round_up_pow2(uint32_t v) {
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
@ -181,75 +179,66 @@ upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) {
}
static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md,
upb_dispatcher *d, upb_status *s);
upb_dispatcher *d);
static upb_flow_t upb_msg_pushval(upb_value val, upb_fielddef *f,
upb_dispatcher *d, upb_status *s) {
upb_dispatcher *d, upb_handlers_fieldent *hf) {
#define CHECK_FLOW(x) do { \
flow = x; if (flow != UPB_CONTINUE) return flow; \
upb_flow_t flow = x; if (flow != UPB_CONTINUE) return flow; \
} while(0)
// For when a SKIP can be implemented just through an early return.
#define CHECK_FLOW_LOCAL(x) do { \
flow = x; \
upb_flow_t flow = x; \
if (flow != UPB_CONTINUE) { \
if (flow == UPB_SKIPSUBMSG) flow = UPB_CONTINUE; \
goto end; \
return flow; \
} \
} while (0)
upb_flow_t flow;
if (upb_issubmsg(f)) {
upb_msg *msg = upb_value_getmsg(val);
CHECK_FLOW_LOCAL(upb_dispatch_startsubmsg(d, f));
CHECK_FLOW_LOCAL(upb_msg_dispatch(msg, upb_downcast_msgdef(f->def), d, s));
CHECK_FLOW(upb_dispatch_endsubmsg(d, f));
CHECK_FLOW_LOCAL(upb_dispatch_startsubmsg(d, hf, 0));
CHECK_FLOW_LOCAL(upb_msg_dispatch(msg, upb_downcast_msgdef(f->def), d));
CHECK_FLOW(upb_dispatch_endsubmsg(d));
} else {
CHECK_FLOW(upb_dispatch_value(d, f, val));
CHECK_FLOW(upb_dispatch_value(d, hf, val));
}
end:
return flow;
return UPB_CONTINUE;
}
static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md,
upb_dispatcher *d, upb_status *s) {
upb_dispatcher *d) {
upb_msg_iter i;
upb_flow_t flow;
for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
upb_fielddef *f = upb_msg_iter_field(i);
if (!upb_msg_has(msg, f)) continue;
upb_handlers_fieldent *hf = upb_dispatcher_lookup(d, f->number);
if (!hf) continue;
upb_value val = upb_msg_get(msg, f);
if (upb_isarray(f)) {
upb_array *arr = upb_value_getarr(val);
for (uint32_t j = 0; j < upb_array_len(arr); ++j) {
CHECK_FLOW_LOCAL(upb_msg_pushval(upb_array_get(arr, f, j), f, d, s));
CHECK_FLOW_LOCAL(upb_msg_pushval(upb_array_get(arr, f, j), f, d, hf));
}
} else {
CHECK_FLOW_LOCAL(upb_msg_pushval(val, f, d, s));
CHECK_FLOW_LOCAL(upb_msg_pushval(val, f, d, hf));
}
}
return UPB_CONTINUE;
end:
// Need to copy/massage the error.
upb_copyerr(s, d->top->handlers.status);
if (upb_ok(s)) {
upb_seterr(s, UPB_ERROR, "Callback returned UPB_BREAK");
}
return flow;
#undef CHECK_FLOW
#undef CHECK_FLOW_LOCAL
}
void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h,
upb_status *status) {
void *closure, upb_status *status) {
upb_dispatcher d;
upb_dispatcher_init(&d);
upb_dispatcher_reset(&d, h, true);
upb_dispatcher_init(&d, h, 0);
if (upb_dispatch_startmsg(&d) != UPB_CONTINUE) return;
if (upb_msg_dispatch(msg, md, &d, status) != UPB_CONTINUE) return;
if (upb_dispatch_endmsg(&d) != UPB_CONTINUE) return;
upb_dispatch_startmsg(&d, closure);
upb_msg_dispatch(msg, md, &d);
upb_dispatch_endmsg(&d, status);
upb_dispatcher_uninit(&d);
}
static upb_valueptr upb_msg_getappendptr(upb_msg *msg, upb_fielddef *f) {
@ -283,7 +272,7 @@ static void upb_msg_appendval(upb_msg *msg, upb_fielddef *f, upb_value val) {
// If you were using this to copy one upb_msg to another this would
// allocate string objects whereas a upb_string_getref could have avoided
// those allocations completely; if this is an issue, we could make it an
// option of the upb_msgpopulator which behavior is desired.
// option of the upb_msgsink which behavior is desired.
upb_string *src = upb_value_getstr(val);
upb_string_recycle(p.str);
upb_string_substr(*p.str, src, 0, upb_string_len(src));
@ -303,59 +292,28 @@ upb_msg *upb_msg_appendmsg(upb_msg *msg, upb_fielddef *f, upb_msgdef *msgdef) {
}
/* upb_msgpopulator ***********************************************************/
void upb_msgpopulator_init(upb_msgpopulator *p) {
upb_status_init(&p->status);
}
void upb_msgpopulator_reset(upb_msgpopulator *p, upb_msg *m, upb_msgdef *md) {
p->top = p->stack;
p->limit = p->stack + sizeof(p->stack);
p->top->msg = m;
p->top->msgdef = md;
}
void upb_msgpopulator_uninit(upb_msgpopulator *p) {
upb_status_uninit(&p->status);
}
/* upb_msg dynhandlers *******************************************************/
static upb_flow_t upb_msgpopulator_value(void *_p, upb_fielddef *f, upb_value val) {
upb_msgpopulator *p = _p;
upb_msg_appendval(p->top->msg, f, val);
static upb_flow_t upb_dmsgsink_value(void *_m, upb_value fval, upb_value val) {
upb_msg *m = _m;
upb_fielddef *f = upb_value_getfielddef(fval);
upb_msg_appendval(m, f, val);
return UPB_CONTINUE;
}
static upb_flow_t upb_msgpopulator_startsubmsg(void *_p, upb_fielddef *f,
upb_handlers *delegate_to) {
upb_msgpopulator *p = _p;
(void)delegate_to;
upb_msg *oldmsg = p->top->msg;
if (++p->top == p->limit) {
upb_seterr(&p->status, UPB_ERROR, "Exceeded maximum nesting");
return UPB_BREAK;
}
static upb_sflow_t upb_dmsgsink_startsubmsg(void *_m, upb_value fval) {
upb_msg *m = _m;
upb_fielddef *f = upb_value_getfielddef(fval);
upb_msgdef *msgdef = upb_downcast_msgdef(f->def);
p->top->msgdef = msgdef;
p->top->msg = upb_msg_appendmsg(oldmsg, f, msgdef);
return UPB_CONTINUE;
}
static upb_flow_t upb_msgpopulator_endsubmsg(void *_p, upb_fielddef *f) {
(void)f;
upb_msgpopulator *p = _p;
--p->top;
return UPB_CONTINUE;
return UPB_CONTINUE_WITH(upb_msg_appendmsg(m, f, msgdef));
}
void upb_msgpopulator_register_handlers(upb_msgpopulator *p, upb_handlers *h) {
static upb_handlerset handlerset = {
NULL, // startmsg
NULL, // endmsg
&upb_msgpopulator_value,
&upb_msgpopulator_startsubmsg,
&upb_msgpopulator_endsubmsg,
};
upb_register_handlerset(h, &handlerset);
upb_set_handler_closure(h, p, &p->status);
void upb_msg_regdhandlers(upb_handlers *h) {
upb_register_all(h,
NULL, // startmsg
NULL, // endmsg
&upb_dmsgsink_value,
&upb_dmsgsink_startsubmsg,
NULL, // endsubmsg
NULL); // unknown
}

@ -17,8 +17,7 @@
#ifndef UPB_MSG_H
#define UPB_MSG_H
#include "upb.h"
#include "upb_def.h"
#include "upb_stream.h"
#include <stdlib.h>
#ifdef __cplusplus
@ -274,26 +273,16 @@ INLINE void upb_msg_clear(upb_msg *msg, upb_msgdef *md) {
memset(msg->data, 0, md->set_flags_bytes);
}
// A non-resumable upb_src that pushes the current contents of the message to
// the given handlers.
// Registers handlers for populating a msg for the given upb_msgdef.
// The upb_msg itself must be passed as the param to the src.
void upb_msg_reghandlers(upb_handlers *h, upb_msgdef *md);
// Registers handlers that are suitable for populating a msg of *any*
// upb_msgdef ("dynamic" handlers). May be slower than upb_msg_reghandlers().
void upb_msg_regdhandlers(upb_handlers *h);
void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h,
upb_status *status);
typedef struct {
upb_msg *msg;
upb_msgdef *msgdef;
} upb_msgpopulator_frame;
typedef struct {
upb_msgpopulator_frame *top, *limit;
upb_status status;
upb_msgpopulator_frame stack[UPB_MAX_NESTING];
} upb_msgpopulator;
void upb_msgpopulator_init(upb_msgpopulator *p);
void upb_msgpopulator_uninit(upb_msgpopulator *p);
void upb_msgpopulator_reset(upb_msgpopulator *p, upb_msg *m, upb_msgdef *md);
void upb_msgpopulator_register_handlers(upb_msgpopulator *p, upb_handlers *h);
void *closure, upb_status *status);
#ifdef __cplusplus
} /* extern "C" */

@ -85,7 +85,6 @@ upb_stdio *upb_stdio_new() {
};
static upb_bytesink_vtbl bytesink_vtbl = {
NULL,
upb_stdio_putstr,
upb_stdio_vprintf
};

@ -0,0 +1,328 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2011 Joshua Haberman. See LICENSE for details.
*/
#include <stdlib.h>
#include "upb_stream.h"
/* upb_handlers ***************************************************************/
static upb_flow_t upb_startmsg_nop(void *closure) {
(void)closure;
return UPB_CONTINUE;
}
static void upb_endmsg_nop(void *closure, upb_status *status) {
(void)closure;
(void)status;
}
static upb_flow_t upb_value_nop(void *closure, upb_value fval, upb_value val) {
(void)closure;
(void)fval;
(void)val;
return UPB_CONTINUE;
}
static upb_sflow_t upb_startsubmsg_nop(void *closure, upb_value fval) {
(void)fval;
return UPB_CONTINUE_WITH(closure);
}
static upb_flow_t upb_endsubmsg_nop(void *closure, upb_value fval) {
(void)closure;
(void)fval;
return UPB_CONTINUE;
}
static upb_flow_t upb_unknownval_nop(void *closure, upb_field_number_t fieldnum,
upb_value val) {
(void)closure;
(void)fieldnum;
(void)val;
return UPB_CONTINUE;
}
static void upb_msgent_init(upb_handlers_msgent *e) {
upb_inttable_init(&e->fieldtab, 8, sizeof(upb_handlers_fieldent));
e->startmsg = &upb_startmsg_nop;
e->endmsg = &upb_endmsg_nop;
e->unknownval = &upb_unknownval_nop;
}
void upb_handlers_init(upb_handlers *h, upb_msgdef *md) {
h->msgs_len = 1;
h->msgs_size = 4;
h->msgs = malloc(h->msgs_size * sizeof(*h->msgs));
h->top = &h->stack[0];
h->limit = &h->stack[UPB_MAX_TYPE_DEPTH];
h->toplevel_msgdef = md;
if (md) upb_msgdef_ref(md);
h->top->msgent_index = 0;
h->top->msgdef = md;
h->msgent = &h->msgs[0];
upb_msgent_init(h->msgent);
}
void upb_handlers_uninit(upb_handlers *h) {
for (int i = 0; i < h->msgs_len; i++) upb_inttable_free(&h->msgs[i].fieldtab);
free(h->msgs);
upb_msgdef_unref(h->toplevel_msgdef);
}
static upb_handlers_fieldent *upb_handlers_getorcreate_without_fval(
upb_handlers *h, upb_field_number_t fieldnum, upb_fieldtype_t type) {
upb_handlers_fieldent *f =
upb_inttable_lookup(&h->msgent->fieldtab, fieldnum);
if (!f) {
upb_wire_type_t native_wire_type = upb_types[type].native_wire_type;
upb_handlers_fieldent new_f = {
false, type, native_wire_type, -1, UPB_NO_VALUE,
{&upb_value_nop}, &upb_endsubmsg_nop};
if (upb_issubmsgtype(type)) new_f.cb.startsubmsg = &upb_startsubmsg_nop;
upb_inttable_insert(&h->msgent->fieldtab, fieldnum, &new_f);
f = upb_inttable_lookup(&h->msgent->fieldtab, fieldnum);
assert(f);
}
assert(f->type == type);
return f;
}
static upb_handlers_fieldent *upb_handlers_getorcreate(
upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type, upb_value fval) {
upb_handlers_fieldent *f =
upb_handlers_getorcreate_without_fval(h, fieldnum, type);
f->fval = fval;
return f;
}
void upb_register_startend(upb_handlers *h, upb_startmsg_handler_t startmsg,
upb_endmsg_handler_t endmsg) {
h->msgent->startmsg = startmsg ? startmsg : &upb_startmsg_nop;
h->msgent->endmsg = endmsg ? endmsg : &upb_endmsg_nop;
}
// TODO:
// void upb_register_unknownval(upb_handlers *h,
// upb_unknownval_handler_t unknown);
// bool upb_handlers_link(upb_handlers *h, upb_fielddef *f);
// void upb_register_path_value(upb_handlers *h, const char *path,
// upb_value_handler_t value, upb_value fval);
void upb_register_all(upb_handlers *h, upb_startmsg_handler_t start,
upb_endmsg_handler_t end,
upb_value_handler_t value,
upb_startsubmsg_handler_t startsubmsg,
upb_endsubmsg_handler_t endsubmsg,
upb_unknownval_handler_t unknown) {
upb_register_startend(h, start, end);
//upb_register_unknownval(h, unknown);
upb_msgdef *m = h->top->msgdef;
upb_msg_iter i;
for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
upb_fielddef *f = upb_msg_iter_field(i);
upb_value fval;
upb_value_setfielddef(&fval, f);
if (upb_issubmsg(f)) {
upb_handlers_push(h, f, startsubmsg, endsubmsg, fval, false);
upb_register_all(h, start, end, value, startsubmsg, endsubmsg, unknown);
upb_handlers_pop(h, f);
} else {
upb_register_value(h, f, value, fval);
}
}
}
void upb_register_typed_value(upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type, upb_value_handler_t value,
upb_value fval) {
upb_handlers_getorcreate(h, fieldnum, type, fval)->cb.value =
value ? value : &upb_value_nop;
}
void upb_register_value(upb_handlers *h, upb_fielddef *f,
upb_value_handler_t value, upb_value fval) {
assert(f->msgdef == h->top->msgdef);
upb_register_typed_value(h, f->number, f->type, value, fval);
}
void upb_register_typed_submsg(upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type,
upb_startsubmsg_handler_t start,
upb_endsubmsg_handler_t end,
upb_value fval) {
upb_handlers_fieldent *f = upb_handlers_getorcreate(h, fieldnum, type, fval);
f->cb.startsubmsg = start ? start : &upb_startsubmsg_nop;
f->endsubmsg = end ? end : &upb_endsubmsg_nop;
}
void upb_handlers_typed_link(upb_handlers *h,
upb_field_number_t fieldnum,
upb_fieldtype_t type,
int frames) {
assert(frames <= (h->top - h->stack));
upb_handlers_fieldent *f =
upb_handlers_getorcreate_without_fval(h, fieldnum, type);
f->msgent_index = (h->top - frames)->msgent_index;
}
void upb_handlers_typed_push(upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type) {
upb_handlers_fieldent *f =
upb_handlers_getorcreate_without_fval(h, fieldnum, type);
if (h->top == h->limit) abort(); // TODO: make growable.
++h->top;
if (f->msgent_index == -1) {
// Need to push a new msgent.
if (h->msgs_size == h->msgs_len) {
h->msgs_size *= 2;
h->msgs = realloc(h->msgs, h->msgs_size * sizeof(*h->msgs));
}
f->msgent_index = h->msgs_len++;
h->msgent = &h->msgs[f->msgent_index];
upb_msgent_init(h->msgent);
} else {
h->msgent = &h->msgs[f->msgent_index];
}
h->top->msgent_index = f->msgent_index;
if (h->toplevel_msgdef) {
upb_fielddef *f = upb_msgdef_itof((h->top - 1)->msgdef, fieldnum);
assert(f);
h->top->msgdef = upb_downcast_msgdef(f->def);
}
}
void upb_handlers_push(upb_handlers *h, upb_fielddef *f,
upb_startsubmsg_handler_t start,
upb_endsubmsg_handler_t end, upb_value fval,
bool delegate) {
assert(f->msgdef == h->top->msgdef);
(void)delegate; // TODO
upb_register_typed_submsg(h, f->number, f->type, start, end, fval);
upb_handlers_typed_push(h, f->number, f->type);
}
void upb_handlers_typed_pop(upb_handlers *h) {
assert(h->top > h->stack);
--h->top;
h->msgent = &h->msgs[h->top->msgent_index];
}
void upb_handlers_pop(upb_handlers *h, upb_fielddef *f) {
(void)f; // TODO: Check that this matches the corresponding push.
upb_handlers_typed_pop(h);
}
/* upb_dispatcher *************************************************************/
static upb_handlers_fieldent toplevel_f = {
false, 0, 0, 0, // The one value that is actually read
#ifdef NDEBUG
{{0}},
#else
{{0}, UPB_VALUETYPE_RAW},
#endif
{NULL}, NULL};
void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h,
size_t top_end_offset) {
d->handlers = h;
for (int i = 0; i < h->msgs_len; i++)
upb_inttable_compact(&h->msgs[i].fieldtab);
d->stack[0].end_offset = top_end_offset;
d->stack[0].f = &toplevel_f;
upb_status_init(&d->status);
}
void upb_dispatcher_reset(upb_dispatcher *d) {
d->msgent = &d->handlers->msgs[0];
d->dispatch_table = &d->msgent->fieldtab;
d->current_depth = 0;
d->skip_depth = INT_MAX;
d->noframe_depth = INT_MAX;
d->delegated_depth = 0;
d->top = d->stack;
d->limit = &d->stack[UPB_MAX_NESTING];
}
void upb_dispatcher_uninit(upb_dispatcher *d) {
upb_status_uninit(&d->status);
}
void upb_dispatcher_break(upb_dispatcher *d) {
assert(d->skip_depth == INT_MAX);
assert(d->noframe_depth == INT_MAX);
d->noframe_depth = d->current_depth;
}
upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d, void *closure) {
d->top->closure = closure;
upb_flow_t flow = d->msgent->startmsg(closure);
if (flow != UPB_CONTINUE) {
d->noframe_depth = d->current_depth + 1;
d->skip_depth = (flow == UPB_BREAK) ? d->delegated_depth : d->current_depth;
return UPB_SKIPSUBMSG;
}
return UPB_CONTINUE;
}
void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status) {
assert(d->top == d->stack);
d->msgent->endmsg(d->top->closure, &d->status);
// TODO: should we avoid this copy by passing client's status obj to cbs?
upb_copyerr(status, &d->status);
}
upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d,
upb_dispatcher_field *f,
size_t userval) {
++d->current_depth;
if (upb_dispatcher_skipping(d)) return UPB_SKIPSUBMSG;
upb_sflow_t sflow = f->cb.startsubmsg(d->top->closure, f->fval);
if (sflow.flow != UPB_CONTINUE) {
d->noframe_depth = d->current_depth;
d->skip_depth = (sflow.flow == UPB_BREAK) ?
d->delegated_depth : d->current_depth;
return UPB_SKIPSUBMSG;
}
++d->top;
if(d->top >= d->limit) {
upb_seterr(&d->status, UPB_ERROR, "Nesting too deep.");
d->noframe_depth = d->current_depth;
d->skip_depth = d->delegated_depth;
return UPB_SKIPSUBMSG;
}
d->top->f = f;
d->top->end_offset = userval;
d->top->closure = sflow.closure;
d->msgent = upb_handlers_getmsgent(d->handlers, f);
d->dispatch_table = &d->msgent->fieldtab;
return upb_dispatch_startmsg(d, d->top->closure);
}
upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d) {
upb_flow_t flow;
if (upb_dispatcher_noframe(d)) {
flow = UPB_SKIPSUBMSG;
} else {
assert(d->top > d->stack);
upb_dispatcher_field *old_f = d->top->f;
d->msgent->endmsg(d->top->closure, &d->status);
--d->top;
d->msgent = upb_handlers_getmsgent(d->handlers, d->top->f);
d->dispatch_table = &d->msgent->fieldtab;
d->noframe_depth = INT_MAX;
if (!upb_dispatcher_skipping(d)) d->skip_depth = INT_MAX;
// Deliver like a regular value.
flow = old_f->endsubmsg(d->top->closure, old_f->fval);
}
--d->current_depth;
return flow;
}

@ -1,26 +1,12 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
* This file defines four general-purpose streaming data interfaces.
* This file defines general-purpose streaming data interfaces:
*
* - upb_handlers: represents a set of callbacks, very much like in XML's SAX
* API, that a client can register to do a streaming tree traversal over a
* stream of structured protobuf data, without knowing where that data is
* coming from. There is only one upb_handlers type (it is not a virtual
* base class), but the object lets you register any set of handlers.
*
* The upb_handlers interface supports delegation: when entering a submessage,
* you can delegate to another set of upb_handlers instead of handling the
* submessage yourself. This allows upb_handlers objects to *compose* -- you
* can implement a set of upb_handlers without knowing or caring whether this
* is the top-level message or not.
*
* The other interfaces are the C equivalent of "virtual base classes" that
* anyone can implement:
*
* - upb_src: an interface that represents a source of streaming protobuf data.
* It lets you register a set of upb_handlers, and then call upb_src_run(),
* which pulls the protobuf data from somewhere and then calls the handlers.
* coming from.
*
* - upb_bytesrc: a pull interface for streams of bytes, basically an
* abstraction of read()/fread(), but it avoids copies where possible.
@ -42,92 +28,149 @@
#ifndef UPB_STREAM_H
#define UPB_STREAM_H
#include <limits.h>
#include "upb.h"
#include "upb_def.h"
#ifdef __cplusplus
extern "C" {
#endif
// Forward-declare. We can't include upb_def.h; it would be circular.
struct _upb_fielddef;
/* upb_handlers ***************************************************************/
// upb_handlers define the interface by which a upb_src passes data to a
// upb_sink.
// A upb_handlers object is a table of callbacks that are bound to specific
// messages and fields. A consumer of data registers callbacks and then
// passes the upb_handlers object to the producer, which calls them at the
// appropriate times.
// Constants that a handler returns to indicate to its caller whether it should
// continue or not.
// All handlers except the endmsg handler return a value from this enum, to
// control whether parsing will continue or not.
typedef enum {
// Caller should continue sending values to the sink.
// Data source should continue calling callbacks.
UPB_CONTINUE = 0,
// Stop processing for now; check status for details. If no status was set,
// a generic error will be returned. If the error is resumable, it is not
// (yet) defined where processing will resume -- waiting for real-world
// examples of resumable decoders and resume-requiring clients. upb_src
// implementations that are not capable of resuming will override the return
// status to be non-resumable if a resumable status was set by the handlers.
// Halt processing permanently (in a non-resumable way). The endmsg handlers
// for any currently open messages will be called which can supply a more
// specific status message. If UPB_BREAK is returned from inside a delegated
// message, processing will continue normally in the containing message (though
// the containing message can inspect the returned status and choose to also
// return UPB_BREAK if it is not ok).
UPB_BREAK,
// Skips to the end of the current submessage (or if we are at the top
// level, skips to the end of the entire message).
// level, skips to the end of the entire message). In other words, it is
// like a UPB_BREAK that applies only to the current level.
//
// If you UPB_SKIPSUBMSG from a startmsg handler, the endmsg handler will
// be called to perform cleanup and return a status. Returning
// UPB_SKIPSUBMSG from a startsubmsg handler will *not* call the startmsg,
// endmsg, or endsubmsg handlers.
UPB_SKIPSUBMSG,
// When returned from a startsubmsg handler, indicates that the submessage
// should be handled by a different set of handlers, which have been
// registered on the provided upb_handlers object. This allows upb_handlers
// objects to compose; a set of upb_handlers need not know whether it is the
// top-level message or a sub-message. May not be returned from any other
// callback.
//
// WARNING! The delegation API is slated for some significant changes.
// See: http://code.google.com/p/upb/issues/detail?id=6
UPB_DELEGATE,
// TODO: Add UPB_SUSPEND, for resumable producers/consumers.
} upb_flow_t;
// upb_handlers
struct _upb_handlers;
typedef struct _upb_sflow upb_sflow_t;
typedef upb_flow_t (*upb_startmsg_handler_t)(void *closure);
typedef void (*upb_endmsg_handler_t)(void *closure, upb_status *status);
typedef upb_flow_t (*upb_value_handler_t)(
void *closure, upb_value fval, upb_value val);
typedef upb_sflow_t (*upb_startsubmsg_handler_t)(
void *closure, upb_value fval);
typedef upb_flow_t (*upb_endsubmsg_handler_t)(void *closure, upb_value fval);
typedef upb_flow_t (*upb_unknownval_handler_t)(
void *closure, upb_field_number_t fieldnum, upb_value val);
typedef struct {
bool junk;
upb_fieldtype_t type;
upb_wire_type_t native_wire_type;
// For upb_issubmsg(f) only, the index into the msgdef array of the submsg.
// -1 if unset (indicates that submsg should be skipped).
int32_t msgent_index;
upb_value fval;
union {
upb_value_handler_t value;
upb_startsubmsg_handler_t startsubmsg;
} cb;
upb_endsubmsg_handler_t endsubmsg;
} upb_handlers_fieldent;
typedef struct {
upb_startmsg_handler_t startmsg;
upb_endmsg_handler_t endmsg;
upb_unknownval_handler_t unknownval;
// Maps field number -> upb_handlers_fieldent.
upb_inttable fieldtab;
} upb_handlers_msgent;
typedef struct {
upb_msgdef *msgdef;
int msgent_index;
} upb_handlers_frame;
struct _upb_handlers {
// Array of msgdefs, [0]=toplevel.
upb_handlers_msgent *msgs;
int msgs_len, msgs_size;
upb_msgdef *toplevel_msgdef; // We own a ref.
upb_handlers_msgent *msgent;
upb_handlers_frame stack[UPB_MAX_TYPE_DEPTH], *top, *limit;
};
typedef struct _upb_handlers upb_handlers;
typedef upb_flow_t (*upb_startmsg_handler_t)(void *closure);
typedef upb_flow_t (*upb_endmsg_handler_t)(void *closure);
typedef upb_flow_t (*upb_value_handler_t)(void *closure,
struct _upb_fielddef *f,
upb_value val);
typedef upb_flow_t (*upb_startsubmsg_handler_t)(void *closure,
struct _upb_fielddef *f,
upb_handlers *delegate_to);
typedef upb_flow_t (*upb_endsubmsg_handler_t)(void *closure,
struct _upb_fielddef *f);
typedef upb_flow_t (*upb_unknownval_handler_t)(void *closure,
upb_field_number_t fieldnum,
upb_value val);
// An empty set of handlers, for convenient copy/paste:
// The handlers object takes a ref on md. md can be NULL iff the client calls
// only upb_*_typed_*() (only upb_symtab should do this).
void upb_handlers_init(upb_handlers *h, upb_msgdef *md);
void upb_handlers_uninit(upb_handlers *h);
// The startsubmsg handler needs to also pass a closure to the submsg.
struct _upb_sflow {
upb_flow_t flow;
void *closure;
};
INLINE upb_sflow_t UPB_SFLOW(upb_flow_t flow, void *closure) {
upb_sflow_t ret = {flow, closure};
return ret;
}
#define UPB_CONTINUE_WITH(c) UPB_SFLOW(UPB_CONTINUE, c)
#define UPB_S_BREAK UPB_SFLOW(UPB_BREAK, NULL)
// Each message can have its own set of handlers. Here are empty definitions
// of the handlers for convenient copy/paste.
// TODO: Should endsubmsg get a copy of the upb_status*, so it can decide what
// to do in the case of a delegated failure?
//
// static upb_flow_t startmsg(void *closure) {
// // Called when the top-level message begins.
// // Called when the message begins. "closure" was supplied by our caller.
// // "mval" is whatever was bound to this message at registration time (for
// // upb_register_all() it will be its upb_msgdef*).
// return UPB_CONTINUE;
// }
//
// static upb_flow_t endmsg(void *closure) {
// // Called when the top-level message ends.
// return UPB_CONTINUE;
// static void endmsg(void *closure, upb_status *status) {
// // Called when processing of this top-level 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.
// //
// // Since this callback is guaranteed to always be called eventually, it
// // can be used to free any resources that were allocated during processing.
// }
//
// static upb_flow_t value(void *closure, upb_fielddef *f, upb_value val) {
// // Called for every value in the stream.
// static upb_flow_t value(void *closure, upb_value fval, upb_value val) {
// // Called for every non-submessage value in the stream. "fval" contains
// // whatever value was bound to this field at registration type
// // (for upb_register_all(), this will be the field's upb_fielddef*).
// return UPB_CONTINUE;
// }
//
// static upb_flow_t startsubmsg(void *closure, upb_fielddef *f,
// upb_handlers *delegate_to) {
// // Called when a submessage begins; can delegate by returning UPB_DELEGATE.
// return UPB_CONTINUE;
// static upb_sflow_t startsubmsg(void *closure, upb_value fval) {
// // Called when a submessage begins. The second element of the return
// // value is the closure for the submessage.
// return UPB_CONTINUE_WITH(closure);
// }
//
// static upb_flow_t endsubmsg(void *closure, upb_fielddef *f) {
// static upb_flow_t endsubmsg(void *closure, upb_value fval) {
// // Called when a submessage ends.
// return UPB_CONTINUE;
// }
@ -137,91 +180,222 @@ typedef upb_flow_t (*upb_unknownval_handler_t)(void *closure,
// // Called with an unknown value is encountered.
// return UPB_CONTINUE;
// }
//
// // Any handlers you don't need can be set to NULL.
// static upb_handlerset handlers = {
// startmsg,
// endmsg,
// value,
// startsubmsg,
// endsubmsg,
// unknownval,
// };
typedef struct {
upb_startmsg_handler_t startmsg;
upb_endmsg_handler_t endmsg;
upb_value_handler_t value;
upb_startsubmsg_handler_t startsubmsg;
upb_endsubmsg_handler_t endsubmsg;
upb_unknownval_handler_t unknownval;
} upb_handlerset;
// Functions to register handlers on a upb_handlers object.
INLINE void upb_handlers_init(upb_handlers *h);
INLINE void upb_handlers_uninit(upb_handlers *h);
INLINE void upb_handlers_reset(upb_handlers *h);
INLINE bool upb_handlers_isempty(upb_handlers *h);
INLINE void upb_register_handlerset(upb_handlers *h, upb_handlerset *set);
// Functions to register the above handlers.
// TODO: as an optimization, we could special-case handlers that don't
// need fval, to avoid even generating the code that sets the argument.
// If a value does not have a handler registered and there is no unknownval
// handler, the value will be skipped.
void upb_register_startend(upb_handlers *h, upb_startmsg_handler_t startmsg,
upb_endmsg_handler_t endmsg);
void upb_register_value(upb_handlers *h, upb_fielddef *f,
upb_value_handler_t value, upb_value fval);
void upb_register_unknownval(upb_handlers *h, upb_unknownval_handler_t unknown);
// To register handlers for a submessage, push the fielddef and pop it
// when you're done. This can be used to delegate a submessage to a
// different processing component which does not need to be aware whether
// it is at the top level or not.
void upb_handlers_push(upb_handlers *h, upb_fielddef *f,
upb_startsubmsg_handler_t start,
upb_endsubmsg_handler_t end, upb_value fval,
bool delegate);
void upb_handlers_pop(upb_handlers *h, upb_fielddef *f);
// In the case where types are self-recursive or mutually recursive, you can
// use this function which will link a set of handlers to a set that is
// already on our stack. This allows us to handle a tree of arbitrary
// depth without having to register an arbitrary number of levels of handlers.
// Returns "true" if the given type is indeed on the stack already and was
// linked.
//
// If more than one message of this type is on the stack, it chooses the
// one that is deepest in the tree (if necessary, we could give the caller
// more control over this).
bool upb_handlers_link(upb_handlers *h, upb_fielddef *f);
// Convenience function for registering the given handler for the given
// field path. This will overwrite any startsubmsg handlers that were
// previously registered along the path. These can be overwritten again
// later if desired.
// TODO: upb_register_path_submsg()?
void upb_register_path_value(upb_handlers *h, const char *path,
upb_value_handler_t value, upb_value fval);
// Convenience function for registering a single set of handlers on every
// message in our hierarchy. mvals are bound to upb_msgdef* and fvals are
// bound to upb_fielddef*. Any of the handlers can be NULL.
void upb_register_all(upb_handlers *h, upb_startmsg_handler_t start,
upb_endmsg_handler_t end,
upb_value_handler_t value,
upb_startsubmsg_handler_t startsubmsg,
upb_endsubmsg_handler_t endsubmsg,
upb_unknownval_handler_t unknown);
// TODO: for clients that want to increase efficiency by preventing bytesrcs
// from automatically being converted to strings in the value callback.
// INLINE void upb_handlers_use_bytesrcs(bool use_bytesrcs);
// The closure will be passed to every handler. The status will be read by the
// upb_src immediately after a handler has returned UPB_BREAK and used as the
// overall upb_src status; it will not be referenced at any other time.
INLINE void upb_set_handler_closure(upb_handlers *h, void *closure,
upb_status *status);
/* upb_src ********************************************************************/
struct _upb_src;
typedef struct _upb_src upb_src;
// upb_src_sethandlers() must be called once and only once before upb_src_run()
// is called. This sets up the callbacks that will handle the parse. A
// upb_src that is fully initialized except for the call to
// upb_src_sethandlers() is called "prepared" -- this is useful for library
// functions that want to consume the output of a generic upb_src.
// Calling sethandlers() multiple times is an error and will trigger an abort().
INLINE void upb_src_sethandlers(upb_src *src, upb_handlers *handlers);
// Runs the src, calling the callbacks that were registered with
// upb_src_sethandlers(), and returning the status of the operation in
// "status." The status might indicate UPB_TRYAGAIN (indicating EAGAIN on a
// non-blocking socket) or a resumable error; in both cases upb_src_run can be
// called again later. TRYAGAIN could come from either the src (input buffers
// are empty) or the handlers (output buffers are full).
INLINE void upb_src_run(upb_src *src, upb_status *status);
// A convenience object that a upb_src can use to invoke handlers. It
// transparently handles delegation so that the upb_src needs only follow the
// protocol as if delegation did not exist.
struct _upb_dispatcher;
typedef struct _upb_dispatcher upb_dispatcher;
INLINE void upb_dispatcher_init(upb_dispatcher *d);
INLINE void upb_dispatcher_reset(upb_dispatcher *d, upb_handlers *h,
bool supports_skip);
INLINE upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d);
INLINE upb_flow_t upb_dispatch_endmsg(upb_dispatcher *d);
INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d,
struct _upb_fielddef *f);
INLINE upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d,
struct _upb_fielddef *f);
INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, struct _upb_fielddef *f,
upb_value val);
INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d,
upb_field_number_t fieldnum,
upb_value val);
// INLINE void upb_handlers_use_bytesrcs(upb_handlers *h, bool use_bytesrcs);
// Low-level functions -- internal-only.
void upb_register_typed_value(upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type, upb_value_handler_t value,
upb_value fval);
void upb_register_typed_submsg(upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type,
upb_startsubmsg_handler_t start,
upb_endsubmsg_handler_t end,
upb_value fval);
void upb_handlers_typed_link(upb_handlers *h,
upb_field_number_t fieldnum,
upb_fieldtype_t type,
int frames);
void upb_handlers_typed_push(upb_handlers *h, upb_field_number_t fieldnum,
upb_fieldtype_t type);
void upb_handlers_typed_pop(upb_handlers *h);
INLINE upb_handlers_msgent *upb_handlers_getmsgent(upb_handlers *h,
upb_handlers_fieldent *f) {
assert(f->msgent_index != -1);
return &h->msgs[f->msgent_index];
}
upb_handlers_fieldent *upb_handlers_lookup(upb_inttable *dispatch_table, upb_field_number_t fieldnum);
/* upb_dispatcher *************************************************************/
// upb_dispatcher can be used by sources of data to invoke the appropriate
// handlers. It takes care of details such as:
// - ensuring all endmsg callbacks (cleanup handlers) are called.
// - propagating status all the way back to the top-level message.
// - handling UPB_BREAK properly (clients only need to handle UPB_SKIPSUBMSG).
// - handling UPB_SKIPSUBMSG if the client doesn't (but this is less
// efficient, because then you can't skip the actual work).
// - tracking the stack of closures.
//
// TODO: it might be best to actually surface UPB_BREAK to clients in the case
// that the can't efficiently skip the submsg; eg. with groups. Then the client
// would know to just unwind the stack without bothering to consume the rest of
// the input. On the other hand, it might be important for all the input to be
// consumed, like if this is a submessage of a larger stream.
typedef struct {
upb_handlers_fieldent *f;
void *closure;
size_t end_offset; // For groups, 0.
} upb_dispatcher_frame;
typedef struct {
upb_dispatcher_frame *top, *limit;
upb_handlers *handlers;
// Msg and dispatch table for the current level.
upb_handlers_msgent *msgent;
upb_inttable *dispatch_table;
// The number of startsubmsg calls without a corresponding endsubmsg call.
int current_depth;
// For all frames >= skip_depth, we are skipping all values in the submsg.
// For all frames >= noframe_depth, we did not even push a frame.
// These are INT_MAX when nothing is being skipped.
// Invariant: noframe_depth >= skip_depth
int skip_depth;
int noframe_depth;
// Depth of stack entries we'll skip if a callback returns UPB_BREAK.
int delegated_depth;
// Stack.
upb_dispatcher_frame stack[UPB_MAX_NESTING];
upb_status status;
} upb_dispatcher;
INLINE bool upb_dispatcher_skipping(upb_dispatcher *d) {
return d->current_depth >= d->skip_depth;
}
// If true, upb_dispatcher_skipping(d) must also be true.
INLINE bool upb_dispatcher_noframe(upb_dispatcher *d) {
return d->current_depth >= d->noframe_depth;
}
typedef upb_handlers_fieldent upb_dispatcher_field;
void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h, size_t top_end_offset);
void upb_dispatcher_reset(upb_dispatcher *d);
void upb_dispatcher_uninit(upb_dispatcher *d);
upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d, void *closure);
void upb_dispatch_endmsg(upb_dispatcher *d, upb_status *status);
// Looks up a field by number for the current message.
INLINE upb_dispatcher_field *upb_dispatcher_lookup(upb_dispatcher *d,
upb_field_number_t n) {
return (upb_dispatcher_field*)upb_inttable_fastlookup(
d->dispatch_table, n, sizeof(upb_dispatcher_field));
}
// Dispatches values or submessages -- the client is responsible for having
// previously looked up the field.
upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d,
upb_dispatcher_field *f,
size_t userval);
upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d);
INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, upb_dispatcher_field *f,
upb_value val) {
if (upb_dispatcher_skipping(d)) return UPB_SKIPSUBMSG;
upb_flow_t flow = f->cb.value(d->top->closure, f->fval, val);
if (flow != UPB_CONTINUE) {
d->noframe_depth = d->current_depth + 1;
d->skip_depth = (flow == UPB_BREAK) ? d->delegated_depth : d->current_depth;
return UPB_SKIPSUBMSG;
}
return UPB_CONTINUE;
}
INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d, upb_field_number_t n,
upb_value val) {
// TODO.
(void)d;
(void)n;
(void)val;
return UPB_CONTINUE;
}
INLINE bool upb_dispatcher_stackempty(upb_dispatcher *d) {
return d->top == d->stack;
}
/* upb_bytesrc ****************************************************************/
// upb_bytesrc is a pull interface for streams of bytes, basically an
// abstraction of read()/fread(), but it avoids copies where possible.
typedef upb_strlen_t (*upb_bytesrc_read_fptr)(
upb_bytesrc *src, void *buf, upb_strlen_t count, upb_status *status);
typedef bool (*upb_bytesrc_getstr_fptr)(
upb_bytesrc *src, upb_string *str, upb_status *status);
typedef struct {
upb_bytesrc_read_fptr read;
upb_bytesrc_getstr_fptr getstr;
} upb_bytesrc_vtbl;
struct _upb_bytesrc {
upb_bytesrc_vtbl *vtbl;
};
INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtbl *vtbl) {
s->vtbl = vtbl;
}
// Reads up to "count" bytes into "buf", returning the total number of bytes
// read. If 0, indicates error and puts details in "status".
INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf,
upb_strlen_t count, upb_status *status);
upb_strlen_t count, upb_status *status) {
return src->vtbl->read(src, buf, count, status);
}
// Like upb_bytesrc_read(), but modifies "str" in-place. Caller must ensure
// that "str" is created or just recycled. Returns "false" if no data was
@ -234,22 +408,36 @@ INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf,
// put it into a different kind of string object) then upb_bytesrc_get() could
// save you a copy.
INLINE bool upb_bytesrc_getstr(upb_bytesrc *src, upb_string *str,
upb_status *status);
// A convenience function for getting all the remaining data in a upb_bytesrc
// as a upb_string. Returns false and sets "status" if the operation fails.
INLINE bool upb_bytesrc_getfullstr(upb_bytesrc *src, upb_string *str,
upb_status *status);
INLINE bool upb_value_getfullstr(upb_value val, upb_string *str,
upb_status *status) {
return upb_bytesrc_getfullstr(upb_value_getbytesrc(val), str, status);
upb_status *status) {
return src->vtbl->getstr(src, str, status);
}
/* upb_bytesink ***************************************************************/
// upb_bytesink: push interface for streams of bytes, basically an abstraction
// of write()/fwrite(), but it avoids copies where possible.
struct _upb_bytesink;
typedef struct _upb_bytesink upb_bytesink;
typedef upb_strlen_t (*upb_bytesink_putstr_fptr)(
upb_bytesink *bytesink, upb_string *str, upb_status *status);
typedef upb_strlen_t (*upb_bytesink_vprintf_fptr)(
upb_bytesink *bytesink, upb_status *status, const char *fmt, va_list args);
typedef struct {
upb_bytesink_putstr_fptr putstr;
upb_bytesink_vprintf_fptr vprintf;
} upb_bytesink_vtbl;
struct _upb_bytesink {
upb_bytesink_vtbl *vtbl;
};
INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtbl *vtbl) {
s->vtbl = vtbl;
}
// TODO: Figure out how buffering should be handled. Should the caller buffer
// data and only call these functions when a buffer is full? Seems most
@ -264,15 +452,21 @@ typedef struct _upb_bytesink upb_bytesink;
// Returns the number of bytes written.
INLINE upb_strlen_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status,
const char *fmt, ...);
const char *fmt, ...) {
va_list args;
va_start(args, fmt);
upb_strlen_t ret = sink->vtbl->vprintf(sink, status, fmt, args);
va_end(args);
return ret;
}
// Puts the given string, returning true if the operation was successful, otherwise
// check "status" for details. Ownership of the string is *not* passed; if
// the callee wants a reference he must call upb_string_getref() on it.
INLINE upb_strlen_t upb_bytesink_putstr(upb_bytesink *sink, upb_string *str,
upb_status *status);
#include "upb_stream_vtbl.h"
upb_status *status) {
return sink->vtbl->putstr(sink, str, status);
}
#ifdef __cplusplus
} /* extern "C" */

@ -1,303 +0,0 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
* vtable declarations for types that are implementing any of the src or sink
* interfaces. Only components that are implementing these interfaces need
* to worry about this file.
*
* Copyright (c) 2010 Joshua Haberman. See LICENSE for details.
*/
#ifndef UPB_SRCSINK_VTBL_H_
#define UPB_SRCSINK_VTBL_H_
#include <assert.h>
#include "upb_stream.h"
#include "upb_string.h"
#ifdef __cplusplus
extern "C" {
#endif
// Typedefs for function pointers to all of the virtual functions.
// upb_src
typedef void (*upb_src_sethandlers_fptr)(upb_src *src, upb_handlers *handlers);
typedef void (*upb_src_run_fptr)(upb_src *src, upb_status *status);
// upb_bytesrc.
typedef upb_strlen_t (*upb_bytesrc_read_fptr)(
upb_bytesrc *src, void *buf, upb_strlen_t count, upb_status *status);
typedef bool (*upb_bytesrc_getstr_fptr)(
upb_bytesrc *src, upb_string *str, upb_status *status);
// upb_bytesink.
typedef upb_strlen_t (*upb_bytesink_write_fptr)(
upb_bytesink *bytesink, void *buf, upb_strlen_t count);
typedef upb_strlen_t (*upb_bytesink_putstr_fptr)(
upb_bytesink *bytesink, upb_string *str, upb_status *status);
typedef upb_strlen_t (*upb_bytesink_vprintf_fptr)(
upb_bytesink *bytesink, upb_status *status, const char *fmt, va_list args);
// Vtables for the above interfaces.
typedef struct {
upb_bytesrc_read_fptr read;
upb_bytesrc_getstr_fptr getstr;
} upb_bytesrc_vtbl;
typedef struct {
upb_bytesink_write_fptr write;
upb_bytesink_putstr_fptr putstr;
upb_bytesink_vprintf_fptr vprintf;
} upb_bytesink_vtbl;
typedef struct {
upb_src_sethandlers_fptr sethandlers;
upb_src_run_fptr run;
} upb_src_vtbl;
// "Base Class" definitions; components that implement these interfaces should
// contain one of these structures.
struct _upb_bytesrc {
upb_bytesrc_vtbl *vtbl;
};
struct _upb_bytesink {
upb_bytesink_vtbl *vtbl;
};
struct _upb_src {
upb_src_vtbl *vtbl;
};
INLINE void upb_bytesrc_init(upb_bytesrc *s, upb_bytesrc_vtbl *vtbl) {
s->vtbl = vtbl;
}
INLINE void upb_bytesink_init(upb_bytesink *s, upb_bytesink_vtbl *vtbl) {
s->vtbl = vtbl;
}
INLINE void upb_src_init(upb_src *s, upb_src_vtbl *vtbl) {
s->vtbl = vtbl;
}
// Implementation of virtual function dispatch.
// upb_src
INLINE void upb_src_sethandlers(upb_src *src, upb_handlers *handlers) {
src->vtbl->sethandlers(src, handlers);
}
INLINE void upb_src_run(upb_src *src, upb_status *status) {
src->vtbl->run(src, status);
}
// upb_bytesrc
INLINE upb_strlen_t upb_bytesrc_read(upb_bytesrc *src, void *buf,
upb_strlen_t count, upb_status *status) {
return src->vtbl->read(src, buf, count, status);
}
INLINE bool upb_bytesrc_getstr(upb_bytesrc *src, upb_string *str,
upb_status *status) {
return src->vtbl->getstr(src, str, status);
}
INLINE bool upb_bytesrc_getfullstr(upb_bytesrc *src, upb_string *str,
upb_status *status) {
// We start with a getstr, because that could possibly alias data instead of
// copying.
if (!upb_bytesrc_getstr(src, str, status)) return false;
// Trade-off between number of read calls and amount of overallocation.
const size_t bufsize = 4096;
do {
upb_strlen_t len = upb_string_len(str);
char *buf = upb_string_getrwbuf(str, len + bufsize);
upb_strlen_t read = upb_bytesrc_read(src, buf + len, bufsize, status);
if (read < 0) return false;
// Resize to proper size.
upb_string_getrwbuf(str, len + read);
} while (!status->code != UPB_EOF);
return true;
}
// upb_bytesink
INLINE upb_strlen_t upb_bytesink_write(upb_bytesink *sink, void *buf,
upb_strlen_t count) {
return sink->vtbl->write(sink, buf, count);
}
INLINE upb_strlen_t upb_bytesink_putstr(upb_bytesink *sink, upb_string *str, upb_status *status) {
return sink->vtbl->putstr(sink, str, status);
}
INLINE upb_strlen_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
upb_strlen_t ret = sink->vtbl->vprintf(sink, status, fmt, args);
va_end(args);
return ret;
}
// upb_handlers
struct _upb_handlers {
upb_handlerset *set;
void *closure;
upb_status *status; // We don't own this.
};
INLINE void upb_handlers_init(upb_handlers *h) {
(void)h;
}
INLINE void upb_handlers_uninit(upb_handlers *h) {
(void)h;
}
INLINE void upb_handlers_reset(upb_handlers *h) {
h->set = NULL;
h->closure = NULL;
}
INLINE bool upb_handlers_isempty(upb_handlers *h) {
return !h->set && !h->closure;
}
INLINE upb_flow_t upb_nop(void *closure) {
(void)closure;
return UPB_CONTINUE;
}
INLINE upb_flow_t upb_value_nop(void *closure, struct _upb_fielddef *f, upb_value val) {
(void)closure;
(void)f;
(void)val;
return UPB_CONTINUE;
}
INLINE upb_flow_t upb_startsubmsg_nop(void *closure, struct _upb_fielddef *f,
upb_handlers *delegate_to) {
(void)closure;
(void)f;
(void)delegate_to;
return UPB_CONTINUE;
}
INLINE upb_flow_t upb_endsubmsg_nop(void *closure, struct _upb_fielddef *f) {
(void)closure;
(void)f;
return UPB_CONTINUE;
}
INLINE upb_flow_t upb_unknownval_nop(void *closure, upb_field_number_t fieldnum,
upb_value val) {
(void)closure;
(void)fieldnum;
(void)val;
return UPB_CONTINUE;
}
INLINE void upb_register_handlerset(upb_handlers *h, upb_handlerset *set) {
if (!set->startmsg) set->startmsg = &upb_nop;
if (!set->endmsg) set->endmsg = &upb_nop;
if (!set->value) set->value = &upb_value_nop;
if (!set->startsubmsg) set->startsubmsg = &upb_startsubmsg_nop;
if (!set->endsubmsg) set->endsubmsg = &upb_endsubmsg_nop;
if (!set->unknownval) set->unknownval = &upb_unknownval_nop;
h->set = set;
}
INLINE void upb_set_handler_closure(upb_handlers *h, void *closure,
upb_status *status) {
h->closure = closure;
h->status = status;
}
// upb_dispatcher
typedef struct {
upb_handlers handlers;
int depth;
} upb_dispatcher_frame;
struct _upb_dispatcher {
upb_dispatcher_frame stack[UPB_MAX_NESTING], *top, *limit;
bool supports_skip;
};
INLINE void upb_dispatcher_init(upb_dispatcher *d) {
d->limit = d->stack + sizeof(d->stack);
}
INLINE void upb_dispatcher_reset(upb_dispatcher *d, upb_handlers *h,
bool supports_skip) {
d->top = d->stack;
d->top->depth = 1; // Never want to trigger end-of-delegation.
d->top->handlers = *h;
d->supports_skip = supports_skip;
}
INLINE upb_flow_t upb_dispatch_startmsg(upb_dispatcher *d) {
assert(d->stack == d->top);
return d->top->handlers.set->startmsg(d->top->handlers.closure);
}
INLINE upb_flow_t upb_dispatch_endmsg(upb_dispatcher *d) {
assert(d->stack == d->top);
return d->top->handlers.set->endmsg(d->top->handlers.closure);
}
// TODO: several edge cases to fix:
// - delegated start returns UPB_BREAK, should replay the start on resume.
// - endsubmsg returns UPB_BREAK, should NOT replay the delegated endmsg.
INLINE upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d,
struct _upb_fielddef *f) {
upb_handlers handlers;
upb_handlers_init(&handlers);
upb_handlers_reset(&handlers);
upb_flow_t ret = d->top->handlers.set->startsubmsg(d->top->handlers.closure, f, &handlers);
assert((ret == UPB_DELEGATE) == !upb_handlers_isempty(&handlers));
if (ret == UPB_DELEGATE) {
++d->top;
d->top->handlers = handlers;
d->top->depth = 0;
ret = d->top->handlers.set->startmsg(d->top->handlers.closure);
}
if (ret == UPB_CONTINUE || !d->supports_skip) ++d->top->depth;
upb_handlers_uninit(&handlers);
return ret;
}
INLINE upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d,
struct _upb_fielddef *f) {
upb_flow_t ret;
if (--d->top->depth == 0) {
ret = d->top->handlers.set->endmsg(d->top->handlers.closure);
//assert(ret != UPB_BREAK);
if (ret != UPB_CONTINUE) return ret;
--d->top;
assert(d->top >= d->stack);
}
return d->top->handlers.set->endsubmsg(d->top->handlers.closure, f);
}
INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d,
struct _upb_fielddef *f,
upb_value val) {
return d->top->handlers.set->value(d->top->handlers.closure, f, val);
}
INLINE upb_flow_t upb_dispatch_unknownval(upb_dispatcher *d,
upb_field_number_t fieldnum,
upb_value val) {
return d->top->handlers.set->unknownval(d->top->handlers.closure,
fieldnum, val);
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

@ -7,7 +7,6 @@
#include "upb_strstream.h"
#include <stdlib.h>
#include "upb_string.h"
/* upb_stringsrc **************************************************************/
@ -108,7 +107,6 @@ static upb_strlen_t upb_stringsink_putstr(upb_bytesink *_sink, upb_string *str,
void upb_stringsink_init(upb_stringsink *s) {
static upb_bytesink_vtbl vtbl = {
NULL,
upb_stringsink_putstr,
upb_stringsink_vprintf
};

@ -7,7 +7,6 @@
*/
#include "upb_table.h"
#include "upb_string.h"
#include <assert.h>
#include <stdlib.h>

@ -9,8 +9,6 @@
#include <inttypes.h>
#include <stdlib.h>
#include <ctype.h>
#include "upb_def.h"
#include "upb_string.h"
struct _upb_textprinter {
upb_bytesink *bytesink;
@ -91,9 +89,10 @@ err:
return -1;
}
static upb_flow_t upb_textprinter_value(void *_p, upb_fielddef *f,
static upb_flow_t upb_textprinter_value(void *_p, upb_value fval,
upb_value val) {
upb_textprinter *p = _p;
upb_fielddef *f = upb_value_getfielddef(fval);
upb_textprinter_indent(p);
CHECK(upb_bytesink_printf(p->bytesink, &p->status, UPB_STRFMT ": ", UPB_STRARG(f->name)));
#define CASE(fmtstr, member) \
@ -144,21 +143,20 @@ err:
return UPB_BREAK;
}
static upb_flow_t upb_textprinter_startsubmsg(void *_p, upb_fielddef *f,
upb_handlers *delegate_to) {
(void)delegate_to;
static upb_sflow_t upb_textprinter_startsubmsg(void *_p, upb_value fval) {
upb_textprinter *p = _p;
upb_fielddef *f = upb_value_getfielddef(fval);
upb_textprinter_indent(p);
CHECK(upb_bytesink_printf(p->bytesink, &p->status, UPB_STRFMT " {", UPB_STRARG(f->name)));
if(!p->single_line) upb_bytesink_putstr(p->bytesink, UPB_STRLIT("\n"), &p->status);
p->indent_depth++;
return UPB_CONTINUE;
return UPB_CONTINUE_WITH(_p);
err:
return UPB_BREAK;
return UPB_S_BREAK;
}
static upb_flow_t upb_textprinter_endsubmsg(void *_p, upb_fielddef *f) {
(void)f;
static upb_flow_t upb_textprinter_endsubmsg(void *_p, upb_value fval) {
(void)fval;
upb_textprinter *p = _p;
p->indent_depth--;
upb_textprinter_indent(p);
@ -176,18 +174,20 @@ void upb_textprinter_free(upb_textprinter *p) {
free(p);
}
void upb_textprinter_reset(upb_textprinter *p, upb_handlers *handlers,
upb_bytesink *sink, bool single_line) {
static upb_handlerset handlerset = {
void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink,
bool single_line) {
p->bytesink = sink;
p->single_line = single_line;
p->indent_depth = 0;
}
void upb_textprinter_reghandlers(upb_handlers *h) {
upb_register_all(h,
NULL, // startmsg
NULL, // endmsg
upb_textprinter_value,
upb_textprinter_startsubmsg,
upb_textprinter_endsubmsg,
};
p->bytesink = sink;
p->single_line = single_line;
p->indent_depth = 0;
upb_register_handlerset(handlers, &handlerset);
upb_set_handler_closure(handlers, p, &p->status);
NULL // Unknown
);
}

@ -18,9 +18,9 @@ typedef struct _upb_textprinter upb_textprinter;
upb_textprinter *upb_textprinter_new();
void upb_textprinter_free(upb_textprinter *p);
void upb_textprinter_reset(upb_textprinter *p, upb_handlers *handlers,
upb_bytesink *sink, bool single_line);
void upb_textprinter_sethandlers(upb_textprinter *p, upb_handlers *h);
void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink,
bool single_line);
void upb_textprinter_reghandlers(upb_handlers *h);
#ifdef __cplusplus
} /* extern "C" */

@ -14,9 +14,6 @@ int main() {
}
free(defs);
upb_msgdef *fds = upb_getfdsdef();
assert(fds != NULL);
upb_def_unref(UPB_UPCAST(fds));
upb_symtab_unref(s);
return 0;
}

Loading…
Cancel
Save