1 package net.sf.saxon.functions; 2 import net.sf.saxon.expr.Token; 3 import net.sf.saxon.expr.XPathContext; 4 import net.sf.saxon.om.Item; 5 import net.sf.saxon.trans.XPathException; 6 import net.sf.saxon.value.AtomicValue; 7 import net.sf.saxon.value.IntegerValue; 8 import net.sf.saxon.value.NumericValue; 9 import net.sf.saxon.value.StringValue; 10 11 14 15 public class Substring extends SystemFunction { 16 17 20 21 public Item evaluateItem(XPathContext context) throws XPathException { 22 23 AtomicValue sv = (AtomicValue)argument[0].evaluateItem(context); 24 if (sv==null) { 25 sv = StringValue.EMPTY_STRING; 26 } 27 CharSequence s = sv.getStringValueCS(); 28 29 AtomicValue a1 = (AtomicValue)argument[1].evaluateItem(context); 30 NumericValue a = (NumericValue)a1.getPrimitiveValue(); 31 32 if (argument.length==2) { 33 return StringValue.makeStringValue(substring(s, a)); 34 } else { 35 AtomicValue b2 = (AtomicValue)argument[2].evaluateItem(context); 36 NumericValue b = (NumericValue)b2.getPrimitiveValue(); 37 return StringValue.makeStringValue(substring(s, a, b, context)); 38 } 39 } 40 41 44 45 private static CharSequence substring(CharSequence s, NumericValue start) { 46 int slength = s.length(); 47 48 long lstart; 49 if (start instanceof IntegerValue) { 50 lstart = ((IntegerValue)start).longValue(); 51 } else { 52 NumericValue rstart = start.round(); 53 if (rstart.compareTo(IntegerValue.ZERO) <= 0) { 55 return s; 56 } else if (rstart.compareTo(new IntegerValue(slength)) > 0) { 57 return ""; 60 } else { 61 try { 62 lstart = rstart.longValue(); 63 } catch (XPathException err) { 64 throw new AssertionError ("string length out of permissible range"); 67 } 68 } 69 } 70 71 int pos=1; 72 int cpos=0; 73 while (cpos<slength) { 74 if (pos >= lstart) { 75 return s.subSequence(cpos, s.length()); 76 } 77 78 int ch = (int)s.charAt(cpos++); 79 if (ch<55296 || ch>56319) pos++; } 81 return ""; 82 } 83 84 87 88 private static CharSequence substring(CharSequence s, NumericValue start, NumericValue len, XPathContext context) { 89 int slength = s.length(); 90 91 long lstart; 92 if (start instanceof IntegerValue) { 93 lstart = ((IntegerValue)start).longValue(); 94 } else { 95 start = start.round(); 96 if (start.compareTo(IntegerValue.ZERO) <= 0) { 98 lstart = 0; 99 } else if (start.compareTo(new IntegerValue(slength)) > 0) { 100 return ""; 103 } else if (start.isNaN()) { 104 return ""; 105 } else { 106 try { 107 lstart = start.longValue(); 108 } catch (XPathException err) { 109 throw new AssertionError ("string length out of permissible range"); 112 } 113 } 114 } 115 116 NumericValue end; 117 try { 118 end = start.arithmetic(Token.PLUS, len.round(), context); 119 } catch (XPathException e) { 120 throw new AssertionError ("Unexpected arithmetic failure in substring"); 121 } 122 long lend; 123 if (end instanceof IntegerValue) { 124 lend = ((IntegerValue)end).longValue(); 125 } else { 126 if (end.compareTo(IntegerValue.ZERO) <= 0) { 128 return ""; 129 } else if (end.isNaN()) { 130 return ""; 131 } else if (end.compareTo(new IntegerValue(slength)) > 0) { 132 lend = slength+1; 135 } else { 136 try { 137 lend = end.ceiling().longValue(); 138 } catch (XPathException err) { 139 throw new AssertionError ("string length out of permissible range"); 142 } 143 } 144 } 145 146 int jstart=-1; 147 int jend=-1; 148 int pos=1; 149 int cpos=0; 150 while (cpos<slength) { 151 if (pos >= lstart) { 152 if (pos < lend) { 153 if (jstart<0) { 154 jstart = cpos; 155 } 156 } else { 157 jend = cpos; 158 break; 159 } 160 } 161 162 int ch = (int)s.charAt(cpos++); 163 if (ch<55296 || ch>56319) pos++; } 165 if (jstart<0 || jstart==jend) { 166 return ""; 167 } else if (jend<0) { 168 return s.subSequence(jstart, s.length()); 169 } else { 170 return s.subSequence(jstart, jend); 171 } 172 } 173 } 174 175 176 177 | Popular Tags |