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 
26 package com.sun.tools.javac.util;
27 
28 import java.util.AbstractQueue;
29 import java.util.Collection;
30 import java.util.Iterator;
31 import 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  */
41 public class ListBuffer<A> extends AbstractQueue<A> {
42 
of(T x)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      */
ListBuffer()68     public ListBuffer() {
69         clear();
70     }
71 
clear()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      */
length()81     public int length() {
82         return count;
83     }
size()84     public int size() {
85         return count;
86     }
87 
88     /** Is buffer empty?
89      */
isEmpty()90     public boolean isEmpty() {
91         return count == 0;
92     }
93 
94     /** Is buffer not empty?
95      */
nonEmpty()96     public boolean nonEmpty() {
97         return count != 0;
98     }
99 
100     /** Copy list and sets last.
101      */
copy()102     private void copy() {
103         if (elems.nonEmpty()) {
104             List<A> orig = elems;
105 
106             elems = last = List.of(orig.head);
107 
108             while ((orig = orig.tail).nonEmpty()) {
109                 last.tail = List.of(orig.head);
110                 last = last.tail;
111             }
112         }
113     }
114 
115     /** Prepend an element to buffer.
116      */
prepend(A x)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      */
append(A x)126     public ListBuffer<A> append(A x) {
127         Assert.checkNonNull(x);
128         if (shared) copy();
129         List<A> newLast = List.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      */
appendList(List<A> xs)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      */
appendList(ListBuffer<A> xs)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      */
appendArray(A[] xs)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      */
toList()167     public List<A> toList() {
168         shared = true;
169         return elems;
170     }
171 
172     /** Does the list contain the specified element?
173      */
contains(Object x)174     public boolean contains(Object x) {
175         return elems.contains(x);
176     }
177 
178     /** Convert buffer to an array
179      */
toArray(T[] vec)180     public <T> T[] toArray(T[] vec) {
181         return elems.toArray(vec);
182     }
toArray()183     public Object[] toArray() {
184         return toArray(new Object[size()]);
185     }
186 
187     /** The first element in this buffer.
188      */
first()189     public A first() {
190         return elems.head;
191     }
192 
193     /** Return first element in this buffer and remove
194      */
next()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      */
iterator()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 
add(A a)226     public boolean add(A a) {
227         append(a);
228         return true;
229     }
230 
remove(Object o)231     public boolean remove(Object o) {
232         throw new UnsupportedOperationException();
233     }
234 
containsAll(Collection<?> c)235     public boolean containsAll(Collection<?> c) {
236         for (Object x: c) {
237             if (!contains(x))
238                 return false;
239         }
240         return true;
241     }
242 
addAll(Collection<? extends A> c)243     public boolean addAll(Collection<? extends A> c) {
244         for (A a: c)
245             append(a);
246         return true;
247     }
248 
removeAll(Collection<?> c)249     public boolean removeAll(Collection<?> c) {
250         throw new UnsupportedOperationException();
251     }
252 
retainAll(Collection<?> c)253     public boolean retainAll(Collection<?> c) {
254         throw new UnsupportedOperationException();
255     }
256 
offer(A a)257     public boolean offer(A a) {
258         append(a);
259         return true;
260     }
261 
poll()262     public A poll() {
263         return next();
264     }
265 
peek()266     public A peek() {
267         return first();
268     }
269 
last()270     public A last() {
271         return last != null ? last.head : null;
272     }
273 }
274