• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
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 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/javanano/javanano_field.h>
36 #include <google/protobuf/compiler/javanano/javanano_helpers.h>
37 #include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
38 #include <google/protobuf/compiler/javanano/javanano_enum_field.h>
39 #include <google/protobuf/compiler/javanano/javanano_map_field.h>
40 #include <google/protobuf/compiler/javanano/javanano_message_field.h>
41 #include <google/protobuf/stubs/common.h>
42 
43 namespace google {
44 namespace protobuf {
45 namespace compiler {
46 namespace javanano {
47 
~FieldGenerator()48 FieldGenerator::~FieldGenerator() {}
49 
SavedDefaultNeeded() const50 bool FieldGenerator::SavedDefaultNeeded() const {
51   // No saved default for this field by default.
52   // Subclasses whose instances may need saved defaults will override this
53   // and return the appropriate value.
54   return false;
55 }
56 
GenerateInitSavedDefaultCode(io::Printer * printer) const57 void FieldGenerator::GenerateInitSavedDefaultCode(io::Printer* printer) const {
58   // No saved default for this field by default.
59   // Subclasses whose instances may need saved defaults will override this
60   // and generate the appropriate init code to the printer.
61 }
62 
GenerateMergingCodeFromPacked(io::Printer * printer) const63 void FieldGenerator::GenerateMergingCodeFromPacked(io::Printer* printer) const {
64   // Reaching here indicates a bug. Cases are:
65   //   - This FieldGenerator should support packing, but this method should be
66   //     overridden.
67   //   - This FieldGenerator doesn't support packing, and this method should
68   //     never have been called.
69   GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
70              << "called on field generator that does not support packing.";
71 }
72 
73 // =============================================
74 
FieldGeneratorMap(const Descriptor * descriptor,const Params & params)75 FieldGeneratorMap::FieldGeneratorMap(
76     const Descriptor* descriptor, const Params &params)
77   : descriptor_(descriptor),
78     field_generators_(
79       new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
80 
81   int next_has_bit_index = 0;
82   bool saved_defaults_needed = false;
83   // Construct all the FieldGenerators.
84   for (int i = 0; i < descriptor->field_count(); i++) {
85     FieldGenerator* field_generator = MakeGenerator(
86         descriptor->field(i), params, &next_has_bit_index);
87     saved_defaults_needed = saved_defaults_needed
88         || field_generator->SavedDefaultNeeded();
89     field_generators_[i].reset(field_generator);
90   }
91   total_bits_ = next_has_bit_index;
92   saved_defaults_needed_ = saved_defaults_needed;
93 }
94 
MakeGenerator(const FieldDescriptor * field,const Params & params,int * next_has_bit_index)95 FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
96     const Params &params, int* next_has_bit_index) {
97   JavaType java_type = GetJavaType(field);
98   if (field->is_repeated()) {
99     switch (java_type) {
100       case JAVATYPE_MESSAGE:
101         if (IsMapEntry(field->message_type())) {
102           return new MapFieldGenerator(field, params);
103         } else {
104           return new RepeatedMessageFieldGenerator(field, params);
105         }
106       case JAVATYPE_ENUM:
107         return new RepeatedEnumFieldGenerator(field, params);
108       default:
109         return new RepeatedPrimitiveFieldGenerator(field, params);
110     }
111   } else if (field->containing_oneof()) {
112     switch (java_type) {
113       case JAVATYPE_MESSAGE:
114         return new MessageOneofFieldGenerator(field, params);
115       case JAVATYPE_ENUM:
116       default:
117         return new PrimitiveOneofFieldGenerator(field, params);
118     }
119   } else if (params.optional_field_accessors() && field->is_optional()
120       && java_type != JAVATYPE_MESSAGE) {
121     // We need a has-bit for each primitive/enum field because their default
122     // values could be same as explicitly set values. But we don't need it
123     // for a message field because they have no defaults and Nano uses 'null'
124     // for unset messages, which cannot be set explicitly.
125     switch (java_type) {
126       case JAVATYPE_ENUM:
127         return new AccessorEnumFieldGenerator(
128             field, params, (*next_has_bit_index)++);
129       default:
130         return new AccessorPrimitiveFieldGenerator(
131             field, params, (*next_has_bit_index)++);
132     }
133   } else {
134     switch (java_type) {
135       case JAVATYPE_MESSAGE:
136         return new MessageFieldGenerator(field, params);
137       case JAVATYPE_ENUM:
138         return new EnumFieldGenerator(field, params);
139       default:
140         return new PrimitiveFieldGenerator(field, params);
141     }
142   }
143 }
144 
~FieldGeneratorMap()145 FieldGeneratorMap::~FieldGeneratorMap() {}
146 
get(const FieldDescriptor * field) const147 const FieldGenerator& FieldGeneratorMap::get(
148     const FieldDescriptor* field) const {
149   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
150   return *field_generators_[field->index()];
151 }
152 
SetCommonOneofVariables(const FieldDescriptor * descriptor,map<string,string> * variables)153 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
154                              map<string, string>* variables) {
155   (*variables)["oneof_name"] =
156       UnderscoresToCamelCase(descriptor->containing_oneof());
157   (*variables)["oneof_capitalized_name"] =
158       UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
159   (*variables)["oneof_index"] =
160       SimpleItoa(descriptor->containing_oneof()->index());
161   (*variables)["set_oneof_case"] =
162       "this." + (*variables)["oneof_name"] +
163       "Case_ = " + SimpleItoa(descriptor->number());
164   (*variables)["clear_oneof_case"] =
165       "this." + (*variables)["oneof_name"] + "Case_ = 0";
166   (*variables)["has_oneof_case"] =
167       "this." + (*variables)["oneof_name"] + "Case_ == " +
168       SimpleItoa(descriptor->number());
169 }
170 
GenerateOneofFieldEquals(const FieldDescriptor * descriptor,const map<string,string> & variables,io::Printer * printer)171 void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
172                               const map<string, string>& variables,
173                               io::Printer* printer) {
174   if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
175     printer->Print(variables,
176       "if (this.has$capitalized_name$()) {\n"
177       "  if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
178       "                               (byte[]) other.$oneof_name$_)) {\n"
179       "    return false;\n"
180       "  }\n"
181       "}\n");
182   } else {
183     printer->Print(variables,
184       "if (this.has$capitalized_name$()) {\n"
185       "  if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
186       "    return false;\n"
187       "  }\n"
188       "}\n");
189   }
190 }
191 
GenerateOneofFieldHashCode(const FieldDescriptor * descriptor,const map<string,string> & variables,io::Printer * printer)192 void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
193                                 const map<string, string>& variables,
194                                 io::Printer* printer) {
195   if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
196     printer->Print(variables,
197       "result = 31 * result + ($has_oneof_case$\n"
198       "   ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
199   } else {
200     printer->Print(variables,
201       "result = 31 * result +\n"
202       "  ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
203   }
204 }
205 
206 }  // namespace javanano
207 }  // namespace compiler
208 }  // namespace protobuf
209 }  // namespace google
210