1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.parser;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public class StringParser {
37
38 protected StringParser() {
39
40 }
41
42
43
44
45
46
47
48 public static String buildString(final CharSequence str, final boolean eatsep) {
49 return buildString(str, eatsep, true);
50 }
51
52
53
54
55
56
57
58 public static String buildTemplate(final CharSequence str, final boolean eatsep) {
59 return buildString(str, eatsep, false);
60 }
61
62
63
64
65
66
67
68
69 private static String buildString(final CharSequence str, final boolean eatsep, final boolean esc) {
70 final StringBuilder strb = new StringBuilder(str.length());
71 final char sep = eatsep ? str.charAt(0) : 0;
72 final int end = str.length() - (eatsep ? 1 : 0);
73 final int begin = (eatsep ? 1 : 0);
74 read(strb, str, begin, end, sep, esc);
75 return strb.toString();
76 }
77
78
79
80
81
82
83 public static String buildRegex(final CharSequence str) {
84 return buildString(str.subSequence(1, str.length()), true);
85 }
86
87
88
89
90
91
92
93
94
95
96 public static int readString(final StringBuilder strb, final CharSequence str, final int index, final char sep) {
97 return read(strb, str, index, str.length(), sep, true);
98 }
99
100 private static final int UCHAR_LEN = 4;
101
102
103
104
105
106
107
108
109
110
111
112
113 private static int read(final StringBuilder strb, final CharSequence str, final int begin, final int end, final char sep, final boolean esc) {
114 boolean escape = false;
115 int index = begin;
116 for (; index < end; ++index) {
117 final char c = str.charAt(index);
118 if (escape) {
119 if (c == 'u' && (index + UCHAR_LEN) < end && readUnicodeChar(strb, str, index + 1) > 0) {
120 index += UCHAR_LEN;
121 } else {
122
123 final boolean notSeparator = sep == 0 ? c != '\'' && c != '"' : c != sep;
124 if (notSeparator && c != '\\') {
125 if (!esc) {
126 strb.append('\\').append(c);
127 } else {
128 switch (c) {
129
130 case 'b':
131 strb.append('\b');
132 break;
133 case 't':
134 strb.append('\t');
135 break;
136 case 'n':
137 strb.append('\n');
138 break;
139
140 case 'f':
141 strb.append('\f');
142 break;
143 case 'r':
144 strb.append('\r');
145 break;
146 default:
147 strb.append('\\').append(c);
148 }
149 }
150 } else {
151 strb.append(c);
152 }
153 }
154 escape = false;
155 continue;
156 }
157 if (c == '\\') {
158 escape = true;
159 continue;
160 }
161 strb.append(c);
162 if (c == sep) {
163 break;
164 }
165 }
166 return index;
167 }
168
169 private static final int SHIFT = 12;
170
171 private static final int BASE10 = 10;
172
173
174
175
176
177
178
179
180 private static int readUnicodeChar(final StringBuilder strb, final CharSequence str, final int begin) {
181 char xc = 0;
182 int bits = SHIFT;
183 int value;
184 for (int offset = 0; offset < UCHAR_LEN; ++offset) {
185 final char c = str.charAt(begin + offset);
186 if (c >= '0' && c <= '9') {
187 value = (c - '0');
188 } else if (c >= 'a' && c <= 'h') {
189 value = (c - 'a' + BASE10);
190 } else if (c >= 'A' && c <= 'H') {
191 value = (c - 'A' + BASE10);
192 } else {
193 return 0;
194 }
195 xc |= value << bits;
196 bits -= UCHAR_LEN;
197 }
198 strb.append(xc);
199 return UCHAR_LEN;
200 }
201
202 private static final char LAST_ASCII = 127;
203
204 private static final char FIRST_ASCII = 32;
205
206
207
208
209
210
211
212 public static String escapeString(final String str, final char delim) {
213 if (str == null) {
214 return null;
215 }
216 final int length = str.length();
217 final StringBuilder strb = new StringBuilder(length + 2);
218 strb.append(delim);
219 for (int i = 0; i < length; ++i) {
220 final char c = str.charAt(i);
221 switch (c) {
222 case 0:
223 continue;
224 case '\b':
225 strb.append('\\');
226 strb.append('b');
227 break;
228 case '\t':
229 strb.append('\\');
230 strb.append('t');
231 break;
232 case '\n':
233 strb.append('\\');
234 strb.append('n');
235 break;
236 case '\f':
237 strb.append('\\');
238 strb.append('f');
239 break;
240 case '\r':
241 strb.append('\\');
242 strb.append('r');
243 break;
244 case '\\':
245 strb.append('\\');
246 strb.append('\\');
247 break;
248 default:
249 if (c == delim) {
250 strb.append('\\');
251 strb.append(delim);
252 } else if (c >= FIRST_ASCII && c <= LAST_ASCII) {
253 strb.append(c);
254 } else {
255
256 strb.append('\\');
257 strb.append('u');
258 final String hex = Integer.toHexString(c);
259 for (int h = hex.length(); h < UCHAR_LEN; ++h) {
260 strb.append('0');
261 }
262 strb.append(hex);
263 }
264 }
265 }
266 strb.append(delim);
267 return strb.toString();
268 }
269
270
271
272
273
274
275 public static String unescapeIdentifier(final String str) {
276 StringBuilder strb = null;
277 if (str != null) {
278 int n = 0;
279 final int last = str.length();
280 while (n < last) {
281 final char c = str.charAt(n);
282 if (c == '\\') {
283 if (strb == null) {
284 strb = new StringBuilder(last);
285 strb.append(str, 0, n);
286 }
287 } else if (strb != null) {
288 strb.append(c);
289 }
290 n += 1;
291 }
292 }
293 return strb == null ? str : strb.toString();
294 }
295
296
297
298
299
300
301 public static String escapeIdentifier(final String str) {
302 StringBuilder strb = null;
303 if (str != null) {
304 int n = 0;
305 final int last = str.length();
306 while (n < last) {
307 final char c = str.charAt(n);
308 switch (c) {
309 case ' ':
310 case '\'':
311 case '"':
312 case '\\': {
313 if (strb == null) {
314 strb = new StringBuilder(last);
315 strb.append(str, 0, n);
316 }
317 strb.append('\\');
318 strb.append(c);
319 break;
320 }
321 default:
322 if (strb != null) {
323 strb.append(c);
324 }
325 }
326 n += 1;
327 }
328 }
329 return strb == null ? str : strb.toString();
330 }
331 }