Commit aba42edd authored by Joshua Haberman's avatar Joshua Haberman

Merge pull request #604 from haberman/ruby-conformance

Added Ruby to conformance tests.
parents 58035596 c2c43a49
...@@ -22,7 +22,7 @@ conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src ...@@ -22,7 +22,7 @@ conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
if USE_EXTERNAL_PROTOC if USE_EXTERNAL_PROTOC
protoc_middleman: $(protoc_inputs) protoc_middleman: $(protoc_inputs)
$(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. $^ $(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. --ruby_out=. $^
touch protoc_middleman touch protoc_middleman
else else
...@@ -31,7 +31,7 @@ else ...@@ -31,7 +31,7 @@ else
# relative to srcdir, which may not be the same as the current directory when # relative to srcdir, which may not be the same as the current directory when
# building out-of-tree. # building out-of-tree.
protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs) protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs)
oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd $(protoc_inputs) ) oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd $(protoc_inputs) )
touch protoc_middleman touch protoc_middleman
endif endif
...@@ -61,3 +61,6 @@ test_cpp: protoc_middleman conformance-test-runner conformance-cpp ...@@ -61,3 +61,6 @@ test_cpp: protoc_middleman conformance-test-runner conformance-cpp
test_java: protoc_middleman conformance-test-runner conformance-java test_java: protoc_middleman conformance-test-runner conformance-java
./conformance-test-runner ./conformance-java ./conformance-test-runner ./conformance-java
test_ruby: protoc_middleman conformance-test-runner
RUBYLIB=../ruby/lib:. ./conformance-test-runner --failure_list failure_list_ruby.txt ./conformance_ruby.rb
#!/usr/bin/env ruby
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
# https://developers.google.com/protocol-buffers/
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'conformance'
$test_count = 0
$verbose = false
def do_test(request)
test_message = Conformance::TestAllTypes.new
response = Conformance::ConformanceResponse.new
begin
case request.payload
when :protobuf_payload
begin
test_message =
Conformance::TestAllTypes.decode(request.protobuf_payload)
rescue Google::Protobuf::ParseError => err
response.parse_error = err.message.encode('utf-8')
return response
end
when :json_payload
test_message = Conformance::TestAllTypes.decode_json(request.json_payload)
when nil
fail "Request didn't have payload"
end
case request.requested_output_format
when :UNSPECIFIED
fail 'Unspecified output format'
when :PROTOBUF
response.protobuf_payload = test_message.to_proto
when :JSON
response.json_payload = test_message.to_json
end
rescue StandardError => err
response.runtime_error = err.message.encode('utf-8')
end
response
end
# Returns true if the test ran successfully, false on legitimate EOF.
# If EOF is encountered in an unexpected place, raises IOError.
def do_test_io
length_bytes = STDIN.read(4)
return false if length_bytes.nil?
length = length_bytes.unpack('V').first
serialized_request = STDIN.read(length)
if serialized_request.nil? || serialized_request.length != length
fail IOError
end
request = Conformance::ConformanceRequest.decode(serialized_request)
response = do_test(request)
serialized_response = Conformance::ConformanceResponse.encode(response)
STDOUT.write([serialized_response.length].pack('V'))
STDOUT.write(serialized_response)
STDOUT.flush
if $verbose
STDERR.puts("conformance-cpp: request={request.to_json}, " \
"response={response.to_json}\n")
end
$test_count += 1
true
end
loop do
unless do_test_io
STDERR.puts('conformance-cpp: received EOF from test runner ' \
"after #{$test_count} tests, exiting")
break
end
end
...@@ -85,6 +85,8 @@ class ConformanceTestSuite { ...@@ -85,6 +85,8 @@ class ConformanceTestSuite {
public: public:
ConformanceTestSuite() : verbose_(false) {} ConformanceTestSuite() : verbose_(false) {}
void SetVerbose(bool verbose) { verbose_ = verbose; }
// Sets the list of tests that are expected to fail when RunSuite() is called. // Sets the list of tests that are expected to fail when RunSuite() is called.
// RunSuite() will fail unless the set of failing tests is exactly the same // RunSuite() will fail unless the set of failing tests is exactly the same
// as this list. // as this list.
......
...@@ -219,12 +219,16 @@ void ParseFailureList(const char *filename, vector<string>* failure_list) { ...@@ -219,12 +219,16 @@ void ParseFailureList(const char *filename, vector<string>* failure_list) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int arg = 1; int arg = 1;
char *program; char *program;
vector<string> failure_list; google::protobuf::ConformanceTestSuite suite;
for (int arg = 1; arg < argc; ++arg) { for (int arg = 1; arg < argc; ++arg) {
if (strcmp(argv[arg], "--failure_list") == 0) { if (strcmp(argv[arg], "--failure_list") == 0) {
if (++arg == argc) UsageError(); if (++arg == argc) UsageError();
vector<string> failure_list;
ParseFailureList(argv[arg], &failure_list); ParseFailureList(argv[arg], &failure_list);
suite.SetFailureList(failure_list);
} else if (strcmp(argv[arg], "--verbose") == 0) {
suite.SetVerbose(true);
} else if (argv[arg][0] == '-') { } else if (argv[arg][0] == '-') {
fprintf(stderr, "Unknown option: %s\n", argv[arg]); fprintf(stderr, "Unknown option: %s\n", argv[arg]);
UsageError(); UsageError();
...@@ -238,8 +242,6 @@ int main(int argc, char *argv[]) { ...@@ -238,8 +242,6 @@ int main(int argc, char *argv[]) {
} }
ForkPipeRunner runner(program); ForkPipeRunner runner(program);
google::protobuf::ConformanceTestSuite suite;
suite.SetFailureList(failure_list);
std::string output; std::string output;
bool ok = suite.RunSuite(&runner, &output); bool ok = suite.RunSuite(&runner, &output);
......
JsonInput.HelloWorld.JsonOutput
JsonInput.HelloWorld.ProtobufOutput
ProtobufInput.PrematureEofBeforeUnknownValue.DOUBLE
ProtobufInput.PrematureEofBeforeUnknownValue.FIXED32
ProtobufInput.PrematureEofBeforeUnknownValue.FIXED64
ProtobufInput.PrematureEofBeforeUnknownValue.FLOAT
ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED32
ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED64
ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.BYTES
ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.MESSAGE
ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.STRING
ProtobufInput.PrematureEofInsideUnknownValue.DOUBLE
ProtobufInput.PrematureEofInsideUnknownValue.FIXED32
ProtobufInput.PrematureEofInsideUnknownValue.FIXED64
ProtobufInput.PrematureEofInsideUnknownValue.FLOAT
ProtobufInput.PrematureEofInsideUnknownValue.SFIXED32
ProtobufInput.PrematureEofInsideUnknownValue.SFIXED64
...@@ -548,7 +548,7 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) { ...@@ -548,7 +548,7 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
#define CONVERT(upb, ruby) \ #define CONVERT(upb, ruby) \
if (SYM2ID(type) == rb_intern( # ruby )) { \ if (SYM2ID(type) == rb_intern( # ruby )) { \
return UPB_TYPE_ ## upb; \ return UPB_TYPE_ ## upb; \
} }
CONVERT(FLOAT, float); CONVERT(FLOAT, float);
...@@ -589,6 +589,68 @@ VALUE fieldtype_to_ruby(upb_fieldtype_t type) { ...@@ -589,6 +589,68 @@ VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
return Qnil; return Qnil;
} }
upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
if (TYPE(type) != T_SYMBOL) {
rb_raise(rb_eArgError, "Expected symbol for field type.");
}
#define CONVERT(upb, ruby) \
if (SYM2ID(type) == rb_intern( # ruby )) { \
return UPB_DESCRIPTOR_TYPE_ ## upb; \
}
CONVERT(FLOAT, float);
CONVERT(DOUBLE, double);
CONVERT(BOOL, bool);
CONVERT(STRING, string);
CONVERT(BYTES, bytes);
CONVERT(MESSAGE, message);
CONVERT(GROUP, group);
CONVERT(ENUM, enum);
CONVERT(INT32, int32);
CONVERT(INT64, int64);
CONVERT(UINT32, uint32);
CONVERT(UINT64, uint64);
CONVERT(SINT32, sint32);
CONVERT(SINT64, sint64);
CONVERT(FIXED32, fixed32);
CONVERT(FIXED64, fixed64);
CONVERT(SFIXED32, sfixed32);
CONVERT(SFIXED64, sfixed64);
#undef CONVERT
rb_raise(rb_eArgError, "Unknown field type.");
return 0;
}
VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
switch (type) {
#define CONVERT(upb, ruby) \
case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
CONVERT(FLOAT, float);
CONVERT(DOUBLE, double);
CONVERT(BOOL, bool);
CONVERT(STRING, string);
CONVERT(BYTES, bytes);
CONVERT(MESSAGE, message);
CONVERT(GROUP, group);
CONVERT(ENUM, enum);
CONVERT(INT32, int32);
CONVERT(INT64, int64);
CONVERT(UINT32, uint32);
CONVERT(UINT64, uint64);
CONVERT(SINT32, sint32);
CONVERT(SINT64, sint64);
CONVERT(FIXED32, fixed32);
CONVERT(FIXED64, fixed64);
CONVERT(SFIXED32, sfixed32);
CONVERT(SFIXED64, sfixed64);
#undef CONVERT
}
return Qnil;
}
/* /*
* call-seq: * call-seq:
* FieldDescriptor.type => type * FieldDescriptor.type => type
...@@ -604,7 +666,7 @@ VALUE FieldDescriptor_type(VALUE _self) { ...@@ -604,7 +666,7 @@ VALUE FieldDescriptor_type(VALUE _self) {
if (!upb_fielddef_typeisset(self->fielddef)) { if (!upb_fielddef_typeisset(self->fielddef)) {
return Qnil; return Qnil;
} }
return fieldtype_to_ruby(upb_fielddef_type(self->fielddef)); return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
} }
/* /*
...@@ -617,7 +679,7 @@ VALUE FieldDescriptor_type(VALUE _self) { ...@@ -617,7 +679,7 @@ VALUE FieldDescriptor_type(VALUE _self) {
VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) { VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
DEFINE_SELF(FieldDescriptor, self, _self); DEFINE_SELF(FieldDescriptor, self, _self);
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef); upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
upb_fielddef_settype(mut_def, ruby_to_fieldtype(type)); upb_fielddef_setdescriptortype(mut_def, ruby_to_descriptortype(type));
return Qnil; return Qnil;
} }
......
...@@ -656,8 +656,10 @@ static bool env_error_func(void* ud, const upb_status* status) { ...@@ -656,8 +656,10 @@ static bool env_error_func(void* ud, const upb_status* status) {
// Free the env -- rb_raise will longjmp up the stack past the encode/decode // Free the env -- rb_raise will longjmp up the stack past the encode/decode
// function so it would not otherwise have been freed. // function so it would not otherwise have been freed.
stackenv_uninit(se); stackenv_uninit(se);
rb_raise(rb_eRuntimeError, se->ruby_error_template,
upb_status_errmsg(status)); // TODO(haberman): have a way to verify that this is actually a parse error,
// instead of just throwing "parse error" unconditionally.
rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status));
// Never reached: rb_raise() always longjmp()s up the stack, past all of our // Never reached: rb_raise() always longjmp()s up the stack, past all of our
// code, back to Ruby. // code, back to Ruby.
return false; return false;
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
// Ruby integers) to MessageDef/EnumDef instances (as Ruby values). // Ruby integers) to MessageDef/EnumDef instances (as Ruby values).
VALUE upb_def_to_ruby_obj_map; VALUE upb_def_to_ruby_obj_map;
VALUE cError;
VALUE cParseError;
void add_def_obj(const void* def, VALUE value) { void add_def_obj(const void* def, VALUE value) {
rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value); rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
} }
...@@ -96,6 +99,9 @@ void Init_protobuf_c() { ...@@ -96,6 +99,9 @@ void Init_protobuf_c() {
RepeatedField_register(protobuf); RepeatedField_register(protobuf);
Map_register(protobuf); Map_register(protobuf);
cError = rb_const_get(protobuf, rb_intern("Error"));
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
rb_define_singleton_method(protobuf, "deep_copy", rb_define_singleton_method(protobuf, "deep_copy",
Google_Protobuf_deep_copy, 1); Google_Protobuf_deep_copy, 1);
......
...@@ -161,6 +161,9 @@ extern VALUE cOneofBuilderContext; ...@@ -161,6 +161,9 @@ extern VALUE cOneofBuilderContext;
extern VALUE cEnumBuilderContext; extern VALUE cEnumBuilderContext;
extern VALUE cBuilder; extern VALUE cBuilder;
extern VALUE cError;
extern VALUE cParseError;
// We forward-declare all of the Ruby method implementations here because we // We forward-declare all of the Ruby method implementations here because we
// sometimes call the methods directly across .c files, rather than going // sometimes call the methods directly across .c files, rather than going
// through Ruby's method dispatching (e.g. during message parse). It's cleaner // through Ruby's method dispatching (e.g. during message parse). It's cleaner
......
// Amalgamated source file // Amalgamated source file
#include "upb.h" #include "upb.h"
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2008-2012 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -1701,12 +1695,6 @@ upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { ...@@ -1701,12 +1695,6 @@ upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
void upb_oneof_iter_setdone(upb_oneof_iter *iter) { void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
upb_inttable_iter_setdone(iter); upb_inttable_iter_setdone(iter);
} }
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2014 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -1980,14 +1968,9 @@ upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) { ...@@ -1980,14 +1968,9 @@ upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) {
return seeded_alloc; return seeded_alloc;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** TODO(haberman): it's unclear whether a lot of the consistency checks should
* ** assert() or return false.
* Copyright (c) 2011-2012 Google Inc. See LICENSE for details. */
* Author: Josh Haberman <jhaberman@gmail.com>
*
* TODO(haberman): it's unclear whether a lot of the consistency checks should
* assert() or return false.
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -2668,24 +2651,21 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h, ...@@ -2668,24 +2651,21 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h,
return true; return true;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::RefCounted Implementation
* **
* Copyright (c) 2012 Google Inc. See LICENSE for details. ** Our key invariants are:
* Author: Josh Haberman <jhaberman@gmail.com> ** 1. reference cycles never span groups
* ** 2. for ref2(to, from), we increment to's count iff group(from) != group(to)
* Our key invariants are: **
* 1. reference cycles never span groups ** The previous two are how we avoid leaking cycles. Other important
* 2. for ref2(to, from), we increment to's count iff group(from) != group(to) ** invariants are:
* ** 3. for mutable objects "from" and "to", if there exists a ref2(to, from)
* The previous two are how we avoid leaking cycles. Other important ** this implies group(from) == group(to). (In practice, what we implement
* invariants are: ** is even stronger; "from" and "to" will share a group if there has *ever*
* 3. for mutable objects "from" and "to", if there exists a ref2(to, from) ** been a ref2(to, from), but all that is necessary for correctness is the
* this implies group(from) == group(to). (In practice, what we implement ** weaker one).
* is even stronger; "from" and "to" will share a group if there has *ever* ** 4. mutable and immutable objects are never in the same group.
* been a ref2(to, from), but all that is necessary for correctness is the */
* weaker one).
* 4. mutable and immutable objects are never in the same group.
*/
#include <setjmp.h> #include <setjmp.h>
...@@ -3514,12 +3494,6 @@ bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s, ...@@ -3514,12 +3494,6 @@ bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
} }
return freeze(roots, n, s, maxdepth); return freeze(roots, n, s, maxdepth);
} }
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2013 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -3605,12 +3579,6 @@ const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s, ...@@ -3605,12 +3579,6 @@ const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s); return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
} }
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2008-2012 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -4041,13 +4009,10 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { ...@@ -4041,13 +4009,10 @@ const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
return upb_value_getptr(upb_strtable_iter_value(&iter->iter)); return upb_value_getptr(upb_strtable_iter_value(&iter->iter));
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb_table Implementation
* **
* Copyright (c) 2009 Google Inc. See LICENSE for details. ** Implementation is heavily inspired by Lua's ltable.c.
* Author: Josh Haberman <jhaberman@gmail.com> */
*
* Implementation is heavily inspired by Lua's ltable.c.
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -4931,12 +4896,6 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) { ...@@ -4931,12 +4896,6 @@ uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) {
#undef MIX #undef MIX
#endif /* UPB_UNALIGNED_READS_OK */ #endif /* UPB_UNALIGNED_READS_OK */
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2009-2012 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
...@@ -5860,17 +5819,12 @@ static upb_inttable reftables[212] = { ...@@ -5860,17 +5819,12 @@ static upb_inttable reftables[212] = {
#endif #endif
/* /*
* upb - a minimalist implementation of protocol buffers. ** XXX: The routines in this file that consume a string do not currently
* ** support having the string span buffers. In the future, as upb_sink and
* Copyright (c) 2008-2009 Google Inc. See LICENSE for details. ** its buffering/sharing functionality evolve there should be an easy and
* Author: Josh Haberman <jhaberman@gmail.com> ** idiomatic way of correctly handling this case. For now, we accept this
* ** limitation since we currently only parse descriptors from single strings.
* XXX: The routines in this file that consume a string do not currently */
* support having the string span buffers. In the future, as upb_sink and
* its buffering/sharing functionality evolve there should be an easy and
* idiomatic way of correctly handling this case. For now, we accept this
* limitation since we currently only parse descriptors from single strings.
*/
#include <errno.h> #include <errno.h>
...@@ -6518,21 +6472,18 @@ const upb_handlers *upb_descreader_newhandlers(const void *owner) { ...@@ -6518,21 +6472,18 @@ const upb_handlers *upb_descreader_newhandlers(const void *owner) {
return h; return h;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** protobuf decoder bytecode compiler
* **
* Copyright (c) 2013 Google Inc. See LICENSE for details. ** Code to compile a upb::Handlers into bytecode for decoding a protobuf
* Author: Josh Haberman <jhaberman@gmail.com> ** according to that specific schema and destination handlers.
* **
* Code to compile a upb::Handlers into bytecode for decoding a protobuf ** Compiling to bytecode is always the first step. If we are using the
* according to that specific schema and destination handlers. ** interpreted decoder we leave it as bytecode and interpret that. If we are
* ** using a JIT decoder we use a code generator to turn the bytecode into native
* Compiling to bytecode is always the first step. If we are using the ** code, LLVM IR, etc.
* interpreted decoder we leave it as bytecode and interpret that. If we are **
* using a JIT decoder we use a code generator to turn the bytecode into native ** Bytecode definition is in decoder.int.h.
* code, LLVM IR, etc. */
*
* Bytecode definition is in decoder.int.h.
*/
#include <stdarg.h> #include <stdarg.h>
...@@ -7502,24 +7453,19 @@ void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) { ...@@ -7502,24 +7453,19 @@ void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) {
opts->lazy = lazy; opts->lazy = lazy;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::Decoder (Bytecode Decoder VM)
* **
* Copyright (c) 2008-2013 Google Inc. See LICENSE for details. ** Bytecode must previously have been generated using the bytecode compiler in
* Author: Josh Haberman <jhaberman@gmail.com> ** compile_decoder.c. This decoder then walks through the bytecode op-by-op to
* ** parse the input.
* This file implements a VM for the interpreted (bytecode) decoder. **
* ** Decoding is fully resumable; we just keep a pointer to the current bytecode
* Bytecode must previously have been generated using the bytecode compiler in ** instruction and resume from there. A fair amount of the logic here is to
* compile_decoder.c. This decoder then walks through the bytecode op-by-op to ** handle the fact that values can span buffer seams and we have to be able to
* parse the input. ** be capable of suspending/resuming from any byte in the stream. This
* ** sometimes requires keeping a few trailing bytes from the last buffer around
* Decoding is fully resumable; we just keep a pointer to the current bytecode ** in the "residual" buffer.
* instruction and resume from there. A fair amount of the logic here is to */
* handle the fact that values can span buffer seams and we have to be able to
* be capable of suspending/resuming from any byte in the stream. This
* sometimes requires keeping a few trailing bytes from the last buffer around
* in the "residual" buffer.
*/
#include <inttypes.h> #include <inttypes.h>
#include <stddef.h> #include <stddef.h>
...@@ -8529,63 +8475,60 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { ...@@ -8529,63 +8475,60 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
return true; return true;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::Encoder
* **
* Copyright (c) 2014 Google Inc. See LICENSE for details. ** Since we are implementing pure handlers (ie. without any out-of-band access
* Author: Josh Haberman <jhaberman@gmail.com> ** to pre-computed lengths), we have to buffer all submessages before we can
* ** emit even their first byte.
* Since we are implementing pure handlers (ie. without any out-of-band access **
* to pre-computed lengths), we have to buffer all submessages before we can ** Not knowing the size of submessages also means we can't write a perfect
* emit even their first byte. ** zero-copy implementation, even with buffering. Lengths are stored as
* ** varints, which means that we don't know how many bytes to reserve for the
* Not knowing the size of submessages also means we can't write a perfect ** length until we know what the length is.
* zero-copy implementation, even with buffering. Lengths are stored as **
* varints, which means that we don't know how many bytes to reserve for the ** This leaves us with three main choices:
* length until we know what the length is. **
* ** 1. buffer all submessage data in a temporary buffer, then copy it exactly
* This leaves us with three main choices: ** once into the output buffer.
* **
* 1. buffer all submessage data in a temporary buffer, then copy it exactly ** 2. attempt to buffer data directly into the output buffer, estimating how
* once into the output buffer. ** many bytes each length will take. When our guesses are wrong, use
* ** memmove() to grow or shrink the allotted space.
* 2. attempt to buffer data directly into the output buffer, estimating how **
* many bytes each length will take. When our guesses are wrong, use ** 3. buffer directly into the output buffer, allocating a max length
* memmove() to grow or shrink the allotted space. ** ahead-of-time for each submessage length. If we overallocated, we waste
* ** space, but no memcpy() or memmove() is required. This approach requires
* 3. buffer directly into the output buffer, allocating a max length ** defining a maximum size for submessages and rejecting submessages that
* ahead-of-time for each submessage length. If we overallocated, we waste ** exceed that size.
* space, but no memcpy() or memmove() is required. This approach requires **
* defining a maximum size for submessages and rejecting submessages that ** (2) and (3) have the potential to have better performance, but they are more
* exceed that size. ** complicated and subtle to implement:
* **
* (2) and (3) have the potential to have better performance, but they are more ** (3) requires making an arbitrary choice of the maximum message size; it
* complicated and subtle to implement: ** wastes space when submessages are shorter than this and fails
* ** completely when they are longer. This makes it more finicky and
* (3) requires making an arbitrary choice of the maximum message size; it ** requires configuration based on the input. It also makes it impossible
* wastes space when submessages are shorter than this and fails ** to perfectly match the output of reference encoders that always use the
* completely when they are longer. This makes it more finicky and ** optimal amount of space for each length.
* requires configuration based on the input. It also makes it impossible **
* to perfectly match the output of reference encoders that always use the ** (2) requires guessing the the size upfront, and if multiple lengths are
* optimal amount of space for each length. ** guessed wrong the minimum required number of memmove() operations may
* ** be complicated to compute correctly. Implemented properly, it may have
* (2) requires guessing the the size upfront, and if multiple lengths are ** a useful amortized or average cost, but more investigation is required
* guessed wrong the minimum required number of memmove() operations may ** to determine this and what the optimal algorithm is to achieve it.
* be complicated to compute correctly. Implemented properly, it may have **
* a useful amortized or average cost, but more investigation is required ** (1) makes you always pay for exactly one copy, but its implementation is
* to determine this and what the optimal algorithm is to achieve it. ** the simplest and its performance is predictable.
* **
* (1) makes you always pay for exactly one copy, but its implementation is ** So for now, we implement (1) only. If we wish to optimize later, we should
* the simplest and its performance is predictable. ** be able to do it without affecting users.
* **
* So for now, we implement (1) only. If we wish to optimize later, we should ** The strategy is to buffer the segments of data that do *not* depend on
* be able to do it without affecting users. ** unknown lengths in one buffer, and keep a separate buffer of segment pointers
* ** and lengths. When the top-level submessage ends, we can go beginning to end,
* The strategy is to buffer the segments of data that do *not* depend on ** alternating the writing of lengths with memcpy() of the rest of the data.
* unknown lengths in one buffer, and keep a separate buffer of segment pointers ** At the top level though, no buffering is required.
* and lengths. When the top-level submessage ends, we can go beginning to end, */
* alternating the writing of lengths with memcpy() of the rest of the data.
* At the top level though, no buffering is required.
*/
#include <stdlib.h> #include <stdlib.h>
...@@ -9095,12 +9038,6 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, ...@@ -9095,12 +9038,6 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
} }
upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; } upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; }
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2010-2012 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include <stdio.h> #include <stdio.h>
...@@ -9189,10 +9126,7 @@ bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname, ...@@ -9189,10 +9126,7 @@ bool upb_load_descriptor_file_into_symtab(upb_symtab *symtab, const char *fname,
return success; return success;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. * upb::pb::TextPrinter
*
* Copyright (c) 2009 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
* *
* OPT: This is not optimized at all. It uses printf() which parses the format * OPT: This is not optimized at all. It uses printf() which parses the format
* string every time, and it allocates memory for every put. * string every time, and it allocates memory for every put.
...@@ -9529,12 +9463,6 @@ upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; } ...@@ -9529,12 +9463,6 @@ upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) { void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
p->single_line_ = single_line; p->single_line_ = single_line;
} }
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2011 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*/
/* Index is descriptor type. */ /* Index is descriptor type. */
...@@ -9662,28 +9590,25 @@ upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) { ...@@ -9662,28 +9590,25 @@ upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
#line 1 "upb/json/parser.rl" #line 1 "upb/json/parser.rl"
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::json::Parser (upb_json_parser)
* **
* Copyright (c) 2014 Google Inc. See LICENSE for details. ** A parser that uses the Ragel State Machine Compiler to generate
* Author: Josh Haberman <jhaberman@gmail.com> ** the finite automata.
* **
* A parser that uses the Ragel State Machine Compiler to generate ** Ragel only natively handles regular languages, but we can manually
* the finite automata. ** program it a bit to handle context-free languages like JSON, by using
* ** the "fcall" and "fret" constructs.
* Ragel only natively handles regular languages, but we can manually **
* program it a bit to handle context-free languages like JSON, by using ** This parser can handle the basics, but needs several things to be fleshed
* the "fcall" and "fret" constructs. ** out:
* **
* This parser can handle the basics, but needs several things to be fleshed ** - handling of unicode escape sequences (including high surrogate pairs).
* out: ** - properly check and report errors for unknown fields, stack overflow,
* ** improper array nesting (or lack of nesting).
* - handling of unicode escape sequences (including high surrogate pairs). ** - handling of base64 sequences with padding characters.
* - properly check and report errors for unknown fields, stack overflow, ** - handling of push-back (non-success returns from sink functions).
* improper array nesting (or lack of nesting). ** - handling of keys/escape-sequences/etc that span input buffers.
* - handling of base64 sequences with padding characters. */
* - handling of push-back (non-success returns from sink functions).
* - handling of keys/escape-sequences/etc that span input buffers.
*/
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
...@@ -9731,7 +9656,7 @@ struct upb_json_parser { ...@@ -9731,7 +9656,7 @@ struct upb_json_parser {
upb_jsonparser_frame *top; upb_jsonparser_frame *top;
upb_jsonparser_frame *limit; upb_jsonparser_frame *limit;
upb_status *status; upb_status status;
/* Ragel's internal parsing stack for the parsing state machine. */ /* Ragel's internal parsing stack for the parsing state machine. */
int current_state; int current_state;
...@@ -9778,7 +9703,8 @@ static upb_selector_t parser_getsel(upb_json_parser *p) { ...@@ -9778,7 +9703,8 @@ static upb_selector_t parser_getsel(upb_json_parser *p) {
static bool check_stack(upb_json_parser *p) { static bool check_stack(upb_json_parser *p) {
if ((p->top + 1) == p->limit) { if ((p->top + 1) == p->limit) {
upb_status_seterrmsg(p->status, "Nesting too deep"); upb_status_seterrmsg(&p->status, "Nesting too deep");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -9860,9 +9786,10 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, ...@@ -9860,9 +9786,10 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
char output[3]; char output[3];
if (limit - ptr < 4) { if (limit - ptr < 4) {
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"Base64 input for bytes field not a multiple of 4: %s", "Base64 input for bytes field not a multiple of 4: %s",
upb_fielddef_name(p->top->f)); upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -9886,9 +9813,10 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, ...@@ -9886,9 +9813,10 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
otherchar: otherchar:
if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) || if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
nonbase64(ptr[3]) ) { nonbase64(ptr[3]) ) {
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"Non-base64 characters in bytes field: %s", "Non-base64 characters in bytes field: %s",
upb_fielddef_name(p->top->f)); upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false; return false;
} if (ptr[2] == '=') { } if (ptr[2] == '=') {
uint32_t val; uint32_t val;
...@@ -9926,10 +9854,11 @@ otherchar: ...@@ -9926,10 +9854,11 @@ otherchar:
} }
badpadding: badpadding:
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"Incorrect base64 padding for field: %s (%.*s)", "Incorrect base64 padding for field: %s (%.*s)",
upb_fielddef_name(p->top->f), upb_fielddef_name(p->top->f),
4, ptr); 4, ptr);
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -9976,7 +9905,8 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) { ...@@ -9976,7 +9905,8 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
if (!mem) { if (!mem) {
upb_status_seterrmsg(p->status, "Out of memory allocating buffer."); upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -9999,7 +9929,8 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, ...@@ -9999,7 +9929,8 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
} }
if (!checked_add(p->accumulated_len, len, &need)) { if (!checked_add(p->accumulated_len, len, &need)) {
upb_status_seterrmsg(p->status, "Integer overflow."); upb_status_seterrmsg(&p->status, "Integer overflow.");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -10077,7 +10008,8 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, ...@@ -10077,7 +10008,8 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
switch (p->multipart_state) { switch (p->multipart_state) {
case MULTIPART_INACTIVE: case MULTIPART_INACTIVE:
upb_status_seterrmsg( upb_status_seterrmsg(
p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
upb_env_reporterror(p->env, &p->status);
return false; return false;
case MULTIPART_ACCUMULATE: case MULTIPART_ACCUMULATE:
...@@ -10336,7 +10268,8 @@ static bool parse_number(upb_json_parser *p) { ...@@ -10336,7 +10268,8 @@ static bool parse_number(upb_json_parser *p) {
return true; return true;
err: err:
upb_status_seterrf(p->status, "error parsing number: %s", buf); upb_status_seterrf(&p->status, "error parsing number: %s", buf);
upb_env_reporterror(p->env, &p->status);
multipart_end(p); multipart_end(p);
return false; return false;
} }
...@@ -10345,9 +10278,10 @@ static bool parser_putbool(upb_json_parser *p, bool val) { ...@@ -10345,9 +10278,10 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
bool ok; bool ok;
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"Boolean value specified for non-bool field: %s", "Boolean value specified for non-bool field: %s",
upb_fielddef_name(p->top->f)); upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -10398,9 +10332,10 @@ static bool start_stringval(upb_json_parser *p) { ...@@ -10398,9 +10332,10 @@ static bool start_stringval(upb_json_parser *p) {
multipart_startaccum(p); multipart_startaccum(p);
return true; return true;
} else { } else {
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"String specified for non-string/non-enum field: %s", "String specified for non-string/non-enum field: %s",
upb_fielddef_name(p->top->f)); upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
} }
...@@ -10438,7 +10373,8 @@ static bool end_stringval(upb_json_parser *p) { ...@@ -10438,7 +10373,8 @@ static bool end_stringval(upb_json_parser *p) {
upb_selector_t sel = parser_getsel(p); upb_selector_t sel = parser_getsel(p);
upb_sink_putint32(&p->top->sink, sel, int_val); upb_sink_putint32(&p->top->sink, sel, int_val);
} else { } else {
upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
upb_env_reporterror(p->env, &p->status);
} }
break; break;
...@@ -10446,7 +10382,8 @@ static bool end_stringval(upb_json_parser *p) { ...@@ -10446,7 +10382,8 @@ static bool end_stringval(upb_json_parser *p) {
default: default:
assert(false); assert(false);
upb_status_seterrmsg(p->status, "Internal error in JSON decoder"); upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
upb_env_reporterror(p->env, &p->status);
ok = false; ok = false;
break; break;
} }
...@@ -10476,7 +10413,8 @@ static bool parse_mapentry_key(upb_json_parser *p) { ...@@ -10476,7 +10413,8 @@ static bool parse_mapentry_key(upb_json_parser *p) {
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY); p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) { if (p->top->f == NULL) {
upb_status_seterrmsg(p->status, "mapentry message has no key"); upb_status_seterrmsg(&p->status, "mapentry message has no key");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
switch (upb_fielddef_type(p->top->f)) { switch (upb_fielddef_type(p->top->f)) {
...@@ -10499,8 +10437,9 @@ static bool parse_mapentry_key(upb_json_parser *p) { ...@@ -10499,8 +10437,9 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return false; return false;
} }
} else { } else {
upb_status_seterrmsg(p->status, upb_status_seterrmsg(&p->status,
"Map bool key not 'true' or 'false'"); "Map bool key not 'true' or 'false'");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
multipart_end(p); multipart_end(p);
...@@ -10518,7 +10457,8 @@ static bool parse_mapentry_key(upb_json_parser *p) { ...@@ -10518,7 +10457,8 @@ static bool parse_mapentry_key(upb_json_parser *p) {
break; break;
} }
default: default:
upb_status_seterrmsg(p->status, "Invalid field type for map key"); upb_status_seterrmsg(&p->status, "Invalid field type for map key");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -10573,7 +10513,8 @@ static bool handle_mapentry(upb_json_parser *p) { ...@@ -10573,7 +10513,8 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */ p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
p->top->mapfield = mapfield; p->top->mapfield = mapfield;
if (p->top->f == NULL) { if (p->top->f == NULL) {
upb_status_seterrmsg(p->status, "mapentry message has no value"); upb_status_seterrmsg(&p->status, "mapentry message has no value");
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -10593,7 +10534,8 @@ static bool end_membername(upb_json_parser *p) { ...@@ -10593,7 +10534,8 @@ static bool end_membername(upb_json_parser *p) {
if (!f) { if (!f) {
/* TODO(haberman): Ignore unknown fields if requested/configured to do /* TODO(haberman): Ignore unknown fields if requested/configured to do
* so. */ * so. */
upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf); upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -10669,9 +10611,10 @@ static bool start_subobject(upb_json_parser *p) { ...@@ -10669,9 +10611,10 @@ static bool start_subobject(upb_json_parser *p) {
return true; return true;
} else { } else {
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"Object specified for non-message/group field: %s", "Object specified for non-message/group field: %s",
upb_fielddef_name(p->top->f)); upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
} }
...@@ -10697,9 +10640,10 @@ static bool start_array(upb_json_parser *p) { ...@@ -10697,9 +10640,10 @@ static bool start_array(upb_json_parser *p) {
assert(p->top->f); assert(p->top->f);
if (!upb_fielddef_isseq(p->top->f)) { if (!upb_fielddef_isseq(p->top->f)) {
upb_status_seterrf(p->status, upb_status_seterrf(&p->status,
"Array specified for non-repeated field: %s", "Array specified for non-repeated field: %s",
upb_fielddef_name(p->top->f)); upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false; return false;
} }
...@@ -10736,7 +10680,11 @@ static void start_object(upb_json_parser *p) { ...@@ -10736,7 +10680,11 @@ static void start_object(upb_json_parser *p) {
static void end_object(upb_json_parser *p) { static void end_object(upb_json_parser *p) {
if (!p->top->is_map) { if (!p->top->is_map) {
upb_status status; upb_status status;
upb_status_clear(&status);
upb_sink_endmsg(&p->top->sink, &status); upb_sink_endmsg(&p->top->sink, &status);
if (!upb_ok(&status)) {
upb_env_reporterror(p->env, &status);
}
} }
} }
...@@ -10762,11 +10710,11 @@ static void end_object(upb_json_parser *p) { ...@@ -10762,11 +10710,11 @@ static void end_object(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */ * final state once, when the closing '"' is seen. */
#line 1198 "upb/json/parser.rl" #line 1218 "upb/json/parser.rl"
#line 1110 "upb/json/parser.c" #line 1130 "upb/json/parser.c"
static const char _json_actions[] = { static const char _json_actions[] = {
0, 1, 0, 1, 2, 1, 3, 1, 0, 1, 0, 1, 2, 1, 3, 1,
5, 1, 6, 1, 7, 1, 8, 1, 5, 1, 6, 1, 7, 1, 8, 1,
...@@ -10915,7 +10863,7 @@ static const int json_en_value_machine = 27; ...@@ -10915,7 +10863,7 @@ static const int json_en_value_machine = 27;
static const int json_en_main = 1; static const int json_en_main = 1;
#line 1201 "upb/json/parser.rl" #line 1221 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size, size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) { const upb_bufhandle *handle) {
...@@ -10937,7 +10885,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, ...@@ -10937,7 +10885,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf); capture_resume(parser, buf);
#line 1281 "upb/json/parser.c" #line 1301 "upb/json/parser.c"
{ {
int _klen; int _klen;
unsigned int _trans; unsigned int _trans;
...@@ -11012,118 +10960,118 @@ _match: ...@@ -11012,118 +10960,118 @@ _match:
switch ( *_acts++ ) switch ( *_acts++ )
{ {
case 0: case 0:
#line 1113 "upb/json/parser.rl" #line 1133 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 1: case 1:
#line 1114 "upb/json/parser.rl" #line 1134 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 10; goto _again;} } { p--; {stack[top++] = cs; cs = 10; goto _again;} }
break; break;
case 2: case 2:
#line 1118 "upb/json/parser.rl" #line 1138 "upb/json/parser.rl"
{ start_text(parser, p); } { start_text(parser, p); }
break; break;
case 3: case 3:
#line 1119 "upb/json/parser.rl" #line 1139 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); } { CHECK_RETURN_TOP(end_text(parser, p)); }
break; break;
case 4: case 4:
#line 1125 "upb/json/parser.rl" #line 1145 "upb/json/parser.rl"
{ start_hex(parser); } { start_hex(parser); }
break; break;
case 5: case 5:
#line 1126 "upb/json/parser.rl" #line 1146 "upb/json/parser.rl"
{ hexdigit(parser, p); } { hexdigit(parser, p); }
break; break;
case 6: case 6:
#line 1127 "upb/json/parser.rl" #line 1147 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); } { CHECK_RETURN_TOP(end_hex(parser)); }
break; break;
case 7: case 7:
#line 1133 "upb/json/parser.rl" #line 1153 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); } { CHECK_RETURN_TOP(escape(parser, p)); }
break; break;
case 8: case 8:
#line 1139 "upb/json/parser.rl" #line 1159 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
case 9: case 9:
#line 1142 "upb/json/parser.rl" #line 1162 "upb/json/parser.rl"
{ {stack[top++] = cs; cs = 19; goto _again;} } { {stack[top++] = cs; cs = 19; goto _again;} }
break; break;
case 10: case 10:
#line 1144 "upb/json/parser.rl" #line 1164 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 27; goto _again;} } { p--; {stack[top++] = cs; cs = 27; goto _again;} }
break; break;
case 11: case 11:
#line 1149 "upb/json/parser.rl" #line 1169 "upb/json/parser.rl"
{ start_member(parser); } { start_member(parser); }
break; break;
case 12: case 12:
#line 1150 "upb/json/parser.rl" #line 1170 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); } { CHECK_RETURN_TOP(end_membername(parser)); }
break; break;
case 13: case 13:
#line 1153 "upb/json/parser.rl" #line 1173 "upb/json/parser.rl"
{ end_member(parser); } { end_member(parser); }
break; break;
case 14: case 14:
#line 1159 "upb/json/parser.rl" #line 1179 "upb/json/parser.rl"
{ start_object(parser); } { start_object(parser); }
break; break;
case 15: case 15:
#line 1162 "upb/json/parser.rl" #line 1182 "upb/json/parser.rl"
{ end_object(parser); } { end_object(parser); }
break; break;
case 16: case 16:
#line 1168 "upb/json/parser.rl" #line 1188 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); } { CHECK_RETURN_TOP(start_array(parser)); }
break; break;
case 17: case 17:
#line 1172 "upb/json/parser.rl" #line 1192 "upb/json/parser.rl"
{ end_array(parser); } { end_array(parser); }
break; break;
case 18: case 18:
#line 1177 "upb/json/parser.rl" #line 1197 "upb/json/parser.rl"
{ start_number(parser, p); } { start_number(parser, p); }
break; break;
case 19: case 19:
#line 1178 "upb/json/parser.rl" #line 1198 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); } { CHECK_RETURN_TOP(end_number(parser, p)); }
break; break;
case 20: case 20:
#line 1180 "upb/json/parser.rl" #line 1200 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); } { CHECK_RETURN_TOP(start_stringval(parser)); }
break; break;
case 21: case 21:
#line 1181 "upb/json/parser.rl" #line 1201 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); } { CHECK_RETURN_TOP(end_stringval(parser)); }
break; break;
case 22: case 22:
#line 1183 "upb/json/parser.rl" #line 1203 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(parser_putbool(parser, true)); } { CHECK_RETURN_TOP(parser_putbool(parser, true)); }
break; break;
case 23: case 23:
#line 1185 "upb/json/parser.rl" #line 1205 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(parser_putbool(parser, false)); } { CHECK_RETURN_TOP(parser_putbool(parser, false)); }
break; break;
case 24: case 24:
#line 1187 "upb/json/parser.rl" #line 1207 "upb/json/parser.rl"
{ /* null value */ } { /* null value */ }
break; break;
case 25: case 25:
#line 1189 "upb/json/parser.rl" #line 1209 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject(parser)); } { CHECK_RETURN_TOP(start_subobject(parser)); }
break; break;
case 26: case 26:
#line 1190 "upb/json/parser.rl" #line 1210 "upb/json/parser.rl"
{ end_subobject(parser); } { end_subobject(parser); }
break; break;
case 27: case 27:
#line 1195 "upb/json/parser.rl" #line 1215 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} } { p--; {cs = stack[--top]; goto _again;} }
break; break;
#line 1467 "upb/json/parser.c" #line 1487 "upb/json/parser.c"
} }
} }
...@@ -11136,10 +11084,11 @@ _again: ...@@ -11136,10 +11084,11 @@ _again:
_out: {} _out: {}
} }
#line 1222 "upb/json/parser.rl" #line 1242 "upb/json/parser.rl"
if (p != pe) { if (p != pe) {
upb_status_seterrf(parser->status, "Parse error at %s\n", p); upb_status_seterrf(&parser->status, "Parse error at %s\n", p);
upb_env_reporterror(parser->env, &parser->status);
} else { } else {
capture_suspend(parser, &p); capture_suspend(parser, &p);
} }
...@@ -11176,19 +11125,20 @@ static void json_parser_reset(upb_json_parser *p) { ...@@ -11176,19 +11125,20 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */ /* Emit Ragel initialization of the parser. */
#line 1520 "upb/json/parser.c" #line 1541 "upb/json/parser.c"
{ {
cs = json_start; cs = json_start;
top = 0; top = 0;
} }
#line 1261 "upb/json/parser.rl" #line 1282 "upb/json/parser.rl"
p->current_state = cs; p->current_state = cs;
p->parser_top = top; p->parser_top = top;
accumulate_clear(p); accumulate_clear(p);
p->multipart_state = MULTIPART_INACTIVE; p->multipart_state = MULTIPART_INACTIVE;
p->capture = NULL; p->capture = NULL;
p->accumulated = NULL; p->accumulated = NULL;
upb_status_clear(&p->status);
} }
...@@ -11214,8 +11164,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) { ...@@ -11214,8 +11164,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_sink *output) {
upb_sink_reset(&p->top->sink, output->handlers, output->closure); upb_sink_reset(&p->top->sink, output->handlers, output->closure);
p->top->m = upb_handlers_msgdef(output->handlers); p->top->m = upb_handlers_msgdef(output->handlers);
/* If this fails, uncomment and increase the value in parser.h. /* If this fails, uncomment and increase the value in parser.h. */
* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE); assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
return p; return p;
} }
...@@ -11224,14 +11174,9 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) { ...@@ -11224,14 +11174,9 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
return &p->input_; return &p->input_;
} }
/* /*
* upb - a minimalist implementation of protocol buffers. ** This currently uses snprintf() to format primitives, and could be optimized
* ** further.
* Copyright (c) 2014 Google Inc. See LICENSE for details. */
* Author: Josh Haberman <jhaberman@gmail.com>
*
* This currently uses snprintf() to format primitives, and could be optimized
* further.
*/
#include <stdlib.h> #include <stdlib.h>
......
// Amalgamated source file // Amalgamated source file
/* /*
* upb - a minimalist implementation of protocol buffers. ** Defs are upb's internal representation of the constructs that can appear
* ** in a .proto file:
* Copyright (c) 2009-2012 Google Inc. See LICENSE for details. **
* Author: Josh Haberman <jhaberman@gmail.com> ** - upb::MessageDef (upb_msgdef): describes a "message" construct.
* ** - upb::FieldDef (upb_fielddef): describes a message field.
* Defs are upb's internal representation of the constructs that can appear ** - upb::EnumDef (upb_enumdef): describes an enum.
* in a .proto file: ** - upb::OneofDef (upb_oneofdef): describes a oneof.
* ** - upb::Def (upb_def): base class of all the others.
* - upb_msgdef: describes a "message" construct. **
* - upb_fielddef: describes a message field. ** TODO: definitions of services.
* - upb_enumdef: describes an enum. **
* (TODO: definitions of services). ** Like upb_refcounted objects, defs are mutable only until frozen, and are
* ** only thread-safe once frozen.
* Like upb_refcounted objects, defs are mutable only until frozen, and are **
* only thread-safe once frozen. ** This is a mixed C/C++ interface that offers a full API to both languages.
* ** See the top-level README for more information.
* This is a mixed C/C++ interface that offers a full API to both languages. */
* See the top-level README for more information.
*/
#ifndef UPB_DEF_H_ #ifndef UPB_DEF_H_
#define UPB_DEF_H_ #define UPB_DEF_H_
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::RefCounted (upb_refcounted)
* **
* Copyright (c) 2009-2012 Google Inc. See LICENSE for details. ** A refcounting scheme that supports circular refs. It accomplishes this by
* Author: Josh Haberman <jhaberman@gmail.com> ** partitioning the set of objects into groups such that no cycle spans groups;
* ** we can then reference-count the group as a whole and ignore refs within the
* A refcounting scheme that supports circular refs. It accomplishes this by ** group. When objects are mutable, these groups are computed very
* partitioning the set of objects into groups such that no cycle spans groups; ** conservatively; we group any objects that have ever had a link between them.
* we can then reference-count the group as a whole and ignore refs within the ** When objects are frozen, we compute strongly-connected components which
* group. When objects are mutable, these groups are computed very ** allows us to be precise and only group objects that are actually cyclic.
* conservatively; we group any objects that have ever had a link between them. **
* When objects are frozen, we compute strongly-connected components which ** This is a mixed C/C++ interface that offers a full API to both languages.
* allows us to be precise and only group objects that are actually cyclic. ** See the top-level README for more information.
* */
* This is a mixed C/C++ interface that offers a full API to both languages.
* See the top-level README for more information.
*/
#ifndef UPB_REFCOUNTED_H_ #ifndef UPB_REFCOUNTED_H_
#define UPB_REFCOUNTED_H_ #define UPB_REFCOUNTED_H_
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb_table
* **
* Copyright (c) 2009 Google Inc. See LICENSE for details. ** This header is INTERNAL-ONLY! Its interfaces are not public or stable!
* Author: Josh Haberman <jhaberman@gmail.com> ** This file defines very fast int->upb_value (inttable) and string->upb_value
* ** (strtable) hash tables.
* This header is INTERNAL-ONLY! Its interfaces are not public or stable! **
* This file defines very fast int->upb_value (inttable) and string->upb_value ** The table uses chained scatter with Brent's variation (inspired by the Lua
* (strtable) hash tables. ** implementation of hash tables). The hash function for strings is Austin
* ** Appleby's "MurmurHash."
* The table uses chained scatter with Brent's variation (inspired by the Lua **
* implementation of hash tables). The hash function for strings is Austin ** The inttable uses uintptr_t as its key, which guarantees it can be used to
* Appleby's "MurmurHash." ** store pointers or integers of at least 32 bits (upb isn't really useful on
* ** systems where sizeof(void*) < 4).
* The inttable uses uintptr_t as its key, which guarantees it can be used to **
* store pointers or integers of at least 32 bits (upb isn't really useful on ** The table must be homogenous (all values of the same type). In debug
* systems where sizeof(void*) < 4). ** mode, we check this on insert and lookup.
* */
* The table must be homogenous (all values of the same type). In debug
* mode, we check this on insert and lookup.
*/
#ifndef UPB_TABLE_H_ #ifndef UPB_TABLE_H_
#define UPB_TABLE_H_ #define UPB_TABLE_H_
...@@ -73,16 +65,11 @@ ...@@ -73,16 +65,11 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
/* /*
* upb - a minimalist implementation of protocol buffers. ** This file contains shared definitions that are widely used across upb.
* **
* Copyright (c) 2009 Google Inc. See LICENSE for details. ** This is a mixed C/C++ interface that offers a full API to both languages.
* Author: Josh Haberman <jhaberman@gmail.com> ** See the top-level README for more information.
* */
* This file contains shared definitions that are widely used across upb.
*
* This is a mixed C/C++ interface that offers a full API to both languages.
* See the top-level README for more information.
*/
#ifndef UPB_H_ #ifndef UPB_H_
#define UPB_H_ #define UPB_H_
...@@ -3006,25 +2993,20 @@ inline bool OneofDef::const_iterator::operator!=( ...@@ -3006,25 +2993,20 @@ inline bool OneofDef::const_iterator::operator!=(
#endif /* UPB_DEF_H_ */ #endif /* UPB_DEF_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** This file contains definitions of structs that should be considered private
* ** and NOT stable across versions of upb.
* Copyright (c) 2015 Google Inc. See LICENSE for details. **
* Author: Josh Haberman <jhaberman@gmail.com> ** The only reason they are declared here and not in .c files is to allow upb
* ** and the application (if desired) to embed statically-initialized instances
* This file contains definitions of structs that should be considered private ** of structures like defs.
* and NOT stable across versions of upb. **
* ** If you include this file, all guarantees of ABI compatibility go out the
* The only reason they are declared here and not in .c files is to allow upb ** window! Any code that includes this file needs to recompile against the
* and the application (if desired) to embed statically-initialized instances ** exact same version of upb that they are linking against.
* of structures like defs. **
* ** You also need to recompile if you change the value of the UPB_DEBUG_REFS
* If you include this file, all guarantees of ABI compatibility go out the ** flag.
* window! Any code that includes this file needs to recompile against the */
* exact same version of upb that they are linking against.
*
* You also need to recompile if you change the value of the UPB_DEBUG_REFS
* flag.
*/
#ifndef UPB_STATICINIT_H_ #ifndef UPB_STATICINIT_H_
...@@ -3181,25 +3163,22 @@ struct upb_symtab { ...@@ -3181,25 +3163,22 @@ struct upb_symtab {
#endif /* UPB_STATICINIT_H_ */ #endif /* UPB_STATICINIT_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::Handlers (upb_handlers)
* **
* Copyright (c) 2010-2012 Google Inc. See LICENSE for details. ** A upb_handlers is like a virtual table for a upb_msgdef. Each field of the
* Author: Josh Haberman <jhaberman@gmail.com> ** message can have associated functions that will be called when we are
* ** parsing or visiting a stream of data. This is similar to how handlers work
* A upb_handlers is like a virtual table for a upb_msgdef. Each field of the ** in SAX (the Simple API for XML).
* message can have associated functions that will be called when we are **
* parsing or visiting a stream of data. This is similar to how handlers work ** The handlers have no idea where the data is coming from, so a single set of
* in SAX (the Simple API for XML). ** handlers could be used with two completely different data sources (for
* ** example, a parser and a visitor over in-memory objects). This decoupling is
* The handlers have no idea where the data is coming from, so a single set of ** the most important feature of upb, because it allows parsers and serializers
* handlers could be used with two completely different data sources (for ** to be highly reusable.
* example, a parser and a visitor over in-memory objects). This decoupling is **
* the most important feature of upb, because it allows parsers and serializers ** This is a mixed C/C++ interface that offers a full API to both languages.
* to be highly reusable. ** See the top-level README for more information.
* */
* This is a mixed C/C++ interface that offers a full API to both languages.
* See the top-level README for more information.
*/
#ifndef UPB_HANDLERS_H #ifndef UPB_HANDLERS_H
#define UPB_HANDLERS_H #define UPB_HANDLERS_H
...@@ -3980,14 +3959,9 @@ uint32_t upb_handlers_selectorcount(const upb_fielddef *f); ...@@ -3980,14 +3959,9 @@ uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
UPB_END_EXTERN_C UPB_END_EXTERN_C
/* /*
* upb - a minimalist implementation of protocol buffers. ** Inline definitions for handlers.h, which are particularly long and a bit
* ** tricky.
* Copyright (c) 2011-2012 Google Inc. See LICENSE for details. */
* Author: Josh Haberman <jhaberman@gmail.com>
*
* Inline definitions for handlers.h, which are particularly long and a bit
* tricky.
*/
#ifndef UPB_HANDLERS_INL_H_ #ifndef UPB_HANDLERS_INL_H_
#define UPB_HANDLERS_INL_H_ #define UPB_HANDLERS_INL_H_
...@@ -5128,21 +5102,18 @@ inline BytesHandler::~BytesHandler() {} ...@@ -5128,21 +5102,18 @@ inline BytesHandler::~BytesHandler() {}
#endif /* UPB_HANDLERS_H */ #endif /* UPB_HANDLERS_H */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::Environment (upb_env)
* **
* Copyright (c) 2014 Google Inc. See LICENSE for details. ** A upb::Environment provides a means for injecting malloc and an
* Author: Josh Haberman <jhaberman@gmail.com> ** error-reporting callback into encoders/decoders. This allows them to be
* ** independent of nearly all assumptions about their actual environment.
* A upb::Environment provides a means for injecting malloc and an **
* error-reporting callback into encoders/decoders. This allows them to be ** It is also a container for allocating the encoders/decoders themselves that
* independent of nearly all assumptions about their actual environment. ** insulates clients from knowing their actual size. This provides ABI
* ** compatibility even if the size of the objects change. And this allows the
* It is also a container for allocating the encoders/decoders themselves that ** structure definitions to be in the .c files instead of the .h files, making
* insulates clients from knowing their actual size. This provides ABI ** the .h files smaller and more readable.
* compatibility even if the size of the objects change. And this allows the */
* structure definitions to be in the .c files instead of the .h files, making
* the .h files smaller and more readable.
*/
#ifndef UPB_ENV_H_ #ifndef UPB_ENV_H_
...@@ -5392,23 +5363,21 @@ inline upb_alloc_func *SeededAllocator::GetAllocationFunction() { ...@@ -5392,23 +5363,21 @@ inline upb_alloc_func *SeededAllocator::GetAllocationFunction() {
#endif /* UPB_ENV_H_ */ #endif /* UPB_ENV_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::Sink (upb_sink)
* ** upb::BytesSink (upb_bytessink)
* Copyright (c) 2010-2012 Google Inc. See LICENSE for details. **
* Author: Josh Haberman <jhaberman@gmail.com> ** A upb_sink is an object that binds a upb_handlers object to some runtime
* ** state. It is the object that can actually receive data via the upb_handlers
* A upb_sink is an object that binds a upb_handlers object to some runtime ** interface.
* state. It is the object that can actually receive data via the upb_handlers **
* interface. ** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
* ** thread-safe. You can create as many of them as you want, but each one may
* Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or ** only be used in a single thread at a time.
* thread-safe. You can create as many of them as you want, but each one may **
* only be used in a single thread at a time. ** If we compare with class-based OOP, a you can think of a upb_def as an
* ** abstract base class, a upb_handlers as a concrete derived class, and a
* If we compare with class-based OOP, a you can think of a upb_def as an ** upb_sink as an object (class instance).
* abstract base class, a upb_handlers as a concrete derived class, and a */
* upb_sink as an object (class instance).
*/
#ifndef UPB_SINK_H #ifndef UPB_SINK_H
#define UPB_SINK_H #define UPB_SINK_H
...@@ -5921,21 +5890,16 @@ inline bool BufferSource::PutBuffer(const char *buf, size_t len, ...@@ -5921,21 +5890,16 @@ inline bool BufferSource::PutBuffer(const char *buf, size_t len,
#endif #endif
/* /*
* upb - a minimalist implementation of protocol buffers. ** For handlers that do very tiny, very simple operations, the function call
* ** overhead of calling a handler can be significant. This file allows the
* Copyright (c) 2013 Google Inc. See LICENSE for details. ** user to define handlers that do something very simple like store the value
* Author: Josh Haberman <jhaberman@gmail.com> ** to memory and/or set a hasbit. JIT compilers can then special-case these
* ** handlers and emit specialized code for them instead of actually calling the
* For handlers that do very tiny, very simple operations, the function call ** handler.
* overhead of calling a handler can be significant. This file allows the **
* user to define handlers that do something very simple like store the value ** The functionality is very simple/limited right now but may expand to be able
* to memory and/or set a hasbit. JIT compilers can then special-case these ** to call another function.
* handlers and emit specialized code for them instead of actually calling the */
* handler.
*
* The functionality is very simple/limited right now but may expand to be able
* to call another function.
*/
#ifndef UPB_SHIM_H #ifndef UPB_SHIM_H
#define UPB_SHIM_H #define UPB_SHIM_H
...@@ -5994,19 +5958,16 @@ inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s, ...@@ -5994,19 +5958,16 @@ inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s,
#endif /* UPB_SHIM_H */ #endif /* UPB_SHIM_H */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::SymbolTable (upb_symtab)
* **
* Copyright (c) 2009-2012 Google Inc. See LICENSE for details. ** A symtab (symbol table) stores a name->def map of upb_defs. Clients could
* Author: Josh Haberman <jhaberman@gmail.com> ** always create such tables themselves, but upb_symtab has logic for resolving
* ** symbolic references, and in particular, for keeping a whole set of consistent
* A symtab (symbol table) stores a name->def map of upb_defs. Clients could ** defs when replacing some subset of those defs. This logic is nontrivial.
* always create such tables themselves, but upb_symtab has logic for resolving **
* symbolic references, and in particular, for keeping a whole set of consistent ** This is a mixed C/C++ interface that offers a full API to both languages.
* defs when replacing some subset of those defs. This logic is nontrivial. ** See the top-level README for more information.
* */
* This is a mixed C/C++ interface that offers a full API to both languages.
* See the top-level README for more information.
*/
#ifndef UPB_SYMTAB_H_ #ifndef UPB_SYMTAB_H_
#define UPB_SYMTAB_H_ #define UPB_SYMTAB_H_
...@@ -6182,14 +6143,10 @@ inline bool SymbolTable::Add( ...@@ -6182,14 +6143,10 @@ inline bool SymbolTable::Add(
#endif /* UPB_SYMTAB_H_ */ #endif /* UPB_SYMTAB_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::descriptor::Reader (upb_descreader)
* **
* Copyright (c) 2011 Google Inc. See LICENSE for details. ** Provides a way of building upb::Defs from data in descriptor.proto format.
* Author: Josh Haberman <jhaberman@gmail.com> */
*
* upb::descriptor::Reader provides a way of building upb::Defs from
* data in descriptor.proto format.
*/
#ifndef UPB_DESCRIPTOR_H #ifndef UPB_DESCRIPTOR_H
#define UPB_DESCRIPTOR_H #define UPB_DESCRIPTOR_H
...@@ -7067,34 +7024,26 @@ inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::Fie ...@@ -7067,34 +7024,26 @@ inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::Fie
#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ */ #endif /* GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** Internal-only definitions for the decoder.
* */
* Copyright (c) 2009-2014 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
* Internal-only definitions for the decoder.
*/
#ifndef UPB_DECODER_INT_H_ #ifndef UPB_DECODER_INT_H_
#define UPB_DECODER_INT_H_ #define UPB_DECODER_INT_H_
#include <stdlib.h> #include <stdlib.h>
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::pb::Decoder
* **
* Copyright (c) 2009-2014 Google Inc. See LICENSE for details. ** A high performance, streaming, resumable decoder for the binary protobuf
* Author: Josh Haberman <jhaberman@gmail.com> ** format.
* **
* upb::pb::Decoder implements a high performance, streaming, resumable decoder ** This interface works the same regardless of what decoder backend is being
* for the binary protobuf format. ** used. A client of this class does not need to know whether decoding is using
* ** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default,
* This interface works the same regardless of what decoder backend is being ** it will always use the fastest available decoder. However, you can call
* used. A client of this class does not need to know whether decoding is using ** set_allow_jit(false) to disable any JIT decoder that might be available.
* a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default, ** This is primarily useful for testing purposes.
* it will always use the fastest available decoder. However, you can call */
* set_allow_jit(false) to disable any JIT decoder that might be available.
* This is primarily useful for testing purposes.
*/
#ifndef UPB_DECODER_H_ #ifndef UPB_DECODER_H_
#define UPB_DECODER_H_ #define UPB_DECODER_H_
...@@ -7702,14 +7651,9 @@ UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs, ...@@ -7702,14 +7651,9 @@ UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs,
#endif /* UPB_DECODER_INT_H_ */ #endif /* UPB_DECODER_INT_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** A number of routines for varint manipulation (we keep them all around to
* ** have multiple approaches available for benchmarking).
* Copyright (c) 2011 Google Inc. See LICENSE for details. */
* Author: Josh Haberman <jhaberman@gmail.com>
*
* A number of routines for varint manipulation (we keep them all around to
* have multiple approaches available for benchmarking).
*/
#ifndef UPB_VARINT_DECODER_H_ #ifndef UPB_VARINT_DECODER_H_
#define UPB_VARINT_DECODER_H_ #define UPB_VARINT_DECODER_H_
...@@ -7873,18 +7817,15 @@ UPB_INLINE uint64_t upb_vencode32(uint32_t val) { ...@@ -7873,18 +7817,15 @@ UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
#endif /* UPB_VARINT_DECODER_H_ */ #endif /* UPB_VARINT_DECODER_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::pb::Encoder (upb_pb_encoder)
* **
* Copyright (c) 2009-2010 Google Inc. See LICENSE for details. ** Implements a set of upb_handlers that write protobuf data to the binary wire
* Author: Josh Haberman <jhaberman@gmail.com> ** format.
* **
* Implements a set of upb_handlers that write protobuf data to the binary wire ** This encoder implementation does not have any access to any out-of-band or
* format. ** precomputed lengths for submessages, so it must buffer submessages internally
* ** before it can emit the first byte.
* This encoder implementation does not have any access to any out-of-band or */
* precomputed lengths for submessages, so it must buffer submessages internally
* before it can emit the first byte.
*/
#ifndef UPB_ENCODER_H_ #ifndef UPB_ENCODER_H_
#define UPB_ENCODER_H_ #define UPB_ENCODER_H_
...@@ -7966,29 +7907,24 @@ inline reffed_ptr<const Handlers> Encoder::NewHandlers( ...@@ -7966,29 +7907,24 @@ inline reffed_ptr<const Handlers> Encoder::NewHandlers(
#endif /* UPB_ENCODER_H_ */ #endif /* UPB_ENCODER_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb's core components like upb_decoder and upb_msg are carefully designed to
* ** avoid depending on each other for maximum orthogonality. In other words,
* Copyright (c) 2011-2012 Google Inc. See LICENSE for details. ** you can use a upb_decoder to decode into *any* kind of structure; upb_msg is
* Author: Josh Haberman <jhaberman@gmail.com> ** just one such structure. A upb_msg can be serialized/deserialized into any
* ** format, protobuf binary format is just one such format.
* upb's core components like upb_decoder and upb_msg are carefully designed to **
* avoid depending on each other for maximum orthogonality. In other words, ** However, for convenience we provide functions here for doing common
* you can use a upb_decoder to decode into *any* kind of structure; upb_msg is ** operations like deserializing protobuf binary format into a upb_msg. The
* just one such structure. A upb_msg can be serialized/deserialized into any ** compromise is that this file drags in almost all of upb as a dependency,
* format, protobuf binary format is just one such format. ** which could be undesirable if you're trying to use a trimmed-down build of
* ** upb.
* However, for convenience we provide functions here for doing common **
* operations like deserializing protobuf binary format into a upb_msg. The ** While these routines are convenient, they do not reuse any encoding/decoding
* compromise is that this file drags in almost all of upb as a dependency, ** state. For example, if a decoder is JIT-based, it will be re-JITted every
* which could be undesirable if you're trying to use a trimmed-down build of ** time these functions are called. For this reason, if you are parsing lots
* upb. ** of data and efficiency is an issue, these may not be the best functions to
* ** use (though they are useful for prototyping, before optimizing).
* While these routines are convenient, they do not reuse any encoding/decoding */
* state. For example, if a decoder is JIT-based, it will be re-JITted every
* time these functions are called. For this reason, if you are parsing lots
* of data and efficiency is an issue, these may not be the best functions to
* use (though they are useful for prototyping, before optimizing).
*/
#ifndef UPB_GLUE_H #ifndef UPB_GLUE_H
#define UPB_GLUE_H #define UPB_GLUE_H
...@@ -8047,11 +7983,10 @@ bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) { ...@@ -8047,11 +7983,10 @@ bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) {
#endif /* UPB_GLUE_H */ #endif /* UPB_GLUE_H */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::pb::TextPrinter (upb_textprinter)
* **
* Copyright (c) 2009 Google Inc. See LICENSE for details. ** Handlers for writing to protobuf text format.
* Author: Josh Haberman <jhaberman@gmail.com> */
*/
#ifndef UPB_TEXT_H_ #ifndef UPB_TEXT_H_
#define UPB_TEXT_H_ #define UPB_TEXT_H_
...@@ -8127,14 +8062,11 @@ inline reffed_ptr<const Handlers> TextPrinter::NewHandlers( ...@@ -8127,14 +8062,11 @@ inline reffed_ptr<const Handlers> TextPrinter::NewHandlers(
#endif /* UPB_TEXT_H_ */ #endif /* UPB_TEXT_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::json::Parser (upb_json_parser)
* **
* Copyright (c) 2014 Google Inc. See LICENSE for details. ** Parses JSON according to a specific schema.
* Author: Josh Haberman <jhaberman@gmail.com> ** Support for parsing arbitrary JSON (schema-less) will be added later.
* */
* upb::json::Parser can parse JSON according to a specific schema.
* Support for parsing arbitrary JSON (schema-less) will be added later.
*/
#ifndef UPB_JSON_PARSER_H_ #ifndef UPB_JSON_PARSER_H_
#define UPB_JSON_PARSER_H_ #define UPB_JSON_PARSER_H_
...@@ -8156,7 +8088,7 @@ UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser) ...@@ -8156,7 +8088,7 @@ UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser)
* constructed. This hint may be an overestimate for some build configurations. * constructed. This hint may be an overestimate for some build configurations.
* But if the parser library is upgraded without recompiling the application, * But if the parser library is upgraded without recompiling the application,
* it may be an underestimate. */ * it may be an underestimate. */
#define UPB_JSON_PARSER_SIZE 3568 #define UPB_JSON_PARSER_SIZE 3704
#ifdef __cplusplus #ifdef __cplusplus
...@@ -8199,14 +8131,10 @@ inline BytesSink* Parser::input() { ...@@ -8199,14 +8131,10 @@ inline BytesSink* Parser::input() {
#endif /* UPB_JSON_PARSER_H_ */ #endif /* UPB_JSON_PARSER_H_ */
/* /*
* upb - a minimalist implementation of protocol buffers. ** upb::json::Printer
* **
* Copyright (c) 2014 Google Inc. See LICENSE for details. ** Handlers that emit JSON according to a specific protobuf schema.
* Author: Josh Haberman <jhaberman@gmail.com> */
*
* upb::json::Printer allows you to create handlers that emit JSON
* according to a specific protobuf schema.
*/
#ifndef UPB_JSON_TYPED_PRINTER_H_ #ifndef UPB_JSON_TYPED_PRINTER_H_
#define UPB_JSON_TYPED_PRINTER_H_ #define UPB_JSON_TYPED_PRINTER_H_
......
...@@ -31,6 +31,15 @@ ...@@ -31,6 +31,15 @@
# require mixins before we hook them into the java & c code # require mixins before we hook them into the java & c code
require 'google/protobuf/message_exts' require 'google/protobuf/message_exts'
# We define these before requiring the platform-specific modules.
# That way the module init can grab references to these.
module Google
module Protobuf
class Error < StandardError; end
class ParseError < Error; end
end
end
if RUBY_PLATFORM == "java" if RUBY_PLATFORM == "java"
require 'json' require 'json'
require 'google/protobuf_java' require 'google/protobuf_java'
......
...@@ -5,11 +5,22 @@ set -e ...@@ -5,11 +5,22 @@ set -e
test_version() { test_version() {
version=$1 version=$1
bash --login -c \ if [ "$version" == "jruby" ] ; then
"rvm install $version && rvm use $version && \ # No conformance tests yet -- JRuby is too broken to run them.
which ruby && \ bash --login -c \
gem install bundler && bundle && \ "rvm install $version && rvm use $version && \
rake test" which ruby && \
gem install bundler && bundle && \
rake test"
else
bash --login -c \
"rvm install $version && rvm use $version && \
which ruby && \
gem install bundler && bundle && \
rake test && \
cd ../conformance && \
make test_ruby"
fi
} }
test_version $1 test_version $1
...@@ -13,7 +13,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do ...@@ -13,7 +13,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
optional :optional_double, :double, 6 optional :optional_double, :double, 6
optional :optional_float, :float, 7 optional :optional_float, :float, 7
optional :optional_string, :string, 8 optional :optional_string, :string, 8
optional :optional_bytes, :string, 9 optional :optional_bytes, :bytes, 9
optional :optional_enum, :enum, 10, "A.B.C.TestEnum" optional :optional_enum, :enum, 10, "A.B.C.TestEnum"
optional :optional_msg, :message, 11, "A.B.C.TestMessage" optional :optional_msg, :message, 11, "A.B.C.TestMessage"
repeated :repeated_int32, :int32, 21 repeated :repeated_int32, :int32, 21
...@@ -24,7 +24,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do ...@@ -24,7 +24,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
repeated :repeated_double, :double, 26 repeated :repeated_double, :double, 26
repeated :repeated_float, :float, 27 repeated :repeated_float, :float, 27
repeated :repeated_string, :string, 28 repeated :repeated_string, :string, 28
repeated :repeated_bytes, :string, 29 repeated :repeated_bytes, :bytes, 29
repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
map :map_int32_string, :int32, :string, 61 map :map_int32_string, :int32, :string, 61
...@@ -47,7 +47,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do ...@@ -47,7 +47,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
optional :oneof_double, :double, 46 optional :oneof_double, :double, 46
optional :oneof_float, :float, 47 optional :oneof_float, :float, 47
optional :oneof_string, :string, 48 optional :oneof_string, :string, 48
optional :oneof_bytes, :string, 49 optional :oneof_bytes, :bytes, 49
optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" optional :oneof_enum, :enum, 50, "A.B.C.TestEnum"
optional :oneof_msg, :message, 51, "A.B.C.TestMessage" optional :oneof_msg, :message, 51, "A.B.C.TestMessage"
end end
......
...@@ -47,7 +47,7 @@ namespace compiler { ...@@ -47,7 +47,7 @@ namespace compiler {
namespace ruby { namespace ruby {
// Forward decls. // Forward decls.
std::string IntToString(uint32 value); std::string IntToString(int32 value);
std::string StripDotProto(const std::string& proto_file); std::string StripDotProto(const std::string& proto_file);
std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string LabelForField(google::protobuf::FieldDescriptor* field);
std::string TypeName(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field);
...@@ -64,7 +64,7 @@ void GenerateEnumAssignment( ...@@ -64,7 +64,7 @@ void GenerateEnumAssignment(
const google::protobuf::EnumDescriptor* en, const google::protobuf::EnumDescriptor* en,
google::protobuf::io::Printer* printer); google::protobuf::io::Printer* printer);
std::string IntToString(uint32 value) { std::string IntToString(int32 value) {
std::ostringstream os; std::ostringstream os;
os << value; os << value;
return os.str(); return os.str();
...@@ -85,17 +85,25 @@ std::string LabelForField(const google::protobuf::FieldDescriptor* field) { ...@@ -85,17 +85,25 @@ std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
} }
std::string TypeName(const google::protobuf::FieldDescriptor* field) { std::string TypeName(const google::protobuf::FieldDescriptor* field) {
switch (field->cpp_type()) { switch (field->type()) {
case FieldDescriptor::CPPTYPE_INT32: return "int32"; case FieldDescriptor::TYPE_INT32: return "int32";
case FieldDescriptor::CPPTYPE_INT64: return "int64"; case FieldDescriptor::TYPE_INT64: return "int64";
case FieldDescriptor::CPPTYPE_UINT32: return "uint32"; case FieldDescriptor::TYPE_UINT32: return "uint32";
case FieldDescriptor::CPPTYPE_UINT64: return "uint64"; case FieldDescriptor::TYPE_UINT64: return "uint64";
case FieldDescriptor::CPPTYPE_DOUBLE: return "double"; case FieldDescriptor::TYPE_SINT32: return "sint32";
case FieldDescriptor::CPPTYPE_FLOAT: return "float"; case FieldDescriptor::TYPE_SINT64: return "sint64";
case FieldDescriptor::CPPTYPE_BOOL: return "bool"; case FieldDescriptor::TYPE_FIXED32: return "fixed32";
case FieldDescriptor::CPPTYPE_ENUM: return "enum"; case FieldDescriptor::TYPE_FIXED64: return "fixed64";
case FieldDescriptor::CPPTYPE_STRING: return "string"; case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
case FieldDescriptor::CPPTYPE_MESSAGE: return "message"; case FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
case FieldDescriptor::TYPE_DOUBLE: return "double";
case FieldDescriptor::TYPE_FLOAT: return "float";
case FieldDescriptor::TYPE_BOOL: return "bool";
case FieldDescriptor::TYPE_ENUM: return "enum";
case FieldDescriptor::TYPE_STRING: return "string";
case FieldDescriptor::TYPE_BYTES: return "bytes";
case FieldDescriptor::TYPE_MESSAGE: return "message";
case FieldDescriptor::TYPE_GROUP: return "group";
default: assert(false); return ""; default: assert(false); return "";
} }
} }
......
...@@ -8,10 +8,16 @@ ...@@ -8,10 +8,16 @@
# .travis.yml uses matrix.exclude to block the cases where app-get can't be # .travis.yml uses matrix.exclude to block the cases where app-get can't be
# use to install things. # use to install things.
build_cpp() { # For when some other test needs the C++ main build, including protoc and
# libprotobuf.
internal_build_cpp() {
./autogen.sh ./autogen.sh
./configure ./configure
make -j2 make -j2
}
build_cpp() {
internal_build_cpp
make check -j2 make check -j2
cd conformance && make test_cpp && cd .. cd conformance && make test_cpp && cd ..
} }
...@@ -62,18 +68,14 @@ use_java() { ...@@ -62,18 +68,14 @@ use_java() {
build_java() { build_java() {
# Java build needs `protoc`. # Java build needs `protoc`.
./autogen.sh internal_build_cpp
./configure
make -j2
cd java && mvn test && cd .. cd java && mvn test && cd ..
cd conformance && make test_java && cd .. cd conformance && make test_java && cd ..
} }
build_javanano() { build_javanano() {
# Java build needs `protoc`. # Java build needs `protoc`.
./autogen.sh internal_build_cpp
./configure
make -j2
cd javanano && mvn test && cd .. cd javanano && mvn test && cd ..
} }
...@@ -104,9 +106,7 @@ build_javanano_oracle7() { ...@@ -104,9 +106,7 @@ build_javanano_oracle7() {
} }
build_python() { build_python() {
./autogen.sh internal_build_cpp
./configure
make -j2
cd python cd python
python setup.py build python setup.py build
python setup.py test python setup.py test
...@@ -116,9 +116,7 @@ build_python() { ...@@ -116,9 +116,7 @@ build_python() {
} }
build_python_cpp() { build_python_cpp() {
./autogen.sh internal_build_cpp
./configure
make -j2
export LD_LIBRARY_PATH=../src/.libs # for Linux export LD_LIBRARY_PATH=../src/.libs # for Linux
export DYLD_LIBRARY_PATH=../src/.libs # for OS X export DYLD_LIBRARY_PATH=../src/.libs # for OS X
cd python cd python
...@@ -130,18 +128,23 @@ build_python_cpp() { ...@@ -130,18 +128,23 @@ build_python_cpp() {
} }
build_ruby19() { build_ruby19() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh ruby-1.9 && cd .. cd ruby && bash travis-test.sh ruby-1.9 && cd ..
} }
build_ruby20() { build_ruby20() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh ruby-2.0 && cd .. cd ruby && bash travis-test.sh ruby-2.0 && cd ..
} }
build_ruby21() { build_ruby21() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh ruby-2.1 && cd .. cd ruby && bash travis-test.sh ruby-2.1 && cd ..
} }
build_ruby22() { build_ruby22() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh ruby-2.2 && cd .. cd ruby && bash travis-test.sh ruby-2.2 && cd ..
} }
build_jruby() { build_jruby() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh jruby && cd .. cd ruby && bash travis-test.sh jruby && cd ..
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment