--- Perl5Substitution.java.orig Thu May 10 12:48:14 2001
+++ Perl5Substitution.java Fri May 11 10:32:37 2001
@@ -135,70 +135,155 @@
*/
public static final int INTERPOLATE_NONE = -1;
- int _numInterpolations;
- ArrayList _substitutions;
- transient String _lastInterpolation;
+ /**
+ * A constant declaring opcode for copy operation
+ */
+ public static final int OPCODE_COPY = -1;
- static ArrayList _parseSubs(String sub) {
- boolean saveDigits, storedInterpolation;
- int current;
- char[] str;
- ArrayList subs;
- StringBuffer numBuffer, strBuffer;
-
- subs = new ArrayList(5);
- numBuffer = new StringBuffer(5);
- strBuffer = new StringBuffer(10);
+ /**
+ * A constant declaring opcode for lowercase char operation
+ */
+ public static final int OPCODE_LOWERCASE_CHAR = -2;
- str = sub.toCharArray();
- current = 0;
- saveDigits = false;
- storedInterpolation = false;
+ /**
+ * A constant declaring opcode for uppercase char operation
+ */
+ public static final int OPCODE_UPPERCASE_CHAR = -3;
- while(current < str.length) {
- if(saveDigits && Character.isDigit(str[current])) {
- numBuffer.append(str[current]);
-
- if(strBuffer.length() > 0) {
- subs.add(strBuffer.toString());
- strBuffer.setLength(0);
- }
- } else {
- if(saveDigits) {
- try {
- subs.add(new Integer(numBuffer.toString()));
- storedInterpolation = true;
- } catch(NumberFormatException e) {
- subs.add(numBuffer.toString());
- }
+ /**
+ * A constant declaring opcode for lowercase mode operation
+ */
+ public static final int OPCODE_LOWERCASE_MODE = -4;
- numBuffer.setLength(0);
- saveDigits = false;
- }
+ /**
+ * A constant declaring opcode for lowercase mode operation
+ */
+ public static final int OPCODE_UPPERCASE_MODE = -5;
- if(str[current] == '$' &&
- current + 1 < str.length && str[current + 1] != '0' &&
- Character.isDigit(str[current + 1]))
- saveDigits = true;
- else
- strBuffer.append(str[current]);
+ /**
+ * A constant declaring opcode for lowercase mode operation
+ */
+ public static final int OPCODE_ENDCASE_MODE = -6;
+
+ private static final int OPCODE_STORAGE_SIZE = 32;
+
+ int _numInterpolations;
+ int[] _subOpcodes;
+ int _subOpcodesCount;
+ char[] _substitution_chars;
+ transient String _lastInterpolation;
+
+ private void addElement(int value) {
+ int len = _subOpcodes.length;
+ if (_subOpcodesCount == len) {
+ int[] newarray = new int[len + OPCODE_STORAGE_SIZE];
+ System.arraycopy(_subOpcodes, 0, newarray, 0, len);
+ _subOpcodes = newarray;
}
+ _subOpcodes[_subOpcodesCount++] = value;
+ }
- ++current;
- } // end while
+ private void _parseSubs(String sub) {
+ boolean saveDigits, escapeMode, caseMode;
+ int posParam;
+ int offset;
+
+ char[] sub_chars = _substitution_chars = sub.toCharArray();
+ int sub_length = sub_chars.length;
+
+ _subOpcodes = new int[OPCODE_STORAGE_SIZE];
+ _subOpcodesCount = 0;
+
+ posParam = 0;
+ offset = -1;
+ saveDigits = false;
+ escapeMode = false;
+ caseMode = false;
+ for (int current = 0; current < sub_length; current++) {
- if(saveDigits) {
- try {
- subs.add(new Integer(numBuffer.toString()));
- storedInterpolation = true;
- } catch(NumberFormatException e) {
- subs.add(numBuffer.toString());
- }
- } else if(strBuffer.length() > 0)
- subs.add(strBuffer.toString());
+ char c = sub_chars[current];
+ int next = current + 1;
+
+ // Save digits
+ if (saveDigits) {
+ int digit = Character.digit(c, 10);
+ if (digit > -1) {
+ if (posParam <= 32767) {
+ posParam *= 10;
+ posParam += digit;
+ }
+ if (next == sub_length) {
+ addElement(posParam);
+ }
+ continue;
+ }
+ addElement(posParam);
+ posParam = 0;
+ saveDigits = false;
+ }
+
+ // Copy
+ if ((c != '$' && c != '\\') || escapeMode) {
+ escapeMode = false;
+ if (offset < 0) {
+ offset = current;
+ addElement(OPCODE_COPY);
+ addElement(offset);
+ }
+ if (next == sub_length) {
+ addElement(next - offset);
+ }
+ continue;
+ }
+
+ // End Copy
+ if (offset >= 0) {
+ addElement(current - offset);
+ offset = -1;
+ }
+
+ // Only do positional and escapes if we have a next char
+ if (next == sub_length)
+ continue;
+ char nextc = sub_chars[next];
+
+ // Positional params
+ if (c == '$') {
+ saveDigits = (nextc != '0' && Character.isDigit(nextc));
+ }
+
+ // Escape codes
+ else if (c == '\\') {
+ if (nextc == 'l') {
+ if (!caseMode){
+ addElement(OPCODE_LOWERCASE_CHAR);
+ current++;
+ }
+ } else if (nextc == 'u') {
+ if (!caseMode) {
+ addElement(OPCODE_UPPERCASE_CHAR);
+ current++;
+ }
+ } else if (nextc == 'L') {
+ addElement(OPCODE_LOWERCASE_MODE);
+ current++;
+ caseMode = true;
+ } else if (nextc == 'U') {
+ addElement(OPCODE_UPPERCASE_MODE);
+ current++;
+ caseMode = true;
+ } else if (nextc == 'E') {
+ addElement(OPCODE_ENDCASE_MODE);
+ current++;
+ caseMode = false;
+ } else {
+ escapeMode = true;
+ }
+ }
+
+ }
- return (storedInterpolation ? subs : null);
}
@@ -209,33 +294,96 @@
}
void _calcSub(StringBuffer buffer, MatchResult result) {
- int size, value;
- Object obj;
- Integer integer;
+ int size, offset, count, caseMode;
String group;
- Iterator it;
+ char[] sub;
+
+ int[] subOpcodes = _subOpcodes;
- it = _substitutions.iterator();
+ caseMode = 0;
+ char[] str = _substitution_chars;
+ char[] match = result.group(0).toCharArray();
- while(it.hasNext()) {
- obj = it.next();
+ size = _subOpcodesCount;
- if(obj instanceof String)
- buffer.append(obj);
- else {
- integer = (Integer)obj;
- value = integer.intValue();
+ for (int element = 0; element < size; element++) {
+ int value = subOpcodes[element];
+
+ // Groups
if(value > 0 && value < result.groups()) {
- group = result.group(value);
- if(group != null)
- buffer.append(group);
- } else {
- buffer.append('$');
- buffer.append(value);
+ offset = result.begin(value);
+ if (offset < 0) continue;
+ int end = result.end(value);
+ if (end < 0) continue;
+
+ int len = result.length();
+
+ if (offset >= len || end > len || offset >= end) continue;
+
+ count = end - offset;
+ sub = match;
+
+ }
+
+ // Copy
+ else if (value == OPCODE_COPY) {
+ element++;
+ if (element >= size) continue;
+ offset = subOpcodes[element];
+ element++;
+ if (element >= size) continue;
+ count = subOpcodes[element];
+ sub = str;
+ }
+
+ // Case char
+ else if (value == OPCODE_LOWERCASE_CHAR || value ==
OPCODE_UPPERCASE_CHAR) {
+ if (caseMode != OPCODE_LOWERCASE_MODE && caseMode !=
OPCODE_UPPERCASE_MODE) {
+ caseMode = value;
+ }
+ continue;
+ }
+
+ // Case mode
+ else if (value == OPCODE_LOWERCASE_MODE || value ==
OPCODE_UPPERCASE_MODE) {
+ caseMode = value;
+ continue;
+ }
+
+ // Case mode end
+ else if (value == OPCODE_ENDCASE_MODE) {
+ caseMode = 0;
+ continue;
+ }
+
+ // Unknown
+ else {
+ continue;
}
- }
+
+ // Apply modes to buf
+ if (caseMode == OPCODE_LOWERCASE_CHAR) {
+ buffer.append(Character.toLowerCase(sub[offset++]));
+ buffer.append(sub, offset, --count);
+ caseMode = 0;
+ } else if (caseMode == OPCODE_UPPERCASE_CHAR) {
+ buffer.append(Character.toUpperCase(sub[offset++]));
+ buffer.append(sub, offset, --count);
+ caseMode = 0;
+ } else if (caseMode == OPCODE_LOWERCASE_MODE) {
+ for (int end = offset + count; offset < end; ) {
+ buffer.append(Character.toLowerCase(sub[offset++]));
+ }
+ } else if (caseMode == OPCODE_UPPERCASE_MODE) {
+ for (int end = offset + count; offset < end; ) {
+ buffer.append(Character.toUpperCase(sub[offset++]));
+ }
+ } else {
+ buffer.append(sub, offset, count);
+ }
+
}
}
@@ -324,10 +472,10 @@
_numInterpolations = numInterpolations;
if(numInterpolations != INTERPOLATE_NONE &&
- substitution.indexOf('$') != -1)
- _substitutions = _parseSubs(substitution);
+ (substitution.indexOf('$') != -1 || substitution.indexOf('\\') != -1))
+ _parseSubs(substitution);
else
- _substitutions = null;
+ _subOpcodes = null;
_lastInterpolation = null;
}
@@ -353,7 +501,7 @@
int substitutionCount, String originalInput,
PatternMatcher matcher, Pattern pattern)
{
- if(_substitutions == null) {
+ if(_subOpcodes == null) {
super.appendSubstitution(appendBuffer, match, substitutionCount,
originalInput, matcher, pattern);
return;