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