blob: a4ffb73b8bb1d6d331bb5e44fa087373dcfa0985 [file] [log] [blame]
Jon Skeet0aac0e42009-09-09 18:48:02 +01001#region Copyright notice and license
Jon Skeetad748532009-06-25 16:55:58 +01002// Protocol Buffers - Google's data interchange format
3// Copyright 2008 Google Inc. All rights reserved.
4// http://github.com/jskeet/dotnet-protobufs/
5// Original C++/Java/Python code:
6// http://code.google.com/p/protobuf/
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11//
12// * Redistributions of source code must retain the above copyright
13// notice, this list of conditions and the following disclaimer.
14// * Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following disclaimer
16// in the documentation and/or other materials provided with the
17// distribution.
18// * Neither the name of Google Inc. nor the names of its
19// contributors may be used to endorse or promote products derived from
20// this software without specific prior written permission.
21//
22// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Jon Skeet0aac0e42009-09-09 18:48:02 +010033#endregion
34
Jon Skeet60c059b2008-10-23 21:17:56 +010035using System;
Jon Skeet68036862008-10-22 13:30:34 +010036using System.Globalization;
Jon Skeet642a8142009-01-27 12:25:21 +000037using Google.ProtocolBuffers.Descriptors;
Jon Skeet68036862008-10-22 13:30:34 +010038
39namespace Google.ProtocolBuffers.ProtoGen {
40 internal abstract class FieldGeneratorBase : SourceGeneratorBase<FieldDescriptor> {
41 protected FieldGeneratorBase(FieldDescriptor descriptor)
42 : base(descriptor) {
43 }
44
45 private static bool AllPrintableAscii(string text) {
46 foreach (char c in text) {
47 if (c < 0x20 || c > 0x7e) {
48 return false;
49 }
50 }
51 return true;
52 }
53
54 protected string DefaultValue {
55 get {
56 string suffix = "";
57 switch (Descriptor.FieldType) {
58 case FieldType.Float: suffix = "F"; break;
59 case FieldType.Double: suffix = "D"; break;
60 case FieldType.Int64: suffix = "L"; break;
61 case FieldType.UInt64: suffix = "UL"; break;
62 }
63 switch (Descriptor.FieldType) {
64 case FieldType.Float:
65 case FieldType.Double:
66 case FieldType.Int32:
67 case FieldType.Int64:
68 case FieldType.SInt32:
69 case FieldType.SInt64:
70 case FieldType.SFixed32:
71 case FieldType.SFixed64:
72 case FieldType.UInt32:
73 case FieldType.UInt64:
74 case FieldType.Fixed32:
75 case FieldType.Fixed64:
76 // The simple Object.ToString converts using the current culture.
77 // We want to always use the invariant culture so it's predictable.
78 IConvertible value = (IConvertible) Descriptor.DefaultValue;
79 return value.ToString(CultureInfo.InvariantCulture) + suffix;
80 case FieldType.Bool:
81 return (bool) Descriptor.DefaultValue ? "true" : "false";
82
83 case FieldType.Bytes:
84 if (!Descriptor.HasDefaultValue) {
85 return "pb::ByteString.Empty";
86 }
Jon Skeetd6343be2008-11-12 23:39:44 +000087 return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
Jon Skeet68036862008-10-22 13:30:34 +010088 case FieldType.String:
89 if (AllPrintableAscii(Descriptor.Proto.DefaultValue)) {
90 // All chars are ASCII and printable. In this case we only
91 // need to escape quotes and backslashes.
92 return "\"" + Descriptor.Proto.DefaultValue
93 .Replace("\\", "\\\\")
94 .Replace("'", "\\'")
95 .Replace("\"", "\\\"")
96 + "\"";
97 }
Jon Skeetd6343be2008-11-12 23:39:44 +000098 return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
Jon Skeet68036862008-10-22 13:30:34 +010099 case FieldType.Enum:
100 return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
101 case FieldType.Message:
102 case FieldType.Group:
103 return TypeName + ".DefaultInstance";
104 default:
105 throw new InvalidOperationException("Invalid field descriptor type");
106 }
107 }
108 }
109
Jon Skeet68036862008-10-22 13:30:34 +0100110 protected string PropertyName {
111 get {
Jon Skeet1d131c92008-11-13 22:29:48 +0000112 return Descriptor.CSharpOptions.PropertyName;
Jon Skeet68036862008-10-22 13:30:34 +0100113 }
114 }
115
Jon Skeet68036862008-10-22 13:30:34 +0100116 protected string Name {
Jon Skeetd6343be2008-11-12 23:39:44 +0000117 get { return NameHelpers.UnderscoresToCamelCase(GetFieldName(Descriptor)); }
Jon Skeet68036862008-10-22 13:30:34 +0100118 }
119
120 protected int Number {
121 get { return Descriptor.FieldNumber; }
122 }
123
Jon Skeet642a8142009-01-27 12:25:21 +0000124 protected void AddNullCheck(TextGenerator writer) {
125 AddNullCheck(writer, "value");
126 }
127
128 protected void AddNullCheck(TextGenerator writer, string name) {
129 if (IsNullableType) {
130 writer.WriteLine(" pb::ThrowHelper.ThrowIfNull({0}, \"{0}\");", name);
131 }
132 }
133
Jon Skeetd6dd0a42009-06-05 22:00:05 +0100134 protected void AddClsComplianceCheck(TextGenerator writer) {
135 if (!Descriptor.IsCLSCompliant) {
136 writer.WriteLine("[global::System.CLSCompliant(false)]");
137 }
138 }
139
Jon Skeet25a28582009-02-18 16:06:22 +0000140 /// <summary>
141 /// For encodings with fixed sizes, returns that size in bytes. Otherwise
142 /// returns -1. TODO(jonskeet): Make this less ugly.
143 /// </summary>
144 protected int FixedSize {
145 get {
146 switch (Descriptor.FieldType) {
147 case FieldType.UInt32:
148 case FieldType.UInt64:
149 case FieldType.Int32:
150 case FieldType.Int64:
151 case FieldType.SInt32:
152 case FieldType.SInt64:
153 case FieldType.Enum:
154 case FieldType.Bytes:
155 case FieldType.String:
156 case FieldType.Message:
157 case FieldType.Group:
158 return -1;
159 case FieldType.Float:
160 return WireFormat.FloatSize;
161 case FieldType.SFixed32:
162 return WireFormat.SFixed32Size;
163 case FieldType.Fixed32:
164 return WireFormat.Fixed32Size;
165 case FieldType.Double:
166 return WireFormat.DoubleSize;
167 case FieldType.SFixed64:
168 return WireFormat.SFixed64Size;
169 case FieldType.Fixed64:
170 return WireFormat.Fixed64Size;
171 case FieldType.Bool:
172 return WireFormat.BoolSize;
173 default:
174 throw new InvalidOperationException("Invalid field descriptor type");
175 }
176 }
177 }
178
Jon Skeet642a8142009-01-27 12:25:21 +0000179 protected bool IsNullableType {
180 get {
181 switch (Descriptor.FieldType) {
182 case FieldType.Float:
183 case FieldType.Double:
184 case FieldType.Int32:
185 case FieldType.Int64:
186 case FieldType.SInt32:
187 case FieldType.SInt64:
188 case FieldType.SFixed32:
189 case FieldType.SFixed64:
190 case FieldType.UInt32:
191 case FieldType.UInt64:
192 case FieldType.Fixed32:
193 case FieldType.Fixed64:
194 case FieldType.Bool:
195 case FieldType.Enum:
196 return false;
197 case FieldType.Bytes:
198 case FieldType.String:
199 case FieldType.Message:
200 case FieldType.Group:
201 return true;
202 default:
203 throw new InvalidOperationException("Invalid field descriptor type");
204 }
205 }
206 }
207
Jon Skeet68036862008-10-22 13:30:34 +0100208 protected string TypeName {
209 get {
210 switch (Descriptor.FieldType) {
211 case FieldType.Enum:
Jon Skeetd6343be2008-11-12 23:39:44 +0000212 return GetClassName(Descriptor.EnumType);
Jon Skeet68036862008-10-22 13:30:34 +0100213 case FieldType.Message:
214 case FieldType.Group:
Jon Skeetd6343be2008-11-12 23:39:44 +0000215 return GetClassName(Descriptor.MessageType);
Jon Skeet68036862008-10-22 13:30:34 +0100216 default:
217 return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
218 }
219 }
220 }
221
222 protected string MessageOrGroup {
223 get { return Descriptor.FieldType == FieldType.Group ? "Group" : "Message"; }
224 }
225
226 /// <summary>
227 /// Returns the type name as used in CodedInputStream method names: SFixed32, UInt32 etc.
228 /// </summary>
229 protected string CapitalizedTypeName {
230 get {
231 // Our enum names match perfectly. How serendipitous.
232 return Descriptor.FieldType.ToString();
233 }
234 }
235 }
236}