View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * 
4    * Copyright (C) 1999-2006, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  
11  package ch.qos.logback.core.helpers;
12  
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  /**
17   * CyclicBuffer holds values in a cyclic array.
18   * 
19   * <p>It allows read access to any element in the buffer not just the first or
20   * last element.
21   * 
22   * @author Ceki G&uuml;lc&uuml;
23   */
24  public class CyclicBuffer<E> {
25  
26    E[] ea;
27    int first;
28    int last;
29    int numElems;
30    int maxSize;
31  
32    /**
33     * Instantiate a new CyclicBuffer of at most <code>maxSize</code> events.
34     * 
35     * The <code>maxSize</code> argument must a positive integer.
36     * 
37     * @param maxSize
38     *                The maximum number of elements in the buffer.
39     */
40    @SuppressWarnings("unchecked")
41    public CyclicBuffer(int maxSize) throws IllegalArgumentException {
42      if (maxSize < 1) {
43        throw new IllegalArgumentException("The maxSize argument (" + maxSize
44            + ") is not a positive integer.");
45      }
46      init(maxSize);
47    }
48  
49    @SuppressWarnings("unchecked")
50    private void init(int maxSize) {
51      this.maxSize = maxSize;
52      ea = (E[]) new Object[maxSize];
53      first = 0;
54      last = 0;
55      numElems = 0;
56    }
57  
58    /**
59     * Clears the buffer and resets all attributes.
60     */
61    public void clear() {
62      init(this.maxSize);
63    }
64  
65    /**
66     * Add an <code>event</code> as the last event in the buffer.
67     * 
68     */
69    public void add(E event) {
70      ea[last] = event;
71      if (++last == maxSize)
72        last = 0;
73  
74      if (numElems < maxSize)
75        numElems++;
76      else if (++first == maxSize)
77        first = 0;
78    }
79  
80    /**
81     * Get the <i>i</i>th oldest event currently in the buffer. If <em>i</em>
82     * is outside the range 0 to the number of elements currently in the buffer,
83     * then <code>null</code> is returned.
84     */
85    public E get(int i) {
86      if (i < 0 || i >= numElems)
87        return null;
88  
89      return ea[(first + i) % maxSize];
90    }
91  
92    public int getMaxSize() {
93      return maxSize;
94    }
95  
96    /**
97     * Get the oldest (first) element in the buffer. The oldest element is removed
98     * from the buffer.
99     */
100   public E get() {
101     E r = null;
102     if (numElems > 0) {
103       numElems--;
104       r = ea[first];
105       ea[first] = null;
106       if (++first == maxSize)
107         first = 0;
108     }
109     return r;
110   }
111   
112   public List<E> asList() {
113     List<E> tList = new ArrayList<E>();
114     for(int i = 0; i < length(); i++) {
115       tList.add(get(i));
116     }
117     return tList;
118   }
119 
120   /**
121    * Get the number of elements in the buffer. This number is guaranteed to be
122    * in the range 0 to <code>maxSize</code> (inclusive).
123    */
124   public int length() {
125     return numElems;
126   }
127 
128   /**
129    * Resize the cyclic buffer to <code>newSize</code>.
130    * 
131    * @throws IllegalArgumentException
132    *                 if <code>newSize</code> is negative.
133    */
134   @SuppressWarnings("unchecked")
135   public void resize(int newSize) {
136     if (newSize < 0) {
137       throw new IllegalArgumentException("Negative array size [" + newSize
138           + "] not allowed.");
139     }
140     if (newSize == numElems)
141       return; // nothing to do
142 
143     // 
144     E[] temp = (E[]) new Object[newSize];
145 
146     int loopLen = newSize < numElems ? newSize : numElems;
147 
148     for (int i = 0; i < loopLen; i++) {
149       temp[i] = ea[first];
150       ea[first] = null;
151       if (++first == numElems)
152         first = 0;
153     }
154     ea = temp;
155     first = 0;
156     numElems = loopLen;
157     maxSize = newSize;
158     if (loopLen == newSize) {
159       last = 0;
160     } else {
161       last = loopLen;
162     }
163   }
164 }