ListBuffer.java revision 2571:10fc81ac75b4
1/*
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.javac.util;
27
28import java.util.AbstractQueue;
29import java.util.Collection;
30import java.util.Iterator;
31import java.util.NoSuchElementException;
32
33/** A class for constructing lists by appending elements. Modelled after
34 *  java.lang.StringBuffer.
35 *
36 *  <p><b>This is NOT part of any supported API.
37 *  If you write code that depends on this, you do so at your own risk.
38 *  This code and its internal interfaces are subject to change or
39 *  deletion without notice.</b>
40 */
41public class ListBuffer<A> extends AbstractQueue<A> {
42
43    public static <T> ListBuffer<T> of(T x) {
44        ListBuffer<T> lb = new ListBuffer<>();
45        lb.add(x);
46        return lb;
47    }
48
49    /** The list of elements of this buffer.
50     */
51    private List<A> elems;
52
53    /** A pointer pointing to the last element of 'elems' containing data,
54     *  or null if the list is empty.
55     */
56    private List<A> last;
57
58    /** The number of element in this buffer.
59     */
60    private int count;
61
62    /** Has a list been created from this buffer yet?
63     */
64    private boolean shared;
65
66    /** Create a new initially empty list buffer.
67     */
68    public ListBuffer() {
69        clear();
70    }
71
72    public final void clear() {
73        this.elems = List.nil();
74        this.last = null;
75        count = 0;
76        shared = false;
77    }
78
79    /** Return the number of elements in this buffer.
80     */
81    public int length() {
82        return count;
83    }
84    public int size() {
85        return count;
86    }
87
88    /** Is buffer empty?
89     */
90    public boolean isEmpty() {
91        return count == 0;
92    }
93
94    /** Is buffer not empty?
95     */
96    public boolean nonEmpty() {
97        return count != 0;
98    }
99
100    /** Copy list and sets last.
101     */
102    private void copy() {
103        if (elems.nonEmpty()) {
104            List<A> orig = elems;
105
106            elems = last = List.<A>of(orig.head);
107
108            while ((orig = orig.tail).nonEmpty()) {
109                last.tail = List.<A>of(orig.head);
110                last = last.tail;
111            }
112        }
113    }
114
115    /** Prepend an element to buffer.
116     */
117    public ListBuffer<A> prepend(A x) {
118        elems = elems.prepend(x);
119        if (last == null) last = elems;
120        count++;
121        return this;
122    }
123
124    /** Append an element to buffer.
125     */
126    public ListBuffer<A> append(A x) {
127        x.getClass(); // null check
128        if (shared) copy();
129        List<A> newLast = List.<A>of(x);
130        if (last != null) {
131            last.tail = newLast;
132            last = newLast;
133        } else {
134            elems = last = newLast;
135        }
136        count++;
137        return this;
138    }
139
140    /** Append all elements in a list to buffer.
141     */
142    public ListBuffer<A> appendList(List<A> xs) {
143        while (xs.nonEmpty()) {
144            append(xs.head);
145            xs = xs.tail;
146        }
147        return this;
148    }
149
150    /** Append all elements in a list to buffer.
151     */
152    public ListBuffer<A> appendList(ListBuffer<A> xs) {
153        return appendList(xs.toList());
154    }
155
156    /** Append all elements in an array to buffer.
157     */
158    public ListBuffer<A> appendArray(A[] xs) {
159        for (A x : xs) {
160            append(x);
161        }
162        return this;
163    }
164
165    /** Convert buffer to a list of all its elements.
166     */
167    public List<A> toList() {
168        shared = true;
169        return elems;
170    }
171
172    /** Does the list contain the specified element?
173     */
174    public boolean contains(Object x) {
175        return elems.contains(x);
176    }
177
178    /** Convert buffer to an array
179     */
180    public <T> T[] toArray(T[] vec) {
181        return elems.toArray(vec);
182    }
183    public Object[] toArray() {
184        return toArray(new Object[size()]);
185    }
186
187    /** The first element in this buffer.
188     */
189    public A first() {
190        return elems.head;
191    }
192
193    /** Return first element in this buffer and remove
194     */
195    public A next() {
196        A x = elems.head;
197        if (!elems.isEmpty()) {
198            elems = elems.tail;
199            if (elems.isEmpty()) last = null;
200            count--;
201        }
202        return x;
203    }
204
205    /** An enumeration of all elements in this buffer.
206     */
207    public Iterator<A> iterator() {
208        return new Iterator<A>() {
209            List<A> elems = ListBuffer.this.elems;
210            public boolean hasNext() {
211                return !elems.isEmpty();
212            }
213            public A next() {
214                if (elems.isEmpty())
215                    throw new NoSuchElementException();
216                A elem = elems.head;
217                elems = elems.tail;
218                return elem;
219            }
220            public void remove() {
221                throw new UnsupportedOperationException();
222            }
223        };
224    }
225
226    public boolean add(A a) {
227        append(a);
228        return true;
229    }
230
231    public boolean remove(Object o) {
232        throw new UnsupportedOperationException();
233    }
234
235    public boolean containsAll(Collection<?> c) {
236        for (Object x: c) {
237            if (!contains(x))
238                return false;
239        }
240        return true;
241    }
242
243    public boolean addAll(Collection<? extends A> c) {
244        for (A a: c)
245            append(a);
246        return true;
247    }
248
249    public boolean removeAll(Collection<?> c) {
250        throw new UnsupportedOperationException();
251    }
252
253    public boolean retainAll(Collection<?> c) {
254        throw new UnsupportedOperationException();
255    }
256
257    public boolean offer(A a) {
258        append(a);
259        return true;
260    }
261
262    public A poll() {
263        return next();
264    }
265
266    public A peek() {
267        return first();
268    }
269
270    public A last() {
271        return last != null ? last.head : null;
272    }
273}
274