FieldGeneratorBase.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #region Copyright notice and license
  2. // 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.
  33. #endregion
  34. using System;
  35. using System.Globalization;
  36. using Google.ProtocolBuffers.Descriptors;
  37. namespace Google.ProtocolBuffers.ProtoGen {
  38. internal abstract class FieldGeneratorBase : SourceGeneratorBase<FieldDescriptor> {
  39. protected FieldGeneratorBase(FieldDescriptor descriptor)
  40. : base(descriptor) {
  41. }
  42. private static bool AllPrintableAscii(string text) {
  43. foreach (char c in text) {
  44. if (c < 0x20 || c > 0x7e) {
  45. return false;
  46. }
  47. }
  48. return true;
  49. }
  50. protected string DefaultValue {
  51. get {
  52. string suffix = "";
  53. switch (Descriptor.FieldType) {
  54. case FieldType.Float: suffix = "F"; break;
  55. case FieldType.Double: suffix = "D"; break;
  56. case FieldType.Int64: suffix = "L"; break;
  57. case FieldType.UInt64: suffix = "UL"; break;
  58. }
  59. switch (Descriptor.FieldType) {
  60. case FieldType.Float:
  61. case FieldType.Double:
  62. case FieldType.Int32:
  63. case FieldType.Int64:
  64. case FieldType.SInt32:
  65. case FieldType.SInt64:
  66. case FieldType.SFixed32:
  67. case FieldType.SFixed64:
  68. case FieldType.UInt32:
  69. case FieldType.UInt64:
  70. case FieldType.Fixed32:
  71. case FieldType.Fixed64:
  72. // The simple Object.ToString converts using the current culture.
  73. // We want to always use the invariant culture so it's predictable.
  74. IConvertible value = (IConvertible) Descriptor.DefaultValue;
  75. return value.ToString(CultureInfo.InvariantCulture) + suffix;
  76. case FieldType.Bool:
  77. return (bool) Descriptor.DefaultValue ? "true" : "false";
  78. case FieldType.Bytes:
  79. if (!Descriptor.HasDefaultValue) {
  80. return "pb::ByteString.Empty";
  81. }
  82. return string.Format("(pb::ByteString) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
  83. case FieldType.String:
  84. if (AllPrintableAscii(Descriptor.Proto.DefaultValue)) {
  85. // All chars are ASCII and printable. In this case we only
  86. // need to escape quotes and backslashes.
  87. return "\"" + Descriptor.Proto.DefaultValue
  88. .Replace("\\", "\\\\")
  89. .Replace("'", "\\'")
  90. .Replace("\"", "\\\"")
  91. + "\"";
  92. }
  93. return string.Format("(string) {0}.Descriptor.Fields[{1}].DefaultValue", GetClassName(Descriptor.ContainingType), Descriptor.Index);
  94. case FieldType.Enum:
  95. return TypeName + "." + ((EnumValueDescriptor) Descriptor.DefaultValue).Name;
  96. case FieldType.Message:
  97. case FieldType.Group:
  98. return TypeName + ".DefaultInstance";
  99. default:
  100. throw new InvalidOperationException("Invalid field descriptor type");
  101. }
  102. }
  103. }
  104. protected string PropertyName {
  105. get {
  106. return Descriptor.CSharpOptions.PropertyName;
  107. }
  108. }
  109. protected string Name {
  110. get { return NameHelpers.UnderscoresToCamelCase(GetFieldName(Descriptor)); }
  111. }
  112. protected int Number {
  113. get { return Descriptor.FieldNumber; }
  114. }
  115. protected void AddNullCheck(TextGenerator writer) {
  116. AddNullCheck(writer, "value");
  117. }
  118. protected void AddNullCheck(TextGenerator writer, string name) {
  119. if (IsNullableType) {
  120. writer.WriteLine(" pb::ThrowHelper.ThrowIfNull({0}, \"{0}\");", name);
  121. }
  122. }
  123. protected void AddClsComplianceCheck(TextGenerator writer) {
  124. if (!Descriptor.IsCLSCompliant && Descriptor.File.CSharpOptions.ClsCompliance) {
  125. writer.WriteLine("[global::System.CLSCompliant(false)]");
  126. }
  127. }
  128. /// <summary>
  129. /// For encodings with fixed sizes, returns that size in bytes. Otherwise
  130. /// returns -1. TODO(jonskeet): Make this less ugly.
  131. /// </summary>
  132. protected int FixedSize {
  133. get {
  134. switch (Descriptor.FieldType) {
  135. case FieldType.UInt32:
  136. case FieldType.UInt64:
  137. case FieldType.Int32:
  138. case FieldType.Int64:
  139. case FieldType.SInt32:
  140. case FieldType.SInt64:
  141. case FieldType.Enum:
  142. case FieldType.Bytes:
  143. case FieldType.String:
  144. case FieldType.Message:
  145. case FieldType.Group:
  146. return -1;
  147. case FieldType.Float:
  148. return WireFormat.FloatSize;
  149. case FieldType.SFixed32:
  150. return WireFormat.SFixed32Size;
  151. case FieldType.Fixed32:
  152. return WireFormat.Fixed32Size;
  153. case FieldType.Double:
  154. return WireFormat.DoubleSize;
  155. case FieldType.SFixed64:
  156. return WireFormat.SFixed64Size;
  157. case FieldType.Fixed64:
  158. return WireFormat.Fixed64Size;
  159. case FieldType.Bool:
  160. return WireFormat.BoolSize;
  161. default:
  162. throw new InvalidOperationException("Invalid field descriptor type");
  163. }
  164. }
  165. }
  166. protected bool IsNullableType {
  167. get {
  168. switch (Descriptor.FieldType) {
  169. case FieldType.Float:
  170. case FieldType.Double:
  171. case FieldType.Int32:
  172. case FieldType.Int64:
  173. case FieldType.SInt32:
  174. case FieldType.SInt64:
  175. case FieldType.SFixed32:
  176. case FieldType.SFixed64:
  177. case FieldType.UInt32:
  178. case FieldType.UInt64:
  179. case FieldType.Fixed32:
  180. case FieldType.Fixed64:
  181. case FieldType.Bool:
  182. case FieldType.Enum:
  183. return false;
  184. case FieldType.Bytes:
  185. case FieldType.String:
  186. case FieldType.Message:
  187. case FieldType.Group:
  188. return true;
  189. default:
  190. throw new InvalidOperationException("Invalid field descriptor type");
  191. }
  192. }
  193. }
  194. protected string TypeName {
  195. get {
  196. switch (Descriptor.FieldType) {
  197. case FieldType.Enum:
  198. return GetClassName(Descriptor.EnumType);
  199. case FieldType.Message:
  200. case FieldType.Group:
  201. return GetClassName(Descriptor.MessageType);
  202. default:
  203. return DescriptorUtil.GetMappedTypeName(Descriptor.MappedType);
  204. }
  205. }
  206. }
  207. protected string MessageOrGroup {
  208. get { return Descriptor.FieldType == FieldType.Group ? "Group" : "Message"; }
  209. }
  210. /// <summary>
  211. /// Returns the type name as used in CodedInputStream method names: SFixed32, UInt32 etc.
  212. /// </summary>
  213. protected string CapitalizedTypeName {
  214. get {
  215. // Our enum names match perfectly. How serendipitous.
  216. return Descriptor.FieldType.ToString();
  217. }
  218. }
  219. }
  220. }