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 
240         byte b;
241 
242         do
243         {
244             chars[pos++] = ( char ) UTF8[bytes.get()];
245         }
246         while ( bytes.position() < bytes.limit() );
247 
248         return new String( chars );
249     }
250 
251 
252     /**
253      * Return an UTF-8 encoded String
254      *
255      * @param bytes The byte array to be transformed to a String
256      * @param length The length of the byte array to be converted
257      * @return A String.
258      */
259     public static String utf8ToString( byte[] bytes, int length )
260     {
261         if ( bytes == null )
262         {
263             return "";
264         }
265 
266         try
267         {
268             return new String( bytes, 0, length, "UTF-8" );
269         }
270         catch ( UnsupportedEncodingException uee )
271         {
272             // if this happens something is really strange
273             throw new RuntimeException( uee );
274         }
275     }
276 
277 
278     /**
279      * Return an UTF-8 encoded String
280      *
281      * @param bytes  The byte array to be transformed to a String
282      * @param start the starting position in the byte array
283      * @param length The length of the byte array to be converted
284      * @return A String.
285      */
286     public static String utf8ToString( byte[] bytes, int start, int length )
287     {
288         if ( bytes == null )
289         {
290             return "";
291         }
292 
293         try
294         {
295             return new String( bytes, start, length, "UTF-8" );
296         }
297         catch ( UnsupportedEncodingException uee )
298         {
299             // if this happens something is really strange
300             throw new RuntimeException( uee );
301         }
302     }
303 
304 
305     /**
306      * <p>
307      * Checks if a String is empty ("") or null.
308      * </p>
309      *
310      * <pre>
311      *  StringUtils.isEmpty(null)      = true
312      *  StringUtils.isEmpty(&quot;&quot;)        = true
313      *  StringUtils.isEmpty(&quot; &quot;)       = false
314      *  StringUtils.isEmpty(&quot;bob&quot;)     = false
315      *  StringUtils.isEmpty(&quot;  bob  &quot;) = false
316      * </pre>
317      *
318      * <p>
319      * NOTE: This method changed in Lang version 2.0. It no longer trims the
320      * String. That functionality is available in isBlank().
321      * </p>
322      *
323      * @param str the String to check, may be null
324      * @return <code>true</code> if the String is empty or null
325      */
326     public static boolean isEmpty( String str )
327     {
328         return ( str == null ) || ( str.length() == 0 );
329     }
330 
331 
332     /**
333      * Checks if a bytes array is empty or null.
334      *
335      * @param bytes The bytes array to check, may be null
336      * @return <code>true</code> if the bytes array is empty or null
337      */
338     public static boolean isEmpty( byte[] bytes )
339     {
340         return ( bytes == null ) || ( bytes.length == 0 );
341     }
342 
343 
344     /**
345      * Return UTF-8 encoded byte[] representation of a String
346      *
347      * @param string The string to be transformed to a byte array
348      * @return The transformed byte array
349      */
350     public static byte[] getBytesUtf8( String string )
351     {
352         if ( string == null )
353         {
354             return EMPTY_BYTES;
355         }
356 
357         try
358         {
359             return string.getBytes( "UTF-8" );
360         }
361         catch ( UnsupportedEncodingException uee )
362         {
363             // if this happens something is really strange
364             throw new RuntimeException( uee );
365         }
366     }
367 
368 
369     /**
370      * When the string to convert to bytes is pure ascii, this is a faster 
371      * method than the getBytesUtf8. Otherwise, it's slower.
372      * 
373      * @param string The string to convert to byte[]
374      * @return The bytes 
375      */
376     public static byte[] getBytesUtf8Ascii( String string )
377     {
378         if ( string == null )
379         {
380             return new byte[0];
381         }
382 
383         try
384         {
385             try
386             {
387                 char[] chars = string.toCharArray();
388                 byte[] bytes = new byte[chars.length];
389                 int pos = 0;
390 
391                 for ( char c : chars )
392                 {
393                     bytes[pos++] = UTF8[c];
394                 }
395 
396                 return bytes;
397             }
398             catch ( ArrayIndexOutOfBoundsException aioobe )
399             {
400                 return string.getBytes( "UTF-8" );
401             }
402         }
403         catch ( UnsupportedEncodingException uee )
404         {
405             // if this happens something is really strange
406             throw new RuntimeException( uee );
407         }
408     }
409 
410 
411     /**
412      * Utility method that return a String representation of a list
413      *
414      * @param list The list to transform to a string
415      * @return A csv string
416      */
417     public static String listToString( List<?> list )
418     {
419         if ( ( list == null ) || ( list.size() == 0 ) )
420         {
421             return "";
422         }
423 
424         StringBuilder sb = new StringBuilder();
425         boolean isFirst = true;
426 
427         for ( Object elem : list )
428         {
429             if ( isFirst )
430             {
431                 isFirst = false;
432             }
433             else
434             {
435                 sb.append( ", " );
436             }
437 
438             sb.append( elem );
439         }
440 
441         return sb.toString();
442     }
443 
444 
445     /**
446      * Utility method that return a String representation of a set
447      *
448      * @param set The set to transform to a string
449      * @return A csv string
450      */
451     public static String setToString( Set<?> set )
452     {
453         if ( ( set == null ) || ( set.size() == 0 ) )
454         {
455             return "";
456         }
457 
458         StringBuilder sb = new StringBuilder();
459         boolean isFirst = true;
460 
461         for ( Object elem : set )
462         {
463             if ( isFirst )
464             {
465                 isFirst = false;
466             }
467             else
468             {
469                 sb.append( ", " );
470             }
471 
472             sb.append( elem );
473         }
474 
475         return sb.toString();
476     }
477 
478 
479     /**
480      * Utility method that return a String representation of a list
481      *
482      * @param list The list to transform to a string
483      * @param tabs The tabs to add in ffront of the elements
484      * @return A csv string
485      */
486     public static String listToString( List<?> list, String tabs )
487     {
488         if ( ( list == null ) || ( list.size() == 0 ) )
489         {
490             return "";
491         }
492 
493         StringBuffer sb = new StringBuffer();
494 
495         for ( Object elem : list )
496         {
497             sb.append( tabs );
498             sb.append( elem );
499             sb.append( '\n' );
500         }
501 
502         return sb.toString();
503     }
504 
505 
506     /**
507      * Utility method that return a String representation of a map. The elements
508      * will be represented as "key = value"
509      *
510      * @param map The map to transform to a string
511      * @return A csv string
512      */
513     public static String mapToString( Map<?, ?> map )
514     {
515         if ( ( map == null ) || ( map.size() == 0 ) )
516         {
517             return "";
518         }
519 
520         StringBuffer sb = new StringBuffer();
521         boolean isFirst = true;
522 
523         for ( Map.Entry<?, ?> entry : map.entrySet() )
524         {
525             if ( isFirst )
526             {
527                 isFirst = false;
528             }
529             else
530             {
531                 sb.append( ", " );
532             }
533 
534             sb.append( entry.getKey() );
535             sb.append( " = '" ).append( entry.getValue() ).append( "'" );
536         }
537 
538         return sb.toString();
539     }
540 
541 
542     /**
543      * Utility method that return a String representation of a map. The elements
544      * will be represented as "key = value"
545      *
546      * @param map The map to transform to a string
547      * @param tabs The tabs to add in ffront of the elements
548      * @return A csv string
549      */
550     public static String mapToString( Map<?, ?> map, String tabs )
551     {
552         if ( ( map == null ) || ( map.size() == 0 ) )
553         {
554             return "";
555         }
556 
557         StringBuffer sb = new StringBuffer();
558 
559         for ( Map.Entry<?, ?> entry : map.entrySet() )
560         {
561             sb.append( tabs );
562             sb.append( entry.getKey() );
563 
564             sb.append( " = '" ).append( entry.getValue().toString() ).append( "'\n" );
565         }
566 
567         return sb.toString();
568     }
569 }