Skip to content

Commit a460795

Browse files
committed
Add base utility to return a Unicode code point from a string
1 parent e76e6ab commit a460795

File tree

10 files changed

+676
-0
lines changed

10 files changed

+676
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2022 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# codePointAt
22+
23+
> Return a Unicode [code point][code-point] from a string at a specified position.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
</section>
30+
31+
<!-- /.intro -->
32+
33+
<!-- Package usage documentation. -->
34+
35+
<section class="usage">
36+
37+
## Usage
38+
39+
```javascript
40+
var codePointAt = require( '@stdlib/string/base/code-point-at' );
41+
```
42+
43+
#### codePointAt( string, position, backward )
44+
45+
Returns a Unicode [code point][code-point] from a string at a specified position.
46+
47+
```javascript
48+
var out = codePointAt( 'last man standing', 4, false );
49+
// returns 32
50+
```
51+
52+
The function supports a `backward` argument for performing backward iteration for low surrogates.
53+
54+
```javascript
55+
var out = codePointAt( '🌷', 1, true );
56+
// returns 127799
57+
```
58+
59+
The function supports providing a negative `position`.
60+
61+
```javascript
62+
var out = codePointAt( 'last man standing', -13, false );
63+
// returns 32
64+
```
65+
66+
</section>
67+
68+
<!-- /.usage -->
69+
70+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
71+
72+
<section class="notes">
73+
74+
## Notes
75+
76+
This function differs from [`String.prototype.codePointAt`][mdn-string-codepointat] in the following ways:
77+
78+
- The function supports providing a negative `position`. If provided a negative `position`, the function determines the string position relative to the end of the string.
79+
- The function supports a `backward` argument for performing backward iteration for low surrogates. [`String.prototype.codePointAt`][mdn-string-codepointat] simply returns the low surrogate value if no [UTF-16][utf-16] surrogate pair begins at the specified position. If invoked with `backward` set to `true`, this function will return the code point after aggregating with the preceding high surrogate, if the specified position does not mark the start of a surrogate pair.
80+
81+
</section>
82+
83+
<!-- /.notes -->
84+
85+
<!-- Package usage examples. -->
86+
87+
<section class="examples">
88+
89+
## Examples
90+
91+
<!-- eslint no-undef: "error" -->
92+
93+
```javascript
94+
var codePointAt = require( '@stdlib/string/base/code-point-at' );
95+
96+
var v = codePointAt( 'last man standing', 4, false );
97+
// returns 32
98+
99+
v = codePointAt( 'presidential election', 8, true );
100+
// returns 116
101+
102+
v = codePointAt( 'अनुच्छेद', 2, false );
103+
// returns 2369
104+
105+
v = codePointAt( '🌷', 1, true );
106+
// returns 127799
107+
```
108+
109+
</section>
110+
111+
<!-- /.examples -->
112+
113+
<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
114+
115+
<section class="references">
116+
117+
</section>
118+
119+
<!-- /.references -->
120+
121+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
122+
123+
<section class="related">
124+
125+
</section>
126+
127+
<!-- /.related -->
128+
129+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
130+
131+
<section class="links">
132+
133+
[code-point]: https://en.wikipedia.org/wiki/Code_point
134+
135+
[mdn-string-codepointat]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt
136+
137+
[utf-16]: https://en.wikipedia.org/wiki/UTF-16
138+
139+
</section>
140+
141+
<!-- /.links -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2022 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var discreteUniform = require( '@stdlib/random/base/discrete-uniform' );
25+
var fromCodePoint = require( '@stdlib/string/from-code-point' );
26+
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
27+
var UNICODE_MAX = require( '@stdlib/constants/unicode/max' );
28+
var pkg = require( './../package.json' ).name;
29+
var codePointAt = require( './../lib' );
30+
31+
32+
// VARIABLES //
33+
34+
var opts = {
35+
'skip': ( typeof String.prototype.codePointAt !== 'function' )
36+
};
37+
var VALUES = [
38+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
39+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
40+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
41+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
42+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
43+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
44+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
45+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) ),
46+
fromCodePoint( discreteUniform( 0, UNICODE_MAX ) )
47+
];
48+
49+
50+
// MAIN //
51+
52+
bench( pkg, function benchmark( b ) {
53+
var out;
54+
var i;
55+
56+
b.tic();
57+
for ( i = 0; i < b.iterations; i++ ) {
58+
out = codePointAt( VALUES[ i%VALUES.length ], 0, false );
59+
if ( typeof out !== 'number' ) {
60+
b.fail( 'should return a number' );
61+
}
62+
}
63+
b.toc();
64+
if ( !isNonNegativeInteger( out ) ) {
65+
b.fail( 'should return a nonnegative integer' );
66+
}
67+
b.pass( 'benchmark finished' );
68+
b.end();
69+
});
70+
71+
bench( pkg+'::built-in', opts, function benchmark( b ) {
72+
var out;
73+
var i;
74+
75+
b.tic();
76+
for ( i = 0; i < b.iterations; i++ ) {
77+
out = VALUES[ i%VALUES.length ].codePointAt( 0 );
78+
if ( typeof out !== 'number' ) {
79+
b.fail( 'should return a number' );
80+
}
81+
}
82+
b.toc();
83+
if ( !isNonNegativeInteger( out ) ) {
84+
b.fail( 'should return a nonnegative integer' );
85+
}
86+
b.pass( 'benchmark finished' );
87+
b.end();
88+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
{{alias}}( str, idx, backward )
3+
Returns a Unicode code point from a string at a specified position.
4+
5+
Parameters
6+
----------
7+
str: string
8+
Input string.
9+
10+
idx: integer
11+
Position. If less than `0`, the string position is determined relative
12+
to the end of the input string.
13+
14+
backward: boolean
15+
Backward iteration for low surrogates.
16+
17+
Returns
18+
-------
19+
out: integer
20+
Unicode code point.
21+
22+
Examples
23+
--------
24+
> var out = {{alias}}( 'last man standing', 4, false )
25+
32
26+
> out = {{alias}}( 'presidential election', 8, true )
27+
116
28+
> out = {{alias}}( 'अनुच्छेद', 2, false )
29+
2369
30+
> out = {{alias}}( '🌷', 1, true )
31+
127799
32+
33+
See Also
34+
--------
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2022 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
// TypeScript Version: 2.0
20+
21+
/**
22+
* Returns a Unicode code point from a string at specified position.
23+
*
24+
* @param str - input string
25+
* @param idx - position
26+
* @param backward - backward iteration for low surrogates
27+
* @returns code point
28+
*
29+
* @example
30+
* var str = codePointAt( 'अनुच्छेद', 2, false );
31+
* // returns 2369
32+
*
33+
* str = codePointAt( '🌷', 1, true );
34+
* // returns 127799
35+
*/
36+
declare function codePointAt( str: string, idx: number, backward: boolean ): number; // tslint:disable-line:max-line-length
37+
38+
39+
// EXPORTS //
40+
41+
export = codePointAt;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2022 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import codePointAt = require( './index' );
20+
21+
22+
// TESTS //
23+
24+
// The function returns a number...
25+
{
26+
codePointAt( 'last man standing', 4, false ); // $ExpectType number
27+
codePointAt( 'presidential election', 8, true ); // $ExpectType number
28+
codePointAt( 'अनुच्छेद', 2, false ); // $ExpectType number
29+
codePointAt( '🌷', 1, true ); // $ExpectType number
30+
}
31+
32+
// The compiler throws an error if the function is provided incorrect arguments...
33+
{
34+
codePointAt( false, 3, false ); // $ExpectError
35+
codePointAt( {}, 3, false ); // $ExpectError
36+
codePointAt( ( x: number ): number => x, 3, false ); // $ExpectError
37+
38+
codePointAt( 'string', true, false ); // $ExpectError
39+
codePointAt( 'string', false, false ); // $ExpectError
40+
codePointAt( 'string', {}, false ); // $ExpectError
41+
codePointAt( 'string', ( x: number ): number => x, false ); // $ExpectError
42+
43+
codePointAt( 'string', 2, {} ); // $ExpectError
44+
codePointAt( 'string', 2, ( x: number ): number => x ); // $ExpectError
45+
}
46+
47+
// The compiler throws an error if the function is provided insufficient arguments...
48+
{
49+
codePointAt(); // $ExpectError
50+
codePointAt( 'abc' ); // $ExpectError
51+
codePointAt( 'abc', 0 ); // $ExpectError
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2022 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
var codePointAt = require( './../lib' );
22+
23+
console.log( codePointAt( 'last man standing', 4, false ) );
24+
// => 32
25+
26+
console.log( codePointAt( 'presidential election', 8, true ) );
27+
// => 116
28+
29+
console.log( codePointAt( 'अनुच्छेद', 2, false ) );
30+
// => 2369
31+
32+
console.log( codePointAt( '🌷', 1, true ) );
33+
// => 127799

0 commit comments

Comments
 (0)