|
|
@@ -1,489 +1,489 @@
|
|
|
-/*
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
- * @copyright Ranides Atterwim
|
|
|
- * @license WTFPL
|
|
|
- * @url http://ranides.net/projects/assira
|
|
|
- */
|
|
|
-package net.ranides.assira.text;
|
|
|
-
|
|
|
-import java.util.*;
|
|
|
-import java.util.regex.Matcher;
|
|
|
-import java.util.regex.Pattern;
|
|
|
-import net.ranides.assira.generic.Function;
|
|
|
-import net.ranides.assira.math.MathUtils;
|
|
|
-
|
|
|
-/**
|
|
|
- *
|
|
|
- * @author ranides
|
|
|
- */
|
|
|
-public final class StringUtils {
|
|
|
-
|
|
|
- public static final String ENDL = String.format("%n");
|
|
|
-
|
|
|
- private static final Pattern REGEX_SPECIAL = Pattern.compile("([\\\\*+\\[\\](){}\\$.?\\^|])");
|
|
|
-
|
|
|
- private StringUtils() { /* utility class */ }
|
|
|
-
|
|
|
- public static String remove(String text, String fragment) {
|
|
|
- StringTokenizer tokenizer = new StringTokenizer(text, fragment, false);
|
|
|
- StringBuilder result = new StringBuilder( text.length() );
|
|
|
- while (tokenizer.hasMoreElements()) {
|
|
|
- result.append( tokenizer.nextElement() );
|
|
|
- }
|
|
|
- return result.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static String remove(String text, char value) {
|
|
|
- final int size = text.length();
|
|
|
- final char buffer[] = new char[size];
|
|
|
- char c;
|
|
|
- int position = 0;
|
|
|
- for(int i=0; i<size; i++) {
|
|
|
- c = text.charAt(i);
|
|
|
- if(c!=value) { buffer[position++] = c; }
|
|
|
- }
|
|
|
- return new String(buffer, 0, position);
|
|
|
- }
|
|
|
-
|
|
|
- public static String removePrefix(String text, String prefix) {
|
|
|
- if( Strings.isEmpty(text)) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if(text.startsWith(prefix)) {
|
|
|
- return text.substring(prefix.length());
|
|
|
- }
|
|
|
- return text;
|
|
|
- }
|
|
|
-
|
|
|
- public static String removeSuffix(String text, String suffix) {
|
|
|
- if( Strings.isEmpty(text)) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if(text.endsWith(suffix)) {
|
|
|
- return text.substring(0, text.length() - suffix.length());
|
|
|
- }
|
|
|
- return text;
|
|
|
- }
|
|
|
-
|
|
|
- public static String condense(String text, char value) {
|
|
|
- final int size = text.length();
|
|
|
- final char buffer[] = new char[size];
|
|
|
- char c;
|
|
|
- boolean pc = false;
|
|
|
- int position = 0;
|
|
|
- for(int i=0; i<size; i++) {
|
|
|
- c = text.charAt(i);
|
|
|
- if(c == value) {
|
|
|
- if(!pc) {
|
|
|
- buffer[position++] = c;
|
|
|
- pc = true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- buffer[position++] = c;
|
|
|
- pc = false;
|
|
|
- }
|
|
|
- }
|
|
|
- return new String(buffer, 0, position);
|
|
|
- }
|
|
|
-
|
|
|
- public static String ltrim(String source) {
|
|
|
- int n = source.length(), offset = 0;
|
|
|
- while( offset<n && Character.isWhitespace(source.charAt(offset)) ) { offset++; }
|
|
|
- return source.substring(offset);
|
|
|
- }
|
|
|
-
|
|
|
- public static String rtrim(String source) {
|
|
|
- int offset = source.length() - 1;
|
|
|
- while(offset >= 0 && Character.isWhitespace(source.charAt(offset)) ) { offset--; }
|
|
|
- return source.substring(0, offset+1);
|
|
|
- }
|
|
|
-
|
|
|
- public static String trim(String source){
|
|
|
- return source.trim();
|
|
|
- }
|
|
|
-
|
|
|
- public static String replace(String text, Pattern pattern, Function<String,Matcher> converter) {
|
|
|
- Matcher matcher = pattern.matcher(text);
|
|
|
- StringBuffer buffer = new StringBuffer();
|
|
|
- while(matcher.find()) {
|
|
|
- String str = converter.apply(matcher);
|
|
|
- if( null!=str ) { matcher.appendReplacement(buffer, str); }
|
|
|
- }
|
|
|
- matcher.appendTail(buffer);
|
|
|
- return buffer.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static String replace(String text, char search, char newval) {
|
|
|
- final char[] buffer = text.toCharArray();
|
|
|
- for(int i=0; i<buffer.length; i++) {
|
|
|
- if(buffer[i]==search) { buffer[i] = newval; }
|
|
|
- }
|
|
|
- return new String(buffer);
|
|
|
- }
|
|
|
-
|
|
|
- public static String replace(String text, char search, String newval) {
|
|
|
- if(null == text) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if(text.isEmpty()) {
|
|
|
- return text;
|
|
|
- }
|
|
|
- int start = 0;
|
|
|
- int end = text.indexOf(search, start);
|
|
|
- if (end == -1) {
|
|
|
- return text;
|
|
|
- }
|
|
|
- final int delta = (newval.length()-1);
|
|
|
-
|
|
|
- StringBuilder buf = new StringBuilder(text.length() + 16*delta );
|
|
|
- while (end != -1) {
|
|
|
- buf.append(text.substring(start, end)).append(newval);
|
|
|
- start = end + 1;
|
|
|
- end = text.indexOf(search, start);
|
|
|
- }
|
|
|
- buf.append(text.substring(start));
|
|
|
- return buf.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static <T extends CharSequence> String join(Iterable<T> values, String separator) {
|
|
|
- if (values instanceof Collection) {
|
|
|
- Collection<?> collection = (Collection<?>)values;
|
|
|
- return join( collection.toArray(new CharSequence[collection.size()]), separator );
|
|
|
- }
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
- boolean first = true;
|
|
|
- for(Object value : values) {
|
|
|
- if(!first) { builder.append(separator); }
|
|
|
- if(null != value) { builder.append(value.toString()); }
|
|
|
- first = false;
|
|
|
- }
|
|
|
- return builder.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static <T extends CharSequence> String join(Iterable<T> values) {
|
|
|
- if (values instanceof Collection) {
|
|
|
- Collection<?> collection = (Collection<?>)values;
|
|
|
- return join( collection.toArray(new CharSequence[collection.size()]));
|
|
|
- }
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
- for(Object value : values) {
|
|
|
- builder.append( value.toString() );
|
|
|
- }
|
|
|
- return builder.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static <T extends CharSequence> String join(T[] list, String separator) {
|
|
|
- if(list.length == 0) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if(list.length == 1) {
|
|
|
- return list[0].toString();
|
|
|
- }
|
|
|
-
|
|
|
- int size = 0;
|
|
|
- for(int i=0; i<list.length; i++) {
|
|
|
- size+=list[i].length();
|
|
|
- }
|
|
|
- size += list.length * separator.length();
|
|
|
-
|
|
|
- StringBuilder result = new StringBuilder(size);
|
|
|
- result.append(list[0]);
|
|
|
- for(int i=1; i<list.length; i++) {
|
|
|
- result.append(separator).append(list[i]);
|
|
|
- }
|
|
|
- return result.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static <T extends CharSequence> String join(T[] list) {
|
|
|
- if(list.length == 0) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if(list.length == 1) {
|
|
|
- return list[0].toString();
|
|
|
- }
|
|
|
-
|
|
|
- int size = 0;
|
|
|
- for(int i=0; i<list.length; i++) {
|
|
|
- size+=list[i].length();
|
|
|
- }
|
|
|
-
|
|
|
- StringBuilder result = new StringBuilder(size);
|
|
|
- for(int i=0; i<list.length; i++) {
|
|
|
- result.append(list[i]);
|
|
|
- }
|
|
|
- return result.toString();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Zamienia pierwszą literę w tekście na dużą. Nie uwzględnia lokalizacji.
|
|
|
- * @param value
|
|
|
- * @return
|
|
|
- */
|
|
|
- public static String capitalize(String value) {
|
|
|
- return capitalize(value, Locale.ROOT);
|
|
|
- }
|
|
|
-
|
|
|
- public static String uncapitalize(String value) {
|
|
|
- return uncapitalize(value, Locale.ROOT);
|
|
|
- }
|
|
|
-
|
|
|
- public static String capitalize(String value, Locale locale) {
|
|
|
- if( value.isEmpty() ) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if( 1==value.length() ) {
|
|
|
- return value.toUpperCase(locale);
|
|
|
- }
|
|
|
- return new StringBuilder(value.length())
|
|
|
- .append( value.substring(0, 1).toUpperCase(locale) )
|
|
|
- .append(value.substring(1))
|
|
|
- .toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static String uncapitalize(String value, Locale locale) {
|
|
|
- if( value.isEmpty() ) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if( 1==value.length() ) {
|
|
|
- return value.toLowerCase(locale);
|
|
|
- }
|
|
|
- return new StringBuilder(value.length())
|
|
|
- .append( value.substring(0, 1).toLowerCase(locale) )
|
|
|
- .append(value.substring(1))
|
|
|
- .toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static String camelize(String value) {
|
|
|
- String[] parts = value.split("_+");
|
|
|
- if(0==parts.length) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- if(1==parts.length) {
|
|
|
- return parts[0].toLowerCase(Locale.ROOT);
|
|
|
- }
|
|
|
-
|
|
|
- StringBuilder result = new StringBuilder(value.length()-parts.length);
|
|
|
- boolean first = true;
|
|
|
- for (String part : parts) {
|
|
|
- if(part.isEmpty()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (first) {
|
|
|
- result.append(part.toLowerCase(Locale.ROOT));
|
|
|
- first = false;
|
|
|
- } else {
|
|
|
- result.append(part.substring(0, 1).toUpperCase(Locale.ROOT));
|
|
|
- result.append(part.substring(1).toLowerCase(Locale.ROOT));
|
|
|
- }
|
|
|
- }
|
|
|
- return result.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static String uncamelize(String value) {
|
|
|
- return replace(value, Pattern.compile("(\\p{Lu})"), new Function<String,Matcher>() {
|
|
|
- @Override
|
|
|
- public String apply(Matcher source) {
|
|
|
- if(0 == source.start(1)) {
|
|
|
- return source.group(1).toLowerCase(Locale.ROOT);
|
|
|
- }
|
|
|
- return "_" + source.group(1).toLowerCase(Locale.ROOT);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- public static String clip(String text, int size) {
|
|
|
- return text.substring(0, MathUtils.clip(size, 0, text.length()));
|
|
|
- }
|
|
|
-
|
|
|
- public static String lpadd(String text, char padd, int size) {
|
|
|
- int n = text.length();
|
|
|
- int d = size - n;
|
|
|
- if(d <= 0) {
|
|
|
- return text;
|
|
|
- }
|
|
|
- char[] buffer = new char[size];
|
|
|
- text.getChars(0, n, buffer, 0);
|
|
|
- for(int i=n; i<size; i++) { buffer[i] = padd; }
|
|
|
- return new String(buffer);
|
|
|
- }
|
|
|
-
|
|
|
- public static String rpadd(String text, char padd, int size) {
|
|
|
- int n = text.length();
|
|
|
- int d = size - n;
|
|
|
- if(d <= 0) {
|
|
|
- return text;
|
|
|
- }
|
|
|
- char[] buffer = new char[size];
|
|
|
- text.getChars(0, n, buffer, d);
|
|
|
- for(int i=0; i<d; i++) { buffer[i] = padd; }
|
|
|
- return new String(buffer);
|
|
|
- }
|
|
|
-
|
|
|
- public static String lcommon(String value1, String value2) {
|
|
|
- if( Strings.isEmpty(value1) || Strings.isEmpty(value2) ) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- int n = Math.min(value1.length(), value2.length());
|
|
|
- for(int i=0; i<n; i++) {
|
|
|
- if( value1.charAt(i)!=value2.charAt(i) ) { return value1.substring(0,i); }
|
|
|
- }
|
|
|
- return value1.substring(0,n);
|
|
|
- }
|
|
|
-
|
|
|
- public static String lcommon(List<String> values) {
|
|
|
- if(values.isEmpty() ) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- String text = values.get(0);
|
|
|
- for(int i=1, n=values.size(); i<n; i++) {
|
|
|
- text = lcommon(text, values.get(i));
|
|
|
- }
|
|
|
- return text;
|
|
|
- }
|
|
|
-
|
|
|
- public static List<String> lcommonTrim(List<String> values) {
|
|
|
- int n = lcommon(values).length();
|
|
|
- List<String> result = new ArrayList<>(values.size());
|
|
|
- for(String text : values) {
|
|
|
- result.add(text.substring(n));
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- public static String reverse(String value) {
|
|
|
- return Strings.isEmpty(value) ? value : new StringBuilder(value).reverse().toString();
|
|
|
- }
|
|
|
-
|
|
|
- public static String find(String text, Pattern pattern) {
|
|
|
- Matcher hit = pattern.matcher(text);
|
|
|
- if( hit.find() ) {
|
|
|
- return hit.groupCount()>0 ? hit.group(1) : hit.group();
|
|
|
- } else {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static String find(String text, String pattern) {
|
|
|
- return find(text, Pattern.compile(pattern));
|
|
|
- }
|
|
|
-
|
|
|
- public static String between(String text, String start, String end) {
|
|
|
- if(start == null) {
|
|
|
- return before(text, end);
|
|
|
- }
|
|
|
- if(end == null) {
|
|
|
- return after(text, start);
|
|
|
- }
|
|
|
- int istart = text.indexOf(start);
|
|
|
- if( istart == -1 ) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- istart += start.length();
|
|
|
- int iend = text.indexOf(end, istart);
|
|
|
- if( iend == -1 ) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- return text.substring(istart, iend);
|
|
|
- }
|
|
|
-
|
|
|
- public static String before(String text, String end) {
|
|
|
- int iend = text.indexOf(end);
|
|
|
- return (-1 == iend) ? "" : text.substring(0, iend);
|
|
|
- }
|
|
|
-
|
|
|
- public static String after(String text, String start) {
|
|
|
- int istart = text.indexOf(start);
|
|
|
- return (-1 == istart) ? "" : text.substring(istart + start.length());
|
|
|
- }
|
|
|
-
|
|
|
- public static CharSequence nCopies(int n, String text) {
|
|
|
- return new NCopies(n, text);
|
|
|
- }
|
|
|
-
|
|
|
- public static CharSequence nCopies(int n, char chr) {
|
|
|
- return new NCCopies(n, chr);
|
|
|
- }
|
|
|
-
|
|
|
- private static class NCCopies implements CharSequence {
|
|
|
- private final int count;
|
|
|
- private final char chr;
|
|
|
-
|
|
|
- public NCCopies(int count, char chr) {
|
|
|
- this.count = count;
|
|
|
- this.chr = chr;
|
|
|
- }
|
|
|
- @Override
|
|
|
- public char charAt(int index) {
|
|
|
- if( index >= count ) {
|
|
|
- throw new IndexOutOfBoundsException(index + " out of bound " + count);
|
|
|
- }
|
|
|
- return chr;
|
|
|
- }
|
|
|
- @Override
|
|
|
- public int length() {
|
|
|
- return count;
|
|
|
- }
|
|
|
- @Override
|
|
|
- public CharSequence subSequence(int start, int end) {
|
|
|
- return new NCCopies(end-start, chr);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public String toString() {
|
|
|
- int n = length();
|
|
|
- char[] data = new char[n];
|
|
|
- Arrays.fill(data, chr);
|
|
|
- return new String(data);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private static class NCopies implements CharSequence {
|
|
|
- private final int start;
|
|
|
- private final int end;
|
|
|
- private final int mod;
|
|
|
- private final String text;
|
|
|
-
|
|
|
- public NCopies(int count, String text) {
|
|
|
- this(text, 0, count * text.length());
|
|
|
- }
|
|
|
-
|
|
|
- public NCopies(String text, int start, int end) {
|
|
|
- this.start = start;
|
|
|
- this.end = end;
|
|
|
- this.mod = text.length();
|
|
|
- this.text = text;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public char charAt(int index) {
|
|
|
- if( index >= end ) {
|
|
|
- throw new IndexOutOfBoundsException(index + " out of bound " + end);
|
|
|
- }
|
|
|
- return text.charAt( (index+start) % mod );
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int length() {
|
|
|
- return end-start;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public CharSequence subSequence(int start, int end) {
|
|
|
- return new NCopies(text, start, end);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public String toString() {
|
|
|
- int n = length();
|
|
|
- char[] data = new char[n];
|
|
|
- for(int i=0; i<n; i++) { data[i] = charAt(i); }
|
|
|
- return new String(data);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public static String escapeRegex(String text) {
|
|
|
- return REGEX_SPECIAL.matcher(text).replaceAll("\\\\$1");
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.text;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+import net.ranides.assira.generic.Function;
|
|
|
+import net.ranides.assira.math.MathUtils;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author ranides
|
|
|
+ */
|
|
|
+public final class StringUtils {
|
|
|
+
|
|
|
+ public static final String ENDL = String.format("%n");
|
|
|
+
|
|
|
+ private static final Pattern REGEX_SPECIAL = Pattern.compile("([\\\\*+\\[\\](){}\\$.?\\^|])");
|
|
|
+
|
|
|
+ private StringUtils() { /* utility class */ }
|
|
|
+
|
|
|
+ public static String remove(String text, String fragment) {
|
|
|
+ StringTokenizer tokenizer = new StringTokenizer(text, fragment, false);
|
|
|
+ StringBuilder result = new StringBuilder( text.length() );
|
|
|
+ while (tokenizer.hasMoreElements()) {
|
|
|
+ result.append( tokenizer.nextElement() );
|
|
|
+ }
|
|
|
+ return result.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String remove(String text, char value) {
|
|
|
+ final int size = text.length();
|
|
|
+ final char buffer[] = new char[size];
|
|
|
+ char c;
|
|
|
+ int position = 0;
|
|
|
+ for(int i=0; i<size; i++) {
|
|
|
+ c = text.charAt(i);
|
|
|
+ if(c!=value) { buffer[position++] = c; }
|
|
|
+ }
|
|
|
+ return new String(buffer, 0, position);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String removePrefix(String text, String prefix) {
|
|
|
+ if( Strings.isEmpty(text)) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(text.startsWith(prefix)) {
|
|
|
+ return text.substring(prefix.length());
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String removeSuffix(String text, String suffix) {
|
|
|
+ if( Strings.isEmpty(text)) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(text.endsWith(suffix)) {
|
|
|
+ return text.substring(0, text.length() - suffix.length());
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String condense(String text, char value) {
|
|
|
+ final int size = text.length();
|
|
|
+ final char buffer[] = new char[size];
|
|
|
+ char c;
|
|
|
+ boolean pc = false;
|
|
|
+ int position = 0;
|
|
|
+ for(int i=0; i<size; i++) {
|
|
|
+ c = text.charAt(i);
|
|
|
+ if(c == value) {
|
|
|
+ if(!pc) {
|
|
|
+ buffer[position++] = c;
|
|
|
+ pc = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ buffer[position++] = c;
|
|
|
+ pc = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new String(buffer, 0, position);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String ltrim(String source) {
|
|
|
+ int n = source.length(), offset = 0;
|
|
|
+ while( offset<n && Character.isWhitespace(source.charAt(offset)) ) { offset++; }
|
|
|
+ return source.substring(offset);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String rtrim(String source) {
|
|
|
+ int offset = source.length() - 1;
|
|
|
+ while(offset >= 0 && Character.isWhitespace(source.charAt(offset)) ) { offset--; }
|
|
|
+ return source.substring(0, offset+1);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String trim(String source){
|
|
|
+ return source.trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String replace(String text, Pattern pattern, Function<String,Matcher> converter) {
|
|
|
+ Matcher matcher = pattern.matcher(text);
|
|
|
+ StringBuffer buffer = new StringBuffer();
|
|
|
+ while(matcher.find()) {
|
|
|
+ String str = converter.apply(matcher);
|
|
|
+ if( null!=str ) { matcher.appendReplacement(buffer, Matcher.quoteReplacement(str)); }
|
|
|
+ }
|
|
|
+ matcher.appendTail(buffer);
|
|
|
+ return buffer.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String replace(String text, char search, char newval) {
|
|
|
+ final char[] buffer = text.toCharArray();
|
|
|
+ for(int i=0; i<buffer.length; i++) {
|
|
|
+ if(buffer[i]==search) { buffer[i] = newval; }
|
|
|
+ }
|
|
|
+ return new String(buffer);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String replace(String text, char search, String newval) {
|
|
|
+ if(null == text) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(text.isEmpty()) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ int start = 0;
|
|
|
+ int end = text.indexOf(search, start);
|
|
|
+ if (end == -1) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ final int delta = (newval.length()-1);
|
|
|
+
|
|
|
+ StringBuilder buf = new StringBuilder(text.length() + 16*delta );
|
|
|
+ while (end != -1) {
|
|
|
+ buf.append(text.substring(start, end)).append(newval);
|
|
|
+ start = end + 1;
|
|
|
+ end = text.indexOf(search, start);
|
|
|
+ }
|
|
|
+ buf.append(text.substring(start));
|
|
|
+ return buf.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <T extends CharSequence> String join(Iterable<T> values, String separator) {
|
|
|
+ if (values instanceof Collection) {
|
|
|
+ Collection<?> collection = (Collection<?>)values;
|
|
|
+ return join( collection.toArray(new CharSequence[collection.size()]), separator );
|
|
|
+ }
|
|
|
+ StringBuilder builder = new StringBuilder();
|
|
|
+ boolean first = true;
|
|
|
+ for(Object value : values) {
|
|
|
+ if(!first) { builder.append(separator); }
|
|
|
+ if(null != value) { builder.append(value.toString()); }
|
|
|
+ first = false;
|
|
|
+ }
|
|
|
+ return builder.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <T extends CharSequence> String join(Iterable<T> values) {
|
|
|
+ if (values instanceof Collection) {
|
|
|
+ Collection<?> collection = (Collection<?>)values;
|
|
|
+ return join( collection.toArray(new CharSequence[collection.size()]));
|
|
|
+ }
|
|
|
+ StringBuilder builder = new StringBuilder();
|
|
|
+ for(Object value : values) {
|
|
|
+ builder.append( value.toString() );
|
|
|
+ }
|
|
|
+ return builder.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <T extends CharSequence> String join(T[] list, String separator) {
|
|
|
+ if(list.length == 0) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(list.length == 1) {
|
|
|
+ return list[0].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ int size = 0;
|
|
|
+ for(int i=0; i<list.length; i++) {
|
|
|
+ size+=list[i].length();
|
|
|
+ }
|
|
|
+ size += list.length * separator.length();
|
|
|
+
|
|
|
+ StringBuilder result = new StringBuilder(size);
|
|
|
+ result.append(list[0]);
|
|
|
+ for(int i=1; i<list.length; i++) {
|
|
|
+ result.append(separator).append(list[i]);
|
|
|
+ }
|
|
|
+ return result.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <T extends CharSequence> String join(T[] list) {
|
|
|
+ if(list.length == 0) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(list.length == 1) {
|
|
|
+ return list[0].toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ int size = 0;
|
|
|
+ for(int i=0; i<list.length; i++) {
|
|
|
+ size+=list[i].length();
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuilder result = new StringBuilder(size);
|
|
|
+ for(int i=0; i<list.length; i++) {
|
|
|
+ result.append(list[i]);
|
|
|
+ }
|
|
|
+ return result.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Zamienia pierwszą literę w tekście na dużą. Nie uwzględnia lokalizacji.
|
|
|
+ * @param value
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String capitalize(String value) {
|
|
|
+ return capitalize(value, Locale.ROOT);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String uncapitalize(String value) {
|
|
|
+ return uncapitalize(value, Locale.ROOT);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String capitalize(String value, Locale locale) {
|
|
|
+ if( value.isEmpty() ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if( 1==value.length() ) {
|
|
|
+ return value.toUpperCase(locale);
|
|
|
+ }
|
|
|
+ return new StringBuilder(value.length())
|
|
|
+ .append( value.substring(0, 1).toUpperCase(locale) )
|
|
|
+ .append(value.substring(1))
|
|
|
+ .toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String uncapitalize(String value, Locale locale) {
|
|
|
+ if( value.isEmpty() ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if( 1==value.length() ) {
|
|
|
+ return value.toLowerCase(locale);
|
|
|
+ }
|
|
|
+ return new StringBuilder(value.length())
|
|
|
+ .append( value.substring(0, 1).toLowerCase(locale) )
|
|
|
+ .append(value.substring(1))
|
|
|
+ .toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String camelize(String value) {
|
|
|
+ String[] parts = value.split("_+");
|
|
|
+ if(0==parts.length) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ if(1==parts.length) {
|
|
|
+ return parts[0].toLowerCase(Locale.ROOT);
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuilder result = new StringBuilder(value.length()-parts.length);
|
|
|
+ boolean first = true;
|
|
|
+ for (String part : parts) {
|
|
|
+ if(part.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (first) {
|
|
|
+ result.append(part.toLowerCase(Locale.ROOT));
|
|
|
+ first = false;
|
|
|
+ } else {
|
|
|
+ result.append(part.substring(0, 1).toUpperCase(Locale.ROOT));
|
|
|
+ result.append(part.substring(1).toLowerCase(Locale.ROOT));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String uncamelize(String value) {
|
|
|
+ return replace(value, Pattern.compile("(\\p{Lu})"), new Function<String,Matcher>() {
|
|
|
+ @Override
|
|
|
+ public String apply(Matcher source) {
|
|
|
+ if(0 == source.start(1)) {
|
|
|
+ return source.group(1).toLowerCase(Locale.ROOT);
|
|
|
+ }
|
|
|
+ return "_" + source.group(1).toLowerCase(Locale.ROOT);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String clip(String text, int size) {
|
|
|
+ return text.substring(0, MathUtils.clip(size, 0, text.length()));
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String lpadd(String text, char padd, int size) {
|
|
|
+ int n = text.length();
|
|
|
+ int d = size - n;
|
|
|
+ if(d <= 0) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ char[] buffer = new char[size];
|
|
|
+ text.getChars(0, n, buffer, 0);
|
|
|
+ for(int i=n; i<size; i++) { buffer[i] = padd; }
|
|
|
+ return new String(buffer);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String rpadd(String text, char padd, int size) {
|
|
|
+ int n = text.length();
|
|
|
+ int d = size - n;
|
|
|
+ if(d <= 0) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+ char[] buffer = new char[size];
|
|
|
+ text.getChars(0, n, buffer, d);
|
|
|
+ for(int i=0; i<d; i++) { buffer[i] = padd; }
|
|
|
+ return new String(buffer);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String lcommon(String value1, String value2) {
|
|
|
+ if( Strings.isEmpty(value1) || Strings.isEmpty(value2) ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ int n = Math.min(value1.length(), value2.length());
|
|
|
+ for(int i=0; i<n; i++) {
|
|
|
+ if( value1.charAt(i)!=value2.charAt(i) ) { return value1.substring(0,i); }
|
|
|
+ }
|
|
|
+ return value1.substring(0,n);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String lcommon(List<String> values) {
|
|
|
+ if(values.isEmpty() ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ String text = values.get(0);
|
|
|
+ for(int i=1, n=values.size(); i<n; i++) {
|
|
|
+ text = lcommon(text, values.get(i));
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static List<String> lcommonTrim(List<String> values) {
|
|
|
+ int n = lcommon(values).length();
|
|
|
+ List<String> result = new ArrayList<>(values.size());
|
|
|
+ for(String text : values) {
|
|
|
+ result.add(text.substring(n));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String reverse(String value) {
|
|
|
+ return Strings.isEmpty(value) ? value : new StringBuilder(value).reverse().toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String find(String text, Pattern pattern) {
|
|
|
+ Matcher hit = pattern.matcher(text);
|
|
|
+ if( hit.find() ) {
|
|
|
+ return hit.groupCount()>0 ? hit.group(1) : hit.group();
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String find(String text, String pattern) {
|
|
|
+ return find(text, Pattern.compile(pattern));
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String between(String text, String start, String end) {
|
|
|
+ if(start == null) {
|
|
|
+ return before(text, end);
|
|
|
+ }
|
|
|
+ if(end == null) {
|
|
|
+ return after(text, start);
|
|
|
+ }
|
|
|
+ int istart = text.indexOf(start);
|
|
|
+ if( istart == -1 ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ istart += start.length();
|
|
|
+ int iend = text.indexOf(end, istart);
|
|
|
+ if( iend == -1 ) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return text.substring(istart, iend);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String before(String text, String end) {
|
|
|
+ int iend = text.indexOf(end);
|
|
|
+ return (-1 == iend) ? "" : text.substring(0, iend);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String after(String text, String start) {
|
|
|
+ int istart = text.indexOf(start);
|
|
|
+ return (-1 == istart) ? "" : text.substring(istart + start.length());
|
|
|
+ }
|
|
|
+
|
|
|
+ public static CharSequence nCopies(int n, String text) {
|
|
|
+ return new NCopies(n, text);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static CharSequence nCopies(int n, char chr) {
|
|
|
+ return new NCCopies(n, chr);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class NCCopies implements CharSequence {
|
|
|
+ private final int count;
|
|
|
+ private final char chr;
|
|
|
+
|
|
|
+ public NCCopies(int count, char chr) {
|
|
|
+ this.count = count;
|
|
|
+ this.chr = chr;
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public char charAt(int index) {
|
|
|
+ if( index >= count ) {
|
|
|
+ throw new IndexOutOfBoundsException(index + " out of bound " + count);
|
|
|
+ }
|
|
|
+ return chr;
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public int length() {
|
|
|
+ return count;
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public CharSequence subSequence(int start, int end) {
|
|
|
+ return new NCCopies(end-start, chr);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ int n = length();
|
|
|
+ char[] data = new char[n];
|
|
|
+ Arrays.fill(data, chr);
|
|
|
+ return new String(data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class NCopies implements CharSequence {
|
|
|
+ private final int start;
|
|
|
+ private final int end;
|
|
|
+ private final int mod;
|
|
|
+ private final String text;
|
|
|
+
|
|
|
+ public NCopies(int count, String text) {
|
|
|
+ this(text, 0, count * text.length());
|
|
|
+ }
|
|
|
+
|
|
|
+ public NCopies(String text, int start, int end) {
|
|
|
+ this.start = start;
|
|
|
+ this.end = end;
|
|
|
+ this.mod = text.length();
|
|
|
+ this.text = text;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public char charAt(int index) {
|
|
|
+ if( index >= end ) {
|
|
|
+ throw new IndexOutOfBoundsException(index + " out of bound " + end);
|
|
|
+ }
|
|
|
+ return text.charAt( (index+start) % mod );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int length() {
|
|
|
+ return end-start;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CharSequence subSequence(int start, int end) {
|
|
|
+ return new NCopies(text, start, end);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ int n = length();
|
|
|
+ char[] data = new char[n];
|
|
|
+ for(int i=0; i<n; i++) { data[i] = charAt(i); }
|
|
|
+ return new String(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String escapeRegex(String text) {
|
|
|
+ return REGEX_SPECIAL.matcher(text).replaceAll("\\\\$1");
|
|
|
+ }
|
|
|
+
|
|
|
+}
|