Return a sub array from an array given a range of indices. Valid indices ragne is [-arrayLen, arrayLen). If range start value is bigger then range end value an empty list will be returnd. If indices are still integers but not in the valid range, only values within the valid range will be returned. If one of the indices is null, null will be returnd. "RETURN [1, 2, 3][0..1]" will
| 283 | If one of the indices is null, null will be returnd. |
| 284 | "RETURN [1, 2, 3][0..1]" will yield [1, 2] */ |
| 285 | SIValue AR_SLICE(SIValue *argv, int argc, void *private_data) { |
| 286 | ASSERT(argc == 3); |
| 287 | if(SI_TYPE(argv[0]) == T_NULL || |
| 288 | SI_TYPE(argv[1]) == T_NULL || |
| 289 | SI_TYPE(argv[2]) == T_NULL) { |
| 290 | return SI_NullVal(); |
| 291 | } |
| 292 | ASSERT(SI_TYPE(argv[0]) == T_ARRAY && SI_TYPE(argv[1]) == T_INT64 && SI_TYPE(argv[2]) == T_INT64); |
| 293 | SIValue array = argv[0]; |
| 294 | |
| 295 | // get array length |
| 296 | uint32_t arrayLen = SIArray_Length(array); |
| 297 | |
| 298 | // get start and end index |
| 299 | SIValue start = argv[1]; |
| 300 | int32_t startIndex = (int32_t)start.longval; |
| 301 | SIValue end = argv[2]; |
| 302 | int32_t endIndex = (int32_t)end.longval; |
| 303 | |
| 304 | // if negative index, calculate offset from end |
| 305 | if(startIndex < 0) startIndex = arrayLen - abs(startIndex); |
| 306 | // if offset from the end is out of bound, start at 0 |
| 307 | if(startIndex < 0) startIndex = 0; |
| 308 | |
| 309 | // if negative index, calculate offset from end |
| 310 | if(endIndex < 0) endIndex = arrayLen - abs(endIndex); |
| 311 | // if index out of bound, end at arrayLen |
| 312 | if(((int32_t)arrayLen) < endIndex) endIndex = arrayLen; |
| 313 | // cant go in reverse |
| 314 | if(endIndex <= startIndex) { |
| 315 | return SI_EmptyArray(); |
| 316 | } |
| 317 | |
| 318 | SIValue subArray = SI_Array(endIndex - startIndex); |
| 319 | for(uint i = startIndex; i < endIndex; i++) { |
| 320 | SIArray_Append(&subArray, SIArray_Get(array, i)); |
| 321 | } |
| 322 | return subArray; |
| 323 | } |
| 324 | |
| 325 | /* Create a new list of integers in the range of [start, end]. If a step was given |
| 326 | the step between two consecutive list members will be this step. |
nothing calls this directly
no test coverage detected