blob: 208d41513bf59a4ddc5467c14043386915793af8 [file] [log] [blame]
Jon Skeet60c059b2008-10-23 21:17:56 +01001using System;
Jon Skeet68036862008-10-22 13:30:34 +01002using System.Collections.Generic;
3using System.Text;
Jon Skeet25a28582009-02-18 16:06:22 +00004using Google.ProtocolBuffers.DescriptorProtos;
Jon Skeet68036862008-10-22 13:30:34 +01005using Google.ProtocolBuffers.Descriptors;
6
7namespace Google.ProtocolBuffers.ProtoGen {
8 internal class RepeatedPrimitiveFieldGenerator : FieldGeneratorBase, IFieldSourceGenerator {
9
10 internal RepeatedPrimitiveFieldGenerator(FieldDescriptor descriptor)
11 : base(descriptor) {
12 }
13
14 public void GenerateMembers(TextGenerator writer) {
Jon Skeet25a28582009-02-18 16:06:22 +000015 if (Descriptor.IsPacked && Descriptor.File.Options.OptimizeFor == FileOptions.Types.OptimizeMode.SPEED) {
16 writer.WriteLine("private int {0}MemoizedSerializedSize;", Name);
17 }
Jon Skeet68036862008-10-22 13:30:34 +010018 writer.WriteLine("private pbc::PopsicleList<{0}> {1}_ = new pbc::PopsicleList<{0}>();", TypeName, Name);
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000019 writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010020 writer.WriteLine(" get {{ return pbc::Lists.AsReadOnly({0}_); }}", Name);
21 writer.WriteLine("}");
22
23 // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option.
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000024 writer.WriteLine("public int {0}Count {{", PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010025 writer.WriteLine(" get {{ return {0}_.Count; }}", Name);
26 writer.WriteLine("}");
27
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000028 writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010029 writer.WriteLine(" return {0}_[index];", Name);
30 writer.WriteLine("}");
31 }
32
33 public void GenerateBuilderMembers(TextGenerator writer) {
34 // Note: We can return the original list here, because we make it unmodifiable when we build
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000035 writer.WriteLine("public scg::IList<{0}> {1}List {{", TypeName, PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010036 writer.WriteLine(" get {{ return result.{0}_; }}", Name);
37 writer.WriteLine("}");
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000038 writer.WriteLine("public int {0}Count {{", PropertyName);
39 writer.WriteLine(" get {{ return result.{0}Count; }}", PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010040 writer.WriteLine("}");
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000041 writer.WriteLine("public {0} Get{1}(int index) {{", TypeName, PropertyName);
42 writer.WriteLine(" return result.Get{0}(index);", PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010043 writer.WriteLine("}");
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000044 writer.WriteLine("public Builder Set{0}(int index, {1} value) {{", PropertyName, TypeName);
Jon Skeet642a8142009-01-27 12:25:21 +000045 AddNullCheck(writer);
Jon Skeet68036862008-10-22 13:30:34 +010046 writer.WriteLine(" result.{0}_[index] = value;", Name);
47 writer.WriteLine(" return this;");
48 writer.WriteLine("}");
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000049 writer.WriteLine("public Builder Add{0}({1} value) {{", PropertyName, TypeName);
Jon Skeet642a8142009-01-27 12:25:21 +000050 AddNullCheck(writer);
Jon Skeet68036862008-10-22 13:30:34 +010051 writer.WriteLine(" result.{0}_.Add(value);", Name, TypeName);
52 writer.WriteLine(" return this;");
53 writer.WriteLine("}");
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000054 writer.WriteLine("public Builder AddRange{0}(scg::IEnumerable<{1}> values) {{", PropertyName, TypeName);
Jon Skeet68036862008-10-22 13:30:34 +010055 writer.WriteLine(" base.AddRange(values, result.{0}_);", Name);
56 writer.WriteLine(" return this;");
57 writer.WriteLine("}");
Jon Skeet4cf9e3c2008-11-24 11:11:28 +000058 writer.WriteLine("public Builder Clear{0}() {{", PropertyName);
Jon Skeet68036862008-10-22 13:30:34 +010059 writer.WriteLine(" result.{0}_.Clear();", Name);
60 writer.WriteLine(" return this;");
61 writer.WriteLine("}");
62 }
63
64 public void GenerateMergingCode(TextGenerator writer) {
65 writer.WriteLine("if (other.{0}_.Count != 0) {{", Name);
66 writer.WriteLine(" base.AddRange(other.{0}_, result.{0}_);", Name);
67 writer.WriteLine("}");
68 }
69
70 public void GenerateBuildingCode(TextGenerator writer) {
71 writer.WriteLine("result.{0}_.MakeReadOnly();", Name);
72 }
73
74 public void GenerateParsingCode(TextGenerator writer) {
Jon Skeet25a28582009-02-18 16:06:22 +000075 if (Descriptor.IsPacked) {
76 writer.WriteLine("int length = input.ReadInt32();");
77 writer.WriteLine("int limit = input.PushLimit(length);");
78 writer.WriteLine("while (!input.ReachedLimit) {");
79 writer.WriteLine(" Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
80 writer.WriteLine("}");
81 writer.WriteLine("input.PopLimit(limit);");
82 } else {
83 writer.WriteLine("Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
84 }
Jon Skeet68036862008-10-22 13:30:34 +010085 }
86
87 public void GenerateSerializationCode(TextGenerator writer) {
Jon Skeet25a28582009-02-18 16:06:22 +000088 writer.WriteLine("if ({0}_.Count > 0) {{", Name);
89 writer.Indent();
90 if (Descriptor.IsPacked) {
91 writer.WriteLine("output.WriteRawVarint32({0});", WireFormat.MakeTag(Descriptor));
92 writer.WriteLine("output.WriteRawVarint32((uint) {0}MemoizedSerializedSize);", Name);
93 writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
94 writer.WriteLine(" output.Write{0}NoTag(element);", CapitalizedTypeName);
95 writer.WriteLine("}");
96 } else {
97 writer.WriteLine("foreach ({0} element in {1}_) {{", TypeName, Name);
98 writer.WriteLine(" output.Write{0}({1}, element);", CapitalizedTypeName, Number);
99 writer.WriteLine("}");
100 }
101 writer.Outdent();
Jon Skeet68036862008-10-22 13:30:34 +0100102 writer.WriteLine("}");
103 }
104
105 public void GenerateSerializedSizeCode(TextGenerator writer) {
Jon Skeet25a28582009-02-18 16:06:22 +0000106 writer.WriteLine("{");
107 writer.Indent();
108 writer.WriteLine("int dataSize = 0;");
109 if (FixedSize == -1) {
110 writer.WriteLine("foreach ({0} element in {1}List) {{", TypeName, PropertyName);
111 writer.WriteLine(" dataSize += pb::CodedOutputStream.Compute{0}SizeNoTag(element);", CapitalizedTypeName, Number);
112 writer.WriteLine("}");
113 } else {
114 writer.WriteLine("dataSize = {0} * {1}_.Count;", FixedSize, Name);
115 }
116 writer.WriteLine("size += dataSize;");
117 int tagSize = CodedOutputStream.ComputeTagSize(Descriptor.FieldNumber);
118 if (Descriptor.IsPacked) {
119 writer.WriteLine("size += {0};", tagSize);
120 writer.WriteLine("size += pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);");
121 } else {
122 writer.WriteLine("size += {0} * {1}_.Count;", tagSize, Name);
123 }
124 // cache the data size for packed fields.
125 if (Descriptor.IsPacked) {
126 writer.WriteLine("{0}MemoizedSerializedSize = dataSize;", Name);
127 }
128 writer.Outdent();
Jon Skeet68036862008-10-22 13:30:34 +0100129 writer.WriteLine("}");
130 }
131 }
132}