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

org.unlaxer.util.Slicer Maven / Gradle / Ivy

package org.unlaxer.util;

import java.util.function.Function;
import java.util.function.Supplier;

import org.unlaxer.CodePointIndex;
import org.unlaxer.CursorRange;
import org.unlaxer.Source;
import org.unlaxer.StringSource;

public class Slicer implements Supplier{
	
	private Source word;
	
	private CodePointIndex beginIndexInclusive;
	private CodePointIndex endIndexExclusive;
	private int step;
	private Source rootSource;
	
	public static Slicer of(String rootString) {
	  return new Slicer(StringSource.createRootSource(rootString));
	}
	
	public Slicer(Source rootSource , String word) {
	  this(StringSource.createDetachedSource(word,rootSource));
	}

	public Slicer(Source word) {
		super();
		rootSource = word.root();
		this.word = word;
		beginIndexInclusive = new CodePointIndex(0);
		endIndexExclusive = this.word.endIndexExclusive();
		step=1;
	}
	
	
	/**
	 * @param beginIndexInclusive if beginIndexInclusive less than 0 then position relative from tail
	 *        (like python slice style)
	 * @return this object
	 */
	public Slicer begin(CodePointIndex beginIndexInclusive){
		this.beginIndexInclusive = beginIndexInclusive.isNegative() ?
				beginIndexInclusive.newWithPlus(word.length()):
				beginIndexInclusive;
		return this;
	}
	
	public Slicer begin(Function positionSpecifier){
		beginIndexInclusive = positionSpecifier.apply(word);
		return this;
	}
	
	/**
	 * @param endIndexExclusive if endIndexExclusive less than 0 then position relative from tail
	 *        (like python slice style)
	 * @return this object
	 */
	public Slicer end(CodePointIndex endIndexExclusive){
		this.endIndexExclusive = endIndexExclusive.isNegative() ?
				endIndexExclusive.newWithPlus(word.length()):
				endIndexExclusive;
		return this;
	}
	
	public Slicer end(Function positionSpecifier){
		endIndexExclusive = positionSpecifier.apply(word);
		return this;
	}
	
	public Slicer range(Function rangeSpecifier){
	  CursorRange range = rangeSpecifier.apply(word);
		begin(range.startIndexInclusive.position());
		end(range.endIndexExclusive.position());
		return this;
	}
	
	public Slicer step(int step){
		this.step = step;
		return this;
	}
	
	public Slicer invalidate(){
		begin(new CodePointIndex(0));
		end(new CodePointIndex(0));
		return this;
	}

	// TODO improve performance see AbstractStringBuilder#reverse
	@Override
	public Source get() {
		
		if(step == 1){
			
			return word.subSource(beginIndexInclusive, endIndexExclusive);
		}else if(step ==0){
			
			return Source.SUB_EMPTY.get(rootSource);
		}
		int start = step < 0 ? endIndexExclusive.value() -1 : beginIndexInclusive.value();
		int end = step < 0 ? beginIndexInclusive.value() : endIndexExclusive.value() ;
		SimpleBuilder builder = new SimpleBuilder();
		if(step < 0){
			
			for(int i = start ; i >= end ; i = i + step){
				builder.append(word.subSource(new CodePointIndex(i) ,new CodePointIndex(i+1)));
			}
		}else{
			
			for(int i = start ; i < end ; i = i + step){
				builder.append(word.subSource(new CodePointIndex(i) ,new CodePointIndex(i+1)));
			}
		}
		return builder.toSource();
	}
	
	public Source reverse() {
		return reverse(true);
	}
	
	public Source reverse(boolean reverse) {
		
		return reverse ? //
				new SimpleBuilder(get()).reverse().toSource():
				get();
	}
	
	public int length(){
		return word.length();
	}
	
	public Slicer pythonian(String colonSeparatedValue){
		
		String[] splits = colonSeparatedValue.split(":",3);
		if(splits.length>2 && false ==splits[2].isEmpty()){
			step(Integer.parseInt(splits[2]));
		}
		if(splits.length>1 && false ==splits[1].isEmpty()){
			end(new CodePointIndex(Integer.parseInt(splits[1])));
		}
		if(false ==splits[0].isEmpty()){
			begin(new CodePointIndex(Integer.parseInt(splits[0])));
		}
		return this;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy