xref: /PHP-8.0/ext/intl/tests/grapheme.phpt (revision 13b791c7)
1--TEST--
2grapheme()
3--SKIPIF--
4<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
5<?php if (version_compare(INTL_ICU_VERSION, '65.0') >= 0) die('skip for ICU < 65.0'); ?>
6--FILE--
7<?php
8
9/*
10 * Test grapheme functions (procedural only)
11 */
12
13function ut_main()
14{
15    $res_str = '';
16
17    $char_a_diaeresis = "\xC3\xA4";	// 'LATIN SMALL LETTER A WITH DIAERESIS' (U+00E4)
18    $char_a_ring = "\xC3\xA5";		// 'LATIN SMALL LETTER A WITH RING ABOVE' (U+00E5)
19    $char_o_diaeresis = "\xC3\xB6";    // 'LATIN SMALL LETTER O WITH DIAERESIS' (U+00F6)
20    $char_O_diaeresis = "\xC3\x96";    // 'LATIN CAPITAL LETTER O WITH DIAERESIS' (U+00D6)
21
22    $char_angstrom_sign = "\xE2\x84\xAB"; // 'ANGSTROM SIGN' (U+212B)
23    $char_A_ring = "\xC3\x85";	// 'LATIN CAPITAL LETTER A WITH RING ABOVE' (U+00C5)
24
25    $char_ohm_sign = "\xE2\x84\xA6";	// 'OHM SIGN' (U+2126)
26    $char_omega = "\xCE\xA9";  // 'GREEK CAPITAL LETTER OMEGA' (U+03A9)
27
28    $char_combining_ring_above = "\xCC\x8A";  // 'COMBINING RING ABOVE' (U+030A)
29
30    $char_fi_ligature = "\xEF\xAC\x81";  // 'LATIN SMALL LIGATURE FI' (U+FB01)
31
32    $char_long_s_dot = "\xE1\xBA\x9B";	// 'LATIN SMALL LETTER LONG S WITH DOT ABOVE' (U+1E9B)
33
34    // the word 'hindi' using Devanagari characters:
35    $hindi = "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xa6\xe0\xa5\x80";
36
37    $char_a_ring_nfd = "a\xCC\x8A";
38    $char_A_ring_nfd = "A\xCC\x8A";
39    $char_o_diaeresis_nfd = "o\xCC\x88";
40    $char_O_diaeresis_nfd = "O\xCC\x88";
41    $char_diaeresis = "\xCC\x88";
42
43    //=====================================================================================
44    $res_str .= "\n" . 'function grapheme_strlen($string) {}' . "\n\n";
45
46
47    $res_str .= "\"hindi\" in devanagari strlen " . grapheme_strlen($hindi) . "\n";
48    $res_str .= "\"ab\" + \"hindi\" + \"cde\" strlen " . grapheme_strlen('ab' . $hindi . 'cde') . "\n";
49    $res_str .= "\"\" strlen " . grapheme_strlen("") . "\n";
50    $res_str .= "char_a_ring_nfd strlen " . grapheme_strlen($char_a_ring_nfd) . "\n";
51    $res_str .= "char_a_ring_nfd + \"bc\" strlen " . grapheme_strlen($char_a_ring_nfd . 'bc') . "\n";
52    $res_str .= "\"abc\" strlen " . grapheme_strlen('abc') . "\n";
53
54
55    //=====================================================================================
56    $res_str .= "\n" . 'function grapheme_strpos($haystack, $needle, $offset = 0) {}' . "\n\n";
57
58    $tests = array(
59        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", 5 ),
60        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "o", "false" ),
61        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, $char_o_diaeresis_nfd, 4 ),
62        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 2 ),
63        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 1 ),
64        array( "abc", $char_a_ring_nfd, "false" ),
65        array( $char_a_ring_nfd . "bc", "a", "false" ),
66        array( "abc", "d", "false" ),
67        array( "abc", "c", 2 ),
68        array( "abc", "b", 1 ),
69        array( "abc", "a", 0 ),
70        array( "abc", "a", 0, 0 ),
71        array( "abc", "a", 1, "false" ),
72        array( "abc", "a", -1, "false" ),
73        array( "ababc", "a", 1, 2 ),
74        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", 2, 6 ),
75        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", -1, 6 ),
76        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", -5, 6 ),
77        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ),
78        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, -4, 3 ),
79
80        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "op", 5 ),
81        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "opq", 5 ),
82        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "abc", "false" ),
83        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "bc" . $char_o_diaeresis_nfd, $char_o_diaeresis_nfd . "bc" . $char_o_diaeresis_nfd, 4 ),
84        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc", 2 ),
85        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc", 1 ),
86        array( "abc", $char_a_ring_nfd . "bc", "false" ),
87        array( $char_a_ring_nfd . "bc", "abcdefg", "false" ),
88        array( "abc", "defghijklmnopq", "false" ),
89        array( "abc", "ab", 0 ),
90        array( "abc", "bc", 1 ),
91        array( "abc", "abc", 0 ),
92        array( "abc", "abcd", "false" ),
93        array( "abc", "ab", 0, 0 ),
94        array( "abc", "abc", 0, 0 ),
95        array( "abc", "abc", 1, "false" ),
96        array( "ababc", "ab", 1, 2 ),
97        array( "ababc", "abc", 1, 2 ),
98        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", 2, 6 ),
99        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", -8, 6 ),
100        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "bc" . $char_a_ring_nfd, 2, 3 ),
101    );
102
103    foreach( $tests as $test ) {
104        $arg1 = urlencode($test[1]);
105        $arg0 = urlencode($test[0]);
106        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_strpos";
107        if ( 3 == count( $test ) ) {
108            $result = grapheme_strpos($test[0], $test[1]);
109        }
110        else {
111            $res_str .= " from $test[2]";
112            $result = grapheme_strpos($test[0], $test[1], $test[2]);
113        }
114        $res_str .= " = ";
115        if ( $result === false ) {
116            $res_str .= 'false';
117        }
118        else {
119            $res_str .= $result;
120        }
121        $res_str .= " == " . $test[count($test)-1] . check_result($result, $test[count($test)-1]) . "\n";
122    }
123
124    //=====================================================================================
125    $res_str .= "\n" . 'function grapheme_stripos($haystack, $needle, $offset = 0) {}' . "\n\n";
126
127    $tests = array(
128        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 2, 6 ),
129        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Oo", "o", -6, 6 ),
130        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ),
131        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 5 ),
132        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "O", "false" ),
133        array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, 4 ),
134        array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, -1, 4 ),
135        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd, 2 ),
136        array( "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 1 ),
137        array( "Abc", $char_a_ring_nfd, "false" ),
138        array( $char_a_ring_nfd . "bc", "A", "false" ),
139        array( "abc", "D", "false" ),
140        array( "abC", "c", 2 ),
141        array( "abc", "B", 1 ),
142        array( "Abc", "a", 0 ),
143        array( "abc", "A", 0, 0 ),
144        array( "Abc", "a", 1, "false" ),
145        array( "ababc", "A", 1, 2 ),
146
147        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", "oP", 5 ),
148        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", "opQ", 5 ),
149        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "abc", "false" ),
150        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "bC" . $char_o_diaeresis_nfd, $char_O_diaeresis_nfd . "bc" . $char_o_diaeresis_nfd, 4 ),
151        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "Bc", $char_A_ring_nfd . "bc", 2 ),
152        array( "a" . $char_a_ring_nfd . "BC", $char_a_ring_nfd . "bc", 1 ),
153        array( "abc", $char_a_ring_nfd . "BC", "false" ),
154        array( $char_a_ring_nfd . "BC", "aBCdefg", "false" ),
155        array( "aBC", "Defghijklmnopq", "false" ),
156        array( "abC", "Ab", 0 ),
157        array( "aBC", "bc", 1 ),
158        array( "abC", "Abc", 0 ),
159        array( "abC", "aBcd", "false" ),
160        array( "ABc", "ab", 0, 0 ),
161        array( "aBc", "abC", 0, 0 ),
162        array( "abc", "aBc", 1, "false" ),
163        array( "ABabc", "AB", 1, 2 ),
164        array( "ABabc", "AB", -4, 2 ),
165        array( "abaBc", "aBc", 1, 2 ),
166        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_A_ring_nfd . "bC", "O" . $char_a_ring_nfd . "bC", 2, 6 ),
167        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bC" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "Bc" . $char_a_ring_nfd, 2, 3 ),
168    );
169
170    foreach( $tests as $test ) {
171        $arg1 = urlencode($test[1]);
172        $arg0 = urlencode($test[0]);
173        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_stripos";
174        if ( 3 == count( $test ) ) {
175            $result = grapheme_stripos($test[0], $test[1]);
176        }
177        else {
178            $res_str .= " from $test[2]";
179            $result = grapheme_stripos($test[0], $test[1], $test[2]);
180        }
181        $res_str .= " = ";
182        if ( $result === false ) {
183            $res_str .= 'false';
184        }
185        else {
186            $res_str .= $result;
187        }
188        $res_str .= " == " . $test[count($test)-1] . check_result($result, $test[count($test)-1]) . "\n";
189    }
190
191
192    //=====================================================================================
193    $res_str .= "\n" . 'function grapheme_strrpos($haystack, $needle, $offset = 0) {}' . "\n\n";
194
195
196    $tests = array(
197        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", 5 ),
198        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "o", "false" ),
199        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, $char_o_diaeresis_nfd, 4 ),
200        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 2 ),
201        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 1 ),
202        array( "abc", $char_a_ring_nfd, "false" ),
203        array( $char_a_ring_nfd . "bc", "a", "false" ),
204        array( "abc", "d", "false" ),
205        array( "abc", "c", 2 ),
206        array( "abc", "b", 1 ),
207        array( "abc", "a", 0 ),
208        array( "abc", "a", 0, 0 ),
209        array( "abc", "a", 1, "false" ),
210        array( "ababc", "a", 1, 2 ),
211        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", 2, 6 ),
212        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ),
213
214        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "op", 5 ),
215        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "opq", "opq", 5 ),
216        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "abc", "false" ),
217        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "bc" . $char_o_diaeresis_nfd, $char_o_diaeresis_nfd . "bc" . $char_o_diaeresis_nfd, 4 ),
218        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc", 2 ),
219        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc", 1 ),
220        array( "abc", $char_a_ring_nfd . "bc", "false" ),
221        array( $char_a_ring_nfd . "bc", "abcdefg", "false" ),
222        array( "abc", "defghijklmnopq", "false" ),
223        array( "abc", "ab", 0 ),
224        array( "abc", "bc", 1 ),
225        array( "abc", "abc", 0 ),
226        array( "abc", "abcd", "false" ),
227        array( "abc", "ab", 0, 0 ),
228        array( "abc", "abc", 0, 0 ),
229        array( "abc", "abc", 1, "false" ),
230        array( "ababc", "ab", 1, 2 ),
231        array( "ababc", "abc", 1, 2 ),
232        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_a_ring_nfd . "bc", "o" . $char_a_ring_nfd . "bc", 2, 6 ),
233        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_a_ring_nfd . "bc" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "bc" . $char_a_ring_nfd, 2, 3 ),
234    );
235
236    foreach( $tests as $test ) {
237        $arg1 = urlencode($test[1]);
238        $arg0 = urlencode($test[0]);
239        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_strrpos";
240        if ( 3 == count( $test ) ) {
241            $result = grapheme_strrpos($test[0], $test[1]);
242        }
243        else {
244            $res_str .= " from $test[2]";
245            $result = grapheme_strrpos($test[0], $test[1], $test[2]);
246        }
247        $res_str .= " = ";
248        if ( $result === false ) {
249            $res_str .= 'false';
250        }
251        else {
252            $res_str .= $result;
253        }
254        $res_str .= " == " . $test[count($test)-1] .  check_result($result, $test[count($test)-1]) . "\n";
255    }
256
257
258    //=====================================================================================
259    $res_str .= "\n" . 'function grapheme_strripos($haystack, $needle, $offset = 0) {}' . "\n\n";
260
261    $tests = array(
262        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 2, 6 ),
263        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 2, 3 ),
264        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", 5 ),
265        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "O", "false" ),
266        array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, $char_o_diaeresis_nfd, 4 ),
267        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd, 2 ),
268        array( "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, 1 ),
269        array( "Abc", $char_a_ring_nfd, "false" ),
270        array( $char_a_ring_nfd . "bc", "A", "false" ),
271        array( "abc", "D", "false" ),
272        array( "abC", "c", 2 ),
273        array( "abc", "B", 1 ),
274        array( "Abc", "a", 0 ),
275        array( "abc", "A", 0, 0 ),
276        array( "Abc", "a", 1, "false" ),
277        array( "ababc", "A", 1, 2 ),
278
279        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", "oP", 5 ),
280        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", "opQ", 5 ),
281        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "abc", "false" ),
282        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "bC" . $char_o_diaeresis_nfd, $char_O_diaeresis_nfd . "bc" . $char_o_diaeresis_nfd, 4 ),
283        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "Bc", $char_A_ring_nfd . "bc", 2 ),
284        array( "a" . $char_a_ring_nfd . "BC", $char_a_ring_nfd . "bc", 1 ),
285        array( "abc", $char_a_ring_nfd . "BC", "false" ),
286        array( $char_a_ring_nfd . "BC", "aBCdefg", "false" ),
287        array( "aBC", "Defghijklmnopq", "false" ),
288        array( "abC", "Ab", 0 ),
289        array( "aBC", "bc", 1 ),
290        array( "abC", "Abc", 0 ),
291        array( "abC", "aBcd", "false" ),
292        array( "ABc", "ab", 0, 0 ),
293        array( "aBc", "abC", 0, 0 ),
294        array( "abc", "aBc", 1, "false" ),
295        array( "ABabc", "AB", 1, 2 ),
296        array( "abaBc", "aBc", 1, 2 ),
297        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o" . $char_A_ring_nfd . "bC", "O" . $char_a_ring_nfd . "bC", 2, 6 ),
298        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bC" . $char_a_ring_nfd . "def", $char_a_ring_nfd . "Bc" . $char_a_ring_nfd, 2, 3 ),
299    );
300
301    foreach( $tests as $test ) {
302        $arg1 = urlencode($test[1]);
303        $arg0 = urlencode($test[0]);
304        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_strripos";
305        if ( 3 == count( $test ) ) {
306            $result = grapheme_strripos($test[0], $test[1]);
307        }
308        else {
309            $res_str .= " from $test[2]";
310            $result = grapheme_strripos($test[0], $test[1], $test[2]);
311        }
312        $res_str .= " = ";
313        if ( $result === false ) {
314            $res_str .= 'false';
315        }
316        else {
317            $res_str .= $result;
318        }
319        $res_str .= " == " . $test[count($test)-1] . check_result($result, $test[count($test)-1]) . "\n";
320    }
321
322
323    //=====================================================================================
324    $res_str .= "\n" . 'function grapheme_substr($string, $start, $length = -1) {}' . "\n\n";
325
326    $tests = array(
327
328        array( "abc", 3, "" ),
329        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, 5, "" ),
330        array( "ao" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", 2, $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O" ),
331        array( $char_o_diaeresis_nfd . $char_a_ring_nfd . "a" . $char_A_ring_nfd . "bc", 2, "a" . $char_A_ring_nfd . "bc" ),
332        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", 5, "O" ),
333        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, 5, "" ),
334        array( "a" . $char_a_ring_nfd . "bc" . $char_O_diaeresis_nfd, 4, $char_O_diaeresis_nfd ),
335        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", 2, $char_a_ring_nfd . "bc" ),
336        array( "a" . $char_A_ring_nfd . "bc", 1, $char_A_ring_nfd . "bc" ),
337        array( "Abc", -5, "Abc" ),
338        array( $char_a_ring_nfd . "bc", 3, "" ),
339        array( "abc", 4, "" ),
340        array( "abC", 2, "C" ),
341        array( "abc", 1, "bc" ),
342        array( "Abc", 1, 1, "b" ),
343        array( "abc", 0, 2, "ab" ),
344        array( "Abc", -4, 1, "A" ),
345        array( "ababc", 1, 2, "ba" ),
346        array( "ababc", 0, 10, "ababc" ),
347
348        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, 10 , "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq" ),
349        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 5, "Opq" ),
350        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 5, -1, "Op" ),
351        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 5, -2, "O" ),
352        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 5, -3, "" ),
353        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 5, -4, "" ),
354
355        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq" ),
356        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -1, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Op" ),
357        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -2, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O" ),
358        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -3, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd ),
359        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -4, "a" . $char_a_ring_nfd . "bc" ),
360        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -5, "a" . $char_a_ring_nfd . "b" ),
361        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -6, "a" . $char_a_ring_nfd ),
362        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -7, "a" ),
363        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -8, "" ),
364        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", 0, -9, "" ),
365
366        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq" ),
367        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -7, $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq" ),
368        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -6, "bc" . $char_o_diaeresis_nfd . "Opq" ),
369        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -5, "c" . $char_o_diaeresis_nfd . "Opq" ),
370        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -4, $char_o_diaeresis_nfd . "Opq" ),
371        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -3, "Opq" ),
372        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -2, "pq" ),
373        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -1, "q" ),
374        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -999, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq" ),
375
376        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 8, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq" ),
377        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 7, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Op" ),
378        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 6, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O" ),
379        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 5, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd ),
380        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 4, "a" . $char_a_ring_nfd . "bc" ),
381        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 3, "a" . $char_a_ring_nfd . "b" ),
382        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 2, "a" . $char_a_ring_nfd ),
383        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 1, "a" ),
384        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, 0, "" ),
385        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -999, "" ),
386
387        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -1, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Op" ),
388        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -2, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O" ),
389        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -3, "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd ),
390        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -4, "a" . $char_a_ring_nfd . "bc" ),
391        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -5, "a" . $char_a_ring_nfd . "b" ),
392        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -6, "a" . $char_a_ring_nfd ),
393        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -7, "a" ),
394        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -8, "" ),
395        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "Opq", -8, -9, "" ),
396
397    );
398
399    foreach( $tests as $test ) {
400        $arg0 = urlencode($test[0]);
401        $res_str .= "substring of \"$arg0\" from \"$test[1]\" - grapheme_substr";
402        if ( 3 == count( $test ) ) {
403            try {
404                $result = grapheme_substr($test[0], $test[1]);
405            } catch (ValueError $exception) {
406                $res_str .= ": " . $exception->getMessage() . "\n";
407            }
408        }
409        else {
410            $res_str .= " with length $test[2]";
411            try {
412                $result = grapheme_substr($test[0], $test[1], $test[2]);
413            } catch (ValueError $exception) {
414                $res_str .= ": " . $exception->getMessage() . "\n";
415            }
416        }
417        $res_str .= " = ";
418        if ( $result === false ) {
419            $res_str .= 'false';
420        }
421        else {
422            $res_str .= urlencode($result);
423        }
424        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
425    }
426
427
428    //=====================================================================================
429    $res_str .= "\n" . 'function grapheme_strstr($haystack, $needle, $before_needle = FALSE) {}' . "\n\n";
430
431    $tests = array(
432        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", "o" ),
433        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "o", "false" ),
434        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, $char_o_diaeresis_nfd, $char_o_diaeresis_nfd ),
435        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, $char_a_ring_nfd . "bc"),
436        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, $char_a_ring_nfd . "bc"),
437        array( "abc", $char_a_ring_nfd, "false" ),
438        array( $char_a_ring_nfd . "bc", "a", "false" ),
439        array( "abc", "d", "false" ),
440        array( "abc", "c", "c" ),
441        array( "abc", "b", "bc" ),
442        array( "abc", "a", "abc" ),
443        array( "abc", "ab", "abc" ),
444        array( "abc", "abc", "abc" ),
445        array( "abc", "bc", "bc" ),
446        array( "abc", "a", FALSE, "abc" ),
447        array( "abc", "a", TRUE, "" ),
448        array( "abc", "b", TRUE, "a" ),
449        array( "abc", "c", TRUE, "ab" ),
450        array( "ababc", "bab", TRUE, "a" ),
451        array( "ababc", "abc", TRUE, "ab" ),
452        array( "ababc", "abc", FALSE, "abc" ),
453
454        array( "ab" . $char_a_ring_nfd . "c", "d", "false" ),
455        array( "bc" . $char_a_ring_nfd . "a", "a", "a" ),
456        array( "a" . $char_a_ring_nfd . "bc", "b", "bc" ),
457        array( $char_a_ring_nfd . "bc", "a", "false" ),
458        array( $char_a_ring_nfd . "abc", "ab", "abc" ),
459        array( "abc" . $char_a_ring_nfd, "abc", "abc" . $char_a_ring_nfd),
460        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc" ),
461        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, FALSE, $char_a_ring_nfd . "bc"),
462        array( "a" . $char_a_ring_nfd . "bc", "a", TRUE, "" ),
463        array( $char_a_ring_nfd . "abc", "b", TRUE, $char_a_ring_nfd . "a" ),
464        array( "ab" . $char_a_ring_nfd . "c", "c", TRUE, "ab" . $char_a_ring_nfd ),
465        array( "aba" . $char_a_ring_nfd . "bc", "ba" . $char_a_ring_nfd . "b", TRUE, "a" ),
466        array( "ababc" . $char_a_ring_nfd, "abc" . $char_a_ring_nfd, TRUE, "ab" ),
467        array( "abab" . $char_a_ring_nfd . "c", "ab" . $char_a_ring_nfd . "c", FALSE, "ab" . $char_a_ring_nfd . "c" ),
468
469    );
470
471    foreach( $tests as $test ) {
472        $arg1 = urlencode($test[1]);
473        $arg0 = urlencode($test[0]);
474        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_strstr";
475        if ( 3 == count( $test ) ) {
476            try {
477                $result = grapheme_strstr($test[0], $test[1]);
478            } catch (ValueError $exception) {
479                $res_str .= ": " . $exception->getMessage() . "\n";
480            }
481        }
482        else {
483            $res_str .= " before flag is " . ( $test[2] ? "TRUE" : "FALSE" );
484            try {
485                $result = grapheme_strstr($test[0], $test[1], $test[2]);
486            } catch (ValueError $exception) {
487                $res_str .= ": " . $exception->getMessage() . "\n";
488            }
489        }
490        $res_str .= " = ";
491        if ( $result === false ) {
492            $res_str .= 'false';
493        }
494        else {
495            $res_str .= urlencode($result);
496        }
497        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
498    }
499
500
501    //=====================================================================================
502    $res_str .= "\n" . 'function grapheme_stristr($haystack, $needle, $before_needle = FALSE) {}' . "\n\n";
503
504    $tests = array(
505        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, $char_O_diaeresis_nfd, $char_o_diaeresis_nfd ),
506        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", "O" ),
507        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "o", "false" ),
508        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, $char_a_ring_nfd . "bc"),
509        array( "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd, $char_a_ring_nfd . "bc"),
510        array( "abc", $char_a_ring_nfd, "false" ),
511        array( $char_a_ring_nfd . "bc", "A", "false" ),
512        array( "abc", "d", "false" ),
513        array( "abc", "C", "c" ),
514        array( "aBc", "b", "Bc" ),
515        array( "abc", "A", "abc" ),
516        array( "abC", "ab", "abC" ),
517        array( "abc", "aBc", "abc" ),
518        array( "abC", "bc", "bC" ),
519        array( "abc", "A", FALSE, "abc" ),
520        array( "abc", "a", TRUE, "" ),
521        array( "aBc", "b", TRUE, "a" ),
522        array( "abc", "C", TRUE, "ab" ),
523        array( "aBabc", "bab", TRUE, "a" ),
524        array( "ababc", "aBc", TRUE, "ab" ),
525        array( "ababc", "abC", FALSE, "abc" ),
526
527        array( "ab" . $char_a_ring_nfd . "c", "d", "false" ),
528        array( "bc" . $char_a_ring_nfd . "A", "a", "A" ),
529        array( "a" . $char_a_ring_nfd . "bc", "B", "bc" ),
530        array( $char_A_ring_nfd . "bc", "a", "false" ),
531        array( $char_a_ring_nfd . "abc", "Ab", "abc" ),
532        array( "abc" . $char_A_ring_nfd, "abc", "abc" . $char_A_ring_nfd),
533        array( "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd . "bc", $char_a_ring_nfd . "bc" ),
534        array( "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, FALSE, $char_A_ring_nfd . "bc" ),
535        array( "a" . $char_a_ring_nfd . "bc", "A", TRUE, "" ),
536        array( $char_a_ring_nfd . "aBc", "b", TRUE, $char_a_ring_nfd . "a" ),
537        array( "ab" . $char_a_ring_nfd . "c", "C", TRUE, "ab" . $char_a_ring_nfd ),
538        array( "aba" . $char_A_ring_nfd . "bc", "ba" . $char_a_ring_nfd . "b", TRUE, "a" ),
539        array( "ababc" . $char_a_ring_nfd, "aBc" . $char_A_ring_nfd, TRUE, "ab" ),
540        array( "abAB" . $char_A_ring_nfd . "c", "ab" . $char_a_ring_nfd . "c", FALSE, "AB" . $char_A_ring_nfd . "c" ),
541
542    );
543
544    foreach( $tests as $test ) {
545        $arg1 = urlencode($test[1]);
546        $arg0 = urlencode($test[0]);
547        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_stristr";
548        if ( 3 == count( $test ) ) {
549            $result = grapheme_stristr($test[0], $test[1]);
550        }
551        else {
552            $res_str .= " before flag is " . ( $test[2] ? "TRUE" : "FALSE" );
553            $result = grapheme_stristr($test[0], $test[1], $test[2]);
554        }
555        $res_str .= " = ";
556        if ( $result === false ) {
557            $res_str .= 'false';
558        }
559        else {
560            $res_str .= urlencode($result);
561        }
562        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
563    }
564
565
566    //=====================================================================================
567    $res_str .= "\n" . 'function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_COUNT, $start = 0[, $next])' . "\n\n";
568
569    $tests = array(
570        // haystack, count, [[offset], [next]], result
571        array( "abc", 3, "abc" ),
572        array( "abc", 2, "ab" ),
573        array( "abc", 1, "a" ),
574        array( "abc", 0, "" ),
575        array( "abc", 1, 0, "a" ),
576        array( "abc", 1, 1, "b" ),
577        array( "abc", 1, 2, "c" ),
578        array( "abc", 0, 2, "" ),
579
580        array( "abc", 3, 0, 3, "abc" ),
581        array( "abc", 2, 0, 2, "ab" ),
582        array( "abc", 1, 0, 1, "a" ),
583        array( "abc", 0, 0, 0, "" ),
584        array( "abc", 1, 0, 1, "a" ),
585        array( "abc", 1, 1, 2, "b" ),
586        array( "abc", 1, 2, 3, "c" ),
587        array( "abc", 1, -2, 2, "b" ),
588        array( "abc", 0, 2, 2, "" ),
589        array( "http://news.bbc.co.uk/2/hi/middle_east/7831588.stm", 48, 48 , 50 , "tm" ),
590
591        array( $char_a_ring_nfd . "bc", 3, $char_a_ring_nfd . "bc" ),
592        array( $char_a_ring_nfd . "bc", 2, $char_a_ring_nfd . "b" ),
593        array( $char_a_ring_nfd . "bc", 1, $char_a_ring_nfd . "" ),
594        array( $char_a_ring_nfd . "bc", 3, 0, 5, $char_a_ring_nfd . "bc" ),
595        array( $char_a_ring_nfd . "bc", 2, 0, 4, $char_a_ring_nfd . "b" ),
596        array( $char_a_ring_nfd . "bc", 1, 0, 3, $char_a_ring_nfd . "" ),
597        array( $char_a_ring_nfd . "bcde", 2, 3, 5, "bc" ),
598        array( $char_a_ring_nfd . "bcde", 2, -4, 5, "bc" ),
599        array( $char_a_ring_nfd . "bcde", 2, 4, 6, "cd" ),
600        array( $char_a_ring_nfd . "bcde", 2, -7, 4, $char_a_ring_nfd . "b" ),
601        array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, 5, 11, "de" . $char_a_ring_nfd . "f" ),
602        array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, -6, 11, "de" . $char_a_ring_nfd . "f" ),
603
604        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd ),
605        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, $char_a_ring_nfd . $char_o_diaeresis_nfd ),
606        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 1, $char_a_ring_nfd . "" ),
607
608        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 0, $char_o_diaeresis_nfd),
609        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 2, $char_o_diaeresis_nfd),
610        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 3, $char_o_diaeresis_nfd),
611        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 4, $char_diaeresis),
612
613        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 0, $char_o_diaeresis_nfd . $char_o_diaeresis_nfd),
614        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 2, $char_o_diaeresis_nfd . $char_o_diaeresis_nfd),
615        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 3, $char_o_diaeresis_nfd . $char_o_diaeresis_nfd),
616        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 4, $char_diaeresis . $char_o_diaeresis_nfd),
617        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 7, $char_diaeresis . $char_o_diaeresis_nfd),
618        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 8, $char_o_diaeresis_nfd),
619        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 10, $char_diaeresis),
620        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 11, "false"),
621
622    );
623
624    $next = -1;
625    foreach( $tests as $test ) {
626        $arg0 = urlencode($test[0]);
627        $res_str .= "extract from \"$arg0\" \"$test[1]\" graphemes - grapheme_extract";
628        if ( 3 == count( $test ) ) {
629            $result = grapheme_extract($test[0], $test[1]);
630        }
631        elseif ( 4 == count ( $test ) ) {
632            $res_str .= " starting at byte position $test[2]";
633            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_COUNT, $test[2]);
634        }
635        else {
636            $res_str .= " starting at byte position $test[2] with \$next";
637            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_COUNT, $test[2], $next);
638        }
639        $res_str .= " = ";
640        if ( $result === false ) {
641            $res_str .= 'false';
642        }
643        else {
644            $res_str .= urlencode($result);
645        }
646        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]);
647        if ( 5 == count ( $test ) ) {
648            $res_str .= " \$next=$next == $test[3] ";
649            if ( $next != $test[3] ) {
650                $res_str .= "***FAILED***";
651            }
652        }
653        $res_str .= "\n";
654    }
655
656
657    //=====================================================================================
658    $res_str .= "\n" . 'function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXBYTES, $start = 0)' . "\n\n";
659
660    $tests = array(
661        array( "abc", 3, "abc" ),
662        array( "abc", 2, "ab" ),
663        array( "abc", 1, "a" ),
664        array( "abc", 0, "" ),
665        array( $char_a_ring_nfd . "bc", 5, $char_a_ring_nfd . "bc" ),
666        array( $char_a_ring_nfd . "bc", 4, $char_a_ring_nfd . "b" ),
667        array( $char_a_ring_nfd . "bc", 1, "" ),
668        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 9, $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd ),
669        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 10, $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd ),
670        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 11, $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd ),
671        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 6, $char_a_ring_nfd . $char_o_diaeresis_nfd ),
672        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 3, $char_a_ring_nfd . "" ),
673        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 4, $char_a_ring_nfd . "" ),
674        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 5, $char_a_ring_nfd . "" ),
675        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 6, $char_a_ring_nfd . $char_o_diaeresis_nfd  ),
676        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 7, $char_a_ring_nfd . $char_o_diaeresis_nfd . "c" ),
677
678        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 0, $char_o_diaeresis_nfd),
679        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 2, $char_o_diaeresis_nfd),
680        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 3, $char_o_diaeresis_nfd),
681        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 4, $char_diaeresis),
682
683        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 6, 0, $char_o_diaeresis_nfd . $char_o_diaeresis_nfd),
684        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 6, 2, $char_o_diaeresis_nfd . $char_o_diaeresis_nfd),
685        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 6, 3, $char_o_diaeresis_nfd . $char_o_diaeresis_nfd),
686        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 5, 4, $char_diaeresis . $char_o_diaeresis_nfd),
687        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 5, 7, $char_diaeresis . $char_o_diaeresis_nfd),
688        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 8, $char_o_diaeresis_nfd),
689        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 10, $char_diaeresis),
690        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 11, "false"),
691
692    );
693
694    foreach( $tests as $test ) {
695        $arg0 = urlencode($test[0]);
696        $res_str .= "extract from \"$arg0\" \"$test[1]\" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES";
697        if ( 3 == count( $test ) ) {
698            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXBYTES);
699        }
700        else {
701            $res_str .= " starting at byte position $test[2]";
702            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXBYTES, $test[2]);
703        }
704        $res_str .= " = ";
705        if ( $result === false ) {
706            $res_str .= 'false';
707        }
708        else {
709            $res_str .= urlencode($result);
710        }
711        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
712    }
713
714
715    //=====================================================================================
716    $res_str .= "\n" . 'function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXCHARS, $start = 0)' . "\n\n";
717
718    $tests = array(
719        array( "abc", 3, "abc" ),
720        array( "abc", 2, "ab" ),
721        array( "abc", 1, "a" ),
722        array( "abc", 0, "" ),
723        array( "abc" . $char_o_diaeresis_nfd, 0, "" ),
724        array( "abc" . $char_o_diaeresis_nfd, 1, "a" ),
725        array( "abc" . $char_o_diaeresis_nfd, 2, "ab" ),
726        array( "abc" . $char_o_diaeresis_nfd, 3, "abc" ),
727        array( "abc" . $char_o_diaeresis_nfd, 4, "abc" ),
728        array( "abc" . $char_o_diaeresis_nfd, 5, "abc" . $char_o_diaeresis_nfd),
729        array( "abc" . $char_o_diaeresis_nfd, 6, "abc" . $char_o_diaeresis_nfd),
730        array( $char_o_diaeresis_nfd . "abc", 0, "" ),
731        array( $char_o_diaeresis_nfd . "abc", 1, "" ),
732        array( $char_o_diaeresis_nfd . "abc", 2, $char_o_diaeresis_nfd ),
733        array( $char_o_diaeresis_nfd . "abc", 3, $char_o_diaeresis_nfd . "a" ),
734        array( $char_o_diaeresis_nfd . "abc", 4, $char_o_diaeresis_nfd . "ab" ),
735        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 5, $char_o_diaeresis_nfd . "abc" ),
736        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 6, $char_o_diaeresis_nfd . "abc" ),
737        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 7, $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd ),
738        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "x" ),
739
740        array( "abc", 3, 0, "abc" ),
741        array( "abc", 2, 1, "bc" ),
742        array( "abc", 1, 2, "c" ),
743        array( "abc", 0, 3, "false" ),
744        array( "abc", 1, 3, "false" ),
745        array( "abc", 1, 999, "false" ),
746        array( $char_o_diaeresis_nfd . "abc", 1, 6, "false" ),
747        array( $char_o_diaeresis_nfd . "abc", 1, 999, "false" ),
748        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 0, $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "x" ),
749        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 1, $char_diaeresis . "abc" . $char_a_ring_nfd . "xy" ),
750        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 2, "abc" . $char_a_ring_nfd . "xyz" ),
751        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 3, "abc" . $char_a_ring_nfd . "xyz" ),
752        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 4, "bc" . $char_a_ring_nfd . "xyz" ),
753        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 5, "c" . $char_a_ring_nfd . "xyz" ),
754        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 6, $char_a_ring_nfd . "xyz" ),
755
756    );
757
758    foreach( $tests as $test ) {
759        $arg0 = urlencode($test[0]);
760        $res_str .= "extract from \"$arg0\" \"$test[1]\" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS";
761        if ( 3 == count( $test ) ) {
762            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXCHARS);
763        }
764        else {
765            $res_str .= " starting at byte position $test[2]";
766            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXCHARS, $test[2]);
767        }
768        $res_str .= " = ";
769        if ( $result === false ) {
770            $res_str .= 'false';
771        }
772        else {
773            $res_str .= urlencode($result);
774        }
775        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
776    }
777
778
779    //=====================================================================================
780
781    return $res_str;
782}
783
784echo ut_main();
785
786function check_result($result, $expected) {
787
788    if ( $result === false ) {
789            $result = 'false';
790    }
791
792    if ( strcmp($result, $expected) != 0 ) {
793        return " **FAILED** ";
794    }
795
796    return "";
797}
798
799?>
800--EXPECT--
801function grapheme_strlen($string) {}
802
803"hindi" in devanagari strlen 3
804"ab" + "hindi" + "cde" strlen 8
805"" strlen 0
806char_a_ring_nfd strlen 1
807char_a_ring_nfd + "bc" strlen 3
808"abc" strlen 3
809
810function grapheme_strpos($haystack, $needle, $offset = 0) {}
811
812find "o" in "aa%CC%8Abco%CC%88o" - grapheme_strpos = 5 == 5
813find "o" in "aa%CC%8Abco%CC%88" - grapheme_strpos = false == false
814find "o%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_strpos = 4 == 4
815find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strpos = 2 == 2
816find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strpos = 1 == 1
817find "a%CC%8A" in "abc" - grapheme_strpos = false == false
818find "a" in "a%CC%8Abc" - grapheme_strpos = false == false
819find "d" in "abc" - grapheme_strpos = false == false
820find "c" in "abc" - grapheme_strpos = 2 == 2
821find "b" in "abc" - grapheme_strpos = 1 == 1
822find "a" in "abc" - grapheme_strpos = 0 == 0
823find "a" in "abc" - grapheme_strpos from 0 = 0 == 0
824find "a" in "abc" - grapheme_strpos from 1 = false == false
825find "a" in "abc" - grapheme_strpos from -1 = false == false
826find "a" in "ababc" - grapheme_strpos from 1 = 2 == 2
827find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from 2 = 6 == 6
828find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -1 = 6 == 6
829find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -5 = 6 == 6
830find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from 2 = 3 == 3
831find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from -4 = 3 == 3
832find "op" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5
833find "opq" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5
834find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strpos = false == false
835find "o%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bco%CC%88" - grapheme_strpos = 4 == 4
836find "a%CC%8Abc" in "o%CC%88aa%CC%8Abc" - grapheme_strpos = 2 == 2
837find "a%CC%8Abc" in "aa%CC%8Abc" - grapheme_strpos = 1 == 1
838find "a%CC%8Abc" in "abc" - grapheme_strpos = false == false
839find "abcdefg" in "a%CC%8Abc" - grapheme_strpos = false == false
840find "defghijklmnopq" in "abc" - grapheme_strpos = false == false
841find "ab" in "abc" - grapheme_strpos = 0 == 0
842find "bc" in "abc" - grapheme_strpos = 1 == 1
843find "abc" in "abc" - grapheme_strpos = 0 == 0
844find "abcd" in "abc" - grapheme_strpos = false == false
845find "ab" in "abc" - grapheme_strpos from 0 = 0 == 0
846find "abc" in "abc" - grapheme_strpos from 0 = 0 == 0
847find "abc" in "abc" - grapheme_strpos from 1 = false == false
848find "ab" in "ababc" - grapheme_strpos from 1 = 2 == 2
849find "abc" in "ababc" - grapheme_strpos from 1 = 2 == 2
850find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from 2 = 6 == 6
851find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from -8 = 6 == 6
852find "a%CC%8Abca%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abca%CC%8Adef" - grapheme_strpos from 2 = 3 == 3
853
854function grapheme_stripos($haystack, $needle, $offset = 0) {}
855
856find "o" in "aoa%CC%8Abco%CC%88O" - grapheme_stripos from 2 = 6 == 6
857find "o" in "aoa%CC%8Abco%CC%88Oo" - grapheme_stripos from -6 = 6 == 6
858find "a%CC%8A" in "o%CC%88a%CC%8AaA%CC%8Abc" - grapheme_stripos from 2 = 3 == 3
859find "o" in "aa%CC%8Abco%CC%88O" - grapheme_stripos = 5 == 5
860find "O" in "aa%CC%8Abco%CC%88" - grapheme_stripos = false == false
861find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos = 4 == 4
862find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos from -1 = 4 == 4
863find "A%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_stripos = 2 == 2
864find "a%CC%8A" in "aA%CC%8Abc" - grapheme_stripos = 1 == 1
865find "a%CC%8A" in "Abc" - grapheme_stripos = false == false
866find "A" in "a%CC%8Abc" - grapheme_stripos = false == false
867find "D" in "abc" - grapheme_stripos = false == false
868find "c" in "abC" - grapheme_stripos = 2 == 2
869find "B" in "abc" - grapheme_stripos = 1 == 1
870find "a" in "Abc" - grapheme_stripos = 0 == 0
871find "A" in "abc" - grapheme_stripos from 0 = 0 == 0
872find "a" in "Abc" - grapheme_stripos from 1 = false == false
873find "A" in "ababc" - grapheme_stripos from 1 = 2 == 2
874find "oP" in "aa%CC%8Abco%CC%88Opq" - grapheme_stripos = 5 == 5
875find "opQ" in "aa%CC%8Abco%CC%88Opq" - grapheme_stripos = 5 == 5
876find "abc" in "aa%CC%8Abco%CC%88" - grapheme_stripos = false == false
877find "O%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bCo%CC%88" - grapheme_stripos = 4 == 4
878find "A%CC%8Abc" in "o%CC%88aa%CC%8ABc" - grapheme_stripos = 2 == 2
879find "a%CC%8Abc" in "aa%CC%8ABC" - grapheme_stripos = 1 == 1
880find "a%CC%8ABC" in "abc" - grapheme_stripos = false == false
881find "aBCdefg" in "a%CC%8ABC" - grapheme_stripos = false == false
882find "Defghijklmnopq" in "aBC" - grapheme_stripos = false == false
883find "Ab" in "abC" - grapheme_stripos = 0 == 0
884find "bc" in "aBC" - grapheme_stripos = 1 == 1
885find "Abc" in "abC" - grapheme_stripos = 0 == 0
886find "aBcd" in "abC" - grapheme_stripos = false == false
887find "ab" in "ABc" - grapheme_stripos from 0 = 0 == 0
888find "abC" in "aBc" - grapheme_stripos from 0 = 0 == 0
889find "aBc" in "abc" - grapheme_stripos from 1 = false == false
890find "AB" in "ABabc" - grapheme_stripos from 1 = 2 == 2
891find "AB" in "ABabc" - grapheme_stripos from -4 = 2 == 2
892find "aBc" in "abaBc" - grapheme_stripos from 1 = 2 == 2
893find "Oa%CC%8AbC" in "aoa%CC%8Abco%CC%88oA%CC%8AbC" - grapheme_stripos from 2 = 6 == 6
894find "a%CC%8ABca%CC%8A" in "o%CC%88a%CC%8AaA%CC%8AbCa%CC%8Adef" - grapheme_stripos from 2 = 3 == 3
895
896function grapheme_strrpos($haystack, $needle, $offset = 0) {}
897
898find "o" in "aa%CC%8Abco%CC%88o" - grapheme_strrpos = 5 == 5
899find "o" in "aa%CC%8Abco%CC%88" - grapheme_strrpos = false == false
900find "o%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_strrpos = 4 == 4
901find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strrpos = 2 == 2
902find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strrpos = 1 == 1
903find "a%CC%8A" in "abc" - grapheme_strrpos = false == false
904find "a" in "a%CC%8Abc" - grapheme_strrpos = false == false
905find "d" in "abc" - grapheme_strrpos = false == false
906find "c" in "abc" - grapheme_strrpos = 2 == 2
907find "b" in "abc" - grapheme_strrpos = 1 == 1
908find "a" in "abc" - grapheme_strrpos = 0 == 0
909find "a" in "abc" - grapheme_strrpos from 0 = 0 == 0
910find "a" in "abc" - grapheme_strrpos from 1 = false == false
911find "a" in "ababc" - grapheme_strrpos from 1 = 2 == 2
912find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strrpos from 2 = 6 == 6
913find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strrpos from 2 = 3 == 3
914find "op" in "aa%CC%8Abco%CC%88opq" - grapheme_strrpos = 5 == 5
915find "opq" in "aa%CC%8Abco%CC%88opq" - grapheme_strrpos = 5 == 5
916find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strrpos = false == false
917find "o%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bco%CC%88" - grapheme_strrpos = 4 == 4
918find "a%CC%8Abc" in "o%CC%88aa%CC%8Abc" - grapheme_strrpos = 2 == 2
919find "a%CC%8Abc" in "aa%CC%8Abc" - grapheme_strrpos = 1 == 1
920find "a%CC%8Abc" in "abc" - grapheme_strrpos = false == false
921find "abcdefg" in "a%CC%8Abc" - grapheme_strrpos = false == false
922find "defghijklmnopq" in "abc" - grapheme_strrpos = false == false
923find "ab" in "abc" - grapheme_strrpos = 0 == 0
924find "bc" in "abc" - grapheme_strrpos = 1 == 1
925find "abc" in "abc" - grapheme_strrpos = 0 == 0
926find "abcd" in "abc" - grapheme_strrpos = false == false
927find "ab" in "abc" - grapheme_strrpos from 0 = 0 == 0
928find "abc" in "abc" - grapheme_strrpos from 0 = 0 == 0
929find "abc" in "abc" - grapheme_strrpos from 1 = false == false
930find "ab" in "ababc" - grapheme_strrpos from 1 = 2 == 2
931find "abc" in "ababc" - grapheme_strrpos from 1 = 2 == 2
932find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strrpos from 2 = 6 == 6
933find "a%CC%8Abca%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abca%CC%8Adef" - grapheme_strrpos from 2 = 3 == 3
934
935function grapheme_strripos($haystack, $needle, $offset = 0) {}
936
937find "o" in "aoa%CC%8Abco%CC%88O" - grapheme_strripos from 2 = 6 == 6
938find "a%CC%8A" in "o%CC%88a%CC%8AaA%CC%8Abc" - grapheme_strripos from 2 = 3 == 3
939find "o" in "aa%CC%8Abco%CC%88O" - grapheme_strripos = 5 == 5
940find "O" in "aa%CC%8Abco%CC%88" - grapheme_strripos = false == false
941find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_strripos = 4 == 4
942find "A%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strripos = 2 == 2
943find "a%CC%8A" in "aA%CC%8Abc" - grapheme_strripos = 1 == 1
944find "a%CC%8A" in "Abc" - grapheme_strripos = false == false
945find "A" in "a%CC%8Abc" - grapheme_strripos = false == false
946find "D" in "abc" - grapheme_strripos = false == false
947find "c" in "abC" - grapheme_strripos = 2 == 2
948find "B" in "abc" - grapheme_strripos = 1 == 1
949find "a" in "Abc" - grapheme_strripos = 0 == 0
950find "A" in "abc" - grapheme_strripos from 0 = 0 == 0
951find "a" in "Abc" - grapheme_strripos from 1 = false == false
952find "A" in "ababc" - grapheme_strripos from 1 = 2 == 2
953find "oP" in "aa%CC%8Abco%CC%88Opq" - grapheme_strripos = 5 == 5
954find "opQ" in "aa%CC%8Abco%CC%88Opq" - grapheme_strripos = 5 == 5
955find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strripos = false == false
956find "O%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bCo%CC%88" - grapheme_strripos = 4 == 4
957find "A%CC%8Abc" in "o%CC%88aa%CC%8ABc" - grapheme_strripos = 2 == 2
958find "a%CC%8Abc" in "aa%CC%8ABC" - grapheme_strripos = 1 == 1
959find "a%CC%8ABC" in "abc" - grapheme_strripos = false == false
960find "aBCdefg" in "a%CC%8ABC" - grapheme_strripos = false == false
961find "Defghijklmnopq" in "aBC" - grapheme_strripos = false == false
962find "Ab" in "abC" - grapheme_strripos = 0 == 0
963find "bc" in "aBC" - grapheme_strripos = 1 == 1
964find "Abc" in "abC" - grapheme_strripos = 0 == 0
965find "aBcd" in "abC" - grapheme_strripos = false == false
966find "ab" in "ABc" - grapheme_strripos from 0 = 0 == 0
967find "abC" in "aBc" - grapheme_strripos from 0 = 0 == 0
968find "aBc" in "abc" - grapheme_strripos from 1 = false == false
969find "AB" in "ABabc" - grapheme_strripos from 1 = 2 == 2
970find "aBc" in "abaBc" - grapheme_strripos from 1 = 2 == 2
971find "Oa%CC%8AbC" in "aoa%CC%8Abco%CC%88oA%CC%8AbC" - grapheme_strripos from 2 = 6 == 6
972find "a%CC%8ABca%CC%8A" in "o%CC%88a%CC%8AaA%CC%8AbCa%CC%8Adef" - grapheme_strripos from 2 = 3 == 3
973
974function grapheme_substr($string, $start, $length = -1) {}
975
976substring of "abc" from "3" - grapheme_substr =  ==
977substring of "aa%CC%8Abco%CC%88" from "5" - grapheme_substr =  ==
978substring of "aoa%CC%8Abco%CC%88O" from "2" - grapheme_substr = a%CC%8Abco%CC%88O == a%CC%8Abco%CC%88O
979substring of "o%CC%88a%CC%8AaA%CC%8Abc" from "2" - grapheme_substr = aA%CC%8Abc == aA%CC%8Abc
980substring of "aa%CC%8Abco%CC%88O" from "5" - grapheme_substr = O == O
981substring of "aa%CC%8Abco%CC%88" from "5" - grapheme_substr =  ==
982substring of "aa%CC%8AbcO%CC%88" from "4" - grapheme_substr = O%CC%88 == O%CC%88
983substring of "o%CC%88aa%CC%8Abc" from "2" - grapheme_substr = a%CC%8Abc == a%CC%8Abc
984substring of "aA%CC%8Abc" from "1" - grapheme_substr = A%CC%8Abc == A%CC%8Abc
985substring of "Abc" from "-5" - grapheme_substr = Abc == Abc
986substring of "a%CC%8Abc" from "3" - grapheme_substr =  ==
987substring of "abc" from "4" - grapheme_substr =  ==
988substring of "abC" from "2" - grapheme_substr = C == C
989substring of "abc" from "1" - grapheme_substr = bc == bc
990substring of "Abc" from "1" - grapheme_substr with length 1 = b == b
991substring of "abc" from "0" - grapheme_substr with length 2 = ab == ab
992substring of "Abc" from "-4" - grapheme_substr with length 1 = A == A
993substring of "ababc" from "1" - grapheme_substr with length 2 = ba == ba
994substring of "ababc" from "0" - grapheme_substr with length 10 = ababc == ababc
995substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length 10 = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
996substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr = Opq == Opq
997substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -1 = Op == Op
998substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -2 = O == O
999substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -3 =  ==
1000substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -4 =  ==
1001substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1002substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -1 = aa%CC%8Abco%CC%88Op == aa%CC%8Abco%CC%88Op
1003substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -2 = aa%CC%8Abco%CC%88O == aa%CC%8Abco%CC%88O
1004substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -3 = aa%CC%8Abco%CC%88 == aa%CC%8Abco%CC%88
1005substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -4 = aa%CC%8Abc == aa%CC%8Abc
1006substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -5 = aa%CC%8Ab == aa%CC%8Ab
1007substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -6 = aa%CC%8A == aa%CC%8A
1008substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -7 = a == a
1009substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -8 =  ==
1010substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -9 =  ==
1011substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1012substring of "aa%CC%8Abco%CC%88Opq" from "-7" - grapheme_substr = a%CC%8Abco%CC%88Opq == a%CC%8Abco%CC%88Opq
1013substring of "aa%CC%8Abco%CC%88Opq" from "-6" - grapheme_substr = bco%CC%88Opq == bco%CC%88Opq
1014substring of "aa%CC%8Abco%CC%88Opq" from "-5" - grapheme_substr = co%CC%88Opq == co%CC%88Opq
1015substring of "aa%CC%8Abco%CC%88Opq" from "-4" - grapheme_substr = o%CC%88Opq == o%CC%88Opq
1016substring of "aa%CC%8Abco%CC%88Opq" from "-3" - grapheme_substr = Opq == Opq
1017substring of "aa%CC%8Abco%CC%88Opq" from "-2" - grapheme_substr = pq == pq
1018substring of "aa%CC%8Abco%CC%88Opq" from "-1" - grapheme_substr = q == q
1019substring of "aa%CC%8Abco%CC%88Opq" from "-999" - grapheme_substr = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1020substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 8 = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1021substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 7 = aa%CC%8Abco%CC%88Op == aa%CC%8Abco%CC%88Op
1022substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 6 = aa%CC%8Abco%CC%88O == aa%CC%8Abco%CC%88O
1023substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 5 = aa%CC%8Abco%CC%88 == aa%CC%8Abco%CC%88
1024substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 4 = aa%CC%8Abc == aa%CC%8Abc
1025substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 3 = aa%CC%8Ab == aa%CC%8Ab
1026substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 2 = aa%CC%8A == aa%CC%8A
1027substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 1 = a == a
1028substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 0 =  ==
1029substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -999 =  ==
1030substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -1 = aa%CC%8Abco%CC%88Op == aa%CC%8Abco%CC%88Op
1031substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -2 = aa%CC%8Abco%CC%88O == aa%CC%8Abco%CC%88O
1032substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -3 = aa%CC%8Abco%CC%88 == aa%CC%8Abco%CC%88
1033substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -4 = aa%CC%8Abc == aa%CC%8Abc
1034substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -5 = aa%CC%8Ab == aa%CC%8Ab
1035substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -6 = aa%CC%8A == aa%CC%8A
1036substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -7 = a == a
1037substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -8 =  ==
1038substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -9 =  ==
1039
1040function grapheme_strstr($haystack, $needle, $before_needle = FALSE) {}
1041
1042find "o" in "aa%CC%8Abco%CC%88o" - grapheme_strstr = o == o
1043find "o" in "aa%CC%8Abco%CC%88" - grapheme_strstr = false == false
1044find "o%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_strstr = o%CC%88 == o%CC%88
1045find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strstr = a%CC%8Abc == a%CC%8Abc
1046find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strstr = a%CC%8Abc == a%CC%8Abc
1047find "a%CC%8A" in "abc" - grapheme_strstr = false == false
1048find "a" in "a%CC%8Abc" - grapheme_strstr = false == false
1049find "d" in "abc" - grapheme_strstr = false == false
1050find "c" in "abc" - grapheme_strstr = c == c
1051find "b" in "abc" - grapheme_strstr = bc == bc
1052find "a" in "abc" - grapheme_strstr = abc == abc
1053find "ab" in "abc" - grapheme_strstr = abc == abc
1054find "abc" in "abc" - grapheme_strstr = abc == abc
1055find "bc" in "abc" - grapheme_strstr = bc == bc
1056find "a" in "abc" - grapheme_strstr before flag is FALSE = abc == abc
1057find "a" in "abc" - grapheme_strstr before flag is TRUE =  ==
1058find "b" in "abc" - grapheme_strstr before flag is TRUE = a == a
1059find "c" in "abc" - grapheme_strstr before flag is TRUE = ab == ab
1060find "bab" in "ababc" - grapheme_strstr before flag is TRUE = a == a
1061find "abc" in "ababc" - grapheme_strstr before flag is TRUE = ab == ab
1062find "abc" in "ababc" - grapheme_strstr before flag is FALSE = abc == abc
1063find "d" in "aba%CC%8Ac" - grapheme_strstr = false == false
1064find "a" in "bca%CC%8Aa" - grapheme_strstr = a == a
1065find "b" in "aa%CC%8Abc" - grapheme_strstr = bc == bc
1066find "a" in "a%CC%8Abc" - grapheme_strstr = false == false
1067find "ab" in "a%CC%8Aabc" - grapheme_strstr = abc == abc
1068find "abc" in "abca%CC%8A" - grapheme_strstr = abca%CC%8A == abca%CC%8A
1069find "a%CC%8Abc" in "aa%CC%8Abc" - grapheme_strstr = a%CC%8Abc == a%CC%8Abc
1070find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strstr before flag is FALSE = a%CC%8Abc == a%CC%8Abc
1071find "a" in "aa%CC%8Abc" - grapheme_strstr before flag is TRUE =  ==
1072find "b" in "a%CC%8Aabc" - grapheme_strstr before flag is TRUE = a%CC%8Aa == a%CC%8Aa
1073find "c" in "aba%CC%8Ac" - grapheme_strstr before flag is TRUE = aba%CC%8A == aba%CC%8A
1074find "baa%CC%8Ab" in "abaa%CC%8Abc" - grapheme_strstr before flag is TRUE = a == a
1075find "abca%CC%8A" in "ababca%CC%8A" - grapheme_strstr before flag is TRUE = ab == ab
1076find "aba%CC%8Ac" in "ababa%CC%8Ac" - grapheme_strstr before flag is FALSE = aba%CC%8Ac == aba%CC%8Ac
1077
1078function grapheme_stristr($haystack, $needle, $before_needle = FALSE) {}
1079
1080find "O%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_stristr = o%CC%88 == o%CC%88
1081find "o" in "aa%CC%8Abco%CC%88O" - grapheme_stristr = O == O
1082find "o" in "aa%CC%8Abco%CC%88" - grapheme_stristr = false == false
1083find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_stristr = a%CC%8Abc == a%CC%8Abc
1084find "A%CC%8A" in "aa%CC%8Abc" - grapheme_stristr = a%CC%8Abc == a%CC%8Abc
1085find "a%CC%8A" in "abc" - grapheme_stristr = false == false
1086find "A" in "a%CC%8Abc" - grapheme_stristr = false == false
1087find "d" in "abc" - grapheme_stristr = false == false
1088find "C" in "abc" - grapheme_stristr = c == c
1089find "b" in "aBc" - grapheme_stristr = Bc == Bc
1090find "A" in "abc" - grapheme_stristr = abc == abc
1091find "ab" in "abC" - grapheme_stristr = abC == abC
1092find "aBc" in "abc" - grapheme_stristr = abc == abc
1093find "bc" in "abC" - grapheme_stristr = bC == bC
1094find "A" in "abc" - grapheme_stristr before flag is FALSE = abc == abc
1095find "a" in "abc" - grapheme_stristr before flag is TRUE =  ==
1096find "b" in "aBc" - grapheme_stristr before flag is TRUE = a == a
1097find "C" in "abc" - grapheme_stristr before flag is TRUE = ab == ab
1098find "bab" in "aBabc" - grapheme_stristr before flag is TRUE = a == a
1099find "aBc" in "ababc" - grapheme_stristr before flag is TRUE = ab == ab
1100find "abC" in "ababc" - grapheme_stristr before flag is FALSE = abc == abc
1101find "d" in "aba%CC%8Ac" - grapheme_stristr = false == false
1102find "a" in "bca%CC%8AA" - grapheme_stristr = A == A
1103find "B" in "aa%CC%8Abc" - grapheme_stristr = bc == bc
1104find "a" in "A%CC%8Abc" - grapheme_stristr = false == false
1105find "Ab" in "a%CC%8Aabc" - grapheme_stristr = abc == abc
1106find "abc" in "abcA%CC%8A" - grapheme_stristr = abcA%CC%8A == abcA%CC%8A
1107find "A%CC%8Abc" in "aa%CC%8Abc" - grapheme_stristr = a%CC%8Abc == a%CC%8Abc
1108find "a%CC%8A" in "aA%CC%8Abc" - grapheme_stristr before flag is FALSE = A%CC%8Abc == A%CC%8Abc
1109find "A" in "aa%CC%8Abc" - grapheme_stristr before flag is TRUE =  ==
1110find "b" in "a%CC%8AaBc" - grapheme_stristr before flag is TRUE = a%CC%8Aa == a%CC%8Aa
1111find "C" in "aba%CC%8Ac" - grapheme_stristr before flag is TRUE = aba%CC%8A == aba%CC%8A
1112find "baa%CC%8Ab" in "abaA%CC%8Abc" - grapheme_stristr before flag is TRUE = a == a
1113find "aBcA%CC%8A" in "ababca%CC%8A" - grapheme_stristr before flag is TRUE = ab == ab
1114find "aba%CC%8Ac" in "abABA%CC%8Ac" - grapheme_stristr before flag is FALSE = ABA%CC%8Ac == ABA%CC%8Ac
1115
1116function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_COUNT, $start = 0[, $next])
1117
1118extract from "abc" "3" graphemes - grapheme_extract = abc == abc
1119extract from "abc" "2" graphemes - grapheme_extract = ab == ab
1120extract from "abc" "1" graphemes - grapheme_extract = a == a
1121extract from "abc" "0" graphemes - grapheme_extract =  ==
1122extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 = a == a
1123extract from "abc" "1" graphemes - grapheme_extract starting at byte position 1 = b == b
1124extract from "abc" "1" graphemes - grapheme_extract starting at byte position 2 = c == c
1125extract from "abc" "0" graphemes - grapheme_extract starting at byte position 2 =  ==
1126extract from "abc" "3" graphemes - grapheme_extract starting at byte position 0 with $next = abc == abc $next=3 == 3
1127extract from "abc" "2" graphemes - grapheme_extract starting at byte position 0 with $next = ab == ab $next=2 == 2
1128extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a == a $next=1 == 1
1129extract from "abc" "0" graphemes - grapheme_extract starting at byte position 0 with $next =  ==  $next=0 == 0
1130extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a == a $next=1 == 1
1131extract from "abc" "1" graphemes - grapheme_extract starting at byte position 1 with $next = b == b $next=2 == 2
1132extract from "abc" "1" graphemes - grapheme_extract starting at byte position 2 with $next = c == c $next=3 == 3
1133extract from "abc" "1" graphemes - grapheme_extract starting at byte position -2 with $next = b == b $next=2 == 2
1134extract from "abc" "0" graphemes - grapheme_extract starting at byte position 2 with $next =  ==  $next=2 == 2
1135extract from "http%3A%2F%2Fnews.bbc.co.uk%2F2%2Fhi%2Fmiddle_east%2F7831588.stm" "48" graphemes - grapheme_extract starting at byte position 48 with $next = tm == tm $next=50 == 50
1136extract from "a%CC%8Abc" "3" graphemes - grapheme_extract = a%CC%8Abc == a%CC%8Abc
1137extract from "a%CC%8Abc" "2" graphemes - grapheme_extract = a%CC%8Ab == a%CC%8Ab
1138extract from "a%CC%8Abc" "1" graphemes - grapheme_extract = a%CC%8A == a%CC%8A
1139extract from "a%CC%8Abc" "3" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8Abc == a%CC%8Abc $next=5 == 5
1140extract from "a%CC%8Abc" "2" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4
1141extract from "a%CC%8Abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8A == a%CC%8A $next=3 == 3
1142extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 3 with $next = bc == bc $next=5 == 5
1143extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -4 with $next = bc == bc $next=5 == 5
1144extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 4 with $next = cd == cd $next=6 == 6
1145extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -7 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4
1146extract from "a%CC%8Abcdea%CC%8Af" "4" graphemes - grapheme_extract starting at byte position 5 with $next = dea%CC%8Af == dea%CC%8Af $next=11 == 11
1147extract from "a%CC%8Abcdea%CC%8Af" "4" graphemes - grapheme_extract starting at byte position -6 with $next = dea%CC%8Af == dea%CC%8Af $next=11 == 11
1148extract from "a%CC%8Ao%CC%88o%CC%88" "3" graphemes - grapheme_extract = a%CC%8Ao%CC%88o%CC%88 == a%CC%8Ao%CC%88o%CC%88
1149extract from "a%CC%8Ao%CC%88o%CC%88" "2" graphemes - grapheme_extract = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88
1150extract from "a%CC%8Ao%CC%88c" "1" graphemes - grapheme_extract = a%CC%8A == a%CC%8A
1151extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "1" graphemes - grapheme_extract starting at byte position 0 = o%CC%88 == o%CC%88
1152extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "1" graphemes - grapheme_extract starting at byte position 2 = o%CC%88 == o%CC%88
1153extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "1" graphemes - grapheme_extract starting at byte position 3 = o%CC%88 == o%CC%88
1154extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "1" graphemes - grapheme_extract starting at byte position 4 = %CC%88 == %CC%88
1155extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 0 = o%CC%88o%CC%88 == o%CC%88o%CC%88
1156extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 2 = o%CC%88o%CC%88 == o%CC%88o%CC%88
1157extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 3 = o%CC%88o%CC%88 == o%CC%88o%CC%88
1158extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 4 = %CC%88o%CC%88 == %CC%88o%CC%88
1159extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 7 = %CC%88o%CC%88 == %CC%88o%CC%88
1160extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 8 = o%CC%88 == o%CC%88
1161extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 10 = %CC%88 == %CC%88
1162extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 11 = false == false
1163
1164function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXBYTES, $start = 0)
1165
1166extract from "abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = abc == abc
1167extract from "abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = ab == ab
1168extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a == a
1169extract from "abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES =  ==
1170extract from "a%CC%8Abc" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Abc == a%CC%8Abc
1171extract from "a%CC%8Abc" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ab == a%CC%8Ab
1172extract from "a%CC%8Abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES =  ==
1173extract from "a%CC%8Ao%CC%88o%CC%88" "9" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88o%CC%88 == a%CC%8Ao%CC%88o%CC%88
1174extract from "a%CC%8Ao%CC%88o%CC%88" "10" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88o%CC%88 == a%CC%8Ao%CC%88o%CC%88
1175extract from "a%CC%8Ao%CC%88o%CC%88" "11" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88o%CC%88 == a%CC%8Ao%CC%88o%CC%88
1176extract from "a%CC%8Ao%CC%88o%CC%88" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88
1177extract from "a%CC%8Ao%CC%88c" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8A == a%CC%8A
1178extract from "a%CC%8Ao%CC%88c" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8A == a%CC%8A
1179extract from "a%CC%8Ao%CC%88c" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8A == a%CC%8A
1180extract from "a%CC%8Ao%CC%88c" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88
1181extract from "a%CC%8Ao%CC%88c" "7" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88c == a%CC%8Ao%CC%88c
1182extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 0 = o%CC%88 == o%CC%88
1183extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 2 = o%CC%88 == o%CC%88
1184extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 3 = o%CC%88 == o%CC%88
1185extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 4 = %CC%88 == %CC%88
1186extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 0 = o%CC%88o%CC%88 == o%CC%88o%CC%88
1187extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 2 = o%CC%88o%CC%88 == o%CC%88o%CC%88
1188extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 3 = o%CC%88o%CC%88 == o%CC%88o%CC%88
1189extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 4 = %CC%88o%CC%88 == %CC%88o%CC%88
1190extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 7 = %CC%88o%CC%88 == %CC%88o%CC%88
1191extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 8 = o%CC%88 == o%CC%88
1192extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 10 = %CC%88 == %CC%88
1193extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 11 = false == false
1194
1195function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXCHARS, $start = 0)
1196
1197extract from "abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abc == abc
1198extract from "abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = ab == ab
1199extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = a == a
1200extract from "abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1201extract from "abco%CC%88" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1202extract from "abco%CC%88" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = a == a
1203extract from "abco%CC%88" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = ab == ab
1204extract from "abco%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abc == abc
1205extract from "abco%CC%88" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abc == abc
1206extract from "abco%CC%88" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abco%CC%88 == abco%CC%88
1207extract from "abco%CC%88" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abco%CC%88 == abco%CC%88
1208extract from "o%CC%88abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1209extract from "o%CC%88abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1210extract from "o%CC%88abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88 == o%CC%88
1211extract from "o%CC%88abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88a == o%CC%88a
1212extract from "o%CC%88abc" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88ab == o%CC%88ab
1213extract from "o%CC%88abca%CC%8Axyz" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abc == o%CC%88abc
1214extract from "o%CC%88abca%CC%8Axyz" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abc == o%CC%88abc
1215extract from "o%CC%88abca%CC%8Axyz" "7" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abca%CC%8A == o%CC%88abca%CC%8A
1216extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abca%CC%8Ax == o%CC%88abca%CC%8Ax
1217extract from "abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 0 = abc == abc
1218extract from "abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 1 = bc == bc
1219extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 2 = c == c
1220extract from "abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 3 = false == false
1221extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 3 = false == false
1222extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 999 = false == false
1223extract from "o%CC%88abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 6 = false == false
1224extract from "o%CC%88abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 999 = false == false
1225extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 0 = o%CC%88abca%CC%8Ax == o%CC%88abca%CC%8Ax
1226extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 1 = %CC%88abca%CC%8Axy == %CC%88abca%CC%8Axy
1227extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 2 = abca%CC%8Axyz == abca%CC%8Axyz
1228extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 3 = abca%CC%8Axyz == abca%CC%8Axyz
1229extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 4 = bca%CC%8Axyz == bca%CC%8Axyz
1230extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 5 = ca%CC%8Axyz == ca%CC%8Axyz
1231extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 6 = a%CC%8Axyz == a%CC%8Axyz
1232