directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: r1062251 [12/13] - in /directory: apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/ apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/entry/ apacheds/trunk/core-api/src/main/java/org/apache/directo...
Date Sat, 22 Jan 2011 20:08:59 GMT
Copied: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/SingletonEnumeration.java (from r1062128, directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/SingletonEnumeration.java)
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/SingletonEnumeration.java?p2=directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/SingletonEnumeration.java&p1=directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/SingletonEnumeration.java&r1=1062128&r2=1062251&rev=1062251&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/SingletonEnumeration.java (original)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/SingletonEnumeration.java Sat Jan 22 20:08:48 2011
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.shared.ldap.util;
+package org.apache.directory.shared.util;
 
 
 import javax.naming.NamingEnumeration;

Propchange: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/SingletonEnumeration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/StringConstants.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/StringConstants.java?rev=1062251&view=auto
==============================================================================
--- directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/StringConstants.java (added)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/StringConstants.java Sat Jan 22 20:08:48 2011
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.shared.util;
+
+
+/**
+ * Various String constants are kept here.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface StringConstants
+{
+    /**
+     * The empty String <code>""</code>.
+     *
+     * @since 2.0
+     */
+    String EMPTY = "";
+    /**
+     * The empty byte[]
+     */
+    byte[] EMPTY_BYTES = new byte[]
+        {};
+    /**
+     * The empty String[]
+     */
+    String[] EMPTY_STRINGS = new String[] {};
+    int NOT_EQUAL = -1;
+}

Modified: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java?rev=1062251&r1=1062250&r2=1062251&view=diff
==============================================================================
--- directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java (original)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java Sat Jan 22 20:08:48 2011
@@ -20,6 +20,16 @@
 package org.apache.directory.shared.util;
 
 
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Various string manipulation methods that are more efficient then chaining
  * string operations: all is done in the same buffer without creating a bunch of
@@ -37,6 +47,91 @@ public final class Strings
     private static final byte[] HEX_CHAR = new byte[]
         { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 
+    /** A table containing booleans when the corresponding char is printable */
+    public static final boolean[] IS_PRINTABLE_CHAR =
+        {
+        false, false, false, false, false, false, false, false, // ---, ---, ---, ---, ---, ---, ---, ---
+        false, false, false, false, false, false, false, false, // ---, ---, ---, ---, ---, ---, ---, ---
+        false, false, false, false, false, false, false, false, // ---, ---, ---, ---, ---, ---, ---, ---
+        false, false, false, false, false, false, false, false, // ---, ---, ---, ---, ---, ---, ---, ---
+        true,  false, false, false, false, false, false, true,  // ' ', ---, ---, ---, ---, ---, ---, "'"
+        true,  true,  false, true,  true,  true,  true,  true,  // '(', ')', ---, '+', ',', '-', '.', '/'
+        true,  true,  true,  true,  true,  true,  true,  true,  // '0', '1', '2', '3', '4', '5', '6', '7',
+        true,  true,  true,  false, false, true,  false, true,  // '8', '9', ':', ---, ---, '=', ---, '?'
+        false, true,  true,  true,  true,  true,  true,  true,  // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+        true,  true,  true,  true,  true,  true,  true,  true,  // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
+        true,  true,  true,  true,  true,  true,  true,  true,  // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
+        true,  true,  true,  false, false, false, false, false, // 'X', 'Y', 'Z', ---, ---, ---, ---, ---
+        false, true,  true,  true,  true,  true,  true,  true,  // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g'
+        true,  true,  true,  true,  true,  true,  true,  true,  // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
+        true,  true,  true,  true,  true,  true,  true,  true,  // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w'
+        true,  true,  true,  false, false, false, false, false  // 'x', 'y', 'z', ---, ---, ---, ---, ---
+        };
+    public static final char[] TO_LOWER_CASE =
+        {
+            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+            0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+            0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+            ' ',  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'',
+            '(',  ')',  0x2A, '+',  ',',  '-',  '.',  '/',
+            '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+            '8',  '9',  ':',  0x3B, 0x3C, '=',  0x3E, '?',
+            0x40, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+            'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+            'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+            'x',  'y',  'z',  0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+            0x60, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+            'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+            'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+            'x',  'y',  'z',  0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+            0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+            0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+            0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+            0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+            0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+            0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+            0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+            0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+            0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+            0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+            0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+            0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+            0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+            0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+            0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+            0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+        };
+    /** upperCase = 'A' .. 'Z', '0'..'9', '-' */
+    public static final char[] UPPER_CASE =
+        {
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0, '-',   0,   0,
+            '0', '1', '2', '3', '4', '5', '6', '7',
+            '8', '9',   0,   0,   0,   0,   0,   0,
+              0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+            'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+            'X', 'Y', 'Z',   0,   0,   0,   0,   0,
+              0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+            'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+            'X', 'Y', 'Z',   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0,
+              0,   0,   0,   0,   0,   0,   0,   0
+        };
+
+
     /**
      * Private constructor
      */
@@ -44,6 +139,7 @@ public final class Strings
     {
     }
 
+
     /**
      * Helper function that dump an array of bytes in hex form
      *
@@ -126,7 +222,7 @@ public final class Strings
      * @param str the string to deep trim
      * @param toLowerCase how to normalize for case: upper or lower
      * @return the deep trimmed string
-     * @see StringTools#deepTrim( String )
+     * @see Strings#deepTrim( String )
      * 
      * TODO Replace the toCharArray() by substring manipulations
      */
@@ -197,7 +293,7 @@ public final class Strings
      * having to create multiple String and StringBuffer objects and is much
      * more efficient.
      * 
-     * @see StringTools#deepTrim( String )
+     * @see Strings#deepTrim( String )
      */
     public static String deepTrimToLower( String string )
     {
@@ -515,4 +611,1210 @@ public final class Strings
             return string.charAt( index ) == car;
         }
     }
+
+    /**
+     * Return an UTF-8 encoded String
+     *
+     * @param bytes The byte array to be transformed to a String
+     * @return A String.
+     */
+    public static String utf8ToString( byte[] bytes )
+    {
+        if ( bytes == null )
+        {
+            return "";
+        }
+
+        try
+        {
+            return new String( bytes, "UTF-8" );
+        }
+        catch ( UnsupportedEncodingException uee )
+        {
+            // if this happens something is really strange
+            throw new RuntimeException( uee );
+        }
+    }
+
+    /**
+     * Return an UTF-8 encoded String
+     *
+     * @param bytes The byte array to be transformed to a String
+     * @param length The length of the byte array to be converted
+     * @return A String.
+     */
+    public static String utf8ToString( byte[] bytes, int length )
+    {
+        if ( bytes == null )
+        {
+            return "";
+        }
+
+        try
+        {
+            return new String( bytes, 0, length, "UTF-8" );
+        }
+        catch ( UnsupportedEncodingException uee )
+        {
+            // if this happens something is really strange
+            throw new RuntimeException( uee );
+        }
+    }
+
+    /**
+     * Return an UTF-8 encoded String
+     *
+     * @param bytes  The byte array to be transformed to a String
+     * @param start the starting position in the byte array
+     * @param length The length of the byte array to be converted
+     * @return A String.
+     */
+    public static String utf8ToString( byte[] bytes, int start, int length )
+    {
+        if ( bytes == null )
+        {
+            return "";
+        }
+
+        try
+        {
+            return new String( bytes, start, length, "UTF-8" );
+        }
+        catch ( UnsupportedEncodingException uee )
+        {
+            // if this happens something is really strange
+            throw new RuntimeException( uee );
+        }
+    }
+
+    /**
+     * Check if a text is present at the current position in a buffer.
+     *
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param text The text we want to check
+     * @return <code>true</code> if the buffer contains the text.
+     */
+    public static int areEquals( byte[] bytes, int index, String text )
+    {
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 )
+            || ( text == null ) )
+        {
+            return StringConstants.NOT_EQUAL;
+        }
+        else
+        {
+            try
+            {
+                byte[] data = text.getBytes( "UTF-8" );
+
+                return areEquals( bytes, index, data );
+            }
+            catch ( UnsupportedEncodingException uee )
+            {
+                // if this happens something is really strange
+                throw new RuntimeException( uee );
+            }
+        }
+    }
+
+    /**
+     * Check if a text is present at the current position in a buffer.
+     *
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param text The text we want to check
+     * @return <code>true</code> if the buffer contains the text.
+     */
+    public static int areEquals( char[] chars, int index, String text )
+    {
+        if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 )
+            || ( text == null ) )
+        {
+            return StringConstants.NOT_EQUAL;
+        }
+        else
+        {
+            char[] data = text.toCharArray();
+
+            return areEquals( chars, index, data );
+        }
+    }
+
+    /**
+     * Check if a text is present at the current position in a buffer.
+     *
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param chars2 The text we want to check
+     * @return <code>true</code> if the buffer contains the text.
+     */
+    public static int areEquals( char[] chars, int index, char[] chars2 )
+    {
+        if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 )
+            || ( chars2 == null ) || ( chars2.length == 0 )
+            || ( chars2.length > ( chars.length + index ) ) )
+        {
+            return StringConstants.NOT_EQUAL;
+        }
+        else
+        {
+            for ( int i = 0; i < chars2.length; i++ )
+            {
+                if ( chars[index++] != chars2[i] )
+                {
+                    return StringConstants.NOT_EQUAL;
+                }
+            }
+
+            return index;
+        }
+    }
+
+    /**
+     * Check if a text is present at the current position in a buffer.
+     *
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param bytes2 The text we want to check
+     * @return <code>true</code> if the buffer contains the text.
+     */
+    public static int areEquals( byte[] bytes, int index, byte[] bytes2 )
+    {
+
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 )
+            || ( bytes2 == null ) || ( bytes2.length == 0 )
+            || ( bytes2.length > ( bytes.length + index ) ) )
+        {
+            return StringConstants.NOT_EQUAL;
+        }
+        else
+        {
+            for ( int i = 0; i < bytes2.length; i++ )
+            {
+                if ( bytes[index++] != bytes2[i] )
+                {
+                    return StringConstants.NOT_EQUAL;
+                }
+            }
+
+            return index;
+        }
+    }
+
+    /**
+     * <p>
+     * Checks if a String is empty ("") or null.
+     * </p>
+     *
+     * <pre>
+     *  StringUtils.isEmpty(null)      = true
+     *  StringUtils.isEmpty(&quot;&quot;)        = true
+     *  StringUtils.isEmpty(&quot; &quot;)       = false
+     *  StringUtils.isEmpty(&quot;bob&quot;)     = false
+     *  StringUtils.isEmpty(&quot;  bob  &quot;) = false
+     * </pre>
+     *
+     * <p>
+     * NOTE: This method changed in Lang version 2.0. It no longer trims the
+     * String. That functionality is available in isBlank().
+     * </p>
+     *
+     * @param str the String to check, may be null
+     * @return <code>true</code> if the String is empty or null
+     */
+    public static boolean isEmpty( String str )
+    {
+        return str == null || str.length() == 0;
+    }
+
+    /**
+     * Checks if a bytes array is empty or null.
+     *
+     * @param bytes The bytes array to check, may be null
+     * @return <code>true</code> if the bytes array is empty or null
+     */
+    public static boolean isEmpty( byte[] bytes )
+    {
+        return bytes == null || bytes.length == 0;
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from both start and ends of this String,
+     * handling <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start and end characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trim(null)          = null
+     *  StringUtils.trim(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trim(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trim(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trim(&quot;    abc    &quot;) = &quot;abc&quot;
+     * </pre>
+     *
+     * @param str the String to be trimmed, may be null
+     * @return the trimmed string, <code>null</code> if null String input
+     */
+    public static String trim( String str )
+    {
+        return ( isEmpty( str ) ? "" : str.trim() );
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from both start and ends of this bytes
+     * array, handling <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start and end characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trim(null)          = null
+     *  StringUtils.trim(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trim(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trim(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trim(&quot;    abc    &quot;) = &quot;abc&quot;
+     * </pre>
+     *
+     * @param bytes the byte array to be trimmed, may be null
+     *
+     * @return the trimmed byte array
+     */
+    public static byte[] trim( byte[] bytes )
+    {
+        if ( isEmpty( bytes ) )
+        {
+            return StringConstants.EMPTY_BYTES;
+        }
+
+        int start = trimLeft( bytes, 0 );
+        int end = trimRight( bytes, bytes.length - 1 );
+
+        int length = end - start + 1;
+
+        if ( length != 0 )
+        {
+            byte[] newBytes = new byte[end - start + 1];
+
+            System.arraycopy( bytes, start, newBytes, 0, length );
+
+            return newBytes;
+        }
+        else
+        {
+            return StringConstants.EMPTY_BYTES;
+        }
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from start of this String, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimLeft(null)          = null
+     *  StringUtils.trimLeft(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimLeft(&quot;    abc    &quot;) = &quot;abc    &quot;
+     * </pre>
+     *
+     * @param str the String to be trimmed, may be null
+     * @return the trimmed string, <code>null</code> if null String input
+     */
+    public static String trimLeft( String str )
+    {
+        if ( isEmpty( str ) )
+        {
+            return "";
+        }
+
+        int start = 0;
+        int end = str.length();
+
+        while ( ( start < end ) && ( str.charAt( start ) == ' ' ) )
+        {
+            start++;
+        }
+
+        return ( start == 0 ? str : str.substring( start ) );
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from start of this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimLeft(null)          = null
+     *  StringUtils.trimLeft(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimLeft(&quot;    abc    &quot;) = &quot;abc    &quot;
+     * </pre>
+     *
+     * @param chars the chars array to be trimmed, may be null
+     * @return the position of the first char which is not a space, or the last
+     *         position of the array.
+     */
+    public static int trimLeft( char[] chars, int pos )
+    {
+        if ( chars == null )
+        {
+            return pos;
+        }
+
+        while ( ( pos < chars.length ) && ( chars[pos] == ' ' ) )
+        {
+            pos++;
+        }
+
+        return pos;
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from a position in this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimLeft(null)          = null
+     *  StringUtils.trimLeft(&quot;&quot;,...)            = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;     &quot;,...)       = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;abc&quot;,...)         = &quot;abc&quot;
+     *  StringUtils.trimLeft(&quot;    abc    &quot;,...) = &quot;abc    &quot;
+     * </pre>
+     *
+     * @param string the string to be trimmed, may be null
+     * @param pos The starting position
+     */
+    public static void trimLeft( String string, Position pos )
+    {
+        if ( string == null )
+        {
+            return;
+        }
+
+        int length = string.length();
+
+        while ( ( pos.start < length ) && ( string.charAt( pos.start ) == ' ' ) )
+        {
+            pos.start++;
+        }
+
+        pos.end = pos.start;
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from a position in this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimLeft(null)          = null
+     *  StringUtils.trimLeft(&quot;&quot;,...)            = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;     &quot;,...)       = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;abc&quot;,...)         = &quot;abc&quot;
+     *  StringUtils.trimLeft(&quot;    abc    &quot;,...) = &quot;abc    &quot;
+     * </pre>
+     *
+     * @param bytes the byte array to be trimmed, may be null
+     * @param pos The starting position
+     */
+    public static void trimLeft( byte[] bytes, Position pos )
+    {
+        if ( bytes == null )
+        {
+            return;
+        }
+
+        int length = bytes.length;
+
+        while ( ( pos.start < length ) && ( bytes[ pos.start ] == ' ' ) )
+        {
+            pos.start++;
+        }
+
+        pos.end = pos.start;
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from start of this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimLeft(null)          = null
+     *  StringUtils.trimLeft(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimLeft(&quot;    abc    &quot;) = &quot;abc    &quot;
+     * </pre>
+     *
+     * @param bytes the byte array to be trimmed, may be null
+     * @return the position of the first byte which is not a space, or the last
+     *         position of the array.
+     */
+    public static int trimLeft( byte[] bytes, int pos )
+    {
+        if ( bytes == null )
+        {
+            return pos;
+        }
+
+        while ( ( pos < bytes.length ) && ( bytes[pos] == ' ' ) )
+        {
+            pos++;
+        }
+
+        return pos;
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this String, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     *
+     * @param str the String to be trimmed, may be null
+     * @return the trimmed string, <code>null</code> if null String input
+     */
+    public static String trimRight( String str )
+    {
+        if ( isEmpty( str ) )
+        {
+            return "";
+        }
+
+        int length = str.length();
+        int end = length;
+
+        while ( ( end > 0 ) && ( str.charAt( end - 1 ) == ' ' ) )
+        {
+            if ( ( end > 1 ) && ( str.charAt(  end - 2 ) == '\\' ) )
+            {
+                break;
+            }
+
+            end--;
+        }
+
+        return ( end == length ? str : str.substring( 0, end ) );
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this String, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     *
+     * @param str the String to be trimmed, may be null
+     * @param escapedSpace The last escaped space, if any
+     * @return the trimmed string, <code>null</code> if null String input
+     */
+    public static String trimRight( String str, int escapedSpace )
+    {
+        if ( isEmpty( str ) )
+        {
+            return "";
+        }
+
+        int length = str.length();
+        int end = length;
+
+        while ( ( end > 0 ) && ( str.charAt( end - 1 ) == ' ' ) && ( end > escapedSpace ) )
+        {
+            if ( ( end > 1 ) && ( str.charAt(  end - 2 ) == '\\' ) )
+            {
+                break;
+            }
+
+            end--;
+        }
+
+        return ( end == length ? str : str.substring( 0, end ) );
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     *
+     * @param chars the chars array to be trimmed, may be null
+     * @return the position of the first char which is not a space, or the last
+     *         position of the array.
+     */
+    public static int trimRight( char[] chars, int pos )
+    {
+        if ( chars == null )
+        {
+            return pos;
+        }
+
+        while ( ( pos >= 0 ) && ( chars[pos - 1] == ' ' ) )
+        {
+            pos--;
+        }
+
+        return pos;
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this string, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     *
+     * @param string the string to be trimmed, may be null
+     * @return the position of the first char which is not a space, or the last
+     *         position of the string.
+     */
+    public static String trimRight( String string, Position pos )
+    {
+        if ( string == null )
+        {
+            return "";
+        }
+
+        while ( ( pos.end >= 0 ) && ( string.charAt( pos.end - 1 ) == ' ' ) )
+        {
+            if ( ( pos.end > 1 ) && ( string.charAt(  pos.end - 2 ) == '\\' ) )
+            {
+                break;
+            }
+
+            pos.end--;
+        }
+
+        return ( pos.end == string.length() ? string : string.substring( 0, pos.end ) );
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this string, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     *
+     * @param bytes the byte array to be trimmed, may be null
+     * @return the position of the first char which is not a space, or the last
+     *         position of the byte array.
+     */
+    public static String trimRight( byte[] bytes, Position pos )
+    {
+        if ( bytes == null )
+        {
+            return "";
+        }
+
+        while ( ( pos.end >= 0 ) && ( bytes[pos.end - 1] == ' ' ) )
+        {
+            if ( ( pos.end > 1 ) && ( bytes[pos.end - 2] == '\\' ) )
+            {
+                break;
+            }
+
+            pos.end--;
+        }
+
+        if ( pos.end == bytes.length )
+        {
+            return utf8ToString(bytes);
+        }
+        else
+        {
+            return utf8ToString(bytes, pos.end);
+        }
+    }
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     *
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     *
+     * @param bytes the byte array to be trimmed, may be null
+     * @return the position of the first char which is not a space, or the last
+     *         position of the array.
+     */
+    public static int trimRight( byte[] bytes, int pos )
+    {
+        if ( bytes == null )
+        {
+            return pos;
+        }
+
+        while ( ( pos >= 0 ) && ( bytes[pos] == ' ' ) )
+        {
+            pos--;
+        }
+
+        return pos;
+    }
+
+    /**
+     * Get the character at a given position in a string, checking fo limits
+     *
+     * @param string The string which contains the data
+     * @param index Current position in the string
+     * @return The character ar the given position, or '\0' if something went wrong
+     */
+    public static char charAt( String string, int index )
+    {
+        if ( string == null )
+        {
+            return '\0';
+        }
+
+        int length = string.length();
+
+        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
+        {
+            return '\0';
+        }
+        else
+        {
+            return string.charAt( index ) ;
+        }
+    }
+
+    /**
+     * Thansform an array of ASCII bytes to a string. the byte array should contains
+     * only values in [0, 127].
+     *
+     * @param bytes The byte array to transform
+     * @return The resulting string
+     */
+    public static String asciiBytesToString( byte[] bytes )
+    {
+        if ( (bytes == null) || (bytes.length == 0 ) )
+        {
+            return "";
+        }
+
+        char[] result = new char[bytes.length];
+
+        for ( int i = 0; i < bytes.length; i++ )
+        {
+            result[i] = (char)bytes[i];
+        }
+
+        return new String( result );
+    }
+
+    /**
+     * Return UTF-8 encoded byte[] representation of a String
+     *
+     * @param string The string to be transformed to a byte array
+     * @return The transformed byte array
+     */
+    public static byte[] getBytesUtf8( String string )
+    {
+        if ( string == null )
+        {
+            return new byte[0];
+        }
+
+        try
+        {
+            return string.getBytes( "UTF-8" );
+        }
+        catch ( UnsupportedEncodingException uee )
+        {
+            // if this happens something is really strange
+            throw new RuntimeException( uee );
+        }
+    }
+
+    /**
+     * Get the default charset
+     *
+     * @return The default charset
+     */
+    public static String getDefaultCharsetName()
+    {
+        if ( null == defaultCharset )
+        {
+            try
+            {
+                // Try with jdk 1.5 method, if we are using a 1.5 jdk :)
+                Method method = Charset.class.getMethod( "defaultCharset", new Class[0] );
+                defaultCharset = ((Charset) method.invoke( null, new Object[0]) ).name();
+            }
+            catch (NoSuchMethodException e)
+            {
+                // fall back to old method
+                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
+            }
+            catch (InvocationTargetException e)
+            {
+                // fall back to old method
+                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
+            }
+            catch (IllegalAccessException e)
+            {
+                // fall back to old method
+                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
+            }
+        }
+
+        return defaultCharset;
+    }
+
+    /**
+     * <p>
+     * Compares two Strings, returning <code>true</code> if they are equal.
+     * </p>
+     * <p>
+     * <code>null</code>s are handled without exceptions. Two
+     * <code>null</code> references are considered to be equal. The comparison
+     * is case sensitive.
+     * </p>
+     *
+     * <pre>
+     *  StringUtils.equals(null, null)   = true
+     *  StringUtils.equals(null, &quot;abc&quot;)  = false
+     *  StringUtils.equals(&quot;abc&quot;, null)  = false
+     *  StringUtils.equals(&quot;abc&quot;, &quot;abc&quot;) = true
+     *  StringUtils.equals(&quot;abc&quot;, &quot;ABC&quot;) = false
+     * </pre>
+     *
+     * @see String#equals(Object)
+     * @param str1 the first String, may be null
+     * @param str2 the second String, may be null
+     * @return <code>true</code> if the Strings are equal, case sensitive, or
+     *         both <code>null</code>
+     */
+    public static boolean equals( String str1, String str2 )
+    {
+        return str1 == null ? str2 == null : str1.equals( str2 );
+    }
+
+    /**
+     * Utility method that return a String representation of a list
+     *
+     * @param list The list to transform to a string
+     * @return A csv string
+     */
+    public static String listToString( List<?> list )
+    {
+        if ( ( list == null ) || ( list.size() == 0 ) )
+        {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        boolean isFirst = true;
+
+        for ( Object elem : list )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                sb.append( ", " );
+            }
+
+            sb.append( elem );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Utility method that return a String representation of a set
+     *
+     * @param set The set to transform to a string
+     * @return A csv string
+     */
+    public static String setToString( Set<?> set )
+    {
+        if ( ( set == null ) || ( set.size() == 0 ) )
+        {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        boolean isFirst = true;
+
+        for ( Object elem : set )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                sb.append( ", " );
+            }
+
+            sb.append( elem );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Utility method that return a String representation of a list
+     *
+     * @param list The list to transform to a string
+     * @param tabs The tabs to add in ffront of the elements
+     * @return A csv string
+     */
+    public static String listToString( List<?> list, String tabs )
+    {
+        if ( ( list == null ) || ( list.size() == 0 ) )
+        {
+            return "";
+        }
+
+        StringBuffer sb = new StringBuffer();
+
+        for ( Object elem : list )
+        {
+            sb.append( tabs );
+            sb.append( elem );
+            sb.append( '\n' );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Utility method that return a String representation of a map. The elements
+     * will be represented as "key = value"
+     *
+     * @param map The map to transform to a string
+     * @return A csv string
+     */
+    public static String mapToString( Map<?,?> map )
+    {
+        if ( ( map == null ) || ( map.size() == 0 ) )
+        {
+            return "";
+        }
+
+        StringBuffer sb = new StringBuffer();
+        boolean isFirst = true;
+
+        for ( Map.Entry<?, ?> entry:map.entrySet() )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                sb.append( ", " );
+            }
+
+            sb.append( entry.getKey() );
+            sb.append( " = '" ).append( entry.getValue() ).append( "'" );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Utility method that return a String representation of a map. The elements
+     * will be represented as "key = value"
+     *
+     * @param map The map to transform to a string
+     * @param tabs The tabs to add in ffront of the elements
+     * @return A csv string
+     */
+    public static String mapToString( Map<?,?> map, String tabs )
+    {
+        if ( ( map == null ) || ( map.size() == 0 ) )
+        {
+            return "";
+        }
+
+        StringBuffer sb = new StringBuffer();
+
+        for ( Map.Entry<?, ?> entry:map.entrySet() )
+        {
+            sb.append( tabs );
+            sb.append( entry.getKey() );
+
+            sb.append( " = '" ).append( entry.getValue().toString() ).append( "'\n" );
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Rewrote the toLowercase method to improve performances.
+     * In Ldap, attributesType are supposed to use ASCII chars :
+     * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only.
+     *
+     * @param value The String to lowercase
+     * @return The lowercase string
+     */
+    public static String toLowerCase( String value )
+    {
+        if ( ( null == value ) || ( value.length() == 0 ) )
+        {
+            return "";
+        }
+
+        char[] chars = value.toCharArray();
+
+        for ( int i = 0; i < chars.length; i++ )
+        {
+            chars[i] = TO_LOWER_CASE[ chars[i] ];
+        }
+
+        return new String( chars );
+    }
+
+    /**
+     * Rewrote the toLowercase method to improve performances.
+     * In Ldap, attributesType are supposed to use ASCII chars :
+     * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only.
+     *
+     * @param value The String to uppercase
+     * @return The uppercase string
+     */
+    public static String toUpperCase( String value )
+    {
+        if ( ( null == value ) || ( value.length() == 0 ) )
+        {
+            return "";
+        }
+
+        char[] chars = value.toCharArray();
+
+        for ( int i = 0; i < chars.length; i++ )
+        {
+            chars[i] = UPPER_CASE[ chars[i] ];
+        }
+
+        return new String( chars );
+    }
+
+    /**
+     * <p>
+     * Converts a String to upper case as per {@link String#toUpperCase()}.
+     * </p>
+     * <p>
+     * A <code>null</code> input String returns <code>null</code>.
+     * </p>
+     *
+     * <pre>
+     *  StringUtils.upperCase(null)  = null
+     *  StringUtils.upperCase(&quot;&quot;)    = &quot;&quot;
+     *  StringUtils.upperCase(&quot;aBc&quot;) = &quot;ABC&quot;
+     * </pre>
+     *
+     * @param str the String to upper case, may be null
+     * @return the upper cased String, <code>null</code> if null String input
+     */
+    public static String upperCase( String str )
+    {
+        if ( str == null )
+        {
+            return null;
+        }
+
+        return str.toUpperCase();
+    }
+
+    /**
+     * <p>
+     * Converts a String to lower case as per {@link String#toLowerCase()}.
+     * </p>
+     * <p>
+     * A <code>null</code> input String returns <code>null</code>.
+     * </p>
+     *
+     * <pre>
+     *  StringUtils.lowerCase(null)  = null
+     *  StringUtils.lowerCase(&quot;&quot;)    = &quot;&quot;
+     *  StringUtils.lowerCase(&quot;aBc&quot;) = &quot;abc&quot;
+     * </pre>
+     *
+     * @param str the String to lower case, may be null
+     * @return the lower cased String, <code>null</code> if null String input
+     */
+    public static String lowerCase( String str )
+    {
+        if ( str == null )
+        {
+            return null;
+        }
+
+        return str.toLowerCase();
+    }
+
+    /**
+     * Rewrote the toLowercase method to improve performances.
+     * In Ldap, attributesType are supposed to use ASCII chars :
+     * 'a'-'z', 'A'-'Z', '0'-'9', '.' and '-' only. We will take
+     * care of any other chars either.
+     *
+     * @param str The String to lowercase
+     * @return The lowercase string
+     */
+    public static String lowerCaseAscii( String str )
+    {
+        if ( str == null )
+        {
+            return null;
+        }
+
+        char[] chars = str.toCharArray();
+        int pos = 0;
+
+        for ( char c:chars )
+        {
+            chars[pos++] = TO_LOWER_CASE[c];
+        }
+
+        return new String( chars );
+    }
+
+    /**
+     *
+     * Check that a String is a valid PrintableString. A PrintableString contains only
+     * the following set of chars :
+     * { ' ', ''', '(', ')', '+', '-', '.', '/', [0-9], ':', '=', '?', [A-Z], [a-z]}
+     *
+     * @param str The String to check
+     * @return <code>true</code> if the string is a PrintableString or is empty,
+     * <code>false</code> otherwise
+     */
+    public static boolean isPrintableString( String str )
+    {
+        if ( ( str == null ) || ( str.length() == 0 ) )
+        {
+            return true;
+        }
+
+        for ( char c:str.toCharArray() )
+        {
+            if ( ( c > 127 ) || !IS_PRINTABLE_CHAR[ c ] )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * <p>
+     * Checks if a String is not empty ("") and not null.
+     * </p>
+     *
+     * <pre>
+     *  StringUtils.isNotEmpty(null)      = false
+     *  StringUtils.isNotEmpty(&quot;&quot;)        = false
+     *  StringUtils.isNotEmpty(&quot; &quot;)       = true
+     *  StringUtils.isNotEmpty(&quot;bob&quot;)     = true
+     *  StringUtils.isNotEmpty(&quot;  bob  &quot;) = true
+     * </pre>
+     *
+     * @param str the String to check, may be null
+     * @return <code>true</code> if the String is not empty and not null
+     */
+    public static boolean isNotEmpty( String str )
+    {
+        return str != null && str.length() > 0;
+    }
+
+    /**
+     *
+     * Check that a String is a valid IA5String. An IA5String contains only
+     * char which values is between [0, 7F]
+     *
+     * @param str The String to check
+     * @return <code>true</code> if the string is an IA5String or is empty,
+     * <code>false</code> otherwise
+     */
+    public static boolean isIA5String( String str )
+    {
+        if ( ( str == null ) || ( str.length() == 0 ) )
+        {
+            return true;
+        }
+
+        // All the chars must be in [0x00, 0x7F]
+        for ( char c:str.toCharArray() )
+        {
+            if ( ( c < 0 ) || ( c > 0x7F ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
 }

Copied: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Unicode.java (from r1062128, directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java)
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Unicode.java?p2=directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Unicode.java&p1=directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java&r1=1062128&r2=1062251&rev=1062251&view=diff
==============================================================================
--- directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Strings.java (original)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/Unicode.java Sat Jan 22 20:08:48 2011
@@ -21,498 +21,383 @@ package org.apache.directory.shared.util
 
 
 /**
- * Various string manipulation methods that are more efficient then chaining
- * string operations: all is done in the same buffer without creating a bunch of
- * string objects.
+ * Various unicode manipulation methods that are more efficient then chaining
+ * operations: all is done in the same buffer without creating a bunch of string
+ * objects.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public final class Strings
+public final class Unicode
 {
-    /** The default charset, because it's not provided by JDK 1.5 */
-    static String defaultCharset = null;
-    
-
-    /** Hex chars */
-    private static final byte[] HEX_CHAR = new byte[]
-        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-    /**
-     * Private constructor
-     */
-    private Strings()
-    {
-    }
-
     /**
-     * Helper function that dump an array of bytes in hex form
+     * Count the number of bytes needed to return an Unicode char. This can be
+     * from 1 to 6.
      *
-     * @param buffer The bytes array to dump
-     * @return A string representation of the array of bytes
+     * @param bytes The bytes to read
+     * @param pos Position to start counting. It must be a valid start of a
+     *            encoded char !
+     * @return The number of bytes to create a char, or -1 if the encoding is
+     *         wrong. TODO : Should stop after the third byte, as a char is only
+     *         2 bytes long.
      */
-    public static String dumpBytes( byte[] buffer )
+    public static int countBytesPerChar( byte[] bytes, int pos )
     {
-        if ( buffer == null )
+        if ( bytes == null )
         {
-            return "";
+            return -1;
         }
 
-        StringBuffer sb = new StringBuffer();
-
-        for ( int i = 0; i < buffer.length; i++ )
+        if ( ( bytes[pos] & UnicodeConstants.UTF8_MULTI_BYTES_MASK ) == 0 )
         {
-            sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ) ).append(
-                ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ) ).append( " " );
+            return 1;
+        }
+        else if ( ( bytes[pos] & UnicodeConstants.UTF8_TWO_BYTES_MASK ) == UnicodeConstants.UTF8_TWO_BYTES )
+        {
+            return 2;
+        }
+        else if ( ( bytes[pos] & UnicodeConstants.UTF8_THREE_BYTES_MASK ) == UnicodeConstants.UTF8_THREE_BYTES )
+        {
+            return 3;
+        }
+        else if ( ( bytes[pos] & UnicodeConstants.UTF8_FOUR_BYTES_MASK ) == UnicodeConstants.UTF8_FOUR_BYTES )
+        {
+            return 4;
+        }
+        else if ( ( bytes[pos] & UnicodeConstants.UTF8_FIVE_BYTES_MASK ) == UnicodeConstants.UTF8_FIVE_BYTES )
+        {
+            return 5;
+        }
+        else if ( ( bytes[pos] & UnicodeConstants.UTF8_SIX_BYTES_MASK ) == UnicodeConstants.UTF8_SIX_BYTES )
+        {
+            return 6;
+        }
+        else
+        {
+            return -1;
         }
-
-        return sb.toString();
-    }
-    
-
-    /**
-     * Helper function that dump a byte in hex form
-     * 
-     * @param octet The byte to dump
-     * @return A string representation of the byte
-     */
-    public static String dumpByte( byte octet )
-    {
-        return new String( new byte[]
-            { '0', 'x', HEX_CHAR[( octet & 0x00F0 ) >> 4], HEX_CHAR[octet & 0x000F] } );
     }
 
-
     /**
-     * Helper function that returns a char from an hex
-     * 
-     * @param hex The hex to dump
-     * @return A char representation of the hex
+     * Return the Unicode char which is coded in the bytes at position 0.
+     *
+     * @param bytes The byte[] represntation of an Unicode string.
+     * @return The first char found.
      */
-    public static char dumpHex( byte hex )
+    public static char bytesToChar( byte[] bytes )
     {
-        return ( char ) HEX_CHAR[hex & 0x000F];
+        return bytesToChar( bytes, 0 );
     }
 
-
     /**
-     * Helper function that dump an array of bytes in hex pair form, 
-     * without '0x' and space chars
-     * 
-     * @param buffer The bytes array to dump
-     * @return A string representation of the array of bytes
+     * Return the Unicode char which is coded in the bytes at the given
+     * position.
+     *
+     * @param bytes The byte[] represntation of an Unicode string.
+     * @param pos The current position to start decoding the char
+     * @return The decoded char, or -1 if no char can be decoded TODO : Should
+     *         stop after the third byte, as a char is only 2 bytes long.
      */
-    public static String dumpHexPairs( byte[] buffer )
+    public static char bytesToChar( byte[] bytes, int pos )
     {
-        if ( buffer == null )
+        if ( bytes == null )
         {
-            return "";
+            return ( char ) -1;
         }
-    
-        char[] str = new char[buffer.length << 1];
-    
-        for ( int i = 0, pos = 0; i < buffer.length; i++ )
-        {
-            str[pos++] = ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] );
-            str[pos++] = ( char ) ( HEX_CHAR[buffer[i] & 0x000F] );
-        }
-    
-        return new String( str );
-    }
 
-
-    /**
-     * Put common code to deepTrim(String) and deepTrimToLower here.
-     * 
-     * @param str the string to deep trim
-     * @param toLowerCase how to normalize for case: upper or lower
-     * @return the deep trimmed string
-     * @see StringTools#deepTrim( String )
-     * 
-     * TODO Replace the toCharArray() by substring manipulations
-     */
-    public static String deepTrim( String str, boolean toLowerCase )
-    {
-        if ( ( null == str ) || ( str.length() == 0 ) )
+        if ( ( bytes[pos] & UnicodeConstants.UTF8_MULTI_BYTES_MASK ) == 0 )
         {
-            return "";
+            return ( char ) bytes[pos];
         }
-    
-        char ch;
-        char[] buf = str.toCharArray();
-        char[] newbuf = new char[buf.length];
-        boolean wsSeen = false;
-        boolean isStart = true;
-        int pos = 0;
-    
-        for ( int i = 0; i < str.length(); i++ )
-        {
-            ch = buf[i];
-    
-            // filter out all uppercase characters
-            if ( toLowerCase && Character.isUpperCase( ch ) )
+        else
+        {
+            if ( ( bytes[pos] & UnicodeConstants.UTF8_TWO_BYTES_MASK ) == UnicodeConstants.UTF8_TWO_BYTES )
             {
-                ch = Character.toLowerCase( ch );
+                // Two bytes char
+                return ( char ) ( ( ( bytes[pos] & 0x1C ) << 6 ) + // 110x-xxyy
+                                                                    // 10zz-zzzz
+                                                                    // ->
+                                                                    // 0000-0xxx
+                                                                    // 0000-0000
+                    ( ( bytes[pos] & 0x03 ) << 6 ) + // 110x-xxyy 10zz-zzzz
+                                                        // -> 0000-0000
+                                                        // yy00-0000
+                ( bytes[pos + 1] & 0x3F ) // 110x-xxyy 10zz-zzzz -> 0000-0000
+                                            // 00zz-zzzz
+                ); // -> 0000-0xxx yyzz-zzzz (07FF)
             }
-    
-            // Check to see if we should add space
-            if ( Character.isWhitespace( ch ) )
+            else if ( ( bytes[pos] & UnicodeConstants.UTF8_THREE_BYTES_MASK ) == UnicodeConstants.UTF8_THREE_BYTES )
             {
-                // If the buffer has had characters added already check last
-                // added character. Only append a spc if last character was
-                // not whitespace.
-                if ( wsSeen )
-                {
-                    continue;
-                }
-                else
-                {
-                    wsSeen = true;
-    
-                    if ( isStart )
-                    {
-                        isStart = false;
-                    }
-                    else
-                    {
-                        newbuf[pos++] = ch;
-                    }
-                }
+                // Three bytes char
+                return ( char ) (
+                // 1110-tttt 10xx-xxyy 10zz-zzzz -> tttt-0000-0000-0000
+                ( ( bytes[pos] & 0x0F ) << 12 )
+                    // 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-xxxx-0000-0000
+                    + ( ( bytes[pos + 1] & 0x3C ) << 6 )
+                    // 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-0000-yy00-0000
+                    + ( ( bytes[pos + 1] & 0x03 ) << 6 )
+                // 1110-tttt 10xx-xxyy 10zz-zzzz -> 0000-0000-00zz-zzzz
+                + ( bytes[pos + 2] & 0x3F )
+                // -> tttt-xxxx yyzz-zzzz (FF FF)
+                );
+            }
+            else if ( ( bytes[pos] & UnicodeConstants.UTF8_FOUR_BYTES_MASK ) == UnicodeConstants.UTF8_FOUR_BYTES )
+            {
+                // Four bytes char
+                return ( char ) (
+                // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 000t-tt00
+                // 0000-0000 0000-0000
+                ( ( bytes[pos] & 0x07 ) << 18 )
+                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-00uu
+                    // 0000-0000 0000-0000
+                    + ( ( bytes[pos + 1] & 0x30 ) << 16 )
+                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
+                    // vvvv-0000 0000-0000
+                    + ( ( bytes[pos + 1] & 0x0F ) << 12 )
+                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
+                    // 0000-xxxx 0000-0000
+                    + ( ( bytes[pos + 2] & 0x3C ) << 6 )
+                    // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
+                    // 0000-0000 yy00-0000
+                    + ( ( bytes[pos + 2] & 0x03 ) << 6 )
+                // 1111-0ttt 10uu-vvvv 10xx-xxyy 10zz-zzzz -> 0000-0000
+                // 0000-0000 00zz-zzzz
+                + ( bytes[pos + 3] & 0x3F )
+                // -> 000t-ttuu vvvv-xxxx yyzz-zzzz (1FFFFF)
+                );
+            }
+            else if ( ( bytes[pos] & UnicodeConstants.UTF8_FIVE_BYTES_MASK ) == UnicodeConstants.UTF8_FIVE_BYTES )
+            {
+                // Five bytes char
+                return ( char ) (
+                // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                // 0000-00tt 0000-0000 0000-0000 0000-0000
+                ( ( bytes[pos] & 0x03 ) << 24 )
+                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                    // 0000-0000 uuuu-uu00 0000-0000 0000-0000
+                    + ( ( bytes[pos + 1] & 0x3F ) << 18 )
+                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                    // 0000-0000 0000-00vv 0000-0000 0000-0000
+                    + ( ( bytes[pos + 2] & 0x30 ) << 12 )
+                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                    // 0000-0000 0000-0000 wwww-0000 0000-0000
+                    + ( ( bytes[pos + 2] & 0x0F ) << 12 )
+                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                    // 0000-0000 0000-0000 0000-xxxx 0000-0000
+                    + ( ( bytes[pos + 3] & 0x3C ) << 6 )
+                    // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                    // 0000-0000 0000-0000 0000-0000 yy00-0000
+                    + ( ( bytes[pos + 3] & 0x03 ) << 6 )
+                // 1111-10tt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz ->
+                // 0000-0000 0000-0000 0000-0000 00zz-zzzz
+                + ( bytes[pos + 4] & 0x3F )
+                // -> 0000-00tt uuuu-uuvv wwww-xxxx yyzz-zzzz (03 FF FF FF)
+                );
+            }
+            else if ( ( bytes[pos] & UnicodeConstants.UTF8_FIVE_BYTES_MASK ) == UnicodeConstants.UTF8_FIVE_BYTES )
+            {
+                // Six bytes char
+                return ( char ) (
+                // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz
+                // ->
+                // 0s00-0000 0000-0000 0000-0000 0000-0000
+                ( ( bytes[pos] & 0x01 ) << 30 )
+                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz
+                    // ->
+                    // 00tt-tttt 0000-0000 0000-0000 0000-0000
+                    + ( ( bytes[pos + 1] & 0x3F ) << 24 )
+                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
+                    // 10zz-zzzz ->
+                    // 0000-0000 uuuu-uu00 0000-0000 0000-0000
+                    + ( ( bytes[pos + 2] & 0x3F ) << 18 )
+                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
+                    // 10zz-zzzz ->
+                    // 0000-0000 0000-00vv 0000-0000 0000-0000
+                    + ( ( bytes[pos + 3] & 0x30 ) << 12 )
+                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
+                    // 10zz-zzzz ->
+                    // 0000-0000 0000-0000 wwww-0000 0000-0000
+                    + ( ( bytes[pos + 3] & 0x0F ) << 12 )
+                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
+                    // 10zz-zzzz ->
+                    // 0000-0000 0000-0000 0000-xxxx 0000-0000
+                    + ( ( bytes[pos + 4] & 0x3C ) << 6 )
+                    // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy
+                    // 10zz-zzzz ->
+                    // 0000-0000 0000-0000 0000-0000 yy00-0000
+                    + ( ( bytes[pos + 4] & 0x03 ) << 6 )
+                // 1111-110s 10tt-tttt 10uu-uuuu 10vv-wwww 10xx-xxyy 10zz-zzzz
+                // ->
+                // 0000-0000 0000-0000 0000-0000 00zz-zzzz
+                + ( bytes[pos + 5] & 0x3F )
+                // -> 0stt-tttt uuuu-uuvv wwww-xxxx yyzz-zzzz (7F FF FF FF)
+                );
             }
             else
             {
-                // Add all non-whitespace
-                wsSeen = false;
-                isStart = false;
-                newbuf[pos++] = ch;
+                return ( char ) -1;
             }
         }
-    
-        return ( pos == 0 ? "" : new String( newbuf, 0, ( wsSeen ? pos - 1 : pos ) ) );
     }
 
-
     /**
-     * This does the same thing as a trim but we also lowercase the string while
-     * performing the deep trim within the same buffer. This saves us from
-     * having to create multiple String and StringBuffer objects and is much
-     * more efficient.
-     * 
-     * @see StringTools#deepTrim( String )
+     * Return the number of bytes that hold an Unicode char.
+     *
+     * @param car The character to be decoded
+     * @return The number of bytes to hold the char. TODO : Should stop after
+     *         the third byte, as a char is only 2 bytes long.
      */
-    public static String deepTrimToLower( String string )
+    public static int countNbBytesPerChar( char car )
     {
-        return deepTrim( string, true );
+        if ( ( car & UnicodeConstants.CHAR_ONE_BYTE_MASK ) == 0 )
+        {
+            return 1;
+        }
+        else if ( ( car & UnicodeConstants.CHAR_TWO_BYTES_MASK ) == 0 )
+        {
+            return 2;
+        }
+        else if ( ( car & UnicodeConstants.CHAR_THREE_BYTES_MASK ) == 0 )
+        {
+            return 3;
+        }
+        else if ( ( car & UnicodeConstants.CHAR_FOUR_BYTES_MASK ) == 0 )
+        {
+            return 4;
+        }
+        else if ( ( car & UnicodeConstants.CHAR_FIVE_BYTES_MASK ) == 0 )
+        {
+            return 5;
+        }
+        else if ( ( car & UnicodeConstants.CHAR_SIX_BYTES_MASK ) == 0 )
+        {
+            return 6;
+        }
+        else
+        {
+            return -1;
+        }
     }
 
-
     /**
-     * A deep trim of a string remove whitespace from the ends as well as
-     * excessive whitespace within the inside of the string between
-     * non-whitespace characters. A deep trim reduces internal whitespace down
-     * to a single space to perserve the whitespace separated tokenization order
-     * of the String.
-     * 
-     * @param string the string to deep trim.
-     * @return the trimmed string.
+     * Count the number of bytes included in the given char[].
+     *
+     * @param chars The char array to decode
+     * @return The number of bytes in the char array
      */
-    public static String deepTrim( String string )
+    public static int countBytes( char[] chars )
     {
-        return deepTrim( string, false );
-    }
+        if ( chars == null )
+        {
+            return 0;
+        }
 
+        int nbBytes = 0;
+        int currentPos = 0;
 
-    /**
-     * Trims several consecutive characters into one.
-     * 
-     * @param str the string to trim consecutive characters of
-     * @param ch the character to trim down
-     * @return the newly trimmed down string
-     */
-    public static String trimConsecutiveToOne( String str, char ch )
-    {
-        if ( ( null == str ) || ( str.length() == 0 ) )
+        while ( currentPos < chars.length )
         {
-            return "";
-        }
-    
-        char[] buffer = str.toCharArray();
-        char[] newbuf = new char[buffer.length];
-        int pos = 0;
-        boolean same = false;
-    
-        for ( int i = 0; i < buffer.length; i++ )
-        {
-            char car = buffer[i];
-    
-            if ( car == ch )
-            {
-                if ( same )
-                {
-                    continue;
-                }
-                else
-                {
-                    same = true;
-                    newbuf[pos++] = car;
-                }
-            }
-            else
-            {
-                same = false;
-                newbuf[pos++] = car;
-            }
+            int nbb = countNbBytesPerChar( chars[currentPos] );
+
+            // If the number of bytes necessary to encode a character is
+            // above 3, we will need two UTF-16 chars
+            currentPos += ( nbb < 4 ? 1 : 2 );
+            nbBytes += nbb;
         }
-    
-        return new String( newbuf, 0, pos );
-    }
-    
 
-    /**
-     * Truncates large Strings showing a portion of the String's head and tail
-     * with the center cut out and replaced with '...'. Also displays the total
-     * length of the truncated string so size of '...' can be interpreted.
-     * Useful for large strings in UIs or hex dumps to log files.
-     * 
-     * @param str the string to truncate
-     * @param head the amount of the head to display
-     * @param tail the amount of the tail to display
-     * @return the center truncated string
-     */
-    public static String centerTrunc( String str, int head, int tail )
-    {
-        StringBuffer buf = null;
-    
-        // Return as-is if String is smaller than or equal to the head plus the
-        // tail plus the number of characters added to the trunc representation
-        // plus the number of digits in the string length.
-        if ( str.length() <= ( head + tail + 7 + str.length() / 10 ) )
-        {
-            return str;
-        }
-    
-        buf = new StringBuffer();
-        buf.append( '[' ).append( str.length() ).append( "][" );
-        buf.append( str.substring( 0, head ) ).append( "..." );
-        buf.append( str.substring( str.length() - tail ) );
-        buf.append( ']' );
-        return buf.toString();
+        return nbBytes;
     }
-    
 
     /**
-     * Gets a hex string from byte array.
-     * 
-     * @param res the byte array
-     * @return the hex string representing the binary values in the array
+     * Count the number of chars included in the given byte[].
+     *
+     * @param bytes The byte array to decode
+     * @return The number of char in the byte array
      */
-    public static String toHexString( byte[] res )
+    public static int countChars( byte[] bytes )
     {
-        StringBuffer buf = new StringBuffer( res.length << 1 );
-        
-        for ( int ii = 0; ii < res.length; ii++ )
-        {
-            String digit = Integer.toHexString( 0xFF & res[ii] );
-            
-            if ( digit.length() == 1 )
-            {
-                digit = '0' + digit;
-            }
-            
-            buf.append( digit );
+        if ( bytes == null )
+        {
+            return 0;
         }
-        return buf.toString().toUpperCase();
-    }
-    
 
-    /**
-     * Get byte array from hex string
-     * 
-     * @param hexString the hex string to convert to a byte array
-     * @return the byte form of the hex string.
-     */
-    public static byte[] toByteArray( String hexString )
-    {
-        int arrLength = hexString.length() >> 1;
-        byte [] buf = new byte[arrLength];
-        
-        for ( int ii = 0; ii < arrLength; ii++ )
-        {
-            int index = ii << 1;
-            
-            String digit = hexString.substring( index, index + 2 );
-            buf[ii] = ( byte ) Integer.parseInt( digit, 16 );
-        }
-        
-        return buf;
-    }
-    
+        int nbChars = 0;
+        int currentPos = 0;
 
-    /**
-     * This method is used to insert HTML block dynamically
-     * 
-     * @param source the HTML code to be processes
-     * @param replaceNl if true '\n' will be replaced by &lt;br>
-     * @param replaceTag if true '<' will be replaced by &lt; and '>' will be replaced
-     *            by &gt;
-     * @param replaceQuote if true '\"' will be replaced by &quot;
-     * @return the formated html block
-     */
-    public static String formatHtml( String source, boolean replaceNl, boolean replaceTag,
-        boolean replaceQuote )
-    {
-        StringBuffer buf = new StringBuffer();
-        int len = source.length();
-    
-        for ( int ii = 0; ii < len; ii++ )
-        {
-            char ch = source.charAt( ii );
-            
-            switch ( ch )
-            {
-                case '\"':
-                    if ( replaceQuote )
-                    {
-                        buf.append( "&quot;" );
-                    }
-                    else
-                    {
-                        buf.append( ch );
-                    }
-                    break;
-    
-                case '<':
-                    if ( replaceTag )
-                    {
-                        buf.append( "&lt;" );
-                    }
-                    else
-                    {
-                        buf.append( ch );
-                    }
-                    break;
-    
-                case '>':
-                    if ( replaceTag )
-                    {
-                        buf.append( "&gt;" );
-                    }
-                    else
-                    {
-                        buf.append( ch );
-                    }
-                    break;
-    
-                case '\n':
-                    if ( replaceNl )
-                    {
-                        if ( replaceTag )
-                        {
-                            buf.append( "&lt;br&gt;" );
-                        }
-                        else
-                        {
-                            buf.append( "<br>" );
-                        }
-                    }
-                    else
-                    {
-                        buf.append( ch );
-                    }
-                    break;
-    
-                case '\r':
-                    break;
-    
-                case '&':
-                    buf.append( "&amp;" );
-                    break;
-    
-                default:
-                    buf.append( ch );
-                    break;
-            }
+        while ( currentPos < bytes.length )
+        {
+            currentPos += countBytesPerChar(bytes, currentPos);
+            nbChars++;
         }
-    
-        return buf.toString();
+
+        return nbChars;
     }
-    
 
     /**
-     * Check if a text is present at the current position in another string.
-     * 
-     * @param string The string which contains the data
-     * @param index Current position in the string
-     * @param text The text we want to check
-     * @return <code>true</code> if the string contains the text.
+     * Return the Unicode char which is coded in the bytes at the given
+     * position.
+     *
+     * @param car The character to be transformed to an array of bytes
+     *
+     * @return The byte array representing the char
+     *
+     * TODO : Should stop after the third byte, as a char is only 2 bytes long.
      */
-    public static boolean areEquals( String string, int index, String text )
+    public static byte[] charToBytes( char car )
     {
-        if ( ( string == null ) || ( text == null ) ) 
+        byte[] bytes = new byte[countNbBytesPerChar(car)];
+
+        if ( car <= 0x7F )
         {
-            return false;
+            // Single byte char
+            bytes[0] = ( byte ) car;
+            return bytes;
         }
-        
-        int length1 = string.length();
-        int length2 = text.length();
-    
-        if ( ( length1 == 0 ) || ( length1 <= index ) || ( index < 0 )
-            || ( length2 == 0 ) || ( length2 > ( length1 + index ) ) )
+        else if ( car <= 0x7FF )
         {
-            return false;
+            // two bytes char
+            bytes[0] = ( byte ) ( 0x00C0 + ( ( car & 0x07C0 ) >> 6 ) );
+            bytes[1] = ( byte ) ( 0x0080 + ( car & 0x3F ) );
         }
         else
         {
-            return string.substring( index ).startsWith( text );
+            // Three bytes char
+            bytes[0] = ( byte ) ( 0x00E0 + ( ( car & 0xF000 ) >> 12 ) );
+            bytes[1] = ( byte ) ( 0x0080 + ( ( car & 0x0FC0 ) >> 6 ) );
+            bytes[2] = ( byte ) ( 0x0080 + ( car & 0x3F ) );
         }
+
+        return bytes;
     }
-    
 
     /**
-     * Test if the current character is equal to a specific character. This
-     * function works only for character between 0 and 127, as it does compare a
-     * byte and a char (which is 16 bits wide)
-     * 
-     * @param byteArray The buffer which contains the data
-     * @param index Current position in the buffer
-     * @param car The character we want to compare with the current buffer position
-     * @return <code>true</code> if the current character equals the given character.
+     * Check if the current char is in the unicodeSubset : all chars but
+     * '\0', '(', ')', '*' and '\'
+     *
+     * @param str The string to check
+     * @param pos Position of the current char
+     * @return True if the current char is in the unicode subset
      */
-    public static boolean isCharASCII( byte[] byteArray, int index, char car )
+    public static boolean isUnicodeSubset( String str, int pos )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( str == null ) || ( str.length() <= pos ) || ( pos < 0 ) )
         {
             return false;
         }
-        else
-        {
-            return ( ( byteArray[index] == car ) ? true : false );
-        }
+
+        char c = str.charAt( pos );
+
+        return ( ( c > 127 ) || UnicodeConstants.UNICODE_SUBSET[c] );
     }
 
     /**
-     * Test if the current character is equal to a specific character.
-     * 
-     * @param string The String which contains the data
-     * @param index Current position in the string
-     * @param car The character we want to compare with the current string position
-     * @return <code>true</code> if the current character equals the given character.
+     * Check if the current char is in the unicodeSubset : all chars but
+     * '\0', '(', ')', '*' and '\'
+     *
+     * @param c The char to check
+     * @return True if the current char is in the unicode subset
      */
-    public static boolean isCharASCII( String string, int index, char car )
+    public static boolean isUnicodeSubset( char c )
     {
-        if ( string == null )
-        {
-            return false;
-        }
-        
-        int length = string.length();
-        
-        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
-        {
-            return false;
-        }
-        else
-        {
-            return string.charAt( index ) == car;
-        }
+        return ( ( c > 127 ) || UnicodeConstants.UNICODE_SUBSET[c] );
     }
 }

Added: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnicodeConstants.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnicodeConstants.java?rev=1062251&view=auto
==============================================================================
--- directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnicodeConstants.java (added)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnicodeConstants.java Sat Jan 22 20:08:48 2011
@@ -0,0 +1,68 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.shared.util;
+
+
+/**
+ * Various UTF constants are kept here.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface UnicodeConstants
+{
+    int UTF8_MULTI_BYTES_MASK = 0x0080;
+    int UTF8_TWO_BYTES_MASK = 0x00E0;
+    int UTF8_TWO_BYTES = 0x00C0;
+    int UTF8_THREE_BYTES_MASK = 0x00F0;
+    int UTF8_THREE_BYTES = 0x00E0;
+    int UTF8_FOUR_BYTES_MASK = 0x00F8;
+    int UTF8_FOUR_BYTES = 0x00F0;
+    int UTF8_FIVE_BYTES_MASK = 0x00FC;
+    int UTF8_FIVE_BYTES = 0x00F8;
+    int UTF8_SIX_BYTES_MASK = 0x00FE;
+    int UTF8_SIX_BYTES = 0x00FC;
+
+    /** %01-%27 %2B-%5B %5D-%7F */
+    boolean[] UNICODE_SUBSET =
+        {
+            false, true,  true,  true,  true,  true,  true,  true, // '\0'
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            false, false, false, true,  true,  true,  true,  true, // '(', ')', '*'
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  false, true,  true,  true, // '\'
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+            true,  true,  true,  true,  true,  true,  true,  true,
+        };
+    int CHAR_ONE_BYTE_MASK = 0xFFFFFF80;
+    int CHAR_TWO_BYTES_MASK = 0xFFFFF800;
+    int CHAR_THREE_BYTES_MASK = 0xFFFF0000;
+    int CHAR_FOUR_BYTES_MASK = 0xFFE00000;
+    int CHAR_FIVE_BYTES_MASK = 0xFC000000;
+    int CHAR_SIX_BYTES_MASK = 0x80000000;
+}

Copied: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnixCrypt.java (from r1062128, directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java)
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnixCrypt.java?p2=directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnixCrypt.java&p1=directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java&r1=1062128&r2=1062251&rev=1062251&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java (original)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnixCrypt.java Sat Jan 22 20:08:48 2011
@@ -38,7 +38,7 @@
  * by Iris Van den Broeke, Daniel Deville
  */
 
-package org.apache.directory.shared.ldap.util;
+package org.apache.directory.shared.util;
 
 import org.apache.directory.shared.i18n.I18n;
 

Propchange: directory/shared/trunk/util/src/main/java/org/apache/directory/shared/util/UnixCrypt.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/ArrayEnumerationTest.java (from r1062128, directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/ArrayEnumerationTest.java)
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/ArrayEnumerationTest.java?p2=directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/ArrayEnumerationTest.java&p1=directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/ArrayEnumerationTest.java&r1=1062128&r2=1062251&rev=1062251&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/ArrayEnumerationTest.java (original)
+++ directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/ArrayEnumerationTest.java Sat Jan 22 20:08:48 2011
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.shared.ldap.util;
+package org.apache.directory.shared.util;
 
 
 import static org.junit.Assert.assertFalse;
@@ -29,6 +29,7 @@ import java.util.NoSuchElementException;
 
 import org.apache.directory.junit.tools.Concurrent;
 import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.util.ArrayEnumeration;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -50,13 +51,13 @@ public class ArrayEnumerationTest
 
         ArrayEnumeration list = new ArrayEnumeration( array );
 
-        assertFalse( list.hasMoreElements() );
+        assertFalse(list.hasMoreElements());
 
         try
         {
             list.nextElement();
 
-            fail( "should never get here due to a NoSuchElementException" );
+            fail("should never get here due to a NoSuchElementException");
         }
         catch ( NoSuchElementException e )
         {
@@ -68,15 +69,15 @@ public class ArrayEnumerationTest
 
         list = new ArrayEnumeration( array );
 
-        assertFalse( list.hasMoreElements() );
+        assertFalse(list.hasMoreElements());
 
-        assertFalse( list.hasMoreElements() );
+        assertFalse(list.hasMoreElements());
 
         try
         {
             list.nextElement();
 
-            fail( "should never get here due to a NoSuchElementException" );
+            fail("should never get here due to a NoSuchElementException");
         }
         catch ( NoSuchElementException e )
         {
@@ -89,17 +90,17 @@ public class ArrayEnumerationTest
 
         list = new ArrayEnumeration( array );
 
-        assertTrue( list.hasMoreElements() );
+        assertTrue(list.hasMoreElements());
 
-        assertNotNull( list.nextElement() );
+        assertNotNull(list.nextElement());
 
-        assertFalse( list.hasMoreElements() );
+        assertFalse(list.hasMoreElements());
 
         try
         {
             list.nextElement();
 
-            fail( "should never get here due to a NoSuchElementException" );
+            fail("should never get here due to a NoSuchElementException");
         }
         catch ( NoSuchElementException e )
         {
@@ -112,21 +113,21 @@ public class ArrayEnumerationTest
 
         list = new ArrayEnumeration( array );
 
-        assertTrue( list.hasMoreElements() );
+        assertTrue(list.hasMoreElements());
 
-        assertNotNull( list.nextElement() );
+        assertNotNull(list.nextElement());
 
-        assertTrue( list.hasMoreElements() );
+        assertTrue(list.hasMoreElements());
 
-        assertNotNull( list.nextElement() );
+        assertNotNull(list.nextElement());
 
-        assertFalse( list.hasMoreElements() );
+        assertFalse(list.hasMoreElements());
 
         try
         {
             list.nextElement();
 
-            fail( "should never get here due to a NoSuchElementException" );
+            fail("should never get here due to a NoSuchElementException");
         }
         catch ( NoSuchElementException e )
         {
@@ -139,25 +140,25 @@ public class ArrayEnumerationTest
 
         list = new ArrayEnumeration( array );
 
-        assertTrue( list.hasMoreElements() );
+        assertTrue(list.hasMoreElements());
 
-        assertNotNull( list.nextElement() );
+        assertNotNull(list.nextElement());
 
-        assertTrue( list.hasMoreElements() );
+        assertTrue(list.hasMoreElements());
 
-        assertNotNull( list.nextElement() );
+        assertNotNull(list.nextElement());
 
-        assertTrue( list.hasMoreElements() );
+        assertTrue(list.hasMoreElements());
 
-        assertNotNull( list.nextElement() );
+        assertNotNull(list.nextElement());
 
-        assertFalse( list.hasMoreElements() );
+        assertFalse(list.hasMoreElements());
 
         try
         {
             list.nextElement();
 
-            fail( "should never get here due to a NoSuchElementException" );
+            fail("should never get here due to a NoSuchElementException");
         }
         catch ( NoSuchElementException e )
         {

Propchange: directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/ArrayEnumerationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/Base32Test.java (from r1062128, directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/Base32Test.java)
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/Base32Test.java?p2=directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/Base32Test.java&p1=directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/Base32Test.java&r1=1062128&r2=1062251&rev=1062251&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/test/java/org/apache/directory/shared/ldap/util/Base32Test.java (original)
+++ directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/Base32Test.java Sat Jan 22 20:08:48 2011
@@ -17,12 +17,13 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.shared.ldap.util;
+package org.apache.directory.shared.util;
 
 import static org.junit.Assert.assertEquals;
 
 import org.apache.directory.junit.tools.Concurrent;
 import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.util.Base32;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -40,9 +41,9 @@ public class Base32Test
         {
             String in = data[i];
         
-            String res = Base32.encode( in );
+            String res = Base32.encode(in);
             
-            assertEquals( expected[i], res );
+            assertEquals(expected[i], res);
         }
     }
 }

Propchange: directory/shared/trunk/util/src/test/java/org/apache/directory/shared/util/Base32Test.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message