diff options
Diffstat (limited to 'NorthstarDedicatedTest/include/protobuf/compiler/objectivec')
26 files changed, 7078 insertions, 0 deletions
diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc new file mode 100644 index 00000000..5510750a --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.cc @@ -0,0 +1,260 @@ +// 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. + +#include <map> +#include <string> + +#include <compiler/objectivec/objectivec_enum.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/printer.h> +#include <stubs/strutil.h> +#include <algorithm> // std::find() + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) + : descriptor_(descriptor), + name_(EnumName(descriptor_)) { + // Track the names for the enum values, and if an alias overlaps a base + // value, skip making a name for it. Likewise if two alias overlap, the + // first one wins. + // The one gap in this logic is if two base values overlap, but for that + // to happen you have to have "Foo" and "FOO" or "FOO_BAR" and "FooBar", + // and if an enum has that, it is already going to be confusing and a + // compile error is just fine. + // The values are still tracked to support the reflection apis and + // TextFormat handing since they are different there. + std::set<std::string> value_names; + + for (int i = 0; i < descriptor_->value_count(); i++) { + const EnumValueDescriptor* value = descriptor_->value(i); + const EnumValueDescriptor* canonical_value = + descriptor_->FindValueByNumber(value->number()); + + if (value == canonical_value) { + base_values_.push_back(value); + value_names.insert(EnumValueName(value)); + } else { + std::string value_name(EnumValueName(value)); + if (value_names.find(value_name) != value_names.end()) { + alias_values_to_skip_.insert(value); + } else { + value_names.insert(value_name); + } + } + all_values_.push_back(value); + } +} + +EnumGenerator::~EnumGenerator() {} + +void EnumGenerator::GenerateHeader(io::Printer* printer) { + std::string enum_comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + enum_comments = BuildCommentsString(location, true); + } else { + enum_comments = ""; + } + + printer->Print( + "#pragma mark - Enum $name$\n" + "\n", + "name", name_); + + // Swift 5 included SE0192 "Handling Future Enum Cases" + // https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md + // Since a .proto file can get new values added to an enum at any time, they + // are effectively "non-frozen". Even in a proto3 syntax file where there is + // support for the unknown value, an edit to the file can always add a new + // value moving something from unknown to known. Since Swift is now ABI + // stable, it also means a binary could contain Swift compiled against one + // version of the .pbobjc.h file, but finally linked against an enum with + // more cases. So the Swift code will always have to treat ObjC Proto Enums + // as "non-frozen". The default behavior in SE0192 is for all objc enums to + // be "non-frozen" unless marked as otherwise, so this means this generation + // doesn't have to bother with the `enum_extensibility` attribute, as the + // default will be what is needed. + + printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n", + "comments", enum_comments, + "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()), + "name", name_); + printer->Indent(); + + if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { + // Include the unknown value. + printer->Print( + "/**\n" + " * Value used if any message's field encounters a value that is not defined\n" + " * by this enum. The message will also have C functions to get/set the rawValue\n" + " * of the field.\n" + " **/\n" + "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n", + "name", name_); + } + for (int i = 0; i < all_values_.size(); i++) { + if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) { + continue; + } + if (all_values_[i]->GetSourceLocation(&location)) { + std::string comments = BuildCommentsString(location, true).c_str(); + if (comments.length() > 0) { + if (i > 0) { + printer->Print("\n"); + } + printer->Print(comments.c_str()); + } + } + + printer->Print( + "$name$$deprecated_attribute$ = $value$,\n", + "name", EnumValueName(all_values_[i]), + "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]), + "value", StrCat(all_values_[i]->number())); + } + printer->Outdent(); + printer->Print( + "};\n" + "\n" + "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n" + "\n" + "/**\n" + " * Checks to see if the given value is defined by the enum or was not known at\n" + " * the time this source was generated.\n" + " **/\n" + "BOOL $name$_IsValidValue(int32_t value);\n" + "\n", + "name", name_); +} + +void EnumGenerator::GenerateSource(io::Printer* printer) { + printer->Print( + "#pragma mark - Enum $name$\n" + "\n", + "name", name_); + + // Note: For the TextFormat decode info, we can't use the enum value as + // the key because protocol buffer enums have 'allow_alias', which lets + // a value be used more than once. Instead, the index into the list of + // enum value descriptions is used. Note: start with -1 so the first one + // will be zero. + TextFormatDecodeData text_format_decode_data; + int enum_value_description_key = -1; + std::string text_blob; + + for (int i = 0; i < all_values_.size(); i++) { + ++enum_value_description_key; + std::string short_name(EnumValueShortName(all_values_[i])); + text_blob += short_name + '\0'; + if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) { + text_format_decode_data.AddString(enum_value_description_key, short_name, + all_values_[i]->name()); + } + } + + printer->Print( + "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n" + " static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n" + " if (!descriptor) {\n", + "name", name_); + + static const int kBytesPerLine = 40; // allow for escaping + printer->Print( + " static const char *valueNames ="); + for (int i = 0; i < text_blob.size(); i += kBytesPerLine) { + printer->Print( + "\n \"$data$\"", + "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine)))); + } + printer->Print( + ";\n" + " static const int32_t values[] = {\n"); + for (int i = 0; i < all_values_.size(); i++) { + printer->Print(" $name$,\n", "name", EnumValueName(all_values_[i])); + } + printer->Print(" };\n"); + + if (text_format_decode_data.num_entries() == 0) { + printer->Print( + " GPBEnumDescriptor *worker =\n" + " [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n" + " valueNames:valueNames\n" + " values:values\n" + " count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n" + " enumVerifier:$name$_IsValidValue];\n", + "name", name_); + } else { + printer->Print( + " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n" + " GPBEnumDescriptor *worker =\n" + " [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n" + " valueNames:valueNames\n" + " values:values\n" + " count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n" + " enumVerifier:$name$_IsValidValue\n" + " extraTextFormatInfo:extraTextFormatInfo];\n", + "name", name_, + "extraTextFormatInfo", CEscape(text_format_decode_data.Data())); + } + printer->Print( + " GPBEnumDescriptor *expected = nil;\n" + " if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n" + " [worker release];\n" + " }\n" + " }\n" + " return descriptor;\n" + "}\n\n"); + + printer->Print( + "BOOL $name$_IsValidValue(int32_t value__) {\n" + " switch (value__) {\n", + "name", name_); + + for (int i = 0; i < base_values_.size(); i++) { + printer->Print( + " case $name$:\n", + "name", EnumValueName(base_values_[i])); + } + + printer->Print( + " return YES;\n" + " default:\n" + " return NO;\n" + " }\n" + "}\n\n"); +} +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h new file mode 100644 index 00000000..51560dd1 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum.h @@ -0,0 +1,71 @@ +// 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_COMPILER_OBJECTIVEC_ENUM_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ + +#include <string> +#include <set> +#include <vector> +#include <descriptor.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class EnumGenerator { + public: + explicit EnumGenerator(const EnumDescriptor* descriptor); + ~EnumGenerator(); + + EnumGenerator(const EnumGenerator&) = delete; + EnumGenerator& operator=(const EnumGenerator&) = delete; + + void GenerateHeader(io::Printer* printer); + void GenerateSource(io::Printer* printer); + + const std::string& name() const { return name_; } + + private: + const EnumDescriptor* descriptor_; + std::vector<const EnumValueDescriptor*> base_values_; + std::vector<const EnumValueDescriptor*> all_values_; + std::set<const EnumValueDescriptor*> alias_values_to_skip_; + const std::string name_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc new file mode 100644 index 00000000..66877afb --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -0,0 +1,149 @@ +// 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. + +#include <map> +#include <string> + +#include <compiler/objectivec/objectivec_enum_field.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/printer.h> +#include <wire_format.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +void SetEnumVariables(const FieldDescriptor* descriptor, + std::map<std::string, std::string>* variables) { + std::string type = EnumName(descriptor->enum_type()); + (*variables)["storage_type"] = type; + // For non repeated fields, if it was defined in a different file, the + // property decls need to use "enum NAME" rather than just "NAME" to support + // the forward declaration of the enums. + if (!descriptor->is_repeated() && + (descriptor->file() != descriptor->enum_type()->file())) { + (*variables)["property_type"] = "enum " + type; + } + (*variables)["enum_verifier"] = type + "_IsValidValue"; + (*variables)["enum_desc_func"] = type + "_EnumDescriptor"; + + (*variables)["dataTypeSpecific_name"] = "enumDescFunc"; + (*variables)["dataTypeSpecific_value"] = (*variables)["enum_desc_func"]; + + const Descriptor* msg_descriptor = descriptor->containing_type(); + (*variables)["owning_message_class"] = ClassName(msg_descriptor); +} +} // namespace + +EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : SingleFieldGenerator(descriptor, options) { + SetEnumVariables(descriptor, &variables_); +} + +EnumFieldGenerator::~EnumFieldGenerator() {} + +void EnumFieldGenerator::GenerateCFunctionDeclarations( + io::Printer* printer) const { + if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { + return; + } + + printer->Print( + variables_, + "/**\n" + " * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n" + " * if the value was not defined by the enum at the time the code was generated.\n" + " **/\n" + "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n" + "/**\n" + " * Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n" + " * it to be set to a value that was not defined by the enum at the time the code\n" + " * was generated.\n" + " **/\n" + "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n" + "\n"); +} + +void EnumFieldGenerator::GenerateCFunctionImplementations( + io::Printer* printer) const { + if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return; + + printer->Print( + variables_, + "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 GPBGetMessageRawEnumField(message, field);\n" + "}\n" + "\n" + "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" + " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" + " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" + " GPBSetMessageRawEnumField(message, field, value);\n" + "}\n" + "\n"); +} + +void EnumFieldGenerator::DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const { + SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls); + // If it is an enum defined in a different file, then we'll need a forward + // declaration for it. When it is in our file, all the enums are output + // before the message, so it will be declared before it is needed. + if (descriptor_->file() != descriptor_->enum_type()->file()) { + // Enum name is already in "storage_type". + const std::string& name = variable("storage_type"); + fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")"); + } +} + +RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : RepeatedFieldGenerator(descriptor, options) { + SetEnumVariables(descriptor, &variables_); + variables_["array_storage_type"] = "GPBEnumArray"; +} + +RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} + +void RepeatedEnumFieldGenerator::FinishInitialization(void) { + RepeatedFieldGenerator::FinishInitialization(); + variables_["array_comment"] = + "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n"; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h new file mode 100644 index 00000000..1f11abcb --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_enum_field.h @@ -0,0 +1,80 @@ +// 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_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ + +#include <map> +#include <string> +#include <compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class EnumFieldGenerator : public SingleFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + EnumFieldGenerator(const EnumFieldGenerator&) = delete; + EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete; + + public: + virtual void GenerateCFunctionDeclarations( + io::Printer* printer) const override; + virtual void GenerateCFunctionImplementations( + io::Printer* printer) const override; + virtual void DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const override; + + protected: + EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options); + virtual ~EnumFieldGenerator(); +}; + +class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + public: + virtual void FinishInitialization() override; + + protected: + RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + virtual ~RepeatedEnumFieldGenerator(); +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc new file mode 100644 index 00000000..7ec80bc9 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.cc @@ -0,0 +1,156 @@ +// 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. + +#include <iostream> + +#include <compiler/objectivec/objectivec_extension.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <descriptor.pb.h> +#include <stubs/strutil.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +ExtensionGenerator::ExtensionGenerator(const std::string& root_class_name, + const FieldDescriptor* descriptor) + : method_name_(ExtensionMethodName(descriptor)), + root_class_and_method_name_(root_class_name + "_" + method_name_), + descriptor_(descriptor) { + 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. + std::cerr << "error: Extension is a map<>!" + << " That used to be blocked by the compiler." << std::endl; + std::cerr.flush(); + abort(); + } +} + +ExtensionGenerator::~ExtensionGenerator() {} + +void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { + std::map<std::string, std::string> vars; + vars["method_name"] = method_name_; + if (IsRetainedName(method_name_)) { + vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; + } else { + vars["storage_attribute"] = ""; + } + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + vars["comments"] = BuildCommentsString(location, true); + } else { + vars["comments"] = ""; + } + // Unlike normal message fields, check if the file for the extension was + // deprecated. + vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()); + printer->Print(vars, + "$comments$" + "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n"); +} + +void ExtensionGenerator::GenerateStaticVariablesInitialization( + io::Printer* printer) { + std::map<std::string, std::string> vars; + vars["root_class_and_method_name"] = root_class_and_method_name_; + const std::string containing_type = ClassName(descriptor_->containing_type()); + vars["extended_type"] = ObjCClass(containing_type); + vars["number"] = StrCat(descriptor_->number()); + + std::vector<std::string> options; + if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated"); + if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked"); + if (descriptor_->containing_type()->options().message_set_wire_format()) { + options.push_back("GPBExtensionSetWireFormat"); + } + vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options); + + ObjectiveCType objc_type = GetObjectiveCType(descriptor_); + if (objc_type == OBJECTIVECTYPE_MESSAGE) { + std::string message_type = ClassName(descriptor_->message_type()); + vars["type"] = ObjCClass(message_type); + } else { + vars["type"] = "Nil"; + } + + vars["default_name"] = GPBGenericValueFieldName(descriptor_); + if (descriptor_->is_repeated()) { + vars["default"] = "nil"; + } else { + vars["default"] = DefaultValue(descriptor_); + } + std::string type = GetCapitalizedType(descriptor_); + vars["extension_type"] = std::string("GPBDataType") + type; + + if (objc_type == OBJECTIVECTYPE_ENUM) { + vars["enum_desc_func_name"] = + EnumName(descriptor_->enum_type()) + "_EnumDescriptor"; + } else { + vars["enum_desc_func_name"] = "NULL"; + } + + printer->Print(vars, + "{\n" + " .defaultValue.$default_name$ = $default$,\n" + " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" + " .extendedClass.clazz = $extended_type$,\n" + " .messageOrGroupClass.clazz = $type$,\n" + " .enumDescriptorFunc = $enum_desc_func_name$,\n" + " .fieldNumber = $number$,\n" + " .dataType = $extension_type$,\n" + " .options = $options$,\n" + "},\n"); +} + +void ExtensionGenerator::DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) { + std::string extended_type = ClassName(descriptor_->containing_type()); + fwd_decls->insert(ObjCClassDeclaration(extended_type)); + ObjectiveCType objc_type = GetObjectiveCType(descriptor_); + if (objc_type == OBJECTIVECTYPE_MESSAGE) { + std::string message_type = ClassName(descriptor_->message_type()); + fwd_decls->insert(ObjCClassDeclaration(message_type)); + } +} + +void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { + printer->Print( + "[registry addExtension:$root_class_and_method_name$];\n", + "root_class_and_method_name", root_class_and_method_name_); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h new file mode 100644 index 00000000..b985d831 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_extension.h @@ -0,0 +1,67 @@ +// 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_COMPILER_OBJECTIVEC_EXTENSION_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ + +#include <descriptor.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class ExtensionGenerator { + public: + ExtensionGenerator(const std::string& root_class_name, + const FieldDescriptor* descriptor); + ~ExtensionGenerator(); + + ExtensionGenerator(const ExtensionGenerator&) = delete; + ExtensionGenerator& operator=(const ExtensionGenerator&) = delete; + + void GenerateMembersHeader(io::Printer* printer); + void GenerateStaticVariablesInitialization(io::Printer* printer); + void GenerateRegistrationSource(io::Printer* printer); + void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls); + + private: + std::string method_name_; + std::string root_class_and_method_name_; + const FieldDescriptor* descriptor_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc new file mode 100644 index 00000000..29f434b5 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.cc @@ -0,0 +1,475 @@ +// 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. + +#include <iostream> + +#include <compiler/objectivec/objectivec_field.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <compiler/objectivec/objectivec_enum_field.h> +#include <compiler/objectivec/objectivec_map_field.h> +#include <compiler/objectivec/objectivec_message_field.h> +#include <compiler/objectivec/objectivec_primitive_field.h> +#include <io/printer.h> +#include <wire_format.h> +#include <stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + std::map<std::string, std::string>* variables) { + std::string camel_case_name = FieldName(descriptor); + std::string raw_field_name; + if (descriptor->type() == FieldDescriptor::TYPE_GROUP) { + raw_field_name = descriptor->message_type()->name(); + } else { + raw_field_name = descriptor->name(); + } + // The logic here has to match -[GGPBFieldDescriptor textFormatName]. + const std::string un_camel_case_name( + UnCamelCaseFieldName(camel_case_name, descriptor)); + const bool needs_custom_name = (raw_field_name != un_camel_case_name); + + SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + (*variables)["comments"] = BuildCommentsString(location, true); + } else { + (*variables)["comments"] = "\n"; + } + const std::string& classname = ClassName(descriptor->containing_type()); + (*variables)["classname"] = classname; + (*variables)["name"] = camel_case_name; + const std::string& capitalized_name = FieldNameCapitalized(descriptor); + (*variables)["capitalized_name"] = capitalized_name; + (*variables)["raw_field_name"] = raw_field_name; + (*variables)["field_number_name"] = + classname + "_FieldNumber_" + capitalized_name; + (*variables)["field_number"] = StrCat(descriptor->number()); + (*variables)["field_type"] = GetCapitalizedType(descriptor); + (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor); + std::vector<std::string> field_flags; + if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated"); + if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired"); + if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional"); + if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked"); + + // ObjC custom flags. + if (descriptor->has_default_value()) + field_flags.push_back("GPBFieldHasDefaultValue"); + if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom"); + if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { + field_flags.push_back("GPBFieldHasEnumDescriptor"); + } + // It will clear on a zero value if... + // - not repeated/map + // - doesn't have presence + bool clear_on_zero = + (!descriptor->is_repeated() && !descriptor->has_presence()); + if (clear_on_zero) { + field_flags.push_back("GPBFieldClearHasIvarOnZero"); + } + + (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); + + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); + + (*variables)["dataTypeSpecific_name"] = "clazz"; + (*variables)["dataTypeSpecific_value"] = "Nil"; + + (*variables)["storage_offset_value"] = + "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")"; + (*variables)["storage_offset_comment"] = ""; + + // Clear some common things so they can be set just when needed. + (*variables)["storage_attribute"] = ""; +} + +} // namespace + +FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options) { + FieldGenerator* result = NULL; + if (field->is_repeated()) { + switch (GetObjectiveCType(field)) { + case OBJECTIVECTYPE_MESSAGE: { + if (field->is_map()) { + result = new MapFieldGenerator(field, options); + } else { + result = new RepeatedMessageFieldGenerator(field, options); + } + break; + } + case OBJECTIVECTYPE_ENUM: + result = new RepeatedEnumFieldGenerator(field, options); + break; + default: + result = new RepeatedPrimitiveFieldGenerator(field, options); + break; + } + } else { + switch (GetObjectiveCType(field)) { + case OBJECTIVECTYPE_MESSAGE: { + result = new MessageFieldGenerator(field, options); + break; + } + case OBJECTIVECTYPE_ENUM: + result = new EnumFieldGenerator(field, options); + break; + default: + if (IsReferenceType(field)) { + result = new PrimitiveObjFieldGenerator(field, options); + } else { + result = new PrimitiveFieldGenerator(field, options); + } + break; + } + } + result->FinishInitialization(); + return result; +} + +FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetCommonFieldVariables(descriptor, &variables_); +} + +FieldGenerator::~FieldGenerator() {} + +void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const { + printer->Print( + variables_, + "$field_number_name$ = $field_number$,\n"); +} + +void FieldGenerator::GenerateCFunctionDeclarations( + io::Printer* printer) const { + // Nothing +} + +void FieldGenerator::GenerateCFunctionImplementations( + io::Printer* printer) const { + // Nothing +} + +void FieldGenerator::DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const { + // Nothing +} + +void FieldGenerator::DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const { + // Nothing +} + +void FieldGenerator::GenerateFieldDescription( + io::Printer* printer, bool include_default) const { + // Printed in the same order as the structure decl. + if (include_default) { + printer->Print( + variables_, + "{\n" + " .defaultValue.$default_name$ = $default$,\n" + " .core.name = \"$name$\",\n" + " .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n" + " .core.number = $field_number_name$,\n" + " .core.hasIndex = $has_index$,\n" + " .core.offset = $storage_offset_value$,$storage_offset_comment$\n" + " .core.flags = $fieldflags$,\n" + " .core.dataType = GPBDataType$field_type$,\n" + "},\n"); + } else { + printer->Print( + variables_, + "{\n" + " .name = \"$name$\",\n" + " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n" + " .number = $field_number_name$,\n" + " .hasIndex = $has_index$,\n" + " .offset = $storage_offset_value$,$storage_offset_comment$\n" + " .flags = $fieldflags$,\n" + " .dataType = GPBDataType$field_type$,\n" + "},\n"); + } +} + +void FieldGenerator::SetRuntimeHasBit(int has_index) { + variables_["has_index"] = StrCat(has_index); +} + +void FieldGenerator::SetNoHasBit(void) { + variables_["has_index"] = "GPBNoHasBit"; +} + +int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { + return 0; +} + +void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) { + // 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. + std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl; + std::cerr.flush(); + abort(); +} + +void FieldGenerator::SetOneofIndexBase(int index_base) { + const OneofDescriptor* oneof = descriptor_->real_containing_oneof(); + if (oneof != NULL) { + int index = oneof->index() + index_base; + // Flip the sign to mark it as a oneof. + variables_["has_index"] = StrCat(-index); + } +} + +bool FieldGenerator::WantsHasProperty(void) const { + return descriptor_->has_presence() && !descriptor_->real_containing_oneof(); +} + +void FieldGenerator::FinishInitialization(void) { + // If "property_type" wasn't set, make it "storage_type". + if ((variables_.find("property_type") == variables_.end()) && + (variables_.find("storage_type") != variables_.end())) { + variables_["property_type"] = variable("storage_type"); + } +} + +SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : FieldGenerator(descriptor, options) { + // Nothing +} + +SingleFieldGenerator::~SingleFieldGenerator() {} + +void SingleFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$storage_type$ $name$;\n"); +} + +void SingleFieldGenerator::GeneratePropertyDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$comments$"); + printer->Print( + variables_, + "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n" + "\n"); + if (WantsHasProperty()) { + printer->Print( + variables_, + "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n"); + } +} + +void SingleFieldGenerator::GeneratePropertyImplementation( + io::Printer* printer) const { + if (WantsHasProperty()) { + printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n"); + } else { + printer->Print(variables_, "@dynamic $name$;\n"); + } +} + +bool SingleFieldGenerator::RuntimeUsesHasBit(void) const { + if (descriptor_->real_containing_oneof()) { + // The oneof tracks what is set instead. + return false; + } + return true; +} + +ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : SingleFieldGenerator(descriptor, options) { + variables_["property_storage_attribute"] = "strong"; + if (IsRetainedName(variables_["name"])) { + variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; + } +} + +ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {} + +void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$storage_type$ *$name$;\n"); +} + +void ObjCObjFieldGenerator::GeneratePropertyDeclaration( + io::Printer* printer) const { + + // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that + // it uses pointers and deals with Objective C's rules around storage name + // conventions (init*, new*, etc.) + + printer->Print(variables_, "$comments$"); + printer->Print( + variables_, + "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"); + if (WantsHasProperty()) { + printer->Print( + variables_, + "/** Test to see if @c $name$ has been set. */\n" + "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\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 + printer->Print(variables_, + "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n"); + } + printer->Print("\n"); +} + +RepeatedFieldGenerator::RepeatedFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : ObjCObjFieldGenerator(descriptor, options) { + // Default to no comment and let the cases needing it fill it in. + variables_["array_comment"] = ""; +} + +RepeatedFieldGenerator::~RepeatedFieldGenerator() {} + +void RepeatedFieldGenerator::FinishInitialization(void) { + FieldGenerator::FinishInitialization(); + if (variables_.find("array_property_type") == variables_.end()) { + variables_["array_property_type"] = variable("array_storage_type"); + } +} + +void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + printer->Print(variables_, "$array_storage_type$ *$name$;\n"); +} + +void RepeatedFieldGenerator::GeneratePropertyImplementation( + io::Printer* printer) const { + printer->Print(variables_, "@dynamic $name$, $name$_Count;\n"); +} + +void RepeatedFieldGenerator::GeneratePropertyDeclaration( + io::Printer* printer) const { + + // 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, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n" + "/** The number of items in @c $name$ without causing the array to be created. */\n" + "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\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 + printer->Print(variables_, + "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n"); + } + printer->Print("\n"); +} + +bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const { + return false; // The array (or map/dict) having anything is what is used. +} + +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + field_generators_(descriptor->field_count()), + extension_generators_(descriptor->extension_count()) { + // Construct all the FieldGenerators. + for (int i = 0; i < descriptor->field_count(); i++) { + field_generators_[i].reset( + FieldGenerator::Make(descriptor->field(i), options)); + } + for (int i = 0; i < descriptor->extension_count(); i++) { + extension_generators_[i].reset( + FieldGenerator::Make(descriptor->extension(i), options)); + } +} + +FieldGeneratorMap::~FieldGeneratorMap() {} + +const FieldGenerator& FieldGeneratorMap::get( + const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; +} + +const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { + return *extension_generators_[index]; +} + +int FieldGeneratorMap::CalculateHasBits(void) { + int total_bits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (field_generators_[i]->RuntimeUsesHasBit()) { + field_generators_[i]->SetRuntimeHasBit(total_bits); + ++total_bits; + } else { + field_generators_[i]->SetNoHasBit(); + } + int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded(); + if (extra_bits) { + field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits); + total_bits += extra_bits; + } + } + return total_bits; +} + +void FieldGeneratorMap::SetOneofIndexBase(int index_base) { + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_[i]->SetOneofIndexBase(index_base); + } +} + +bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const { + for (int i = 0; i < descriptor_->field_count(); i++) { + if (HasNonZeroDefaultValue(descriptor_->field(i))) { + return true; + } + } + + return false; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h new file mode 100644 index 00000000..ee213ff4 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_field.h @@ -0,0 +1,194 @@ +// 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_COMPILER_OBJECTIVEC_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ + +#include <map> +#include <string> +#include <compiler/objectivec/objectivec_helpers.h> +#include <descriptor.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class FieldGenerator { + public: + static FieldGenerator* Make(const FieldDescriptor* field, + const Options& options); + + virtual ~FieldGenerator(); + + FieldGenerator(const FieldGenerator&) = delete; + FieldGenerator& operator=(const FieldGenerator&) = delete; + + // Exposed for subclasses to fill in. + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0; + virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0; + + // Called by GenerateFieldDescription, exposed for classes that need custom + // generation. + + // Exposed for subclasses to extend, base does nothing. + virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; + virtual void GenerateCFunctionImplementations(io::Printer* printer) const; + + // Exposed for subclasses, should always call it on the parent class also. + virtual void DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const; + virtual void DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const; + + // Used during generation, not intended to be extended by subclasses. + void GenerateFieldDescription( + io::Printer* printer, bool include_default) const; + void GenerateFieldNumberConstant(io::Printer* printer) const; + + // Exposed to get and set the has bits information. + virtual bool RuntimeUsesHasBit(void) const = 0; + void SetRuntimeHasBit(int has_index); + void SetNoHasBit(void); + virtual int ExtraRuntimeHasBitsNeeded(void) const; + virtual void SetExtraRuntimeHasBitsBase(int index_base); + void SetOneofIndexBase(int index_base); + + std::string variable(const char* key) const { + return variables_.find(key)->second; + } + + bool needs_textformat_name_support() const { + const std::string& field_flags = variable("fieldflags"); + return field_flags.find("GPBFieldTextFormatNameCustom") != + std::string::npos; + } + std::string generated_objc_name() const { return variable("name"); } + std::string raw_field_name() const { return variable("raw_field_name"); } + + protected: + FieldGenerator(const FieldDescriptor* descriptor, const Options& options); + + virtual void FinishInitialization(void); + bool WantsHasProperty(void) const; + + const FieldDescriptor* descriptor_; + std::map<std::string, std::string> variables_; +}; + +class SingleFieldGenerator : public FieldGenerator { + public: + virtual ~SingleFieldGenerator(); + + SingleFieldGenerator(const SingleFieldGenerator&) = delete; + SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete; + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const override; + + virtual void GeneratePropertyImplementation(io::Printer* printer) const override; + + virtual bool RuntimeUsesHasBit(void) const override; + + protected: + SingleFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); +}; + +// Subclass with common support for when the field ends up as an ObjC Object. +class ObjCObjFieldGenerator : public SingleFieldGenerator { + public: + virtual ~ObjCObjFieldGenerator(); + + ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete; + ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete; + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const override; + + protected: + ObjCObjFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); +}; + +class RepeatedFieldGenerator : public ObjCObjFieldGenerator { + public: + virtual ~RepeatedFieldGenerator(); + + RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete; + RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete; + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + virtual void GeneratePropertyDeclaration(io::Printer* printer) const override; + + virtual void GeneratePropertyImplementation(io::Printer* printer) const override; + + virtual bool RuntimeUsesHasBit(void) const override; + + protected: + RepeatedFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + virtual void FinishInitialization(void) override; +}; + +// Convenience class which constructs FieldGenerators for a Descriptor. +class FieldGeneratorMap { + public: + FieldGeneratorMap(const Descriptor* descriptor, const Options& options); + ~FieldGeneratorMap(); + + FieldGeneratorMap(const FieldGeneratorMap&) = delete; + FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete; + + const FieldGenerator& get(const FieldDescriptor* field) const; + const FieldGenerator& get_extension(int index) const; + + // Assigns the has bits and returns the number of bits needed. + int CalculateHasBits(void); + + void SetOneofIndexBase(int index_base); + + // Check if any field of this message has a non zero default. + bool DoesAnyFieldHaveNonZeroDefault(void) const; + + private: + const Descriptor* descriptor_; + std::vector<std::unique_ptr<FieldGenerator>> field_generators_; + std::vector<std::unique_ptr<FieldGenerator>> extension_generators_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc new file mode 100644 index 00000000..e98a8985 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.cc @@ -0,0 +1,610 @@ +// 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. + +#include <compiler/objectivec/objectivec_file.h> +#include <compiler/objectivec/objectivec_enum.h> +#include <compiler/objectivec/objectivec_extension.h> +#include <compiler/objectivec/objectivec_message.h> +#include <compiler/code_generator.h> +#include <io/printer.h> +#include <io/zero_copy_stream_impl.h> +#include <stubs/stl_util.h> +#include <stubs/strutil.h> +#include <algorithm> // std::find() +#include <iostream> +#include <sstream> + +// 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. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +// This is also found in GPBBootstrap.h, and needs to be kept in sync. +const int32_t GOOGLE_PROTOBUF_OBJC_VERSION = 30004; + +const char* kHeaderExtension = ".pbobjc.h"; + +// Checks if a message contains any enums definitions (on the message or +// a nested message under it). +bool MessageContainsEnums(const Descriptor* message) { + if (message->enum_type_count() > 0) { + return true; + } + for (int i = 0; i < message->nested_type_count(); i++) { + if (MessageContainsEnums(message->nested_type(i))) { + return true; + } + } + return false; +} + +// Checks if a message contains any extension definitions (on the message or +// a nested message under it). +bool MessageContainsExtensions(const Descriptor* message) { + if (message->extension_count() > 0) { + return true; + } + for (int i = 0; i < message->nested_type_count(); i++) { + if (MessageContainsExtensions(message->nested_type(i))) { + return true; + } + } + return false; +} + +// Checks if the file contains any enum definitions (at the root or +// nested under a message). +bool FileContainsEnums(const FileDescriptor* file) { + if (file->enum_type_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageContainsEnums(file->message_type(i))) { + return true; + } + } + return false; +} + +// Checks if the file contains any extensions definitions (at the root or +// nested under a message). +bool FileContainsExtensions(const FileDescriptor* file) { + if (file->extension_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageContainsExtensions(file->message_type(i))) { + return true; + } + } + return false; +} + +// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all +// deps as visited and prunes them from the needed files list. +void PruneFileAndDepsMarkingAsVisited( + const FileDescriptor* file, + std::vector<const FileDescriptor*>* files, + std::set<const FileDescriptor*>* files_visited) { + std::vector<const FileDescriptor*>::iterator iter = + std::find(files->begin(), files->end(), file); + if (iter != files->end()) { + files->erase(iter); + } + files_visited->insert(file); + for (int i = 0; i < file->dependency_count(); i++) { + PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited); + } +} + +// Helper for CollectMinimalFileDepsContainingExtensions. +void CollectMinimalFileDepsContainingExtensionsWorker( + const FileDescriptor* file, + std::vector<const FileDescriptor*>* files, + std::set<const FileDescriptor*>* files_visited) { + if (files_visited->find(file) != files_visited->end()) { + return; + } + files_visited->insert(file); + + if (FileContainsExtensions(file)) { + files->push_back(file); + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + PruneFileAndDepsMarkingAsVisited(dep, files, files_visited); + } + } else { + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + CollectMinimalFileDepsContainingExtensionsWorker(dep, files, + files_visited); + } + } +} + +// Collect the deps of the given file that contain extensions. This can be used to +// create the chain of roots that need to be wired together. +// +// NOTE: If any changes are made to this and the supporting functions, you will +// need to manually validate what the generated code is for the test files: +// objectivec/Tests/unittest_extension_chain_*.proto +// There are comments about what the expected code should be line and limited +// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports +// specifically). +void CollectMinimalFileDepsContainingExtensions( + const FileDescriptor* file, + std::vector<const FileDescriptor*>* files) { + std::set<const FileDescriptor*> files_visited; + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + CollectMinimalFileDepsContainingExtensionsWorker(dep, files, + &files_visited); + } +} + +bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { + for (int i = 0; i < file->dependency_count(); i++) { + if (dep == file->dependency(i)) { + return true; + } + } + return false; +} + +} // namespace + +FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) + : file_(file), + root_class_name_(FileClassName(file)), + is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)), + options_(options) { + for (int i = 0; i < file_->enum_type_count(); i++) { + EnumGenerator* generator = new EnumGenerator(file_->enum_type(i)); + enum_generators_.emplace_back(generator); + } + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator* generator = + new MessageGenerator(root_class_name_, file_->message_type(i), options_); + message_generators_.emplace_back(generator); + } + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator* generator = + new ExtensionGenerator(root_class_name_, file_->extension(i)); + extension_generators_.emplace_back(generator); + } +} + +FileGenerator::~FileGenerator() {} + +void FileGenerator::GenerateHeader(io::Printer* printer) { + std::vector<std::string> headers; + // Generated files bundled with the library get minimal imports, everything + // else gets the wrapper so everything is usable. + if (is_bundled_proto_) { + headers.push_back("GPBDescriptor.h"); + headers.push_back("GPBMessage.h"); + headers.push_back("GPBRootObject.h"); + } else { + headers.push_back("GPBProtocolBuffers.h"); + } + PrintFileRuntimePreamble(printer, headers); + + // Add some verification that the generated code matches the source the + // code is being compiled with. + // NOTE: This captures the raw numeric values at the time the generator was + // compiled, since that will be the versions for the ObjC runtime at that + // time. The constants in the generated code will then get their values at + // at compile time (so checking against the headers being used to compile). + printer->Print( + "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n" + "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n" + "#endif\n" + "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n" + "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n" + "#endif\n" + "\n", + "google_protobuf_objc_version", StrCat(GOOGLE_PROTOBUF_OBJC_VERSION)); + + // #import any headers for "public imports" in the proto file. + { + ImportWriter import_writer( + options_.generate_for_named_framework, + options_.named_framework_to_proto_path_mappings_path, + options_.runtime_import_prefix, + is_bundled_proto_); + const std::string header_extension(kHeaderExtension); + for (int i = 0; i < file_->public_dependency_count(); i++) { + import_writer.AddFile(file_->public_dependency(i), header_extension); + } + import_writer.Print(printer); + } + + // Note: + // deprecated-declarations suppression is only needed if some place in this + // proto file is something deprecated or if it references something from + // another file that is deprecated. + printer->Print( + "// @@protoc_insertion_point(imports)\n" + "\n" + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n" + "\n" + "CF_EXTERN_C_BEGIN\n" + "\n"); + + std::set<std::string> fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineForwardDeclarations(&fwd_decls); + } + for (std::set<std::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"); + } + + printer->Print( + "NS_ASSUME_NONNULL_BEGIN\n" + "\n"); + + // need to write out all enums first + for (const auto& generator : enum_generators_) { + generator->GenerateHeader(printer); + } + + for (const auto& generator : message_generators_) { + generator->GenerateEnumHeader(printer); + } + + // For extensions to chain together, the Root gets created even if there + // are no extensions. + printer->Print( + "#pragma mark - $root_class_name$\n" + "\n" + "/**\n" + " * Exposes the extension registry for this file.\n" + " *\n" + " * The base class provides:\n" + " * @code\n" + " * + (GPBExtensionRegistry *)extensionRegistry;\n" + " * @endcode\n" + " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" + " * this file and all files that it depends on.\n" + " **/\n" + "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n" + "@end\n" + "\n", + "root_class_name", root_class_name_); + + if (!extension_generators_.empty()) { + // The dynamic methods block is only needed if there are extensions. + printer->Print( + "@interface $root_class_name$ (DynamicMethods)\n", + "root_class_name", root_class_name_); + + for (const auto& generator : extension_generators_) { + generator->GenerateMembersHeader(printer); + } + + printer->Print("@end\n\n"); + } // !extension_generators_.empty() + + for (const auto& generator : message_generators_) { + generator->GenerateMessageHeader(printer); + } + + printer->Print( + "NS_ASSUME_NONNULL_END\n" + "\n" + "CF_EXTERN_C_END\n" + "\n" + "#pragma clang diagnostic pop\n" + "\n" + "// @@protoc_insertion_point(global_scope)\n"); +} + +void FileGenerator::GenerateSource(io::Printer* printer) { + // #import the runtime support. + std::vector<std::string> headers; + headers.push_back("GPBProtocolBuffers_RuntimeSupport.h"); + PrintFileRuntimePreamble(printer, headers); + + // Enums use atomic in the generated code, so add the system import as needed. + if (FileContainsEnums(file_)) { + printer->Print( + "#import <stdatomic.h>\n" + "\n"); + } + + std::vector<const FileDescriptor*> deps_with_extensions; + CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions); + + { + ImportWriter import_writer( + options_.generate_for_named_framework, + options_.named_framework_to_proto_path_mappings_path, + options_.runtime_import_prefix, + is_bundled_proto_); + const std::string header_extension(kHeaderExtension); + + // #import the header for this proto file. + import_writer.AddFile(file_, header_extension); + + // #import the headers for anything that a plain dependency of this proto + // file (that means they were just an include, not a "public" include). + std::set<std::string> public_import_names; + for (int i = 0; i < file_->public_dependency_count(); i++) { + public_import_names.insert(file_->public_dependency(i)->name()); + } + for (int i = 0; i < file_->dependency_count(); i++) { + const FileDescriptor *dep = file_->dependency(i); + bool public_import = (public_import_names.count(dep->name()) != 0); + if (!public_import) { + import_writer.AddFile(dep, header_extension); + } + } + + // If any indirect dependency provided extensions, it needs to be directly + // imported so it can get merged into the root's extensions registry. + // See the Note by CollectMinimalFileDepsContainingExtensions before + // changing this. + for (std::vector<const FileDescriptor*>::iterator iter = + deps_with_extensions.begin(); + iter != deps_with_extensions.end(); ++iter) { + if (!IsDirectDependency(*iter, file_)) { + import_writer.AddFile(*iter, header_extension); + } + } + + import_writer.Print(printer); + } + + bool includes_oneof = false; + for (const auto& generator : message_generators_) { + if (generator->IncludesOneOfDefinition()) { + includes_oneof = true; + break; + } + } + + std::set<std::string> fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + + // Note: + // deprecated-declarations suppression is only needed if some place in this + // proto file is something deprecated or if it references something from + // another file that is deprecated. + // dollar-in-identifier-extension is needed because we use references to + // objc class names that have $ in identifiers. + printer->Print( + "// @@protoc_insertion_point(imports)\n" + "\n" + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); + if (includes_oneof) { + // The generated code for oneof's uses direct ivar access, suppress the + // warning in case developer turn that on in the context they compile the + // generated code. + printer->Print( + "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); + } + if (!fwd_decls.empty()) { + printer->Print( + "#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n"); + } + printer->Print( + "\n"); + if (!fwd_decls.empty()) { + printer->Print( + "#pragma mark - Objective C Class declarations\n" + "// Forward declarations of Objective C classes that we can use as\n" + "// static values in struct initializers.\n" + "// We don't use [Foo class] because it is not a static value.\n"); + } + for (const auto& i : fwd_decls) { + printer->Print("$value$\n", "value", i); + } + if (!fwd_decls.empty()) { + printer->Print("\n"); + } + printer->Print( + "#pragma mark - $root_class_name$\n" + "\n" + "@implementation $root_class_name$\n\n", + "root_class_name", root_class_name_); + + const bool file_contains_extensions = FileContainsExtensions(file_); + + // If there were any extensions or this file has any dependencies, output + // a registry to override to create the file specific registry. + if (file_contains_extensions || !deps_with_extensions.empty()) { + 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" + " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n" + " registry = [[GPBExtensionRegistry alloc] init];\n"); + + printer->Indent(); + printer->Indent(); + + if (file_contains_extensions) { + printer->Print( + "static GPBExtensionDescription descriptions[] = {\n"); + printer->Indent(); + for (const auto& generator : extension_generators_) { + generator->GenerateStaticVariablesInitialization(printer); + } + for (const auto& generator : message_generators_) { + generator->GenerateStaticVariablesInitialization(printer); + } + 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" + " usesClassRefs:YES];\n" + " [registry addExtension:extension];\n" + " [self globallyRegisterExtension:extension];\n" + " [extension release];\n" + "}\n"); + } + + if (deps_with_extensions.empty()) { + printer->Print( + "// None of the imports (direct or indirect) defined extensions, so no need to add\n" + "// them to this registry.\n"); + } else { + printer->Print( + "// Merge in the imports (direct or indirect) that defined extensions.\n"); + for (std::vector<const FileDescriptor*>::iterator iter = + deps_with_extensions.begin(); + iter != deps_with_extensions.end(); ++iter) { + const std::string root_class_name(FileClassName((*iter))); + printer->Print( + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", root_class_name); + } + } + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " return registry;\n" + "}\n"); + } else { + if (file_->dependency_count() > 0) { + printer->Print( + "// No extensions in the file and none of the imports (direct or indirect)\n" + "// defined extensions, so no need to generate +extensionRegistry.\n"); + } else { + printer->Print( + "// No extensions in the file and no imports, so no need to generate\n" + "// +extensionRegistry.\n"); + } + } + + printer->Print("\n@end\n\n"); + + // File descriptor only needed if there are messages to use it. + if (!message_generators_.empty()) { + std::map<std::string, std::string> vars; + vars["root_class_name"] = root_class_name_; + vars["package"] = file_->package(); + vars["objc_prefix"] = FileClassPrefix(file_); + switch (file_->syntax()) { + case FileDescriptor::SYNTAX_UNKNOWN: + vars["syntax"] = "GPBFileSyntaxUnknown"; + break; + case FileDescriptor::SYNTAX_PROTO2: + vars["syntax"] = "GPBFileSyntaxProto2"; + break; + case FileDescriptor::SYNTAX_PROTO3: + vars["syntax"] = "GPBFileSyntaxProto3"; + break; + } + printer->Print(vars, + "#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" + " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"); + if (!vars["objc_prefix"].empty()) { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " objcPrefix:@\"$objc_prefix$\"\n" + " syntax:$syntax$];\n"); + } else { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n"); + } + printer->Print( + " }\n" + " return descriptor;\n" + "}\n" + "\n"); + } + + for (const auto& generator : enum_generators_) { + generator->GenerateSource(printer); + } + for (const auto& generator : message_generators_) { + generator->GenerateSource(printer); + } + + printer->Print( + "\n" + "#pragma clang diagnostic pop\n" + "\n" + "// @@protoc_insertion_point(global_scope)\n"); +} + +// Helper to print the import of the runtime support at the top of generated +// files. This currently only supports the runtime coming from a framework +// as defined by the official CocoaPod. +void FileGenerator::PrintFileRuntimePreamble( + io::Printer* printer, + const std::vector<std::string>& headers_to_import) const { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + ImportWriter::PrintRuntimeImports( + printer, headers_to_import, options_.runtime_import_prefix, true); + printer->Print("\n"); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h new file mode 100644 index 00000000..61572802 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_file.h @@ -0,0 +1,82 @@ +// 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_COMPILER_OBJECTIVEC_FILE_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ + +#include <string> +#include <set> +#include <vector> +#include <compiler/objectivec/objectivec_helpers.h> +#include <descriptor.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class EnumGenerator; +class ExtensionGenerator; +class MessageGenerator; + +class FileGenerator { + public: + FileGenerator(const FileDescriptor* file, const Options& options); + ~FileGenerator(); + + FileGenerator(const FileGenerator&) = delete; + FileGenerator& operator=(const FileGenerator&) = delete; + + void GenerateSource(io::Printer* printer); + void GenerateHeader(io::Printer* printer); + + private: + const FileDescriptor* file_; + std::string root_class_name_; + bool is_bundled_proto_; + + std::vector<std::unique_ptr<EnumGenerator>> enum_generators_; + std::vector<std::unique_ptr<MessageGenerator>> message_generators_; + std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; + + const Options options_; + + void PrintFileRuntimePreamble( + io::Printer* printer, + const std::vector<std::string>& headers_to_import) const; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc new file mode 100644 index 00000000..3dbd1d43 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.cc @@ -0,0 +1,276 @@ +// 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. + +#include <fstream> +#include <iostream> +#include <string> +#include <unordered_set> +#include <compiler/objectivec/objectivec_generator.h> +#include <compiler/objectivec/objectivec_file.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/printer.h> +#include <io/zero_copy_stream.h> +#include <stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +// Convert a string with "yes"/"no" (case insensitive) to a boolean, returning +// true/false for if the input string was a valid value. If the input string is +// invalid, `result` is unchanged. +bool StringToBool(const std::string& value, bool* result) { + std::string upper_value(value); + UpperString(&upper_value); + if (upper_value == "NO") { + *result = false; + return true; + } + if (upper_value == "YES") { + *result = true; + return true; + } + + return false; +} + +} // namespace + +ObjectiveCGenerator::ObjectiveCGenerator() {} + +ObjectiveCGenerator::~ObjectiveCGenerator() {} + +bool ObjectiveCGenerator::HasGenerateAll() const { + return true; +} + +bool ObjectiveCGenerator::Generate(const FileDescriptor* file, + const std::string& parameter, + GeneratorContext* context, + std::string* error) const { + *error = "Unimplemented Generate() method. Call GenerateAll() instead."; + return false; +} + +bool ObjectiveCGenerator::GenerateAll( + const std::vector<const FileDescriptor*>& files, + const std::string& parameter, GeneratorContext* context, + std::string* error) const { + // ----------------------------------------------------------------- + // Parse generator options. These options are passed to the compiler using the + // --objc_opt flag. The options are passed as a comma separated list of + // options along with their values. If the option appears multiple times, only + // the last value will be considered. + // + // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework + + Options generation_options; + + std::vector<std::pair<std::string, std::string> > options; + ParseGeneratorParameter(parameter, &options); + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "expected_prefixes_path") { + // Path to find a file containing the expected prefixes + // (objc_class_prefix "PREFIX") for proto packages (package NAME). The + // generator will then issue warnings/errors if in the proto files being + // generated the option is not listed/wrong/etc in the file. + // + // The format of the file is: + // - An entry is a line of "package=prefix". + // - Comments start with "#". + // - A comment can go on a line after a expected package/prefix pair. + // (i.e. - "package=prefix # comment") + // + // There is no validation that the prefixes are good prefixes, it is + // assumed that they are when you create the file. + generation_options.expected_prefixes_path = options[i].second; + } else if (options[i].first == "expected_prefixes_suppressions") { + // A semicolon delimited string that lists the paths of .proto files to + // exclude from the package prefix validations (expected_prefixes_path). + // This is provided as an "out", to skip some files being checked. + for (StringPiece split_piece : Split( + options[i].second, ";", true)) { + generation_options.expected_prefixes_suppressions.push_back( + std::string(split_piece)); + } + } else if (options[i].first == "prefixes_must_be_registered") { + // If objc prefix file option value must be registered to be used. This + // option has no meaning if an "expected_prefixes_path" isn't set. The + // available options are: + // "no": They don't have to be registered. + // "yes": They must be registered and an error will be raised if a files + // tried to use a prefix that isn't registered. + // Default is "no". + if (!StringToBool(options[i].second, + &generation_options.prefixes_must_be_registered)) { + *error = "error: Unknown value for prefixes_must_be_registered: " + options[i].second; + return false; + } + } else if (options[i].first == "require_prefixes") { + // If every file must have an objc prefix file option to be used. The + // available options are: + // "no": Files can be generated without the prefix option. + // "yes": Files must have the objc prefix option, and an error will be + // raised if a files doesn't have one. + // Default is "no". + if (!StringToBool(options[i].second, + &generation_options.require_prefixes)) { + *error = "error: Unknown value for require_prefixes: " + options[i].second; + return false; + } + } else if (options[i].first == "generate_for_named_framework") { + // The name of the framework that protos are being generated for. This + // will cause the #import statements to be framework based using this + // name (i.e. - "#import <NAME/proto.pbobjc.h>). + // + // NOTE: If this option is used with + // named_framework_to_proto_path_mappings_path, then this is effectively + // the "default" framework name used for everything that wasn't mapped by + // the mapping file. + generation_options.generate_for_named_framework = options[i].second; + } else if (options[i].first == "named_framework_to_proto_path_mappings_path") { + // Path to find a file containing the list of framework names and proto + // files. The generator uses this to decide if a proto file + // referenced should use a framework style import vs. a user level import + // (#import <FRAMEWORK/file.pbobjc.h> vs #import "dir/file.pbobjc.h"). + // + // The format of the file is: + // - An entry is a line of "frameworkName: file.proto, dir/file2.proto". + // - Comments start with "#". + // - A comment can go on a line after a expected package/prefix pair. + // (i.e. - "frameworkName: file.proto # comment") + // + // Any number of files can be listed for a framework, just separate them + // with commas. + // + // There can be multiple lines listing the same frameworkName in case it + // has a lot of proto files included in it; having multiple lines makes + // things easier to read. If a proto file is not configured in the + // mappings file, it will use the default framework name if one was passed + // with generate_for_named_framework, or the relative path to it's include + // path otherwise. + generation_options.named_framework_to_proto_path_mappings_path = options[i].second; + } else if (options[i].first == "runtime_import_prefix") { + // Path to use as a prefix on #imports of runtime provided headers in the + // generated files. When integrating ObjC protos into a build system, + // this can be used to avoid having to add the runtime directory to the + // header search path since the generate #import will be more complete. + generation_options.runtime_import_prefix = + StripSuffixString(options[i].second, "/"); + } else if (options[i].first == "use_package_as_prefix") { + // Controls how the symbols should be prefixed to avoid symbols + // collisions. The objc_class_prefix file option is always honored, this + // is just what to do if that isn't set. The available options are: + // "no": Not prefixed (the existing mode). + // "yes": Make a prefix out of the proto package. + bool value = false; + if (StringToBool(options[i].second, &value)) { + SetUseProtoPackageAsDefaultPrefix(value); + } else { + *error = "error: Unknown use_package_as_prefix: " + options[i].second; + return false; + } + } else if (options[i].first == "proto_package_prefix_exceptions_path") { + // Path to find a file containing the list of proto package names that are + // exceptions when use_package_as_prefix is enabled. This can be used to + // migrate packages one at a time to use_package_as_prefix since there + // are likely code updates needed with each one. + // + // The format of the file is: + // - An entry is a line of "proto.package.name". + // - Comments start with "#". + // - A comment can go on a line after a expected package/prefix pair. + // (i.e. - "some.proto.package # comment") + SetProtoPackagePrefixExceptionList(options[i].second); + } else { + *error = "error: Unknown generator option: " + options[i].first; + return false; + } + } + + // ----------------------------------------------------------------- + + // These are not official generation options and could be removed/changed in + // the future and doing that won't count as a breaking change. + bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != NULL; + std::unordered_set<std::string> skip_impls; + if (getenv("GPB_OBJC_SKIP_IMPLS_FILE") != NULL) { + std::ifstream skip_file(getenv("GPB_OBJC_SKIP_IMPLS_FILE")); + if (skip_file.is_open()) { + std::string line; + while (std::getline(skip_file, line)) { + skip_impls.insert(line); + } + } else { + *error = "error: Failed to open GPB_OBJC_SKIP_IMPLS_FILE file"; + return false; + } + } + + // ----------------------------------------------------------------- + + // Validate the objc prefix/package pairings. + if (!ValidateObjCClassPrefixes(files, generation_options, error)) { + // *error will have been filled in. + return false; + } + + for (int i = 0; i < files.size(); i++) { + const FileDescriptor* file = files[i]; + FileGenerator file_generator(file, generation_options); + std::string filepath = FilePath(file); + + // Generate header. + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + context->Open(filepath + ".pbobjc.h")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateHeader(&printer); + } + + // Generate m file. + if (!headers_only && skip_impls.count(file->name()) == 0) { + std::unique_ptr<io::ZeroCopyOutputStream> output( + context->Open(filepath + ".pbobjc.m")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateSource(&printer); + } + } + + return true; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h new file mode 100644 index 00000000..c7cfe8d3 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_generator.h @@ -0,0 +1,79 @@ +// 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. + +// Generates ObjectiveC code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ + +#include <string> +#include <compiler/code_generator.h> +#include <descriptor.h> + +#include <port_def.inc> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// CodeGenerator implementation which generates a ObjectiveC source file and +// header. If you create your own protocol compiler binary and you want it to +// support ObjectiveC output, you can do so by registering an instance of this +// CodeGenerator with the CommandLineInterface in your main() function. +class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { + public: + ObjectiveCGenerator(); + ~ObjectiveCGenerator(); + + ObjectiveCGenerator(const ObjectiveCGenerator&) = delete; + ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete; + + // implements CodeGenerator ---------------------------------------- + bool HasGenerateAll() const override; + bool Generate(const FileDescriptor* file, const std::string& parameter, + GeneratorContext* context, std::string* error) const override; + bool GenerateAll(const std::vector<const FileDescriptor*>& files, + const std::string& parameter, GeneratorContext* context, + std::string* error) const override; + + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include <port_undef.inc> + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc new file mode 100644 index 00000000..014edb9e --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -0,0 +1,1960 @@ +// 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 _MSC_VER +#include <unistd.h> +#endif +#include <climits> +#include <errno.h> +#include <fcntl.h> +#include <fstream> +#include <iostream> +#include <sstream> +#include <stdlib.h> +#include <unordered_set> +#include <vector> + +#include <compiler/code_generator.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <compiler/objectivec/objectivec_nsobject_methods.h> +#include <descriptor.pb.h> +#include <io/coded_stream.h> +#include <io/printer.h> +#include <io/zero_copy_stream_impl.h> +#include <io/io_win32.h> +#include <port.h> +#include <stubs/common.h> +#include <stubs/strutil.h> + +// 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. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// <io.h> is transitively included in this file. Import the functions explicitly +// in this port namespace to avoid ambiguous definition. +namespace posix { +#ifdef _WIN32 +using ::google::protobuf::io::win32::open; +#else +using ::open; +#endif +} // namespace port + +namespace { + +class SimpleLineCollector : public LineConsumer { + public: + SimpleLineCollector(std::unordered_set<std::string>* inout_set) + : set_(inout_set) {} + + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override { + set_->insert(std::string(line)); + return true; + } + + private: + std::unordered_set<std::string>* set_; +}; + +class PrefixModeStorage { + public: + PrefixModeStorage(); + + bool use_package_name() const { return use_package_name_; } + void set_use_package_name(bool on_or_off) { use_package_name_ = on_or_off; } + + const std::string exception_path() const { return exception_path_; } + void set_exception_path(const std::string& path) { + exception_path_ = path; + exceptions_.clear(); + } + + bool is_package_exempted(const std::string& package); + + private: + bool use_package_name_; + std::string exception_path_; + std::unordered_set<std::string> exceptions_; +}; + +PrefixModeStorage::PrefixModeStorage() { + // Even thought there are generation options, have an env back door since some + // of these helpers could be used in other plugins. + + const char* use_package_cstr = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX"); + use_package_name_ = + (use_package_cstr && (std::string("YES") == ToUpper(use_package_cstr))); + + const char* exception_path = getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH"); + if (exception_path) { + exception_path_ = exception_path; + } +} + +bool PrefixModeStorage::is_package_exempted(const std::string& package) { + if (exceptions_.empty() && !exception_path_.empty()) { + std::string error_str; + SimpleLineCollector collector(&exceptions_); + if (!ParseSimpleFile(exception_path_, &collector, &error_str)) { + if (error_str.empty()) { + error_str = std::string("protoc:0: warning: Failed to parse") + + std::string(" package prefix exceptions file: ") + + exception_path_; + } + std::cerr << error_str << std::endl; + std::cerr.flush(); + exceptions_.clear(); + } + + // If the file was empty put something in it so it doesn't get reloaded over + // and over. + if (exceptions_.empty()) { + exceptions_.insert("<not a real package>"); + } + } + + return exceptions_.count(package) != 0; +} + +PrefixModeStorage g_prefix_mode; + +} // namespace + +bool UseProtoPackageAsDefaultPrefix() { + return g_prefix_mode.use_package_name(); +} + +void SetUseProtoPackageAsDefaultPrefix(bool on_or_off) { + g_prefix_mode.set_use_package_name(on_or_off); +} + +std::string GetProtoPackagePrefixExceptionList() { + return g_prefix_mode.exception_path(); +} + +void SetProtoPackagePrefixExceptionList(const std::string& file_path) { + g_prefix_mode.set_exception_path(file_path); +} + +Options::Options() { + // Default is the value of the env for the package prefixes. + const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); + if (file_path) { + expected_prefixes_path = file_path; + } + const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS"); + if (suppressions) { + expected_prefixes_suppressions = + Split(suppressions, ";", true); + } + prefixes_must_be_registered = false; + require_prefixes = false; +} + +namespace { + +std::unordered_set<std::string> MakeWordsMap(const char* const words[], + size_t num_words) { + std::unordered_set<std::string> result; + for (int i = 0; i < num_words; i++) { + result.insert(words[i]); + } + return result; +} + +const char* const kUpperSegmentsList[] = {"url", "http", "https"}; + +std::unordered_set<std::string> kUpperSegments = + MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList)); + +bool ascii_isnewline(char c) { + return c == '\n' || c == '\r'; +} + +// Internal helper for name handing. +// Do not expose this outside of helpers, stick to having functions for specific +// cases (ClassName(), FieldName()), so there is always consistent suffix rules. +std::string UnderscoresToCamelCase(const std::string& input, + bool first_capitalized) { + std::vector<std::string> values; + std::string current; + + bool last_char_was_number = false; + bool last_char_was_lower = false; + bool last_char_was_upper = false; + for (int i = 0; i < input.size(); i++) { + char c = input[i]; + if (ascii_isdigit(c)) { + if (!last_char_was_number) { + values.push_back(current); + current = ""; + } + current += c; + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_number = true; + } else if (ascii_islower(c)) { + // lowercase letter can follow a lowercase or uppercase letter + if (!last_char_was_lower && !last_char_was_upper) { + values.push_back(current); + current = ""; + } + current += c; // already lower + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_lower = true; + } else if (ascii_isupper(c)) { + if (!last_char_was_upper) { + values.push_back(current); + current = ""; + } + current += ascii_tolower(c); + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_upper = true; + } else { + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + } + } + values.push_back(current); + + std::string result; + bool first_segment_forces_upper = false; + for (std::vector<std::string>::iterator i = values.begin(); i != values.end(); + ++i) { + std::string value = *i; + bool all_upper = (kUpperSegments.count(value) > 0); + if (all_upper && (result.length() == 0)) { + first_segment_forces_upper = true; + } + for (int j = 0; j < value.length(); j++) { + if (j == 0 || all_upper) { + value[j] = ascii_toupper(value[j]); + } else { + // Nothing, already in lower. + } + } + result += value; + } + if ((result.length() != 0) && + !first_capitalized && + !first_segment_forces_upper) { + result[0] = ascii_tolower(result[0]); + } + return result; +} + +const char* const kReservedWordList[] = { + // Note NSObject Methods: + // These are brought in from objectivec_nsobject_methods.h that is generated + // using method_dump.sh. See kNSObjectMethods below. + + // Objective C "keywords" that aren't in C + // From + // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c + // with some others added on. + "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway", + "self", "instancetype", "nullable", "nonnull", "nil", "Nil", + "YES", "NO", "weak", + + // C/C++ keywords (Incl C++ 0x11) + // From http://en.cppreference.com/w/cpp/keywords + "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor", + "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", + "compl", "const", "constexpr", "const_cast", "continue", "decltype", + "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit", + "export", "extern ", "false", "float", "for", "friend", "goto", "if", + "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", + "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", + "public", "register", "reinterpret_cast", "return", "short", "signed", + "sizeof", "static", "static_assert", "static_cast", "struct", "switch", + "template", "this", "thread_local", "throw", "true", "try", "typedef", + "typeid", "typename", "union", "unsigned", "using", "virtual", "void", + "volatile", "wchar_t", "while", "xor", "xor_eq", + + // C99 keywords + // From + // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm + "restrict", + + // GCC/Clang extension + "typeof", + + // Not a keyword, but will break you + "NULL", + + // C88+ specs call for these to be macros, so depending on what they are + // defined to be it can lead to odd errors for some Xcode/SDK versions. + "stdin", "stdout", "stderr", + + // Objective-C Runtime typedefs + // From <obc/runtime.h> + "Category", "Ivar", "Method", "Protocol", + + // GPBMessage Methods + // Only need to add instance methods that may conflict with + // method declared in protos. The main cases are methods + // that take no arguments, or setFoo:/hasFoo: type methods. + "clear", "data", "delimitedData", "descriptor", "extensionRegistry", + "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize", + "sortedExtensionsInUse", "unknownFields", + + // MacTypes.h names + "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount", + "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount", + "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType", + "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style", + "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord", +}; + +// returns true is input starts with __ or _[A-Z] which are reserved identifiers +// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here +// but this verifies and allows for future expansion if we decide to redefine what a +// reserved C identifier is (for example the GNU list +// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html ) +bool IsReservedCIdentifier(const std::string& input) { + if (input.length() > 2) { + if (input.at(0) == '_') { + if (isupper(input.at(1)) || input.at(1) == '_') { + return true; + } + } + } + return false; +} + +std::string SanitizeNameForObjC(const std::string& prefix, + const std::string& input, + const std::string& extension, + std::string* out_suffix_added) { + static const std::unordered_set<std::string> kReservedWords = + MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); + static const std::unordered_set<std::string> kNSObjectMethods = + MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList)); + std::string sanitized; + // We add the prefix in the cases where the string is missing a prefix. + // We define "missing a prefix" as where 'input': + // a) Doesn't start with the prefix or + // b) Isn't equivalent to the prefix or + // c) Has the prefix, but the letter after the prefix is lowercase + if (HasPrefixString(input, prefix)) { + if (input.length() == prefix.length() || !ascii_isupper(input[prefix.length()])) { + sanitized = prefix + input; + } else { + sanitized = input; + } + } else { + sanitized = prefix + input; + } + if (IsReservedCIdentifier(sanitized) || + (kReservedWords.count(sanitized) > 0) || + (kNSObjectMethods.count(sanitized) > 0)) { + if (out_suffix_added) *out_suffix_added = extension; + return sanitized + extension; + } + if (out_suffix_added) out_suffix_added->clear(); + return sanitized; +} + +std::string NameFromFieldDescriptor(const FieldDescriptor* field) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + return field->message_type()->name(); + } else { + return field->name(); + } +} + +void PathSplit(const std::string& path, std::string* directory, + std::string* basename) { + std::string::size_type last_slash = path.rfind('/'); + if (last_slash == std::string::npos) { + if (directory) { + *directory = ""; + } + if (basename) { + *basename = path; + } + } else { + if (directory) { + *directory = path.substr(0, last_slash); + } + if (basename) { + *basename = path.substr(last_slash + 1); + } + } +} + +bool IsSpecialName(const std::string& name, const std::string* special_names, + size_t count) { + for (size_t i = 0; i < count; ++i) { + size_t length = special_names[i].length(); + if (name.compare(0, length, special_names[i]) == 0) { + if (name.length() > length) { + // If name is longer than the retained_name[i] that it matches + // the next character must be not lower case (newton vs newTon vs + // new_ton). + return !ascii_islower(name[length]); + } else { + return true; + } + } + } + return false; +} + +std::string GetZeroEnumNameForFlagType(const FlagType flag_type) { + switch(flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlag_None"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionNone"; + case FLAGTYPE_FIELD: + return "GPBFieldNone"; + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + return "0"; + } +} + +std::string GetEnumNameForFlagType(const FlagType flag_type) { + switch(flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlags"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionOptions"; + case FLAGTYPE_FIELD: + return "GPBFieldFlags"; + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + return std::string(); + } +} + +void MaybeUnQuote(StringPiece* input) { + if ((input->length() >= 2) && + ((*input->data() == '\'' || *input->data() == '"')) && + ((*input)[input->length() - 1] == *input->data())) { + input->remove_prefix(1); + input->remove_suffix(1); + } +} + +} // namespace + +// Escape C++ trigraphs by escaping question marks to \? +std::string EscapeTrigraphs(const std::string& to_escape) { + return StringReplace(to_escape, "?", "\\?", true); +} + +void TrimWhitespace(StringPiece* input) { + while (!input->empty() && ascii_isspace(*input->data())) { + input->remove_prefix(1); + } + while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) { + input->remove_suffix(1); + } +} + +bool IsRetainedName(const std::string& name) { + // List of prefixes from + // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html + static const std::string retained_names[] = {"new", "alloc", "copy", + "mutableCopy"}; + return IsSpecialName(name, retained_names, + sizeof(retained_names) / sizeof(retained_names[0])); +} + +bool IsInitName(const std::string& name) { + static const std::string init_names[] = {"init"}; + return IsSpecialName(name, init_names, + sizeof(init_names) / sizeof(init_names[0])); +} + +std::string BaseFileName(const FileDescriptor* file) { + std::string basename; + PathSplit(file->name(), NULL, &basename); + return basename; +} + +std::string FileClassPrefix(const FileDescriptor* file) { + // Always honor the file option. + if (file->options().has_objc_class_prefix()) { + return file->options().objc_class_prefix(); + } + + // If package prefix isn't enabled or no package, done. + if (!g_prefix_mode.use_package_name() || file->package().empty()) { + return ""; + } + + // If the package is in the exceptions list, done. + if (g_prefix_mode.is_package_exempted(file->package())) { + return ""; + } + + // Transform the package into a prefix: use the dot segments as part, + // camelcase each one and then join them with underscores, and add an + // underscore at the end. + std::string result; + const std::vector<std::string> segments = Split(file->package(), ".", true); + for (const auto& segment : segments) { + const std::string part = UnderscoresToCamelCase(segment, true); + if (part.empty()) { + continue; + } + if (!result.empty()) { + result.append("_"); + } + result.append(part); + } + if (!result.empty()) { + result.append("_"); + } + return result; +} + +std::string FilePath(const FileDescriptor* file) { + std::string output; + std::string basename; + std::string directory; + PathSplit(file->name(), &directory, &basename); + if (directory.length() > 0) { + output = directory + "/"; + } + basename = StripProto(basename); + + // CamelCase to be more ObjC friendly. + basename = UnderscoresToCamelCase(basename, true); + + output += basename; + return output; +} + +std::string FilePathBasename(const FileDescriptor* file) { + std::string output; + std::string basename; + std::string directory; + PathSplit(file->name(), &directory, &basename); + basename = StripProto(basename); + + // CamelCase to be more ObjC friendly. + output = UnderscoresToCamelCase(basename, true); + + return output; +} + +std::string FileClassName(const FileDescriptor* file) { + const std::string prefix = FileClassPrefix(file); + const std::string name = + UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root"; + // There aren't really any reserved words that end in "Root", but playing + // it safe and checking. + return SanitizeNameForObjC(prefix, name, "_RootClass", NULL); +} + +std::string ClassNameWorker(const Descriptor* descriptor) { + std::string name; + if (descriptor->containing_type() != NULL) { + name = ClassNameWorker(descriptor->containing_type()); + name += "_"; + } + return name + descriptor->name(); +} + +std::string ClassNameWorker(const EnumDescriptor* descriptor) { + std::string name; + if (descriptor->containing_type() != NULL) { + name = ClassNameWorker(descriptor->containing_type()); + name += "_"; + } + return name + descriptor->name(); +} + +std::string ClassName(const Descriptor* descriptor) { + return ClassName(descriptor, NULL); +} + +std::string ClassName(const Descriptor* descriptor, + std::string* out_suffix_added) { + // 1. Message names are used as is (style calls for CamelCase, trust it). + // 2. Check for reserved word at the very end and then suffix things. + const std::string prefix = FileClassPrefix(descriptor->file()); + const std::string name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added); +} + +std::string EnumName(const EnumDescriptor* descriptor) { + // 1. Enum names are used as is (style calls for CamelCase, trust it). + // 2. Check for reserved word at the every end and then suffix things. + // message Fixed { + // message Size {...} + // enum Mumble {...} + // ... + // } + // yields Fixed_Class, Fixed_Size. + const std::string prefix = FileClassPrefix(descriptor->file()); + const std::string name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix, name, "_Enum", NULL); +} + +std::string EnumValueName(const EnumValueDescriptor* descriptor) { + // Because of the Switch enum compatibility, the name on the enum has to have + // the suffix handing, so it slightly diverges from how nested classes work. + // enum Fixed { + // FOO = 1 + // } + // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo). + const std::string class_name = EnumName(descriptor->type()); + const std::string value_str = + UnderscoresToCamelCase(descriptor->name(), true); + const std::string name = class_name + "_" + value_str; + // There aren't really any reserved words with an underscore and a leading + // capital letter, but playing it safe and checking. + return SanitizeNameForObjC("", name, "_Value", NULL); +} + +std::string EnumValueShortName(const EnumValueDescriptor* descriptor) { + // Enum value names (EnumValueName above) are the enum name turned into + // a class name and then the value name is CamelCased and concatenated; the + // whole thing then gets sanitized for reserved words. + // The "short name" is intended to be the final leaf, the value name; but + // you can't simply send that off to sanitize as that could result in it + // getting modified when the full name didn't. For example enum + // "StorageModes" has a value "retain". So the full name is + // "StorageModes_Retain", but if we sanitize "retain" it would become + // "RetainValue". + // So the right way to get the short name is to take the full enum name + // and then strip off the enum name (leaving the value name and anything + // done by sanitize). + const std::string class_name = EnumName(descriptor->type()); + const std::string long_name_prefix = class_name + "_"; + const std::string long_name = EnumValueName(descriptor); + return StripPrefixString(long_name, long_name_prefix); +} + +std::string UnCamelCaseEnumShortName(const std::string& name) { + std::string result; + for (int i = 0; i < name.size(); i++) { + char c = name[i]; + if (i > 0 && ascii_isupper(c)) { + result += '_'; + } + result += ascii_toupper(c); + } + return result; +} + +std::string ExtensionMethodName(const FieldDescriptor* descriptor) { + const std::string name = NameFromFieldDescriptor(descriptor); + const std::string result = UnderscoresToCamelCase(name, false); + return SanitizeNameForObjC("", result, "_Extension", NULL); +} + +std::string FieldName(const FieldDescriptor* field) { + const std::string name = NameFromFieldDescriptor(field); + std::string result = UnderscoresToCamelCase(name, false); + if (field->is_repeated() && !field->is_map()) { + // Add "Array" before do check for reserved worlds. + result += "Array"; + } else { + // If it wasn't repeated, but ends in "Array", force on the _p suffix. + if (HasSuffixString(result, "Array")) { + result += "_p"; + } + } + return SanitizeNameForObjC("", result, "_p", NULL); +} + +std::string FieldNameCapitalized(const FieldDescriptor* field) { + // Want the same suffix handling, so upcase the first letter of the other + // name. + std::string result = FieldName(field); + if (result.length() > 0) { + result[0] = ascii_toupper(result[0]); + } + return result; +} + +std::string OneofEnumName(const OneofDescriptor* descriptor) { + const Descriptor* fieldDescriptor = descriptor->containing_type(); + std::string name = ClassName(fieldDescriptor); + name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase"; + // No sanitize needed because the OS never has names that end in _OneOfCase. + return name; +} + +std::string OneofName(const OneofDescriptor* descriptor) { + std::string name = UnderscoresToCamelCase(descriptor->name(), false); + // No sanitize needed because it gets OneOfCase added and that shouldn't + // ever conflict. + return name; +} + +std::string OneofNameCapitalized(const OneofDescriptor* descriptor) { + // Use the common handling and then up-case the first letter. + std::string result = OneofName(descriptor); + if (result.length() > 0) { + result[0] = ascii_toupper(result[0]); + } + return result; +} + +std::string ObjCClass(const std::string& class_name) { + return std::string("GPBObjCClass(") + class_name + ")"; +} + +std::string ObjCClassDeclaration(const std::string& class_name) { + return std::string("GPBObjCClassDeclaration(") + class_name + ");"; +} + +std::string UnCamelCaseFieldName(const std::string& name, const FieldDescriptor* field) { + std::string worker(name); + if (HasSuffixString(worker, "_p")) { + worker = StripSuffixString(worker, "_p"); + } + if (field->is_repeated() && HasSuffixString(worker, "Array")) { + worker = StripSuffixString(worker, "Array"); + } + if (field->type() == FieldDescriptor::TYPE_GROUP) { + if (worker.length() > 0) { + if (ascii_islower(worker[0])) { + worker[0] = ascii_toupper(worker[0]); + } + } + return worker; + } else { + std::string result; + for (int i = 0; i < worker.size(); i++) { + char c = worker[i]; + if (ascii_isupper(c)) { + if (i > 0) { + result += '_'; + } + result += ascii_tolower(c); + } else { + result += c; + } + } + return result; + } +} + +std::string GetCapitalizedType(const FieldDescriptor* field) { + switch (field->type()) { + case FieldDescriptor::TYPE_INT32: + return "Int32"; + case FieldDescriptor::TYPE_UINT32: + return "UInt32"; + case FieldDescriptor::TYPE_SINT32: + return "SInt32"; + case FieldDescriptor::TYPE_FIXED32: + return "Fixed32"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFixed32"; + case FieldDescriptor::TYPE_INT64: + return "Int64"; + case FieldDescriptor::TYPE_UINT64: + return "UInt64"; + case FieldDescriptor::TYPE_SINT64: + return "SInt64"; + case FieldDescriptor::TYPE_FIXED64: + return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_DOUBLE: + return "Double"; + case FieldDescriptor::TYPE_BOOL: + return "Bool"; + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: + return "Bytes"; + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + case FieldDescriptor::TYPE_GROUP: + return "Group"; + case FieldDescriptor::TYPE_MESSAGE: + return "Message"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return std::string(); +} + +ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SFIXED32: + return OBJECTIVECTYPE_INT32; + + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_FIXED32: + return OBJECTIVECTYPE_UINT32; + + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_SFIXED64: + return OBJECTIVECTYPE_INT64; + + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_FIXED64: + return OBJECTIVECTYPE_UINT64; + + case FieldDescriptor::TYPE_FLOAT: + return OBJECTIVECTYPE_FLOAT; + + case FieldDescriptor::TYPE_DOUBLE: + return OBJECTIVECTYPE_DOUBLE; + + case FieldDescriptor::TYPE_BOOL: + return OBJECTIVECTYPE_BOOLEAN; + + case FieldDescriptor::TYPE_STRING: + return OBJECTIVECTYPE_STRING; + + case FieldDescriptor::TYPE_BYTES: + return OBJECTIVECTYPE_DATA; + + case FieldDescriptor::TYPE_ENUM: + return OBJECTIVECTYPE_ENUM; + + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + return OBJECTIVECTYPE_MESSAGE; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return OBJECTIVECTYPE_INT32; +} + +bool IsPrimitiveType(const FieldDescriptor* field) { + ObjectiveCType type = GetObjectiveCType(field); + switch (type) { + case OBJECTIVECTYPE_INT32: + case OBJECTIVECTYPE_UINT32: + case OBJECTIVECTYPE_INT64: + case OBJECTIVECTYPE_UINT64: + case OBJECTIVECTYPE_FLOAT: + case OBJECTIVECTYPE_DOUBLE: + case OBJECTIVECTYPE_BOOLEAN: + case OBJECTIVECTYPE_ENUM: + return true; + break; + default: + return false; + } +} + +bool IsReferenceType(const FieldDescriptor* field) { + return !IsPrimitiveType(field); +} + +static std::string HandleExtremeFloatingPoint(std::string val, + bool add_float_suffix) { + if (val == "nan") { + return "NAN"; + } else if (val == "inf") { + return "INFINITY"; + } else if (val == "-inf") { + return "-INFINITY"; + } else { + // float strings with ., e or E need to have f appended + if (add_float_suffix && (val.find(".") != std::string::npos || + val.find("e") != std::string::npos || + val.find("E") != std::string::npos)) { + val += "f"; + } + return val; + } +} + +std::string GPBGenericValueFieldName(const FieldDescriptor* field) { + // Returns the field within the GPBGenericValue union to use for the given + // field. + if (field->is_repeated()) { + return "valueMessage"; + } + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return "valueInt32"; + case FieldDescriptor::CPPTYPE_UINT32: + return "valueUInt32"; + case FieldDescriptor::CPPTYPE_INT64: + return "valueInt64"; + case FieldDescriptor::CPPTYPE_UINT64: + return "valueUInt64"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "valueFloat"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return "valueDouble"; + case FieldDescriptor::CPPTYPE_BOOL: + return "valueBool"; + case FieldDescriptor::CPPTYPE_STRING: + if (field->type() == FieldDescriptor::TYPE_BYTES) { + return "valueData"; + } else { + return "valueString"; + } + case FieldDescriptor::CPPTYPE_ENUM: + return "valueEnum"; + case FieldDescriptor::CPPTYPE_MESSAGE: + return "valueMessage"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return std::string(); +} + + +std::string DefaultValue(const FieldDescriptor* field) { + // Repeated fields don't have defaults. + if (field->is_repeated()) { + return "nil"; + } + + // Switch on cpp_type since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + // gcc and llvm reject the decimal form of kint32min and kint64min. + if (field->default_value_int32() == INT_MIN) { + return "-0x80000000"; + } + return StrCat(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + return StrCat(field->default_value_uint32()) + "U"; + case FieldDescriptor::CPPTYPE_INT64: + // gcc and llvm reject the decimal form of kint32min and kint64min. + if (field->default_value_int64() == LLONG_MIN) { + return "-0x8000000000000000LL"; + } + return StrCat(field->default_value_int64()) + "LL"; + case FieldDescriptor::CPPTYPE_UINT64: + return StrCat(field->default_value_uint64()) + "ULL"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return HandleExtremeFloatingPoint( + SimpleDtoa(field->default_value_double()), false); + case FieldDescriptor::CPPTYPE_FLOAT: + return HandleExtremeFloatingPoint( + SimpleFtoa(field->default_value_float()), true); + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "YES" : "NO"; + case FieldDescriptor::CPPTYPE_STRING: { + const bool has_default_value = field->has_default_value(); + const std::string& default_string = field->default_value_string(); + if (!has_default_value || default_string.length() == 0) { + // If the field is defined as being the empty string, + // then we will just assign to nil, as the empty string is the + // default for both strings and data. + return "nil"; + } + if (field->type() == FieldDescriptor::TYPE_BYTES) { + // We want constant fields in our data structures so we can + // declare them as static. To achieve this we cheat and stuff + // a escaped c string (prefixed with a length) into the data + // field, and cast it to an (NSData*) so it will compile. + // The runtime library knows how to handle it. + + // Must convert to a standard byte order for packing length into + // a cstring. + uint32_t length = ghtonl(default_string.length()); + std::string bytes((const char*)&length, sizeof(length)); + bytes.append(default_string); + return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\""; + } else { + return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\""; + } + } + case FieldDescriptor::CPPTYPE_ENUM: + return EnumValueName(field->default_value_enum()); + case FieldDescriptor::CPPTYPE_MESSAGE: + return "nil"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return std::string(); +} + +bool HasNonZeroDefaultValue(const FieldDescriptor* field) { + // Repeated fields don't have defaults. + if (field->is_repeated()) { + return false; + } + + // As much as checking field->has_default_value() seems useful, it isn't + // because of enums. proto2 syntax allows the first item in an enum (the + // default) to be non zero. So checking field->has_default_value() would + // result in missing this non zero default. See MessageWithOneBasedEnum in + // objectivec/Tests/unittest_objc.proto for a test Message to confirm this. + + // Some proto file set the default to the zero value, so make sure the value + // isn't the zero case. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() != 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() != 0U; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() != 0LL; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() != 0ULL; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() != 0.0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() != 0.0f; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool(); + case FieldDescriptor::CPPTYPE_STRING: { + const std::string& default_string = field->default_value_string(); + return default_string.length() != 0; + } + case FieldDescriptor::CPPTYPE_ENUM: + return field->default_value_enum()->number() != 0; + case FieldDescriptor::CPPTYPE_MESSAGE: + return false; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +std::string BuildFlagsString(const FlagType flag_type, + const std::vector<std::string>& strings) { + if (strings.empty()) { + return GetZeroEnumNameForFlagType(flag_type); + } else if (strings.size() == 1) { + return strings[0]; + } + std::string string("(" + GetEnumNameForFlagType(flag_type) + ")("); + for (size_t i = 0; i != strings.size(); ++i) { + if (i > 0) { + string.append(" | "); + } + string.append(strings[i]); + } + string.append(")"); + return string; +} + +std::string BuildCommentsString(const SourceLocation& location, + bool prefer_single_line) { + const std::string& comments = location.leading_comments.empty() + ? location.trailing_comments + : location.leading_comments; + std::vector<std::string> lines; + lines = Split(comments, "\n", false); + while (!lines.empty() && lines.back().empty()) { + lines.pop_back(); + } + // If there are no comments, just return an empty string. + if (lines.empty()) { + return ""; + } + + std::string prefix; + std::string suffix; + std::string final_comments; + std::string epilogue; + + bool add_leading_space = false; + + if (prefer_single_line && lines.size() == 1) { + prefix = "/** "; + suffix = " */\n"; + } else { + prefix = "* "; + suffix = "\n"; + final_comments += "/**\n"; + epilogue = " **/\n"; + add_leading_space = true; + } + + for (int i = 0; i < lines.size(); i++) { + std::string line = StripPrefixString(lines[i], " "); + // HeaderDoc and appledoc use '\' and '@' for markers; escape them. + line = StringReplace(line, "\\", "\\\\", true); + line = StringReplace(line, "@", "\\@", true); + // Decouple / from * to not have inline comments inside comments. + line = StringReplace(line, "/*", "/\\*", true); + line = StringReplace(line, "*/", "*\\/", true); + line = prefix + line; + StripWhitespace(&line); + // If not a one line, need to add the first space before *, as + // StripWhitespace would have removed it. + line = (add_leading_space ? " " : "") + line; + final_comments += line + suffix; + } + final_comments += epilogue; + return final_comments; +} + +// Making these a generator option for folks that don't use CocoaPods, but do +// want to put the library in a framework is an interesting question. The +// problem is it means changing sources shipped with the library to actually +// use a different value; so it isn't as simple as a option. +const char* const ProtobufLibraryFrameworkName = "Protobuf"; + +std::string ProtobufFrameworkImportSymbol(const std::string& framework_name) { + // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS + std::string result = std::string("GPB_USE_"); + result += ToUpper(framework_name); + result += "_FRAMEWORK_IMPORTS"; + return result; +} + +bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) { + // We don't check the name prefix or proto package because some files + // (descriptor.proto), aren't shipped generated by the library, so this + // seems to be the safest way to only catch the ones shipped. + const std::string name = file->name(); + if (name == "google/protobuf/any.proto" || + name == "google/protobuf/api.proto" || + name == "google/protobuf/duration.proto" || + name == "google/protobuf/empty.proto" || + name == "google/protobuf/field_mask.proto" || + name == "google/protobuf/source_context.proto" || + name == "google/protobuf/struct.proto" || + name == "google/protobuf/timestamp.proto" || + name == "google/protobuf/type.proto" || + name == "google/protobuf/wrappers.proto") { + return true; + } + return false; +} + +bool ReadLine(StringPiece* input, StringPiece* line) { + for (int len = 0; len < input->size(); ++len) { + if (ascii_isnewline((*input)[len])) { + *line = StringPiece(input->data(), len); + ++len; // advance over the newline + *input = StringPiece(input->data() + len, input->size() - len); + return true; + } + } + return false; // Ran out of input with no newline. +} + +void RemoveComment(StringPiece* input) { + int offset = input->find('#'); + if (offset != StringPiece::npos) { + input->remove_suffix(input->length() - offset); + } +} + +namespace { + +class ExpectedPrefixesCollector : public LineConsumer { + public: + ExpectedPrefixesCollector(std::map<std::string, std::string>* inout_package_to_prefix_map) + : prefix_map_(inout_package_to_prefix_map) {} + + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override; + + private: + std::map<std::string, std::string>* prefix_map_; +}; + +bool ExpectedPrefixesCollector::ConsumeLine( + const StringPiece& line, std::string* out_error) { + int offset = line.find('='); + if (offset == StringPiece::npos) { + *out_error = std::string("Expected prefixes file line without equal sign: '") + + std::string(line) + "'."; + return false; + } + StringPiece package = line.substr(0, offset); + StringPiece prefix = line.substr(offset + 1); + TrimWhitespace(&package); + TrimWhitespace(&prefix); + MaybeUnQuote(&prefix); + // Don't really worry about error checking the package/prefix for + // being valid. Assume the file is validated when it is created/edited. + (*prefix_map_)[std::string(package)] = std::string(prefix); + return true; +} + +bool LoadExpectedPackagePrefixes(const Options& generation_options, + std::map<std::string, std::string>* prefix_map, + std::string* out_error) { + if (generation_options.expected_prefixes_path.empty()) { + return true; + } + + ExpectedPrefixesCollector collector(prefix_map); + return ParseSimpleFile( + generation_options.expected_prefixes_path, &collector, out_error); +} + +bool ValidateObjCClassPrefix( + const FileDescriptor* file, const std::string& expected_prefixes_path, + const std::map<std::string, std::string>& expected_package_prefixes, + bool prefixes_must_be_registered, bool require_prefixes, + std::string* out_error) { + // Reminder: An explicit prefix option of "" is valid in case the default + // prefixing is set to use the proto package and a file needs to be generated + // without any prefix at all (for legacy reasons). + + bool has_prefix = file->options().has_objc_class_prefix(); + bool have_expected_prefix_file = !expected_prefixes_path.empty(); + + const std::string prefix = file->options().objc_class_prefix(); + const std::string package = file->package(); + + // 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 warnings. + + // Check: Error - See if there was an expected prefix for the package and + // report if it doesn't match (wrong or missing). + std::map<std::string, std::string>::const_iterator package_match = + expected_package_prefixes.find(package); + if (package_match != expected_package_prefixes.end()) { + // There was an entry, and... + if (has_prefix && package_match->second == prefix) { + // ...it matches. All good, out of here! + return true; + } else { + // ...it didn't match! + *out_error = "error: Expected 'option objc_class_prefix = \"" + + package_match->second + "\";' for package '" + package + + "' in '" + file->name() + "'"; + if (has_prefix) { + *out_error += "; but found '" + prefix + "' instead"; + } + *out_error += "."; + return false; + } + } + + // If there was no prefix option, we're done at this point. + if (!has_prefix) { + if (require_prefixes) { + *out_error = + "error: '" + file->name() + "' does not have a required 'option" + + " objc_class_prefix'."; + return false; + } + return true; + } + + // When the prefix is non empty, check it against the expected entries. + if (!prefix.empty() && have_expected_prefix_file) { + // For a non empty prefix, look for any other package that uses the prefix. + std::string other_package_for_prefix; + for (std::map<std::string, std::string>::const_iterator i = + expected_package_prefixes.begin(); + i != expected_package_prefixes.end(); ++i) { + if (i->second == prefix) { + other_package_for_prefix = i->first; + break; + } + } + + // Check: Warning - If the file does not have a package, check whether the + // prefix was declared is being used by another package or not. This is + // a special case for empty packages. + if (package.empty()) { + // The file does not have a package and ... + if (other_package_for_prefix.empty()) { + // ... no other package has declared that prefix. + std::cerr + << "protoc:0: warning: File '" << file->name() << "' has no " + << "package. Consider adding a new package to the proto and adding '" + << "new.package = " << prefix << "' to the expected prefixes file (" + << expected_prefixes_path << ")." << std::endl; + std::cerr.flush(); + } else { + // ... another package has declared the same prefix. + std::cerr + << "protoc:0: warning: File '" << file->name() << "' has no package " + << "and package '" << other_package_for_prefix << "' already uses '" + << prefix << "' as its prefix. Consider either adding a new package " + << "to the proto, or reusing one of the packages already using this " + << "prefix in the expected prefixes file (" + << expected_prefixes_path << ")." << std::endl; + std::cerr.flush(); + } + return true; + } + + // Check: Error - Make sure the prefix wasn't expected for a different + // package (overlap is allowed, but it has to be listed as an expected + // overlap). + if (!other_package_for_prefix.empty()) { + *out_error = + "error: Found 'option objc_class_prefix = \"" + prefix + + "\";' in '" + file->name() + + "'; that prefix is already used for 'package " + + other_package_for_prefix + ";'. It can only be reused by listing " + + "it in the expected file (" + + expected_prefixes_path + ")."; + return false; // Only report first usage of the prefix. + } + } // !prefix.empty() + + // Check: Warning - Make sure the prefix is is a reasonable value according + // to Apple's rules (the checks above implicitly whitelist anything that + // doesn't meet these rules). + if (!prefix.empty() && !ascii_isupper(prefix[0])) { + std::cerr + << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " it should start with a capital letter." << std::endl; + std::cerr.flush(); + } + if (!prefix.empty() && prefix.length() < 3) { + // Apple reserves 2 character prefixes for themselves. They do use some + // 3 character prefixes, but they haven't updated the rules/docs. + std::cerr + << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " Apple recommends they should be at least 3 characters long." + << std::endl; + std::cerr.flush(); + } + + // Check: Error/Warning - If the given package/prefix pair wasn't expected, + // issue a error/warning to added to the file. + if (have_expected_prefix_file) { + if (prefixes_must_be_registered) { + *out_error = + "error: '" + file->name() + "' has 'option objc_class_prefix = \"" + + prefix + "\";', but it is not registered; add it to the expected " + + "prefixes file (" + expected_prefixes_path + ") for the package '" + + package + "'."; + return false; + } + + std::cerr + << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " consider adding it to the expected prefixes file (" + << expected_prefixes_path << ")." << std::endl; + std::cerr.flush(); + } + + return true; +} + +} // namespace + +bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, + const Options& generation_options, + std::string* out_error) { + // Allow a '-' as the path for the expected prefixes to completely disable + // even the most basic of checks. + if (generation_options.expected_prefixes_path == "-") { + return true; + } + + // Load the expected package prefixes, if available, to validate against. + std::map<std::string, std::string> expected_package_prefixes; + if (!LoadExpectedPackagePrefixes(generation_options, + &expected_package_prefixes, + out_error)) { + return false; + } + + for (int i = 0; i < files.size(); i++) { + bool should_skip = + (std::find(generation_options.expected_prefixes_suppressions.begin(), + generation_options.expected_prefixes_suppressions.end(), + files[i]->name()) + != generation_options.expected_prefixes_suppressions.end()); + if (should_skip) { + continue; + } + + bool is_valid = + ValidateObjCClassPrefix(files[i], + generation_options.expected_prefixes_path, + expected_package_prefixes, + generation_options.prefixes_must_be_registered, + generation_options.require_prefixes, + out_error); + if (!is_valid) { + return false; + } + } + return true; +} + +TextFormatDecodeData::TextFormatDecodeData() { } + +TextFormatDecodeData::~TextFormatDecodeData() { } + +void TextFormatDecodeData::AddString(int32_t key, + const std::string& input_for_decode, + const std::string& desired_output) { + for (std::vector<DataEntry>::const_iterator i = entries_.begin(); + i != entries_.end(); ++i) { + if (i->first == key) { + std::cerr << "error: duplicate key (" << key + << ") making TextFormat data, input: \"" << input_for_decode + << "\", desired: \"" << desired_output << "\"." << std::endl; + std::cerr.flush(); + abort(); + } + } + + const std::string& data = TextFormatDecodeData::DecodeDataForString( + input_for_decode, desired_output); + entries_.push_back(DataEntry(key, data)); +} + +std::string TextFormatDecodeData::Data() const { + std::ostringstream data_stringstream; + + if (num_entries() > 0) { + io::OstreamOutputStream data_outputstream(&data_stringstream); + io::CodedOutputStream output_stream(&data_outputstream); + + output_stream.WriteVarint32(num_entries()); + for (std::vector<DataEntry>::const_iterator i = entries_.begin(); + i != entries_.end(); ++i) { + output_stream.WriteVarint32(i->first); + output_stream.WriteString(i->second); + } + } + + data_stringstream.flush(); + return data_stringstream.str(); +} + +namespace { + +// Helper to build up the decode data for a string. +class DecodeDataBuilder { + public: + DecodeDataBuilder() { Reset(); } + + bool AddCharacter(const char desired, const char input); + void AddUnderscore() { + Push(); + need_underscore_ = true; + } + std::string Finish() { + Push(); + return decode_data_; + } + + private: + static constexpr uint8_t kAddUnderscore = 0x80; + + static constexpr uint8_t kOpAsIs = 0x00; + static constexpr uint8_t kOpFirstUpper = 0x40; + static constexpr uint8_t kOpFirstLower = 0x20; + static constexpr uint8_t kOpAllUpper = 0x60; + + static constexpr int kMaxSegmentLen = 0x1f; + + void AddChar(const char desired) { + ++segment_len_; + is_all_upper_ &= ascii_isupper(desired); + } + + void Push() { + uint8_t op = (op_ | segment_len_); + if (need_underscore_) op |= kAddUnderscore; + if (op != 0) { + decode_data_ += (char)op; + } + Reset(); + } + + bool AddFirst(const char desired, const char input) { + if (desired == input) { + op_ = kOpAsIs; + } else if (desired == ascii_toupper(input)) { + op_ = kOpFirstUpper; + } else if (desired == ascii_tolower(input)) { + op_ = kOpFirstLower; + } else { + // Can't be transformed to match. + return false; + } + AddChar(desired); + return true; + } + + void Reset() { + need_underscore_ = false; + op_ = 0; + segment_len_ = 0; + is_all_upper_ = true; + } + + bool need_underscore_; + bool is_all_upper_; + uint8_t op_; + int segment_len_; + + std::string decode_data_; +}; + +bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { + // If we've hit the max size, push to start a new segment. + if (segment_len_ == kMaxSegmentLen) { + Push(); + } + if (segment_len_ == 0) { + return AddFirst(desired, input); + } + + // Desired and input match... + if (desired == input) { + // If we aren't transforming it, or we're upper casing it and it is + // supposed to be uppercase; just add it to the segment. + if ((op_ != kOpAllUpper) || ascii_isupper(desired)) { + AddChar(desired); + return true; + } + + // Add the current segment, and start the next one. + Push(); + return AddFirst(desired, input); + } + + // If we need to uppercase, and everything so far has been uppercase, + // promote op to AllUpper. + if ((desired == ascii_toupper(input)) && is_all_upper_) { + op_ = kOpAllUpper; + AddChar(desired); + return true; + } + + // Give up, push and start a new segment. + Push(); + return AddFirst(desired, input); +} + +// If decode data can't be generated, a directive for the raw string +// is used instead. +std::string DirectDecodeString(const std::string& str) { + std::string result; + result += (char)'\0'; // Marker for full string. + result += str; + result += (char)'\0'; // End of string. + return result; +} + +} // namespace + +// static +std::string TextFormatDecodeData::DecodeDataForString( + const std::string& input_for_decode, const std::string& desired_output) { + if (input_for_decode.empty() || desired_output.empty()) { + std::cerr << "error: got empty string for making TextFormat data, input: \"" + << input_for_decode << "\", desired: \"" << desired_output << "\"." + << std::endl; + std::cerr.flush(); + abort(); + } + if ((input_for_decode.find('\0') != std::string::npos) || + (desired_output.find('\0') != std::string::npos)) { + std::cerr << "error: got a null char in a string for making TextFormat data," + << " input: \"" << CEscape(input_for_decode) << "\", desired: \"" + << CEscape(desired_output) << "\"." << std::endl; + std::cerr.flush(); + abort(); + } + + DecodeDataBuilder builder; + + // Walk the output building it from the input. + int x = 0; + for (int y = 0; y < desired_output.size(); y++) { + const char d = desired_output[y]; + if (d == '_') { + builder.AddUnderscore(); + continue; + } + + if (x >= input_for_decode.size()) { + // Out of input, no way to encode it, just return a full decode. + return DirectDecodeString(desired_output); + } + if (builder.AddCharacter(d, input_for_decode[x])) { + ++x; // Consumed one input + } else { + // Couldn't transform for the next character, just return a full decode. + return DirectDecodeString(desired_output); + } + } + + if (x != input_for_decode.size()) { + // Extra input (suffix from name sanitizing?), just return a full decode. + return DirectDecodeString(desired_output); + } + + // Add the end marker. + return builder.Finish() + (char)'\0'; +} + +namespace { + +class Parser { + public: + Parser(LineConsumer* line_consumer) + : line_consumer_(line_consumer), line_(0) {} + + // Feeds in some input, parse what it can, returning success/failure. Calling + // again after an error is undefined. + bool ParseChunk(StringPiece chunk, std::string* out_error); + + // Should be called to finish parsing (after all input has been provided via + // successful calls to ParseChunk(), calling after a ParseChunk() failure is + // undefined). Returns success/failure. + bool Finish(std::string* out_error); + + int last_line() const { return line_; } + + private: + LineConsumer* line_consumer_; + int line_; + std::string leftover_; +}; + +bool Parser::ParseChunk(StringPiece chunk, std::string* out_error) { + StringPiece full_chunk; + if (!leftover_.empty()) { + leftover_ += std::string(chunk); + full_chunk = StringPiece(leftover_); + } else { + full_chunk = chunk; + } + + StringPiece line; + while (ReadLine(&full_chunk, &line)) { + ++line_; + RemoveComment(&line); + TrimWhitespace(&line); + if (!line.empty() && !line_consumer_->ConsumeLine(line, out_error)) { + if (out_error->empty()) { + *out_error = "ConsumeLine failed without setting an error."; + } + leftover_.clear(); + return false; + } + } + + if (full_chunk.empty()) { + leftover_.clear(); + } else { + leftover_ = std::string(full_chunk); + } + return true; +} + +bool Parser::Finish(std::string* out_error) { + // If there is still something to go, flush it with a newline. + if (!leftover_.empty() && !ParseChunk("\n", out_error)) { + return false; + } + // This really should never fail if ParseChunk succeeded, but check to be sure. + if (!leftover_.empty()) { + *out_error = "ParseSimple Internal error: finished with pending data."; + return false; + } + return true; +} + +std::string FullErrorString(const std::string& name, int line_num, const std::string& msg) { + return std::string("error: ") + name + " Line " + StrCat(line_num) + ", " + msg; +} + +} // namespace + +LineConsumer::LineConsumer() {} + +LineConsumer::~LineConsumer() {} + +bool ParseSimpleFile(const std::string& path, LineConsumer* line_consumer, + std::string* out_error) { + int fd; + do { + fd = posix::open(path.c_str(), O_RDONLY); + } while (fd < 0 && errno == EINTR); + if (fd < 0) { + *out_error = std::string("error: Unable to open \"") + path + "\", " + + strerror(errno); + return false; + } + io::FileInputStream file_stream(fd); + file_stream.SetCloseOnDelete(true); + + return ParseSimpleStream(file_stream, path, line_consumer, out_error); +} + +bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream, + const std::string& stream_name, + LineConsumer* line_consumer, + std::string* out_error) { + std::string local_error; + Parser parser(line_consumer); + const void* buf; + int buf_len; + while (input_stream.Next(&buf, &buf_len)) { + if (buf_len == 0) { + continue; + } + + if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len), + &local_error)) { + *out_error = FullErrorString(stream_name, parser.last_line(), local_error); + return false; + } + } + if (!parser.Finish(&local_error)) { + *out_error = FullErrorString(stream_name, parser.last_line(), local_error); + return false; + } + return true; +} + +ImportWriter::ImportWriter( + const std::string& generate_for_named_framework, + const std::string& named_framework_to_proto_path_mappings_path, + const std::string& runtime_import_prefix, bool include_wkt_imports) + : generate_for_named_framework_(generate_for_named_framework), + named_framework_to_proto_path_mappings_path_( + named_framework_to_proto_path_mappings_path), + runtime_import_prefix_(runtime_import_prefix), + include_wkt_imports_(include_wkt_imports), + need_to_parse_mapping_file_(true) {} + +ImportWriter::~ImportWriter() {} + +void ImportWriter::AddFile(const FileDescriptor* file, + const std::string& header_extension) { + if (IsProtobufLibraryBundledProtoFile(file)) { + // The imports of the WKTs are only needed within the library itself, + // in other cases, they get skipped because the generated code already + // import GPBProtocolBuffers.h and hence proves them. + if (include_wkt_imports_) { + const std::string header_name = + "GPB" + FilePathBasename(file) + header_extension; + protobuf_imports_.push_back(header_name); + } + return; + } + + // Lazy parse any mappings. + if (need_to_parse_mapping_file_) { + ParseFrameworkMappings(); + } + + std::map<std::string, std::string>::iterator proto_lookup = + proto_file_to_framework_name_.find(file->name()); + if (proto_lookup != proto_file_to_framework_name_.end()) { + other_framework_imports_.push_back( + proto_lookup->second + "/" + + FilePathBasename(file) + header_extension); + return; + } + + if (!generate_for_named_framework_.empty()) { + other_framework_imports_.push_back( + generate_for_named_framework_ + "/" + + FilePathBasename(file) + header_extension); + return; + } + + other_imports_.push_back(FilePath(file) + header_extension); +} + +void ImportWriter::Print(io::Printer* printer) const { + bool add_blank_line = false; + + if (!protobuf_imports_.empty()) { + PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_); + add_blank_line = true; + } + + if (!other_framework_imports_.empty()) { + if (add_blank_line) { + printer->Print("\n"); + } + + for (std::vector<std::string>::const_iterator iter = + other_framework_imports_.begin(); + iter != other_framework_imports_.end(); ++iter) { + printer->Print( + "#import <$header$>\n", + "header", *iter); + } + + add_blank_line = true; + } + + if (!other_imports_.empty()) { + if (add_blank_line) { + printer->Print("\n"); + } + + for (std::vector<std::string>::const_iterator iter = other_imports_.begin(); + iter != other_imports_.end(); ++iter) { + printer->Print( + "#import \"$header$\"\n", + "header", *iter); + } + } +} + +void ImportWriter::PrintRuntimeImports( + io::Printer* printer, const std::vector<std::string>& header_to_import, + const std::string& runtime_import_prefix, bool default_cpp_symbol) { + // Given an override, use that. + if (!runtime_import_prefix.empty()) { + for (const auto& header : header_to_import) { + printer->Print( + " #import \"$import_prefix$/$header$\"\n", + "import_prefix", runtime_import_prefix, + "header", header); + } + return; + } + + const std::string framework_name(ProtobufLibraryFrameworkName); + const std::string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); + + if (default_cpp_symbol) { + printer->Print( + "// This CPP symbol can be defined to use imports that match up to the framework\n" + "// imports needed when using CocoaPods.\n" + "#if !defined($cpp_symbol$)\n" + " #define $cpp_symbol$ 0\n" + "#endif\n" + "\n", + "cpp_symbol", cpp_symbol); + } + + printer->Print( + "#if $cpp_symbol$\n", + "cpp_symbol", cpp_symbol); + for (const auto& header : header_to_import) { + printer->Print( + " #import <$framework_name$/$header$>\n", + "framework_name", framework_name, + "header", header); + } + printer->Print( + "#else\n"); + for (const auto& header : header_to_import) { + printer->Print( + " #import \"$header$\"\n", + "header", header); + } + printer->Print( + "#endif\n"); +} + +void ImportWriter::ParseFrameworkMappings() { + need_to_parse_mapping_file_ = false; + if (named_framework_to_proto_path_mappings_path_.empty()) { + return; // Nothing to do. + } + + ProtoFrameworkCollector collector(&proto_file_to_framework_name_); + std::string parse_error; + if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, + &collector, &parse_error)) { + std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_ + << " : " << parse_error << std::endl; + std::cerr.flush(); + } +} + +bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( + const StringPiece& line, std::string* out_error) { + int offset = line.find(':'); + if (offset == StringPiece::npos) { + *out_error = + std::string("Framework/proto file mapping line without colon sign: '") + + std::string(line) + "'."; + return false; + } + StringPiece framework_name = line.substr(0, offset); + StringPiece proto_file_list = line.substr(offset + 1); + TrimWhitespace(&framework_name); + + int start = 0; + while (start < proto_file_list.length()) { + offset = proto_file_list.find(',', start); + if (offset == StringPiece::npos) { + offset = proto_file_list.length(); + } + + StringPiece proto_file = proto_file_list.substr(start, offset - start); + TrimWhitespace(&proto_file); + if (!proto_file.empty()) { + std::map<std::string, std::string>::iterator existing_entry = + map_->find(std::string(proto_file)); + if (existing_entry != map_->end()) { + std::cerr << "warning: duplicate proto file reference, replacing " + "framework entry for '" + << std::string(proto_file) << "' with '" << std::string(framework_name) + << "' (was '" << existing_entry->second << "')." << std::endl; + std::cerr.flush(); + } + + if (proto_file.find(' ') != StringPiece::npos) { + std::cerr << "note: framework mapping file had a proto file with a " + "space in, hopefully that isn't a missing comma: '" + << std::string(proto_file) << "'" << std::endl; + std::cerr.flush(); + } + + (*map_)[std::string(proto_file)] = std::string(framework_name); + } + + start = offset + 1; + } + + return true; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h new file mode 100644 index 00000000..e6a3e436 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers.h @@ -0,0 +1,347 @@ +// 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. + +// Helper functions for generating ObjectiveC code. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ + +#include <string> +#include <vector> + +#include <descriptor.h> +#include <descriptor.pb.h> +#include <io/zero_copy_stream.h> + +#include <port_def.inc> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// Get/Set if the proto package should be used to make the default prefix for +// symbols. This will then impact most of the type naming apis below. It is done +// as a global to not break any other generator reusing the methods since they +// are exported. +bool PROTOC_EXPORT UseProtoPackageAsDefaultPrefix(); +void PROTOC_EXPORT SetUseProtoPackageAsDefaultPrefix(bool on_or_off); +// Get/Set the path to a file to load as exceptions when +// `UseProtoPackageAsDefaultPrefixUseProtoPackageAsDefaultPrefix()` is `true`. +// And empty string means there should be no exceptions loaded. +std::string PROTOC_EXPORT GetProtoPackagePrefixExceptionList(); +void PROTOC_EXPORT SetProtoPackagePrefixExceptionList( + const std::string& file_path); + +// Generator options (see objectivec_generator.cc for a description of each): +struct Options { + Options(); + std::string expected_prefixes_path; + std::vector<std::string> expected_prefixes_suppressions; + std::string generate_for_named_framework; + std::string named_framework_to_proto_path_mappings_path; + std::string runtime_import_prefix; + bool prefixes_must_be_registered; + bool require_prefixes; +}; + +// Escape C++ trigraphs by escaping question marks to "\?". +std::string PROTOC_EXPORT EscapeTrigraphs(const std::string& to_escape); + +// Remove white space from either end of a StringPiece. +void PROTOC_EXPORT TrimWhitespace(StringPiece* input); + +// Returns true if the name requires a ns_returns_not_retained attribute applied +// to it. +bool PROTOC_EXPORT IsRetainedName(const std::string& name); + +// Returns true if the name starts with "init" and will need to have special +// handling under ARC. +bool PROTOC_EXPORT IsInitName(const std::string& name); + +// Gets the objc_class_prefix or the prefix made from the proto package. +std::string PROTOC_EXPORT FileClassPrefix(const FileDescriptor* file); + +// Gets the path of the file we're going to generate (sans the .pb.h +// extension). The path will be dependent on the objectivec package +// declared in the proto package. +std::string PROTOC_EXPORT FilePath(const FileDescriptor* file); + +// Just like FilePath(), but without the directory part. +std::string PROTOC_EXPORT FilePathBasename(const FileDescriptor* file); + +// Gets the name of the root class we'll generate in the file. This class +// is not meant for external consumption, but instead contains helpers that +// the rest of the classes need +std::string PROTOC_EXPORT FileClassName(const FileDescriptor* file); + +// These return the fully-qualified class name corresponding to the given +// descriptor. +std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor); +std::string PROTOC_EXPORT ClassName(const Descriptor* descriptor, + std::string* out_suffix_added); +std::string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor); + +// Returns the fully-qualified name of the enum value corresponding to the +// the descriptor. +std::string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor); + +// Returns the name of the enum value corresponding to the descriptor. +std::string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor); + +// Reverse what an enum does. +std::string PROTOC_EXPORT UnCamelCaseEnumShortName(const std::string& name); + +// Returns the name to use for the extension (used as the method off the file's +// Root class). +std::string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor); + +// Returns the transformed field name. +std::string PROTOC_EXPORT FieldName(const FieldDescriptor* field); +std::string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field); + +// Returns the transformed oneof name. +std::string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); +std::string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); +std::string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); + +// Returns a symbol that can be used in C code to refer to an Objective C +// class without initializing the class. +std::string PROTOC_EXPORT ObjCClass(const std::string& class_name); + +// Declares an Objective C class without initializing the class so that it can +// be refrerred to by ObjCClass. +std::string PROTOC_EXPORT ObjCClassDeclaration(const std::string& class_name); + +inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) { + return file->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + +inline bool IsMapEntryMessage(const Descriptor* descriptor) { + return descriptor->options().map_entry(); +} + +// Reverse of the above. +std::string PROTOC_EXPORT UnCamelCaseFieldName(const std::string& name, + const FieldDescriptor* field); + +enum ObjectiveCType { + OBJECTIVECTYPE_INT32, + OBJECTIVECTYPE_UINT32, + OBJECTIVECTYPE_INT64, + OBJECTIVECTYPE_UINT64, + OBJECTIVECTYPE_FLOAT, + OBJECTIVECTYPE_DOUBLE, + OBJECTIVECTYPE_BOOLEAN, + OBJECTIVECTYPE_STRING, + OBJECTIVECTYPE_DATA, + OBJECTIVECTYPE_ENUM, + OBJECTIVECTYPE_MESSAGE +}; + +enum FlagType { + FLAGTYPE_DESCRIPTOR_INITIALIZATION, + FLAGTYPE_EXTENSION, + FLAGTYPE_FIELD +}; + +template <class TDescriptor> +std::string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, + const FileDescriptor* file = NULL, + bool preSpace = true, + bool postNewline = false) { + bool isDeprecated = descriptor->options().deprecated(); + // The file is only passed when checking Messages & Enums, so those types + // get tagged. At the moment, it doesn't seem to make sense to tag every + // field or enum value with when the file is deprecated. + bool isFileLevelDeprecation = false; + if (!isDeprecated && file) { + isFileLevelDeprecation = file->options().deprecated(); + isDeprecated = isFileLevelDeprecation; + } + if (isDeprecated) { + std::string message; + const FileDescriptor* sourceFile = descriptor->file(); + if (isFileLevelDeprecation) { + message = sourceFile->name() + " is deprecated."; + } else { + message = descriptor->full_name() + " is deprecated (see " + + sourceFile->name() + ")."; + } + + std::string result = std::string("GPB_DEPRECATED_MSG(\"") + message + "\")"; + if (preSpace) { + result.insert(0, " "); + } + if (postNewline) { + result.append("\n"); + } + return result; + } else { + return ""; + } +} + +std::string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field); + +ObjectiveCType PROTOC_EXPORT +GetObjectiveCType(FieldDescriptor::Type field_type); + +inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { + return GetObjectiveCType(field->type()); +} + +bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field); +bool PROTOC_EXPORT IsReferenceType(const FieldDescriptor* field); + +std::string PROTOC_EXPORT +GPBGenericValueFieldName(const FieldDescriptor* field); +std::string PROTOC_EXPORT DefaultValue(const FieldDescriptor* field); +bool PROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field); + +std::string PROTOC_EXPORT +BuildFlagsString(const FlagType type, const std::vector<std::string>& strings); + +// Builds HeaderDoc/appledoc style comments out of the comments in the .proto +// file. +std::string PROTOC_EXPORT BuildCommentsString(const SourceLocation& location, + bool prefer_single_line); + +// The name the commonly used by the library when built as a framework. +// This lines up to the name used in the CocoaPod. +extern PROTOC_EXPORT const char* const ProtobufLibraryFrameworkName; +// Returns the CPP symbol name to use as the gate for framework style imports +// for the given framework name to use. +std::string PROTOC_EXPORT +ProtobufFrameworkImportSymbol(const std::string& framework_name); + +// Checks if the file is one of the proto's bundled with the library. +bool PROTOC_EXPORT +IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); + +// Checks the prefix for the given files and outputs any warnings as needed. If +// there are flat out errors, then out_error is filled in with the first error +// and the result is false. +bool PROTOC_EXPORT ValidateObjCClassPrefixes( + const std::vector<const FileDescriptor*>& files, + const Options& generation_options, std::string* out_error); + +// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform +// the input into the expected output. +class PROTOC_EXPORT TextFormatDecodeData { + public: + TextFormatDecodeData(); + ~TextFormatDecodeData(); + + TextFormatDecodeData(const TextFormatDecodeData&) = delete; + TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete; + + void AddString(int32_t key, const std::string& input_for_decode, + const std::string& desired_output); + size_t num_entries() const { return entries_.size(); } + std::string Data() const; + + static std::string DecodeDataForString(const std::string& input_for_decode, + const std::string& desired_output); + + private: + typedef std::pair<int32_t, std::string> DataEntry; + std::vector<DataEntry> entries_; +}; + +// Helper for parsing simple files. +class PROTOC_EXPORT LineConsumer { + public: + LineConsumer(); + virtual ~LineConsumer(); + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) = 0; +}; + +bool PROTOC_EXPORT ParseSimpleFile(const std::string& path, + LineConsumer* line_consumer, + std::string* out_error); + +bool PROTOC_EXPORT ParseSimpleStream(io::ZeroCopyInputStream& input_stream, + const std::string& stream_name, + LineConsumer* line_consumer, + std::string* out_error); + +// Helper class for parsing framework import mappings and generating +// import statements. +class PROTOC_EXPORT ImportWriter { + public: + ImportWriter(const std::string& generate_for_named_framework, + const std::string& named_framework_to_proto_path_mappings_path, + const std::string& runtime_import_prefix, + bool include_wkt_imports); + ~ImportWriter(); + + void AddFile(const FileDescriptor* file, const std::string& header_extension); + void Print(io::Printer* printer) const; + + static void PrintRuntimeImports(io::Printer* printer, + const std::vector<std::string>& header_to_import, + const std::string& runtime_import_prefix, + bool default_cpp_symbol = false); + + private: + class ProtoFrameworkCollector : public LineConsumer { + public: + ProtoFrameworkCollector(std::map<std::string, std::string>* inout_proto_file_to_framework_name) + : map_(inout_proto_file_to_framework_name) {} + + virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override; + + private: + std::map<std::string, std::string>* map_; + }; + + void ParseFrameworkMappings(); + + const std::string generate_for_named_framework_; + const std::string named_framework_to_proto_path_mappings_path_; + const std::string runtime_import_prefix_; + const bool include_wkt_imports_; + std::map<std::string, std::string> proto_file_to_framework_name_; + bool need_to_parse_mapping_file_; + + std::vector<std::string> protobuf_imports_; + std::vector<std::string> other_framework_imports_; + std::vector<std::string> other_imports_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include <port_undef.inc> + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc new file mode 100644 index 00000000..85f150b9 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -0,0 +1,385 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 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. + +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/zero_copy_stream_impl_lite.h> +#include <testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { +namespace { + +TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) { + std::string input_for_decode("abcdefghIJ"); + std::string desired_output_for_decode; + std::string expected; + std::string result; + + // Different data, can't transform. + + desired_output_for_decode = "zbcdefghIJ"; + expected = std::string("\0zbcdefghIJ\0", 12); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + desired_output_for_decode = "abcdezghIJ"; + expected = std::string("\0abcdezghIJ\0", 12); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + // Shortened data, can't transform. + + desired_output_for_decode = "abcdefghI"; + expected = std::string("\0abcdefghI\0", 11); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + // Extra data, can't transform. + + desired_output_for_decode = "abcdefghIJz"; + expected = std::string("\0abcdefghIJz\0", 13); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); +} + +TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) { + std::string input_for_decode("abcdefghIJ"); + std::string desired_output_for_decode; + std::string expected; + std::string result; + + desired_output_for_decode = "abcdefghIJ"; + expected = std::string("\x0A\x0", 2); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + desired_output_for_decode = "_AbcdefghIJ"; + expected = std::string("\xCA\x0", 2); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + desired_output_for_decode = "ABCD__EfghI_j"; + expected = std::string("\x64\x80\xC5\xA1\x0", 5); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); + + // Long name so multiple decode ops are needed. + + input_for_decode = + "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000"; + desired_output_for_decode = + "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000"; + expected = std::string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9); + result = TextFormatDecodeData::DecodeDataForString(input_for_decode, + desired_output_for_decode); + EXPECT_EQ(expected, result); +} + +// Death tests do not work on Windows as of yet. +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) { + // Empty inputs. + + EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + + // Null char in the string. + + std::string str_with_null_char("ab\0c", 4); + EXPECT_EXIT( + TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); + EXPECT_EXIT( + TextFormatDecodeData::DecodeDataForString("def", str_with_null_char), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); +} +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(ObjCHelper, TextFormatDecodeData_RawStrings) { + TextFormatDecodeData decode_data; + + // Different data, can't transform. + decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ"); + decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ"); + // Shortened data, can't transform. + decode_data.AddString(2, "abcdefghIJ", "abcdefghI"); + // Extra data, can't transform. + decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz"); + + EXPECT_EQ(4, decode_data.num_entries()); + + uint8 expected_data[] = { + 0x4, + 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0, + 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0, + 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0, + 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0, + }; + std::string expected((const char*)expected_data, sizeof(expected_data)); + + EXPECT_EQ(expected, decode_data.Data()); +} + +TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) { + TextFormatDecodeData decode_data; + + decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ"); + decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ"); + decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ"); + decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j"); + decode_data.AddString(1000, + "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000", + "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000"); + + EXPECT_EQ(5, decode_data.num_entries()); + + uint8 expected_data[] = { + 0x5, + // All as is (00 op) + 0x1, 0x0A, 0x0, + // Underscore, upper + 9 (10 op) + 0x3, 0xCA, 0x0, + // Upper + 3 (10 op), underscore, upper + 5 (10 op) + 0x2, 0x44, 0xC6, 0x0, + // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op), + // underscore, lower + 0 (01 op) + 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0, + // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op), + // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op), + // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 + // op), + // underscore, as is + 3 (00 op) + 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0, + }; + std::string expected((const char*)expected_data, sizeof(expected_data)); + + EXPECT_EQ(expected, decode_data.Data()); +} + + +// Death tests do not work on Windows as of yet. +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { + TextFormatDecodeData decode_data; + + // Empty inputs. + + EXPECT_EXIT(decode_data.AddString(1, "", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(decode_data.AddString(1, "a", ""), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + EXPECT_EXIT(decode_data.AddString(1, "", "a"), + ::testing::KilledBySignal(SIGABRT), + "error: got empty string for making TextFormat data, input:"); + + // Null char in the string. + + std::string str_with_null_char("ab\0c", 4); + EXPECT_EXIT( + decode_data.AddString(1, str_with_null_char, "def"), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); + EXPECT_EXIT( + decode_data.AddString(1, "def", str_with_null_char), + ::testing::KilledBySignal(SIGABRT), + "error: got a null char in a string for making TextFormat data, input:"); + + // Duplicate keys + + decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ"); + decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ"); + decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ"); + EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"), + ::testing::KilledBySignal(SIGABRT), + "error: duplicate key \\(2\\) making TextFormat data, input:"); +} +#endif // PROTOBUF_HAS_DEATH_TEST + +class TestLineCollector : public LineConsumer { + public: + TestLineCollector(std::vector<std::string>* inout_lines, + const std::string* reject_line = nullptr, + bool skip_msg = false) + : lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {} + + bool ConsumeLine(const StringPiece& line, std::string* out_error) override { + if (reject_ && *reject_ == line) { + if (!skip_msg_) { + *out_error = std::string("Rejected '") + *reject_ + "'"; + } + return false; + } + if (lines_) { + lines_->emplace_back(line); + } + return true; + } + + private: + std::vector<std::string>* lines_; + const std::string* reject_; + bool skip_msg_; +}; + +const int kBlockSizes[] = {-1, 1, 2, 5, 64}; +const int kBlockSizeCount = GOOGLE_ARRAYSIZE(kBlockSizes); + +TEST(ObjCHelper, ParseSimple_BasicsSuccess) { + const std::vector<std::pair<std::string, std::vector<std::string>>> tests = { + {"", {}}, + {"a", {"a"}}, + {"a c", {"a c"}}, + {" a c ", {"a c"}}, + {"\ta c ", {"a c"}}, + {"abc\n", {"abc"}}, + {"abc\nd f", {"abc", "d f"}}, + {"\n abc \n def \n\n", {"abc", "def"}}, + }; + + for (const auto& test : tests) { + for (int i = 0; i < kBlockSizeCount; i++) { + io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]); + std::string err_str; + std::vector<std::string> lines; + TestLineCollector collector(&lines); + EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str)); + EXPECT_EQ(lines, test.second); + EXPECT_TRUE(err_str.empty()); + } + } +} + +TEST(ObjCHelper, ParseSimple_DropsComments) { + const std::vector<std::pair<std::string, std::vector<std::string>>> tests = { + {"# nothing", {}}, + {"#", {}}, + {"##", {}}, + {"\n# nothing\n", {}}, + {"a # same line", {"a"}}, + {"a # same line\n", {"a"}}, + {"a\n# line\nc", {"a", "c"}}, + {"# n o t # h i n g #", {}}, + {"## n o # t h i n g #", {}}, + {"a# n o t # h i n g #", {"a"}}, + {"a\n## n o # t h i n g #", {"a"}}, + }; + + for (const auto& test : tests) { + for (int i = 0; i < kBlockSizeCount; i++) { + io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]); + std::string err_str; + std::vector<std::string> lines; + TestLineCollector collector(&lines); + EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str)); + EXPECT_EQ(lines, test.second); + EXPECT_TRUE(err_str.empty()); + } + } +} + +TEST(ObjCHelper, ParseSimple_RejectLines) { + const std::vector<std::tuple<std::string, std::string, int>> tests = { + std::make_tuple("a\nb\nc", "a", 1), + std::make_tuple("a\nb\nc", "b", 2), + std::make_tuple("a\nb\nc", "c", 3), + std::make_tuple("a\nb\nc\n", "c", 3), + }; + + for (const auto& test : tests) { + for (int i = 0; i < kBlockSizeCount; i++) { + io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(), + kBlockSizes[i]); + std::string err_str; + TestLineCollector collector(nullptr, &std::get<1>(test)); + EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str)); + std::string expected_err = + StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '", std::get<1>(test), "'"); + EXPECT_EQ(err_str, expected_err); + } + } +} + +TEST(ObjCHelper, ParseSimple_RejectLinesNoMessage) { + const std::vector<std::tuple<std::string, std::string, int>> tests = { + std::make_tuple("a\nb\nc", "a", 1), + std::make_tuple("a\nb\nc", "b", 2), + std::make_tuple("a\nb\nc", "c", 3), + std::make_tuple("a\nb\nc\n", "c", 3), + }; + + for (const auto& test : tests) { + for (int i = 0; i < kBlockSizeCount; i++) { + io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(), + kBlockSizes[i]); + std::string err_str; + TestLineCollector collector(nullptr, &std::get<1>(test), true /* skip msg */); + EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str)); + std::string expected_err = + StrCat("error: dummy Line ", std::get<2>(test), + ", ConsumeLine failed without setting an error."); + EXPECT_EQ(err_str, expected_err); + } + } +} + +// 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 +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc new file mode 100644 index 00000000..58681ae4 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -0,0 +1,189 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 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. + +#include <map> +#include <string> + +#include <compiler/objectivec/objectivec_map_field.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// MapFieldGenerator uses RepeatedFieldGenerator as the parent because it +// provides a bunch of things (no has* methods, comments for contained type, +// etc.). + +namespace { + +const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) { + ObjectiveCType type = GetObjectiveCType(descriptor); + switch (type) { + case OBJECTIVECTYPE_INT32: + return "Int32"; + case OBJECTIVECTYPE_UINT32: + return "UInt32"; + case OBJECTIVECTYPE_INT64: + return "Int64"; + case OBJECTIVECTYPE_UINT64: + return "UInt64"; + case OBJECTIVECTYPE_FLOAT: + return "Float"; + case OBJECTIVECTYPE_DOUBLE: + return "Double"; + case OBJECTIVECTYPE_BOOLEAN: + return "Bool"; + case OBJECTIVECTYPE_STRING: + return (isKey ? "String" : "Object"); + case OBJECTIVECTYPE_DATA: + return "Object"; + case OBJECTIVECTYPE_ENUM: + return "Enum"; + case OBJECTIVECTYPE_MESSAGE: + return "Object"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +} // namespace + +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : RepeatedFieldGenerator(descriptor, options) { + const FieldDescriptor* key_descriptor = + descriptor->message_type()->map_key(); + const FieldDescriptor* value_descriptor = + descriptor->message_type()->map_value(); + value_field_generator_.reset(FieldGenerator::Make(value_descriptor, options)); + + // Pull over some variables_ from the value. + variables_["field_type"] = value_field_generator_->variable("field_type"); + variables_["default"] = value_field_generator_->variable("default"); + variables_["default_name"] = value_field_generator_->variable("default_name"); + + // Build custom field flags. + std::vector<std::string> field_flags; + field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor)); + // Pull over the current text format custom name values that was calculated. + if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") != + std::string::npos) { + field_flags.push_back("GPBFieldTextFormatNameCustom"); + } + // Pull over some info from the value's flags. + const std::string& value_field_flags = + value_field_generator_->variable("fieldflags"); + if (value_field_flags.find("GPBFieldHasDefaultValue") != std::string::npos) { + field_flags.push_back("GPBFieldHasDefaultValue"); + } + if (value_field_flags.find("GPBFieldHasEnumDescriptor") != + std::string::npos) { + field_flags.push_back("GPBFieldHasEnumDescriptor"); + } + + variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); + + ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); + const bool value_is_object_type = + ((value_objc_type == OBJECTIVECTYPE_STRING) || + (value_objc_type == OBJECTIVECTYPE_DATA) || + (value_objc_type == OBJECTIVECTYPE_MESSAGE)); + if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) && + value_is_object_type) { + variables_["array_storage_type"] = "NSMutableDictionary"; + variables_["array_property_type"] = + "NSMutableDictionary<NSString*, " + + value_field_generator_->variable("storage_type") + "*>"; + } else { + std::string class_name("GPB"); + class_name += MapEntryTypeName(key_descriptor, true); + class_name += MapEntryTypeName(value_descriptor, false); + class_name += "Dictionary"; + variables_["array_storage_type"] = class_name; + if (value_is_object_type) { + variables_["array_property_type"] = + class_name + "<" + + value_field_generator_->variable("storage_type") + "*>"; + } + } + + variables_["dataTypeSpecific_name"] = + value_field_generator_->variable("dataTypeSpecific_name"); + variables_["dataTypeSpecific_value"] = + value_field_generator_->variable("dataTypeSpecific_value"); +} + +MapFieldGenerator::~MapFieldGenerator() {} + +void MapFieldGenerator::FinishInitialization(void) { + RepeatedFieldGenerator::FinishInitialization(); + // Use the array_comment support in RepeatedFieldGenerator to output what the + // values in the map are. + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) { + variables_["array_comment"] = + "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n"; + } +} + +void MapFieldGenerator::DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const { + RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls); + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { + const std::string& value_storage_type = + value_field_generator_->variable("storage_type"); + fwd_decls->insert("@class " + value_storage_type); + } +} + +void MapFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const { + // Class name is already in "storage_type". + const FieldDescriptor* value_descriptor = + descriptor_->message_type()->FindFieldByName("value"); + if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { + fwd_decls->insert(ObjCClassDeclaration( + value_field_generator_->variable("storage_type"))); + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h new file mode 100644 index 00000000..32371123 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_map_field.h @@ -0,0 +1,71 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 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_COMPILER_OBJECTIVEC_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ + +#include <map> +#include <string> +#include <compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class MapFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + public: + virtual void FinishInitialization(void) override; + + MapFieldGenerator(const MapFieldGenerator&) = delete; + MapFieldGenerator& operator=(const MapFieldGenerator&) = delete; + + protected: + MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options); + virtual ~MapFieldGenerator(); + + virtual void DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const override; + virtual void DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const override; + + private: + std::unique_ptr<FieldGenerator> value_field_generator_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc new file mode 100644 index 00000000..0e8bfec9 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.cc @@ -0,0 +1,636 @@ +// 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. + +#include <algorithm> +#include <iostream> +#include <sstream> + +#include <compiler/objectivec/objectivec_message.h> +#include <compiler/objectivec/objectivec_enum.h> +#include <compiler/objectivec/objectivec_extension.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <stubs/stl_util.h> +#include <stubs/strutil.h> +#include <io/printer.h> +#include <io/coded_stream.h> +#include <io/zero_copy_stream_impl.h> +#include <wire_format.h> +#include <wire_format_lite.h> +#include <descriptor.pb.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { + // The first item in the object structure is our uint32[] for has bits. + // We then want to order things to make the instances as small as + // possible. So we follow the has bits with: + // 1. Anything always 4 bytes - float, *32, enums + // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit + // builds and 4 bytes on 32bit builds. + // 3. Anything always 8 bytes - double, *64 + // + // NOTE: Bools aren't listed, they were stored in the has bits. + // + // Why? Using 64bit builds as an example, this means worse case, we have + // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes + // are wasted before the 4 byte values. Then if we have an odd number of + // those 4 byte values, the 8 byte values will be pushed down by 32bits to + // keep them aligned. But the structure will end 8 byte aligned, so no + // waste on the end. If you did the reverse order, you could waste 4 bytes + // before the first 8 byte value (after the has array), then a single + // bool on the end would need 7 bytes of padding to make the overall + // structure 8 byte aligned; so 11 bytes, wasted total. + + // Anything repeated is a GPB*Array/NSArray, so pointer. + if (descriptor->is_repeated()) { + return 3; + } + + switch (descriptor->type()) { + // All always 8 bytes. + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_FIXED64: + return 4; + + // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes + // depending on the build architecture. + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return 3; + + // All always 4 bytes (enums are int32s). + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_ENUM: + return 2; + + // 0 bytes. Stored in the has bits. + case FieldDescriptor::TYPE_BOOL: + return 99; // End of the list (doesn't really matter). + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; +} + +struct FieldOrderingByStorageSize { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + // Order by grouping. + const int order_group_a = OrderGroupForFieldDescriptor(a); + const int order_group_b = OrderGroupForFieldDescriptor(b); + if (order_group_a != order_group_b) { + return order_group_a < order_group_b; + } + // Within the group, order by field number (provides stable ordering). + return a->number() < b->number(); + } +}; + +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor* [descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber()); + return fields; +} + +// Sort the fields of the given Descriptor by storage size into a new[]'d +// array and return it. +const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor* [descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByStorageSize()); + return fields; +} +} // namespace + +MessageGenerator::MessageGenerator(const std::string& root_classname, + const Descriptor* descriptor, + const Options& options) + : root_classname_(root_classname), + descriptor_(descriptor), + field_generators_(descriptor, options), + class_name_(ClassName(descriptor_)), + deprecated_attribute_(GetOptionalDeprecatedAttribute( + descriptor, descriptor->file(), false, true)) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_.emplace_back( + new ExtensionGenerator(class_name_, descriptor_->extension(i))); + } + + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); + oneof_generators_.emplace_back(generator); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); + enum_generators_.emplace_back(generator); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator* generator = + new MessageGenerator(root_classname_, + descriptor_->nested_type(i), + options); + nested_message_generators_.emplace_back(generator); + } +} + +MessageGenerator::~MessageGenerator() {} + +void MessageGenerator::GenerateStaticVariablesInitialization( + io::Printer* printer) { + for (const auto& generator : extension_generators_) { + generator->GenerateStaticVariablesInitialization(printer); + } + + for (const auto& generator : nested_message_generators_) { + generator->GenerateStaticVariablesInitialization(printer); + } +} + +void MessageGenerator::DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) { + if (!IsMapEntryMessage(descriptor_)) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineForwardDeclarations(fwd_decls); + } + } + + for (const auto& generator : nested_message_generators_) { + generator->DetermineForwardDeclarations(fwd_decls); + } +} + +void MessageGenerator::DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) { + if (!IsMapEntryMessage(descriptor_)) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineObjectiveCClassDefinitions(fwd_decls); + } + } + + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(fwd_decls); + } + + for (const auto& generator : nested_message_generators_) { + generator->DetermineObjectiveCClassDefinitions(fwd_decls); + } + + const Descriptor* containing_descriptor = descriptor_->containing_type(); + if (containing_descriptor != NULL) { + std::string containing_class = ClassName(containing_descriptor); + fwd_decls->insert(ObjCClassDeclaration(containing_class)); + } +} + +bool MessageGenerator::IncludesOneOfDefinition() const { + if (!oneof_generators_.empty()) { + return true; + } + + for (const auto& generator : nested_message_generators_) { + if (generator->IncludesOneOfDefinition()) { + return true; + } + } + + return false; +} + +void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { + for (const auto& generator : enum_generators_) { + generator->GenerateHeader(printer); + } + + for (const auto& generator : nested_message_generators_) { + generator->GenerateEnumHeader(printer); + } +} + +void MessageGenerator::GenerateExtensionRegistrationSource( + io::Printer* printer) { + for (const auto& generator : extension_generators_) { + generator->GenerateRegistrationSource(printer); + } + + for (const auto& generator : nested_message_generators_) { + generator->GenerateExtensionRegistrationSource(printer); + } +} + +void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { + // This a a map entry message, just recurse and do nothing directly. + if (IsMapEntryMessage(descriptor_)) { + for (const auto& generator : nested_message_generators_) { + generator->GenerateMessageHeader(printer); + } + return; + } + + printer->Print( + "#pragma mark - $classname$\n" + "\n", + "classname", class_name_); + + if (descriptor_->field_count()) { + std::unique_ptr<const FieldDescriptor*[]> sorted_fields( + SortFieldsByNumber(descriptor_)); + + printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", + "classname", class_name_); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateFieldNumberConstant(printer); + } + + printer->Outdent(); + printer->Print("};\n\n"); + } + + for (const auto& generator : oneof_generators_) { + generator->GenerateCaseEnum(printer); + } + + std::string message_comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + message_comments = BuildCommentsString(location, false); + } else { + message_comments = ""; + } + + printer->Print( + "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n", + "classname", class_name_, + "deprecated_attribute", deprecated_attribute_, + "comments", message_comments); + + std::vector<char> seen_oneofs(oneof_generators_.size(), 0); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const OneofDescriptor* oneof = field->real_containing_oneof(); + if (oneof) { + const int oneof_index = oneof->index(); + if (!seen_oneofs[oneof_index]) { + seen_oneofs[oneof_index] = 1; + oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( + printer); + } + } + field_generators_.get(field).GeneratePropertyDeclaration(printer); + } + + printer->Print("@end\n\n"); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionDeclarations(printer); + } + + if (!oneof_generators_.empty()) { + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionDeclaration(printer); + } + printer->Print("\n"); + } + + if (descriptor_->extension_count() > 0) { + printer->Print("@interface $classname$ (DynamicMethods)\n\n", + "classname", class_name_); + for (const auto& generator : extension_generators_) { + generator->GenerateMembersHeader(printer); + } + printer->Print("@end\n\n"); + } + + for (const auto& generator : nested_message_generators_) { + generator->GenerateMessageHeader(printer); + } +} + +void MessageGenerator::GenerateSource(io::Printer* printer) { + if (!IsMapEntryMessage(descriptor_)) { + printer->Print( + "#pragma mark - $classname$\n" + "\n", + "classname", class_name_); + + if (!deprecated_attribute_.empty()) { + // No warnings when compiling the impl of this deprecated class. + printer->Print( + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n" + "\n"); + } + + printer->Print("@implementation $classname$\n\n", + "classname", class_name_); + + for (const auto& generator : oneof_generators_) { + generator->GeneratePropertyImplementation(printer); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GeneratePropertyImplementation(printer); + } + + std::unique_ptr<const FieldDescriptor*[]> sorted_fields( + SortFieldsByNumber(descriptor_)); + std::unique_ptr<const FieldDescriptor*[]> size_order_fields( + SortFieldsByStorageSize(descriptor_)); + + std::vector<const Descriptor::ExtensionRange*> sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); + + // Assign has bits: + // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing + // who needs has bits and assigning them. + // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative + // index that groups all the elements in the oneof. + size_t num_has_bits = field_generators_.CalculateHasBits(); + size_t sizeof_has_storage = (num_has_bits + 31) / 32; + if (sizeof_has_storage == 0) { + // In the case where no field needs has bits, don't let the _has_storage_ + // end up as zero length (zero length arrays are sort of a grey area + // since it has to be at the start of the struct). This also ensures a + // field with only oneofs keeps the required negative indices they need. + sizeof_has_storage = 1; + } + // Tell all the fields the oneof base. + for (const auto& generator : oneof_generators_) { + generator->SetOneofIndexBase(sizeof_has_storage); + } + field_generators_.SetOneofIndexBase(sizeof_has_storage); + // sizeof_has_storage needs enough bits for the single fields that aren't in + // any oneof, and then one int32 for each oneof (to store the field number). + sizeof_has_storage += oneof_generators_.size(); + + printer->Print( + "\n" + "typedef struct $classname$__storage_ {\n" + " uint32_t _has_storage_[$sizeof_has_storage$];\n", + "classname", class_name_, + "sizeof_has_storage", StrCat(sizeof_has_storage)); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(size_order_fields[i]) + .GenerateFieldStorageDeclaration(printer); + } + printer->Outdent(); + + 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 = nil;\n" + " if (!descriptor) {\n"); + + TextFormatDecodeData text_format_decode_data; + bool has_fields = descriptor_->field_count() > 0; + bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); + std::string field_description_type; + if (need_defaults) { + field_description_type = "GPBMessageFieldDescriptionWithDefault"; + } else { + field_description_type = "GPBMessageFieldDescription"; + } + if (has_fields) { + printer->Indent(); + printer->Indent(); + printer->Print( + "static $field_description_type$ fields[] = {\n", + "field_description_type", field_description_type); + 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, need_defaults); + 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->Print( + "};\n"); + printer->Outdent(); + printer->Outdent(); + } + + std::map<std::string, std::string> vars; + vars["classname"] = class_name_; + vars["rootclassname"] = root_classname_; + vars["fields"] = has_fields ? "fields" : "NULL"; + if (has_fields) { + vars["fields_count"] = + "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))"; + } else { + vars["fields_count"] = "0"; + } + + std::vector<std::string> init_flags; + init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); + init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); + if (need_defaults) { + init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); + } + if (descriptor_->options().message_set_wire_format()) { + init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); + } + vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, + init_flags); + + printer->Print( + vars, + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" + " rootClass:[$rootclassname$ class]\n" + " file:$rootclassname$_FileDescriptor()\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\n" + " storageSize:sizeof($classname$__storage_)\n" + " flags:$init_flags$];\n"); + if (!oneof_generators_.empty()) { + printer->Print( + " static const char *oneofs[] = {\n"); + for (const auto& generator : oneof_generators_) { + printer->Print(" \"$name$\",\n", "name", + generator->DescriptorName()); + } + printer->Print( + " };\n" + " [localDescriptor setupOneofs:oneofs\n" + " count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n" + " firstHasIndex:$first_has_index$];\n", + "first_has_index", oneof_generators_[0]->HasIndexAsString()); + } + if (text_format_decode_data.num_entries() != 0) { + const std::string text_format_data_str(text_format_decode_data.Data()); + printer->Print( + "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" + " static const char *extraTextFormatInfo ="); + static const int kBytesPerLine = 40; // allow for escaping + for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) { + printer->Print( + "\n \"$data$\"", + "data", EscapeTrigraphs( + CEscape(text_format_data_str.substr(i, kBytesPerLine)))); + } + printer->Print( + ";\n" + " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" + "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); + } + if (!sorted_extensions.empty()) { + printer->Print( + " static const GPBExtensionRange ranges[] = {\n"); + for (int i = 0; i < sorted_extensions.size(); i++) { + printer->Print(" { .start = $start$, .end = $end$ },\n", + "start", StrCat(sorted_extensions[i]->start), + "end", StrCat(sorted_extensions[i]->end)); + } + printer->Print( + " };\n" + " [localDescriptor setupExtensionRanges:ranges\n" + " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); + } + if (descriptor_->containing_type() != NULL) { + std::string containing_class = ClassName(descriptor_->containing_type()); + std::string parent_class_ref = ObjCClass(containing_class); + printer->Print( + " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", + "parent_class_ref", parent_class_ref); + } + std::string suffix_added; + ClassName(descriptor_, &suffix_added); + if (!suffix_added.empty()) { + printer->Print( + " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", + "suffix", suffix_added); + } + printer->Print( + " #if defined(DEBUG) && DEBUG\n" + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " #endif // DEBUG\n" + " descriptor = localDescriptor;\n" + " }\n" + " return descriptor;\n" + "}\n\n" + "@end\n\n"); + + if (!deprecated_attribute_.empty()) { + printer->Print( + "#pragma clang diagnostic pop\n" + "\n"); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionImplementations(printer); + } + + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionImplementation(printer); + } + } + + for (const auto& generator : enum_generators_) { + generator->GenerateSource(printer); + } + + for (const auto& generator : nested_message_generators_) { + generator->GenerateSource(printer); + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h new file mode 100644 index 00000000..64c7b49f --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message.h @@ -0,0 +1,99 @@ +// 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_COMPILER_OBJECTIVEC_MESSAGE_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ + +#include <string> +#include <set> +#include <vector> +#include <compiler/objectivec/objectivec_field.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <compiler/objectivec/objectivec_oneof.h> +#include <descriptor.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class ExtensionGenerator; +class EnumGenerator; + +class MessageGenerator { + public: + MessageGenerator(const std::string& root_classname, + const Descriptor* descriptor, const Options& options); + ~MessageGenerator(); + + MessageGenerator(const MessageGenerator&) = delete; + MessageGenerator& operator=(const MessageGenerator&) = delete; + + 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 DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls); + void DetermineForwardDeclarations(std::set<std::string>* fwd_decls); + + // Checks if the message or a nested message includes a oneof definition. + bool IncludesOneOfDefinition() const; + + private: + void GenerateParseFromMethodsHeader(io::Printer* printer); + + void GenerateSerializeOneFieldSource(io::Printer* printer, + const FieldDescriptor* field); + void GenerateSerializeOneExtensionRangeSource( + io::Printer* printer, const Descriptor::ExtensionRange* range); + + void GenerateMessageDescriptionSource(io::Printer* printer); + void GenerateDescriptionOneFieldSource(io::Printer* printer, + const FieldDescriptor* field); + + const std::string root_classname_; + const Descriptor* descriptor_; + FieldGeneratorMap field_generators_; + const std::string class_name_; + const std::string deprecated_attribute_; + std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; + std::vector<std::unique_ptr<EnumGenerator>> enum_generators_; + std::vector<std::unique_ptr<MessageGenerator>> nested_message_generators_; + std::vector<std::unique_ptr<OneofGenerator>> oneof_generators_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc new file mode 100644 index 00000000..241ae0fa --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -0,0 +1,107 @@ +// 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. + +#include <map> +#include <string> + +#include <compiler/objectivec/objectivec_message_field.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/printer.h> +#include <wire_format.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +void SetMessageVariables(const FieldDescriptor* descriptor, + std::map<std::string, std::string>* variables) { + const std::string& message_type = ClassName(descriptor->message_type()); + const std::string& containing_class = + ClassName(descriptor->containing_type()); + (*variables)["type"] = message_type; + (*variables)["containing_class"] = containing_class; + (*variables)["storage_type"] = message_type; + (*variables)["group_or_message"] = + (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; + (*variables)["dataTypeSpecific_value"] = ObjCClass(message_type); +} + +} // namespace + +MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : ObjCObjFieldGenerator(descriptor, options) { + SetMessageVariables(descriptor, &variables_); +} + +MessageFieldGenerator::~MessageFieldGenerator() {} + +void MessageFieldGenerator::DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const { + ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls); + // Class name is already in "storage_type". + fwd_decls->insert("@class " + variable("storage_type")); +} + +void MessageFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const { + fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); +} + +RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : RepeatedFieldGenerator(descriptor, options) { + SetMessageVariables(descriptor, &variables_); + variables_["array_storage_type"] = "NSMutableArray"; + variables_["array_property_type"] = + "NSMutableArray<" + variables_["storage_type"] + "*>"; +} + +RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} + +void RepeatedMessageFieldGenerator::DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const { + RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls); + // Class name is already in "storage_type". + fwd_decls->insert("@class " + variable("storage_type")); +} + +void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const { + fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h new file mode 100644 index 00000000..7ea99c37 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_message_field.h @@ -0,0 +1,87 @@ +// 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_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ + +#include <map> +#include <string> +#include <compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class MessageFieldGenerator : public ObjCObjFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + protected: + MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + + MessageFieldGenerator(const MessageFieldGenerator&) = delete; + MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete; + + virtual ~MessageFieldGenerator(); + + public: + virtual void DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const override; + virtual void DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const override; +}; + +class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + protected: + RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + virtual ~RepeatedMessageFieldGenerator(); + + RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete; + RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete; + + public: + virtual void DetermineForwardDeclarations( + std::set<std::string>* fwd_decls) const override; + virtual void DetermineObjectiveCClassDefinitions( + std::set<std::string>* fwd_decls) const override; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h new file mode 100644 index 00000000..16330466 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_nsobject_methods.h @@ -0,0 +1,197 @@ +// NSObject methods +// Autogenerated by method_dump.sh. Do not edit by hand. +// Date: Thu Nov 1 14:12:16 PDT 2018 +// macOS: MacOSX10.14.sdk +// iOS: iPhoneSimulator12.1.sdk + +const char* const kNSObjectMethodsList[] = { + "CAMLType", + "CA_copyRenderValue", + "CA_prepareRenderValue", + "NS_copyCGImage", + "NS_tiledLayerVisibleRect", + "___tryRetain_OA", + "__autorelease_OA", + "__dealloc_zombie", + "__release_OA", + "__retain_OA", + "_accessibilityFinalize", + "_accessibilityIsTableViewDescendant", + "_accessibilityUIElementSpecifier", + "_accessibilityUseConvenienceAPI", + "_allowsDirectEncoding", + "_asScriptTerminologyNameArray", + "_asScriptTerminologyNameString", + "_bindingAdaptor", + "_cfTypeID", + "_copyDescription", + "_destroyObserverList", + "_didEndKeyValueObserving", + "_implicitObservationInfo", + "_internalAccessibilityAttributedHint", + "_internalAccessibilityAttributedLabel", + "_internalAccessibilityAttributedValue", + "_isAXConnector", + "_isAccessibilityContainerSectionCandidate", + "_isAccessibilityContentNavigatorSectionCandidate", + "_isAccessibilityContentSectionCandidate", + "_isAccessibilityTopLevelNavigatorSectionCandidate", + "_isDeallocating", + "_isKVOA", + "_isToManyChangeInformation", + "_ivarDescription", + "_localClassNameForClass", + "_methodDescription", + "_observerStorage", + "_overrideUseFastBlockObservers", + "_propertyDescription", + "_releaseBindingAdaptor", + "_scriptingCount", + "_scriptingCountNonrecursively", + "_scriptingDebugDescription", + "_scriptingExists", + "_scriptingShouldCheckObjectIndexes", + "_shortMethodDescription", + "_shouldSearchChildrenForSection", + "_traitStorageList", + "_tryRetain", + "_ui_descriptionBuilder", + "_uikit_variesByTraitCollections", + "_web_description", + "_webkit_invokeOnMainThread", + "_willBeginKeyValueObserving", + "accessibilityActivate", + "accessibilityActivationPoint", + "accessibilityAllowsOverriddenAttributesWhenIgnored", + "accessibilityAssistiveTechnologyFocusedIdentifiers", + "accessibilityAttributedHint", + "accessibilityAttributedLabel", + "accessibilityAttributedValue", + "accessibilityContainer", + "accessibilityContainerType", + "accessibilityCustomActions", + "accessibilityCustomRotors", + "accessibilityDecrement", + "accessibilityDragSourceDescriptors", + "accessibilityDropPointDescriptors", + "accessibilityElementCount", + "accessibilityElementDidBecomeFocused", + "accessibilityElementDidLoseFocus", + "accessibilityElementIsFocused", + "accessibilityElements", + "accessibilityElementsHidden", + "accessibilityFrame", + "accessibilityHeaderElements", + "accessibilityHint", + "accessibilityIdentification", + "accessibilityIdentifier", + "accessibilityIncrement", + "accessibilityLabel", + "accessibilityLanguage", + "accessibilityLocalizedStringKey", + "accessibilityNavigationStyle", + "accessibilityOverriddenAttributes", + "accessibilityParameterizedAttributeNames", + "accessibilityPath", + "accessibilityPerformEscape", + "accessibilityPerformMagicTap", + "accessibilityPresenterProcessIdentifier", + "accessibilityShouldUseUniqueId", + "accessibilitySupportsNotifications", + "accessibilitySupportsOverriddenAttributes", + "accessibilityTemporaryChildren", + "accessibilityTraits", + "accessibilityValue", + "accessibilityViewIsModal", + "accessibilityVisibleArea", + "allPropertyKeys", + "allowsWeakReference", + "attributeKeys", + "autoContentAccessingProxy", + "autorelease", + "awakeFromNib", + "boolValueSafe", + "bs_encoded", + "bs_isPlistableType", + "bs_secureEncoded", + "cl_json_serializeKey", + "class", + "classCode", + "classDescription", + "classForArchiver", + "classForCoder", + "classForKeyedArchiver", + "classForPortCoder", + "className", + "clearProperties", + "copy", + "dealloc", + "debugDescription", + "defaultAccessibilityTraits", + "description", + "doubleValueSafe", + "entityName", + "exposedBindings", + "finalize", + "finishObserving", + "flushKeyBindings", + "hash", + "init", + "int64ValueSafe", + "isAccessibilityElement", + "isAccessibilityElementByDefault", + "isElementAccessibilityExposedToInterfaceBuilder", + "isFault", + "isNSArray__", + "isNSCFConstantString__", + "isNSData__", + "isNSDate__", + "isNSDictionary__", + "isNSNumber__", + "isNSObject__", + "isNSOrderedSet__", + "isNSSet__", + "isNSString__", + "isNSTimeZone__", + "isNSValue__", + "isProxy", + "mutableCopy", + "nilValueForKey", + "objectSpecifier", + "observationInfo", + "pep_onDetachedThread", + "pep_onMainThread", + "pep_onMainThreadIfNecessary", + "prepareForInterfaceBuilder", + "release", + "releaseOnMainThread", + "retain", + "retainCount", + "retainWeakReference", + "scriptingProperties", + "self", + "shouldGroupAccessibilityChildren", + "storedAccessibilityActivationPoint", + "storedAccessibilityContainerType", + "storedAccessibilityElementsHidden", + "storedAccessibilityFrame", + "storedAccessibilityNavigationStyle", + "storedAccessibilityTraits", + "storedAccessibilityViewIsModal", + "storedIsAccessibilityElement", + "storedShouldGroupAccessibilityChildren", + "stringValueSafe", + "superclass", + "toManyRelationshipKeys", + "toOneRelationshipKeys", + "traitStorageList", + "un_safeBoolValue", + "userInterfaceItemIdentifier", + "utf8ValueSafe", + "valuesForKeysWithDictionary", + "zone", +// Protocol: CAAnimatableValue +// Protocol: CARenderValue +// Protocol: NSObject +// Protocol: ROCKRemoteInvocationInterface +}; diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc new file mode 100644 index 00000000..de00a1f4 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -0,0 +1,140 @@ +// 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. + +#include <map> +#include <string> + +#include <compiler/objectivec/objectivec_oneof.h> +#include <compiler/objectivec/objectivec_helpers.h> +#include <io/printer.h> +#include <stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor) + : descriptor_(descriptor) { + variables_["enum_name"] = OneofEnumName(descriptor_); + variables_["name"] = OneofName(descriptor_); + variables_["capitalized_name"] = OneofNameCapitalized(descriptor_); + variables_["raw_index"] = StrCat(descriptor_->index()); + const Descriptor* msg_descriptor = descriptor_->containing_type(); + variables_["owning_message_class"] = ClassName(msg_descriptor); + + std::string comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + comments = BuildCommentsString(location, true); + } else { + comments = ""; + } + variables_["comments"] = comments; +} + +OneofGenerator::~OneofGenerator() {} + +void OneofGenerator::SetOneofIndexBase(int index_base) { + int index = descriptor_->index() + index_base; + // Flip the sign to mark it as a oneof. + variables_["index"] = StrCat(-index); +} + +void OneofGenerator::GenerateCaseEnum(io::Printer* printer) { + printer->Print( + variables_, + "typedef GPB_ENUM($enum_name$) {\n"); + printer->Indent(); + printer->Print( + variables_, + "$enum_name$_GPBUnsetOneOfCase = 0,\n"); + std::string enum_name = variables_["enum_name"]; + for (int j = 0; j < descriptor_->field_count(); j++) { + const FieldDescriptor* field = descriptor_->field(j); + std::string field_name = FieldNameCapitalized(field); + printer->Print( + "$enum_name$_$field_name$ = $field_number$,\n", + "enum_name", enum_name, + "field_name", field_name, + "field_number", StrCat(field->number())); + } + printer->Outdent(); + printer->Print( + "};\n" + "\n"); +} + +void OneofGenerator::GeneratePublicCasePropertyDeclaration( + io::Printer* printer) { + printer->Print( + variables_, + "$comments$" + "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n" + "\n"); +} + +void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) { + printer->Print( + variables_, + "/**\n" + " * Clears whatever value was set for the oneof '$name$'.\n" + " **/\n" + "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n"); +} + +void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) { + printer->Print( + variables_, + "@dynamic $name$OneOfCase;\n"); +} + +void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { + printer->Print( + variables_, + "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" + " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" + " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n" + " GPBClearOneof(message, oneof);\n" + "}\n"); +} + +std::string OneofGenerator::DescriptorName(void) const { + return variables_.find("name")->second; +} + +std::string OneofGenerator::HasIndexAsString(void) const { + return variables_.find("index")->second; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h new file mode 100644 index 00000000..3d59f4ff --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_oneof.h @@ -0,0 +1,76 @@ +// 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_COMPILER_OBJECTIVEC_ONEOF_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ + +#include <string> +#include <set> +#include <vector> +#include <descriptor.h> +#include <io/printer.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class OneofGenerator { + public: + explicit OneofGenerator(const OneofDescriptor* descriptor); + ~OneofGenerator(); + + OneofGenerator(const OneofGenerator&) = delete; + OneofGenerator& operator=(const OneofGenerator&) = delete; + + void SetOneofIndexBase(int index_base); + + void GenerateCaseEnum(io::Printer* printer); + + void GeneratePublicCasePropertyDeclaration(io::Printer* printer); + void GenerateClearFunctionDeclaration(io::Printer* printer); + + void GeneratePropertyImplementation(io::Printer* printer); + void GenerateClearFunctionImplementation(io::Printer* printer); + + std::string DescriptorName(void) const; + std::string HasIndexAsString(void) const; + + private: + const OneofDescriptor* descriptor_; + std::map<std::string, std::string> variables_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc new file mode 100644 index 00000000..7b5eec0c --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.cc @@ -0,0 +1,190 @@ +// 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. + +#include <map> +#include <string> + +#include <compiler/objectivec/objectivec_helpers.h> +#include <compiler/objectivec/objectivec_primitive_field.h> +#include <io/printer.h> +#include <stubs/strutil.h> +#include <wire_format.h> +#include <wire_format_lite.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { + ObjectiveCType type = GetObjectiveCType(descriptor); + switch (type) { + case OBJECTIVECTYPE_INT32: + return "int32_t"; + case OBJECTIVECTYPE_UINT32: + return "uint32_t"; + case OBJECTIVECTYPE_INT64: + return "int64_t"; + case OBJECTIVECTYPE_UINT64: + return "uint64_t"; + case OBJECTIVECTYPE_FLOAT: + return "float"; + case OBJECTIVECTYPE_DOUBLE: + return "double"; + case OBJECTIVECTYPE_BOOLEAN: + return "BOOL"; + case OBJECTIVECTYPE_STRING: + return "NSString"; + case OBJECTIVECTYPE_DATA: + return "NSData"; + case OBJECTIVECTYPE_ENUM: + return "int32_t"; + case OBJECTIVECTYPE_MESSAGE: + return NULL; // Messages go through objectivec_message_field.cc|h. + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { + ObjectiveCType type = GetObjectiveCType(descriptor); + switch (type) { + case OBJECTIVECTYPE_INT32: + return "Int32"; + case OBJECTIVECTYPE_UINT32: + return "UInt32"; + case OBJECTIVECTYPE_INT64: + return "Int64"; + case OBJECTIVECTYPE_UINT64: + return "UInt64"; + case OBJECTIVECTYPE_FLOAT: + return "Float"; + case OBJECTIVECTYPE_DOUBLE: + return "Double"; + case OBJECTIVECTYPE_BOOLEAN: + return "Bool"; + case OBJECTIVECTYPE_STRING: + return ""; // Want NSArray + case OBJECTIVECTYPE_DATA: + return ""; // Want NSArray + case OBJECTIVECTYPE_ENUM: + return "Enum"; + case OBJECTIVECTYPE_MESSAGE: + // Want NSArray (but goes through objectivec_message_field.cc|h). + return ""; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + std::map<std::string, std::string>* variables) { + std::string primitive_name = PrimitiveTypeName(descriptor); + (*variables)["type"] = primitive_name; + (*variables)["storage_type"] = primitive_name; +} + +} // namespace + +PrimitiveFieldGenerator::PrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : SingleFieldGenerator(descriptor, options) { + SetPrimitiveVariables(descriptor, &variables_); +} + +PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} + +void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration( + io::Printer* printer) const { + if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { + // Nothing, BOOLs are stored in the has bits. + } else { + SingleFieldGenerator::GenerateFieldStorageDeclaration(printer); + } +} + +int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { + if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { + // Reserve a bit for the storage of the boolean. + return 1; + } + return 0; +} + +void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) { + if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { + // Set into the offset the has bit to use for the actual value. + variables_["storage_offset_value"] = StrCat(has_base); + variables_["storage_offset_comment"] = + " // Stored in _has_storage_ to save space."; + } +} + +PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : ObjCObjFieldGenerator(descriptor, options) { + SetPrimitiveVariables(descriptor, &variables_); + variables_["property_storage_attribute"] = "copy"; +} + +PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {} + +RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : RepeatedFieldGenerator(descriptor, options) { + SetPrimitiveVariables(descriptor, &variables_); + + std::string base_name = PrimitiveArrayTypeName(descriptor); + if (base_name.length()) { + variables_["array_storage_type"] = "GPB" + base_name + "Array"; + } else { + variables_["array_storage_type"] = "NSMutableArray"; + variables_["array_property_type"] = + "NSMutableArray<" + variables_["storage_type"] + "*>"; + } +} + +RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h new file mode 100644 index 00000000..88e91ba8 --- /dev/null +++ b/NorthstarDedicatedTest/include/protobuf/compiler/objectivec/objectivec_primitive_field.h @@ -0,0 +1,95 @@ +// 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_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ + +#include <map> +#include <string> +#include <compiler/objectivec/objectivec_field.h> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +class PrimitiveFieldGenerator : public SingleFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + protected: + PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + virtual ~PrimitiveFieldGenerator(); + + PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete; + PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete; + + virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + + virtual int ExtraRuntimeHasBitsNeeded(void) const override; + virtual void SetExtraRuntimeHasBitsBase(int index_base) override; +}; + +class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + protected: + PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + virtual ~PrimitiveObjFieldGenerator(); + + PrimitiveObjFieldGenerator(const PrimitiveObjFieldGenerator&) = delete; + PrimitiveObjFieldGenerator& operator=(const PrimitiveObjFieldGenerator&) = + delete; +}; + +class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { + friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field, + const Options& options); + + protected: + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + virtual ~RepeatedPrimitiveFieldGenerator(); + + RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = + delete; + RepeatedPrimitiveFieldGenerator& operator=( + const RepeatedPrimitiveFieldGenerator&) = delete; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ |