Completed
Push — master ( 55a9f3...13acd2 )
by Alexey
05:06
created

IdnaConvert   D

Complexity

Total Complexity 235

Size/Duplication

Total Lines 1553
Duplicated Lines 2.45 %

Coupling/Cohesion

Components 1
Dependencies 0
Metric Value
wmc 235
lcom 1
cbo 0
dl 38
loc 1553
rs 4.4102

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 4
C set_parameter() 0 46 15
F decode() 20 94 33
F encode() 10 77 22
F encode_uri() 0 23 12
A get_last_error() 0 4 1
C _decode() 0 51 13
F _encode() 0 86 29
A _adapt() 0 9 3
A _encode_digit() 0 4 1
A _decode_digit() 0 5 4
A _error() 0 4 1
C _nameprep() 0 74 23
A _hangul_decompose() 0 11 4
C _hangul_compose() 0 35 12
A _get_combining_class() 0 4 2
C _apply_cannonical_ordering() 0 26 7
C _combine() 0 22 8
C _utf8_to_ucs4() 8 70 22
B _ucs4_to_utf8() 0 19 6
A _ucs4_to_ucs4_string() 0 10 2
B _ucs4_string_to_ucs4() 0 21 5
A byteLength() 0 7 2
A getInstance() 0 4 1
A singleton() 0 12 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like IdnaConvert often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use IdnaConvert, and based on these observations, apply Extract Interface, too.

1
<?php
2
// {{{ license
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
20
// | USA.                                                                 |
21
// +----------------------------------------------------------------------+
22
//
23
24
// }}}
25
26
/**
27
 * Encode/decode Internationalized Domain Names.
28
 *
29
 * The class allows to convert internationalized domain names
30
 * (see RFC 3490 for details) as they can be used with various registries worldwide
31
 * to be translated between their original (localized) form and their encoded form
32
 * as it will be used in the DNS (Domain Name System).
33
 *
34
 * The class provides two public methods, encode() and decode(), which do exactly
35
 * what you would expect them to do. You are allowed to use complete domain names,
36
 * simple strings and complete email addresses as well. That means, that you might
37
 * use any of the following notations:
38
 *
39
 * - www.nörgler.com
40
 * - xn--nrgler-wxa
41
 * - xn--brse-5qa.xn--knrz-1ra.info
42
 *
43
 * Unicode input might be given as either UTF-8 string, UCS-4 string or UCS-4 array.
44
 * Unicode output is available in the same formats.
45
 * You can select your preferred format via {@link set_paramter()}.
46
 *
47
 * ACE input and output is always expected to be ASCII.
48
 *
49
 * @author  Matthias Sommerfeld <[email protected]>
50
 * @copyright 2004-2011 phlyLabs Berlin, http://phlylabs.de
51
 * @version 0.8.1 2011-12-19
52
 */
53
class IdnaConvert
54
{
55
    // NP See below
56
57
    // Internal settings, do not mess with them
58
    protected $_punycode_prefix = 'xn--';
59
    protected $_invalid_ucs = 0x80000000;
60
    protected $_max_ucs = 0x10FFFF;
61
    protected $_base = 36;
62
    protected $_tmin = 1;
63
    protected $_tmax = 26;
64
    protected $_skew = 38;
65
    protected $_damp = 700;
66
    protected $_initial_bias = 72;
67
    protected $_initial_n = 0x80;
68
    protected $_sbase = 0xAC00;
69
    protected $_lbase = 0x1100;
70
    protected $_vbase = 0x1161;
71
    protected $_tbase = 0x11A7;
72
    protected $_lcount = 19;
73
    protected $_vcount = 21;
74
    protected $_tcount = 28;
75
    protected $_ncount = 588;   // _vcount * _tcount
76
    protected $_scount = 11172; // _lcount * _tcount * _vcount
77
    protected $_error = false;
78
79
    protected static $_mb_string_overload = null;
80
81
    // See {@link set_paramter()} for details of how to change the following
82
    // settings from within your script / application
83
    protected $_api_encoding = 'utf8';   // Default input charset is UTF-8
84
    protected $_allow_overlong = false;  // Overlong UTF-8 encodings are forbidden
85
    protected $_strict_mode = false;     // Behave strict or not
86
    protected $_idn_version = 2003;      // Can be either 2003 (old, default) or 2008
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
87
88
    /**
89
     * the constructor
90
     *
91
     * @param array $options
92
     * @return boolean
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
93
     * @since 0.5.2
94
     */
95
    public function __construct($options = false)
96
    {
97
        $this->slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount;
0 ignored issues
show
Bug introduced by
The property slast does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
98
        // If parameters are given, pass these to the respective method
99
        if (is_array($options)) {
100
            $this->set_parameter($options);
101
        }
102
103
        // populate mbstring overloading cache if not set
104
        if (self::$_mb_string_overload === null) {
105
            self::$_mb_string_overload = (extension_loaded('mbstring')
106
                && (ini_get('mbstring.func_overload') & 0x02) === 0x02);
107
        }
108
    }
109
110
    /**
111
     * Sets a new option value. Available options and values:
112
     * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8,
113
     *         'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8]
114
     * [overlong - Unicode does not allow unnecessarily long encodings of chars,
115
     *             to allow this, set this parameter to true, else to false;
116
     *             default is false.]
117
     * [strict - true: strict mode, good for registration purposes - Causes errors
118
     *           on failures; false: loose mode, ideal for "wildlife" applications
119
     *           by silently ignoring errors and returning the original input instead
120
     *
121
     * @param    mixed     Parameter to set (string: single parameter; array of Parameter => Value pairs)
122
     * @param    string    Value to use (if parameter 1 is a string)
123
     * @return   boolean   true on success, false otherwise
124
     */
125
    public function set_parameter($option, $value = false)
126
    {
127
        if (!is_array($option)) {
128
            $option = array($option => $value);
129
        }
130
        foreach ($option as $k => $v) {
131
            switch ($k) {
132
            case 'encoding':
133
                switch ($v) {
134
                case 'utf8':
135
                case 'ucs4_string':
136
                case 'ucs4_array':
137
                    $this->_api_encoding = $v;
138
                    break;
139
                default:
140
                    $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k);
141
                    return false;
142
                }
143
                break;
144
            case 'overlong':
145
                $this->_allow_overlong = ($v) ? true : false;
146
                break;
147
            case 'strict':
148
                $this->_strict_mode = ($v) ? true : false;
149
                break;
150
            case 'idn_version':
151
                if (in_array($v, array('2003', '2008'))) {
152
                    $this->_idn_version = $v;
153
                } else {
154
                    $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k);
155
                }
156
                break;
157
            case 'encode_german_sz': // Deprecated
158
                if (!$v) {
159
                    self::$NP['replacemaps'][0xDF] = array(0x73, 0x73);
160
                } else {
161
                    unset(self::$NP['replacemaps'][0xDF]);
162
                }
163
                break;
164
            default:
165
                $this->_error('Set Parameter: Unknown option '.$k);
166
                return false;
167
            }
168
        }
169
        return true;
170
    }
171
172
    /**
173
     * Decode a given ACE domain name
174
     * @param    string   Domain name (ACE string)
175
     * [@param    string   Desired output encoding, see {@link set_parameter}]
176
     * @return   string   Decoded Domain name (UTF-8 or UCS-4)
177
     */
178
    public function decode($input, $one_time_encoding = false)
179
    {
180
        // Optionally set
181
        if ($one_time_encoding) {
182
            switch ($one_time_encoding) {
183
            case 'utf8':
184
            case 'ucs4_string':
185
            case 'ucs4_array':
186
                break;
187
            default:
188
                $this->_error('Unknown encoding '.$one_time_encoding);
189
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by IdnaConvert::decode of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
190
            }
191
        }
192
        // Make sure to drop any newline characters around
193
        $input = trim($input);
194
195
        // Negotiate input and try to determine, whether it is a plain string,
196
        // an email address or something like a complete URL
197
        if (strpos($input, '@')) { // Maybe it is an email address
198
            // No no in strict mode
199
            if ($this->_strict_mode) {
200
                $this->_error('Only simple domain name parts can be handled in strict mode');
201
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by IdnaConvert::decode of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
202
            }
203
            list ($email_pref, $input) = explode('@', $input, 2);
204
            $arr = explode('.', $input);
205 View Code Duplication
            foreach ($arr as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
                if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
207
                    $conv = $this->_decode($v);
208
                    if ($conv) $arr[$k] = $conv;
0 ignored issues
show
Bug Best Practice introduced by
The expression $conv of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
209
                }
210
            }
211
            $input = join('.', $arr);
212
            $arr = explode('.', $email_pref);
213 View Code Duplication
            foreach ($arr as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
                if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
215
                    $conv = $this->_decode($v);
216
                    if ($conv) $arr[$k] = $conv;
0 ignored issues
show
Bug Best Practice introduced by
The expression $conv of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
217
                }
218
            }
219
            $email_pref = join('.', $arr);
220
            $return = $email_pref . '@' . $input;
221
        } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters)
222
            // No no in strict mode
223
            if ($this->_strict_mode) {
224
                $this->_error('Only simple domain name parts can be handled in strict mode');
225
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by IdnaConvert::decode of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
226
            }
227
            $parsed = parse_url($input);
228
            if (isset($parsed['host'])) {
229
                $arr = explode('.', $parsed['host']);
230 View Code Duplication
                foreach ($arr as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
231
                    $conv = $this->_decode($v);
232
                    if ($conv) $arr[$k] = $conv;
0 ignored issues
show
Bug Best Practice introduced by
The expression $conv of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
233
                }
234
                $parsed['host'] = join('.', $arr);
235
                $return =
236
                        (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'))
237
                        .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@')
238
                        .$parsed['host']
239
                        .(empty($parsed['port']) ? '' : ':'.$parsed['port'])
240
                        .(empty($parsed['path']) ? '' : $parsed['path'])
241
                        .(empty($parsed['query']) ? '' : '?'.$parsed['query'])
242
                        .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']);
243
            } else { // parse_url seems to have failed, try without it
244
                $arr = explode('.', $input);
245 View Code Duplication
                foreach ($arr as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
246
                    $conv = $this->_decode($v);
247
                    $arr[$k] = ($conv) ? $conv : $v;
248
                }
249
                $return = join('.', $arr);
250
            }
251
        } else { // Otherwise we consider it being a pure domain name string
252
            $return = $this->_decode($input);
253
            if (!$return) $return = $input;
0 ignored issues
show
Bug Best Practice introduced by
The expression $return of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
254
        }
255
        // The output is UTF-8 by default, other output formats need conversion here
256
        // If one time encoding is given, use this, else the objects property
257
        switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) {
258
        case 'utf8':
259
            return $return;
260
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
261
        case 'ucs4_string':
262
           return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return));
0 ignored issues
show
Security Bug introduced by
It seems like $this->_utf8_to_ucs4($return) targeting IdnaConvert::_utf8_to_ucs4() can also be of type false; however, IdnaConvert::_ucs4_to_ucs4_string() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
263
           break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
264
        case 'ucs4_array':
265
            return $this->_utf8_to_ucs4($return);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->_utf8_to_ucs4($return); (false|array) is incompatible with the return type documented by IdnaConvert::decode of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
266
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
267
        default:
268
            $this->_error('Unsupported output format');
269
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by IdnaConvert::decode of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
270
        }
271
    }
272
273
    /**
274
     * Encode a given UTF-8 domain name
275
     * @param    string   Domain name (UTF-8 or UCS-4)
276
     * [@param    string   Desired input encoding, see {@link set_parameter}]
277
     * @return   string   Encoded Domain name (ACE string)
278
     */
279
    public function encode($decoded, $one_time_encoding = false)
280
    {
281
        // Forcing conversion of input to UCS4 array
282
        // If one time encoding is given, use this, else the objects property
283
        switch ($one_time_encoding ? $one_time_encoding : $this->_api_encoding) {
284
        case 'utf8':
285
            $decoded = $this->_utf8_to_ucs4($decoded);
286
            break;
287
        case 'ucs4_string':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
288
           $decoded = $this->_ucs4_string_to_ucs4($decoded);
289
        case 'ucs4_array':
290
           break;
291
        default:
292
            $this->_error('Unsupported input format: '.($one_time_encoding ? $one_time_encoding : $this->_api_encoding));
293
            return false;
294
        }
295
296
        // No input, no output, what else did you expect?
297
        if (empty($decoded)) return '';
298
299
        // Anchors for iteration
300
        $last_begin = 0;
301
        // Output string
302
        $output = '';
303
        foreach ($decoded as $k => $v) {
304
            // Make sure to use just the plain dot
305
            switch($v) {
306
            case 0x3002:
307
            case 0xFF0E:
308
            case 0xFF61:
309
                $decoded[$k] = 0x2E;
310
                // Right, no break here, the above are converted to dots anyway
311
            // Stumbling across an anchoring character
312
            case 0x2E:
313
            case 0x2F:
314
            case 0x3A:
315
            case 0x3F:
316
            case 0x40:
317
                // Neither email addresses nor URLs allowed in strict mode
318
                if ($this->_strict_mode) {
319
                   $this->_error('Neither email addresses nor URLs are allowed in strict mode.');
320
                   return false;
321
                } else {
322
                    // Skip first char
323
                    if ($k) {
324
                        $encoded = '';
0 ignored issues
show
Unused Code introduced by
$encoded is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
325
                        $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin)));
326 View Code Duplication
                        if ($encoded) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encoded of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
327
                            $output .= $encoded;
328
                        } else {
329
                            $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin)));
0 ignored issues
show
Documentation introduced by
array_slice($decoded, $l...egin, $k - $last_begin) is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
330
                        }
331
                        $output .= chr($decoded[$k]);
332
                    }
333
                    $last_begin = $k + 1;
334
                }
335
            }
336
        }
337
        // Catch the rest of the string
338
        if ($last_begin) {
339
            $inp_len = sizeof($decoded);
340
            $encoded = '';
0 ignored issues
show
Unused Code introduced by
$encoded is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
341
            $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
342 View Code Duplication
            if ($encoded) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $encoded of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
343
                $output .= $encoded;
344
            } else {
345
                $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
0 ignored issues
show
Documentation introduced by
array_slice($decoded, $l...$inp_len - $last_begin) is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
346
            }
347
            return $output;
348
        } else {
349
            if ($output = $this->_encode($decoded)) {
350
                return $output;
351
            } else {
352
                return $this->_ucs4_to_utf8($decoded);
353
            }
354
        }
355
    }
356
357
    /**
358
     * Removes a weakness of encode(), which cannot properly handle URIs but instead encodes their
359
     * path or query components, too.
360
     * @param string  $uri  Expects the URI as a UTF-8 (or ASCII) string
361
     * @return  string  The URI encoded to Punycode, everything but the host component is left alone
362
     * @since 0.6.4
363
     */
364
    public function encode_uri($uri)
365
    {
366
        $parsed = parse_url($uri);
367
        if (!isset($parsed['host'])) {
368
            $this->_error('The given string does not look like a URI');
369
            return false;
370
        }
371
        $arr = explode('.', $parsed['host']);
372
        foreach ($arr as $k => $v) {
373
            $conv = $this->encode($v, 'utf8');
0 ignored issues
show
Documentation introduced by
'utf8' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
374
            if ($conv) $arr[$k] = $conv;
0 ignored issues
show
Bug Best Practice introduced by
The expression $conv of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
375
        }
376
        $parsed['host'] = join('.', $arr);
377
        $return =
378
                (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'))
379
                .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@')
380
                .$parsed['host']
381
                .(empty($parsed['port']) ? '' : ':'.$parsed['port'])
382
                .(empty($parsed['path']) ? '' : $parsed['path'])
383
                .(empty($parsed['query']) ? '' : '?'.$parsed['query'])
384
                .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']);
385
        return $return;
386
    }
387
388
    /**
389
     * Use this method to get the last error ocurred
390
     * @param    void
391
     * @return   string   The last error, that occured
392
     */
393
    public function get_last_error()
394
    {
395
        return $this->_error;
396
    }
397
398
    /**
399
     * The actual decoding algorithm
400
     * @param string
401
     * @return mixed
402
     */
403
    protected function _decode($encoded)
404
    {
405
        $decoded = array();
406
        // find the Punycode prefix
407
        if (!preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $encoded)) {
408
            $this->_error('This is not a punycode string');
409
            return false;
410
        }
411
        $encode_test = preg_replace('!^'.preg_quote($this->_punycode_prefix, '!').'!', '', $encoded);
412
        // If nothing left after removing the prefix, it is hopeless
413
        if (!$encode_test) {
414
            $this->_error('The given encoded string was empty');
415
            return false;
416
        }
417
        // Find last occurence of the delimiter
418
        $delim_pos = strrpos($encoded, '-');
419
        if ($delim_pos > self::byteLength($this->_punycode_prefix)) {
420
            for ($k = self::byteLength($this->_punycode_prefix); $k < $delim_pos; ++$k) {
421
                $decoded[] = ord($encoded{$k});
422
            }
423
        }
424
        $deco_len = count($decoded);
425
        $enco_len = self::byteLength($encoded);
426
427
        // Wandering through the strings; init
428
        $is_first = true;
429
        $bias = $this->_initial_bias;
430
        $idx = 0;
431
        $char = $this->_initial_n;
432
433
        for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
434
            for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) {
435
                $digit = $this->_decode_digit($encoded{$enco_idx++});
436
                $idx += $digit * $w;
437
                $t = ($k <= $bias) ? $this->_tmin :
438
                        (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias));
439
                if ($digit < $t) break;
440
                $w = (int) ($w * ($this->_base - $t));
441
            }
442
            $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first);
0 ignored issues
show
Documentation introduced by
$is_first is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
443
            $is_first = false;
444
            $char += (int) ($idx / ($deco_len + 1));
445
            $idx %= ($deco_len + 1);
446
            if ($deco_len > 0) {
447
                // Make room for the decoded char
448
                for ($i = $deco_len; $i > $idx; $i--) $decoded[$i] = $decoded[($i - 1)];
449
            }
450
            $decoded[$idx++] = $char;
451
        }
452
        return $this->_ucs4_to_utf8($decoded);
0 ignored issues
show
Documentation introduced by
$decoded is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
453
    }
454
455
    /**
456
     * The actual encoding algorithm
457
     * @param  string
458
     * @return mixed
459
     */
460
    protected function _encode($decoded)
461
    {
462
        // We cannot encode a domain name containing the Punycode prefix
463
        $extract = self::byteLength($this->_punycode_prefix);
464
        $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix);
465
        $check_deco = array_slice($decoded, 0, $extract);
466
467
        if ($check_pref == $check_deco) {
468
            $this->_error('This is already a punycode string');
469
            return false;
470
        }
471
        // We will not try to encode strings consisting of basic code points only
472
        $encodable = false;
473
        foreach ($decoded as $k => $v) {
474
            if ($v > 0x7a) {
475
                $encodable = true;
476
                break;
477
            }
478
        }
479
        if (!$encodable) {
480
            $this->_error('The given string does not contain encodable chars');
481
            return false;
482
        }
483
        // Do NAMEPREP
484
        $decoded = $this->_nameprep($decoded);
485
        if (!$decoded || !is_array($decoded)) return false; // NAMEPREP failed
486
        $deco_len  = count($decoded);
487
        if (!$deco_len) return false; // Empty array
488
        $codecount = 0; // How many chars have been consumed
489
        $encoded = '';
490
        // Copy all basic code points to output
491
        for ($i = 0; $i < $deco_len; ++$i) {
492
            $test = $decoded[$i];
493
            // Will match [-0-9a-zA-Z]
494
            if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B)
495
                    || (0x60 < $test && $test <= 0x7B) || (0x2D == $test)) {
496
                $encoded .= chr($decoded[$i]);
497
                $codecount++;
498
            }
499
        }
500
        if ($codecount == $deco_len) return $encoded; // All codepoints were basic ones
501
502
        // Start with the prefix; copy it to output
503
        $encoded = $this->_punycode_prefix.$encoded;
504
        // If we have basic code points in output, add an hyphen to the end
505
        if ($codecount) $encoded .= '-';
506
        // Now find and encode all non-basic code points
507
        $is_first = true;
508
        $cur_code = $this->_initial_n;
509
        $bias = $this->_initial_bias;
510
        $delta = 0;
511
        while ($codecount < $deco_len) {
512
            // Find the smallest code point >= the current code point and
513
            // remember the last ouccrence of it in the input
514
            for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) {
515
                if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) {
516
                    $next_code = $decoded[$i];
517
                }
518
            }
519
            $delta += ($next_code - $cur_code) * ($codecount + 1);
520
            $cur_code = $next_code;
521
522
            // Scan input again and encode all characters whose code point is $cur_code
523
            for ($i = 0; $i < $deco_len; $i++) {
524
                if ($decoded[$i] < $cur_code) {
525
                    $delta++;
526
                } elseif ($decoded[$i] == $cur_code) {
527
                    for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) {
528
                        $t = ($k <= $bias) ? $this->_tmin :
529
                                (($k >= $bias + $this->_tmax) ? $this->_tmax : $k - $bias);
530
                        if ($q < $t) break;
531
                        $encoded .= $this->_encode_digit(intval($t + (($q - $t) % ($this->_base - $t)))); //v0.4.5 Changed from ceil() to intval()
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
532
                        $q = (int) (($q - $t) / ($this->_base - $t));
533
                    }
534
                    $encoded .= $this->_encode_digit($q);
535
                    $bias = $this->_adapt($delta, $codecount+1, $is_first);
0 ignored issues
show
Documentation introduced by
$is_first is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
536
                    $codecount++;
537
                    $delta = 0;
538
                    $is_first = false;
539
                }
540
            }
541
            $delta++;
542
            $cur_code++;
543
        }
544
        return $encoded;
545
    }
546
547
    /**
548
     * Adapt the bias according to the current code point and position
549
     * @param int $delta
550
     * @param int $npoints
551
     * @param int $is_first
552
     * @return int
553
     */
554
    protected function _adapt($delta, $npoints, $is_first)
555
    {
556
        $delta = intval($is_first ? ($delta / $this->_damp) : ($delta / 2));
557
        $delta += intval($delta / $npoints);
558
        for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) {
559
            $delta = intval($delta / ($this->_base - $this->_tmin));
560
        }
561
        return intval($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew));
562
    }
563
564
    /**
565
     * Encoding a certain digit
566
     * @param    int $d
567
     * @return string
568
     */
569
    protected function _encode_digit($d)
570
    {
571
        return chr($d + 22 + 75 * ($d < 26));
572
    }
573
574
    /**
575
     * Decode a certain digit
576
     * @param    int $cp
577
     * @return int
578
     */
579
    protected function _decode_digit($cp)
580
    {
581
        $cp = ord($cp);
582
        return ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $this->_base));
583
    }
584
585
    /**
586
     * Internal error handling method
587
     * @param  string $error
588
     */
589
    protected function _error($error = '')
590
    {
591
        $this->_error = $error;
0 ignored issues
show
Documentation Bug introduced by
The property $_error was declared of type boolean, but $error is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
592
    }
593
594
    /**
595
     * Do Nameprep according to RFC3491 and RFC3454
596
     * @param    array    Unicode Characters
597
     * @return   string   Unicode Characters, Nameprep'd
598
     */
599
    protected function _nameprep($input)
600
    {
601
        $output = array();
602
        $error = false;
0 ignored issues
show
Unused Code introduced by
$error is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
603
        //
604
        // Mapping
605
        // Walking through the input array, performing the required steps on each of
606
        // the input chars and putting the result into the output array
607
        // While mapping required chars we apply the cannonical ordering
608
        foreach ($input as $v) {
609
            // Map to nothing == skip that code point
610
            if (in_array($v, self::$NP['map_nothing'])) continue;
611
            // Try to find prohibited input
612
            if (in_array($v, self::$NP['prohibit']) || in_array($v, self::$NP['general_prohibited'])) {
613
                $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
614
                return false;
615
            }
616
            foreach (self::$NP['prohibit_ranges'] as $range) {
617
                if ($range[0] <= $v && $v <= $range[1]) {
618
                    $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
619
                    return false;
620
                }
621
            }
622
623
            if (0xAC00 <= $v && $v <= 0xD7AF) {
624
                // Hangul syllable decomposition
625
                foreach ($this->_hangul_decompose($v) as $out) {
626
                    $output[] = (int) $out;
627
                }
628
            } elseif (($this->_idn_version == '2003') && isset(self::$NP['replacemaps'][$v])) {
629
                // There's a decomposition mapping for that code point
630
                // Decompositions only in version 2003 (original) of IDNA
631
                foreach ($this->_apply_cannonical_ordering(self::$NP['replacemaps'][$v]) as $out) {
632
                    $output[] = (int) $out;
633
                }
634
            } else {
635
                $output[] = (int) $v;
636
            }
637
        }
638
        // Before applying any Combining, try to rearrange any Hangul syllables
639
        $output = $this->_hangul_compose($output);
640
        //
641
        // Combine code points
642
        //
643
        $last_class = 0;
644
        $last_starter = 0;
645
        $out_len = count($output);
646
        for ($i = 0; $i < $out_len; ++$i) {
647
            $class = $this->_get_combining_class($output[$i]);
648
            if ((!$last_class || $last_class > $class) && $class) {
649
                // Try to match
650
                $seq_len = $i - $last_starter;
651
                $out = $this->_combine(array_slice($output, $last_starter, $seq_len));
652
                // On match: Replace the last starter with the composed character and remove
653
                // the now redundant non-starter(s)
654
                if ($out) {
655
                    $output[$last_starter] = $out;
656
                    if (count($out) != $seq_len) {
657
                        for ($j = $i+1; $j < $out_len; ++$j) $output[$j-1] = $output[$j];
658
                        unset($output[$out_len]);
659
                    }
660
                    // Rewind the for loop by one, since there can be more possible compositions
661
                    $i--;
662
                    $out_len--;
663
                    $last_class = ($i == $last_starter) ? 0 : $this->_get_combining_class($output[$i-1]);
664
                    continue;
665
                }
666
            }
667
            // The current class is 0
668
            if (!$class) $last_starter = $i;
669
            $last_class = $class;
670
        }
671
        return $output;
672
    }
673
674
    /**
675
     * Decomposes a Hangul syllable
676
     * (see http://www.unicode.org/unicode/reports/tr15/#Hangul
677
     * @param    integer  32bit UCS4 code point
678
     * @return   array    Either Hangul Syllable decomposed or original 32bit value as one value array
679
     */
680
    protected function _hangul_decompose($char)
681
    {
682
        $sindex = (int) $char - $this->_sbase;
683
        if ($sindex < 0 || $sindex >= $this->_scount) return array($char);
684
        $result = array();
685
        $result[] = (int) $this->_lbase + $sindex / $this->_ncount;
686
        $result[] = (int) $this->_vbase + ($sindex % $this->_ncount) / $this->_tcount;
687
        $T = intval($this->_tbase + $sindex % $this->_tcount);
688
        if ($T != $this->_tbase) $result[] = $T;
689
        return $result;
690
    }
691
    /**
692
     * Ccomposes a Hangul syllable
693
     * (see http://www.unicode.org/unicode/reports/tr15/#Hangul
694
     * @param    array    Decomposed UCS4 sequence
695
     * @return   array    UCS4 sequence with syllables composed
696
     */
697
    protected function _hangul_compose($input)
698
    {
699
        $inp_len = count($input);
700
        if (!$inp_len) return array();
701
        $result = array();
702
        $last = (int) $input[0];
703
        $result[] = $last; // copy first char from input to output
704
705
        for ($i = 1; $i < $inp_len; ++$i) {
706
            $char = (int) $input[$i];
707
            $sindex = $last - $this->_sbase;
708
            $lindex = $last - $this->_lbase;
709
            $vindex = $char - $this->_vbase;
710
            $tindex = $char - $this->_tbase;
711
            // Find out, whether two current characters are LV and T
712
            if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount == 0)
713
                    && 0 <= $tindex && $tindex <= $this->_tcount) {
714
                // create syllable of form LVT
715
                $last += $tindex;
716
                $result[(count($result) - 1)] = $last; // reset last
717
                continue; // discard char
718
            }
719
            // Find out, whether two current characters form L and V
720
            if (0 <= $lindex && $lindex < $this->_lcount && 0 <= $vindex && $vindex < $this->_vcount) {
721
                // create syllable of form LV
722
                $last = (int) $this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount;
723
                $result[(count($result) - 1)] = $last; // reset last
724
                continue; // discard char
725
            }
726
            // if neither case was true, just add the character
727
            $last = $char;
728
            $result[] = $char;
729
        }
730
        return $result;
731
    }
732
733
    /**
734
     * Returns the combining class of a certain wide char
735
     * @param    integer    Wide char to check (32bit integer)
736
     * @return   integer    Combining class if found, else 0
737
     */
738
    protected function _get_combining_class($char)
739
    {
740
        return isset(self::$NP['norm_combcls'][$char]) ? self::$NP['norm_combcls'][$char] : 0;
741
    }
742
743
    /**
744
     * Applies the cannonical ordering of a decomposed UCS4 sequence
745
     * @param    array      Decomposed UCS4 sequence
746
     * @return   array      Ordered USC4 sequence
747
     */
748
    protected function _apply_cannonical_ordering($input)
749
    {
750
        $swap = true;
751
        $size = count($input);
752
        while ($swap) {
753
            $swap = false;
754
            $last = $this->_get_combining_class(intval($input[0]));
755
            for ($i = 0; $i < $size-1; ++$i) {
756
                $next = $this->_get_combining_class(intval($input[$i+1]));
757
                if ($next != 0 && $last > $next) {
758
                    // Move item leftward until it fits
759
                    for ($j = $i + 1; $j > 0; --$j) {
760
                        if ($this->_get_combining_class(intval($input[$j-1])) <= $next) break;
761
                        $t = intval($input[$j]);
762
                        $input[$j] = intval($input[$j-1]);
763
                        $input[$j-1] = $t;
764
                        $swap = true;
765
                    }
766
                    // Reentering the loop looking at the old character again
767
                    $next = $last;
768
                }
769
                $last = $next;
770
            }
771
        }
772
        return $input;
773
    }
774
775
    /**
776
     * Do composition of a sequence of starter and non-starter
777
     * @param    array      UCS4 Decomposed sequence
778
     * @return   array      Ordered USC4 sequence
779
     */
780
    protected function _combine($input)
781
    {
782
        $inp_len = count($input);
783
        if (0 == $inp_len) {
784
            return false;
785
        }
786
        foreach (self::$NP['replacemaps'] as $np_src => $np_target) {
787
            if ($np_target[0] != $input[0]) continue;
788
            if (count($np_target) != $inp_len) continue;
789
            $hit = false;
790
            foreach ($input as $k2 => $v2) {
791
                if ($v2 == $np_target[$k2]) {
792
                    $hit = true;
793
                } else {
794
                    $hit = false;
795
                    break;
796
                }
797
            }
798
            if ($hit) return $np_src;
799
        }
800
        return false;
801
    }
802
803
    /**
804
     * This converts an UTF-8 encoded string to its UCS-4 representation
805
     * By talking about UCS-4 "strings" we mean arrays of 32bit integers representing
806
     * each of the "chars". This is due to PHP not being able to handle strings with
807
     * bit depth different from 8. This apllies to the reverse method _ucs4_to_utf8(), too.
808
     * The following UTF-8 encodings are supported:
809
     * bytes bits  representation
810
     * 1        7  0xxxxxxx
811
     * 2       11  110xxxxx 10xxxxxx
812
     * 3       16  1110xxxx 10xxxxxx 10xxxxxx
813
     * 4       21  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
814
     * 5       26  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
815
     * 6       31  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
816
     * Each x represents a bit that can be used to store character data.
817
     * The five and six byte sequences are part of Annex D of ISO/IEC 10646-1:2000
818
     * @param string $input
819
     * @return string
820
     */
821
    protected function _utf8_to_ucs4($input)
822
    {
823
        $output = array();
824
        $out_len = 0;
825
        $inp_len = self::byteLength($input);
826
        $mode = 'next';
827
        $test = 'none';
828
        for ($k = 0; $k < $inp_len; ++$k) {
829
            $v = ord($input{$k}); // Extract byte from input string
830
            if ($v < 128) { // We found an ASCII char - put into stirng as is
831
                $output[$out_len] = $v;
832
                ++$out_len;
833
                if ('add' == $mode) {
834
                    $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
835
                    return false;
836
                }
837
                continue;
838
            }
839
            if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
840
                $start_byte = $v;
841
                $mode = 'add';
842
                $test = 'range';
843
                if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
844
                    $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
845
                    $v = ($v - 192) << 6;
846 View Code Duplication
                } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
847
                    $next_byte = 1;
848
                    $v = ($v - 224) << 12;
849
                } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
850
                    $next_byte = 2;
851
                    $v = ($v - 240) << 18;
852 View Code Duplication
                } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
853
                    $next_byte = 3;
854
                    $v = ($v - 248) << 24;
855
                } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
856
                    $next_byte = 4;
857
                    $v = ($v - 252) << 30;
858
                } else {
859
                    $this->_error('This might be UTF-8, but I don\'t understand it at byte '.$k);
860
                    return false;
861
                }
862
                if ('add' == $mode) {
863
                    $output[$out_len] = (int) $v;
864
                    ++$out_len;
865
                    continue;
866
                }
867
            }
868
            if ('add' == $mode) {
869
                if (!$this->_allow_overlong && $test == 'range') {
870
                    $test = 'none';
871
                    if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
872
                        $this->_error('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
873
                        return false;
874
                    }
875
                }
876
                if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
877
                    $v = ($v - 128) << ($next_byte * 6);
878
                    $output[($out_len - 1)] += $v;
879
                    --$next_byte;
880
                } else {
881
                    $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
882
                    return false;
883
                }
884
                if ($next_byte < 0) {
885
                    $mode = 'next';
886
                }
887
            }
888
        } // for
889
        return $output;
890
    }
891
892
    /**
893
     * Convert UCS-4 string into UTF-8 string
894
     * See _utf8_to_ucs4() for details
895
     * @param string  $input
896
     * @return string
897
     */
898
    protected function _ucs4_to_utf8($input)
899
    {
900
        $output = '';
901
        foreach ($input as $k => $v) {
0 ignored issues
show
Bug introduced by
The expression $input of type string is not traversable.
Loading history...
902
            if ($v < 128) { // 7bit are transferred literally
903
                $output .= chr($v);
904
            } elseif ($v < (1 << 11)) { // 2 bytes
905
                $output .= chr(192+($v >> 6)).chr(128+($v & 63));
906
            } elseif ($v < (1 << 16)) { // 3 bytes
907
                $output .= chr(224+($v >> 12)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63));
908
            } elseif ($v < (1 << 21)) { // 4 bytes
909
                $output .= chr(240+($v >> 18)).chr(128+(($v >> 12) & 63)).chr(128+(($v >> 6) & 63)).chr(128+($v & 63));
910
            } else {
911
                $this->_error('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k);
912
                return false;
913
            }
914
        }
915
        return $output;
916
    }
917
918
    /**
919
     * Convert UCS-4 array into UCS-4 string
920
     *
921
     * @param array $input
922
     * @return string
923
     */
924
    protected function _ucs4_to_ucs4_string($input)
925
    {
926
        $output = '';
927
        // Take array values and split output to 4 bytes per value
928
        // The bit mask is 255, which reads &11111111
929
        foreach ($input as $v) {
930
            $output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255);
931
        }
932
        return $output;
933
    }
934
935
    /**
936
     * Convert UCS-4 strin into UCS-4 garray
937
     *
938
     * @param  string $input
939
     * @return array
940
     */
941
    protected function _ucs4_string_to_ucs4($input)
942
    {
943
        $output = array();
944
        $inp_len = self::byteLength($input);
945
        // Input length must be dividable by 4
946
        if ($inp_len % 4) {
947
            $this->_error('Input UCS4 string is broken');
948
            return false;
949
        }
950
        // Empty input - return empty output
951
        if (!$inp_len) return $output;
952
        for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
953
            // Increment output position every 4 input bytes
954
            if (!($i % 4)) {
955
                $out_len++;
956
                $output[$out_len] = 0;
957
            }
958
            $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
959
        }
960
        return $output;
961
    }
962
963
    /**
964
     * Gets the length of a string in bytes even if mbstring function
965
     * overloading is turned on
966
     *
967
     * @param string $string the string for which to get the length.
968
     * @return integer the length of the string in bytes.
969
     */
970
    protected static function byteLength($string)
971
    {
972
        if (self::$_mb_string_overload) {
973
            return mb_strlen($string, '8bit');
974
        }
975
        return strlen((binary) $string);
976
    }
977
978
    /**
979
     * Attempts to return a concrete IDNA instance.
980
     *
981
     * @param array $params Set of paramaters
982
     * @return idna_convert
983
     * @access public
984
     */
985
    public function getInstance($params = array())
986
    {
987
        return new idna_convert($params);
988
    }
989
990
    /**
991
     * Attempts to return a concrete IDNA instance for either php4 or php5,
992
     * only creating a new instance if no IDNA instance with the same
993
     * parameters currently exists.
994
     *
995
     * @param array $params Set of paramaters
996
     *
997
     * @return object idna_convert
998
     * @access public
999
     */
1000
    public function singleton($params = array())
1001
    {
1002
        static $instances;
1003
        if (!isset($instances)) {
1004
            $instances = array();
1005
        }
1006
        $signature = serialize($params);
1007
        if (!isset($instances[$signature])) {
1008
            $instances[$signature] = idna_convert::getInstance($params);
1009
        }
1010
        return $instances[$signature];
1011
    }
1012
1013
    /**
1014
     * Holds all relevant mapping tables
1015
     * See RFC3454 for details
1016
     *
1017
     * @private array
1018
     * @since 0.5.2
1019
     */
1020
    protected static $NP = array
1021
            ('map_nothing' => array(0xAD, 0x34F, 0x1806, 0x180B, 0x180C, 0x180D, 0x200B, 0x200C
1022
                    ,0x200D, 0x2060, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07
1023
                    ,0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, 0xFEFF
1024
                    )
1025
            ,'general_prohibited' => array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
1026
                    ,20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ,33, 34, 35, 36, 37, 38, 39, 40, 41, 42
1027
                    ,43, 44, 47, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126, 127, 0x3002
1028
                    )
1029
            ,'prohibit' => array(0xA0, 0x340, 0x341, 0x6DD, 0x70F, 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003
1030
                    ,0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D, 0x200E, 0x200F
1031
                    ,0x2028, 0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, 0x202F, 0x205F, 0x206A, 0x206B, 0x206C
1032
                    ,0x206D, 0x206E, 0x206F, 0x3000, 0xFEFF, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF
1033
                    ,0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE
1034
                    ,0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF
1035
                    ,0xCFFFE, 0xCFFFF, 0xDFFFE, 0xDFFFF, 0xE0001, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF
1036
                    )
1037
            ,'prohibit_ranges' => array(array(0x80, 0x9F), array(0x2060, 0x206F), array(0x1D173, 0x1D17A)
1038
                    ,array(0xE000, 0xF8FF) ,array(0xF0000, 0xFFFFD), array(0x100000, 0x10FFFD)
1039
                    ,array(0xFDD0, 0xFDEF), array(0xD800, 0xDFFF), array(0x2FF0, 0x2FFB), array(0xE0020, 0xE007F)
1040
                    )
1041
            ,'replacemaps' => array(0x41 => array(0x61), 0x42 => array(0x62), 0x43 => array(0x63)
1042
                    ,0x44 => array(0x64), 0x45 => array(0x65), 0x46 => array(0x66), 0x47 => array(0x67)
1043
                    ,0x48 => array(0x68), 0x49 => array(0x69), 0x4A => array(0x6A), 0x4B => array(0x6B)
1044
                    ,0x4C => array(0x6C), 0x4D => array(0x6D), 0x4E => array(0x6E), 0x4F => array(0x6F)
1045
                    ,0x50 => array(0x70), 0x51 => array(0x71), 0x52 => array(0x72), 0x53 => array(0x73)
1046
                    ,0x54 => array(0x74), 0x55 => array(0x75), 0x56 => array(0x76), 0x57 => array(0x77)
1047
                    ,0x58 => array(0x78), 0x59 => array(0x79), 0x5A => array(0x7A), 0xB5 => array(0x3BC)
1048
                    ,0xC0 => array(0xE0), 0xC1 => array(0xE1), 0xC2 => array(0xE2), 0xC3 => array(0xE3)
1049
                    ,0xC4 => array(0xE4), 0xC5 => array(0xE5), 0xC6 => array(0xE6), 0xC7 => array(0xE7)
1050
                    ,0xC8 => array(0xE8), 0xC9 => array(0xE9), 0xCA => array(0xEA), 0xCB => array(0xEB)
1051
                    ,0xCC => array(0xEC), 0xCD => array(0xED), 0xCE => array(0xEE), 0xCF => array(0xEF)
1052
                    ,0xD0 => array(0xF0), 0xD1 => array(0xF1), 0xD2 => array(0xF2), 0xD3 => array(0xF3)
1053
                    ,0xD4 => array(0xF4), 0xD5 => array(0xF5), 0xD6 => array(0xF6), 0xD8 => array(0xF8)
1054
                    ,0xD9 => array(0xF9), 0xDA => array(0xFA), 0xDB => array(0xFB), 0xDC => array(0xFC)
1055
                    ,0xDD => array(0xFD), 0xDE => array(0xFE), 0xDF => array(0x73, 0x73)
1056
                    ,0x100 => array(0x101), 0x102 => array(0x103), 0x104 => array(0x105)
1057
                    ,0x106 => array(0x107), 0x108 => array(0x109), 0x10A => array(0x10B)
1058
                    ,0x10C => array(0x10D), 0x10E => array(0x10F), 0x110 => array(0x111)
1059
                    ,0x112 => array(0x113), 0x114 => array(0x115), 0x116 => array(0x117)
1060
                    ,0x118 => array(0x119), 0x11A => array(0x11B), 0x11C => array(0x11D)
1061
                    ,0x11E => array(0x11F), 0x120 => array(0x121), 0x122 => array(0x123)
1062
                    ,0x124 => array(0x125), 0x126 => array(0x127), 0x128 => array(0x129)
1063
                    ,0x12A => array(0x12B), 0x12C => array(0x12D), 0x12E => array(0x12F)
1064
                    ,0x130 => array(0x69, 0x307), 0x132 => array(0x133), 0x134 => array(0x135)
1065
                    ,0x136 => array(0x137), 0x139 => array(0x13A), 0x13B => array(0x13C)
1066
                    ,0x13D => array(0x13E), 0x13F => array(0x140), 0x141 => array(0x142)
1067
                    ,0x143 => array(0x144), 0x145 => array(0x146), 0x147 => array(0x148)
1068
                    ,0x149 => array(0x2BC, 0x6E), 0x14A => array(0x14B), 0x14C => array(0x14D)
1069
                    ,0x14E => array(0x14F), 0x150 => array(0x151), 0x152 => array(0x153)
1070
                    ,0x154 => array(0x155), 0x156 => array(0x157), 0x158 => array(0x159)
1071
                    ,0x15A => array(0x15B), 0x15C => array(0x15D), 0x15E => array(0x15F)
1072
                    ,0x160 => array(0x161), 0x162 => array(0x163), 0x164 => array(0x165)
1073
                    ,0x166 => array(0x167), 0x168 => array(0x169), 0x16A => array(0x16B)
1074
                    ,0x16C => array(0x16D), 0x16E => array(0x16F), 0x170 => array(0x171)
1075
                    ,0x172 => array(0x173), 0x174 => array(0x175), 0x176 => array(0x177)
1076
                    ,0x178 => array(0xFF), 0x179 => array(0x17A), 0x17B => array(0x17C)
1077
                    ,0x17D => array(0x17E), 0x17F => array(0x73), 0x181 => array(0x253)
1078
                    ,0x182 => array(0x183), 0x184 => array(0x185), 0x186 => array(0x254)
1079
                    ,0x187 => array(0x188), 0x189 => array(0x256), 0x18A => array(0x257)
1080
                    ,0x18B => array(0x18C), 0x18E => array(0x1DD), 0x18F => array(0x259)
1081
                    ,0x190 => array(0x25B), 0x191 => array(0x192), 0x193 => array(0x260)
1082
                    ,0x194 => array(0x263), 0x196 => array(0x269), 0x197 => array(0x268)
1083
                    ,0x198 => array(0x199), 0x19C => array(0x26F), 0x19D => array(0x272)
1084
                    ,0x19F => array(0x275), 0x1A0 => array(0x1A1), 0x1A2 => array(0x1A3)
1085
                    ,0x1A4 => array(0x1A5), 0x1A6 => array(0x280), 0x1A7 => array(0x1A8)
1086
                    ,0x1A9 => array(0x283), 0x1AC => array(0x1AD), 0x1AE => array(0x288)
1087
                    ,0x1AF => array(0x1B0), 0x1B1 => array(0x28A), 0x1B2 => array(0x28B)
1088
                    ,0x1B3 => array(0x1B4), 0x1B5 => array(0x1B6), 0x1B7 => array(0x292)
1089
                    ,0x1B8 => array(0x1B9), 0x1BC => array(0x1BD), 0x1C4 => array(0x1C6)
1090
                    ,0x1C5 => array(0x1C6), 0x1C7 => array(0x1C9), 0x1C8 => array(0x1C9)
1091
                    ,0x1CA => array(0x1CC), 0x1CB => array(0x1CC), 0x1CD => array(0x1CE)
1092
                    ,0x1CF => array(0x1D0), 0x1D1   => array(0x1D2), 0x1D3   => array(0x1D4)
1093
                    ,0x1D5   => array(0x1D6), 0x1D7   => array(0x1D8), 0x1D9   => array(0x1DA)
1094
                    ,0x1DB   => array(0x1DC), 0x1DE   => array(0x1DF), 0x1E0   => array(0x1E1)
1095
                    ,0x1E2   => array(0x1E3), 0x1E4   => array(0x1E5), 0x1E6   => array(0x1E7)
1096
                    ,0x1E8   => array(0x1E9), 0x1EA   => array(0x1EB), 0x1EC   => array(0x1ED)
1097
                    ,0x1EE   => array(0x1EF), 0x1F0   => array(0x6A, 0x30C), 0x1F1   => array(0x1F3)
1098
                    ,0x1F2   => array(0x1F3), 0x1F4   => array(0x1F5), 0x1F6   => array(0x195)
1099
                    ,0x1F7   => array(0x1BF), 0x1F8   => array(0x1F9), 0x1FA   => array(0x1FB)
1100
                    ,0x1FC   => array(0x1FD), 0x1FE   => array(0x1FF), 0x200   => array(0x201)
1101
                    ,0x202   => array(0x203), 0x204   => array(0x205), 0x206   => array(0x207)
1102
                    ,0x208   => array(0x209), 0x20A   => array(0x20B), 0x20C   => array(0x20D)
1103
                    ,0x20E   => array(0x20F), 0x210   => array(0x211), 0x212   => array(0x213)
1104
                    ,0x214   => array(0x215), 0x216   => array(0x217), 0x218   => array(0x219)
1105
                    ,0x21A   => array(0x21B), 0x21C   => array(0x21D), 0x21E   => array(0x21F)
1106
                    ,0x220   => array(0x19E), 0x222   => array(0x223), 0x224   => array(0x225)
1107
                    ,0x226   => array(0x227), 0x228   => array(0x229), 0x22A   => array(0x22B)
1108
                    ,0x22C   => array(0x22D), 0x22E   => array(0x22F), 0x230   => array(0x231)
1109
                    ,0x232   => array(0x233), 0x345   => array(0x3B9), 0x37A   => array(0x20, 0x3B9)
1110
                    ,0x386   => array(0x3AC), 0x388   => array(0x3AD), 0x389   => array(0x3AE)
1111
                    ,0x38A   => array(0x3AF), 0x38C   => array(0x3CC), 0x38E   => array(0x3CD)
1112
                    ,0x38F   => array(0x3CE), 0x390   => array(0x3B9, 0x308, 0x301)
1113
                    ,0x391   => array(0x3B1), 0x392   => array(0x3B2), 0x393   => array(0x3B3)
1114
                    ,0x394   => array(0x3B4), 0x395   => array(0x3B5), 0x396   => array(0x3B6)
1115
                    ,0x397   => array(0x3B7), 0x398   => array(0x3B8), 0x399   => array(0x3B9)
1116
                    ,0x39A   => array(0x3BA), 0x39B   => array(0x3BB), 0x39C   => array(0x3BC)
1117
                    ,0x39D   => array(0x3BD), 0x39E   => array(0x3BE), 0x39F   => array(0x3BF)
1118
                    ,0x3A0   => array(0x3C0), 0x3A1   => array(0x3C1), 0x3A3   => array(0x3C3)
1119
                    ,0x3A4   => array(0x3C4), 0x3A5   => array(0x3C5), 0x3A6   => array(0x3C6)
1120
                    ,0x3A7   => array(0x3C7), 0x3A8   => array(0x3C8), 0x3A9   => array(0x3C9)
1121
                    ,0x3AA   => array(0x3CA), 0x3AB   => array(0x3CB), 0x3B0   => array(0x3C5, 0x308, 0x301)
1122
                    ,0x3C2   => array(0x3C3), 0x3D0   => array(0x3B2), 0x3D1   => array(0x3B8)
1123
                    ,0x3D2   => array(0x3C5), 0x3D3   => array(0x3CD), 0x3D4   => array(0x3CB)
1124
                    ,0x3D5   => array(0x3C6), 0x3D6   => array(0x3C0), 0x3D8   => array(0x3D9)
1125
                    ,0x3DA   => array(0x3DB), 0x3DC   => array(0x3DD), 0x3DE   => array(0x3DF)
1126
                    ,0x3E0   => array(0x3E1), 0x3E2   => array(0x3E3), 0x3E4   => array(0x3E5)
1127
                    ,0x3E6   => array(0x3E7), 0x3E8   => array(0x3E9), 0x3EA   => array(0x3EB)
1128
                    ,0x3EC   => array(0x3ED), 0x3EE   => array(0x3EF), 0x3F0   => array(0x3BA)
1129
                    ,0x3F1   => array(0x3C1), 0x3F2   => array(0x3C3), 0x3F4   => array(0x3B8)
1130
                    ,0x3F5   => array(0x3B5), 0x400   => array(0x450), 0x401   => array(0x451)
1131
                    ,0x402   => array(0x452), 0x403   => array(0x453), 0x404   => array(0x454)
1132
                    ,0x405   => array(0x455), 0x406   => array(0x456), 0x407   => array(0x457)
1133
                    ,0x408   => array(0x458), 0x409   => array(0x459), 0x40A   => array(0x45A)
1134
                    ,0x40B   => array(0x45B), 0x40C   => array(0x45C), 0x40D   => array(0x45D)
1135
                    ,0x40E   => array(0x45E), 0x40F   => array(0x45F), 0x410   => array(0x430)
1136
                    ,0x411   => array(0x431), 0x412   => array(0x432), 0x413   => array(0x433)
1137
                    ,0x414   => array(0x434), 0x415   => array(0x435), 0x416   => array(0x436)
1138
                    ,0x417   => array(0x437), 0x418   => array(0x438), 0x419   => array(0x439)
1139
                    ,0x41A   => array(0x43A), 0x41B   => array(0x43B), 0x41C   => array(0x43C)
1140
                    ,0x41D   => array(0x43D), 0x41E   => array(0x43E), 0x41F   => array(0x43F)
1141
                    ,0x420   => array(0x440), 0x421   => array(0x441), 0x422   => array(0x442)
1142
                    ,0x423   => array(0x443), 0x424   => array(0x444), 0x425   => array(0x445)
1143
                    ,0x426   => array(0x446), 0x427   => array(0x447), 0x428   => array(0x448)
1144
                    ,0x429   => array(0x449), 0x42A   => array(0x44A), 0x42B   => array(0x44B)
1145
                    ,0x42C   => array(0x44C), 0x42D   => array(0x44D), 0x42E   => array(0x44E)
1146
                    ,0x42F   => array(0x44F), 0x460   => array(0x461), 0x462   => array(0x463)
1147
                    ,0x464   => array(0x465), 0x466   => array(0x467), 0x468   => array(0x469)
1148
                    ,0x46A   => array(0x46B), 0x46C   => array(0x46D), 0x46E   => array(0x46F)
1149
                    ,0x470   => array(0x471), 0x472   => array(0x473), 0x474   => array(0x475)
1150
                    ,0x476   => array(0x477), 0x478   => array(0x479), 0x47A   => array(0x47B)
1151
                    ,0x47C   => array(0x47D), 0x47E   => array(0x47F), 0x480   => array(0x481)
1152
                    ,0x48A   => array(0x48B), 0x48C   => array(0x48D), 0x48E   => array(0x48F)
1153
                    ,0x490   => array(0x491), 0x492   => array(0x493), 0x494   => array(0x495)
1154
                    ,0x496   => array(0x497), 0x498   => array(0x499), 0x49A   => array(0x49B)
1155
                    ,0x49C   => array(0x49D), 0x49E   => array(0x49F), 0x4A0   => array(0x4A1)
1156
                    ,0x4A2   => array(0x4A3), 0x4A4   => array(0x4A5), 0x4A6   => array(0x4A7)
1157
                    ,0x4A8   => array(0x4A9), 0x4AA   => array(0x4AB), 0x4AC   => array(0x4AD)
1158
                    ,0x4AE   => array(0x4AF), 0x4B0   => array(0x4B1), 0x4B2   => array(0x4B3)
1159
                    ,0x4B4   => array(0x4B5), 0x4B6   => array(0x4B7), 0x4B8   => array(0x4B9)
1160
                    ,0x4BA   => array(0x4BB), 0x4BC   => array(0x4BD), 0x4BE   => array(0x4BF)
1161
                    ,0x4C1   => array(0x4C2), 0x4C3   => array(0x4C4), 0x4C5   => array(0x4C6)
1162
                    ,0x4C7   => array(0x4C8), 0x4C9   => array(0x4CA), 0x4CB   => array(0x4CC)
1163
                    ,0x4CD   => array(0x4CE), 0x4D0   => array(0x4D1), 0x4D2   => array(0x4D3)
1164
                    ,0x4D4   => array(0x4D5), 0x4D6   => array(0x4D7), 0x4D8   => array(0x4D9)
1165
                    ,0x4DA   => array(0x4DB), 0x4DC   => array(0x4DD), 0x4DE   => array(0x4DF)
1166
                    ,0x4E0   => array(0x4E1), 0x4E2   => array(0x4E3), 0x4E4   => array(0x4E5)
1167
                    ,0x4E6   => array(0x4E7), 0x4E8   => array(0x4E9), 0x4EA   => array(0x4EB)
1168
                    ,0x4EC   => array(0x4ED), 0x4EE   => array(0x4EF), 0x4F0   => array(0x4F1)
1169
                    ,0x4F2   => array(0x4F3), 0x4F4   => array(0x4F5), 0x4F8   => array(0x4F9)
1170
                    ,0x500   => array(0x501), 0x502   => array(0x503), 0x504   => array(0x505)
1171
                    ,0x506   => array(0x507), 0x508   => array(0x509), 0x50A   => array(0x50B)
1172
                    ,0x50C   => array(0x50D), 0x50E   => array(0x50F), 0x531   => array(0x561)
1173
                    ,0x532   => array(0x562), 0x533   => array(0x563), 0x534   => array(0x564)
1174
                    ,0x535   => array(0x565), 0x536   => array(0x566), 0x537   => array(0x567)
1175
                    ,0x538   => array(0x568), 0x539   => array(0x569), 0x53A   => array(0x56A)
1176
                    ,0x53B   => array(0x56B), 0x53C   => array(0x56C), 0x53D   => array(0x56D)
1177
                    ,0x53E   => array(0x56E), 0x53F   => array(0x56F), 0x540   => array(0x570)
1178
                    ,0x541   => array(0x571), 0x542   => array(0x572), 0x543   => array(0x573)
1179
                    ,0x544   => array(0x574), 0x545   => array(0x575), 0x546   => array(0x576)
1180
                    ,0x547   => array(0x577), 0x548   => array(0x578), 0x549   => array(0x579)
1181
                    ,0x54A   => array(0x57A), 0x54B   => array(0x57B), 0x54C   => array(0x57C)
1182
                    ,0x54D   => array(0x57D), 0x54E   => array(0x57E), 0x54F   => array(0x57F)
1183
                    ,0x550   => array(0x580), 0x551   => array(0x581), 0x552   => array(0x582)
1184
                    ,0x553   => array(0x583), 0x554   => array(0x584), 0x555   => array(0x585)
1185
                    ,0x556 => array(0x586), 0x587 => array(0x565, 0x582), 0xE33 => array(0xE4D, 0xE32)
1186
                    ,0x1E00  => array(0x1E01), 0x1E02  => array(0x1E03), 0x1E04  => array(0x1E05)
1187
                    ,0x1E06  => array(0x1E07), 0x1E08  => array(0x1E09), 0x1E0A  => array(0x1E0B)
1188
                    ,0x1E0C  => array(0x1E0D), 0x1E0E  => array(0x1E0F), 0x1E10  => array(0x1E11)
1189
                    ,0x1E12  => array(0x1E13), 0x1E14  => array(0x1E15), 0x1E16  => array(0x1E17)
1190
                    ,0x1E18  => array(0x1E19), 0x1E1A  => array(0x1E1B), 0x1E1C  => array(0x1E1D)
1191
                    ,0x1E1E  => array(0x1E1F), 0x1E20  => array(0x1E21), 0x1E22  => array(0x1E23)
1192
                    ,0x1E24  => array(0x1E25), 0x1E26  => array(0x1E27), 0x1E28  => array(0x1E29)
1193
                    ,0x1E2A  => array(0x1E2B), 0x1E2C  => array(0x1E2D), 0x1E2E  => array(0x1E2F)
1194
                    ,0x1E30  => array(0x1E31), 0x1E32  => array(0x1E33), 0x1E34  => array(0x1E35)
1195
                    ,0x1E36  => array(0x1E37), 0x1E38  => array(0x1E39), 0x1E3A  => array(0x1E3B)
1196
                    ,0x1E3C  => array(0x1E3D), 0x1E3E  => array(0x1E3F), 0x1E40  => array(0x1E41)
1197
                    ,0x1E42  => array(0x1E43), 0x1E44  => array(0x1E45), 0x1E46  => array(0x1E47)
1198
                    ,0x1E48  => array(0x1E49), 0x1E4A  => array(0x1E4B), 0x1E4C  => array(0x1E4D)
1199
                    ,0x1E4E  => array(0x1E4F), 0x1E50  => array(0x1E51), 0x1E52  => array(0x1E53)
1200
                    ,0x1E54  => array(0x1E55), 0x1E56  => array(0x1E57), 0x1E58  => array(0x1E59)
1201
                    ,0x1E5A  => array(0x1E5B), 0x1E5C  => array(0x1E5D), 0x1E5E  => array(0x1E5F)
1202
                    ,0x1E60  => array(0x1E61), 0x1E62  => array(0x1E63), 0x1E64  => array(0x1E65)
1203
                    ,0x1E66  => array(0x1E67), 0x1E68  => array(0x1E69), 0x1E6A  => array(0x1E6B)
1204
                    ,0x1E6C  => array(0x1E6D), 0x1E6E  => array(0x1E6F), 0x1E70  => array(0x1E71)
1205
                    ,0x1E72  => array(0x1E73), 0x1E74  => array(0x1E75), 0x1E76  => array(0x1E77)
1206
                    ,0x1E78  => array(0x1E79), 0x1E7A  => array(0x1E7B), 0x1E7C  => array(0x1E7D)
1207
                    ,0x1E7E  => array(0x1E7F), 0x1E80  => array(0x1E81), 0x1E82  => array(0x1E83)
1208
                    ,0x1E84  => array(0x1E85), 0x1E86  => array(0x1E87), 0x1E88  => array(0x1E89)
1209
                    ,0x1E8A  => array(0x1E8B), 0x1E8C  => array(0x1E8D), 0x1E8E  => array(0x1E8F)
1210
                    ,0x1E90  => array(0x1E91), 0x1E92  => array(0x1E93), 0x1E94  => array(0x1E95)
1211
                    ,0x1E96  => array(0x68, 0x331), 0x1E97  => array(0x74, 0x308), 0x1E98  => array(0x77, 0x30A)
1212
                    ,0x1E99  => array(0x79, 0x30A), 0x1E9A  => array(0x61, 0x2BE), 0x1E9B  => array(0x1E61)
1213
                    ,0x1EA0  => array(0x1EA1), 0x1EA2  => array(0x1EA3), 0x1EA4  => array(0x1EA5)
1214
                    ,0x1EA6  => array(0x1EA7), 0x1EA8  => array(0x1EA9), 0x1EAA  => array(0x1EAB)
1215
                    ,0x1EAC  => array(0x1EAD), 0x1EAE  => array(0x1EAF), 0x1EB0  => array(0x1EB1)
1216
                    ,0x1EB2  => array(0x1EB3), 0x1EB4  => array(0x1EB5), 0x1EB6  => array(0x1EB7)
1217
                    ,0x1EB8  => array(0x1EB9), 0x1EBA  => array(0x1EBB), 0x1EBC  => array(0x1EBD)
1218
                    ,0x1EBE  => array(0x1EBF), 0x1EC0  => array(0x1EC1), 0x1EC2  => array(0x1EC3)
1219
                    ,0x1EC4  => array(0x1EC5), 0x1EC6  => array(0x1EC7), 0x1EC8  => array(0x1EC9)
1220
                    ,0x1ECA  => array(0x1ECB), 0x1ECC  => array(0x1ECD), 0x1ECE  => array(0x1ECF)
1221
                    ,0x1ED0  => array(0x1ED1), 0x1ED2  => array(0x1ED3), 0x1ED4  => array(0x1ED5)
1222
                    ,0x1ED6  => array(0x1ED7), 0x1ED8  => array(0x1ED9), 0x1EDA  => array(0x1EDB)
1223
                    ,0x1EDC  => array(0x1EDD), 0x1EDE  => array(0x1EDF), 0x1EE0  => array(0x1EE1)
1224
                    ,0x1EE2  => array(0x1EE3), 0x1EE4  => array(0x1EE5), 0x1EE6  => array(0x1EE7)
1225
                    ,0x1EE8  => array(0x1EE9), 0x1EEA  => array(0x1EEB), 0x1EEC  => array(0x1EED)
1226
                    ,0x1EEE  => array(0x1EEF), 0x1EF0  => array(0x1EF1), 0x1EF2  => array(0x1EF3)
1227
                    ,0x1EF4  => array(0x1EF5), 0x1EF6  => array(0x1EF7), 0x1EF8  => array(0x1EF9)
1228
                    ,0x1F08  => array(0x1F00), 0x1F09  => array(0x1F01), 0x1F0A  => array(0x1F02)
1229
                    ,0x1F0B  => array(0x1F03), 0x1F0C  => array(0x1F04), 0x1F0D  => array(0x1F05)
1230
                    ,0x1F0E  => array(0x1F06), 0x1F0F  => array(0x1F07), 0x1F18  => array(0x1F10)
1231
                    ,0x1F19  => array(0x1F11), 0x1F1A  => array(0x1F12), 0x1F1B  => array(0x1F13)
1232
                    ,0x1F1C  => array(0x1F14), 0x1F1D  => array(0x1F15), 0x1F28  => array(0x1F20)
1233
                    ,0x1F29  => array(0x1F21), 0x1F2A  => array(0x1F22), 0x1F2B  => array(0x1F23)
1234
                    ,0x1F2C  => array(0x1F24), 0x1F2D  => array(0x1F25), 0x1F2E  => array(0x1F26)
1235
                    ,0x1F2F  => array(0x1F27), 0x1F38  => array(0x1F30), 0x1F39  => array(0x1F31)
1236
                    ,0x1F3A  => array(0x1F32), 0x1F3B  => array(0x1F33), 0x1F3C  => array(0x1F34)
1237
                    ,0x1F3D  => array(0x1F35), 0x1F3E  => array(0x1F36), 0x1F3F  => array(0x1F37)
1238
                    ,0x1F48  => array(0x1F40), 0x1F49  => array(0x1F41), 0x1F4A  => array(0x1F42)
1239
                    ,0x1F4B  => array(0x1F43), 0x1F4C  => array(0x1F44), 0x1F4D  => array(0x1F45)
1240
                    ,0x1F50  => array(0x3C5, 0x313), 0x1F52  => array(0x3C5, 0x313, 0x300)
1241
                    ,0x1F54  => array(0x3C5, 0x313, 0x301), 0x1F56  => array(0x3C5, 0x313, 0x342)
1242
                    ,0x1F59  => array(0x1F51), 0x1F5B  => array(0x1F53), 0x1F5D  => array(0x1F55)
1243
                    ,0x1F5F  => array(0x1F57), 0x1F68  => array(0x1F60), 0x1F69  => array(0x1F61)
1244
                    ,0x1F6A  => array(0x1F62), 0x1F6B  => array(0x1F63), 0x1F6C  => array(0x1F64)
1245
                    ,0x1F6D  => array(0x1F65), 0x1F6E  => array(0x1F66), 0x1F6F  => array(0x1F67)
1246
                    ,0x1F80  => array(0x1F00, 0x3B9), 0x1F81  => array(0x1F01, 0x3B9)
1247
                    ,0x1F82  => array(0x1F02, 0x3B9), 0x1F83  => array(0x1F03, 0x3B9)
1248
                    ,0x1F84  => array(0x1F04, 0x3B9), 0x1F85  => array(0x1F05, 0x3B9)
1249
                    ,0x1F86  => array(0x1F06, 0x3B9), 0x1F87  => array(0x1F07, 0x3B9)
1250
                    ,0x1F88  => array(0x1F00, 0x3B9), 0x1F89  => array(0x1F01, 0x3B9)
1251
                    ,0x1F8A  => array(0x1F02, 0x3B9), 0x1F8B  => array(0x1F03, 0x3B9)
1252
                    ,0x1F8C  => array(0x1F04, 0x3B9), 0x1F8D  => array(0x1F05, 0x3B9)
1253
                    ,0x1F8E  => array(0x1F06, 0x3B9), 0x1F8F  => array(0x1F07, 0x3B9)
1254
                    ,0x1F90  => array(0x1F20, 0x3B9), 0x1F91  => array(0x1F21, 0x3B9)
1255
                    ,0x1F92  => array(0x1F22, 0x3B9), 0x1F93  => array(0x1F23, 0x3B9)
1256
                    ,0x1F94  => array(0x1F24, 0x3B9), 0x1F95  => array(0x1F25, 0x3B9)
1257
                    ,0x1F96  => array(0x1F26, 0x3B9), 0x1F97  => array(0x1F27, 0x3B9)
1258
                    ,0x1F98  => array(0x1F20, 0x3B9), 0x1F99  => array(0x1F21, 0x3B9)
1259
                    ,0x1F9A  => array(0x1F22, 0x3B9), 0x1F9B  => array(0x1F23, 0x3B9)
1260
                    ,0x1F9C  => array(0x1F24, 0x3B9), 0x1F9D  => array(0x1F25, 0x3B9)
1261
                    ,0x1F9E  => array(0x1F26, 0x3B9), 0x1F9F  => array(0x1F27, 0x3B9)
1262
                    ,0x1FA0  => array(0x1F60, 0x3B9), 0x1FA1  => array(0x1F61, 0x3B9)
1263
                    ,0x1FA2  => array(0x1F62, 0x3B9), 0x1FA3  => array(0x1F63, 0x3B9)
1264
                    ,0x1FA4  => array(0x1F64, 0x3B9), 0x1FA5  => array(0x1F65, 0x3B9)
1265
                    ,0x1FA6  => array(0x1F66, 0x3B9), 0x1FA7  => array(0x1F67, 0x3B9)
1266
                    ,0x1FA8  => array(0x1F60, 0x3B9), 0x1FA9  => array(0x1F61, 0x3B9)
1267
                    ,0x1FAA  => array(0x1F62, 0x3B9), 0x1FAB  => array(0x1F63, 0x3B9)
1268
                    ,0x1FAC  => array(0x1F64, 0x3B9), 0x1FAD  => array(0x1F65, 0x3B9)
1269
                    ,0x1FAE  => array(0x1F66, 0x3B9), 0x1FAF  => array(0x1F67, 0x3B9)
1270
                    ,0x1FB2  => array(0x1F70, 0x3B9), 0x1FB3  => array(0x3B1, 0x3B9)
1271
                    ,0x1FB4  => array(0x3AC, 0x3B9), 0x1FB6  => array(0x3B1, 0x342)
1272
                    ,0x1FB7  => array(0x3B1, 0x342, 0x3B9), 0x1FB8  => array(0x1FB0)
1273
                    ,0x1FB9  => array(0x1FB1), 0x1FBA  => array(0x1F70), 0x1FBB  => array(0x1F71)
1274
                    ,0x1FBC  => array(0x3B1, 0x3B9), 0x1FBE  => array(0x3B9)
1275
                    ,0x1FC2  => array(0x1F74, 0x3B9), 0x1FC3  => array(0x3B7, 0x3B9)
1276
                    ,0x1FC4  => array(0x3AE, 0x3B9), 0x1FC6  => array(0x3B7, 0x342)
1277
                    ,0x1FC7  => array(0x3B7, 0x342, 0x3B9), 0x1FC8  => array(0x1F72)
1278
                    ,0x1FC9  => array(0x1F73), 0x1FCA  => array(0x1F74), 0x1FCB  => array(0x1F75)
1279
                    ,0x1FCC  => array(0x3B7, 0x3B9), 0x1FD2  => array(0x3B9, 0x308, 0x300)
1280
                    ,0x1FD3  => array(0x3B9, 0x308, 0x301), 0x1FD6  => array(0x3B9, 0x342)
1281
                    ,0x1FD7  => array(0x3B9, 0x308, 0x342), 0x1FD8  => array(0x1FD0)
1282
                    ,0x1FD9  => array(0x1FD1), 0x1FDA  => array(0x1F76)
1283
                    ,0x1FDB  => array(0x1F77), 0x1FE2  => array(0x3C5, 0x308, 0x300)
1284
                    ,0x1FE3  => array(0x3C5, 0x308, 0x301), 0x1FE4  => array(0x3C1, 0x313)
1285
                    ,0x1FE6  => array(0x3C5, 0x342), 0x1FE7  => array(0x3C5, 0x308, 0x342)
1286
                    ,0x1FE8  => array(0x1FE0), 0x1FE9  => array(0x1FE1)
1287
                    ,0x1FEA  => array(0x1F7A), 0x1FEB  => array(0x1F7B)
1288
                    ,0x1FEC  => array(0x1FE5), 0x1FF2  => array(0x1F7C, 0x3B9)
1289
                    ,0x1FF3  => array(0x3C9, 0x3B9), 0x1FF4  => array(0x3CE, 0x3B9)
1290
                    ,0x1FF6  => array(0x3C9, 0x342), 0x1FF7  => array(0x3C9, 0x342, 0x3B9)
1291
                    ,0x1FF8  => array(0x1F78), 0x1FF9  => array(0x1F79), 0x1FFA  => array(0x1F7C)
1292
                    ,0x1FFB  => array(0x1F7D), 0x1FFC  => array(0x3C9, 0x3B9)
1293
                    ,0x20A8  => array(0x72, 0x73), 0x2102  => array(0x63), 0x2103  => array(0xB0, 0x63)
1294
                    ,0x2107  => array(0x25B), 0x2109  => array(0xB0, 0x66), 0x210B  => array(0x68)
1295
                    ,0x210C  => array(0x68), 0x210D  => array(0x68), 0x2110  => array(0x69)
1296
                    ,0x2111  => array(0x69), 0x2112  => array(0x6C), 0x2115  => array(0x6E)
1297
                    ,0x2116  => array(0x6E, 0x6F), 0x2119  => array(0x70), 0x211A  => array(0x71)
1298
                    ,0x211B  => array(0x72), 0x211C  => array(0x72), 0x211D  => array(0x72)
1299
                    ,0x2120  => array(0x73, 0x6D), 0x2121  => array(0x74, 0x65, 0x6C)
1300
                    ,0x2122  => array(0x74, 0x6D), 0x2124  => array(0x7A), 0x2126  => array(0x3C9)
1301
                    ,0x2128  => array(0x7A), 0x212A  => array(0x6B), 0x212B  => array(0xE5)
1302
                    ,0x212C  => array(0x62), 0x212D  => array(0x63), 0x2130  => array(0x65)
1303
                    ,0x2131  => array(0x66), 0x2133  => array(0x6D), 0x213E  => array(0x3B3)
1304
                    ,0x213F  => array(0x3C0), 0x2145  => array(0x64) ,0x2160  => array(0x2170)
1305
                    ,0x2161  => array(0x2171), 0x2162  => array(0x2172), 0x2163  => array(0x2173)
1306
                    ,0x2164  => array(0x2174), 0x2165  => array(0x2175), 0x2166  => array(0x2176)
1307
                    ,0x2167  => array(0x2177), 0x2168  => array(0x2178), 0x2169  => array(0x2179)
1308
                    ,0x216A  => array(0x217A), 0x216B  => array(0x217B), 0x216C  => array(0x217C)
1309
                    ,0x216D  => array(0x217D), 0x216E  => array(0x217E), 0x216F  => array(0x217F)
1310
                    ,0x24B6  => array(0x24D0), 0x24B7  => array(0x24D1), 0x24B8  => array(0x24D2)
1311
                    ,0x24B9  => array(0x24D3), 0x24BA  => array(0x24D4), 0x24BB  => array(0x24D5)
1312
                    ,0x24BC  => array(0x24D6), 0x24BD  => array(0x24D7), 0x24BE  => array(0x24D8)
1313
                    ,0x24BF  => array(0x24D9), 0x24C0  => array(0x24DA), 0x24C1  => array(0x24DB)
1314
                    ,0x24C2  => array(0x24DC), 0x24C3  => array(0x24DD), 0x24C4  => array(0x24DE)
1315
                    ,0x24C5  => array(0x24DF), 0x24C6  => array(0x24E0), 0x24C7  => array(0x24E1)
1316
                    ,0x24C8  => array(0x24E2), 0x24C9  => array(0x24E3), 0x24CA  => array(0x24E4)
1317
                    ,0x24CB  => array(0x24E5), 0x24CC  => array(0x24E6), 0x24CD  => array(0x24E7)
1318
                    ,0x24CE  => array(0x24E8), 0x24CF  => array(0x24E9), 0x3371  => array(0x68, 0x70, 0x61)
1319
                    ,0x3373  => array(0x61, 0x75), 0x3375  => array(0x6F, 0x76)
1320
                    ,0x3380  => array(0x70, 0x61), 0x3381  => array(0x6E, 0x61)
1321
                    ,0x3382  => array(0x3BC, 0x61), 0x3383  => array(0x6D, 0x61)
1322
                    ,0x3384  => array(0x6B, 0x61), 0x3385  => array(0x6B, 0x62)
1323
                    ,0x3386  => array(0x6D, 0x62), 0x3387  => array(0x67, 0x62)
1324
                    ,0x338A  => array(0x70, 0x66), 0x338B  => array(0x6E, 0x66)
1325
                    ,0x338C  => array(0x3BC, 0x66), 0x3390  => array(0x68, 0x7A)
1326
                    ,0x3391  => array(0x6B, 0x68, 0x7A), 0x3392  => array(0x6D, 0x68, 0x7A)
1327
                    ,0x3393  => array(0x67, 0x68, 0x7A), 0x3394  => array(0x74, 0x68, 0x7A)
1328
                    ,0x33A9  => array(0x70, 0x61), 0x33AA  => array(0x6B, 0x70, 0x61)
1329
                    ,0x33AB  => array(0x6D, 0x70, 0x61), 0x33AC  => array(0x67, 0x70, 0x61)
1330
                    ,0x33B4  => array(0x70, 0x76), 0x33B5  => array(0x6E, 0x76)
1331
                    ,0x33B6  => array(0x3BC, 0x76), 0x33B7  => array(0x6D, 0x76)
1332
                    ,0x33B8  => array(0x6B, 0x76), 0x33B9  => array(0x6D, 0x76)
1333
                    ,0x33BA  => array(0x70, 0x77), 0x33BB  => array(0x6E, 0x77)
1334
                    ,0x33BC  => array(0x3BC, 0x77), 0x33BD  => array(0x6D, 0x77)
1335
                    ,0x33BE  => array(0x6B, 0x77), 0x33BF  => array(0x6D, 0x77)
1336
                    ,0x33C0  => array(0x6B, 0x3C9), 0x33C1  => array(0x6D, 0x3C9) /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1337
                    ,0x33C2  => array(0x61, 0x2E, 0x6D, 0x2E) */
1338
                    ,0x33C3  => array(0x62, 0x71), 0x33C6  => array(0x63, 0x2215, 0x6B, 0x67)
1339
                    ,0x33C7  => array(0x63, 0x6F, 0x2E), 0x33C8  => array(0x64, 0x62)
1340
                    ,0x33C9  => array(0x67, 0x79), 0x33CB  => array(0x68, 0x70)
1341
                    ,0x33CD  => array(0x6B, 0x6B), 0x33CE  => array(0x6B, 0x6D)
1342
                    ,0x33D7  => array(0x70, 0x68), 0x33D9  => array(0x70, 0x70, 0x6D)
1343
                    ,0x33DA  => array(0x70, 0x72), 0x33DC  => array(0x73, 0x76)
1344
                    ,0x33DD  => array(0x77, 0x62), 0xFB00  => array(0x66, 0x66)
1345
                    ,0xFB01  => array(0x66, 0x69), 0xFB02  => array(0x66, 0x6C)
1346
                    ,0xFB03  => array(0x66, 0x66, 0x69), 0xFB04  => array(0x66, 0x66, 0x6C)
1347
                    ,0xFB05  => array(0x73, 0x74), 0xFB06  => array(0x73, 0x74)
1348
                    ,0xFB13  => array(0x574, 0x576), 0xFB14  => array(0x574, 0x565)
1349
                    ,0xFB15  => array(0x574, 0x56B), 0xFB16  => array(0x57E, 0x576)
1350
                    ,0xFB17  => array(0x574, 0x56D), 0xFF21  => array(0xFF41)
1351
                    ,0xFF22  => array(0xFF42), 0xFF23  => array(0xFF43), 0xFF24  => array(0xFF44)
1352
                    ,0xFF25  => array(0xFF45), 0xFF26  => array(0xFF46), 0xFF27  => array(0xFF47)
1353
                    ,0xFF28  => array(0xFF48), 0xFF29  => array(0xFF49), 0xFF2A  => array(0xFF4A)
1354
                    ,0xFF2B  => array(0xFF4B), 0xFF2C  => array(0xFF4C), 0xFF2D  => array(0xFF4D)
1355
                    ,0xFF2E  => array(0xFF4E), 0xFF2F  => array(0xFF4F), 0xFF30  => array(0xFF50)
1356
                    ,0xFF31  => array(0xFF51), 0xFF32  => array(0xFF52), 0xFF33  => array(0xFF53)
1357
                    ,0xFF34  => array(0xFF54), 0xFF35  => array(0xFF55), 0xFF36  => array(0xFF56)
1358
                    ,0xFF37  => array(0xFF57), 0xFF38  => array(0xFF58), 0xFF39  => array(0xFF59)
1359
                    ,0xFF3A  => array(0xFF5A), 0x10400 => array(0x10428), 0x10401 => array(0x10429)
1360
                    ,0x10402 => array(0x1042A), 0x10403 => array(0x1042B), 0x10404 => array(0x1042C)
1361
                    ,0x10405 => array(0x1042D), 0x10406 => array(0x1042E), 0x10407 => array(0x1042F)
1362
                    ,0x10408 => array(0x10430), 0x10409 => array(0x10431), 0x1040A => array(0x10432)
1363
                    ,0x1040B => array(0x10433), 0x1040C => array(0x10434), 0x1040D => array(0x10435)
1364
                    ,0x1040E => array(0x10436), 0x1040F => array(0x10437), 0x10410 => array(0x10438)
1365
                    ,0x10411 => array(0x10439), 0x10412 => array(0x1043A), 0x10413 => array(0x1043B)
1366
                    ,0x10414 => array(0x1043C), 0x10415 => array(0x1043D), 0x10416 => array(0x1043E)
1367
                    ,0x10417 => array(0x1043F), 0x10418 => array(0x10440), 0x10419 => array(0x10441)
1368
                    ,0x1041A => array(0x10442), 0x1041B => array(0x10443), 0x1041C => array(0x10444)
1369
                    ,0x1041D => array(0x10445), 0x1041E => array(0x10446), 0x1041F => array(0x10447)
1370
                    ,0x10420 => array(0x10448), 0x10421 => array(0x10449), 0x10422 => array(0x1044A)
1371
                    ,0x10423 => array(0x1044B), 0x10424 => array(0x1044C), 0x10425 => array(0x1044D)
1372
                    ,0x1D400 => array(0x61), 0x1D401 => array(0x62), 0x1D402 => array(0x63)
1373
                    ,0x1D403 => array(0x64), 0x1D404 => array(0x65), 0x1D405 => array(0x66)
1374
                    ,0x1D406 => array(0x67), 0x1D407 => array(0x68), 0x1D408 => array(0x69)
1375
                    ,0x1D409 => array(0x6A), 0x1D40A => array(0x6B), 0x1D40B => array(0x6C)
1376
                    ,0x1D40C => array(0x6D), 0x1D40D => array(0x6E), 0x1D40E => array(0x6F)
1377
                    ,0x1D40F => array(0x70), 0x1D410 => array(0x71), 0x1D411 => array(0x72)
1378
                    ,0x1D412 => array(0x73), 0x1D413 => array(0x74), 0x1D414 => array(0x75)
1379
                    ,0x1D415 => array(0x76), 0x1D416 => array(0x77), 0x1D417 => array(0x78)
1380
                    ,0x1D418 => array(0x79), 0x1D419 => array(0x7A), 0x1D434 => array(0x61)
1381
                    ,0x1D435 => array(0x62), 0x1D436 => array(0x63), 0x1D437 => array(0x64)
1382
                    ,0x1D438 => array(0x65), 0x1D439 => array(0x66), 0x1D43A => array(0x67)
1383
                    ,0x1D43B => array(0x68), 0x1D43C => array(0x69), 0x1D43D => array(0x6A)
1384
                    ,0x1D43E => array(0x6B), 0x1D43F => array(0x6C), 0x1D440 => array(0x6D)
1385
                    ,0x1D441 => array(0x6E), 0x1D442 => array(0x6F), 0x1D443 => array(0x70)
1386
                    ,0x1D444 => array(0x71), 0x1D445 => array(0x72), 0x1D446 => array(0x73)
1387
                    ,0x1D447 => array(0x74), 0x1D448 => array(0x75), 0x1D449 => array(0x76)
1388
                    ,0x1D44A => array(0x77), 0x1D44B => array(0x78), 0x1D44C => array(0x79)
1389
                    ,0x1D44D => array(0x7A), 0x1D468 => array(0x61), 0x1D469 => array(0x62)
1390
                    ,0x1D46A => array(0x63), 0x1D46B => array(0x64), 0x1D46C => array(0x65)
1391
                    ,0x1D46D => array(0x66), 0x1D46E => array(0x67), 0x1D46F => array(0x68)
1392
                    ,0x1D470 => array(0x69), 0x1D471 => array(0x6A), 0x1D472 => array(0x6B)
1393
                    ,0x1D473 => array(0x6C), 0x1D474 => array(0x6D), 0x1D475 => array(0x6E)
1394
                    ,0x1D476 => array(0x6F), 0x1D477 => array(0x70), 0x1D478 => array(0x71)
1395
                    ,0x1D479 => array(0x72), 0x1D47A => array(0x73), 0x1D47B => array(0x74)
1396
                    ,0x1D47C => array(0x75), 0x1D47D => array(0x76), 0x1D47E => array(0x77)
1397
                    ,0x1D47F => array(0x78), 0x1D480 => array(0x79), 0x1D481 => array(0x7A)
1398
                    ,0x1D49C => array(0x61), 0x1D49E => array(0x63), 0x1D49F => array(0x64)
1399
                    ,0x1D4A2 => array(0x67), 0x1D4A5 => array(0x6A), 0x1D4A6 => array(0x6B)
1400
                    ,0x1D4A9 => array(0x6E), 0x1D4AA => array(0x6F), 0x1D4AB => array(0x70)
1401
                    ,0x1D4AC => array(0x71), 0x1D4AE => array(0x73), 0x1D4AF => array(0x74)
1402
                    ,0x1D4B0 => array(0x75), 0x1D4B1 => array(0x76), 0x1D4B2 => array(0x77)
1403
                    ,0x1D4B3 => array(0x78), 0x1D4B4 => array(0x79), 0x1D4B5 => array(0x7A)
1404
                    ,0x1D4D0 => array(0x61), 0x1D4D1 => array(0x62), 0x1D4D2 => array(0x63)
1405
                    ,0x1D4D3 => array(0x64), 0x1D4D4 => array(0x65), 0x1D4D5 => array(0x66)
1406
                    ,0x1D4D6 => array(0x67), 0x1D4D7 => array(0x68), 0x1D4D8 => array(0x69)
1407
                    ,0x1D4D9 => array(0x6A), 0x1D4DA => array(0x6B), 0x1D4DB => array(0x6C)
1408
                    ,0x1D4DC => array(0x6D), 0x1D4DD => array(0x6E), 0x1D4DE => array(0x6F)
1409
                    ,0x1D4DF => array(0x70), 0x1D4E0 => array(0x71), 0x1D4E1 => array(0x72)
1410
                    ,0x1D4E2 => array(0x73), 0x1D4E3 => array(0x74), 0x1D4E4 => array(0x75)
1411
                    ,0x1D4E5 => array(0x76), 0x1D4E6 => array(0x77), 0x1D4E7 => array(0x78)
1412
                    ,0x1D4E8 => array(0x79), 0x1D4E9 => array(0x7A), 0x1D504 => array(0x61)
1413
                    ,0x1D505 => array(0x62), 0x1D507 => array(0x64), 0x1D508 => array(0x65)
1414
                    ,0x1D509 => array(0x66), 0x1D50A => array(0x67), 0x1D50D => array(0x6A)
1415
                    ,0x1D50E => array(0x6B), 0x1D50F => array(0x6C), 0x1D510 => array(0x6D)
1416
                    ,0x1D511 => array(0x6E), 0x1D512 => array(0x6F), 0x1D513 => array(0x70)
1417
                    ,0x1D514 => array(0x71), 0x1D516 => array(0x73), 0x1D517 => array(0x74)
1418
                    ,0x1D518 => array(0x75), 0x1D519 => array(0x76), 0x1D51A => array(0x77)
1419
                    ,0x1D51B => array(0x78), 0x1D51C => array(0x79), 0x1D538 => array(0x61)
1420
                    ,0x1D539 => array(0x62), 0x1D53B => array(0x64), 0x1D53C => array(0x65)
1421
                    ,0x1D53D => array(0x66), 0x1D53E => array(0x67), 0x1D540 => array(0x69)
1422
                    ,0x1D541 => array(0x6A), 0x1D542 => array(0x6B), 0x1D543 => array(0x6C)
1423
                    ,0x1D544 => array(0x6D), 0x1D546 => array(0x6F), 0x1D54A => array(0x73)
1424
                    ,0x1D54B => array(0x74), 0x1D54C => array(0x75), 0x1D54D => array(0x76)
1425
                    ,0x1D54E => array(0x77), 0x1D54F => array(0x78), 0x1D550 => array(0x79)
1426
                    ,0x1D56C => array(0x61), 0x1D56D => array(0x62), 0x1D56E => array(0x63)
1427
                    ,0x1D56F => array(0x64), 0x1D570 => array(0x65), 0x1D571 => array(0x66)
1428
                    ,0x1D572 => array(0x67), 0x1D573 => array(0x68), 0x1D574 => array(0x69)
1429
                    ,0x1D575 => array(0x6A), 0x1D576 => array(0x6B), 0x1D577 => array(0x6C)
1430
                    ,0x1D578 => array(0x6D), 0x1D579 => array(0x6E), 0x1D57A => array(0x6F)
1431
                    ,0x1D57B => array(0x70), 0x1D57C => array(0x71), 0x1D57D => array(0x72)
1432
                    ,0x1D57E => array(0x73), 0x1D57F => array(0x74), 0x1D580 => array(0x75)
1433
                    ,0x1D581 => array(0x76), 0x1D582 => array(0x77), 0x1D583 => array(0x78)
1434
                    ,0x1D584 => array(0x79), 0x1D585 => array(0x7A), 0x1D5A0 => array(0x61)
1435
                    ,0x1D5A1 => array(0x62), 0x1D5A2 => array(0x63), 0x1D5A3 => array(0x64)
1436
                    ,0x1D5A4 => array(0x65), 0x1D5A5 => array(0x66), 0x1D5A6 => array(0x67)
1437
                    ,0x1D5A7 => array(0x68), 0x1D5A8 => array(0x69), 0x1D5A9 => array(0x6A)
1438
                    ,0x1D5AA => array(0x6B), 0x1D5AB => array(0x6C), 0x1D5AC => array(0x6D)
1439
                    ,0x1D5AD => array(0x6E), 0x1D5AE => array(0x6F), 0x1D5AF => array(0x70)
1440
                    ,0x1D5B0 => array(0x71), 0x1D5B1 => array(0x72), 0x1D5B2 => array(0x73)
1441
                    ,0x1D5B3 => array(0x74), 0x1D5B4 => array(0x75), 0x1D5B5 => array(0x76)
1442
                    ,0x1D5B6 => array(0x77), 0x1D5B7 => array(0x78), 0x1D5B8 => array(0x79)
1443
                    ,0x1D5B9 => array(0x7A), 0x1D5D4 => array(0x61), 0x1D5D5 => array(0x62)
1444
                    ,0x1D5D6 => array(0x63), 0x1D5D7 => array(0x64), 0x1D5D8 => array(0x65)
1445
                    ,0x1D5D9 => array(0x66), 0x1D5DA => array(0x67), 0x1D5DB => array(0x68)
1446
                    ,0x1D5DC => array(0x69), 0x1D5DD => array(0x6A), 0x1D5DE => array(0x6B)
1447
                    ,0x1D5DF => array(0x6C), 0x1D5E0 => array(0x6D), 0x1D5E1 => array(0x6E)
1448
                    ,0x1D5E2 => array(0x6F), 0x1D5E3 => array(0x70), 0x1D5E4 => array(0x71)
1449
                    ,0x1D5E5 => array(0x72), 0x1D5E6 => array(0x73), 0x1D5E7 => array(0x74)
1450
                    ,0x1D5E8 => array(0x75), 0x1D5E9 => array(0x76), 0x1D5EA => array(0x77)
1451
                    ,0x1D5EB => array(0x78), 0x1D5EC => array(0x79), 0x1D5ED => array(0x7A)
1452
                    ,0x1D608 => array(0x61), 0x1D609 => array(0x62) ,0x1D60A => array(0x63)
1453
                    ,0x1D60B => array(0x64), 0x1D60C => array(0x65), 0x1D60D => array(0x66)
1454
                    ,0x1D60E => array(0x67), 0x1D60F => array(0x68), 0x1D610 => array(0x69)
1455
                    ,0x1D611 => array(0x6A), 0x1D612 => array(0x6B), 0x1D613 => array(0x6C)
1456
                    ,0x1D614 => array(0x6D), 0x1D615 => array(0x6E), 0x1D616 => array(0x6F)
1457
                    ,0x1D617 => array(0x70), 0x1D618 => array(0x71), 0x1D619 => array(0x72)
1458
                    ,0x1D61A => array(0x73), 0x1D61B => array(0x74), 0x1D61C => array(0x75)
1459
                    ,0x1D61D => array(0x76), 0x1D61E => array(0x77), 0x1D61F => array(0x78)
1460
                    ,0x1D620 => array(0x79), 0x1D621 => array(0x7A), 0x1D63C => array(0x61)
1461
                    ,0x1D63D => array(0x62), 0x1D63E => array(0x63), 0x1D63F => array(0x64)
1462
                    ,0x1D640 => array(0x65), 0x1D641 => array(0x66), 0x1D642 => array(0x67)
1463
                    ,0x1D643 => array(0x68), 0x1D644 => array(0x69), 0x1D645 => array(0x6A)
1464
                    ,0x1D646 => array(0x6B), 0x1D647 => array(0x6C), 0x1D648 => array(0x6D)
1465
                    ,0x1D649 => array(0x6E), 0x1D64A => array(0x6F), 0x1D64B => array(0x70)
1466
                    ,0x1D64C => array(0x71), 0x1D64D => array(0x72), 0x1D64E => array(0x73)
1467
                    ,0x1D64F => array(0x74), 0x1D650 => array(0x75), 0x1D651 => array(0x76)
1468
                    ,0x1D652 => array(0x77), 0x1D653 => array(0x78), 0x1D654 => array(0x79)
1469
                    ,0x1D655 => array(0x7A), 0x1D670 => array(0x61), 0x1D671 => array(0x62)
1470
                    ,0x1D672 => array(0x63), 0x1D673 => array(0x64), 0x1D674 => array(0x65)
1471
                    ,0x1D675 => array(0x66), 0x1D676 => array(0x67), 0x1D677 => array(0x68)
1472
                    ,0x1D678 => array(0x69), 0x1D679 => array(0x6A), 0x1D67A => array(0x6B)
1473
                    ,0x1D67B => array(0x6C), 0x1D67C => array(0x6D), 0x1D67D => array(0x6E)
1474
                    ,0x1D67E => array(0x6F), 0x1D67F => array(0x70), 0x1D680 => array(0x71)
1475
                    ,0x1D681 => array(0x72), 0x1D682 => array(0x73), 0x1D683 => array(0x74)
1476
                    ,0x1D684 => array(0x75), 0x1D685 => array(0x76), 0x1D686 => array(0x77)
1477
                    ,0x1D687 => array(0x78), 0x1D688 => array(0x79), 0x1D689 => array(0x7A)
1478
                    ,0x1D6A8 => array(0x3B1), 0x1D6A9 => array(0x3B2), 0x1D6AA => array(0x3B3)
1479
                    ,0x1D6AB => array(0x3B4), 0x1D6AC => array(0x3B5), 0x1D6AD => array(0x3B6)
1480
                    ,0x1D6AE => array(0x3B7), 0x1D6AF => array(0x3B8), 0x1D6B0 => array(0x3B9)
1481
                    ,0x1D6B1 => array(0x3BA), 0x1D6B2 => array(0x3BB), 0x1D6B3 => array(0x3BC)
1482
                    ,0x1D6B4 => array(0x3BD), 0x1D6B5 => array(0x3BE), 0x1D6B6 => array(0x3BF)
1483
                    ,0x1D6B7 => array(0x3C0), 0x1D6B8 => array(0x3C1), 0x1D6B9 => array(0x3B8)
1484
                    ,0x1D6BA => array(0x3C3), 0x1D6BB => array(0x3C4), 0x1D6BC => array(0x3C5)
1485
                    ,0x1D6BD => array(0x3C6), 0x1D6BE => array(0x3C7), 0x1D6BF => array(0x3C8)
1486
                    ,0x1D6C0 => array(0x3C9), 0x1D6D3 => array(0x3C3), 0x1D6E2 => array(0x3B1)
1487
                    ,0x1D6E3 => array(0x3B2), 0x1D6E4 => array(0x3B3), 0x1D6E5 => array(0x3B4)
1488
                    ,0x1D6E6 => array(0x3B5), 0x1D6E7 => array(0x3B6), 0x1D6E8 => array(0x3B7)
1489
                    ,0x1D6E9 => array(0x3B8), 0x1D6EA => array(0x3B9), 0x1D6EB => array(0x3BA)
1490
                    ,0x1D6EC => array(0x3BB), 0x1D6ED => array(0x3BC), 0x1D6EE => array(0x3BD)
1491
                    ,0x1D6EF => array(0x3BE), 0x1D6F0 => array(0x3BF), 0x1D6F1 => array(0x3C0)
1492
                    ,0x1D6F2 => array(0x3C1), 0x1D6F3 => array(0x3B8) ,0x1D6F4 => array(0x3C3)
1493
                    ,0x1D6F5 => array(0x3C4), 0x1D6F6 => array(0x3C5), 0x1D6F7 => array(0x3C6)
1494
                    ,0x1D6F8 => array(0x3C7), 0x1D6F9 => array(0x3C8) ,0x1D6FA => array(0x3C9)
1495
                    ,0x1D70D => array(0x3C3), 0x1D71C => array(0x3B1), 0x1D71D => array(0x3B2)
1496
                    ,0x1D71E => array(0x3B3), 0x1D71F => array(0x3B4), 0x1D720 => array(0x3B5)
1497
                    ,0x1D721 => array(0x3B6), 0x1D722 => array(0x3B7), 0x1D723 => array(0x3B8)
1498
                    ,0x1D724 => array(0x3B9), 0x1D725 => array(0x3BA), 0x1D726 => array(0x3BB)
1499
                    ,0x1D727 => array(0x3BC), 0x1D728 => array(0x3BD), 0x1D729 => array(0x3BE)
1500
                    ,0x1D72A => array(0x3BF), 0x1D72B => array(0x3C0), 0x1D72C => array(0x3C1)
1501
                    ,0x1D72D => array(0x3B8), 0x1D72E => array(0x3C3), 0x1D72F => array(0x3C4)
1502
                    ,0x1D730 => array(0x3C5), 0x1D731 => array(0x3C6), 0x1D732 => array(0x3C7)
1503
                    ,0x1D733 => array(0x3C8), 0x1D734 => array(0x3C9), 0x1D747 => array(0x3C3)
1504
                    ,0x1D756 => array(0x3B1), 0x1D757 => array(0x3B2), 0x1D758 => array(0x3B3)
1505
                    ,0x1D759 => array(0x3B4), 0x1D75A => array(0x3B5), 0x1D75B => array(0x3B6)
1506
                    ,0x1D75C => array(0x3B7), 0x1D75D => array(0x3B8), 0x1D75E => array(0x3B9)
1507
                    ,0x1D75F => array(0x3BA), 0x1D760 => array(0x3BB), 0x1D761 => array(0x3BC)
1508
                    ,0x1D762 => array(0x3BD), 0x1D763 => array(0x3BE), 0x1D764 => array(0x3BF)
1509
                    ,0x1D765 => array(0x3C0), 0x1D766 => array(0x3C1), 0x1D767 => array(0x3B8)
1510
                    ,0x1D768 => array(0x3C3), 0x1D769 => array(0x3C4), 0x1D76A => array(0x3C5)
1511
                    ,0x1D76B => array(0x3C6), 0x1D76C => array(0x3C7), 0x1D76D => array(0x3C8)
1512
                    ,0x1D76E => array(0x3C9), 0x1D781 => array(0x3C3), 0x1D790 => array(0x3B1)
1513
                    ,0x1D791 => array(0x3B2), 0x1D792 => array(0x3B3), 0x1D793 => array(0x3B4)
1514
                    ,0x1D794 => array(0x3B5), 0x1D795 => array(0x3B6), 0x1D796 => array(0x3B7)
1515
                    ,0x1D797 => array(0x3B8), 0x1D798 => array(0x3B9), 0x1D799 => array(0x3BA)
1516
                    ,0x1D79A => array(0x3BB), 0x1D79B => array(0x3BC), 0x1D79C => array(0x3BD)
1517
                    ,0x1D79D => array(0x3BE), 0x1D79E => array(0x3BF), 0x1D79F => array(0x3C0)
1518
                    ,0x1D7A0 => array(0x3C1), 0x1D7A1 => array(0x3B8), 0x1D7A2 => array(0x3C3)
1519
                    ,0x1D7A3 => array(0x3C4), 0x1D7A4 => array(0x3C5), 0x1D7A5 => array(0x3C6)
1520
                    ,0x1D7A6 => array(0x3C7), 0x1D7A7 => array(0x3C8), 0x1D7A8 => array(0x3C9)
1521
                    ,0x1D7BB => array(0x3C3), 0x3F9   => array(0x3C3), 0x1D2C  => array(0x61)
1522
                    ,0x1D2D  => array(0xE6), 0x1D2E  => array(0x62), 0x1D30  => array(0x64)
1523
                    ,0x1D31  => array(0x65), 0x1D32  => array(0x1DD), 0x1D33  => array(0x67)
1524
                    ,0x1D34  => array(0x68), 0x1D35  => array(0x69), 0x1D36  => array(0x6A)
1525
                    ,0x1D37  => array(0x6B), 0x1D38  => array(0x6C), 0x1D39  => array(0x6D)
1526
                    ,0x1D3A  => array(0x6E), 0x1D3C  => array(0x6F), 0x1D3D  => array(0x223)
1527
                    ,0x1D3E  => array(0x70), 0x1D3F  => array(0x72), 0x1D40  => array(0x74)
1528
                    ,0x1D41  => array(0x75), 0x1D42  => array(0x77), 0x213B  => array(0x66, 0x61, 0x78)
1529
                    ,0x3250  => array(0x70, 0x74, 0x65), 0x32CC  => array(0x68, 0x67)
1530
                    ,0x32CE  => array(0x65, 0x76), 0x32CF  => array(0x6C, 0x74, 0x64)
1531
                    ,0x337A  => array(0x69, 0x75), 0x33DE  => array(0x76, 0x2215, 0x6D)
1532
                    ,0x33DF  => array(0x61, 0x2215, 0x6D)
1533
                    )
1534
            ,'norm_combcls' => array(0x334   => 1,   0x335   => 1,   0x336   => 1,   0x337   => 1
1535
                    ,0x338   => 1,   0x93C   => 7,   0x9BC   => 7,   0xA3C   => 7,   0xABC   => 7
1536
                    ,0xB3C   => 7,   0xCBC   => 7,   0x1037  => 7,   0x3099  => 8,   0x309A  => 8
1537
                    ,0x94D   => 9,   0x9CD   => 9,   0xA4D   => 9,   0xACD   => 9,   0xB4D   => 9
1538
                    ,0xBCD   => 9,   0xC4D   => 9,   0xCCD   => 9,   0xD4D   => 9,   0xDCA   => 9
1539
                    ,0xE3A   => 9,   0xF84   => 9,   0x1039  => 9,   0x1714  => 9,   0x1734  => 9
1540
                    ,0x17D2  => 9,   0x5B0   => 10,  0x5B1   => 11,  0x5B2   => 12,  0x5B3   => 13
1541
                    ,0x5B4   => 14,  0x5B5   => 15,  0x5B6   => 16,  0x5B7   => 17,  0x5B8   => 18
1542
                    ,0x5B9   => 19,  0x5BB   => 20,  0x5Bc   => 21,  0x5BD   => 22,  0x5BF   => 23
1543
                    ,0x5C1   => 24,  0x5C2   => 25,  0xFB1E  => 26,  0x64B   => 27,  0x64C   => 28
1544
                    ,0x64D   => 29,  0x64E   => 30,  0x64F   => 31,  0x650   => 32,  0x651   => 33
1545
                    ,0x652   => 34,  0x670   => 35,  0x711   => 36,  0xC55   => 84,  0xC56   => 91
1546
                    ,0xE38   => 103, 0xE39   => 103, 0xE48   => 107, 0xE49   => 107, 0xE4A   => 107
1547
                    ,0xE4B   => 107, 0xEB8   => 118, 0xEB9   => 118, 0xEC8   => 122, 0xEC9   => 122
1548
                    ,0xECA   => 122, 0xECB   => 122, 0xF71   => 129, 0xF72   => 130, 0xF7A   => 130
1549
                    ,0xF7B   => 130, 0xF7C   => 130, 0xF7D   => 130, 0xF80   => 130, 0xF74   => 132
1550
                    ,0x321   => 202, 0x322   => 202, 0x327   => 202, 0x328   => 202, 0x31B   => 216
1551
                    ,0xF39   => 216, 0x1D165 => 216, 0x1D166 => 216, 0x1D16E => 216, 0x1D16F => 216
1552
                    ,0x1D170 => 216, 0x1D171 => 216, 0x1D172 => 216, 0x302A  => 218, 0x316   => 220
1553
                    ,0x317   => 220, 0x318   => 220, 0x319   => 220, 0x31C   => 220, 0x31D   => 220
1554
                    ,0x31E   => 220, 0x31F   => 220, 0x320   => 220, 0x323   => 220, 0x324   => 220
1555
                    ,0x325   => 220, 0x326   => 220, 0x329   => 220, 0x32A   => 220, 0x32B   => 220
1556
                    ,0x32C   => 220, 0x32D   => 220, 0x32E   => 220, 0x32F   => 220, 0x330   => 220
1557
                    ,0x331   => 220, 0x332   => 220, 0x333   => 220, 0x339   => 220, 0x33A   => 220
1558
                    ,0x33B   => 220, 0x33C   => 220, 0x347   => 220, 0x348   => 220, 0x349   => 220
1559
                    ,0x34D   => 220, 0x34E   => 220, 0x353   => 220, 0x354   => 220, 0x355   => 220
1560
                    ,0x356   => 220, 0x591   => 220, 0x596   => 220, 0x59B   => 220, 0x5A3   => 220
1561
                    ,0x5A4   => 220, 0x5A5   => 220, 0x5A6   => 220, 0x5A7   => 220, 0x5AA   => 220
1562
                    ,0x655   => 220, 0x656   => 220, 0x6E3   => 220, 0x6EA   => 220, 0x6ED   => 220
1563
                    ,0x731   => 220, 0x734   => 220, 0x737   => 220, 0x738   => 220, 0x739   => 220
1564
                    ,0x73B   => 220, 0x73C   => 220, 0x73E   => 220, 0x742   => 220, 0x744   => 220
1565
                    ,0x746   => 220, 0x748   => 220, 0x952   => 220, 0xF18   => 220, 0xF19   => 220
1566
                    ,0xF35   => 220, 0xF37   => 220, 0xFC6   => 220, 0x193B  => 220, 0x20E8  => 220
1567
                    ,0x1D17B => 220, 0x1D17C => 220, 0x1D17D => 220, 0x1D17E => 220, 0x1D17F => 220
1568
                    ,0x1D180 => 220, 0x1D181 => 220, 0x1D182 => 220, 0x1D18A => 220, 0x1D18B => 220
1569
                    ,0x59A   => 222, 0x5AD   => 222, 0x1929  => 222, 0x302D  => 222, 0x302E  => 224
1570
                    ,0x302F  => 224, 0x1D16D => 226, 0x5AE   => 228, 0x18A9  => 228, 0x302B  => 228
1571
                    ,0x300   => 230, 0x301   => 230, 0x302   => 230, 0x303   => 230, 0x304   => 230
1572
                    ,0x305   => 230, 0x306   => 230, 0x307   => 230, 0x308   => 230, 0x309   => 230
1573
                    ,0x30A   => 230, 0x30B   => 230, 0x30C   => 230, 0x30D   => 230, 0x30E   => 230
1574
                    ,0x30F   => 230, 0x310   => 230, 0x311   => 230, 0x312   => 230, 0x313   => 230
1575
                    ,0x314   => 230, 0x33D   => 230, 0x33E   => 230, 0x33F   => 230, 0x340   => 230
1576
                    ,0x341   => 230, 0x342   => 230, 0x343   => 230, 0x344   => 230, 0x346   => 230
1577
                    ,0x34A   => 230, 0x34B   => 230, 0x34C   => 230, 0x350   => 230, 0x351   => 230
1578
                    ,0x352   => 230, 0x357   => 230, 0x363   => 230, 0x364   => 230, 0x365   => 230
1579
                    ,0x366   => 230, 0x367   => 230, 0x368   => 230, 0x369   => 230, 0x36A   => 230
1580
                    ,0x36B   => 230, 0x36C   => 230, 0x36D   => 230, 0x36E   => 230, 0x36F   => 230
1581
                    ,0x483   => 230, 0x484   => 230, 0x485   => 230, 0x486   => 230, 0x592   => 230
1582
                    ,0x593   => 230, 0x594   => 230, 0x595   => 230, 0x597   => 230, 0x598   => 230
1583
                    ,0x599   => 230, 0x59C   => 230, 0x59D   => 230, 0x59E   => 230, 0x59F   => 230
1584
                    ,0x5A0   => 230, 0x5A1   => 230, 0x5A8   => 230, 0x5A9   => 230, 0x5AB   => 230
1585
                    ,0x5AC   => 230, 0x5AF   => 230, 0x5C4   => 230, 0x610   => 230, 0x611   => 230
1586
                    ,0x612   => 230, 0x613   => 230, 0x614   => 230, 0x615   => 230, 0x653   => 230
1587
                    ,0x654   => 230, 0x657   => 230, 0x658   => 230, 0x6D6   => 230, 0x6D7   => 230
1588
                    ,0x6D8   => 230, 0x6D9   => 230, 0x6DA   => 230, 0x6DB   => 230, 0x6DC   => 230
1589
                    ,0x6DF   => 230, 0x6E0   => 230, 0x6E1   => 230, 0x6E2   => 230, 0x6E4   => 230
1590
                    ,0x6E7   => 230, 0x6E8   => 230, 0x6EB   => 230, 0x6EC   => 230, 0x730   => 230
1591
                    ,0x732   => 230, 0x733   => 230, 0x735   => 230, 0x736   => 230, 0x73A   => 230
1592
                    ,0x73D   => 230, 0x73F   => 230, 0x740   => 230, 0x741   => 230, 0x743   => 230
1593
                    ,0x745   => 230, 0x747   => 230, 0x749   => 230, 0x74A   => 230, 0x951   => 230
1594
                    ,0x953   => 230, 0x954   => 230, 0xF82   => 230, 0xF83   => 230, 0xF86   => 230
1595
                    ,0xF87   => 230, 0x170D  => 230, 0x193A  => 230, 0x20D0  => 230, 0x20D1  => 230
1596
                    ,0x20D4  => 230, 0x20D5  => 230, 0x20D6  => 230, 0x20D7  => 230, 0x20DB  => 230
1597
                    ,0x20DC  => 230, 0x20E1  => 230, 0x20E7  => 230, 0x20E9  => 230, 0xFE20  => 230
1598
                    ,0xFE21  => 230, 0xFE22  => 230, 0xFE23  => 230, 0x1D185 => 230, 0x1D186 => 230
1599
                    ,0x1D187 => 230, 0x1D189 => 230, 0x1D188 => 230, 0x1D1AA => 230, 0x1D1AB => 230
1600
                    ,0x1D1AC => 230, 0x1D1AD => 230, 0x315   => 232, 0x31A   => 232, 0x302C  => 232
1601
                    ,0x35F   => 233, 0x362   => 233, 0x35D   => 234, 0x35E   => 234, 0x360   => 234
1602
                    ,0x361   => 234, 0x345   => 240
1603
                    )
1604
            );
1605
}
1606
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...