001: /**
002: *******************************************************************************
003: * Copyright (C) 2006, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: *
007: *******************************************************************************
008: */package com.ibm.icu.charset;
009:
010: import java.nio.ByteBuffer;
011: import java.nio.CharBuffer;
012: import java.nio.IntBuffer;
013: import java.nio.charset.CharsetDecoder;
014: import java.nio.charset.CharsetEncoder;
015: import java.nio.charset.CoderResult;
016:
017: import com.ibm.icu.lang.UCharacter;
018: import com.ibm.icu.text.UTF16;
019:
020: class CharsetASCII extends CharsetICU {
021: protected byte[] fromUSubstitution = new byte[] { (byte) 0x1a };
022:
023: public CharsetASCII(String icuCanonicalName,
024: String javaCanonicalName, String[] aliases) {
025: super (icuCanonicalName, javaCanonicalName, aliases);
026: maxBytesPerChar = 1;
027: minBytesPerChar = 1;
028: maxCharsPerByte = 1;
029: }
030:
031: class CharsetDecoderASCII extends CharsetDecoderICU {
032:
033: public CharsetDecoderASCII(CharsetICU cs) {
034: super (cs);
035: }
036:
037: protected CoderResult decodeLoop(ByteBuffer source,
038: CharBuffer target, IntBuffer offsets, boolean flush) {
039: CoderResult cr = CoderResult.UNDERFLOW;
040: if (!source.hasRemaining() && toUnicodeStatus == 0) {
041: /* no input, nothing to do */
042: return cr;
043: }
044: if (!target.hasRemaining()) {
045: return CoderResult.OVERFLOW;
046: }
047:
048: int sourceArrayIndex = source.position(), count = 0;
049: int sourceIndex = 0;
050: char c = 0;
051: int oldTarget = target.position();
052:
053: /* conversion loop */
054: c = 0;
055: while (sourceArrayIndex < source.limit()
056: && (c = (char) source.get(sourceArrayIndex)) <= 0x7f
057: && target.hasRemaining()) {
058: target.put(c);
059: sourceArrayIndex++;
060: }
061:
062: if (c > 0x7f) {
063: /* callback(illegal); copy the current bytes to toUBytes[] */
064: toUBytesArray[0] = (byte) c;
065: toULength = 1;
066: cr = CoderResult.malformedForLength(toULength);
067: } else if (sourceArrayIndex < source.limit()
068: && !target.hasRemaining()) {
069: /* target is full */
070: cr = CoderResult.OVERFLOW;
071: }
072:
073: /* set offsets since the start */
074: if (offsets != null) {
075: count = target.position() - oldTarget;
076: while (count > 0) {
077: offsets.put(sourceIndex++);
078: --count;
079: }
080: }
081: source.position(sourceArrayIndex);
082: return cr;
083: }
084:
085: }
086:
087: class CharsetEncoderASCII extends CharsetEncoderICU {
088:
089: public CharsetEncoderASCII(CharsetICU cs) {
090: super (cs, fromUSubstitution);
091: implReset();
092: }
093:
094: private final static int NEED_TO_WRITE_BOM = 1;
095:
096: protected void implReset() {
097: super .implReset();
098: fromUnicodeStatus = NEED_TO_WRITE_BOM;
099: }
100:
101: protected CoderResult encodeLoop(CharBuffer source,
102: ByteBuffer target, IntBuffer offsets, boolean flush) {
103: CoderResult cr = CoderResult.UNDERFLOW;
104: if (!source.hasRemaining()) {
105: /* no input, nothing to do */
106: return cr;
107: }
108:
109: if (!target.hasRemaining()) {
110: return CoderResult.OVERFLOW;
111: }
112:
113: int sourceArrayIndex = source.position(), count = 0;
114: int sourceIndex = 0;
115: int ch = 0;
116: int oldTarget = target.position();
117: boolean doloop = true;
118:
119: if (fromUChar32 != 0 && target.hasRemaining()) {
120: ch = fromUChar32;
121: fromUChar32 = 0;
122:
123: if (sourceArrayIndex < source.limit()) {
124: /* test the following code unit */
125: char trail = source.get(sourceArrayIndex);
126: if (UTF16.isTrailSurrogate(trail)) {
127: ++sourceArrayIndex;
128: ch = UCharacter.getCodePoint((char) ch, trail);
129: /* convert this supplementary code point */
130: /* callback(unassigned) */
131: cr = CoderResult
132: .unmappableForLength(sourceArrayIndex);
133: doloop = false;
134: } else {
135: /* this is an unmatched lead code unit (1st surrogate) */
136: /* callback(illegal) */
137: fromUChar32 = (int) ch;
138: cr = CoderResult
139: .malformedForLength(sourceArrayIndex);
140: doloop = false;
141: }
142: } else {
143: /* no more input */
144: fromUChar32 = (int) ch;
145: doloop = false;
146: }
147: }
148: if (doloop) {
149: /* conversion loop */
150: ch = 0;
151: int ch2 = 0;
152: while (sourceArrayIndex < source.limit()) {
153: ch = source.get(sourceArrayIndex++);
154: if (ch <= 0xff) {
155: if (target.hasRemaining()) {
156: target.put((byte) ch);
157: } else {
158: cr = CoderResult.OVERFLOW;
159: break;
160: }
161: } else {
162: if (UTF16.isSurrogate((char) ch)) {
163: if (UTF16.isLeadSurrogate((char) ch)) {
164: //lowsurogate:
165: if (sourceArrayIndex < source.limit()) {
166: ch2 = source.get(sourceArrayIndex);
167: if (UTF16
168: .isTrailSurrogate((char) ch2)) {
169: ch = ((ch - UConverterSharedData.SURROGATE_HIGH_START) << UConverterSharedData.HALF_SHIFT)
170: + ch2
171: + UConverterSharedData.SURROGATE_LOW_BASE;
172: sourceArrayIndex++;
173: } else {
174: /* this is an unmatched trail code unit (2nd surrogate) */
175: /* callback(illegal) */
176: fromUChar32 = ch;
177: cr = CoderResult.OVERFLOW;
178: break;
179: }
180: } else {
181: /* ran out of source */
182: fromUChar32 = ch;
183: if (flush) {
184: /* this is an unmatched trail code unit (2nd surrogate) */
185: /* callback(illegal) */
186: cr = CoderResult
187: .malformedForLength(sourceArrayIndex);
188: }
189: break;
190: }
191: }
192: }
193: fromUChar32 = ch;
194: cr = CoderResult
195: .malformedForLength(sourceArrayIndex);
196: break;
197: }
198: }
199: }
200: /* set offsets since the start */
201: if (offsets != null) {
202: count = target.position() - oldTarget;
203: while (count > 0) {
204: offsets.put(sourceIndex++);
205: --count;
206: }
207: }
208:
209: source.position(sourceArrayIndex);
210: return cr;
211: }
212: }
213:
214: public CharsetDecoder newDecoder() {
215: return new CharsetDecoderASCII(this );
216: }
217:
218: public CharsetEncoder newEncoder() {
219: return new CharsetEncoderASCII(this);
220: }
221:
222: }
|