diff options
Diffstat (limited to 'src')
33 files changed, 615 insertions, 633 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0dc18916..3c2d244f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,17 +4,25 @@ if HAVE_ZLIB GZCHECKPROGRAMS = zcgzip zcgunzip GZHEADERS = google/protobuf/io/gzip_stream.h GZTESTS = google/protobuf/io/gzip_stream_unittest.sh +ZLIB_DEF = -DHAVE_ZLIB=1 else GZCHECKPROGRAMS = GZHEADERS = GZTESTS = +ZLIB_DEF = +endif + +if HAVE_PTHREAD +PTHREAD_DEF = -DHAVE_PTHREAD=1 +else +PTHREAD_DEF = endif if GCC # These are good warnings to turn on by default -NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare +NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare else -NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) +NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) endif AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) @@ -41,24 +49,12 @@ nobase_dist_proto_DATA = google/protobuf/descriptor.proto \ clean-local: rm -f *.loT -public_config = google/protobuf/stubs/pbconfig.h - -CLEANFILES = $(protoc_outputs) $(public_config) unittest_proto_middleman \ +CLEANFILES = $(protoc_outputs) unittest_proto_middleman \ testzip.jar testzip.list testzip.proto testzip.zip MAINTAINERCLEANFILES = \ Makefile.in -# Generate and distribute a minimum config.h file to make hash_map work. -# The autoheader config has too much info, which might conflict with other -# macros applications might include. Thus, we create a stubs/pbconfig.h, that -# only #defines what we really need, and prefix it with GOOGLE_PROTOBUF_ to -# avoid conflicts. -$(public_config): $(top_builddir)/config.h $(top_srcdir)/config.h.include - echo "// Note: Google Protobuf internal only. Do NOT include." > $@ - cat $(top_builddir)/config.h | grep -f $(top_srcdir)/config.h.include | \ - sed 's,#define , #define GOOGLE_PROTOBUF_,' >> $@ - nobase_include_HEADERS = \ google/protobuf/stubs/atomic_sequence_num.h \ google/protobuf/stubs/atomicops.h \ @@ -80,6 +76,7 @@ nobase_include_HEADERS = \ google/protobuf/stubs/fastmem.h \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/once.h \ + google/protobuf/stubs/pbconfig.h \ google/protobuf/stubs/platform_macros.h \ google/protobuf/stubs/shared_ptr.h \ google/protobuf/stubs/singleton.h \ @@ -147,14 +144,11 @@ nobase_include_HEADERS = \ google/protobuf/compiler/java/java_names.h \ google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/objectivec/objectivec_generator.h \ - google/protobuf/compiler/objectivec/objectivec_helpers.h \ + google/protobuf/compiler/objectivec/objectivec_helpers.h \ google/protobuf/compiler/python/python_generator.h \ google/protobuf/compiler/ruby/ruby_generator.h \ google/protobuf/compiler/csharp/csharp_generator.h -nobase_nodist_include_HEADERS = \ - $(public_config) - lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) @@ -180,7 +174,6 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/io/coded_stream_inl.h \ google/protobuf/io/zero_copy_stream.cc \ google/protobuf/io/zero_copy_stream_impl_lite.cc -nodist_libprotobuf_lite_la_SOURCES = $(public_config) libprotobuf_la_LIBADD = $(PTHREAD_LIBS) libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined @@ -408,6 +401,7 @@ protoc_inputs = \ google/protobuf/unittest_drop_unknown_fields.proto \ google/protobuf/unittest_embed_optimize_for.proto \ google/protobuf/unittest_empty.proto \ + google/protobuf/unittest_enormous_descriptor.proto \ google/protobuf/unittest_import_lite.proto \ google/protobuf/unittest_import.proto \ google/protobuf/unittest_import_public_lite.proto \ @@ -449,8 +443,7 @@ EXTRA_DIST = \ google/protobuf/compiler/ruby/ruby_generated_code.proto \ google/protobuf/compiler/ruby/ruby_generated_code.rb \ google/protobuf/compiler/package_info.h \ - google/protobuf/compiler/zip_output_unittest.sh \ - google/protobuf/unittest_enormous_descriptor.proto + google/protobuf/compiler/zip_output_unittest.sh protoc_lite_outputs = \ google/protobuf/map_lite_unittest.pb.cc \ @@ -482,6 +475,8 @@ protoc_outputs = \ google/protobuf/unittest_embed_optimize_for.pb.h \ google/protobuf/unittest_empty.pb.cc \ google/protobuf/unittest_empty.pb.h \ + google/protobuf/unittest_enormous_descriptor.pb.cc \ + google/protobuf/unittest_enormous_descriptor.pb.h \ google/protobuf/unittest_import.pb.cc \ google/protobuf/unittest_import.pb.h \ google/protobuf/unittest_import_public.pb.cc \ @@ -513,7 +508,7 @@ protoc_outputs = \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h -BUILT_SOURCES = $(public_config) $(protoc_outputs) +BUILT_SOURCES = $(protoc_outputs) if USE_EXTERNAL_PROTOC diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 96009645..ed1c5ef2 100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -43,7 +43,7 @@ Arena::ThreadCache& Arena::thread_cache() { static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL }; return thread_cache_; } -#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) Arena::ThreadCache& Arena::thread_cache() { static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ = new internal::ThreadLocalStorage<ThreadCache>(); diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 6c3f606e..51149bae 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -39,6 +39,7 @@ #include <google/protobuf/stubs/atomic_sequence_num.h> #include <google/protobuf/stubs/atomicops.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/platform_macros.h> #include <google/protobuf/stubs/type_traits.h> namespace google { @@ -528,7 +529,7 @@ class LIBPROTOBUF_EXPORT Arena { // Thread local variables cannot be exposed through DLL interface but we can // wrap them in static functions. static ThreadCache& thread_cache(); -#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +#elif defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread // local storage class we implemented. // iOS also does not support the GOOGLE_THREAD_LOCAL keyword. diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index b997a51a..1f0a8205 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -434,20 +434,52 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { string file_data; file_proto.SerializeToString(&file_data); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); - - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print("\n \"$data$\"", - "data", - EscapeTrigraphs( - CEscape(file_data.substr(i, kBytesPerLine)))); + // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 + // bytes in length". Declare a static array of characters rather than use a + // string literal. + if (file_data.size() > 65535) { + printer->Print( + "static const char descriptor[] = {\n"); + printer->Indent(); + + // Only write 25 bytes per line. + static const int kBytesPerLine = 25; + for (int i = 0; i < file_data.size();) { + for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { + printer->Print( + "$char$, ", + "char", SimpleItoa(file_data[i])); + } + printer->Print( + "\n"); + } + + printer->Outdent(); + printer->Print( + "};\n"); + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n", + "size", SimpleItoa(file_data.size())); + + } else { + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", + "data", + EscapeTrigraphs( + CEscape(file_data.substr(i, kBytesPerLine)))); + } + printer->Print( + ", $size$);\n", + "size", SimpleItoa(file_data.size())); + } - printer->Print( - ", $size$);\n", - "size", SimpleItoa(file_data.size())); // Call MessageFactory::InternalRegisterGeneratedFile(). printer->Print( diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 212fe2e1..af85919a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -3510,7 +3510,7 @@ GenerateByteSize(io::Printer* printer) { } else { if (HasFieldPresence(descriptor_->file())) { printer->Print( - "if (_has_bits_[$index$ / 32] & $mask$) {\n", + "if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index", SimpleItoa(i), "mask", SimpleItoa(mask)); printer->Indent(); diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index b11fb21a..bd1c0fde 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -55,6 +55,7 @@ #include <google/protobuf/unittest.pb.h> #include <google/protobuf/unittest_optimize_for.pb.h> #include <google/protobuf/unittest_embed_optimize_for.pb.h> +#include <google/protobuf/unittest_enormous_descriptor.pb.h> #include <google/protobuf/unittest_no_generic_services.pb.h> #include <google/protobuf/test_util.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> @@ -130,6 +131,17 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) { generated_decsriptor_proto.DebugString()); } +// Test that generated code has proper descriptors: +// Touch a descriptor generated from an enormous message to validate special +// handling for descriptors exceeding the C++ standard's recommended minimum +// limit for string literal size +TEST(GeneratedDescriptorTest, EnormousDescriptor) { + const Descriptor* generated_descriptor = + TestEnormousDescriptor::descriptor(); + + EXPECT_TRUE(generated_descriptor != NULL); +} + #endif // !PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index d6609692..30a13ddb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -55,8 +55,6 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (descriptor->file() != descriptor->enum_type()->file())) { (*variables)["property_type"] = "enum " + type; } - // TODO(thomasvl): Make inclusion of descriptor compile time and output - // both of these. Note: Extensions currently have to have the EnumDescription. (*variables)["enum_verifier"] = type + "_IsValidValue"; (*variables)["enum_desc_func"] = type + "_EnumDescriptor"; @@ -74,11 +72,9 @@ EnumFieldGenerator::~EnumFieldGenerator() {} void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. printer->Print( variables_, - " .typeSpecific.enumDescFunc = $enum_desc_func$,\n"); + " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n"); } void EnumFieldGenerator::GenerateCFunctionDeclarations( @@ -103,7 +99,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" - " return GPBGetInt32IvarWithField(message, field);\n" + " return GPBGetMessageInt32Field(message, field);\n" "}\n" "\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" @@ -137,11 +133,9 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. printer->Print( variables_, - " .typeSpecific.enumDescFunc = $enum_desc_func$,\n"); + " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n"); } } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index 76137c80..4e348393 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -46,24 +46,6 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, : method_name_(ExtensionMethodName(descriptor)), root_class_and_method_name_(root_class_name + "_" + method_name_), descriptor_(descriptor) { - // Extensions can be filtered via the method they are accessed off the - // file's Root with. - if (FilterClass(root_class_and_method_name_)) { - filter_reason_ = - string("Extension |") + root_class_and_method_name_ + "| was not whitelisted."; - } else { - // Extensions that add a Message field also require that field be allowed - // by the filter, or they aren't usable. - ObjectiveCType objc_type = GetObjectiveCType(descriptor_); - if (objc_type == OBJECTIVECTYPE_MESSAGE) { - const string message_class_name(ClassName(descriptor_->message_type())); - if (FilterClass(message_class_name)) { - filter_reason_ = string("Extension |") + root_class_and_method_name_ + - "| needs message |" + message_class_name + - "|, which was not whitelisted."; - } - } - } if (descriptor->is_map()) { // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some // error cases, so it seems to be ok to use as a back door for errors. @@ -77,10 +59,6 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, ExtensionGenerator::~ExtensionGenerator() {} void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { - if (IsFiltered()) { - printer->Print("// $filter_reason$\n\n", "filter_reason", filter_reason_); - return; - } map<string, string> vars; vars["method_name"] = method_name_; SourceLocation location; @@ -91,15 +69,11 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { } printer->Print(vars, "$comments$" - "+ (GPBExtensionField*)$method_name$;\n"); + "+ (GPBExtensionDescriptor *)$method_name$;\n"); } void ExtensionGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer, bool* out_generated, bool root) { - if (IsFiltered()) { - return; - } - *out_generated = true; + io::Printer* printer) { map<string, string> vars; vars["root_class_and_method_name"] = root_class_and_method_name_; vars["extended_type"] = ClassName(descriptor_->containing_type()); @@ -122,14 +96,14 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( vars["type"] = "NULL"; } - vars["default_name"] = GPBValueFieldName(descriptor_); + vars["default_name"] = GPBGenericValueFieldName(descriptor_); if (descriptor_->is_repeated()) { vars["default"] = "nil"; } else { vars["default"] = DefaultValue(descriptor_); } string type = GetCapitalizedType(descriptor_); - vars["extension_type"] = string("GPBType") + type; + vars["extension_type"] = string("GPBDataType") + type; if (objc_type == OBJECTIVECTYPE_ENUM) { vars["enum_desc_func_name"] = @@ -141,7 +115,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( printer->Print(vars, "{\n" " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" - " .type = $extension_type$,\n" + " .dataType = $extension_type$,\n" " .extendedClass = GPBStringifySymbol($extended_type$),\n" " .fieldNumber = $number$,\n" " .defaultValue.$default_name$ = $default$,\n" @@ -152,9 +126,6 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( } void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { - if (IsFiltered()) { - return; - } printer->Print( "[registry addExtension:$root_class_and_method_name$];\n", "root_class_and_method_name", root_class_and_method_name_); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h index 553f0887..e361e639 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -52,16 +52,12 @@ class ExtensionGenerator { ~ExtensionGenerator(); void GenerateMembersHeader(io::Printer* printer); - void GenerateStaticVariablesInitialization(io::Printer* printer, - bool* out_generated, bool root); + void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateRegistrationSource(io::Printer* printer); - bool IsFiltered() const { return filter_reason_.length() > 0; } - private: string method_name_; string root_class_and_method_name_; - string filter_reason_; const FieldDescriptor* descriptor_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index c5f05653..0f96a4e6 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -87,18 +87,16 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, field_flags.push_back("GPBFieldHasDefaultValue"); if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom"); if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. field_flags.push_back("GPBFieldHasEnumDescriptor"); } (*variables)["fieldflags"] = BuildFlagsString(field_flags); (*variables)["default"] = DefaultValue(descriptor); - (*variables)["default_name"] = GPBValueFieldName(descriptor); + (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); - (*variables)["typeSpecific_name"] = "className"; - (*variables)["typeSpecific_value"] = "NULL"; + (*variables)["dataTypeSpecific_name"] = "className"; + (*variables)["dataTypeSpecific_value"] = "NULL"; string field_options = descriptor->options().SerializeAsString(); // Must convert to a standard byte order for packing length into @@ -117,45 +115,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["storage_attribute"] = ""; } -// A field generator that writes nothing. -class EmptyFieldGenerator : public FieldGenerator { - public: - EmptyFieldGenerator(const FieldDescriptor* descriptor, const string& reason) - : FieldGenerator(descriptor), reason_(reason) {} - virtual ~EmptyFieldGenerator() {} - - virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const {} - virtual void GeneratePropertyDeclaration(io::Printer* printer) const { - string name = FieldName(descriptor_); - string type; - switch (GetObjectiveCType(descriptor_)) { - case OBJECTIVECTYPE_MESSAGE: - type = ClassName(descriptor_->message_type()) + " *"; - break; - - case OBJECTIVECTYPE_ENUM: - type = EnumName(descriptor_->enum_type()) + " "; - break; - - default: - type = string(descriptor_->type_name()) + " "; - break; - } - printer->Print("// Field |$type$$name$| $reason$\n\n", "type", type, "name", - name, "reason", reason_); - } - - virtual void GenerateFieldNumberConstant(io::Printer* printer) const {} - virtual void GeneratePropertyImplementation(io::Printer* printer) const {} - virtual void GenerateFieldDescription(io::Printer* printer) const {} - - virtual bool WantsHasProperty(void) const { return false; } - - private: - string reason_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EmptyFieldGenerator); -}; - } // namespace FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { @@ -163,12 +122,7 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { if (field->is_repeated()) { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { - string type = ClassName(field->message_type()); - if (FilterClass(type)) { - string reason = - "Filtered by |" + type + "| not being whitelisted."; - result = new EmptyFieldGenerator(field, reason); - } else if (field->is_map()) { + if (field->is_map()) { result = new MapFieldGenerator(field); } else { result = new RepeatedMessageFieldGenerator(field); @@ -185,14 +139,7 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { } else { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { - string type = ClassName(field->message_type()); - if (FilterClass(type)) { - string reason = - "Filtered by |" + type + "| not being whitelisted."; - result = new EmptyFieldGenerator(field, reason); - } else { - result = new MessageFieldGenerator(field); - } + result = new MessageFieldGenerator(field); break; } case OBJECTIVECTYPE_ENUM: @@ -249,11 +196,17 @@ void FieldGenerator::GenerateFieldDescription( " .number = $field_number_name$,\n" " .hasIndex = $has_index$,\n" " .flags = $fieldflags$,\n" - " .type = GPBType$field_type$,\n" - " .offset = offsetof($classname$_Storage, $name$),\n" + " .dataType = GPBDataType$field_type$,\n" + " .offset = offsetof($classname$__storage_, $name$),\n" " .defaultValue.$default_name$ = $default$,\n"); - // " .typeSpecific.value* = [something]," + // TODO(thomasvl): It might be useful to add a CPP wrapper to support + // compiling away the EnumDescriptors. To do that, we'd need a #if here + // to control setting the descriptor vs. the validator, and above in + // SetCommonFieldVariables() we'd want to wrap how we add + // GPBFieldHasDefaultValue to the flags. + + // " .dataTypeSpecific.value* = [something]," GenerateFieldDescriptionTypeSpecific(printer); const string& field_options(variables_.find("fieldoptions")->second); @@ -280,7 +233,7 @@ void FieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { printer->Print( variables_, - " .typeSpecific.$typeSpecific_name$ = $typeSpecific_value$,\n"); + " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"); } void FieldGenerator::SetOneofIndexBase(int index_base) { @@ -410,22 +363,24 @@ void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( void RepeatedFieldGenerator::GeneratePropertyImplementation( io::Printer* printer) const { - printer->Print(variables_, "@dynamic $name$;\n"); + printer->Print(variables_, "@dynamic $name$, $name$_Count;\n"); } void RepeatedFieldGenerator::GeneratePropertyDeclaration( io::Printer* printer) const { - // Repeated fields don't need the has* properties, but this has the same - // logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for dealing - // with needing Objective C's rules around storage name conventions (init*, - // new*, etc.) + // Repeated fields don't need the has* properties, but they do expose a + // *Count (to check without autocreation). So for the field property we need + // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for + // dealing with needing Objective C's rules around storage name conventions + // (init*, new*, etc.) printer->Print( variables_, "$comments$" "$array_comment$" - "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n"); + "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n" + "@property(nonatomic, readonly) NSUInteger $name$_Count;\n"); if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index d04eee85..1955c053 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -54,35 +54,24 @@ namespace objectivec { FileGenerator::FileGenerator(const FileDescriptor *file) : file_(file), root_class_name_(FileClassName(file)), - is_filtered_(true), - all_extensions_filtered_(true), is_public_dep_(false) { - // Validate the objc prefix, do this even if the file's contents are filtered - // to catch a bad prefix as soon as it is found. + // Validate the objc prefix. ValidateObjCClassPrefix(file_); for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); - // The enums are exposed via C functions, so they will dead strip if - // not used. - is_filtered_ &= false; enum_generators_.push_back(generator); } for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator *generator = new MessageGenerator(root_class_name_, file_->message_type(i)); - is_filtered_ &= generator->IsFiltered(); - is_filtered_ &= generator->IsSubContentFiltered(); message_generators_.push_back(generator); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator *generator = new ExtensionGenerator(root_class_name_, file_->extension(i)); - is_filtered_ &= generator->IsFiltered(); - all_extensions_filtered_ &= generator->IsFiltered(); extension_generators_.push_back(generator); } - // If there is nothing in the file we filter it. } FileGenerator::~FileGenerator() { @@ -116,8 +105,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "protoc_gen_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); + const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); for (vector<FileGenerator *>::const_iterator iter = dependency_generators.begin(); iter != dependency_generators.end(); ++iter) { @@ -133,19 +121,17 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { printer->Print("CF_EXTERN_C_BEGIN\n\n"); - if (!IsFiltered()) { - set<string> fwd_decls; - for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->DetermineForwardDeclarations(&fwd_decls); - } - for (set<string>::const_iterator i(fwd_decls.begin()); - i != fwd_decls.end(); ++i) { - printer->Print("$value$;\n", "value", *i); - } - if (fwd_decls.begin() != fwd_decls.end()) { - printer->Print("\n"); - } + set<string> fwd_decls; + for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->DetermineForwardDeclarations(&fwd_decls); + } + for (set<string>::const_iterator i(fwd_decls.begin()); + i != fwd_decls.end(); ++i) { + printer->Print("$value$;\n", "value", *i); + } + if (fwd_decls.begin() != fwd_decls.end()) { + printer->Print("\n"); } // need to write out all enums first @@ -160,36 +146,27 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { } // For extensions to chain together, the Root gets created even if there - // are no extensions. So if the entire file isn't filtered away, output it. - if (!IsFiltered()) { - printer->Print( - "\n" - "#pragma mark - $root_class_name$\n" - "\n" - "@interface $root_class_name$ : GPBRootObject\n" - "\n" - "// The base class provides:\n" - "// + (GPBExtensionRegistry *)extensionRegistry;\n" - "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" - "// this file and all files that it depends on.\n" - "\n" - "@end\n" - "\n", - "root_class_name", root_class_name_); - } + // are no extensions. + printer->Print( + "\n" + "#pragma mark - $root_class_name$\n" + "\n" + "@interface $root_class_name$ : GPBRootObject\n" + "\n" + "// The base class provides:\n" + "// + (GPBExtensionRegistry *)extensionRegistry;\n" + "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" + "// this file and all files that it depends on.\n" + "\n" + "@end\n" + "\n", + "root_class_name", root_class_name_); if (extension_generators_.size() > 0) { - // The dynamic methods block is only needed if there are extensions. If - // they are all filtered, output the @interface as a comment so there is - // something left in the header for anyone that looks. - const char *root_line_prefix = ""; - if (AreAllExtensionsFiltered()) { - root_line_prefix = "// "; - } + // The dynamic methods block is only needed if there are extensions. printer->Print( - "$root_line_prefix$@interface $root_class_name$ (DynamicMethods)\n", - "root_class_name", root_class_name_, - "root_line_prefix", root_line_prefix); + "@interface $root_class_name$ (DynamicMethods)\n", + "root_class_name", root_class_name_); for (vector<ExtensionGenerator *>::iterator iter = extension_generators_.begin(); @@ -197,8 +174,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { (*iter)->GenerateMembersHeader(printer); } - printer->Print("$root_line_prefix$@end\n\n", - "root_line_prefix", root_line_prefix); + printer->Print("@end\n\n"); } // extension_generators_.size() > 0 for (vector<MessageGenerator *>::iterator iter = message_generators_.begin(); @@ -239,136 +215,119 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "// @@protoc_insertion_point(imports)\n" "\n"); - if (IsFiltered()) { - printer->Print( - "// File empty because all messages, extensions and enum have been filtered.\n" - "\n" - "\n" - "// Dummy symbol that will be stripped but will avoid linker warnings about\n" - "// no symbols in the .o form compiling this file.\n" - "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n" - "\n" - "// @@protoc_insertion_point(global_scope)\n", - "root_class_name", root_class_name_); - return; - } - printer->Print( "#pragma mark - $root_class_name$\n" "\n" "@implementation $root_class_name$\n\n", "root_class_name", root_class_name_); - bool generated_extensions = false; - if (file_->extension_count() + file_->message_type_count() + - file_->dependency_count() > - 0) { - ostringstream extensions_stringstream; - - if (file_->extension_count() + file_->message_type_count() > 0) { - io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); - io::Printer extensions_printer(&extensions_outputstream, '$'); - extensions_printer.Print( - "static GPBExtensionDescription descriptions[] = {\n"); - extensions_printer.Indent(); - for (vector<ExtensionGenerator *>::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization( - &extensions_printer, &generated_extensions, true); - } - for (vector<MessageGenerator *>::iterator iter = - message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(&extensions_printer, - &generated_extensions); - } - extensions_printer.Outdent(); - extensions_printer.Print("};\n"); - if (generated_extensions) { - extensions_printer.Print( - "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" - " GPBExtensionField *extension = [[GPBExtensionField alloc] initWithDescription:&descriptions[i]];\n" - " [registry addExtension:extension];\n" - " [self globallyRegisterExtension:extension];\n" - " [extension release];\n" - "}\n"); - } else { - extensions_printer.Print("#pragma unused (descriptions)\n"); - } - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); - if (dependency_generators.size()) { - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - if (!(*iter)->IsFiltered()) { - extensions_printer.Print( - "[registry addExtensions:[$dependency$ extensionRegistry]];\n", - "dependency", (*iter)->RootClassName()); - generated_extensions = true; - } - } - } else if (!generated_extensions) { - extensions_printer.Print("#pragma unused (registry)\n"); - } + // Generate the extension initialization structures for the top level and + // any nested messages. + ostringstream extensions_stringstream; + if (file_->extension_count() + file_->message_type_count() > 0) { + io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); + io::Printer extensions_printer(&extensions_outputstream, '$'); + for (vector<ExtensionGenerator *>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); + } + for (vector<MessageGenerator *>::iterator iter = + message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); } + extensions_stringstream.flush(); + } - if (generated_extensions) { + // If there were any extensions or this file has any dependencies, output + // a registry to override to create the file specific registry. + const string& extensions_str = extensions_stringstream.str(); + if (extensions_str.length() > 0 || file_->dependency_count() > 0) { + printer->Print( + "+ (GPBExtensionRegistry*)extensionRegistry {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety and initialization of registry.\n" + " static GPBExtensionRegistry* registry = nil;\n" + " if (!registry) {\n" + " GPBDebugCheckRuntimeVersion();\n" + " registry = [[GPBExtensionRegistry alloc] init];\n"); + + printer->Indent(); + printer->Indent(); + + if (extensions_str.length() > 0) { printer->Print( - "+ (GPBExtensionRegistry*)extensionRegistry {\n" - " // This is called by +initialize so there is no need to worry\n" - " // about thread safety and initialization of registry.\n" - " static GPBExtensionRegistry* registry = nil;\n" - " if (!registry) {\n" - " registry = [[GPBExtensionRegistry alloc] init];\n"); - - printer->Indent(); + "static GPBExtensionDescription descriptions[] = {\n"); printer->Indent(); - - extensions_stringstream.flush(); - printer->Print(extensions_stringstream.str().c_str()); - printer->Outdent(); + printer->Print(extensions_str.c_str()); printer->Outdent(); + printer->Print( + "};\n" + "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" + " GPBExtensionDescriptor *extension =\n" + " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n" + " [registry addExtension:extension];\n" + " [self globallyRegisterExtension:extension];\n" + " [extension release];\n" + "}\n"); + } + const vector<FileGenerator *> &dependency_generators = + DependencyGenerators(); + for (vector<FileGenerator *>::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { printer->Print( - " }\n" - " return registry;\n" - "}\n" - "\n"); + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", (*iter)->RootClassName()); } + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " return registry;\n" + "}\n" + "\n"); } printer->Print("@end\n\n"); - - string syntax; - switch (file_->syntax()) { - case FileDescriptor::SYNTAX_UNKNOWN: - syntax = "GPBFileSyntaxUnknown"; - break; - case FileDescriptor::SYNTAX_PROTO2: - syntax = "GPBFileSyntaxProto2"; - break; - case FileDescriptor::SYNTAX_PROTO3: - syntax = "GPBFileSyntaxProto3"; - break; + // File descriptor only needed if there are messages to use it. + if (message_generators_.size() > 0) { + string syntax; + switch (file_->syntax()) { + case FileDescriptor::SYNTAX_UNKNOWN: + syntax = "GPBFileSyntaxUnknown"; + break; + case FileDescriptor::SYNTAX_PROTO2: + syntax = "GPBFileSyntaxProto2"; + break; + case FileDescriptor::SYNTAX_PROTO3: + syntax = "GPBFileSyntaxProto3"; + break; + } + printer->Print( + "#pragma mark - $root_class_name$_FileDescriptor\n" + "\n" + "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety of the singleton.\n" + " static GPBFileDescriptor *descriptor = NULL;\n" + " if (!descriptor) {\n" + " GPBDebugCheckRuntimeVersion();\n" + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n" + " }\n" + " return descriptor;\n" + "}\n" + "\n", + "root_class_name", root_class_name_, + "package", file_->package(), + "syntax", syntax); } - printer->Print( - "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" - " // This is called by +initialize so there is no need to worry\n" - " // about thread safety of the singleton.\n" - " static GPBFileDescriptor *descriptor = NULL;\n" - " if (!descriptor) {\n" - " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" - " syntax:$syntax$];\n" - " }\n" - " return descriptor;\n" - "}\n" - "\n", - "root_class_name", root_class_name_, - "package", file_->package(), - "syntax", syntax); for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); iter != enum_generators_.end(); ++iter) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 95d17bfd..1bb4f0ea 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -64,8 +64,6 @@ class FileGenerator { const string& RootClassName() const { return root_class_name_; } const string Path() const; - bool IsFiltered() const { return is_filtered_; } - bool AreAllExtensionsFiltered() const { return all_extensions_filtered_; } bool IsPublicDependency() const { return is_public_dep_; } protected: @@ -84,8 +82,6 @@ class FileGenerator { vector<EnumGenerator*> enum_generators_; vector<MessageGenerator*> message_generators_; vector<ExtensionGenerator*> extension_generators_; - bool is_filtered_; - bool all_extensions_filtered_; bool is_public_dep_; const vector<FileGenerator*>& DependencyGenerators(); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 17776715..85e438f4 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -58,10 +58,6 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, return false; } - if (!InitializeClassWhitelist(error)) { - return false; - } - FileGenerator file_generator(file); string filepath = FilePath(file); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 6d6e5959..9b645f09 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -50,8 +50,6 @@ namespace objectivec { namespace { -hash_set<string> gClassWhitelist; - // islower()/isupper()/tolower()/toupper() change based on locale. // // src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the @@ -580,7 +578,7 @@ string GetCapitalizedType(const FieldDescriptor* field) { case FieldDescriptor::TYPE_STRING: return "String"; case FieldDescriptor::TYPE_BYTES: - return "Data"; + return "Bytes"; case FieldDescriptor::TYPE_ENUM: return "Enum"; case FieldDescriptor::TYPE_GROUP: @@ -684,8 +682,9 @@ static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) { } } -string GPBValueFieldName(const FieldDescriptor* field) { - // Returns the field within the GPBValue union to use for the given field. +string GPBGenericValueFieldName(const FieldDescriptor* field) { + // Returns the field within the GPBGenericValue union to use for the given + // field. if (field->is_repeated()) { return "valueMessage"; } @@ -831,60 +830,6 @@ string BuildCommentsString(const SourceLocation& location) { return final_comments; } -bool InitializeClassWhitelist(string* error) { - const char* env_var_value = getenv("GPB_OBJC_CLASS_WHITELIST_PATHS"); - if (env_var_value == NULL) { - return true; - } - - // The values are joined with ';' in case we ever want to make this a - // generator parameter also (instead of env var), and generator parameter - // parsing already has meaning for ',' and ':'. - vector<string> file_paths = Split(env_var_value, ";", true); - - for (vector<string>::const_iterator i = file_paths.begin(); - i != file_paths.end(); ++i) { - const string& file_path = *i; - - ifstream stream(file_path.c_str(), ifstream::in); - if (!stream.good()) { - if (error != NULL) { - stringstream err_stream; - err_stream << endl << file_path << ":0:0: error: Unable to open"; - *error = err_stream.str(); - return false; - } - } - - string input_line; - while (stream.good()) { - getline(stream, input_line); - string trimmed_line(TrimString(input_line)); - if (trimmed_line.length() == 0) { - // Skip empty lines - continue; - } - if (trimmed_line[0] == '/' || trimmed_line[0] == '#') { - // Skip comments and potential preprocessor symbols - continue; - } - gClassWhitelist.insert(trimmed_line); - } - } - return true; -} - -bool FilterClass(const string& name) { - if (gClassWhitelist.count(name) > 0) { - // Whitelisted, don't filter. - return false; - } - - // If there was no list, default to everything in. - // If there was a list, default to everything out. - return gClassWhitelist.size() > 0; -} - void TextFormatDecodeData::AddString(int32 key, const string& input_for_decode, const string& desired_output) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 19317698..10d51a34 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -138,16 +138,13 @@ inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { bool IsPrimitiveType(const FieldDescriptor* field); bool IsReferenceType(const FieldDescriptor* field); -string GPBValueFieldName(const FieldDescriptor* field); +string GPBGenericValueFieldName(const FieldDescriptor* field); string DefaultValue(const FieldDescriptor* field); string BuildFlagsString(const vector<string>& strings); string BuildCommentsString(const SourceLocation& location); -bool InitializeClassWhitelist(string* error); -bool FilterClass(const string& name); - // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the the expected output. class LIBPROTOC_EXPORT TextFormatDecodeData { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc index b091b77a..dc1cef55 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -242,6 +242,14 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { } #endif // PROTOBUF_HAS_DEATH_TEST +// TODO(thomasvl): Should probably add some unittests for all the special cases +// of name mangling (class name, field name, enum names). Rather than doing +// this with an ObjC test in the objectivec directory, we should be able to +// use src/google/protobuf/compiler/importer* (like other tests) to support a +// virtual file system to feed in protos, once we have the Descriptor tree, the +// tests could use the helper methods for generating names and validate the +// right things are happening. + } // namespace } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 52e583bf..32671d42 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -178,49 +178,25 @@ MessageGenerator::MessageGenerator(const string& root_classname, : root_classname_(root_classname), descriptor_(descriptor), field_generators_(descriptor), - class_name_(ClassName(descriptor_)), - sub_content_filtered_(true) { - if (FilterClass(class_name_)) { - filter_reason_ = - string("Message |") + class_name_ + "| was not whitelisted."; + class_name_(ClassName(descriptor_)) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_.push_back( + new ExtensionGenerator(class_name_, descriptor_->extension(i))); } - if (!IsFiltered()) { - // No need to generate extensions if this message is filtered - for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators_.push_back( - new ExtensionGenerator(class_name_, descriptor_->extension(i))); - } - // No need to generate oneofs if this message is filtered. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); - oneof_generators_.push_back(generator); - } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); + oneof_generators_.push_back(generator); } - // We may have enums of this message that are used even if the message - // itself is filtered. for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); - // The enums are exposed via C functions, so they will dead strip if - // not used. - sub_content_filtered_ &= false; enum_generators_.push_back(generator); } - // We may have nested messages that are used even if the message itself - // is filtered. for (int i = 0; i < descriptor_->nested_type_count(); i++) { - const Descriptor* nested_descriptor = descriptor_->nested_type(i); MessageGenerator* generator = - new MessageGenerator(root_classname_, nested_descriptor); - // Don't check map entries for being filtered, as they don't directly - // generate anything in Objective C. In theory, they only should include - // references to other toplevel types, but we still make the generators - // to be safe. - if (!IsMapEntryMessage(nested_descriptor)) { - sub_content_filtered_ &= generator->IsFiltered(); - } - sub_content_filtered_ &= generator->IsSubContentFiltered(); + new MessageGenerator(root_classname_, descriptor_->nested_type(i)); nested_message_generators_.push_back(generator); } } @@ -236,31 +212,26 @@ MessageGenerator::~MessageGenerator() { } void MessageGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer, bool* out_generated) { - if (!IsFiltered()) { - // Skip extensions if we are filtered. - for (vector<ExtensionGenerator*>::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer, out_generated, - false); - } + io::Printer* printer) { + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); } - // Generating sub messages is perfectly fine though. for (vector<MessageGenerator*>::iterator iter = nested_message_generators_.begin(); iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer, out_generated); + (*iter)->GenerateStaticVariablesInitialization(printer); } } void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) { - if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + if (!IsMapEntryMessage(descriptor_)) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - // If it is a the field is repeated, the type will be and *Array, - // and we don't need any forward decl. + // If it is a the field is repeated, the type will be and *Array, and we + // don't need any forward decl. if (fieldDescriptor->is_repeated()) { continue; } @@ -291,12 +262,10 @@ void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { void MessageGenerator::GenerateExtensionRegistrationSource( io::Printer* printer) { - if (!IsFiltered()) { - for (vector<ExtensionGenerator*>::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateRegistrationSource(printer); - } + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateRegistrationSource(printer); } for (vector<MessageGenerator*>::iterator iter = @@ -317,101 +286,84 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { return; } - if (IsFiltered()) { - printer->Print("// $filter_reason$\n\n", - "filter_reason", filter_reason_); - } else { - printer->Print( - "#pragma mark - $classname$\n" - "\n", - "classname", class_name_); + printer->Print( + "#pragma mark - $classname$\n" + "\n", + "classname", class_name_); - if (descriptor_->field_count()) { - // Even if there are fields, they could be filtered away, so always use - // a buffer to confirm we have something. - ostringstream fieldnumber_stringstream; - { - scoped_array<const FieldDescriptor*> sorted_fields( - SortFieldsByNumber(descriptor_)); - - io::OstreamOutputStream fieldnumber_outputstream( - &fieldnumber_stringstream); - io::Printer fieldnumber_printer(&fieldnumber_outputstream, '$'); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]) - .GenerateFieldNumberConstant(&fieldnumber_printer); - } - fieldnumber_stringstream.flush(); - } - const string& fieldnumber_str = fieldnumber_stringstream.str(); - if (fieldnumber_str.length()) { - printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", - "classname", class_name_); - printer->Indent(); - printer->Print(fieldnumber_str.c_str()); - printer->Outdent(); - printer->Print("};\n\n"); - } - } + if (descriptor_->field_count()) { + scoped_array<const FieldDescriptor*> sorted_fields( + SortFieldsByNumber(descriptor_)); - for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateCaseEnum(printer); - } + printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", + "classname", class_name_); + printer->Indent(); - string message_comments; - SourceLocation location; - if (descriptor_->GetSourceLocation(&location)) { - message_comments = BuildCommentsString(location); - } else { - message_comments = ""; + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateFieldNumberConstant(printer); } - printer->Print( - "$comments$@interface $classname$ : GPBMessage\n\n", - "classname", class_name_, - "comments", message_comments); + printer->Outdent(); + printer->Print("};\n\n"); + } - vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() != NULL) { - const int oneof_index = field->containing_oneof()->index(); - if (!seen_oneofs[oneof_index]) { - seen_oneofs[oneof_index] = 1; - oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( - printer); - } + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GenerateCaseEnum(printer); + } + + string message_comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + message_comments = BuildCommentsString(location); + } else { + message_comments = ""; + } + + printer->Print( + "$comments$@interface $classname$ : GPBMessage\n\n", + "classname", class_name_, + "comments", message_comments); + + vector<char> seen_oneofs(descriptor_->oneof_decl_count(), 0); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof() != NULL) { + const int oneof_index = field->containing_oneof()->index(); + if (!seen_oneofs[oneof_index]) { + seen_oneofs[oneof_index] = 1; + oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( + printer); } - field_generators_.get(field) - .GeneratePropertyDeclaration(printer); } + field_generators_.get(field).GeneratePropertyDeclaration(printer); + } - printer->Print("@end\n\n"); + printer->Print("@end\n\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateCFunctionDeclarations(printer); - } + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionDeclarations(printer); + } - if (!oneof_generators_.empty()) { - for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateClearFunctionDeclaration(printer); - } - printer->Print("\n"); + if (!oneof_generators_.empty()) { + for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin(); + iter != oneof_generators_.end(); ++iter) { + (*iter)->GenerateClearFunctionDeclaration(printer); } + printer->Print("\n"); + } - if (descriptor_->extension_count() > 0) { - printer->Print("@interface $classname$ (DynamicMethods)\n\n", - "classname", class_name_); - for (vector<ExtensionGenerator*>::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateMembersHeader(printer); - } - printer->Print("@end\n\n"); + if (descriptor_->extension_count() > 0) { + printer->Print("@interface $classname$ (DynamicMethods)\n\n", + "classname", class_name_); + for (vector<ExtensionGenerator*>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateMembersHeader(printer); } + printer->Print("@end\n\n"); } for (vector<MessageGenerator*>::iterator iter = @@ -422,7 +374,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { } void MessageGenerator::GenerateSource(io::Printer* printer) { - if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + if (!IsMapEntryMessage(descriptor_)) { printer->Print( "#pragma mark - $classname$\n" "\n", @@ -454,6 +406,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeOrdering()); + // TODO(thomasvl): Finish optimizing has bit. The current behavior is as + // follows: + // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index + // to the field's index in the list of fields. + // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to + // GPBNoHasBit because repeated fields & map<> fields don't use the has + // bit. + // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative + // index that groups all the elements on of the oneof. + // So in has_storage, we need enough bits for the single fields that aren't + // in any oneof, and then one int32 for each oneof (to store the field + // number). So we could save a little space by not using the field's index + // and instead make a second pass only assigning indexes for the fields + // that would need it. The only savings would come when messages have over + // a multiple of 32 fields with some number being repeated or in oneofs to + // drop the count below that 32 multiple; so it hasn't seemed worth doing + // at the moment. size_t num_has_bits = descriptor_->field_count(); size_t sizeof_has_storage = (num_has_bits + 31) / 32; // Tell all the fields the oneof base. @@ -467,7 +436,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Print( "\n" - "typedef struct $classname$_Storage {\n" + "typedef struct $classname$__storage_ {\n" " uint32_t _has_storage_[$sizeof_has_storage$];\n", "classname", class_name_, "sizeof_has_storage", SimpleItoa(sizeof_has_storage)); @@ -479,14 +448,14 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { } printer->Outdent(); - printer->Print("} $classname$_Storage;\n\n", "classname", class_name_); + printer->Print("} $classname$__storage_;\n\n", "classname", class_name_); printer->Print( "// This method is threadsafe because it is initially called\n" "// in +initialize for each subclass.\n" "+ (GPBDescriptor *)descriptor {\n" - " static GPBDescriptor *descriptor = NULL;\n" + " static GPBDescriptor *descriptor = nil;\n" " if (!descriptor) {\n"); bool has_oneofs = oneof_generators_.size(); @@ -507,30 +476,45 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " };\n"); } - printer->Print( - " static GPBMessageFieldDescription fields[] = {\n"); - printer->Indent(); - printer->Indent(); - printer->Indent(); TextFormatDecodeData text_format_decode_data; - for (int i = 0; i < descriptor_->field_count(); ++i) { - const FieldGenerator& field_generator = - field_generators_.get(sorted_fields[i]); - field_generator.GenerateFieldDescription(printer); - if (field_generator.needs_textformat_name_support()) { - text_format_decode_data.AddString(sorted_fields[i]->number(), - field_generator.generated_objc_name(), - field_generator.raw_field_name()); + bool has_fields = descriptor_->field_count() > 0; + if (has_fields) { + // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription() + // wraps the fieldOptions's value of this structure in an CPP gate so + // they can be compiled away; but that still results in a const char* in + // the structure for a NULL pointer for every message field. If the + // fieldOptions are moved to a separate payload like the TextFormat extra + // data is, then it would shrink that static data shrinking the binaries + // a little more. + // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the + // structure because primitive types are always zero. If we add a second + // structure and a different initializer, we can avoid the wasted static + // storage for every field in a proto3 message. + printer->Print( + " static GPBMessageFieldDescription fields[] = {\n"); + printer->Indent(); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldGenerator& field_generator = + field_generators_.get(sorted_fields[i]); + field_generator.GenerateFieldDescription(printer); + if (field_generator.needs_textformat_name_support()) { + text_format_decode_data.AddString(sorted_fields[i]->number(), + field_generator.generated_objc_name(), + field_generator.raw_field_name()); + } } + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " };\n"); } - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); bool has_enums = enum_generators_.size(); if (has_enums) { printer->Print( - " };\n" " static GPBMessageEnumDescription enums[] = {\n"); printer->Indent(); printer->Indent(); @@ -543,12 +527,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Outdent(); + printer->Print( + " };\n"); } bool has_extensions = sorted_extensions.size(); if (has_extensions) { printer->Print( - " };\n" " static GPBExtensionRange ranges[] = {\n"); printer->Indent(); printer->Indent(); @@ -561,11 +546,16 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Outdent(); + printer->Print( + " };\n"); } map<string, string> vars; vars["classname"] = class_name_; vars["rootclassname"] = root_classname_; + vars["fields"] = has_fields ? "fields" : "NULL"; + vars["fields_count"] = + has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0"; vars["oneofs"] = has_oneofs ? "oneofs" : "NULL"; vars["oneof_count"] = has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0"; @@ -578,23 +568,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { vars["wireformat"] = descriptor_->options().message_set_wire_format() ? "YES" : "NO"; - printer->Print(" };\n"); if (text_format_decode_data.num_entries() == 0) { printer->Print( vars, - " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" - " rootClass:[$rootclassname$ class]\n" - " file:$rootclassname$_FileDescriptor()\n" - " fields:fields\n" - " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n" - " oneofs:$oneofs$\n" - " oneofCount:$oneof_count$\n" - " enums:$enums$\n" - " enumCount:$enum_count$\n" - " ranges:$ranges$\n" - " rangeCount:$range_count$\n" - " storageSize:sizeof($classname$_Storage)\n" - " wireFormat:$wireformat$];\n"); + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\n" + " oneofs:$oneofs$\n" + " oneofCount:$oneof_count$\n" + " enums:$enums$\n" + " enumCount:$enum_count$\n" + " ranges:$ranges$\n" + " rangeCount:$range_count$\n" + " storageSize:sizeof($classname$__storage_)\n" + " wireFormat:$wireformat$];\n"); } else { vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data()); printer->Print( @@ -604,26 +594,29 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "#else\n" " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n" "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" - " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" - " rootClass:[$rootclassname$ class]\n" - " file:$rootclassname$_FileDescriptor()\n" - " fields:fields\n" - " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n" - " oneofs:$oneofs$\n" - " oneofCount:$oneof_count$\n" - " enums:$enums$\n" - " enumCount:$enum_count$\n" - " ranges:$ranges$\n" - " rangeCount:$range_count$\n" - " storageSize:sizeof($classname$_Storage)\n" - " wireFormat:$wireformat$\n" - " extraTextFormatInfo:extraTextFormatInfo];\n"); + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\n" + " oneofs:$oneofs$\n" + " oneofCount:$oneof_count$\n" + " enums:$enums$\n" + " enumCount:$enum_count$\n" + " ranges:$ranges$\n" + " rangeCount:$range_count$\n" + " storageSize:sizeof($classname$__storage_)\n" + " wireFormat:$wireformat$\n" + " extraTextFormatInfo:extraTextFormatInfo];\n"); } printer->Print( - " }\n" - " return descriptor;\n" - "}\n\n" - "@end\n\n"); + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " descriptor = localDescriptor;\n" + " }\n" + " return descriptor;\n" + "}\n\n" + "@end\n\n"); for (int i = 0; i < descriptor_->field_count(); i++) { field_generators_.get(descriptor_->field(i)) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 8d03c0b8..06b536ff 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -57,20 +57,13 @@ class MessageGenerator { MessageGenerator(const string& root_classname, const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariablesInitialization(io::Printer* printer, - bool* out_generated); + void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateEnumHeader(io::Printer* printer); void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); void GenerateExtensionRegistrationSource(io::Printer* printer); void DetermineForwardDeclarations(set<string>* fwd_decls); - // This only speaks for this message, not sub message/enums. - bool IsFiltered() const { return filter_reason_.length() > 0; } - // This message being filtered doesn't effect this, instead it covers if - // there are any nested messages or enums. - bool IsSubContentFiltered() const { return sub_content_filtered_; } - private: void GenerateParseFromMethodsHeader(io::Printer* printer); @@ -87,8 +80,6 @@ class MessageGenerator { const Descriptor* descriptor_; FieldGeneratorMap field_generators_; const string class_name_; - string filter_reason_; - bool sub_content_filtered_; vector<ExtensionGenerator*> extension_generators_; vector<EnumGenerator*> enum_generators_; vector<MessageGenerator*> nested_message_generators_; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 2e3bdfdb..f2ce4e5b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -53,7 +53,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["group_or_message"] = (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; - (*variables)["typeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; + (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; } } // namespace diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 344ed450..e7890fae 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -913,7 +913,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( int CodeGeneratorResponse_File::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 7) { + if (_has_bits_[0 / 32] & 7u) { // optional string name = 1; if (has_name()) { total_size += 1 + diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 6c203ab6..1b04cb32 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -47,6 +47,7 @@ namespace { string FindRubyTestDir(const string& file) { // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF string prefix = "."; while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) { if (!File::Exists(prefix)) { @@ -57,6 +58,9 @@ string FindRubyTestDir(const string& file) { prefix += "/.."; } return prefix + "/src/google/protobuf/compiler/ruby"; +#else + return "third_party/protobuf/src/google/protobuf/compiler/ruby"; +#endif // GOOGLE_THIRD_PARTY_PROTOBUF } // This test is a simple golden-file test over the output of the Ruby code diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 755c2617..30b3a3a7 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -753,9 +753,10 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" - "ached_comments\030\006 \003(\tBY\n\023com.google.proto" - "bufB\020DescriptorProtosH\001\242\002\003GPB\252\002\'Google.P" - "rotocolBuffers.DescriptorProtos", 4951); + "ached_comments\030\006 \003(\tBe\n\023com.google.proto" + "bufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003GP" + "B\252\002\'Google.ProtocolBuffers.DescriptorPro" + "tos", 4963); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -1648,7 +1649,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( int FileDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -1664,7 +1665,7 @@ int FileDescriptorProto::ByteSize() const { } } - if (_has_bits_[9 / 32] & 3584) { + if (_has_bits_[9 / 32] & 3584u) { // optional .google.protobuf.FileOptions options = 8; if (has_options()) { total_size += 1 + @@ -2534,7 +2535,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( int DescriptorProto_ExtensionRange::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional int32 start = 1; if (has_start()) { total_size += 1 + @@ -2817,7 +2818,7 @@ void DescriptorProto_ReservedRange::SerializeWithCachedSizes( int DescriptorProto_ReservedRange::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional int32 start = 1; if (has_start()) { total_size += 1 + @@ -3373,7 +3374,7 @@ void DescriptorProto::SerializeWithCachedSizes( int DescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 129) { + if (_has_bits_[0 / 32] & 129u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -4558,7 +4559,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( int FieldDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 255) { + if (_has_bits_[0 / 32] & 255u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -5633,7 +5634,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( int EnumDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 5) { + if (_has_bits_[0 / 32] & 5u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -6102,7 +6103,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( int EnumValueDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 7) { + if (_has_bits_[0 / 32] & 7u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -6569,7 +6570,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( int ServiceDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 5) { + if (_has_bits_[0 / 32] & 5u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -7165,7 +7166,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( int MethodDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 63u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -8240,7 +8241,7 @@ void FileOptions::SerializeWithCachedSizes( int FileOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 255) { + if (_has_bits_[0 / 32] & 255u) { // optional string java_package = 1; if (has_java_package()) { total_size += 1 + @@ -8289,7 +8290,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 16128) { + if (_has_bits_[8 / 32] & 16128u) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -9279,7 +9280,7 @@ void MessageOptions::SerializeWithCachedSizes( int MessageOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 15) { + if (_has_bits_[0 / 32] & 15u) { // optional bool message_set_wire_format = 1 [default = false]; if (has_message_set_wire_format()) { total_size += 1 + 1; @@ -9939,7 +9940,7 @@ void FieldOptions::SerializeWithCachedSizes( int FieldOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 63u) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { total_size += 1 + @@ -10498,7 +10499,7 @@ void EnumOptions::SerializeWithCachedSizes( int EnumOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional bool allow_alias = 2; if (has_allow_alias()) { total_size += 1 + 1; @@ -12410,7 +12411,7 @@ void UninterpretedOption::SerializeWithCachedSizes( int UninterpretedOption::ByteSize() const { int total_size = 0; - if (_has_bits_[1 / 32] & 126) { + if (_has_bits_[1 / 32] & 126u) { // optional string identifier_value = 3; if (has_identifier_value()) { total_size += 1 + @@ -13248,7 +13249,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( int SourceCodeInfo_Location::ByteSize() const { int total_size = 0; - if (_has_bits_[2 / 32] & 12) { + if (_has_bits_[2 / 32] & 12u) { // optional string leading_comments = 3; if (has_leading_comments()) { total_size += 1 + diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 97741b6a..82de7b09 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -40,6 +40,7 @@ syntax = "proto2"; package google.protobuf; +option go_package = "descriptor"; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.DescriptorProtos"; diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index c9f4ca7f..dd7c036e 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -33,8 +33,6 @@ // This file contains the implementation of classes GzipInputStream and // GzipOutputStream. -#include "config.h" - #if HAVE_ZLIB #include <google/protobuf/io/gzip_stream.h> diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index dd3d1285..f2e5b629 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -46,8 +46,6 @@ // "parametized tests" so that one set of tests can be used on all the // implementations. -#include "config.h" - #ifdef _MSC_VER #include <io.h> #else diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h index bbe2d845..cd20caac 100644 --- a/src/google/protobuf/stubs/atomicops.h +++ b/src/google/protobuf/stubs/atomicops.h @@ -56,6 +56,7 @@ // Don't include this file for people not concerned about thread safety. #ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY +#include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/platform_macros.h> namespace google { diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index 54e00ccb..22cc5aa1 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -36,8 +36,6 @@ #include <errno.h> #include <vector> -#include "config.h" - #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN // We only need minimal includes #include <windows.h> diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 3acaeba1..49d16020 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -62,6 +62,8 @@ #include <exception> #endif +#include <google/protobuf/stubs/platform_macros.h> + #if defined(__APPLE__) #include <TargetConditionals.h> // for TARGET_OS_IPHONE #endif @@ -258,7 +260,7 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); #ifndef GOOGLE_PREDICT_FALSE #ifdef __GNUC__ // Provided at least since GCC 3.0. -#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(!!(x), 1)) +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) #else #define GOOGLE_PREDICT_FALSE #endif @@ -1174,11 +1176,7 @@ class LIBPROTOBUF_EXPORT MutexLockMaybe { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); }; -#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE) -// Android ndk does not support the __thread keyword very well yet. Here -// we use pthread_key_create()/pthread_getspecific()/... methods for -// TLS support on android. -// iOS also does not support the __thread keyword. +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) template<typename T> class ThreadLocalStorage { public: diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 5f458e98..f9e2cfd4 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -39,8 +39,6 @@ #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> -#include "config.h" - namespace google { namespace protobuf { namespace { diff --git a/src/google/protobuf/stubs/pbconfig.h b/src/google/protobuf/stubs/pbconfig.h new file mode 100644 index 00000000..0f21c560 --- /dev/null +++ b/src/google/protobuf/stubs/pbconfig.h @@ -0,0 +1,142 @@ +// 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_PBCONFIG_H__ +#define GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ + +#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 +#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 + +// Use C++11 unordered_{map|set} if available. +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH + +// For XCode >= 4.6: the compiler is clang with libc++. +// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. +// libc++ provides <unordered_map> and friends even in non C++11 mode, +// and it does not provide the tr1 library. Therefore the following macro +// checks against this special case. +// Note that we should not test the __APPLE_CC__ version number or the +// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in +// which case <unordered_map> is not compilable without -std=c++11 +#elif defined(__APPLE_CC__) +# if defined(_LIBCPP_VERSION) +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH +# elif __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# else +// Not tested for gcc < 4... These setting can compile under 4.2.1 though. +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx +# define GOOGLE_PROTOBUF_HASH_MAP_H <ext/hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <ext/hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for gcc. +#elif defined(__GNUC__) +// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the +// instructions from: +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html +# if __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# elif __GNUC__ >= 3 +# define GOOGLE_PROTOBUF_HASH_MAP_H <backward/hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <backward/hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later +# endif +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE +# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for MSC. +// Apparently Microsoft decided to move hash_map *back* to the std namespace in +// MSVC 2010: +// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx +// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That +// said, use unordered_map for MSVC 2010 and beyond is our safest bet. +#elif defined(_MSC_VER) +# if _MSC_VER >= 1600 // Since Visual Studio 2010 +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH +# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare +# elif _MSC_VER >= 1500 // Since Visual Studio 2008 +# define GOOGLE_PROTOBUF_HAS_TR1 +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# elif _MSC_VER >= 1310 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext +# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# define GOOGLE_PROTOBUF_HASH_SET_H <hash_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# endif + +// **ADD NEW COMPILERS SUPPORT HERE.** +// For other compilers, undefine the macro and fallback to use std::map, in +// google/protobuf/stubs/hash.h +#else +# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP +# undef GOOGLE_PROTOBUF_HAVE_HASH_SET +#endif + +#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#elif defined(GOOGLE_PROTOBUF_HAS_TR1) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 +# define GOOGLE_PROTOBUF_HASH_MAP_H <tr1/unordered_map> +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# define GOOGLE_PROTOBUF_HASH_SET_H <tr1/unordered_set> +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#endif + +#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH +#undef GOOGLE_PROTOBUF_HAS_TR1 + +#endif // GOOGLE_PROTOBUF_STUBS_PBCONFIG_H__ diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h index 2ce7fc8f..9e0344d8 100644 --- a/src/google/protobuf/stubs/platform_macros.h +++ b/src/google/protobuf/stubs/platform_macros.h @@ -31,8 +31,6 @@ #ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ #define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ -#include <google/protobuf/stubs/common.h> - #define GOOGLE_PROTOBUF_PLATFORM_ERROR \ #error "Host platform was not detected as supported by protobuf" @@ -111,4 +109,12 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR #undef GOOGLE_PROTOBUF_PLATFORM_ERROR +#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +// Android ndk does not support the __thread keyword very well yet. Here +// we use pthread_key_create()/pthread_getspecific()/... methods for +// TLS support on android. +// iOS also does not support the __thread keyword. +#define GOOGLE_PROTOBUF_NO_THREADLOCAL +#endif + #endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/src/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc index daf74ff1..c9d085c8 100644 --- a/src/google/protobuf/testing/zcgunzip.cc +++ b/src/google/protobuf/testing/zcgunzip.cc @@ -38,8 +38,6 @@ // Reads gzip stream on standard input and writes decompressed data to standard // output. -#include "config.h" - #include <assert.h> #include <stdio.h> #include <stdlib.h> diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc index a4101999..e910f321 100644 --- a/src/google/protobuf/testing/zcgzip.cc +++ b/src/google/protobuf/testing/zcgzip.cc @@ -38,8 +38,6 @@ // Reads data on standard input and writes compressed gzip stream to standard // output. -#include "config.h" - #include <stdio.h> #include <stdlib.h> #include <fcntl.h> |