📄 rangetoken.java
字号:
/* * Copyright 1999-2002,2004,2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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.sun.org.apache.xerces.internal.impl.xpath.regex;/** * This class represents a character class such as [a-z] or a period. * * @xerces.internal * * @version $Id: RangeToken.java,v 1.2.6.1 2005/09/06 11:46:33 neerajbj Exp $ */final class RangeToken extends Token implements java.io.Serializable { private static final long serialVersionUID = 3257568399592010545L; int[] ranges; boolean sorted; boolean compacted; RangeToken icaseCache = null; int[] map = null; int nonMapIndex; RangeToken(int type) { super(type); this.setSorted(false); } // for RANGE or NRANGE protected void addRange(int start, int end) { this.icaseCache = null; //System.err.println("Token#addRange(): "+start+" "+end); int r1, r2; if (start <= end) { r1 = start; r2 = end; } else { r1 = end; r2 = start; } int pos = 0; if (this.ranges == null) { this.ranges = new int[2]; this.ranges[0] = r1; this.ranges[1] = r2; this.setSorted(true); } else { pos = this.ranges.length; if (this.ranges[pos-1]+1 == r1) { this.ranges[pos-1] = r2; return; } int[] temp = new int[pos+2]; System.arraycopy(this.ranges, 0, temp, 0, pos); this.ranges = temp; if (this.ranges[pos-1] >= r1) this.setSorted(false); this.ranges[pos++] = r1; this.ranges[pos] = r2; if (!this.sorted) this.sortRanges(); } } private final boolean isSorted() { return this.sorted; } private final void setSorted(boolean sort) { this.sorted = sort; if (!sort) this.compacted = false; } private final boolean isCompacted() { return this.compacted; } private final void setCompacted() { this.compacted = true; } protected void sortRanges() { if (this.isSorted()) return; if (this.ranges == null) return; //System.err.println("Do sorting: "+this.ranges.length); // Bubble sort // Why? -- In many cases, // this.ranges has few elements. for (int i = this.ranges.length-4; i >= 0; i -= 2) { for (int j = 0; j <= i; j += 2) { if (this.ranges[j] > this.ranges[j+2] || this.ranges[j] == this.ranges[j+2] && this.ranges[j+1] > this.ranges[j+3]) { int tmp; tmp = this.ranges[j+2]; this.ranges[j+2] = this.ranges[j]; this.ranges[j] = tmp; tmp = this.ranges[j+3]; this.ranges[j+3] = this.ranges[j+1]; this.ranges[j+1] = tmp; } } } this.setSorted(true); } /** * this.ranges is sorted. */ protected void compactRanges() { boolean DEBUG = false; if (this.ranges == null || this.ranges.length <= 2) return; if (this.isCompacted()) return; int base = 0; // Index of writing point int target = 0; // Index of processing point while (target < this.ranges.length) { if (base != target) { this.ranges[base] = this.ranges[target++]; this.ranges[base+1] = this.ranges[target++]; } else target += 2; int baseend = this.ranges[base+1]; while (target < this.ranges.length) { if (baseend+1 < this.ranges[target]) break; if (baseend+1 == this.ranges[target]) { if (DEBUG) System.err.println("Token#compactRanges(): Compaction: ["+this.ranges[base] +", "+this.ranges[base+1] +"], ["+this.ranges[target] +", "+this.ranges[target+1] +"] -> ["+this.ranges[base] +", "+this.ranges[target+1] +"]"); this.ranges[base+1] = this.ranges[target+1]; baseend = this.ranges[base+1]; target += 2; } else if (baseend >= this.ranges[target+1]) { if (DEBUG) System.err.println("Token#compactRanges(): Compaction: ["+this.ranges[base] +", "+this.ranges[base+1] +"], ["+this.ranges[target] +", "+this.ranges[target+1] +"] -> ["+this.ranges[base] +", "+this.ranges[base+1] +"]"); target += 2; } else if (baseend < this.ranges[target+1]) { if (DEBUG) System.err.println("Token#compactRanges(): Compaction: ["+this.ranges[base] +", "+this.ranges[base+1] +"], ["+this.ranges[target] +", "+this.ranges[target+1] +"] -> ["+this.ranges[base] +", "+this.ranges[target+1] +"]"); this.ranges[base+1] = this.ranges[target+1]; baseend = this.ranges[base+1]; target += 2; } else { throw new RuntimeException("Token#compactRanges(): Internel Error: [" +this.ranges[base] +","+this.ranges[base+1] +"] ["+this.ranges[target] +","+this.ranges[target+1]+"]"); } } // while base += 2; } if (base != this.ranges.length) { int[] result = new int[base]; System.arraycopy(this.ranges, 0, result, 0, base); this.ranges = result; } this.setCompacted(); } protected void mergeRanges(Token token) { RangeToken tok = (RangeToken)token; this.sortRanges(); tok.sortRanges(); if (tok.ranges == null) return; this.icaseCache = null; this.setSorted(true); if (this.ranges == null) { this.ranges = new int[tok.ranges.length]; System.arraycopy(tok.ranges, 0, this.ranges, 0, tok.ranges.length); return; } int[] result = new int[this.ranges.length+tok.ranges.length]; for (int i = 0, j = 0, k = 0; i < this.ranges.length || j < tok.ranges.length;) { if (i >= this.ranges.length) { result[k++] = tok.ranges[j++]; result[k++] = tok.ranges[j++]; } else if (j >= tok.ranges.length) { result[k++] = this.ranges[i++]; result[k++] = this.ranges[i++]; } else if (tok.ranges[j] < this.ranges[i] || tok.ranges[j] == this.ranges[i] && tok.ranges[j+1] < this.ranges[i+1]) { result[k++] = tok.ranges[j++]; result[k++] = tok.ranges[j++]; } else { result[k++] = this.ranges[i++]; result[k++] = this.ranges[i++]; } } this.ranges = result; } protected void subtractRanges(Token token) { if (token.type == NRANGE) { this.intersectRanges(token); return; } RangeToken tok = (RangeToken)token; if (tok.ranges == null || this.ranges == null) return; this.icaseCache = null; this.sortRanges(); this.compactRanges(); tok.sortRanges(); tok.compactRanges(); //System.err.println("Token#substractRanges(): Entry: "+this.ranges.length+", "+tok.ranges.length); int[] result = new int[this.ranges.length+tok.ranges.length]; int wp = 0, src = 0, sub = 0; while (src < this.ranges.length && sub < tok.ranges.length) { int srcbegin = this.ranges[src]; int srcend = this.ranges[src+1]; int subbegin = tok.ranges[sub]; int subend = tok.ranges[sub+1]; if (srcend < subbegin) { // Not overlapped // src: o-----o // sub: o-----o // res: o-----o // Reuse sub result[wp++] = this.ranges[src++]; result[wp++] = this.ranges[src++]; } else if (srcend >= subbegin && srcbegin <= subend) { // Overlapped // src: o--------o // sub: o----o // sub: o----o // sub: o----o // sub: o------------o if (subbegin <= srcbegin && srcend <= subend) { // src: o--------o // sub: o------------o // res: empty // Reuse sub src += 2; } else if (subbegin <= srcbegin) { // src: o--------o // sub: o----o // res: o-----o // Reuse src(=res) this.ranges[src] = subend+1; sub += 2; } else if (srcend <= subend) { // src: o--------o // sub: o----o // res: o-----o // Reuse sub result[wp++] = srcbegin; result[wp++] = subbegin-1; src += 2; } else { // src: o--------o // sub: o----o // res: o-o o-o // Reuse src(=right res) result[wp++] = srcbegin; result[wp++] = subbegin-1; this.ranges[src] = subend+1; sub += 2; } } else if (subend < srcbegin) { // Not overlapped // src: o-----o // sub: o----o sub += 2; } else { throw new RuntimeException("Token#subtractRanges(): Internal Error: ["+this.ranges[src] +","+this.ranges[src+1] +"] - ["+tok.ranges[sub] +","+tok.ranges[sub+1] +"]"); } } while (src < this.ranges.length) { result[wp++] = this.ranges[src++]; result[wp++] = this.ranges[src++];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -