Statistics
| Revision:

root / tmp / org.txm.groovy.core / src / groovy / org / txm / macroproto / cqp / LittleEndianOutputStream.groovy @ 822

History | View | Annotate | Download (8.7 kB)

1
/*
2
 * @(#)LittleEndianOutputStream.java  1.0.1 99/05/19
3
 * 
4
 * Copyright 1998, 1999 Elliotte Rusty Harold
5
 *  
6
 */
7

    
8
package org.txm.macroproto.cqp;
9

    
10
/**
11
 * A little endian output stream writes primitive Java numbers 
12
 * and characters to an output stream in a little endian format. 
13
 * The standard java.io.DataOutputStream class which this class
14
 * imitates uses big-endian integers.
15
 *
16
 * @author  Elliotte Rusty Harold
17
 * @version 1.0.1, 19 May 1999
18
 * @see     com.macfaq.io.LittleEndianInputStream
19
 * @see     java.io.DataOutputStream
20
 */
21
public class LittleEndianOutputStream extends FilterOutputStream {
22

    
23
  /**
24
   * The number of bytes written so far to the little endian output stream. 
25
   */
26
  protected int written;
27

    
28
  /**
29
   * Creates a new little endian output stream and chains it to the  
30
   * output stream specified by the out argument. 
31
   *
32
   * @param   out   the underlying output stream.
33
   * @see     java.io.FilterOutputStream#out
34
   */
35
  public LittleEndianOutputStream(OutputStream out) {
36
    super(out);
37
  }
38

    
39
  /**
40
   * Writes the specified byte value to the underlying output stream. 
41
   *
42
   * @param      b   the <code>byte</code> value to be written.
43
   * @exception  IOException  if the underlying stream throws an IOException.
44
   */
45
  public synchronized void write(int b) throws IOException {
46
    out.write(b);
47
    written++;
48
  }
49

    
50
  /**
51
   * Writes <code>length</code> bytes from the specified byte array 
52
   * starting at <code>offset</code> to the underlying output stream.
53
   *
54
   * @param      data     the data.
55
   * @param      offset   the start offset in the data.
56
   * @param      length   the number of bytes to write.
57
   * @exception  IOException  if the underlying stream throws an IOException.
58
   */
59
  public synchronized void write(byte[] data, int offset, int length) 
60
   throws IOException {
61
    out.write(data, offset, length);
62
    written += length;
63
  }
64

    
65

    
66
  /**
67
   * Writes a <code>boolean</code> to the underlying output stream as 
68
   * a single byte. If the argument is true, the byte value 1 is written.
69
   * If the argument is false, the byte value <code>0</code> in written.
70
   *
71
   * @param      b   the <code>boolean</code> value to be written.
72
   * @exception  IOException  if the underlying stream throws an IOException.
73
   */
74
  public void writeBoolean(boolean b) throws IOException {
75
  
76
    if (b) this.write(1);
77
    else this.write(0);
78

    
79
  }
80

    
81
  /**
82
   * Writes out a <code>byte</code> to the underlying output stream
83
   *
84
   * @param      b   the <code>byte</code> value to be written.
85
   * @exception  IOException  if the underlying stream throws an IOException.
86
   */
87
  public void writeByte(int b) throws IOException {
88
    out.write(b);
89
    written++;
90
  }
91

    
92
  /**
93
   * Writes a two byte <code>short</code> to the underlying output stream in
94
   * little endian order, low byte first. 
95
   *
96
   * @param      s   the <code>short</code> to be written.
97
   * @exception  IOException  if the underlying stream throws an IOException.
98
   */
99
  public void writeShort(int s) throws IOException {
100

    
101
    out.write(s & 0xFF);
102
    out.write((s >>> 8) & 0xFF);
103
    written += 2;
104
    
105
  }
106

    
107
  /**
108
   * Writes a two byte <code>char</code> to the underlying output stream 
109
   * in little endian order, low byte first. 
110
   *
111
   * @param      c   the <code>char</code> value to be written.
112
   * @exception  IOException  if the underlying stream throws an IOException.
113
   */
114
  public void writeChar(int c) throws IOException {
115

    
116
    out.write(c & 0xFF);
117
    out.write((c >>> 8) & 0xFF);
118
    written += 2;
119
    
120
  }
121

    
122
  /**
123
   * Writes a four-byte <code>int</code> to the underlying output stream 
124
   * in little endian order, low byte first, high byte last
125
   *
126
   * @param      i   the <code>int</code> to be written.
127
   * @exception  IOException  if the underlying stream throws an IOException.
128
   */
129
  public void writeInt(int i) throws IOException {
130

    
131
    out.write(i & 0xFF);
132
    out.write((i >>> 8) & 0xFF);
133
    out.write((i >>> 16) & 0xFF);
134
    out.write((i >>> 24) & 0xFF);
135
    written += 4;
136
    
137
  }
138

    
139
  /**
140
   * Writes an eight-byte <code>long</code> to the underlying output stream 
141
   * in little endian order, low byte first, high byte last
142
   *
143
   * @param      l   the <code>long</code> to be written.
144
   * @exception  IOException  if the underlying stream throws an IOException.
145
   */
146
  public void writeLong(long l) throws IOException {
147

    
148
    out.write((int) l & 0xFF);
149
    out.write((int) (l >>> 8) & 0xFF);
150
    out.write((int) (l >>> 16) & 0xFF);
151
    out.write((int) (l >>> 24) & 0xFF);
152
    out.write((int) (l >>> 32) & 0xFF);
153
    out.write((int) (l >>> 40) & 0xFF);
154
    out.write((int) (l >>> 48) & 0xFF);
155
    out.write((int) (l >>> 56) & 0xFF);
156
    written += 8;
157

    
158
  }
159

    
160
 /**
161
  * Writes a 4 byte Java float to the underlying output stream in
162
  * little endian order.
163
  *
164
  * @param      f   the <code>float</code> value to be written.
165
  * @exception  IOException  if an I/O error occurs.
166
  */
167
  public final void writeFloat(float f) throws IOException {
168
  
169
    this.writeInt(Float.floatToIntBits(f));
170
    
171
  }
172

    
173
 /**
174
  * Writes an 8 byte Java double to the underlying output stream in
175
  * little endian order.
176
  *
177
  * @param      d   the <code>double</code> value to be written.
178
  * @exception  IOException  if an I/O error occurs.
179
  */
180
  public final void writeDouble(double d) throws IOException {
181
  
182
    this.writeLong(Double.doubleToLongBits(d));
183
    
184
  }
185

    
186
  /**
187
   * Writes a string to the underlying output stream as a sequence of 
188
   * bytes. Each character is written to the data output stream as 
189
   * if by the <code>writeByte()</code> method. 
190
   *
191
   * @param      s   the <code>String</code> value to be written.
192
   * @exception  IOException  if the underlying stream throws an IOException.
193
   * @see        java.io.LittleEndianOutputStream#writeByte(int)
194
   * @see        java.io.LittleEndianOutputStream#out
195
   */
196
  public void writeBytes(String s) throws IOException {
197

    
198
    int length = s.length();
199
    for (int i = 0; i < length; i++) {
200
      out.write((byte) s.charAt(i));
201
    }
202
    written += length;
203
    }
204

    
205
  /**
206
   * Writes a string to the underlying output stream as a sequence of 
207
   * characters. Each character is written to the data output stream as 
208
   * if by the <code>writeChar</code> method. 
209
   *
210
   * @param      s   a <code>String</code> value to be written.
211
   * @exception  IOException  if the underlying stream throws an IOException.
212
   * @see        java.io.LittleEndianOutputStream#writeChar(int)
213
   * @see        java.io.LittleEndianOutputStream#out
214
   */
215
  public void writeChars(String s) throws IOException {
216

    
217
    int length = s.length();
218
    for (int i = 0; i < length; i++) {
219
      int c = s.charAt(i);
220
      out.write(c & 0xFF);
221
      out.write((c >>> 8) & 0xFF);
222
    }
223
    written += length * 2;
224
    
225
  }
226

    
227
  /**
228
   * Writes a string of no more than 65,535 characters 
229
   * to the underlying output stream using UTF-8 
230
   * encoding. This method first writes a two byte short 
231
   * in <b>big</b> endian order as required by the 
232
   * UTF-8 specification. This gives the number of bytes in the 
233
   * UTF-8 encoded version of the string, not the number of characters
234
   * in the string. Next each character of the string is written
235
   * using the UTF-8 encoding for the character.
236
   *
237
   * @param      s   the string to be written.
238
   * @exception  UTFDataFormatException if the string is longer than 
239
   *             65,535 characters.
240
   * @exception  IOException  if the underlying stream throws an IOException.
241
   */
242
  public void writeUTF(String s) throws IOException {
243

    
244
    int numchars = s.length();
245
    int numbytes = 0;
246

    
247
    for (int i = 0 ; i < numchars ; i++) {
248
      int c = s.charAt(i);
249
      if ((c >= 0x0001) && (c <= 0x007F)) numbytes++;
250
      else if (c > 0x07FF) numbytes += 3;
251
      else numbytes += 2;
252
    }
253

    
254
    if (numbytes > 65535) throw new UTFDataFormatException();     
255

    
256
    out.write((numbytes >>> 8) & 0xFF);
257
    out.write(numbytes & 0xFF);
258
    for (int i = 0 ; i < numchars ; i++) {
259
      int c = s.charAt(i);
260
      if ((c >= 0x0001) && (c <= 0x007F)) {
261
        out.write(c);
262
      }
263
      else if (c > 0x07FF) {
264
        out.write(0xE0 | ((c >> 12) & 0x0F));
265
        out.write(0x80 | ((c >>  6) & 0x3F));
266
        out.write(0x80 | (c & 0x3F));
267
        written += 2;
268
      } 
269
      else {
270
        out.write(0xC0 | ((c >>  6) & 0x1F));
271
        out.write(0x80 | (c & 0x3F));
272
        written += 1;
273
      }
274
    }
275
    
276
    written += numchars + 2;
277
    
278
  }
279

    
280
  /**
281
   * Returns the number of bytes written to this little endian output stream.
282
   * (This class is not thread-safe with respect to this method. It is 
283
   * possible that this number is temporarily less than the actual 
284
   * number of bytes written.)
285
   * @return  the value of the <code>written</code> field.
286
   * @see     java.io.LittleEndianOutputStream#written
287
   */
288
  public int size() {
289
    return this.written;
290
  }
291
  
292
}