org.unlaxer.Source Maven / Gradle / Ivy
package org.unlaxer;
import java.util.Collections;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Stream;
import org.unlaxer.util.FactoryBoundCache;
import org.unlaxer.util.function.TriFunction;
public interface Source extends CodePointAccessor , PositionResolver {
public enum SourceKind{
root,
detached,
subSource
;
public boolean isRoot() {
return this == root;
}
public boolean isDetached() {
return this == detached;
}
public boolean isSubSource() {
return this == subSource;
}
}
PositionResolver positionResolver();
SourceKind sourceKind();
CursorRange cursorRange();
Stream linesAsSource();
// default CursorRange cursorRangeOnParent() {
//
// }
// CursorRange cursorRangeOnRoot();
CodePointOffset offsetFromParent();
// static InfiniteLoopDetector infiniteLoopDetector = new InfiniteLoopDetector();
default CodePointOffset offsetFromRoot() {
CodePointOffset codePointOffset = new CodePointOffset(0);
Source current = thisSource();
while(true) {
// infiniteLoopDetector.incrementsAndThrow(20);
if(current.isRoot()) {
// infiniteLoopDetector.reset();
return codePointOffset;
}
current = current.parent().get();
codePointOffset.newWithPlus(current.offsetFromParent());
}
}
Source peek(CodePointIndex startIndexInclusive, CodePointLength length);
default Source peek(CodePointIndex startIndexInclusive, CodePointIndex endIndexExclusive) {
return peek(startIndexInclusive , new CodePointLength(endIndexExclusive.newWithMinus(startIndexInclusive)));
}
default Source peekLast(CodePointIndex endIndexInclusive, CodePointLength length) {
CodePointIndex start = endIndexInclusive.newWithMinus(length)
.createIfMatch(CodePointIndex::isNegative, ()->new CodePointIndex(0));
return peek(start , endIndexInclusive);
}
default Source subSource(CursorRange cursorRange) {
return subSource(cursorRange.startIndexInclusive.position(), cursorRange.endIndexExclusive.position());
}
Source subSource(CodePointIndex startIndexInclusive, CodePointIndex endIndexExclusive);
Source subSource(CodePointIndex startIndexInclusive, CodePointLength codePointLength);
Optional parent();
Source root();
Source thisSource();
Depth depth();
boolean isRoot();
default boolean isPresent() {
return stringLength().value() > 0;
}
default boolean isEmpty() {
return stringLength().value() == 0;
}
default boolean hasParent() {
return parent().isPresent();
}
default PositionResolver createPositionResolver(int[] codePoints) {
return PositionResolver.createPositionResolver(codePoints);
}
// Function stringToSource();
Function sourceToStgring();
TriFunction parentSourceAndStringToSource();
default Source subSource(CodePointIndex beginIndex) {
return parentSourceAndStringToSource().apply(
thisSource(),
stringIndexAccessor().substring(toStringIndex(beginIndex).value()),
new CodePointOffset(beginIndex)
);
}
// default Source subSource(CodePointIndex beginIndex, CodePointIndex endIndex) {
// return parentSourceAndStringToSource().apply(
// thisSource(),
// stringIndexAccessor().substring(toStringIndex(beginIndex).value(),toStringIndex(endIndex).value()),
// new CodePointOffset(beginIndex)
// );
// }
//
// default Source subSource(CodePointIndex beginIndex, CodePointLength length) {
//
// return subSource(beginIndex , beginIndex.newWithAdd(length()));
// }
default Source concat(CodePointAccessor str) {
return parentSourceAndStringToSource().apply(
thisSource() ,
concat(str.sourceAsString()),
CodePointOffset.ZERO
);
}
default Source replaceAsStringInterface(char oldChar, char newChar) {
return parentSourceAndStringToSource().apply(
thisSource() ,
replace(oldChar, newChar),
CodePointOffset.ZERO
);
}
default Source replaceFirst(String regex, CodePointAccessor replacement) {
return parentSourceAndStringToSource().apply(
thisSource() ,
replaceFirst(regex, replacement.toString()),
CodePointOffset.ZERO
);
}
default Source replaceAll(String regex, CodePointAccessor replacement) {
return parentSourceAndStringToSource().apply(
thisSource() ,
replaceAll(regex, replacement.toString()),
CodePointOffset.ZERO
);
}
default Source replaceaAsStringInterface(CharSequence target, CharSequence replacement) {
return parentSourceAndStringToSource().apply(
thisSource() ,
replace(target, replacement),
CodePointOffset.ZERO
);
}
default Source[] splitAsStringInterface(String regex, int limit) {
String[] returning = split(regex, limit);
Source[] result = new Source[returning.length];
int i =0;
int index =0;
for (String string : returning) {
int indexOf = indexOf(string, index);
if(indexOf ==-1) {
throw new IllegalArgumentException();
}
CodePointIndex codePointIndex = toCodePointIndex(new StringIndex(indexOf));
result[i++] = parentSourceAndStringToSource().apply(
thisSource() , string , new CodePointOffset(codePointIndex));
index++;
}
return result;
}
default Source[] splitAsStringInterface(String regex) {
String[] returning = split(regex);
Source[] result = new Source[returning.length];
int i =0;
int index =0;
for (String string : returning) {
int indexOf = indexOf(string, index);
if(indexOf ==-1) {
throw new IllegalArgumentException();
}
CodePointIndex codePointIndex = toCodePointIndex(new StringIndex(indexOf));
result[i++] = parentSourceAndStringToSource().apply(
thisSource() , string , new CodePointOffset(codePointIndex));
index++;
}
return result;
}
default Source toLowerCaseAsStringInterface(Locale locale){
return parentSourceAndStringToSource().apply(
thisSource() , toLowerCase(locale),CodePointOffset.ZERO);
}
default Source toLowerCaseAsStringInterface(){
return parentSourceAndStringToSource().apply(
thisSource() , toLowerCase(),CodePointOffset.ZERO);
}
default Source toUpperCaseAsStringInterface(Locale locale){
return parentSourceAndStringToSource().apply(
thisSource() , toUpperCase(locale),CodePointOffset.ZERO);
}
default Source toUpperCaseAsStringInterface(){
return parentSourceAndStringToSource().apply(
thisSource() , toUpperCase(),CodePointOffset.ZERO);
}
default Source trimAsStringInterface() {
return parentSourceAndStringToSource().apply(
thisSource() , trim(),CodePointOffset.ZERO);
}
default Source stripAsStringInterface() {
return parentSourceAndStringToSource().apply(
thisSource() , strip(),CodePointOffset.ZERO);
}
default Source stripLeadingAsStringInterface() {
return parentSourceAndStringToSource().apply(
thisSource() , stripLeading(),CodePointOffset.ZERO);
}
default Source stripTrailingAsStringInterface() {
return parentSourceAndStringToSource().apply(
thisSource() , stripTrailing(),CodePointOffset.ZERO);
}
default Stream linesAsStringInterface(){
TriFunction parentSourceAndStringToSource =
parentSourceAndStringToSource();
AtomicInteger index = new AtomicInteger();
return lines().map(line -> {
int indexOf = indexOf(line, index.intValue());
index.set(indexOf);
index.incrementAndGet();
CodePointIndex codePointIndex = toCodePointIndex(new StringIndex(indexOf));
return parentSourceAndStringToSource.apply(thisSource(), line , new CodePointOffset(codePointIndex));
});
}
default Source repeatAsStringInterface(int count) {
return parentSourceAndStringToSource().apply(
thisSource() , repeat(count),CodePointOffset.ZERO);
}
// public boolean detached();
// /**
// * Returns a {@code Collector} that concatenates the input elements into a
// * {@code String}, in encounter order.
// *
// * @return a {@code Collector} that concatenates the input elements into a
// * {@code String}, in encounter order
// */
// public static Collector joining() {
// return new CollectorImpl(
// SimpleBuilder::new, SimpleBuilder::append,
// (r1, r2) -> {
// SimpleBuilder append = r1.append(r2);
// return append;
// },
// SimpleBuilder::toSource, CH_NOID);
// }
/**
* Returns a {@code Collector} that concatenates the input elements into a
* {@code String}, in encounter order.
*
* @return a {@code Collector} that concatenates the input elements into a
* {@code String}, in encounter order
*/
public static Collector joining() {
return joining("");
}
/**
* Returns a {@code Collector} that concatenates the input elements,
* separated by the specified delimiter, in encounter order.
*
* @param delimiter the delimiter to be used between each element
* @return A {@code Collector} which concatenates CharSequence elements,
* separated by the specified delimiter, in encounter order
*/
public static Collector joining(CharSequence delimiter) {
return joining(delimiter, "", "");
}
/**
* Returns a {@code Collector} that concatenates the input elements,
* separated by the specified delimiter, with the specified prefix and
* suffix, in encounter order.
*
* @param delimiter the delimiter to be used between each element
* @param prefix the sequence of characters to be used at the beginning
* of the joined result
* @param suffix the sequence of characters to be used at the end
* of the joined result
* @return A {@code Collector} which concatenates CharSequence elements,
* separated by the specified delimiter, in encounter order
*/
public static Collector joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
return new CollectorImpl<>(
() -> new SourceJoiner(delimiter, prefix, suffix),
SourceJoiner::add, SourceJoiner::merge,
SourceJoiner::toSource, CH_NOID);
}
/**
* Simple implementation class for {@code Collector}.
*
* @param the type of elements to be collected
* @param the type of the result
*/
static class CollectorImpl implements Collector {
private final Supplier supplier;
private final BiConsumer accumulator;
private final BinaryOperator combiner;
private final Function finisher;
private final Set characteristics;
CollectorImpl(Supplier supplier,
BiConsumer accumulator,
BinaryOperator combiner,
Function finisher,
Set characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
}
CollectorImpl(Supplier supplier,
BiConsumer accumulator,
BinaryOperator combiner,
Set characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
}
@Override
public BiConsumer accumulator() {
return accumulator;
}
@Override
public Supplier supplier() {
return supplier;
}
@Override
public BinaryOperator combiner() {
return combiner;
}
@Override
public Function finisher() {
return finisher;
}
@Override
public Set characteristics() {
return characteristics;
}
}
@SuppressWarnings("unchecked")
private static Function castingIdentity() {
return i -> (R) i;
}
static final Set CH_NOID = Collections.emptySet();
public static final Source EMPTY = StringSource.createRootSource("");
public static final FactoryBoundCache SUB_EMPTY =
new FactoryBoundCache<>(
rootSource -> StringSource.createSubSource("" , rootSource ,CodePointOffset.ZERO)
);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy