|
|
|
|
|
|
|
*/ |
|
/* |
|
* 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 com.sun.org.apache.xml.internal.utils; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class Trie |
|
{ |
|
|
|
|
|
public static final int ALPHA_SIZE = 128; |
|
|
|
|
|
Node m_Root; |
|
|
|
|
|
private char[] m_charBuffer = new char[0]; |
|
|
|
|
|
|
|
*/ |
|
public Trie() |
|
{ |
|
m_Root = new Node(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Object put(String key, Object value) |
|
{ |
|
|
|
final int len = key.length(); |
|
if (len > m_charBuffer.length) |
|
{ |
|
|
|
m_charBuffer = new char[len]; |
|
} |
|
|
|
Node node = m_Root; |
|
|
|
for (int i = 0; i < len; i++) |
|
{ |
|
Node nextNode = node.m_nextChar[Character.toUpperCase(key.charAt(i))]; |
|
|
|
if (nextNode != null) |
|
{ |
|
node = nextNode; |
|
} |
|
else |
|
{ |
|
for (; i < len; i++) |
|
{ |
|
Node newNode = new Node(); |
|
|
|
node.m_nextChar[Character.toUpperCase(key.charAt(i))] = newNode; |
|
node.m_nextChar[Character.toLowerCase(key.charAt(i))] = newNode; |
|
node = newNode; |
|
} |
|
break; |
|
} |
|
} |
|
|
|
Object ret = node.m_Value; |
|
|
|
node.m_Value = value; |
|
|
|
return ret; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Object get(final String key) |
|
{ |
|
|
|
final int len = key.length(); |
|
|
|
|
|
|
|
*/ |
|
if (m_charBuffer.length < len) |
|
return null; |
|
|
|
Node node = m_Root; |
|
switch (len) |
|
{ |
|
// case 0 looks silly, but the generated bytecode runs |
|
// faster for lookup of elements of length 2 with this in |
|
|
|
case 0 : |
|
{ |
|
return null; |
|
} |
|
|
|
case 1 : |
|
{ |
|
final char ch = key.charAt(0); |
|
if (ch < ALPHA_SIZE) |
|
{ |
|
node = node.m_nextChar[ch]; |
|
if (node != null) |
|
return node.m_Value; |
|
} |
|
return null; |
|
} |
|
// comment out case 2 because the default is faster |
|
// case 2 : |
|
// { |
|
// final char ch0 = key.charAt(0); |
|
// final char ch1 = key.charAt(1); |
|
// if (ch0 < ALPHA_SIZE && ch1 < ALPHA_SIZE) |
|
// { |
|
// node = node.m_nextChar[ch0]; |
|
// if (node != null) |
|
// { |
|
// |
|
// if (ch1 < ALPHA_SIZE) |
|
// { |
|
// node = node.m_nextChar[ch1]; |
|
// if (node != null) |
|
// return node.m_Value; |
|
// } |
|
// } |
|
// } |
|
// return null; |
|
|
|
default : |
|
{ |
|
key.getChars(0, len, m_charBuffer, 0); |
|
|
|
for (int i = 0; i < len; i++) |
|
{ |
|
final char ch = m_charBuffer[i]; |
|
if (ALPHA_SIZE <= ch) |
|
{ |
|
|
|
return null; |
|
} |
|
|
|
node = node.m_nextChar[ch]; |
|
if (node == null) |
|
return null; |
|
} |
|
|
|
return node.m_Value; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
class Node |
|
{ |
|
|
|
|
|
|
|
*/ |
|
Node() |
|
{ |
|
m_nextChar = new Node[ALPHA_SIZE]; |
|
m_Value = null; |
|
} |
|
|
|
|
|
Node m_nextChar[]; |
|
|
|
|
|
Object m_Value; |
|
} |
|
} |