KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xsocket > stream > ByteBufferParser


1 // $Id: ByteBufferParser.java 1449 2007-07-04 16:06:49Z grro $
2
/*
3  * Copyright (c) xsocket.org, 2006 - 2007. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
20  * The latest copy of this software may be found on http://www.xsocket.org/
21  */

22 package org.xsocket.stream;
23
24 import java.io.IOException JavaDoc;
25 import java.nio.BufferUnderflowException JavaDoc;
26 import java.nio.ByteBuffer JavaDoc;
27 import java.util.LinkedList JavaDoc;
28
29
30 /**
31  * Helper class to parse a ByteBuffer queue for a delimiter and
32  * to extract data based on a length field or the delimiter
33  *
34  * @author grro@xsocket.org
35  */

36 final class ByteBufferParser {
37
38
39     /**
40      * returns a index, which gives the position
41      * of a record by using the delimiter
42      *
43      * @param bufferQueue the queue
44      * @param delimiter the delimiter
45      *
46      * @return the index
47      */

48     public Index find(LinkedList JavaDoc<ByteBuffer JavaDoc> bufferQueue, byte[] delimiter) {
49         return find(bufferQueue, new Index(delimiter));
50     }
51
52
53     /**
54      * returns a index, which gives the position
55      * of a record by using the delimiter
56      *
57      * @param bufferQueue the queue
58      * @param index index the index
59      *
60      * @return the index
61      */

62     public Index find(LinkedList JavaDoc<ByteBuffer JavaDoc> bufferQueue, Index index) {
63
64         int queueSize = bufferQueue.size();
65
66         // iterate all buffers (beginning with new since last scanned for index)
67
for (int bufNr = index.scannedBuffers; (bufNr <queueSize) && (!index.hasDelimiterFound); bufNr++) {
68
69             // retieve buffer
70
ByteBuffer JavaDoc buffer = bufferQueue.get(bufNr);
71
72             // save current buffer positions
73
int savedPos = buffer.position();
74             int savedLimit = buffer.limit();
75
76             int contentLength = savedLimit - savedPos;
77
78             // iterator over buffer content
79
bufferLoop: for (int pos = savedPos; ((pos < contentLength) && !index.hasDelimiterFound); pos++) {
80
81                 byte b = buffer.get(pos);
82                 index.readBytes++;
83
84                 // intermediate delimiter byte check
85
if (index.delimiterPos > 0) {
86                     if (b == index.delimiterBytes[index.delimiterPos]) {
87                         // is last byte of delimiter?
88
if ((index.delimiterPos + 1) == index.delimiterLength) {
89                             index.hasDelimiterFound = true;
90                             break bufferLoop;
91                         }
92
93                         // inc position
94
index.delimiterPos++;
95                         continue;
96
97                     // no delimiter byte found -> reset counter
98
} else {
99                         index.delimiterPos = 0;
100                     }
101                 }
102
103
104                 // first delimiter byte check
105
if (index.delimiterPos == 0) {
106                     if (b == index.delimiterBytes[index.delimiterPos]) {
107                         // inc position
108
index.delimiterPos++;
109
110                         // is single byte delimiter?
111
if (index.delimiterLength == 1) {
112                             index.hasDelimiterFound = true;
113                             break bufferLoop;
114                         }
115                     }
116                 }
117             } // end buffer loop
118

119             index.scannedBuffers++;
120
121
122             // restore buffer positions
123
buffer.position(savedPos);
124             buffer.limit(savedLimit);
125         }
126
127         return index;
128     }
129
130
131
132     /**
133      * extracts the record from the given buffer by using a length field
134      *
135      * @param inOutBuffer the buffer, which contains the data. The extracted data will be removed
136      * @param length the length to read
137      * @return the extracted data
138      * @throws BufferUnderflowException if the delimiter has not been found
139      * @throws IOException If some other I/O error occurs
140      */

141     public LinkedList JavaDoc<ByteBuffer JavaDoc> extract(LinkedList JavaDoc<ByteBuffer JavaDoc> inOutBuffer, int length) throws IOException JavaDoc, BufferUnderflowException JavaDoc {
142
143         LinkedList JavaDoc<ByteBuffer JavaDoc> result = new LinkedList JavaDoc<ByteBuffer JavaDoc>();
144
145         int remainingToExtract = length;
146         ByteBuffer JavaDoc buffer = null;
147
148         do {
149             // get the next buffer
150
buffer = inOutBuffer.remove();
151             if (buffer == null) {
152                 throw new BufferUnderflowException JavaDoc();
153             }
154
155             // can complete buffer be taken?
156
int bufLength = buffer.limit() - buffer.position();
157             if (remainingToExtract >= bufLength) {
158                 // write taken into out channel
159
result.addLast(buffer);
160                 remainingToExtract -= bufLength;
161
162             // .. no
163
} else {
164                 int savedLimit = buffer.limit();
165
166                 // extract the takenable
167
buffer.limit(buffer.position() + remainingToExtract);
168                 ByteBuffer JavaDoc leftPart = buffer.slice();
169                 result.addLast(leftPart);
170                 buffer.position(buffer.limit());
171                 buffer.limit(savedLimit);
172                 ByteBuffer JavaDoc rightPart = buffer.slice();
173                 inOutBuffer.addFirst(rightPart);
174                 break;
175             }
176
177         } while (remainingToExtract > 0);
178
179         return result;
180     }
181
182
183
184     /**
185      * extracts the record from the given buffer by using the index
186      *
187      * @param inOutBuffer the buffer, which contains the data. The extracted data will be removed
188      * @param index the index
189      * @return the extracted data
190      * @throws IOException If some other I/O error occurs
191
192      */

193     public LinkedList JavaDoc<ByteBuffer JavaDoc> extract(LinkedList JavaDoc<ByteBuffer JavaDoc> inOutBuffer, Index index) throws IOException JavaDoc {
194         assert (index.isValid) : "Index is invalid";
195         assert (index.hasDelimiterFound());
196
197         // extract content data based on delimiter position
198
LinkedList JavaDoc<ByteBuffer JavaDoc> result = extract(inOutBuffer, index.getReadBytes() - index.getDelimiterLength());
199
200         // extract delimiter
201
extract(inOutBuffer, index.getDelimiterLength());
202
203         return result;
204     }
205
206
207
208
209     /**
210      * the index to mark the position of the delimiter
211      *
212      */

213     public final static class Index {
214         public static final int NULL = -1;
215
216         // flags
217
private boolean isValid = true;
218         private boolean hasDelimiterFound = false;
219
220
221         // delimiter
222
private byte[] delimiterBytes = null;
223         private int delimiterLength = 0;
224         private int delimiterPos = 0;
225
226
227         // positions
228
private int scannedBuffers = 0;
229         private int readBytes = 0;
230
231
232
233         Index(byte[] delimiterBytes) {
234             this.delimiterBytes = delimiterBytes;
235             this.delimiterLength = delimiterBytes.length;
236         }
237
238         public boolean hasDelimiterFound() {
239             return hasDelimiterFound;
240         }
241
242         public int getReadBytes() {
243             return readBytes;
244         }
245
246         public boolean isDelimiterEquals(byte[] other) {
247
248             if (other.length != delimiterLength) {
249                 return false;
250             }
251
252             for (int i = 0; i < delimiterLength; i++) {
253                 if (other[i] != delimiterBytes[i]) {
254                     return false;
255                 }
256             }
257
258             return true;
259         }
260
261
262         int getDelimiterLength() {
263             return delimiterLength;
264         }
265
266         public int getDelimiterPos() {
267             return delimiterPos;
268         }
269     }
270 }
Popular Tags