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
39namespace google {
40namespace protobuf {
41namespace compiler {
42namespace objectivec {
43
44using internal::WireFormat;
45using internal::WireFormatLite;
46
47namespace {
48
49const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
50 ObjectiveCType type = GetObjectiveCType(field: 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
82const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
83 ObjectiveCType type = GetObjectiveCType(field: 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
116void 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
125PrimitiveFieldGenerator::PrimitiveFieldGenerator(
126 const FieldDescriptor* descriptor)
127 : SingleFieldGenerator(descriptor) {
128 SetPrimitiveVariables(descriptor, variables: &variables_);
129}
130
131PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
132
133void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration(
134 io::Printer* printer) const {
135 if (GetObjectiveCType(field: descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
136 // Nothing, BOOLs are stored in the has bits.
137 } else {
138 SingleFieldGenerator::GenerateFieldStorageDeclaration(printer);
139 }
140}
141
142int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
143 if (GetObjectiveCType(field: descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
144 // Reserve a bit for the storage of the boolean.
145 return 1;
146 }
147 return 0;
148}
149
150void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) {
151 if (GetObjectiveCType(field: descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
152 // Set into the offset the has bit to use for the actual value.
153 variables_["storage_offset_value"] = StrCat(a: has_base);
154 variables_["storage_offset_comment"] =
155 " // Stored in _has_storage_ to save space.";
156 }
157}
158
159PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
160 const FieldDescriptor* descriptor)
161 : ObjCObjFieldGenerator(descriptor) {
162 SetPrimitiveVariables(descriptor, variables: &variables_);
163 variables_["property_storage_attribute"] = "copy";
164}
165
166PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
167
168RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
169 const FieldDescriptor* descriptor)
170 : RepeatedFieldGenerator(descriptor) {
171 SetPrimitiveVariables(descriptor, variables: &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
183RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
184
185} // namespace objectivec
186} // namespace compiler
187} // namespace protobuf
188} // namespace google
189