Skip to content

Commit 61295ba

Browse files
committed
refactor: support returning an out-of-bounds error code when resolving end index
1 parent a50b6b1 commit 61295ba

File tree

2 files changed

+52
-37
lines changed

2 files changed

+52
-37
lines changed

lib/node_modules/@stdlib/slice/base/seq2slice/lib/main.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ function seq2slice( str, len ) {
371371
}
372372
// Check for the use of the "end" keyword...
373373
else if ( RE_END.test( v ) ) {
374-
v = resolveEnd( v, len, parts[ 2 ] < 0 );
375-
if ( v === -1 ) {
374+
v = resolveEnd( v, len, parts[ 2 ] < 0, false );
375+
if ( v < 0 ) {
376376
return null;
377377
}
378378
if ( parts[ 2 ] < 0 && v >= len ) {
@@ -416,8 +416,8 @@ function seq2slice( str, len ) {
416416
}
417417
// Check for the use of the "end" keyword...
418418
else if ( RE_END.test( v ) ) {
419-
v = resolveEnd( v, len, parts[ 2 ] < 0 );
420-
if ( v === -1 ) {
419+
v = resolveEnd( v, len, parts[ 2 ] < 0, false );
420+
if ( v < 0 ) {
421421
return null;
422422
}
423423
parts[ 1 ] = v;

lib/node_modules/@stdlib/slice/base/seq2slice/lib/resolve_end.js

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -30,118 +30,130 @@ var RE_END_DIVIDE = require( './re_end_divide.js' );
3030
/**
3131
* Resolves an "end" index.
3232
*
33+
* ## Notes
34+
*
35+
* - The function returns `-1` if provided an invalid character sequence.
36+
* - The function returns `-2` if the resolved end index is out-of-bounds.
37+
*
3338
* @private
3439
* @param {string} v - character sequence containing the "end" keyword
3540
* @param {NonNegativeInteger} len - maximum number of elements allowed in the slice
3641
* @param {boolean} decrement - boolean indicating whether a subsequence has a negative decrement
42+
* @param {boolean} strict - boolean indicating whether to enforce strict bounds checking
3743
* @returns {NonNegativeInteger} end index (exclusive)
3844
*
3945
* @example
40-
* var idx = resolveEnd( 'end', 10, false );
46+
* var idx = resolveEnd( 'end', 10, false, false );
4147
* // returns 10
4248
*
43-
* idx = resolveEnd( 'end', 10, true );
49+
* idx = resolveEnd( 'end', 10, true, false );
4450
* // returns 10
4551
*
4652
* @example
47-
* var idx = resolveEnd( 'end-1', 10, false );
53+
* var idx = resolveEnd( 'end-1', 10, false, false );
4854
* // returns 9
4955
*
50-
* idx = resolveEnd( 'end-1', 10, true );
56+
* idx = resolveEnd( 'end-1', 10, true, false );
5157
* // returns 9
5258
*
5359
* @example
54-
* var idx = resolveEnd( 'end-2', 10, false );
60+
* var idx = resolveEnd( 'end-2', 10, false, false );
5561
* // returns 8
5662
*
57-
* idx = resolveEnd( 'end-2', 10, true );
63+
* idx = resolveEnd( 'end-2', 10, true, false );
5864
* // returns 8
5965
*
6066
* @example
61-
* var idx = resolveEnd( 'end/2', 10, false );
67+
* var idx = resolveEnd( 'end/2', 10, false, false );
6268
* // returns 5
6369
*
64-
* idx = resolveEnd( 'end/2', 10, true );
70+
* idx = resolveEnd( 'end/2', 10, true, false );
6571
* // returns 4
6672
*
6773
* @example
68-
* var idx = resolveEnd( 'end/2', 11, false );
74+
* var idx = resolveEnd( 'end/2', 11, false, false );
6975
* // returns 5
7076
*
71-
* idx = resolveEnd( 'end/2', 11, true );
77+
* idx = resolveEnd( 'end/2', 11, true, false );
7278
* // returns 5
7379
*
7480
* @example
75-
* var idx = resolveEnd( 'end/3', 10, false );
81+
* var idx = resolveEnd( 'end/3', 10, false, false );
7682
* // returns 3
7783
*
78-
* idx = resolveEnd( 'end/3', 10, true );
84+
* idx = resolveEnd( 'end/3', 10, true, false );
7985
* // returns 3
8086
*
8187
* @example
82-
* var idx = resolveEnd( 'end/3', 11, false );
88+
* var idx = resolveEnd( 'end/3', 11, false, false );
8389
* // returns 3
8490
*
85-
* idx = resolveEnd( 'end/3', 11, true );
91+
* idx = resolveEnd( 'end/3', 11, true, false );
8692
* // returns 3
8793
*
8894
* @example
89-
* var idx = resolveEnd( 'end/4', 10, false );
95+
* var idx = resolveEnd( 'end/4', 10, false, false );
9096
* // returns 2
9197
*
92-
* idx = resolveEnd( 'end/4', 10, true );
98+
* idx = resolveEnd( 'end/4', 10, true, false );
9399
* // returns 2
94100
*
95101
* @example
96-
* var idx = resolveEnd( 'end/4', 11, false );
102+
* var idx = resolveEnd( 'end/4', 11, false, false );
97103
* // returns 2
98104
*
99-
* idx = resolveEnd( 'end/4', 11, true );
105+
* idx = resolveEnd( 'end/4', 11, true, false );
100106
* // returns 2
101107
*
102108
* @example
103-
* var idx = resolveEnd( 'end/5', 10, false );
109+
* var idx = resolveEnd( 'end/5', 10, false, false );
104110
* // returns 2
105111
*
106-
* idx = resolveEnd( 'end/5', 10, true );
112+
* idx = resolveEnd( 'end/5', 10, true, false );
107113
* // returns 1
108114
*
109115
* @example
110-
* var idx = resolveEnd( 'end/5', 11, false );
116+
* var idx = resolveEnd( 'end/5', 11, false, false );
111117
* // returns 2
112118
*
113-
* idx = resolveEnd( 'end/5', 11, true );
119+
* idx = resolveEnd( 'end/5', 11, true, false );
114120
* // returns 2
115121
*
116122
* @example
117-
* var idx = resolveEnd( 'end-20', 10, false );
123+
* var idx = resolveEnd( 'end-20', 10, false, false );
118124
* // returns 0
119125
*
120-
* idx = resolveEnd( 'end-20', 10, true );
126+
* idx = resolveEnd( 'end-20', 10, true, false );
121127
* // returns 0
122128
*
129+
* idx = resolveEnd( 'end-20', 10, true, true );
130+
* // returns -2
131+
*
123132
* @example
124-
* var idx = resolveEnd( 'end*2', 10, false );
133+
* var idx = resolveEnd( 'end*2', 10, false, false );
125134
* // returns -1
126135
*
127-
* idx = resolveEnd( 'end*2', 10, true );
136+
* idx = resolveEnd( 'end*2', 10, true, false );
128137
* // returns -1
129138
*
130139
* @example
131-
* var idx = resolveEnd( 'end+1', 10, false );
140+
* var idx = resolveEnd( 'end+1', 10, false, false );
132141
* // returns -1
133142
*
134-
* idx = resolveEnd( 'end+1', 10, true );
143+
* idx = resolveEnd( 'end+1', 10, true, false );
135144
* // returns -1
136145
*
137146
* @example
138-
* var idx = resolveEnd( 'end/0.5', 10, false );
147+
* var idx = resolveEnd( 'end/0.5', 10, false, false );
139148
* // returns -1
140149
*
141-
* idx = resolveEnd( 'end/0.5', 10, true );
150+
* idx = resolveEnd( 'end/0.5', 10, true, false );
142151
* // returns -1
152+
*
153+
* idx = resolveEnd( 'end/0.5', 10, true, true );
154+
* // returns -2
143155
*/
144-
function resolveEnd( v, len, decrement ) {
156+
function resolveEnd( v, len, decrement, strict ) {
145157
var tmp;
146158

147159
// Check for the simple case where "end" refers to the last index (exclusive)...
@@ -155,7 +167,10 @@ function resolveEnd( v, len, decrement ) {
155167

156168
// If the computed index exceeds the index bounds, clamp to the first index...
157169
if ( v < 0 ) {
158-
v = 0; // TODO: if we ever support throwing an exception for out-of-bounds slices, we'd need to generate an exception here.
170+
if ( strict ) {
171+
return -2; // return out-of-bounds error code
172+
}
173+
v = 0;
159174
}
160175
return v;
161176
}
@@ -164,7 +179,7 @@ function resolveEnd( v, len, decrement ) {
164179
if ( tmp ) {
165180
v = parseFloat( tmp[ 1 ] );
166181
if ( v < 1.0 ) {
167-
return -1;
182+
return ( strict ) ? -2 : -1; // if `end/x > end`, then need to return out-of-bounds error code
168183
}
169184
// Handle division differently for increasing and decreasing increments in order to preserve the `:n + n: = :` identity and to satisfy user expectation that symmetry be maintained. The main issue being that, e.g., given a length 10 subsequence, `end/2` will yield `5`. Hence, `:end/2 + end/2: = :5 + :5 = :` (i.e., the first five elements (0,1,2,3,4) and the second five elements (5,6,7,8,9)); however, if increasing and decreasing are treated the same, `:end/2:-1 + end/2::-1 = :5:-1 + 5::-1 = :`, but the elements are not the same (i.e., the first elements (9,8,7,6) and the second elements (5,4,3,2,1)), due to the non-inclusive aspect of `j` in `i:j:k`. The slight adjustment (`len-1`) yields `:4:-1 + 4::-1 = :` and the slices (9,8,7,6,5) and (4,3,2,1,0), which better matches user expectation. For a length 11 subsequence, we get (0,1,2,3,4) and (5,6,7,8,9,10) for an increasing increment and (10,9,8,7,6) and (5,4,3,2,1,0), which seems fine given asymmetry in both cases.
170185
if ( decrement && len > 0 && v !== 1.0 ) { // note: avoid violating `end/1 = end` identity

0 commit comments

Comments
 (0)