Added read-only collection wrappers for IDictionary<>, IList<> and ICollection<> since the classes provided by the .NET framework in System.Collections.ObjectModel are incomplete and inconsistent (eg. System.Collections.ObjectModel.ReadOnlyCollection wraps an IList<>!); minor improvements to documentation; added ReverseComparer for inverting the results of an existing IComparer<> or simply comparing values in inverted order

git-svn-id: file:///srv/devel/repo-conversion/nusu@80 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2008-07-17 20:44:40 +00:00
parent f5eefc6765
commit 2cc7b27b0c
7 changed files with 748 additions and 16 deletions

View File

@ -81,6 +81,8 @@
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
@ -100,6 +102,10 @@
<Compile Include="Source\Collections\PriorityQueue.Test.cs">
<DependentUpon>PriorityQueue.cs</DependentUpon>
</Compile>
<Compile Include="Source\Collections\ReadOnlyCollection.cs" />
<Compile Include="Source\Collections\ReadOnlyDictionary.cs" />
<Compile Include="Source\Collections\ReadOnlyList.cs" />
<Compile Include="Source\Collections\ReverseComparer.cs" />
<Compile Include="Source\Collections\RingMemoryStream.cs" />
<Compile Include="Source\Collections\RingMemoryStream.Test.cs">
<DependentUpon>RingMemoryStream.cs</DependentUpon>

View File

@ -127,7 +127,7 @@ namespace Nuclex.Support.Collections {
ItemType result = this.heap[0];
--this.count;
trickleDown(0, heap[this.count]);
trickleDown(0, this.heap[this.count]);
++this.version;

View File

@ -0,0 +1,120 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Nuclex.Support.Collections {
/// <summary>Wraps a Collection and prevents users from modifying it</summary>
/// <typeparam name="ItemType">Type of items to manage in the Collection</typeparam>
public class ReadOnlyCollection<ItemType> :
ICollection<ItemType>,
ICollection {
/// <summary>Initializes a new read-only Collection wrapper</summary>
/// <param name="collection">Collection that will be wrapped</param>
public ReadOnlyCollection(ICollection<ItemType> collection) {
this.typedCollection = collection;
this.objectCollection = (collection as ICollection);
}
/// <summary>Determines whether the List contains the specified item</summary>
/// <param name="item">Item that will be checked for</param>
/// <returns>True if the specified item is contained in the List</returns>
public bool Contains(ItemType item) {
return this.typedCollection.Contains(item);
}
/// <summary>Copies the contents of the List into an array</summary>
/// <param name="array">Array the List will be copied into</param>
/// <param name="arrayIndex">
/// Starting index at which to begin filling the destination array
/// </param>
public void CopyTo(ItemType[] array, int arrayIndex) {
this.typedCollection.CopyTo(array, arrayIndex);
}
/// <summary>The number of items current contained in the List</summary>
public int Count {
get { return this.typedCollection.Count; }
}
/// <summary>Whether the List is write-protected</summary>
public bool IsReadOnly {
get { return true; }
}
/// <summary>Returns a new enumerator over the contents of the List</summary>
/// <returns>The new List contents enumerator</returns>
public IEnumerator<ItemType> GetEnumerator() {
return this.typedCollection.GetEnumerator();
}
#region ICollection<> implementation
/// <summary>Adds an item to the end of the List</summary>
/// <param name="item">Item that will be added to the List</param>
void ICollection<ItemType>.Add(ItemType item) {
throw new NotSupportedException(
"Adding items is not supported by the read-only List"
);
}
/// <summary>Removes all items from the List</summary>
void ICollection<ItemType>.Clear() {
throw new NotSupportedException(
"Clearing is not supported by the read-only List"
);
}
/// <summary>Removes the specified item from the List</summary>
/// <param name="item">Item that will be removed from the List</param>
/// <returns>True of the specified item was found in the List and removed</returns>
bool ICollection<ItemType>.Remove(ItemType item) {
throw new NotSupportedException(
"Removing items is not supported by the read-only List"
);
}
#endregion
#region IEnumerable implementation
/// <summary>Returns a new enumerator over the contents of the List</summary>
/// <returns>The new List contents enumerator</returns>
IEnumerator IEnumerable.GetEnumerator() {
return this.objectCollection.GetEnumerator();
}
#endregion
#region ICollection implementation
/// <summary>Copies the contents of the List into an array</summary>
/// <param name="array">Array the List will be copied into</param>
/// <param name="index">
/// Starting index at which to begin filling the destination array
/// </param>
void ICollection.CopyTo(Array array, int index) {
throw new NotImplementedException();
}
/// <summary>Whether the List is synchronized for multi-threaded usage</summary>
bool ICollection.IsSynchronized {
get { throw new NotImplementedException(); }
}
/// <summary>Synchronization root on which the List locks</summary>
object ICollection.SyncRoot {
get { throw new NotImplementedException(); }
}
#endregion
/// <summary>The wrapped Collection under its type-safe interface</summary>
private ICollection<ItemType> typedCollection;
/// <summary>The wrapped Collection under its object interface</summary>
private ICollection objectCollection;
}
} // namespace Nuclex.Support.Collections

View File

@ -0,0 +1,326 @@
using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
namespace Nuclex.Support.Collections {
/// <summary>Wraps a Dictionary and prevents users from modifying it</summary>
/// <typeparam name="KeyType">Type of the keys used in the Dictionary</typeparam>
/// <typeparam name="ValueType">Type of the values used in the Dictionary</typeparam>
public class ReadOnlyDictionary<KeyType, ValueType> :
IDictionary<KeyType, ValueType>,
IDictionary,
ISerializable,
IDeserializationCallback {
/// <summary>Initializes a new read-only Dictionary wrapper</summary>
/// <param name="dictionary">Dictionary that will be wrapped</param>
public ReadOnlyDictionary(IDictionary<KeyType, ValueType> dictionary) {
this.typedDictionary = dictionary;
this.objectDictionary = (this.typedDictionary as IDictionary);
}
/// <summary>Whether the directory is write-protected</summary>
public bool IsReadOnly {
get { return true; }
}
/// <summary>
/// Determines whether the specified KeyValuePair is contained in the Dictionary
/// </summary>
/// <param name="item">KeyValuePair that will be checked for</param>
/// <returns>True if the provided KeyValuePair was contained in the Dictionary</returns>
public bool Contains(KeyValuePair<KeyType, ValueType> item) {
return this.typedDictionary.Contains(item);
}
/// <summary>Determines whether the Dictionary contains the specified key</summary>
/// <param name="key">Key that will be checked for</param>
/// <returns>
/// True if an entry with the specified key was contained in the Dictionary
/// </returns>
public bool ContainsKey(KeyType key) {
return this.typedDictionary.ContainsKey(key);
}
/// <summary>Copies the contents of the Dictionary into an array</summary>
/// <param name="array">Array the Dictionary will be copied into</param>
/// <param name="arrayIndex">
/// Starting index at which to begin filling the destination array
/// </param>
public void CopyTo(KeyValuePair<KeyType, ValueType>[] array, int arrayIndex) {
this.typedDictionary.CopyTo(array, arrayIndex);
}
/// <summary>Number of elements contained in the Dictionary</summary>
public int Count {
get { return this.typedDictionary.Count; }
}
/// <summary>Creates a new enumerator for the Dictionary</summary>
/// <returns>The new Dictionary enumerator</returns>
public IEnumerator<KeyValuePair<KeyType, ValueType>> GetEnumerator() {
return this.typedDictionary.GetEnumerator();
}
/// <summary>Collection of all keys contained in the Dictionary</summary>
public ICollection<KeyType> Keys {
get {
if(this.readonlyKeyCollection == null) {
this.readonlyKeyCollection = new ReadOnlyCollection<KeyType>(
this.typedDictionary.Keys
);
}
return this.readonlyKeyCollection;
}
}
/// <summary>Collection aller Werte im Dictionary</summary>
public ICollection<ValueType> Values { // TODO: RO-Wrappen!
get {
if(this.readonlyValueCollection == null) {
this.readonlyValueCollection = new ReadOnlyCollection<ValueType>(
this.typedDictionary.Values
);
}
return this.readonlyValueCollection;
}
}
/// <summary>
/// Attempts to retrieve the item with the specified key from the Dictionary
/// </summary>
/// <param name="key">Key of the item to attempt to retrieve</param>
/// <param name="value">
/// Output parameter that will receive the key upon successful completion
/// </param>
/// <returns>
/// True if the item was found and has been placed in the output parameter
/// </returns>
public bool TryGetValue(KeyType key, out ValueType value) {
return this.typedDictionary.TryGetValue(key, out value);
}
/// <summary>Accesses an item in the Dictionary by its key</summary>
/// <param name="key">Key of the item that will be accessed</param>
public ValueType this[KeyType key] {
get { return this.typedDictionary[key]; }
}
#region IDictionary<,> implementation
/// <summary>Inserts an item into the Dictionary</summary>
/// <param name="key">Key under which to add the new item</param>
/// <param name="value">Item that will be added to the Dictionary</param>
void IDictionary<KeyType, ValueType>.Add(KeyType key, ValueType value) {
throw new NotSupportedException(
"Adding items is not supported by the read-only Dictionary"
);
}
/// <summary>Removes the item with the specified key from the Dictionary</summary>
/// <param name="key">Key of the elementes that will be removed</param>
/// <returns>True if an item with the specified key was found and removed</returns>
bool IDictionary<KeyType, ValueType>.Remove(KeyType key) {
throw new NotSupportedException(
"Removing items is not supported by the read-only Dictionary"
);
}
/// <summary>Accesses an item in the Dictionary by its key</summary>
/// <param name="key">Key of the item that will be accessed</param>
ValueType IDictionary<KeyType, ValueType>.this[KeyType key] {
get { return this.typedDictionary[key]; }
set {
throw new NotSupportedException(
"Assigning items is not supported in a read-only Dictionary"
);
}
}
#endregion
#region IEnumerable implementation
/// <summary>Returns a new object enumerator for the Dictionary</summary>
/// <returns>The new object enumerator</returns>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return (this.typedDictionary as IEnumerable).GetEnumerator();
}
#endregion
#region IDictionary implementation
/// <summary>Removes all items from the Dictionary</summary>
void IDictionary.Clear() {
throw new NotSupportedException(
"Clearing is not supported in a read-only Dictionary"
);
}
/// <summary>Adds an item into the Dictionary</summary>
/// <param name="key">Key under which the item will be added</param>
/// <param name="value">Item that will be added</param>
void IDictionary.Add(object key, object value) {
throw new NotSupportedException(
"Adding items is not supported in a read-only Dictionary"
);
}
/// <summary>Determines whether the specified key exists in the Dictionary</summary>
/// <param name="key">Key that will be checked for</param>
/// <returns>True if an item with the specified key exists in the Dictionary</returns>
bool IDictionary.Contains(object key) {
return this.objectDictionary.Contains(key);
}
/// <summary>Returns a new entry enumerator for the dictionary</summary>
/// <returns>The new entry enumerator</returns>
IDictionaryEnumerator IDictionary.GetEnumerator() {
return this.objectDictionary.GetEnumerator();
}
/// <summary>Whether the size of the Dictionary is fixed</summary>
bool IDictionary.IsFixedSize {
get { return this.objectDictionary.IsFixedSize; }
}
/// <summary>Returns a collection of all keys in the Dictionary</summary>
ICollection IDictionary.Keys {
get {
if(this.readonlyKeyCollection == null) {
this.readonlyKeyCollection = new ReadOnlyCollection<KeyType>(
this.typedDictionary.Keys
);
}
return this.readonlyKeyCollection;
}
}
/// <summary>Returns a collection of all values stored in the Dictionary</summary>
ICollection IDictionary.Values {
get {
if(this.readonlyValueCollection == null) {
this.readonlyValueCollection = new ReadOnlyCollection<ValueType>(
this.typedDictionary.Values
);
}
return this.readonlyValueCollection;
}
}
/// <summary>Removes an item from the Dictionary</summary>
/// <param name="key">Key of the item that will be removed</param>
void IDictionary.Remove(object key) {
throw new NotSupportedException(
"Removing is not supported by the read-only Dictionary"
);
}
/// <summary>Accesses an item in the Dictionary by its key</summary>
/// <param name="key">Key of the item that will be accessed</param>
/// <returns>The item with the specified key</returns>
object IDictionary.this[object key] {
get { return this.objectDictionary[key]; }
set {
throw new NotSupportedException(
"Assigning items is not supported by the read-only Dictionary"
);
}
}
#endregion
#region ICollection<> implementation
/// <summary>Inserts an already prepared element into the Dictionary</summary>
/// <param name="item">Prepared element that will be added to the Dictionary</param>
void ICollection<KeyValuePair<KeyType, ValueType>>.Add(
KeyValuePair<KeyType, ValueType> item
) {
throw new NotSupportedException(
"Adding items is not supported by the read-only Dictionary"
);
}
/// <summary>Removes all items from the Dictionary</summary>
void ICollection<KeyValuePair<KeyType, ValueType>>.Clear() {
throw new NotSupportedException(
"Clearing is not supported in a read-only Dictionary"
);
}
/// <summary>Removes all items from the Dictionary</summary>
/// <param name="itemToRemove">Item that will be removed from the Dictionary</param>
bool ICollection<KeyValuePair<KeyType, ValueType>>.Remove(
KeyValuePair<KeyType, ValueType> itemToRemove
) {
throw new NotSupportedException(
"Removing items is not supported in a read-only Dictionary"
);
}
#endregion
#region ICollection implementation
/// <summary>Copies the contents of the Dictionary into an array</summary>
/// <param name="array">Array the Dictionary contents will be copied into</param>
/// <param name="index">
/// Starting index at which to begin filling the destination array
/// </param>
void ICollection.CopyTo(Array array, int index) {
this.objectDictionary.CopyTo(array, index);
}
/// <summary>Whether the Dictionary is synchronized for multi-threaded usage</summary>
bool ICollection.IsSynchronized {
get { return this.objectDictionary.IsSynchronized; }
}
/// <summary>Synchronization root on which the Dictionary locks</summary>
object ICollection.SyncRoot {
get { return this.objectDictionary.SyncRoot; }
}
#endregion
#region ISerializable implementation
/// <summary>Serializes the Dictionary</summary>
/// <param name="info">
/// Provides the container into which the Dictionary will serialize itself
/// </param>
/// <param name="context">
/// Contextual informations about the serialization environment
/// </param>
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
(this.typedDictionary as ISerializable).GetObjectData(info, context);
}
/// <summary>Called after all objects have been successfully deserialized</summary>
/// <param name="sender">Nicht unterstützt</param>
void IDeserializationCallback.OnDeserialization(object sender) {
(this.typedDictionary as IDeserializationCallback).OnDeserialization(sender);
}
#endregion
/// <summary>The wrapped Dictionary under its type-safe interface</summary>
private IDictionary<KeyType, ValueType> typedDictionary;
/// <summary>The wrapped Dictionary under its object interface</summary>
private IDictionary objectDictionary;
/// <summary>ReadOnly wrapper for the keys collection of the Dictionary</summary>
private ReadOnlyCollection<KeyType> readonlyKeyCollection;
/// <summary>ReadOnly wrapper for the values collection of the Dictionary</summary>
private ReadOnlyCollection<ValueType> readonlyValueCollection;
}
} // namespace Nuclex.Support.Collections

View File

@ -0,0 +1,240 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Nuclex.Support.Collections {
/// <summary>Wraps a List and prevents users from modifying it</summary>
/// <typeparam name="ItemType">Type of items to manage in the List</typeparam>
public class ReadOnlyList<ItemType> :
IList<ItemType>,
IList {
/// <summary>Initializes a new read-only List wrapper</summary>
/// <param name="list">List that will be wrapped</param>
public ReadOnlyList(IList<ItemType> list) {
this.typedList = list;
this.objectList = (list as IList);
}
/// <summary>Retrieves the index of an item within the List</summary>
/// <param name="item">Item whose index will be returned</param>
/// <returns>The zero-based index of the specified item in the List</returns>
public int IndexOf(ItemType item) {
return this.typedList.IndexOf(item);
}
/// <summary>Accesses the List item with the specified index</summary>
/// <param name="index">Zero-based index of the List item that will be accessed</param>
public ItemType this[int index] {
get { return this.typedList[index]; }
}
/// <summary>Determines whether the List contains the specified item</summary>
/// <param name="item">Item that will be checked for</param>
/// <returns>True if the specified item is contained in the List</returns>
public bool Contains(ItemType item) {
return this.typedList.Contains(item);
}
/// <summary>Copies the contents of the List into an array</summary>
/// <param name="array">Array the List will be copied into</param>
/// <param name="arrayIndex">
/// Starting index at which to begin filling the destination array
/// </param>
public void CopyTo(ItemType[] array, int arrayIndex) {
this.typedList.CopyTo(array, arrayIndex);
}
/// <summary>The number of items current contained in the List</summary>
public int Count {
get { return this.typedList.Count; }
}
/// <summary>Whether the List is write-protected</summary>
public bool IsReadOnly {
get { return true; }
}
/// <summary>Returns a new enumerator over the contents of the List</summary>
/// <returns>The new List contents enumerator</returns>
public IEnumerator<ItemType> GetEnumerator() {
return this.typedList.GetEnumerator();
}
#region IList<> implementation
/// <summary>Inserts an item into the List</summary>
/// <param name="index">Zero-based index before which the item will be inserted</param>
/// <param name="item">Item that will be inserted into the List</param>
void IList<ItemType>.Insert(int index, ItemType item) {
throw new NotSupportedException(
"Inserting items is not supported by the read-only List"
);
}
/// <summary>Removes an item from the list</summary>
/// <param name="index">Zero-based index of the item that will be removed</param>
void IList<ItemType>.RemoveAt(int index) {
throw new NotSupportedException(
"Removing items is not supported by the read-only List"
);
}
/// <summary>Accesses the List item with the specified index</summary>
/// <param name="index">Zero-based index of the List item that will be accessed</param>
ItemType IList<ItemType>.this[int index] {
get { return this.typedList[index]; }
set {
throw new NotSupportedException(
"Assigning items is not supported by the read-only List"
);
}
}
#endregion
#region ICollection<> implementation
/// <summary>Adds an item to the end of the List</summary>
/// <param name="item">Item that will be added to the List</param>
void ICollection<ItemType>.Add(ItemType item) {
throw new NotSupportedException(
"Adding items is not supported by the read-only List"
);
}
/// <summary>Removes all items from the List</summary>
void ICollection<ItemType>.Clear() {
throw new NotSupportedException(
"Clearing is not supported by the read-only List"
);
}
/// <summary>Removes the specified item from the List</summary>
/// <param name="item">Item that will be removed from the List</param>
/// <returns>True of the specified item was found in the List and removed</returns>
bool ICollection<ItemType>.Remove(ItemType item) {
throw new NotSupportedException(
"Removing items is not supported by the read-only List"
);
}
#endregion
#region IEnumerable implementation
/// <summary>Returns a new enumerator over the contents of the List</summary>
/// <returns>The new List contents enumerator</returns>
IEnumerator IEnumerable.GetEnumerator() {
return this.objectList.GetEnumerator();
}
#endregion
#region IList implementation
/// <summary>Removes all items from the List</summary>
void IList.Clear() {
throw new NotSupportedException(
"Clearing is not supported by the read-only List"
);
}
/// <summary>Adds an item to the end of the List</summary>
/// <param name="value">Item that will be added to the List</param>
int IList.Add(object value) {
throw new NotSupportedException(
"Adding items is not supported by the read-only List"
);
}
/// <summary>Determines whether the List contains the specified item</summary>
/// <param name="value">Item that will be checked for</param>
/// <returns>True if the specified item is contained in the List</returns>
bool IList.Contains(object value) {
return this.objectList.Contains(value);
}
/// <summary>Retrieves the index of an item within the List</summary>
/// <param name="value">Item whose index will be returned</param>
/// <returns>The zero-based index of the specified item in the List</returns>
int IList.IndexOf(object value) {
return this.objectList.IndexOf(value);
}
/// <summary>Inserts an item into the List</summary>
/// <param name="index">Zero-based index before which the item will be inserted</param>
/// <param name="value">Item that will be inserted into the List</param>
void IList.Insert(int index, object value) {
throw new NotSupportedException(
"Inserting items is not supported by the read-only List"
);
}
/// <summary>Whether the size of the List is fixed</summary>
bool IList.IsFixedSize {
get { throw new NotImplementedException(); }
}
/// <summary>Removes the specified item from the List</summary>
/// <param name="value">Item that will be removed from the List</param>
/// <returns>True of the specified item was found in the List and removed</returns>
void IList.Remove(object value) {
throw new NotSupportedException(
"Removing items is not supported by the read-only List"
);
}
/// <summary>Removes an item from the list</summary>
/// <param name="index">Zero-based index of the item that will be removed</param>
void IList.RemoveAt(int index) {
throw new NotSupportedException(
"Removing items is not supported by the read-only List"
);
}
/// <summary>Accesses the List item with the specified index</summary>
/// <param name="index">Zero-based index of the List item that will be accessed</param>
object IList.this[int index] {
get { return this.objectList[index]; }
set {
throw new NotSupportedException(
"Assigning items is not supported by the read-only List"
);
}
}
#endregion
#region ICollection implementation
/// <summary>Copies the contents of the List into an array</summary>
/// <param name="array">Array the List will be copied into</param>
/// <param name="index">
/// Starting index at which to begin filling the destination array
/// </param>
void ICollection.CopyTo(Array array, int index) {
this.objectList.CopyTo(array, index);
}
/// <summary>Whether the List is synchronized for multi-threaded usage</summary>
bool ICollection.IsSynchronized {
get { return this.objectList.IsSynchronized; }
}
/// <summary>Synchronization root on which the List locks</summary>
object ICollection.SyncRoot {
get { return this.objectList.SyncRoot; }
}
#endregion
/// <summary>The wrapped List under its type-safe interface</summary>
private IList<ItemType> typedList;
/// <summary>The wrapped List under its object interface</summary>
private IList objectList;
}
} // namespace Nuclex.Support.Collections

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
namespace Nuclex.Support.Collections {
/// <summary>
/// Compares two values in reverse or reverses the output of another comparer
/// </summary>
/// <typeparam name="ComparedType">Type of values to be compared</typeparam>
public class ReverseComparer<ComparedType> : IComparer<ComparedType> {
/// <summary>Initializes a new reverse comparer</summary>
public ReverseComparer() : this(Comparer<ComparedType>.Default) { }
/// <summary>
/// Initializes the comparer to provide the inverse results of another comparer
/// </summary>
/// <param name="comparerToReverse">Comparer whose results will be inversed</param>
public ReverseComparer(IComparer<ComparedType> comparerToReverse) {
this.comparer = comparerToReverse;
}
/// <summary>Compares the left value to the right value</summary>
/// <param name="left">Value on the left side</param>
/// <param name="right">Value on the right side</param>
/// <returns>The relationship of the two values</returns>
public int Compare(ComparedType left, ComparedType right) {
return this.comparer.Compare(right, left); // intentionally reversed
}
/// <summary>The default comparer from the .NET framework</summary>
private IComparer<ComparedType> comparer;
}
} // namespace Nuclex.Support.Collections

View File

@ -25,7 +25,7 @@ namespace Nuclex.Support.Collections {
/// <summary>Specialized memory stream for ring buffers</summary>
/// <remarks>
/// This ring buffer class is specialized for binary data and attempts to achieve
/// This ring buffer class is specialized for binary data and tries to achieve
/// optimal efficiency when storing and retrieving chunks of several bytes
/// at once. Typical use cases include audio and network buffers where one party
/// is responsible for refilling the buffer at regular intervals while the other
@ -50,10 +50,11 @@ namespace Nuclex.Support.Collections {
get { return this.ringBuffer.Length; }
set {
int length = (int)Length;
if(value < length)
if(value < length) {
throw new ArgumentOutOfRangeException(
"New capacity is less than the stream's length"
"New capacity is less than the stream's current length"
);
}
// This could be done in a more efficient manner than just replacing
// the entire buffer, but since this operation will probably be only called
@ -62,8 +63,9 @@ namespace Nuclex.Support.Collections {
MemoryStream newBuffer = new MemoryStream((int)value);
newBuffer.SetLength(value);
if(length > 0)
if(length > 0) {
Read(newBuffer.GetBuffer(), 0, length);
}
this.ringBuffer.Close(); // Equals dispose of the old buffer
this.ringBuffer = newBuffer;
@ -119,12 +121,13 @@ namespace Nuclex.Support.Collections {
this.ringBuffer.Read(buffer, offset, count);
this.startIndex += count;
if(this.startIndex == this.endIndex)
if(this.startIndex == this.endIndex) {
setEmpty();
}
}
// The end index lies before the start index, so the data in the
// ring memory stream is fragmented. Example: |#####>-------<#####|
// The end index lies before the start index, so the data in the
// ring memory stream is fragmented. Example: |#####>-------<#####|
} else {
int linearAvailable = (int)this.ringBuffer.Length - this.startIndex;
@ -142,8 +145,8 @@ namespace Nuclex.Support.Collections {
this.startIndex = count - linearAvailable;
this.ringBuffer.Read(buffer, offset + linearAvailable, this.startIndex);
// Nope, the amount of requested data can be read in one piece without
// crossing the end of the ring buffer
// Nope, the amount of requested data can be read in one piece without
// crossing the end of the ring buffer
} else {
this.ringBuffer.Position = this.startIndex;
this.ringBuffer.Read(buffer, offset, count);
@ -151,8 +154,9 @@ namespace Nuclex.Support.Collections {
}
if(this.startIndex == this.endIndex)
if(this.startIndex == this.endIndex) {
setEmpty();
}
}
return count;
@ -183,8 +187,8 @@ namespace Nuclex.Support.Collections {
this.endIndex = count - linearAvailable;
this.ringBuffer.Write(buffer, offset + linearAvailable, this.endIndex);
// All data can be appended at the current stream position without
// crossing the ring memory stream's end
// All data can be appended at the current stream position without
// crossing the ring memory stream's end
} else {
this.ringBuffer.Position = this.endIndex;
this.ringBuffer.Write(buffer, offset, count);
@ -193,9 +197,9 @@ namespace Nuclex.Support.Collections {
this.empty = false;
// The end index lies before the start index, so the data in the ring memory
// stream has been fragmented. This means the gap into which we are about
// to write is not fragmented. Example: |#####>-------<#####|
// The end index lies before the start index, so the data in the ring memory
// stream has been fragmented. This means the gap into which we are about
// to write is not fragmented. Example: |#####>-------<#####|
} else {
if(count > (this.startIndex - this.endIndex))
throw new OverflowException("Data does not fit in buffer");