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
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;
......@@ -163,6 +166,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.
......@@ -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,9 +553,13 @@ namespace Google.ProtocolBuffers
else
{
Object value = null;
do
{
if (ReadPrimitiveField(fieldType, ref value))
list.Add((T)value);
}
while (ContinueArray(fieldTag));
}
}
[CLSCompliant(false)]
......@@ -537,11 +589,19 @@ namespace Google.ProtocolBuffers
PopLimit(limit);
}
else
{
do
{
if (ReadEnum(ref value, out unkval, mapping))
list.Add(value);
else
unknown = new object[] { unkval };
{
if (unknown == null)
unknown = new List<object>();
unknown.Add(unkval);
}
}
while (ContinueArray(fieldTag));
}
}
......@@ -573,29 +633,45 @@ namespace Google.ProtocolBuffers
PopLimit(limit);
}
else
{
do
{
if (ReadEnum(ref value, out unkval))
list.Add(value);
else
unknown = new object[] { unkval };
{
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
{
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
{
do
{
IBuilderLite builder = messageType.WeakCreateBuilderForType();
ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry);
list.Add((T)builder.WeakBuildPartial());
}
while (ContinueArray(fieldTag));
}
/// <summary>
/// Reads a field of any primitive type. Enums, groups and embedded
......
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