All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.amygdalum.util.io.SmallRangeCharClassMapper 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.List;

import net.amygdalum.util.text.CharRange;

public class SmallRangeCharClassMapper implements CharClassMapper {

	private char[] chars;
	private char lowerBound;
	private char upperBound;
	private int dead;
	private int[] charToClass;

	public SmallRangeCharClassMapper(List liveRanges) {
		this.lowerBound = liveRanges.isEmpty() ? MAX_VALUE : liveRanges.get(0).from;
		this.upperBound = liveRanges.isEmpty() ? MIN_VALUE : liveRanges.get(liveRanges.size() - 1).to;
		this.dead = deadClass(liveRanges);
		this.chars = chars(dead, liveRanges);
		this.charToClass = computeCharClasses(dead, liveRanges);
	}

	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[] 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 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[] computeCharClasses(int dead, List liveRanges) {
		if (liveRanges.isEmpty()) {
			return new int[0];
		}
		char low = liveRanges.get(0).from;
		char high = liveRanges.get(liveRanges.size() - 1).to;
		int[] charToClass = new int[high - low + 1];
		int charClass = dead + 1;
		for (CharRange range : liveRanges) {
			for (int i = range.from; i <= range.to; i++) {
				charToClass[i - low] = charClass;
			}
			charClass++;
		}
		return charToClass;
	}

	@Override
	public int getIndex(char ch) {
		if (ch < lowerBound || ch > upperBound) {
			return dead;
		}
		return charToClass[ch - lowerBound];
	}

	@Override
	public int indexCount() {
		return chars.length;
	}

	@Override
	public char representative(int i) {
		return chars[i];
	}
	
	@Override
	public char representative(char ch) {
		if (ch < lowerBound || ch > upperBound) {
			return chars[dead];
		}
		return chars[charToClass[ch - lowerBound]];
	}
	
	@Override
	public char[] representatives() {
		return chars;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy