1 /* 2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.cs.ext; 27 28 import java.nio.ByteBuffer; 29 import java.nio.CharBuffer; 30 import java.nio.charset.Charset; 31 import java.nio.charset.CharsetDecoder; 32 import java.nio.charset.CharsetEncoder; 33 import java.nio.charset.CoderResult; 34 import java.nio.charset.CodingErrorAction; 35 import sun.nio.cs.HistoricallyNamedCharset; 36 import sun.nio.cs.Surrogate; 37 import sun.nio.cs.US_ASCII; 38 import static sun.nio.cs.CharsetMapping.*; 39 40 /* 41 * Implementation notes: 42 * 43 * (1)"Standard based" (ASCII, JIS_X_0201 and JIS_X_0208) ISO2022-JP charset 44 * is provided by the base implementation of this class. 45 * 46 * Three Microsoft ISO2022-JP variants, MS50220, MS50221 and MSISO2022JP 47 * are provided via subclasses. 48 * 49 * (2)MS50220 and MS50221 are assumed to work the same way as Microsoft 50 * CP50220 and CP50221's 7-bit implementation works by using CP5022X 51 * specific JIS0208 and JIS0212 mapping tables (generated via Microsoft's 52 * MultiByteToWideChar/WideCharToMultiByte APIs). The only difference 53 * between these 2 classes is that MS50220 does not support singlebyte 54 * halfwidth kana (Uff61-Uff9f) shiftin mechanism when "encoding", instead 55 * these halfwidth kana characters are converted to their fullwidth JIS0208 56 * counterparts. 57 * 58 * The difference between the standard JIS_X_0208 and JIS_X_0212 mappings 59 * and the CP50220/50221 specific are 60 * 61 * 0208 mapping: 62 * 1)0x213d <-> U2015 (compared to U2014) 63 * 2)One way mappings for 5 characters below 64 * u2225 (ms) -> 0x2142 <-> u2016 (jis) 65 * uff0d (ms) -> 0x215d <-> u2212 (jis) 66 * uffe0 (ms) -> 0x2171 <-> u00a2 (jis) 67 * uffe1 (ms) -> 0x2172 <-> u00a3 (jis) 68 * uffe2 (ms) -> 0x224c <-> u00ac (jis) 69 * //should consider 0xff5e -> 0x2141 <-> U301c? 70 * 3)NEC Row13 0x2d21-0x2d79 71 * 4)85-94 ku <-> UE000,UE3AB (includes NEC selected 72 * IBM kanji in 89-92ku) 73 * 5)UFF61-UFF9f -> Fullwidth 0208 KANA 74 * 75 * 0212 mapping: 76 * 1)0x2237 <-> UFF5E (Fullwidth Tilde) 77 * 2)0x2271 <-> U2116 (Numero Sign) 78 * 3)85-94 ku <-> UE3AC - UE757 79 * 80 * (3)MSISO2022JP uses a JIS0208 mapping generated from MS932DB.b2c 81 * and MS932DB.c2b by converting the SJIS codepoints back to their 82 * JIS0208 counterparts. With the exception of 83 * 84 * (a)Codepoints with a resulting JIS0208 codepoints beyond 0x7e00 are 85 * dropped (this includs the IBM Extended Kanji/Non-kanji from 0x9321 86 * to 0x972c) 87 * (b)The Unicode codepoints that the IBM Extended Kanji/Non-kanji are 88 * mapped to (in MS932) are mapped back to NEC selected IBM Kanji/ 89 * Non-kanji area at 0x7921-0x7c7e. 90 * 91 * Compared to JIS_X_0208 mapping, this MS932 based mapping has 92 93 * (a)different mappings for 7 JIS codepoints 94 * 0x213d <-> U2015 95 * 0x2141 <-> UFF5E 96 * 0x2142 <-> U2225 97 * 0x215d <-> Uff0d 98 * 0x2171 <-> Uffe0 99 * 0x2172 <-> Uffe1 100 * 0x224c <-> Uffe2 101 * (b)added one-way c2b mappings for 102 * U00b8 -> 0x2124 103 * U00b7 -> 0x2126 104 * U00af -> 0x2131 105 * U00ab -> 0x2263 106 * U00bb -> 0x2264 107 * U3094 -> 0x2574 108 * U00b5 -> 0x264c 109 * (c)NEC Row 13 110 * (d)NEC selected IBM extended Kanji/Non-kanji 111 * These codepoints are mapped to the same Unicode codepoints as 112 * the MS932 does, while MS50220/50221 maps them to the Unicode 113 * private area. 114 * 115 * # There is also an interesting difference when compared to MS5022X 116 * 0208 mapping for JIS codepoint "0x2D60", MS932 maps it to U301d 117 * but MS5022X maps it to U301e, obvious MS5022X is wrong, but... 118 */ 119 120 public class ISO2022_JP 121 extends Charset 122 implements HistoricallyNamedCharset 123 { 124 private static final int ASCII = 0; // ESC ( B 125 private static final int JISX0201_1976 = 1; // ESC ( J 126 private static final int JISX0208_1978 = 2; // ESC $ @ 127 private static final int JISX0208_1983 = 3; // ESC $ B 128 private static final int JISX0212_1990 = 4; // ESC $ ( D 129 private static final int JISX0201_1976_KANA = 5; // ESC ( I 130 private static final int SHIFTOUT = 6; 131 132 private static final int ESC = 0x1b; 133 private static final int SO = 0x0e; 134 private static final int SI = 0x0f; 135 136 public ISO2022_JP() { 137 super("ISO-2022-JP", 138 ExtendedCharsets.aliasesFor("ISO-2022-JP")); 139 } 140 141 protected ISO2022_JP(String canonicalName, 142 String[] aliases) { 143 super(canonicalName, aliases); 144 } 145 146 public String historicalName() { 147 return "ISO2022JP"; 148 } 149 150 public boolean contains(Charset cs) { 151 return ((cs instanceof JIS_X_0201) 152 || (cs instanceof US_ASCII) 153 || (cs instanceof JIS_X_0208) 154 || (cs instanceof ISO2022_JP)); 155 } 156 157 public CharsetDecoder newDecoder() { 158 return new Decoder(this); 159 } 160 161 public CharsetEncoder newEncoder() { 162 return new Encoder(this); 163 } 164 165 protected boolean doSBKANA() { 166 return true; 167 } 168 169 static class Decoder extends CharsetDecoder 170 implements DelegatableDecoder { 171 172 final static DoubleByte.Decoder DEC0208 = 173 (DoubleByte.Decoder)new JIS_X_0208().newDecoder(); 174 175 private int currentState; 176 private int previousState; 177 178 private DoubleByte.Decoder dec0208; 179 private DoubleByte.Decoder dec0212; 180 181 private Decoder(Charset cs) { 182 this(cs, DEC0208, null); 183 } 184 185 protected Decoder(Charset cs, 186 DoubleByte.Decoder dec0208, 187 DoubleByte.Decoder dec0212) { 188 super(cs, 0.5f, 1.0f); 189 this.dec0208 = dec0208; 190 this.dec0212 = dec0212; 191 currentState = ASCII; 192 previousState = ASCII; 193 } 194 195 public void implReset() { 196 currentState = ASCII; 197 previousState = ASCII; 198 } 199 200 private CoderResult decodeArrayLoop(ByteBuffer src, 201 CharBuffer dst) 202 { 203 int inputSize = 0; 204 int b1 = 0, b2 = 0, b3 = 0, b4 = 0; 205 char c = UNMAPPABLE_DECODING; 206 byte[] sa = src.array(); 207 int sp = src.arrayOffset() + src.position(); 208 int sl = src.arrayOffset() + src.limit(); 209 assert (sp <= sl); 210 sp = (sp <= sl ? sp : sl); 211 212 char[] da = dst.array(); 213 int dp = dst.arrayOffset() + dst.position(); 214 int dl = dst.arrayOffset() + dst.limit(); 215 assert (dp <= dl); 216 dp = (dp <= dl ? dp : dl); 217 218 try { 219 while (sp < sl) { 220 b1 = sa[sp] & 0xff; 221 inputSize = 1; 222 if ((b1 & 0x80) != 0) { 223 return CoderResult.malformedForLength(inputSize); 224 } 225 if (b1 == ESC || b1 == SO || b1 == SI) { 226 if (b1 == ESC) { 227 if (sp + inputSize + 2 > sl) 228 return CoderResult.UNDERFLOW; 229 b2 = sa[sp + inputSize++] & 0xff; 230 if (b2 == '(') { 231 b3 = sa[sp + inputSize++] & 0xff; 232 if (b3 == 'B'){ 233 currentState = ASCII; 234 } else if (b3 == 'J'){ 235 currentState = JISX0201_1976; 236 } else if (b3 == 'I'){ 237 currentState = JISX0201_1976_KANA; 238 } else { 239 return CoderResult.malformedForLength(inputSize); 240 } 241 } else if (b2 == '$'){ 242 b3 = sa[sp + inputSize++] & 0xff; 243 if (b3 == '@'){ 244 currentState = JISX0208_1978; 245 } else if (b3 == 'B'){ 246 currentState = JISX0208_1983; 247 } else if (b3 == '(' && dec0212 != null) { 248 if (sp + inputSize + 1 > sl) 249 return CoderResult.UNDERFLOW; 250 b4 = sa[sp + inputSize++] & 0xff; 251 if (b4 == 'D') { 252 currentState = JISX0212_1990; 253 } else { 254 return CoderResult.malformedForLength(inputSize); 255 } 256 } else { 257 return CoderResult.malformedForLength(inputSize); 258 } 259 } else { 260 return CoderResult.malformedForLength(inputSize); 261 } 262 } else if (b1 == SO) { 263 previousState = currentState; 264 currentState = SHIFTOUT; 265 } else if (b1 == SI) { 266 currentState = previousState; 267 } 268 sp += inputSize; 269 continue; 270 } 271 if (dp + 1 > dl) 272 return CoderResult.OVERFLOW; 273 274 switch (currentState){ 275 case ASCII: 276 da[dp++] = (char)(b1 & 0xff); 277 break; 278 case JISX0201_1976: 279 switch (b1) { 280 case 0x5c: // Yen/tilde substitution 281 da[dp++] = '\u00a5'; 282 break; 283 case 0x7e: 284 da[dp++] = '\u203e'; 285 break; 286 default: 287 da[dp++] = (char)b1; 288 break; 289 } 290 break; 291 case JISX0208_1978: 292 case JISX0208_1983: 293 if (sp + inputSize + 1 > sl) 294 return CoderResult.UNDERFLOW; 295 b2 = sa[sp + inputSize++] & 0xff; 296 c = dec0208.decodeDouble(b1,b2); 297 if (c == UNMAPPABLE_DECODING) 298 return CoderResult.unmappableForLength(inputSize); 299 da[dp++] = c; 300 break; 301 case JISX0212_1990: 302 if (sp + inputSize + 1 > sl) 303 return CoderResult.UNDERFLOW; 304 b2 = sa[sp + inputSize++] & 0xff; 305 c = dec0212.decodeDouble(b1,b2); 306 if (c == UNMAPPABLE_DECODING) 307 return CoderResult.unmappableForLength(inputSize); 308 da[dp++] = c; 309 break; 310 case JISX0201_1976_KANA: 311 case SHIFTOUT: 312 if (b1 > 0x5f) { 313 return CoderResult.malformedForLength(inputSize); 314 } 315 da[dp++] = (char)(b1 + 0xff40); 316 break; 317 } 318 sp += inputSize; 319 } 320 return CoderResult.UNDERFLOW; 321 } finally { 322 src.position(sp - src.arrayOffset()); 323 dst.position(dp - dst.arrayOffset()); 324 } 325 } 326 327 private CoderResult decodeBufferLoop(ByteBuffer src, 328 CharBuffer dst) 329 { 330 int mark = src.position(); 331 int b1 = 0, b2 = 0, b3 = 0, b4=0; 332 char c = UNMAPPABLE_DECODING; 333 int inputSize = 0; 334 try { 335 while (src.hasRemaining()) { 336 b1 = src.get() & 0xff; 337 inputSize = 1; 338 if ((b1 & 0x80) != 0) 339 return CoderResult.malformedForLength(inputSize); 340 if (b1 == ESC || b1 == SO || b1 == SI) { 341 if (b1 == ESC) { // ESC 342 if (src.remaining() < 2) 343 return CoderResult.UNDERFLOW; 344 b2 = src.get() & 0xff; 345 inputSize++; 346 if (b2 == '(') { 347 b3 = src.get() & 0xff; 348 inputSize++; 349 if (b3 == 'B'){ 350 currentState = ASCII; 351 } else if (b3 == 'J'){ 352 currentState = JISX0201_1976; 353 } else if (b3 == 'I'){ 354 currentState = JISX0201_1976_KANA; 355 } else { 356 return CoderResult.malformedForLength(inputSize); 357 } 358 } else if (b2 == '$'){ 359 b3 = src.get() & 0xff; 360 inputSize++; 361 if (b3 == '@'){ 362 currentState = JISX0208_1978; 363 } else if (b3 == 'B'){ 364 currentState = JISX0208_1983; 365 } else if (b3 == '(' && dec0212 != null) { 366 if (!src.hasRemaining()) 367 return CoderResult.UNDERFLOW; 368 b4 = src.get() & 0xff; 369 inputSize++; 370 if (b4 == 'D') { 371 currentState = JISX0212_1990; 372 } else { 373 return CoderResult.malformedForLength(inputSize); 374 } 375 } else { 376 return CoderResult.malformedForLength(inputSize); 377 } 378 } else { 379 return CoderResult.malformedForLength(inputSize); 380 } 381 } else if (b1 == SO) { 382 previousState = currentState; 383 currentState = SHIFTOUT; 384 } else if (b1 == SI) { // shift back in 385 currentState = previousState; 386 } 387 mark += inputSize; 388 continue; 389 } 390 if (!dst.hasRemaining()) 391 return CoderResult.OVERFLOW; 392 393 switch (currentState){ 394 case ASCII: 395 dst.put((char)(b1 & 0xff)); 396 break; 397 case JISX0201_1976: 398 switch (b1) { 399 case 0x5c: // Yen/tilde substitution 400 dst.put('\u00a5'); 401 break; 402 case 0x7e: 403 dst.put('\u203e'); 404 break; 405 default: 406 dst.put((char)b1); 407 break; 408 } 409 break; 410 case JISX0208_1978: 411 case JISX0208_1983: 412 if (!src.hasRemaining()) 413 return CoderResult.UNDERFLOW; 414 b2 = src.get() & 0xff; 415 inputSize++; 416 c = dec0208.decodeDouble(b1,b2); 417 if (c == UNMAPPABLE_DECODING) 418 return CoderResult.unmappableForLength(inputSize); 419 dst.put(c); 420 break; 421 case JISX0212_1990: 422 if (!src.hasRemaining()) 423 return CoderResult.UNDERFLOW; 424 b2 = src.get() & 0xff; 425 inputSize++; 426 c = dec0212.decodeDouble(b1,b2); 427 if (c == UNMAPPABLE_DECODING) 428 return CoderResult.unmappableForLength(inputSize); 429 dst.put(c); 430 break; 431 case JISX0201_1976_KANA: 432 case SHIFTOUT: 433 if (b1 > 0x5f) { 434 return CoderResult.malformedForLength(inputSize); 435 } 436 dst.put((char)(b1 + 0xff40)); 437 break; 438 } 439 mark += inputSize; 440 } 441 return CoderResult.UNDERFLOW; 442 } finally { 443 src.position(mark); 444 } 445 } 446 447 // Make some protected methods public for use by JISAutoDetect 448 public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { 449 if (src.hasArray() && dst.hasArray()) 450 return decodeArrayLoop(src, dst); 451 else 452 return decodeBufferLoop(src, dst); 453 } 454 455 public CoderResult implFlush(CharBuffer out) { 456 return super.implFlush(out); 457 } 458 } 459 460 static class Encoder extends CharsetEncoder { 461 462 final static DoubleByte.Encoder ENC0208 = 463 (DoubleByte.Encoder)new JIS_X_0208().newEncoder(); 464 465 private static byte[] repl = { (byte)0x21, (byte)0x29 }; 466 private int currentMode = ASCII; 467 private int replaceMode = JISX0208_1983; 468 private DoubleByte.Encoder enc0208; 469 private DoubleByte.Encoder enc0212; 470 private boolean doSBKANA; 471 472 private Encoder(Charset cs) { 473 this(cs, ENC0208, null, true); 474 } 475 476 Encoder(Charset cs, 477 DoubleByte.Encoder enc0208, 478 DoubleByte.Encoder enc0212, 479 boolean doSBKANA) { 480 super(cs, 4.0f, (enc0212 != null)? 9.0f : 8.0f, repl); 481 this.enc0208 = enc0208; 482 this.enc0212 = enc0212; 483 this.doSBKANA = doSBKANA; 484 } 485 486 protected int encodeSingle(char inputChar) { 487 return -1; 488 } 489 490 protected void implReset() { 491 currentMode = ASCII; 492 } 493 494 protected void implReplaceWith(byte[] newReplacement) { 495 /* It's almost impossible to decide which charset they belong 496 to. The best thing we can do here is to "guess" based on 497 the length of newReplacement. 498 */ 499 if (newReplacement.length == 1) { 500 replaceMode = ASCII; 501 } else if (newReplacement.length == 2) { 502 replaceMode = JISX0208_1983; 503 } 504 } 505 506 protected CoderResult implFlush(ByteBuffer out) { 507 if (currentMode != ASCII) { 508 if (out.remaining() < 3) 509 return CoderResult.OVERFLOW; 510 out.put((byte)0x1b); 511 out.put((byte)0x28); 512 out.put((byte)0x42); 513 currentMode = ASCII; 514 } 515 return CoderResult.UNDERFLOW; 516 } 517 518 public boolean canEncode(char c) { 519 return ((c <= '\u007F') || 520 (c >= 0xFF61 && c <= 0xFF9F) || 521 (c == '\u00A5') || 522 (c == '\u203E') || 523 enc0208.canEncode(c) || 524 (enc0212!=null && enc0212.canEncode(c))); 525 } 526 527 private final Surrogate.Parser sgp = new Surrogate.Parser(); 528 529 private CoderResult encodeArrayLoop(CharBuffer src, 530 ByteBuffer dst) 531 { 532 char[] sa = src.array(); 533 int sp = src.arrayOffset() + src.position(); 534 int sl = src.arrayOffset() + src.limit(); 535 assert (sp <= sl); 536 sp = (sp <= sl ? sp : sl); 537 byte[] da = dst.array(); 538 int dp = dst.arrayOffset() + dst.position(); 539 int dl = dst.arrayOffset() + dst.limit(); 540 assert (dp <= dl); 541 dp = (dp <= dl ? dp : dl); 542 543 try { 544 while (sp < sl) { 545 char c = sa[sp]; 546 if (c <= '\u007F') { 547 if (currentMode != ASCII) { 548 if (dl - dp < 3) 549 return CoderResult.OVERFLOW; 550 da[dp++] = (byte)0x1b; 551 da[dp++] = (byte)0x28; 552 da[dp++] = (byte)0x42; 553 currentMode = ASCII; 554 } 555 if (dl - dp < 1) 556 return CoderResult.OVERFLOW; 557 da[dp++] = (byte)c; 558 } else if (c >= 0xff61 && c <= 0xff9f && doSBKANA) { 559 //a single byte kana 560 if (currentMode != JISX0201_1976_KANA) { 561 if (dl - dp < 3) 562 return CoderResult.OVERFLOW; 563 da[dp++] = (byte)0x1b; 564 da[dp++] = (byte)0x28; 565 da[dp++] = (byte)0x49; 566 currentMode = JISX0201_1976_KANA; 567 } 568 if (dl - dp < 1) 569 return CoderResult.OVERFLOW; 570 da[dp++] = (byte)(c - 0xff40); 571 } else if (c == '\u00A5' || c == '\u203E') { 572 //backslash or tilde 573 if (currentMode != JISX0201_1976) { 574 if (dl - dp < 3) 575 return CoderResult.OVERFLOW; 576 da[dp++] = (byte)0x1b; 577 da[dp++] = (byte)0x28; 578 da[dp++] = (byte)0x4a; 579 currentMode = JISX0201_1976; 580 } 581 if (dl - dp < 1) 582 return CoderResult.OVERFLOW; 583 da[dp++] = (c == '\u00A5')?(byte)0x5C:(byte)0x7e; 584 } else { 585 int index = enc0208.encodeChar(c); 586 if (index != UNMAPPABLE_ENCODING) { 587 if (currentMode != JISX0208_1983) { 588 if (dl - dp < 3) 589 return CoderResult.OVERFLOW; 590 da[dp++] = (byte)0x1b; 591 da[dp++] = (byte)0x24; 592 da[dp++] = (byte)0x42; 593 currentMode = JISX0208_1983; 594 } 595 if (dl - dp < 2) 596 return CoderResult.OVERFLOW; 597 da[dp++] = (byte)(index >> 8); 598 da[dp++] = (byte)(index & 0xff); 599 } else if (enc0212 != null && 600 (index = enc0212.encodeChar(c)) != UNMAPPABLE_ENCODING) { 601 if (currentMode != JISX0212_1990) { 602 if (dl - dp < 4) 603 return CoderResult.OVERFLOW; 604 da[dp++] = (byte)0x1b; 605 da[dp++] = (byte)0x24; 606 da[dp++] = (byte)0x28; 607 da[dp++] = (byte)0x44; 608 currentMode = JISX0212_1990; 609 } 610 if (dl - dp < 2) 611 return CoderResult.OVERFLOW; 612 da[dp++] = (byte)(index >> 8); 613 da[dp++] = (byte)(index & 0xff); 614 } else { 615 if (Character.isSurrogate(c) && sgp.parse(c, sa, sp, sl) < 0) 616 return sgp.error(); 617 if (unmappableCharacterAction() 618 == CodingErrorAction.REPLACE 619 && currentMode != replaceMode) { 620 if (dl - dp < 3) 621 return CoderResult.OVERFLOW; 622 if (replaceMode == ASCII) { 623 da[dp++] = (byte)0x1b; 624 da[dp++] = (byte)0x28; 625 da[dp++] = (byte)0x42; 626 } else { 627 da[dp++] = (byte)0x1b; 628 da[dp++] = (byte)0x24; 629 da[dp++] = (byte)0x42; 630 } 631 currentMode = replaceMode; 632 } 633 if (Character.isSurrogate(c)) 634 return sgp.unmappableResult(); 635 return CoderResult.unmappableForLength(1); 636 } 637 } 638 sp++; 639 } 640 return CoderResult.UNDERFLOW; 641 } finally { 642 src.position(sp - src.arrayOffset()); 643 dst.position(dp - dst.arrayOffset()); 644 } 645 } 646 647 private CoderResult encodeBufferLoop(CharBuffer src, 648 ByteBuffer dst) 649 { 650 int mark = src.position(); 651 try { 652 while (src.hasRemaining()) { 653 char c = src.get(); 654 655 if (c <= '\u007F') { 656 if (currentMode != ASCII) { 657 if (dst.remaining() < 3) 658 return CoderResult.OVERFLOW; 659 dst.put((byte)0x1b); 660 dst.put((byte)0x28); 661 dst.put((byte)0x42); 662 currentMode = ASCII; 663 } 664 if (dst.remaining() < 1) 665 return CoderResult.OVERFLOW; 666 dst.put((byte)c); 667 } else if (c >= 0xff61 && c <= 0xff9f && doSBKANA) { 668 //Is it a single byte kana? 669 if (currentMode != JISX0201_1976_KANA) { 670 if (dst.remaining() < 3) 671 return CoderResult.OVERFLOW; 672 dst.put((byte)0x1b); 673 dst.put((byte)0x28); 674 dst.put((byte)0x49); 675 currentMode = JISX0201_1976_KANA; 676 } 677 if (dst.remaining() < 1) 678 return CoderResult.OVERFLOW; 679 dst.put((byte)(c - 0xff40)); 680 } else if (c == '\u00a5' || c == '\u203E') { 681 if (currentMode != JISX0201_1976) { 682 if (dst.remaining() < 3) 683 return CoderResult.OVERFLOW; 684 dst.put((byte)0x1b); 685 dst.put((byte)0x28); 686 dst.put((byte)0x4a); 687 currentMode = JISX0201_1976; 688 } 689 if (dst.remaining() < 1) 690 return CoderResult.OVERFLOW; 691 dst.put((c == '\u00A5')?(byte)0x5C:(byte)0x7e); 692 } else { 693 int index = enc0208.encodeChar(c); 694 if (index != UNMAPPABLE_ENCODING) { 695 if (currentMode != JISX0208_1983) { 696 if (dst.remaining() < 3) 697 return CoderResult.OVERFLOW; 698 dst.put((byte)0x1b); 699 dst.put((byte)0x24); 700 dst.put((byte)0x42); 701 currentMode = JISX0208_1983; 702 } 703 if (dst.remaining() < 2) 704 return CoderResult.OVERFLOW; 705 dst.put((byte)(index >> 8)); 706 dst.put((byte)(index & 0xff)); 707 } else if (enc0212 != null && 708 (index = enc0212.encodeChar(c)) != UNMAPPABLE_ENCODING) { 709 if (currentMode != JISX0212_1990) { 710 if (dst.remaining() < 4) 711 return CoderResult.OVERFLOW; 712 dst.put((byte)0x1b); 713 dst.put((byte)0x24); 714 dst.put((byte)0x28); 715 dst.put((byte)0x44); 716 currentMode = JISX0212_1990; 717 } 718 if (dst.remaining() < 2) 719 return CoderResult.OVERFLOW; 720 dst.put((byte)(index >> 8)); 721 dst.put((byte)(index & 0xff)); 722 } else { 723 if (Character.isSurrogate(c) && sgp.parse(c, src) < 0) 724 return sgp.error(); 725 if (unmappableCharacterAction() == CodingErrorAction.REPLACE 726 && currentMode != replaceMode) { 727 if (dst.remaining() < 3) 728 return CoderResult.OVERFLOW; 729 if (replaceMode == ASCII) { 730 dst.put((byte)0x1b); 731 dst.put((byte)0x28); 732 dst.put((byte)0x42); 733 } else { 734 dst.put((byte)0x1b); 735 dst.put((byte)0x24); 736 dst.put((byte)0x42); 737 } 738 currentMode = replaceMode; 739 } 740 if (Character.isSurrogate(c)) 741 return sgp.unmappableResult(); 742 return CoderResult.unmappableForLength(1); 743 } 744 } 745 mark++; 746 } 747 return CoderResult.UNDERFLOW; 748 } finally { 749 src.position(mark); 750 } 751 } 752 753 protected CoderResult encodeLoop(CharBuffer src, 754 ByteBuffer dst) 755 { 756 if (src.hasArray() && dst.hasArray()) 757 return encodeArrayLoop(src, dst); 758 else 759 return encodeBufferLoop(src, dst); 760 } 761 } 762 }