View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.mavibot.btree.util;
21  
22  
23  import java.io.UnsupportedEncodingException;
24  import java.nio.ByteBuffer;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  
30  /**
31   * Various string manipulation methods that are more efficient then chaining
32   * string operations: all is done in the same buffer without creating a bunch of
33   * string objects.
34   *
35   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
36   */
37  public final class Strings
38  {
39      /** Hex chars */
40      private static final byte[] HEX_CHAR = new byte[]
41          { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
42  
43      /** A empty byte array */
44      public static final byte[] EMPTY_BYTES = new byte[0];
45  
46  
47      /**
48       * Helper function that dump an array of bytes in hex form
49       *
50       * @param buffer The bytes array to dump
51       * @return A string representation of the array of bytes
52       */
53      public static String dumpBytes( byte[] buffer )
54      {
55          if ( buffer == null )
56          {
57              return "";
58          }
59  
60          StringBuffer sb = new StringBuffer();
61  
62          for ( byte b : buffer )
63          {
64              sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( b & 0x00F0 ) >> 4] ) ).append(
65                  ( char ) ( HEX_CHAR[b & 0x000F] ) ).append( " " );
66          }
67  
68          return sb.toString();
69      }
70  
71  
72      /**
73       * Helper function that dump a byte in hex form
74       *
75       * @param octet The byte to dump
76       * @return A string representation of the byte
77       */
78      public static String dumpByte( byte octet )
79      {
80          return new String( new byte[]
81              { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } );
82      }
83  
84  
85      /**
86       * Helper function that returns a char from an hex
87       *
88       * @param hex The hex to dump
89       * @return A char representation of the hex
90       */
91      public static char dumpHex( byte hex )
92      {
93          return ( char ) HEX_CHAR[hex & 0x000F];
94      }
95  
96  
97      /**
98       * Helper function that dump an array of bytes in hex pair form,
99       * without '0x' and space chars
100      *
101      * @param buffer The bytes array to dump
102      * @return A string representation of the array of bytes
103      */
104     public static String dumpHexPairs( byte[] buffer )
105     {
106         if ( buffer == null )
107         {
108             return "";
109         }
110 
111         char[] str = new char[buffer.length << 1];
112 
113         int pos = 0;
114 
115         for ( byte b : buffer )
116         {
117             str[pos++] = ( char ) ( HEX_CHAR[( b & 0x00F0 ) >> 4] );
118             str[pos++] = ( char ) ( HEX_CHAR[b & 0x000F] );
119         }
120 
121         return new String( str );
122     }
123 
124 
125     /**
126      * Gets a hex string from byte array.
127      *
128      * @param res the byte array
129      * @return the hex string representing the binary values in the array
130      */
131     public static String toHexString( byte[] res )
132     {
133         StringBuffer buf = new StringBuffer( res.length << 1 );
134 
135         for ( byte b : res )
136         {
137             String digit = Integer.toHexString( 0xFF & b );
138 
139             if ( digit.length() == 1 )
140             {
141                 digit = '0' + digit;
142             }
143 
144             buf.append( digit );
145         }
146 
147         return buf.toString().toUpperCase();
148     }
149 
150 
151     /**
152      * Get byte array from hex string
153      *
154      * @param hexString the hex string to convert to a byte array
155      * @return the byte form of the hex string.
156      */
157     public static byte[] toByteArray( String hexString )
158     {
159         int arrLength = hexString.length() >> 1;
160         byte[] buf = new byte[arrLength];
161 
162         for ( int ii = 0; ii < arrLength; ii++ )
163         {
164             int index = ii << 1;
165 
166             String digit = hexString.substring( index, index + 2 );
167             buf[ii] = ( byte ) Integer.parseInt( digit, 16 );
168         }
169 
170         return buf;
171     }
172 
173     private static final byte[] UTF8 = new byte[]
174         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
175             0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
176             0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
177             0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
178             0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
179             0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
180             0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
181             0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F };
182 
183 
184     /**
185      * Return an UTF-8 encoded String
186      *
187      * @param bytes The byte array to be transformed to a String
188      * @return A String.
189      */
190     public static String utf8ToString( byte[] bytes )
191     {
192         if ( bytes == null )
193         {
194             return "";
195         }
196 
197         char[] chars = new char[bytes.length];
198         int pos = 0;
199 
200         try
201         {
202             for ( byte b : bytes )
203             {
204                 chars[pos++] = ( char ) UTF8[b];
205             }
206         }
207         catch ( ArrayIndexOutOfBoundsException aioobe )
208         {
209             try
210             {
211                 return new String( bytes, "UTF-8" );
212             }
213             catch ( UnsupportedEncodingException uee )
214             {
215                 // if this happens something is really strange
216                 throw new RuntimeException( uee );
217             }
218         }
219 
220         return new String( chars );
221     }
222 
223 
224     /**
225      * Return an UTF-8 encoded String
226      *
227      * @param bytes The byte array to be transformed to a String
228      * @return A String.
229      */
230     public static String utf8ToString( ByteBuffer bytes )
231     {
232         if ( bytes == null )
233         {
234             return "";
235         }
236 
237         char[] chars = new char[bytes.limit()];
238         int pos = 0;
239         int currentPos = bytes.position();
240 
241         do
242         {
243             chars[pos++] = ( char ) UTF8[bytes.get()];
244         }
245         while ( bytes.position() < bytes.limit() );
246 
247         // restore the buffer
248         bytes.position( currentPos );
249 
250         return new String( chars );
251     }
252 
253 
254     /**
255      * Return an UTF-8 encoded String
256      *
257      * @param bytes The byte array to be transformed to a String
258      * @param length The length of the byte array to be converted
259      * @return A String.
260      */
261     public static String utf8ToString( byte[] bytes, int length )
262     {
263         if ( bytes == null )
264         {
265             return "";
266         }
267 
268         try
269         {
270             return new String( bytes, 0, length, "UTF-8" );
271         }
272         catch ( UnsupportedEncodingException uee )
273         {
274             // if this happens something is really strange
275             throw new RuntimeException( uee );
276         }
277     }
278 
279 
280     /**
281      * Return an UTF-8 encoded String
282      *
283      * @param bytes  The byte array to be transformed to a String
284      * @param start the starting position in the byte array
285      * @param length The length of the byte array to be converted
286      * @return A String.
287      */
288     public static String utf8ToString( byte[] bytes, int start, int length )
289     {
290         if ( bytes == null )
291         {
292             return "";
293         }
294 
295         try
296         {
297             return new String( bytes, start, length, "UTF-8" );
298         }
299         catch ( UnsupportedEncodingException uee )
300         {
301             // if this happens something is really strange
302             throw new RuntimeException( uee );
303         }
304     }
305 
306 
307     /**
308      * <p>
309      * Checks if a String is empty ("") or null.
310      * </p>
311      *
312      * <pre>
313      *  StringUtils.isEmpty(null)      = true
314      *  StringUtils.isEmpty(&quot;&quot;)        = true
315      *  StringUtils.isEmpty(&quot; &quot;)       = false
316      *  StringUtils.isEmpty(&quot;bob&quot;)     = false
317      *  StringUtils.isEmpty(&quot;  bob  &quot;) = false
318      * </pre>
319      *
320      * <p>
321      * NOTE: This method changed in Lang version 2.0. It no longer trims the
322      * String. That functionality is available in isBlank().
323      * </p>
324      *
325      * @param str the String to check, may be null
326      * @return <code>true</code> if the String is empty or null
327      */
328     public static boolean isEmpty( String str )
329     {
330         return ( str == null ) || ( str.length() == 0 );
331     }
332 
333 
334     /**
335      * Checks if a bytes array is empty or null.
336      *
337      * @param bytes The bytes array to check, may be null
338      * @return <code>true</code> if the bytes array is empty or null
339      */
340     public static boolean isEmpty( byte[] bytes )
341     {
342         return ( bytes == null ) || ( bytes.length == 0 );
343     }
344 
345 
346     /**
347      * Return UTF-8 encoded byte[] representation of a String
348      *
349      * @param string The string to be transformed to a byte array
350      * @return The transformed byte array
351      */
352     public static byte[] getBytesUtf8( String string )
353     {
354         if ( string == null )
355         {
356             return EMPTY_BYTES;
357         }
358 
359         try
360         {
361             return string.getBytes( "UTF-8" );
362         }
363         catch ( UnsupportedEncodingException uee )
364         {
365             // if this happens something is really strange
366             throw new RuntimeException( uee );
367         }
368     }
369 
370 
371     /**
372      * When the string to convert to bytes is pure ascii, this is a faster 
373      * method than the getBytesUtf8. Otherwise, it's slower.
374      * 
375      * @param string The string to convert to byte[]
376      * @return The bytes 
377      */
378     public static byte[] getBytesUtf8Ascii( String string )
379     {
380         if ( string == null )
381         {
382             return new byte[0];
383         }
384 
385         try
386         {
387             try
388             {
389                 char[] chars = string.toCharArray();
390                 byte[] bytes = new byte[chars.length];
391                 int pos = 0;
392 
393                 for ( char c : chars )
394                 {
395                     bytes[pos++] = UTF8[c];
396                 }
397 
398                 return bytes;
399             }
400             catch ( ArrayIndexOutOfBoundsException aioobe )
401             {
402                 return string.getBytes( "UTF-8" );
403             }
404         }
405         catch ( UnsupportedEncodingException uee )
406         {
407             // if this happens something is really strange
408             throw new RuntimeException( uee );
409         }
410     }
411 
412 
413     /**
414      * Utility method that return a String representation of a list
415      *
416      * @param list The list to transform to a string
417      * @return A csv string
418      */
419     public static String listToString( List<?> list )
420     {
421         if ( ( list == null ) || ( list.size() == 0 ) )
422         {
423             return "";
424         }
425 
426         StringBuilder sb = new StringBuilder();
427         boolean isFirst = true;
428 
429         for ( Object elem : list )
430         {
431             if ( isFirst )
432             {
433                 isFirst = false;
434             }
435             else
436             {
437                 sb.append( ", " );
438             }
439 
440             sb.append( elem );
441         }
442 
443         return sb.toString();
444     }
445 
446 
447     /**
448      * Utility method that return a String representation of a set
449      *
450      * @param set The set to transform to a string
451      * @return A csv string
452      */
453     public static String setToString( Set<?> set )
454     {
455         if ( ( set == null ) || ( set.size() == 0 ) )
456         {
457             return "";
458         }
459 
460         StringBuilder sb = new StringBuilder();
461         boolean isFirst = true;
462 
463         for ( Object elem : set )
464         {
465             if ( isFirst )
466             {
467                 isFirst = false;
468             }
469             else
470             {
471                 sb.append( ", " );
472             }
473 
474             sb.append( elem );
475         }
476 
477         return sb.toString();
478     }
479 
480 
481     /**
482      * Utility method that return a String representation of a list
483      *
484      * @param list The list to transform to a string
485      * @param tabs The tabs to add in ffront of the elements
486      * @return A csv string
487      */
488     public static String listToString( List<?> list, String tabs )
489     {
490         if ( ( list == null ) || ( list.size() == 0 ) )
491         {
492             return "";
493         }
494 
495         StringBuffer sb = new StringBuffer();
496 
497         for ( Object elem : list )
498         {
499             sb.append( tabs );
500             sb.append( elem );
501             sb.append( '\n' );
502         }
503 
504         return sb.toString();
505     }
506 
507 
508     /**
509      * Utility method that return a String representation of a map. The elements
510      * will be represented as "key = value"
511      *
512      * @param map The map to transform to a string
513      * @return A csv string
514      */
515     public static String mapToString( Map<?, ?> map )
516     {
517         if ( ( map == null ) || ( map.size() == 0 ) )
518         {
519             return "";
520         }
521 
522         StringBuffer sb = new StringBuffer();
523         boolean isFirst = true;
524 
525         for ( Map.Entry<?, ?> entry : map.entrySet() )
526         {
527             if ( isFirst )
528             {
529                 isFirst = false;
530             }
531             else
532             {
533                 sb.append( ", " );
534             }
535 
536             sb.append( entry.getKey() );
537             sb.append( " = '" ).append( entry.getValue() ).append( "'" );
538         }
539 
540         return sb.toString();
541     }
542 
543 
544     /**
545      * Utility method that return a String representation of a map. The elements
546      * will be represented as "key = value"
547      *
548      * @param map The map to transform to a string
549      * @param tabs The tabs to add in ffront of the elements
550      * @return A csv string
551      */
552     public static String mapToString( Map<?, ?> map, String tabs )
553     {
554         if ( ( map == null ) || ( map.size() == 0 ) )
555         {
556             return "";
557         }
558 
559         StringBuffer sb = new StringBuffer();
560 
561         for ( Map.Entry<?, ?> entry : map.entrySet() )
562         {
563             sb.append( tabs );
564             sb.append( entry.getKey() );
565 
566             sb.append( " = '" ).append( entry.getValue().toString() ).append( "'\n" );
567         }
568 
569         return sb.toString();
570     }
571 }