1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util;
20
21 import java.io.UnsupportedEncodingException;
22 import java.nio.charset.Charset;
23 import java.nio.charset.StandardCharsets;
24
25 import org.eclipse.jetty.util.log.Log;
26 import org.eclipse.jetty.util.log.Logger;
27
28
29
30
31
32
33
34
35
36
37 public class StringUtil
38 {
39 private static final Logger LOG = Log.getLogger(StringUtil.class);
40
41
42 private final static Trie<String> CHARSETS= new ArrayTrie<>(256);
43
44 public static final String ALL_INTERFACES="0.0.0.0";
45 public static final String CRLF="\015\012";
46
47
48 @Deprecated
49 public static final String __LINE_SEPARATOR = System.lineSeparator();
50
51 public static final String __ISO_8859_1="ISO-8859-1";
52 public final static String __UTF8="UTF-8";
53 public final static String __UTF16="UTF-16";
54
55
56
57
58 @Deprecated
59 public final static Charset __UTF8_CHARSET=StandardCharsets.UTF_8;
60
61
62
63 @Deprecated
64 public final static Charset __ISO_8859_1_CHARSET=StandardCharsets.ISO_8859_1;
65
66
67
68 @Deprecated
69 public final static Charset __UTF16_CHARSET=StandardCharsets.UTF_16;
70
71
72
73 @Deprecated
74 public final static Charset __US_ASCII_CHARSET=StandardCharsets.US_ASCII;
75
76 static
77 {
78 CHARSETS.put("UTF-8",__UTF8);
79 CHARSETS.put("UTF8",__UTF8);
80 CHARSETS.put("UTF-16",__UTF16);
81 CHARSETS.put("UTF16",__UTF16);
82 CHARSETS.put("ISO-8859-1",__ISO_8859_1);
83 CHARSETS.put("ISO_8859_1",__ISO_8859_1);
84 }
85
86
87
88
89
90 public static String normalizeCharset(String s)
91 {
92 String n=CHARSETS.get(s);
93 return (n==null)?s:n;
94 }
95
96
97
98
99
100 public static String normalizeCharset(String s,int offset,int length)
101 {
102 String n=CHARSETS.get(s,offset,length);
103 return (n==null)?s.substring(offset,offset+length):n;
104 }
105
106
107
108 public static final char[] lowercases = {
109 '\000','\001','\002','\003','\004','\005','\006','\007',
110 '\010','\011','\012','\013','\014','\015','\016','\017',
111 '\020','\021','\022','\023','\024','\025','\026','\027',
112 '\030','\031','\032','\033','\034','\035','\036','\037',
113 '\040','\041','\042','\043','\044','\045','\046','\047',
114 '\050','\051','\052','\053','\054','\055','\056','\057',
115 '\060','\061','\062','\063','\064','\065','\066','\067',
116 '\070','\071','\072','\073','\074','\075','\076','\077',
117 '\100','\141','\142','\143','\144','\145','\146','\147',
118 '\150','\151','\152','\153','\154','\155','\156','\157',
119 '\160','\161','\162','\163','\164','\165','\166','\167',
120 '\170','\171','\172','\133','\134','\135','\136','\137',
121 '\140','\141','\142','\143','\144','\145','\146','\147',
122 '\150','\151','\152','\153','\154','\155','\156','\157',
123 '\160','\161','\162','\163','\164','\165','\166','\167',
124 '\170','\171','\172','\173','\174','\175','\176','\177' };
125
126
127
128
129
130
131
132 public static String asciiToLowerCase(String s)
133 {
134 char[] c = null;
135 int i=s.length();
136
137
138 while (i-->0)
139 {
140 char c1=s.charAt(i);
141 if (c1<=127)
142 {
143 char c2=lowercases[c1];
144 if (c1!=c2)
145 {
146 c=s.toCharArray();
147 c[i]=c2;
148 break;
149 }
150 }
151 }
152
153 while (i-->0)
154 {
155 if(c[i]<=127)
156 c[i] = lowercases[c[i]];
157 }
158
159 return c==null?s:new String(c);
160 }
161
162
163
164 public static boolean startsWithIgnoreCase(String s,String w)
165 {
166 if (w==null)
167 return true;
168
169 if (s==null || s.length()<w.length())
170 return false;
171
172 for (int i=0;i<w.length();i++)
173 {
174 char c1=s.charAt(i);
175 char c2=w.charAt(i);
176 if (c1!=c2)
177 {
178 if (c1<=127)
179 c1=lowercases[c1];
180 if (c2<=127)
181 c2=lowercases[c2];
182 if (c1!=c2)
183 return false;
184 }
185 }
186 return true;
187 }
188
189
190 public static boolean endsWithIgnoreCase(String s,String w)
191 {
192 if (w==null)
193 return true;
194
195 if (s==null)
196 return false;
197
198 int sl=s.length();
199 int wl=w.length();
200
201 if (sl<wl)
202 return false;
203
204 for (int i=wl;i-->0;)
205 {
206 char c1=s.charAt(--sl);
207 char c2=w.charAt(i);
208 if (c1!=c2)
209 {
210 if (c1<=127)
211 c1=lowercases[c1];
212 if (c2<=127)
213 c2=lowercases[c2];
214 if (c1!=c2)
215 return false;
216 }
217 }
218 return true;
219 }
220
221
222
223
224
225 public static int indexFrom(String s,String chars)
226 {
227 for (int i=0;i<s.length();i++)
228 if (chars.indexOf(s.charAt(i))>=0)
229 return i;
230 return -1;
231 }
232
233
234
235
236
237 public static String replace(String s, String sub, String with)
238 {
239 int c=0;
240 int i=s.indexOf(sub,c);
241 if (i == -1)
242 return s;
243
244 StringBuilder buf = new StringBuilder(s.length()+with.length());
245
246 do
247 {
248 buf.append(s.substring(c,i));
249 buf.append(with);
250 c=i+sub.length();
251 } while ((i=s.indexOf(sub,c))!=-1);
252
253 if (c<s.length())
254 buf.append(s.substring(c,s.length()));
255
256 return buf.toString();
257
258 }
259
260
261
262
263
264 public static String unquote(String s)
265 {
266 return QuotedStringTokenizer.unquote(s);
267 }
268
269
270
271
272
273
274
275
276
277 public static void append(StringBuilder buf,
278 String s,
279 int offset,
280 int length)
281 {
282 synchronized(buf)
283 {
284 int end=offset+length;
285 for (int i=offset; i<end;i++)
286 {
287 if (i>=s.length())
288 break;
289 buf.append(s.charAt(i));
290 }
291 }
292 }
293
294
295
296
297
298
299
300 public static void append(StringBuilder buf,byte b,int base)
301 {
302 int bi=0xff&b;
303 int c='0'+(bi/base)%base;
304 if (c>'9')
305 c= 'a'+(c-'0'-10);
306 buf.append((char)c);
307 c='0'+bi%base;
308 if (c>'9')
309 c= 'a'+(c-'0'-10);
310 buf.append((char)c);
311 }
312
313
314 public static void append2digits(StringBuffer buf,int i)
315 {
316 if (i<100)
317 {
318 buf.append((char)(i/10+'0'));
319 buf.append((char)(i%10+'0'));
320 }
321 }
322
323
324 public static void append2digits(StringBuilder buf,int i)
325 {
326 if (i<100)
327 {
328 buf.append((char)(i/10+'0'));
329 buf.append((char)(i%10+'0'));
330 }
331 }
332
333
334
335
336
337
338 public static String nonNull(String s)
339 {
340 if (s==null)
341 return "";
342 return s;
343 }
344
345
346 public static boolean equals(String s,char[] buf, int offset, int length)
347 {
348 if (s.length()!=length)
349 return false;
350 for (int i=0;i<length;i++)
351 if (buf[offset+i]!=s.charAt(i))
352 return false;
353 return true;
354 }
355
356
357 public static String toUTF8String(byte[] b,int offset,int length)
358 {
359 return new String(b,offset,length,StandardCharsets.UTF_8);
360 }
361
362
363 public static String toString(byte[] b,int offset,int length,String charset)
364 {
365 try
366 {
367 return new String(b,offset,length,charset);
368 }
369 catch (UnsupportedEncodingException e)
370 {
371 throw new IllegalArgumentException(e);
372 }
373 }
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 public static boolean isBlank(String str)
397 {
398 if (str == null)
399 {
400 return true;
401 }
402 int len = str.length();
403 for (int i = 0; i < len; i++)
404 {
405 if (!Character.isWhitespace(str.codePointAt(i)))
406 {
407
408 return false;
409 }
410 }
411
412 return true;
413 }
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436 public static boolean isNotBlank(String str)
437 {
438 if (str == null)
439 {
440 return false;
441 }
442 int len = str.length();
443 for (int i = 0; i < len; i++)
444 {
445 if (!Character.isWhitespace(str.codePointAt(i)))
446 {
447
448 return true;
449 }
450 }
451
452 return false;
453 }
454
455
456 public static boolean isUTF8(String charset)
457 {
458 return __UTF8.equalsIgnoreCase(charset)||__UTF8.equalsIgnoreCase(normalizeCharset(charset));
459 }
460
461
462
463 public static String printable(String name)
464 {
465 if (name==null)
466 return null;
467 StringBuilder buf = new StringBuilder(name.length());
468 for (int i=0;i<name.length();i++)
469 {
470 char c=name.charAt(i);
471 if (!Character.isISOControl(c))
472 buf.append(c);
473 }
474 return buf.toString();
475 }
476
477
478 public static String printable(byte[] b)
479 {
480 StringBuilder buf = new StringBuilder();
481 for (int i=0;i<b.length;i++)
482 {
483 char c=(char)b[i];
484 if (Character.isWhitespace(c)|| c>' ' && c<0x7f)
485 buf.append(c);
486 else
487 {
488 buf.append("0x");
489 TypeUtil.toHex(b[i],buf);
490 }
491 }
492 return buf.toString();
493 }
494
495 public static byte[] getBytes(String s)
496 {
497 return s.getBytes(StandardCharsets.ISO_8859_1);
498 }
499
500 public static byte[] getUtf8Bytes(String s)
501 {
502 return s.getBytes(StandardCharsets.UTF_8);
503 }
504
505 public static byte[] getBytes(String s,String charset)
506 {
507 try
508 {
509 return s.getBytes(charset);
510 }
511 catch(Exception e)
512 {
513 LOG.warn(e);
514 return s.getBytes();
515 }
516 }
517
518
519
520
521
522
523
524
525
526
527 public static String sidBytesToString(byte[] sidBytes)
528 {
529 StringBuilder sidString = new StringBuilder();
530
531
532 sidString.append("S-");
533
534
535 sidString.append(Byte.toString(sidBytes[0])).append('-');
536
537 StringBuilder tmpBuilder = new StringBuilder();
538
539
540 for (int i = 2; i <= 7; ++i)
541 {
542 tmpBuilder.append(Integer.toHexString(sidBytes[i] & 0xFF));
543 }
544
545 sidString.append(Long.parseLong(tmpBuilder.toString(), 16));
546
547
548 int subAuthorityCount = sidBytes[1];
549
550
551 for (int i = 0; i < subAuthorityCount; ++i)
552 {
553 int offset = i * 4;
554 tmpBuilder.setLength(0);
555
556 tmpBuilder.append(String.format("%02X%02X%02X%02X",
557 (sidBytes[11 + offset] & 0xFF),
558 (sidBytes[10 + offset] & 0xFF),
559 (sidBytes[9 + offset] & 0xFF),
560 (sidBytes[8 + offset] & 0xFF)));
561 sidString.append('-').append(Long.parseLong(tmpBuilder.toString(), 16));
562 }
563
564 return sidString.toString();
565 }
566
567
568
569
570
571
572
573
574 public static byte[] sidStringToBytes( String sidString )
575 {
576 String[] sidTokens = sidString.split("-");
577
578 int subAuthorityCount = sidTokens.length - 3;
579
580 int byteCount = 0;
581 byte[] sidBytes = new byte[1 + 1 + 6 + (4 * subAuthorityCount)];
582
583
584 sidBytes[byteCount++] = (byte)Integer.parseInt(sidTokens[1]);
585
586
587 sidBytes[byteCount++] = (byte)subAuthorityCount;
588
589
590 String hexStr = Long.toHexString(Long.parseLong(sidTokens[2]));
591
592 while( hexStr.length() < 12)
593 {
594 hexStr = "0" + hexStr;
595 }
596
597
598 for ( int i = 0 ; i < hexStr.length(); i = i + 2)
599 {
600 sidBytes[byteCount++] = (byte)Integer.parseInt(hexStr.substring(i, i + 2),16);
601 }
602
603
604 for ( int i = 3; i < sidTokens.length ; ++i)
605 {
606 hexStr = Long.toHexString(Long.parseLong(sidTokens[i]));
607
608 while( hexStr.length() < 8)
609 {
610 hexStr = "0" + hexStr;
611 }
612
613
614 for ( int j = hexStr.length(); j > 0; j = j - 2)
615 {
616 sidBytes[byteCount++] = (byte)Integer.parseInt(hexStr.substring(j-2, j),16);
617 }
618 }
619
620 return sidBytes;
621 }
622
623
624
625
626
627
628
629
630
631 public static int toInt(String string)
632 {
633 int val = 0;
634 boolean started = false;
635 boolean minus = false;
636
637 for (int i = 0; i < string.length(); i++)
638 {
639 char b = string.charAt(i);
640 if (b <= ' ')
641 {
642 if (started)
643 break;
644 }
645 else if (b >= '0' && b <= '9')
646 {
647 val = val * 10 + (b - '0');
648 started = true;
649 }
650 else if (b == '-' && !started)
651 {
652 minus = true;
653 }
654 else
655 break;
656 }
657
658 if (started)
659 return minus?(-val):val;
660 throw new NumberFormatException(string);
661 }
662
663
664
665
666
667
668
669
670 public static long toLong(String string)
671 {
672 long val = 0;
673 boolean started = false;
674 boolean minus = false;
675
676 for (int i = 0; i < string.length(); i++)
677 {
678 char b = string.charAt(i);
679 if (b <= ' ')
680 {
681 if (started)
682 break;
683 }
684 else if (b >= '0' && b <= '9')
685 {
686 val = val * 10L + (b - '0');
687 started = true;
688 }
689 else if (b == '-' && !started)
690 {
691 minus = true;
692 }
693 else
694 break;
695 }
696
697 if (started)
698 return minus?(-val):val;
699 throw new NumberFormatException(string);
700 }
701
702
703
704
705
706
707
708
709 public static String truncate(String str, int maxSize)
710 {
711 if (str == null)
712 {
713 return null;
714 }
715
716 if (str.length() <= maxSize)
717 {
718 return str;
719 }
720
721 return str.substring(0,maxSize);
722 }
723
724 public static String[] arrayFromString(String s)
725 {
726 if (s==null)
727 return new String[]{};
728
729 if (!s.startsWith("[") || !s.endsWith("]"))
730 throw new IllegalArgumentException();
731 if (s.length()==2)
732 return new String[]{};
733
734 return s.substring(1,s.length()-1).split(" *, *");
735 }
736
737 }