@@ -173,7 +173,8 @@ static Point decode(@Nonnull final String argMapcode,
173173
174174 private static final int CCODE_EARTH = 540 ;
175175
176- private final static int [] decode_chars = {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
176+ private final static int [] DECODE_CHARS = {
177+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
177178 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
178179 -1 , -1 , -1 , -1 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -2 , 10 , 11 , 12 , -3 , 13 , 14 , 15 ,
179180 1 , 16 , 17 , 18 , 19 , 20 , 0 , 21 , 22 , 23 , 24 , 25 , -4 , 26 , 27 , 28 , 29 , 30 , -1 , -1 , -1 , -1 , -1 , -1 , -2 , 10 , 11 ,
@@ -197,6 +198,23 @@ public Unicode2Ascii(final int min, final int max, @Nullable final String conver
197198 }
198199 }
199200
201+ private final static int [][] ASCII2LANGUAGE = {
202+ {0x0041 , 0x0042 , 0x0043 , 0x0044 , 0x0045 , 0x0046 , 0x0047 , 0x0048 , 0x0049 , 0x004a , 0x004b , 0x004c , 0x004d , 0x004e , 0x004f , 0x0050 , 0x0051 , 0x0052 , 0x0053 , 0x0054 , 0x0055 , 0x0056 , 0x0057 , 0x0058 , 0x0059 , 0x005a , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // roman
203+ {0x0391 , 0x0392 , 0x039e , 0x0394 , 0x003f , 0x0395 , 0x0393 , 0x0397 , 0x0399 , 0x03a0 , 0x039a , 0x039b , 0x039c , 0x039d , 0x039f , 0x03a1 , 0x0398 , 0x03a8 , 0x03a3 , 0x03a4 , 0x003f , 0x03a6 , 0x03a9 , 0x03a7 , 0x03a5 , 0x0396 , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // greek
204+ {0x0410 , 0x0412 , 0x0421 , 0x0414 , 0x0415 , 0x0416 , 0x0413 , 0x041d , 0x0418 , 0x041f , 0x041a , 0x041b , 0x041c , 0x0417 , 0x041e , 0x0420 , 0x0424 , 0x042f , 0x0426 , 0x0422 , 0x042d , 0x0427 , 0x0428 , 0x0425 , 0x0423 , 0x0411 , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // cyrillic
205+ {0x05d0 , 0x05d1 , 0x05d2 , 0x05d3 , 0x05e3 , 0x05d4 , 0x05d6 , 0x05d7 , 0x05d5 , 0x05d8 , 0x05d9 , 0x05da , 0x05db , 0x05dc , 0x05e1 , 0x05dd , 0x05de , 0x05e0 , 0x05e2 , 0x05e4 , 0x05e5 , 0x05e6 , 0x05e7 , 0x05e8 , 0x05e9 , 0x05ea , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // hebrew
206+ {0x0905 , 0x0915 , 0x0917 , 0x0918 , 0x090f , 0x091a , 0x091c , 0x091f , 0x003f , 0x0920 , 0x0923 , 0x0924 , 0x0926 , 0x0927 , 0x003f , 0x0928 , 0x092a , 0x092d , 0x092e , 0x0930 , 0x092b , 0x0932 , 0x0935 , 0x0938 , 0x0939 , 0x0921 , 0x0966 , 0x0967 , 0x0968 , 0x0969 , 0x096a , 0x096b , 0x096c , 0x096d , 0x096e , 0x096f }, // hindi
207+ {0x0d12 , 0x0d15 , 0x0d16 , 0x0d17 , 0x0d0b , 0x0d1a , 0x0d1c , 0x0d1f , 0x0d07 , 0x0d21 , 0x0d24 , 0x0d25 , 0x0d26 , 0x0d27 , 0x0d20 , 0x0d28 , 0x0d2e , 0x0d30 , 0x0d31 , 0x0d32 , 0x0d09 , 0x0d34 , 0x0d35 , 0x0d36 , 0x0d38 , 0x0d39 , 0x0d66 , 0x0d67 , 0x0d68 , 0x0d69 , 0x0d6a , 0x0d6b , 0x0d6c , 0x0d6d , 0x0d6e , 0x0d6f }, // malay
208+ {0x10a0 , 0x10a1 , 0x10a3 , 0x10a6 , 0x10a4 , 0x10a9 , 0x10ab , 0x10ac , 0x10b3 , 0x10ae , 0x10b0 , 0x10b1 , 0x10b2 , 0x10b4 , 0x10ad , 0x10b5 , 0x10b6 , 0x10b7 , 0x10b8 , 0x10b9 , 0x10a8 , 0x10ba , 0x10bb , 0x10bd , 0x10be , 0x10bf , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // Georgian
209+ {0x30a2 , 0x30ab , 0x30ad , 0x30af , 0x30aa , 0x30b1 , 0x30b3 , 0x30b5 , 0x30a4 , 0x30b9 , 0x30c1 , 0x30c8 , 0x30ca , 0x30cc , 0x30a6 , 0x30d2 , 0x30d5 , 0x30d8 , 0x30db , 0x30e1 , 0x30a8 , 0x30e2 , 0x30e8 , 0x30e9 , 0x30ed , 0x30f2 , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // Katakana
210+ {0x0e30 , 0x0e01 , 0x0e02 , 0x0e04 , 0x0e32 , 0x0e07 , 0x0e08 , 0x0e09 , 0x0e31 , 0x0e0a , 0x0e11 , 0x0e14 , 0x0e16 , 0x0e17 , 0x0e0d , 0x0e18 , 0x0e1a , 0x0e1c , 0x0e21 , 0x0e23 , 0x0e2c , 0x0e25 , 0x0e27 , 0x0e2d , 0x0e2e , 0x0e2f , 0x0e50 , 0x0e51 , 0x0e52 , 0x0e53 , 0x0e54 , 0x0e55 , 0x0e56 , 0x0e57 , 0x0e58 , 0x0e59 }, // Thai
211+ {0x0eb0 , 0x0e81 , 0x0e82 , 0x0e84 , 0x0ec3 , 0x0e87 , 0x0e88 , 0x0e8a , 0x0ec4 , 0x0e8d , 0x0e94 , 0x0e97 , 0x0e99 , 0x0e9a , 0x0ec6 , 0x0e9c , 0x0e9e , 0x0ea1 , 0x0ea2 , 0x0ea3 , 0x0ebd , 0x0ea7 , 0x0eaa , 0x0eab , 0x0ead , 0x0eaf , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // Laos
212+ {0x0556 , 0x0532 , 0x0533 , 0x0534 , 0x0535 , 0x0538 , 0x0539 , 0x053a , 0x053b , 0x053d , 0x053f , 0x0540 , 0x0541 , 0x0543 , 0x0555 , 0x0547 , 0x0548 , 0x054a , 0x054d , 0x054e , 0x0545 , 0x054f , 0x0550 , 0x0551 , 0x0552 , 0x0553 , 0x0030 , 0x0031 , 0x0032 , 0x0033 , 0x0034 , 0x0035 , 0x0036 , 0x0037 , 0x0038 , 0x0039 }, // armenian
213+ {0x0985 , 0x098c , 0x0995 , 0x0996 , 0x098f , 0x0997 , 0x0999 , 0x099a , 0x003f , 0x099d , 0x09a0 , 0x09a1 , 0x09a2 , 0x09a3 , 0x003f , 0x09a4 , 0x09a5 , 0x09a6 , 0x09a8 , 0x09aa , 0x0993 , 0x09ac , 0x09ad , 0x09af , 0x09b2 , 0x09b9 , 0x09e6 , 0x09e7 , 0x09e8 , 0x09e9 , 0x09ea , 0x09eb , 0x09ec , 0x09ed , 0x09ee , 0x09ef }, // Bengali
214+ {0x0a05 , 0x0a15 , 0x0a17 , 0x0a18 , 0x0a0f , 0x0a1a , 0x0a1c , 0x0a1f , 0x003f , 0x0a20 , 0x0a23 , 0x0a24 , 0x0a26 , 0x0a27 , 0x003f , 0x0a28 , 0x0a2a , 0x0a2d , 0x0a2e , 0x0a30 , 0x0a2b , 0x0a32 , 0x0a35 , 0x0a38 , 0x0a39 , 0x0a21 , 0x0a66 , 0x0a67 , 0x0a68 , 0x0a69 , 0x0a6a , 0x0a6b , 0x0a6c , 0x0a6d , 0x0a6e , 0x0a6f }, // Gurmukhi
215+ {0x0f58 , 0x0f40 , 0x0f41 , 0x0f42 , 0x0f64 , 0x0f44 , 0x0f45 , 0x0f46 , 0x003f , 0x0f47 , 0x0f4a , 0x0f4c , 0x0f4e , 0x0f4f , 0x003f , 0x0f51 , 0x0f53 , 0x0f54 , 0x0f56 , 0x0f5e , 0x0f65 , 0x0f5f , 0x0f61 , 0x0f62 , 0x0f63 , 0x0f66 , 0x0f20 , 0x0f21 , 0x0f22 , 0x0f23 , 0x0f24 , 0x0f25 , 0x0f26 , 0x0f27 , 0x0f28 , 0x0f29 }, // Tibetan
216+ };
217+
200218 private final static Unicode2Ascii [] UNICODE2ASCII = {
201219 new Unicode2Ascii (0x0041 , 0x005a , "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ), // Roman
202220 new Unicode2Ascii (0x0391 , 0x03a9 , "ABGDFZHQIKLMNCOJP?STYVXRW" ), // Greek
@@ -331,7 +349,7 @@ private static Point decodeNameless(final String str, final int firstrec, final
331349 boolean swapletters = false ;
332350
333351 if ((mapcoderData .getCodex () != 21 ) && (a <= 31 )) {
334- final int offset = decode_chars [(int ) result .charAt (0 )];
352+ final int offset = DECODE_CHARS [(int ) result .charAt (0 )];
335353
336354 if (offset < (r * (p + 1 ))) {
337355 nrX = offset / (p + 1 );
@@ -340,7 +358,7 @@ private static Point decodeNameless(final String str, final int firstrec, final
340358 nrX = r + ((offset - (r * (p + 1 ))) / p );
341359 }
342360 } else if ((mapcoderData .getCodex () != 21 ) && (a < 62 )) {
343- nrX = decode_chars [(int ) result .charAt (0 )];
361+ nrX = DECODE_CHARS [(int ) result .charAt (0 )];
344362 if (nrX < (62 - a )) {
345363 swapletters = mapcoderData .getCodex () == 22 ;
346364 } else {
@@ -513,11 +531,11 @@ private static String aeuUnpack(final String argStr) {
513531 // less than 2 letters after dot
514532
515533 if (str .charAt (0 ) == 'A' ) { // v1.50
516- int v1 = decode_chars [(int ) str .charAt (lastpos )];
534+ int v1 = DECODE_CHARS [(int ) str .charAt (lastpos )];
517535 if (v1 < 0 ) {
518536 v1 = 31 ;
519537 }
520- int v2 = decode_chars [(int ) str .charAt (lastpos - 1 )];
538+ int v2 = DECODE_CHARS [(int ) str .charAt (lastpos - 1 )];
521539 if (v2 < 0 ) {
522540 v2 = 31 ;
523541 }
@@ -548,7 +566,7 @@ private static String aeuUnpack(final String argStr) {
548566 } else if (e == 'U' ) {
549567 v += 33 ;
550568 } else {
551- final int ve = decode_chars [(int ) str .charAt (lastpos )];
569+ final int ve = DECODE_CHARS [(int ) str .charAt (lastpos )];
552570 if (ve < 0 ) {
553571 return "" ;
554572 }
@@ -569,9 +587,10 @@ private static String aeuUnpack(final String argStr) {
569587
570588 for (int v = 0 ; v <= lastpos ; v ++) {
571589 if (v != dotpos ) {
572- if (decode_chars [(int ) str .charAt (v )] < 0 ) {
590+ final int i = (int ) str .charAt (v );
591+ if (DECODE_CHARS [i ] < 0 ) {
573592 return "" ; // bad char!
574- } else if (voweled && (decode_chars [(int ) str .charAt (v )] > 9 )) {
593+ } else if (voweled && (DECODE_CHARS [(int ) str .charAt (v )] > 9 )) {
575594 return "" ; // nonodigit!
576595 }
577596 }
@@ -618,10 +637,43 @@ static String decodeUTF16(final String str) {
618637 return asciibuf .toString ();
619638 }
620639
640+ static String encodeUTF16 (final String string , final int alphabet ) {
641+ final StringBuilder sb = new StringBuilder ();
642+ for (char ch : string .toCharArray ()) {
643+ ch = Character .toUpperCase (ch );
644+ if (ch > 'Z' ) {
645+ // Not in any valid range?
646+ sb .append ('?' );
647+ } else if (ch < 'A' ) {
648+ // Valid but not a letter (e.g. a dot, a space...).
649+ // Leave untranslated.
650+ sb .append (ch );
651+ } else {
652+ sb .append ((char ) ASCII2LANGUAGE [alphabet ][(int ) ch - (int ) 'A' ]);
653+ }
654+ }
655+ return sb .toString ();
656+ }
657+
658+ static String encodeToAlphabetCode (final String mapcode , int alphabetCode ) {
659+ if (ASCII2LANGUAGE [alphabetCode ][4 ] == 0x003f ) {
660+ if (mapcode .matches ("^.*[EUeu].*" )) {
661+ final String unpacked = aeuUnpack (mapcode );
662+ if (unpacked .isEmpty ()) {
663+ throw new AssertionError ("encodeToAlphabetCode: cannot encode '" + mapcode +
664+ "' to alphabet " + alphabetCode + ' ' + Alphabet .fromCode (alphabetCode ));
665+ }
666+ final String packed = Encoder .aeuPack (unpacked , true );
667+ return encodeUTF16 (packed , alphabetCode );
668+ }
669+ }
670+ return encodeUTF16 (mapcode , alphabetCode );
671+ }
672+
621673 @ Nonnull
622674 private static Point decodeTriple (final String str ) {
623675 //noinspection NumericCastThatLosesPrecision
624- final byte c1 = (byte ) decode_chars [(int ) str .charAt (0 )];
676+ final byte c1 = (byte ) DECODE_CHARS [(int ) str .charAt (0 )];
625677 final int x = fastDecode (str .substring (1 ));
626678 if (c1 < 24 ) {
627679 return Point .fromMicroDeg (((c1 / 6 ) * 34 ) + (x % 34 ), ((c1 % 6 ) * 28 ) + (x / 34 ));
@@ -655,10 +707,10 @@ private static int fastDecode(final String code)
655707 {
656708 return value ;
657709 }
658- if (decode_chars [c ] < 0 ) {
710+ if (DECODE_CHARS [c ] < 0 ) {
659711 return -1 ;
660712 }
661- value = (value * 31 ) + decode_chars [c ];
713+ value = (value * 31 ) + DECODE_CHARS [c ];
662714 }
663715 return value ;
664716 }
@@ -667,7 +719,7 @@ private static int fastDecode(final String code)
667719 private static Point add2res (final int y , final int x , final int dividerx4 , final int dividery , final int ydirection , final String extrapostfix ) {
668720 if (!extrapostfix .isEmpty ()) {
669721 int c1 = (int ) extrapostfix .charAt (0 );
670- c1 = decode_chars [c1 ];
722+ c1 = DECODE_CHARS [c1 ];
671723 if (c1 < 0 ) {
672724 c1 = 0 ;
673725 } else if (c1 > 29 ) {
@@ -677,7 +729,7 @@ private static Point add2res(final int y, final int x, final int dividerx4, fina
677729 final int x1 = c1 % 5 ;
678730 int c2 = (extrapostfix .length () == 2 ) ? (int ) extrapostfix .charAt (1 ) : 72 ; // 72='H'=code
679731 // 15=(3+2*6)
680- c2 = decode_chars [c2 ];
732+ c2 = DECODE_CHARS [c2 ];
681733 if (c2 < 0 ) {
682734 c2 = 0 ;
683735 } else if (c2 > 29 ) {
0 commit comments