package xapi.util;
import xapi.collect.api.CharPool;
import xapi.fu.In1Out1;
import xapi.inject.X_Inject;
import static xapi.util.service.StringService.binarySuffix;
import static xapi.util.service.StringService.metricSuffix;
import java.util.Iterator;
public class X_String {
private X_String() {}
public static byte[] getBytes(String source) {
return source.getBytes();
}
public static CharPool getCharPool() {
return X_Inject.singleton(CharPool.class);
}
public static String toMetricSuffix(double val) {
String suffix;
int index = 3; //we go from nano to giga; up three and down three.
if (val > 1) {
//count up
while(val >= 1000){
index++;
val = val / 1000.0;
if (index==6)break;
}
suffix = metricSuffix[index];
return ((int)(10*val)/10.0)+suffix;
}else {
//count down
while(val < 1.0){
if (index==0) {
if (val < 0.1) {
//nano scale, we need to stop and truncate to nearest non-zero values.
suffix = Double.toString(val);
for (int pos = 2; pos < suffix.length(); pos++) {
if (suffix.charAt(pos)!='0') {
suffix = suffix.substring(0, Math.min(pos+1,suffix.length()-1));
return suffix+metricSuffix[index];
}
}
return "0";
}
break;
}
index--;
val = val * 1000.0;
}
suffix = metricSuffix[index];
return ((int)(10.001*val)/10.0)+suffix;
}
}
public static String toBinarySuffix(double val) {
String suffix;
boolean neg = val < 0;
if (neg)val = val*-1;
int index = 0;
while(val >= 1024){
index++;
val = val / 1024.0;
}
suffix = binarySuffix[Math.min(index,binarySuffix.length-1)];
return (neg?"-":"")+((int)(10*val))/10.0+suffix;
}
@SafeVarargs
public static <T> String joinObjects(
@SuppressWarnings("unchecked") T ... values
) {
return joinObjects(", ", values);
}
@SafeVarargs
public static <T> String joinObjects(
String separator,
@SuppressWarnings("unchecked") T ... values
) {
int i = values.length;
String[] copy = new String[i];
for(;i-->0;)
copy[i] = String.valueOf(values[i]);
return join(separator, copy);
}
public static String joinClasses(String separator, Class<?> ... values) {
String[] copy = classesToQualified(values);
return join(separator, copy);
}
public static String joinClasses(String separator, In1Out1<Class<?>, String> mapper, Class<?> ... values) {
String[] copy = classesMapped(mapper, values);
return join(separator, copy);
}
public static String classToQualified(Class<?> cls) {
return classesToQualified(cls)[0];
}
public static String[] classesToQualified(Class<?> ... values) {
return classesMapped(Class::getCanonicalName, values);
}
public static String[] classesMapped(In1Out1<Class<?>, String> mapper, Class<?> ... values) {
int i = values.length;
String[] copy = new String[i];
for(;i-->0;){
Class<?> cls = values[i];
if (cls != null)
copy[i] = mapper.io(cls);
}
return copy;
}
public static String classToSourceFiles(Class<?> cls) {
return classesToSourceFiles(cls)[0];
}
public static String[] classesToSourceFiles(Class<?> ... values) {
int i = values.length;
String[] copy = new String[i];
for(;i-->0;){
Class<?> cls = values[i];
if (cls != null)
copy[i] = cls.getCanonicalName().replace('.', X_Runtime.fileSeparatorChar()) + ".java";
}
return copy;
}
public static String classToBinary(Class<?> cls) {
return classesToBinary(cls)[0];
}
public static String[] classesToBinary(Class<?> ... values) {
int i = values.length;
String[] copy = new String[i];
for(;i-->0;){
Class<?> cls = values[i];
if (cls != null)
copy[i] = cls.getName();
}
return copy;
}
public static String joinStrings(String ... values) {
return join(", ", values);
}
public static String join(String separator, String ... values)
/*js:
return values.join(separator);
:js*/
{//java:
if (values.length == 0) return "";// need at least one element
// all string operations use a new array, so minimize all calls possible
char[] sep = separator.toCharArray();
// determine final size and normalize nulls
int totalSize = (values.length - 1) * sep.length;// separator size
for (int i = 0; i < values.length; i++) {
if (values[i] == null)
values[i] = "";
else
totalSize += values[i].length();
}
// exact size; no bounds checks or resizes
char[] joined = new char[totalSize];
int pos = 0;
// note, we are iterating all the elements except the last one
for (int i = 0, end = values.length - 1; i < end; i++) {
System.arraycopy(values[i].toCharArray(), 0, joined, pos, values[i].length());
pos += values[i].length();
System.arraycopy(sep, 0, joined, pos, sep.length);
pos += sep.length;
}
// now, add the last element;
// this is why we short-circuited values.length == 0 off the hop
System.arraycopy(values[values.length - 1].toCharArray(), 0, joined, pos,
values[values.length - 1].length());
return new String(joined);
}//:java
public static String join(String separator, Iterable values) {
StringBuilder b = new StringBuilder();
final Iterator itr = values.iterator();
if (itr.hasNext()) {
b.append(String.valueOf(itr.next()));
}
while (itr.hasNext()) {
b.append(separator).append(String.valueOf(itr.next()));
}
return b.toString();
}
public static boolean isEmpty(String enclosing) {
return enclosing == null || enclosing.length() == 0;
}
public static boolean isEmptyTrimmed(String enclosing) {
return enclosing == null || enclosing.trim().length() == 0;
}
public static boolean isNotEmpty(String enclosing) {
return enclosing != null && enclosing.length() > 0;
}
public static boolean isEmpty(String[] enclosing) {
if (enclosing == null || enclosing.length == 0) {
return true;
}
for (String s : enclosing) {
if (isNotEmpty(s)) {
return false;
}
}
return true;
}
public static boolean isNotEmpty(String[] enclosing) {
return !isEmpty(enclosing);
}
public static boolean isNotEmptyTrimmed(String enclosing) {
return enclosing != null && enclosing.trim().length() > 0;
}
public static String firstChunk(String string, char c) {
assert string != null : "No nulls to X_String.firstChunk, please.";
int i = string.charAt(c);
if (i == -1)
return string;
return string.substring(0, i);
}
public static String firstNotEmpty(String groupId1, String groupId2) {
return isEmptyTrimmed(groupId1) ? groupId2 : groupId1;
}
public static String[] splitNewLine(String str) {
return str.split("\n");
}
public static String notNull(String str) {
return str == null ? "" : str;
}
public static String chopOrReturnEmpty(String source, String match) {
int ind = source.lastIndexOf(match);
if (ind == -1) {
return "";
}
return source.substring(0, ind);
}
public static String toTitleCase(String name) {
return isEmpty(name) ? name : Character.toUpperCase(name.charAt(0))+name.substring(1);
}
public static String normalizeNewlines(String text) {
return text.replaceAll("\\r\\n?", "\n");
}
public static String repeat(String s, int i) {
StringBuilder b = new StringBuilder();
while (i --> 0) {
b.append(s);
}
return b.toString();
}
public static String toTimestamp(int year, int month, int date, int hour, int minute, int milli, int offsetMinutes) {
// Ya... It's more lines of code than using a library,
// but it's also the minimum overhead possible.
char[] result = "yyyy-MM-ddTHH:mm.sss+00:00".toCharArray();
result[3] = Character.forDigit(year%10, 10);
result[2] = Character.forDigit((year/=10)%10, 10);
result[1] = Character.forDigit((year/=10)%10, 10);
result[0] = Character.forDigit((year/10)%10, 10);
result[5] = Character.forDigit(month/10, 10);
result[6] = Character.forDigit(month%10, 10);
result[8] = Character.forDigit(date/10, 10);
result[9] = Character.forDigit(date%10, 10);
result[11] = Character.forDigit(hour/10, 10);
result[12] = Character.forDigit(hour%10, 10);
result[14] = Character.forDigit(minute/10, 10);
result[15] = Character.forDigit(minute%10, 10);
result[19] = Character.forDigit(milli%10, 10);
result[18] = Character.forDigit((milli/=10)%10, 10);
result[17] = Character.forDigit((milli/10)%10, 10);
if (offsetMinutes < 0) {
result[20] = '-';
offsetMinutes = -offsetMinutes;
}
int hours = offsetMinutes / 60;
result[21] = Character.forDigit(hours/10, 10);
result[22] = Character.forDigit(hours%10, 10);
offsetMinutes = offsetMinutes%60;
result[24] = Character.forDigit((offsetMinutes/10)%10, 10);
result[25] = Character.forDigit(offsetMinutes%10, 10);
return new String(result);
}
}