// (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