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