package client.net.sf.saxon.ce.functions;
import client.net.sf.saxon.ce.expr.XPathContext;
import client.net.sf.saxon.ce.om.Item;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.tree.util.FastStringBuffer;
import client.net.sf.saxon.ce.value.DoubleValue;
import client.net.sf.saxon.ce.value.StringValue;
/**
* This class implements the XPath substring() function
*/
public class Substring extends SystemFunction {
public Substring newInstance() {
return new Substring();
}
/**
* Evaluate the function
*/
public Item evaluateItem(XPathContext context) throws XPathException {
StringValue sv = (StringValue)argument[0].evaluateItem(context);
if (sv==null) {
return StringValue.EMPTY_STRING;
}
String str = sv.getStringValue();
double start = ((DoubleValue)argument[1].evaluateItem(context)).round().getDoubleValue();
double length;
if (argument.length==2) {
length = (double)str.length();
} else {
length = ((DoubleValue)argument[2].evaluateItem(context)).round().getDoubleValue();
if (length < 0) {
length = 0;
}
}
FastStringBuffer sb = new FastStringBuffer((int)length);
int i=0;
int pos=0;
while(i<start-1 && pos<str.length()) {
int c = (int)str.charAt(pos++);
if (c<55296 || c>56319) i++; // don't count high surrogates, i.e. D800 to DBFF
}
int j=0;
while (j<length && pos<str.length()) {
char c = str.charAt(pos++);
sb.append(c);
if ((int)c<55296 || (int)c>56319) j++; // don't count high surrogates, i.e. D800 to DBFF
}
StringValue result = new StringValue(sb);
if (sv.isKnownToContainNoSurrogates()) {
result.setContainsNoSurrogates();
}
return result;
}
}
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.