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 */
180 protected void addNode( Node nodeToInsert, Node insertBeforeNode )
181 {
182 // Insert node.
183 nodeToInsert.next = insertBeforeNode;
184 nodeToInsert.previous = insertBeforeNode.previous;
185 insertBeforeNode.previous.next = nodeToInsert;
186 insertBeforeNode.previous = nodeToInsert;
187 }
188
189
190 /**
191 * Removes the specified node from the list.
192 *
193 * @param node the node to remove
194 */
195 protected Node removeNode( Node node )
196 {
197 // Remove node.
198 node.previous.next = node.next;
199 node.next.previous = node.previous;
200 node.removed = true;
201 return node;
202 }
203
204 //-----------------------------------------------------------------------
205 /**
206 * A node within the linked list.
207 * <p>
208 * From Commons Collections 3.1, all access to the <code>value</code> property
209 * is via the methods on this class.
210 */
211 public class Node
212 {
213
214 /** A pointer to the node before this node */
215 private Node previous;
216
217 /** A pointer to the node after this node */
218 private Node next;
219
220 /** The ByteArray contained within this node */
221 private ByteArray ba;
222
223 private boolean removed;
224
225
226 /**
227 * Constructs a new header node.
228 */
229 private Node()
230 {
231 super();
232 previous = this;
233 next = this;
234 }
235
236
237 /**
238 * Constructs a new node with a value.
239 */
240 private Node( ByteArray ba )
241 {
242 super();
243
244 if ( ba == null )
245 {
246 throw new IllegalArgumentException( "ByteArray must not be null." );
247 }
248
249 this.ba = ba;
250 }
251
252
253 /**
254 * Gets the previous node.
255 *
256 * @return the previous node
257 */
258 public Node getPreviousNode()
259 {
260 if ( !hasPreviousNode() )
261 {
262 throw new NoSuchElementException();
263 }
264 return previous;
265 }
266
267
268 /**
269 * Gets the next node.
270 *
271 * @return the next node
272 */
273 public Node getNextNode()
274 {
275 if ( !hasNextNode() )
276 {
277 throw new NoSuchElementException();
278 }
279 return next;
280 }
281
282
283 public boolean hasPreviousNode()
284 {
285 return previous != header;
286 }
287
288
289 public boolean hasNextNode()
290 {
291 return next != header;
292 }
293
294
295 public ByteArray getByteArray()
296 {
297 return ba;
298 }
299
300
301 public boolean isRemoved()
302 {
303 return removed;
304 }
305 }
306
307 }