All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jlangch.venice.impl.util.StringUtil Maven / Gradle / Ivy

/*   __    __         _
 *   \ \  / /__ _ __ (_) ___ ___
 *    \ \/ / _ \ '_ \| |/ __/ _ \
 *     \  /  __/ | | | | (_|  __/
 *      \/ \___|_| |_|_|\___\___|
 *
 *
 * Copyright 2017-2024 Venice
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.jlangch.venice.impl.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


public class StringUtil {

    /**
     * 

Replaces a String with another String inside a larger String, * for the first {@code max} values of the search String, * case sensitively/insensitively based on {@code ignoreCase} value.

* *

A {@code null} reference passed to this method is a no-op.

* * @param text text to search and replace in, may be null * @param searchString the String to search for (case insensitive), may be null * @param replacement the String to replace it with, may be null * @param max maximum number of values to replace, or {@code -1} if no maximum * @param ignoreCase if true replace is case insensitive, otherwise case sensitive * @return the text with any replacements processed, */ public static String replace( final String text, final String searchString, final String replacement, final int max, final boolean ignoreCase ) { if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) { return text; } final String textLowerCase = ignoreCase ? text.toLowerCase() : null; final String searchStringLowerCase = ignoreCase ? searchString.toLowerCase() : null; int start = 0; int end = ignoreCase ? textLowerCase.indexOf(searchStringLowerCase, start) : text.indexOf(searchString, start); if (end == -1) { return text; } int count = max; final int replLength = searchString.length(); final StringBuilder buf = new StringBuilder(text.length()); while (end != -1) { buf.append(text, start, end).append(replacement); start = end + replLength; if (--count == 0) { break; } end = ignoreCase ? textLowerCase.indexOf(searchStringLowerCase, start) : text.indexOf(searchString, start); } if (start < text.length()) { buf.append(text, start, text.length()); } return buf.toString(); } /** *

Replaces a String with another String inside a larger String, * for the last value of the search String, * case sensitively/insensitively based on {@code ignoreCase} value.

* *

A {@code null} reference passed to this method is a no-op.

* * @param text text to search and replace in, may be null * @param searchString the String to search for (case insensitive), may be null * @param replacement the String to replace it with, may be null * @param ignoreCase if true replace is case insensitive, otherwise case sensitive * @return the text with any replacements processed, */ public static String replaceLast( final String text, final String searchString, final String replacement, final boolean ignoreCase ) { if (isEmpty(text) || isEmpty(searchString) || replacement == null) { return text; } final String textLowerCase = ignoreCase ? text.toLowerCase() : null; final String searchStringLowerCase = ignoreCase ? searchString.toLowerCase() : null; int end = ignoreCase ? textLowerCase.lastIndexOf(searchStringLowerCase) : text.lastIndexOf(searchString); if (end == -1) { return text; } final StringBuilder buf = new StringBuilder(text.length()); buf.append(text, 0, end); buf.append(replacement); buf.append(text, end + searchString.length(), text.length()); return buf.toString(); } /** * Splits a string into columns * * @param text a string * @param colStartPos a list of colum start pos * * @return the splitted columns */ public static List splitColumns(final String text, final int[] colStartPos) { if (colStartPos == null || colStartPos.length == 0) { throw new IllegalArgumentException("A 'colStartPos' array must not be null or empty"); } final List columns = new ArrayList<>(); String tmp = text; for(int ii=colStartPos.length-1; ii>=0; ii--) { int pos = colStartPos[ii]; if (pos <= 0) { columns.add(StringUtil.trimToEmpty(tmp)); tmp = ""; } else if (pos >= tmp.length()) { columns.add(""); } else { columns.add(StringUtil.trimToEmpty(tmp.substring(pos))); tmp = tmp.substring(0, pos); } } Collections.reverse(columns); return columns; } /** * Splits a text into lines * * @param text a string * * @return the lines (maybe empty if the text was null or empty */ public static List splitIntoLines(final String text) { if (text == null || text.isEmpty()) { return new ArrayList<>(); } else { try(final BufferedReader br = new BufferedReader(new StringReader(text))) { return br.lines().collect(Collectors.toList()); } catch(IOException | RuntimeException ex) { throw new RuntimeException("Failed to split text into lines", ex); } } } /** * Escapes a text * * Backspace is replaced with \b * Form feed is replaced with \f * Newline is replaced with \n * Carriage return is replaced with \r * Tab is replaced with \t * Double quote is replaced with \" * Backslash is replaced with \\ * * @param text text to escape * @return the escaped text */ public static String escape(final String text) { if (text == null) { return text; } final StringBuilder sb = new StringBuilder(); for(char c : text.toCharArray()) { switch(c) { case '\n': sb.append('\\').append('n'); break; case '\r': sb.append('\\').append('r'); break; case '\t': sb.append('\\').append('t'); break; case '\f': sb.append('\\').append('f'); break; case '\b': sb.append('\\').append('b'); break; case '"': sb.append('\\').append('"'); break; case '\\': sb.append('\\').append('\\'); break; default: sb.append(c < 32 || c == 127 ? toEscapedUnicode(c) : c); break; } } return sb.toString(); } public static int indexOneCharOf(final String text, final String searchChars, final int startPos) { if (text == null) { throw new IllegalArgumentException("A text must not be null"); } if (isEmpty(searchChars)) { throw new IllegalArgumentException("A searchChars must not be empty"); } if (startPos < 0) { throw new IllegalArgumentException("A startPos must not be negativ"); } if (startPos >= text.length()) { return -1; } final Set chars = searchChars.chars().mapToObj(c -> (char)c).collect(Collectors.toSet()); int pos = startPos; while(pos < text.length()) { if (chars.contains(text.charAt(pos))) { return pos; } else { pos++; } } return -1; } public static int indexNotOf(final String text, final String searchChars, final int startPos) { if (text == null) { throw new IllegalArgumentException("A text must not be null"); } if (isEmpty(searchChars)) { throw new IllegalArgumentException("A searchChars must not be empty"); } if (startPos < 0) { throw new IllegalArgumentException("A startPos must not be negativ"); } if (startPos >= text.length()) { return -1; } final Set chars = searchChars.chars().mapToObj(c -> (char)c).collect(Collectors.toSet()); int pos = startPos; while(pos < text.length()) { if (chars.contains(text.charAt(pos))) { pos++; } else { return pos; } } return -1; } public static String indent(final String text, final int indent) { if (text == null || text.isEmpty()) { return text; } final String indentStr = repeat(' ', Math.min(200, Math.max(0, indent))); return StringUtil .splitIntoLines(text) .stream() .map(s -> indentStr + s) .collect(Collectors.joining("\n")); } public static String stripIndent(final String text) { if (text == null || text.isEmpty()) { return text; } List lines = StringUtil.splitIntoLines(text); // get the indent from the first line final String indent = indentStr(lines.get(0)) ; if (indent != null) { lines = stripIndent(indent, lines); } return String.join("\n", lines); } public static String stripIndentIfFirstLineEmpty(final String text) { if (text == null || text.isEmpty()) { return text; } List lines = StringUtil.splitIntoLines(text); if (lines.size() == 1 || !lines.get(0).isEmpty()) { // just a single line or does not start with an empty line return String.join("\n", lines); } // skip the first empty line lines = lines.subList(1, lines.size()); final String indent = indentStr(lines.get(0)) ; if (indent != null) { lines = stripIndent(indent, lines); // remove an optional last empty line if (lines.get(lines.size()-1).isEmpty()) { lines = lines.subList(0, lines.size()-1); } } lines = joinLinesEndingWithBackslash(lines); return String.join("\n", lines); } public static String stripMargin(final String text, final char margin) { if (text == null || text.isEmpty()) { return text; } return StringUtil .splitIntoLines(text) .stream() .map(s -> { int pos = s.indexOf(margin); return pos < 0 ? s : s.substring(pos+1); }) .collect(Collectors.joining("\n")); } /** * Truncates a string. * * @param text a string * @param maxLen the max length of the truncated string (truncation marker included) * @param truncationMarker a truncation marker * @return the truncated string */ public static String truncate( final String text, final int maxLen, final String truncationMarker ) { if (truncationMarker == null) { throw new IllegalArgumentException("A truncationMarker must not be null"); } int lenTruncationMarker = truncationMarker.length(); if (maxLen <= lenTruncationMarker){ throw new IllegalArgumentException( "A maxLen must greater than the length of the truncation marker"); } if (text == null || text.length() <= maxLen) { return text; } return text.substring(0, maxLen - lenTruncationMarker) + truncationMarker; } public static String repeat(final String s, final int times) { if (s == null) { throw new IllegalArgumentException("s must not be null"); } if (times < 0) { throw new IllegalArgumentException("A times must not be negative"); } if (times == 0) { return ""; } else { final StringBuilder sb = new StringBuilder(); for(int ii=0; ii= 'A' && ch <= 'Z'; } public static String removeStart(final String str, final String remove) { if (isEmpty(str) || isEmpty(remove)) { return str; } else if (str.startsWith(remove)) { return str.substring(remove.length()); } else { return str; } } public static String removeEnd(final String str, final String remove) { if (isEmpty(str) || isEmpty(remove)) { return str; } else if (str.endsWith(remove)) { return str.substring(0, str.length()-remove.length()); } else { return str; } } public static String emptyToNull(final String s) { return isEmpty(s) ? null : s; } public static String nullToEmpty(final String s) { return s == null ? "" : s; } public static String trimToEmpty(final String str) { return str == null ? "" : str.trim(); } public static String trimToNull(final String str) { final String s = str == null ? null : str.trim(); return isEmpty(s) ? null : s; } public static String trimLeft(final String str) { if (str == null || str.isEmpty()) { return str; } int pos = 0; while (pos < str.length() && str.charAt(pos) <= ' ') { pos++; } return str.substring(pos); } public static String trimRight(final String str) { if (str == null || str.isEmpty()) { return str; } int end = str.length(); while (end != 0 && str.charAt(end - 1) <= ' ') { end--; } return str.substring(0, end); } public static String crlf_to_lf(final String str) { if (str == null || str.isEmpty()) { return str; } return str.replaceAll("[\\r]", ""); } // Simplified helper for unit tests public static String to_lf(final Object str) { if (str == null) { return null; } return crlf_to_lf((String)str); } public static String decodeUnicode(final String s) { String working = s; int index; index = working.indexOf("\\u"); while(index > -1) { int length = working.length(); if(index > (length-6)) break; int numStart = index + 2; int numFinish = numStart + 4; String substring = working.substring(numStart, numFinish); int number = Integer.parseInt(substring,16); String stringStart = working.substring(0, index); String stringEnd = working.substring(numFinish); working = stringStart + ((char)number) + stringEnd; index = working.indexOf("\\u"); } return working; } public static String quote(final String str, final char quote) { return new StringBuilder().append(quote).append(str).append(quote).toString(); } public static String replaceLeadingSpaces(final String text, final char replaceChar) { if (text == null) { return null; } final int count = StringUtil.indexNotOf(text, " ", 0); if (count > 0) { final StringBuilder sb = new StringBuilder(); sb.append(repeat(replaceChar, count)); sb.append(text.substring(count)); return sb.toString(); } else { return text; } } public static String padLeft(final String s, final int len) { final int padLen = len - s.length(); return padLen > 0 ? repeat(' ', padLen) + s : s; } public static String padRight(final String s, final int len) { final int padLen = len - s.length(); return padLen > 0 ? s + repeat(' ', padLen) : s; } public static String padCenter(final String s, final int len) { final int padLen = len - s.length(); final int padRight = padLen / 2; final int padLeft = padLen - padRight; return padLen > 0 ? repeat(' ', padLeft) + s + repeat(' ', padRight) : s; } public static String toEscapedUnicode(final char ch) { return String.format("\\u%04x", (int)ch); } private static List stripIndent(final String indent, final List lines) { final int skipChars = indent.length(); return lines .stream() .map(s -> s.startsWith(indent) ? s.substring(skipChars) : s) .collect(Collectors.toList()); } private static String indentStr(final String line) { final int firstBlankPos = StringUtil.indexOneCharOf(line, " \t", 0); if (firstBlankPos < 0) { return null; } else { final int firstNonBlankPos = StringUtil.indexNotOf(line, " \t", 0); return firstNonBlankPos < 0 ? line : line.substring(0, firstNonBlankPos); } } private static List joinLinesEndingWithBackslash(final List lines) { final List joined = new ArrayList<>(); // join lines if the line ends with a '\' String joinLine = null; for(int ii=0; ii




© 2015 - 2025 Weber Informatics LLC | Privacy Policy