Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/voytechs/jnetstream/io/ProtocolDataInputStream.java


1   /*
2    * File: ProtocolDataInputStream.java
3    * Auth: Mark Bednarczyk
4    * Date: 2003-06-30
5    *   Id: $Id: ProtocolDataInputStream.java,v 1.1.1.1 2003/09/22 16:32:07 voytechs Exp $
6    ********************************************
7    Copyright (C) 2003  Mark Bednarczyk
8   
9    This program is free software; you can redistribute it and/or
10   modify it under the terms of the GNU General Public License
11   as published by the Free Software Foundation; either version 2
12   of the License, or (at your option) any later version.
13  
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18  
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22   ********************************************
23   * $Log: ProtocolDataInputStream.java,v $
24   * Revision 1.1.1.1  2003/09/22 16:32:07  voytechs
25   * Initial import.
26   *
27   */
28  package com.voytechs.jnetstream.io;
29  
30  import java.lang.*;
31  import java.util.*;
32  import java.io.*;
33  
34  /**
35   * This stream object extends the DataInputStream which defines how
36   * to read basic data types from a binary stream. This stream in addition
37   * to the Java native primitives that DataInput defines, add ability to
38   * read on a variable bit boundry. Any subset of bits can be read and returned
39   * in 'int' data type.
40   */
41  abstract public class ProtocolDataInputStream 
42    extends InputStream {
43  
44    /* Internal attributes */
45    private static final boolean debug = false;
46  
47  
48    /**
49     * Keep the current byte value out of which we are reading various bits.
50     * Only have to keep track of the last byte.
51     */
52    private int cacheByte = 0;
53  
54    /**
55     * This is the bit offset wihin the bytes that we have read so far.
56     * If bitsLeft == 0 then there is no real data in the chachedByte variable
57     * if bitsLeft > 1 and bitOffset < 7  then we have real data in the 
58     * cached byte and should read from upto the remainder of the cache.
59     * It should always have values between 0 and 7;
60     */
61    protected int bitsLeft = 0;
62  
63  
64    /**
65     * Our source DataInputStream since we require to provide similar
66     * interface as it is.
67     */
68    protected DataInputStream in;
69  
70  
71    /**
72     * Initialize with DataInputStream. We will besides the baseclasses
73     * functions to read native data types from the stream we will define
74     * methods for accessing on variouable bit boundries.
75     * @param inputStream Stream to read underlying data from.
76     */
77    public ProtocolDataInputStream(DataInputStream inputStream) {
78      this.in = inputStream;
79    }
80  
81    public ProtocolDataInputStream(InputStream inputStream) {
82      this.in = new DataInputStream(inputStream);
83    }
84  
85    /**
86     * Any normal read() operation invalidates our bit cache since we only
87     * allow reads to happen at the byte boudary.
88     * @return reads the next byte of the stream and returns it as an int.
89     * Invalidates any bit positioning within the stream and aligns the next
90     * bit read at the start of the next byte.
91     *
92     * @exception IOException any exceptions thrown by source input stream
93     */
94    public int read() 
95      throws IOException {
96  
97      if(bitsLeft != 0) {
98        return(readBits(8));
99      }
100 
101     bitsLeft = 0;
102 
103 
104     int b = in.read();
105     if(b == -1)
106       throw new EOFException();
107 
108     return(b);
109   }
110 
111 
112   /**
113    * Read from the stream number of bits and return them as a 'int' data type
114    * while advancing the bit-based position in the stream.
115    *
116    * @param numOfBits Number of bits (0 to 32) to read from the stream 
117    * starting at the current byte and bit position. The maximum number of 
118    * bits that can be read is 32. 0 count of bits will always return 
119    * value 0 and will not advance the position in the stream. 
120    * Less then 0 will generate an IvalidArgumentException.
121    *
122    * @exception InvalidArgumentExcpeption is trown if numOfBits is outside
123    * the 0 to 32 range.
124    * @exception IOException any IOException thrown by source input stream.
125    */
126   public int readBits(int numOfBits) 
127     throws IOException {
128 
129     if(numOfBits == 0)
130       return(0);
131 
132     if(numOfBits > 32)
133       throw 
134         new IndexOutOfBoundsException("0 >= range <= 32bits");
135 
136     int returnValue = 0;;
137 
138     /**
139      * Loop through and copy 1 bit at a time numOfBits amount of bits
140      * into returnValue integer.
141      */
142     while(--numOfBits >= 0) {
143 
144 
145       /**
146        * Check to see if we have any unprocessed bits in the cache.
147        * if not fetch the next byte and set the bitsLeft counter to 8.
148        * 8 is the number of bits in the byte since we just fetched a single 
149        * byte.
150        */
151       if(bitsLeft == 0) // empty cache
152         loadChacheByte();
153 
154       bitsLeft --;
155 
156       /**
157        * Read the bit at the current offset position out of the cache
158        * and advance the pointer but reducing number of bits left.
159        */
160       int bit = cacheByte & (0x1 << bitsLeft);
161       if(bit != 0)
162         returnValue |= 1 << numOfBits ;
163 
164       if(debug)
165         System.out.println("[" + numOfBits 
166                             + ":" + (0x1 << bitsLeft) 
167                             + "=" + bit + "]");
168 
169       /**
170        * Copy the saved bit into our return value at the specified
171        * offset within the new integer.
172        */
173 
174     }
175 
176     return(returnValue);
177   }
178 
179   /**
180    * Read from the stream number of bits and return them as a 'long' data type
181    * while advancing the bit-based position in the stream.
182    *
183    * @param numOfBits Number of bits (0 to 64) to read from the stream 
184    * starting at the current byte and bit position. The maximum number of 
185    * bits that can be read is 64. 0 count of bits will always return 
186    * value 0 and will not advance the position in the stream. 
187    * Less then 0 will generate an IvalidArgumentException.
188    *
189    * @exception InvalidArgumentExcpeption is trown if numOfBits is outside
190    * the 0 to 64 range.
191    * @exception IOException any IOException thrown by source input stream.
192    */
193   public long readBitsLong(int numOfBits) 
194     throws IOException {
195 
196     if(numOfBits == 0)
197       return(0);
198 
199     if(numOfBits > 64)
200       throw 
201         new IndexOutOfBoundsException("0 >= range <= 64bits");
202 
203     long returnValue = 0;;
204 
205     /**
206      * Loop through and copy 1 bit at a time numOfBits amount of bits
207      * into returnValue integer.
208      */
209     while(--numOfBits >= 0) {
210 
211 
212       /**
213        * Check to see if we have any unprocessed bits in the cache.
214        * if not fetch the next byte and set the bitsLeft counter to 8.
215        * 8 is the number of bits in the byte since we just fetched a single 
216        * byte.
217        */
218       if(bitsLeft == 0) // empty cache
219         loadChacheByte();
220 
221       bitsLeft --;
222 
223       /**
224        * Read the bit at the current offset position out of the cache
225        * and advance the pointer but reducing number of bits left.
226        */
227       int bit = cacheByte & (0x1 << bitsLeft);
228       if(bit != 0)
229         bit = 1;
230       else
231         bit = 0;
232 
233       if(debug)
234         System.out.println("[" + numOfBits 
235                             + ":" + (0x1 << bitsLeft) 
236                             + "=" + bit + "]");
237 
238       /**
239        * Copy the saved bit into our return value at the specified
240        * offset within the new integer.
241        */
242       returnValue |= bit << numOfBits ;
243 
244     }
245 
246     return(returnValue);
247   }
248 
249   private void loadChacheByte() 
250     throws IOException {
251 
252     cacheByte = in.read();
253 
254     if(cacheByte == -1)
255       throw new EOFException();
256 
257     bitsLeft = 8;
258   }
259 
260 
261   /*
262    *
263    ******************************************************
264    ********   Redo java.io.DataInputStream Interface ****
265    ******************************************************
266    *
267    */
268 
269   abstract protected boolean isReady(int len) throws EOPacket;
270   abstract protected boolean isReady() throws EOPacket;
271 
272   /**
273    * Read one byte from the stream.
274    */
275   public byte readByte() 
276     throws IOException, EOPacket, EOPacketStream {
277 
278     isReady(1);
279 
280     try {
281       return(in.readByte());
282     }
283     catch(IOException ioe) {
284       reThrow(ioe);
285       throw ioe; // Never reached
286     }
287   }
288 
289   /**
290    * Read one input byte and returns true if that byte is nonzero, 
291    * false if that bye is zero.
292    */
293   public boolean readBoolean() 
294     throws IOException, EOPacket, EOPacketStream {
295 
296     isReady(1);
297 
298     try {
299       return(in.readBoolean());
300     }
301     catch(IOException ioe) {
302       reThrow(ioe);
303       throw ioe; // Never reached
304     }
305   }
306 
307   /**
308    * Reads a 32bit int using Big Endian encoding from stream.
309    */
310   public int readInt() 
311     throws IOException, EOPacket, EOPacketStream {
312 
313     isReady(4);
314 
315     try {
316       return(in.readInt());
317     }
318     catch(IOException ioe) {
319       reThrow(ioe);
320       throw ioe; // Never reached
321     }
322   }
323 
324   /**
325    * Reads a 32bit int using Big Endian encoding from stream.
326    */
327   public int readShort() 
328     throws IOException, EOPacket, EOPacketStream {
329 
330     isReady(2);
331 
332     try {
333       return(in.readShort());
334     }
335     catch(IOException ioe) {
336       reThrow(ioe);
337       throw ioe; // Never reached
338     }
339   }
340 
341   /**
342    * Reads a 32bit unsigned int using Big Endian encoding from stream.
343    */
344   public long readUnsignedInt() 
345     throws IOException, EOPacket, EOPacketStream {
346 
347     isReady(4);
348 
349     try {
350       long returnValue = 0;
351 
352       returnValue = (((long)read()) & 0xFF) << 24;
353       returnValue |= (((long)read()) & 0xFF) << 16;
354       returnValue |= (((long)read()) & 0xFF) << 8;
355       returnValue |= (((long)read()) & 0xFF) << 0;
356 
357       return(returnValue);
358     }
359     catch(IOException ioe) {
360       reThrow(ioe);
361       throw ioe; // Never reached
362     }
363   }
364 
365   /**
366    * Reads a 16bit unsigned int using Big Endian encoding from stream.
367    */
368   public int readUnsignedShort() 
369     throws IOException, EOPacket, EOPacketStream {
370 
371     isReady(2);
372 
373     try {
374       return(in.readUnsignedShort());
375     }
376     catch(IOException ioe) {
377       reThrow(ioe);
378       throw ioe; // Never reached
379     }
380   }
381 
382   /**
383    * Reads a 64bit unsigned int using Big Endian encoding from stream.
384    */
385   public long readLong() 
386     throws IOException, EOPacket, EOPacketStream {
387 
388     isReady(8);
389 
390     try {
391       return(in.readLong());
392     }
393     catch(IOException ioe) {
394       reThrow(ioe);
395       throw ioe; // Never reached
396     }
397   }
398 
399   /**
400    * Reads a 16bit short using Little Endian encoding from stream.
401    */
402   public short readShortLittleEndian() 
403     throws IOException, EOPacket, EOPacketStream {
404 
405     isReady(2);
406 
407     try {
408       short returnValue = 0;
409 
410       returnValue = (short)((read() & 0xFF) << 0);
411       returnValue |= (short)((read() & 0xFF) << 8);
412 
413       return(returnValue);
414     }
415     catch(IOException ioe) {
416       reThrow(ioe);
417       throw ioe; // Never reached
418     }
419   }
420 
421   /**
422    * Reads a 32bit int using Little Endian encoding from stream.
423    */
424   public int readIntLittleEndian() 
425     throws IOException, EOPacket, EOPacketStream {
426 
427     isReady(4);
428 
429     try {
430       int returnValue = 0;
431 
432       returnValue = (read() & 0xFF) << 0;
433       returnValue |= (read() & 0xFF) << 8;
434       returnValue |= (read() & 0xFF) << 16;
435       returnValue |= (read() & 0xFF) << 24;
436 
437       return(returnValue);
438     }
439     catch(IOException ioe) {
440       reThrow(ioe);
441       throw ioe; // Never reached
442     }
443   }
444 
445   /**
446    * Reads a 32bit int using Little Endian encoding from stream.
447    */
448   public long readUnsignedIntLittleEndian() 
449     throws IOException, EOPacket, EOPacketStream {
450 
451     isReady(4);
452 
453     try {
454       long returnValue = 0;
455       int b;
456 
457       returnValue = (((b = read())  < 0)?(long)b + 256:b) << 0;
458       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 8;
459       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 16;
460       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 24;
461 
462       return(returnValue);
463     }
464     catch(IOException ioe) {
465       reThrow(ioe);
466       throw ioe; // Never reached
467     }
468   }
469 
470   /**
471    * Reads a 64bit long int using Little Endian encoding from stream.
472    */
473   public long readLongLittleEndian() 
474     throws IOException, EOPacket, EOPacketStream {
475 
476     isReady(8);
477 
478     try {
479       long returnValue = 0;
480 
481       int b;
482       returnValue = (((b = read())  < 0)?(long)b + 256:b) << 0;
483       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 8;
484       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 16;
485       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 24;
486       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 32;
487       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 48;
488       returnValue |= (((b = read())  < 0)?(long)b + 256:b) << 56;
489 
490       return(returnValue);
491     }
492     catch(IOException ioe) {
493       reThrow(ioe);
494       throw ioe; // Never reached
495     }
496   }
497 
498   /**
499    * Reads a 16bit unsigned short using Little Endian encoding from stream.
500    */
501   public int readUnsignedShortLittleEndian() 
502     throws IOException, EOPacket, EOPacketStream {
503 
504     isReady(2);
505 
506     try {
507       int returnValue = 0;
508 
509       int b;
510       returnValue = (((b = read())  < 0)?(int)b + 256:b) << 0;
511       returnValue |= (((b = read())  < 0)?(int)b + 256:b) << 8;
512 
513 
514       return(returnValue);
515     }
516     catch(IOException ioe) {
517       reThrow(ioe);
518 
519       throw ioe; // Never reached
520     }
521   }
522 
523 
524   /**
525    * Reads a 1 byte from stream but returns it as an int.
526    * This is replaces the normal read() method but implements
527    * ProtocolStream specific exception reporting.
528    */
529   public int readFromPacket() 
530     throws IOException, EOPacket, EOPacketStream {
531 
532     isReady(1);
533 
534     try {
535       return(read());
536     }
537     catch(IOException ioe) {
538       reThrow(ioe);
539 
540       throw ioe; // Never reached
541     }
542   }
543 
544   /**
545    * Reads n bytes from stream but returns it as an int.
546    * This is replaces the normal read() method but implements
547    * ProtocolStream specific exception reporting.
548    */
549   public int readFromPacket(byte [] array) 
550     throws IOException, EOPacket, EOPacketStream {
551 
552     isReady(array.length);
553 
554     try {
555       return(read(array));
556     }
557     catch(IOException ioe) {
558       reThrow(ioe);
559 
560       throw ioe; // Never reached
561     }
562   }
563 
564   /**
565    * Reads a 1 byte from stream but returns it as an int.
566    * This is replaces the normal read() method but implements
567    * ProtocolStream specific exception reporting.
568    */
569   public int readUnsignedByte() 
570     throws IOException, EOPacket, EOPacketStream {
571 
572     return(readFromPacket());
573   }
574 
575 
576 
577 
578   /**
579    * Conveniece method that checks if the stream has thrown
580    * EOFException. If yes then EOPacketStream exception is thrown
581    * instead otherwise the original exception is re-thrown.
582    *
583    * This method always throws an exception. Either original or new
584    * EOPacketStream.
585    *
586    * @param ioe IOException to check if its EOFException.
587    * @exception IOException original exception re-thrown again.
588    * @exception EOPacketStream a replacement exception is thrown which
589    * indicates that end of packet stream has been reached.
590    */
591   protected void reThrow (IOException ioe) 
592     throws IOException, EOPacketStream {
593 
594     if(ioe instanceof EOFException)
595       throw new EOPacketStream();
596     else
597       throw ioe;
598   }
599 
600 
601 
602   /**
603    * Test function for ProtocolDataInputStream
604    * @param args command line arguments
605    */
606   public static void main(String [] args) {
607   }
608 
609 } /* END OF: ProtocolDataInputStream */