TYPO3  7.6
idna_convert.class.php
Go to the documentation of this file.
1 <?php
2 // {{{ license
3 
4 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
5 //
6 // +----------------------------------------------------------------------+
7 // | This library is free software; you can redistribute it and/or modify |
8 // | it under the terms of the GNU Lesser General Public License as |
9 // | published by the Free Software Foundation; either version 2.1 of the |
10 // | License, or (at your option) any later version. |
11 // | |
12 // | This library is distributed in the hope that it will be useful, but |
13 // | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 // | Lesser General Public License for more details. |
16 // | |
17 // | You should have received a copy of the GNU Lesser General Public |
18 // | License along with this library; if not, write to the Free Software |
19 // | Foundation, Inc., 51 Franklin St, Boston, MA 02110, United States |
20 // +----------------------------------------------------------------------+
21 //
22 
23 // }}}
24 
53 {
54  // NP See below
55 
56  // Internal settings, do not mess with them
57  protected $_punycode_prefix = 'xn--';
58  protected $_invalid_ucs = 0x80000000;
59  protected $_max_ucs = 0x10FFFF;
60  protected $_base = 36;
61  protected $_tmin = 1;
62  protected $_tmax = 26;
63  protected $_skew = 38;
64  protected $_damp = 700;
65  protected $_initial_bias = 72;
66  protected $_initial_n = 0x80;
67  protected $_sbase = 0xAC00;
68  protected $_lbase = 0x1100;
69  protected $_vbase = 0x1161;
70  protected $_tbase = 0x11A7;
71  protected $_lcount = 19;
72  protected $_vcount = 21;
73  protected $_tcount = 28;
74  protected $_ncount = 588; // _vcount * _tcount
75  protected $_scount = 11172; // _lcount * _tcount * _vcount
76  protected $_error = false;
77 
78  protected static $_mb_string_overload = null;
79 
80  // See {@link set_paramter()} for details of how to change the following
81  // settings from within your script / application
82  protected $_api_encoding = 'utf8'; // Default input charset is UTF-8
83  protected $_allow_overlong = false; // Overlong UTF-8 encodings are forbidden
84  protected $_strict_mode = false; // Behave strict or not
85  protected $_idn_version = 2003; // Can be either 2003 (old, default) or 2008
86 
94  public function __construct($options = false)
95  {
96  $this->slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount;
97  // If parameters are given, pass these to the respective method
98  if (is_array($options)) {
99  $this->set_parameter($options);
100  }
101 
102  // populate mbstring overloading cache if not set
103  if (self::$_mb_string_overload === null) {
104  self::$_mb_string_overload = (extension_loaded('mbstring')
105  && (ini_get('mbstring.func_overload') & 0x02) === 0x02);
106  }
107  }
108 
124  public function set_parameter($option, $value = false)
125  {
126  if (!is_array($option)) {
127  $option = array($option => $value);
128  }
129  foreach ($option as $k => $v) {
130  switch ($k) {
131  case 'encoding':
132  switch ($v) {
133  case 'utf8':
134  case 'ucs4_string':
135  case 'ucs4_array':
136  $this->_api_encoding = $v;
137  break;
138  default:
139  $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k);
140  return false;
141  }
142  break;
143  case 'overlong':
144  $this->_allow_overlong = ($v) ? true : false;
145  break;
146  case 'strict':
147  $this->_strict_mode = ($v) ? true : false;
148  break;
149  case 'idn_version':
150  if (in_array($v, array('2003', '2008'))) {
151  $this->_idn_version = $v;
152  } else {
153  $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k);
154  }
155  break;
156  case 'encode_german_sz': // Deprecated
157  if (!$v) {
158  self::$NP['replacemaps'][0xDF] = array(0x73, 0x73);
159  } else {
160  unset(self::$NP['replacemaps'][0xDF]);
161  }
162  break;
163  default:
164  $this->_error('Set Parameter: Unknown option '.$k);
165  return false;
166  }
167  }
168  return true;
169  }
170 
177  public function decode($input, $one_time_encoding = false)
178  {
179  // Optionally set
180  if ($one_time_encoding) {
181  switch ($one_time_encoding) {
182  case 'utf8':
183  case 'ucs4_string':
184  case 'ucs4_array':
185  break;
186  default:
187  $this->_error('Unknown encoding '.$one_time_encoding);
188  return false;
189  }
190  }
191  // Make sure to drop any newline characters around
192  $input = trim($input);
193 
194  // Negotiate input and try to determine, whether it is a plain string,
195  // an email address or something like a complete URL
196  if (strpos($input, '@')) { // Maybe it is an email address
197  // No no in strict mode
198  if ($this->_strict_mode) {
199  $this->_error('Only simple domain name parts can be handled in strict mode');
200  return false;
201  }
202  list ($email_pref, $input) = explode('@', $input, 2);
203  $arr = explode('.', $input);
204  foreach ($arr as $k => $v) {
205  if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
206  $conv = $this->_decode($v);
207  if ($conv) $arr[$k] = $conv;
208  }
209  }
210  $input = join('.', $arr);
211  $arr = explode('.', $email_pref);
212  foreach ($arr as $k => $v) {
213  if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
214  $conv = $this->_decode($v);
215  if ($conv) $arr[$k] = $conv;
216  }
217  }
218  $email_pref = join('.', $arr);
219  $return = $email_pref . '@' . $input;
220  } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters)
221  // No no in strict mode
222  if ($this->_strict_mode) {
223  $this->_error('Only simple domain name parts can be handled in strict mode');
224  return false;
225  }
226  $parsed = parse_url($input);
227  if (isset($parsed['host'])) {
228  $arr = explode('.', $parsed['host']);
229  foreach ($arr as $k => $v) {
230  $conv = $this->_decode($v);
231  if ($conv) $arr[$k] = $conv;
232  }
233  $parsed['host'] = join('.', $arr);
234  $return =
235  (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'))
236  .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@')
237  .$parsed['host']
238  .(empty($parsed['port']) ? '' : ':'.$parsed['port'])
239  .(empty($parsed['path']) ? '' : $parsed['path'])
240  .(empty($parsed['query']) ? '' : '?'.$parsed['query'])
241  .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']);
242  } else { // parse_url seems to have failed, try without it
243  $arr = explode('.', $input);
244  foreach ($arr as $k => $v) {
245  $conv = $this->_decode($v);
246  $arr[$k] = ($conv) ? $conv : $v;
247  }
248  $return = join('.', $arr);
249  }
250  } else { // Otherwise we consider it being a pure domain name string
251  $return = $this->_decode($input);
252  if (!$return) $return = $input;
253  }
254  // The output is UTF-8 by default, other output formats need conversion here
255  // If one time encoding is given, use this, else the objects property
256  switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) {
257  case 'utf8':
258  return $return;
259  break;
260  case 'ucs4_string':
261  return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return));
262  break;
263  case 'ucs4_array':
264  return $this->_utf8_to_ucs4($return);
265  break;
266  default:
267  $this->_error('Unsupported output format');
268  return false;
269  }
270  }
271 
278  public function encode($decoded, $one_time_encoding = false)
279  {
280  // Forcing conversion of input to UCS4 array
281  // If one time encoding is given, use this, else the objects property
282  switch ($one_time_encoding ? $one_time_encoding : $this->_api_encoding) {
283  case 'utf8':
284  $decoded = $this->_utf8_to_ucs4($decoded);
285  break;
286  case 'ucs4_string':
287  $decoded = $this->_ucs4_string_to_ucs4($decoded);
288  case 'ucs4_array':
289  break;
290  default:
291  $this->_error('Unsupported input format: '.($one_time_encoding ? $one_time_encoding : $this->_api_encoding));
292  return false;
293  }
294 
295  // No input, no output, what else did you expect?
296  if (empty($decoded)) return '';
297 
298  // Anchors for iteration
299  $last_begin = 0;
300  // Output string
301  $output = '';
302  foreach ($decoded as $k => $v) {
303  // Make sure to use just the plain dot
304  switch($v) {
305  case 0x3002:
306  case 0xFF0E:
307  case 0xFF61:
308  $decoded[$k] = 0x2E;
309  // Right, no break here, the above are converted to dots anyway
310  // Stumbling across an anchoring character
311  case 0x2E:
312  case 0x2F:
313  case 0x3A:
314  case 0x3F:
315  case 0x40:
316  // Neither email addresses nor URLs allowed in strict mode
317  if ($this->_strict_mode) {
318  $this->_error('Neither email addresses nor URLs are allowed in strict mode.');
319  return false;
320  } else {
321  // Skip first char
322  if ($k) {
323  $encoded = '';
324  $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin)));
325  if ($encoded) {
326  $output .= $encoded;
327  } else {
328  $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin)));
329  }
330  $output .= chr($decoded[$k]);
331  }
332  $last_begin = $k + 1;
333  }
334  }
335  }
336  // Catch the rest of the string
337  if ($last_begin) {
338  $inp_len = sizeof($decoded);
339  $encoded = '';
340  $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
341  if ($encoded) {
342  $output .= $encoded;
343  } else {
344  $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
345  }
346  return $output;
347  } else {
348  if ($output = $this->_encode($decoded)) {
349  return $output;
350  } else {
351  return $this->_ucs4_to_utf8($decoded);
352  }
353  }
354  }
355 
363  public function encode_uri($uri)
364  {
365  $parsed = parse_url($uri);
366  if (!isset($parsed['host'])) {
367  $this->_error('The given string does not look like a URI');
368  return false;
369  }
370  $arr = explode('.', $parsed['host']);
371  foreach ($arr as $k => $v) {
372  $conv = $this->encode($v, 'utf8');
373  if ($conv) $arr[$k] = $conv;
374  }
375  $parsed['host'] = join('.', $arr);
376  $return =
377  (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'))
378  .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@')
379  .$parsed['host']
380  .(empty($parsed['port']) ? '' : ':'.$parsed['port'])
381  .(empty($parsed['path']) ? '' : $parsed['path'])
382  .(empty($parsed['query']) ? '' : '?'.$parsed['query'])
383  .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']);
384  return $return;
385  }
386 
392  public function get_last_error()
393  {
394  return $this->_error;
395  }
396 
402  protected function _decode($encoded)
403  {
404  $decoded = array();
405  // find the Punycode prefix
406  if (!preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $encoded)) {
407  $this->_error('This is not a punycode string');
408  return false;
409  }
410  $encode_test = preg_replace('!^'.preg_quote($this->_punycode_prefix, '!').'!', '', $encoded);
411  // If nothing left after removing the prefix, it is hopeless
412  if (!$encode_test) {
413  $this->_error('The given encoded string was empty');
414  return false;
415  }
416  // Find last occurence of the delimiter
417  $delim_pos = strrpos($encoded, '-');
418  if ($delim_pos > self::byteLength($this->_punycode_prefix)) {
419  for ($k = self::byteLength($this->_punycode_prefix); $k < $delim_pos; ++$k) {
420  $decoded[] = ord($encoded{$k});
421  }
422  }
423  $deco_len = count($decoded);
424  $enco_len = self::byteLength($encoded);
425 
426  // Wandering through the strings; init
427  $is_first = true;
428  $bias = $this->_initial_bias;
429  $idx = 0;
430  $char = $this->_initial_n;
431 
432  for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
433  for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) {
434  $digit = $this->_decode_digit($encoded{$enco_idx++});
435  $idx += $digit * $w;
436  $t = ($k <= $bias) ? $this->_tmin :
437  (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias));
438  if ($digit < $t) break;
439  $w = (int) ($w * ($this->_base - $t));
440  }
441  $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first);
442  $is_first = false;
443  $char += (int) ($idx / ($deco_len + 1));
444  $idx %= ($deco_len + 1);
445  if ($deco_len > 0) {
446  // Make room for the decoded char
447  for ($i = $deco_len; $i > $idx; $i--) $decoded[$i] = $decoded[($i - 1)];
448  }
449  $decoded[$idx++] = $char;
450  }
451  return $this->_ucs4_to_utf8($decoded);
452  }
453 
459  protected function _encode($decoded)
460  {
461  // We cannot encode a domain name containing the Punycode prefix
462  $extract = self::byteLength($this->_punycode_prefix);
463  $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix);
464  $check_deco = array_slice($decoded, 0, $extract);
465 
466  if ($check_pref == $check_deco) {
467  $this->_error('This is already a punycode string');
468  return false;
469  }
470  // We will not try to encode strings consisting of basic code points only
471  $encodable = false;
472  foreach ($decoded as $k => $v) {
473  if ($v > 0x7a) {
474  $encodable = true;
475  break;
476  }
477  }
478  if (!$encodable) {
479  $this->_error('The given string does not contain encodable chars');
480  return false;
481  }
482  // Do NAMEPREP
483  $decoded = $this->_nameprep($decoded);
484  if (!$decoded || !is_array($decoded)) return false; // NAMEPREP failed
485  $deco_len = count($decoded);
486  if (!$deco_len) return false; // Empty array
487  $codecount = 0; // How many chars have been consumed
488  $encoded = '';
489  // Copy all basic code points to output
490  for ($i = 0; $i < $deco_len; ++$i) {
491  $test = $decoded[$i];
492  // Will match [-0-9a-zA-Z]
493  if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B)
494  || (0x60 < $test && $test <= 0x7B) || (0x2D == $test)) {
495  $encoded .= chr($decoded[$i]);
496  $codecount++;
497  }
498  }
499  if ($codecount == $deco_len) return $encoded; // All codepoints were basic ones
500 
501  // Start with the prefix; copy it to output
502  $encoded = $this->_punycode_prefix.$encoded;
503  // If we have basic code points in output, add an hyphen to the end
504  if ($codecount) $encoded .= '-';
505  // Now find and encode all non-basic code points
506  $is_first = true;
507  $cur_code = $this->_initial_n;
508  $bias = $this->_initial_bias;
509  $delta = 0;
510  while ($codecount < $deco_len) {
511  // Find the smallest code point >= the current code point and
512  // remember the last ouccrence of it in the input
513  for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) {
514  if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) {
515  $next_code = $decoded[$i];
516  }
517  }
518  $delta += ($next_code - $cur_code) * ($codecount + 1);
519  $cur_code = $next_code;
520 
521  // Scan input again and encode all characters whose code point is $cur_code
522  for ($i = 0; $i < $deco_len; $i++) {
523  if ($decoded[$i] < $cur_code) {
524  $delta++;
525  } elseif ($decoded[$i] == $cur_code) {
526  for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) {
527  $t = ($k <= $bias) ? $this->_tmin :
528  (($k >= $bias + $this->_tmax) ? $this->_tmax : $k - $bias);
529  if ($q < $t) break;
530  $encoded .= $this->_encode_digit(intval($t + (($q - $t) % ($this->_base - $t)))); //v0.4.5 Changed from ceil() to intval()
531  $q = (int) (($q - $t) / ($this->_base - $t));
532  }
533  $encoded .= $this->_encode_digit($q);
534  $bias = $this->_adapt($delta, $codecount+1, $is_first);
535  $codecount++;
536  $delta = 0;
537  $is_first = false;
538  }
539  }
540  $delta++;
541  $cur_code++;
542  }
543  return $encoded;
544  }
545 
553  protected function _adapt($delta, $npoints, $is_first)
554  {
555  $delta = intval($is_first ? ($delta / $this->_damp) : ($delta / 2));
556  $delta += intval($delta / $npoints);
557  for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) {
558  $delta = intval($delta / ($this->_base - $this->_tmin));
559  }
560  return intval($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew));
561  }
562 
568  protected function _encode_digit($d)
569  {
570  return chr($d + 22 + 75 * ($d < 26));
571  }
572 
578  protected function _decode_digit($cp)
579  {
580  $cp = ord($cp);
581  return ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $this->_base));
582  }
583 
588  protected function _error($error = '')
589  {
590  $this->_error = $error;
591  }
592 
598  protected function _nameprep($input)
599  {
600  $output = array();
601  $error = false;
602  //
603  // Mapping
604  // Walking through the input array, performing the required steps on each of
605  // the input chars and putting the result into the output array
606  // While mapping required chars we apply the cannonical ordering
607  foreach ($input as $v) {
608  // Map to nothing == skip that code point
609  if (in_array($v, self::$NP['map_nothing'])) continue;
610  // Try to find prohibited input
611  if (in_array($v, self::$NP['prohibit']) || in_array($v, self::$NP['general_prohibited'])) {
612  $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
613  return false;
614  }
615  foreach (self::$NP['prohibit_ranges'] as $range) {
616  if ($range[0] <= $v && $v <= $range[1]) {
617  $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
618  return false;
619  }
620  }
621 
622  if (0xAC00 <= $v && $v <= 0xD7AF) {
623  // Hangul syllable decomposition
624  foreach ($this->_hangul_decompose($v) as $out) {
625  $output[] = (int) $out;
626  }
627  } elseif (($this->_idn_version == '2003') && isset(self::$NP['replacemaps'][$v])) {
628  // There's a decomposition mapping for that code point
629  // Decompositions only in version 2003 (original) of IDNA
630  foreach ($this->_apply_cannonical_ordering(self::$NP['replacemaps'][$v]) as $out) {
631  $output[] = (int) $out;
632  }
633  } else {
634  $output[] = (int) $v;
635  }
636  }
637  // Before applying any Combining, try to rearrange any Hangul syllables
638  $output = $this->_hangul_compose($output);
639  //
640  // Combine code points
641  //
642  $last_class = 0;
643  $last_starter = 0;
644  $out_len = count($output);
645  for ($i = 0; $i < $out_len; ++$i) {
646  $class = $this->_get_combining_class($output[$i]);
647  if ((!$last_class || $last_class > $class) && $class) {
648  // Try to match
649  $seq_len = $i - $last_starter;
650  $out = $this->_combine(array_slice($output, $last_starter, $seq_len));
651  // On match: Replace the last starter with the composed character and remove
652  // the now redundant non-starter(s)
653  if ($out) {
654  $output[$last_starter] = $out;
655  if (count($out) != $seq_len) {
656  for ($j = $i+1; $j < $out_len; ++$j) $output[$j-1] = $output[$j];
657  unset($output[$out_len]);
658  }
659  // Rewind the for loop by one, since there can be more possible compositions
660  $i--;
661  $out_len--;
662  $last_class = ($i == $last_starter) ? 0 : $this->_get_combining_class($output[$i-1]);
663  continue;
664  }
665  }
666  // The current class is 0
667  if (!$class) $last_starter = $i;
668  $last_class = $class;
669  }
670  return $output;
671  }
672 
679  protected function _hangul_decompose($char)
680  {
681  $sindex = (int) $char - $this->_sbase;
682  if ($sindex < 0 || $sindex >= $this->_scount) return array($char);
683  $result = array();
684  $result[] = (int) $this->_lbase + $sindex / $this->_ncount;
685  $result[] = (int) $this->_vbase + ($sindex % $this->_ncount) / $this->_tcount;
686  $T = intval($this->_tbase + $sindex % $this->_tcount);
687  if ($T != $this->_tbase) $result[] = $T;
688  return $result;
689  }
696  protected function _hangul_compose($input)
697  {
698  $inp_len = count($input);
699  if (!$inp_len) return array();
700  $result = array();
701  $last = (int) $input[0];
702  $result[] = $last; // copy first char from input to output
703 
704  for ($i = 1; $i < $inp_len; ++$i) {
705  $char = (int) $input[$i];
706  $sindex = $last - $this->_sbase;
707  $lindex = $last - $this->_lbase;
708  $vindex = $char - $this->_vbase;
709  $tindex = $char - $this->_tbase;
710  // Find out, whether two current characters are LV and T
711  if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount == 0)
712  && 0 <= $tindex && $tindex <= $this->_tcount) {
713  // create syllable of form LVT
714  $last += $tindex;
715  $result[(count($result) - 1)] = $last; // reset last
716  continue; // discard char
717  }
718  // Find out, whether two current characters form L and V
719  if (0 <= $lindex && $lindex < $this->_lcount && 0 <= $vindex && $vindex < $this->_vcount) {
720  // create syllable of form LV
721  $last = (int) $this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount;
722  $result[(count($result) - 1)] = $last; // reset last
723  continue; // discard char
724  }
725  // if neither case was true, just add the character
726  $last = $char;
727  $result[] = $char;
728  }
729  return $result;
730  }
731 
737  protected function _get_combining_class($char)
738  {
739  return isset(self::$NP['norm_combcls'][$char]) ? self::$NP['norm_combcls'][$char] : 0;
740  }
741 
747  protected function _apply_cannonical_ordering($input)
748  {
749  $swap = true;
750  $size = count($input);
751  while ($swap) {
752  $swap = false;
753  $last = $this->_get_combining_class(intval($input[0]));
754  for ($i = 0; $i < $size-1; ++$i) {
755  $next = $this->_get_combining_class(intval($input[$i+1]));
756  if ($next != 0 && $last > $next) {
757  // Move item leftward until it fits
758  for ($j = $i + 1; $j > 0; --$j) {
759  if ($this->_get_combining_class(intval($input[$j-1])) <= $next) break;
760  $t = intval($input[$j]);
761  $input[$j] = intval($input[$j-1]);
762  $input[$j-1] = $t;
763  $swap = true;
764  }
765  // Reentering the loop looking at the old character again
766  $next = $last;
767  }
768  $last = $next;
769  }
770  }
771  return $input;
772  }
773 
779  protected function _combine($input)
780  {
781  $inp_len = count($input);
782  if (0 == $inp_len) {
783  return false;
784  }
785  foreach (self::$NP['replacemaps'] as $np_src => $np_target) {
786  if ($np_target[0] != $input[0]) continue;
787  if (count($np_target) != $inp_len) continue;
788  $hit = false;
789  foreach ($input as $k2 => $v2) {
790  if ($v2 == $np_target[$k2]) {
791  $hit = true;
792  } else {
793  $hit = false;
794  break;
795  }
796  }
797  if ($hit) return $np_src;
798  }
799  return false;
800  }
801 
820  protected function _utf8_to_ucs4($input)
821  {
822  $output = array();
823  $out_len = 0;
824  $inp_len = self::byteLength($input);
825  $mode = 'next';
826  $test = 'none';
827  for ($k = 0; $k < $inp_len; ++$k) {
828  $v = ord($input{$k}); // Extract byte from input string
829  if ($v < 128) { // We found an ASCII char - put into stirng as is
830  $output[$out_len] = $v;
831  ++$out_len;
832  if ('add' == $mode) {
833  $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
834  return false;
835  }
836  continue;
837  }
838  if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
839  $start_byte = $v;
840  $mode = 'add';
841  $test = 'range';
842  if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
843  $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
844  $v = ($v - 192) << 6;
845  } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
846  $next_byte = 1;
847  $v = ($v - 224) << 12;
848  } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
849  $next_byte = 2;
850  $v = ($v - 240) << 18;
851  } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
852  $next_byte = 3;
853  $v = ($v - 248) << 24;
854  } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
855  $next_byte = 4;
856  $v = ($v - 252) << 30;
857  } else {
858  $this->_error('This might be UTF-8, but I don\'t understand it at byte '.$k);
859  return false;
860  }
861  if ('add' == $mode) {
862  $output[$out_len] = (int) $v;
863  ++$out_len;
864  continue;
865  }
866  }
867  if ('add' == $mode) {
868  if (!$this->_allow_overlong && $test == 'range') {
869  $test = 'none';
870  if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
871  $this->_error('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
872  return false;
873  }
874  }
875  if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
876  $v = ($v - 128) << ($next_byte * 6);
877  $output[($out_len - 1)] += $v;
878  --$next_byte;
879  } else {
880  $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
881  return false;
882  }
883  if ($next_byte < 0) {
884  $mode = 'next';
885  }
886  }
887  } // for
888  return $output;
889  }
890 
897  protected function _ucs4_to_utf8($input)
898  {
899  $output = '';
900  foreach ($input as $k => $v) {
901  if ($v < 128) { // 7bit are transferred literally
902  $output .= chr($v);
903  } elseif ($v < (1 << 11)) { // 2 bytes
904  $output .= chr(192+($v >> 6)).chr(128+($v & 63));
905  } elseif ($v < (1 << 16)) { // 3 bytes
906  $output .= chr(224+($v >> 12)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63));
907  } elseif ($v < (1 << 21)) { // 4 bytes
908  $output .= chr(240+($v >> 18)).chr(128+(($v >> 12) & 63)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63));
909  } else {
910  $this->_error('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k);
911  return false;
912  }
913  }
914  return $output;
915  }
916 
923  protected function _ucs4_to_ucs4_string($input)
924  {
925  $output = '';
926  // Take array values and split output to 4 bytes per value
927  // The bit mask is 255, which reads &11111111
928  foreach ($input as $v) {
929  $output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255);
930  }
931  return $output;
932  }
933 
940  protected function _ucs4_string_to_ucs4($input)
941  {
942  $output = array();
943  $inp_len = self::byteLength($input);
944  // Input length must be dividable by 4
945  if ($inp_len % 4) {
946  $this->_error('Input UCS4 string is broken');
947  return false;
948  }
949  // Empty input - return empty output
950  if (!$inp_len) return $output;
951  for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
952  // Increment output position every 4 input bytes
953  if (!($i % 4)) {
954  $out_len++;
955  $output[$out_len] = 0;
956  }
957  $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
958  }
959  return $output;
960  }
961 
969  protected static function byteLength($string)
970  {
971  if (self::$_mb_string_overload) {
972  return mb_strlen($string, '8bit');
973  }
974  return strlen((binary) $string);
975  }
976 
984  public function getInstance($params = array())
985  {
986  return new idna_convert($params);
987  }
988 
999  public function singleton($params = array())
1000  {
1001  static $instances;
1002  if (!isset($instances)) {
1003  $instances = array();
1004  }
1005  $signature = serialize($params);
1006  if (!isset($instances[$signature])) {
1007  $instances[$signature] = idna_convert::getInstance($params);
1008  }
1009  return $instances[$signature];
1010  }
1011 
1019  protected static $NP = array
1020  ('map_nothing' => array(0xAD, 0x34F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C
1021  ,0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07
1022  ,0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF
1023  )
1024  ,'general_prohibited' => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
1025  ,20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ,33, 34, 35, 36, 37, 38, 39, 40, 41, 42
1026  ,43, 44, 47, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126, 127, 0x3002
1027  )
1028  ,'prohibit' => array(0xA0, 0x340, 0x341, 0x6DD, 0x70F, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003
1029  ,0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x200E, 0x200F
1030  ,0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, 0x202F, 0x205F, 0x206A, 0x206B, 0x206C
1031  ,0x206D, 0x206E, 0x206F, 0x3000, 0xFEFF, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF
1032  ,0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE
1033  ,0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF
1034  ,0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xE0001, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF
1035  )
1036  ,'prohibit_ranges' => array(array(0x80, 0x9F), array(0x2060, 0x206F), array(0x1D173, 0x1D17A)
1037  ,array(0xE000, 0xF8FF) ,array(0xF0000, 0xFFFFD), array(0x100000, 0x10FFFD)
1038  ,array(0xFDD0, 0xFDEF), array(0xD800, 0xDFFF), array(0x2FF0, 0x2FFB), array(0xE0020, 0xE007F)
1039  )
1040  ,'replacemaps' => array(0x41 => array(0x61), 0x42 => array(0x62), 0x43 => array(0x63)
1041  ,0x44 => array(0x64), 0x45 => array(0x65), 0x46 => array(0x66), 0x47 => array(0x67)
1042  ,0x48 => array(0x68), 0x49 => array(0x69), 0x4A => array(0x6A), 0x4B => array(0x6B)
1043  ,0x4C => array(0x6C), 0x4D => array(0x6D), 0x4E => array(0x6E), 0x4F => array(0x6F)
1044  ,0x50 => array(0x70), 0x51 => array(0x71), 0x52 => array(0x72), 0x53 => array(0x73)
1045  ,0x54 => array(0x74), 0x55 => array(0x75), 0x56 => array(0x76), 0x57 => array(0x77)
1046  ,0x58 => array(0x78), 0x59 => array(0x79), 0x5A => array(0x7A), 0xB5 => array(0x3BC)
1047  ,0xC0 => array(0xE0), 0xC1 => array(0xE1), 0xC2 => array(0xE2), 0xC3 => array(0xE3)
1048  ,0xC4 => array(0xE4), 0xC5 => array(0xE5), 0xC6 => array(0xE6), 0xC7 => array(0xE7)
1049  ,0xC8 => array(0xE8), 0xC9 => array(0xE9), 0xCA => array(0xEA), 0xCB => array(0xEB)
1050  ,0xCC => array(0xEC), 0xCD => array(0xED), 0xCE => array(0xEE), 0xCF => array(0xEF)
1051  ,0xD0 => array(0xF0), 0xD1 => array(0xF1), 0xD2 => array(0xF2), 0xD3 => array(0xF3)
1052  ,0xD4 => array(0xF4), 0xD5 => array(0xF5), 0xD6 => array(0xF6), 0xD8 => array(0xF8)
1053  ,0xD9 => array(0xF9), 0xDA => array(0xFA), 0xDB => array(0xFB), 0xDC => array(0xFC)
1054  ,0xDD => array(0xFD), 0xDE => array(0xFE), 0xDF => array(0x73, 0x73)
1055  ,0x100 => array(0x101), 0x102 => array(0x103), 0x104 => array(0x105)
1056  ,0x106 => array(0x107), 0x108 => array(0x109), 0x10A => array(0x10B)
1057  ,0x10C => array(0x10D), 0x10E => array(0x10F), 0x110 => array(0x111)
1058  ,0x112 => array(0x113), 0x114 => array(0x115), 0x116 => array(0x117)
1059  ,0x118 => array(0x119), 0x11A => array(0x11B), 0x11C => array(0x11D)
1060  ,0x11E => array(0x11F), 0x120 => array(0x121), 0x122 => array(0x123)
1061  ,0x124 => array(0x125), 0x126 => array(0x127), 0x128 => array(0x129)
1062  ,0x12A => array(0x12B), 0x12C => array(0x12D), 0x12E => array(0x12F)
1063  ,0x130 => array(0x69, 0x307), 0x132 => array(0x133), 0x134 => array(0x135)
1064  ,0x136 => array(0x137), 0x139 => array(0x13A), 0x13B => array(0x13C)
1065  ,0x13D => array(0x13E), 0x13F => array(0x140), 0x141 => array(0x142)
1066  ,0x143 => array(0x144), 0x145 => array(0x146), 0x147 => array(0x148)
1067  ,0x149 => array(0x2BC, 0x6E), 0x14A => array(0x14B), 0x14C => array(0x14D)
1068  ,0x14E => array(0x14F), 0x150 => array(0x151), 0x152 => array(0x153)
1069  ,0x154 => array(0x155), 0x156 => array(0x157), 0x158 => array(0x159)
1070  ,0x15A => array(0x15B), 0x15C => array(0x15D), 0x15E => array(0x15F)
1071  ,0x160 => array(0x161), 0x162 => array(0x163), 0x164 => array(0x165)
1072  ,0x166 => array(0x167), 0x168 => array(0x169), 0x16A => array(0x16B)
1073  ,0x16C => array(0x16D), 0x16E => array(0x16F), 0x170 => array(0x171)
1074  ,0x172 => array(0x173), 0x174 => array(0x175), 0x176 => array(0x177)
1075  ,0x178 => array(0xFF), 0x179 => array(0x17A), 0x17B => array(0x17C)
1076  ,0x17D => array(0x17E), 0x17F => array(0x73), 0x181 => array(0x253)
1077  ,0x182 => array(0x183), 0x184 => array(0x185), 0x186 => array(0x254)
1078  ,0x187 => array(0x188), 0x189 => array(0x256), 0x18A => array(0x257)
1079  ,0x18B => array(0x18C), 0x18E => array(0x1DD), 0x18F => array(0x259)
1080  ,0x190 => array(0x25B), 0x191 => array(0x192), 0x193 => array(0x260)
1081  ,0x194 => array(0x263), 0x196 => array(0x269), 0x197 => array(0x268)
1082  ,0x198 => array(0x199), 0x19C => array(0x26F), 0x19D => array(0x272)
1083  ,0x19F => array(0x275), 0x1A0 => array(0x1A1), 0x1A2 => array(0x1A3)
1084  ,0x1A4 => array(0x1A5), 0x1A6 => array(0x280), 0x1A7 => array(0x1A8)
1085  ,0x1A9 => array(0x283), 0x1AC => array(0x1AD), 0x1AE => array(0x288)
1086  ,0x1AF => array(0x1B0), 0x1B1 => array(0x28A), 0x1B2 => array(0x28B)
1087  ,0x1B3 => array(0x1B4), 0x1B5 => array(0x1B6), 0x1B7 => array(0x292)
1088  ,0x1B8 => array(0x1B9), 0x1BC => array(0x1BD), 0x1C4 => array(0x1C6)
1089  ,0x1C5 => array(0x1C6), 0x1C7 => array(0x1C9), 0x1C8 => array(0x1C9)
1090  ,0x1CA => array(0x1CC), 0x1CB => array(0x1CC), 0x1CD => array(0x1CE)
1091  ,0x1CF => array(0x1D0), 0x1D1 => array(0x1D2), 0x1D3 => array(0x1D4)
1092  ,0x1D5 => array(0x1D6), 0x1D7 => array(0x1D8), 0x1D9 => array(0x1DA)
1093  ,0x1DB => array(0x1DC), 0x1DE => array(0x1DF), 0x1E0 => array(0x1E1)
1094  ,0x1E2 => array(0x1E3), 0x1E4 => array(0x1E5), 0x1E6 => array(0x1E7)
1095  ,0x1E8 => array(0x1E9), 0x1EA => array(0x1EB), 0x1EC => array(0x1ED)
1096  ,0x1EE => array(0x1EF), 0x1F0 => array(0x6A, 0x30C), 0x1F1 => array(0x1F3)
1097  ,0x1F2 => array(0x1F3), 0x1F4 => array(0x1F5), 0x1F6 => array(0x195)
1098  ,0x1F7 => array(0x1BF), 0x1F8 => array(0x1F9), 0x1FA => array(0x1FB)
1099  ,0x1FC => array(0x1FD), 0x1FE => array(0x1FF), 0x200 => array(0x201)
1100  ,0x202 => array(0x203), 0x204 => array(0x205), 0x206 => array(0x207)
1101  ,0x208 => array(0x209), 0x20A => array(0x20B), 0x20C => array(0x20D)
1102  ,0x20E => array(0x20F), 0x210 => array(0x211), 0x212 => array(0x213)
1103  ,0x214 => array(0x215), 0x216 => array(0x217), 0x218 => array(0x219)
1104  ,0x21A => array(0x21B), 0x21C => array(0x21D), 0x21E => array(0x21F)
1105  ,0x220 => array(0x19E), 0x222 => array(0x223), 0x224 => array(0x225)
1106  ,0x226 => array(0x227), 0x228 => array(0x229), 0x22A => array(0x22B)
1107  ,0x22C => array(0x22D), 0x22E => array(0x22F), 0x230 => array(0x231)
1108  ,0x232 => array(0x233), 0x345 => array(0x3B9), 0x37A => array(0x20, 0x3B9)
1109  ,0x386 => array(0x3AC), 0x388 => array(0x3AD), 0x389 => array(0x3AE)
1110  ,0x38A => array(0x3AF), 0x38C => array(0x3CC), 0x38E => array(0x3CD)
1111  ,0x38F => array(0x3CE), 0x390 => array(0x3B9, 0x308, 0x301)
1112  ,0x391 => array(0x3B1), 0x392 => array(0x3B2), 0x393 => array(0x3B3)
1113  ,0x394 => array(0x3B4), 0x395 => array(0x3B5), 0x396 => array(0x3B6)
1114  ,0x397 => array(0x3B7), 0x398 => array(0x3B8), 0x399 => array(0x3B9)
1115  ,0x39A => array(0x3BA), 0x39B => array(0x3BB), 0x39C => array(0x3BC)
1116  ,0x39D => array(0x3BD), 0x39E => array(0x3BE), 0x39F => array(0x3BF)
1117  ,0x3A0 => array(0x3C0), 0x3A1 => array(0x3C1), 0x3A3 => array(0x3C3)
1118  ,0x3A4 => array(0x3C4), 0x3A5 => array(0x3C5), 0x3A6 => array(0x3C6)
1119  ,0x3A7 => array(0x3C7), 0x3A8 => array(0x3C8), 0x3A9 => array(0x3C9)
1120  ,0x3AA => array(0x3CA), 0x3AB => array(0x3CB), 0x3B0 => array(0x3C5, 0x308, 0x301)
1121  ,0x3C2 => array(0x3C3), 0x3D0 => array(0x3B2), 0x3D1 => array(0x3B8)
1122  ,0x3D2 => array(0x3C5), 0x3D3 => array(0x3CD), 0x3D4 => array(0x3CB)
1123  ,0x3D5 => array(0x3C6), 0x3D6 => array(0x3C0), 0x3D8 => array(0x3D9)
1124  ,0x3DA => array(0x3DB), 0x3DC => array(0x3DD), 0x3DE => array(0x3DF)
1125  ,0x3E0 => array(0x3E1), 0x3E2 => array(0x3E3), 0x3E4 => array(0x3E5)
1126  ,0x3E6 => array(0x3E7), 0x3E8 => array(0x3E9), 0x3EA => array(0x3EB)
1127  ,0x3EC => array(0x3ED), 0x3EE => array(0x3EF), 0x3F0 => array(0x3BA)
1128  ,0x3F1 => array(0x3C1), 0x3F2 => array(0x3C3), 0x3F4 => array(0x3B8)
1129  ,0x3F5 => array(0x3B5), 0x400 => array(0x450), 0x401 => array(0x451)
1130  ,0x402 => array(0x452), 0x403 => array(0x453), 0x404 => array(0x454)
1131  ,0x405 => array(0x455), 0x406 => array(0x456), 0x407 => array(0x457)
1132  ,0x408 => array(0x458), 0x409 => array(0x459), 0x40A => array(0x45A)
1133  ,0x40B => array(0x45B), 0x40C => array(0x45C), 0x40D => array(0x45D)
1134  ,0x40E => array(0x45E), 0x40F => array(0x45F), 0x410 => array(0x430)
1135  ,0x411 => array(0x431), 0x412 => array(0x432), 0x413 => array(0x433)
1136  ,0x414 => array(0x434), 0x415 => array(0x435), 0x416 => array(0x436)
1137  ,0x417 => array(0x437), 0x418 => array(0x438), 0x419 => array(0x439)
1138  ,0x41A => array(0x43A), 0x41B => array(0x43B), 0x41C => array(0x43C)
1139  ,0x41D => array(0x43D), 0x41E => array(0x43E), 0x41F => array(0x43F)
1140  ,0x420 => array(0x440), 0x421 => array(0x441), 0x422 => array(0x442)
1141  ,0x423 => array(0x443), 0x424 => array(0x444), 0x425 => array(0x445)
1142  ,0x426 => array(0x446), 0x427 => array(0x447), 0x428 => array(0x448)
1143  ,0x429 => array(0x449), 0x42A => array(0x44A), 0x42B => array(0x44B)
1144  ,0x42C => array(0x44C), 0x42D => array(0x44D), 0x42E => array(0x44E)
1145  ,0x42F => array(0x44F), 0x460 => array(0x461), 0x462 => array(0x463)
1146  ,0x464 => array(0x465), 0x466 => array(0x467), 0x468 => array(0x469)
1147  ,0x46A => array(0x46B), 0x46C => array(0x46D), 0x46E => array(0x46F)
1148  ,0x470 => array(0x471), 0x472 => array(0x473), 0x474 => array(0x475)
1149  ,0x476 => array(0x477), 0x478 => array(0x479), 0x47A => array(0x47B)
1150  ,0x47C => array(0x47D), 0x47E => array(0x47F), 0x480 => array(0x481)
1151  ,0x48A => array(0x48B), 0x48C => array(0x48D), 0x48E => array(0x48F)
1152  ,0x490 => array(0x491), 0x492 => array(0x493), 0x494 => array(0x495)
1153  ,0x496 => array(0x497), 0x498 => array(0x499), 0x49A => array(0x49B)
1154  ,0x49C => array(0x49D), 0x49E => array(0x49F), 0x4A0 => array(0x4A1)
1155  ,0x4A2 => array(0x4A3), 0x4A4 => array(0x4A5), 0x4A6 => array(0x4A7)
1156  ,0x4A8 => array(0x4A9), 0x4AA => array(0x4AB), 0x4AC => array(0x4AD)
1157  ,0x4AE => array(0x4AF), 0x4B0 => array(0x4B1), 0x4B2 => array(0x4B3)
1158  ,0x4B4 => array(0x4B5), 0x4B6 => array(0x4B7), 0x4B8 => array(0x4B9)
1159  ,0x4BA => array(0x4BB), 0x4BC => array(0x4BD), 0x4BE => array(0x4BF)
1160  ,0x4C1 => array(0x4C2), 0x4C3 => array(0x4C4), 0x4C5 => array(0x4C6)
1161  ,0x4C7 => array(0x4C8), 0x4C9 => array(0x4CA), 0x4CB => array(0x4CC)
1162  ,0x4CD => array(0x4CE), 0x4D0 => array(0x4D1), 0x4D2 => array(0x4D3)
1163  ,0x4D4 => array(0x4D5), 0x4D6 => array(0x4D7), 0x4D8 => array(0x4D9)
1164  ,0x4DA => array(0x4DB), 0x4DC => array(0x4DD), 0x4DE => array(0x4DF)
1165  ,0x4E0 => array(0x4E1), 0x4E2 => array(0x4E3), 0x4E4 => array(0x4E5)
1166  ,0x4E6 => array(0x4E7), 0x4E8 => array(0x4E9), 0x4EA => array(0x4EB)
1167  ,0x4EC => array(0x4ED), 0x4EE => array(0x4EF), 0x4F0 => array(0x4F1)
1168  ,0x4F2 => array(0x4F3), 0x4F4 => array(0x4F5), 0x4F8 => array(0x4F9)
1169  ,0x500 => array(0x501), 0x502 => array(0x503), 0x504 => array(0x505)
1170  ,0x506 => array(0x507), 0x508 => array(0x509), 0x50A => array(0x50B)
1171  ,0x50C => array(0x50D), 0x50E => array(0x50F), 0x531 => array(0x561)
1172  ,0x532 => array(0x562), 0x533 => array(0x563), 0x534 => array(0x564)
1173  ,0x535 => array(0x565), 0x536 => array(0x566), 0x537 => array(0x567)
1174  ,0x538 => array(0x568), 0x539 => array(0x569), 0x53A => array(0x56A)
1175  ,0x53B => array(0x56B), 0x53C => array(0x56C), 0x53D => array(0x56D)
1176  ,0x53E => array(0x56E), 0x53F => array(0x56F), 0x540 => array(0x570)
1177  ,0x541 => array(0x571), 0x542 => array(0x572), 0x543 => array(0x573)
1178  ,0x544 => array(0x574), 0x545 => array(0x575), 0x546 => array(0x576)
1179  ,0x547 => array(0x577), 0x548 => array(0x578), 0x549 => array(0x579)
1180  ,0x54A => array(0x57A), 0x54B => array(0x57B), 0x54C => array(0x57C)
1181  ,0x54D => array(0x57D), 0x54E => array(0x57E), 0x54F => array(0x57F)
1182  ,0x550 => array(0x580), 0x551 => array(0x581), 0x552 => array(0x582)
1183  ,0x553 => array(0x583), 0x554 => array(0x584), 0x555 => array(0x585)
1184  ,0x556 => array(0x586), 0x587 => array(0x565, 0x582), 0xE33 => array(0xE4D, 0xE32)
1185  ,0x1E00 => array(0x1E01), 0x1E02 => array(0x1E03), 0x1E04 => array(0x1E05)
1186  ,0x1E06 => array(0x1E07), 0x1E08 => array(0x1E09), 0x1E0A => array(0x1E0B)
1187  ,0x1E0C => array(0x1E0D), 0x1E0E => array(0x1E0F), 0x1E10 => array(0x1E11)
1188  ,0x1E12 => array(0x1E13), 0x1E14 => array(0x1E15), 0x1E16 => array(0x1E17)
1189  ,0x1E18 => array(0x1E19), 0x1E1A => array(0x1E1B), 0x1E1C => array(0x1E1D)
1190  ,0x1E1E => array(0x1E1F), 0x1E20 => array(0x1E21), 0x1E22 => array(0x1E23)
1191  ,0x1E24 => array(0x1E25), 0x1E26 => array(0x1E27), 0x1E28 => array(0x1E29)
1192  ,0x1E2A => array(0x1E2B), 0x1E2C => array(0x1E2D), 0x1E2E => array(0x1E2F)
1193  ,0x1E30 => array(0x1E31), 0x1E32 => array(0x1E33), 0x1E34 => array(0x1E35)
1194  ,0x1E36 => array(0x1E37), 0x1E38 => array(0x1E39), 0x1E3A => array(0x1E3B)
1195  ,0x1E3C => array(0x1E3D), 0x1E3E => array(0x1E3F), 0x1E40 => array(0x1E41)
1196  ,0x1E42 => array(0x1E43), 0x1E44 => array(0x1E45), 0x1E46 => array(0x1E47)
1197  ,0x1E48 => array(0x1E49), 0x1E4A => array(0x1E4B), 0x1E4C => array(0x1E4D)
1198  ,0x1E4E => array(0x1E4F), 0x1E50 => array(0x1E51), 0x1E52 => array(0x1E53)
1199  ,0x1E54 => array(0x1E55), 0x1E56 => array(0x1E57), 0x1E58 => array(0x1E59)
1200  ,0x1E5A => array(0x1E5B), 0x1E5C => array(0x1E5D), 0x1E5E => array(0x1E5F)
1201  ,0x1E60 => array(0x1E61), 0x1E62 => array(0x1E63), 0x1E64 => array(0x1E65)
1202  ,0x1E66 => array(0x1E67), 0x1E68 => array(0x1E69), 0x1E6A => array(0x1E6B)
1203  ,0x1E6C => array(0x1E6D), 0x1E6E => array(0x1E6F), 0x1E70 => array(0x1E71)
1204  ,0x1E72 => array(0x1E73), 0x1E74 => array(0x1E75), 0x1E76 => array(0x1E77)
1205  ,0x1E78 => array(0x1E79), 0x1E7A => array(0x1E7B), 0x1E7C => array(0x1E7D)
1206  ,0x1E7E => array(0x1E7F), 0x1E80 => array(0x1E81), 0x1E82 => array(0x1E83)
1207  ,0x1E84 => array(0x1E85), 0x1E86 => array(0x1E87), 0x1E88 => array(0x1E89)
1208  ,0x1E8A => array(0x1E8B), 0x1E8C => array(0x1E8D), 0x1E8E => array(0x1E8F)
1209  ,0x1E90 => array(0x1E91), 0x1E92 => array(0x1E93), 0x1E94 => array(0x1E95)
1210  ,0x1E96 => array(0x68, 0x331), 0x1E97 => array(0x74, 0x308), 0x1E98 => array(0x77, 0x30A)
1211  ,0x1E99 => array(0x79, 0x30A), 0x1E9A => array(0x61, 0x2BE), 0x1E9B => array(0x1E61)
1212  ,0x1EA0 => array(0x1EA1), 0x1EA2 => array(0x1EA3), 0x1EA4 => array(0x1EA5)
1213  ,0x1EA6 => array(0x1EA7), 0x1EA8 => array(0x1EA9), 0x1EAA => array(0x1EAB)
1214  ,0x1EAC => array(0x1EAD), 0x1EAE => array(0x1EAF), 0x1EB0 => array(0x1EB1)
1215  ,0x1EB2 => array(0x1EB3), 0x1EB4 => array(0x1EB5), 0x1EB6 => array(0x1EB7)
1216  ,0x1EB8 => array(0x1EB9), 0x1EBA => array(0x1EBB), 0x1EBC => array(0x1EBD)
1217  ,0x1EBE => array(0x1EBF), 0x1EC0 => array(0x1EC1), 0x1EC2 => array(0x1EC3)
1218  ,0x1EC4 => array(0x1EC5), 0x1EC6 => array(0x1EC7), 0x1EC8 => array(0x1EC9)
1219  ,0x1ECA => array(0x1ECB), 0x1ECC => array(0x1ECD), 0x1ECE => array(0x1ECF)
1220  ,0x1ED0 => array(0x1ED1), 0x1ED2 => array(0x1ED3), 0x1ED4 => array(0x1ED5)
1221  ,0x1ED6 => array(0x1ED7), 0x1ED8 => array(0x1ED9), 0x1EDA => array(0x1EDB)
1222  ,0x1EDC => array(0x1EDD), 0x1EDE => array(0x1EDF), 0x1EE0 => array(0x1EE1)
1223  ,0x1EE2 => array(0x1EE3), 0x1EE4 => array(0x1EE5), 0x1EE6 => array(0x1EE7)
1224  ,0x1EE8 => array(0x1EE9), 0x1EEA => array(0x1EEB), 0x1EEC => array(0x1EED)
1225  ,0x1EEE => array(0x1EEF), 0x1EF0 => array(0x1EF1), 0x1EF2 => array(0x1EF3)
1226  ,0x1EF4 => array(0x1EF5), 0x1EF6 => array(0x1EF7), 0x1EF8 => array(0x1EF9)
1227  ,0x1F08 => array(0x1F00), 0x1F09 => array(0x1F01), 0x1F0A => array(0x1F02)
1228  ,0x1F0B => array(0x1F03), 0x1F0C => array(0x1F04), 0x1F0D => array(0x1F05)
1229  ,0x1F0E => array(0x1F06), 0x1F0F => array(0x1F07), 0x1F18 => array(0x1F10)
1230  ,0x1F19 => array(0x1F11), 0x1F1A => array(0x1F12), 0x1F1B => array(0x1F13)
1231  ,0x1F1C => array(0x1F14), 0x1F1D => array(0x1F15), 0x1F28 => array(0x1F20)
1232  ,0x1F29 => array(0x1F21), 0x1F2A => array(0x1F22), 0x1F2B => array(0x1F23)
1233  ,0x1F2C => array(0x1F24), 0x1F2D => array(0x1F25), 0x1F2E => array(0x1F26)
1234  ,0x1F2F => array(0x1F27), 0x1F38 => array(0x1F30), 0x1F39 => array(0x1F31)
1235  ,0x1F3A => array(0x1F32), 0x1F3B => array(0x1F33), 0x1F3C => array(0x1F34)
1236  ,0x1F3D => array(0x1F35), 0x1F3E => array(0x1F36), 0x1F3F => array(0x1F37)
1237  ,0x1F48 => array(0x1F40), 0x1F49 => array(0x1F41), 0x1F4A => array(0x1F42)
1238  ,0x1F4B => array(0x1F43), 0x1F4C => array(0x1F44), 0x1F4D => array(0x1F45)
1239  ,0x1F50 => array(0x3C5, 0x313), 0x1F52 => array(0x3C5, 0x313, 0x300)
1240  ,0x1F54 => array(0x3C5, 0x313, 0x301), 0x1F56 => array(0x3C5, 0x313, 0x342)
1241  ,0x1F59 => array(0x1F51), 0x1F5B => array(0x1F53), 0x1F5D => array(0x1F55)
1242  ,0x1F5F => array(0x1F57), 0x1F68 => array(0x1F60), 0x1F69 => array(0x1F61)
1243  ,0x1F6A => array(0x1F62), 0x1F6B => array(0x1F63), 0x1F6C => array(0x1F64)
1244  ,0x1F6D => array(0x1F65), 0x1F6E => array(0x1F66), 0x1F6F => array(0x1F67)
1245  ,0x1F80 => array(0x1F00, 0x3B9), 0x1F81 => array(0x1F01, 0x3B9)
1246  ,0x1F82 => array(0x1F02, 0x3B9), 0x1F83 => array(0x1F03, 0x3B9)
1247  ,0x1F84 => array(0x1F04, 0x3B9), 0x1F85 => array(0x1F05, 0x3B9)
1248  ,0x1F86 => array(0x1F06, 0x3B9), 0x1F87 => array(0x1F07, 0x3B9)
1249  ,0x1F88 => array(0x1F00, 0x3B9), 0x1F89 => array(0x1F01, 0x3B9)
1250  ,0x1F8A => array(0x1F02, 0x3B9), 0x1F8B => array(0x1F03, 0x3B9)
1251  ,0x1F8C => array(0x1F04, 0x3B9), 0x1F8D => array(0x1F05, 0x3B9)
1252  ,0x1F8E => array(0x1F06, 0x3B9), 0x1F8F => array(0x1F07, 0x3B9)
1253  ,0x1F90 => array(0x1F20, 0x3B9), 0x1F91 => array(0x1F21, 0x3B9)
1254  ,0x1F92 => array(0x1F22, 0x3B9), 0x1F93 => array(0x1F23, 0x3B9)
1255  ,0x1F94 => array(0x1F24, 0x3B9), 0x1F95 => array(0x1F25, 0x3B9)
1256  ,0x1F96 => array(0x1F26, 0x3B9), 0x1F97 => array(0x1F27, 0x3B9)
1257  ,0x1F98 => array(0x1F20, 0x3B9), 0x1F99 => array(0x1F21, 0x3B9)
1258  ,0x1F9A => array(0x1F22, 0x3B9), 0x1F9B => array(0x1F23, 0x3B9)
1259  ,0x1F9C => array(0x1F24, 0x3B9), 0x1F9D => array(0x1F25, 0x3B9)
1260  ,0x1F9E => array(0x1F26, 0x3B9), 0x1F9F => array(0x1F27, 0x3B9)
1261  ,0x1FA0 => array(0x1F60, 0x3B9), 0x1FA1 => array(0x1F61, 0x3B9)
1262  ,0x1FA2 => array(0x1F62, 0x3B9), 0x1FA3 => array(0x1F63, 0x3B9)
1263  ,0x1FA4 => array(0x1F64, 0x3B9), 0x1FA5 => array(0x1F65, 0x3B9)
1264  ,0x1FA6 => array(0x1F66, 0x3B9), 0x1FA7 => array(0x1F67, 0x3B9)
1265  ,0x1FA8 => array(0x1F60, 0x3B9), 0x1FA9 => array(0x1F61, 0x3B9)
1266  ,0x1FAA => array(0x1F62, 0x3B9), 0x1FAB => array(0x1F63, 0x3B9)
1267  ,0x1FAC => array(0x1F64, 0x3B9), 0x1FAD => array(0x1F65, 0x3B9)
1268  ,0x1FAE => array(0x1F66, 0x3B9), 0x1FAF => array(0x1F67, 0x3B9)
1269  ,0x1FB2 => array(0x1F70, 0x3B9), 0x1FB3 => array(0x3B1, 0x3B9)
1270  ,0x1FB4 => array(0x3AC, 0x3B9), 0x1FB6 => array(0x3B1, 0x342)
1271  ,0x1FB7 => array(0x3B1, 0x342, 0x3B9), 0x1FB8 => array(0x1FB0)
1272  ,0x1FB9 => array(0x1FB1), 0x1FBA => array(0x1F70), 0x1FBB => array(0x1F71)
1273  ,0x1FBC => array(0x3B1, 0x3B9), 0x1FBE => array(0x3B9)
1274  ,0x1FC2 => array(0x1F74, 0x3B9), 0x1FC3 => array(0x3B7, 0x3B9)
1275  ,0x1FC4 => array(0x3AE, 0x3B9), 0x1FC6 => array(0x3B7, 0x342)
1276  ,0x1FC7 => array(0x3B7, 0x342, 0x3B9), 0x1FC8 => array(0x1F72)
1277  ,0x1FC9 => array(0x1F73), 0x1FCA => array(0x1F74), 0x1FCB => array(0x1F75)
1278  ,0x1FCC => array(0x3B7, 0x3B9), 0x1FD2 => array(0x3B9, 0x308, 0x300)
1279  ,0x1FD3 => array(0x3B9, 0x308, 0x301), 0x1FD6 => array(0x3B9, 0x342)
1280  ,0x1FD7 => array(0x3B9, 0x308, 0x342), 0x1FD8 => array(0x1FD0)
1281  ,0x1FD9 => array(0x1FD1), 0x1FDA => array(0x1F76)
1282  ,0x1FDB => array(0x1F77), 0x1FE2 => array(0x3C5, 0x308, 0x300)
1283  ,0x1FE3 => array(0x3C5, 0x308, 0x301), 0x1FE4 => array(0x3C1, 0x313)
1284  ,0x1FE6 => array(0x3C5, 0x342), 0x1FE7 => array(0x3C5, 0x308, 0x342)
1285  ,0x1FE8 => array(0x1FE0), 0x1FE9 => array(0x1FE1)
1286  ,0x1FEA => array(0x1F7A), 0x1FEB => array(0x1F7B)
1287  ,0x1FEC => array(0x1FE5), 0x1FF2 => array(0x1F7C, 0x3B9)
1288  ,0x1FF3 => array(0x3C9, 0x3B9), 0x1FF4 => array(0x3CE, 0x3B9)
1289  ,0x1FF6 => array(0x3C9, 0x342), 0x1FF7 => array(0x3C9, 0x342, 0x3B9)
1290  ,0x1FF8 => array(0x1F78), 0x1FF9 => array(0x1F79), 0x1FFA => array(0x1F7C)
1291  ,0x1FFB => array(0x1F7D), 0x1FFC => array(0x3C9, 0x3B9)
1292  ,0x20A8 => array(0x72, 0x73), 0x2102 => array(0x63), 0x2103 => array(0xB0, 0x63)
1293  ,0x2107 => array(0x25B), 0x2109 => array(0xB0, 0x66), 0x210B => array(0x68)
1294  ,0x210C => array(0x68), 0x210D => array(0x68), 0x2110 => array(0x69)
1295  ,0x2111 => array(0x69), 0x2112 => array(0x6C), 0x2115 => array(0x6E)
1296  ,0x2116 => array(0x6E, 0x6F), 0x2119 => array(0x70), 0x211A => array(0x71)
1297  ,0x211B => array(0x72), 0x211C => array(0x72), 0x211D => array(0x72)
1298  ,0x2120 => array(0x73, 0x6D), 0x2121 => array(0x74, 0x65, 0x6C)
1299  ,0x2122 => array(0x74, 0x6D), 0x2124 => array(0x7A), 0x2126 => array(0x3C9)
1300  ,0x2128 => array(0x7A), 0x212A => array(0x6B), 0x212B => array(0xE5)
1301  ,0x212C => array(0x62), 0x212D => array(0x63), 0x2130 => array(0x65)
1302  ,0x2131 => array(0x66), 0x2133 => array(0x6D), 0x213E => array(0x3B3)
1303  ,0x213F => array(0x3C0), 0x2145 => array(0x64) ,0x2160 => array(0x2170)
1304  ,0x2161 => array(0x2171), 0x2162 => array(0x2172), 0x2163 => array(0x2173)
1305  ,0x2164 => array(0x2174), 0x2165 => array(0x2175), 0x2166 => array(0x2176)
1306  ,0x2167 => array(0x2177), 0x2168 => array(0x2178), 0x2169 => array(0x2179)
1307  ,0x216A => array(0x217A), 0x216B => array(0x217B), 0x216C => array(0x217C)
1308  ,0x216D => array(0x217D), 0x216E => array(0x217E), 0x216F => array(0x217F)
1309  ,0x24B6 => array(0x24D0), 0x24B7 => array(0x24D1), 0x24B8 => array(0x24D2)
1310  ,0x24B9 => array(0x24D3), 0x24BA => array(0x24D4), 0x24BB => array(0x24D5)
1311  ,0x24BC => array(0x24D6), 0x24BD => array(0x24D7), 0x24BE => array(0x24D8)
1312  ,0x24BF => array(0x24D9), 0x24C0 => array(0x24DA), 0x24C1 => array(0x24DB)
1313  ,0x24C2 => array(0x24DC), 0x24C3 => array(0x24DD), 0x24C4 => array(0x24DE)
1314  ,0x24C5 => array(0x24DF), 0x24C6 => array(0x24E0), 0x24C7 => array(0x24E1)
1315  ,0x24C8 => array(0x24E2), 0x24C9 => array(0x24E3), 0x24CA => array(0x24E4)
1316  ,0x24CB => array(0x24E5), 0x24CC => array(0x24E6), 0x24CD => array(0x24E7)
1317  ,0x24CE => array(0x24E8), 0x24CF => array(0x24E9), 0x3371 => array(0x68, 0x70, 0x61)
1318  ,0x3373 => array(0x61, 0x75), 0x3375 => array(0x6F, 0x76)
1319  ,0x3380 => array(0x70, 0x61), 0x3381 => array(0x6E, 0x61)
1320  ,0x3382 => array(0x3BC, 0x61), 0x3383 => array(0x6D, 0x61)
1321  ,0x3384 => array(0x6B, 0x61), 0x3385 => array(0x6B, 0x62)
1322  ,0x3386 => array(0x6D, 0x62), 0x3387 => array(0x67, 0x62)
1323  ,0x338A => array(0x70, 0x66), 0x338B => array(0x6E, 0x66)
1324  ,0x338C => array(0x3BC, 0x66), 0x3390 => array(0x68, 0x7A)
1325  ,0x3391 => array(0x6B, 0x68, 0x7A), 0x3392 => array(0x6D, 0x68, 0x7A)
1326  ,0x3393 => array(0x67, 0x68, 0x7A), 0x3394 => array(0x74, 0x68, 0x7A)
1327  ,0x33A9 => array(0x70, 0x61), 0x33AA => array(0x6B, 0x70, 0x61)
1328  ,0x33AB => array(0x6D, 0x70, 0x61), 0x33AC => array(0x67, 0x70, 0x61)
1329  ,0x33B4 => array(0x70, 0x76), 0x33B5 => array(0x6E, 0x76)
1330  ,0x33B6 => array(0x3BC, 0x76), 0x33B7 => array(0x6D, 0x76)
1331  ,0x33B8 => array(0x6B, 0x76), 0x33B9 => array(0x6D, 0x76)
1332  ,0x33BA => array(0x70, 0x77), 0x33BB => array(0x6E, 0x77)
1333  ,0x33BC => array(0x3BC, 0x77), 0x33BD => array(0x6D, 0x77)
1334  ,0x33BE => array(0x6B, 0x77), 0x33BF => array(0x6D, 0x77)
1335  ,0x33C0 => array(0x6B, 0x3C9), 0x33C1 => array(0x6D, 0x3C9) /*
1336  ,0x33C2 => array(0x61, 0x2E, 0x6D, 0x2E) */
1337  ,0x33C3 => array(0x62, 0x71), 0x33C6 => array(0x63, 0x2215, 0x6B, 0x67)
1338  ,0x33C7 => array(0x63, 0x6F, 0x2E), 0x33C8 => array(0x64, 0x62)
1339  ,0x33C9 => array(0x67, 0x79), 0x33CB => array(0x68, 0x70)
1340  ,0x33CD => array(0x6B, 0x6B), 0x33CE => array(0x6B, 0x6D)
1341  ,0x33D7 => array(0x70, 0x68), 0x33D9 => array(0x70, 0x70, 0x6D)
1342  ,0x33DA => array(0x70, 0x72), 0x33DC => array(0x73, 0x76)
1343  ,0x33DD => array(0x77, 0x62), 0xFB00 => array(0x66, 0x66)
1344  ,0xFB01 => array(0x66, 0x69), 0xFB02 => array(0x66, 0x6C)
1345  ,0xFB03 => array(0x66, 0x66, 0x69), 0xFB04 => array(0x66, 0x66, 0x6C)
1346  ,0xFB05 => array(0x73, 0x74), 0xFB06 => array(0x73, 0x74)
1347  ,0xFB13 => array(0x574, 0x576), 0xFB14 => array(0x574, 0x565)
1348  ,0xFB15 => array(0x574, 0x56B), 0xFB16 => array(0x57E, 0x576)
1349  ,0xFB17 => array(0x574, 0x56D), 0xFF21 => array(0xFF41)
1350  ,0xFF22 => array(0xFF42), 0xFF23 => array(0xFF43), 0xFF24 => array(0xFF44)
1351  ,0xFF25 => array(0xFF45), 0xFF26 => array(0xFF46), 0xFF27 => array(0xFF47)
1352  ,0xFF28 => array(0xFF48), 0xFF29 => array(0xFF49), 0xFF2A => array(0xFF4A)
1353  ,0xFF2B => array(0xFF4B), 0xFF2C => array(0xFF4C), 0xFF2D => array(0xFF4D)
1354  ,0xFF2E => array(0xFF4E), 0xFF2F => array(0xFF4F), 0xFF30 => array(0xFF50)
1355  ,0xFF31 => array(0xFF51), 0xFF32 => array(0xFF52), 0xFF33 => array(0xFF53)
1356  ,0xFF34 => array(0xFF54), 0xFF35 => array(0xFF55), 0xFF36 => array(0xFF56)
1357  ,0xFF37 => array(0xFF57), 0xFF38 => array(0xFF58), 0xFF39 => array(0xFF59)
1358  ,0xFF3A => array(0xFF5A), 0x10400 => array(0x10428), 0x10401 => array(0x10429)
1359  ,0x10402 => array(0x1042A), 0x10403 => array(0x1042B), 0x10404 => array(0x1042C)
1360  ,0x10405 => array(0x1042D), 0x10406 => array(0x1042E), 0x10407 => array(0x1042F)
1361  ,0x10408 => array(0x10430), 0x10409 => array(0x10431), 0x1040A => array(0x10432)
1362  ,0x1040B => array(0x10433), 0x1040C => array(0x10434), 0x1040D => array(0x10435)
1363  ,0x1040E => array(0x10436), 0x1040F => array(0x10437), 0x10410 => array(0x10438)
1364  ,0x10411 => array(0x10439), 0x10412 => array(0x1043A), 0x10413 => array(0x1043B)
1365  ,0x10414 => array(0x1043C), 0x10415 => array(0x1043D), 0x10416 => array(0x1043E)
1366  ,0x10417 => array(0x1043F), 0x10418 => array(0x10440), 0x10419 => array(0x10441)
1367  ,0x1041A => array(0x10442), 0x1041B => array(0x10443), 0x1041C => array(0x10444)
1368  ,0x1041D => array(0x10445), 0x1041E => array(0x10446), 0x1041F => array(0x10447)
1369  ,0x10420 => array(0x10448), 0x10421 => array(0x10449), 0x10422 => array(0x1044A)
1370  ,0x10423 => array(0x1044B), 0x10424 => array(0x1044C), 0x10425 => array(0x1044D)
1371  ,0x1D400 => array(0x61), 0x1D401 => array(0x62), 0x1D402 => array(0x63)
1372  ,0x1D403 => array(0x64), 0x1D404 => array(0x65), 0x1D405 => array(0x66)
1373  ,0x1D406 => array(0x67), 0x1D407 => array(0x68), 0x1D408 => array(0x69)
1374  ,0x1D409 => array(0x6A), 0x1D40A => array(0x6B), 0x1D40B => array(0x6C)
1375  ,0x1D40C => array(0x6D), 0x1D40D => array(0x6E), 0x1D40E => array(0x6F)
1376  ,0x1D40F => array(0x70), 0x1D410 => array(0x71), 0x1D411 => array(0x72)
1377  ,0x1D412 => array(0x73), 0x1D413 => array(0x74), 0x1D414 => array(0x75)
1378  ,0x1D415 => array(0x76), 0x1D416 => array(0x77), 0x1D417 => array(0x78)
1379  ,0x1D418 => array(0x79), 0x1D419 => array(0x7A), 0x1D434 => array(0x61)
1380  ,0x1D435 => array(0x62), 0x1D436 => array(0x63), 0x1D437 => array(0x64)
1381  ,0x1D438 => array(0x65), 0x1D439 => array(0x66), 0x1D43A => array(0x67)
1382  ,0x1D43B => array(0x68), 0x1D43C => array(0x69), 0x1D43D => array(0x6A)
1383  ,0x1D43E => array(0x6B), 0x1D43F => array(0x6C), 0x1D440 => array(0x6D)
1384  ,0x1D441 => array(0x6E), 0x1D442 => array(0x6F), 0x1D443 => array(0x70)
1385  ,0x1D444 => array(0x71), 0x1D445 => array(0x72), 0x1D446 => array(0x73)
1386  ,0x1D447 => array(0x74), 0x1D448 => array(0x75), 0x1D449 => array(0x76)
1387  ,0x1D44A => array(0x77), 0x1D44B => array(0x78), 0x1D44C => array(0x79)
1388  ,0x1D44D => array(0x7A), 0x1D468 => array(0x61), 0x1D469 => array(0x62)
1389  ,0x1D46A => array(0x63), 0x1D46B => array(0x64), 0x1D46C => array(0x65)
1390  ,0x1D46D => array(0x66), 0x1D46E => array(0x67), 0x1D46F => array(0x68)
1391  ,0x1D470 => array(0x69), 0x1D471 => array(0x6A), 0x1D472 => array(0x6B)
1392  ,0x1D473 => array(0x6C), 0x1D474 => array(0x6D), 0x1D475 => array(0x6E)
1393  ,0x1D476 => array(0x6F), 0x1D477 => array(0x70), 0x1D478 => array(0x71)
1394  ,0x1D479 => array(0x72), 0x1D47A => array(0x73), 0x1D47B => array(0x74)
1395  ,0x1D47C => array(0x75), 0x1D47D => array(0x76), 0x1D47E => array(0x77)
1396  ,0x1D47F => array(0x78), 0x1D480 => array(0x79), 0x1D481 => array(0x7A)
1397  ,0x1D49C => array(0x61), 0x1D49E => array(0x63), 0x1D49F => array(0x64)
1398  ,0x1D4A2 => array(0x67), 0x1D4A5 => array(0x6A), 0x1D4A6 => array(0x6B)
1399  ,0x1D4A9 => array(0x6E), 0x1D4AA => array(0x6F), 0x1D4AB => array(0x70)
1400  ,0x1D4AC => array(0x71), 0x1D4AE => array(0x73), 0x1D4AF => array(0x74)
1401  ,0x1D4B0 => array(0x75), 0x1D4B1 => array(0x76), 0x1D4B2 => array(0x77)
1402  ,0x1D4B3 => array(0x78), 0x1D4B4 => array(0x79), 0x1D4B5 => array(0x7A)
1403  ,0x1D4D0 => array(0x61), 0x1D4D1 => array(0x62), 0x1D4D2 => array(0x63)
1404  ,0x1D4D3 => array(0x64), 0x1D4D4 => array(0x65), 0x1D4D5 => array(0x66)
1405  ,0x1D4D6 => array(0x67), 0x1D4D7 => array(0x68), 0x1D4D8 => array(0x69)
1406  ,0x1D4D9 => array(0x6A), 0x1D4DA => array(0x6B), 0x1D4DB => array(0x6C)
1407  ,0x1D4DC => array(0x6D), 0x1D4DD => array(0x6E), 0x1D4DE => array(0x6F)
1408  ,0x1D4DF => array(0x70), 0x1D4E0 => array(0x71), 0x1D4E1 => array(0x72)
1409  ,0x1D4E2 => array(0x73), 0x1D4E3 => array(0x74), 0x1D4E4 => array(0x75)
1410  ,0x1D4E5 => array(0x76), 0x1D4E6 => array(0x77), 0x1D4E7 => array(0x78)
1411  ,0x1D4E8 => array(0x79), 0x1D4E9 => array(0x7A), 0x1D504 => array(0x61)
1412  ,0x1D505 => array(0x62), 0x1D507 => array(0x64), 0x1D508 => array(0x65)
1413  ,0x1D509 => array(0x66), 0x1D50A => array(0x67), 0x1D50D => array(0x6A)
1414  ,0x1D50E => array(0x6B), 0x1D50F => array(0x6C), 0x1D510 => array(0x6D)
1415  ,0x1D511 => array(0x6E), 0x1D512 => array(0x6F), 0x1D513 => array(0x70)
1416  ,0x1D514 => array(0x71), 0x1D516 => array(0x73), 0x1D517 => array(0x74)
1417  ,0x1D518 => array(0x75), 0x1D519 => array(0x76), 0x1D51A => array(0x77)
1418  ,0x1D51B => array(0x78), 0x1D51C => array(0x79), 0x1D538 => array(0x61)
1419  ,0x1D539 => array(0x62), 0x1D53B => array(0x64), 0x1D53C => array(0x65)
1420  ,0x1D53D => array(0x66), 0x1D53E => array(0x67), 0x1D540 => array(0x69)
1421  ,0x1D541 => array(0x6A), 0x1D542 => array(0x6B), 0x1D543 => array(0x6C)
1422  ,0x1D544 => array(0x6D), 0x1D546 => array(0x6F), 0x1D54A => array(0x73)
1423  ,0x1D54B => array(0x74), 0x1D54C => array(0x75), 0x1D54D => array(0x76)
1424  ,0x1D54E => array(0x77), 0x1D54F => array(0x78), 0x1D550 => array(0x79)
1425  ,0x1D56C => array(0x61), 0x1D56D => array(0x62), 0x1D56E => array(0x63)
1426  ,0x1D56F => array(0x64), 0x1D570 => array(0x65), 0x1D571 => array(0x66)
1427  ,0x1D572 => array(0x67), 0x1D573 => array(0x68), 0x1D574 => array(0x69)
1428  ,0x1D575 => array(0x6A), 0x1D576 => array(0x6B), 0x1D577 => array(0x6C)
1429  ,0x1D578 => array(0x6D), 0x1D579 => array(0x6E), 0x1D57A => array(0x6F)
1430  ,0x1D57B => array(0x70), 0x1D57C => array(0x71), 0x1D57D => array(0x72)
1431  ,0x1D57E => array(0x73), 0x1D57F => array(0x74), 0x1D580 => array(0x75)
1432  ,0x1D581 => array(0x76), 0x1D582 => array(0x77), 0x1D583 => array(0x78)
1433  ,0x1D584 => array(0x79), 0x1D585 => array(0x7A), 0x1D5A0 => array(0x61)
1434  ,0x1D5A1 => array(0x62), 0x1D5A2 => array(0x63), 0x1D5A3 => array(0x64)
1435  ,0x1D5A4 => array(0x65), 0x1D5A5 => array(0x66), 0x1D5A6 => array(0x67)
1436  ,0x1D5A7 => array(0x68), 0x1D5A8 => array(0x69), 0x1D5A9 => array(0x6A)
1437  ,0x1D5AA => array(0x6B), 0x1D5AB => array(0x6C), 0x1D5AC => array(0x6D)
1438  ,0x1D5AD => array(0x6E), 0x1D5AE => array(0x6F), 0x1D5AF => array(0x70)
1439  ,0x1D5B0 => array(0x71), 0x1D5B1 => array(0x72), 0x1D5B2 => array(0x73)
1440  ,0x1D5B3 => array(0x74), 0x1D5B4 => array(0x75), 0x1D5B5 => array(0x76)
1441  ,0x1D5B6 => array(0x77), 0x1D5B7 => array(0x78), 0x1D5B8 => array(0x79)
1442  ,0x1D5B9 => array(0x7A), 0x1D5D4 => array(0x61), 0x1D5D5 => array(0x62)
1443  ,0x1D5D6 => array(0x63), 0x1D5D7 => array(0x64), 0x1D5D8 => array(0x65)
1444  ,0x1D5D9 => array(0x66), 0x1D5DA => array(0x67), 0x1D5DB => array(0x68)
1445  ,0x1D5DC => array(0x69), 0x1D5DD => array(0x6A), 0x1D5DE => array(0x6B)
1446  ,0x1D5DF => array(0x6C), 0x1D5E0 => array(0x6D), 0x1D5E1 => array(0x6E)
1447  ,0x1D5E2 => array(0x6F), 0x1D5E3 => array(0x70), 0x1D5E4 => array(0x71)
1448  ,0x1D5E5 => array(0x72), 0x1D5E6 => array(0x73), 0x1D5E7 => array(0x74)
1449  ,0x1D5E8 => array(0x75), 0x1D5E9 => array(0x76), 0x1D5EA => array(0x77)
1450  ,0x1D5EB => array(0x78), 0x1D5EC => array(0x79), 0x1D5ED => array(0x7A)
1451  ,0x1D608 => array(0x61), 0x1D609 => array(0x62) ,0x1D60A => array(0x63)
1452  ,0x1D60B => array(0x64), 0x1D60C => array(0x65), 0x1D60D => array(0x66)
1453  ,0x1D60E => array(0x67), 0x1D60F => array(0x68), 0x1D610 => array(0x69)
1454  ,0x1D611 => array(0x6A), 0x1D612 => array(0x6B), 0x1D613 => array(0x6C)
1455  ,0x1D614 => array(0x6D), 0x1D615 => array(0x6E), 0x1D616 => array(0x6F)
1456  ,0x1D617 => array(0x70), 0x1D618 => array(0x71), 0x1D619 => array(0x72)
1457  ,0x1D61A => array(0x73), 0x1D61B => array(0x74), 0x1D61C => array(0x75)
1458  ,0x1D61D => array(0x76), 0x1D61E => array(0x77), 0x1D61F => array(0x78)
1459  ,0x1D620 => array(0x79), 0x1D621 => array(0x7A), 0x1D63C => array(0x61)
1460  ,0x1D63D => array(0x62), 0x1D63E => array(0x63), 0x1D63F => array(0x64)
1461  ,0x1D640 => array(0x65), 0x1D641 => array(0x66), 0x1D642 => array(0x67)
1462  ,0x1D643 => array(0x68), 0x1D644 => array(0x69), 0x1D645 => array(0x6A)
1463  ,0x1D646 => array(0x6B), 0x1D647 => array(0x6C), 0x1D648 => array(0x6D)
1464  ,0x1D649 => array(0x6E), 0x1D64A => array(0x6F), 0x1D64B => array(0x70)
1465  ,0x1D64C => array(0x71), 0x1D64D => array(0x72), 0x1D64E => array(0x73)
1466  ,0x1D64F => array(0x74), 0x1D650 => array(0x75), 0x1D651 => array(0x76)
1467  ,0x1D652 => array(0x77), 0x1D653 => array(0x78), 0x1D654 => array(0x79)
1468  ,0x1D655 => array(0x7A), 0x1D670 => array(0x61), 0x1D671 => array(0x62)
1469  ,0x1D672 => array(0x63), 0x1D673 => array(0x64), 0x1D674 => array(0x65)
1470  ,0x1D675 => array(0x66), 0x1D676 => array(0x67), 0x1D677 => array(0x68)
1471  ,0x1D678 => array(0x69), 0x1D679 => array(0x6A), 0x1D67A => array(0x6B)
1472  ,0x1D67B => array(0x6C), 0x1D67C => array(0x6D), 0x1D67D => array(0x6E)
1473  ,0x1D67E => array(0x6F), 0x1D67F => array(0x70), 0x1D680 => array(0x71)
1474  ,0x1D681 => array(0x72), 0x1D682 => array(0x73), 0x1D683 => array(0x74)
1475  ,0x1D684 => array(0x75), 0x1D685 => array(0x76), 0x1D686 => array(0x77)
1476  ,0x1D687 => array(0x78), 0x1D688 => array(0x79), 0x1D689 => array(0x7A)
1477  ,0x1D6A8 => array(0x3B1), 0x1D6A9 => array(0x3B2), 0x1D6AA => array(0x3B3)
1478  ,0x1D6AB => array(0x3B4), 0x1D6AC => array(0x3B5), 0x1D6AD => array(0x3B6)
1479  ,0x1D6AE => array(0x3B7), 0x1D6AF => array(0x3B8), 0x1D6B0 => array(0x3B9)
1480  ,0x1D6B1 => array(0x3BA), 0x1D6B2 => array(0x3BB), 0x1D6B3 => array(0x3BC)
1481  ,0x1D6B4 => array(0x3BD), 0x1D6B5 => array(0x3BE), 0x1D6B6 => array(0x3BF)
1482  ,0x1D6B7 => array(0x3C0), 0x1D6B8 => array(0x3C1), 0x1D6B9 => array(0x3B8)
1483  ,0x1D6BA => array(0x3C3), 0x1D6BB => array(0x3C4), 0x1D6BC => array(0x3C5)
1484  ,0x1D6BD => array(0x3C6), 0x1D6BE => array(0x3C7), 0x1D6BF => array(0x3C8)
1485  ,0x1D6C0 => array(0x3C9), 0x1D6D3 => array(0x3C3), 0x1D6E2 => array(0x3B1)
1486  ,0x1D6E3 => array(0x3B2), 0x1D6E4 => array(0x3B3), 0x1D6E5 => array(0x3B4)
1487  ,0x1D6E6 => array(0x3B5), 0x1D6E7 => array(0x3B6), 0x1D6E8 => array(0x3B7)
1488  ,0x1D6E9 => array(0x3B8), 0x1D6EA => array(0x3B9), 0x1D6EB => array(0x3BA)
1489  ,0x1D6EC => array(0x3BB), 0x1D6ED => array(0x3BC), 0x1D6EE => array(0x3BD)
1490  ,0x1D6EF => array(0x3BE), 0x1D6F0 => array(0x3BF), 0x1D6F1 => array(0x3C0)
1491  ,0x1D6F2 => array(0x3C1), 0x1D6F3 => array(0x3B8) ,0x1D6F4 => array(0x3C3)
1492  ,0x1D6F5 => array(0x3C4), 0x1D6F6 => array(0x3C5), 0x1D6F7 => array(0x3C6)
1493  ,0x1D6F8 => array(0x3C7), 0x1D6F9 => array(0x3C8) ,0x1D6FA => array(0x3C9)
1494  ,0x1D70D => array(0x3C3), 0x1D71C => array(0x3B1), 0x1D71D => array(0x3B2)
1495  ,0x1D71E => array(0x3B3), 0x1D71F => array(0x3B4), 0x1D720 => array(0x3B5)
1496  ,0x1D721 => array(0x3B6), 0x1D722 => array(0x3B7), 0x1D723 => array(0x3B8)
1497  ,0x1D724 => array(0x3B9), 0x1D725 => array(0x3BA), 0x1D726 => array(0x3BB)
1498  ,0x1D727 => array(0x3BC), 0x1D728 => array(0x3BD), 0x1D729 => array(0x3BE)
1499  ,0x1D72A => array(0x3BF), 0x1D72B => array(0x3C0), 0x1D72C => array(0x3C1)
1500  ,0x1D72D => array(0x3B8), 0x1D72E => array(0x3C3), 0x1D72F => array(0x3C4)
1501  ,0x1D730 => array(0x3C5), 0x1D731 => array(0x3C6), 0x1D732 => array(0x3C7)
1502  ,0x1D733 => array(0x3C8), 0x1D734 => array(0x3C9), 0x1D747 => array(0x3C3)
1503  ,0x1D756 => array(0x3B1), 0x1D757 => array(0x3B2), 0x1D758 => array(0x3B3)
1504  ,0x1D759 => array(0x3B4), 0x1D75A => array(0x3B5), 0x1D75B => array(0x3B6)
1505  ,0x1D75C => array(0x3B7), 0x1D75D => array(0x3B8), 0x1D75E => array(0x3B9)
1506  ,0x1D75F => array(0x3BA), 0x1D760 => array(0x3BB), 0x1D761 => array(0x3BC)
1507  ,0x1D762 => array(0x3BD), 0x1D763 => array(0x3BE), 0x1D764 => array(0x3BF)
1508  ,0x1D765 => array(0x3C0), 0x1D766 => array(0x3C1), 0x1D767 => array(0x3B8)
1509  ,0x1D768 => array(0x3C3), 0x1D769 => array(0x3C4), 0x1D76A => array(0x3C5)
1510  ,0x1D76B => array(0x3C6), 0x1D76C => array(0x3C7), 0x1D76D => array(0x3C8)
1511  ,0x1D76E => array(0x3C9), 0x1D781 => array(0x3C3), 0x1D790 => array(0x3B1)
1512  ,0x1D791 => array(0x3B2), 0x1D792 => array(0x3B3), 0x1D793 => array(0x3B4)
1513  ,0x1D794 => array(0x3B5), 0x1D795 => array(0x3B6), 0x1D796 => array(0x3B7)
1514  ,0x1D797 => array(0x3B8), 0x1D798 => array(0x3B9), 0x1D799 => array(0x3BA)
1515  ,0x1D79A => array(0x3BB), 0x1D79B => array(0x3BC), 0x1D79C => array(0x3BD)
1516  ,0x1D79D => array(0x3BE), 0x1D79E => array(0x3BF), 0x1D79F => array(0x3C0)
1517  ,0x1D7A0 => array(0x3C1), 0x1D7A1 => array(0x3B8), 0x1D7A2 => array(0x3C3)
1518  ,0x1D7A3 => array(0x3C4), 0x1D7A4 => array(0x3C5), 0x1D7A5 => array(0x3C6)
1519  ,0x1D7A6 => array(0x3C7), 0x1D7A7 => array(0x3C8), 0x1D7A8 => array(0x3C9)
1520  ,0x1D7BB => array(0x3C3), 0x3F9 => array(0x3C3), 0x1D2C => array(0x61)
1521  ,0x1D2D => array(0xE6), 0x1D2E => array(0x62), 0x1D30 => array(0x64)
1522  ,0x1D31 => array(0x65), 0x1D32 => array(0x1DD), 0x1D33 => array(0x67)
1523  ,0x1D34 => array(0x68), 0x1D35 => array(0x69), 0x1D36 => array(0x6A)
1524  ,0x1D37 => array(0x6B), 0x1D38 => array(0x6C), 0x1D39 => array(0x6D)
1525  ,0x1D3A => array(0x6E), 0x1D3C => array(0x6F), 0x1D3D => array(0x223)
1526  ,0x1D3E => array(0x70), 0x1D3F => array(0x72), 0x1D40 => array(0x74)
1527  ,0x1D41 => array(0x75), 0x1D42 => array(0x77), 0x213B => array(0x66, 0x61, 0x78)
1528  ,0x3250 => array(0x70, 0x74, 0x65), 0x32CC => array(0x68, 0x67)
1529  ,0x32CE => array(0x65, 0x76), 0x32CF => array(0x6C, 0x74, 0x64)
1530  ,0x337A => array(0x69, 0x75), 0x33DE => array(0x76, 0x2215, 0x6D)
1531  ,0x33DF => array(0x61, 0x2215, 0x6D)
1532  )
1533  ,'norm_combcls' => array(0x334 => 1, 0x335 => 1, 0x336 => 1, 0x337 => 1
1534  ,0x338 => 1, 0x93C => 7, 0x9BC => 7, 0xA3C => 7, 0xABC => 7
1535  ,0xB3C => 7, 0xCBC => 7, 0x1037 => 7, 0x3099 => 8, 0x309A => 8
1536  ,0x94D => 9, 0x9CD => 9, 0xA4D => 9, 0xACD => 9, 0xB4D => 9
1537  ,0xBCD => 9, 0xC4D => 9, 0xCCD => 9, 0xD4D => 9, 0xDCA => 9
1538  ,0xE3A => 9, 0xF84 => 9, 0x1039 => 9, 0x1714 => 9, 0x1734 => 9
1539  ,0x17D2 => 9, 0x5B0 => 10, 0x5B1 => 11, 0x5B2 => 12, 0x5B3 => 13
1540  ,0x5B4 => 14, 0x5B5 => 15, 0x5B6 => 16, 0x5B7 => 17, 0x5B8 => 18
1541  ,0x5B9 => 19, 0x5BB => 20, 0x5Bc => 21, 0x5BD => 22, 0x5BF => 23
1542  ,0x5C1 => 24, 0x5C2 => 25, 0xFB1E => 26, 0x64B => 27, 0x64C => 28
1543  ,0x64D => 29, 0x64E => 30, 0x64F => 31, 0x650 => 32, 0x651 => 33
1544  ,0x652 => 34, 0x670 => 35, 0x711 => 36, 0xC55 => 84, 0xC56 => 91
1545  ,0xE38 => 103, 0xE39 => 103, 0xE48 => 107, 0xE49 => 107, 0xE4A => 107
1546  ,0xE4B => 107, 0xEB8 => 118, 0xEB9 => 118, 0xEC8 => 122, 0xEC9 => 122
1547  ,0xECA => 122, 0xECB => 122, 0xF71 => 129, 0xF72 => 130, 0xF7A => 130
1548  ,0xF7B => 130, 0xF7C => 130, 0xF7D => 130, 0xF80 => 130, 0xF74 => 132
1549  ,0x321 => 202, 0x322 => 202, 0x327 => 202, 0x328 => 202, 0x31B => 216
1550  ,0xF39 => 216, 0x1D165 => 216, 0x1D166 => 216, 0x1D16E => 216, 0x1D16F => 216
1551  ,0x1D170 => 216, 0x1D171 => 216, 0x1D172 => 216, 0x302A => 218, 0x316 => 220
1552  ,0x317 => 220, 0x318 => 220, 0x319 => 220, 0x31C => 220, 0x31D => 220
1553  ,0x31E => 220, 0x31F => 220, 0x320 => 220, 0x323 => 220, 0x324 => 220
1554  ,0x325 => 220, 0x326 => 220, 0x329 => 220, 0x32A => 220, 0x32B => 220
1555  ,0x32C => 220, 0x32D => 220, 0x32E => 220, 0x32F => 220, 0x330 => 220
1556  ,0x331 => 220, 0x332 => 220, 0x333 => 220, 0x339 => 220, 0x33A => 220
1557  ,0x33B => 220, 0x33C => 220, 0x347 => 220, 0x348 => 220, 0x349 => 220
1558  ,0x34D => 220, 0x34E => 220, 0x353 => 220, 0x354 => 220, 0x355 => 220
1559  ,0x356 => 220, 0x591 => 220, 0x596 => 220, 0x59B => 220, 0x5A3 => 220
1560  ,0x5A4 => 220, 0x5A5 => 220, 0x5A6 => 220, 0x5A7 => 220, 0x5AA => 220
1561  ,0x655 => 220, 0x656 => 220, 0x6E3 => 220, 0x6EA => 220, 0x6ED => 220
1562  ,0x731 => 220, 0x734 => 220, 0x737 => 220, 0x738 => 220, 0x739 => 220
1563  ,0x73B => 220, 0x73C => 220, 0x73E => 220, 0x742 => 220, 0x744 => 220
1564  ,0x746 => 220, 0x748 => 220, 0x952 => 220, 0xF18 => 220, 0xF19 => 220
1565  ,0xF35 => 220, 0xF37 => 220, 0xFC6 => 220, 0x193B => 220, 0x20E8 => 220
1566  ,0x1D17B => 220, 0x1D17C => 220, 0x1D17D => 220, 0x1D17E => 220, 0x1D17F => 220
1567  ,0x1D180 => 220, 0x1D181 => 220, 0x1D182 => 220, 0x1D18A => 220, 0x1D18B => 220
1568  ,0x59A => 222, 0x5AD => 222, 0x1929 => 222, 0x302D => 222, 0x302E => 224
1569  ,0x302F => 224, 0x1D16D => 226, 0x5AE => 228, 0x18A9 => 228, 0x302B => 228
1570  ,0x300 => 230, 0x301 => 230, 0x302 => 230, 0x303 => 230, 0x304 => 230
1571  ,0x305 => 230, 0x306 => 230, 0x307 => 230, 0x308 => 230, 0x309 => 230
1572  ,0x30A => 230, 0x30B => 230, 0x30C => 230, 0x30D => 230, 0x30E => 230
1573  ,0x30F => 230, 0x310 => 230, 0x311 => 230, 0x312 => 230, 0x313 => 230
1574  ,0x314 => 230, 0x33D => 230, 0x33E => 230, 0x33F => 230, 0x340 => 230
1575  ,0x341 => 230, 0x342 => 230, 0x343 => 230, 0x344 => 230, 0x346 => 230
1576  ,0x34A => 230, 0x34B => 230, 0x34C => 230, 0x350 => 230, 0x351 => 230
1577  ,0x352 => 230, 0x357 => 230, 0x363 => 230, 0x364 => 230, 0x365 => 230
1578  ,0x366 => 230, 0x367 => 230, 0x368 => 230, 0x369 => 230, 0x36A => 230
1579  ,0x36B => 230, 0x36C => 230, 0x36D => 230, 0x36E => 230, 0x36F => 230
1580  ,0x483 => 230, 0x484 => 230, 0x485 => 230, 0x486 => 230, 0x592 => 230
1581  ,0x593 => 230, 0x594 => 230, 0x595 => 230, 0x597 => 230, 0x598 => 230
1582  ,0x599 => 230, 0x59C => 230, 0x59D => 230, 0x59E => 230, 0x59F => 230
1583  ,0x5A0 => 230, 0x5A1 => 230, 0x5A8 => 230, 0x5A9 => 230, 0x5AB => 230
1584  ,0x5AC => 230, 0x5AF => 230, 0x5C4 => 230, 0x610 => 230, 0x611 => 230
1585  ,0x612 => 230, 0x613 => 230, 0x614 => 230, 0x615 => 230, 0x653 => 230
1586  ,0x654 => 230, 0x657 => 230, 0x658 => 230, 0x6D6 => 230, 0x6D7 => 230
1587  ,0x6D8 => 230, 0x6D9 => 230, 0x6DA => 230, 0x6DB => 230, 0x6DC => 230
1588  ,0x6DF => 230, 0x6E0 => 230, 0x6E1 => 230, 0x6E2 => 230, 0x6E4 => 230
1589  ,0x6E7 => 230, 0x6E8 => 230, 0x6EB => 230, 0x6EC => 230, 0x730 => 230
1590  ,0x732 => 230, 0x733 => 230, 0x735 => 230, 0x736 => 230, 0x73A => 230
1591  ,0x73D => 230, 0x73F => 230, 0x740 => 230, 0x741 => 230, 0x743 => 230
1592  ,0x745 => 230, 0x747 => 230, 0x749 => 230, 0x74A => 230, 0x951 => 230
1593  ,0x953 => 230, 0x954 => 230, 0xF82 => 230, 0xF83 => 230, 0xF86 => 230
1594  ,0xF87 => 230, 0x170D => 230, 0x193A => 230, 0x20D0 => 230, 0x20D1 => 230
1595  ,0x20D4 => 230, 0x20D5 => 230, 0x20D6 => 230, 0x20D7 => 230, 0x20DB => 230
1596  ,0x20DC => 230, 0x20E1 => 230, 0x20E7 => 230, 0x20E9 => 230, 0xFE20 => 230
1597  ,0xFE21 => 230, 0xFE22 => 230, 0xFE23 => 230, 0x1D185 => 230, 0x1D186 => 230
1598  ,0x1D187 => 230, 0x1D189 => 230, 0x1D188 => 230, 0x1D1AA => 230, 0x1D1AB => 230
1599  ,0x1D1AC => 230, 0x1D1AD => 230, 0x315 => 232, 0x31A => 232, 0x302C => 232
1600  ,0x35F => 233, 0x362 => 233, 0x35D => 234, 0x35E => 234, 0x360 => 234
1601  ,0x361 => 234, 0x345 => 240
1602  )
1603  );
1604 }
1605 ?>