Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2015 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
4 : //
5 : // Redistribution and use in source and binary forms, with or without
6 : // modification, are permitted provided that the following conditions are
7 : // met:
8 : //
9 : // * Redistributions of source code must retain the above copyright
10 : // notice, this list of conditions and the following disclaimer.
11 : // * Redistributions in binary form must reproduce the above
12 : // copyright notice, this list of conditions and the following disclaimer
13 : // in the documentation and/or other materials provided with the
14 : // distribution.
15 : // * Neither the name of Google Inc. nor the names of its
16 : // contributors may be used to endorse or promote products derived from
17 : // this software without specific prior written permission.
18 : //
19 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 :
31 : #include <map>
32 : #include <string>
33 :
34 : #include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
35 : #include <google/protobuf/stubs/common.h>
36 : #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
37 : #include <google/protobuf/io/printer.h>
38 : #include <google/protobuf/stubs/strutil.h>
39 : #include <google/protobuf/stubs/substitute.h>
40 :
41 : namespace google {
42 : namespace protobuf {
43 : namespace compiler {
44 : namespace objectivec {
45 :
46 : // MapFieldGenerator uses RepeatedFieldGenerator as the parent because it
47 : // provides a bunch of things (no has* methods, comments for contained type,
48 : // etc.).
49 :
50 : namespace {
51 :
52 0 : const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
53 0 : ObjectiveCType type = GetObjectiveCType(descriptor);
54 0 : switch (type) {
55 : case OBJECTIVECTYPE_INT32:
56 : return "Int32";
57 : case OBJECTIVECTYPE_UINT32:
58 0 : return "UInt32";
59 : case OBJECTIVECTYPE_INT64:
60 0 : return "Int64";
61 : case OBJECTIVECTYPE_UINT64:
62 0 : return "UInt64";
63 : case OBJECTIVECTYPE_FLOAT:
64 0 : return "Float";
65 : case OBJECTIVECTYPE_DOUBLE:
66 0 : return "Double";
67 : case OBJECTIVECTYPE_BOOLEAN:
68 0 : return "Bool";
69 : case OBJECTIVECTYPE_STRING:
70 0 : return (isKey ? "String" : "Object");
71 : case OBJECTIVECTYPE_DATA:
72 0 : return "Object";
73 : case OBJECTIVECTYPE_ENUM:
74 0 : return "Enum";
75 : case OBJECTIVECTYPE_MESSAGE:
76 0 : return "Object";
77 : }
78 :
79 : // Some compilers report reaching end of function even though all cases of
80 : // the enum are handed in the switch.
81 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
82 0 : return NULL;
83 : }
84 :
85 : } // namespace
86 :
87 0 : MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
88 0 : : RepeatedFieldGenerator(descriptor) {
89 : const FieldDescriptor* key_descriptor =
90 0 : descriptor->message_type()->FindFieldByName("key");
91 : const FieldDescriptor* value_descriptor =
92 0 : descriptor->message_type()->FindFieldByName("value");
93 0 : value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
94 :
95 : // Pull over some variables_ from the value.
96 0 : variables_["field_type"] = value_field_generator_->variable("field_type");
97 0 : variables_["default"] = value_field_generator_->variable("default");
98 0 : variables_["default_name"] = value_field_generator_->variable("default_name");
99 :
100 : // Build custom field flags.
101 : std::vector<string> field_flags;
102 0 : field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor));
103 : // Pull over the current text format custom name values that was calculated.
104 0 : if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") !=
105 : string::npos) {
106 0 : field_flags.push_back("GPBFieldTextFormatNameCustom");
107 : }
108 : // Pull over some info from the value's flags.
109 : const string& value_field_flags =
110 0 : value_field_generator_->variable("fieldflags");
111 0 : if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) {
112 0 : field_flags.push_back("GPBFieldHasDefaultValue");
113 : }
114 0 : if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
115 0 : field_flags.push_back("GPBFieldHasEnumDescriptor");
116 : }
117 0 : variables_["fieldflags"] = BuildFlagsString(field_flags);
118 :
119 0 : ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
120 0 : if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
121 0 : ((value_objc_type == OBJECTIVECTYPE_STRING) ||
122 0 : (value_objc_type == OBJECTIVECTYPE_DATA) ||
123 0 : (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
124 0 : variables_["array_storage_type"] = "NSMutableDictionary";
125 : } else {
126 0 : string base_name = MapEntryTypeName(key_descriptor, true);
127 0 : base_name += MapEntryTypeName(value_descriptor, false);
128 : base_name += "Dictionary";
129 0 : variables_["array_storage_type"] = "GPB" + base_name;
130 0 : }
131 0 : }
132 :
133 0 : MapFieldGenerator::~MapFieldGenerator() {}
134 :
135 0 : void MapFieldGenerator::FinishInitialization(void) {
136 0 : RepeatedFieldGenerator::FinishInitialization();
137 : // Use the array_comment suport in RepeatedFieldGenerator to output what the
138 : // values in the map are.
139 : const FieldDescriptor* value_descriptor =
140 0 : descriptor_->message_type()->FindFieldByName("value");
141 0 : ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
142 0 : if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
143 0 : (value_objc_type == OBJECTIVECTYPE_DATA) ||
144 0 : (value_objc_type == OBJECTIVECTYPE_STRING) ||
145 0 : (value_objc_type == OBJECTIVECTYPE_ENUM)) {
146 0 : variables_["array_comment"] =
147 0 : "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
148 : } else {
149 0 : variables_["array_comment"] = "";
150 : }
151 0 : }
152 :
153 0 : void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
154 : io::Printer* printer) const {
155 : // Relay it to the value generator to provide enum validator, message
156 : // class, etc.
157 0 : value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
158 0 : }
159 :
160 : } // namespace objectivec
161 : } // namespace compiler
162 : } // namespace protobuf
163 : } // namespace google
|