substr.php 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <?php
  2. /**
  3. * UTF8::substr
  4. *
  5. * @package KO7
  6. *
  7. * @copyright (c) 2007-2016 Kohana Team
  8. * @copyright (c) since 2016 Koseven Team
  9. * @copyright (c) 2005 Harry Fuecks
  10. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
  11. */
  12. function _substr($str, $offset, $length = NULL)
  13. {
  14. if (UTF8::is_ascii($str))
  15. return ($length === NULL) ? substr($str, $offset) : substr($str, $offset, $length);
  16. // Normalize params
  17. $str = (string) $str;
  18. $strlen = UTF8::strlen($str);
  19. $offset = (int) ($offset < 0) ? max(0, $strlen + $offset) : $offset; // Normalize to positive offset
  20. $length = ($length === NULL) ? NULL : (int) $length;
  21. // Impossible
  22. if ($length === 0 OR $offset >= $strlen OR ($length < 0 AND $length <= $offset - $strlen))
  23. return '';
  24. // Whole string
  25. if ($offset == 0 AND ($length === NULL OR $length >= $strlen))
  26. return $str;
  27. // Build regex
  28. $regex = '^';
  29. // Create an offset expression
  30. if ($offset > 0)
  31. {
  32. // PCRE repeating quantifiers must be less than 65536, so repeat when necessary
  33. $x = (int) ($offset / 65535);
  34. $y = (int) ($offset % 65535);
  35. $regex .= ($x == 0) ? '' : ('(?:.{65535}){'.$x.'}');
  36. $regex .= ($y == 0) ? '' : ('.{'.$y.'}');
  37. }
  38. // Create a length expression
  39. if ($length === NULL)
  40. {
  41. $regex .= '(.*)'; // No length set, grab it all
  42. }
  43. // Find length from the left (positive length)
  44. elseif ($length > 0)
  45. {
  46. // Reduce length so that it can't go beyond the end of the string
  47. $length = min($strlen - $offset, $length);
  48. $x = (int) ($length / 65535);
  49. $y = (int) ($length % 65535);
  50. $regex .= '(';
  51. $regex .= ($x == 0) ? '' : ('(?:.{65535}){'.$x.'}');
  52. $regex .= '.{'.$y.'})';
  53. }
  54. // Find length from the right (negative length)
  55. else
  56. {
  57. $x = (int) (-$length / 65535);
  58. $y = (int) (-$length % 65535);
  59. $regex .= '(.*)';
  60. $regex .= ($x == 0) ? '' : ('(?:.{65535}){'.$x.'}');
  61. $regex .= '.{'.$y.'}';
  62. }
  63. preg_match('/'.$regex.'/us', $str, $matches);
  64. return $matches[1];
  65. }