001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.internal.reflect;
019:
020: class ProxyCharArrayCache {
021: static boolean equals(char[] first, char[] second) {
022: if (first == second) {
023: return true;
024: }
025: if (first == null || second == null) {
026: return false;
027: }
028: if (first.length != second.length) {
029: return false;
030: }
031:
032: for (int i = first.length; --i >= 0;) {
033: if (first[i] != second[i]) {
034: return false;
035: }
036: }
037: return true;
038: }
039:
040: // to avoid using Enumerations, walk the individual tables skipping nulls
041: private char[] keyTable[];
042:
043: private int valueTable[];
044:
045: // number of elements in the table
046: private int elementSize;
047:
048: private int threshold;
049:
050: ProxyCharArrayCache(int initialCapacity) {
051: if (initialCapacity < 13) {
052: initialCapacity = 13;
053: }
054: this .elementSize = 0;
055: this .threshold = (int) (initialCapacity * 0.66f);
056: this .keyTable = new char[initialCapacity][];
057: this .valueTable = new int[initialCapacity];
058: }
059:
060: int get(char[] key) {
061: int index = hashCodeChar(key);
062: while (keyTable[index] != null) {
063: if (equals(keyTable[index], key)) {
064: return valueTable[index];
065: }
066: index = (index + 1) % keyTable.length;
067: }
068: return -1;
069: }
070:
071: private int hashCodeChar(char[] val) {
072: int length = val.length;
073: int hash = 0;
074: int n = 2; // number of characters skipped
075: for (int i = 0; i < length; i += n) {
076: hash += val[i];
077: }
078: return (hash & 0x7FFFFFFF) % keyTable.length;
079: }
080:
081: int put(char[] key, int value) {
082: int index = hashCodeChar(key);
083: while (keyTable[index] != null) {
084: if (equals(keyTable[index], key)) {
085: return valueTable[index] = value;
086: }
087: index = (index + 1) % keyTable.length;
088: }
089: keyTable[index] = key;
090: valueTable[index] = value;
091:
092: // assumes the threshold is never equal to the size of the table
093: if (++elementSize > threshold) {
094: rehash();
095: }
096: return value;
097: }
098:
099: private void rehash() {
100: ProxyCharArrayCache newHashtable = new ProxyCharArrayCache(
101: keyTable.length * 2);
102: for (int i = keyTable.length; --i >= 0;) {
103: if (keyTable[i] != null) {
104: newHashtable.put(keyTable[i], valueTable[i]);
105: }
106: }
107:
108: this .keyTable = newHashtable.keyTable;
109: this .valueTable = newHashtable.valueTable;
110: this .threshold = newHashtable.threshold;
111: }
112:
113: int size() {
114: return elementSize;
115: }
116:
117: @Override
118: public String toString() {
119: int max = size();
120: StringBuilder buf = new StringBuilder();
121: buf.append("{"); //$NON-NLS-1$
122: for (int i = 0; i < max; ++i) {
123: if (keyTable[i] != null) {
124: buf.append(keyTable[i])
125: .append("->").append(valueTable[i]); //$NON-NLS-1$
126: }
127: if (i < max) {
128: buf.append(", "); //$NON-NLS-1$
129: }
130: }
131: buf.append("}"); //$NON-NLS-1$
132: return buf.toString();
133: }
134: }
|