Commit 367e0226 authored by csharptest's avatar csharptest Committed by rogerk

Performance tweek for reading entire unpacked array

parent 920b09a3
...@@ -67,6 +67,9 @@ namespace Google.ProtocolBuffers ...@@ -67,6 +67,9 @@ namespace Google.ProtocolBuffers
private readonly Stream input; private readonly Stream input;
private uint lastTag = 0; private uint lastTag = 0;
private uint nextTag = 0;
private bool hasNextTag = false;
internal const int DefaultRecursionLimit = 64; internal const int DefaultRecursionLimit = 64;
internal const int DefaultSizeLimit = 64 << 20; // 64MB internal const int DefaultSizeLimit = 64 << 20; // 64MB
public const int BufferSize = 4096; public const int BufferSize = 4096;
...@@ -163,6 +166,26 @@ namespace Google.ProtocolBuffers ...@@ -163,6 +166,26 @@ namespace Google.ProtocolBuffers
#region Reading of tags etc #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> /// <summary>
/// Attempt to read a field tag, returning false if we have reached the end /// Attempt to read a field tag, returning false if we have reached the end
/// of the input data. /// of the input data.
...@@ -183,6 +206,13 @@ namespace Google.ProtocolBuffers ...@@ -183,6 +206,13 @@ namespace Google.ProtocolBuffers
{ {
fieldName = null; fieldName = null;
if (hasNextTag)
{
lastTag = fieldTag = nextTag;
hasNextTag = false;
return true;
}
if (IsAtEnd) if (IsAtEnd)
{ {
lastTag = fieldTag = 0; lastTag = fieldTag = 0;
...@@ -483,6 +513,24 @@ namespace Google.ProtocolBuffers ...@@ -483,6 +513,24 @@ namespace Google.ProtocolBuffers
return true; 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)] [CLSCompliant(false)]
public void ReadPrimitiveArray<T>(FieldType fieldType, uint fieldTag, string fieldName, ICollection<T> list) public void ReadPrimitiveArray<T>(FieldType fieldType, uint fieldTag, string fieldName, ICollection<T> list)
{ {
...@@ -505,8 +553,12 @@ namespace Google.ProtocolBuffers ...@@ -505,8 +553,12 @@ namespace Google.ProtocolBuffers
else else
{ {
Object value = null; Object value = null;
if (ReadPrimitiveField(fieldType, ref value)) do
list.Add((T)value); {
if (ReadPrimitiveField(fieldType, ref value))
list.Add((T)value);
}
while (ContinueArray(fieldTag));
} }
} }
...@@ -538,10 +590,18 @@ namespace Google.ProtocolBuffers ...@@ -538,10 +590,18 @@ namespace Google.ProtocolBuffers
} }
else else
{ {
if (ReadEnum(ref value, out unkval, mapping)) do
list.Add(value); {
else if (ReadEnum(ref value, out unkval, mapping))
unknown = new object[] { unkval }; list.Add(value);
else
{
if (unknown == null)
unknown = new List<object>();
unknown.Add(unkval);
}
}
while (ContinueArray(fieldTag));
} }
} }
...@@ -574,27 +634,43 @@ namespace Google.ProtocolBuffers ...@@ -574,27 +634,43 @@ namespace Google.ProtocolBuffers
} }
else else
{ {
if (ReadEnum(ref value, out unkval)) do
list.Add(value); {
else if (ReadEnum(ref value, out unkval))
unknown = new object[] { unkval }; list.Add(value);
else
{
if (unknown == null)
unknown = new List<object>();
unknown.Add(unkval);
}
}
while (ContinueArray(fieldTag));
} }
} }
[CLSCompliant(false)] [CLSCompliant(false)]
public void ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite public void ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite
{ {
IBuilderLite builder = messageType.WeakCreateBuilderForType(); do
ReadMessage(builder, registry); {
list.Add((T)builder.WeakBuildPartial()); IBuilderLite builder = messageType.WeakCreateBuilderForType();
ReadMessage(builder, registry);
list.Add((T)builder.WeakBuildPartial());
}
while (ContinueArray(fieldTag));
} }
[CLSCompliant(false)] [CLSCompliant(false)]
public void ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite public void ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite
{ {
IBuilderLite builder = messageType.WeakCreateBuilderForType(); do
ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry); {
list.Add((T)builder.WeakBuildPartial()); IBuilderLite builder = messageType.WeakCreateBuilderForType();
ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry);
list.Add((T)builder.WeakBuildPartial());
}
while (ContinueArray(fieldTag));
} }
/// <summary> /// <summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment