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

org.unlaxer.StringSource Maven / Gradle / Ivy

package org.unlaxer;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.unlaxer.util.function.TriFunction;

public class StringSource implements Source {
  
  private final Source root;
  private final Source parent;
  private final String sourceString;
//private final CodePoint[] codePoints;
  private final int[] codePoints;
  private final RootPositionResolver rootPositionResolver;
  private final SubPositionResolver subPositionResolver;
  private final Depth depth;
  private final SourceKind sourceKind;
  private final CodePointOffset offsetFromParent;
  private final StringIndexAccessor stringIndexAccessor;
  
  public static StringSource create(String source , SourceKind sourceKind) {
    if(sourceKind == SourceKind.subSource) {
      throw new IllegalArgumentException();
    }
    return new StringSource(source , sourceKind , new CodePointOffset(0));
  }
  
  public static StringSource createRootSource(String source) {
    return new StringSource(source , SourceKind.root , null ,  new CodePointOffset(0));
  }
  
  public static StringSource createDetachedSource(String source , Source root) {
    return new StringSource(source , SourceKind.detached , root , new CodePointOffset(0));
  }
  
  public static StringSource createDetachedSource(String source) {
    return new StringSource(source , SourceKind.detached , null , new CodePointOffset(0));
  }

  
  public static StringSource createDetachedSource(String source , Source root , CodePointOffset codePointOffset) {
    return new StringSource(source , SourceKind.detached , root , codePointOffset);
  }
  
  public StringSource(String source , SourceKind sourceKind , CodePointOffset offsetFromParent) {
    this(source , sourceKind , null , offsetFromParent);
  }

  
  StringSource(String source , SourceKind sourceKind , Source root , CodePointOffset offsetFromParent) {
    super();
    Objects.requireNonNull(source,"source require non null");
    this.root = root == null ? this : root;
    parent = this.root;
    depth = new Depth(0);
    this.sourceKind = sourceKind;
    this.sourceString = source;
    this.offsetFromParent = offsetFromParent;
//    codePoints = source.codePoints().mapToObj(CodePoint::new).toArray(CodePoint[]::new);
    codePoints = source.codePoints().toArray();
    rootPositionResolver = root == null ? 
        new RootPositionResolverImpl(codePoints) : 
        root.rootPositionResolver(); 
    subPositionResolver = new SubPositionResolverImpl(codePoints,rootPositionResolver, offsetFromParent);
    stringIndexAccessor = new StringIndexAccessorImpl(source);
  }

  
  private StringSource(Source parent , Source source , CodePointOffset offsetFromParent) {
    super();
    this.sourceString = source.toString();
    this.root = parent.root();
    if(false == this.root.isRoot()) {
      throw new IllegalArgumentException();
    }
    this.parent = parent;
    this.offsetFromParent = offsetFromParent;
    depth = parent.depth().newWithIncrements();
    sourceKind = SourceKind.subSource;
//    codePoints = source.codePoints().mapToObj(CodePoint::new).toArray(CodePoint[]::new);
    codePoints = source.codePoints().toArray();
    rootPositionResolver = root.rootPositionResolver();
    subPositionResolver = new SubPositionResolverImpl(codePoints,rootPositionResolver, offsetFromParent);
    stringIndexAccessor = new StringIndexAccessorImpl(source.sourceAsString());

//    Source _root = parent;
//    while(true) {
//      if(_root == null || _root.parent().isEmpty()) {
//        root = _root;
//        break;
//      }
//      _root = parent;
//    }
  }
  
  
  public StringSource(Source parent , String source , CodePointOffset codePointOffset) {
    super();
    Objects.requireNonNull(source,"source require non null");
    this.sourceString = source.toString();
    this.parent = parent;
    this.root = parent.root();
    depth = parent.depth().newWithIncrements();
    sourceKind = SourceKind.subSource;
    offsetFromParent = codePointOffset;
//    codePoints = source.codePoints().mapToObj(CodePoint::new).toArray(CodePoint[]::new);
    codePoints = source.codePoints().toArray();
    rootPositionResolver = root.rootPositionResolver();
    subPositionResolver = new SubPositionResolverImpl(codePoints,rootPositionResolver, offsetFromParent);
    stringIndexAccessor = new StringIndexAccessorImpl(source);
    
//    Source _root = parent;
//    while(true) {
//      if(_root == null || _root.parent().isEmpty()) {
//        root = _root;
//        break;
//      }
//      _root = parent;
//    }
  }
  
  public LineNumber lineNumberFrom(CodePointIndex codePointIndex) {
    return rootPositionResolver.lineNumberFrom(codePointIndex);
  }

  public StringIndex stringIndexFrom(CodePointIndex codePointIndex) {
    return rootPositionResolver.stringIndexFrom(codePointIndex);
  }

  public CodePointIndex codePointIndexFrom(StringIndex stringIndex) {
    return rootPositionResolver.codePointIndexFrom(stringIndex);
  }

  public CursorRange rootCursorRange() {
    return rootPositionResolver.rootCursorRange();
  }

  public Stream lines(Source root) {
    return rootPositionResolver.lines(root);
  }

  public Size lineSize() {
    return rootPositionResolver.lineSize();
  }

  public LineNumber subLineNumberFrom(CodePointIndex subCodePointIndex) {
    return subPositionResolver.subLineNumberFrom(subCodePointIndex);
  }

  public StringIndex subStringIndexFrom(CodePointIndex subCodePointIndex) {
    return subPositionResolver.subStringIndexFrom(subCodePointIndex);
  }

  public CodePointIndex subCodePointIndexFrom(StringIndex subStringIndex) {
    return subPositionResolver.subCodePointIndexFrom(subStringIndex);
  }

  static Function stringToStringInterface = string-> StringSource.createRootSource(string);
  static TriFunction parentSourceAndStringToSource = 
      (parent,sourceAsString , codePointOffset)-> 
        new StringSource(parent, 
            StringSource.createDetachedSource(sourceAsString,parent.root()),
            codePointOffset);
  static Function stringInterfaceToStgring = StringSource::toString;
  
  @Override
  public TriFunction parentSourceAndStringToSource() {
    return parentSourceAndStringToSource;
  }

  @Override
  public Function sourceToStgring() {
    return stringInterfaceToStgring;
  }

  @Override
  public StringLength stringLength() {
    return new StringLength(sourceString.length());
  }
  
  @Override
  public CodePointLength codePointLength() {
    return new CodePointLength(codePoints.length);
  }

  @Override
  public boolean isEmpty() {
    return sourceString.isEmpty();
  }

  @Override
  public char charAt(int index) {
    return sourceString.charAt(index);
  }

  @Override
  public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
    return sourceString.getBytes(charsetName);
  }

  @Override
  public byte[] getBytes(Charset charset) {
    return sourceString.getBytes(charset);
  }

  @Override
  public byte[] getBytes() {
    return sourceString.getBytes();
  }

  @Override
  public boolean contentEquals(StringBuffer sb) {
    return sourceString.contentEquals(sb);
  }

  @Override
  public boolean contentEquals(CharSequence cs) {
    return sourceString.contentEquals(cs);
  }

  @Override
  public boolean equalsIgnoreCase(String anotherString) {
    return sourceString.equalsIgnoreCase(anotherString);
  }

  @Override
  public int compareTo(String anotherString) {
    return sourceString.compareTo(anotherString);
  }

  @Override
  public int compareToIgnoreCase(String str) {
    return sourceString.compareToIgnoreCase(str);
  }

  @Override
  public boolean startsWith(String prefix) {
    return sourceString.startsWith(prefix);
  }

  @Override
  public boolean endsWith(String suffix) {
    return sourceString.endsWith(suffix);
  }

  @Override
  public int indexOf(int ch) {
    return sourceString.indexOf(ch);
  }

  @Override
  public int lastIndexOf(int ch) {
    return sourceString.lastIndexOf(ch);
  }

  @Override
  public int indexOf(String str) {
    return sourceString.indexOf(str);
  }

  @Override
  public int lastIndexOf(String str) {
    return sourceString.lastIndexOf(str);
  }
  
  @Override
  public int indexOf(int ch, int fromIndex) {
    return sourceString.indexOf(ch,fromIndex);
  }

  @Override
  public int lastIndexOf(int ch, int fromIndex) {
    return sourceString.lastIndexOf(ch, fromIndex);
  }

  @Override
  public int lastIndexOf(String str, int fromIndex) {
    return sourceString.lastIndexOf(str, fromIndex);
  }

  @Override
  public int indexOf(String str, int fromIndex) {
    return sourceString.indexOf(str,fromIndex);
  }

  @Override
  public CharSequence subSequence(int beginIndex, int endIndex) {
    return sourceString.subSequence(beginIndex, endIndex);
  }

  @Override
  public String concat(String str) {
    return sourceString.concat(str);
  }

  @Override
  public String replace(char oldChar, char newChar) {
    return sourceString.replace(oldChar, newChar);
  }

  @Override
  public boolean matches(String regex) {
    return sourceString.matches(regex);
  }

  @Override
  public boolean contains(CharSequence s) {
    return sourceString.contains(s);
  }

  @Override
  public String replaceFirst(String regex, String replacement) {
    return sourceString.replaceFirst(regex, replacement);
  }

  @Override
  public String replaceAll(String regex, String replacement) {
    return sourceString.replaceAll(regex, replacement);
  }

  @Override
  public String replace(CharSequence target, CharSequence replacement) {
    return sourceString.replace(target, replacement);
  }

  @Override
  public String[] split(String regex, int limit) {
    return sourceString.split(regex,limit);
  }

  @Override
  public String[] split(String regex) {
    return sourceString.split(regex);
  }

  @Override
  public String toLowerCase(Locale locale) {
    return sourceString.toLowerCase(locale);
  }

  @Override
  public String toLowerCase() {
    return sourceString.toLowerCase();
  }

  @Override
  public String toUpperCase(Locale locale) {
    return sourceString.toUpperCase(locale);
  }

  @Override
  public String toUpperCase() {
    return sourceString.toUpperCase();
  }

  @Override
  public String trim() {
    return sourceString.trim();
  }

  @Override
  public String strip() {
    return sourceString.strip();
  }

  @Override
  public String stripLeading() {
    return sourceString.stripLeading();
  }

  @Override
  public String stripTrailing() {
    return sourceString.stripTrailing();
  }

  @Override
  public boolean isBlank() {
    return sourceString.isBlank();
  }

  @Override
  public Stream lines() {
    return sourceString.lines();
  }

  @Override
  public IntStream chars() {
    return sourceString.chars();
  }

  @Override
  public IntStream codePoints() {
    return sourceString.codePoints();
  }

  @Override
  public char[] toCharArray() {
    return sourceString.toCharArray();
  }

  @Override
  public String intern() {
    return sourceString.intern();
  }

  @Override
  public String repeat(int count) {
    return sourceString.repeat(count);
  }

  @Override
  public StringIndex toStringIndex(CodePointIndex codePointIndex) {
    StringIndex stringIndexFrom = rootPositionResolver.stringIndexFrom(codePointIndex);
    if(stringIndexFrom == null) {
      stringIndexFrom = rootPositionResolver.stringIndexFrom(codePointIndex.newWithMinus(1)).newWithAdd(1);
    }
    return stringIndexFrom;
  }

  @Override
  public CodePointIndex toCodePointIndex(StringIndex stringIndex) {
    return rootPositionResolver.codePointIndexFrom(stringIndex);
  }

  @Override
  public int hashCode() {
    return sourceString.hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    if(obj instanceof Source) {
      return sourceString.equals(((Source)obj).sourceAsString());
    }
    return sourceString.equals(obj);
  }

  @Override
  public String toString() {
    return sourceString;
  }

  @Override
  public Source source() {
    return this;
  }

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

  @Override
  public StringIndexWithNegativeValue toStringIndex(CodePointIndexWithNegativeValue codePointIndex) {
    if(codePointIndex.isNegative()) {
      return new StringIndexWithNegativeValue(codePointIndex.value());
    }
    return new StringIndexWithNegativeValue(toStringIndex(codePointIndex.toCodePointIndex()));
  }

  @Override
  public CodePointIndexWithNegativeValue toCodePointIndexWithNegativeValue(StringIndexWithNegativeValue stringIndex) {
    if(stringIndex.isNegative()) {
      return new CodePointIndexWithNegativeValue(stringIndex.value());
    }
    return new CodePointIndexWithNegativeValue(toCodePointIndex(stringIndex.toStringIndex()));
  }

  @Override
  public StringIndexAccessor stringIndexAccessor() {
    return stringIndexAccessor;
  }
  
  public static String toString(CodePointAccessor codePointAccessor) {
    
    return codePointAccessor.toString();
  }

  @Override
  public Source peek(CodePointIndex startIndexInclusive, CodePointLength length) {
    
    CodePointOffset offset = new CodePointOffset(startIndexInclusive);
    if(startIndexInclusive.value() + length.value() > codePoints.length){
//      CodePointIndex index = new CodePointIndex(startIndexInclusive.value());
//      CursorRange cursorRange = new CursorRange(new CursorImpl()
//          .setPosition(index)
//          .setLineNumber(lineNUmber(index))
//      );
//      return new StringSource(this , cursorRange , null);
      return new StringSource(this , 
          subSource(startIndexInclusive, new CodePointLength(0)),
          offset);
    }
    
    return new StringSource(this , subSource(startIndexInclusive, length),offset);
  }
  
  @Override
  public Source subSource(CodePointIndex startIndexInclusive, CodePointIndex endIndexExclusive) {
    return new StringSource(this,
        subString(startIndexInclusive,endIndexExclusive),
        new CodePointOffset(startIndexInclusive)
    );
  }
  
  @Override
  public Source subSource(CodePointIndex startIndexInclusive, CodePointLength codePointLength) {
    return new StringSource(this,
        subString(startIndexInclusive,codePointLength),
        new CodePointOffset(startIndexInclusive)
    );
  }
 
  @Override
  public int[] subCodePoints(CodePointIndex startIndexInclusive, CodePointIndex endIndexExclusive) {
    return Arrays.copyOfRange(codePoints, startIndexInclusive.value() , endIndexExclusive.value());
  }
  
  public String subString(CodePointIndex startIndexInclusive, CodePointIndex endIndexExclusive) {
    return new String(codePoints, startIndexInclusive.value() , endIndexExclusive.value() - startIndexInclusive.value());
  }
  
  public String subString(CodePointIndex startIndexInclusive, CodePointLength length) {
    return new String(codePoints, startIndexInclusive.value() , length.value());
  }

  @Override
  public LineNumber lineNumber(CodePointIndex Position) {
    return rootPositionResolver.lineNumberFrom(Position);
  }

  @Override
  public String sourceAsString() {
    return sourceString;
  }

  @Override
  public Optional parent() {
    return Optional.ofNullable(parent);
  }

  @Override
  public Source root() {
    return root;
  }

  @Override
  public Source thisSource() {
    return this;
  }

  @Override
  public Depth depth() {
    return depth;
  }

  @Override
  public CursorRange cursorRange() {
    return subPositionResolver.cursorRange();
  }
  
  ThreadLocal count = new ThreadLocal<>() {

    @Override
    protected Integer initialValue() {
      return 1;
    }
    
  };
  boolean infLoopDebugging = true;

  @Override
  public CodePointOffset offsetFromParent() {
    CodePointOffset offset = offsetFromParent;
    Source _root = parent;
    while(true) {
      if(_root == null || _root.isRoot() ) {
        break;
      }
      if(infLoopDebugging) {
        Integer integer = count.get();
        count.set(integer+1);
        if(integer > 10) {
          System.out.println("too much Loop");
        }
      }

      _root = parent;
      offset = offset.newWithAdd(_root.offsetFromParent());
    }
    if(infLoopDebugging) {
      count.set(0);
    }
    return offset;
  }

  @Override
  public SourceKind sourceKind() {
    return sourceKind;
  }

  @Override
  public Stream linesAsSource() {
    return rootPositionResolver.lines(this);
  }

  @Override
  public boolean isRoot() {
    return /*parent == null && *//*sourceKind == SourceKind.root &&*/
        (parent == null || parent == root)
        ;
  }

  @Override
  public RootPositionResolver rootPositionResolver() {
    return rootPositionResolver;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy