From 9c1d3ff0b3422960f31e3cbe83bb7c87039ea337 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 9 Feb 2012 18:02:51 +1100 Subject: [PATCH] jetty-9 temporary tree map impl --- .../org/eclipse/jetty/io/BufferCacheTest.java | 151 ------- .../org/eclipse/jetty/util/StringMap.java | 390 ++++-------------- .../org/eclipse/jetty/util/StringUtil.java | 8 +- .../org/eclipse/jetty/util/StringMapTest.java | 50 --- 4 files changed, 90 insertions(+), 509 deletions(-) delete mode 100644 jetty-io/src/test/java/org/eclipse/jetty/io/BufferCacheTest.java diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/BufferCacheTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/BufferCacheTest.java deleted file mode 100644 index 07cc172562e..00000000000 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/BufferCacheTest.java +++ /dev/null @@ -1,151 +0,0 @@ -// ======================================================================== -// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== - -package org.eclipse.jetty.io; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import org.eclipse.jetty.io.BufferCache.CachedBuffer; -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.StringUtil; -import org.junit.Before; -import org.junit.Test; -import java.nio.ByteBuffer; - -/** - * - */ -public class BufferCacheTest -{ - private final static String[] S = {"S0", "S1", "s2", "s3" }; - - private BufferCache cache; - - @Before - public void init() throws Exception - { - cache=new BufferCache(); - cache.add(S[1],1); - cache.add(S[2],2); - cache.add(S[3],3); - } - - @Test - public void testLookupIndex() - { - for (int i=0; i0) - assertEquals(i,index); - else - assertEquals(-1,index); - } - } - - @Test - public void testGetBuffer() - { - for (int i=0; i0) - assertEquals(S[i],b.toString()); - else - assertEquals(null,b); - } - } - - @Test - public void testLookupBuffer() - { - for (int i=0; i0) - assertEquals(""+i, S[i], BufferUtil.toString(b)); - else - { - assertNotSame(""+i, S[i], BufferUtil.toString(b)); - assertEquals(""+i, S[i], BufferUtil.toString(b)); - } - } - } - - @Test - public void testLookupPartialBuffer() - { - String key="44444"; - cache.add(key,4); - - ByteBuffer buf=BufferUtil.toBuffer("44444"); - ByteBuffer b=cache.get(buf).getBuffer(); - assertEquals("44444",BufferUtil.toString(b)); - assertEquals(4,cache.getOrdinal(b)); - - buf=BufferUtil.toBuffer("4444"); - assertEquals(null,cache.get(buf)); - assertSame(buf,cache.getBuffer(buf)); - assertEquals(-1,cache.getOrdinal(buf)); - - buf=BufferUtil.toBuffer("44444x"); - assertEquals("44444",cache.get(buf).toString()); - assertEquals(4,cache.getOrdinal(buf)); - - } - - @Test - public void testToString() - { - for (int i=0; i0) - assertSame(S[i], str); - else - assertNotSame(S[i], str); - } - } -} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java index 539f80d0f1a..7e2477bb02b 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringMap.java @@ -16,9 +16,10 @@ package org.eclipse.jetty.util; import java.nio.ByteBuffer; import java.util.AbstractMap; import java.util.Collections; -import java.util.HashSet; +import java.util.Comparator; import java.util.Map; import java.util.Set; +import java.util.TreeMap; /* ------------------------------------------------------------ */ /** Map implementation Optimized for Strings keys.. @@ -34,39 +35,83 @@ import java.util.Set; */ public class StringMap extends AbstractMap { + private final TreeMap _map; + + public static final boolean CASE_INSENSTIVE=true; - protected static final int __HASH_WIDTH=17; /* ------------------------------------------------------------ */ - private final boolean _ignoreCase; + private final boolean _caseInsensitive; - protected Node _root; - protected HashSet> _entrySet=new HashSet<>(3); /* ------------------------------------------------------------ */ /** Constructor. */ public StringMap() { - _ignoreCase=false; + this(false); } /* ------------------------------------------------------------ */ /** Constructor. * @param ignoreCase */ - public StringMap(boolean ignoreCase) + public StringMap(final boolean ignoreCase) { - _ignoreCase=ignoreCase; + _caseInsensitive=ignoreCase; + _map = new TreeMap<>(new Comparator() + { + @Override + public int compare(Object o1, Object o2) + { + String s1=(o1 instanceof String)?(String)o1:null; + ByteBuffer b1=(o1 instanceof ByteBuffer)?(ByteBuffer)o1:null; + if (s1==null && b1==null) + s1=o1.toString(); + String s2=(String)o2; + + + int n1 = s1==null?b1.remaining():s1.length(); + int n2 = s2.length(); + int min = Math.min(n1, n2); + for (int i = 0; i < min; i++) { + char c1 = s1==null?(char)b1.get(b1.position()+i):s1.charAt(i); + char c2 = s2.charAt(i); + if (c1 != c2) { + + if (ignoreCase) + { + 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; + } + } + } + else + return c1 - c2; + } + } + return n1 - n2; + + } + }); + + } /* ------------------------------------------------------------ */ public boolean isIgnoreCase() { - return _ignoreCase; + return _caseInsensitive; } - + + /* ------------------------------------------------------------ */ public static void main(String[] arg) { StringMap map = new StringMap<>(); @@ -92,366 +137,103 @@ public class StringMap extends AbstractMap System.err.println("3="+map.get("foob")); System.err.println("1="+map.get("foo")); + map.put("fool","4"); + map.put("fop","5"); + map.put("fred","6"); + + + System.err.println("2="+map.get(BufferUtil.toBuffer("foobar"))); + System.err.println("3="+map.get(BufferUtil.toBuffer("foob"))); + System.err.println("1="+map.get(BufferUtil.toBuffer("foo"))); + + } /* ------------------------------------------------------------ */ @Override public O put(String key, O value) { - if (key==null) - throw new IllegalArgumentException(); - - Node node = _root; - Node last = null; - - for (int i=0;i(key,value,_ignoreCase); - _entrySet.add(node); - if (last==null) - _root=node; - else - { - throw new Error("unimplemented"); - } - - return null; - } - else - { - last=node; - node=node.nextNode(i,ch); - - if (node==null) - { - node = new Node(key,value,_ignoreCase); - _entrySet.add(node); - last.addNext(node); - return null; - } - - } - } - - if (node!=null) - { - if (key.equals(node.getKey())) - return node.setValue(value); - - } - - - return null; + return _map.put(key,value); } /* ------------------------------------------------------------ */ @Override public O get(Object key) { - if (key==null) - throw new IllegalArgumentException(); - return get(key.toString()); + return _map.get(key); } /* ------------------------------------------------------------ */ public O get(String key) { - if (key==null) - throw new IllegalArgumentException(); - - - Map.Entry entry = getEntry(key,0,key.length()); - if (entry==null) - return null; - return entry.getValue(); + return _map.get(key); + } + + /* ------------------------------------------------------------ */ + public O get(String key,int offset,int length) + { + return _map.get(key.substring(offset,offset+length)); } /* ------------------------------------------------------------ */ public O get(ByteBuffer buffer, int position, int length) { - Map.Entry entry = getEntry(buffer,position,length); - if (entry==null) - return null; - return entry.getValue(); + ByteBuffer slice=buffer.slice(); + slice.position(position); + slice.limit(position+length); + return _map.get(slice); } - /* ------------------------------------------------------------ */ - /** Get a map entry by substring key. - * @param key String containing the key - * @param offset Offset of the key within the String. - * @param length The length of the key - * @return The Map.Entry for the key or null if the key is not in - * the map. - */ - public Map.Entry getEntry(String key,int offset, int length) - { - if (key==null) - throw new IllegalArgumentException(); - - Node node = _root; - - for (int i=0;i getEntry(char[] key,int offset, int length) - { - if (key==null) - throw new IllegalArgumentException(); - - Node node = _root; - return node; - } - - /* ------------------------------------------------------------ */ - /** Get a map entry by byte array key, using as much of the passed key as needed for a match. - * A simple 8859-1 byte to char mapping is assumed. - * @param key byte array containing the key - * @param offset Offset of the key within the array. - * @param length The length of the key - * @return The Map.Entry for the key or null if the key is not in - * the map. - */ - public Map.Entry getEntry(byte[] key,int offset, int length) - { - if (key==null) - throw new IllegalArgumentException(); - - Node node = _root; - - - - return node; - } - - /* ------------------------------------------------------------ */ - /** Get a map entry by ByteBuffer key, using as much of the passed key as needed for a match. - * A simple 8859-1 byte to char mapping is assumed. - * @param key ByteBuffer containing the key - * @return The Map.Entry for the key or null if the key is not in - * the map. - */ - public Map.Entry getEntry(ByteBuffer key) - { - return getEntry(key,key.position(),key.remaining()); - } - - /* ------------------------------------------------------------ */ - /** Get a map entry by ByteBuffer key, using as much of the passed key as needed for a match. - * A simple 8859-1 byte to char mapping is assumed. - * @param key ByteBuffer containing the key - * @return The Map.Entry for the key or null if the key is not in - * the map. - */ - public Map.Entry getEntry(ByteBuffer key,int position,int length) - { - if (key==null) - throw new IllegalArgumentException(); - - if (!key.isReadOnly() && !key.isDirect()) - return getEntry(key.array(),key.position(),key.remaining()); - - Node node = _root; - return node; - } /* ------------------------------------------------------------ */ @Override public O remove(Object key) { - if (key==null) - return remove(null); - return remove(key.toString()); + return _map.remove(key); } /* ------------------------------------------------------------ */ public O remove(String key) { - if (key==null) - throw new IllegalArgumentException(); - - Node node = _root; - O old = node._value; - _entrySet.remove(node); - node._value=null; - - return old; + return _map.remove(key); } /* ------------------------------------------------------------ */ @Override public Set> entrySet() { - return Collections.unmodifiableSet(_entrySet); + Object o=_map.entrySet(); + return Collections.unmodifiableSet((Set>)o); } /* ------------------------------------------------------------ */ @Override public int size() { - return _entrySet.size(); + return _map.size(); } /* ------------------------------------------------------------ */ @Override public boolean isEmpty() { - return _entrySet.isEmpty(); + return _map.isEmpty(); } /* ------------------------------------------------------------ */ @Override public boolean containsKey(Object key) { - if (key==null) - return false; - return - getEntry(key.toString(),0,key==null?0:key.toString().length())!=null; + return _map.containsKey(key); } /* ------------------------------------------------------------ */ @Override public void clear() { - _root=null; - _entrySet.clear(); - } - - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - private static class Node implements Map.Entry - { - private final String _key; - private O _value; - private final char[] _chars; - private final int _length; - private final Node[] _splits; - private Node _next; - - - Node(String key, O value, boolean caseInsensitive) - { - _key=key; - _value=value; - _chars = _key.toCharArray(); - _length=_chars.length; - if (caseInsensitive) - for (int i=_length;i-->0;) - _chars[i]=Character.toLowerCase(_chars[i]); - _splits=null; - } - - public int length() - { - return _length; - } - - Node(char[] chars,int length) - { - _key=null; - _value=null; - _chars = chars; - _length=length; - _splits=new Node[__HASH_WIDTH]; - } - - Node nextNode(int index,char c) - { - if (index<_chars.length) - { - if (_chars[index]==c) - return this; - if (_next!=null) - return _next.nextNode(index,c); - } - - if (index==_chars.length && _splits!=null) - { - Node split=_splits[c%_splits.length]; - if (split!=null) - return split.nextNode(index,c); - } - - if (_next!=null) - return _next.nextNode(index,c); - - return null; - } - - Node split(int index) - { - Node pre = new Node(_chars,index); - pre.addSplit(this); - return pre; - } - - void addSplit(Node split) - { - char c=_chars[_length]; - int i=c%__HASH_WIDTH; - Node s=_splits[i]; - if (s==null) - _splits[i]=split; - else - _splits[i].addNext(split); - } - - void addNext(Node next) - { - Node s = this; - while (s._next!=null) - s=s._next; - s._next=next; - } - - - @Override - public String getKey() - { - return _key; - } - - @Override - public O getValue() - { - return _value; - } - - @Override - public O setValue(O value) - { - O old=_value; - _value=value; - return old; - } + _map.clear(); } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java index 3b41ca2e74e..de79ee258c9 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java @@ -80,8 +80,8 @@ public class StringUtil */ public static String normalizeCharset(String s,int offset,int length) { - Map.Entry n=CHARSETS.getEntry(s,offset,length); - return (n==null)?s.substring(offset,offset+length):n.getValue(); + String n=CHARSETS.get(s,offset,length); + return (n==null)?s.substring(offset,offset+length):n; } /* ------------------------------------------------------------ */ @@ -90,9 +90,9 @@ public class StringUtil */ public static String normalizeCharset(ByteBuffer b,int position,int length) { - Map.Entry n=CHARSETS.getEntry(b,position,length); + String n=CHARSETS.get(b,position,length); if (n!=null) - return n.getValue(); + return n; ByteBuffer slice = b.slice(); slice.position(position); slice.limit(position+length); diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java index d53bec17e5f..fed67a66474 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/StringMapTest.java @@ -131,56 +131,6 @@ public class StringMapTest } - /* - * Test for Map.Entry getEntry(String, int, int) - */ - @Test - public void testGetEntryStringintint() - { - Map.Entry entry; - - entry=m5.getEntry("xabcyz",1,3); - assertTrue(entry!=null); - assertEquals("abc",entry.getKey()); - assertEquals("2",entry.getValue()); - - entry=m5.getEntry("xaBcyz",1,3); - assertTrue(entry==null); - - entry=m5i.getEntry("xaBcyz",1,3); - assertTrue(entry!=null); - assertEquals("abc",entry.getKey()); - assertEquals("2",entry.getValue()); - entry.setValue("x"); - assertEquals("{[c:abc=x]}",entry.toString()); - - - } - - /* - * Test for Map.Entry getEntry(char[], int, int) - */ - @Test - public void testGetEntrycharArrayintint() - { - char[] xabcyz = {'x','a','b','c','y','z'}; - char[] xaBcyz = {'x','a','B','c','y','z'}; - Map.Entry entry; - - entry=m5.getEntry(xabcyz,1,3); - assertTrue(entry!=null); - assertEquals("abc",entry.getKey()); - assertEquals("2",entry.getValue()); - - entry=m5.getEntry(xaBcyz,1,3); - assertTrue(entry==null); - - entry=m5i.getEntry(xaBcyz,1,3); - assertTrue(entry!=null); - assertEquals("abc",entry.getKey()); - assertEquals("2",entry.getValue()); - } - /* * Test for Object remove(Object) */