package nodebox.function;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import nodebox.util.StringUtils;
import java.util.List;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Random;
/**
* Library with functions for String manipulation.
*/
public class StringFunctions {
public static final FunctionLibrary LIBRARY;
static {
LIBRARY = JavaLibrary.ofClass("string", StringFunctions.class,
"string", "makeStrings", "length", "wordCount", "concatenate", "changeCase", "formatNumber",
"characters", "randomCharacter", "asBinaryString", "asBinaryList", "asNumberList", "countCharacters",
"characterAt", "contains", "endsWith", "equal", "replace", "startsWith", "subString", "trim" );
}
/**
* Return the input string, as-is.
* <p/>
* This function is used for using strings as variables in NodeBox.
*/
public static String string(String s) {
return s;
}
/**
* Make a list of strings from a big string with separators.
* Whitespace is not stripped.
*
* @param s The input string, e.g. "a;b;c"
* @param separator The separator, e.g. ";". If the separator is empty, return each character separately.
* @return A list of strings.
*/
public static List<String> makeStrings(String s, String separator) {
if (s == null) {
return ImmutableList.of();
}
if (separator == null || separator.isEmpty()) {
return ImmutableList.copyOf(Splitter.fixedLength(1).split(s));
}
return ImmutableList.copyOf(Splitter.on(separator).split(s));
}
public static int length(String s) {
if (s == null) return 0;
return s.length();
}
public static int wordCount(String s) {
if (s == null) return 0;
Iterable<String> split = Splitter.onPattern("\\w+").split(s);
return Iterables.size(split) - 1;
}
public static String concatenate(String s1, String s2, String s3, String s4) {
s1 = s1 != null ? s1 : "";
s2 = s2 != null ? s2 : "";
s3 = s3 != null ? s3 : "";
s4 = s4 != null ? s4 : "";
return s1 + s2 + s3 + s4;
}
public static String changeCase(String value, String caseMethod) {
caseMethod = caseMethod.toLowerCase();
if (caseMethod.equals("lowercase")) {
return value.toLowerCase();
} else if (caseMethod.equals("uppercase")) {
return value.toUpperCase();
} else if (caseMethod.equals("titlecase")) {
return StringUtils.toTitleCase(value);
} else {
return value;
}
}
public static String formatNumber(double value, String format) {
return String.format(Locale.US, format, value);
}
/**
* split the string into a list of characters
* this duplicates some of the functionalility of makeStrings
* added because it wasn't obvious that makeString would give
* you characters when no seperator was present
*/
public static List<String> characters(String s) {
if (s == null) {
return ImmutableList.of();
}
return ImmutableList.copyOf(Splitter.fixedLength(1).split(s));
}
/**
* generates a list of random characters
* characters pulled from characterSet
*/
public static List<String> randomCharacter(String characterSet, long amount, long seed) {
List<String> result = new ArrayList<String>();
Random r = new Random(seed * 1000000000);
for (long i = 0; i < amount; i++) {
int index = (int)(r.nextDouble() * characterSet.length());
result.add( String.valueOf(characterSet.charAt(index)) );
}
return result;
}
/**
* generates a formatted binary string
* converts strings into a series of bytes
* then converts those bytes into a binary representation
* with proper zero padding
*/
public static String asBinaryString(String s, String digitSep, String byteSep) {
if (s ==null) {
return s;
}
byte[] bytes = s.getBytes();
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
int val = b;
for (int i = 0; i < 8; i++) {
result.append( ((val & 128) == 0 ? "0" : "1") );
if( i < 7) {
result.append( digitSep );
}
val <<= 1;
}
result.append( byteSep );
}
return result.toString();
}
/**
* generates a list of binary values from a string
* converts strings into a series of bytes
* then converts those bytes into a binary representation
* with proper zero padding
*/
public static List<String> asBinaryList(String s) {
List<String> result = new ArrayList<String>();
if (s == null) {
return result;
}
byte[] bytes = s.getBytes();
for (byte b : bytes) {
int val = b;
for (int i = 0; i < 8; i++) {
result.add( (val & 128) == 0 ? "0" : "1" );
val <<= 1;
}
}
return result;
}
/**
* generates a list of strings (number representation) from a string
* converts strings into a series of bytes
* then converts those bytes into a numeric representation
* numbers are converted into a given base/radix
* checked to base/radix 20
* optional zero padding
*/
public static List<String> asNumberList(String s, long radix, boolean padding) {
List<String> numberList = new ArrayList<String>();
if ((radix < 2) || (s == null)) {
return numberList;
}
byte[] bytes = s.getBytes();
if (padding) {
if (radix == 2) { // binary
for (byte b : bytes) {
int cval = b;
StringBuilder result = new StringBuilder();
for (int i = 0; i < 8; i++) {
result.append( (cval & 128) == 0 ? "0" : "1" );
cval <<= 1;
}
numberList.add( result.toString() );
}
} else if (radix == 3) {
for (byte b : bytes) {
int val = Integer.parseInt( Integer.toString( b, (int)radix ) );
numberList.add( String.format("%06d", val) );
}
} else if ((radix > 3) && (radix < 7) ) {
for (byte b : bytes) {
int val = Integer.parseInt( Integer.toString( b, (int)radix ) );
numberList.add( String.format("%04d", val) );
}
} else if ((radix < 15) ) {
for (byte b : bytes) {
StringBuilder result = new StringBuilder( Integer.toString( b, (int)radix ) );
for (int i = result.length(); i < 3; i++) {
result.insert( 0, "0" ); // zero pad the beginning of the string
}
numberList.add( result.toString() );
}
} else {
for (byte b : bytes) {
StringBuilder result = new StringBuilder( Integer.toString( b, (int)radix ) );
for (int i = result.length(); i < 2; i++) {
result.insert( 0, "0" ); // zero pad the beginning of the string
}
numberList.add( result.toString() );
}
}
} else {
if (radix == 2) { // binary
for (byte b : bytes) {
int cval = b;
StringBuilder result = new StringBuilder();
for (int i = 0; i < 8; i++) {
result.append( (cval & 128) == 0 ? "0" : "1" );
cval <<= 1;
}
numberList.add( result.toString() );
}
} else {
for (byte b : bytes) {
numberList.add( Integer.toString( b, (int)radix ) );
}
}
}
return numberList;
}
/**
* output the character at a given index
*/
public static String characterAt(String s, long index) {
if (s == null || s.isEmpty()) {
return s;
}
if (index < 0) {
index = s.length() + index;
}
if (index >= s.length() || index < 0) { return ""; }
return String.valueOf(s.charAt((int) index));
}
/**
* output a list of characters:count pairs
*/
public static String countCharacters(String s) {
// TODO
return s;
}
/**
* Determine if the string contains a given string
*/
public static boolean contains(String s, String value) {
if ((s==null) || (value==null)) {
return false;
}
return s.contains(value);
}
/**
* Determine if the string end with a given string
*/
public static boolean endsWith(String s, String value) {
if ((s==null) || (value==null)) {
return false;
}
return s.endsWith(value);
}
/**
* Determine if the string equals a given string
* optional case sensitivity
* function renamed to equal because of name conflict
*/
public static boolean equal(String s, String value, boolean caseSensitive) {
if ((s==null) || (value==null)) {
return false;
}
if (caseSensitive) {
return s.equals(value);
} else {
return s.equalsIgnoreCase(value);
}
}
/**
* Replace part of a string
*/
public static String replace(String s, String oldVal, String newVal) {
if ((oldVal==null) || (newVal==null)) {
return s;
}
return s.replace(oldVal, newVal);
}
/**
* Determine if the string starts with a given string
*/
public static boolean startsWith(String s, String value) {
if ((s==null) || (value==null)) {
return false;
}
return s.startsWith(value);
}
/**
* Output a portion of a string
* start and end values are indices of the characters
* endOffset controls whether the character at the end position should be included or not
*/
public static String subString(String s, long start, long end, boolean endOffset) {
if (s == null) {
return s;
}
if (end < start) { return ""; }
if (start < 0 && end < 0) {
start = s.length() + start;
end = s.length() + end;
}
if (endOffset) {
end++;
}
return s.substring((int) Math.max(0, start), (int) Math.min(s.length(), end));
}
/**
* Remove white space from the start and end
*/
public static String trim(String s) {
if (s==null) {
return s;
}
return s.trim();
}
}