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 ISO_8859_1 extends Charset {
030:
031: public ISO_8859_1(String csName, String[] aliases) {
032: super (csName, aliases);
033: }
034:
035: public boolean contains(Charset cs) {
036: return cs instanceof ISO_8859_1 || cs instanceof US_ASCII;
037: }
038:
039: public CharsetDecoder newDecoder() {
040: return new Decoder(this );
041: }
042:
043: public CharsetEncoder newEncoder() {
044: return new Encoder(this );
045: }
046:
047: private final class Decoder extends CharsetDecoder {
048: private Decoder(Charset cs) {
049: super (cs, 1, 1);
050:
051: }
052:
053: public native int nDecode(char[] array, int arrPosition,
054: int remaining, long outAddr, int absolutePos);
055:
056: protected CoderResult decodeLoop(ByteBuffer bb, CharBuffer cb) {
057: int bbRemaining = bb.remaining();
058: if (bbRemaining == 0) {
059: return CoderResult.UNDERFLOW;
060: }
061: int cbRemaining = cb.remaining();
062: boolean cbHasArray = cb.hasArray();
063: if (cbHasArray) {
064: if (bb.hasArray()) {
065: int rem = bbRemaining;
066: rem = cbRemaining >= rem ? rem : cbRemaining;
067: byte[] arr = bb.array();
068: char[] cArr = cb.array();
069: int bStart = bb.position();
070: int cStart = cb.position();
071: int i;
072: for (i = bStart; i < bStart + rem; i++) {
073: cArr[cStart++] = (char) ((int) arr[i] & 0xFF);
074: }
075: bb.position(i);
076: cb.position(cStart);
077: if (rem == cbRemaining && bb.hasRemaining()) {
078: return CoderResult.OVERFLOW;
079: }
080: return CoderResult.UNDERFLOW;
081: } else if (bb.isDirect()) {
082: int toProceed = bbRemaining;
083: boolean throwOverflow = false;
084: int cbPos = cb.position();
085: int bbPos = bb.position();
086: if (cbRemaining < toProceed) {
087: toProceed = cbRemaining;
088: throwOverflow = true;
089: }
090: int res = nDecode(cb.array(), cb.arrayOffset()
091: + cbPos, toProceed, AddressUtil
092: .getDirectBufferAddress(bb), bbPos);
093: cb.position(cbPos + res);
094: bb.position(bbPos + res);
095: if (throwOverflow) {
096: return CoderResult.OVERFLOW;
097: }
098: return CoderResult.UNDERFLOW;
099: }
100: }
101: int rem = bbRemaining;
102: rem = cbRemaining >= rem ? rem : cbRemaining;
103: byte[] arr = new byte[rem];
104: bb.get(arr);
105: char[] cArr = new char[rem];
106: for (int i = 0; i < rem; i++) {
107: cArr[i] = (char) ((int) arr[i] & 0xFF);
108: }
109: cb.put(cArr);
110: if (cb.remaining() == 0) {
111: return CoderResult.OVERFLOW;
112: }
113: return CoderResult.UNDERFLOW;
114: }
115: }
116:
117: private final class Encoder extends CharsetEncoder {
118: private Encoder(Charset cs) {
119: super (cs, 1, 1);
120: }
121:
122: private native void nEncode(long outAddr, int absolutePos,
123: char[] array, int arrPosition, int[] res);
124:
125: protected CoderResult encodeLoop(CharBuffer cb, ByteBuffer bb) {
126: int cbRemaining = cb.remaining();
127: if (cbRemaining == 0) {
128: return CoderResult.UNDERFLOW;
129: }
130: int bbRemaining = bb.remaining();
131: boolean cbHasArray = cb.hasArray();
132: boolean bbHasArray = bb.hasArray();
133: if (cbHasArray) {
134: if (bbHasArray) {
135: byte[] byteArr = bb.array();
136: char[] charArr = cb.array();
137: int byteArrStart = bb.position();
138: int rem = bbRemaining <= cbRemaining ? bbRemaining
139: : cbRemaining;
140: int cbPos = cb.position();
141: int x;
142: int jchar = 0;
143: for (x = cbPos; x < cbPos + rem; x++) {
144: jchar = (int) charArr[x];
145: if (jchar <= 0xFF) {
146: byteArr[byteArrStart++] = (byte) jchar;
147: } else {
148: break;
149: }
150: }
151: bb.position(byteArrStart);
152: cb.position(x);
153: if (x == cbPos + rem) {
154: // everything is ok
155: if (rem == bbRemaining && cb.hasRemaining()) {
156: return CoderResult.OVERFLOW;
157: }
158: return CoderResult.UNDERFLOW;
159: }
160: // here is jchar >0xFF
161: if (jchar >= 0xD800 && jchar <= 0xDFFF) {
162: if (x + 1 < cb.limit()) {
163: char c1 = charArr[x + 1];
164: if (c1 >= 0xD800 && c1 <= 0xDFFF) {
165: return CoderResult
166: .unmappableForLength(2);
167: }
168: } else {
169: return CoderResult.UNDERFLOW;
170: }
171: return CoderResult.malformedForLength(1);
172: }
173: return CoderResult.unmappableForLength(1);
174: } else if (bb.isDirect()) {
175: int toProceed = cbRemaining;
176: boolean throwOverflow = false;
177: int cbPos = cb.position();
178: int bbPos = bb.position();
179: if (bbRemaining < toProceed) {
180: toProceed = bbRemaining;
181: throwOverflow = true;
182: }
183: int[] res = { toProceed, 0 };
184: nEncode(AddressUtil.getDirectBufferAddress(bb),
185: bbPos, cb.array(),
186: cb.arrayOffset() + cbPos, res);
187: if (res[0] <= 0) {
188: bb.position(bbPos - res[0]);
189: cb.position(cbPos - res[0]);
190: if (res[1] != 0) {
191: if (res[1] < 0) {
192: return CoderResult
193: .malformedForLength(-res[1]);
194: } else {
195: return CoderResult
196: .unmappableForLength(res[1]);
197: }
198: }
199: } else {
200: bb.position(bbPos + res[0]);
201: cb.position(cbPos + res[0]);
202: if (throwOverflow) {
203: return CoderResult.OVERFLOW;
204: }
205: }
206: return CoderResult.UNDERFLOW;
207: }
208: }
209: while (cb.hasRemaining()) {
210: if (bbRemaining == 0) {
211: return CoderResult.OVERFLOW;
212: }
213: char c = cb.get();
214: if (c > (char) 0x00FF) {
215: if (c >= 0xD800 && c <= 0xDFFF) {
216: if (cb.hasRemaining()) {
217: char c1 = cb.get();
218: if (c1 >= 0xD800 && c1 <= 0xDFFF) {
219: cb.position(cb.position() - 2);
220: return CoderResult
221: .unmappableForLength(2);
222: } else {
223: cb.position(cb.position() - 1);
224: }
225: } else {
226: cb.position(cb.position() - 1);
227: return CoderResult.UNDERFLOW;
228: }
229: cb.position(cb.position() - 1);
230: return CoderResult.malformedForLength(1);
231: }
232: cb.position(cb.position() - 1);
233: return CoderResult.unmappableForLength(1);
234: } else {
235: bb.put((byte) c);
236: bbRemaining--;
237: }
238: }
239: return CoderResult.UNDERFLOW;
240: }
241:
242: }
243: }
|