xref: /PHP-8.0/ext/intl/tests/grapheme2.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        try {
401            $arg0 = urlencode($test[0]);
402            $res_str .= "substring of \"$arg0\" from \"$test[1]\" - grapheme_substr";
403            if ( 3 == count( $test ) ) {
404                $result = grapheme_substr($test[0], $test[1]);
405            }
406            else {
407                $res_str .= " with length $test[2]";
408                $result = grapheme_substr($test[0], $test[1], $test[2]);
409            }
410            $res_str .= " = ";
411            if ( $result === false ) {
412                $res_str .= 'false';
413            }
414            else {
415                $res_str .= urlencode($result);
416            }
417            $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
418        } catch (ValueError $exception) {
419             $res_str .= ": " . $exception->getMessage() . "\n";
420        }
421    }
422
423
424    //=====================================================================================
425    $res_str .= "\n" . 'function grapheme_strstr($haystack, $needle, $before_needle = FALSE) {}' . "\n\n";
426
427    $tests = array(
428        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "o", "o", "o" ),
429        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "o", "false" ),
430        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, $char_o_diaeresis_nfd, $char_o_diaeresis_nfd ),
431        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, $char_a_ring_nfd . "bc"),
432        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, $char_a_ring_nfd . "bc"),
433        array( "abc", $char_a_ring_nfd, "false" ),
434        array( $char_a_ring_nfd . "bc", "a", "false" ),
435        array( "abc", "d", "false" ),
436        array( "abc", "c", "c" ),
437        array( "abc", "b", "bc" ),
438        array( "abc", "a", "abc" ),
439        array( "abc", "ab", "abc" ),
440        array( "abc", "abc", "abc" ),
441        array( "abc", "bc", "bc" ),
442        array( "abc", "a", FALSE, "abc" ),
443        array( "abc", "a", TRUE, "" ),
444        array( "abc", "b", TRUE, "a" ),
445        array( "abc", "c", TRUE, "ab" ),
446        array( "ababc", "bab", TRUE, "a" ),
447        array( "ababc", "abc", TRUE, "ab" ),
448        array( "ababc", "abc", FALSE, "abc" ),
449
450        array( "ab" . $char_a_ring_nfd . "c", "d", "false" ),
451        array( "bc" . $char_a_ring_nfd . "a", "a", "a" ),
452        array( "a" . $char_a_ring_nfd . "bc", "b", "bc" ),
453        array( $char_a_ring_nfd . "bc", "a", "false" ),
454        array( $char_a_ring_nfd . "abc", "ab", "abc" ),
455        array( "abc" . $char_a_ring_nfd, "abc", "abc" . $char_a_ring_nfd),
456        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc", $char_a_ring_nfd . "bc" ),
457        array( "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, FALSE, $char_a_ring_nfd . "bc"),
458        array( "a" . $char_a_ring_nfd . "bc", "a", TRUE, "" ),
459        array( $char_a_ring_nfd . "abc", "b", TRUE, $char_a_ring_nfd . "a" ),
460        array( "ab" . $char_a_ring_nfd . "c", "c", TRUE, "ab" . $char_a_ring_nfd ),
461        array( "aba" . $char_a_ring_nfd . "bc", "ba" . $char_a_ring_nfd . "b", TRUE, "a" ),
462        array( "ababc" . $char_a_ring_nfd, "abc" . $char_a_ring_nfd, TRUE, "ab" ),
463        array( "abab" . $char_a_ring_nfd . "c", "ab" . $char_a_ring_nfd . "c", FALSE, "ab" . $char_a_ring_nfd . "c" ),
464
465    );
466
467    foreach( $tests as $test ) {
468        $arg1 = urlencode($test[1]);
469        $arg0 = urlencode($test[0]);
470        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_strstr";
471        if ( 3 == count( $test ) ) {
472            $result = grapheme_strstr($test[0], $test[1]);
473        }
474        else {
475            $res_str .= " before flag is " . ( $test[2] ? "TRUE" : "FALSE" );
476            $result = grapheme_strstr($test[0], $test[1], $test[2]);
477        }
478        $res_str .= " = ";
479        if ( $result === false ) {
480            $res_str .= 'false';
481        }
482        else {
483            $res_str .= urlencode($result);
484        }
485        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
486    }
487
488
489    //=====================================================================================
490    $res_str .= "\n" . 'function grapheme_stristr($haystack, $needle, $before_needle = FALSE) {}' . "\n\n";
491
492    $tests = array(
493        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, $char_O_diaeresis_nfd, $char_o_diaeresis_nfd ),
494        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd . "O", "o", "O" ),
495        array( "a" . $char_a_ring_nfd . "bc" . $char_o_diaeresis_nfd, "o", "false" ),
496        array( $char_o_diaeresis_nfd . "a" . $char_a_ring_nfd . "bc", $char_a_ring_nfd, $char_a_ring_nfd . "bc"),
497        array( "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd, $char_a_ring_nfd . "bc"),
498        array( "abc", $char_a_ring_nfd, "false" ),
499        array( $char_a_ring_nfd . "bc", "A", "false" ),
500        array( "abc", "d", "false" ),
501        array( "abc", "C", "c" ),
502        array( "aBc", "b", "Bc" ),
503        array( "abc", "A", "abc" ),
504        array( "abC", "ab", "abC" ),
505        array( "abc", "aBc", "abc" ),
506        array( "abC", "bc", "bC" ),
507        array( "abc", "A", FALSE, "abc" ),
508        array( "abc", "a", TRUE, "" ),
509        array( "aBc", "b", TRUE, "a" ),
510        array( "abc", "C", TRUE, "ab" ),
511        array( "aBabc", "bab", TRUE, "a" ),
512        array( "ababc", "aBc", TRUE, "ab" ),
513        array( "ababc", "abC", FALSE, "abc" ),
514
515        array( "ab" . $char_a_ring_nfd . "c", "d", "false" ),
516        array( "bc" . $char_a_ring_nfd . "A", "a", "A" ),
517        array( "a" . $char_a_ring_nfd . "bc", "B", "bc" ),
518        array( $char_A_ring_nfd . "bc", "a", "false" ),
519        array( $char_a_ring_nfd . "abc", "Ab", "abc" ),
520        array( "abc" . $char_A_ring_nfd, "abc", "abc" . $char_A_ring_nfd),
521        array( "a" . $char_a_ring_nfd . "bc", $char_A_ring_nfd . "bc", $char_a_ring_nfd . "bc" ),
522        array( "a" . $char_A_ring_nfd . "bc", $char_a_ring_nfd, FALSE, $char_A_ring_nfd . "bc" ),
523        array( "a" . $char_a_ring_nfd . "bc", "A", TRUE, "" ),
524        array( $char_a_ring_nfd . "aBc", "b", TRUE, $char_a_ring_nfd . "a" ),
525        array( "ab" . $char_a_ring_nfd . "c", "C", TRUE, "ab" . $char_a_ring_nfd ),
526        array( "aba" . $char_A_ring_nfd . "bc", "ba" . $char_a_ring_nfd . "b", TRUE, "a" ),
527        array( "ababc" . $char_a_ring_nfd, "aBc" . $char_A_ring_nfd, TRUE, "ab" ),
528        array( "abAB" . $char_A_ring_nfd . "c", "ab" . $char_a_ring_nfd . "c", FALSE, "AB" . $char_A_ring_nfd . "c" ),
529
530    );
531
532    foreach( $tests as $test ) {
533        $arg1 = urlencode($test[1]);
534        $arg0 = urlencode($test[0]);
535        $res_str .= "find \"$arg1\" in \"$arg0\" - grapheme_stristr";
536        if ( 3 == count( $test ) ) {
537            $result = grapheme_stristr($test[0], $test[1]);
538        }
539        else {
540            $res_str .= " before flag is " . ( $test[2] ? "TRUE" : "FALSE" );
541            $result = grapheme_stristr($test[0], $test[1], $test[2]);
542        }
543        $res_str .= " = ";
544        if ( $result === false ) {
545            $res_str .= 'false';
546        }
547        else {
548            $res_str .= urlencode($result);
549        }
550        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
551    }
552
553
554    //=====================================================================================
555    $res_str .= "\n" . 'function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_COUNT, $start = 0[, $next])' . "\n\n";
556
557    $tests = array(
558        // haystack, count, [[offset], [next]], result
559        array( "abc", 3, "abc" ),
560        array( "abc", 2, "ab" ),
561        array( "abc", 1, "a" ),
562        array( "abc", 0, "" ),
563        array( "abc", 1, 0, "a" ),
564        array( "abc", 1, 1, "b" ),
565        array( "abc", 1, 2, "c" ),
566        array( "abc", 0, 2, "" ),
567
568        array( "abc", 3, 0, 3, "abc" ),
569        array( "abc", 2, 0, 2, "ab" ),
570        array( "abc", 1, 0, 1, "a" ),
571        array( "abc", 0, 0, 0, "" ),
572        array( "abc", 1, 0, 1, "a" ),
573        array( "abc", 1, 1, 2, "b" ),
574        array( "abc", 1, 2, 3, "c" ),
575        array( "abc", 1, -2, 2, "b" ),
576        array( "abc", 0, 2, 2, "" ),
577        array( "http://news.bbc.co.uk/2/hi/middle_east/7831588.stm", 48, 48 , 50 , "tm" ),
578
579        array( $char_a_ring_nfd . "bc", 3, $char_a_ring_nfd . "bc" ),
580        array( $char_a_ring_nfd . "bc", 2, $char_a_ring_nfd . "b" ),
581        array( $char_a_ring_nfd . "bc", 1, $char_a_ring_nfd . "" ),
582        array( $char_a_ring_nfd . "bc", 3, 0, 5, $char_a_ring_nfd . "bc" ),
583        array( $char_a_ring_nfd . "bc", 2, 0, 4, $char_a_ring_nfd . "b" ),
584        array( $char_a_ring_nfd . "bc", 1, 0, 3, $char_a_ring_nfd . "" ),
585        array( $char_a_ring_nfd . "bcde", 2, 3, 5, "bc" ),
586        array( $char_a_ring_nfd . "bcde", 2, -4, 5, "bc" ),
587        array( $char_a_ring_nfd . "bcde", 2, 4, 6, "cd" ),
588        array( $char_a_ring_nfd . "bcde", 2, -7, 4, $char_a_ring_nfd . "b" ),
589        array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, 5, 11, "de" . $char_a_ring_nfd . "f" ),
590        array( $char_a_ring_nfd . "bcde" . $char_a_ring_nfd . "f", 4, -6, 11, "de" . $char_a_ring_nfd . "f" ),
591
592        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 ),
593        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, $char_a_ring_nfd . $char_o_diaeresis_nfd ),
594        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 1, $char_a_ring_nfd . "" ),
595
596        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 0, $char_o_diaeresis_nfd),
597        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 2, $char_o_diaeresis_nfd),
598        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 3, $char_o_diaeresis_nfd),
599        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 1, 4, $char_diaeresis),
600
601        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),
602        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),
603        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),
604        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),
605        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),
606        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 8, $char_o_diaeresis_nfd),
607        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 10, $char_diaeresis),
608        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 11, "false"),
609
610    );
611
612    $next = -1;
613    foreach( $tests as $test ) {
614        $arg0 = urlencode($test[0]);
615        $res_str .= "extract from \"$arg0\" \"$test[1]\" graphemes - grapheme_extract";
616        if ( 3 == count( $test ) ) {
617            $result = grapheme_extract($test[0], $test[1]);
618        }
619        elseif ( 4 == count ( $test ) ) {
620            $res_str .= " starting at byte position $test[2]";
621            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_COUNT, $test[2]);
622        }
623        else {
624            $res_str .= " starting at byte position $test[2] with \$next";
625            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_COUNT, $test[2], $next);
626        }
627        $res_str .= " = ";
628        if ( $result === false ) {
629            $res_str .= 'false';
630        }
631        else {
632            $res_str .= urlencode($result);
633        }
634        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]);
635        if ( 5 == count ( $test ) ) {
636            $res_str .= " \$next=$next == $test[3] ";
637            if ( $next != $test[3] ) {
638                $res_str .= "***FAILED***";
639            }
640        }
641        $res_str .= "\n";
642    }
643
644
645    //=====================================================================================
646    $res_str .= "\n" . 'function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXBYTES, $start = 0)' . "\n\n";
647
648    $tests = array(
649        array( "abc", 3, "abc" ),
650        array( "abc", 2, "ab" ),
651        array( "abc", 1, "a" ),
652        array( "abc", 0, "" ),
653        array( $char_a_ring_nfd . "bc", 5, $char_a_ring_nfd . "bc" ),
654        array( $char_a_ring_nfd . "bc", 4, $char_a_ring_nfd . "b" ),
655        array( $char_a_ring_nfd . "bc", 1, "" ),
656        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 ),
657        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 ),
658        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 ),
659        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 6, $char_a_ring_nfd . $char_o_diaeresis_nfd ),
660        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 3, $char_a_ring_nfd . "" ),
661        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 4, $char_a_ring_nfd . "" ),
662        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 5, $char_a_ring_nfd . "" ),
663        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 6, $char_a_ring_nfd . $char_o_diaeresis_nfd  ),
664        array( $char_a_ring_nfd . $char_o_diaeresis_nfd . "c", 7, $char_a_ring_nfd . $char_o_diaeresis_nfd . "c" ),
665
666        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 0, $char_o_diaeresis_nfd),
667        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 2, $char_o_diaeresis_nfd),
668        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 3, $char_o_diaeresis_nfd),
669        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 4, $char_diaeresis),
670
671        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),
672        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),
673        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),
674        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),
675        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),
676        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 3, 8, $char_o_diaeresis_nfd),
677        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 10, $char_diaeresis),
678        array( $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd . $char_o_diaeresis_nfd, 2, 11, "false"),
679
680    );
681
682    foreach( $tests as $test ) {
683        $arg0 = urlencode($test[0]);
684        $res_str .= "extract from \"$arg0\" \"$test[1]\" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES";
685        if ( 3 == count( $test ) ) {
686            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXBYTES);
687        }
688        else {
689            $res_str .= " starting at byte position $test[2]";
690            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXBYTES, $test[2]);
691        }
692        $res_str .= " = ";
693        if ( $result === false ) {
694            $res_str .= 'false';
695        }
696        else {
697            $res_str .= urlencode($result);
698        }
699        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
700    }
701
702
703    //=====================================================================================
704    $res_str .= "\n" . 'function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXCHARS, $start = 0)' . "\n\n";
705
706    $tests = array(
707        array( "abc", 3, "abc" ),
708        array( "abc", 2, "ab" ),
709        array( "abc", 1, "a" ),
710        array( "abc", 0, "" ),
711        array( "abc" . $char_o_diaeresis_nfd, 0, "" ),
712        array( "abc" . $char_o_diaeresis_nfd, 1, "a" ),
713        array( "abc" . $char_o_diaeresis_nfd, 2, "ab" ),
714        array( "abc" . $char_o_diaeresis_nfd, 3, "abc" ),
715        array( "abc" . $char_o_diaeresis_nfd, 4, "abc" ),
716        array( "abc" . $char_o_diaeresis_nfd, 5, "abc" . $char_o_diaeresis_nfd),
717        array( "abc" . $char_o_diaeresis_nfd, 6, "abc" . $char_o_diaeresis_nfd),
718        array( $char_o_diaeresis_nfd . "abc", 0, "" ),
719        array( $char_o_diaeresis_nfd . "abc", 1, "" ),
720        array( $char_o_diaeresis_nfd . "abc", 2, $char_o_diaeresis_nfd ),
721        array( $char_o_diaeresis_nfd . "abc", 3, $char_o_diaeresis_nfd . "a" ),
722        array( $char_o_diaeresis_nfd . "abc", 4, $char_o_diaeresis_nfd . "ab" ),
723        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 5, $char_o_diaeresis_nfd . "abc" ),
724        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 6, $char_o_diaeresis_nfd . "abc" ),
725        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 7, $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd ),
726        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "x" ),
727
728        array( "abc", 3, 0, "abc" ),
729        array( "abc", 2, 1, "bc" ),
730        array( "abc", 1, 2, "c" ),
731        array( "abc", 0, 3, "false" ),
732        array( "abc", 1, 3, "false" ),
733        array( "abc", 1, 999, "false" ),
734        array( $char_o_diaeresis_nfd . "abc", 1, 6, "false" ),
735        array( $char_o_diaeresis_nfd . "abc", 1, 999, "false" ),
736        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 0, $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "x" ),
737        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 1, $char_diaeresis . "abc" . $char_a_ring_nfd . "xy" ),
738        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 2, "abc" . $char_a_ring_nfd . "xyz" ),
739        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 3, "abc" . $char_a_ring_nfd . "xyz" ),
740        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 4, "bc" . $char_a_ring_nfd . "xyz" ),
741        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 5, "c" . $char_a_ring_nfd . "xyz" ),
742        array( $char_o_diaeresis_nfd . "abc" . $char_a_ring_nfd . "xyz", 8, 6, $char_a_ring_nfd . "xyz" ),
743
744    );
745
746    foreach( $tests as $test ) {
747        $arg0 = urlencode($test[0]);
748        $res_str .= "extract from \"$arg0\" \"$test[1]\" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS";
749        if ( 3 == count( $test ) ) {
750            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXCHARS);
751        }
752        else {
753            $res_str .= " starting at byte position $test[2]";
754            $result = grapheme_extract($test[0], $test[1], GRAPHEME_EXTR_MAXCHARS, $test[2]);
755        }
756        $res_str .= " = ";
757        if ( $result === false ) {
758            $res_str .= 'false';
759        }
760        else {
761            $res_str .= urlencode($result);
762        }
763        $res_str .= " == " . urlencode($test[count($test)-1]) . check_result($result, $test[count($test)-1]) . "\n";
764    }
765
766
767    //=====================================================================================
768
769    return $res_str;
770}
771
772echo ut_main();
773
774function check_result($result, $expected) {
775
776    if ( $result === false ) {
777            $result = 'false';
778    }
779
780    if ( strcmp($result, $expected) != 0 ) {
781        return " **FAILED** ";
782    }
783
784    return "";
785}
786
787?>
788--EXPECT--
789function grapheme_strlen($string) {}
790
791"hindi" in devanagari strlen 2
792"ab" + "hindi" + "cde" strlen 7
793"" strlen 0
794char_a_ring_nfd strlen 1
795char_a_ring_nfd + "bc" strlen 3
796"abc" strlen 3
797
798function grapheme_strpos($haystack, $needle, $offset = 0) {}
799
800find "o" in "aa%CC%8Abco%CC%88o" - grapheme_strpos = 5 == 5
801find "o" in "aa%CC%8Abco%CC%88" - grapheme_strpos = false == false
802find "o%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_strpos = 4 == 4
803find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strpos = 2 == 2
804find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strpos = 1 == 1
805find "a%CC%8A" in "abc" - grapheme_strpos = false == false
806find "a" in "a%CC%8Abc" - grapheme_strpos = false == false
807find "d" in "abc" - grapheme_strpos = false == false
808find "c" in "abc" - grapheme_strpos = 2 == 2
809find "b" in "abc" - grapheme_strpos = 1 == 1
810find "a" in "abc" - grapheme_strpos = 0 == 0
811find "a" in "abc" - grapheme_strpos from 0 = 0 == 0
812find "a" in "abc" - grapheme_strpos from 1 = false == false
813find "a" in "abc" - grapheme_strpos from -1 = false == false
814find "a" in "ababc" - grapheme_strpos from 1 = 2 == 2
815find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from 2 = 6 == 6
816find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -1 = 6 == 6
817find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strpos from -5 = 6 == 6
818find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from 2 = 3 == 3
819find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strpos from -4 = 3 == 3
820find "op" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5
821find "opq" in "aa%CC%8Abco%CC%88opq" - grapheme_strpos = 5 == 5
822find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strpos = false == false
823find "o%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bco%CC%88" - grapheme_strpos = 4 == 4
824find "a%CC%8Abc" in "o%CC%88aa%CC%8Abc" - grapheme_strpos = 2 == 2
825find "a%CC%8Abc" in "aa%CC%8Abc" - grapheme_strpos = 1 == 1
826find "a%CC%8Abc" in "abc" - grapheme_strpos = false == false
827find "abcdefg" in "a%CC%8Abc" - grapheme_strpos = false == false
828find "defghijklmnopq" in "abc" - grapheme_strpos = false == false
829find "ab" in "abc" - grapheme_strpos = 0 == 0
830find "bc" in "abc" - grapheme_strpos = 1 == 1
831find "abc" in "abc" - grapheme_strpos = 0 == 0
832find "abcd" in "abc" - grapheme_strpos = false == false
833find "ab" in "abc" - grapheme_strpos from 0 = 0 == 0
834find "abc" in "abc" - grapheme_strpos from 0 = 0 == 0
835find "abc" in "abc" - grapheme_strpos from 1 = false == false
836find "ab" in "ababc" - grapheme_strpos from 1 = 2 == 2
837find "abc" in "ababc" - grapheme_strpos from 1 = 2 == 2
838find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from 2 = 6 == 6
839find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strpos from -8 = 6 == 6
840find "a%CC%8Abca%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abca%CC%8Adef" - grapheme_strpos from 2 = 3 == 3
841
842function grapheme_stripos($haystack, $needle, $offset = 0) {}
843
844find "o" in "aoa%CC%8Abco%CC%88O" - grapheme_stripos from 2 = 6 == 6
845find "o" in "aoa%CC%8Abco%CC%88Oo" - grapheme_stripos from -6 = 6 == 6
846find "a%CC%8A" in "o%CC%88a%CC%8AaA%CC%8Abc" - grapheme_stripos from 2 = 3 == 3
847find "o" in "aa%CC%8Abco%CC%88O" - grapheme_stripos = 5 == 5
848find "O" in "aa%CC%8Abco%CC%88" - grapheme_stripos = false == false
849find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos = 4 == 4
850find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_stripos from -1 = 4 == 4
851find "A%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_stripos = 2 == 2
852find "a%CC%8A" in "aA%CC%8Abc" - grapheme_stripos = 1 == 1
853find "a%CC%8A" in "Abc" - grapheme_stripos = false == false
854find "A" in "a%CC%8Abc" - grapheme_stripos = false == false
855find "D" in "abc" - grapheme_stripos = false == false
856find "c" in "abC" - grapheme_stripos = 2 == 2
857find "B" in "abc" - grapheme_stripos = 1 == 1
858find "a" in "Abc" - grapheme_stripos = 0 == 0
859find "A" in "abc" - grapheme_stripos from 0 = 0 == 0
860find "a" in "Abc" - grapheme_stripos from 1 = false == false
861find "A" in "ababc" - grapheme_stripos from 1 = 2 == 2
862find "oP" in "aa%CC%8Abco%CC%88Opq" - grapheme_stripos = 5 == 5
863find "opQ" in "aa%CC%8Abco%CC%88Opq" - grapheme_stripos = 5 == 5
864find "abc" in "aa%CC%8Abco%CC%88" - grapheme_stripos = false == false
865find "O%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bCo%CC%88" - grapheme_stripos = 4 == 4
866find "A%CC%8Abc" in "o%CC%88aa%CC%8ABc" - grapheme_stripos = 2 == 2
867find "a%CC%8Abc" in "aa%CC%8ABC" - grapheme_stripos = 1 == 1
868find "a%CC%8ABC" in "abc" - grapheme_stripos = false == false
869find "aBCdefg" in "a%CC%8ABC" - grapheme_stripos = false == false
870find "Defghijklmnopq" in "aBC" - grapheme_stripos = false == false
871find "Ab" in "abC" - grapheme_stripos = 0 == 0
872find "bc" in "aBC" - grapheme_stripos = 1 == 1
873find "Abc" in "abC" - grapheme_stripos = 0 == 0
874find "aBcd" in "abC" - grapheme_stripos = false == false
875find "ab" in "ABc" - grapheme_stripos from 0 = 0 == 0
876find "abC" in "aBc" - grapheme_stripos from 0 = 0 == 0
877find "aBc" in "abc" - grapheme_stripos from 1 = false == false
878find "AB" in "ABabc" - grapheme_stripos from 1 = 2 == 2
879find "AB" in "ABabc" - grapheme_stripos from -4 = 2 == 2
880find "aBc" in "abaBc" - grapheme_stripos from 1 = 2 == 2
881find "Oa%CC%8AbC" in "aoa%CC%8Abco%CC%88oA%CC%8AbC" - grapheme_stripos from 2 = 6 == 6
882find "a%CC%8ABca%CC%8A" in "o%CC%88a%CC%8AaA%CC%8AbCa%CC%8Adef" - grapheme_stripos from 2 = 3 == 3
883
884function grapheme_strrpos($haystack, $needle, $offset = 0) {}
885
886find "o" in "aa%CC%8Abco%CC%88o" - grapheme_strrpos = 5 == 5
887find "o" in "aa%CC%8Abco%CC%88" - grapheme_strrpos = false == false
888find "o%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_strrpos = 4 == 4
889find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strrpos = 2 == 2
890find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strrpos = 1 == 1
891find "a%CC%8A" in "abc" - grapheme_strrpos = false == false
892find "a" in "a%CC%8Abc" - grapheme_strrpos = false == false
893find "d" in "abc" - grapheme_strrpos = false == false
894find "c" in "abc" - grapheme_strrpos = 2 == 2
895find "b" in "abc" - grapheme_strrpos = 1 == 1
896find "a" in "abc" - grapheme_strrpos = 0 == 0
897find "a" in "abc" - grapheme_strrpos from 0 = 0 == 0
898find "a" in "abc" - grapheme_strrpos from 1 = false == false
899find "a" in "ababc" - grapheme_strrpos from 1 = 2 == 2
900find "o" in "aoa%CC%8Abco%CC%88o" - grapheme_strrpos from 2 = 6 == 6
901find "a%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abc" - grapheme_strrpos from 2 = 3 == 3
902find "op" in "aa%CC%8Abco%CC%88opq" - grapheme_strrpos = 5 == 5
903find "opq" in "aa%CC%8Abco%CC%88opq" - grapheme_strrpos = 5 == 5
904find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strrpos = false == false
905find "o%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bco%CC%88" - grapheme_strrpos = 4 == 4
906find "a%CC%8Abc" in "o%CC%88aa%CC%8Abc" - grapheme_strrpos = 2 == 2
907find "a%CC%8Abc" in "aa%CC%8Abc" - grapheme_strrpos = 1 == 1
908find "a%CC%8Abc" in "abc" - grapheme_strrpos = false == false
909find "abcdefg" in "a%CC%8Abc" - grapheme_strrpos = false == false
910find "defghijklmnopq" in "abc" - grapheme_strrpos = false == false
911find "ab" in "abc" - grapheme_strrpos = 0 == 0
912find "bc" in "abc" - grapheme_strrpos = 1 == 1
913find "abc" in "abc" - grapheme_strrpos = 0 == 0
914find "abcd" in "abc" - grapheme_strrpos = false == false
915find "ab" in "abc" - grapheme_strrpos from 0 = 0 == 0
916find "abc" in "abc" - grapheme_strrpos from 0 = 0 == 0
917find "abc" in "abc" - grapheme_strrpos from 1 = false == false
918find "ab" in "ababc" - grapheme_strrpos from 1 = 2 == 2
919find "abc" in "ababc" - grapheme_strrpos from 1 = 2 == 2
920find "oa%CC%8Abc" in "aoa%CC%8Abco%CC%88oa%CC%8Abc" - grapheme_strrpos from 2 = 6 == 6
921find "a%CC%8Abca%CC%8A" in "o%CC%88a%CC%8Aaa%CC%8Abca%CC%8Adef" - grapheme_strrpos from 2 = 3 == 3
922
923function grapheme_strripos($haystack, $needle, $offset = 0) {}
924
925find "o" in "aoa%CC%8Abco%CC%88O" - grapheme_strripos from 2 = 6 == 6
926find "a%CC%8A" in "o%CC%88a%CC%8AaA%CC%8Abc" - grapheme_strripos from 2 = 3 == 3
927find "o" in "aa%CC%8Abco%CC%88O" - grapheme_strripos = 5 == 5
928find "O" in "aa%CC%8Abco%CC%88" - grapheme_strripos = false == false
929find "o%CC%88" in "aa%CC%8AbcO%CC%88" - grapheme_strripos = 4 == 4
930find "A%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strripos = 2 == 2
931find "a%CC%8A" in "aA%CC%8Abc" - grapheme_strripos = 1 == 1
932find "a%CC%8A" in "Abc" - grapheme_strripos = false == false
933find "A" in "a%CC%8Abc" - grapheme_strripos = false == false
934find "D" in "abc" - grapheme_strripos = false == false
935find "c" in "abC" - grapheme_strripos = 2 == 2
936find "B" in "abc" - grapheme_strripos = 1 == 1
937find "a" in "Abc" - grapheme_strripos = 0 == 0
938find "A" in "abc" - grapheme_strripos from 0 = 0 == 0
939find "a" in "Abc" - grapheme_strripos from 1 = false == false
940find "A" in "ababc" - grapheme_strripos from 1 = 2 == 2
941find "oP" in "aa%CC%8Abco%CC%88Opq" - grapheme_strripos = 5 == 5
942find "opQ" in "aa%CC%8Abco%CC%88Opq" - grapheme_strripos = 5 == 5
943find "abc" in "aa%CC%8Abco%CC%88" - grapheme_strripos = false == false
944find "O%CC%88bco%CC%88" in "aa%CC%8Abco%CC%88bCo%CC%88" - grapheme_strripos = 4 == 4
945find "A%CC%8Abc" in "o%CC%88aa%CC%8ABc" - grapheme_strripos = 2 == 2
946find "a%CC%8Abc" in "aa%CC%8ABC" - grapheme_strripos = 1 == 1
947find "a%CC%8ABC" in "abc" - grapheme_strripos = false == false
948find "aBCdefg" in "a%CC%8ABC" - grapheme_strripos = false == false
949find "Defghijklmnopq" in "aBC" - grapheme_strripos = false == false
950find "Ab" in "abC" - grapheme_strripos = 0 == 0
951find "bc" in "aBC" - grapheme_strripos = 1 == 1
952find "Abc" in "abC" - grapheme_strripos = 0 == 0
953find "aBcd" in "abC" - grapheme_strripos = false == false
954find "ab" in "ABc" - grapheme_strripos from 0 = 0 == 0
955find "abC" in "aBc" - grapheme_strripos from 0 = 0 == 0
956find "aBc" in "abc" - grapheme_strripos from 1 = false == false
957find "AB" in "ABabc" - grapheme_strripos from 1 = 2 == 2
958find "aBc" in "abaBc" - grapheme_strripos from 1 = 2 == 2
959find "Oa%CC%8AbC" in "aoa%CC%8Abco%CC%88oA%CC%8AbC" - grapheme_strripos from 2 = 6 == 6
960find "a%CC%8ABca%CC%8A" in "o%CC%88a%CC%8AaA%CC%8AbCa%CC%8Adef" - grapheme_strripos from 2 = 3 == 3
961
962function grapheme_substr($string, $start, $length = -1) {}
963
964substring of "abc" from "3" - grapheme_substr =  ==
965substring of "aa%CC%8Abco%CC%88" from "5" - grapheme_substr =  ==
966substring of "aoa%CC%8Abco%CC%88O" from "2" - grapheme_substr = a%CC%8Abco%CC%88O == a%CC%8Abco%CC%88O
967substring of "o%CC%88a%CC%8AaA%CC%8Abc" from "2" - grapheme_substr = aA%CC%8Abc == aA%CC%8Abc
968substring of "aa%CC%8Abco%CC%88O" from "5" - grapheme_substr = O == O
969substring of "aa%CC%8Abco%CC%88" from "5" - grapheme_substr =  ==
970substring of "aa%CC%8AbcO%CC%88" from "4" - grapheme_substr = O%CC%88 == O%CC%88
971substring of "o%CC%88aa%CC%8Abc" from "2" - grapheme_substr = a%CC%8Abc == a%CC%8Abc
972substring of "aA%CC%8Abc" from "1" - grapheme_substr = A%CC%8Abc == A%CC%8Abc
973substring of "Abc" from "-5" - grapheme_substr = Abc == Abc
974substring of "a%CC%8Abc" from "3" - grapheme_substr =  ==
975substring of "abc" from "4" - grapheme_substr =  ==
976substring of "abC" from "2" - grapheme_substr = C == C
977substring of "abc" from "1" - grapheme_substr = bc == bc
978substring of "Abc" from "1" - grapheme_substr with length 1 = b == b
979substring of "abc" from "0" - grapheme_substr with length 2 = ab == ab
980substring of "Abc" from "-4" - grapheme_substr with length 1 = A == A
981substring of "ababc" from "1" - grapheme_substr with length 2 = ba == ba
982substring of "ababc" from "0" - grapheme_substr with length 10 = ababc == ababc
983substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length 10 = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
984substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr = Opq == Opq
985substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -1 = Op == Op
986substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -2 = O == O
987substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -3 =  ==
988substring of "aa%CC%8Abco%CC%88Opq" from "5" - grapheme_substr with length -4 =  ==
989substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
990substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -1 = aa%CC%8Abco%CC%88Op == aa%CC%8Abco%CC%88Op
991substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -2 = aa%CC%8Abco%CC%88O == aa%CC%8Abco%CC%88O
992substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -3 = aa%CC%8Abco%CC%88 == aa%CC%8Abco%CC%88
993substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -4 = aa%CC%8Abc == aa%CC%8Abc
994substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -5 = aa%CC%8Ab == aa%CC%8Ab
995substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -6 = aa%CC%8A == aa%CC%8A
996substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -7 = a == a
997substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -8 =  ==
998substring of "aa%CC%8Abco%CC%88Opq" from "0" - grapheme_substr with length -9 =  ==
999substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1000substring of "aa%CC%8Abco%CC%88Opq" from "-7" - grapheme_substr = a%CC%8Abco%CC%88Opq == a%CC%8Abco%CC%88Opq
1001substring of "aa%CC%8Abco%CC%88Opq" from "-6" - grapheme_substr = bco%CC%88Opq == bco%CC%88Opq
1002substring of "aa%CC%8Abco%CC%88Opq" from "-5" - grapheme_substr = co%CC%88Opq == co%CC%88Opq
1003substring of "aa%CC%8Abco%CC%88Opq" from "-4" - grapheme_substr = o%CC%88Opq == o%CC%88Opq
1004substring of "aa%CC%8Abco%CC%88Opq" from "-3" - grapheme_substr = Opq == Opq
1005substring of "aa%CC%8Abco%CC%88Opq" from "-2" - grapheme_substr = pq == pq
1006substring of "aa%CC%8Abco%CC%88Opq" from "-1" - grapheme_substr = q == q
1007substring of "aa%CC%8Abco%CC%88Opq" from "-999" - grapheme_substr = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1008substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 8 = aa%CC%8Abco%CC%88Opq == aa%CC%8Abco%CC%88Opq
1009substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 7 = aa%CC%8Abco%CC%88Op == aa%CC%8Abco%CC%88Op
1010substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 6 = aa%CC%8Abco%CC%88O == aa%CC%8Abco%CC%88O
1011substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 5 = aa%CC%8Abco%CC%88 == aa%CC%8Abco%CC%88
1012substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 4 = aa%CC%8Abc == aa%CC%8Abc
1013substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 3 = aa%CC%8Ab == aa%CC%8Ab
1014substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 2 = aa%CC%8A == aa%CC%8A
1015substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 1 = a == a
1016substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length 0 =  ==
1017substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -999 =  ==
1018substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -1 = aa%CC%8Abco%CC%88Op == aa%CC%8Abco%CC%88Op
1019substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -2 = aa%CC%8Abco%CC%88O == aa%CC%8Abco%CC%88O
1020substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -3 = aa%CC%8Abco%CC%88 == aa%CC%8Abco%CC%88
1021substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -4 = aa%CC%8Abc == aa%CC%8Abc
1022substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -5 = aa%CC%8Ab == aa%CC%8Ab
1023substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -6 = aa%CC%8A == aa%CC%8A
1024substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -7 = a == a
1025substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -8 =  ==
1026substring of "aa%CC%8Abco%CC%88Opq" from "-8" - grapheme_substr with length -9 =  ==
1027
1028function grapheme_strstr($haystack, $needle, $before_needle = FALSE) {}
1029
1030find "o" in "aa%CC%8Abco%CC%88o" - grapheme_strstr = o == o
1031find "o" in "aa%CC%8Abco%CC%88" - grapheme_strstr = false == false
1032find "o%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_strstr = o%CC%88 == o%CC%88
1033find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_strstr = a%CC%8Abc == a%CC%8Abc
1034find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strstr = a%CC%8Abc == a%CC%8Abc
1035find "a%CC%8A" in "abc" - grapheme_strstr = false == false
1036find "a" in "a%CC%8Abc" - grapheme_strstr = false == false
1037find "d" in "abc" - grapheme_strstr = false == false
1038find "c" in "abc" - grapheme_strstr = c == c
1039find "b" in "abc" - grapheme_strstr = bc == bc
1040find "a" in "abc" - grapheme_strstr = abc == abc
1041find "ab" in "abc" - grapheme_strstr = abc == abc
1042find "abc" in "abc" - grapheme_strstr = abc == abc
1043find "bc" in "abc" - grapheme_strstr = bc == bc
1044find "a" in "abc" - grapheme_strstr before flag is FALSE = abc == abc
1045find "a" in "abc" - grapheme_strstr before flag is TRUE =  ==
1046find "b" in "abc" - grapheme_strstr before flag is TRUE = a == a
1047find "c" in "abc" - grapheme_strstr before flag is TRUE = ab == ab
1048find "bab" in "ababc" - grapheme_strstr before flag is TRUE = a == a
1049find "abc" in "ababc" - grapheme_strstr before flag is TRUE = ab == ab
1050find "abc" in "ababc" - grapheme_strstr before flag is FALSE = abc == abc
1051find "d" in "aba%CC%8Ac" - grapheme_strstr = false == false
1052find "a" in "bca%CC%8Aa" - grapheme_strstr = a == a
1053find "b" in "aa%CC%8Abc" - grapheme_strstr = bc == bc
1054find "a" in "a%CC%8Abc" - grapheme_strstr = false == false
1055find "ab" in "a%CC%8Aabc" - grapheme_strstr = abc == abc
1056find "abc" in "abca%CC%8A" - grapheme_strstr = abca%CC%8A == abca%CC%8A
1057find "a%CC%8Abc" in "aa%CC%8Abc" - grapheme_strstr = a%CC%8Abc == a%CC%8Abc
1058find "a%CC%8A" in "aa%CC%8Abc" - grapheme_strstr before flag is FALSE = a%CC%8Abc == a%CC%8Abc
1059find "a" in "aa%CC%8Abc" - grapheme_strstr before flag is TRUE =  ==
1060find "b" in "a%CC%8Aabc" - grapheme_strstr before flag is TRUE = a%CC%8Aa == a%CC%8Aa
1061find "c" in "aba%CC%8Ac" - grapheme_strstr before flag is TRUE = aba%CC%8A == aba%CC%8A
1062find "baa%CC%8Ab" in "abaa%CC%8Abc" - grapheme_strstr before flag is TRUE = a == a
1063find "abca%CC%8A" in "ababca%CC%8A" - grapheme_strstr before flag is TRUE = ab == ab
1064find "aba%CC%8Ac" in "ababa%CC%8Ac" - grapheme_strstr before flag is FALSE = aba%CC%8Ac == aba%CC%8Ac
1065
1066function grapheme_stristr($haystack, $needle, $before_needle = FALSE) {}
1067
1068find "O%CC%88" in "aa%CC%8Abco%CC%88" - grapheme_stristr = o%CC%88 == o%CC%88
1069find "o" in "aa%CC%8Abco%CC%88O" - grapheme_stristr = O == O
1070find "o" in "aa%CC%8Abco%CC%88" - grapheme_stristr = false == false
1071find "a%CC%8A" in "o%CC%88aa%CC%8Abc" - grapheme_stristr = a%CC%8Abc == a%CC%8Abc
1072find "A%CC%8A" in "aa%CC%8Abc" - grapheme_stristr = a%CC%8Abc == a%CC%8Abc
1073find "a%CC%8A" in "abc" - grapheme_stristr = false == false
1074find "A" in "a%CC%8Abc" - grapheme_stristr = false == false
1075find "d" in "abc" - grapheme_stristr = false == false
1076find "C" in "abc" - grapheme_stristr = c == c
1077find "b" in "aBc" - grapheme_stristr = Bc == Bc
1078find "A" in "abc" - grapheme_stristr = abc == abc
1079find "ab" in "abC" - grapheme_stristr = abC == abC
1080find "aBc" in "abc" - grapheme_stristr = abc == abc
1081find "bc" in "abC" - grapheme_stristr = bC == bC
1082find "A" in "abc" - grapheme_stristr before flag is FALSE = abc == abc
1083find "a" in "abc" - grapheme_stristr before flag is TRUE =  ==
1084find "b" in "aBc" - grapheme_stristr before flag is TRUE = a == a
1085find "C" in "abc" - grapheme_stristr before flag is TRUE = ab == ab
1086find "bab" in "aBabc" - grapheme_stristr before flag is TRUE = a == a
1087find "aBc" in "ababc" - grapheme_stristr before flag is TRUE = ab == ab
1088find "abC" in "ababc" - grapheme_stristr before flag is FALSE = abc == abc
1089find "d" in "aba%CC%8Ac" - grapheme_stristr = false == false
1090find "a" in "bca%CC%8AA" - grapheme_stristr = A == A
1091find "B" in "aa%CC%8Abc" - grapheme_stristr = bc == bc
1092find "a" in "A%CC%8Abc" - grapheme_stristr = false == false
1093find "Ab" in "a%CC%8Aabc" - grapheme_stristr = abc == abc
1094find "abc" in "abcA%CC%8A" - grapheme_stristr = abcA%CC%8A == abcA%CC%8A
1095find "A%CC%8Abc" in "aa%CC%8Abc" - grapheme_stristr = a%CC%8Abc == a%CC%8Abc
1096find "a%CC%8A" in "aA%CC%8Abc" - grapheme_stristr before flag is FALSE = A%CC%8Abc == A%CC%8Abc
1097find "A" in "aa%CC%8Abc" - grapheme_stristr before flag is TRUE =  ==
1098find "b" in "a%CC%8AaBc" - grapheme_stristr before flag is TRUE = a%CC%8Aa == a%CC%8Aa
1099find "C" in "aba%CC%8Ac" - grapheme_stristr before flag is TRUE = aba%CC%8A == aba%CC%8A
1100find "baa%CC%8Ab" in "abaA%CC%8Abc" - grapheme_stristr before flag is TRUE = a == a
1101find "aBcA%CC%8A" in "ababca%CC%8A" - grapheme_stristr before flag is TRUE = ab == ab
1102find "aba%CC%8Ac" in "abABA%CC%8Ac" - grapheme_stristr before flag is FALSE = ABA%CC%8Ac == ABA%CC%8Ac
1103
1104function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_COUNT, $start = 0[, $next])
1105
1106extract from "abc" "3" graphemes - grapheme_extract = abc == abc
1107extract from "abc" "2" graphemes - grapheme_extract = ab == ab
1108extract from "abc" "1" graphemes - grapheme_extract = a == a
1109extract from "abc" "0" graphemes - grapheme_extract =  ==
1110extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 = a == a
1111extract from "abc" "1" graphemes - grapheme_extract starting at byte position 1 = b == b
1112extract from "abc" "1" graphemes - grapheme_extract starting at byte position 2 = c == c
1113extract from "abc" "0" graphemes - grapheme_extract starting at byte position 2 =  ==
1114extract from "abc" "3" graphemes - grapheme_extract starting at byte position 0 with $next = abc == abc $next=3 == 3
1115extract from "abc" "2" graphemes - grapheme_extract starting at byte position 0 with $next = ab == ab $next=2 == 2
1116extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a == a $next=1 == 1
1117extract from "abc" "0" graphemes - grapheme_extract starting at byte position 0 with $next =  ==  $next=0 == 0
1118extract from "abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a == a $next=1 == 1
1119extract from "abc" "1" graphemes - grapheme_extract starting at byte position 1 with $next = b == b $next=2 == 2
1120extract from "abc" "1" graphemes - grapheme_extract starting at byte position 2 with $next = c == c $next=3 == 3
1121extract from "abc" "1" graphemes - grapheme_extract starting at byte position -2 with $next = b == b $next=2 == 2
1122extract from "abc" "0" graphemes - grapheme_extract starting at byte position 2 with $next =  ==  $next=2 == 2
1123extract 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
1124extract from "a%CC%8Abc" "3" graphemes - grapheme_extract = a%CC%8Abc == a%CC%8Abc
1125extract from "a%CC%8Abc" "2" graphemes - grapheme_extract = a%CC%8Ab == a%CC%8Ab
1126extract from "a%CC%8Abc" "1" graphemes - grapheme_extract = a%CC%8A == a%CC%8A
1127extract from "a%CC%8Abc" "3" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8Abc == a%CC%8Abc $next=5 == 5
1128extract from "a%CC%8Abc" "2" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4
1129extract from "a%CC%8Abc" "1" graphemes - grapheme_extract starting at byte position 0 with $next = a%CC%8A == a%CC%8A $next=3 == 3
1130extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 3 with $next = bc == bc $next=5 == 5
1131extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -4 with $next = bc == bc $next=5 == 5
1132extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position 4 with $next = cd == cd $next=6 == 6
1133extract from "a%CC%8Abcde" "2" graphemes - grapheme_extract starting at byte position -7 with $next = a%CC%8Ab == a%CC%8Ab $next=4 == 4
1134extract 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
1135extract 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
1136extract 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
1137extract from "a%CC%8Ao%CC%88o%CC%88" "2" graphemes - grapheme_extract = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88
1138extract from "a%CC%8Ao%CC%88c" "1" graphemes - grapheme_extract = a%CC%8A == a%CC%8A
1139extract 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
1140extract 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
1141extract 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
1142extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "1" graphemes - grapheme_extract starting at byte position 4 = %CC%88 == %CC%88
1143extract 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
1144extract 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
1145extract 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
1146extract 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
1147extract 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
1148extract 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
1149extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 10 = %CC%88 == %CC%88
1150extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract starting at byte position 11 = false == false
1151
1152function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXBYTES, $start = 0)
1153
1154extract from "abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = abc == abc
1155extract from "abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = ab == ab
1156extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a == a
1157extract from "abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES =  ==
1158extract from "a%CC%8Abc" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Abc == a%CC%8Abc
1159extract from "a%CC%8Abc" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ab == a%CC%8Ab
1160extract from "a%CC%8Abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES =  ==
1161extract 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
1162extract 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
1163extract 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
1164extract 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
1165extract from "a%CC%8Ao%CC%88c" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8A == a%CC%8A
1166extract from "a%CC%8Ao%CC%88c" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8A == a%CC%8A
1167extract from "a%CC%8Ao%CC%88c" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8A == a%CC%8A
1168extract from "a%CC%8Ao%CC%88c" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88 == a%CC%8Ao%CC%88
1169extract from "a%CC%8Ao%CC%88c" "7" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES = a%CC%8Ao%CC%88c == a%CC%8Ao%CC%88c
1170extract 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
1171extract 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
1172extract 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
1173extract 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
1174extract 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
1175extract 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
1176extract 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
1177extract 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
1178extract 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
1179extract 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
1180extract 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
1181extract from "o%CC%88o%CC%88o%CC%88o%CC%88" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXBYTES starting at byte position 11 = false == false
1182
1183function grapheme_extract($haystack, $size, $extract_type = GRAPHEME_EXTR_MAXCHARS, $start = 0)
1184
1185extract from "abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abc == abc
1186extract from "abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = ab == ab
1187extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = a == a
1188extract from "abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1189extract from "abco%CC%88" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1190extract from "abco%CC%88" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = a == a
1191extract from "abco%CC%88" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = ab == ab
1192extract from "abco%CC%88" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abc == abc
1193extract from "abco%CC%88" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abc == abc
1194extract from "abco%CC%88" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abco%CC%88 == abco%CC%88
1195extract from "abco%CC%88" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = abco%CC%88 == abco%CC%88
1196extract from "o%CC%88abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1197extract from "o%CC%88abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS =  ==
1198extract from "o%CC%88abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88 == o%CC%88
1199extract from "o%CC%88abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88a == o%CC%88a
1200extract from "o%CC%88abc" "4" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88ab == o%CC%88ab
1201extract from "o%CC%88abca%CC%8Axyz" "5" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abc == o%CC%88abc
1202extract from "o%CC%88abca%CC%8Axyz" "6" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abc == o%CC%88abc
1203extract from "o%CC%88abca%CC%8Axyz" "7" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abca%CC%8A == o%CC%88abca%CC%8A
1204extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS = o%CC%88abca%CC%8Ax == o%CC%88abca%CC%8Ax
1205extract from "abc" "3" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 0 = abc == abc
1206extract from "abc" "2" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 1 = bc == bc
1207extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 2 = c == c
1208extract from "abc" "0" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 3 = false == false
1209extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 3 = false == false
1210extract from "abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 999 = false == false
1211extract from "o%CC%88abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 6 = false == false
1212extract from "o%CC%88abc" "1" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 999 = false == false
1213extract 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
1214extract 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
1215extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 2 = abca%CC%8Axyz == abca%CC%8Axyz
1216extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 3 = abca%CC%8Axyz == abca%CC%8Axyz
1217extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 4 = bca%CC%8Axyz == bca%CC%8Axyz
1218extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 5 = ca%CC%8Axyz == ca%CC%8Axyz
1219extract from "o%CC%88abca%CC%8Axyz" "8" graphemes - grapheme_extract GRAPHEME_EXTR_MAXCHARS starting at byte position 6 = a%CC%8Axyz == a%CC%8Axyz
1220