519 lines
16 KiB
Java
519 lines
16 KiB
Java
/*
|
|
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*
|
|
* THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
|
|
*/
|
|
|
|
package com.sun.xml.internal.fastinfoset.util;
|
|
|
|
import com.sun.xml.internal.fastinfoset.EncodingConstants;
|
|
import com.sun.xml.internal.fastinfoset.CommonResourceBundle;
|
|
import java.util.Iterator;
|
|
import java.util.NoSuchElementException;
|
|
import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException;
|
|
|
|
public class PrefixArray extends ValueArray {
|
|
public static final int PREFIX_MAP_SIZE = 64;
|
|
|
|
private int _initialCapacity;
|
|
|
|
public String[] _array;
|
|
|
|
private PrefixArray _readOnlyArray;
|
|
|
|
private static class PrefixEntry {
|
|
private PrefixEntry next;
|
|
private int prefixId;
|
|
}
|
|
|
|
private PrefixEntry[] _prefixMap = new PrefixEntry[PREFIX_MAP_SIZE];
|
|
|
|
private PrefixEntry _prefixPool;
|
|
|
|
private static class NamespaceEntry {
|
|
private NamespaceEntry next;
|
|
private int declarationId;
|
|
private int namespaceIndex;
|
|
|
|
private String prefix;
|
|
private String namespaceName;
|
|
private int prefixEntryIndex;
|
|
}
|
|
|
|
private NamespaceEntry _namespacePool;
|
|
|
|
private NamespaceEntry[] _inScopeNamespaces;
|
|
|
|
public int[] _currentInScope;
|
|
|
|
public int _declarationId;
|
|
|
|
public PrefixArray(int initialCapacity, int maximumCapacity) {
|
|
_initialCapacity = initialCapacity;
|
|
_maximumCapacity = maximumCapacity;
|
|
|
|
_array = new String[initialCapacity];
|
|
// Sizes of _inScopeNamespaces and _currentInScope need to be two
|
|
// greater than _array because 0 represents the empty string and
|
|
// 1 represents the xml prefix
|
|
_inScopeNamespaces = new NamespaceEntry[initialCapacity + 2];
|
|
_currentInScope = new int[initialCapacity + 2];
|
|
|
|
increaseNamespacePool(initialCapacity);
|
|
increasePrefixPool(initialCapacity);
|
|
|
|
initializeEntries();
|
|
}
|
|
|
|
public PrefixArray() {
|
|
this(DEFAULT_CAPACITY, MAXIMUM_CAPACITY);
|
|
}
|
|
|
|
private final void initializeEntries() {
|
|
_inScopeNamespaces[0] = _namespacePool;
|
|
_namespacePool = _namespacePool.next;
|
|
_inScopeNamespaces[0].next = null;
|
|
_inScopeNamespaces[0].prefix = "";
|
|
_inScopeNamespaces[0].namespaceName = "";
|
|
_inScopeNamespaces[0].namespaceIndex = _currentInScope[0] = 0;
|
|
|
|
int index = KeyIntMap.indexFor(KeyIntMap.hashHash(_inScopeNamespaces[0].prefix.hashCode()), _prefixMap.length);
|
|
_prefixMap[index] = _prefixPool;
|
|
_prefixPool = _prefixPool.next;
|
|
_prefixMap[index].next = null;
|
|
_prefixMap[index].prefixId = 0;
|
|
|
|
|
|
_inScopeNamespaces[1] = _namespacePool;
|
|
_namespacePool = _namespacePool.next;
|
|
_inScopeNamespaces[1].next = null;
|
|
_inScopeNamespaces[1].prefix = EncodingConstants.XML_NAMESPACE_PREFIX;
|
|
_inScopeNamespaces[1].namespaceName = EncodingConstants.XML_NAMESPACE_NAME;
|
|
_inScopeNamespaces[1].namespaceIndex = _currentInScope[1] = 1;
|
|
|
|
index = KeyIntMap.indexFor(KeyIntMap.hashHash(_inScopeNamespaces[1].prefix.hashCode()), _prefixMap.length);
|
|
if (_prefixMap[index] == null) {
|
|
_prefixMap[index] = _prefixPool;
|
|
_prefixPool = _prefixPool.next;
|
|
_prefixMap[index].next = null;
|
|
} else {
|
|
final PrefixEntry e = _prefixMap[index];
|
|
_prefixMap[index] = _prefixPool;
|
|
_prefixPool = _prefixPool.next;
|
|
_prefixMap[index].next = e;
|
|
}
|
|
_prefixMap[index].prefixId = 1;
|
|
}
|
|
|
|
private final void increaseNamespacePool(int capacity) {
|
|
if (_namespacePool == null) {
|
|
_namespacePool = new NamespaceEntry();
|
|
}
|
|
|
|
for (int i = 0; i < capacity; i++) {
|
|
NamespaceEntry ne = new NamespaceEntry();
|
|
ne.next = _namespacePool;
|
|
_namespacePool = ne;
|
|
}
|
|
}
|
|
|
|
private final void increasePrefixPool(int capacity) {
|
|
if (_prefixPool == null) {
|
|
_prefixPool = new PrefixEntry();
|
|
}
|
|
|
|
for (int i = 0; i < capacity; i++) {
|
|
PrefixEntry pe = new PrefixEntry();
|
|
pe.next = _prefixPool;
|
|
_prefixPool = pe;
|
|
}
|
|
}
|
|
|
|
public int countNamespacePool() {
|
|
int i = 0;
|
|
NamespaceEntry e = _namespacePool;
|
|
while (e != null) {
|
|
i++;
|
|
e = e.next;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
public int countPrefixPool() {
|
|
int i = 0;
|
|
PrefixEntry e = _prefixPool;
|
|
while (e != null) {
|
|
i++;
|
|
e = e.next;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
public final void clear() {
|
|
for (int i = _readOnlyArraySize; i < _size; i++) {
|
|
_array[i] = null;
|
|
}
|
|
_size = _readOnlyArraySize;
|
|
}
|
|
|
|
public final void clearCompletely() {
|
|
_prefixPool = null;
|
|
_namespacePool = null;
|
|
|
|
for (int i = 0; i < _size + 2; i++) {
|
|
_currentInScope[i] = 0;
|
|
_inScopeNamespaces[i] = null;
|
|
}
|
|
|
|
for (int i = 0; i < _prefixMap.length; i++) {
|
|
_prefixMap[i] = null;
|
|
}
|
|
|
|
increaseNamespacePool(_initialCapacity);
|
|
increasePrefixPool(_initialCapacity);
|
|
|
|
initializeEntries();
|
|
|
|
_declarationId = 0;
|
|
|
|
clear();
|
|
}
|
|
|
|
/**
|
|
* Returns cloned version of internal String[].
|
|
* @return cloned version of internal String[].
|
|
*/
|
|
public final String[] getArray() {
|
|
if (_array == null) return null;
|
|
|
|
final String[] clonedArray = new String[_array.length];
|
|
System.arraycopy(_array, 0, clonedArray, 0, _array.length);
|
|
return clonedArray;
|
|
}
|
|
|
|
public final void setReadOnlyArray(ValueArray readOnlyArray, boolean clear) {
|
|
if (!(readOnlyArray instanceof PrefixArray)) {
|
|
throw new IllegalArgumentException(CommonResourceBundle.getInstance().
|
|
getString("message.illegalClass", new Object[]{readOnlyArray}));
|
|
}
|
|
|
|
setReadOnlyArray((PrefixArray)readOnlyArray, clear);
|
|
}
|
|
|
|
public final void setReadOnlyArray(PrefixArray readOnlyArray, boolean clear) {
|
|
if (readOnlyArray != null) {
|
|
_readOnlyArray = readOnlyArray;
|
|
_readOnlyArraySize = readOnlyArray.getSize();
|
|
|
|
clearCompletely();
|
|
|
|
// Resize according to size of read only arrays
|
|
_inScopeNamespaces = new NamespaceEntry[_readOnlyArraySize + _inScopeNamespaces.length];
|
|
_currentInScope = new int[_readOnlyArraySize + _currentInScope.length];
|
|
// Intialize first two entries
|
|
initializeEntries();
|
|
|
|
if (clear) {
|
|
clear();
|
|
}
|
|
|
|
_array = getCompleteArray();
|
|
_size = _readOnlyArraySize;
|
|
}
|
|
}
|
|
|
|
public final String[] getCompleteArray() {
|
|
if (_readOnlyArray == null) {
|
|
// Return cloned version of internal _array
|
|
return getArray();
|
|
// return _array;
|
|
} else {
|
|
final String[] ra = _readOnlyArray.getCompleteArray();
|
|
final String[] a = new String[_readOnlyArraySize + _array.length];
|
|
System.arraycopy(ra, 0, a, 0, _readOnlyArraySize);
|
|
return a;
|
|
}
|
|
}
|
|
|
|
public final String get(int i) {
|
|
return _array[i];
|
|
}
|
|
|
|
public final int add(String s) {
|
|
if (_size == _array.length) {
|
|
resize();
|
|
}
|
|
|
|
_array[_size++] = s;
|
|
return _size;
|
|
}
|
|
|
|
protected final void resize() {
|
|
if (_size == _maximumCapacity) {
|
|
throw new ValueArrayResourceException(CommonResourceBundle.getInstance().getString("message.arrayMaxCapacity"));
|
|
}
|
|
|
|
int newSize = _size * 3 / 2 + 1;
|
|
if (newSize > _maximumCapacity) {
|
|
newSize = _maximumCapacity;
|
|
}
|
|
|
|
final String[] newArray = new String[newSize];
|
|
System.arraycopy(_array, 0, newArray, 0, _size);
|
|
_array = newArray;
|
|
|
|
newSize += 2;
|
|
final NamespaceEntry[] newInScopeNamespaces = new NamespaceEntry[newSize];
|
|
System.arraycopy(_inScopeNamespaces, 0, newInScopeNamespaces, 0, _inScopeNamespaces.length);
|
|
_inScopeNamespaces = newInScopeNamespaces;
|
|
|
|
final int[] newCurrentInScope = new int[newSize];
|
|
System.arraycopy(_currentInScope, 0, newCurrentInScope, 0, _currentInScope.length);
|
|
_currentInScope = newCurrentInScope;
|
|
}
|
|
|
|
public final void clearDeclarationIds() {
|
|
for (int i = 0; i < _size; i++) {
|
|
final NamespaceEntry e = _inScopeNamespaces[i];
|
|
if (e != null) {
|
|
e.declarationId = 0;
|
|
}
|
|
}
|
|
|
|
_declarationId = 1;
|
|
}
|
|
|
|
public final void pushScope(int prefixIndex, int namespaceIndex) throws FastInfosetException {
|
|
if (_namespacePool == null) {
|
|
increaseNamespacePool(16);
|
|
}
|
|
|
|
final NamespaceEntry e = _namespacePool;
|
|
_namespacePool = e.next;
|
|
|
|
final NamespaceEntry current = _inScopeNamespaces[++prefixIndex];
|
|
if (current == null) {
|
|
e.declarationId = _declarationId;
|
|
e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
|
|
e.next = null;
|
|
|
|
_inScopeNamespaces[prefixIndex] = e;
|
|
} else if (current.declarationId < _declarationId) {
|
|
e.declarationId = _declarationId;
|
|
e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
|
|
e.next = current;
|
|
|
|
current.declarationId = 0;
|
|
_inScopeNamespaces[prefixIndex] = e;
|
|
} else {
|
|
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.duplicateNamespaceAttribute"));
|
|
}
|
|
}
|
|
|
|
public final void pushScopeWithPrefixEntry(String prefix, String namespaceName,
|
|
int prefixIndex, int namespaceIndex) throws FastInfosetException {
|
|
if (_namespacePool == null) {
|
|
increaseNamespacePool(16);
|
|
}
|
|
if (_prefixPool == null) {
|
|
increasePrefixPool(16);
|
|
}
|
|
|
|
final NamespaceEntry e = _namespacePool;
|
|
_namespacePool = e.next;
|
|
|
|
final NamespaceEntry current = _inScopeNamespaces[++prefixIndex];
|
|
if (current == null) {
|
|
e.declarationId = _declarationId;
|
|
e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
|
|
e.next = null;
|
|
|
|
_inScopeNamespaces[prefixIndex] = e;
|
|
} else if (current.declarationId < _declarationId) {
|
|
e.declarationId = _declarationId;
|
|
e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex;
|
|
e.next = current;
|
|
|
|
current.declarationId = 0;
|
|
_inScopeNamespaces[prefixIndex] = e;
|
|
} else {
|
|
throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.duplicateNamespaceAttribute"));
|
|
}
|
|
|
|
final PrefixEntry p = _prefixPool;
|
|
_prefixPool = _prefixPool.next;
|
|
p.prefixId = prefixIndex;
|
|
|
|
e.prefix = prefix;
|
|
e.namespaceName = namespaceName;
|
|
e.prefixEntryIndex = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix.hashCode()), _prefixMap.length);
|
|
|
|
final PrefixEntry pCurrent = _prefixMap[e.prefixEntryIndex];
|
|
p.next = pCurrent;
|
|
_prefixMap[e.prefixEntryIndex] = p;
|
|
}
|
|
|
|
public final void popScope(int prefixIndex) {
|
|
final NamespaceEntry e = _inScopeNamespaces[++prefixIndex];
|
|
_inScopeNamespaces[prefixIndex] = e.next;
|
|
_currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex : 0;
|
|
|
|
e.next = _namespacePool;
|
|
_namespacePool = e;
|
|
}
|
|
|
|
public final void popScopeWithPrefixEntry(int prefixIndex) {
|
|
final NamespaceEntry e = _inScopeNamespaces[++prefixIndex];
|
|
|
|
_inScopeNamespaces[prefixIndex] = e.next;
|
|
_currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex : 0;
|
|
|
|
e.prefix = e.namespaceName = null;
|
|
e.next = _namespacePool;
|
|
_namespacePool = e;
|
|
|
|
PrefixEntry current = _prefixMap[e.prefixEntryIndex];
|
|
if (current.prefixId == prefixIndex) {
|
|
_prefixMap[e.prefixEntryIndex] = current.next;
|
|
current.next = _prefixPool;
|
|
_prefixPool = current;
|
|
} else {
|
|
PrefixEntry prev = current;
|
|
current = current.next;
|
|
while (current != null) {
|
|
if (current.prefixId == prefixIndex) {
|
|
prev.next = current.next;
|
|
current.next = _prefixPool;
|
|
_prefixPool = current;
|
|
break;
|
|
}
|
|
prev = current;
|
|
current = current.next;
|
|
}
|
|
}
|
|
}
|
|
|
|
public final String getNamespaceFromPrefix(String prefix) {
|
|
final int index = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix.hashCode()), _prefixMap.length);
|
|
PrefixEntry pe = _prefixMap[index];
|
|
while (pe != null) {
|
|
final NamespaceEntry ne = _inScopeNamespaces[pe.prefixId];
|
|
if (prefix == ne.prefix || prefix.equals(ne.prefix)) {
|
|
return ne.namespaceName;
|
|
}
|
|
pe = pe.next;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public final String getPrefixFromNamespace(String namespaceName) {
|
|
int position = 0;
|
|
while (++position < _size + 2) {
|
|
final NamespaceEntry ne = _inScopeNamespaces[position];
|
|
if (ne != null && namespaceName.equals(ne.namespaceName)) {
|
|
return ne.prefix;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public final Iterator getPrefixes() {
|
|
return new Iterator() {
|
|
int _position = 1;
|
|
NamespaceEntry _ne = _inScopeNamespaces[_position];
|
|
|
|
public boolean hasNext() {
|
|
return _ne != null;
|
|
}
|
|
|
|
public Object next() {
|
|
if (_position == _size + 2) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
|
|
final String prefix = _ne.prefix;
|
|
moveToNext();
|
|
return prefix;
|
|
}
|
|
|
|
public void remove() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
private final void moveToNext() {
|
|
while (++_position < _size + 2) {
|
|
_ne = _inScopeNamespaces[_position];
|
|
if (_ne != null) {
|
|
return;
|
|
}
|
|
}
|
|
_ne = null;
|
|
}
|
|
|
|
};
|
|
}
|
|
|
|
public final Iterator getPrefixesFromNamespace(final String namespaceName) {
|
|
return new Iterator() {
|
|
String _namespaceName = namespaceName;
|
|
int _position = 0;
|
|
NamespaceEntry _ne;
|
|
|
|
{
|
|
moveToNext();
|
|
}
|
|
|
|
public boolean hasNext() {
|
|
return _ne != null;
|
|
}
|
|
|
|
public Object next() {
|
|
if (_position == _size + 2) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
|
|
final String prefix = _ne.prefix;
|
|
moveToNext();
|
|
return prefix;
|
|
}
|
|
|
|
public void remove() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
private final void moveToNext() {
|
|
while (++_position < _size + 2) {
|
|
_ne = _inScopeNamespaces[_position];
|
|
if (_ne != null && _namespaceName.equals(_ne.namespaceName)) {
|
|
return;
|
|
}
|
|
}
|
|
_ne = null;
|
|
}
|
|
};
|
|
}
|
|
}
|