1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.util;
15
16 import java.util.NoSuchElementException;
17 import java.util.StringTokenizer;
18
19
20
21
22
23
24
25
26
27
28
29
30
31 public class QuotedStringTokenizer
32 extends StringTokenizer
33 {
34 private final static String __delim="\t\n\r";
35 private String _string;
36 private String _delim = __delim;
37 private boolean _returnQuotes=false;
38 private boolean _returnDelimiters=false;
39 private StringBuffer _token;
40 private boolean _hasToken=false;
41 private int _i=0;
42 private int _lastStart=0;
43 private boolean _double=true;
44 private boolean _single=true;
45
46
47 public QuotedStringTokenizer(String str,
48 String delim,
49 boolean returnDelimiters,
50 boolean returnQuotes)
51 {
52 super("");
53 _string=str;
54 if (delim!=null)
55 _delim=delim;
56 _returnDelimiters=returnDelimiters;
57 _returnQuotes=returnQuotes;
58
59 if (_delim.indexOf('\'')>=0 ||
60 _delim.indexOf('"')>=0)
61 throw new Error("Can't use quotes as delimiters: "+_delim);
62
63 _token=new StringBuffer(_string.length()>1024?512:_string.length()/2);
64 }
65
66
67 public QuotedStringTokenizer(String str,
68 String delim,
69 boolean returnDelimiters)
70 {
71 this(str,delim,returnDelimiters,false);
72 }
73
74
75 public QuotedStringTokenizer(String str,
76 String delim)
77 {
78 this(str,delim,false,false);
79 }
80
81
82 public QuotedStringTokenizer(String str)
83 {
84 this(str,null,false,false);
85 }
86
87
88 public boolean hasMoreTokens()
89 {
90
91 if (_hasToken)
92 return true;
93
94 _lastStart=_i;
95
96 int state=0;
97 boolean escape=false;
98 while (_i<_string.length())
99 {
100 char c=_string.charAt(_i++);
101
102 switch (state)
103 {
104 case 0:
105 if(_delim.indexOf(c)>=0)
106 {
107 if (_returnDelimiters)
108 {
109 _token.append(c);
110 return _hasToken=true;
111 }
112 }
113 else if (c=='\'' && _single)
114 {
115 if (_returnQuotes)
116 _token.append(c);
117 state=2;
118 }
119 else if (c=='\"' && _double)
120 {
121 if (_returnQuotes)
122 _token.append(c);
123 state=3;
124 }
125 else
126 {
127 _token.append(c);
128 _hasToken=true;
129 state=1;
130 }
131 continue;
132
133 case 1:
134 _hasToken=true;
135 if(_delim.indexOf(c)>=0)
136 {
137 if (_returnDelimiters)
138 _i--;
139 return _hasToken;
140 }
141 else if (c=='\'' && _single)
142 {
143 if (_returnQuotes)
144 _token.append(c);
145 state=2;
146 }
147 else if (c=='\"' && _double)
148 {
149 if (_returnQuotes)
150 _token.append(c);
151 state=3;
152 }
153 else
154 _token.append(c);
155 continue;
156
157
158 case 2:
159 _hasToken=true;
160 if (escape)
161 {
162 escape=false;
163 _token.append(c);
164 }
165 else if (c=='\'')
166 {
167 if (_returnQuotes)
168 _token.append(c);
169 state=1;
170 }
171 else if (c=='\\')
172 {
173 if (_returnQuotes)
174 _token.append(c);
175 escape=true;
176 }
177 else
178 _token.append(c);
179 continue;
180
181
182 case 3:
183 _hasToken=true;
184 if (escape)
185 {
186 escape=false;
187 _token.append(c);
188 }
189 else if (c=='\"')
190 {
191 if (_returnQuotes)
192 _token.append(c);
193 state=1;
194 }
195 else if (c=='\\')
196 {
197 if (_returnQuotes)
198 _token.append(c);
199 escape=true;
200 }
201 else
202 _token.append(c);
203 continue;
204 }
205 }
206
207 return _hasToken;
208 }
209
210
211 public String nextToken()
212 throws NoSuchElementException
213 {
214 if (!hasMoreTokens() || _token==null)
215 throw new NoSuchElementException();
216 String t=_token.toString();
217 _token.setLength(0);
218 _hasToken=false;
219 return t;
220 }
221
222
223 public String nextToken(String delim)
224 throws NoSuchElementException
225 {
226 _delim=delim;
227 _i=_lastStart;
228 _token.setLength(0);
229 _hasToken=false;
230 return nextToken();
231 }
232
233
234 public boolean hasMoreElements()
235 {
236 return hasMoreTokens();
237 }
238
239
240 public Object nextElement()
241 throws NoSuchElementException
242 {
243 return nextToken();
244 }
245
246
247
248
249 public int countTokens()
250 {
251 return -1;
252 }
253
254
255
256
257
258
259
260
261
262
263 public static String quote(String s, String delim)
264 {
265 if (s==null)
266 return null;
267 if (s.length()==0)
268 return "\"\"";
269
270
271 for (int i=0;i<s.length();i++)
272 {
273 char c = s.charAt(i);
274 if (c=='\\' || c=='"' || c=='\'' || Character.isWhitespace(c) || delim.indexOf(c)>=0)
275 {
276 StringBuffer b=new StringBuffer(s.length()+8);
277 quote(b,s);
278 return b.toString();
279 }
280 }
281
282 return s;
283 }
284
285
286
287
288
289
290
291
292
293 public static String quote(String s)
294 {
295 if (s==null)
296 return null;
297 if (s.length()==0)
298 return "\"\"";
299
300 StringBuffer b=new StringBuffer(s.length()+8);
301 quote(b,s);
302 return b.toString();
303
304 }
305
306
307
308
309
310
311
312
313 public static void quote(StringBuffer buf, String s)
314 {
315 synchronized(buf)
316 {
317 buf.append('"');
318
319 int i=0;
320 loop:
321 for (;i<s.length();i++)
322 {
323 char c = s.charAt(i);
324 switch(c)
325 {
326 case '"':
327 buf.append(s,0,i);
328 buf.append("\\\"");
329 break loop;
330 case '\\':
331 buf.append(s,0,i);
332 buf.append("\\\\");
333 break loop;
334 case '\n':
335 buf.append(s,0,i);
336 buf.append("\\n");
337 break loop;
338 case '\r':
339 buf.append(s,0,i);
340 buf.append("\\r");
341 break loop;
342 case '\t':
343 buf.append(s,0,i);
344 buf.append("\\t");
345 break loop;
346 case '\f':
347 buf.append(s,0,i);
348 buf.append("\\f");
349 break loop;
350 case '\b':
351 buf.append(s,0,i);
352 buf.append("\\b");
353 break loop;
354
355 default:
356 continue;
357 }
358 }
359 if (i==s.length())
360 buf.append(s);
361 else
362 {
363 i++;
364 for (;i<s.length();i++)
365 {
366 char c = s.charAt(i);
367 switch(c)
368 {
369 case '"':
370 buf.append("\\\"");
371 continue;
372 case '\\':
373 buf.append("\\\\");
374 continue;
375 case '\n':
376 buf.append("\\n");
377 continue;
378 case '\r':
379 buf.append("\\r");
380 continue;
381 case '\t':
382 buf.append("\\t");
383 continue;
384 case '\f':
385 buf.append("\\f");
386 continue;
387 case '\b':
388 buf.append("\\b");
389 continue;
390
391 default:
392 buf.append(c);
393 continue;
394 }
395 }
396 }
397
398 buf.append('"');
399 }
400
401
402
403 }
404
405
406
407
408
409
410
411
412 public static void quote(StringBuilder buf, String s)
413 {
414 buf.append('"');
415
416 int i=0;
417 loop:
418 for (;i<s.length();i++)
419 {
420 char c = s.charAt(i);
421 switch(c)
422 {
423 case '"':
424 buf.append(s,0,i);
425 buf.append("\\\"");
426 break loop;
427 case '\\':
428 buf.append(s,0,i);
429 buf.append("\\\\");
430 break loop;
431 case '\n':
432 buf.append(s,0,i);
433 buf.append("\\n");
434 break loop;
435 case '\r':
436 buf.append(s,0,i);
437 buf.append("\\r");
438 break loop;
439 case '\t':
440 buf.append(s,0,i);
441 buf.append("\\t");
442 break loop;
443 case '\f':
444 buf.append(s,0,i);
445 buf.append("\\f");
446 break loop;
447 case '\b':
448 buf.append(s,0,i);
449 buf.append("\\b");
450 break loop;
451
452 default:
453 continue;
454 }
455 }
456 if (i==s.length())
457 buf.append(s);
458 else
459 {
460 i++;
461 for (;i<s.length();i++)
462 {
463 char c = s.charAt(i);
464 switch(c)
465 {
466 case '"':
467 buf.append("\\\"");
468 continue;
469 case '\\':
470 buf.append("\\\\");
471 continue;
472 case '\n':
473 buf.append("\\n");
474 continue;
475 case '\r':
476 buf.append("\\r");
477 continue;
478 case '\t':
479 buf.append("\\t");
480 continue;
481 case '\f':
482 buf.append("\\f");
483 continue;
484 case '\b':
485 buf.append("\\b");
486 continue;
487
488 default:
489 buf.append(c);
490 continue;
491 }
492 }
493 }
494
495 buf.append('"');
496 }
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511 public static void quoteIfNeeded(StringBuffer buf, String s)
512 {
513 synchronized(buf)
514 {
515 int e=-1;
516
517 search: for (int i=0;i<s.length();i++)
518 {
519 char c = s.charAt(i);
520 switch(c)
521 {
522 case '"':
523 case '\\':
524 case '\n':
525 case '\r':
526 case '\t':
527 case '\f':
528 case '\b':
529 case '%':
530 case '+':
531 case ' ':
532 case ';':
533 case '=':
534 e=i;
535 buf.append('"');
536
537 for (int j=0;j<e;j++)
538 buf.append(s.charAt(j));
539 break search;
540
541 default:
542 continue;
543 }
544 }
545
546 if (e<0)
547 {
548 buf.append(s);
549 return;
550 }
551
552 for (int i=e;i<s.length();i++)
553 {
554 char c = s.charAt(i);
555 switch(c)
556 {
557 case '"':
558 buf.append("\\\"");
559 continue;
560 case '\\':
561 buf.append("\\\\");
562 continue;
563 case '\n':
564 buf.append("\\n");
565 continue;
566 case '\r':
567 buf.append("\\r");
568 continue;
569 case '\t':
570 buf.append("\\t");
571 continue;
572 case '\f':
573 buf.append("\\f");
574 continue;
575 case '\b':
576 buf.append("\\b");
577 continue;
578
579 default:
580 buf.append(c);
581 continue;
582 }
583 }
584 buf.append('"');
585 }
586 }
587
588
589
590
591
592
593
594
595
596
597 public static void quoteIfNeeded(StringBuilder buf, String s)
598 {
599 int e=-1;
600
601 search: for (int i=0;i<s.length();i++)
602 {
603 char c = s.charAt(i);
604 switch(c)
605 {
606 case '"':
607 case '\\':
608 case '\n':
609 case '\r':
610 case '\t':
611 case '\f':
612 case '\b':
613 case '%':
614 case '+':
615 case ' ':
616 case ';':
617 case '=':
618 e=i;
619 buf.append('"');
620
621 for (int j=0;j<e;j++)
622 buf.append(s.charAt(j));
623 break search;
624
625 default:
626 continue;
627 }
628 }
629
630 if (e<0)
631 {
632 buf.append(s);
633 return;
634 }
635
636 for (int i=e;i<s.length();i++)
637 {
638 char c = s.charAt(i);
639 switch(c)
640 {
641 case '"':
642 buf.append("\\\"");
643 continue;
644 case '\\':
645 buf.append("\\\\");
646 continue;
647 case '\n':
648 buf.append("\\n");
649 continue;
650 case '\r':
651 buf.append("\\r");
652 continue;
653 case '\t':
654 buf.append("\\t");
655 continue;
656 case '\f':
657 buf.append("\\f");
658 continue;
659 case '\b':
660 buf.append("\\b");
661 continue;
662
663 default:
664 buf.append(c);
665 continue;
666 }
667 }
668 buf.append('"');
669
670 }
671
672
673
674
675
676
677 public static String unquote(String s)
678 {
679 if (s==null)
680 return null;
681 if (s.length()<2)
682 return s;
683
684 char first=s.charAt(0);
685 char last=s.charAt(s.length()-1);
686 if (first!=last || (first!='"' && first!='\''))
687 return s;
688
689 StringBuffer b=new StringBuffer(s.length()-2);
690 synchronized(b)
691 {
692 boolean escape=false;
693 for (int i=1;i<s.length()-1;i++)
694 {
695 char c = s.charAt(i);
696
697 if (escape)
698 {
699 escape=false;
700 switch (c)
701 {
702 case 'n':
703 b.append('\n');
704 break;
705 case 'r':
706 b.append('\r');
707 break;
708 case 't':
709 b.append('\t');
710 break;
711 case 'f':
712 b.append('\f');
713 break;
714 case 'b':
715 b.append('\b');
716 break;
717 case 'u':
718 b.append((char)(
719 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+
720 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+
721 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+
722 (TypeUtil.convertHexDigit((byte)s.charAt(i++)))
723 )
724 );
725 break;
726 default:
727 b.append(c);
728 }
729 }
730 else if (c=='\\')
731 {
732 escape=true;
733 continue;
734 }
735 else
736 b.append(c);
737 }
738
739 return b.toString();
740 }
741 }
742
743
744
745
746
747 public boolean getDouble()
748 {
749 return _double;
750 }
751
752
753
754
755
756 public void setDouble(boolean d)
757 {
758 _double=d;
759 }
760
761
762
763
764
765 public boolean getSingle()
766 {
767 return _single;
768 }
769
770
771
772
773
774 public void setSingle(boolean single)
775 {
776 _single=single;
777 }
778 }
779
780
781
782
783
784
785
786
787
788
789
790