• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sstream>
32 
33 #include <google/protobuf/compiler/code_generator.h>
34 #include <google/protobuf/compiler/plugin.h>
35 #include <google/protobuf/descriptor.h>
36 #include <google/protobuf/descriptor.pb.h>
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/io/zero_copy_stream.h>
39 #include <google/protobuf/stubs/strutil.h>
40 
41 #include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
42 #include <google/protobuf/compiler/csharp/csharp_helpers.h>
43 #include <google/protobuf/compiler/csharp/csharp_options.h>
44 #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
45 
46 namespace google {
47 namespace protobuf {
48 namespace compiler {
49 namespace csharp {
50 
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,int fieldOrdinal,const Options * options)51 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
52     const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
53     : FieldGeneratorBase(descriptor, fieldOrdinal, options) {
54   // TODO(jonskeet): Make this cleaner...
55   is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING
56       && descriptor->type() != FieldDescriptor::TYPE_BYTES;
57   if (!is_value_type) {
58     variables_["has_property_check"] = variables_["property_name"] + ".Length != 0";
59     variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0";
60   }
61 }
62 
~PrimitiveFieldGenerator()63 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {
64 }
65 
GenerateMembers(io::Printer * printer)66 void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {
67   // TODO(jonskeet): Work out whether we want to prevent the fields from ever being
68   // null, or whether we just handle it, in the cases of bytes and string.
69   // (Basically, should null-handling code be in the getter or the setter?)
70   printer->Print(
71     variables_,
72     "private $type_name$ $name_def_message$;\n");
73   WritePropertyDocComment(printer, descriptor_);
74   AddDeprecatedFlag(printer);
75   printer->Print(
76     variables_,
77     "$access_level$ $type_name$ $property_name$ {\n"
78     "  get { return $name$_; }\n"
79     "  set {\n");
80   if (is_value_type) {
81     printer->Print(
82       variables_,
83       "    $name$_ = value;\n");
84   } else {
85     printer->Print(
86       variables_,
87       "    $name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
88   }
89   printer->Print(
90     "  }\n"
91     "}\n");
92 }
93 
GenerateMergingCode(io::Printer * printer)94 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) {
95   printer->Print(
96     variables_,
97     "if ($other_has_property_check$) {\n"
98     "  $property_name$ = other.$property_name$;\n"
99     "}\n");
100 }
101 
GenerateParsingCode(io::Printer * printer)102 void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) {
103   // Note: invoke the property setter rather than writing straight to the field,
104   // so that we can normalize "null to empty" for strings and bytes.
105   printer->Print(
106     variables_,
107     "$property_name$ = input.Read$capitalized_type_name$();\n");
108 }
109 
GenerateSerializationCode(io::Printer * printer)110 void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
111   printer->Print(
112     variables_,
113     "if ($has_property_check$) {\n"
114     "  output.WriteRawTag($tag_bytes$);\n"
115     "  output.Write$capitalized_type_name$($property_name$);\n"
116     "}\n");
117 }
118 
GenerateSerializedSizeCode(io::Printer * printer)119 void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
120   printer->Print(
121     variables_,
122     "if ($has_property_check$) {\n");
123   printer->Indent();
124   int fixedSize = GetFixedSize(descriptor_->type());
125   if (fixedSize == -1) {
126     printer->Print(
127       variables_,
128       "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n");
129   } else {
130     printer->Print(
131       "size += $tag_size$ + $fixed_size$;\n",
132       "fixed_size", SimpleItoa(fixedSize),
133       "tag_size", variables_["tag_size"]);
134   }
135   printer->Outdent();
136   printer->Print("}\n");
137 }
138 
WriteHash(io::Printer * printer)139 void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) {
140   printer->Print(
141     variables_,
142     "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n");
143 }
WriteEquals(io::Printer * printer)144 void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) {
145   printer->Print(
146     variables_,
147     "if ($property_name$ != other.$property_name$) return false;\n");
148 }
WriteToString(io::Printer * printer)149 void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
150   printer->Print(
151     variables_,
152     "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n");
153 }
154 
GenerateCloningCode(io::Printer * printer)155 void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
156   printer->Print(variables_,
157     "$name$_ = other.$name$_;\n");
158 }
159 
GenerateCodecCode(io::Printer * printer)160 void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
161   printer->Print(
162     variables_,
163     "pb::FieldCodec.For$capitalized_type_name$($tag$)");
164 }
165 
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,int fieldOrdinal,const Options * options)166 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
167     const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options)
168     : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) {
169   SetCommonOneofFieldVariables(&variables_);
170 }
171 
~PrimitiveOneofFieldGenerator()172 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {
173 }
174 
GenerateMembers(io::Printer * printer)175 void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) {
176   WritePropertyDocComment(printer, descriptor_);
177   AddDeprecatedFlag(printer);
178   printer->Print(
179     variables_,
180     "$access_level$ $type_name$ $property_name$ {\n"
181     "  get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n"
182     "  set {\n");
183     if (is_value_type) {
184       printer->Print(
185         variables_,
186         "    $oneof_name$_ = value;\n");
187     } else {
188       printer->Print(
189         variables_,
190         "    $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n");
191     }
192     printer->Print(
193       variables_,
194       "    $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"
195       "  }\n"
196       "}\n");
197 }
198 
WriteToString(io::Printer * printer)199 void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) {
200   printer->Print(variables_,
201     "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
202 }
203 
GenerateParsingCode(io::Printer * printer)204 void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
205     printer->Print(
206       variables_,
207       "$property_name$ = input.Read$capitalized_type_name$();\n");
208 }
209 
GenerateCloningCode(io::Printer * printer)210 void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
211   printer->Print(variables_,
212     "$property_name$ = other.$property_name$;\n");
213 }
214 
215 }  // namespace csharp
216 }  // namespace compiler
217 }  // namespace protobuf
218 }  // namespace google
219