<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package fusionLib
 * @copyright Copyright (c) 2006 - 2013 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flUtf8 Class
 *
 * Class to supply PHP capability specific functions for UTF-8 support.
 *
 * @package fusionLib
 */
abstract class flUtf8 extends _flUtf8Base {

	/**
	 * Convert string to uppercase.
	 *
	 * @param string $str The string to convert.
	 * @return string The uppercased string.
	 */
	static function toUpper($str) {
		return strtoupper($str);
	}

	/**
	 * Convert string to lowercase.
	 *
	 * @param string $str The string to convert.
	 * @return string The lowercased string.
	 */
	static function toLower($str) {
		return strtolower($str);
	}

	/**
	 * Find the length of a UTF-8 encoded string.
	 *
	 * @param string $string The string to find the length of.
	 * @return int The length of the string in characters.
	 * @static
	 */
	static function strlen($string) {
		return strlen(utf8_decode($string));
	}

	/**
	 * Extract part of a UTF-8 string.
	 *
	 * @param string $string The string to extract characters from.
	 * @param int $start If non-negative the returned string will start at the start'th position in the
	 * string starting at zero. If negative the returned string will start at the start'th character from the end
	 * of the string.
	 * @param int $length If given and positive the string will contain at most length characters, if negative
	 * then that many characters will be omitted from the end of the string.
	 * @return string The extracted portion of the string.
	 * @static
	 */
	static function substr($string, $start, $length = null) {

		// Early out on trival cases
		if($length === 0 || ($start < 0 && $length < 0 && $length < $start))
			return '';

		// Fix -ve start
		if($start < 0) {
			$start = ($strlength = strlen(utf8_decode($string))) + $start;
			if($start < 0)
				$start = 0;
		}

		$startExp = '^'; // Expression for skipping the start chars
		$lenExp = ''; // Expression for grabbing the length chars

		// Create start offset expression
		if($start) {
			// Find number of chars and 65535 char chunks to skip (preg can only do 65535 chars at a time)
			$blocks = (int)($start / 65535);
			$chars = $start % 65535;

			$startExp = '^(?:' . ($blocks ? '(?:.{65535}){' . $blocks . '}' : '') . '.{' . $chars . '})';
		}

		// Create the length capture expression
		if(is_null($length))
			$lenExp = '(.*)$';	// Grab everything
		else {
			if(!isset($strlength))
				$strlength = strlen(utf8_decode($string));

			// If start after string length
			if($start > $strlength)
				return '';

			// If -ve length then make +ve
			if($length < 0 && ($length = ($strlength + $length) - $start) <= 0)
				return '';

			// Limit to max length of string
			$length = min($strlength - $start, $length);

			// Find number of chars and 65535 char chunks to grab (preg can only do 65535 chars at a time)
			$blocks = (int)($length / 65535);
			$chars = $length % 65535;

			$lenExp = '(' . ($blocks ? '(?:.{65535}){' . $blocks . '}' : '') . '.{' . $chars . '})';
		}

		// Extract with a reg expression
		$match = array();
		if(!preg_match('#' . $startExp . $lenExp . '#us', $string, $match))
			return '';
		else
			return $match[1];
	}
}
