substr.php 1.9 KB

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