aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
diff options
context:
space:
mode:
authorJon Skeet <jonskeet@google.com>2015-06-23 16:09:27 +0100
committerJon Skeet <jonskeet@google.com>2015-06-24 17:56:22 +0100
commitbfee2dfe137b07e64ebd46baf71d932d58d01b1f (patch)
tree4bf6258a990369335cc82c8a8059eaaf1dc2dd06 /csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
parent94071b54d24d2f2f1cb5933a692b5397a047057c (diff)
downloadprotobuf-bfee2dfe137b07e64ebd46baf71d932d58d01b1f.tar.gz
protobuf-bfee2dfe137b07e64ebd46baf71d932d58d01b1f.tar.bz2
protobuf-bfee2dfe137b07e64ebd46baf71d932d58d01b1f.zip
Implement freezing for messages and repeated fields.
Fixes issue #523.
Diffstat (limited to 'csharp/src/ProtocolBuffers/Collections/RepeatedField.cs')
-rw-r--r--csharp/src/ProtocolBuffers/Collections/RepeatedField.cs35
1 files changed, 33 insertions, 2 deletions
diff --git a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
index 5100e4db..ebfc522f 100644
--- a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
+++ b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
@@ -4,10 +4,16 @@ using System.Collections.Generic;
namespace Google.Protobuf.Collections
{
- public sealed class RepeatedField<T> : IList<T>, IEquatable<RepeatedField<T>>
+ /// <summary>
+ /// The contents of a repeated field: essentially, a collection with some extra
+ /// restrictions (no null values) and capabilities (deep cloning and freezing).
+ /// </summary>
+ /// <typeparam name="T">The element type of the repeated field.</typeparam>
+ public sealed class RepeatedField<T> : IList<T>, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, IFreezable
{
private static readonly T[] EmptyArray = new T[0];
+ private bool frozen;
private const int MinArraySize = 8;
private T[] array = EmptyArray;
private int count = 0;
@@ -26,6 +32,7 @@ namespace Google.Protobuf.Collections
public RepeatedField<T> Clone()
{
RepeatedField<T> clone = new RepeatedField<T>();
+ // Clone is implicitly *not* frozen, even if this object is.
if (array != EmptyArray)
{
clone.array = (T[])array.Clone();
@@ -42,6 +49,21 @@ namespace Google.Protobuf.Collections
return clone;
}
+ public bool IsFrozen { get { return frozen; } }
+
+ public void Freeze()
+ {
+ frozen = true;
+ IFreezable[] freezableArray = array as IFreezable[];
+ if (freezableArray != null)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ freezableArray[i].Freeze();
+ }
+ }
+ }
+
private void EnsureSize(int size)
{
size = Math.Max(size, MinArraySize);
@@ -60,6 +82,7 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentNullException("item");
}
+ this.CheckMutable();
EnsureSize(count + 1);
array[count++] = item;
}
@@ -70,6 +93,7 @@ namespace Google.Protobuf.Collections
/// <param name="readEnum"></param>
internal void AddInt32(int item)
{
+ this.CheckMutable();
EnsureSize(count + 1);
int[] castArray = (int[]) (object) array;
castArray[count++] = item;
@@ -77,6 +101,7 @@ namespace Google.Protobuf.Collections
public void Clear()
{
+ this.CheckMutable();
array = EmptyArray;
count = 0;
}
@@ -93,6 +118,7 @@ namespace Google.Protobuf.Collections
public bool Remove(T item)
{
+ this.CheckMutable();
int index = IndexOf(item);
if (index == -1)
{
@@ -107,7 +133,7 @@ namespace Google.Protobuf.Collections
public int Count { get { return count; } }
// TODO(jonskeet): If we implement freezing, make this reflect it.
- public bool IsReadOnly { get { return false; } }
+ public bool IsReadOnly { get { return IsFrozen; } }
public void Add(RepeatedField<T> values)
{
@@ -115,6 +141,7 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentNullException("values");
}
+ this.CheckMutable();
EnsureSize(count + values.count);
// We know that all the values will be valid, because it's a RepeatedField.
Array.Copy(values.array, 0, array, count, values.count);
@@ -127,6 +154,7 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentNullException("values");
}
+ this.CheckMutable();
// TODO: Check for ICollection and get the Count?
foreach (T item in values)
{
@@ -227,6 +255,7 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentOutOfRangeException("index");
}
+ this.CheckMutable();
EnsureSize(count + 1);
Array.Copy(array, index, array, index + 1, count - index);
count++;
@@ -238,6 +267,7 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentOutOfRangeException("index");
}
+ this.CheckMutable();
Array.Copy(array, index + 1, array, index, count - index - 1);
count--;
array[count] = default(T);
@@ -259,6 +289,7 @@ namespace Google.Protobuf.Collections
{
throw new ArgumentOutOfRangeException("index");
}
+ this.CheckMutable();
if (value == null)
{
throw new ArgumentNullException("value");