Path: blob/master/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java
41161 views
/*1* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26*/2728package sun.nio.cs.ext;2930import java.nio.ByteBuffer;31import java.nio.CharBuffer;32import java.nio.charset.Charset;33import java.nio.charset.CharsetDecoder;34import java.nio.charset.CharsetEncoder;35import java.nio.charset.CoderResult;36import sun.nio.cs.Surrogate;3738abstract class ISO202239extends Charset40{41public ISO2022(String csname, String[] aliases) {42super(csname, aliases);43}4445public abstract CharsetDecoder newDecoder();4647public abstract CharsetEncoder newEncoder();4849// No default Decoder implementation is provided here; the concrete50// encodings differ enough that most had been specialized for51// performance reasons, leaving the generic implementation that existed52// here before JDK-8261418 unused except by ISO2022_KR. As both a53// simplification and an optimization the implementation was moved54// there and specialized.5556protected static class Encoder extends CharsetEncoder {5758private static final byte ISO_ESC = 0x1b;59private static final byte ISO_SI = 0x0f;60private static final byte ISO_SO = 0x0e;61private static final byte ISO_SS2_7 = 0x4e;62private static final byte ISO_SS3_7 = 0x4f;6364private final Surrogate.Parser sgp = new Surrogate.Parser();65public static final byte SS2 = (byte)0x8e;66public static final byte PLANE2 = (byte)0xA2;67public static final byte PLANE3 = (byte)0xA3;6869protected final byte maximumDesignatorLength = 4;7071protected byte[] SODesig,72SS2Desig = null,73SS3Desig = null;7475protected CharsetEncoder ISOEncoder;7677private boolean shiftout = false;78private boolean SODesDefined = false;79private boolean SS2DesDefined = false;80private boolean SS3DesDefined = false;8182private boolean newshiftout = false;83private boolean newSODesDefined = false;84private boolean newSS2DesDefined = false;85private boolean newSS3DesDefined = false;8687protected Encoder(Charset cs) {88super(cs, 4.0f, 8.0f);89}9091public boolean canEncode(char c) {92return (ISOEncoder.canEncode(c));93}9495protected void implReset() {96shiftout = false;97SODesDefined = false;98SS2DesDefined = false;99SS3DesDefined = false;100}101102private int unicodeToNative(char unicode, byte ebyte[]) {103int index = 0;104char[] convChar = {unicode};105byte[] convByte = new byte[4];106int converted;107108try{109CharBuffer cc = CharBuffer.wrap(convChar);110ByteBuffer bb = ByteBuffer.wrap(convByte);111ISOEncoder.encode(cc, bb, true);112bb.flip();113converted = bb.remaining();114} catch(Exception e) {115return -1;116}117118if (converted == 2) {119if (!SODesDefined) {120newSODesDefined = true;121ebyte[0] = ISO_ESC;122System.arraycopy(SODesig, 0, ebyte, 1, SODesig.length);123index = SODesig.length + 1;124}125if (!shiftout) {126newshiftout = true;127ebyte[index++] = ISO_SO;128}129ebyte[index++] = (byte)(convByte[0] & 0x7f);130ebyte[index++] = (byte)(convByte[1] & 0x7f);131} else {132if(convByte[0] == SS2) {133if (convByte[1] == PLANE2) {134if (!SS2DesDefined) {135newSS2DesDefined = true;136ebyte[0] = ISO_ESC;137System.arraycopy(SS2Desig, 0, ebyte, 1, SS2Desig.length);138index = SS2Desig.length + 1;139}140ebyte[index++] = ISO_ESC;141ebyte[index++] = ISO_SS2_7;142ebyte[index++] = (byte)(convByte[2] & 0x7f);143ebyte[index++] = (byte)(convByte[3] & 0x7f);144} else if (convByte[1] == PLANE3) {145if(!SS3DesDefined){146newSS3DesDefined = true;147ebyte[0] = ISO_ESC;148System.arraycopy(SS3Desig, 0, ebyte, 1, SS3Desig.length);149index = SS3Desig.length + 1;150}151ebyte[index++] = ISO_ESC;152ebyte[index++] = ISO_SS3_7;153ebyte[index++] = (byte)(convByte[2] & 0x7f);154ebyte[index++] = (byte)(convByte[3] & 0x7f);155}156}157}158return index;159}160161private CoderResult encodeArrayLoop(CharBuffer src,162ByteBuffer dst)163{164char[] sa = src.array();165int sp = src.arrayOffset() + src.position();166int sl = src.arrayOffset() + src.limit();167168byte[] da = dst.array();169int dp = dst.arrayOffset() + dst.position();170int dl = dst.arrayOffset() + dst.limit();171172int outputSize;173byte[] outputByte = new byte[8];174newshiftout = shiftout;175newSODesDefined = SODesDefined;176newSS2DesDefined = SS2DesDefined;177newSS3DesDefined = SS3DesDefined;178179try {180while (sp < sl) {181char c = sa[sp];182if (Character.isSurrogate(c)) {183if (sgp.parse(c, sa, sp, sl) < 0)184return sgp.error();185return sgp.unmappableResult();186}187188if (c < 0x80) { // ASCII189if (shiftout){190newshiftout = false;191outputSize = 2;192outputByte[0] = ISO_SI;193outputByte[1] = (byte)(c & 0x7f);194} else {195outputSize = 1;196outputByte[0] = (byte)(c & 0x7f);197}198if(sa[sp] == '\n'){199newSODesDefined = false;200newSS2DesDefined = false;201newSS3DesDefined = false;202}203} else {204outputSize = unicodeToNative(c, outputByte);205if (outputSize == 0) {206return CoderResult.unmappableForLength(1);207}208}209if (dl - dp < outputSize)210return CoderResult.OVERFLOW;211212for (int i = 0; i < outputSize; i++)213da[dp++] = outputByte[i];214sp++;215shiftout = newshiftout;216SODesDefined = newSODesDefined;217SS2DesDefined = newSS2DesDefined;218SS3DesDefined = newSS3DesDefined;219}220return CoderResult.UNDERFLOW;221} finally {222src.position(sp - src.arrayOffset());223dst.position(dp - dst.arrayOffset());224}225}226227private CoderResult encodeBufferLoop(CharBuffer src,228ByteBuffer dst)229{230int outputSize;231byte[] outputByte = new byte[8];232newshiftout = shiftout;233newSODesDefined = SODesDefined;234newSS2DesDefined = SS2DesDefined;235newSS3DesDefined = SS3DesDefined;236int mark = src.position();237238try {239while (src.hasRemaining()) {240char inputChar = src.get();241if (Character.isSurrogate(inputChar)) {242if (sgp.parse(inputChar, src) < 0)243return sgp.error();244return sgp.unmappableResult();245}246if (inputChar < 0x80) { // ASCII247if (shiftout){248newshiftout = false;249outputSize = 2;250outputByte[0] = ISO_SI;251outputByte[1] = (byte)(inputChar & 0x7f);252} else {253outputSize = 1;254outputByte[0] = (byte)(inputChar & 0x7f);255}256if (inputChar == '\n') {257newSODesDefined = false;258newSS2DesDefined = false;259newSS3DesDefined = false;260}261} else {262outputSize = unicodeToNative(inputChar, outputByte);263if (outputSize == 0) {264return CoderResult.unmappableForLength(1);265}266}267268if (dst.remaining() < outputSize)269return CoderResult.OVERFLOW;270for (int i = 0; i < outputSize; i++)271dst.put(outputByte[i]);272mark++;273shiftout = newshiftout;274SODesDefined = newSODesDefined;275SS2DesDefined = newSS2DesDefined;276SS3DesDefined = newSS3DesDefined;277}278return CoderResult.UNDERFLOW;279} finally {280src.position(mark);281}282}283284protected CoderResult encodeLoop(CharBuffer src,285ByteBuffer dst)286{287if (src.hasArray() && dst.hasArray())288return encodeArrayLoop(src, dst);289else290return encodeBufferLoop(src, dst);291}292}293}294295296