001: /*
002: * SplitCmd.java
003: *
004: * Copyright (c) 1997 Sun Microsystems, Inc.
005: *
006: * See the file "license.terms" for information on usage and
007: * redistribution of this file, and for a DISCLAIMER OF ALL
008: * WARRANTIES.
009: *
010: * RCS: @(#) $Id: SplitCmd.java,v 1.3 2006/06/06 04:48:03 mdejong Exp $
011: *
012: */
013:
014: package tcl.lang;
015:
016: /**
017: * This class implements the built-in "split" command in Tcl.
018: */
019:
020: class SplitCmd implements Command {
021:
022: // Default characters for splitting up strings.
023:
024: private final static char defSplitChars[] = { ' ', '\n', '\t', '\r' };
025:
026: /**
027: * This procedure is invoked to process the "split" Tcl
028: * command. See Tcl user documentation for details.
029: *
030: * @param interp the current interpreter.
031: * @param objv command arguments.
032: * @exception TclException If incorrect number of arguments.
033: */
034:
035: public void cmdProc(Interp interp, TclObject[] objv)
036: throws TclException {
037: int numSplitChars;
038: String splitString = null;
039:
040: if (objv.length == 2) {
041: numSplitChars = defSplitChars.length;
042: } else if (objv.length == 3) {
043: splitString = objv[2].toString();
044: if (splitString.equals("")) {
045: numSplitChars = 0;
046: } else if (splitString.length() == 1) {
047: numSplitChars = 1;
048: } else {
049: numSplitChars = splitString.length();
050: }
051: } else {
052: throw new TclNumArgsException(interp, 1, objv,
053: "string ?splitChars?");
054: }
055:
056: String string = objv[1].toString();
057: final int slen = string.length();
058: int elemStart = 0;
059: int i = 0;
060:
061: TclObject list = TclList.newInstance();
062: list.preserve();
063:
064: try {
065: if (numSplitChars == 0) {
066: // Splitting on every character.
067:
068: for (; i < slen; i++) {
069: TclObject tobj = interp.checkCommonCharacter(string
070: .charAt(i));
071: if (tobj == null) {
072: tobj = TclString.newInstance(string.substring(
073: i, i + 1));
074: }
075: TclList.append(interp, list, tobj);
076: }
077: } else if (numSplitChars == 1) {
078: // Splitting on one character.
079: // Discard instances of the split character.
080:
081: char splitChar = splitString.charAt(0);
082:
083: for (; i < slen; i++) {
084: if (string.charAt(i) == splitChar) {
085: appendElement(interp, list, string, elemStart,
086: i);
087: elemStart = i + 1;
088: }
089: }
090: if (i != 0) {
091: appendElement(interp, list, string, elemStart, i);
092: }
093: } else {
094: // Splitting on any char in a group of character.
095: // Discard instances of the split characters.
096:
097: char[] splitChars;
098: if (objv.length == 2) {
099: splitChars = defSplitChars;
100: } else {
101: splitChars = splitString.toCharArray();
102: }
103:
104: for (; i < slen; i++) {
105: char c = string.charAt(i);
106: for (int j = 0; j < numSplitChars; j++) {
107: if (c == splitChars[j]) {
108: appendElement(interp, list, string,
109: elemStart, i);
110: elemStart = i + 1;
111: break;
112: }
113: }
114: }
115: if (i != 0) {
116: appendElement(interp, list, string, elemStart, i);
117: }
118: }
119:
120: interp.setResult(list);
121: } finally {
122: list.release();
123: }
124: }
125:
126: // Util method used to append a string range
127: // to a TclList. The range might indicate
128: // an empty string or a single character, so
129: // use shared objects to optimize those cases.
130:
131: static void appendElement(Interp interp, TclObject list,
132: String string, int starti, int endi) throws TclException {
133: TclObject tobj;
134:
135: switch (endi - starti) {
136: case 0: {
137: tobj = interp.checkCommonString(null);
138: break;
139: }
140: case 1: {
141: tobj = interp.checkCommonCharacter(string.charAt(starti));
142: if (tobj != null) {
143: break;
144: }
145: // Fall through when not a common character
146: }
147: default: {
148: tobj = TclString
149: .newInstance(string.substring(starti, endi));
150: break;
151: }
152: }
153:
154: TclList.append(interp, list, tobj);
155: return;
156: }
157:
158: }
|