/**
* Проверка данных на принадлежность классу символов ASCII
* Для значений null, integer, float, boolean возвращает TRUE.
*
* Массивы обходятся рекурсивно, если в хотябы одном элементе массива
* его значение не ASCII, возвращается FALSE.
*
* @param array|scalar|null $data
* @return bool
*/
public static function is_ascii($data)
{
if (! ReflectionTypehint::isValid()) return false;
if (is_array($data))
{
foreach ($data as $k => &$v)
{
if (! self::is_ascii($k) || ! self::is_ascii($v)) return false;
}
return true;
}
#if (is_string($data)) return preg_match('/^[\x00-\x7f]*$/sSX', $data);
if (is_string($data)) return ltrim($data, "\x00..\x7f") === ''; #small speed improve
if (is_scalar($data) || is_null($data)) return true; #~ null, integer, float, boolean
return false; #object or resource
}
/**
* Returns true if data is valid UTF-8 and false otherwise.
* Для значений null, integer, float, boolean возвращает TRUE.
*
* Массивы обходятся рекурсивно, если в хотябы одном элементе массива
* его значение не в кодировке UTF-8, возвращается FALSE.
*
* @link http://www.w3.org/International/questions/qa-forms-utf-8.html
* @link http://ru3.php.net/mb_detect_encoding
* @link http://webtest.philigon.ru/articles/utf8/
* @link http://unicode.coeurlumiere.com/
* @param array|scalar|null $data
* @param bool $is_strict строгая проверка диапазона ASCII?
* @return bool
*/
public static function is_utf8($data, $is_strict = true)
{
if (! ReflectionTypehint::isValid()) return false;
if (is_array($data))
{
foreach ($data as $k => &$v)
{
if (! self::is_utf8($k, $is_strict) || ! self::is_utf8($v, $is_strict)) return false;
}
return true;
}
if (is_string($data))
{
if ($data === '') return true; #speed improve
if ($is_strict && preg_match('/[^\x09\x0A\x0D\x20-\xBF\xC2-\xF7]/sSX', $data)) return false;
#the fastest variant:
if (function_exists('mb_check_encoding')) return mb_check_encoding($data, 'UTF-8');
if (function_exists('iconv')) return @iconv('UTF-8', 'UTF-16', $data) !== false; #TODO: check work with test
/*
Рег. выражения имеют внутренние ограничения на длину повторов шаблонов поиска *, +, {x,y}
равное 65536, поэтому используем preg_replace() вместо preg_match()
*/
$result = $is_strict ? preg_replace('/(?>' . self::$char_re . '
#| (.) # catch bad bytes
)+/sxSX', '', $data)
: #the current check allows only values in the range U+0 to U+10FFFF, excluding U+D800 to U+DFFF.
preg_replace('/\X+/suSX', '', $data); #\X is equivalent to \P{M}\p{M}*+
if (function_exists('preg_last_error'))
{
if (preg_last_error() === PREG_NO_ERROR) return $result === '';
if (preg_last_error() === PREG_BAD_UTF8_ERROR) return false;
}
elseif (is_string($result)) return $result === '';
#в этом месте произошла ошибка выполнения регулярного выражения
#проверяем ещё одним, самым медленным способом:
return self::check($data, $is_strict);
}
if (is_scalar($data) || is_null($data)) return true; #~ null, integer, float, boolean
return false; #object or resource
}