Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/misc/CharacterEncoder.java
38829 views
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
}
355
356