Project

Profile

Help

Revision a4077369

Added by Michael Kay about 1 year ago

Fix bug #4535

View differences:

latest10/hej/net/sf/saxon/ma/arrays/AbstractArrayItem.java
148 148
     * Invoke the array in its role as a function
149 149
     *
150 150
     * @param context the XPath dynamic evaluation context
151
     * @param args    the actual arguments to be supplied (a single integer)
151
     * @param args    the actual arguments to be supplied (a single integer, one-based)
152 152
     * @return the result of invoking the function
153
     * @throws XPathException if a dynamic error occurs within the function
153
     * @throws XPathException if the index is out of bounds
154 154
     */
155 155

  
156 156
    public GroundedValue call(XPathContext context, Sequence[] args) throws XPathException {
157 157
        IntegerValue subscript = (IntegerValue) args[0].head();
158
        return get(ArrayFunctionSet.checkSubscript(subscript) - 1);
158
        return get(ArrayFunctionSet.checkSubscript(subscript, arrayLength()) - 1);
159 159
    }
160 160

  
161 161
    /**
latest10/hej/net/sf/saxon/ma/arrays/ArrayFunctionSet.java
170 170
     * as a Java int
171 171
     *
172 172
     * @param subscript the proposed subscript
173
     * @param limit the upper limit allowed (usually the size of the array, sometimes arraysize + 1)
173 174
     * @return the proposed subscript as an int, if it is in range
174 175
     * @throws XPathException if the subscript is 0, negative, or outside the permitted range
175 176
     */
176
    public static int checkSubscript(IntegerValue subscript) throws XPathException {
177
    public static int checkSubscript(IntegerValue subscript, int limit) throws XPathException {
177 178
        int index = subscript.asSubscript();
178 179
        if (index <= 0) {
179 180
            throw new XPathException("Array subscript " + subscript.getStringValue() + " is out of range", "FOAY0001");
180 181
        }
182
        if (index > limit) {
183
            throw new XPathException("Array subscript " + subscript.getStringValue() +
184
                                             " exceeds limit (" + limit + ")", "FOAY0001");
185
        }
181 186
        return index;
182 187
    }
183 188

  
......
190 195
        public ArrayItem call(XPathContext context, Sequence[] arguments) throws XPathException {
191 196
            ArrayItem array = (ArrayItem) arguments[0].head();
192 197
            assert array != null;
193
            return append(array, (Sequence)arguments[1]);
198
            return append(array, arguments[1]);
194 199
        }
195 200

  
196 201
        public static ArrayItem append(ArrayItem array, Sequence member) throws XPathException {
......
242 247

  
243 248
        public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
244 249
            List<Item> out = new ArrayList<>();
245
            flatten((Sequence)arguments[0], out);
250
            flatten(arguments[0], out);
246 251
            return SequenceExtent.makeSequenceExtent(out);
247 252
        }
248 253
    }
......
257 262
            ArrayItem array = (ArrayItem) arguments[0].head();
258 263
            assert array != null;
259 264
            int arraySize = array.arrayLength();
260
            Sequence zero = ((Sequence)arguments[1]).head();
265
            Sequence zero = arguments[1].head();
261 266
            Function fn = (Function) arguments[2].head();
262 267
            int i;
263 268
            for (i=0; i < arraySize; i++) {
......
335 340
        public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
336 341
            ArrayItem array = (ArrayItem) arguments[0].head();
337 342
            IntegerValue index = (IntegerValue) arguments[1].head();
338
            return array.get(checkSubscript(index) - 1);
343
            return array.get(checkSubscript(index, array.arrayLength()) - 1);
339 344
        }
340 345

  
341 346
    }
......
365 370
        public ArrayItem call(XPathContext context, Sequence[] arguments) throws XPathException {
366 371
            ArrayItem array = (ArrayItem) arguments[0].head();
367 372
            assert array != null;
368
            int index = checkSubscript((IntegerValue) arguments[1].head()) - 1;
373
            int index = checkSubscript((IntegerValue) arguments[1].head(), array.arrayLength() + 1) - 1;
369 374
            if (index < 0 || index > array.arrayLength()){
370 375
                throw new XPathException("Specified position is not in range","FOAY0001");
371 376
            }
372
            Sequence newMember = (Sequence)arguments[2];
377
            Sequence newMember = arguments[2];
373 378
            return array.insert(index, newMember.materialize());
374 379
        }
375 380

  
......
401 406
        @Override
402 407
        public ArrayItem call(XPathContext context, Sequence[] arguments) throws XPathException {
403 408
            ArrayItem array = (ArrayItem) arguments[0].head();
404
            int index = checkSubscript((IntegerValue) arguments[1].head()) - 1;
405
            GroundedValue newVal = ((Sequence)arguments[2]).materialize();
409
            int index = checkSubscript((IntegerValue) arguments[1].head(), array.arrayLength()) - 1;
410
            GroundedValue newVal = arguments[2].materialize();
406 411
            return array.put(index, newVal);
407 412
        }
408 413

  
......
417 422
        public ArrayItem call(XPathContext context, Sequence[] arguments) throws XPathException {
418 423
            ArrayItem array = (ArrayItem) arguments[0].head();
419 424
            if (arguments[1] instanceof IntegerValue) {
420
                int index = checkSubscript((IntegerValue) arguments[1]) - 1;
421
                if (index >= array.arrayLength()) {
422
                    throw new XPathException("Position " + index + " is not in range", "FOAY0001");
423
                }
425
                int index = checkSubscript((IntegerValue) arguments[1], array.arrayLength()) - 1;
424 426
                return array.remove(index);
425 427
            }
426 428
            IntSet positions = new IntHashSet();
427 429
            SequenceIterator arg1 = arguments[1].iterate();
428 430
            arg1.forEachOrFail(pos -> {
429
                int index = checkSubscript((IntegerValue)pos) - 1;
430
                if (index >= array.arrayLength()) {
431
                    throw new XPathException("Position " + index + " is not in range", "FOAY0001");
432
                }
431
                int index = checkSubscript((IntegerValue)pos, array.arrayLength()) - 1;
433 432
                positions.add(index);
434 433
            });
435 434
            return array.removeSeveral(positions);
......
473 472
     */
474 473
    public static class ArraySubarray extends SystemFunction {
475 474

  
476

  
477 475
        public ArrayItem call(XPathContext context, Sequence[] arguments) throws XPathException {
478 476
            ArrayItem array = (ArrayItem) arguments[0].head();
479 477
            assert array != null;
480
            int start = checkSubscript((IntegerValue) arguments[1].head());
478
            int start = checkSubscript((IntegerValue) arguments[1].head(), array.arrayLength()+1);
481 479
            int length;
482 480
            if (arguments.length == 3) {
483 481
                IntegerValue len = (IntegerValue) arguments[2].head();
......
485 483
                if (signum < 0) {
486 484
                    throw new XPathException("Specified length of subarray is less than zero", "FOAY0002");
487 485
                }
488
                length = signum == 0 ? 0 : checkSubscript(len);
486
                length = signum == 0 ? 0 : checkSubscript(len, array.arrayLength());
489 487
            }
490 488
            else {
491 489
                length = array.arrayLength() - start + 1;
latest10/hej/net/sf/saxon/ma/arrays/ArrayItem.java
11 11
import net.sf.saxon.om.Function;
12 12
import net.sf.saxon.om.Genre;
13 13
import net.sf.saxon.om.GroundedValue;
14
import net.sf.saxon.trans.XPathException;
15 14
import net.sf.saxon.type.TypeHierarchy;
16 15
import net.sf.saxon.value.SequenceType;
17 16
import net.sf.saxon.z.IntSet;
......
29 28
     *
30 29
     * @param index the position of the member to retrieve (zero-based)
31 30
     * @return the value at the given position.
32
     * @throws XPathException if the index is out of range
31
     * @throws IndexOutOfBoundsException if the index is out of range
33 32
     */
34 33

  
35
    GroundedValue get(int index) throws XPathException;
34
    GroundedValue get(int index);
36 35

  
37 36
    /**
38 37
     * Replace a member of the array
......
40 39
     * @param index the position of the member to replace (zero-based)
41 40
     * @param newValue the replacement value
42 41
     * @return the value at the given position.
43
     * @throws XPathException if the index is out of range
42
     * @throws IndexOutOfBoundsException if the index is out of range
44 43
     */
45 44

  
46
    ArrayItem put(int index, GroundedValue newValue) throws XPathException;
45
    ArrayItem put(int index, GroundedValue newValue);
47 46

  
48 47
    /**
49 48
     * Get the number of members in the array
......
96 95
     * @param positions the positions of the members to be removed (zero-based).
97 96
     *                  A value that is out of range is ignored.
98 97
     * @return a new array in which the requested member has been removed
98
     * @throws IndexOutOfBoundsException if any of the positions is out of range
99 99
     */
100 100

  
101 101
    ArrayItem removeSeveral(IntSet positions);
latest10/hej/net/sf/saxon/ma/arrays/ImmutableArrayItem.java
9 9

  
10 10
import net.sf.saxon.ma.parray.ImmList;
11 11
import net.sf.saxon.om.GroundedValue;
12
import net.sf.saxon.trans.XPathException;
13 12
import net.sf.saxon.z.IntIterator;
14 13
import net.sf.saxon.z.IntSet;
15 14

  
......
37 36
     *
38 37
     * @param index the position of the member to retrieve (zero-based)
39 38
     * @return the value at the given position.
40
     * @throws XPathException if the index is out of range
39
     * @throws IndexOutOfBoundsException if the index is out of range
41 40
     */
42 41
    @Override
43
    public GroundedValue get(int index) throws XPathException {
44
        try {
45
            return vector.get(index);
46
        } catch (IndexOutOfBoundsException e) {
47
            throw new XPathException(e.getMessage(), "FOAY0001");
48
        }
42
    public GroundedValue get(int index) {
43
        return vector.get(index);
49 44
    }
50 45

  
51 46
    /**
......
54 49
     * @param index    the position of the member to replace (zero-based)
55 50
     * @param newValue the replacement value
56 51
     * @return the value at the given position.
57
     * @throws XPathException if the index is out of range
52
     * @throws IndexOutOfBoundsException if the index is out of range
58 53
     */
59 54
    @Override
60
    public ArrayItem put(int index, GroundedValue newValue) throws XPathException {
61
        try {
62
            ImmList<GroundedValue> v2 = vector.replace(index, newValue);
63
            return v2 == vector ? this : new ImmutableArrayItem(v2);
64
        } catch (IndexOutOfBoundsException e) {
65
            throw new XPathException(e.getMessage(), "FOAY0001");
66
        }
55
    public ArrayItem put(int index, GroundedValue newValue)  {
56
        ImmList<GroundedValue> v2 = vector.replace(index, newValue);
57
        return v2 == vector ? this : new ImmutableArrayItem(v2);
67 58
    }
68 59

  
69 60
    /**
latest10/hej/net/sf/saxon/ma/arrays/SimpleArrayItem.java
8 8
package net.sf.saxon.ma.arrays;
9 9

  
10 10
import net.sf.saxon.expr.OperandRole;
11
import net.sf.saxon.om.*;
11
import net.sf.saxon.om.GroundedValue;
12
import net.sf.saxon.om.Sequence;
13
import net.sf.saxon.om.SequenceIterator;
12 14
import net.sf.saxon.query.AnnotationList;
13 15
import net.sf.saxon.trans.Err;
14 16
import net.sf.saxon.trans.XPathException;
15 17
import net.sf.saxon.tree.util.FastStringBuffer;
16 18
import net.sf.saxon.value.ExternalObject;
17
import net.sf.saxon.value.SequenceType;
18 19
import net.sf.saxon.z.IntSet;
19 20

  
20 21
import java.util.ArrayList;
......
32 33
    public static final SimpleArrayItem EMPTY_ARRAY =
33 34
            new SimpleArrayItem(new ArrayList<>());
34 35

  
35
    private List<GroundedValue> members;
36
    private final List<GroundedValue> members;
36 37
    private boolean knownToBeGrounded = false;
37
    private SequenceType memberType = null; // computed on demand
38 38

  
39 39
    /**
40 40
     * Construct an array whose members are arbitrary sequences
......
129 129
     *
130 130
     * @param index the position of the member to retrieve (zero-based)
131 131
     * @return the value at the given position.
132
     * @throws XPathException if the index is out of range
132
     * @throws IndexOutOfBoundsException if the index is out of range
133 133
     */
134 134

  
135 135

  
136
    public GroundedValue get(int index) throws XPathException {
137
        if (index < 0 || index >= members.size()) {
138
            throw new XPathException("Array index (" + (index+1) + ") out of range (1 to " + members.size() + ")", "FOAY0001");
139
        }
136
    public GroundedValue get(int index) {
140 137
        return members.get(index);
141 138
    }
142 139

  
......
146 143
     * @param index    the position of the member to replace (zero-based)
147 144
     * @param newValue the replacement value
148 145
     * @return the value at the given position.
149
     * @throws XPathException if the index is out of range
146
     * @throws IndexOutOfBoundsException if the index is out of range
150 147
     */
151 148
    @Override
152
    public ArrayItem put(int index, GroundedValue newValue) throws XPathException {
149
    public ArrayItem put(int index, GroundedValue newValue) {
153 150
        ImmutableArrayItem a2 = new ImmutableArrayItem(this);
154 151
        return a2.put(index, newValue);
155 152
    }
......
195 192
    public ArrayItem removeSeveral(IntSet positions) {
196 193
        ImmutableArrayItem a2 = new ImmutableArrayItem(this);
197 194
        return a2.removeSeveral(positions);
198
//        List<Sequence> newList = new ArrayList<Sequence>(members.size() - 1);
199
//        for (int i = 0; i < members.size(); i++) {
200
//            if (!positions.contains(i)) {
201
//                newList.add(members.get(i));
202
//            }
203
//        }
204
//        SimpleArrayItem result = new SimpleArrayItem(newList);
205
//        if (knownToBeGrounded) {
206
//            result.knownToBeGrounded = true;
207
//        }
208
//        result.memberType = memberType;
209
//        return result;
210 195
    }
211 196

  
212 197
    /**
......
220 205
    public ArrayItem remove(int pos) {
221 206
        ImmutableArrayItem a2 = new ImmutableArrayItem(this);
222 207
        return a2.remove(pos);
223
//        List<Sequence> newList = new ArrayList<Sequence>(members.size() - 1);
224
//        newList.addAll(members.subList(0, pos));
225
//        newList.addAll(members.subList(pos + 1, members.size()));
226
//        SimpleArrayItem result = new SimpleArrayItem(newList);
227
//        if (knownToBeGrounded) {
228
//            result.knownToBeGrounded = true;
229
//        }
230
//        result.memberType = memberType;
231
//        return result;
232 208
    }
233 209

  
234 210
    /**
......
269 245
    public ArrayItem concat(ArrayItem other) {
270 246
        ImmutableArrayItem a2 = new ImmutableArrayItem(this);
271 247
        return a2.concat(other);
272
//        List<Sequence> newList = new ArrayList<Sequence>(members.size() + other.arrayLength());
273
//        newList.addAll(members);
274
//        for (Sequence s : other) {
275
//            newList.add(s);
276
//        }
277
//        SimpleArrayItem result = new SimpleArrayItem(newList);
278
//        if (other instanceof SimpleArrayItem) {
279
//            if (knownToBeGrounded && ((SimpleArrayItem) other).knownToBeGrounded) {
280
//                result.knownToBeGrounded = true;
281
//            }
282
//            if (memberType != null && memberType.equals(((SimpleArrayItem) other).memberType)) {
283
//                result.memberType = memberType;
284
//            }
285
//        }
286
//        return result;
287 248
    }
288 249

  
289 250

  
latest10/hej/net/sf/saxon/s9api/XdmArray.java
98 98
     */
99 99

  
100 100
    public XdmValue get(int n) throws IndexOutOfBoundsException {
101
        try {
102
            Sequence member = getUnderlyingValue().get(n);
103
            return XdmValue.wrap(member);
104
        } catch (XPathException e) {
105
            throw new IndexOutOfBoundsException();
106
        }
101
        Sequence member = getUnderlyingValue().get(n);
102
        return XdmValue.wrap(member);
107 103
    }
108 104

  
109 105
    /**
......
119 115
     */
120 116

  
121 117
    public XdmArray put(int n, XdmValue value) throws IndexOutOfBoundsException {
122
        try {
123
            GroundedValue member = value.getUnderlyingValue();
124
            return (XdmArray)XdmValue.wrap(getUnderlyingValue().put(n, member));
125
        } catch (XPathException e) {
126
            throw new IndexOutOfBoundsException();
127
        }
118
        GroundedValue member = value.getUnderlyingValue();
119
        return (XdmArray)XdmValue.wrap(getUnderlyingValue().put(n, member));
128 120
    }
129 121

  
130 122
    /**

Also available in: Unified diff