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