Collections/RingCollection.cs
author moel.mich
Mon, 13 Feb 2012 20:34:39 +0000
changeset 338 f580591971ce
child 344 3145aadca3d2
permissions -rw-r--r--
Small correction to the Sandforce SSD detection to prevent Marvell controllers (M4, C300) from getting identified as Sandforce.
moel@298
     1
/*
moel@298
     2
  
moel@298
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@298
     4
moel@298
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@298
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@298
     7
  the License. You may obtain a copy of the License at
moel@298
     8
 
moel@298
     9
  http://www.mozilla.org/MPL/
moel@298
    10
moel@298
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@298
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@298
    13
  for the specific language governing rights and limitations under the License.
moel@298
    14
moel@298
    15
  The Original Code is the Open Hardware Monitor code.
moel@298
    16
moel@298
    17
  The Initial Developer of the Original Code is 
moel@298
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@298
    19
  Portions created by the Initial Developer are Copyright (C) 2011
moel@298
    20
  the Initial Developer. All Rights Reserved.
moel@298
    21
moel@298
    22
  Contributor(s):
moel@298
    23
moel@298
    24
  Alternatively, the contents of this file may be used under the terms of
moel@298
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@298
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@298
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@298
    28
  of those above. If you wish to allow use of your version of this file only
moel@298
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@298
    30
  use your version of this file under the terms of the MPL, indicate your
moel@298
    31
  decision by deleting the provisions above and replace them with the notice
moel@298
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@298
    33
  the provisions above, a recipient may use your version of this file under
moel@298
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@298
    35
 
moel@298
    36
*/
moel@298
    37
moel@298
    38
using System;
moel@298
    39
using System.Collections;
moel@298
    40
using System.Collections.Generic;
moel@298
    41
moel@298
    42
namespace OpenHardwareMonitor.Collections {
moel@298
    43
  public class RingCollection<T> : IEnumerable<T> {
moel@298
    44
moel@298
    45
    private T[] array;
moel@298
    46
moel@298
    47
    // first item of collection
moel@298
    48
    private int head;
moel@298
    49
moel@298
    50
    // index after the last item of the collection
moel@298
    51
    private int tail;
moel@298
    52
moel@298
    53
    // number of items in the collection
moel@298
    54
    private int size;
moel@298
    55
moel@298
    56
    public RingCollection() : this(0) { }
moel@298
    57
moel@298
    58
    public RingCollection(int capacity) {
moel@298
    59
      if (capacity < 0)
moel@298
    60
        throw new ArgumentOutOfRangeException("capacity");
moel@298
    61
      this.array = new T[capacity];
moel@298
    62
      this.head = 0; 
moel@298
    63
      this.tail = 0;
moel@298
    64
      this.size = 0;
moel@298
    65
    }
moel@298
    66
moel@298
    67
    public int Capacity {
moel@298
    68
      get {
moel@298
    69
        return array.Length;
moel@298
    70
      }
moel@298
    71
      set {
moel@298
    72
        T[] newArray = new T[value];
moel@298
    73
        if (size > 0) {
moel@298
    74
          if (head < tail) {
moel@298
    75
            Array.Copy(array, head, newArray, 0, size);
moel@298
    76
          } else {
moel@298
    77
            Array.Copy(array, head, newArray, 0, array.Length - head);
moel@298
    78
            Array.Copy(array, 0, newArray, array.Length - head, tail);
moel@298
    79
          }
moel@298
    80
        }
moel@298
    81
        this.array = newArray;
moel@298
    82
        this.head = 0;
moel@298
    83
        this.tail = size == value ? 0 : size;
moel@298
    84
      }
moel@298
    85
    }
moel@298
    86
moel@298
    87
    public void Clear() {
moel@298
    88
      
moel@298
    89
      // remove potential references 
moel@298
    90
      if (head < tail) {
moel@298
    91
        Array.Clear(array, head, size);
moel@298
    92
      } else {
moel@298
    93
        Array.Clear(array, 0, tail);
moel@298
    94
        Array.Clear(array, head, array.Length - head);
moel@298
    95
      }
moel@298
    96
moel@298
    97
      this.head = 0;
moel@298
    98
      this.tail = 0;
moel@298
    99
      this.size = 0;
moel@298
   100
    }
moel@298
   101
moel@298
   102
    public void Append(T item) {
moel@298
   103
      if (size == array.Length) {
moel@298
   104
        int newCapacity = array.Length * 3 / 2;
moel@298
   105
        if (newCapacity < array.Length + 8)
moel@298
   106
          newCapacity = array.Length + 8;
moel@298
   107
        Capacity = newCapacity;
moel@298
   108
      }
moel@298
   109
moel@298
   110
      array[tail] = item;
moel@298
   111
      tail = tail + 1 == array.Length ? 0 : tail + 1;
moel@298
   112
      size++;
moel@298
   113
    }
moel@298
   114
moel@298
   115
    public T Remove() {
moel@298
   116
      if (size == 0)
moel@298
   117
        throw new InvalidOperationException();
moel@298
   118
moel@298
   119
      T result = array[head];
moel@298
   120
      array[head] = default(T);
moel@298
   121
      head = head + 1 == array.Length ? 0 : head + 1;
moel@298
   122
      size--;
moel@298
   123
moel@298
   124
      return result;
moel@298
   125
    }
moel@298
   126
moel@298
   127
    public int Count {
moel@298
   128
      get {
moel@298
   129
        return size;
moel@298
   130
      }
moel@298
   131
    }
moel@298
   132
moel@298
   133
    public T this[int index] {
moel@298
   134
      get {
moel@298
   135
        if (index < 0 || index >= size)
moel@298
   136
          throw new IndexOutOfRangeException();
moel@298
   137
        int i = head + index;
moel@298
   138
        if (i >= array.Length)
moel@298
   139
          i -= array.Length;
moel@298
   140
        return array[i];
moel@298
   141
      }
moel@298
   142
      set {
moel@298
   143
        if (index < 0 || index >= size)
moel@298
   144
          throw new IndexOutOfRangeException();
moel@298
   145
        int i = head + index;
moel@298
   146
        if (i >= array.Length)
moel@298
   147
          i -= array.Length;
moel@298
   148
        array[i] = value;
moel@298
   149
      }
moel@298
   150
    }
moel@298
   151
moel@298
   152
    public T First {
moel@298
   153
      get {
moel@298
   154
        if (size == 0)
moel@298
   155
          throw new InvalidOperationException();
moel@298
   156
        return array[head];
moel@298
   157
      }
moel@298
   158
      set {
moel@298
   159
        if (size == 0)
moel@298
   160
          throw new InvalidOperationException();
moel@298
   161
        array[head] = value;
moel@298
   162
      }
moel@298
   163
    }
moel@298
   164
moel@298
   165
    public T Last {
moel@298
   166
      get {
moel@298
   167
        if (size == 0)
moel@298
   168
          throw new InvalidOperationException();
moel@298
   169
        return array[tail == 0 ? array.Length - 1 : tail - 1];
moel@298
   170
      }
moel@298
   171
      set {
moel@298
   172
        if (size == 0)
moel@298
   173
          throw new InvalidOperationException();
moel@298
   174
        array[tail == 0 ? array.Length - 1 : tail - 1] = value;
moel@298
   175
      }
moel@298
   176
    }
moel@298
   177
moel@298
   178
    IEnumerator<T> IEnumerable<T>.GetEnumerator() {
moel@298
   179
      return new RingCollection<T>.Enumerator(this);
moel@298
   180
    }
moel@298
   181
moel@298
   182
    IEnumerator IEnumerable.GetEnumerator() {
moel@298
   183
      return new RingCollection<T>.Enumerator(this);
moel@298
   184
    }
moel@298
   185
moel@298
   186
    private struct Enumerator : IEnumerator<T>, IEnumerator {
moel@298
   187
moel@298
   188
      private RingCollection<T> collection;
moel@298
   189
      private int index;
moel@298
   190
moel@298
   191
      public Enumerator(RingCollection<T> collection) {
moel@298
   192
        this.collection = collection;
moel@298
   193
        this.index = -1;
moel@298
   194
      }
moel@298
   195
moel@298
   196
      public void Dispose() {
moel@298
   197
        this.index = -2;
moel@298
   198
      }
moel@298
   199
moel@298
   200
      public void Reset() {
moel@298
   201
        this.index = -1;
moel@298
   202
      }
moel@298
   203
moel@298
   204
      public T Current {
moel@298
   205
        get {
moel@298
   206
          if (index < 0)
moel@298
   207
            throw new InvalidOperationException();
moel@298
   208
          return collection[index];
moel@298
   209
        }
moel@298
   210
      }
moel@298
   211
moel@298
   212
      object IEnumerator.Current {
moel@298
   213
        get {
moel@298
   214
          if (index < 0)
moel@298
   215
            throw new InvalidOperationException();
moel@298
   216
          return collection[index];
moel@298
   217
        }
moel@298
   218
      }
moel@298
   219
moel@298
   220
      public bool MoveNext() {
moel@298
   221
        if (index == -2)
moel@298
   222
          return false;
moel@298
   223
moel@298
   224
        index++;
moel@298
   225
moel@298
   226
        if (index == collection.size) {
moel@298
   227
          index = -2;
moel@298
   228
          return false;
moel@298
   229
        }
moel@298
   230
moel@298
   231
        return true;
moel@298
   232
      }
moel@298
   233
    }
moel@298
   234
  }
moel@298
   235
}