1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.util.byteaccess;
21
22
23 import java.util.NoSuchElementException;
24
25
26 /**
27 * A linked list that stores <code>ByteArray</code>s and maintains several useful invariants.
28 *
29 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
30 */
31 class ByteArrayList
32 {
33
34 /**
35 * A {@link Node} which indicates the start and end of the list and does not
36 * hold a value. The value of <code>next</code> is the first item in the
37 * list. The value of of <code>previous</code> is the last item in the list.
38 */
39 private final Node header;
40
41 /**
42 * The first byte in the array list
43 */
44 private int firstByte;
45
46 /**
47 * The last byte in the array list
48 */
49 private int lastByte;
50
51 /**
52 *
53 * Creates a new instance of ByteArrayList.
54 *
55 */
56 protected ByteArrayList()
57 {
58 header = new Node();
59 }
60
61 /**
62 *
63 * Returns the last byte in the array list
64 *
65 * @return
66 * The last byte in the array list
67 */
68 public int lastByte()
69 {
70 return lastByte;
71 }
72
73 /**
74 *
75 * Returns the first byte in the array list
76 *
77 * @return
78 * The first byte in the array list
79 */
80 public int firstByte()
81 {
82 return firstByte;
83 }
84
85 /**
86 *
87 * Check to see if this is empty
88 *
89 * @return
90 * True if empty, otherwise false
91 */
92 public boolean isEmpty()
93 {
94 return header.next == header;
95 }
96
97 /**
98 * Returns the first node in the byte array
99 *
100 * @return
101 *
102 */
103 public Node getFirst()
104 {
105 return header.getNextNode();
106 }
107
108 /**
109 * Returns the last {@link Node} in the list
110 *
111 * @return
112 * The last node in the list
113 */
114 public Node getLast()
115 {
116 return header.getPreviousNode();
117 }
118
119 /**
120 * Adds the specified {@link ByteArray} to
121 * the beginning of the list
122 *
123 * @param ba
124 * The ByteArray to be added to the list
125 */
126 public void addFirst( ByteArray ba )
127 {
128 addNode( new Node( ba ), header.next );
129 firstByte -= ba.last();
130 }
131
132 /**
133 * Add the specified {@link ByteArray} to
134 * the end of the list
135 *
136 * @param ba
137 * The ByteArray to be added to the list
138 */
139 public void addLast( ByteArray ba )
140 {
141 addNode( new Node( ba ), header );
142 lastByte += ba.last();
143 }
144
145 /**
146 * Removes the first node from this list
147 *
148 * @return
149 * The node that was removed
150 */
151 public Node removeFirst()
152 {
153 Node node = header.getNextNode();
154 firstByte += node.ba.last();
155 return removeNode( node );
156 }
157
158 /**
159 * Removes the last node in this list
160 *
161 * @return
162 * The node that was taken off of the list
163 */
164 public Node removeLast()
165 {
166 Node node = header.getPreviousNode();
167 lastByte -= node.ba.last();
168 return removeNode( node );
169 }
170
171
172 //-----------------------------------------------------------------------
173
174 /**
175 * Inserts a new node into the list.
176 *
177 * @param nodeToInsert new node to insert
178 * @param insertBeforeNode node to insert before
179 * @throws NullPointerException if either node is null
180 */
181 protected void addNode( Node nodeToInsert, Node insertBeforeNode )
182 {
183 // Insert node.
184 nodeToInsert.next = insertBeforeNode;
185 nodeToInsert.previous = insertBeforeNode.previous;
186 insertBeforeNode.previous.next = nodeToInsert;
187 insertBeforeNode.previous = nodeToInsert;
188 }
189
190
191 /**
192 * Removes the specified node from the list.
193 *
194 * @param node the node to remove
195 * @throws NullPointerException if <code>node</code> is null
196 */
197 protected Node removeNode( Node node )
198 {
199 // Remove node.
200 node.previous.next = node.next;
201 node.next.previous = node.previous;
202 node.removed = true;
203 return node;
204 }
205
206 //-----------------------------------------------------------------------
207 /**
208 * A node within the linked list.
209 * <p>
210 * From Commons Collections 3.1, all access to the <code>value</code> property
211 * is via the methods on this class.
212 */
213 public class Node
214 {
215
216 /** A pointer to the node before this node */
217 private Node previous;
218
219 /** A pointer to the node after this node */
220 private Node next;
221
222 /** The ByteArray contained within this node */
223 private ByteArray ba;
224
225 private boolean removed;
226
227
228 /**
229 * Constructs a new header node.
230 */
231 private Node()
232 {
233 super();
234 previous = this;
235 next = this;
236 }
237
238
239 /**
240 * Constructs a new node with a value.
241 */
242 private Node( ByteArray ba )
243 {
244 super();
245
246 if ( ba == null )
247 {
248 throw new NullPointerException( "ByteArray must not be null." );
249 }
250 this.ba = ba;
251 }
252
253
254 /**
255 * Gets the previous node.
256 *
257 * @return the previous node
258 */
259 public Node getPreviousNode()
260 {
261 if ( !hasPreviousNode() )
262 {
263 throw new NoSuchElementException();
264 }
265 return previous;
266 }
267
268
269 /**
270 * Gets the next node.
271 *
272 * @return the next node
273 */
274 public Node getNextNode()
275 {
276 if ( !hasNextNode() )
277 {
278 throw new NoSuchElementException();
279 }
280 return next;
281 }
282
283
284 public boolean hasPreviousNode()
285 {
286 return previous != header;
287 }
288
289
290 public boolean hasNextNode()
291 {
292 return next != header;
293 }
294
295
296 public ByteArray getByteArray()
297 {
298 return ba;
299 }
300
301
302 public boolean isRemoved()
303 {
304 return removed;
305 }
306 }
307
308 }