blob: f34d01cd012f6a306ed03b507f4d2806f3f9dd06 [file] [log] [blame]
Jon Skeet60c059b2008-10-23 21:17:56 +01001using System;
Jon Skeet68036862008-10-22 13:30:34 +01002using System.Globalization;
Jon Skeet642a8142009-01-27 12:25:21 +00003using Google.ProtocolBuffers.Descriptors;
Jon Skeet68036862008-10-22 13:30:34 +01004
5namespace Google.ProtocolBuffers.ProtoGen {
6 internal abstract class FieldGeneratorBase : SourceGeneratorBase<FieldDescriptor> {
7 protected FieldGeneratorBase(FieldDescriptor descriptor)
8 : base(descriptor) {
9 }
10
11 private static bool AllPrintableAscii(string text) {
12 foreach (char c in text) {
13 if (c < 0x20 || c > 0x7e) {
14 return false;
15 }
16 }
17 return true;
18 }
19
20 protected string DefaultValue {
21 get {
22 string suffix = "";
23 switch (Descriptor.FieldType) {
24 case FieldType.Float: suffix = "F"; break;
25 case FieldType.Double: suffix = "D"; break;
26 case FieldType.Int64: suffix = "L"; break;
27 case FieldType.UInt64: suffix = "UL"; break;
28 }
29 switch (Descriptor.FieldType) {
30 case FieldType.Float:
31 case FieldType.Double:
32 case FieldType.Int32:
33 case FieldType.Int64:
34 case FieldType.SInt32:
35 case FieldType.SInt64:
36 case FieldType.SFixed32:
37 case FieldType.SFixed64:
38 case FieldType.UInt32:
39 case FieldType.UInt64:
40 case FieldType.Fixed32:
41 case FieldType.Fixed64:
42 // The simple Object.ToString converts using the current culture.
43 // We want to always use the invariant culture so it's predictable.
44 IConvertible value = (IConvertible) Descriptor.DefaultValue;
45 return value.ToString(CultureInfo.InvariantCulture) + suffix;
46 case FieldType.Bool:
47 return (bool) Descriptor.DefaultValue ? "true" : "false";
48
49 case FieldType.Bytes:
50 if (!Descriptor.HasDefaultValue) {
51 return "pb::ByteString.Empty";
52 }
Jon Skeetd6343be2008-11-12 23:39:44 +000053 return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
Jon Skeet68036862008-10-22 13:30:34 +010054 case FieldType.String:
55 if (AllPrintableAscii(Descriptor.Proto.DefaultValue)) {
56 // All chars are ASCII and printable. In this case we only
57 // need to escape quotes and backslashes.
58 return "\"" + Descriptor.Proto.DefaultValue
59 .Replace("\\", "\\\\")
60 .Replace("'", "\\'")
61 .Replace("\"", "\\\"")
62 + "\"";
63 }
Jon Skeetd6343be2008-11-12 23:39:44 +000064 return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
Jon Skeet68036862008-10-22 13:30:34 +010065 case FieldType.Enum:
66 return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
67 case FieldType.Message:
68 case FieldType.Group:
69 return TypeName + ".DefaultInstance";
70 default:
71 throw new InvalidOperationException("Invalid field descriptor type");
72 }
73 }
74 }
75
Jon Skeet68036862008-10-22 13:30:34 +010076 protected string PropertyName {
77 get {
Jon Skeet1d131c92008-11-13 22:29:48 +000078 return Descriptor.CSharpOptions.PropertyName;
Jon Skeet68036862008-10-22 13:30:34 +010079 }
80 }
81
Jon Skeet68036862008-10-22 13:30:34 +010082 protected string Name {
Jon Skeetd6343be2008-11-12 23:39:44 +000083 get { return NameHelpers.UnderscoresToCamelCase(GetFieldName(Descriptor)); }
Jon Skeet68036862008-10-22 13:30:34 +010084 }
85
86 protected int Number {
87 get { return Descriptor.FieldNumber; }
88 }
89
Jon Skeet642a8142009-01-27 12:25:21 +000090 protected void AddNullCheck(TextGenerator writer) {
91 AddNullCheck(writer, "value");
92 }
93
94 protected void AddNullCheck(TextGenerator writer, string name) {
95 if (IsNullableType) {
96 writer.WriteLine(" pb::ThrowHelper.ThrowIfNull({0}, \"{0}\");", name);
97 }
98 }
99
Jon Skeetd6dd0a42009-06-05 22:00:05 +0100100 protected void AddClsComplianceCheck(TextGenerator writer) {
101 if (!Descriptor.IsCLSCompliant) {
102 writer.WriteLine("[global::System.CLSCompliant(false)]");
103 }
104 }
105
Jon Skeet25a28582009-02-18 16:06:22 +0000106 /// <summary>
107 /// For encodings with fixed sizes, returns that size in bytes. Otherwise
108 /// returns -1. TODO(jonskeet): Make this less ugly.
109 /// </summary>
110 protected int FixedSize {
111 get {
112 switch (Descriptor.FieldType) {
113 case FieldType.UInt32:
114 case FieldType.UInt64:
115 case FieldType.Int32:
116 case FieldType.Int64:
117 case FieldType.SInt32:
118 case FieldType.SInt64:
119 case FieldType.Enum:
120 case FieldType.Bytes:
121 case FieldType.String:
122 case FieldType.Message:
123 case FieldType.Group:
124 return -1;
125 case FieldType.Float:
126 return WireFormat.FloatSize;
127 case FieldType.SFixed32:
128 return WireFormat.SFixed32Size;
129 case FieldType.Fixed32:
130 return WireFormat.Fixed32Size;
131 case FieldType.Double:
132 return WireFormat.DoubleSize;
133 case FieldType.SFixed64:
134 return WireFormat.SFixed64Size;
135 case FieldType.Fixed64:
136 return WireFormat.Fixed64Size;
137 case FieldType.Bool:
138 return WireFormat.BoolSize;
139 default:
140 throw new InvalidOperationException("Invalid field descriptor type");
141 }
142 }
143 }
144
Jon Skeet642a8142009-01-27 12:25:21 +0000145 protected bool IsNullableType {
146 get {
147 switch (Descriptor.FieldType) {
148 case FieldType.Float:
149 case FieldType.Double:
150 case FieldType.Int32:
151 case FieldType.Int64:
152 case FieldType.SInt32:
153 case FieldType.SInt64:
154 case FieldType.SFixed32:
155 case FieldType.SFixed64:
156 case FieldType.UInt32:
157 case FieldType.UInt64:
158 case FieldType.Fixed32:
159 case FieldType.Fixed64:
160 case FieldType.Bool:
161 case FieldType.Enum:
162 return false;
163 case FieldType.Bytes:
164 case FieldType.String:
165 case FieldType.Message:
166 case FieldType.Group:
167 return true;
168 default:
169 throw new InvalidOperationException("Invalid field descriptor type");
170 }
171 }
172 }
173
Jon Skeet68036862008-10-22 13:30:34 +0100174 protected string TypeName {
175 get {
176 switch (Descriptor.FieldType) {
177 case FieldType.Enum:
Jon Skeetd6343be2008-11-12 23:39:44 +0000178 return GetClassName(Descriptor.EnumType);
Jon Skeet68036862008-10-22 13:30:34 +0100179 case FieldType.Message:
180 case FieldType.Group:
Jon Skeetd6343be2008-11-12 23:39:44 +0000181 return GetClassName(Descriptor.MessageType);
Jon Skeet68036862008-10-22 13:30:34 +0100182 default:
183 return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
184 }
185 }
186 }
187
188 protected string MessageOrGroup {
189 get { return Descriptor.FieldType == FieldType.Group ? "Group" : "Message"; }
190 }
191
192 /// <summary>
193 /// Returns the type name as used in CodedInputStream method names: SFixed32, UInt32 etc.
194 /// </summary>
195 protected string CapitalizedTypeName {
196 get {
197 // Our enum names match perfectly. How serendipitous.
198 return Descriptor.FieldType.ToString();
199 }
200 }
201 }
202}