aboutsummaryrefslogtreecommitdiff
path: root/src/ProtocolBuffers/CodedInputStream.cs
diff options
context:
space:
mode:
authorcsharptest <roger@csharptest.net>2011-06-09 12:47:46 -0500
committerrogerk <devnull@localhost>2011-06-09 12:47:46 -0500
commit367e02261c6bee9bce37cb6942bd6cbf743fb67c (patch)
treef43a19073eea22c85c874aa6c347d7a1715d4381 /src/ProtocolBuffers/CodedInputStream.cs
parent920b09a3b0af58440ed936183d5dfd5342eae1a0 (diff)
downloadprotobuf-367e02261c6bee9bce37cb6942bd6cbf743fb67c.tar.gz
protobuf-367e02261c6bee9bce37cb6942bd6cbf743fb67c.tar.bz2
protobuf-367e02261c6bee9bce37cb6942bd6cbf743fb67c.zip
Performance tweek for reading entire unpacked array
Diffstat (limited to 'src/ProtocolBuffers/CodedInputStream.cs')
-rw-r--r--src/ProtocolBuffers/CodedInputStream.cs108
1 files changed, 92 insertions, 16 deletions
diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs
index 000065bd..1fea7346 100644
--- a/src/ProtocolBuffers/CodedInputStream.cs
+++ b/src/ProtocolBuffers/CodedInputStream.cs
@@ -67,6 +67,9 @@ namespace Google.ProtocolBuffers
private readonly Stream input;
private uint lastTag = 0;
+ private uint nextTag = 0;
+ private bool hasNextTag = false;
+
internal const int DefaultRecursionLimit = 64;
internal const int DefaultSizeLimit = 64 << 20; // 64MB
public const int BufferSize = 4096;
@@ -164,6 +167,26 @@ namespace Google.ProtocolBuffers
#region Reading of tags etc
/// <summary>
+ /// Attempt to peek at the next field tag.
+ /// </summary>
+ [CLSCompliant(false)]
+ public bool PeekNextTag(out uint fieldTag, out string fieldName)
+ {
+ if (hasNextTag)
+ {
+ fieldName = null;
+ fieldTag = nextTag;
+ return true;
+ }
+
+ uint savedLast = lastTag;
+ hasNextTag = ReadTag(out nextTag, out fieldName);
+ lastTag = savedLast;
+ fieldTag = nextTag;
+ return hasNextTag;
+ }
+
+ /// <summary>
/// Attempt to read a field tag, returning false if we have reached the end
/// of the input data.
/// </summary>
@@ -183,6 +206,13 @@ namespace Google.ProtocolBuffers
{
fieldName = null;
+ if (hasNextTag)
+ {
+ lastTag = fieldTag = nextTag;
+ hasNextTag = false;
+ return true;
+ }
+
if (IsAtEnd)
{
lastTag = fieldTag = 0;
@@ -483,6 +513,24 @@ namespace Google.ProtocolBuffers
return true;
}
+ /// <summary>
+ /// Returns true if the next tag is also part of the same unpacked array
+ /// </summary>
+ private bool ContinueArray(uint currentTag)
+ {
+ string ignore;
+ uint next;
+ if (PeekNextTag(out next, out ignore))
+ {
+ if (next == currentTag)
+ {
+ hasNextTag = false;
+ return true;
+ }
+ }
+ return false;
+ }
+
[CLSCompliant(false)]
public void ReadPrimitiveArray<T>(FieldType fieldType, uint fieldTag, string fieldName, ICollection<T> list)
{
@@ -505,8 +553,12 @@ namespace Google.ProtocolBuffers
else
{
Object value = null;
- if (ReadPrimitiveField(fieldType, ref value))
- list.Add((T)value);
+ do
+ {
+ if (ReadPrimitiveField(fieldType, ref value))
+ list.Add((T)value);
+ }
+ while (ContinueArray(fieldTag));
}
}
@@ -538,10 +590,18 @@ namespace Google.ProtocolBuffers
}
else
{
- if (ReadEnum(ref value, out unkval, mapping))
- list.Add(value);
- else
- unknown = new object[] { unkval };
+ do
+ {
+ if (ReadEnum(ref value, out unkval, mapping))
+ list.Add(value);
+ else
+ {
+ if (unknown == null)
+ unknown = new List<object>();
+ unknown.Add(unkval);
+ }
+ }
+ while (ContinueArray(fieldTag));
}
}
@@ -574,27 +634,43 @@ namespace Google.ProtocolBuffers
}
else
{
- if (ReadEnum(ref value, out unkval))
- list.Add(value);
- else
- unknown = new object[] { unkval };
+ do
+ {
+ if (ReadEnum(ref value, out unkval))
+ list.Add(value);
+ else
+ {
+ if (unknown == null)
+ unknown = new List<object>();
+ unknown.Add(unkval);
+ }
+ }
+ while (ContinueArray(fieldTag));
}
}
[CLSCompliant(false)]
public void ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite
{
- IBuilderLite builder = messageType.WeakCreateBuilderForType();
- ReadMessage(builder, registry);
- list.Add((T)builder.WeakBuildPartial());
+ do
+ {
+ IBuilderLite builder = messageType.WeakCreateBuilderForType();
+ ReadMessage(builder, registry);
+ list.Add((T)builder.WeakBuildPartial());
+ }
+ while (ContinueArray(fieldTag));
}
[CLSCompliant(false)]
public void ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite
{
- IBuilderLite builder = messageType.WeakCreateBuilderForType();
- ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry);
- list.Add((T)builder.WeakBuildPartial());
+ do
+ {
+ IBuilderLite builder = messageType.WeakCreateBuilderForType();
+ ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry);
+ list.Add((T)builder.WeakBuildPartial());
+ }
+ while (ContinueArray(fieldTag));
}
/// <summary>