package com.googlecode.totallylazy; import com.googlecode.totallylazy.functions.CurriedMonoid; import com.googlecode.totallylazy.functions.ConcatCharSequence; import com.googlecode.totallylazy.numbers.Numbers; import com.googlecode.totallylazy.predicates.LogicalPredicate; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Set; import static com.googlecode.totallylazy.predicates.Predicates.not; import static com.googlecode.totallylazy.Sequences.forwardOnly; public class Characters { public static Charset UTF8 = Charset.forName("UTF-8"); public static Charset UTF16 = Charset.forName("UTF-16"); public static Charset ASCII = Charset.forName("ASCII"); public static final CurriedMonoid<CharSequence> join = ConcatCharSequence.instance; public static Sequence<Character> characters(final CharSequence value) { return Sequences.characters(value); } public static Sequence<Character> characters(final char[] value) { return Sequences.characters(value); } public static LogicalPredicate<Character> in(Charset charset) { final CharsetEncoder encoder = charset.newEncoder(); return new LogicalPredicate<Character>() { @Override public boolean matches(Character other) { return encoder.canEncode(other); } }; } public static LogicalPredicate<Character> in(final String characters) { return new LogicalPredicate<Character>() { @Override public boolean matches(Character other) { return characters.indexOf(other) != -1; } @Override public String toString() { return "[" + characters + "]"; } }; } public static LogicalPredicate<Character> among(String value) { return in(value); } public static LogicalPredicate<Character> notAmong(String value) { return not(in(value)); } public static LogicalPredicate<Character> identifierStart = new LogicalPredicate<Character>() { @Override public boolean matches(Character other) { return Character.isJavaIdentifierStart(other); } }; public static LogicalPredicate<Character> identifierPart = new LogicalPredicate<Character>() { @Override public boolean matches(Character other) { return Character.isJavaIdentifierPart(other); } }; public static LogicalPredicate<Character> letter = new LogicalPredicate<Character>() { public boolean matches(Character other) { return Character.isLetter(other); } }; public static LogicalPredicate<Character> digit = new LogicalPredicate<Character>() { public boolean matches(Character other) { return Character.isDigit(other); } }; public static LogicalPredicate<Character> whitespace = new LogicalPredicate<Character>() { public boolean matches(Character other) { return Character.isWhitespace(other); } }; public static LogicalPredicate<Character> between(final char start, final char end) { return new LogicalPredicate<Character>() { public boolean matches(Character other) { return other >= start && other <= end; } }; } public static LogicalPredicate<Character> alphaNumeric = between('A', 'Z').or(between('a', 'z')).or(between('0', '9')); public static LogicalPredicate<Character> hexDigit = between('A', 'F').or(between('a', 'f')).or(between('0', '9')); public static Sequence<Character> range(char start, char end) { return Numbers.range((int) start, (int) end).map(number -> (char) number.intValue()); } public static Set<Character> set(Charset charset) { return characters(charset).toSet(); } public static Sequence<Character> characters(Charset charset) { return characters().filter(in(charset)); } public static Sequence<Character> characters() { return range(Character.MIN_VALUE, Character.MAX_VALUE); } public static boolean equals(CharSequence a, CharSequence b) { return Iterators.equalsTo(a.chars().iterator(), b.chars().iterator()); } public static int hashCode(CharSequence value) { return forwardOnly(value.chars().iterator()).hashCode(); } }