1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 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_helpers.h>
35 #include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
36 #include <google/protobuf/io/printer.h>
37 #include <google/protobuf/stubs/strutil.h>
38 
39 namespace google {
40 namespace protobuf {
41 namespace compiler {
42 namespace objectivec {
43 
44 using internal::WireFormat;
45 using internal::WireFormatLite;
46 
47 namespace {
48 
PrimitiveTypeName(const FieldDescriptor * descriptor)49 const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
50   ObjectiveCType type = GetObjectiveCType(descriptor);
51   switch (type) {
52     case OBJECTIVECTYPE_INT32:
53       return "int32_t";
54     case OBJECTIVECTYPE_UINT32:
55       return "uint32_t";
56     case OBJECTIVECTYPE_INT64:
57       return "int64_t";
58     case OBJECTIVECTYPE_UINT64:
59       return "uint64_t";
60     case OBJECTIVECTYPE_FLOAT:
61       return "float";
62     case OBJECTIVECTYPE_DOUBLE:
63       return "double";
64     case OBJECTIVECTYPE_BOOLEAN:
65       return "BOOL";
66     case OBJECTIVECTYPE_STRING:
67       return "NSString";
68     case OBJECTIVECTYPE_DATA:
69       return "NSData";
70     case OBJECTIVECTYPE_ENUM:
71       return "int32_t";
72     case OBJECTIVECTYPE_MESSAGE:
73       return NULL;  // Messages go through objectivec_message_field.cc|h.
74   }
75 
76   // Some compilers report reaching end of function even though all cases of
77   // the enum are handed in the switch.
78   GOOGLE_LOG(FATAL) << "Can't get here.";
79   return NULL;
80 }
81 
PrimitiveArrayTypeName(const FieldDescriptor * descriptor)82 const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
83   ObjectiveCType type = GetObjectiveCType(descriptor);
84   switch (type) {
85     case OBJECTIVECTYPE_INT32:
86       return "Int32";
87     case OBJECTIVECTYPE_UINT32:
88       return "UInt32";
89     case OBJECTIVECTYPE_INT64:
90       return "Int64";
91     case OBJECTIVECTYPE_UINT64:
92       return "UInt64";
93     case OBJECTIVECTYPE_FLOAT:
94       return "Float";
95     case OBJECTIVECTYPE_DOUBLE:
96       return "Double";
97     case OBJECTIVECTYPE_BOOLEAN:
98       return "Bool";
99     case OBJECTIVECTYPE_STRING:
100       return "";  // Want NSArray
101     case OBJECTIVECTYPE_DATA:
102       return "";  // Want NSArray
103     case OBJECTIVECTYPE_ENUM:
104       return "Enum";
105     case OBJECTIVECTYPE_MESSAGE:
106       // Want NSArray (but goes through objectivec_message_field.cc|h).
107       return "";
108   }
109 
110   // Some compilers report reaching end of function even though all cases of
111   // the enum are handed in the switch.
112   GOOGLE_LOG(FATAL) << "Can't get here.";
113   return NULL;
114 }
115 
SetPrimitiveVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables)116 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
117                            std::map<std::string, std::string>* variables) {
118   std::string primitive_name = PrimitiveTypeName(descriptor);
119   (*variables)["type"] = primitive_name;
120   (*variables)["storage_type"] = primitive_name;
121 }
122 
123 }  // namespace
124 
PrimitiveFieldGenerator(const FieldDescriptor * descriptor)125 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
126     const FieldDescriptor* descriptor)
127     : SingleFieldGenerator(descriptor) {
128   SetPrimitiveVariables(descriptor, &variables_);
129 }
130 
~PrimitiveFieldGenerator()131 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
132 
GenerateFieldStorageDeclaration(io::Printer * printer) const133 void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration(
134     io::Printer* printer) const {
135   if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
136     // Nothing, BOOLs are stored in the has bits.
137   } else {
138     SingleFieldGenerator::GenerateFieldStorageDeclaration(printer);
139   }
140 }
141 
ExtraRuntimeHasBitsNeeded(void) const142 int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
143   if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
144     // Reserve a bit for the storage of the boolean.
145     return 1;
146   }
147   return 0;
148 }
149 
SetExtraRuntimeHasBitsBase(int has_base)150 void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) {
151   if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
152     // Set into the offset the has bit to use for the actual value.
153     variables_["storage_offset_value"] = StrCat(has_base);
154     variables_["storage_offset_comment"] =
155         "  // Stored in _has_storage_ to save space.";
156   }
157 }
158 
PrimitiveObjFieldGenerator(const FieldDescriptor * descriptor)159 PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
160     const FieldDescriptor* descriptor)
161     : ObjCObjFieldGenerator(descriptor) {
162   SetPrimitiveVariables(descriptor, &variables_);
163   variables_["property_storage_attribute"] = "copy";
164 }
165 
~PrimitiveObjFieldGenerator()166 PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
167 
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor)168 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
169     const FieldDescriptor* descriptor)
170     : RepeatedFieldGenerator(descriptor) {
171   SetPrimitiveVariables(descriptor, &variables_);
172 
173   std::string base_name = PrimitiveArrayTypeName(descriptor);
174   if (base_name.length()) {
175     variables_["array_storage_type"] = "GPB" + base_name + "Array";
176   } else {
177     variables_["array_storage_type"] = "NSMutableArray";
178     variables_["array_property_type"] =
179         "NSMutableArray<" + variables_["storage_type"] + "*>";
180   }
181 }
182 
~RepeatedPrimitiveFieldGenerator()183 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
184 
185 }  // namespace objectivec
186 }  // namespace compiler
187 }  // namespace protobuf
188 }  // namespace google
189