001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.niochar.charset;
019:
020: import java.nio.ByteBuffer;
021: import java.nio.CharBuffer;
022: import java.nio.charset.Charset;
023: import java.nio.charset.CharsetDecoder;
024: import java.nio.charset.CharsetEncoder;
025: import java.nio.charset.CoderResult;
026:
027: import org.apache.harmony.nio.AddressUtil;
028:
029: public class US_ASCII extends Charset {
030:
031: public US_ASCII(String csName, String[] aliases) {
032: super (csName, aliases);
033: }
034:
035: /* (non-Javadoc)
036: * @see java.nio.charset.Charset#newEncoder()
037: */
038: public CharsetEncoder newEncoder() {
039: return new Encoder(this );
040: }
041:
042: /* (non-Javadoc)
043: * @see java.nio.charset.Charset#newDecoder()
044: */
045: public CharsetDecoder newDecoder() {
046: return new Decoder(this );
047: }
048:
049: /* (non-Javadoc)
050: * @see java.nio.charset.Charset#contains(java.nio.charset.Charset)
051: */
052: public boolean contains(Charset cs) {
053: return cs instanceof US_ASCII;
054: }
055:
056: private final class Decoder extends CharsetDecoder {
057: private Decoder(Charset cs) {
058: super (cs, 1, 1);
059: }
060:
061: public native int nDecode(char[] array, int arrPosition,
062: int remaining, long outAddr, int absolutePos);
063:
064: protected CoderResult decodeLoop(ByteBuffer bb, CharBuffer cb) {
065: if (bb.isDirect() && bb.hasRemaining() && cb.hasArray()) {
066: int toProceed = bb.remaining();
067: boolean throwOverflow = false;
068: if (cb.remaining() < toProceed) {
069: toProceed = cb.remaining();
070: throwOverflow = true;
071: }
072: int res = nDecode(cb.array(), cb.arrayOffset()
073: + cb.position(), toProceed, AddressUtil
074: .getDirectBufferAddress(bb), bb.position());
075: if (res <= 0) {
076: bb.position(bb.position() - res);
077: cb.position(cb.position() - res);
078: return CoderResult.unmappableForLength(1);
079: } else {
080: cb.position(cb.position() + res);
081: bb.position(bb.position() + res);
082: if (throwOverflow)
083: return CoderResult.OVERFLOW;
084: }
085: } else {
086: int cbRemaining = cb.remaining();
087: if (bb.hasArray() && cb.hasArray()) {
088: int rem = bb.remaining();
089: rem = cbRemaining >= rem ? rem : cbRemaining;
090: byte[] bArr = bb.array();
091: char[] cArr = cb.array();
092: int bStart = bb.position();
093: int cStart = cb.position();
094: int i;
095: for (i = bStart; i < bStart + rem; i++) {
096: byte b = bArr[i];
097: if (b < 0) {
098: bb.position(i);
099: cb.position(cStart);
100: return CoderResult.malformedForLength(1);
101: }
102: cArr[cStart++] = (char) b;
103: }
104: bb.position(i);
105: cb.position(cStart);
106: if (rem == cbRemaining && bb.hasRemaining())
107: return CoderResult.OVERFLOW;
108: } else {
109: while (bb.hasRemaining()) {
110: if (cbRemaining == 0)
111: return CoderResult.OVERFLOW;
112: byte b = bb.get();
113: if (b < 0) {
114: bb.position(bb.position() - 1);
115: return CoderResult.malformedForLength(1);
116: }
117: cb.put((char) b);
118: cbRemaining--;
119: }
120: }
121: }
122: return CoderResult.UNDERFLOW;
123: }
124: }
125:
126: private final class Encoder extends CharsetEncoder {
127:
128: private Encoder(Charset cs) {
129: super (cs, 1, 1);
130: }
131:
132: private native void nEncode(long outAddr, int absolutePos,
133: char[] array, int arrPosition, int[] res);
134:
135: protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) {
136: int bbRemaining = bb.remaining();
137: if (bb.isDirect() && cb.hasRemaining() && cb.hasArray()) {
138: int toProceed = cb.remaining();
139: boolean throwOverflow = false;
140: int cbPos = cb.position();
141: int bbPos = bb.position();
142: if (bbRemaining < toProceed) {
143: toProceed = bbRemaining;
144: throwOverflow = true;
145: }
146: int[] res = { toProceed, 0 };
147: nEncode(AddressUtil.getDirectBufferAddress(bb), bbPos,
148: cb.array(), cb.arrayOffset() + cbPos, res);
149: if (res[0] <= 0) {
150: bb.position(bbPos - res[0]);
151: cb.position(cbPos - res[0]);
152: if (res[1] != 0) {
153: if (res[1] < 0)
154: return CoderResult
155: .malformedForLength(-res[1]);
156: else
157: return CoderResult
158: .unmappableForLength(res[1]);
159: }
160: } else {
161: bb.position(bbPos + res[0]);
162: cb.position(cbPos + res[0]);
163: if (throwOverflow)
164: return CoderResult.OVERFLOW;
165: }
166: } else {
167: if (bb.hasArray() && cb.hasArray()) {
168: byte[] byteArr = bb.array();
169: char[] charArr = cb.array();
170: int rem = cb.remaining();
171: int byteArrStart = bb.position();
172: rem = bbRemaining <= rem ? bbRemaining : rem;
173: int x;
174: for (x = cb.position(); x < cb.position() + rem; x++) {
175: char c = charArr[x];
176: if (c > Byte.MAX_VALUE) {
177: if (c >= 0xD800 && c <= 0xDFFF) {
178: if (x + 1 < cb.limit()) {
179: char c1 = charArr[x + 1];
180: if (c1 >= 0xD800 && c1 <= 0xDFFF) {
181: cb.position(x);
182: bb.position(byteArrStart);
183: return CoderResult
184: .unmappableForLength(2);
185: }
186: } else {
187: cb.position(x);
188: bb.position(byteArrStart);
189: return CoderResult.UNDERFLOW;
190: }
191: cb.position(x);
192: bb.position(byteArrStart);
193: return CoderResult
194: .malformedForLength(1);
195: }
196: cb.position(x);
197: bb.position(byteArrStart);
198: return CoderResult.unmappableForLength(1);
199: }
200: byteArr[byteArrStart++] = (byte) c;
201: }
202: cb.position(x);
203: bb.position(byteArrStart);
204: if (rem == bbRemaining && cb.hasRemaining()) {
205: return CoderResult.OVERFLOW;
206: }
207: } else {
208: while (cb.hasRemaining()) {
209: if (bbRemaining == 0)
210: return CoderResult.OVERFLOW;
211: char c = cb.get();
212: if (c > Byte.MAX_VALUE) {
213: if (c >= 0xD800 && c <= 0xDFFF) {
214: if (cb.hasRemaining()) {
215: char c1 = cb.get();
216: if (c1 >= 0xD800 && c1 <= 0xDFFF) {
217: cb.position(cb.position() - 2);
218: return CoderResult
219: .unmappableForLength(2);
220: } else {
221: cb.position(cb.position() - 1);
222: }
223: } else {
224: cb.position(cb.position() - 1);
225: return CoderResult.UNDERFLOW;
226: }
227: cb.position(cb.position() - 1);
228: return CoderResult
229: .malformedForLength(1);
230: }
231: cb.position(cb.position() - 1);
232: return CoderResult.unmappableForLength(1);
233: }
234: bb.put((byte) c);
235: bbRemaining--;
236: }
237: }
238: }
239: return CoderResult.UNDERFLOW;
240: }
241: }
242: }
|