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 __UTF16="UTF-16";
55      
56      
57      private static char[] lowercases = {
58            '\000','\001','\002','\003','\004','\005','\006','\007',
59            '\010','\011','\012','\013','\014','\015','\016','\017',
60            '\020','\021','\022','\023','\024','\025','\026','\027',
61            '\030','\031','\032','\033','\034','\035','\036','\037',
62            '\040','\041','\042','\043','\044','\045','\046','\047',
63            '\050','\051','\052','\053','\054','\055','\056','\057',
64            '\060','\061','\062','\063','\064','\065','\066','\067',
65            '\070','\071','\072','\073','\074','\075','\076','\077',
66            '\100','\141','\142','\143','\144','\145','\146','\147',
67            '\150','\151','\152','\153','\154','\155','\156','\157',
68            '\160','\161','\162','\163','\164','\165','\166','\167',
69            '\170','\171','\172','\133','\134','\135','\136','\137',
70            '\140','\141','\142','\143','\144','\145','\146','\147',
71            '\150','\151','\152','\153','\154','\155','\156','\157',
72            '\160','\161','\162','\163','\164','\165','\166','\167',
73            '\170','\171','\172','\173','\174','\175','\176','\177' };
74  
75      /* ------------------------------------------------------------ */
76      /**
77       * fast lower case conversion. Only works on ascii (not unicode)
78       * @param s the string to convert
79       * @return a lower case version of s
80       */
81      public static String asciiToLowerCase(String s)
82      {
83          char[] c = null;
84          int i=s.length();
85  
86          // look for first conversion
87          while (i-->0)
88          {
89              char c1=s.charAt(i);
90              if (c1<=127)
91              {
92                  char c2=lowercases[c1];
93                  if (c1!=c2)
94                  {
95                      c=s.toCharArray();
96                      c[i]=c2;
97                      break;
98                  }
99              }
100         }
101 
102         while (i-->0)
103         {
104             if(c[i]<=127)
105                 c[i] = lowercases[c[i]];
106         }
107         
108         return c==null?s:new String(c);
109     }
110 
111 
112     /* ------------------------------------------------------------ */
113     public static boolean startsWithIgnoreCase(String s,String w)
114     {
115         if (w==null)
116             return true;
117         
118         if (s==null || s.length()<w.length())
119             return false;
120         
121         for (int i=0;i<w.length();i++)
122         {
123             char c1=s.charAt(i);
124             char c2=w.charAt(i);
125             if (c1!=c2)
126             {
127                 if (c1<=127)
128                     c1=lowercases[c1];
129                 if (c2<=127)
130                     c2=lowercases[c2];
131                 if (c1!=c2)
132                     return false;
133             }
134         }
135         return true;
136     }
137     
138     /* ------------------------------------------------------------ */
139     public static boolean endsWithIgnoreCase(String s,String w)
140     {
141         if (w==null)
142             return true;
143 
144         if (s==null)
145             return false;
146             
147         int sl=s.length();
148         int wl=w.length();
149         
150         if (sl<wl)
151             return false;
152         
153         for (int i=wl;i-->0;)
154         {
155             char c1=s.charAt(--sl);
156             char c2=w.charAt(i);
157             if (c1!=c2)
158             {
159                 if (c1<=127)
160                     c1=lowercases[c1];
161                 if (c2<=127)
162                     c2=lowercases[c2];
163                 if (c1!=c2)
164                     return false;
165             }
166         }
167         return true;
168     }
169     
170     /* ------------------------------------------------------------ */
171     /**
172      * returns the next index of a character from the chars string
173      */
174     public static int indexFrom(String s,String chars)
175     {
176         for (int i=0;i<s.length();i++)
177            if (chars.indexOf(s.charAt(i))>=0)
178               return i;
179         return -1;
180     }
181     
182     /* ------------------------------------------------------------ */
183     /**
184      * replace substrings within string.
185      */
186     public static String replace(String s, String sub, String with)
187     {
188         int c=0;
189         int i=s.indexOf(sub,c);
190         if (i == -1)
191             return s;
192     
193         StringBuffer buf = new StringBuffer(s.length()+with.length());
194 
195         synchronized(buf)
196         {
197             do
198             {
199                 buf.append(s.substring(c,i));
200                 buf.append(with);
201                 c=i+sub.length();
202             } while ((i=s.indexOf(sub,c))!=-1);
203             
204             if (c<s.length())
205                 buf.append(s.substring(c,s.length()));
206             
207             return buf.toString();
208         }
209     }
210 
211 
212     /* ------------------------------------------------------------ */
213     /** Remove single or double quotes.
214      */
215     public static String unquote(String s)
216     {
217         return QuotedStringTokenizer.unquote(s);
218     }
219 
220 
221     /* ------------------------------------------------------------ */
222     /** Append substring to StringBuffer 
223      * @param buf StringBuffer to append to
224      * @param s String to append from
225      * @param offset The offset of the substring
226      * @param length The length of the substring
227      */
228     public static void append(StringBuffer buf,
229                               String s,
230                               int offset,
231                               int length)
232     {
233         synchronized(buf)
234         {
235             int end=offset+length;
236             for (int i=offset; i<end;i++)
237             {
238                 if (i>=s.length())
239                     break;
240                 buf.append(s.charAt(i));
241             }
242         }
243     }
244 
245     
246     /* ------------------------------------------------------------ */
247     /**
248      * append hex digit
249      * 
250      */
251     public static void append(StringBuffer buf,byte b,int base)
252     {
253         int bi=0xff&b;
254         int c='0'+(bi/base)%base;
255         if (c>'9')
256             c= 'a'+(c-'0'-10);
257         buf.append((char)c);
258         c='0'+bi%base;
259         if (c>'9')
260             c= 'a'+(c-'0'-10);
261         buf.append((char)c);
262     }
263 
264     
265     /* ------------------------------------------------------------ */
266     public static void append2digits(StringBuffer buf,int i)
267     {
268         if (i<100)
269         {
270             buf.append((char)(i/10+'0'));
271             buf.append((char)(i%10+'0'));
272         }
273     }
274     
275     /* ------------------------------------------------------------ */
276     /** Return a non null string.
277      * @param s String
278      * @return The string passed in or empty string if it is null. 
279      */
280     public static String nonNull(String s)
281     {
282         if (s==null)
283             return "";
284         return s;
285     }
286     
287     /* ------------------------------------------------------------ */
288     public static boolean equals(String s,char[] buf, int offset, int length)
289     {
290         if (s.length()!=length)
291             return false;
292         for (int i=0;i<length;i++)
293             if (buf[offset+i]!=s.charAt(i))
294                 return false;
295         return true;
296     }
297 
298     /* ------------------------------------------------------------ */
299     public static String toUTF8String(byte[] b,int offset,int length)
300     {
301         try
302         {
303             if (length<32)
304             {
305                 Utf8StringBuffer buffer = new Utf8StringBuffer(length);
306                 buffer.append(b,offset,length);
307                 return buffer.toString();
308             }
309             
310             return new String(b,offset,length,__UTF8);
311         }
312         catch (UnsupportedEncodingException e)
313         {
314             e.printStackTrace();
315             return null;
316         }
317     }
318 
319     /* ------------------------------------------------------------ */
320     public static String toString(byte[] b,int offset,int length,String charset)
321     {
322         if (charset==null || StringUtil.isUTF8(charset))
323             return toUTF8String(b,offset,length);
324         
325         try
326         {
327             return new String(b,offset,length,charset);
328         }
329         catch (UnsupportedEncodingException e)
330         {
331             e.printStackTrace();
332             return null;
333         }
334     }
335 
336 
337     /* ------------------------------------------------------------ */
338     public static boolean isUTF8(String charset)
339     {
340         return charset==__UTF8 || __UTF8.equalsIgnoreCase(charset);
341     }
342 
343 
344     /* ------------------------------------------------------------ */
345     public static String printable(String name)
346     {
347         if (name==null)
348             return null;
349         StringBuffer buf = new StringBuffer(name.length());
350         for (int i=0;i<name.length();i++)
351         {
352             char c=name.charAt(i);
353             if (!Character.isISOControl(c))
354                 buf.append(c);
355         }
356         return buf.toString();
357     }
358     
359     
360 }