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