38 |
package gnu.java.nio.charset; |
package gnu.java.nio.charset; |
39 |
|
|
40 |
import java.nio.ByteBuffer; |
import java.nio.ByteBuffer; |
41 |
|
import java.nio.ByteOrder; |
42 |
import java.nio.CharBuffer; |
import java.nio.CharBuffer; |
43 |
import java.nio.charset.Charset; |
import java.nio.charset.Charset; |
44 |
import java.nio.charset.CharsetEncoder; |
import java.nio.charset.CharsetEncoder; |
55 |
static final int BIG_ENDIAN = 0; |
static final int BIG_ENDIAN = 0; |
56 |
static final int LITTLE_ENDIAN = 1; |
static final int LITTLE_ENDIAN = 1; |
57 |
|
|
58 |
private static final char BYTE_ORDER_MARK = '\uFEFF'; |
private static final char BYTE_ORDER_MARK = 0xFEFF; |
59 |
|
|
60 |
private final int byteOrder; |
private final ByteOrder byteOrder; |
61 |
private final boolean useByteOrderMark; |
private final boolean useByteOrderMark; |
62 |
private boolean needsByteOrderMark; |
private boolean needsByteOrderMark; |
63 |
|
|
64 |
UTF_16Encoder (Charset cs, int byteOrder, boolean useByteOrderMark) |
UTF_16Encoder (Charset cs, int byteOrder, boolean useByteOrderMark) |
65 |
{ |
{ |
66 |
super (cs, 2.0f, |
super (cs, 2.0f, |
67 |
useByteOrderMark ? 2.0f : 4.0f, |
useByteOrderMark ? 4.0f : 2.0f, |
68 |
byteOrder == BIG_ENDIAN |
byteOrder == BIG_ENDIAN |
69 |
? new byte[] { (byte) 0xFF, (byte) 0xFD } |
? new byte[] { (byte) 0xFF, (byte) 0xFD } |
70 |
: new byte[] { (byte) 0xFD, (byte) 0xFF }); |
: new byte[] { (byte) 0xFD, (byte) 0xFF }); |
71 |
this.byteOrder = byteOrder; |
this.byteOrder = (byteOrder == BIG_ENDIAN) ? |
72 |
|
ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; |
73 |
this.useByteOrderMark = useByteOrderMark; |
this.useByteOrderMark = useByteOrderMark; |
74 |
this.needsByteOrderMark = useByteOrderMark; |
this.needsByteOrderMark = useByteOrderMark; |
75 |
} |
} |
78 |
{ |
{ |
79 |
// TODO: Optimize this in the case in.hasArray() / out.hasArray() |
// TODO: Optimize this in the case in.hasArray() / out.hasArray() |
80 |
|
|
81 |
|
ByteOrder originalBO = out.order(); |
82 |
|
out.order(byteOrder); |
83 |
|
|
84 |
if (needsByteOrderMark) |
if (needsByteOrderMark) |
85 |
{ |
{ |
86 |
if (out.remaining () < 2) |
if (out.remaining () < 2) |
87 |
return CoderResult.OVERFLOW; |
{ |
88 |
put (out, BYTE_ORDER_MARK); |
out.order(originalBO); |
89 |
|
return CoderResult.OVERFLOW; |
90 |
|
} |
91 |
|
out.putChar (BYTE_ORDER_MARK); |
92 |
needsByteOrderMark = false; |
needsByteOrderMark = false; |
93 |
} |
} |
94 |
|
|
98 |
while (in.hasRemaining ()) |
while (in.hasRemaining ()) |
99 |
{ |
{ |
100 |
char c = in.get (); |
char c = in.get (); |
|
|
|
101 |
if (0xD800 <= c && c <= 0xDFFF) |
if (0xD800 <= c && c <= 0xDFFF) |
102 |
{ |
{ |
103 |
// c is a surrogate |
// c is a surrogate |
111 |
// make sure d is a low surrogate |
// make sure d is a low surrogate |
112 |
if (d < 0xDC00 || d > 0xDFFF) |
if (d < 0xDC00 || d > 0xDFFF) |
113 |
return CoderResult.malformedForLength (1); |
return CoderResult.malformedForLength (1); |
114 |
put (out, c); |
out.putChar (c); |
115 |
put (out, d); |
out.putChar (d); |
116 |
inPos += 2; |
inPos += 2; |
117 |
} |
} |
118 |
else |
else |
119 |
{ |
{ |
120 |
|
out.order(originalBO); |
121 |
if (out.remaining () < 2) |
if (out.remaining () < 2) |
122 |
return CoderResult.OVERFLOW; |
return CoderResult.OVERFLOW; |
123 |
put (out, c); |
out.putChar (c); |
124 |
inPos++; |
inPos++; |
125 |
} |
} |
126 |
} |
} |
127 |
|
out.order(originalBO); |
128 |
return CoderResult.UNDERFLOW; |
return CoderResult.UNDERFLOW; |
129 |
} |
} |
130 |
finally |
finally |
133 |
} |
} |
134 |
} |
} |
135 |
|
|
|
/** |
|
|
* Writes <code>c</code> to <code>out</code> in the byte order |
|
|
* specified by <code>byteOrder</code>. |
|
|
**/ |
|
|
private void put (ByteBuffer out, char c) |
|
|
{ |
|
|
if (byteOrder == BIG_ENDIAN) |
|
|
{ |
|
|
out.put ((byte) (c >> 8)); |
|
|
out.put ((byte) (c & 0xFF)); |
|
|
} |
|
|
else |
|
|
{ |
|
|
out.put ((byte) (c & 0xFF)); |
|
|
out.put ((byte) (c >> 8)); |
|
|
} |
|
|
} |
|
|
|
|
136 |
protected void implReset () |
protected void implReset () |
137 |
{ |
{ |
138 |
needsByteOrderMark = useByteOrderMark; |
needsByteOrderMark = useByteOrderMark; |