Skip to content

Commit 941b40e

Browse files
committed
feat: add support for performing bounds checking
1 parent 2b7b89a commit 941b40e

File tree

9 files changed

+1030
-894
lines changed

9 files changed

+1030
-894
lines changed

lib/node_modules/@stdlib/slice/seq2slice/README.md

+36-27
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ var seq2slice = require( '@stdlib/slice/seq2slice' );
4242

4343
<a name="main"></a>
4444

45-
#### seq2slice( str, len )
45+
#### seq2slice( str, len, strict )
4646

4747
Converts a subsequence string to a [`Slice`][@stdlib/slice/ctor] object, where `len` specifies the maximum number of elements allowed in the slice.
4848

4949
```javascript
50-
var s = seq2slice( ':5', 10 );
50+
var s = seq2slice( ':5', 10, false );
5151
// returns <Slice>
5252

5353
var v = s.start;
@@ -77,7 +77,7 @@ where
7777
- The `end` keyword resolves to the provided length `len`. Thus, `:-1` is equivalent to `:end-1`, `:-2` is equivalent to `:end-2`, and so on and so forth. The exception is when performing a division operation when the `increment` is less than zero; in which case, `end` is equal to `len-1` in order to preserve user expectations when `end/d` equals a whole number and slicing from right-to-left. The result from a division operation is **rounded down** to the nearest integer value.
7878

7979
```javascript
80-
var s = seq2slice( 'end:2:-1', 10 );
80+
var s = seq2slice( 'end:2:-1', 10, false );
8181
// returns <Slice>
8282

8383
var v = s.start;
@@ -89,7 +89,7 @@ v = s.stop;
8989
v = s.step;
9090
// returns -1
9191

92-
s = seq2slice( 'end-2:2:-1', 10 );
92+
s = seq2slice( 'end-2:2:-1', 10, false );
9393
// returns <Slice>
9494

9595
v = s.start;
@@ -101,7 +101,7 @@ v = s.stop;
101101
v = s.step;
102102
// returns -1
103103

104-
s = seq2slice( 'end/2:2:-1', 10 );
104+
s = seq2slice( 'end/2:2:-1', 10, false );
105105
// returns <Slice>
106106

107107
v = s.start;
@@ -114,6 +114,15 @@ v = s.step;
114114
// returns -1
115115
```
116116

117+
When `strict` is `true`, the function throws an error if a subsequence string resolves to a slice exceeding index bounds.
118+
119+
<!-- run throws: true -->
120+
121+
```javascript
122+
var s = seq2slice( '10:20', 10, true );
123+
// throws <RangeError>
124+
```
125+
117126
</section>
118127

119128
<!-- /.usage -->
@@ -125,8 +134,8 @@ v = s.step;
125134
## Notes
126135

127136
- When `len` is zero, the function always returns a Slice object equivalent to `0:0:<increment>`.
128-
- The resolved slice start is clamped to the slice index bounds (i.e., `[0, len)`).
129-
- The resolved slice end is upper bound clamped to `len` (i.e., one greater than the last possible index).
137+
- When `strict` is `false`, the resolved slice start is clamped to the slice index bounds (i.e., `[0, len)`).
138+
- When `strict` is `false`, the resolved slice end is upper bound clamped to `len` (i.e., one greater than the last possible index).
130139
- When the increment is negative, the resolved slice end value may be `null`, thus indicating that a non-empty slice should include the first index.
131140
- The function ensures that results satisfy the convention that `:n` combined with `n:` is equivalent to `:` (i.e., selecting all elements). This convention matches Python slice semantics, but diverges from the MATLAB convention where `:n` and `n:` overlap by one element.
132141
- Unlike MATLAB, but like Python, the subsequence string is upper-bound exclusive. For example, in Python, `0:2` corresponds to the sequence `{0,1}`. In MATLAB, `1:3` corresponds to `{1,2,3}`.
@@ -146,83 +155,83 @@ v = s.step;
146155
```javascript
147156
var seq2slice = require( '@stdlib/slice/seq2slice' );
148157

149-
var s = seq2slice( ':', 5 );
158+
var s = seq2slice( ':', 5, false );
150159
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
151160
// => 'start: 0. stop: 5. step: 1.'
152161

153-
s = seq2slice( '2:', 5 );
162+
s = seq2slice( '2:', 5, false );
154163
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
155164
// => 'start: 2. stop: 5. step: 1.'
156165

157-
s = seq2slice( ':3', 5 );
166+
s = seq2slice( ':3', 5, false );
158167
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
159168
// => 'start: 0. stop: 3. step: 1.'
160169

161-
s = seq2slice( '2:4', 5 );
170+
s = seq2slice( '2:4', 5, false );
162171
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
163172
// => 'start: 2. stop: 4. step: 1.'
164173

165-
s = seq2slice( '1:4:2', 5 );
174+
s = seq2slice( '1:4:2', 5, false );
166175
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
167176
// => 'start: 1. stop: 4. step: 2.'
168177

169-
s = seq2slice( '2::2', 5 );
178+
s = seq2slice( '2::2', 5, false );
170179
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
171180
// => 'start: 2. stop: 5. step: 2.'
172181

173-
s = seq2slice( ':-2', 5 );
182+
s = seq2slice( ':-2', 5, false );
174183
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
175184
// => 'start: 0. stop: 3. step: 1.'
176185

177-
s = seq2slice( ':-1:2', 5 );
186+
s = seq2slice( ':-1:2', 5, false );
178187
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
179188
// => 'start: 0. stop: 4. step: 2.'
180189

181-
s = seq2slice( '-4:-1:2', 5 );
190+
s = seq2slice( '-4:-1:2', 5, false );
182191
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
183192
// => 'start: 1. stop: 4. step: 2.'
184193

185-
s = seq2slice( '-5:-1', 5 );
194+
s = seq2slice( '-5:-1', 5, false );
186195
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
187196
// => 'start: 0. stop: 4. step: 1.'
188197

189-
s = seq2slice( '::-1', 5 );
198+
s = seq2slice( '::-1', 5, false );
190199
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
191200
// => 'start: 4. stop: null. step: -1.'
192201

193-
s = seq2slice( ':0:-1', 5 );
202+
s = seq2slice( ':0:-1', 5, false );
194203
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
195204
// => 'start: 4. stop: 0. step: -1.'
196205

197-
s = seq2slice( '3:0:-1', 5 );
206+
s = seq2slice( '3:0:-1', 5, false );
198207
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
199208
// => 'start: 3. stop: 0. step: -1.'
200209

201-
s = seq2slice( '-1:-4:-2', 5 );
210+
s = seq2slice( '-1:-4:-2', 5, false );
202211
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
203212
// => 'start: 4. stop: 1. step: -2.'
204213

205-
s = seq2slice( ':end', 5 );
214+
s = seq2slice( ':end', 5, false );
206215
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
207216
// => 'start: 0. stop: 5. step: 1.'
208217

209-
s = seq2slice( ':end-1', 5 );
218+
s = seq2slice( ':end-1', 5, false );
210219
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
211220
// => 'start: 0. stop: 4. step: 1.'
212221

213-
s = seq2slice( ':end/2', 5 );
222+
s = seq2slice( ':end/2', 5, false );
214223
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
215224
// => 'start: 0. stop: 2. step: 1.'
216225

217-
s = seq2slice( 'end/2::-1', 5 );
226+
s = seq2slice( 'end/2::-1', 5, false );
218227
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
219228
// => 'start: 2. stop: null. step: -1.'
220229

221-
s = seq2slice( 'end-2::-1', 5 );
230+
s = seq2slice( 'end-2::-1', 5, false );
222231
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
223232
// => 'start: 3. stop: null. step: -1.'
224233

225-
s = seq2slice( 'end/2:', 5 );
234+
s = seq2slice( 'end/2:', 5, false );
226235
console.log( 'start: %s. stop: %s. step: %s.', s.start, s.stop, s.step );
227236
// => 'start: 2. stop: 5. step: 1.'
228237
```

lib/node_modules/@stdlib/slice/seq2slice/benchmark/benchmark.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ bench( pkg+'::defaults', function benchmark( b ) {
4040

4141
b.tic();
4242
for ( i = 0; i < b.iterations; i++ ) {
43-
out = seq2slice( values[ i%values.length ], 10 );
43+
out = seq2slice( values[ i%values.length ], 10, false );
4444
if ( typeof out !== 'object' ) {
4545
b.fail( 'should return an object' );
4646
}
@@ -70,7 +70,7 @@ bench( pkg+'::positive_integers', function benchmark( b ) {
7070

7171
b.tic();
7272
for ( i = 0; i < b.iterations; i++ ) {
73-
out = seq2slice( values[ i%values.length ], 10 );
73+
out = seq2slice( values[ i%values.length ], 10, false );
7474
if ( typeof out !== 'object' ) {
7575
b.fail( 'should return an object' );
7676
}
@@ -100,7 +100,7 @@ bench( pkg+'::negative_integers', function benchmark( b ) {
100100

101101
b.tic();
102102
for ( i = 0; i < b.iterations; i++ ) {
103-
out = seq2slice( values[ i%values.length ], 10 );
103+
out = seq2slice( values[ i%values.length ], 10, false );
104104
if ( typeof out !== 'object' ) {
105105
b.fail( 'should return an object' );
106106
}
@@ -126,7 +126,7 @@ bench( pkg+'::end,defaults', function benchmark( b ) {
126126

127127
b.tic();
128128
for ( i = 0; i < b.iterations; i++ ) {
129-
out = seq2slice( values[ i%values.length ], 10 );
129+
out = seq2slice( values[ i%values.length ], 10, false );
130130
if ( typeof out !== 'object' ) {
131131
b.fail( 'should return an object' );
132132
}
@@ -154,7 +154,7 @@ bench( pkg+'::end,subtraction', function benchmark( b ) {
154154

155155
b.tic();
156156
for ( i = 0; i < b.iterations; i++ ) {
157-
out = seq2slice( values[ i%values.length ], 10 );
157+
out = seq2slice( values[ i%values.length ], 10, false );
158158
if ( typeof out !== 'object' ) {
159159
b.fail( 'should return an object' );
160160
}
@@ -182,7 +182,7 @@ bench( pkg+'::end,division', function benchmark( b ) {
182182

183183
b.tic();
184184
for ( i = 0; i < b.iterations; i++ ) {
185-
out = seq2slice( values[ i%values.length ], 10 );
185+
out = seq2slice( values[ i%values.length ], 10, false );
186186
if ( typeof out !== 'object' ) {
187187
b.fail( 'should return an object' );
188188
}

lib/node_modules/@stdlib/slice/seq2slice/docs/repl.txt

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
{{alias}}( str, len )
2+
{{alias}}( str, len, strict )
33
Converts a subsequence string to a Slice object.
44

55
A subsequence string has the following format:
@@ -32,10 +32,11 @@
3232
to-left. The result from a division operation is rounded down to the nearest
3333
integer value.
3434

35-
The resolved slice start is clamped to the slice index bounds [0, len).
35+
In non-strict mode, the resolved slice start is clamped to the slice index
36+
bounds [0, len).
3637

37-
The resolved slice end is upper bound clamped to the provided length (i.e.,
38-
one greater than the last possible index).
38+
In non-strict mode, Tte resolved slice end is upper bound clamped to the
39+
provided length (i.e., one greater than the last possible index).
3940

4041
When the increment is negative, the resolved slice end value may be `null`,
4142
thus indicating that a non-empty slice should include the first index.
@@ -54,21 +55,24 @@
5455
len: integer
5556
Maximum number of elements allowed in the slice.
5657

58+
strict: boolean
59+
Boolean indicating whether to enforce strict bounds checking.
60+
5761
Returns
5862
-------
5963
s: Slice
6064
Slice instance.
6165

6266
Examples
6367
--------
64-
> var s = new {{alias}}( '1:10', 10 );
68+
> var s = new {{alias}}( '1:10', 10, false );
6569
> s.start
6670
1
6771
> s.stop
6872
10
6973
> s.step
7074
1
71-
> s = new {{alias}}( '2:5:2', 10 );
75+
> s = new {{alias}}( '2:5:2', 10, false );
7276
> s.start
7377
2
7478
> s.stop

lib/node_modules/@stdlib/slice/seq2slice/docs/types/index.d.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ import { Slice } from '@stdlib/types/slice';
4343
* - Both `start` and `stop` can use the `end` keyword (e.g., `end-2::2`, `end-3:`, etc), which supports basic subtraction and division.
4444
* - The `end` keyword resolves to the provided length `len`. Thus, `:-1` is equivalent to `:end-1`, `:-2` is equivalent to `:end-2`, and so on and so forth. The exception is when performing a division operation when the `increment` is less than zero; in which case, `end` is equal to `len-1` in order to preserve user expectations when `end/d` equals a whole number and slicing from right-to-left. The result from a division operation is **rounded down** to the nearest integer value.
4545
*
46-
* - The resolved slice start is clamped to the slice index bounds (i.e., `[0, len)`).
46+
* - When `strict` is `false`, the resolved slice start is clamped to the slice index bounds (i.e., `[0, len)`).
4747
*
48-
* - The resolved slice end is upper bound clamped to `len` (i.e., one greater than the last possible index).
48+
* - When `strict` is `false`, the resolved slice end is upper bound clamped to `len` (i.e., one greater than the last possible index).
4949
*
5050
* - When the increment is negative, the resolved slice end value may be `null`, thus indicating that a non-empty slice should include the first index.
5151
*
@@ -55,12 +55,15 @@ import { Slice } from '@stdlib/types/slice';
5555
*
5656
* @param str - input string
5757
* @param len - maximum number of elements allowed in the slice
58+
* @param strict - boolean indicating whether to enforce strict bounds checking
5859
* @throws first argument must be a valid subsequence string
5960
* @throws second argument must be a nonnegative integer
61+
* @throws a subsequence string must have a non-zero increment
62+
* @throws subsequence string resolves to a slice exceeding index bounds
6063
* @returns Slice object
6164
*
6265
* @example
63-
* var s = seq2slice( '0:10:1', 10 );
66+
* var s = seq2slice( '0:10:1', 10, false );
6467
* // returns <Slice>
6568
*
6669
* var v = s.start;
@@ -73,7 +76,7 @@ import { Slice } from '@stdlib/types/slice';
7376
* // returns 1
7477
*
7578
* @example
76-
* var s = seq2slice( '::-1', 10 );
79+
* var s = seq2slice( '::-1', 10, false );
7780
* // returns <Slice>
7881
*
7982
* var v = s.start;
@@ -86,7 +89,7 @@ import { Slice } from '@stdlib/types/slice';
8689
* // returns -1
8790
*
8891
* @example
89-
* var s = seq2slice( 'end::-1', 10 );
92+
* var s = seq2slice( 'end::-1', 10, false );
9093
* // returns <Slice>
9194
*
9295
* var v = s.start;
@@ -98,7 +101,7 @@ import { Slice } from '@stdlib/types/slice';
98101
* v = s.step;
99102
* // returns -1
100103
*/
101-
declare function seq2slice( str: string, len: number ): Slice<number, number | null, number>;
104+
declare function seq2slice( str: string, len: number, strict: boolean ): Slice<number, number | null, number>;
102105

103106

104107
// EXPORTS //

0 commit comments

Comments
 (0)