com.fasterxml.aalto.in.PNameC Maven / Gradle / Ivy
Show all versions of aalto-xml Show documentation
/* Woodstox Lite ("wool") XML processor
*
* Copyright (c) 2006- Tatu Saloranta, [email protected]
*
* Licensed under the License specified in the file LICENSE which is
* included with the source code.
* You may not use this file except in compliance with the License.
*
* 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.fasterxml.aalto.in;
import com.fasterxml.aalto.impl.ErrorConsts;
/**
* An alternate implementation of PName: instead of coming straight from
* byte contents, it is actually just built from a character array.
*
* Note: one unfortunate result of this being a somewhat different PName
* is that equality comparison between this and other implementations will not
* work as expected. As such, these should only be used as temporary names.
*/
public final class PNameC
extends PName
{
/**
* Since the hash may be calculated different from the way eventual
* String's hash will be (right now it is not), we better store
* "our" hash here.
*/
protected final int mHash;
public PNameC(String pname, String prefix, String ln, int hash)
{
super(pname, prefix, ln);
mHash = hash;
}
@Override
public PName createBoundName(NsBinding nsb)
{
PNameC newName = new PNameC(_prefixedName, _prefix, _localName, mHash);
newName._namespaceBinding = nsb;
return newName;
}
public static PNameC construct(String pname)
{
return construct(pname, calcHash(pname));
}
public static PNameC construct(String pname, int hash)
{
int colonIx = pname.indexOf(':');
if (colonIx < 0) {
return new PNameC(pname, null, pname, hash);
}
/* !!! TODO: cache prefix intern() calls, since they are bound
* to cluster nicely (and quite often within same thread too)
*/
return new PNameC(pname, pname.substring(0, colonIx).intern(),
pname.substring(colonIx+1).intern(), hash);
}
/*
//////////////////////////////////////////////////////////
// Sub-class API
//////////////////////////////////////////////////////////
*/
public boolean equalsPName(char[] buffer, int start, int len, int hash)
{
if (hash != mHash) {
return false;
}
String pname = _prefixedName;
int plen = pname.length();
if (len != plen) {
return false;
}
for (int i = 0; i < len; ++i) {
if (buffer[start+i] != pname.charAt(i)) {
return false;
}
}
return true;
}
public int getCustomHash() { return mHash; }
/**
* Implementation of a hashing method for variable length
* Strings. Most of the time intention is that this calculation
* is done by caller during parsing, not here; however, sometimes
* it needs to be done for parsed "String" too.
*
* @param len Length of String; has to be at least 1 (caller guarantees
* this pre-condition)
*/
public static int calcHash(char[] buffer, int start, int len) {
int hash = (int) buffer[0];
for (int i = 1; i < len; ++i) {
hash = (hash * 31) + (int) buffer[i];
}
return hash;
}
public static int calcHash(String key) {
int hash = (int) key.charAt(0);
for (int i = 1, len = key.length(); i < len; ++i) {
hash = (hash * 31) + (int) key.charAt(i);
}
return hash;
}
/*
//////////////////////////////////////////////////////////
// Methods for package/core parser
//////////////////////////////////////////////////////////
*/
/**
* This method should never get called on instances of this class,
* so let's throw an exception if that does happen.
*/
@Override
public int sizeInQuads()
{
ErrorConsts.throwInternalError();
return 0; // never gets here
}
@Override
public int getFirstQuad()
{
ErrorConsts.throwInternalError();
return 0; // never gets here
}
@Override
public final int getLastQuad()
{
ErrorConsts.throwInternalError();
return 0; // never gets here
}
@Override
public int getQuad(int index)
{
ErrorConsts.throwInternalError();
return 0; // never gets here
}
/*
//////////////////////////////////////////////////////////
// Redefined standard methods
//////////////////////////////////////////////////////////
*/
/**
* Whether we should use internal hash, or the hash of prefixed
* name string itself is an open question. For now, let's use
* former.
*/
@Override
public int hashCode() { return mHash; }
}