net.amygdalum.util.io.BitMaskCharClassMapper Maven / Gradle / Ivy
package net.amygdalum.util.io;
import static java.lang.Character.MAX_VALUE;
import static java.lang.Character.MIN_VALUE;
import static net.amygdalum.util.text.CharUtils.after;
import java.util.Arrays;
import java.util.List;
import net.amygdalum.util.text.CharRange;
public final class BitMaskCharClassMapper implements CharClassMapper {
private int dead;
private char[] chars;
private int[][] bytes;
public BitMaskCharClassMapper(List liveRanges) {
this.dead = deadClass(liveRanges);
this.chars = chars(dead, liveRanges);
this.bytes = computeBytes(dead, liveRanges);
}
private static char[] chars(int dead, List liveRanges) {
int liveIndex = dead + 1;
char[] chars = new char[liveIndex + liveRanges.size()];
if (dead == 0) {
chars[dead] = deadChar(liveRanges);
}
for (CharRange range : liveRanges) {
chars[liveIndex] = range.from;
liveIndex++;
}
return chars;
}
private static int deadClass(List liveRanges) {
if (liveRanges.isEmpty()) {
return 0;
}
char nextCandidate = MIN_VALUE;
for (CharRange range : liveRanges) {
if (range.contains(nextCandidate)) {
nextCandidate = after(range.to);
} else {
return 0;
}
}
if (nextCandidate == after(MAX_VALUE)) {
return -1;
} else {
return 0;
}
}
private static char deadChar(List liveRanges) {
char nextCandidate = MIN_VALUE;
for (CharRange range : liveRanges) {
if (range.contains(nextCandidate)) {
nextCandidate = after(range.to);
} else {
return nextCandidate;
}
}
if (nextCandidate == after(MAX_VALUE)) {
return 0;
} else {
return nextCandidate;
}
}
private static int[][] computeBytes(int dead, List liveRanges) {
int[] deadbytes = new int[256];
Arrays.fill(deadbytes, dead);
int[][] bytes = new int[256][];
Arrays.fill(bytes, deadbytes);
int index = dead;
for (CharRange range : liveRanges) {
index++;
int lowFrom = range.from & 0xff;
int highFrom = (range.from >> 8) & 0xff;
int lowTo = range.to & 0xff;
int highTo = (range.to >> 8) & 0xff;
for (int i = highFrom; i <= highTo; i++) {
if (bytes[i] == deadbytes) {
bytes[i] = new int[256];
Arrays.fill(bytes[i], dead);
}
int start = (i == highFrom) ? lowFrom : 0;
int end = (i == highTo) ? lowTo : 255;
for (int j = start; j <= end; j++) {
bytes[i][j] = index;
}
}
}
return bytes;
}
@Override
public int getIndex(char ch) {
int h = (ch >> 8) & 0xff;
int l = ch & 0xff;
return bytes[h][l];
}
@Override
public int indexCount() {
return chars.length;
}
@Override
public char representative(int i) {
return chars[i];
}
@Override
public char representative(char ch) {
int h = (ch >> 8) & 0xff;
int l = ch & 0xff;
return chars[bytes[h][l]];
}
@Override
public char[] representatives() {
return chars;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy