KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > services > io > ArrayInputStream


1 /*
2
3    Derby - Class org.apache.derby.iapi.services.io.ArrayInputStream
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.derby.iapi.services.io;
23
24 import java.io.InputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.ObjectInput JavaDoc;
27 import java.io.EOFException JavaDoc;
28
29 import org.apache.derby.iapi.services.sanity.SanityManager;
30
31 import org.apache.derby.iapi.services.io.LimitObjectInput;
32 import org.apache.derby.iapi.services.io.ErrorObjectInput;
33
34 import java.io.UTFDataFormatException JavaDoc;
35
36 /**
37     An InputStream that allows reading from an array of bytes. The array
38     of bytes that is read from can be changed without having to create a new
39     instance of this class.
40 */

41 public final class ArrayInputStream extends InputStream JavaDoc implements LimitObjectInput {
42
43     private byte[] pageData;
44
45     private int start;
46     private int end; // exclusive
47
private int position;
48
49     public ArrayInputStream() {
50         this(null);
51     }
52
53     private ErrorObjectInput oi;
54
55     public ArrayInputStream(byte[] data) {
56         super();
57         setData(data);
58         oi = new org.apache.derby.iapi.services.io.FormatIdInputStream(this);
59     }
60
61     public ArrayInputStream(byte[] data, int offset, int length) throws IOException JavaDoc {
62         this(data);
63         setLimit(offset, length);
64     }
65
66     /*
67     ** Public methods
68     */

69
70     /**
71         Set the array of bytes to be read.
72     */

73     public void setData(byte[] data) {
74         pageData = data;
75         clearLimit();
76     }
77
78     public void setData(byte[] data, int offset, int length) throws IOException JavaDoc {
79         pageData = data;
80         setLimit(offset, length);
81     }
82
83     /**
84         Return a reference to the array of bytes this stream is going to read
85         from so that caller may load it with stuff
86     */

87     public byte[] getData()
88     {
89         return pageData;
90     }
91
92     /*
93     ** Methods of InputStream
94     */

95
96     public int read() throws IOException JavaDoc {
97         if (position == end)
98             return -1; // end of file
99

100         return pageData[position++] & 0xff ;
101
102     }
103
104     public int read(byte b[], int off, int len) throws IOException JavaDoc {
105
106         if ((position + len) > end) {
107
108             len = end - position;
109
110             if (len == 0) {
111                 return -1; // end of file
112
}
113         }
114
115         System.arraycopy(pageData, position, b, off, len);
116         position += len;
117         return len;
118     }
119
120     public long skip(long count) throws IOException JavaDoc {
121
122         if ((position + count) > end) {
123
124             count = end - position;
125
126             if (count == 0)
127                 return 0; // end of file
128
}
129
130         position += count;
131
132         return count;
133
134     }
135
136     public int getPosition() {
137         return position;
138     }
139
140     public final void setPosition(int newPosition)
141         throws IOException JavaDoc {
142
143         if ((newPosition >= start) && (newPosition < end))
144             position = newPosition;
145         else
146             throw new EOFException JavaDoc();
147     }
148
149     public int available() throws IOException JavaDoc {
150
151         return end - position;
152     }
153
154
155     /**
156         A setLimit which also sets the position to be offset.
157
158         @exception IOException limit is out of range
159     */

160     public int setLimit(int offset, int length) throws IOException JavaDoc {
161
162         if ((offset < 0) || (length < 0)) {
163             start = end = position = 0;
164             throw new EOFException JavaDoc();
165         }
166
167         start = offset;
168         end = offset + length;
169
170         if (end > pageData.length) {
171             start = end = position = 0;
172             throw new EOFException JavaDoc();
173         }
174
175         position = start;
176
177         return length;
178     }
179
180     /*
181     ** Methods of Limit
182     */

183
184     public final void setLimit(int length) throws IOException JavaDoc {
185
186         start = position;
187         end = position + length;
188
189         if (end <= pageData.length)
190         {
191             return;
192         }
193         else
194         {
195             start = end = position = 0;
196             throw new EOFException JavaDoc();
197         }
198     }
199
200     /**
201         Clears the limit by setting the limit to be the entire byte array.
202
203         @see Limit#clearLimit
204     */

205     public final int clearLimit() {
206
207         if (pageData != null) {
208             start = 0;
209             int remainingBytes = end - position;
210             end = pageData.length;
211             return remainingBytes;
212         } else {
213             start = end = position = 0;
214             return 0;
215         }
216     }
217
218     /*
219     ** Methods of DataInput
220     */

221
222     public final void readFully(byte b[]) throws IOException JavaDoc {
223         readFully(b, 0, b.length);
224     }
225
226     public final void readFully(byte b[], int off, int len) throws IOException JavaDoc {
227
228         if ((position + len) > end) {
229
230             throw new EOFException JavaDoc();
231         }
232
233         System.arraycopy(pageData, position, b, off, len);
234         position += len;
235     }
236
237     public final int skipBytes(int n) throws IOException JavaDoc {
238         if ((position + n) > end) {
239
240             throw new EOFException JavaDoc();
241         }
242         position += n;
243         return n;
244     }
245
246     public final boolean readBoolean() throws IOException JavaDoc {
247         if (position == end)
248             throw new EOFException JavaDoc(); // end of file
249

250         return pageData[position++] != 0;
251     }
252
253     public final byte readByte() throws IOException JavaDoc {
254         if (position == end)
255             throw new EOFException JavaDoc(); // end of file
256

257         return pageData[position++];
258     }
259
260     public final int readUnsignedByte() throws IOException JavaDoc {
261         if (position == end)
262             throw new EOFException JavaDoc(); // end of file
263

264         return pageData[position++] & 0xff ;
265     }
266
267     public final short readShort() throws IOException JavaDoc {
268
269         int pos = position;
270         byte[] data = pageData;
271
272         if (pos >= (end - 1))
273             throw new EOFException JavaDoc(); // end of file
274

275         int s = ((data[pos++] & 0xff) << 8) | (data[pos++] & 0xff);
276
277         position = pos;
278
279         return (short) s;
280     }
281
282    public final int readUnsignedShort() throws IOException JavaDoc {
283         int pos = position;
284         byte[] data = pageData;
285
286         if (pos >= (end - 1))
287             throw new EOFException JavaDoc(); // end of file
288

289         int us = ((data[pos++] & 0xff) << 8) | (data[pos++] & 0xff);
290
291         position = pos;
292
293         return us;
294    }
295
296     public final char readChar() throws IOException JavaDoc {
297         int pos = position;
298         byte[] data = pageData;
299
300         if (pos >= (end -1))
301             throw new EOFException JavaDoc(); // end of file
302

303         int c = ((data[pos++] & 0xff) << 8) | (data[pos++] & 0xff);
304
305         position = pos;
306
307         return (char) c;
308     }
309
310     public final int readInt() throws IOException JavaDoc {
311
312         int pos = position;
313         byte[] data = pageData;
314
315         if (pos >= (end - 3))
316             throw new EOFException JavaDoc(); // end of file
317

318
319
320         int i = ((data[pos++] & 0xff) << 24) |
321                 ((data[pos++] & 0xff) << 16) |
322                 ((data[pos++] & 0xff) << 8) |
323                 ((data[pos++] & 0xff) );
324
325         position = pos;
326
327         return i;
328     }
329
330     public final long readLong() throws IOException JavaDoc {
331         int pos = position;
332         byte[] data = pageData;
333
334         if (pos >= (end - 7))
335             throw new EOFException JavaDoc(); // end of file
336

337         long l =
338             (((long) (data[pos++] & 0xff)) << 56) |
339             (((long) (data[pos++] & 0xff)) << 48) |
340             (((long) (data[pos++] & 0xff)) << 40) |
341             (((long) (data[pos++] & 0xff)) << 32) |
342             (((long) (data[pos++] & 0xff)) << 24) |
343             (((long) (data[pos++] & 0xff)) << 16) |
344             (((long) (data[pos++] & 0xff)) << 8) |
345             (((long) (data[pos++] & 0xff)) );
346
347         position = pos;
348
349         return l;
350     }
351
352     public final float readFloat() throws IOException JavaDoc {
353         return Float.intBitsToFloat(readInt());
354     }
355
356     public final double readDouble() throws IOException JavaDoc {
357         return Double.longBitsToDouble(readLong());
358     }
359
360     public final String JavaDoc readLine() throws IOException JavaDoc {
361         return oi.readLine();
362     }
363     public final String JavaDoc readUTF() throws IOException JavaDoc {
364         return oi.readUTF();
365     }
366
367     /**
368      * read in a cloudscape UTF formated string into a char[].
369      * <p>
370      * This routine inline's the code to read a UTF format string from a
371      * byte[] array (pageData), into a char[] array. The string will
372      * be read into the char[] array passed into this routine through
373      * rawData_array[0] if it is big enough. If it is not big enough
374      * a new char[] will be alocated and returned to the caller by putting
375      * it into rawData_array[0].
376      * <p>
377      * To see detailed description of the cloudscape UTF format see
378      * the writeExternal() routine of SQLChar.
379      * <p>
380      * The routine returns the number of char's read into the returned
381      * char[], note that this length may smaller than the actual length
382      * of the char[] array.
383      *
384      * @return The the number of valid char's in the returned char[].
385      *
386      * @param rawData_array This parameter uses a element array to implement
387      * an in/out function parameter. The char[] array
388      * in rawData_array[0] is used to read the data into
389      * unless it is not big enough, then a new array
390      * is allocated and the old one discarded. In
391      * either case on return rawData_array[0] contains
392      * the filled in char[] - caller must allow that
393      * the array may or may not be different from the
394      * one passed in.
395      *
396      * @exception StandardException Standard exception policy.
397      **/

398     public final int readCloudscapeUTF(char[][] rawData_array)
399         throws IOException JavaDoc
400     {
401         // copy globals locally, to give compiler chance to optimize.
402
byte[] data = pageData;
403         int end_pos = end;
404         int pos = position;
405
406         // get header length - stored as an unsigned short.
407

408         int utflen;
409         if (pos + 1 < end_pos)
410         {
411             utflen = (((data[pos++] & 0xff) << 8) | (data[pos++] & 0xff));
412         }
413         else
414         {
415             throw new EOFException JavaDoc(); // end of file
416
}
417
418         /**
419          * 3 cases - can they all happen?
420          *
421          * o utflen == 0 and end is marked E0, 0, 0
422          * o utflen == 0 and there is no data (ie. 0 length string)
423          * o utflen != 0, utflen is exact length of following bytes
424          **/

425
426         // requiredLength is the amount of bytes to read from the array,
427
// either the utflen in the header length, or the number of bytes
428
// available in the array. Throw an exception if we know up front
429
// that utflen is bigger than number of bytes in the array.
430
int requiredLength;
431         if (utflen != 0)
432         {
433             // this is the only place we need to check for end of file,
434
// the subsequent loop will not read past bytes_available_in_array.
435

436             if (utflen <= (end_pos - pos))
437             {
438                 requiredLength = utflen;
439             }
440             else
441             {
442                 throw new EOFException JavaDoc();
443             }
444         }
445         else
446         {
447             // the byte header returned 0, so read what is left in the array.
448

449             requiredLength = (end_pos - pos);
450         }
451
452         // Use the passed in char[] array if it is long enough, otherwise
453
// allocate a new array, and will pass it back to caller at the end.
454
// Note that requiredLength is the worst case length for the array,
455
// as the number of char characters must be <= number of bytes (ie.
456
// all characters were stored compressed in 1 byte each - the ascii
457
// default) - if there are any 2 or 3 byte stored characters then
458
// the array will have extra space at the end. "strlen" tracks the
459
// real number of char's in str[].
460
char[] str = rawData_array[0];
461         if ((str == null) || (requiredLength > str.length))
462         {
463             str = new char[requiredLength];
464             rawData_array[0] = str;
465         }
466
467         end_pos = pos + requiredLength;
468         int strlen = 0;
469
470         while (pos < end_pos)
471         {
472             int char1 = (data[pos++] & 0xff);
473
474             // top fours bits of the first unsigned byte that maps to a 1,2
475
// or 3 byte character
476
//
477
// 0000xxxx - 0 - 1 byte char
478
// 0001xxxx - 1 - 1 byte char
479
// 0010xxxx - 2 - 1 byte char
480
// 0011xxxx - 3 - 1 byte char
481
// 0100xxxx - 4 - 1 byte char
482
// 0101xxxx - 5 - 1 byte char
483
// 0110xxxx - 6 - 1 byte char
484
// 0111xxxx - 7 - 1 byte char
485
// 1000xxxx - 8 - error
486
// 1001xxxx - 9 - error
487
// 1010xxxx - 10 - error
488
// 1011xxxx - 11 - error
489
// 1100xxxx - 12 - 2 byte char
490
// 1101xxxx - 13 - 2 byte char
491
// 1110xxxx - 14 - 3 byte char
492
// 1111xxxx - 15 - error
493

494             int char2, char3;
495             if ((char1 & 0x80) == 0x00)
496             {
497                 // one byte character
498
str[strlen++] = (char) char1;
499             }
500             else if ((char1 & 0x60) == 0x40) // we know the top bit is set here
501
{
502                 // two byte character, make sure read of next byte is in bounds.
503
if (pos >= end_pos)
504                     throw new UTFDataFormatException JavaDoc();
505
506                 char2 = (data[pos++] & 0xff);
507
508                 if ((char2 & 0xC0) != 0x80)
509                     throw new UTFDataFormatException JavaDoc();
510
511                 str[strlen++] = (char)(((char1 & 0x1F) << 6) | (char2 & 0x3F));
512             }
513             else if ((char1 & 0x70) == 0x60) // we know the top bit is set here
514
{
515                 // three byte character
516

517                 // 3 byte character, make sure read of next 2 bytes in bounds.
518
if (pos + 1 >= end_pos)
519                     throw new UTFDataFormatException JavaDoc();
520
521                 char2 = (data[pos++] & 0xff);
522                 char3 = (data[pos++] & 0xff);
523
524                 if ((char1 == 0xE0) &&
525                     (char2 == 0) &&
526                     (char3 == 0) &&
527                     (utflen == 0))
528                 {
529                     // we reached the end of a long string,
530
// that was terminated with
531
// (11100000, 00000000, 00000000)
532
break;
533                 }
534                 else if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
535                 {
536                     throw new UTFDataFormatException JavaDoc();
537                 }
538                 else
539                 {
540                     str[strlen++] = (char)
541                         (((char1 & 0x0F) << 12) |
542                          ((char2 & 0x3F) << 6) |
543                          ((char3 & 0x3F) << 0));
544                 }
545             }
546             else
547             {
548                 throw new UTFDataFormatException JavaDoc();
549             }
550
551         }
552
553         // update global on successful read exit.
554
position = pos;
555
556         return(strlen);
557     }
558
559     /**
560      * Read a compressed int from the stream.
561      * <p>
562      * Read a compressed int from the stream, which is assumed to have
563      * been written by a call to CompressNumber.writeInt().
564      * <p>
565      * Code from CompressedNumber is inlined here so that these fields can
566      * be read from the array with a minimum of function calls.
567      * <p>
568      * The format of a compressed int is as follows:
569      *
570      * Formats are (with x representing value bits):
571      * <PRE>
572      * 1 Byte- 00xxxxxx val <= 63 (0x3f)
573      * 2 Byte- 01xxxxxx xxxxxxxx val > 63 && <= 16383 (0x3fff)
574      * 4 byte- 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx val > 16383 && <= MAX_INT
575      * </PRE>
576      *
577      * @exception StandardException Standard exception policy.
578      **/

579     public final int readCompressedInt()
580         throws IOException JavaDoc
581     {
582         int pos = position;
583         byte[] data = pageData;
584
585         try
586         {
587             int value = data[pos++];
588
589             if ((value & ~0x3f) == 0)
590             {
591                 // entire value is stored in this byte, we also know that the
592
// 0x80 bit was not set, so no need to mask off the sign
593
// extension from the byte to int conversion.
594
}
595             else if ((value & 0x80) == 0)
596             {
597                 // value stored in 2 bytes. only use low 6 bits from 1st byte.
598

599                 if (SanityManager.DEBUG)
600                 {
601                     SanityManager.ASSERT((value & 0x40) == 0x40);
602                 }
603
604                 // top 8 bits of 2 byte value is stored in this byte, we also
605
// know that the 0x80 bit was not set, so no need to mask off
606
// the sign extension from the 1st byte to int conversion.
607
// Need to mask the byte in data[pos + 1] to account for
608
// possible sign extension.
609

610                 value =
611                     (((value & 0x3f) << 8) | (data[pos++] & 0xff));
612             }
613             else
614             {
615                 // value stored in 4 bytes. only use low 7 bits from 1st byte.
616

617                 if (SanityManager.DEBUG)
618                 {
619                     SanityManager.ASSERT((value & 0x80) == 0x80);
620                 }
621
622                 // top 8 bits of 4 byte value is stored in this byte, we also
623
// know that the 0x80 bit was set, so need to mask off the
624
// sign extension from the 1st byte to int conversion. Need to
625
// mask the bytes from the next 3 bytes data[pos + 1,2,3] to
626
// account for possible sign extension.
627
//
628

629                 value =
630                     ((value & 0x7f) << 24) |
631                     ((data[pos++] & 0xff) << 16) |
632                     ((data[pos++] & 0xff) << 8) |
633                     ((data[pos++] & 0xff) );
634             }
635
636             position = pos;
637
638             return(value);
639         }
640         catch (java.lang.ArrayIndexOutOfBoundsException JavaDoc ex)
641         {
642             throw new EOFException JavaDoc(); // end of file
643
}
644
645     }
646
647     /**
648      * Read a compressed long from the stream.
649      * <p>
650      * Read a compressed long from the stream, which is assumed to have
651      * been written by a call to CompressNumber.writeLong().
652      * <p>
653      * Code from CompressedNumber is inlined here so that these fields can
654      * be read from the array with a minimum of function calls.
655      * <p>
656      * The format of a compressed int is as follows:
657      *
658      * Formats are (with x representing value bits):
659      * <PRE>
660      * value <= 16383 (0x3fff):
661      * 2 byte - 00xxxxxx xxxxxxxx
662      *
663      * value > 16383 && <= 0x3fffffff:
664      * 4 byte - 01xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
665      *
666      * value > 0x3fffffff && <= MAX_LONG:
667      * 8 byte - 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
668      * </PRE>
669      *
670      **/

671     public final long readCompressedLong()
672         throws IOException JavaDoc
673     {
674         try
675         {
676             // copy globals locally, to give compiler chance to optimize.
677
int pos = position;
678             byte[] data = pageData;
679
680             // int_value tells whether it is 1, 4, or 8 bytes long.
681
int int_value = data[pos++];
682
683             // build up long value and return it through this variable.
684
long long_value;
685
686             if ((int_value & ~0x3f) == 0)
687             {
688                 // 2 byte representation
689

690                 // 1st byte of value is stored in int_value, we also know that
691
// the 0x80 bit was not set, so no need to mask off the sign
692
// extension from the 1st byte to int conversion.
693
long_value = ((int_value << 8) | (data[pos++] & 0xff));
694             }
695             else if ((int_value & 0x80) == 0)
696             {
697                 // value stored in 4 bytes. only use low 6 bits from 1st byte.
698

699                 // Need to mask the bytes from the next 3 bytes
700
// data[pos + 1,2,3] to account for possible sign extension.
701

702                 long_value =
703                     ((int_value & 0x3f) << 24) |
704                     ((data[pos++] & 0xff) << 16) |
705                     ((data[pos++] & 0xff) << 8) |
706                     ((data[pos++] & 0xff) );
707             }
708             else
709             {
710                 // top 7 bits of 4 byte value is stored in int_value, we also
711
// know that the 0x80 bit was set, so need to mask off the
712
// sign extension from the 1st byte to int conversion. Need to
713
// mask the bytes from the next 7 bytes data[pos + 1,2,...] to
714
// account for possible sign extension.
715
//
716

717                 // value stored in 8 bytes. only use low 6 bits from 1st byte.
718
long_value =
719                     (((long) (int_value & 0x7f)) << 56) |
720                     (((long) (data[pos++] & 0xff)) << 48) |
721                     (((long) (data[pos++] & 0xff)) << 40) |
722                     (((long) (data[pos++] & 0xff)) << 32) |
723                     (((long) (data[pos++] & 0xff)) << 24) |
724                     (((long) (data[pos++] & 0xff)) << 16) |
725                     (((long) (data[pos++] & 0xff)) << 8) |
726                     (((long) (data[pos++] & 0xff)) );
727             }
728
729             position = pos;
730
731             return(long_value);
732         }
733         catch (java.lang.ArrayIndexOutOfBoundsException JavaDoc ex)
734         {
735             // let java figure out if we went past end of data[] array.
736

737             throw new EOFException JavaDoc(); // end of file
738
}
739     }
740
741     public Object JavaDoc readObject() throws ClassNotFoundException JavaDoc, IOException JavaDoc {
742         return oi.readObject();
743     }
744
745     public String JavaDoc getErrorInfo() {
746         return oi.getErrorInfo();
747     }
748
749     public Exception JavaDoc getNestedException() {
750         return oi.getNestedException();
751     }
752 }
753
Popular Tags