1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.util;
16
17 import java.util.NoSuchElementException;
18 import java.util.StringTokenizer;
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public class QuotedStringTokenizer
33 extends StringTokenizer
34 {
35 private final static String __delim="\t\n\r";
36 private String _string;
37 private String _delim = __delim;
38 private boolean _returnQuotes=false;
39 private boolean _returnDelimiters=false;
40 private StringBuffer _token;
41 private boolean _hasToken=false;
42 private int _i=0;
43 private int _lastStart=0;
44 private boolean _double=true;
45 private boolean _single=true;
46
47
48 public QuotedStringTokenizer(String str,
49 String delim,
50 boolean returnDelimiters,
51 boolean returnQuotes)
52 {
53 super("");
54 _string=str;
55 if (delim!=null)
56 _delim=delim;
57 _returnDelimiters=returnDelimiters;
58 _returnQuotes=returnQuotes;
59
60 if (_delim.indexOf('\'')>=0 ||
61 _delim.indexOf('"')>=0)
62 throw new Error("Can't use quotes as delimiters: "+_delim);
63
64 _token=new StringBuffer(_string.length()>1024?512:_string.length()/2);
65 }
66
67
68 public QuotedStringTokenizer(String str,
69 String delim,
70 boolean returnDelimiters)
71 {
72 this(str,delim,returnDelimiters,false);
73 }
74
75
76 public QuotedStringTokenizer(String str,
77 String delim)
78 {
79 this(str,delim,false,false);
80 }
81
82
83 public QuotedStringTokenizer(String str)
84 {
85 this(str,null,false,false);
86 }
87
88
89 public boolean hasMoreTokens()
90 {
91
92 if (_hasToken)
93 return true;
94
95 _lastStart=_i;
96
97 int state=0;
98 boolean escape=false;
99 while (_i<_string.length())
100 {
101 char c=_string.charAt(_i++);
102
103 switch (state)
104 {
105 case 0:
106 if(_delim.indexOf(c)>=0)
107 {
108 if (_returnDelimiters)
109 {
110 _token.append(c);
111 return _hasToken=true;
112 }
113 }
114 else if (c=='\'' && _single)
115 {
116 if (_returnQuotes)
117 _token.append(c);
118 state=2;
119 }
120 else if (c=='\"' && _double)
121 {
122 if (_returnQuotes)
123 _token.append(c);
124 state=3;
125 }
126 else
127 {
128 _token.append(c);
129 _hasToken=true;
130 state=1;
131 }
132 continue;
133
134 case 1:
135 _hasToken=true;
136 if(_delim.indexOf(c)>=0)
137 {
138 if (_returnDelimiters)
139 _i--;
140 return _hasToken;
141 }
142 else if (c=='\'' && _single)
143 {
144 if (_returnQuotes)
145 _token.append(c);
146 state=2;
147 }
148 else if (c=='\"' && _double)
149 {
150 if (_returnQuotes)
151 _token.append(c);
152 state=3;
153 }
154 else
155 _token.append(c);
156 continue;
157
158
159 case 2:
160 _hasToken=true;
161 if (escape)
162 {
163 escape=false;
164 _token.append(c);
165 }
166 else if (c=='\'')
167 {
168 if (_returnQuotes)
169 _token.append(c);
170 state=1;
171 }
172 else if (c=='\\')
173 {
174 if (_returnQuotes)
175 _token.append(c);
176 escape=true;
177 }
178 else
179 _token.append(c);
180 continue;
181
182
183 case 3:
184 _hasToken=true;
185 if (escape)
186 {
187 escape=false;
188 _token.append(c);
189 }
190 else if (c=='\"')
191 {
192 if (_returnQuotes)
193 _token.append(c);
194 state=1;
195 }
196 else if (c=='\\')
197 {
198 if (_returnQuotes)
199 _token.append(c);
200 escape=true;
201 }
202 else
203 _token.append(c);
204 continue;
205 }
206 }
207
208 return _hasToken;
209 }
210
211
212 public String nextToken()
213 throws NoSuchElementException
214 {
215 if (!hasMoreTokens() || _token==null)
216 throw new NoSuchElementException();
217 String t=_token.toString();
218 _token.setLength(0);
219 _hasToken=false;
220 return t;
221 }
222
223
224 public String nextToken(String delim)
225 throws NoSuchElementException
226 {
227 _delim=delim;
228 _i=_lastStart;
229 _token.setLength(0);
230 _hasToken=false;
231 return nextToken();
232 }
233
234
235 public boolean hasMoreElements()
236 {
237 return hasMoreTokens();
238 }
239
240
241 public Object nextElement()
242 throws NoSuchElementException
243 {
244 return nextToken();
245 }
246
247
248
249
250 public int countTokens()
251 {
252 return -1;
253 }
254
255
256
257
258
259
260
261
262
263
264 public static String quote(String s, String delim)
265 {
266 if (s==null)
267 return null;
268 if (s.length()==0)
269 return "\"\"";
270
271
272 for (int i=0;i<s.length();i++)
273 {
274 char c = s.charAt(i);
275 if (c=='\\' || c=='"' || c=='\'' || Character.isWhitespace(c) || delim.indexOf(c)>=0)
276 {
277 StringBuffer b=new StringBuffer(s.length()+8);
278 quote(b,s);
279 return b.toString();
280 }
281 }
282
283 return s;
284 }
285
286
287
288
289
290
291
292
293
294 public static String quote(String s)
295 {
296 if (s==null)
297 return null;
298 if (s.length()==0)
299 return "\"\"";
300
301 StringBuffer b=new StringBuffer(s.length()+8);
302 quote(b,s);
303 return b.toString();
304
305 }
306
307
308
309
310
311
312
313
314 public static void quote(StringBuffer buf, String s)
315 {
316 synchronized(buf)
317 {
318 buf.append('"');
319
320 int i=0;
321 loop:
322 for (;i<s.length();i++)
323 {
324 char c = s.charAt(i);
325 switch(c)
326 {
327 case '"':
328 buf.append(s,0,i);
329 buf.append("\\\"");
330 break loop;
331 case '\\':
332 buf.append(s,0,i);
333 buf.append("\\\\");
334 break loop;
335 case '\n':
336 buf.append(s,0,i);
337 buf.append("\\n");
338 break loop;
339 case '\r':
340 buf.append(s,0,i);
341 buf.append("\\r");
342 break loop;
343 case '\t':
344 buf.append(s,0,i);
345 buf.append("\\t");
346 break loop;
347 case '\f':
348 buf.append(s,0,i);
349 buf.append("\\f");
350 break loop;
351 case '\b':
352 buf.append(s,0,i);
353 buf.append("\\b");
354 break loop;
355
356 default:
357 continue;
358 }
359 }
360 if (i==s.length())
361 buf.append(s);
362 else
363 {
364 i++;
365 for (;i<s.length();i++)
366 {
367 char c = s.charAt(i);
368 switch(c)
369 {
370 case '"':
371 buf.append("\\\"");
372 continue;
373 case '\\':
374 buf.append("\\\\");
375 continue;
376 case '\n':
377 buf.append("\\n");
378 continue;
379 case '\r':
380 buf.append("\\r");
381 continue;
382 case '\t':
383 buf.append("\\t");
384 continue;
385 case '\f':
386 buf.append("\\f");
387 continue;
388 case '\b':
389 buf.append("\\b");
390 continue;
391
392 default:
393 buf.append(c);
394 continue;
395 }
396 }
397 }
398
399 buf.append('"');
400 }
401
402
403
404 }
405
406
407
408
409
410
411
412
413
414
415
416 public static void quoteIfNeeded(StringBuffer buf, String s)
417 {
418 synchronized(buf)
419 {
420 int e=-1;
421
422 search: for (int i=0;i<s.length();i++)
423 {
424 char c = s.charAt(i);
425 switch(c)
426 {
427 case '"':
428 case '\\':
429 case '\n':
430 case '\r':
431 case '\t':
432 case '\f':
433 case '\b':
434 case '%':
435 case '+':
436 case ' ':
437 e=i;
438 buf.append('"');
439
440 for (int j=0;j<e;j++)
441 buf.append(s.charAt(j));
442 break search;
443
444 default:
445 continue;
446 }
447 }
448
449 if (e<0)
450 {
451 buf.append(s);
452 return;
453 }
454
455 for (int i=e;i<s.length();i++)
456 {
457 char c = s.charAt(i);
458 switch(c)
459 {
460 case '"':
461 buf.append("\\\"");
462 continue;
463 case '\\':
464 buf.append("\\\\");
465 continue;
466 case '\n':
467 buf.append("\\n");
468 continue;
469 case '\r':
470 buf.append("\\r");
471 continue;
472 case '\t':
473 buf.append("\\t");
474 continue;
475 case '\f':
476 buf.append("\\f");
477 continue;
478 case '\b':
479 buf.append("\\b");
480 continue;
481
482 default:
483 buf.append(c);
484 continue;
485 }
486 }
487 buf.append('"');
488 }
489 }
490
491
492
493
494
495
496 public static String unquote(String s)
497 {
498 if (s==null)
499 return null;
500 if (s.length()<2)
501 return s;
502
503 char first=s.charAt(0);
504 char last=s.charAt(s.length()-1);
505 if (first!=last || (first!='"' && first!='\''))
506 return s;
507
508 StringBuffer b=new StringBuffer(s.length()-2);
509 synchronized(b)
510 {
511 boolean escape=false;
512 for (int i=1;i<s.length()-1;i++)
513 {
514 char c = s.charAt(i);
515
516 if (escape)
517 {
518 escape=false;
519 switch (c)
520 {
521 case 'n':
522 b.append('\n');
523 break;
524 case 'r':
525 b.append('\r');
526 break;
527 case 't':
528 b.append('\t');
529 break;
530 case 'f':
531 b.append('\f');
532 break;
533 case 'b':
534 b.append('\b');
535 break;
536 case 'u':
537 b.append((char)(
538 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+
539 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+
540 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+
541 (TypeUtil.convertHexDigit((byte)s.charAt(i++)))
542 )
543 );
544 break;
545 default:
546 b.append(c);
547 }
548 }
549 else if (c=='\\')
550 {
551 escape=true;
552 continue;
553 }
554 else
555 b.append(c);
556 }
557
558 return b.toString();
559 }
560 }
561
562
563
564
565
566 public boolean getDouble()
567 {
568 return _double;
569 }
570
571
572
573
574
575 public void setDouble(boolean d)
576 {
577 _double=d;
578 }
579
580
581
582
583
584 public boolean getSingle()
585 {
586 return _single;
587 }
588
589
590
591
592
593 public void setSingle(boolean single)
594 {
595 _single=single;
596 }
597 }
598
599
600
601
602
603
604
605
606
607
608
609