The deque class now fully supports the IList<> and IList interfaces (with the exception of CopyTo() and CopyToArray() which are not implemented yet); implemented a Clear() method; the deque enumerator is now fully functioning (but still missing an out-of-sync check); moved IndexOf() into its own file; wrote several additional unit tests to verify all the new interface methods are working and to keep test coverage at 100%
git-svn-id: file:///srv/devel/repo-conversion/nusu@163 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
		
							parent
							
								
									a817f52406
								
							
						
					
					
						commit
						3ee5fdfc67
					
				
					 8 changed files with 713 additions and 94 deletions
				
			
		| 
						 | 
					@ -73,9 +73,15 @@
 | 
				
			||||||
    <Compile Include="Source\Collections\Deque.Insertion.cs">
 | 
					    <Compile Include="Source\Collections\Deque.Insertion.cs">
 | 
				
			||||||
      <DependentUpon>Deque.cs</DependentUpon>
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="Source\Collections\Deque.Interfaces.cs">
 | 
				
			||||||
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="Source\Collections\Deque.Removal.cs">
 | 
					    <Compile Include="Source\Collections\Deque.Removal.cs">
 | 
				
			||||||
      <DependentUpon>Deque.cs</DependentUpon>
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="Source\Collections\Deque.Search.cs">
 | 
				
			||||||
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="Source\Collections\Deque.Test.cs">
 | 
					    <Compile Include="Source\Collections\Deque.Test.cs">
 | 
				
			||||||
      <DependentUpon>Deque.cs</DependentUpon>
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,9 +55,15 @@
 | 
				
			||||||
    <Compile Include="Source\Collections\Deque.Insertion.cs">
 | 
					    <Compile Include="Source\Collections\Deque.Insertion.cs">
 | 
				
			||||||
      <DependentUpon>Deque.cs</DependentUpon>
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="Source\Collections\Deque.Interfaces.cs">
 | 
				
			||||||
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="Source\Collections\Deque.Removal.cs">
 | 
					    <Compile Include="Source\Collections\Deque.Removal.cs">
 | 
				
			||||||
      <DependentUpon>Deque.cs</DependentUpon>
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="Source\Collections\Deque.Search.cs">
 | 
				
			||||||
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="Source\Collections\Deque.Test.cs">
 | 
					    <Compile Include="Source\Collections\Deque.Test.cs">
 | 
				
			||||||
      <DependentUpon>Deque.cs</DependentUpon>
 | 
					      <DependentUpon>Deque.cs</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,14 +23,14 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    /// <summary>Appends an item to the end of the double-ended queue</summary>
 | 
					    /// <summary>Appends an item to the end of the double-ended queue</summary>
 | 
				
			||||||
    /// <param name="item">Item that will be appended to the queue</param>
 | 
					    /// <param name="item">Item that will be appended to the queue</param>
 | 
				
			||||||
    public void AddLast(ItemType item) {
 | 
					    public void AddLast(ItemType item) {
 | 
				
			||||||
      if(this.lastBlockEndIndex < this.blockSize) {
 | 
					      if(this.lastBlockCount < this.blockSize) {
 | 
				
			||||||
        ++this.lastBlockEndIndex;
 | 
					        ++this.lastBlockCount;
 | 
				
			||||||
      } else { // Need to allocate a new block
 | 
					      } else { // Need to allocate a new block
 | 
				
			||||||
        this.blocks.Add(new ItemType[this.blockSize]);
 | 
					        this.blocks.Add(new ItemType[this.blockSize]);
 | 
				
			||||||
        this.lastBlockEndIndex = 1;
 | 
					        this.lastBlockCount = 1;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.blocks[this.blocks.Count - 1][this.lastBlockEndIndex - 1] = item;
 | 
					      this.blocks[this.blocks.Count - 1][this.lastBlockCount - 1] = item;
 | 
				
			||||||
      ++this.count;
 | 
					      ++this.count;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -137,15 +137,15 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
        int blockLength;
 | 
					        int blockLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If the lastmost block is full, we need to add another block
 | 
					        // If the lastmost block is full, we need to add another block
 | 
				
			||||||
        if(this.lastBlockEndIndex == this.blockSize) {
 | 
					        if(this.lastBlockCount == this.blockSize) {
 | 
				
			||||||
          this.blocks.Add(new ItemType[this.blockSize]);
 | 
					          this.blocks.Add(new ItemType[this.blockSize]);
 | 
				
			||||||
          this.blocks[lastBlock + 1][0] = this.blocks[lastBlock][this.blockSize - 1];
 | 
					          this.blocks[lastBlock + 1][0] = this.blocks[lastBlock][this.blockSize - 1];
 | 
				
			||||||
          this.lastBlockEndIndex = 1;
 | 
					          this.lastBlockCount = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          blockLength = this.blockSize - 1;
 | 
					          blockLength = this.blockSize - 1;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          blockLength = this.lastBlockEndIndex;
 | 
					          blockLength = this.lastBlockCount;
 | 
				
			||||||
          ++this.lastBlockEndIndex;
 | 
					          ++this.lastBlockCount;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If the insertion point is not in the lastmost block
 | 
					        // If the insertion point is not in the lastmost block
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										126
									
								
								Source/Collections/Deque.Interfaces.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								Source/Collections/Deque.Interfaces.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,126 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Nuclex.Support.Collections {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  partial class Deque<ItemType> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #region IEnumerable members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Obtains a new enumerator for the contents of the deque</summary>
 | 
				
			||||||
 | 
					    /// <returns>The new enumerator</returns>
 | 
				
			||||||
 | 
					    IEnumerator IEnumerable.GetEnumerator() {
 | 
				
			||||||
 | 
					      return new Enumerator(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #region IList Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Adds an item to the deque</summary>
 | 
				
			||||||
 | 
					    /// <param name="value">Item that will be added to the deque</param>
 | 
				
			||||||
 | 
					    /// <returns>The index at which the new item was added</returns>
 | 
				
			||||||
 | 
					    int IList.Add(object value) {
 | 
				
			||||||
 | 
					      verifyCompatibleObject(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      AddLast((ItemType)value);
 | 
				
			||||||
 | 
					      return this.count - 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Checks whether the deque contains the specified item</summary>
 | 
				
			||||||
 | 
					    /// <param name="value">Item the deque will be scanned for</param>
 | 
				
			||||||
 | 
					    /// <returns>True if the deque contained the specified item</returns>
 | 
				
			||||||
 | 
					    bool IList.Contains(object value) {
 | 
				
			||||||
 | 
					      return isCompatibleObject(value) && Contains((ItemType)value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Determines the index of the item in the deque</summary>
 | 
				
			||||||
 | 
					    /// <param name="value">Item whose index will be determined</param>
 | 
				
			||||||
 | 
					    /// <returns>The index of the specified item in the deque</returns>
 | 
				
			||||||
 | 
					    int IList.IndexOf(object value) {
 | 
				
			||||||
 | 
					      if(isCompatibleObject(value)) {
 | 
				
			||||||
 | 
					        return IndexOf((ItemType)value);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Inserts an item into the deque at the specified location</summary>
 | 
				
			||||||
 | 
					    /// <param name="index">Index at which the item will be inserted</param>
 | 
				
			||||||
 | 
					    /// <param name="value">Item that will be inserted</param>
 | 
				
			||||||
 | 
					    void IList.Insert(int index, object value) {
 | 
				
			||||||
 | 
					      verifyCompatibleObject(value);
 | 
				
			||||||
 | 
					      Insert(index, (ItemType)value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Whether the deque has a fixed size</summary>
 | 
				
			||||||
 | 
					    bool IList.IsFixedSize {
 | 
				
			||||||
 | 
					      get { return false; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Whether the deque is read-only</summary>
 | 
				
			||||||
 | 
					    bool IList.IsReadOnly {
 | 
				
			||||||
 | 
					      get { throw new NotImplementedException(); }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Removes the specified item from the deque</summary>
 | 
				
			||||||
 | 
					    /// <param name="value">Item that will be removed from the deque</param>
 | 
				
			||||||
 | 
					    void IList.Remove(object value) {
 | 
				
			||||||
 | 
					      if(isCompatibleObject(value)) {
 | 
				
			||||||
 | 
					        Remove((ItemType)value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Accesses an item in the deque by its index</summary>
 | 
				
			||||||
 | 
					    /// <param name="index">Index of the item that will be accessed</param>
 | 
				
			||||||
 | 
					    /// <returns>The item at the specified index</returns>
 | 
				
			||||||
 | 
					    object IList.this[int index] {
 | 
				
			||||||
 | 
					      get { return this[index]; }
 | 
				
			||||||
 | 
					      set {
 | 
				
			||||||
 | 
					        verifyCompatibleObject(value);
 | 
				
			||||||
 | 
					        this[index] = (ItemType)value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #region ICollection<ItemType> Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Adds an item into the deque</summary>
 | 
				
			||||||
 | 
					    /// <param name="item">Item that will be added to the deque</param>
 | 
				
			||||||
 | 
					    void ICollection<ItemType>.Add(ItemType item) {
 | 
				
			||||||
 | 
					      AddLast(item);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Whether the collection is read-only</summary>
 | 
				
			||||||
 | 
					    bool ICollection<ItemType>.IsReadOnly {
 | 
				
			||||||
 | 
					      get { return false; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #region ICollection Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Copies the contents of the deque into an array</summary>
 | 
				
			||||||
 | 
					    /// <param name="array">Array the contents of the deque will be copied into</param>
 | 
				
			||||||
 | 
					    /// <param name="index">Index at which writing into the array will begin</param>
 | 
				
			||||||
 | 
					    void ICollection.CopyTo(Array array, int index) {
 | 
				
			||||||
 | 
					      throw new NotImplementedException();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Whether the deque is thread-synchronized</summary>
 | 
				
			||||||
 | 
					    bool ICollection.IsSynchronized {
 | 
				
			||||||
 | 
					      get { return false; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Synchronization root of the instance</summary>
 | 
				
			||||||
 | 
					    object ICollection.SyncRoot {
 | 
				
			||||||
 | 
					      get { return this; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Nuclex.Support.Collections
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,49 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  partial class Deque<ItemType> {
 | 
					  partial class Deque<ItemType> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Removes all items from the deque</summary>
 | 
				
			||||||
 | 
					    public void Clear() {
 | 
				
			||||||
 | 
					      if(this.blocks.Count > 1) { // Are there multiple blocks?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Clear the items in the first block to avoid holding on to references
 | 
				
			||||||
 | 
					        // in memory unreachable to the user
 | 
				
			||||||
 | 
					        for(int index = this.firstBlockStartIndex; index < this.blockSize; ++index) {
 | 
				
			||||||
 | 
					          this.blocks[0][index] = default(ItemType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Remove any other blocks
 | 
				
			||||||
 | 
					        this.blocks.RemoveRange(1, this.blocks.Count - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      } else { // Nope, only a single block exists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Clear the items in the block to release any reference we may be keeping alive
 | 
				
			||||||
 | 
					        for(
 | 
				
			||||||
 | 
					          int index = this.firstBlockStartIndex; index < this.lastBlockCount; ++index
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					          this.blocks[0][index] = default(ItemType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Reset the counters to restart the deque from scratch
 | 
				
			||||||
 | 
					      this.firstBlockStartIndex = 0;
 | 
				
			||||||
 | 
					      this.lastBlockCount = 0;
 | 
				
			||||||
 | 
					      this.count = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Removes the specified item from the deque</summary>
 | 
				
			||||||
 | 
					    /// <param name="item">Item that will be removed from the deque</param>
 | 
				
			||||||
 | 
					    /// <returns>True if the item was found and removed</returns>
 | 
				
			||||||
 | 
					    public bool Remove(ItemType item) {
 | 
				
			||||||
 | 
					      int index = IndexOf(item);
 | 
				
			||||||
 | 
					      if(index == -1) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      RemoveAt(index);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>Removes the first item in the double-ended queue</summary>
 | 
					    /// <summary>Removes the first item in the double-ended queue</summary>
 | 
				
			||||||
    public void RemoveFirst() {
 | 
					    public void RemoveFirst() {
 | 
				
			||||||
      if(this.count == 0) {
 | 
					      if(this.count == 0) {
 | 
				
			||||||
| 
						 | 
					@ -16,6 +59,8 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
      // in unreachable spaces of its memory.
 | 
					      // in unreachable spaces of its memory.
 | 
				
			||||||
      this.blocks[0][this.firstBlockStartIndex] = default(ItemType);
 | 
					      this.blocks[0][this.firstBlockStartIndex] = default(ItemType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Cut off the item from the first block. If the block became empty and it's
 | 
				
			||||||
 | 
					      // not the last remaining block, remove it as well.
 | 
				
			||||||
      ++this.firstBlockStartIndex;
 | 
					      ++this.firstBlockStartIndex;
 | 
				
			||||||
      if(this.firstBlockStartIndex >= this.blockSize) { // Block became empty
 | 
					      if(this.firstBlockStartIndex >= this.blockSize) { // Block became empty
 | 
				
			||||||
        if(this.count > 1) { // Still more blocks in queue, remove block
 | 
					        if(this.count > 1) { // Still more blocks in queue, remove block
 | 
				
			||||||
| 
						 | 
					@ -23,7 +68,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
          this.firstBlockStartIndex = 0;
 | 
					          this.firstBlockStartIndex = 0;
 | 
				
			||||||
        } else { // Last block - do not remove
 | 
					        } else { // Last block - do not remove
 | 
				
			||||||
          this.firstBlockStartIndex = 0;
 | 
					          this.firstBlockStartIndex = 0;
 | 
				
			||||||
          this.lastBlockEndIndex = 0;
 | 
					          this.lastBlockCount = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      --this.count;
 | 
					      --this.count;
 | 
				
			||||||
| 
						 | 
					@ -38,16 +83,18 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
      // This is necessary to make sure the deque doesn't hold dead objects alive
 | 
					      // This is necessary to make sure the deque doesn't hold dead objects alive
 | 
				
			||||||
      // in unreachable spaces of its memory.
 | 
					      // in unreachable spaces of its memory.
 | 
				
			||||||
      int lastBlock = this.blocks.Count - 1;
 | 
					      int lastBlock = this.blocks.Count - 1;
 | 
				
			||||||
      this.blocks[lastBlock][this.lastBlockEndIndex - 1] = default(ItemType);
 | 
					      this.blocks[lastBlock][this.lastBlockCount - 1] = default(ItemType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      --this.lastBlockEndIndex;
 | 
					      // Cut off the last item in the last block. If the block became empty and it's
 | 
				
			||||||
      if(this.lastBlockEndIndex == 0) { // Block became empty
 | 
					      // not the last remaining block, remove it as well.
 | 
				
			||||||
 | 
					      --this.lastBlockCount;
 | 
				
			||||||
 | 
					      if(this.lastBlockCount == 0) { // Block became empty
 | 
				
			||||||
        if(this.count > 1) {
 | 
					        if(this.count > 1) {
 | 
				
			||||||
          this.blocks.RemoveAt(lastBlock);
 | 
					          this.blocks.RemoveAt(lastBlock);
 | 
				
			||||||
          this.lastBlockEndIndex = this.blockSize;
 | 
					          this.lastBlockCount = this.blockSize;
 | 
				
			||||||
        } else { // Last block - do not remove
 | 
					        } else { // Last block - do not remove
 | 
				
			||||||
          this.firstBlockStartIndex = 0;
 | 
					          this.firstBlockStartIndex = 0;
 | 
				
			||||||
          this.lastBlockEndIndex = 0;
 | 
					          this.lastBlockCount = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      --this.count;
 | 
					      --this.count;
 | 
				
			||||||
| 
						 | 
					@ -159,15 +206,15 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
        Array.Copy(
 | 
					        Array.Copy(
 | 
				
			||||||
          this.blocks[lastBlock], startIndex + 1,
 | 
					          this.blocks[lastBlock], startIndex + 1,
 | 
				
			||||||
          this.blocks[lastBlock], startIndex,
 | 
					          this.blocks[lastBlock], startIndex,
 | 
				
			||||||
          this.lastBlockEndIndex - startIndex - 1
 | 
					          this.lastBlockCount - startIndex - 1
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(this.lastBlockEndIndex == 1) {
 | 
					        if(this.lastBlockCount == 1) {
 | 
				
			||||||
          this.blocks.RemoveAt(lastBlock);
 | 
					          this.blocks.RemoveAt(lastBlock);
 | 
				
			||||||
          this.lastBlockEndIndex = this.blockSize;
 | 
					          this.lastBlockCount = this.blockSize;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          this.blocks[lastBlock][this.lastBlockEndIndex - 1] = default(ItemType);
 | 
					          this.blocks[lastBlock][this.lastBlockCount - 1] = default(ItemType);
 | 
				
			||||||
          --this.lastBlockEndIndex;
 | 
					          --this.lastBlockCount;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        --this.count;
 | 
					        --this.count;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										66
									
								
								Source/Collections/Deque.Search.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								Source/Collections/Deque.Search.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,66 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Nuclex.Support.Collections {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  partial class Deque<ItemType> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Determines the index of the first occurence of the specified item in the deque
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="item">Item that will be located in the deque</param>
 | 
				
			||||||
 | 
					    /// <returns>The index of the item or -1 if it wasn't found</returns>
 | 
				
			||||||
 | 
					    public int IndexOf(ItemType item) {
 | 
				
			||||||
 | 
					      if(this.blocks.Count == 1) { // Only one block to scan?
 | 
				
			||||||
 | 
					        int length = this.lastBlockCount - this.firstBlockStartIndex;
 | 
				
			||||||
 | 
					        int index = Array.IndexOf<ItemType>(
 | 
				
			||||||
 | 
					          this.blocks[0], item, this.firstBlockStartIndex, length
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If we found something, we need to adjust its index so the first item in
 | 
				
			||||||
 | 
					        // the deque always appears at index 0 to the user
 | 
				
			||||||
 | 
					        if(index != -1) {
 | 
				
			||||||
 | 
					          return (index - this.firstBlockStartIndex);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else { // At least two blocks exist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Scan the first block for the item and if found, return the index
 | 
				
			||||||
 | 
					        int length = this.blockSize - this.firstBlockStartIndex;
 | 
				
			||||||
 | 
					        int index = Array.IndexOf<ItemType>(
 | 
				
			||||||
 | 
					          this.blocks[0], item, this.firstBlockStartIndex, length
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If we found something, we need to adjust its index
 | 
				
			||||||
 | 
					        if(index != -1) {
 | 
				
			||||||
 | 
					          return (index - this.firstBlockStartIndex);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int lastBlock = this.blocks.Count - 1;
 | 
				
			||||||
 | 
					        for(int tempIndex = 1; tempIndex < lastBlock; ++tempIndex) {
 | 
				
			||||||
 | 
					          index = Array.IndexOf<ItemType>(
 | 
				
			||||||
 | 
					            this.blocks[tempIndex], item, 0, this.blockSize
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					          if(index != -1) {
 | 
				
			||||||
 | 
					            return (index - this.firstBlockStartIndex + tempIndex * this.blockSize);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Nothing found, continue the search in the 
 | 
				
			||||||
 | 
					        index = Array.IndexOf<ItemType>(
 | 
				
			||||||
 | 
					          this.blocks[lastBlock], item, 0, this.lastBlockCount
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        if(index == -1) {
 | 
				
			||||||
 | 
					          return -1;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          return (index - this.firstBlockStartIndex + lastBlock * this.blockSize);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Nuclex.Support.Collections
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@ License along with this library
 | 
				
			||||||
#if UNITTEST
 | 
					#if UNITTEST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using NUnit.Framework;
 | 
					using NUnit.Framework;
 | 
				
			||||||
| 
						 | 
					@ -103,10 +104,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    [Test]
 | 
					    [Test]
 | 
				
			||||||
    public void TestInsert() {
 | 
					    public void TestInsert() {
 | 
				
			||||||
      for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
 | 
					      for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
 | 
				
			||||||
        Deque<int> intDeque = new Deque<int>(16);
 | 
					        Deque<int> intDeque = createDeque(96);
 | 
				
			||||||
        for(int item = 0; item < 96; ++item) {
 | 
					 | 
				
			||||||
          intDeque.AddLast(item);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        intDeque.Insert(testedIndex, 12345);
 | 
					        intDeque.Insert(testedIndex, 12345);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,14 +127,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    [Test]
 | 
					    [Test]
 | 
				
			||||||
    public void TestInsertNonNormalized() {
 | 
					    public void TestInsertNonNormalized() {
 | 
				
			||||||
      for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
 | 
					      for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
 | 
				
			||||||
        Deque<int> intDeque = new Deque<int>(16);
 | 
					        Deque<int> intDeque = createNonNormalizedDeque(96);
 | 
				
			||||||
        for(int item = 4; item < 96; ++item) {
 | 
					 | 
				
			||||||
          intDeque.AddLast(item);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        intDeque.AddFirst(3);
 | 
					 | 
				
			||||||
        intDeque.AddFirst(2);
 | 
					 | 
				
			||||||
        intDeque.AddFirst(1);
 | 
					 | 
				
			||||||
        intDeque.AddFirst(0);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        intDeque.Insert(testedIndex, 12345);
 | 
					        intDeque.Insert(testedIndex, 12345);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,7 +193,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>
 | 
				
			||||||
    ///   Tests whether the RemoveAt() method keeps the state of the deque intact when
 | 
					    ///   Tests whether the RemoveAt() method keeps the state of the deque intact when
 | 
				
			||||||
    ///   it has to remove a block from the left end of the deque
 | 
					    ///   it has to remove a block from the left end of the deque
 | 
				
			||||||
| 
						 | 
					@ -301,10 +292,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    [Test]
 | 
					    [Test]
 | 
				
			||||||
    public void TestIndexAssignment() {
 | 
					    public void TestIndexAssignment() {
 | 
				
			||||||
      Deque<int> intDeque = new Deque<int>(16);
 | 
					      Deque<int> intDeque = createDeque(32);
 | 
				
			||||||
      for(int item = 0; item < 32; ++item) {
 | 
					 | 
				
			||||||
        intDeque.AddLast(item);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      intDeque[16] = 12345;
 | 
					      intDeque[16] = 12345;
 | 
				
			||||||
      intDeque[17] = 54321;
 | 
					      intDeque[17] = 54321;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -351,7 +339,290 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    [Test, TestCase(0), TestCase(16), TestCase(32), TestCase(48)]
 | 
					    [Test, TestCase(0), TestCase(16), TestCase(32), TestCase(48)]
 | 
				
			||||||
    public void TestIndexOfNonNormalized(int count) {
 | 
					    public void TestIndexOfNonNormalized(int count) {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createNonNormalizedDeque(count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for(int item = 0; item < count; ++item) {
 | 
				
			||||||
 | 
					        Assert.AreEqual(item, intDeque.IndexOf(item));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      Assert.AreEqual(-1, intDeque.IndexOf(count));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Verifies that the deque's enumerator works</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestEnumerator() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createNonNormalizedDeque(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for(int testRun = 0; testRun < 2; ++testRun) {
 | 
				
			||||||
 | 
					        using(IEnumerator<int> enumerator = intDeque.GetEnumerator()) {
 | 
				
			||||||
 | 
					          for(int index = 0; index < intDeque.Count; ++index) {
 | 
				
			||||||
 | 
					            Assert.IsTrue(enumerator.MoveNext());
 | 
				
			||||||
 | 
					            Assert.AreEqual(index, enumerator.Current);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          Assert.IsFalse(enumerator.MoveNext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          enumerator.Reset();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Verifies that the deque's enumerator works</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestObjectEnumerator() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createNonNormalizedDeque(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for(int testRun = 0; testRun < 2; ++testRun) {
 | 
				
			||||||
 | 
					        IEnumerator enumerator = ((IEnumerable)intDeque).GetEnumerator();
 | 
				
			||||||
 | 
					        for(int index = 0; index < intDeque.Count; ++index) {
 | 
				
			||||||
 | 
					          Assert.IsTrue(enumerator.MoveNext());
 | 
				
			||||||
 | 
					          Assert.AreEqual(index, enumerator.Current);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Assert.IsFalse(enumerator.MoveNext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        enumerator.Reset();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Verifies that an exception is thrown if the enumerator is accessed in
 | 
				
			||||||
 | 
					    ///   an invalid position
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestThrowOnInvalidEnumeratorPosition() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createNonNormalizedDeque(40);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      using(IEnumerator<int> enumerator = intDeque.GetEnumerator()) {
 | 
				
			||||||
 | 
					        Assert.Throws<InvalidOperationException>(
 | 
				
			||||||
 | 
					          delegate() { Console.WriteLine(enumerator.Current); }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while(enumerator.MoveNext()) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Assert.Throws<InvalidOperationException>(
 | 
				
			||||||
 | 
					          delegate() { Console.WriteLine(enumerator.Current); }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests whether a small deque can be cleared</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestClearSmallDeque() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(12);
 | 
				
			||||||
 | 
					      intDeque.Clear();
 | 
				
			||||||
 | 
					      Assert.AreEqual(0, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests whether a large deque can be cleared</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestClearLargeDeque() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(40);
 | 
				
			||||||
 | 
					      intDeque.Clear();
 | 
				
			||||||
 | 
					      Assert.AreEqual(0, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Verifies that the non-typesafe Add() method is working</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestAddObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					      Assert.AreEqual(0, ((IList)intDeque).Add(123));
 | 
				
			||||||
 | 
					      Assert.AreEqual(1, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Tests whether an exception is thrown if the non-typesafe Add() method is
 | 
				
			||||||
 | 
					    ///   used to add an incompatible object into the deque
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestThrowOnAddIncompatibleObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					      Assert.Throws<ArgumentException>(
 | 
				
			||||||
 | 
					        delegate() { ((IList)intDeque).Add("Hello World"); }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Verifies that the Add() method is working</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestAdd() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					      ((IList<int>)intDeque).Add(123);
 | 
				
			||||||
 | 
					      Assert.AreEqual(1, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests whether the Contains() method is working</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestContains() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(16);
 | 
				
			||||||
 | 
					      Assert.IsTrue(intDeque.Contains(14));
 | 
				
			||||||
 | 
					      Assert.IsFalse(intDeque.Contains(16));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests the non-typesafe Contains() method</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestContainsObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(16);
 | 
				
			||||||
 | 
					      Assert.IsTrue(((IList)intDeque).Contains(14));
 | 
				
			||||||
 | 
					      Assert.IsFalse(((IList)intDeque).Contains(16));
 | 
				
			||||||
 | 
					      Assert.IsFalse(((IList)intDeque).Contains("Hello World"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests the non-typesafe Contains() method</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestIndexOfObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(16);
 | 
				
			||||||
 | 
					      Assert.AreEqual(14, ((IList)intDeque).IndexOf(14));
 | 
				
			||||||
 | 
					      Assert.AreEqual(-1, ((IList)intDeque).IndexOf(16));
 | 
				
			||||||
 | 
					      Assert.AreEqual(-1, ((IList)intDeque).IndexOf("Hello World"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests wether the non-typesafe Insert() method is working</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestInsertObject() {
 | 
				
			||||||
 | 
					      for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
 | 
				
			||||||
 | 
					        Deque<int> intDeque = createDeque(96);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ((IList)intDeque).Insert(testedIndex, 12345);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Assert.AreEqual(97, intDeque.Count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(int index = 0; index < testedIndex; ++index) {
 | 
				
			||||||
 | 
					          Assert.AreEqual(index, intDeque[index]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Assert.AreEqual(12345, intDeque[testedIndex]);
 | 
				
			||||||
 | 
					        for(int index = testedIndex + 1; index < 97; ++index) {
 | 
				
			||||||
 | 
					          Assert.AreEqual(index - 1, intDeque[index]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Verifies that an exception is thrown if an incompatible object is inserted
 | 
				
			||||||
 | 
					    ///   into the deque
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestThrowOnInsertIncompatibleObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(12);
 | 
				
			||||||
 | 
					      Assert.Throws<ArgumentException>(
 | 
				
			||||||
 | 
					        delegate() { ((IList)intDeque).Insert(8, "Hello World"); }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Validates that the IsFixedObject property is set to false</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestIsFixedObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					      Assert.IsFalse(((IList)intDeque).IsFixedSize);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Validates that the IsSynchronized property is set to false</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestIsSynchronized() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					      Assert.IsFalse(((IList)intDeque).IsSynchronized);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Verifies that items can be assigned by their index using the non-typesafe
 | 
				
			||||||
 | 
					    ///   IList interface
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestObjectIndexAssignment() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      ((IList)intDeque)[16] = 12345;
 | 
				
			||||||
 | 
					      ((IList)intDeque)[17] = 54321;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Assert.AreEqual(12345, ((IList)intDeque)[16]);
 | 
				
			||||||
 | 
					      Assert.AreEqual(54321, ((IList)intDeque)[17]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Tests whether an exception is thrown if an incompatible object is assigned
 | 
				
			||||||
 | 
					    ///   to the deque
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestIncompatibleObjectIndexAssignment() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(2);
 | 
				
			||||||
 | 
					      Assert.Throws<ArgumentException>(
 | 
				
			||||||
 | 
					        delegate() { ((IList)intDeque)[0] = "Hello World"; }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Verifies that the Remove() method is working correctly</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestRemove() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(16);
 | 
				
			||||||
 | 
					      Assert.AreEqual(16, intDeque.Count);
 | 
				
			||||||
 | 
					      Assert.IsTrue(intDeque.Remove(13));
 | 
				
			||||||
 | 
					      Assert.IsFalse(intDeque.Remove(13));
 | 
				
			||||||
 | 
					      Assert.AreEqual(15, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests the non-typesafe remove method</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestRemoveObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(10);
 | 
				
			||||||
 | 
					      Assert.IsTrue(intDeque.Contains(8));
 | 
				
			||||||
 | 
					      Assert.AreEqual(10, intDeque.Count);
 | 
				
			||||||
 | 
					      ((IList)intDeque).Remove(8);
 | 
				
			||||||
 | 
					      Assert.IsFalse(intDeque.Contains(8));
 | 
				
			||||||
 | 
					      Assert.AreEqual(9, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Tests the non-typesafe remove method used to remove an incompatible object
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestRemoveIncompatibleObject() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = createDeque(10);
 | 
				
			||||||
 | 
					      ((IList)intDeque).Remove("Hello World"); // should simply do nothing
 | 
				
			||||||
 | 
					      Assert.AreEqual(10, intDeque.Count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Verifies that the IsSynchronized property and the SyncRoot property are working
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestSynchronization() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if(!(intDeque as ICollection).IsSynchronized) {
 | 
				
			||||||
 | 
					        lock((intDeque as ICollection).SyncRoot) {
 | 
				
			||||||
 | 
					          Assert.AreEqual(0, intDeque.Count);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Validates that the IsReadOnly property of the deque returns false
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestIsReadOnly() {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>();
 | 
				
			||||||
 | 
					      Assert.IsFalse(((IList)intDeque).IsReadOnly);
 | 
				
			||||||
 | 
					      Assert.IsFalse(((ICollection<int>)intDeque).IsReadOnly);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests the non-typesafe CopyTo() method</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestCopyToObjectArray() {
 | 
				
			||||||
 | 
					      // TODO Write a unit test for the non-typesafe CopyTo() method
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Tests the CopyTo() method</summary>
 | 
				
			||||||
 | 
					    [Test]
 | 
				
			||||||
 | 
					    public void TestCopyToArray() {
 | 
				
			||||||
 | 
					      // TODO Write a unit test for the typesafe CopyTo() method
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Creates a deque whose first element does not coincide with a block boundary
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="count">Number of items the deque will be filled with</param>
 | 
				
			||||||
 | 
					    /// <returns>The newly created deque</returns>
 | 
				
			||||||
 | 
					    private static Deque<int> createNonNormalizedDeque(int count) {
 | 
				
			||||||
      Deque<int> intDeque = new Deque<int>(16);
 | 
					      Deque<int> intDeque = new Deque<int>(16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for(int item = 4; item < count; ++item) {
 | 
					      for(int item = 4; item < count; ++item) {
 | 
				
			||||||
        intDeque.AddLast(item);
 | 
					        intDeque.AddLast(item);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -360,10 +631,21 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
      if(count > 1) { intDeque.AddFirst(1); }
 | 
					      if(count > 1) { intDeque.AddFirst(1); }
 | 
				
			||||||
      if(count > 0) { intDeque.AddFirst(0); }
 | 
					      if(count > 0) { intDeque.AddFirst(0); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return intDeque;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Creates a deque filled with the specified number of items
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="count">Number of items the deque will be filled with</param>
 | 
				
			||||||
 | 
					    /// <returns>The newly created deque</returns>
 | 
				
			||||||
 | 
					    private static Deque<int> createDeque(int count) {
 | 
				
			||||||
 | 
					      Deque<int> intDeque = new Deque<int>(16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for(int item = 0; item < count; ++item) {
 | 
					      for(int item = 0; item < count; ++item) {
 | 
				
			||||||
        Assert.AreEqual(item, intDeque.IndexOf(item));
 | 
					        intDeque.AddLast(item);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      Assert.AreEqual(-1, intDeque.IndexOf(count));
 | 
					
 | 
				
			||||||
 | 
					      return intDeque;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,111 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
  ///     require items to be copied around and still can be accessed by index.
 | 
					  ///     require items to be copied around and still can be accessed by index.
 | 
				
			||||||
  ///   </para>
 | 
					  ///   </para>
 | 
				
			||||||
  /// </remarks>
 | 
					  /// </remarks>
 | 
				
			||||||
  public partial class Deque<ItemType> /*: IList<ItemType>, IList*/ {
 | 
					  public partial class Deque<ItemType> : IList<ItemType>, IList {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #region class Enumerator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Enumerates over the items in a deque</summary>
 | 
				
			||||||
 | 
					    private class Enumerator : IEnumerator<ItemType>, IEnumerator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>Initializes a new deque enumerator</summary>
 | 
				
			||||||
 | 
					      /// <param name="deque">Deque whose items will be enumerated</param>
 | 
				
			||||||
 | 
					      public Enumerator(Deque<ItemType> deque) {
 | 
				
			||||||
 | 
					        this.deque = deque;
 | 
				
			||||||
 | 
					        this.blockSize = this.deque.blockSize;
 | 
				
			||||||
 | 
					        this.lastBlock = this.deque.blocks.Count - 1;
 | 
				
			||||||
 | 
					        this.lastBlockEndIndex = this.deque.lastBlockCount - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Reset();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>Immediately releases all resources owned by the instance</summary>
 | 
				
			||||||
 | 
					      public void Dispose() {
 | 
				
			||||||
 | 
					        this.deque = null;
 | 
				
			||||||
 | 
					        this.currentBlock = null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>The item at the enumerator's current position</summary>
 | 
				
			||||||
 | 
					      public ItemType Current {
 | 
				
			||||||
 | 
					        get {
 | 
				
			||||||
 | 
					          if(this.currentBlock == null) {
 | 
				
			||||||
 | 
					            throw new InvalidOperationException("Enumerator is not on a valid position");
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          return this.currentBlock[this.subIndex];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>Advances the enumerator to the next item</summary>
 | 
				
			||||||
 | 
					      /// <returns>True if there was a next item</returns>
 | 
				
			||||||
 | 
					      public bool MoveNext() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If we haven't reached the last block yet      
 | 
				
			||||||
 | 
					        if(this.currentBlockIndex < this.lastBlock) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Advance to the next item. If the end of the current block is reached,
 | 
				
			||||||
 | 
					          // go to the next block's first item
 | 
				
			||||||
 | 
					          ++this.subIndex;
 | 
				
			||||||
 | 
					          if(this.subIndex >= this.blockSize) {
 | 
				
			||||||
 | 
					            ++this.currentBlockIndex;
 | 
				
			||||||
 | 
					            this.currentBlock = this.deque.blocks[this.currentBlockIndex];
 | 
				
			||||||
 | 
					            if(this.currentBlockIndex == 0) {
 | 
				
			||||||
 | 
					              this.subIndex = this.deque.firstBlockStartIndex;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              this.subIndex = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Item found. If the current block wasn't the last block, an item *has*
 | 
				
			||||||
 | 
					          // to follow since otherwise, no further blocks would exist!
 | 
				
			||||||
 | 
					          return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else { // We in or beyond the last block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Are there any items left to advance to?
 | 
				
			||||||
 | 
					          if(this.subIndex < this.lastBlockEndIndex) {
 | 
				
			||||||
 | 
					            ++this.subIndex;
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					          } else { // Nope, we've reached the end of the deque
 | 
				
			||||||
 | 
					            this.currentBlock = null;
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>Resets the enumerator to its initial position</summary>
 | 
				
			||||||
 | 
					      public void Reset() {
 | 
				
			||||||
 | 
					        this.currentBlock = null;
 | 
				
			||||||
 | 
					        this.currentBlockIndex = -1;
 | 
				
			||||||
 | 
					        this.subIndex = this.deque.blockSize - 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>The item at the enumerator's current position</summary>
 | 
				
			||||||
 | 
					      object IEnumerator.Current {
 | 
				
			||||||
 | 
					        get { return Current; }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>Deque the enumerator belongs to</summary>
 | 
				
			||||||
 | 
					      private Deque<ItemType> deque;
 | 
				
			||||||
 | 
					      /// <summary>Size of the blocks in the deque</summary>
 | 
				
			||||||
 | 
					      private int blockSize;
 | 
				
			||||||
 | 
					      /// <summary>Index of the last block in the deque</summary>
 | 
				
			||||||
 | 
					      private int lastBlock;
 | 
				
			||||||
 | 
					      /// <summary>End index of the items in the deque's last block</summary>
 | 
				
			||||||
 | 
					      private int lastBlockEndIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      /// <summary>Index of the block the enumerator currently is in</summary>
 | 
				
			||||||
 | 
					      private int currentBlockIndex;
 | 
				
			||||||
 | 
					      /// <summary>Reference to the block being enumerated</summary>
 | 
				
			||||||
 | 
					      private ItemType[] currentBlock;
 | 
				
			||||||
 | 
					      /// <summary>Index in the current block</summary>
 | 
				
			||||||
 | 
					      private int subIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #endregion // class Enumerator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>Initializes a new deque</summary>
 | 
					    /// <summary>Initializes a new deque</summary>
 | 
				
			||||||
    public Deque() : this(512) { }
 | 
					    public Deque() : this(512) { }
 | 
				
			||||||
| 
						 | 
					@ -58,7 +162,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    /// <summary>The first item in the double-ended queue</summary>
 | 
					    /// <summary>The first item in the double-ended queue</summary>
 | 
				
			||||||
    public ItemType First {
 | 
					    public ItemType First {
 | 
				
			||||||
      get {
 | 
					      get {
 | 
				
			||||||
        if(this.lastBlockEndIndex <= this.firstBlockStartIndex) {
 | 
					        if(this.count == 0) {
 | 
				
			||||||
          throw new InvalidOperationException("The deque is empty");
 | 
					          throw new InvalidOperationException("The deque is empty");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return this.blocks[0][this.firstBlockStartIndex];
 | 
					        return this.blocks[0][this.firstBlockStartIndex];
 | 
				
			||||||
| 
						 | 
					@ -68,66 +172,31 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    /// <summary>The last item in the double-ended queue</summary>
 | 
					    /// <summary>The last item in the double-ended queue</summary>
 | 
				
			||||||
    public ItemType Last {
 | 
					    public ItemType Last {
 | 
				
			||||||
      get {
 | 
					      get {
 | 
				
			||||||
        if(this.lastBlockEndIndex <= this.firstBlockStartIndex) {
 | 
					        if(this.count == 0) {
 | 
				
			||||||
          throw new InvalidOperationException("The deque is empty");
 | 
					          throw new InvalidOperationException("The deque is empty");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return this.blocks[this.blocks.Count - 1][this.lastBlockEndIndex - 1];
 | 
					        return this.blocks[this.blocks.Count - 1][this.lastBlockCount - 1];
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>
 | 
					    /// <summary>Determines whether the deque contains the specified item</summary>
 | 
				
			||||||
    ///   Determines the index of the first occurence of the specified item in the deque
 | 
					    /// <param name="item">Item the deque will be scanned for</param>
 | 
				
			||||||
    /// </summary>
 | 
					    /// <returns>True if the deque contains the item, false otherwise</returns>
 | 
				
			||||||
    /// <param name="item">Item that will be located in the deque</param>
 | 
					    public bool Contains(ItemType item) {
 | 
				
			||||||
    /// <returns>The index of the item or -1 if it wasn't found</returns>
 | 
					      return (IndexOf(item) != -1);
 | 
				
			||||||
    public int IndexOf(ItemType item) {
 | 
					    }
 | 
				
			||||||
      if(this.blocks.Count == 1) { // Only one block to scan?
 | 
					 | 
				
			||||||
        int length = this.lastBlockEndIndex - this.firstBlockStartIndex;
 | 
					 | 
				
			||||||
        int index = Array.IndexOf<ItemType>(
 | 
					 | 
				
			||||||
          this.blocks[0], item, this.firstBlockStartIndex, length
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If we found something, we need to adjust its index so the first item in
 | 
					    /// <summary>Copies the contents of the deque into an array</summary>
 | 
				
			||||||
        // the deque always appears at index 0 to the user
 | 
					    /// <param name="array">Array the contents of the deque will be copied into</param>
 | 
				
			||||||
        if(index != -1) {
 | 
					    /// <param name="arrayIndex">Array index the deque contents will begin at</param>
 | 
				
			||||||
          return (index - this.firstBlockStartIndex);
 | 
					    public void CopyTo(ItemType[] array, int arrayIndex) {
 | 
				
			||||||
        } else {
 | 
					      throw new NotImplementedException();
 | 
				
			||||||
          return -1;
 | 
					    }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      } else { // At least two blocks exist
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Scan the first block for the item and if found, return the index
 | 
					    /// <summary>Obtains a new enumerator for the contents of the deque</summary>
 | 
				
			||||||
        int length = this.blockSize - this.firstBlockStartIndex;
 | 
					    /// <returns>The new enumerator</returns>
 | 
				
			||||||
        int index = Array.IndexOf<ItemType>(
 | 
					    public IEnumerator<ItemType> GetEnumerator() {
 | 
				
			||||||
          this.blocks[0], item, this.firstBlockStartIndex, length
 | 
					      return new Enumerator(this);
 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // If we found something, we need to adjust its index
 | 
					 | 
				
			||||||
        if(index != -1) {
 | 
					 | 
				
			||||||
          return (index - this.firstBlockStartIndex);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int lastBlock = this.blocks.Count - 1;
 | 
					 | 
				
			||||||
        for(int tempIndex = 1; tempIndex < lastBlock; ++tempIndex) {
 | 
					 | 
				
			||||||
          index = Array.IndexOf<ItemType>(
 | 
					 | 
				
			||||||
            this.blocks[tempIndex], item, 0, this.blockSize
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
          if(index != -1) {
 | 
					 | 
				
			||||||
            return (index - this.firstBlockStartIndex + tempIndex * this.blockSize);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Nothing found, continue the search in the 
 | 
					 | 
				
			||||||
        index = Array.IndexOf<ItemType>(
 | 
					 | 
				
			||||||
          this.blocks[lastBlock], item, 0, this.lastBlockEndIndex
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        if(index == -1) {
 | 
					 | 
				
			||||||
          return -1;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          return (index - this.firstBlockStartIndex + lastBlock * this.blockSize);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>Calculates the block index and local sub index of an entry</summary>
 | 
					    /// <summary>Calculates the block index and local sub index of an entry</summary>
 | 
				
			||||||
| 
						 | 
					@ -143,6 +212,23 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
      blockIndex = Math.DivRem(index, this.blockSize, out subIndex);
 | 
					      blockIndex = Math.DivRem(index, this.blockSize, out subIndex);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    ///   Determines whether the provided object can be placed in the deque
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <param name="value">Value that will be checked for compatibility</param>
 | 
				
			||||||
 | 
					    /// <returns>True if the value can be placed in the deque</returns>
 | 
				
			||||||
 | 
					    private static bool isCompatibleObject(object value) {
 | 
				
			||||||
 | 
					      return ((value is ItemType) || ((value == null) && !typeof(ItemType).IsValueType));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// <summary>Verifies that the provided object matches the deque's type</summary>
 | 
				
			||||||
 | 
					    /// <param name="value">Value that will be checked for compatibility</param>
 | 
				
			||||||
 | 
					    private static void verifyCompatibleObject(object value) {
 | 
				
			||||||
 | 
					      if(!isCompatibleObject(value)) {
 | 
				
			||||||
 | 
					        throw new ArgumentException("Value does not match the deque's type", "value");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// <summary>Number if items currently stored in the deque</summary>
 | 
					    /// <summary>Number if items currently stored in the deque</summary>
 | 
				
			||||||
    private int count;
 | 
					    private int count;
 | 
				
			||||||
    /// <summary>Size of a single deque block</summary>
 | 
					    /// <summary>Size of a single deque block</summary>
 | 
				
			||||||
| 
						 | 
					@ -152,7 +238,7 @@ namespace Nuclex.Support.Collections {
 | 
				
			||||||
    /// <summary>Starting index of data in the first block</summary>
 | 
					    /// <summary>Starting index of data in the first block</summary>
 | 
				
			||||||
    private int firstBlockStartIndex;
 | 
					    private int firstBlockStartIndex;
 | 
				
			||||||
    /// <summary>End index of data in the last block</summary>
 | 
					    /// <summary>End index of data in the last block</summary>
 | 
				
			||||||
    private int lastBlockEndIndex;
 | 
					    private int lastBlockCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue