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