Media CAS Proxy SDK release: 16.5.0

This commit is contained in:
Buildbot
2021-07-12 21:46:29 +00:00
parent 760d53c347
commit d69222d492
1968 changed files with 638006 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
#!/bin/bash
# Updates objectivec_nsobject_methods.h by generating a list of all of the properties
# and methods on NSObject that Protobufs should not overload from iOS and macOS combined.
#
# The rules:
# - No property should ever be overloaded.
# - Do not overload any methods that have 0 args such as "autorelease".
# - Do not overload any methods that start with "set[A-Z]" and have 1 arg such as
# "setValuesForKeysWithDictionary:". Note that these will end up in the list as just
# the "proto field" name, so "setValuesForKeysWithDictionary:" will become
# "valuesForKeysWithDictionary".
set -eu
trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
echo -n "$var"
}
objc_code=$(cat <<'END_CODE'
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
Class cls = [NSObject class];
// List out the protocols on NSObject just so we are aware if they change.
unsigned int protocolCount;
__unsafe_unretained Protocol **protocols =
class_copyProtocolList(cls, &protocolCount);
for (unsigned int i = 0; i < protocolCount; i++) {
printf("// Protocol: %s\n", protocol_getName(protocols[i]));
}
free(protocols);
// Grab all the properties.
unsigned int propCount;
objc_property_t *props = class_copyPropertyList(cls, &propCount);
NSMutableSet *reservedNames = [[NSMutableSet alloc] init];
for (unsigned int i = 0; i < propCount; ++i) {
NSString *propertyName = [NSString stringWithUTF8String:property_getName(props[i])];
[reservedNames addObject:propertyName];
}
free(props);
// Note that methods have 2 defaults args (_cmd and SEL) so a method "0 arg method"
// actually has 2.
unsigned int methodCount;
Method *methods = class_copyMethodList(cls, &methodCount);
for (unsigned int i = 0; i < methodCount; ++i) {
int argCount = method_getNumberOfArguments(methods[i]);
NSString *methodName =
[NSString stringWithUTF8String:sel_getName(method_getName(methods[i]))];
if (argCount == 2) {
[reservedNames addObject:methodName];
}
if (argCount == 3 && [methodName hasPrefix:@"set"] && methodName.length > 4) {
NSString *firstLetter = [methodName substringWithRange:NSMakeRange(3,1)];
NSString *lowerFirstLetter = [firstLetter lowercaseString];
if ([lowerFirstLetter isEqual:firstLetter]) {
// Make sure the next letter is a capital letter so we do not take things like
// settingSomething:
continue;
}
// -5 because 3 for set, 1 for the firstLetter and 1 for the colon on the end.
NSString *restOfString =
[methodName substringWithRange:NSMakeRange(4, methodName.length - 5)];
methodName = [lowerFirstLetter stringByAppendingString:restOfString];
[reservedNames addObject:methodName];
}
}
free(methods);
SEL sortSelector = @selector(caseInsensitiveCompare:);
NSArray *array = [reservedNames.allObjects sortedArrayUsingSelector:sortSelector];
for (NSString *item in array) {
// Some items with _ in them get returned in quotes, so do not add more.
if ([item hasPrefix:@"\""]) {
printf("\t%s,\n", item.UTF8String);
} else {
printf("\t\"%s\",\n", item.UTF8String);
}
}
}
return 0;
}
END_CODE
)
file_header=$(cat <<'END_HEADER'
// NSObject methods
// Autogenerated by method_dump.sh. Do not edit by hand.
// Date: %DATE%
// macOS: %MACOS%
// iOS: %IOS%
const char* const kNSObjectMethodsList[] = {
END_HEADER
)
file_footer=$(cat <<'END_FOOTER'
};
END_FOOTER
)
# Check to make sure we are updating the correct file.
if [[ ! -e "objectivec_nsobject_methods.h" ]]; then
echo "error: Must be run in the src/google/protobuf/compiler/objectivec directory"
exit 1
fi
temp_dir=$(mktemp -d)
echo "$objc_code" >> "$temp_dir"/method_dump.m
# Compile up iphonesimulator and macos version of cmd line app.
iphone_simulator_sdk=$(xcrun --sdk iphonesimulator --show-sdk-path)
clang -isysroot "$iphone_simulator_sdk" -o "$temp_dir"/method_dump_ios \
-framework Foundation -framework UIKit "$temp_dir"/method_dump.m
macos_sdk=$(xcrun --sdk macosx --show-sdk-path)
clang -isysroot "$macos_sdk" -o "$temp_dir"/method_dump_macos -framework Foundation \
-framework Cocoa "$temp_dir"/method_dump.m
# Create a device of the latest phone and iphonesimulator SDK and run our iOS cmd line.
device_type=$(xcrun simctl list devicetypes | grep \.iPhone- | tail -1 | sed 's/.*(\(.*\))/\1/')
# runtimes come with a space at the end (for Xcode 10) so let's trim all of our input to
# be safe.
device_type=$(trim "$device_type")
runtime=$(xcrun simctl list runtimes | grep \.iOS- | tail -1 | \
sed 's/.*\(com\.apple.\CoreSimulator\.SimRuntime\.iOS.*\)/\1/')
runtime=$(trim "$runtime")
uuid=$(uuidgen)
device_name="method_dump_device_$uuid"
device=$(xcrun simctl create "$device_name" "$device_type" "$runtime")
xcrun simctl spawn "$device" "$temp_dir"/method_dump_ios > "$temp_dir"/methods_unsorted_ios.txt
xcrun simctl delete "$device"
# Run the Mac version
"$temp_dir"/method_dump_macos >> "$temp_dir"/methods_unsorted_macos.txt
# Generate sorted output
echo "$file_header" | sed -e "s|%DATE%|$(date)|" -e "s|%MACOS%|$(basename $macos_sdk)|" \
-e "s|%IOS%|$(basename $iphone_simulator_sdk)|" > "$temp_dir"/methods_sorted.txt
sort -u "$temp_dir"/methods_unsorted_ios.txt \
"$temp_dir"/methods_unsorted_macos.txt >> "$temp_dir"/methods_sorted.txt
echo $"$file_footer" >> "$temp_dir"/methods_sorted.txt
# Check for differences. Turn off error checking because we expect diff to fail when
# there are no differences.
set +e
diff_out=$(diff -I "^//.*$" "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h)
removed_methods=$(echo "$diff_out" | grep '^>.*$')
set -e
if [[ -n "$removed_methods" ]]; then
echo "error: Methods removed from NSObject"
echo "It appears that some methods may have been removed from NSObject."
echo "This could mean that there may be some backwards compatibility issues."
echo "You could potentially build apps that may not work on earlier systems than:"
echo "$iphone_simulator_sdk"
echo "$macos_sdk"
echo "If they declare protobuf types that use any of the following as names:"
echo "$removed_methods"
echo ""
echo "New Version: $temp_dir/methods_sorted.txt"
echo "Old Version: objectivec_nsobject_methods.h"
exit 1
fi
if [[ -n "$diff_out" ]]; then
echo "Added Methods:"
echo "$(echo "$diff_out" | grep '^<.*$' | sed -e 's/^< "\(.*\)",$/ \1/')"
fi;
cp "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h
rm -rf "$temp_dir"

View File

@@ -0,0 +1,261 @@
// 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 <google/protobuf/compiler/objectivec/objectivec_enum.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/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;
}
SourceLocation location;
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

View File

@@ -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 <google/protobuf/descriptor.h>
#include <google/protobuf/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__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/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

View File

@@ -0,0 +1,78 @@
// 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 <google/protobuf/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;
virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
virtual void DetermineForwardDeclarations(
std::set<std::string>* fwd_decls) const;
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();
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__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_extension.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/descriptor.h>
#include <google/protobuf/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__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/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;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
virtual void GeneratePropertyImplementation(io::Printer* printer) const;
virtual bool RuntimeUsesHasBit(void) const;
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;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
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;
virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
virtual void GeneratePropertyImplementation(io::Printer* printer) const;
virtual bool RuntimeUsesHasBit(void) const;
protected:
RepeatedFieldGenerator(const FieldDescriptor* descriptor,
const Options& options);
virtual void FinishInitialization(void);
};
// 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__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_file.h>
#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
#include <google/protobuf/compiler/objectivec/objectivec_message.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/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 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

View File

@@ -0,0 +1,84 @@
// 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 <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/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);
const std::string& RootClassName() const { return root_class_name_; }
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__

View File

@@ -0,0 +1,182 @@
// 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 <string>
#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
#include <google/protobuf/compiler/objectivec/objectivec_file.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace objectivec {
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 == "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 {
*error = "error: Unknown generator option: " + options[i].first;
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.
{
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

View File

@@ -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 <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/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 <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,329 @@
// 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 <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/port_def.inc>
namespace google {
namespace protobuf {
namespace compiler {
namespace objectivec {
// 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;
};
// Escape C++ trigraphs by escaping question marks to "\?".
std::string PROTOC_EXPORT EscapeTrigraphs(const std::string& to_escape);
// Strips ".proto" or ".protodevel" from the end of a filename.
std::string PROTOC_EXPORT StripProto(const std::string& filename);
// 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.
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 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, 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);
// 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);
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 <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__

View File

@@ -0,0 +1,257 @@
// 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 <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/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
// 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

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_map_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/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);
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;
virtual void DetermineForwardDeclarations(
std::set<std::string>* fwd_decls) const;
private:
std::unique_ptr<FieldGenerator> value_field_generator_;
};
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_message.h>
#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/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__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_message_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/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;
virtual void DetermineObjectiveCClassDefinitions(
std::set<std::string>* fwd_decls) const;
};
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;
virtual void DetermineObjectiveCClassDefinitions(
std::set<std::string>* fwd_decls) const;
};
} // namespace objectivec
} // namespace compiler
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__

View File

@@ -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
};

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_oneof.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/descriptor.h>
#include <google/protobuf/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__

View File

@@ -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 <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/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

View File

@@ -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 <google/protobuf/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;
virtual int ExtraRuntimeHasBitsNeeded(void) const;
virtual void SetExtraRuntimeHasBitsBase(int index_base);
};
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__