aoqi@0: /* aoqi@0: * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.fastinfoset.util; aoqi@0: aoqi@0: import com.sun.xml.internal.fastinfoset.QualifiedName; aoqi@0: import com.sun.xml.internal.fastinfoset.CommonResourceBundle; aoqi@0: aoqi@0: public class LocalNameQualifiedNamesMap extends KeyIntMap { aoqi@0: aoqi@0: private LocalNameQualifiedNamesMap _readOnlyMap; aoqi@0: aoqi@0: private int _index; aoqi@0: aoqi@0: public static class Entry { aoqi@0: final String _key; aoqi@0: final int _hash; aoqi@0: public QualifiedName[] _value; aoqi@0: public int _valueIndex; aoqi@0: Entry _next; aoqi@0: aoqi@0: public Entry(String key, int hash, Entry next) { aoqi@0: _key = key; aoqi@0: _hash = hash; aoqi@0: _next = next; aoqi@0: _value = new QualifiedName[1]; aoqi@0: } aoqi@0: aoqi@0: public void addQualifiedName(QualifiedName name) { aoqi@0: if (_valueIndex < _value.length) { aoqi@0: _value[_valueIndex++] = name; aoqi@0: } else if (_valueIndex == _value.length) { aoqi@0: QualifiedName[] newValue = new QualifiedName[_valueIndex * 3 / 2 + 1]; aoqi@0: System.arraycopy(_value, 0, newValue, 0, _valueIndex); aoqi@0: _value = newValue; aoqi@0: _value[_valueIndex++] = name; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private Entry[] _table; aoqi@0: aoqi@0: public LocalNameQualifiedNamesMap(int initialCapacity, float loadFactor) { aoqi@0: super(initialCapacity, loadFactor); aoqi@0: aoqi@0: _table = new Entry[_capacity]; aoqi@0: } aoqi@0: aoqi@0: public LocalNameQualifiedNamesMap(int initialCapacity) { aoqi@0: this(initialCapacity, DEFAULT_LOAD_FACTOR); aoqi@0: } aoqi@0: aoqi@0: public LocalNameQualifiedNamesMap() { aoqi@0: this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); aoqi@0: } aoqi@0: aoqi@0: public final void clear() { aoqi@0: for (int i = 0; i < _table.length; i++) { aoqi@0: _table[i] = null; aoqi@0: } aoqi@0: _size = 0; aoqi@0: aoqi@0: if (_readOnlyMap != null) { aoqi@0: _index = _readOnlyMap.getIndex(); aoqi@0: } else { aoqi@0: _index = 0; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final void setReadOnlyMap(KeyIntMap readOnlyMap, boolean clear) { aoqi@0: if (!(readOnlyMap instanceof LocalNameQualifiedNamesMap)) { aoqi@0: throw new IllegalArgumentException(CommonResourceBundle.getInstance(). aoqi@0: getString("message.illegalClass", new Object[]{readOnlyMap})); aoqi@0: } aoqi@0: aoqi@0: setReadOnlyMap((LocalNameQualifiedNamesMap)readOnlyMap, clear); aoqi@0: } aoqi@0: aoqi@0: public final void setReadOnlyMap(LocalNameQualifiedNamesMap readOnlyMap, boolean clear) { aoqi@0: _readOnlyMap = readOnlyMap; aoqi@0: if (_readOnlyMap != null) { aoqi@0: _readOnlyMapSize = _readOnlyMap.size(); aoqi@0: _index = _readOnlyMap.getIndex(); aoqi@0: if (clear) { aoqi@0: clear(); aoqi@0: } aoqi@0: } else { aoqi@0: _readOnlyMapSize = 0; aoqi@0: _index = 0; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final boolean isQNameFromReadOnlyMap(QualifiedName name) { aoqi@0: return (_readOnlyMap != null && name.index <= _readOnlyMap.getIndex()); aoqi@0: } aoqi@0: aoqi@0: public final int getNextIndex() { aoqi@0: return _index++; aoqi@0: } aoqi@0: aoqi@0: public final int getIndex() { aoqi@0: return _index; aoqi@0: } aoqi@0: aoqi@0: public final Entry obtainEntry(String key) { aoqi@0: final int hash = hashHash(key.hashCode()); aoqi@0: aoqi@0: if (_readOnlyMap != null) { aoqi@0: final Entry entry = _readOnlyMap.getEntry(key, hash); aoqi@0: if (entry != null) { aoqi@0: return entry; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final int tableIndex = indexFor(hash, _table.length); aoqi@0: for (Entry e = _table[tableIndex]; e != null; e = e._next) { aoqi@0: if (e._hash == hash && eq(key, e._key)) { aoqi@0: return e; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return addEntry(key, hash, tableIndex); aoqi@0: } aoqi@0: aoqi@0: public final Entry obtainDynamicEntry(String key) { aoqi@0: final int hash = hashHash(key.hashCode()); aoqi@0: aoqi@0: final int tableIndex = indexFor(hash, _table.length); aoqi@0: for (Entry e = _table[tableIndex]; e != null; e = e._next) { aoqi@0: if (e._hash == hash && eq(key, e._key)) { aoqi@0: return e; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return addEntry(key, hash, tableIndex); aoqi@0: } aoqi@0: aoqi@0: private final Entry getEntry(String key, int hash) { aoqi@0: if (_readOnlyMap != null) { aoqi@0: final Entry entry = _readOnlyMap.getEntry(key, hash); aoqi@0: if (entry != null) { aoqi@0: return entry; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final int tableIndex = indexFor(hash, _table.length); aoqi@0: for (Entry e = _table[tableIndex]; e != null; e = e._next) { aoqi@0: if (e._hash == hash && eq(key, e._key)) { aoqi@0: return e; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: private final Entry addEntry(String key, int hash, int bucketIndex) { aoqi@0: Entry e = _table[bucketIndex]; aoqi@0: _table[bucketIndex] = new Entry(key, hash, e); aoqi@0: e = _table[bucketIndex]; aoqi@0: if (_size++ >= _threshold) { aoqi@0: resize(2 * _table.length); aoqi@0: } aoqi@0: aoqi@0: return e; aoqi@0: } aoqi@0: aoqi@0: private final void resize(int newCapacity) { aoqi@0: _capacity = newCapacity; aoqi@0: Entry[] oldTable = _table; aoqi@0: int oldCapacity = oldTable.length; aoqi@0: if (oldCapacity == MAXIMUM_CAPACITY) { aoqi@0: _threshold = Integer.MAX_VALUE; aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: Entry[] newTable = new Entry[_capacity]; aoqi@0: transfer(newTable); aoqi@0: _table = newTable; aoqi@0: _threshold = (int)(_capacity * _loadFactor); aoqi@0: } aoqi@0: aoqi@0: private final void transfer(Entry[] newTable) { aoqi@0: Entry[] src = _table; aoqi@0: int newCapacity = newTable.length; aoqi@0: for (int j = 0; j < src.length; j++) { aoqi@0: Entry e = src[j]; aoqi@0: if (e != null) { aoqi@0: src[j] = null; aoqi@0: do { aoqi@0: Entry next = e._next; aoqi@0: int i = indexFor(e._hash, newCapacity); aoqi@0: e._next = newTable[i]; aoqi@0: newTable[i] = e; aoqi@0: e = next; aoqi@0: } while (e != null); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private final boolean eq(String x, String y) { aoqi@0: return x == y || x.equals(y); aoqi@0: } aoqi@0: aoqi@0: }