@Test public void substitute() { assertEquals("bar", new Substitutor(singletonMap("foo", "bar")).replace("${foo}")); }
private int substitute(final StringBuilder buf, final int offset, final int length, List<String> priorVariables) { final boolean top = priorVariables == null; boolean altered = false; int lengthChange = 0; char[] chars = buf.toString().toCharArray(); int bufEnd = offset + length; int pos = offset; while (pos < bufEnd) { final int startMatchLen = isMatch(PREFIX, chars, pos, bufEnd); if (startMatchLen == 0) { pos++; } else { if (pos > offset && chars[pos - 1] == ESCAPE) { buf.deleteCharAt(pos - 1); chars = buf.toString().toCharArray(); lengthChange--; altered = true; bufEnd--; } else { final int startPos = pos; pos += startMatchLen; int endMatchLen; while (pos < bufEnd) { endMatchLen = isMatch(SUFFIX, chars, pos, bufEnd); if (endMatchLen == 0) { pos++; } else { String varNameExpr = new String(chars, startPos + startMatchLen, pos - startPos - startMatchLen); pos += endMatchLen; final int endPos = pos; String varName = varNameExpr; String varDefaultValue = null; final char[] varNameExprChars = varNameExpr.toCharArray(); for (int i = 0; i < varNameExprChars.length; i++) { if (isMatch(PREFIX, varNameExprChars, i, varNameExprChars.length) != 0) { break; } final int match = isMatch(VALUE_DELIMITER, varNameExprChars, i, varNameExprChars.length); if (match != 0) { varName = varNameExpr.substring(0, i); varDefaultValue = varNameExpr.substring(i + match); break; } } if (priorVariables == null) { priorVariables = new ArrayList<>(); priorVariables.add(new String(chars, offset, length)); } checkCyclicSubstitution(varName, priorVariables); priorVariables.add(varName); final String varValue = getOrDefault(varName, varDefaultValue); if (varValue != null) { final int varLen = varValue.length(); buf.replace(startPos, endPos, varValue); altered = true; int change = substitute(buf, startPos, varLen, priorVariables); change = change + varLen - (endPos - startPos); pos += change; bufEnd += change; lengthChange += change; chars = buf.toString().toCharArray(); } priorVariables.remove(priorVariables.size() - 1); break; } } } } } if (top) { return altered ? 1 : 0; } return lengthChange; }
Substitutor { private int substitute(final StringBuilder buf, final int offset, final int length, List<String> priorVariables) { final boolean top = priorVariables == null; boolean altered = false; int lengthChange = 0; char[] chars = buf.toString().toCharArray(); int bufEnd = offset + length; int pos = offset; while (pos < bufEnd) { final int startMatchLen = isMatch(PREFIX, chars, pos, bufEnd); if (startMatchLen == 0) { pos++; } else { if (pos > offset && chars[pos - 1] == ESCAPE) { buf.deleteCharAt(pos - 1); chars = buf.toString().toCharArray(); lengthChange--; altered = true; bufEnd--; } else { final int startPos = pos; pos += startMatchLen; int endMatchLen; while (pos < bufEnd) { endMatchLen = isMatch(SUFFIX, chars, pos, bufEnd); if (endMatchLen == 0) { pos++; } else { String varNameExpr = new String(chars, startPos + startMatchLen, pos - startPos - startMatchLen); pos += endMatchLen; final int endPos = pos; String varName = varNameExpr; String varDefaultValue = null; final char[] varNameExprChars = varNameExpr.toCharArray(); for (int i = 0; i < varNameExprChars.length; i++) { if (isMatch(PREFIX, varNameExprChars, i, varNameExprChars.length) != 0) { break; } final int match = isMatch(VALUE_DELIMITER, varNameExprChars, i, varNameExprChars.length); if (match != 0) { varName = varNameExpr.substring(0, i); varDefaultValue = varNameExpr.substring(i + match); break; } } if (priorVariables == null) { priorVariables = new ArrayList<>(); priorVariables.add(new String(chars, offset, length)); } checkCyclicSubstitution(varName, priorVariables); priorVariables.add(varName); final String varValue = getOrDefault(varName, varDefaultValue); if (varValue != null) { final int varLen = varValue.length(); buf.replace(startPos, endPos, varValue); altered = true; int change = substitute(buf, startPos, varLen, priorVariables); change = change + varLen - (endPos - startPos); pos += change; bufEnd += change; lengthChange += change; chars = buf.toString().toCharArray(); } priorVariables.remove(priorVariables.size() - 1); break; } } } } } if (top) { return altered ? 1 : 0; } return lengthChange; } }
Substitutor { private int substitute(final StringBuilder buf, final int offset, final int length, List<String> priorVariables) { final boolean top = priorVariables == null; boolean altered = false; int lengthChange = 0; char[] chars = buf.toString().toCharArray(); int bufEnd = offset + length; int pos = offset; while (pos < bufEnd) { final int startMatchLen = isMatch(PREFIX, chars, pos, bufEnd); if (startMatchLen == 0) { pos++; } else { if (pos > offset && chars[pos - 1] == ESCAPE) { buf.deleteCharAt(pos - 1); chars = buf.toString().toCharArray(); lengthChange--; altered = true; bufEnd--; } else { final int startPos = pos; pos += startMatchLen; int endMatchLen; while (pos < bufEnd) { endMatchLen = isMatch(SUFFIX, chars, pos, bufEnd); if (endMatchLen == 0) { pos++; } else { String varNameExpr = new String(chars, startPos + startMatchLen, pos - startPos - startMatchLen); pos += endMatchLen; final int endPos = pos; String varName = varNameExpr; String varDefaultValue = null; final char[] varNameExprChars = varNameExpr.toCharArray(); for (int i = 0; i < varNameExprChars.length; i++) { if (isMatch(PREFIX, varNameExprChars, i, varNameExprChars.length) != 0) { break; } final int match = isMatch(VALUE_DELIMITER, varNameExprChars, i, varNameExprChars.length); if (match != 0) { varName = varNameExpr.substring(0, i); varDefaultValue = varNameExpr.substring(i + match); break; } } if (priorVariables == null) { priorVariables = new ArrayList<>(); priorVariables.add(new String(chars, offset, length)); } checkCyclicSubstitution(varName, priorVariables); priorVariables.add(varName); final String varValue = getOrDefault(varName, varDefaultValue); if (varValue != null) { final int varLen = varValue.length(); buf.replace(startPos, endPos, varValue); altered = true; int change = substitute(buf, startPos, varLen, priorVariables); change = change + varLen - (endPos - startPos); pos += change; bufEnd += change; lengthChange += change; chars = buf.toString().toCharArray(); } priorVariables.remove(priorVariables.size() - 1); break; } } } } } if (top) { return altered ? 1 : 0; } return lengthChange; } Substitutor(final Map<String, String> valueMap); }
Substitutor { private int substitute(final StringBuilder buf, final int offset, final int length, List<String> priorVariables) { final boolean top = priorVariables == null; boolean altered = false; int lengthChange = 0; char[] chars = buf.toString().toCharArray(); int bufEnd = offset + length; int pos = offset; while (pos < bufEnd) { final int startMatchLen = isMatch(PREFIX, chars, pos, bufEnd); if (startMatchLen == 0) { pos++; } else { if (pos > offset && chars[pos - 1] == ESCAPE) { buf.deleteCharAt(pos - 1); chars = buf.toString().toCharArray(); lengthChange--; altered = true; bufEnd--; } else { final int startPos = pos; pos += startMatchLen; int endMatchLen; while (pos < bufEnd) { endMatchLen = isMatch(SUFFIX, chars, pos, bufEnd); if (endMatchLen == 0) { pos++; } else { String varNameExpr = new String(chars, startPos + startMatchLen, pos - startPos - startMatchLen); pos += endMatchLen; final int endPos = pos; String varName = varNameExpr; String varDefaultValue = null; final char[] varNameExprChars = varNameExpr.toCharArray(); for (int i = 0; i < varNameExprChars.length; i++) { if (isMatch(PREFIX, varNameExprChars, i, varNameExprChars.length) != 0) { break; } final int match = isMatch(VALUE_DELIMITER, varNameExprChars, i, varNameExprChars.length); if (match != 0) { varName = varNameExpr.substring(0, i); varDefaultValue = varNameExpr.substring(i + match); break; } } if (priorVariables == null) { priorVariables = new ArrayList<>(); priorVariables.add(new String(chars, offset, length)); } checkCyclicSubstitution(varName, priorVariables); priorVariables.add(varName); final String varValue = getOrDefault(varName, varDefaultValue); if (varValue != null) { final int varLen = varValue.length(); buf.replace(startPos, endPos, varValue); altered = true; int change = substitute(buf, startPos, varLen, priorVariables); change = change + varLen - (endPos - startPos); pos += change; bufEnd += change; lengthChange += change; chars = buf.toString().toCharArray(); } priorVariables.remove(priorVariables.size() - 1); break; } } } } } if (top) { return altered ? 1 : 0; } return lengthChange; } Substitutor(final Map<String, String> valueMap); String replace(final String source); }
Substitutor { private int substitute(final StringBuilder buf, final int offset, final int length, List<String> priorVariables) { final boolean top = priorVariables == null; boolean altered = false; int lengthChange = 0; char[] chars = buf.toString().toCharArray(); int bufEnd = offset + length; int pos = offset; while (pos < bufEnd) { final int startMatchLen = isMatch(PREFIX, chars, pos, bufEnd); if (startMatchLen == 0) { pos++; } else { if (pos > offset && chars[pos - 1] == ESCAPE) { buf.deleteCharAt(pos - 1); chars = buf.toString().toCharArray(); lengthChange--; altered = true; bufEnd--; } else { final int startPos = pos; pos += startMatchLen; int endMatchLen; while (pos < bufEnd) { endMatchLen = isMatch(SUFFIX, chars, pos, bufEnd); if (endMatchLen == 0) { pos++; } else { String varNameExpr = new String(chars, startPos + startMatchLen, pos - startPos - startMatchLen); pos += endMatchLen; final int endPos = pos; String varName = varNameExpr; String varDefaultValue = null; final char[] varNameExprChars = varNameExpr.toCharArray(); for (int i = 0; i < varNameExprChars.length; i++) { if (isMatch(PREFIX, varNameExprChars, i, varNameExprChars.length) != 0) { break; } final int match = isMatch(VALUE_DELIMITER, varNameExprChars, i, varNameExprChars.length); if (match != 0) { varName = varNameExpr.substring(0, i); varDefaultValue = varNameExpr.substring(i + match); break; } } if (priorVariables == null) { priorVariables = new ArrayList<>(); priorVariables.add(new String(chars, offset, length)); } checkCyclicSubstitution(varName, priorVariables); priorVariables.add(varName); final String varValue = getOrDefault(varName, varDefaultValue); if (varValue != null) { final int varLen = varValue.length(); buf.replace(startPos, endPos, varValue); altered = true; int change = substitute(buf, startPos, varLen, priorVariables); change = change + varLen - (endPos - startPos); pos += change; bufEnd += change; lengthChange += change; chars = buf.toString().toCharArray(); } priorVariables.remove(priorVariables.size() - 1); break; } } } } } if (top) { return altered ? 1 : 0; } return lengthChange; } Substitutor(final Map<String, String> valueMap); String replace(final String source);  }