History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/misc/CharacterEncoder.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/misc/CharacterEncoder.java+354−0
@@ -0,0 +1,354 @@
1+/*
2+ * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.misc;
27+
28+import java.io.InputStream;
29+import java.io.ByteArrayInputStream;
30+import java.io.OutputStream;
31+import java.io.ByteArrayOutputStream;
32+import java.io.PrintStream;
33+import java.io.IOException;
34+import java.nio.ByteBuffer;
35+
36+
37+/**
38+ * This class defines the encoding half of character encoders.
39+ * A character encoder is an algorithim for transforming 8 bit binary
40+ * data into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text)
41+ * for transmition over text channels such as e-mail and network news.
42+ *
43+ * The character encoders have been structured around a central theme
44+ * that, in general, the encoded text has the form:
45+ *
46+ * <pre>
47+ * [Buffer Prefix]
48+ * [Line Prefix][encoded data atoms][Line Suffix]
49+ * [Buffer Suffix]
50+ * </pre>
51+ *
52+ * In the CharacterEncoder and CharacterDecoder classes, one complete
53+ * chunk of data is referred to as a <i>buffer</i>. Encoded buffers
54+ * are all text, and decoded buffers (sometimes just referred to as
55+ * buffers) are binary octets.
56+ *
57+ * To create a custom encoder, you must, at a minimum, overide three
58+ * abstract methods in this class.
59+ * <DL>
60+ * <DD>bytesPerAtom which tells the encoder how many bytes to
61+ * send to encodeAtom
62+ * <DD>encodeAtom which encodes the bytes sent to it as text.
63+ * <DD>bytesPerLine which tells the encoder the maximum number of
64+ * bytes per line.
65+ * </DL>
66+ *
67+ * Several useful encoders have already been written and are
68+ * referenced in the See Also list below.
69+ *
70+ * @author Chuck McManis
71+ * @see CharacterDecoder;
72+ * @see UCEncoder
73+ * @see UUEncoder
74+ * @see BASE64Encoder
75+ */
76+public abstract class CharacterEncoder {
77+
78+ /** Stream that understands "printing" */
79+ protected PrintStream pStream;
80+
81+ /** Return the number of bytes per atom of encoding */
82+ abstract protected int bytesPerAtom();
83+
84+ /** Return the number of bytes that can be encoded per line */
85+ abstract protected int bytesPerLine();
86+
87+ /**
88+ * Encode the prefix for the entire buffer. By default is simply
89+ * opens the PrintStream for use by the other functions.
90+ */
91+ protected void encodeBufferPrefix(OutputStream aStream) throws IOException {
92+ pStream = new PrintStream(aStream);
93+ }
94+
95+ /**
96+ * Encode the suffix for the entire buffer.
97+ */
98+ protected void encodeBufferSuffix(OutputStream aStream) throws IOException {
99+ }
100+
101+ /**
102+ * Encode the prefix that starts every output line.
103+ */
104+ protected void encodeLinePrefix(OutputStream aStream, int aLength)
105+ throws IOException {
106+ }
107+
108+ /**
109+ * Encode the suffix that ends every output line. By default
110+ * this method just prints a <newline> into the output stream.
111+ */
112+ protected void encodeLineSuffix(OutputStream aStream) throws IOException {
113+ pStream.println();
114+ }
115+
116+ /** Encode one "atom" of information into characters. */
117+ abstract protected void encodeAtom(OutputStream aStream, byte someBytes[],
118+ int anOffset, int aLength) throws IOException;
119+
120+ /**
121+ * This method works around the bizarre semantics of BufferedInputStream's
122+ * read method.
123+ */
124+ protected int readFully(InputStream in, byte buffer[])
125+ throws java.io.IOException {
126+ for (int i = 0; i < buffer.length; i++) {
127+ int q = in.read();
128+ if (q == -1)
129+ return i;
130+ buffer[i] = (byte)q;
131+ }
132+ return buffer.length;
133+ }
134+
135+ /**
136+ * Encode bytes from the input stream, and write them as text characters
137+ * to the output stream. This method will run until it exhausts the
138+ * input stream, but does not print the line suffix for a final
139+ * line that is shorter than bytesPerLine().
140+ */
141+ public void encode(InputStream inStream, OutputStream outStream)
142+ throws IOException {
143+ int j;
144+ int numBytes;
145+ byte tmpbuffer[] = new byte[bytesPerLine()];
146+
147+ encodeBufferPrefix(outStream);
148+
149+ while (true) {
150+ numBytes = readFully(inStream, tmpbuffer);
151+ if (numBytes == 0) {
152+ break;
153+ }
154+ encodeLinePrefix(outStream, numBytes);
155+ for (j = 0; j < numBytes; j += bytesPerAtom()) {
156+
157+ if ((j + bytesPerAtom()) <= numBytes) {
158+ encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
159+ } else {
160+ encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
161+ }
162+ }
163+ if (numBytes < bytesPerLine()) {
164+ break;
165+ } else {
166+ encodeLineSuffix(outStream);
167+ }
168+ }
169+ encodeBufferSuffix(outStream);
170+ }
171+
172+ /**
173+ * Encode the buffer in <i>aBuffer</i> and write the encoded
174+ * result to the OutputStream <i>aStream</i>.
175+ */
176+ public void encode(byte aBuffer[], OutputStream aStream)
177+ throws IOException {
178+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
179+ encode(inStream, aStream);
180+ }
181+
182+ /**
183+ * A 'streamless' version of encode that simply takes a buffer of
184+ * bytes and returns a string containing the encoded buffer.
185+ */
186+ public String encode(byte aBuffer[]) {
187+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
188+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
189+ String retVal = null;
190+ try {
191+ encode(inStream, outStream);
192+ // explicit ascii->unicode conversion
193+ retVal = outStream.toString("8859_1");
194+ } catch (Exception IOException) {
195+ // This should never happen.
196+ throw new Error("CharacterEncoder.encode internal error");
197+ }
198+ return (retVal);
199+ }
200+
201+ /**
202+ * Return a byte array from the remaining bytes in this ByteBuffer.
203+ * <P>
204+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
205+ * <P>
206+ * To avoid an extra copy, the implementation will attempt to return the
207+ * byte array backing the ByteBuffer. If this is not possible, a
208+ * new byte array will be created.
209+ */
210+ private byte [] getBytes(ByteBuffer bb) {
211+ /*
212+ * This should never return a BufferOverflowException, as we're
213+ * careful to allocate just the right amount.
214+ */
215+ byte [] buf = null;
216+
217+ /*
218+ * If it has a usable backing byte buffer, use it. Use only
219+ * if the array exactly represents the current ByteBuffer.
220+ */
221+ if (bb.hasArray()) {
222+ byte [] tmp = bb.array();
223+ if ((tmp.length == bb.capacity()) &&
224+ (tmp.length == bb.remaining())) {
225+ buf = tmp;
226+ bb.position(bb.limit());
227+ }
228+ }
229+
230+ if (buf == null) {
231+ /*
232+ * This class doesn't have a concept of encode(buf, len, off),
233+ * so if we have a partial buffer, we must reallocate
234+ * space.
235+ */
236+ buf = new byte[bb.remaining()];
237+
238+ /*
239+ * position() automatically updated
240+ */
241+ bb.get(buf);
242+ }
243+
244+ return buf;
245+ }
246+
247+ /**
248+ * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
249+ * result to the OutputStream <i>aStream</i>.
250+ * <P>
251+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
252+ */
253+ public void encode(ByteBuffer aBuffer, OutputStream aStream)
254+ throws IOException {
255+ byte [] buf = getBytes(aBuffer);
256+ encode(buf, aStream);
257+ }
258+
259+ /**
260+ * A 'streamless' version of encode that simply takes a ByteBuffer
261+ * and returns a string containing the encoded buffer.
262+ * <P>
263+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
264+ */
265+ public String encode(ByteBuffer aBuffer) {
266+ byte [] buf = getBytes(aBuffer);
267+ return encode(buf);
268+ }
269+
270+ /**
271+ * Encode bytes from the input stream, and write them as text characters
272+ * to the output stream. This method will run until it exhausts the
273+ * input stream. It differs from encode in that it will add the
274+ * line at the end of a final line that is shorter than bytesPerLine().
275+ */
276+ public void encodeBuffer(InputStream inStream, OutputStream outStream)
277+ throws IOException {
278+ int j;
279+ int numBytes;
280+ byte tmpbuffer[] = new byte[bytesPerLine()];
281+
282+ encodeBufferPrefix(outStream);
283+
284+ while (true) {
285+ numBytes = readFully(inStream, tmpbuffer);
286+ if (numBytes == 0) {
287+ break;
288+ }
289+ encodeLinePrefix(outStream, numBytes);
290+ for (j = 0; j < numBytes; j += bytesPerAtom()) {
291+ if ((j + bytesPerAtom()) <= numBytes) {
292+ encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
293+ } else {
294+ encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
295+ }
296+ }
297+ encodeLineSuffix(outStream);
298+ if (numBytes < bytesPerLine()) {
299+ break;
300+ }
301+ }
302+ encodeBufferSuffix(outStream);
303+ }
304+
305+ /**
306+ * Encode the buffer in <i>aBuffer</i> and write the encoded
307+ * result to the OutputStream <i>aStream</i>.
308+ */
309+ public void encodeBuffer(byte aBuffer[], OutputStream aStream)
310+ throws IOException {
311+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
312+ encodeBuffer(inStream, aStream);
313+ }
314+
315+ /**
316+ * A 'streamless' version of encode that simply takes a buffer of
317+ * bytes and returns a string containing the encoded buffer.
318+ */
319+ public String encodeBuffer(byte aBuffer[]) {
320+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
321+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
322+ try {
323+ encodeBuffer(inStream, outStream);
324+ } catch (Exception IOException) {
325+ // This should never happen.
326+ throw new Error("CharacterEncoder.encodeBuffer internal error");
327+ }
328+ return (outStream.toString());
329+ }
330+
331+ /**
332+ * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
333+ * result to the OutputStream <i>aStream</i>.
334+ * <P>
335+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
336+ */
337+ public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
338+ throws IOException {
339+ byte [] buf = getBytes(aBuffer);
340+ encodeBuffer(buf, aStream);
341+ }
342+
343+ /**
344+ * A 'streamless' version of encode that simply takes a ByteBuffer
345+ * and returns a string containing the encoded buffer.
346+ * <P>
347+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
348+ */
349+ public String encodeBuffer(ByteBuffer aBuffer) {
350+ byte [] buf = getBytes(aBuffer);
351+ return encodeBuffer(buf);
352+ }
353+
354+}