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