[FELIX-4821] Use a faster implementation for StringMap

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1663617 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/util/StringMap.java b/framework/src/main/java/org/apache/felix/framework/util/StringMap.java
index 39c2eb6..6cb0469 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/StringMap.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/StringMap.java
@@ -18,7 +18,9 @@
  */
 package org.apache.felix.framework.util;
 
-import java.util.*;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * Simple utility class that creates a map for string-based keys.
@@ -28,190 +30,72 @@
  * <tt>toString()</tt> method, since it is only intended to
  * compare strings.
  **/
-public class StringMap extends AbstractMap<String, Object>
+public class StringMap extends TreeMap<String, Object>
 {
-    private static final CharArrayComparator COMPARATOR = new CharArrayComparator();
-
-    private final TreeMap<char[], KeyValueEntry> m_map = new TreeMap<char[], KeyValueEntry>(COMPARATOR);
+    private static final CaseInsensitiveComparator COMPARATOR = new CaseInsensitiveComparator();
 
     public StringMap()
     {
+        super(COMPARATOR);
     }
 
-    public StringMap(Map<? extends Object, ? extends Object> map)
+    public StringMap(Map<?, ?> map)
     {
-        for (Map.Entry<? extends Object, ? extends Object> e : map.entrySet())
-        {
-            KeyValueEntry kve = (KeyValueEntry) m_map.put(
-                toUpperCase(e.getKey().toString()),
-                new KeyValueEntry(e.getKey().toString(), e.getValue()));
-        }
-    }
-
-    @Override
-    public int size()
-    {
-        return m_map.size();
-    }
-
-    @Override
-    public boolean isEmpty()
-    {
-        return m_map.isEmpty();
-    }
-
-    @Override
-    public boolean containsKey(Object arg0)
-    {
-        return m_map.containsKey(toUpperCase(arg0.toString()));
-    }
-
-    @Override
-    public boolean containsValue(Object arg0)
-    {
-        return m_map.containsValue(arg0);
-    }
-
-    @Override
-    public Object get(Object arg0)
-    {
-        KeyValueEntry kve = m_map.get(toUpperCase(arg0.toString()));
-        return (kve != null) ? kve.value : null;
-    }
-
-    @Override
-    public Object put(String key, Object value)
-    {
-        KeyValueEntry kve = (KeyValueEntry) m_map.put(toUpperCase(key), new KeyValueEntry(key, value));
-        return (kve != null) ? kve.value : null;
-    }
-
-    @Override
-    public void putAll(Map<? extends String, ? extends Object> map)
-    {
-        for (Map.Entry<? extends String, ? extends Object> e : map.entrySet())
+        super(COMPARATOR);
+        for (Map.Entry<?, ?> e : map.entrySet())
         {
             put(e.getKey().toString(), e.getValue());
         }
     }
 
-    @Override
-    public Object remove(Object arg0)
+    private static class CaseInsensitiveComparator implements Comparator<String>
     {
-        KeyValueEntry kve = m_map.remove(toUpperCase(arg0.toString()));
-        return (kve != null) ? kve.value : null;
-    }
 
-    @Override
-    public void clear()
-    {
-        m_map.clear();
-    }
-
-    public Set<Entry<String, Object>> entrySet()
-    {
-        return new AbstractSet<Entry<String, Object>>()
+        public int compare(String s1, String s2)
         {
-            @Override
-            public Iterator<Entry<String, Object>> iterator()
+            int n1 = s1.length();
+            int n2 = s2.length();
+            int min = n1 < n2 ? n1 : n2;
+            for ( int i = 0; i < min; i++ )
             {
-                return new Iterator<Entry<String, Object>>()
+                char c1 = s1.charAt( i );
+                char c2 = s2.charAt( i );
+                if ( c1 != c2 )
                 {
-                    Iterator<Entry<char[], KeyValueEntry>> it = m_map.entrySet().iterator();
-
-                    public boolean hasNext()
+                    // Fast check for simple ascii codes
+                    if ( c1 <= 128 && c2 <= 128 )
                     {
-                        return it.hasNext();
+                        c1 = toLowerCaseFast(c1);
+                        c2 = toLowerCaseFast(c2);
+                        if ( c1 != c2 )
+                        {
+                            return c1 - c2;
+                        }
                     }
-
-                    public Entry<String, Object> next()
+                    else
                     {
-                        return it.next().getValue();
+                        c1 = Character.toUpperCase( c1 );
+                        c2 = Character.toUpperCase( c2 );
+                        if ( c1 != c2 )
+                        {
+                            c1 = Character.toLowerCase( c1 );
+                            c2 = Character.toLowerCase( c2 );
+                            if ( c1 != c2 )
+                            {
+                                // No overflow because of numeric promotion
+                                return c1 - c2;
+                            }
+                        }
                     }
-
-                    public void remove()
-                    {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-
-            @Override
-            public int size()
-            {
-                return m_map.size();
-            }
-        };
-    }
-
-    private static char[] toUpperCase(String str)
-    {
-        char[] ch = str.toCharArray();
-        for (int i = 0; i < ch.length; i++)
-        {
-            char c = ch[i];
-            if (c < 128)
-            {
-                if ('a' <= c && c <= 'z')
-                {
-                    ch[i] = (char)(c - ('a' - 'A'));
                 }
             }
-            else
-            {
-                ch[i] = Character.toUpperCase(c);
-            }
+            return n1 - n2;
         }
-        return ch;
     }
 
-    private static class CharArrayComparator implements Comparator<char[]>
+    private static char toLowerCaseFast( char ch )
     {
-        public int compare(char[] v1, char[] v2)
-        {
-            int len1 = v1.length;
-            int len2 = v2.length;
-            int n = Math.min(len1, len2);
-            int k = 0;
-            while (k < n)
-            {
-                char c1 = v1[k];
-                char c2 = v2[k];
-                if (c1 != c2)
-                {
-                    return c1 - c2;
-                }
-                k++;
-            }
-            return len1 - len2;
-        }
+        return ( ch >= 'A' && ch <= 'Z' ) ? ( char ) ( ch + 'a' - 'A' ) : ch;
     }
 
-    private static class KeyValueEntry implements Map.Entry<String, Object>
-    {
-        private KeyValueEntry(String key, Object value)
-        {
-            this.key = key;
-            this.value = value;
-        }
-
-        public String getKey()
-        {
-            return key;
-        }
-
-        public Object getValue()
-        {
-            return value;
-        }
-
-        public Object setValue(Object value)
-        {
-            Object v = this.value;
-            this.value = value;
-            return v;
-        }
-        String key;
-        Object value;
-    }
 }