View Javadoc

1   /*
2    *   Copyright 2005 The Apache Software Foundation
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    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.asn1new.util;
18  
19  import java.io.UnsupportedEncodingException;
20  
21  /***
22   * Little helper class. Nothing that should stay here, but I need those 
23   * to debug.
24   * 
25   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
26   */
27  public class StringUtils
28  {
29      //~ Static fields/initializers -----------------------------------------------------------------
30  
31      /*** Hex chars */
32      private static final byte[] HEX_CHAR =
33          new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
34      
35      private static int UTF8_MULTI_BYTES_MASK = 0x0080;
36      
37      private static int UTF8_TWO_BYTES_MASK = 0x00E0;
38      private static int UTF8_TWO_BYTES = 0x00C0;
39      
40      private static int UTF8_THREE_BYTES_MASK = 0x00F0;
41      private static int UTF8_THREE_BYTES = 0x00E0;
42  
43      private static int UTF8_FOUR_BYTES_MASK = 0x00F8;
44      private static int UTF8_FOUR_BYTES = 0x00F0;
45      
46      private static int UTF8_FIVE_BYTES_MASK = 0x00FC;
47      private static int UTF8_FIVE_BYTES = 0x00F8;
48  
49      private static int UTF8_SIX_BYTES_MASK = 0x00FE;
50      private static int UTF8_SIX_BYTES = 0x00FC;
51      
52      /*** <alpha>    ::= [0x41-0x5A] | [0x61-0x7A] */
53      public static final boolean[] ALPHA =
54      {
55          false, false, false, false, false, false, false, false, false, false, false, false, false,
56          false, false, false, false, false, false, false, false, false, false, false, false, false,
57          false, false, false, false, false, false, false, false, false, false, false, false, false,
58          false, false, false, false, false, false, false, false, false, false, false, false, false,
59          false, false, false, false, false, false, false, false, false, false, false, false, false,
60          true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
61          true, true, true, true, true, true, true, true, true, true, true, false, false, false,
62          false, false, false, true, true, true, true, true, true, true, true, true, true, true,
63          true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
64          false, false, false, false, false
65      };
66  
67      /*** <alpha> | <digit> | '-' */
68      public static final boolean[] CHAR =
69      {
70          false, false, false, false, false, false, false, false, false, false, false, false, false,
71          false, false, false, false, false, false, false, false, false, false, false, false, false,
72          false, false, false, false, false, false, false, false, false, false, false, false, false,
73          false, false, false, false, false, false, true, false, false, true, true, true, true, true,
74          true, true, true, true, true, false, false, false, false, false, false, false, true, true,
75          true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
76          true, true, true, true, true, true, true, true, true, false, false, false, false, false,
77          false, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
78          true, true, true, true, true, true, true, true, true, true, true, true, false, false,
79          false, false, false
80      };
81  
82      /*** '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' */
83      public static final boolean[] DIGIT =
84      {
85          false, false, false, false, false, false, false, false, false, false, false, false, false,
86          false, false, false, false, false, false, false, false, false, false, false, false, false,
87          false, false, false, false, false, false, false, false, false, false, false, false, false,
88          false, false, false, false, false, false, false, false, false, true, true, true, true,
89          true, true, true, true, true, true, false, false, false, false, false, false, false, false,
90          false, false, false, false, false, false, false, false, false, false, false, false, false,
91          false, false, false, false, false, false, false, false, false, false, false, false, false,
92          false, false, false, false, false, false, false, false, false, false, false, false, false,
93          false, false, false, false, false, false, false, false, false, false, false, false, false,
94          false, false, false, false, false, false, false, false, false, false,
95      };
96  
97      /*** <hex>    ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66] */
98      private static final boolean[] HEX =
99      {
100         false, false, false, false, false, false, false, false, false, false, false, false, false,
101         false, false, false, false, false, false, false, false, false, false, false, false, false,
102         false, false, false, false, false, false, false, false, false, false, false, false, false,
103         false, false, false, false, false, false, false, false, false, true, true, true, true,
104         true, true, true, true, true, true, false, false, false, false, false, false, false, true,
105         true, true, true, true, true, false, false, false, false, false, false, false, false,
106         false, false, false, false, false, false, false, false, false, false, false, false, false,
107         false, false, false, false, false, true, true, true, true, true, true, false, false, false,
108         false, false, false, false, false, false, false, false, false, false, false, false, false,
109         false, false, false, false, false, false, false, false, false
110     };
111 
112     private static int CHAR_ONE_BYTE_MASK    = 0xFFFFFF80;
113     
114     private static int CHAR_TWO_BYTES_MASK   = 0xFFFFF800;
115     
116     private static int CHAR_THREE_BYTES_MASK = 0xFFFF0000;
117     
118     private static int CHAR_FOUR_BYTES_MASK  = 0xFFE00000;
119     
120     private static int CHAR_FIVE_BYTES_MASK  = 0xFC000000;
121     
122     private static int CHAR_SIX_BYTES_MASK   = 0x80000000;
123     
124     public static final int NOT_EQUAL = -1;
125 
126     //~ Methods ------------------------------------------------------------------------------------
127 
128     /***
129      * Helper function that dump a byte in hex form
130      * 
131      * @param octet The byte to dump
132      * @return A string representation of the byte
133      */
134     public static String dumpByte( byte octet )
135     {
136         return new String(
137                 new byte[] { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } );
138     }
139     
140     /***
141      * Helper function that dump an array of bytes in hex form
142      * 
143      * @param octet The bytes array to dump
144      * @return A string representation of the array of bytes
145      */
146     public static String dumpBytes( byte[] buffer )
147     {
148         StringBuffer sb = new StringBuffer();
149         
150         for (int i = 0; i < buffer.length ; i++)
151         {
152             sb.append("0x").append((char)(HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4])).append((char)(HEX_CHAR[buffer[i] & 0x000F])).append(" ");
153         }
154         
155         return sb.toString();
156     }
157     
158     /***
159      * Return the Unicode char which is coded in the bytes at position 0.
160      * 
161      * @param bytes The byte[] represntation of an Unicode string. 
162      * @return The first char found.
163      */
164     public static char bytesToChar(byte[] bytes)
165     {
166         return bytesToChar(bytes, 0);
167     }
168 
169     /***
170      * Count the number of bytes needed to return an Unicode char. This
171      * can be from 1 to 6. 
172      * @param bytes The bytes to read
173      * @param pos Position to start counting. It must be a valid start of a 
174      * encoded char !
175      * @return The number of bytes to create a char, or -1 if the encoding is wrong.
176      * 
177      * TODO : Should stop after the third byte, as a char is only 2 bytes long.
178      */
179     public static int countBytesPerChar(byte[] bytes, int pos)
180     {
181         if ((bytes[pos] & UTF8_MULTI_BYTES_MASK) == 0)
182         {
183             return 1;
184         } else if ((bytes[pos] & UTF8_TWO_BYTES_MASK) == UTF8_TWO_BYTES)
185     	{
186             return 2;
187     	}
188     	else if ((bytes[pos] & UTF8_THREE_BYTES_MASK) == UTF8_THREE_BYTES)
189     	{
190     	    return 3;
191     	}
192     	else if ((bytes[pos] & UTF8_FOUR_BYTES_MASK) == UTF8_FOUR_BYTES)
193     	{
194     	    return 4;
195     	}
196     	else if ((bytes[pos] & UTF8_FIVE_BYTES_MASK) == UTF8_FIVE_BYTES)
197     	{
198     	    return 5;
199     	}
200     	else if ((bytes[pos] & UTF8_SIX_BYTES_MASK) == UTF8_SIX_BYTES)
201     	{
202     	    return 6;
203         } 
204     	else
205     	{
206     	    return -1;
207     	}
208     }
209     
210     /***
211      * Return the number of bytes that hold an Unicode char.
212      * 
213      * @param car The character to be decoded
214      * @return The number of bytes to hold the char.
215      * 
216      * TODO : Should stop after the third byte, as a char is only 2 bytes long.
217      */
218     public static int countNbBytesPerChar( char car )
219     {
220         if ( ( car & CHAR_ONE_BYTE_MASK ) == 0 )
221         {
222             return 1;
223         }
224         else if ( ( car & CHAR_TWO_BYTES_MASK ) == 0 )
225         {
226             return 2;
227         }
228         else if ( ( car & CHAR_THREE_BYTES_MASK ) == 0 )
229         {
230             return 3;
231         }
232         else if ( ( car & CHAR_FOUR_BYTES_MASK ) == 0 )
233         {
234             return 4;
235         }
236         else if ( ( car & CHAR_FIVE_BYTES_MASK ) == 0 )
237         {
238             return 5;
239         }
240         else if ( ( car & CHAR_SIX_BYTES_MASK ) == 0 )
241         {
242             return 6;
243         } 
244         else
245         {
246             return -1;
247         }
248     }
249     
250     /***
251      * Count the number of bytes included in the given char[].  
252      * @param chars The char array to decode
253      * @return The number of bytes in the char array
254      */
255     public static int countBytes(char[] chars) throws UnsupportedEncodingException
256     {
257         int nbBytes = 0;
258         int currentPos = 0;
259         
260         while ( currentPos < chars.length )
261         {
262             int nbb = countNbBytesPerChar( chars[currentPos] );
263             
264             // If the number of bytes necessary to encode a character is
265             // above 3, we will need two UTF-16 chars
266             currentPos += (nbb < 4 ? 1 : 2 );
267             nbBytes += nbb;
268         }
269 
270         return nbBytes;
271     }
272     
273     /***
274      * Return the Unicode char which is coded in the bytes at the given position. 
275      * @param bytes The byte[] represntation of an Unicode string. 
276      * @param pos The current position to start decoding the char
277      * @return The char found.
278      * @return The decoded char, or -1 if no char can be decoded
279      * 
280      * TODO : Should stop after the third byte, as a char is only 2 bytes long.
281      */
282     public static char bytesToChar(byte[] bytes, int pos)
283     {
284     	if ((bytes[pos] & UTF8_MULTI_BYTES_MASK) == 0)
285 		{
286     		return (char)bytes[pos];
287 		}
288     	else
289     	{
290     		if ((bytes[pos] & UTF8_TWO_BYTES_MASK) == UTF8_TWO_BYTES)
291     		{
292     			// Two bytes char
293     			return (char)( 
294     					( ( bytes[pos] & 0x1C ) << 6 ) + 	// 110x-xxyy 10zz-zzzz -> 0000-0xxx 0000-0000
295     					( ( bytes[pos] & 0x03 ) << 6 ) + 	// 110x-xxyy 10zz-zzzz -> 0000-0000 yy00-0000
296 						( bytes[pos + 1] & 0x3F ) 		   	// 110x-xxyy 10zz-zzzz -> 0000-0000 00zz-zzzz
297 						); 								//                     -> 0000-0xxx yyzz-zzzz (07FF)
298     		}
299     		else if ((bytes[pos] & UTF8_THREE_BYTES_MASK) == UTF8_THREE_BYTES)
300     		{
301     			// Three bytes char
302     			return (char)( 
303     					// 1110-tttt 10xx-xxyy 10zz-zzzz -> tttt-0000-0000-0000
304     					( ( bytes[pos] & 0x0F) << 12 ) + 	
305 						// 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-xxxx-0000-0000
306     					( ( bytes[pos + 1] & 0x3C) << 6 ) + 	
307 						// 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-0000-yy00-0000
308     					( ( bytes[pos + 1] & 0x03) << 6 ) + 	
309 						// 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-0000-00zz-zzzz
310 						( bytes[pos + 2] & 0x3F )				
311 						//                               -> tttt-xxxx yyzz-zzzz (FF FF)
312 						);   							 
313     		}
314     		else if ((bytes[pos] & UTF8_FOUR_BYTES_MASK) == UTF8_FOUR_BYTES)
315     		{
316     			// Four bytes char
317     			return (char)(
318     					// 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 000t-tt00 0000-0000 0000-0000
319     					( ( bytes[pos] & 0x07) << 18 ) +
320 						// 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-00uu 0000-0000 0000-0000
321     					( ( bytes[pos + 1] & 0x30) << 16 ) + 
322 						// 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000 vvvv-0000 0000-0000
323     					( ( bytes[pos + 1] & 0x0F) << 12 ) + 
324 						// 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-xxxx 0000-0000
325     					( ( bytes[pos + 2] & 0x3C) << 6 ) + 
326 						// 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-0000 yy00-0000
327     					( ( bytes[pos + 2] & 0x03) << 6 ) +
328 						// 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-0000 00zz-zzzz
329 						( bytes[pos + 3] & 0x3F )
330 						//                                         -> 000t-ttuu vvvv-xxxx yyzz-zzzz (1FFFFF)
331 						);   
332     		}
333     		else if ((bytes[pos] & UTF8_FIVE_BYTES_MASK) == UTF8_FIVE_BYTES)
334     		{
335     			// Five bytes char
336     			return (char)( 
337     					// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-00tt 0000-0000 0000-0000 0000-0000
338     					( ( bytes[pos] & 0x03) << 24 ) + 
339     					// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-0000 uuuu-uu00 0000-0000 0000-0000
340     					( ( bytes[pos + 1] & 0x3F) << 18 ) + 
341     					// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-00vv 0000-0000 0000-0000
342     					( ( bytes[pos + 2] & 0x30) << 12 ) + 
343     					// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-0000 wwww-0000 0000-0000
344     					( ( bytes[pos + 2] & 0x0F) << 12 ) + 
345     					// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-0000 0000-xxxx 0000-0000
346     					( ( bytes[pos + 3] & 0x3C) << 6 ) + 
347     					// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-0000 0000-0000 yy00-0000
348     					( ( bytes[pos + 3] & 0x03) << 6 ) + 
349 						// 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz -> 0000-0000 0000-0000 0000-0000 00zz-zzzz
350 						( bytes[pos + 4] & 0x3F )
351 						// -> 0000-00tt uuuu-uuvv wwww-xxxx yyzz-zzzz (03 FF FF FF)
352 						);   
353     		}
354     		else if ((bytes[pos] & UTF8_FIVE_BYTES_MASK) == UTF8_FIVE_BYTES)
355     		{
356     			// Six bytes char
357     			return (char)( 
358     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
359     			        // 0s00-0000 0000-0000 0000-0000 0000-0000
360     					( ( bytes[pos] & 0x01) << 30 ) + 
361     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
362     			        // 00tt-tttt 0000-0000 0000-0000 0000-0000
363     					( ( bytes[pos + 1] & 0x3F) << 24 ) + 
364     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
365     			        // 0000-0000 uuuu-uu00 0000-0000 0000-0000
366     					( ( bytes[pos + 2] & 0x3F) << 18 ) + 
367     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
368     			        // 0000-0000 0000-00vv 0000-0000 0000-0000
369     					( ( bytes[pos + 3] & 0x30) << 12 ) + 
370     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
371     			        // 0000-0000 0000-0000 wwww-0000 0000-0000
372     					( ( bytes[pos + 3] & 0x0F) << 12 ) + 
373     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
374     					// 0000-0000 0000-0000 0000-xxxx 0000-0000
375     					( ( bytes[pos + 4] & 0x3C) << 6 ) + 
376     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
377     					// 0000-0000 0000-0000 0000-0000 yy00-0000
378     					( ( bytes[pos + 4] & 0x03) << 6 ) + 
379     			        // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
380     					// 0000-0000 0000-0000 0000-0000 00zz-zzzz
381 						( bytes[pos + 5] & 0x3F )
382     			        // -> 0stt-tttt uuuu-uuvv wwww-xxxx yyzz-zzzz (7F FF FF FF)
383 						);   
384     		} 
385     		else
386     		{
387     		    return (char)-1;
388     		}
389     	}
390     }
391     
392     /***
393      * Count the number of chars included in the given byte[].  
394      * @param bytes The byte array to decode
395      * @return The number of char in the byte array
396      */
397     public static int countChars(byte[] bytes)
398     {
399         int nbChars = 0;
400         int currentPos = 0;
401         
402         while (currentPos < bytes.length)
403         {
404             currentPos += countBytesPerChar(bytes, currentPos);
405             nbChars ++;
406         }
407 
408         return nbChars;
409     }
410     
411     /***
412      * Check if a text is present at the current position in a buffer.
413      *
414      * @param byteArray The buffer which contains the data
415      * @param index Current position in the buffer
416      * @param text The text we want to check
417      *
418      * @return <code>true</code> if the buffer contains the text.
419      */
420     public static int areEquals( byte[] byteArray, int index, String text )
421     {
422         if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( byteArray.length <= index ) ||
423                 ( index < 0 ) || ( text == null ) )
424         {
425             return NOT_EQUAL;
426         }
427         else
428         {
429             try
430             {
431                 byte[] data = text.getBytes( "UTF-8" );
432 
433                 return areEquals( byteArray, index, data );
434             }
435             catch ( UnsupportedEncodingException uee )
436             {
437                 return NOT_EQUAL;
438             }
439         }
440     }
441 
442     /***
443      * Check if a text is present at the current position in a buffer.
444      *
445      * @param byteArray The buffer which contains the data
446      * @param index Current position in the buffer
447      * @param text The text we want to check
448      *
449      * @return <code>true</code> if the buffer contains the text.
450      */
451     public static int areEquals( char[] charArray, int index, String text )
452     {
453         if ( ( charArray == null ) || ( charArray.length == 0 ) || ( charArray.length <= index ) ||
454                 ( index < 0 ) || ( text == null ) )
455         {
456             return NOT_EQUAL;
457         }
458         else
459         {
460             char[] data = text.toCharArray();
461 
462             return areEquals( charArray, index, data );
463         }
464     }
465 
466     /***
467      * Check if a text is present at the current position in a buffer.
468      *
469      * @param charArray The buffer which contains the data
470      * @param index Current position in the buffer
471      * @param charArray2 The text we want to check
472      *
473      * @return <code>true</code> if the buffer contains the text.
474      */
475     public static int areEquals( char[] charArray, int index, char[] charArray2 )
476     {
477 
478         if ( ( charArray == null ) ||
479                 ( charArray.length == 0 ) ||
480                 ( charArray.length <= index ) ||
481                 ( index < 0 ) ||
482                 ( charArray2 == null ) ||
483                 ( charArray2.length == 0 ) ||
484                 ( charArray2.length > ( charArray.length + index ) ) )
485         {
486             return NOT_EQUAL;
487         }
488         else
489         {
490             for ( int i = 0; i < charArray2.length; i++ )
491             {
492                 if ( charArray[index++] != charArray2[i] )
493                 {
494                     return NOT_EQUAL;
495                 }
496             }
497 
498             return index;
499         }
500     }
501 
502     /***
503      * Check if a text is present at the current position in a buffer.
504      *
505      * @param byteArray The buffer which contains the data
506      * @param index Current position in the buffer
507      * @param byteArray2 The text we want to check
508      *
509      * @return <code>true</code> if the buffer contains the text.
510      */
511     public static int areEquals( byte[] byteArray, int index, byte[] byteArray2 )
512     {
513 
514         if ( ( byteArray == null ) ||
515                 ( byteArray.length == 0 ) ||
516                 ( byteArray.length <= index ) ||
517                 ( index < 0 ) ||
518                 ( byteArray2 == null ) ||
519                 ( byteArray2.length == 0 ) ||
520                 ( byteArray2.length > ( byteArray.length + index ) ) )
521         {
522             return NOT_EQUAL;
523         }
524         else
525         {
526             for ( int i = 0; i < byteArray2.length; i++ )
527             {
528                 if ( byteArray[index++] != byteArray2[i] )
529                 {
530                     return NOT_EQUAL;
531                 }
532             }
533 
534             return index;
535         }
536     }
537 
538     /***
539      * Test if the current character is equal to a specific character.
540      * This function works only for character between 0 and 127, as it
541      * does compare a byte and a char (which is 16 bits wide)
542      * 
543      *
544      * @param byteArray The buffer which contains the data
545      * @param index Current position in the buffer
546      * @param car The character we want to compare with the current buffer position
547      *
548      * @return <code>true</code> if the current character equals the given character.
549      */
550     public static boolean isCharASCII( byte[] byteArray, int index, char car )
551     {
552         if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) ||
553                 ( index >= byteArray.length ) )
554         {
555             return false;
556         }
557         else
558         {
559             return ( ( byteArray[index] == car ) ? true : false );
560         }
561     }
562 
563     /***
564      * Test if the current character is equal to a specific character.
565      * 
566      *
567      * @param byteArray The buffer which contains the data
568      * @param index Current position in the buffer
569      * @param car The character we want to compare with the current buffer position
570      *
571      * @return <code>true</code> if the current character equals the given character.
572      */
573     public static boolean isCharASCII( char[] chars, int index, char car )
574     {
575         if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) ||
576                 ( index >= chars.length ) )
577         {
578             return false;
579         }
580         else
581         {
582             return ( ( chars[index] == car ) ? true : false );
583         }
584     }
585 
586     /***
587      * Check if the current character is an Hex Char
588      *  <hex>    ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
589      * 
590      * @param byteArray The buffer which contains the data
591      * @param index Current position in the buffer
592      *
593      * @return <code>true</code> if the current character is a Hex Char
594      */
595     public static boolean isHex( byte[] byteArray, int index )
596     {
597         if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) ||
598                 ( index >= byteArray.length ) )
599         {
600             return false;
601         }
602         else
603         {
604             byte c = byteArray[index];
605 
606             if ( ( c > 127 ) || ( StringUtils.HEX[c] == false ) )
607             {
608                 return false;
609             }
610             else
611             {
612                 return true;
613             }
614         }
615     }
616 
617     /***
618      * Check if the current character is an Hex Char
619      *  <hex>    ::= [0x30-0x39] | [0x41-0x46] | [0x61-0x66]
620      * 
621      * @param chars The buffer which contains the data
622      * @param index Current position in the buffer
623      *
624      * @return <code>true</code> if the current character is a Hex Char
625      */
626     public static boolean isHex( char[] chars, int index )
627     {
628         if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) ||
629                 ( index >= chars.length ) )
630         {
631             return false;
632         }
633         else
634         {
635             char c = chars[index];
636 
637             if ( ( c > 127 ) || ( StringUtils.HEX[c] == false ) )
638             {
639                 return false;
640             }
641             else
642             {
643                 return true;
644             }
645         }
646     }
647 
648     /***
649      * Test if the current character is a digit
650      * <digit>    ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
651      *
652      * @param byteArray The buffer which contains the data
653      *
654      * @return <code>true</code> if the current character is a Digit
655      */
656     public static boolean isDigit( byte[] byteArray )
657     {
658         if ( ( byteArray == null ) || ( byteArray.length == 0 ) )
659         {
660             return false;
661         }
662         else
663         {
664             return ( ( ( byteArray[0] > 127 ) || ! StringUtils.DIGIT[byteArray[0]] ) ? false : true );
665         }
666     }
667 
668     /***
669      * Test if the current character is an Alpha character :
670      *  <alpha>    ::= [0x41-0x5A] | [0x61-0x7A]
671      * 
672      * @param byteArray The buffer which contains the data
673      * @param index Current position in the buffer
674      *
675      * @return <code>true</code> if the current character is an Alpha character
676      */
677     public static boolean isAlphaASCII( byte[] byteArray, int index )
678     {
679         if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) ||
680                 ( index >= byteArray.length ) )
681         {
682             return false;
683         }
684         else
685         {
686             byte c = byteArray[index++];
687 
688             if ( ( c > 127 ) || ( StringUtils.ALPHA[c] == false ) )
689             {
690                 return false;
691             }
692             else
693             {
694                 return true;
695             }
696         }
697     }
698 
699     /***
700      * Test if the current character is an Alpha character :
701      *  <alpha>    ::= [0x41-0x5A] | [0x61-0x7A]
702      * 
703      * @param chars The buffer which contains the data
704      * @param index Current position in the buffer
705      *
706      * @return <code>true</code> if the current character is an Alpha character
707      */
708     public static boolean isAlphaASCII( char[] chars, int index )
709     {
710         if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) ||
711                 ( index >= chars.length ) )
712         {
713             return false;
714         }
715         else
716         {
717             char c = chars[index++];
718 
719             if ( ( c > 127 ) || ( StringUtils.ALPHA[c] == false ) )
720             {
721                 return false;
722             }
723             else
724             {
725                 return true;
726             }
727         }
728     }
729 
730     /***
731      * Test if the current character is a digit
732      * <digit>    ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
733      *
734      * @param byteArray The buffer which contains the data
735      * @param index Current position in the buffer
736      *
737      * @return <code>true</code> if the current character is a Digit
738      */
739     public static boolean isDigit( byte[] byteArray, int index )
740     {
741         if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) ||
742                 ( index >= byteArray.length ) )
743         {
744             return false;
745         }
746         else
747         {
748             return ( ( ( byteArray[index] > 127 ) || ! StringUtils.DIGIT[byteArray[index]] ) ? false : true );
749         }
750     }
751 
752     /***
753      * Test if the current character is a digit
754      * <digit>    ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
755      *
756      * @param byteArray The buffer which contains the data
757      * @param index Current position in the buffer
758      *
759      * @return <code>true</code> if the current character is a Digit
760      */
761     public static boolean isDigit( char[] chars, int index )
762     {
763         if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) ||
764                 ( index >= chars.length ) )
765         {
766             return false;
767         }
768         else
769         {
770             return ( ( ( chars[index] > 127 ) || ! StringUtils.DIGIT[chars[index]] ) ? false : true );
771         }
772     }
773 
774     /***
775      * Test if the current character is a digit
776      * <digit>    ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
777      *
778      * @param byteArray The buffer which contains the data
779      *
780      * @return <code>true</code> if the current character is a Digit
781      */
782     public static boolean isDigit( char[] chars )
783     {
784         if ( ( chars == null ) || ( chars.length == 0 ) )
785         {
786             return false;
787         }
788         else
789         {
790             return ( ( ( chars[0] > 127 ) || ! StringUtils.DIGIT[chars[0]] ) ? false : true );
791         }
792     }
793 
794     /***
795      * Check if the current character is an 7 bits ASCII CHAR (between 0 and 127).
796      *   <char>    ::= <alpha> | <digit> | '-'
797      *
798      * @param byteArray The buffer which contains the data
799      * @param index Current position in the buffer
800      *
801      * @return The position of the next character, if the current one is a CHAR.
802      */
803     public static boolean isAlphaDigitMinus( byte[] byteArray, int index )
804     {
805         if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) ||
806                 ( index >= byteArray.length ) )
807         {
808             return false;
809         }
810         else
811         {
812             byte c = byteArray[index++];
813 
814             if ( ( c > 127 ) || ( StringUtils.CHAR[c] == false ) )
815             {
816                 return false;
817             }
818             else
819             {
820                 return true;
821             }
822         }
823     }
824 
825     /***
826      * Check if the current character is an 7 bits ASCII CHAR (between 0 and 127).
827      *   <char>    ::= <alpha> | <digit> | '-'
828      *
829      * @param chars The buffer which contains the data
830      * @param index Current position in the buffer
831      *
832      * @return The position of the next character, if the current one is a CHAR.
833      */
834     public static boolean isAlphaDigitMinus( char[] chars, int index )
835     {
836         if ( ( chars == null ) || ( chars.length == 0 ) || ( index < 0 ) ||
837                 ( index >= chars.length ) )
838         {
839             return false;
840         }
841         else
842         {
843             char c = chars[index++];
844 
845             if ( ( c > 127 ) || ( StringUtils.CHAR[c] == false ) )
846             {
847                 return false;
848             }
849             else
850             {
851                 return true;
852             }
853         }
854     }
855     
856     // The following methods are taken from org.apache.commons.lang.StringUtils
857     
858     /***
859      * The empty String <code>""</code>.
860      * @since 2.0
861      */
862     public static final String EMPTY = "";
863 
864     // Empty checks
865     //-----------------------------------------------------------------------
866     /***
867      * <p>Checks if a String is empty ("") or null.</p>
868      *
869      * <pre>
870      * StringUtils.isEmpty(null)      = true
871      * StringUtils.isEmpty("")        = true
872      * StringUtils.isEmpty(" ")       = false
873      * StringUtils.isEmpty("bob")     = false
874      * StringUtils.isEmpty("  bob  ") = false
875      * </pre>
876      *
877      * <p>NOTE: This method changed in Lang version 2.0.
878      * It no longer trims the String.
879      * That functionality is available in isBlank().</p>
880      *
881      * @param str  the String to check, may be null
882      * @return <code>true</code> if the String is empty or null
883      */
884     public static boolean isEmpty(String str) {
885         return str == null || str.length() == 0;
886     }
887 
888     /***
889      * <p>Checks if a String is not empty ("") and not null.</p>
890      *
891      * <pre>
892      * StringUtils.isNotEmpty(null)      = false
893      * StringUtils.isNotEmpty("")        = false
894      * StringUtils.isNotEmpty(" ")       = true
895      * StringUtils.isNotEmpty("bob")     = true
896      * StringUtils.isNotEmpty("  bob  ") = true
897      * </pre>
898      *
899      * @param str  the String to check, may be null
900      * @return <code>true</code> if the String is not empty and not null
901      */
902     public static boolean isNotEmpty(String str) {
903         return str != null && str.length() > 0;
904     }
905 
906     /***
907      * <p>Removes spaces (char &lt;= 32) from both start and
908      * ends of this String, handling <code>null</code> by returning
909      * <code>null</code>.</p>
910      *
911      * Trim removes start and end characters &lt;= 32.
912      *
913      * <pre>
914      * StringUtils.trim(null)          = null
915      * StringUtils.trim("")            = ""
916      * StringUtils.trim("     ")       = ""
917      * StringUtils.trim("abc")         = "abc"
918      * StringUtils.trim("    abc    ") = "abc"
919      * </pre>
920      *
921      * @param str  the String to be trimmed, may be null
922      * @return the trimmed string, <code>null</code> if null String input
923      */
924     public static String trim(String str) {
925         if ( isEmpty( str ) )
926         {
927             return str;
928         }
929         
930         char[] array = str.toCharArray();
931         int start = 0;
932         int end = array.length;
933         
934         while ( ( start < end ) && ( array[start] == ' ' ) )
935         {
936             start++;
937         }
938         
939         while ( ( end > start ) && ( array[end - 1] == ' ' ) )
940         {
941             end--;
942         }
943         
944         return new String( array, start, ( end - start ) );
945     }
946 
947     /***
948      * <p>Removes spaces (char &lt;= 32) from start
949      * of this String, handling <code>null</code> by returning
950      * <code>null</code>.</p>
951      *
952      * Trim removes start characters &lt;= 32.
953      *
954      * <pre>
955      * StringUtils.trimLeft(null)          = null
956      * StringUtils.trimLeft("")            = ""
957      * StringUtils.trimLeft("     ")       = ""
958      * StringUtils.trimLeft("abc")         = "abc"
959      * StringUtils.trimLeft("    abc    ") = "abc    "
960      * </pre>
961      *
962      * @param str  the String to be trimmed, may be null
963      * @return the trimmed string, <code>null</code> if null String input
964      */
965     public static String trimLeft( String str ) {
966         if ( isEmpty( str ) )
967         {
968             return str;
969         }
970         
971         char[] array = str.toCharArray();
972         int start = 0;
973         
974         while ( ( start < array.length ) && ( array[start] == ' ' ) )
975         {
976             start++;
977         }
978         
979         return new String( array, start, array.length - start );
980     }
981     /***
982      * <p>Removes spaces (char &lt;= 32) from start
983      * of this array, handling <code>null</code> by returning
984      * <code>null</code>.</p>
985      *
986      * Trim removes start characters &lt;= 32.
987      *
988      * <pre>
989      * StringUtils.trimLeft(null)          = null
990      * StringUtils.trimLeft("")            = ""
991      * StringUtils.trimLeft("     ")       = ""
992      * StringUtils.trimLeft("abc")         = "abc"
993      * StringUtils.trimLeft("    abc    ") = "abc    "
994      * </pre>
995      *
996      * @param chars  the chars array to be trimmed, may be null
997      * @return the position of the first char which is not a space,
998      * or the last position of the array.
999      */
1000     public static int trimLeft( char[] chars, int pos ) {
1001         if ( chars == null )
1002         {
1003             return pos;
1004         }
1005         
1006         while ( ( pos < chars.length ) && ( chars[pos] == ' ' ) )
1007         {
1008             pos++;
1009         }
1010         
1011         return pos;
1012     }
1013 
1014     /***
1015      * <p>Removes spaces (char &lt;= 32) from start
1016      * of this array, handling <code>null</code> by returning
1017      * <code>null</code>.</p>
1018      *
1019      * Trim removes start characters &lt;= 32.
1020      *
1021      * <pre>
1022      * StringUtils.trimLeft(null)          = null
1023      * StringUtils.trimLeft("")            = ""
1024      * StringUtils.trimLeft("     ")       = ""
1025      * StringUtils.trimLeft("abc")         = "abc"
1026      * StringUtils.trimLeft("    abc    ") = "abc    "
1027      * </pre>
1028      *
1029      * @param bytes  the byte array to be trimmed, may be null
1030      * @return the position of the first byte which is not a space,
1031      * or the last position of the array.
1032      */
1033     public static int trimLeft( byte[] bytes, int pos ) {
1034         if ( bytes == null )
1035         {
1036             return pos;
1037         }
1038         
1039         while ( ( pos < bytes.length ) && ( bytes[pos] == ' ' ) )
1040         {
1041             pos++;
1042         }
1043         
1044         return pos;
1045     }
1046 
1047 
1048     /***
1049      * <p>Removes spaces (char &lt;= 32) from end
1050      * of this String, handling <code>null</code> by returning
1051      * <code>null</code>.</p>
1052      *
1053      * Trim removes start characters &lt;= 32.
1054      *
1055      * <pre>
1056      * StringUtils.trimRight(null)          = null
1057      * StringUtils.trimRight("")            = ""
1058      * StringUtils.trimRight("     ")       = ""
1059      * StringUtils.trimRight("abc")         = "abc"
1060      * StringUtils.trimRight("    abc    ") = "    abc"
1061      * </pre>
1062      *
1063      * @param str  the String to be trimmed, may be null
1064      * @return the trimmed string, <code>null</code> if null String input
1065      */
1066     public static String trimRight( String str ) {
1067         if ( isEmpty( str ) )
1068         {
1069             return str;
1070         }
1071         
1072         char[] array = str.toCharArray();
1073         int start = 0;
1074         int end = array.length;
1075         
1076         while ( ( start < end ) && ( array[start] == ' ' ) )
1077         {
1078             start++;
1079         }
1080         
1081         return new String( array, start, ( end - start ) );
1082     }
1083 
1084     /***
1085      * <p>Removes spaces (char &lt;= 32) from end
1086      * of this array, handling <code>null</code> by returning
1087      * <code>null</code>.</p>
1088      *
1089      * Trim removes start characters &lt;= 32.
1090      *
1091      * <pre>
1092      * StringUtils.trimRight(null)          = null
1093      * StringUtils.trimRight("")            = ""
1094      * StringUtils.trimRight("     ")       = ""
1095      * StringUtils.trimRight("abc")         = "abc"
1096      * StringUtils.trimRight("    abc    ") = "    abc"
1097      * </pre>
1098      *
1099      * @param chars  the chars array to be trimmed, may be null
1100      * @return the position of the first char which is not a space,
1101      * or the last position of the array.
1102      */
1103     public static int trimRight( char[] chars, int pos ) {
1104         if ( chars == null )
1105         {
1106             return pos;
1107         }
1108         
1109         while ( ( pos > 0 ) && ( chars[pos - 1] == ' ' ) )
1110         {
1111             pos--;
1112         }
1113         
1114         return pos;
1115     }
1116 
1117     /***
1118      * <p>Removes spaces (char &lt;= 32) from end
1119      * of this array, handling <code>null</code> by returning
1120      * <code>null</code>.</p>
1121      *
1122      * Trim removes start characters &lt;= 32.
1123      *
1124      * <pre>
1125      * StringUtils.trimRight(null)          = null
1126      * StringUtils.trimRight("")            = ""
1127      * StringUtils.trimRight("     ")       = ""
1128      * StringUtils.trimRight("abc")         = "abc"
1129      * StringUtils.trimRight("    abc    ") = "    abc"
1130      * </pre>
1131      *
1132      * @param chars  the chars array to be trimmed, may be null
1133      * @return the position of the first char which is not a space,
1134      * or the last position of the array.
1135      */
1136     public static int trimRight( byte[] bytes, int pos ) {
1137         if ( bytes == null )
1138         {
1139             return pos;
1140         }
1141         
1142         while ( ( pos >= 0 ) && ( bytes[pos] == ' ' ) )
1143         {
1144             pos--;
1145         }
1146         
1147         return pos;
1148     }
1149 
1150     // Case conversion
1151     //-----------------------------------------------------------------------
1152     /***
1153      * <p>Converts a String to upper case as per {@link String#toUpperCase()}.</p>
1154      *
1155      * <p>A <code>null</code> input String returns <code>null</code>.</p>
1156      *
1157      * <pre>
1158      * StringUtils.upperCase(null)  = null
1159      * StringUtils.upperCase("")    = ""
1160      * StringUtils.upperCase("aBc") = "ABC"
1161      * </pre>
1162      *
1163      * @param str  the String to upper case, may be null
1164      * @return the upper cased String, <code>null</code> if null String input
1165      */
1166     public static String upperCase(String str) {
1167         if (str == null) {
1168             return null;
1169         }
1170         return str.toUpperCase();
1171     }
1172 
1173     /***
1174      * <p>Converts a String to lower case as per {@link String#toLowerCase()}.</p>
1175      *
1176      * <p>A <code>null</code> input String returns <code>null</code>.</p>
1177      *
1178      * <pre>
1179      * StringUtils.lowerCase(null)  = null
1180      * StringUtils.lowerCase("")    = ""
1181      * StringUtils.lowerCase("aBc") = "abc"
1182      * </pre>
1183      *
1184      * @param str  the String to lower case, may be null
1185      * @return the lower cased String, <code>null</code> if null String input
1186      */
1187     public static String lowerCase(String str) {
1188         if (str == null) {
1189             return null;
1190         }
1191         return str.toLowerCase();
1192     }
1193 
1194     // Equals
1195     //-----------------------------------------------------------------------
1196     /***
1197      * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>
1198      *
1199      * <p><code>null</code>s are handled without exceptions. Two <code>null</code>
1200      * references are considered to be equal. The comparison is case sensitive.</p>
1201      *
1202      * <pre>
1203      * StringUtils.equals(null, null)   = true
1204      * StringUtils.equals(null, "abc")  = false
1205      * StringUtils.equals("abc", null)  = false
1206      * StringUtils.equals("abc", "abc") = true
1207      * StringUtils.equals("abc", "ABC") = false
1208      * </pre>
1209      *
1210      * @see java.lang.String#equals(Object)
1211      * @param str1  the first String, may be null
1212      * @param str2  the second String, may be null
1213      * @return <code>true</code> if the Strings are equal, case sensitive, or
1214      *  both <code>null</code>
1215      */
1216     public static boolean equals(String str1, String str2) {
1217         return str1 == null ? str2 == null : str1.equals(str2);
1218     }
1219     
1220     /***
1221      * Return an UTF-8 encoded String
1222      * @param bytes The byte array to be transformed to a String
1223      * @return A String. 
1224      */
1225     public static String toUtf8( byte[] bytes )
1226     {
1227         try
1228         {
1229             return new String( bytes, "UTF-8" );
1230         }
1231         catch ( UnsupportedEncodingException uee )
1232         {
1233             return "";
1234         }
1235     }
1236 
1237     /***
1238      * Return an UTF-8 encoded String
1239      * @param bytes The byte array to be transformed to a String
1240      * @return A String. 
1241      */
1242     public static byte[] getBytesUtf8( String string )
1243     {
1244         try
1245         {
1246             return string.getBytes( "UTF-8" );
1247         }
1248         catch ( UnsupportedEncodingException uee )
1249         {
1250             return new byte[]{};
1251         }
1252     }
1253 }