KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javolution > io > Utf8ByteBufferWriter


1 /*
2  * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
3  * Copyright (C) 2005 - Javolution (http://javolution.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package javolution.io;
10
11 import j2me.lang.CharSequence;
12 import j2me.lang.IllegalStateException;
13 import j2me.io.CharConversionException;
14 import j2me.nio.ByteBuffer;
15
16 import java.io.IOException;
17 import java.io.Writer;
18
19 import javolution.lang.Reusable;
20
21 /**
22  * <p> This class represents a UTF-8 <code>j2me.nio.ByteBuffer</code>
23  * writer.</p>
24  *
25  * <p> This writer supports surrogate <code>char</code> pairs (representing
26  * characters in the range [U+10000 .. U+10FFFF]). It can also be used
27  * to write characters from their unicodes (31 bits) directly
28  * (ref. {@link #write(int)}).</p>
29  *
30  * <p> Instances of this class can be reused for different output streams
31  * and can be part of a higher level component (e.g. serializer) in order
32  * to avoid dynamic buffer allocation when the destination output changes.
33  * Also wrapping using a <code>java.io.BufferedWriter</code> is unnescessary
34  * as instances of this class embed their own data buffers.</p>
35  *
36  * <p> Note: This writer is unsynchronized and always produces well-formed
37  * UTF-8 sequences.</p>
38  *
39  * @author <a HREF="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
40  * @version 2.0, December 9, 2004
41  * @see Utf8ByteBufferReader
42  */

43 public final class Utf8ByteBufferWriter extends Writer implements Reusable {
44
45     /**
46      * Holds the byte buffer destination.
47      */

48     private ByteBuffer _byteBuffer;
49
50     /**
51      * Default constructor.
52      */

53     public Utf8ByteBufferWriter() {
54     }
55
56     /**
57      * Sets the byte buffer to use for writing until this writer is closed.
58      *
59      * @param byteBuffer the destination byte buffer.
60      * @return this UTF-8 writer.
61      * @throws IllegalStateException if this writer is being reused and
62      * it has not been {@link #close closed} or {@link #reset reset}.
63      */

64     public Utf8ByteBufferWriter setByteBuffer(ByteBuffer byteBuffer) {
65         if (_byteBuffer != null)
66             throw new IllegalStateException("Writer not closed or reset");
67         _byteBuffer = byteBuffer;
68         return this;
69     }
70
71     /**
72      * Writes a single character. This method supports 16-bits
73      * character surrogates.
74      *
75      * @param c <code>char</code> the character to be written (possibly
76      * a surrogate).
77      * @throws IOException if an I/O error occurs.
78      */

79     public void write(char c) throws IOException {
80         if ((c < 0xd800) || (c > 0xdfff)) {
81             write((int) c);
82         } else if (c < 0xdc00) { // High surrogate.
83
_highSurrogate = c;
84         } else { // Low surrogate.
85
int code = ((_highSurrogate - 0xd800) << 10) + (c - 0xdc00)
86                     + 0x10000;
87             write(code);
88         }
89     }
90
91     private char _highSurrogate;
92
93     /**
94      * Writes a character given its 31-bits Unicode.
95      *
96      * @param code the 31 bits Unicode of the character to be written.
97      * @throws IOException if an I/O error occurs.
98      */

99     public void write(int code) throws IOException {
100         if ((code & 0xffffff80) == 0) {
101             _byteBuffer.put((byte) code);
102         } else { // Writes more than one byte.
103
write2(code);
104         }
105     }
106
107     private void write2(int c) throws IOException {
108         if ((c & 0xfffff800) == 0) { // 2 bytes.
109
_byteBuffer.put((byte) (0xc0 | (c >> 6)));
110             _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
111         } else if ((c & 0xffff0000) == 0) { // 3 bytes.
112
_byteBuffer.put((byte) (0xe0 | (c >> 12)));
113             _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
114             _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
115         } else if ((c & 0xff200000) == 0) { // 4 bytes.
116
_byteBuffer.put((byte) (0xf0 | (c >> 18)));
117             _byteBuffer.put((byte) (0x80 | ((c >> 12) & 0x3f)));
118             _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
119             _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
120         } else if ((c & 0xf4000000) == 0) { // 5 bytes.
121
_byteBuffer.put((byte) (0xf8 | (c >> 24)));
122             _byteBuffer.put((byte) (0x80 | ((c >> 18) & 0x3f)));
123             _byteBuffer.put((byte) (0x80 | ((c >> 12) & 0x3f)));
124             _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3f)));
125             _byteBuffer.put((byte) (0x80 | (c & 0x3f)));
126         } else if ((c & 0x80000000) == 0) { // 6 bytes.
127
_byteBuffer.put((byte) (0xfc | (c >> 30)));
128             _byteBuffer.put((byte) (0x80 | ((c >> 24) & 0x3f)));
129             _byteBuffer.put((byte) (0x80 | ((c >> 18) & 0x3f)));
130             _byteBuffer.put((byte) (0x80 | ((c >> 12) & 0x3F)));
131             _byteBuffer.put((byte) (0x80 | ((c >> 6) & 0x3F)));
132             _byteBuffer.put((byte) (0x80 | (c & 0x3F)));
133         } else {
134             throw new CharConversionException("Illegal character U+"
135                     + Integer.toHexString(c));
136         }
137     }
138
139     /**
140      * Writes a portion of an array of characters.
141      *
142      * @param cbuf the array of characters.
143      * @param off the offset from which to start writing characters.
144      * @param len the number of characters to write.
145      * @throws IOException if an I/O error occurs.
146      */

147     public void write(char cbuf[], int off, int len) throws IOException {
148         final int off_plus_len = off + len;
149         for (int i = off; i < off_plus_len;) {
150             char c = cbuf[i++];
151             if (c < 0x80) {
152                 _byteBuffer.put((byte) c);
153             } else {
154                 write(c);
155             }
156         }
157     }
158
159     /**
160      * Writes a portion of a string.
161      *
162      * @param str a String.
163      * @param off the offset from which to start writing characters.
164      * @param len the number of characters to write.
165      * @throws IOException if an I/O error occurs
166      */

167     public void write(String str, int off, int len) throws IOException {
168         final int off_plus_len = off + len;
169         for (int i = off; i < off_plus_len;) {
170             char c = str.charAt(i++);
171             if (c < 0x80) {
172                 _byteBuffer.put((byte) c);
173             } else {
174                 write(c);
175             }
176         }
177     }
178
179     /**
180      * Writes the specified character sequence.
181      *
182      * @param csq the character sequence.
183      * @throws IOException if an I/O error occurs
184      */

185     public void write(CharSequence csq) throws IOException {
186         final int length = csq.length();
187         for (int i = 0; i < length;) {
188             char c = csq.charAt(i++);
189             if (c < 0x80) {
190                 _byteBuffer.put((byte) c);
191             } else {
192                 write(c);
193             }
194         }
195     }
196
197     /**
198      * Flushes the stream (this method has no effect, the data is
199      * always directly written to the <code>ByteBuffer</code>).
200      *
201      * @throws IOException if an I/O error occurs.
202      */

203     public void flush() throws IOException {
204         if (_byteBuffer == null) {
205             throw new IOException("Writer closed");
206         }
207     }
208
209     /**
210      * Closes and {@link #reset resets} this writer for reuse.
211      *
212      * @throws IOException if an I/O error occurs
213      */

214     public void close() throws IOException {
215         if (_byteBuffer != null) {
216             reset();
217         }
218     }
219
220     // Implements Reusable.
221
public void reset() {
222         _byteBuffer = null;
223         _highSurrogate = 0;
224     }
225
226 }
Popular Tags