// (c) Tuomas J. Lukka and Benja Fallenstein package org.nongnu.alph; /** A Transcludable String - the most important user-visible * class in Alph Lite. * A transcludable replacement for the java.lang.String object. *

* Time guarantees for a string of length L (in spans): * creating a substring of length k * of length L is O(k + log(L)). charAt is O(log(L)). */ public final class TString { static private TString empty = new TString(new TextSpan[] {}); /** The incremental offsets of the spans. * Length = spans.length + 1 */ private final int[] offsets; /** The spans that this TString consists of. * The value null is not allowed. */ private final TextSpan[] spans; /** Private constructor for TString. * @param spans The spans array (used directly, not to be modified later. * Used like this because this is a private constructor) */ private TString(TextSpan[] spans) { this.spans = spans; offsets = new int[spans.length + 1]; offsets[0] = 0; int offs = 0; for(int i=1; i offsets[offsets.length-1]) throw new StringIndexOutOfBoundsException(offset); int lower = 0; int upper = offsets.length - 1; boolean rienNeVaPlus = false; while(true) { int i = lower + (upper-lower)/2; if(offset < offsets[i]) upper = i; else if(offset >= offsets[i+1]) lower = i; else return i; if(upper == lower+1) { if(!rienNeVaPlus) rienNeVaPlus = true; else return upper; } } } /** As String.substring(int, int). */ public TString substring(int offset1, int offset2) { if(offset2 < offset1) throw new StringIndexOutOfBoundsException(""+offset1+" "+offset2); int spi1 = getSpanIndex(offset1); int spi2 = getSpanIndex(offset2); // Exceptions have been thrown if(offset1 == offset2) return empty; TextSpan[] newSpans; if(spi2 == spans.length || offsets[spi2] == offset2) { newSpans = new TextSpan[spi2 - spi1]; newSpans[0] = (TextSpan)(spans[spi1].subSpan( offset1 - offsets[spi1] )); System.arraycopy(spans, spi1+1, newSpans, 1, newSpans.length - 1); return new TString(newSpans); } if(spi1 == spi2) { return new TString(new TextSpan[] { (TextSpan)(spans[spi1].subSpan(offset1 - offsets[spi1], offset2 - offsets[spi1])) }); } newSpans = new TextSpan[spi2 - spi1 + 1]; newSpans[0] = (TextSpan)(spans[spi1].subSpan( offset1 - offsets[spi1] )); newSpans[newSpans.length-1] = (TextSpan)(spans[spi2].subSpan(0, offset2 - offsets[spi2])); System.arraycopy(spans, spi1+1, newSpans, 1, newSpans.length - 2); return new TString(newSpans); } public String toString() { StringBuffer buf = new StringBuffer(); for(int i=0; i