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 char[] chars = null;
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 chars = s.toCharArray();
329 buf.append(chars,0,i);
330 buf.append("\\\"");
331 break loop;
332 case '\\':
333 chars = s.toCharArray();
334 buf.append(chars,0,i);
335 buf.append("\\\\");
336 break loop;
337 case '\n':
338 chars = s.toCharArray();
339 buf.append(chars,0,i);
340 buf.append("\\n");
341 break loop;
342 case '\r':
343 chars = s.toCharArray();
344 buf.append(chars,0,i);
345 buf.append("\\r");
346 break loop;
347 case '\t':
348 chars = s.toCharArray();
349 buf.append(chars,0,i);
350 buf.append("\\t");
351 break loop;
352 case '\f':
353 chars = s.toCharArray();
354 buf.append(chars,0,i);
355 buf.append("\\f");
356 break loop;
357 case '\b':
358 chars = s.toCharArray();
359 buf.append(chars,0,i);
360 buf.append("\\b");
361 break loop;
362
363 default:
364 continue;
365 }
366 }
367 if (chars==null)
368 buf.append(s);
369 else
370 {
371 i++;
372 for (;i<s.length();i++)
373 {
374 char c = s.charAt(i);
375 switch(c)
376 {
377 case '"':
378 buf.append("\\\"");
379 continue;
380 case '\\':
381 buf.append("\\\\");
382 continue;
383 case '\n':
384 buf.append("\\n");
385 continue;
386 case '\r':
387 buf.append("\\r");
388 continue;
389 case '\t':
390 buf.append("\\t");
391 continue;
392 case '\f':
393 buf.append("\\f");
394 continue;
395 case '\b':
396 buf.append("\\b");
397 continue;
398
399 default:
400 buf.append(c);
401 continue;
402 }
403 }
404 }
405
406 buf.append('"');
407 }
408 }
409
410
411
412
413
414
415
416
417
418
419
420 public static void quoteIfNeeded(StringBuffer buf, String s)
421 {
422 synchronized(buf)
423 {
424 int e=-1;
425
426 search: for (int i=0;i<s.length();i++)
427 {
428 char c = s.charAt(i);
429 switch(c)
430 {
431 case '"':
432 case '\\':
433 case '\n':
434 case '\r':
435 case '\t':
436 case '\f':
437 case '\b':
438 case '%':
439 case '+':
440 case ' ':
441 e=i;
442 buf.append('"');
443
444 for (int j=0;j<e;j++)
445 buf.append(s.charAt(j));
446 break search;
447
448 default:
449 continue;
450 }
451 }
452
453 if (e<0)
454 {
455 buf.append(s);
456 return;
457 }
458
459 for (int i=e;i<s.length();i++)
460 {
461 char c = s.charAt(i);
462 switch(c)
463 {
464 case '"':
465 buf.append("\\\"");
466 continue;
467 case '\\':
468 buf.append("\\\\");
469 continue;
470 case '\n':
471 buf.append("\\n");
472 continue;
473 case '\r':
474 buf.append("\\r");
475 continue;
476 case '\t':
477 buf.append("\\t");
478 continue;
479 case '\f':
480 buf.append("\\f");
481 continue;
482 case '\b':
483 buf.append("\\b");
484 continue;
485
486 default:
487 buf.append(c);
488 continue;
489 }
490 }
491 buf.append('"');
492 }
493 }
494
495
496
497
498
499
500 public static String unquote(String s)
501 {
502 if (s==null)
503 return null;
504 if (s.length()<2)
505 return s;
506
507 char first=s.charAt(0);
508 char last=s.charAt(s.length()-1);
509 if (first!=last || (first!='"' && first!='\''))
510 return s;
511
512 StringBuffer b=new StringBuffer(s.length()-2);
513 synchronized(b)
514 {
515 boolean escape=false;
516 for (int i=1;i<s.length()-1;i++)
517 {
518 char c = s.charAt(i);
519
520 if (escape)
521 {
522 escape=false;
523 switch (c)
524 {
525 case 'n':
526 b.append('\n');
527 break;
528 case 'r':
529 b.append('\r');
530 break;
531 case 't':
532 b.append('\t');
533 break;
534 case 'f':
535 b.append('\f');
536 break;
537 case 'b':
538 b.append('\b');
539 break;
540 case 'u':
541 b.append((char)(
542 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+
543 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+
544 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+
545 (TypeUtil.convertHexDigit((byte)s.charAt(i++)))
546 )
547 );
548 break;
549 default:
550 b.append(c);
551 }
552 }
553 else if (c=='\\')
554 {
555 escape=true;
556 continue;
557 }
558 else
559 b.append(c);
560 }
561
562 return b.toString();
563 }
564 }
565
566
567
568
569
570 public boolean getDouble()
571 {
572 return _double;
573 }
574
575
576
577
578
579 public void setDouble(boolean d)
580 {
581 _double=d;
582 }
583
584
585
586
587
588 public boolean getSingle()
589 {
590 return _single;
591 }
592
593
594
595
596
597 public void setSingle(boolean single)
598 {
599 _single=single;
600 }
601 }
602
603
604
605
606
607
608
609
610
611
612
613