Skip to content

Commit

Permalink
Trivial tweak: reuse closures for string replacement
Browse files Browse the repository at this point in the history
  • Loading branch information
daniellansun committed Jan 11, 2025
1 parent da6aa1e commit e3491f5
Showing 1 changed file with 93 additions and 126 deletions.
219 changes: 93 additions & 126 deletions src/main/java/org/apache/groovy/parser/antlr4/util/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,143 +20,57 @@

import groovy.lang.Closure;
import org.apache.groovy.util.Maps;
import org.codehaus.groovy.runtime.StringGroovyMethods;

import java.util.Map;
import java.util.regex.Pattern;

import static org.codehaus.groovy.runtime.StringGroovyMethods.replaceAll;

/**
* Utilities for handling strings
*
*/
public class StringUtils {
private static final String BACKSLASH = "\\";
private static final Pattern HEX_ESCAPES_PATTERN = Pattern.compile("(\\\\*)\\\\u([0-9abcdefABCDEF]{4})");
private static final Pattern OCTAL_ESCAPES_PATTERN = Pattern.compile("(\\\\*)\\\\([0-3]?[0-7]?[0-7])");
private static final Pattern STANDARD_ESCAPES_PATTERN = Pattern.compile("(\\\\*)\\\\([btnfrs\"'])");
private static final Pattern LINE_ESCAPE_PATTERN = Pattern.compile("(\\\\*)\\\\\r?\n");

public static String replaceHexEscapes(String text) {
if (!text.contains(BACKSLASH)) {
return text;
}

return StringGroovyMethods.replaceAll((CharSequence) text, HEX_ESCAPES_PATTERN, new Closure<Void>(null, null) {
Object doCall(String _0, String _1, String _2) {
if (isLengthOdd(_1)) {
return _0;
}

return _1 + new String(Character.toChars(Integer.parseInt(_2, 16)));
}
});
public static final int NONE_SLASHY = 0;
public static final int SLASHY = 1;
public static final int DOLLAR_SLASHY = 2;

public static String replaceEscapes(String text, int slashyType) {
if (slashyType == SLASHY || slashyType == DOLLAR_SLASHY) {
text = StringUtils.replaceHexEscapes(text);
text = StringUtils.replaceLineEscape(text);

if (slashyType == SLASHY) {
text = replace(text,"\\/", "/");
} else if (slashyType == DOLLAR_SLASHY) {
text = replace(text,"$/", "/");
text = replace(text,"$$", "$");
}
} else if (slashyType == NONE_SLASHY) {
text = StringUtils.replaceEscapes(text);
} else {
throw new IllegalArgumentException("Invalid slashyType: " + slashyType);
}

return text;
}

public static String replaceHexEscapes(String text) {
if (!text.contains(BACKSLASH)) return text;
return replaceAll((CharSequence) text, HEX_ESCAPES_PATTERN, REPLACE_HEX_ESCAPES);
}

public static String replaceOctalEscapes(String text) {
if (!text.contains(BACKSLASH)) {
return text;
}

return StringGroovyMethods.replaceAll((CharSequence) text, OCTAL_ESCAPES_PATTERN, new Closure<Void>(null, null) {
Object doCall(String _0, String _1, String _2) {
if (isLengthOdd(_1)) {
return _0;
}

return _1 + new String(Character.toChars(Integer.parseInt(_2, 8)));
}
});
if (!text.contains(BACKSLASH)) return text;
return replaceAll((CharSequence) text, OCTAL_ESCAPES_PATTERN, REPLACE_OCTAL_ESCAPES);
}

private static final Map<Character, Character> STANDARD_ESCAPES = Maps.of(
'b', '\b',
't', '\t',
'n', '\n',
'f', '\f',
'r', '\r',
's', ' '
);

public static String replaceStandardEscapes(String text) {
if (!text.contains(BACKSLASH)) {
return text;
}

String result = StringGroovyMethods.replaceAll((CharSequence) text, STANDARD_ESCAPES_PATTERN, new Closure<Void>(null, null) {
Object doCall(String _0, String _1, String _2) {
if (isLengthOdd(_1)) {
return _0;
}

Character character = STANDARD_ESCAPES.get(_2.charAt(0));
return _1 + (character != null ? character : _2);
}
});

public static String replaceStandardEscapes(String text) {
if (!text.contains(BACKSLASH)) return text;
final String result = replaceAll((CharSequence) text, STANDARD_ESCAPES_PATTERN, REPLACE_STANDARD_ESCAPES);
return replace(result,"\\\\", "\\");
}

public static final int NONE_SLASHY = 0;
public static final int SLASHY = 1;
public static final int DOLLAR_SLASHY = 2;

public static String replaceEscapes(String text, int slashyType) {
if (slashyType == SLASHY || slashyType == DOLLAR_SLASHY) {
text = StringUtils.replaceHexEscapes(text);
text = StringUtils.replaceLineEscape(text);

if (slashyType == SLASHY) {
text = replace(text,"\\/", "/");
}

if (slashyType == DOLLAR_SLASHY) {
text = replace(text,"$/", "/");
text = replace(text,"$$", "$");
}

} else if (slashyType == NONE_SLASHY) {
text = StringUtils.replaceEscapes(text);
} else {
throw new IllegalArgumentException("Invalid slashyType: " + slashyType);
}

return text;
}

private static String replaceEscapes(String text) {
if (!text.contains(BACKSLASH)) {
return text;
}

text = replace(text,"\\$", "$");

text = StringUtils.replaceLineEscape(text);

return StringUtils.replaceStandardEscapes(replaceHexEscapes(replaceOctalEscapes(text)));
}

private static String replaceLineEscape(String text) {
if (!text.contains(BACKSLASH)) {
return text;
}

text = StringGroovyMethods.replaceAll((CharSequence) text, LINE_ESCAPE_PATTERN, new Closure<Void>(null, null) {
Object doCall(String _0, String _1) {
if (isLengthOdd(_1)) {
return _0;
}

return _1;
}
});

return text;
}

private static boolean isLengthOdd(String str) {
return null != str && str.length() % 2 == 1;
}

public static String removeCR(String text) {
return replace(text,"\r\n", "\n");
}
Expand All @@ -167,7 +81,6 @@ public static long countChar(String text, char c) {

public static String trimQuotations(String text, int quotationLength) {
int length = text.length();

return length == quotationLength << 1 ? "" : text.substring(quotationLength, length - quotationLength);
}

Expand Down Expand Up @@ -200,9 +113,8 @@ public static boolean matches(String text, Pattern pattern) {
* {@code null} if null String input
*/
public static String replace(final String text, String searchString, final String replacement) {
if (isEmpty(text) || isEmpty(searchString) || replacement == null) {
return text;
}
if (isEmpty(text) || isEmpty(searchString) || replacement == null) return text;

int start = 0;
int end = text.indexOf(searchString, start);
if (end == INDEX_NOT_FOUND) {
Expand Down Expand Up @@ -245,10 +157,65 @@ public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}

/**
private static String replaceEscapes(String text) {
if (!text.contains(BACKSLASH)) return text;
text = replace(text,"\\$", "$");
text = StringUtils.replaceLineEscape(text);
return StringUtils.replaceStandardEscapes(replaceHexEscapes(replaceOctalEscapes(text)));
}

private static String replaceLineEscape(String text) {
if (!text.contains(BACKSLASH)) return text;
text = replaceAll((CharSequence) text, LINE_ESCAPE_PATTERN, REPLACE_LINE_ESCAPE);
return text;
}

private static boolean isLengthOdd(String str) {
return null != str && str.length() % 2 == 1;
}

/**
* Copied from Apache commons-lang3-3.6
*
* Represents a failed index search.
*/
private static final int INDEX_NOT_FOUND = -1;
}
private static final String BACKSLASH = "\\";
private static final Pattern HEX_ESCAPES_PATTERN = Pattern.compile("(\\\\*)\\\\u([0-9abcdefABCDEF]{4})");
private static final Pattern OCTAL_ESCAPES_PATTERN = Pattern.compile("(\\\\*)\\\\([0-3]?[0-7]?[0-7])");
private static final Pattern STANDARD_ESCAPES_PATTERN = Pattern.compile("(\\\\*)\\\\([btnfrs\"'])");
private static final Pattern LINE_ESCAPE_PATTERN = Pattern.compile("(\\\\*)\\\\\r?\n");
private static final Map<Character, Character> STANDARD_ESCAPES = Maps.of(
'b', '\b',
't', '\t',
'n', '\n',
'f', '\f',
'r', '\r',
's', ' '
);
private static final Closure<String> REPLACE_STANDARD_ESCAPES = new Closure<String>(null, null) {
String doCall(String _0, String _1, String _2) {
if (isLengthOdd(_1)) return _0;
final Character character = STANDARD_ESCAPES.get(_2.charAt(0));
return _1 + (character != null ? character : _2);
}
};
private static final Closure<String> REPLACE_OCTAL_ESCAPES = new Closure<String>(null, null) {
String doCall(String _0, String _1, String _2) {
if (isLengthOdd(_1)) return _0;
return _1 + new String(Character.toChars(Integer.parseInt(_2, 8)));
}
};
private static final Closure<String> REPLACE_HEX_ESCAPES = new Closure<String>(null, null) {
String doCall(String _0, String _1, String _2) {
if (isLengthOdd(_1)) return _0;
return _1 + new String(Character.toChars(Integer.parseInt(_2, 16)));
}
};
private static final Closure<String> REPLACE_LINE_ESCAPE = new Closure<String>(null, null) {
String doCall(String _0, String _1) {
if (isLengthOdd(_1)) return _0;
return _1;
}
};
}

0 comments on commit e3491f5

Please # to comment.