123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- // 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/common.h>
- #include <google/protobuf/stubs/strutil.h>
- namespace google {
- namespace protobuf {
- namespace compiler {
- namespace objectivec {
- namespace {
- void SetCommonFieldVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- string camel_case_name = FieldName(descriptor);
- 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 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);
- } else {
- (*variables)["comments"] = "\n";
- }
- const string& classname = ClassName(descriptor->containing_type());
- (*variables)["classname"] = classname;
- (*variables)["name"] = camel_case_name;
- const 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"] = SimpleItoa(descriptor->number());
- (*variables)["field_type"] = GetCapitalizedType(descriptor);
- (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
- std::vector<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");
- }
- (*variables)["fieldflags"] = BuildFlagsString(field_flags);
- (*variables)["default"] = DefaultValue(descriptor);
- (*variables)["default_name"] = GPBGenericValueFieldName(descriptor);
- (*variables)["dataTypeSpecific_name"] = "className";
- (*variables)["dataTypeSpecific_value"] = "NULL";
- (*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(
- set<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"] = SimpleItoa(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.
- cerr << "Error: should have overriden SetExtraRuntimeHasBitsBase()." << endl;
- cerr.flush();
- abort();
- }
- void FieldGenerator::SetOneofIndexBase(int index_base) {
- if (descriptor_->containing_oneof() != NULL) {
- int index = descriptor_->containing_oneof()->index() + index_base;
- // Flip the sign to mark it as a oneof.
- variables_["has_index"] = SimpleItoa(-index);
- }
- }
- 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::WantsHasProperty(void) const {
- if (descriptor_->containing_oneof() != NULL) {
- // If in a oneof, it uses the oneofcase instead of a has bit.
- return false;
- }
- if (HasFieldPresence(descriptor_->file())) {
- // In proto1/proto2, every field has a has_$name$() method.
- return true;
- }
- return false;
- }
- bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
- if (descriptor_->containing_oneof() != NULL) {
- // 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::WantsHasProperty(void) const {
- // Consumer check the array size/existance rather than a has bit.
- return false;
- }
- bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
- return false; // The array having anything is what is used.
- }
- FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor),
- field_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
- extension_generators_(
- new scoped_ptr<FieldGenerator>[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
|