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 case ';':
442 case '=':
443 e=i;
444 buf.append('"');
445
446 for (int j=0;j<e;j++)
447 buf.append(s.charAt(j));
448 break search;
449
450 default:
451 continue;
452 }
453 }
454
455 if (e<0)
456 {
457 buf.append(s);
458 return;
459 }
460
461 for (int i=e;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 buf.append('"');
494 }
495 }
496
497
498
499
500
501
502 public static String unquote(String s)
503 {
504 if (s==null)
505 return null;
506 if (s.length()<2)
507 return s;
508
509 char first=s.charAt(0);
510 char last=s.charAt(s.length()-1);
511 if (first!=last || (first!='"' && first!='\''))
512 return s;
513
514 StringBuffer b=new StringBuffer(s.length()-2);
515 synchronized(b)
516 {
517 boolean escape=false;
518 for (int i=1;i<s.length()-1;i++)
519 {
520 char c = s.charAt(i);
521
522 if (escape)
523 {
524 escape=false;
525 switch (c)
526 {
527 case 'n':
528 b.append('\n');
529 break;
530 case 'r':
531 b.append('\r');
532 break;
533 case 't':
534 b.append('\t');
535 break;
536 case 'f':
537 b.append('\f');
538 break;
539 case 'b':
540 b.append('\b');
541 break;
542 case 'u':
543 b.append((char)(
544 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+
545 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+
546 (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+
547 (TypeUtil.convertHexDigit((byte)s.charAt(i++)))
548 )
549 );
550 break;
551 default:
552 b.append(c);
553 }
554 }
555 else if (c=='\\')
556 {
557 escape=true;
558 continue;
559 }
560 else
561 b.append(c);
562 }
563
564 return b.toString();
565 }
566 }
567
568
569
570
571
572 public boolean getDouble()
573 {
574 return _double;
575 }
576
577
578
579
580
581 public void setDouble(boolean d)
582 {
583 _double=d;
584 }
585
586
587
588
589
590 public boolean getSingle()
591 {
592 return _single;
593 }
594
595
596
597
598
599 public void setSingle(boolean single)
600 {
601 _single=single;
602 }
603 }
604
605
606
607
608
609
610
611
612
613
614
615