KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > util > streams > LoopingAlphabetReader


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.util.streams;
23
24 import java.io.IOException JavaDoc;
25 import java.io.Reader JavaDoc;
26
27 /**
28  * A stream returning characters by looping over an alphabet.
29  */

30 public class LoopingAlphabetReader
31     extends Reader JavaDoc {
32
33     /**
34      * Maximum size of buffer.
35      * Balance between size and memory usage.
36      */

37     private static final int MAX_BUF_SIZE = 32*1024;
38     /** The character used for blanks (SPACE). */
39     private static final int SPACE = ' ';
40
41     /** Number of characters in the reader. */
42     private final long length;
43     /** Number of blanks at the end of stream. */
44     private final int trailingBlanks;
45     /** Remaining non-blank characters. */
46     private long remainingNonBlanks;
47     /** Remaining blanks. */
48     private long remainingBlanks;
49     /**
50      * Internal buffer of characters.
51      * Used by the read-methods with a char[] argument.
52      */

53     private char[] buffer = new char[0];
54     /** The alphabet to draw letters from. */
55     private final CharAlphabet alphabet;
56     /** Tell if the reader is closed or not. */
57     private boolean closed = false;
58
59     /**
60      * Create a looping modern latin alphabet reader of the specified length.
61      *
62      * @param length the number of characters
63      */

64     public LoopingAlphabetReader(long length) {
65         this(length, 0);
66     }
67
68     /**
69      * Create a looping modern latin alphabet of the specified length, with
70      * the specified number of trailing blanks.
71      *
72      * The number of non-blank characters is
73      * <code>length - trailingBlanks</code>.
74      *
75      * @param length total number of characters
76      * @param trailingBlanks number of blank characters at the end
77      */

78     public LoopingAlphabetReader(long length, int trailingBlanks) {
79         this.length = length;
80         this.trailingBlanks = trailingBlanks;
81         this.remainingNonBlanks = length - trailingBlanks;
82         this.remainingBlanks = trailingBlanks;
83         this.alphabet = CharAlphabet.modernLatinLowercase();
84         fillBuffer(alphabet.charCount());
85     }
86
87     /**
88      * Create a looping alphabet of the specified type and length.
89      *
90      * @param length the number of chars in the reader
91      * @param alphabet the alphabet to loop over
92      */

93     public LoopingAlphabetReader(long length, CharAlphabet alphabet) {
94         this(length, alphabet, 0);
95     }
96
97     /**
98      * Create a looping alphabet of the specified type and length, with
99      * the specified number of trailing blanks.
100      *
101      * The number of non-blank characters is
102      * <code>length - trailingBlanks</code>.
103      *
104      * @param length total number of characters
105      * @param alphabet the alphabet to draw characters from
106      * @param trailingBlanks number of blank characters at the end
107      */

108     public LoopingAlphabetReader(long length,
109                                  CharAlphabet alphabet,
110                                  int trailingBlanks) {
111         this.length = length;
112         this.trailingBlanks = trailingBlanks;
113         this.remainingNonBlanks = length - trailingBlanks;
114         this.remainingBlanks = trailingBlanks;
115         this.alphabet = alphabet;
116         fillBuffer(alphabet.charCount());
117     }
118
119     public int read()
120             throws IOException JavaDoc {
121         ensureOpen();
122         if (remainingBlanks <= 0 && remainingNonBlanks <= 0) {
123             return -1;
124         }
125         if (remainingNonBlanks <= 0) {
126             remainingBlanks--;
127             return SPACE;
128         }
129         remainingNonBlanks--;
130         return alphabet.nextCharAsInt();
131     }
132
133     public int read(char[] buf, int off, int length)
134             throws IOException JavaDoc {
135         ensureOpen();
136         if (remainingBlanks <= 0 && remainingNonBlanks <= 0) {
137             return -1;
138         }
139         // We can only read as many chars as there are in the stream.
140
int nonBlankLength = Math.min((int)remainingNonBlanks, length);
141         fillBuffer(nonBlankLength);
142         int read = 0;
143         // Find position of next char in the buffer.
144
int cOff = alphabet.nextCharToRead(0);
145         if (nonBlankLength <= (buffer.length - cOff)) {
146             System.arraycopy(buffer, cOff, buf, off, nonBlankLength);
147             remainingNonBlanks -= nonBlankLength;
148             read = nonBlankLength;
149             alphabet.nextCharToRead(nonBlankLength);
150         } else {
151             // Must read several times from the buffer.
152
int toRead = 0;
153             while (remainingNonBlanks > 0 && read < nonBlankLength) {
154                 cOff = alphabet.nextCharToRead(toRead);
155                 toRead = Math.min(buffer.length - cOff, nonBlankLength - read);
156                 System.arraycopy(buffer, cOff, buf, off + read, toRead);
157                 remainingNonBlanks -= toRead;
158                 read += toRead;
159             }
160             cOff = alphabet.nextCharToRead(toRead);
161         }
162         if (read < length && remainingBlanks > 0) {
163             read += fillBlanks(buf, off + read, length - read);
164         }
165         return read;
166     }
167
168     /**
169      * Reset the stream.
170      */

171     public void reset()
172             throws IOException JavaDoc {
173         ensureOpen();
174         remainingNonBlanks = length - trailingBlanks;
175         remainingBlanks = trailingBlanks;
176         alphabet.reset();
177     }
178
179     /**
180      * Return remaining characters in the stream.
181      */

182     public int available() {
183         return (int)(remainingNonBlanks + remainingBlanks);
184     }
185
186     /**
187      * Close the reader.
188      */

189     public void close() {
190         this.closed = true;
191     }
192
193     /**
194      * Fill internal buffer of character sequence.
195      *
196      * @param bufSize the wanted size, might be ignored if too big
197      */

198     private void fillBuffer(int bufSize) {
199         if (bufSize > MAX_BUF_SIZE) {
200             bufSize = MAX_BUF_SIZE;
201         }
202         if (bufSize <= buffer.length) {
203             return;
204         }
205         int curOff = alphabet.nextCharToRead(0);
206         // First letter in buffer is always the first letter in the alphabet.
207
alphabet.reset();
208         buffer = new char[bufSize];
209         for (int i=0; i < bufSize; i++) {
210             buffer[i] = alphabet.nextChar();
211         }
212         // Must reset internal state of the alphabet, as we have not yet
213
// delivered any bytes.
214
alphabet.reset();
215         alphabet.nextCharToRead(curOff);
216     }
217
218     /**
219      * Fill array with blanks (SPACE).
220      *
221      * @param buf array to fill
222      * @param off starting offset
223      * @param length maximum number of blanks to fill in
224      */

225     private int fillBlanks(char[] buf, int off, int length) {
226         int i=0;
227         for (; i < length; i++) {
228             if (remainingBlanks > 0) {
229                 buf[off+i] = SPACE;
230                 remainingBlanks--;
231             } else {
232                 break;
233             }
234         }
235         return i;
236     }
237
238     /**
239      * Ensure reader is open.
240      *
241      * @throws IOException if reader is closed
242      */

243     private final void ensureOpen()
244             throws IOException JavaDoc {
245         if (closed) {
246             throw new IOException JavaDoc("Reader closed");
247         }
248     }
249 } // End class LoopingAlphabetReader
250
Popular Tags