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