Collections/RingCollection.cs
author StephaneLenclud
Mon, 02 Feb 2015 21:06:44 +0100
branchMiniDisplay
changeset 449 b3792b2fe742
parent 298 96263190189a
permissions -rw-r--r--
Solution Build Config update.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2011 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Collections;
    13 using System.Collections.Generic;
    14 
    15 namespace OpenHardwareMonitor.Collections {
    16   public class RingCollection<T> : IEnumerable<T> {
    17 
    18     private T[] array;
    19 
    20     // first item of collection
    21     private int head;
    22 
    23     // index after the last item of the collection
    24     private int tail;
    25 
    26     // number of items in the collection
    27     private int size;
    28 
    29     public RingCollection() : this(0) { }
    30 
    31     public RingCollection(int capacity) {
    32       if (capacity < 0)
    33         throw new ArgumentOutOfRangeException("capacity");
    34       this.array = new T[capacity];
    35       this.head = 0; 
    36       this.tail = 0;
    37       this.size = 0;
    38     }
    39 
    40     public int Capacity {
    41       get {
    42         return array.Length;
    43       }
    44       set {
    45         T[] newArray = new T[value];
    46         if (size > 0) {
    47           if (head < tail) {
    48             Array.Copy(array, head, newArray, 0, size);
    49           } else {
    50             Array.Copy(array, head, newArray, 0, array.Length - head);
    51             Array.Copy(array, 0, newArray, array.Length - head, tail);
    52           }
    53         }
    54         this.array = newArray;
    55         this.head = 0;
    56         this.tail = size == value ? 0 : size;
    57       }
    58     }
    59 
    60     public void Clear() {
    61       
    62       // remove potential references 
    63       if (head < tail) {
    64         Array.Clear(array, head, size);
    65       } else {
    66         Array.Clear(array, 0, tail);
    67         Array.Clear(array, head, array.Length - head);
    68       }
    69 
    70       this.head = 0;
    71       this.tail = 0;
    72       this.size = 0;
    73     }
    74 
    75     public void Append(T item) {
    76       if (size == array.Length) {
    77         int newCapacity = array.Length * 3 / 2;
    78         if (newCapacity < array.Length + 8)
    79           newCapacity = array.Length + 8;
    80         Capacity = newCapacity;
    81       }
    82 
    83       array[tail] = item;
    84       tail = tail + 1 == array.Length ? 0 : tail + 1;
    85       size++;
    86     }
    87 
    88     public T Remove() {
    89       if (size == 0)
    90         throw new InvalidOperationException();
    91 
    92       T result = array[head];
    93       array[head] = default(T);
    94       head = head + 1 == array.Length ? 0 : head + 1;
    95       size--;
    96 
    97       return result;
    98     }
    99 
   100     public int Count {
   101       get {
   102         return size;
   103       }
   104     }
   105 
   106     public T this[int index] {
   107       get {
   108         if (index < 0 || index >= size)
   109           throw new IndexOutOfRangeException();
   110         int i = head + index;
   111         if (i >= array.Length)
   112           i -= array.Length;
   113         return array[i];
   114       }
   115       set {
   116         if (index < 0 || index >= size)
   117           throw new IndexOutOfRangeException();
   118         int i = head + index;
   119         if (i >= array.Length)
   120           i -= array.Length;
   121         array[i] = value;
   122       }
   123     }
   124 
   125     public T First {
   126       get {
   127         if (size == 0)
   128           throw new InvalidOperationException();
   129         return array[head];
   130       }
   131       set {
   132         if (size == 0)
   133           throw new InvalidOperationException();
   134         array[head] = value;
   135       }
   136     }
   137 
   138     public T Last {
   139       get {
   140         if (size == 0)
   141           throw new InvalidOperationException();
   142         return array[tail == 0 ? array.Length - 1 : tail - 1];
   143       }
   144       set {
   145         if (size == 0)
   146           throw new InvalidOperationException();
   147         array[tail == 0 ? array.Length - 1 : tail - 1] = value;
   148       }
   149     }
   150 
   151     IEnumerator<T> IEnumerable<T>.GetEnumerator() {
   152       return new RingCollection<T>.Enumerator(this);
   153     }
   154 
   155     IEnumerator IEnumerable.GetEnumerator() {
   156       return new RingCollection<T>.Enumerator(this);
   157     }
   158 
   159     private struct Enumerator : IEnumerator<T>, IEnumerator {
   160 
   161       private RingCollection<T> collection;
   162       private int index;
   163 
   164       public Enumerator(RingCollection<T> collection) {
   165         this.collection = collection;
   166         this.index = -1;
   167       }
   168 
   169       public void Dispose() {
   170         this.index = -2;
   171       }
   172 
   173       public void Reset() {
   174         this.index = -1;
   175       }
   176 
   177       public T Current {
   178         get {
   179           if (index < 0)
   180             throw new InvalidOperationException();
   181           return collection[index];
   182         }
   183       }
   184 
   185       object IEnumerator.Current {
   186         get {
   187           if (index < 0)
   188             throw new InvalidOperationException();
   189           return collection[index];
   190         }
   191       }
   192 
   193       public bool MoveNext() {
   194         if (index == -2)
   195           return false;
   196 
   197         index++;
   198 
   199         if (index == collection.size) {
   200           index = -2;
   201           return false;
   202         }
   203 
   204         return true;
   205       }
   206     }
   207   }
   208 }