HashedMatcherBase.java
package tools.jackson.core.sym;
import java.util.Locale;
/**
* Intermediate base class for matchers that use hash-array based approach
* with Strings.
*/
public abstract class HashedMatcherBase
extends PropertyNameMatcher
{
private static final long serialVersionUID = 1L;
/**
* Mask used to get index from raw hash code, within hash area.
*/
protected final int _mask;
// // // Main hash area (ints) along with Strings it maps (sparse)
protected final int[] _offsets;
protected final String[] _names;
/*
/**********************************************************************
/* Construction
/**********************************************************************
*/
protected HashedMatcherBase(Locale locale, String[] names, int[] offsets, int mask,
PropertyNameMatcher backup, String[] nameLookup)
{
super(locale, backup, nameLookup);
_names = names;
_offsets = offsets;
_mask = mask;
}
protected HashedMatcherBase(HashedMatcherBase base, String[] nameLookup) {
this(base._locale, base._names, base._offsets, base._mask, base._backupMatcher, nameLookup);
}
protected HashedMatcherBase(HashedMatcherBase base, PropertyNameMatcher fallback) {
this(base._locale, base._names, base._offsets, base._mask, fallback, base._nameLookup);
}
/*
/**********************************************************************
/* API: lookup by String
/**********************************************************************
*/
@Override
public final int matchName(String toMatch)
{
// Logic here is that it is expected most names to match are intern()ed
// anyway; as are (typically) contents. So identity check is likely to
// work, just not guaranteed. So do fast checks for primary, secondary here
int ix = _hash(toMatch.hashCode(), _mask);
if (_names[ix] == toMatch) {
return _offsets[ix];
}
// check secondary slot
int ix2 = (_mask + 1) + (ix >> 1);
if (_names[ix2] == toMatch) {
return _offsets[ix2];
}
return _matchName2(toMatch, ix, ix2);
}
private final int _matchName2(String toMatch, int ix, int ix2)
{
String name = _names[ix];
if (toMatch.equals(name)) {
return _offsets[ix];
}
if (name != null) {
name = _names[ix2];
if (toMatch.equals(name)) {
return _offsets[ix2];
}
if (name != null) {
return _matchSpill(toMatch);
}
}
return matchSecondary(toMatch);
}
protected int _matchSpill(String toMatch) {
int ix = (_mask+1);
ix += (ix>>1);
for (int end = _names.length; ix < end; ++ix) {
String name = _names[ix];
if (toMatch.equals(name)) {
return _offsets[ix];
}
if (name == null) {
break;
}
}
return matchSecondary(toMatch);
}
/*
/**********************************************************************
/* Test methods
/**********************************************************************
*/
public int spillCount() {
int spillStart = (_mask+1) + ((_mask+1) >> 1);
int count = 0;
for (int i = spillStart; i < _names.length; ++i) {
if (_names[i] != null) {
++count;
}
}
return count;
}
public int secondaryCount() {
int spillStart = (_mask+1) + ((_mask+1) >> 1);
int count = 0;
for (int i = _mask+1; i < spillStart; ++i) {
if (_names[i] != null) {
++count;
}
}
return count;
}
}