Commit 2ee4b566 authored by Jon Skeet's avatar Jon Skeet

Merge pull request #629 from google/master

Integrate changes from upstream/master into csharp-experimental
parents c792db5d 353b7a99
......@@ -85,15 +85,24 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_intern
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_tsan.h include\google\protobuf\stubs\atomicops_internals_tsan.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h include\google\protobuf\stubs\atomicops_internals_x86_gcc.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h include\google\protobuf\stubs\bytestream.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h include\google\protobuf\stubs\callback.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h include\google\protobuf\stubs\casts.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastmem.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h include\google\protobuf\stubs\logging.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h include\google\protobuf\stubs\macros.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h include\google\protobuf\stubs\mutex.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h include\google\protobuf\stubs\port.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\scoped_ptr.h include\google\protobuf\stubs\scoped_ptr.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\shared_ptr.h include\google\protobuf\stubs\shared_ptr.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h include\google\protobuf\stubs\status.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h include\google\protobuf\stubs\stringpiece.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h include\google\protobuf\text_format.h
......
......@@ -22,7 +22,7 @@ conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
if USE_EXTERNAL_PROTOC
protoc_middleman: $(protoc_inputs)
$(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. $^
$(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. --ruby_out=. $^
touch protoc_middleman
else
......@@ -31,7 +31,7 @@ else
# relative to srcdir, which may not be the same as the current directory when
# building out-of-tree.
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
endif
......@@ -61,3 +61,6 @@ test_cpp: protoc_middleman conformance-test-runner conformance-cpp
test_java: protoc_middleman 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 {
public:
ConformanceTestSuite() : verbose_(false) {}
void SetVerbose(bool verbose) { verbose_ = verbose; }
// 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
// as this list.
......
......@@ -219,12 +219,16 @@ void ParseFailureList(const char *filename, vector<string>* failure_list) {
int main(int argc, char *argv[]) {
int arg = 1;
char *program;
vector<string> failure_list;
google::protobuf::ConformanceTestSuite suite;
for (int arg = 1; arg < argc; ++arg) {
if (strcmp(argv[arg], "--failure_list") == 0) {
if (++arg == argc) UsageError();
vector<string> 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] == '-') {
fprintf(stderr, "Unknown option: %s\n", argv[arg]);
UsageError();
......@@ -238,8 +242,6 @@ int main(int argc, char *argv[]) {
}
ForkPipeRunner runner(program);
google::protobuf::ConformanceTestSuite suite;
suite.SetFailureList(failure_list);
std::string 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
......@@ -50,7 +50,7 @@ class AddPerson {
stdout.println("Unknown phone type. Using default.");
}
person.addPhone(phoneNumber);
person.addPhones(phoneNumber);
}
return person.build();
......@@ -80,7 +80,7 @@ class AddPerson {
}
// Add an address.
addressBook.addPerson(
addressBook.addPeople(
PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
System.out));
......
......@@ -9,14 +9,14 @@ import java.io.PrintStream;
class ListPeople {
// Iterates though all people in the AddressBook and prints info about them.
static void Print(AddressBook addressBook) {
for (Person person: addressBook.getPersonList()) {
for (Person person: addressBook.getPeopleList()) {
System.out.println("Person ID: " + person.getId());
System.out.println(" Name: " + person.getName());
if (person.hasEmail()) {
if (!person.getEmail().isEmpty()) {
System.out.println(" E-mail address: " + person.getEmail());
}
for (Person.PhoneNumber phoneNumber : person.getPhoneList()) {
for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {
switch (phoneNumber.getType()) {
case MOBILE:
System.out.print(" Mobile phone #: ");
......
......@@ -32,7 +32,7 @@ void PromptForAddress(tutorial::Person* person) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phone();
tutorial::Person::PhoneNumber* phone_number = person->add_phones();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
......@@ -77,7 +77,7 @@ int main(int argc, char* argv[]) {
}
// Add an address.
PromptForAddress(address_book.add_person());
PromptForAddress(address_book.add_people());
{
// Write the new address book back to disk.
......
......@@ -19,7 +19,7 @@ def PromptForAddress(person):
if number == "":
break
phone_number = person.phone.add()
phone_number = person.phones.add()
phone_number.number = number
type = raw_input("Is this a mobile, home, or work phone? ")
......@@ -50,7 +50,7 @@ except IOError:
print sys.argv[1] + ": File not found. Creating a new file."
# Add an address.
PromptForAddress(address_book.person.add())
PromptForAddress(address_book.people.add())
# Write the new address book back to disk.
f = open(sys.argv[1], "wb")
......
......@@ -8,17 +8,17 @@ using namespace std;
// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {
for (int i = 0; i < address_book.person_size(); i++) {
const tutorial::Person& person = address_book.person(i);
for (int i = 0; i < address_book.people_size(); i++) {
const tutorial::Person& person = address_book.people(i);
cout << "Person ID: " << person.id() << endl;
cout << " Name: " << person.name() << endl;
if (person.has_email()) {
if (person.email() != "") {
cout << " E-mail address: " << person.email() << endl;
}
for (int j = 0; j < person.phone_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phone(j);
for (int j = 0; j < person.phones_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phones(j);
switch (phone_number.type()) {
case tutorial::Person::MOBILE:
......
......@@ -7,13 +7,13 @@ import sys
# Iterates though all people in the AddressBook and prints info about them.
def ListPeople(address_book):
for person in address_book.person:
for person in address_book.people:
print "Person ID:", person.id
print " Name:", person.name
if person.HasField('email'):
if person.email != "":
print " E-mail address:", person.email
for phone_number in person.phone:
for phone_number in person.phones:
if phone_number.type == addressbook_pb2.Person.MOBILE:
print " Mobile phone #:",
elif phone_number.type == addressbook_pb2.Person.HOME:
......
......@@ -548,7 +548,7 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
#define CONVERT(upb, ruby) \
if (SYM2ID(type) == rb_intern( # ruby )) { \
return UPB_TYPE_ ## upb; \
return UPB_TYPE_ ## upb; \
}
CONVERT(FLOAT, float);
......@@ -589,6 +589,68 @@ VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
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:
* FieldDescriptor.type => type
......@@ -604,7 +666,7 @@ VALUE FieldDescriptor_type(VALUE _self) {
if (!upb_fielddef_typeisset(self->fielddef)) {
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) {
VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
DEFINE_SELF(FieldDescriptor, self, _self);
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;
}
......
......@@ -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
// function so it would not otherwise have been freed.
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
// code, back to Ruby.
return false;
......
......@@ -39,6 +39,9 @@
// Ruby integers) to MessageDef/EnumDef instances (as Ruby values).
VALUE upb_def_to_ruby_obj_map;
VALUE cError;
VALUE cParseError;
void add_def_obj(const void* def, VALUE value) {
rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
}
......@@ -96,6 +99,9 @@ void Init_protobuf_c() {
RepeatedField_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",
Google_Protobuf_deep_copy, 1);
......
......@@ -161,6 +161,9 @@ extern VALUE cOneofBuilderContext;
extern VALUE cEnumBuilderContext;
extern VALUE cBuilder;
extern VALUE cError;
extern VALUE cParseError;
// We forward-declare all of the Ruby method implementations here because we
// sometimes call the methods directly across .c files, rather than going
// through Ruby's method dispatching (e.g. during message parse). It's cleaner
......
This diff is collapsed.
This diff is collapsed.
......@@ -31,6 +31,15 @@
# require mixins before we hook them into the java & c code
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"
require 'json'
require 'google/protobuf_java'
......
......@@ -5,11 +5,22 @@ set -e
test_version() {
version=$1
bash --login -c \
"rvm install $version && rvm use $version && \
which ruby && \
gem install bundler && bundle && \
rake test"
if [ "$version" == "jruby" ] ; then
# No conformance tests yet -- JRuby is too broken to run them.
bash --login -c \
"rvm install $version && rvm use $version && \
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
......@@ -71,15 +71,24 @@ nobase_include_HEADERS = \
google/protobuf/stubs/atomicops_internals_tsan.h \
google/protobuf/stubs/atomicops_internals_x86_gcc.h \
google/protobuf/stubs/atomicops_internals_x86_msvc.h \
google/protobuf/stubs/callback.h \
google/protobuf/stubs/bytestream.h \
google/protobuf/stubs/casts.h \
google/protobuf/stubs/common.h \
google/protobuf/stubs/fastmem.h \
google/protobuf/stubs/hash.h \
google/protobuf/stubs/logging.h \
google/protobuf/stubs/macros.h \
google/protobuf/stubs/mutex.h \
google/protobuf/stubs/once.h \
google/protobuf/stubs/platform_macros.h \
google/protobuf/stubs/port.h \
google/protobuf/stubs/scoped_ptr.h \
google/protobuf/stubs/shared_ptr.h \
google/protobuf/stubs/singleton.h \
google/protobuf/stubs/status.h \
google/protobuf/stubs/stl_util.h \
google/protobuf/stubs/stringpiece.h \
google/protobuf/stubs/template_util.h \
google/protobuf/stubs/type_traits.h \
google/protobuf/any.pb.h \
......
......@@ -229,6 +229,32 @@ TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) {
typedef ParserTest ParseMessageTest;
TEST_F(ParseMessageTest, IgnoreBOM) {
char input[] = " message TestMessage {\n"
" required int32 foo = 1;\n"
"}\n";
// Set UTF-8 BOM.
input[0] = (char)0xEF;
input[1] = (char)0xBB;
input[2] = (char)0xBF;
ExpectParsesTo(input,
"message_type {"
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
"}");
}
TEST_F(ParseMessageTest, BOMError) {
char input[] = " message TestMessage {\n"
" required int32 foo = 1;\n"
"}\n";
input[0] = (char)0xEF;
ExpectHasErrors(input,
"0:1: Proto file starts with 0xEF but not UTF-8 BOM. "
"Only UTF-8 is accepted for proto file.\n"
"0:0: Expected top-level statement (e.g. \"message\").\n");
}
TEST_F(ParseMessageTest, SimpleMessage) {
ExpectParsesTo(
"message TestMessage {\n"
......
......@@ -13,7 +13,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
optional :optional_double, :double, 6
optional :optional_float, :float, 7
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_msg, :message, 11, "A.B.C.TestMessage"
repeated :repeated_int32, :int32, 21
......@@ -24,7 +24,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
repeated :repeated_double, :double, 26
repeated :repeated_float, :float, 27
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_msg, :message, 31, "A.B.C.TestMessage"
map :map_int32_string, :int32, :string, 61
......@@ -47,7 +47,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
optional :oneof_double, :double, 46
optional :oneof_float, :float, 47
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_msg, :message, 51, "A.B.C.TestMessage"
end
......
......@@ -47,7 +47,7 @@ namespace compiler {
namespace ruby {
// Forward decls.
std::string IntToString(uint32 value);
std::string IntToString(int32 value);
std::string StripDotProto(const std::string& proto_file);
std::string LabelForField(google::protobuf::FieldDescriptor* field);
std::string TypeName(google::protobuf::FieldDescriptor* field);
......@@ -64,7 +64,7 @@ void GenerateEnumAssignment(
const google::protobuf::EnumDescriptor* en,
google::protobuf::io::Printer* printer);
std::string IntToString(uint32 value) {
std::string IntToString(int32 value) {
std::ostringstream os;
os << value;
return os.str();
......@@ -85,17 +85,25 @@ std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
}
std::string TypeName(const google::protobuf::FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32: return "int32";
case FieldDescriptor::CPPTYPE_INT64: return "int64";
case FieldDescriptor::CPPTYPE_UINT32: return "uint32";
case FieldDescriptor::CPPTYPE_UINT64: return "uint64";
case FieldDescriptor::CPPTYPE_DOUBLE: return "double";
case FieldDescriptor::CPPTYPE_FLOAT: return "float";
case FieldDescriptor::CPPTYPE_BOOL: return "bool";
case FieldDescriptor::CPPTYPE_ENUM: return "enum";
case FieldDescriptor::CPPTYPE_STRING: return "string";
case FieldDescriptor::CPPTYPE_MESSAGE: return "message";
switch (field->type()) {
case FieldDescriptor::TYPE_INT32: return "int32";
case FieldDescriptor::TYPE_INT64: return "int64";
case FieldDescriptor::TYPE_UINT32: return "uint32";
case FieldDescriptor::TYPE_UINT64: return "uint64";
case FieldDescriptor::TYPE_SINT32: return "sint32";
case FieldDescriptor::TYPE_SINT64: return "sint64";
case FieldDescriptor::TYPE_FIXED32: return "fixed32";
case FieldDescriptor::TYPE_FIXED64: return "fixed64";
case FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
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 "";
}
}
......
......@@ -762,6 +762,15 @@ bool Tokenizer::NextWithComments(string* prev_trailing_comments,
next_leading_comments);
if (current_.type == TYPE_START) {
// Ignore unicode byte order mark(BOM) if it appears at the file
// beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted.
if (TryConsume((char)0xEF)) {
if (!TryConsume((char)0xBB) || !TryConsume((char)0xBF)) {
AddError("Proto file starts with 0xEF but not UTF-8 BOM. "
"Only UTF-8 is accepted for proto file.");
return false;
}
}
collector.DetachFromPrev();
} else {
// A comment appearing on the same line must be attached to the previous
......
This diff is collapsed.
This diff is collapsed.
// 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.
#ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_
#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
#include <google/protobuf/stubs/macros.h>
#include <google/protobuf/stubs/port.h>
// ===================================================================
// emulates google3/base/logging.h
namespace google {
namespace protobuf {
enum LogLevel {
LOGLEVEL_INFO, // Informational. This is never actually used by
// libprotobuf.
LOGLEVEL_WARNING, // Warns about issues that, although not technically a
// problem now, could cause problems in the future. For
// example, a // warning will be printed when parsing a
// message that is near the message size limit.
LOGLEVEL_ERROR, // An error occurred which should never happen during
// normal use.
LOGLEVEL_FATAL, // An error occurred from which the library cannot
// recover. This usually indicates a programming error
// in the code which calls the library, especially when
// compiled in debug mode.
#ifdef NDEBUG
LOGLEVEL_DFATAL = LOGLEVEL_ERROR
#else
LOGLEVEL_DFATAL = LOGLEVEL_FATAL
#endif
};
class StringPiece;
namespace util {
class Status;
}
namespace internal {
class LogFinisher;
class LIBPROTOBUF_EXPORT LogMessage {
public:
LogMessage(LogLevel level, const char* filename, int line);
~LogMessage();
LogMessage& operator<<(const std::string& value);
LogMessage& operator<<(const char* value);
LogMessage& operator<<(char value);
LogMessage& operator<<(int value);
LogMessage& operator<<(unsigned int value);
LogMessage& operator<<(long value);
LogMessage& operator<<(unsigned long value);
LogMessage& operator<<(long long value);
LogMessage& operator<<(unsigned long long value);
LogMessage& operator<<(double value);
LogMessage& operator<<(void* value);
LogMessage& operator<<(const StringPiece& value);
LogMessage& operator<<(const ::google::protobuf::util::Status& status);
private:
friend class LogFinisher;
void Finish();
LogLevel level_;
const char* filename_;
int line_;
std::string message_;
};
// Used to make the entire "LOG(BLAH) << etc." expression have a void return
// type and print a newline after each message.
class LIBPROTOBUF_EXPORT LogFinisher {
public:
void operator=(LogMessage& other);
};
template<typename T>
bool IsOk(T status) { return status.ok(); }
template<>
inline bool IsOk(bool status) { return status; }
} // namespace internal
// Undef everything in case we're being mixed with some other Google library
// which already defined them itself. Presumably all Google libraries will
// support the same syntax for these so it should not be a big deal if they
// end up using our definitions instead.
#undef GOOGLE_LOG
#undef GOOGLE_LOG_IF
#undef GOOGLE_CHECK
#undef GOOGLE_CHECK_OK
#undef GOOGLE_CHECK_EQ
#undef GOOGLE_CHECK_NE
#undef GOOGLE_CHECK_LT
#undef GOOGLE_CHECK_LE
#undef GOOGLE_CHECK_GT
#undef GOOGLE_CHECK_GE
#undef GOOGLE_CHECK_NOTNULL
#undef GOOGLE_DLOG
#undef GOOGLE_DCHECK
#undef GOOGLE_DCHECK_OK
#undef GOOGLE_DCHECK_EQ
#undef GOOGLE_DCHECK_NE
#undef GOOGLE_DCHECK_LT
#undef GOOGLE_DCHECK_LE
#undef GOOGLE_DCHECK_GT
#undef GOOGLE_DCHECK_GE
#define GOOGLE_LOG(LEVEL) \
::google::protobuf::internal::LogFinisher() = \
::google::protobuf::internal::LogMessage( \
::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__)
#define GOOGLE_LOG_IF(LEVEL, CONDITION) \
!(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL)
#define GOOGLE_CHECK(EXPRESSION) \
GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": "
#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A))
#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B))
#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B))
#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B))
#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B))
#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
namespace internal {
template<typename T>
T* CheckNotNull(const char* /* file */, int /* line */,
const char* name, T* val) {
if (val == NULL) {
GOOGLE_LOG(FATAL) << name;
}
return val;
}
} // namespace internal
#define GOOGLE_CHECK_NOTNULL(A) \
::google::protobuf::internal::CheckNotNull(\
__FILE__, __LINE__, "'" #A "' must not be NULL", (A))
#ifdef NDEBUG
#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION)
#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E))
#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B))
#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B))
#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B))
#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B))
#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B))
#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B))
#else // NDEBUG
#define GOOGLE_DLOG GOOGLE_LOG
#define GOOGLE_DCHECK GOOGLE_CHECK
#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK
#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ
#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE
#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT
#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE
#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT
#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE
#endif // !NDEBUG
typedef void LogHandler(LogLevel level, const char* filename, int line,
const std::string& message);
// The protobuf library sometimes writes warning and error messages to
// stderr. These messages are primarily useful for developers, but may
// also help end users figure out a problem. If you would prefer that
// these messages be sent somewhere other than stderr, call SetLogHandler()
// to set your own handler. This returns the old handler. Set the handler
// to NULL to ignore log messages (but see also LogSilencer, below).
//
// Obviously, SetLogHandler is not thread-safe. You should only call it
// at initialization time, and probably not from library code. If you
// simply want to suppress log messages temporarily (e.g. because you
// have some code that tends to trigger them frequently and you know
// the warnings are not important to you), use the LogSilencer class
// below.
LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func);
// Create a LogSilencer if you want to temporarily suppress all log
// messages. As long as any LogSilencer objects exist, non-fatal
// log messages will be discarded (the current LogHandler will *not*
// be called). Constructing a LogSilencer is thread-safe. You may
// accidentally suppress log messages occurring in another thread, but
// since messages are generally for debugging purposes only, this isn't
// a big deal. If you want to intercept log messages, use SetLogHandler().
class LIBPROTOBUF_EXPORT LogSilencer {
public:
LogSilencer();
~LogSilencer();
};
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_
// 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.
#ifndef GOOGLE_PROTOBUF_MACROS_H__
#define GOOGLE_PROTOBUF_MACROS_H__
#include <google/protobuf/stubs/port.h>
namespace google {
namespace protobuf {
#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// ===================================================================
// from google3/base/basictypes.h
// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example.
//
// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error
//
// "warning: division by zero in ..."
//
// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
//
// The following comments are on the implementation details, and can
// be ignored by the users.
//
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
// the array) and sizeof(*(arr)) (the # of bytes in one array
// element). If the former is divisible by the latter, perhaps arr is
// indeed an array, in which case the division result is the # of
// elements in the array. Otherwise, arr cannot possibly be an array,
// and we generate a compiler error to prevent the code from
// compiling.
//
// Since the size of bool is implementation-defined, we need to cast
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
// result has type size_t.
//
// This macro is not perfect as it wrongfully accepts certain
// pointers, namely where the pointer size is divisible by the pointee
// size. Since all our code has to go through a 32-bit compiler,
// where a pointer is 4 bytes, this means all pointers to a type whose
// size is 3 or greater than 4 will be (righteously) rejected.
//
// Kudos to Jorg Brown for this simple and elegant implementation.
#undef GOOGLE_ARRAYSIZE
#define GOOGLE_ARRAYSIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
// The COMPILE_ASSERT macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
//
// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
// content_type_names_incorrect_size);
//
// or to make sure a struct is smaller than a certain size:
//
// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
//
// The second argument to the macro is the name of the variable. If
// the expression is false, most compilers will issue a warning/error
// containing the name of the variable.
namespace internal {
template <bool>
struct CompileAssert {
};
} // namespace internal
#undef GOOGLE_COMPILE_ASSERT
#if __cplusplus >= 201103L
#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
#else
#define GOOGLE_COMPILE_ASSERT(expr, msg) \
::google::protobuf::internal::CompileAssert<(bool(expr))> \
msg[bool(expr) ? 1 : -1]; \
(void)msg
// Implementation details of COMPILE_ASSERT:
//
// - COMPILE_ASSERT works by defining an array type that has -1
// elements (and thus is invalid) when the expression is false.
//
// - The simpler definition
//
// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
//
// does not work, as gcc supports variable-length arrays whose sizes
// are determined at run-time (this is gcc's extension and not part
// of the C++ standard). As a result, gcc fails to reject the
// following code with the simple definition:
//
// int foo;
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
// // not a compile-time constant.
//
// - By using the type CompileAssert<(bool(expr))>, we ensures that
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
//
// CompileAssert<bool(expr)>
//
// instead, these compilers will refuse to compile
//
// COMPILE_ASSERT(5 > 0, some_message);
//
// (They seem to think the ">" in "5 > 0" marks the end of the
// template argument list.)
//
// - The array size is (bool(expr) ? 1 : -1), instead of simply
//
// ((expr) ? 1 : -1).
//
// This is to avoid running into a bug in MS VC 7.1, which
// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
#endif // __cplusplus >= 201103L
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_MACROS_H__
......@@ -34,6 +34,7 @@
#include <math.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/mathlimits.h>
namespace google {
......
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// 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.
#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_
#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
#include <google/protobuf/stubs/macros.h>
// ===================================================================
// emulates google3/base/mutex.h
namespace google {
namespace protobuf {
namespace internal {
// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T
// may hold a mutex at a given time. If T attempts to Lock() the same Mutex
// while holding it, T will deadlock.
class LIBPROTOBUF_EXPORT Mutex {
public:
// Create a Mutex that is not held by anybody.
Mutex();
// Destructor
~Mutex();
// Block if necessary until this Mutex is free, then acquire it exclusively.
void Lock();
// Release this Mutex. Caller must hold it exclusively.
void Unlock();
// Crash if this Mutex is not held exclusively by this thread.
// May fail to crash when it should; will never crash when it should not.
void AssertHeld();
private:
struct Internal;
Internal* mInternal;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
};
// Undefine the macros to workaround the conflicts with Google internal
// MutexLock implementation.
// TODO(liujisi): Remove the undef once internal macros are removed.
#undef MutexLock
#undef ReaderMutexLock
#undef WriterMutexLock
#undef MutexLockMaybe
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
class LIBPROTOBUF_EXPORT MutexLock {
public:
explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); }
~MutexLock() { this->mu_->Unlock(); }
private:
Mutex *const mu_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
};
// TODO(kenton): Implement these? Hard to implement portably.
typedef MutexLock ReaderMutexLock;
typedef MutexLock WriterMutexLock;
// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
class LIBPROTOBUF_EXPORT MutexLockMaybe {
public:
explicit MutexLockMaybe(Mutex *mu) :
mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } }
~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } }
private:
Mutex *const mu_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
};
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
template<typename T>
class ThreadLocalStorage {
public:
ThreadLocalStorage() {
pthread_key_create(&key_, &ThreadLocalStorage::Delete);
}
~ThreadLocalStorage() {
pthread_key_delete(key_);
}
T* Get() {
T* result = static_cast<T*>(pthread_getspecific(key_));
if (result == NULL) {
result = new T();
pthread_setspecific(key_, result);
}
return result;
}
private:
static void Delete(void* value) {
delete static_cast<T*>(value);
}
pthread_key_t key_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
};
#endif
} // namespace internal
// We made these internal so that they would show up as such in the docs,
// but we don't want to stick "internal::" in front of them everywhere.
using internal::Mutex;
using internal::MutexLock;
using internal::ReaderMutexLock;
using internal::WriterMutexLock;
using internal::MutexLockMaybe;
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
......@@ -79,6 +79,7 @@
#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
#include <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
namespace google {
......
This diff is collapsed.
This diff is collapsed.
......@@ -59,9 +59,9 @@
#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
#include <cstddef> // for NULL
#include <utility> // For pair
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/template_util.h> // For true_type and false_type
namespace google {
......
This diff is collapsed.
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