package org.develnext.jphp.zend.ext.standard; import php.runtime.Memory; import php.runtime.annotation.Runtime; import php.runtime.ext.support.compile.FunctionsContainer; /** * ctype extension * documentation: http://us1.php.net/manual/ru/book.ctype.php * * Notice: supports UNICODE */ public class CTypeFunctions extends FunctionsContainer { private final static char CHAR_UNDEFINED = 0xFFFF; private static int tryGetChar(Memory value){ if (value.type == Memory.Type.INT){ int val = (int)value.toLong(); if (val > -128 && val <= Character.MAX_CODE_POINT){ if (val < 0) val += 256; return val; } } return -1; } private static boolean isPrintableChar( char c ) { Character.UnicodeBlock block = Character.UnicodeBlock.of( c ); return (!Character.isISOControl(c)) && c != CHAR_UNDEFINED && block != null && block != Character.UnicodeBlock.SPECIALS; } public static boolean ctype_apply(Memory value, Checker checker){ int c = tryGetChar(value); if (c > -1) return checker.check((char)c); String str = value.toString(); int len = str.length(); for(int i = 0; i < len; i++){ char ch = str.charAt(i); if (!checker.check(ch)) return false; } return true; } @Runtime.Immutable public static boolean ctype_alnum(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isLetter(ch) || Character.isDigit(ch); } }); } @Runtime.Immutable public static boolean ctype_alpha(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isLetter(ch); } }); } @Runtime.Immutable public static boolean ctype_cntrl(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isISOControl(ch); } }); } @Runtime.Immutable public static boolean ctype_digit(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isDigit(ch); } }); } @Runtime.Immutable public static boolean ctype_graph(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isSpaceChar(ch) || isPrintableChar(ch); } }); } @Runtime.Immutable public static boolean ctype_lower(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isLowerCase(ch); } }); } @Runtime.Immutable public static boolean ctype_print(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return isPrintableChar(ch); } }); } @Runtime.Immutable public static boolean ctype_punct(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return !Character.isDigit(ch) && !Character.isLetter(ch) && !Character.isSpaceChar(ch) && isPrintableChar(ch); } }); } @Runtime.Immutable public static boolean ctype_space(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isSpaceChar(ch); } }); } @Runtime.Immutable public static boolean ctype_upper(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isUpperCase(ch); } }); } @Runtime.Immutable public static boolean ctype_xdigit(Memory value){ return ctype_apply(value, new Checker() { @Override boolean check(char ch) { return Character.isDigit(ch) || ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')); } }); } abstract private static class Checker { abstract boolean check(char ch); } }