Merge branch 'maint/7.0'
[ninja.git] / system / core / utf8 / substr.php
blobdaf66b815fe1937646a84cf3d6d9a7a3640075bb
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * utf8::substr
5 * @package Core
6 * @author Kohana Team
7 * @copyright (c) 2007 Kohana Team
8 * @copyright (c) 2005 Harry Fuecks
9 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
11 function _substr($str, $offset, $length = NULL)
13 if (SERVER_UTF8)
14 return ($length === NULL) ? mb_substr($str, $offset) : mb_substr($str, $offset, $length);
16 if (utf8::is_ascii($str))
17 return ($length === NULL) ? substr($str, $offset) : substr($str, $offset, $length);
19 // Normalize params
20 $str = (string) $str;
21 $strlen = utf8::strlen($str);
22 $offset = (int) ($offset < 0) ? max(0, $strlen + $offset) : $offset; // Normalize to positive offset
23 $length = ($length === NULL) ? NULL : (int) $length;
25 // Impossible
26 if ($length === 0 OR $offset >= $strlen OR ($length < 0 AND $length <= $offset - $strlen))
27 return '';
29 // Whole string
30 if ($offset == 0 AND ($length === NULL OR $length >= $strlen))
31 return $str;
33 // Build regex
34 $regex = '^';
36 // Create an offset expression
37 if ($offset > 0)
39 // PCRE repeating quantifiers must be less than 65536, so repeat when necessary
40 $x = (int) ($offset / 65535);
41 $y = (int) ($offset % 65535);
42 $regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}';
43 $regex .= ($y == 0) ? '' : '.{'.$y.'}';
46 // Create a length expression
47 if ($length === NULL)
49 $regex .= '(.*)'; // No length set, grab it all
51 // Find length from the left (positive length)
52 elseif ($length > 0)
54 // Reduce length so that it can't go beyond the end of the string
55 $length = min($strlen - $offset, $length);
57 $x = (int) ($length / 65535);
58 $y = (int) ($length % 65535);
59 $regex .= '(';
60 $regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}';
61 $regex .= '.{'.$y.'})';
63 // Find length from the right (negative length)
64 else
66 $x = (int) (-$length / 65535);
67 $y = (int) (-$length % 65535);
68 $regex .= '(.*)';
69 $regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}';
70 $regex .= '.{'.$y.'}';
73 preg_match('/'.$regex.'/us', $str, $matches);
74 return $matches[1];