View Javadoc

1   // ========================================================================
2   // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // Licensed under the Apache License, Version 2.0 (the "License");
5   // you may not use this file except in compliance with the License.
6   // You may obtain a copy of the License at 
7   // http://www.apache.org/licenses/LICENSE-2.0
8   // Unless required by applicable law or agreed to in writing, software
9   // distributed under the License is distributed on an "AS IS" BASIS,
10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  // See the License for the specific language governing permissions and
12  // limitations under the License.
13  // ========================================================================
14  
15  package org.mortbay.util;
16  
17  import java.io.UnsupportedEncodingException;
18  
19  // ====================================================================
20  /** Fast String Utilities.
21   *
22   * These string utilities provide both conveniance methods and
23   * performance improvements over most standard library versions. The
24   * main aim of the optimizations is to avoid object creation unless
25   * absolutely required.
26   *
27   * @author Greg Wilkins (gregw)
28   */
29  public class StringUtil
30  {
31      public static final String CRLF="\015\012";
32      public static final String __LINE_SEPARATOR=
33          System.getProperty("line.separator","\n");
34      
35      public static final String __ISO_8859_1;
36      static
37      {
38          String iso=System.getProperty("ISO_8859_1");
39          if (iso==null)
40          {
41              try{
42                  new String(new byte[]{(byte)20},"ISO-8859-1");
43                  iso="ISO-8859-1";
44              }
45              catch(java.io.UnsupportedEncodingException e)
46              {
47                  iso="ISO8859_1";
48              }        
49          }
50          __ISO_8859_1=iso;
51      }
52      
53      public final static String __UTF8="UTF-8";
54      public final static String __UTF8Alt="UTF8";
55      public final static String __UTF16="UTF-16";
56      
57      
58      private static char[] lowercases = {
59            '\000','\001','\002','\003','\004','\005','\006','\007',
60            '\010','\011','\012','\013','\014','\015','\016','\017',
61            '\020','\021','\022','\023','\024','\025','\026','\027',
62            '\030','\031','\032','\033','\034','\035','\036','\037',
63            '\040','\041','\042','\043','\044','\045','\046','\047',
64            '\050','\051','\052','\053','\054','\055','\056','\057',
65            '\060','\061','\062','\063','\064','\065','\066','\067',
66            '\070','\071','\072','\073','\074','\075','\076','\077',
67            '\100','\141','\142','\143','\144','\145','\146','\147',
68            '\150','\151','\152','\153','\154','\155','\156','\157',
69            '\160','\161','\162','\163','\164','\165','\166','\167',
70            '\170','\171','\172','\133','\134','\135','\136','\137',
71            '\140','\141','\142','\143','\144','\145','\146','\147',
72            '\150','\151','\152','\153','\154','\155','\156','\157',
73            '\160','\161','\162','\163','\164','\165','\166','\167',
74            '\170','\171','\172','\173','\174','\175','\176','\177' };
75  
76      /* ------------------------------------------------------------ */
77      /**
78       * fast lower case conversion. Only works on ascii (not unicode)
79       * @param s the string to convert
80       * @return a lower case version of s
81       */
82      public static String asciiToLowerCase(String s)
83      {
84          char[] c = null;
85          int i=s.length();
86  
87          // look for first conversion
88          while (i-->0)
89          {
90              char c1=s.charAt(i);
91              if (c1<=127)
92              {
93                  char c2=lowercases[c1];
94                  if (c1!=c2)
95                  {
96                      c=s.toCharArray();
97                      c[i]=c2;
98                      break;
99                  }
100             }
101         }
102 
103         while (i-->0)
104         {
105             if(c[i]<=127)
106                 c[i] = lowercases[c[i]];
107         }
108         
109         return c==null?s:new String(c);
110     }
111 
112 
113     /* ------------------------------------------------------------ */
114     public static boolean startsWithIgnoreCase(String s,String w)
115     {
116         if (w==null)
117             return true;
118         
119         if (s==null || s.length()<w.length())
120             return false;
121         
122         for (int i=0;i<w.length();i++)
123         {
124             char c1=s.charAt(i);
125             char c2=w.charAt(i);
126             if (c1!=c2)
127             {
128                 if (c1<=127)
129                     c1=lowercases[c1];
130                 if (c2<=127)
131                     c2=lowercases[c2];
132                 if (c1!=c2)
133                     return false;
134             }
135         }
136         return true;
137     }
138     
139     /* ------------------------------------------------------------ */
140     public static boolean endsWithIgnoreCase(String s,String w)
141     {
142         if (w==null)
143             return true;
144 
145         if (s==null)
146             return false;
147             
148         int sl=s.length();
149         int wl=w.length();
150         
151         if (sl<wl)
152             return false;
153         
154         for (int i=wl;i-->0;)
155         {
156             char c1=s.charAt(--sl);
157             char c2=w.charAt(i);
158             if (c1!=c2)
159             {
160                 if (c1<=127)
161                     c1=lowercases[c1];
162                 if (c2<=127)
163                     c2=lowercases[c2];
164                 if (c1!=c2)
165                     return false;
166             }
167         }
168         return true;
169     }
170     
171     /* ------------------------------------------------------------ */
172     /**
173      * returns the next index of a character from the chars string
174      */
175     public static int indexFrom(String s,String chars)
176     {
177         for (int i=0;i<s.length();i++)
178            if (chars.indexOf(s.charAt(i))>=0)
179               return i;
180         return -1;
181     }
182     
183     /* ------------------------------------------------------------ */
184     /**
185      * replace substrings within string.
186      */
187     public static String replace(String s, String sub, String with)
188     {
189         int c=0;
190         int i=s.indexOf(sub,c);
191         if (i == -1)
192             return s;
193     
194         StringBuffer buf = new StringBuffer(s.length()+with.length());
195 
196         synchronized(buf)
197         {
198             do
199             {
200                 buf.append(s.substring(c,i));
201                 buf.append(with);
202                 c=i+sub.length();
203             } while ((i=s.indexOf(sub,c))!=-1);
204             
205             if (c<s.length())
206                 buf.append(s.substring(c,s.length()));
207             
208             return buf.toString();
209         }
210     }
211 
212 
213     /* ------------------------------------------------------------ */
214     /** Remove single or double quotes.
215      */
216     public static String unquote(String s)
217     {
218         return QuotedStringTokenizer.unquote(s);
219     }
220 
221 
222     /* ------------------------------------------------------------ */
223     /** Append substring to StringBuffer 
224      * @param buf StringBuffer to append to
225      * @param s String to append from
226      * @param offset The offset of the substring
227      * @param length The length of the substring
228      */
229     public static void append(StringBuffer buf,
230                               String s,
231                               int offset,
232                               int length)
233     {
234         synchronized(buf)
235         {
236             int end=offset+length;
237             for (int i=offset; i<end;i++)
238             {
239                 if (i>=s.length())
240                     break;
241                 buf.append(s.charAt(i));
242             }
243         }
244     }
245 
246     
247     /* ------------------------------------------------------------ */
248     /**
249      * append hex digit
250      * 
251      */
252     public static void append(StringBuffer buf,byte b,int base)
253     {
254         int bi=0xff&b;
255         int c='0'+(bi/base)%base;
256         if (c>'9')
257             c= 'a'+(c-'0'-10);
258         buf.append((char)c);
259         c='0'+bi%base;
260         if (c>'9')
261             c= 'a'+(c-'0'-10);
262         buf.append((char)c);
263     }
264 
265     
266     /* ------------------------------------------------------------ */
267     public static void append2digits(StringBuffer buf,int i)
268     {
269         if (i<100)
270         {
271             buf.append((char)(i/10+'0'));
272             buf.append((char)(i%10+'0'));
273         }
274     }
275     
276     /* ------------------------------------------------------------ */
277     /** Return a non null string.
278      * @param s String
279      * @return The string passed in or empty string if it is null. 
280      */
281     public static String nonNull(String s)
282     {
283         if (s==null)
284             return "";
285         return s;
286     }
287     
288     /* ------------------------------------------------------------ */
289     public static boolean equals(String s,char[] buf, int offset, int length)
290     {
291         if (s.length()!=length)
292             return false;
293         for (int i=0;i<length;i++)
294             if (buf[offset+i]!=s.charAt(i))
295                 return false;
296         return true;
297     }
298 
299     /* ------------------------------------------------------------ */
300     public static String toUTF8String(byte[] b,int offset,int length)
301     {
302         try
303         {
304             if (length<32)
305             {
306                 Utf8StringBuffer buffer = new Utf8StringBuffer(length);
307                 buffer.append(b,offset,length);
308                 return buffer.toString();
309             }
310             
311             return new String(b,offset,length,__UTF8);
312         }
313         catch (UnsupportedEncodingException e)
314         {
315             e.printStackTrace();
316             return null;
317         }
318     }
319 
320     /* ------------------------------------------------------------ */
321     public static String toString(byte[] b,int offset,int length,String charset)
322     {
323         if (charset==null || StringUtil.isUTF8(charset))
324             return toUTF8String(b,offset,length);
325         
326         try
327         {
328             return new String(b,offset,length,charset);
329         }
330         catch (UnsupportedEncodingException e)
331         {
332             e.printStackTrace();
333             return null;
334         }
335     }
336 
337 
338     /* ------------------------------------------------------------ */
339     public static boolean isUTF8(String charset)
340     {
341         return charset==__UTF8||__UTF8.equalsIgnoreCase(charset)||__UTF8Alt.equalsIgnoreCase(charset);
342     }
343 
344 
345     /* ------------------------------------------------------------ */
346     public static String printable(String name)
347     {
348         if (name==null)
349             return null;
350         StringBuffer buf = new StringBuffer(name.length());
351         for (int i=0;i<name.length();i++)
352         {
353             char c=name.charAt(i);
354             if (!Character.isISOControl(c))
355                 buf.append(c);
356         }
357         return buf.toString();
358     }
359     
360     
361 }