001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1997-1999 Raja Vallee-Rai
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: /* 04.04.2006 mbatch added handling of \r, as compilers throw error if unicode */
027:
028: package soot.util;
029:
030: import java.text.*;
031:
032: /** Utility methods for string manipulations commonly used in Soot. */
033: public class StringTools {
034:
035: /** Returns fromString, but with non-isalpha() characters printed as
036: * <code>'\\unnnn'</code>. Used by SootClass to generate output. */
037: public static java.lang.String getEscapedStringOf(String fromString) {
038: char[] fromStringArray;
039: int cr, lf, ch;
040: StringBuffer whole = new StringBuffer();
041: StringBuffer mini = new StringBuffer();
042:
043: fromStringArray = fromString.toCharArray();
044:
045: cr = lineSeparator.charAt(0);
046: lf = -1;
047:
048: if (lineSeparator.length() == 2)
049: lf = lineSeparator.charAt(1);
050:
051: for (char element : fromStringArray) {
052: ch = element;
053: if (((ch >= 32 && ch <= 126) || ch == cr || ch == lf)
054: && ch != '\\') {
055: whole.append((char) ch);
056:
057: continue;
058: }
059:
060: mini.setLength(0);
061: mini.append(Integer.toHexString(ch));
062:
063: while (mini.length() < 4)
064: mini.insert(0, "0");
065:
066: mini.insert(0, "\\u");
067: whole.append(mini.toString());
068: }
069:
070: return whole.toString();
071: }
072:
073: /** Convenience field storing the system line separator. */
074: public final static String lineSeparator = System
075: .getProperty("line.separator");;
076:
077: /** Returns fromString, but with certain characters printed as
078: * if they were in a Java string literal.
079: * Used by StringConstant.toString() */
080: public static java.lang.String getQuotedStringOf(String fromString) {
081: StringBuffer toStringBuffer;
082: char[] fromStringArray;
083:
084: toStringBuffer = new java.lang.StringBuffer();
085: fromStringArray = fromString.toCharArray();
086:
087: toStringBuffer.append("\"");
088:
089: for (char ch : fromStringArray) {
090: {
091: if (ch == '\\') {
092: toStringBuffer.append("\\\\");
093: continue;
094: }
095: if (ch == '\'') {
096: toStringBuffer.append("\\\'");
097: continue;
098: }
099: if (ch == '\"') {
100: toStringBuffer.append("\\\"");
101: continue;
102: }
103: if (ch == '\n') {
104: toStringBuffer.append("\\n");
105: continue;
106: }
107: if (ch == '\t') {
108: toStringBuffer.append("\\t");
109: continue;
110: }
111: /* 04.04.2006 mbatch added handling of \r, as compilers throw error if unicode */
112: if (ch == '\r') {
113: toStringBuffer.append("\\r");
114: continue;
115: }
116: /* 10.04.2006 Nomait A Naeem added handling of \f, as compilers throw error if unicode */
117: if (ch == '\f') {
118: toStringBuffer.append("\\f");
119: continue;
120: } else if (ch >= 32 && ch <= 126) {
121: toStringBuffer.append(ch);
122: continue;
123: }
124: }
125:
126: toStringBuffer.append(getUnicodeStringFromChar(ch));
127: }
128:
129: toStringBuffer.append("\"");
130: return toStringBuffer.toString();
131: }
132:
133: /** Returns a String containing the escaped <code>\\unnnn</code>
134: * representation for <code>ch</code>. */
135: public static String getUnicodeStringFromChar(char ch) {
136: String s = Integer.toHexString(ch);
137: String padding = null;
138:
139: switch (s.length()) {
140: case 1:
141: padding = "000";
142: break;
143: case 2:
144: padding = "00";
145: break;
146: case 3:
147: padding = "0";
148: break;
149: case 4:
150: padding = "";
151: break;
152: }
153:
154: return "\\u" + padding + s;
155: }
156:
157: /** Returns a String de-escaping the <code>\\unnnn</code>
158: * representation for any escaped characters in the string. */
159: public static String getUnEscapedStringOf(String str) {
160: StringBuffer buf = new StringBuffer();
161: CharacterIterator iter = new StringCharacterIterator(str);
162:
163: for (char ch = iter.first(); ch != CharacterIterator.DONE; ch = iter
164: .next()) {
165: if (ch != '\\')
166: buf.append(ch);
167: else { // enter escaped mode
168: ch = iter.next();
169: char format;
170:
171: if (ch == '\\')
172: buf.append(ch);
173: else if ((format = getCFormatChar(ch)) != '\0')
174: buf.append(format);
175: else if (ch == 'u') { //enter unicode mode
176: StringBuffer mini = new StringBuffer(4);
177: for (int i = 0; i < 4; i++)
178: mini.append(iter.next());
179:
180: ch = (char) Integer.parseInt(mini.toString(), 16);
181: buf.append(ch);
182: } else {
183: throw new RuntimeException("Unexpected char: " + ch);
184: }
185: }
186: }
187: return buf.toString();
188: }
189:
190: /** Returns the canonical C-string representation of c. */
191: public static char getCFormatChar(char c) {
192: char res;
193:
194: switch (c) {
195: case 'n':
196: res = '\n';
197: break;
198: case 't':
199: res = '\t';
200: break;
201: case 'r':
202: res = '\r';
203: break;
204: case 'b':
205: res = '\b';
206: break;
207: case '\"':
208: res = '\"';
209: break;
210: case '\'':
211: res = '\'';
212: break;
213:
214: default:
215: res = '\0';
216: break;
217: }
218: return res;
219: }
220:
221: /**
222: * Replaces all occurrences of the given substring with the
223: * given replacement string.
224: *
225: * @param orig The string in which all occurrences of the substring
226: * are to be replaced.
227: *
228: * @param toBeReplaced The substring which is to be replaced.
229: *
230: * @param replacment The string which is to replace
231: * <code>toBeReplaced</code>.
232: *
233: * @return The resulting {@link String}.
234: *
235: * <p>This method provides a facility similar to the
236: * String.replaceAll() method available in Java 1.4, except that
237: * it can only replace substrings rather than regular expressions.
238: * So if Soot ever abandons compatibility with pre-1.4
239: * definitions of the Java API, it can also abandon replaceAllIn().
240: */
241: public static String replaceAll(String orig, String toBeReplaced,
242: String replacement) {
243: int quarryLength = toBeReplaced.length();
244: if (quarryLength <= 0) {
245: return orig;
246: }
247:
248: int index = orig.indexOf(toBeReplaced);
249: if (index < 0) {
250: return orig;
251: } else {
252: int from = 0;
253: StringBuffer sb;
254: if (quarryLength < replacement.length()) {
255: sb = new StringBuffer(orig.length());
256: } else {
257: sb = new StringBuffer(orig.length() * 2);
258: }
259:
260: do {
261: sb.append(orig.substring(from, index));
262: sb.append(replacement);
263: from = index + quarryLength;
264: index = orig.indexOf(toBeReplaced, from);
265: } while (index >= 0);
266:
267: sb.append(orig.substring(from));
268: return sb.toString();
269: }
270: }
271: }
|