/* * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package jdk.nashorn.internal.runtime.regexp.joni; import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException; @SuppressWarnings("javadoc") public final class CodeRangeBuffer implements Cloneable { private static final int INIT_MULTI_BYTE_RANGE_SIZE = 5; private static final int ALL_MULTI_BYTE_RANGE = 0x7fffffff; int[] p; int used; public CodeRangeBuffer() { p = new int[INIT_MULTI_BYTE_RANGE_SIZE]; writeCodePoint(0, 0); } // CodeRange.isInCodeRange public boolean isInCodeRange(final int code) { int low = 0; final int n = p[0]; int high = n; while (low < high) { final int x = (low + high) >> 1; if (code > p[(x << 1) + 2]) { low = x + 1; } else { high = x; } } return low < n && code >= p[(low << 1) + 1]; } private CodeRangeBuffer(final CodeRangeBuffer orig) { p = new int[orig.p.length]; System.arraycopy(orig.p, 0, p, 0, p.length); used = orig.used; } @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append("CodeRange"); buf.append("\n used: ").append(used); buf.append("\n code point: ").append(p[0]); buf.append("\n ranges: "); for (int i=0; i
0 && i % 6 == 0) {
buf.append("\n ");
}
}
return buf.toString();
}
private static String rangeNumToString(final int num){
return "0x" + Integer.toString(num, 16);
}
public void expand(final int low) {
int length = p.length;
do { length <<= 1; } while (length < low);
final int[]tmp = new int[length];
System.arraycopy(p, 0, tmp, 0, used);
p = tmp;
}
public void ensureSize(final int size) {
int length = p.length;
while (length < size ) { length <<= 1; }
if (p.length != length) {
final int[]tmp = new int[length];
System.arraycopy(p, 0, tmp, 0, used);
p = tmp;
}
}
private void moveRight(final int from, final int to, final int n) {
if (to + n > p.length) {
expand(to + n);
}
System.arraycopy(p, from, p, to, n);
if (to + n > used) {
used = to + n;
}
}
protected void moveLeft(final int from, final int to, final int n) {
System.arraycopy(p, from, p, to, n);
}
private void moveLeftAndReduce(final int from, final int to) {
System.arraycopy(p, from, p, to, used - from);
used -= from - to;
}
public void writeCodePoint(final int pos, final int b) {
final int u = pos + 1;
if (p.length < u) {
expand(u);
}
p[pos] = b;
if (used < u) {
used = u;
}
}
@Override
public CodeRangeBuffer clone() {
return new CodeRangeBuffer(this);
}
// ugly part: these methods should be made OO
// add_code_range_to_buf
public static CodeRangeBuffer addCodeRangeToBuff(final CodeRangeBuffer pbufp, final int fromp, final int top) {
int from = fromp, to = top;
CodeRangeBuffer pbuf = pbufp;
if (from > to) {
final int n = from;
from = to;
to = n;
}
if (pbuf == null) {
pbuf = new CodeRangeBuffer(); // move to CClassNode
}
final int[]p = pbuf.p;
int n = p[0];
int low = 0;
int bound = n;
while (low < bound) {
final int x = (low + bound) >>> 1;
if (from > p[x * 2 + 2]) {
low = x + 1;
} else {
bound = x;
}
}
int high = low;
bound = n;
while (high < bound) {
final int x = (high + bound) >>> 1;
if (to >= p[x * 2 + 1] - 1) {
high = x + 1;
} else {
bound = x;
}
}
final int incN = low + 1 - high;
if (n + incN > Config.MAX_MULTI_BYTE_RANGES_NUM) {
throw new ValueException(ErrorMessages.ERR_TOO_MANY_MULTI_BYTE_RANGES);
}
if (incN != 1) {
if (from > p[low * 2 + 1]) {
from = p[low * 2 + 1];
}
if (to < p[(high - 1) * 2 + 2]) {
to = p[(high - 1) * 2 + 2];
}
}
if (incN != 0 && high < n) {
final int fromPos = 1 + high * 2;
final int toPos = 1 + (low + 1) * 2;
final int size = (n - high) * 2;
if (incN > 0) {
pbuf.moveRight(fromPos, toPos, size);
} else {
pbuf.moveLeftAndReduce(fromPos, toPos);
}
}
final int pos = 1 + low * 2;
// pbuf.ensureSize(pos + 2);
pbuf.writeCodePoint(pos, from);
pbuf.writeCodePoint(pos + 1, to);
n += incN;
pbuf.writeCodePoint(0, n);
return pbuf;
}
// add_code_range, be aware of it returning null!
public static CodeRangeBuffer addCodeRange(final CodeRangeBuffer pbuf, final ScanEnvironment env, final int from, final int to) {
if (from > to) {
if (env.syntax.allowEmptyRangeInCC()) {
return pbuf;
}
throw new ValueException(ErrorMessages.ERR_EMPTY_RANGE_IN_CHAR_CLASS);
}
return addCodeRangeToBuff(pbuf, from, to);
}
// SET_ALL_MULTI_BYTE_RANGE
protected static CodeRangeBuffer setAllMultiByteRange(final CodeRangeBuffer pbuf) {
return addCodeRangeToBuff(pbuf, EncodingHelper.mbcodeStartPosition(), ALL_MULTI_BYTE_RANGE);
}
// ADD_ALL_MULTI_BYTE_RANGE
public static CodeRangeBuffer addAllMultiByteRange(final CodeRangeBuffer pbuf) {
return setAllMultiByteRange(pbuf);
}
// not_code_range_buf
public static CodeRangeBuffer notCodeRangeBuff(final CodeRangeBuffer bbuf) {
CodeRangeBuffer pbuf = null;
if (bbuf == null) {
return setAllMultiByteRange(pbuf);
}
final int[]p = bbuf.p;
final int n = p[0];
if (n <= 0) {
return setAllMultiByteRange(pbuf);
}
int pre = EncodingHelper.mbcodeStartPosition();
int from;
int to = 0;
for (int i=0; i