From e75c13addfd43b1d3486b09d8e2e572b3922a7c9 Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Sat, 20 Apr 2024 06:28:21 +0000 Subject: [PATCH] Auto-generated commit --- CONTRIBUTORS | 4 + base/for-each-code-point-right/README.md | 146 ++++++++++++++++ .../benchmark/benchmark.js | 61 +++++++ base/for-each-code-point-right/docs/repl.txt | 38 ++++ .../docs/types/index.d.ts | 93 ++++++++++ .../docs/types/test.ts | 86 +++++++++ .../examples/index.js | 30 ++++ base/for-each-code-point-right/lib/index.js | 43 +++++ base/for-each-code-point-right/lib/main.js | 81 +++++++++ base/for-each-code-point-right/package.json | 69 ++++++++ base/for-each-code-point-right/test/test.js | 165 ++++++++++++++++++ 11 files changed, 816 insertions(+) create mode 100644 base/for-each-code-point-right/README.md create mode 100644 base/for-each-code-point-right/benchmark/benchmark.js create mode 100644 base/for-each-code-point-right/docs/repl.txt create mode 100644 base/for-each-code-point-right/docs/types/index.d.ts create mode 100644 base/for-each-code-point-right/docs/types/test.ts create mode 100644 base/for-each-code-point-right/examples/index.js create mode 100644 base/for-each-code-point-right/lib/index.js create mode 100644 base/for-each-code-point-right/lib/main.js create mode 100644 base/for-each-code-point-right/package.json create mode 100644 base/for-each-code-point-right/test/test.js diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 4500383..0570891 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -5,6 +5,7 @@ Adarsh Palaskar Aditya Sapra AgPriyanshu18 <113460573+AgPriyanshu18@users.noreply.github.com> +Aleksandr <112382387+alextes90@users.noreply.github.com> Ali Salesi Aman Bhansali Amit Jimiwal @@ -69,8 +70,10 @@ Seyyed Parsa Neshaei Shashank Shekhar Singh Shivam <11shivam00@gmail.com> Shraddheya Shendre +Shubh Mehta <93862397+Shubh942@users.noreply.github.com> Shubham Mishra Snehil Shah <130062020+Snehil-Shah@users.noreply.github.com> +Soumajit Chatterjee <121816890+soumajit23@users.noreply.github.com> Spandan Barve Stephannie Jiménez Gacha Suraj kumar <125961509+kumarsuraj212003@users.noreply.github.com> @@ -83,4 +86,5 @@ Yernar Yergaziyev naveen nishant-s7 <97207366+nishant-s7@users.noreply.github.com> orimiles5 <97595296+orimiles5@users.noreply.github.com> +rainn <88160429+AmCodesLame@users.noreply.github.com> rei2hu diff --git a/base/for-each-code-point-right/README.md b/base/for-each-code-point-right/README.md new file mode 100644 index 0000000..0c680a8 --- /dev/null +++ b/base/for-each-code-point-right/README.md @@ -0,0 +1,146 @@ + + +# forEachCodePointRight + +> Invokes a function for each Unicode code point in a string, iterating from right to left. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var forEachCodePointRight = require( '@stdlib/string/base/for-each-code-point-right' ); +``` + +#### forEachCodePointRight( str, clbk\[, thisArg ] ) + +Invokes a function for each Unicode code point in a string, iterating from right to left. + +```javascript +function log( value, index ) { + console.log( '%d: %s', index, value ); +} + +forEachCodePointRight( 'Beep!', log ); +/* => + 4: ! + 3: p + 2: e + 1: e + 0: B +*/ +``` + +The invoked function is provided three arguments: + +- **value**: Unicode code point. +- **index**: starting Unicode code point index. +- **str**: input string. + +To set the function execution context, provide a `thisArg`. + +```javascript +function clbk() { + this.count += 1; +} + +var str = '👉🏿'; + +var ctx = { + 'count': 0 +}; + +forEachCodePointRight( str, clbk, ctx ); + +var cnt = ctx.count; +// returns 2 +``` + +
+ + + + + +
+ +
+ + + + + +
+ +## Examples + + + +```javascript +var forEachCodePointRight = require( '@stdlib/string/base/for-each-code-point-right' ); + +function log( value, index ) { + console.log( '%d: %s', index, value ); +} + +forEachCodePointRight( 'presidential election', log ); +forEachCodePointRight( 'Iñtërnâtiônàlizætiøn', log ); +forEachCodePointRight( '🌷🍕', log ); +forEachCodePointRight( '\uD834\uDD1E', log ); +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/base/for-each-code-point-right/benchmark/benchmark.js b/base/for-each-code-point-right/benchmark/benchmark.js new file mode 100644 index 0000000..4445af7 --- /dev/null +++ b/base/for-each-code-point-right/benchmark/benchmark.js @@ -0,0 +1,61 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var pkg = require( './../package.json' ).name; +var forEachRight = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var values; + var out; + var i; + + values = [ + 'Iñtërnâtiônàlizætiøn', + 'presidential election', + '🐶🐮🐷🐰🐸' + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = forEachRight( values[ i%values.length ], clbk ); + if ( typeof out !== 'string' ) { + b.fail( 'should return a string' ); + } + } + b.toc(); + if ( !isString( out ) ) { + b.fail( 'should return a string' ); + } + b.pass( 'benchmark finished' ); + b.end(); + + function clbk( v ) { + if ( typeof v !== 'string' ) { + b.fail( 'unexpected value' ); + } + } +}); diff --git a/base/for-each-code-point-right/docs/repl.txt b/base/for-each-code-point-right/docs/repl.txt new file mode 100644 index 0000000..68cbecd --- /dev/null +++ b/base/for-each-code-point-right/docs/repl.txt @@ -0,0 +1,38 @@ + +{{alias}}( str, clbk[, thisArg] ) + Invokes a function for each Unicode code point in a string, iterating from + right to left. + + When invoked, the provided function is provided three arguments: + + - value: code point + - index: starting code point index + - str: input string + + Parameters + ---------- + str: string + Input string over which to iterate. + + clbk: Function + The function to invoke for each Unicode code point in the input string. + + thisArg: any (optional) + Execution context. + + Returns + ------- + out: string + Input string. + + Examples + -------- + > var n = 0; + > function fcn() { n += 1; }; + > {{alias}}( 'hello world!', fcn ); + > n + 12 + + See Also + -------- + diff --git a/base/for-each-code-point-right/docs/types/index.d.ts b/base/for-each-code-point-right/docs/types/index.d.ts new file mode 100644 index 0000000..eca3b44 --- /dev/null +++ b/base/for-each-code-point-right/docs/types/index.d.ts @@ -0,0 +1,93 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/** +* Callback invoked for each Unicode code point in a string. +* +* @returns result +*/ +type Nullary = ( this: T ) => any; + +/** +* Callback invoked for each Unicode code point in a string. +* +* @param value - code point +* @returns result +*/ +type Unary = ( this: T, value: string ) => any; + +/** +* Callback invoked for each Unicode code point in a string. +* +* @param value - code point +* @param index - starting code point index +* @returns result +*/ +type Binary = ( this: T, value: string, index: number ) => any; + +/** +* Callback invoked for each Unicode code point in a string. +* +* @param value - code point +* @param index - starting code point index +* @param str - input string +* @returns result +*/ +type Ternary = ( this: T, value: string, index: number, str: string ) => any; + +/** +* Callback invoked for each Unicode code point in a string. +* +* @param value - code point +* @param index - starting code point index +* @param str - input string +* @returns result +*/ +type Callback = Nullary | Unary | Binary | Ternary; + +/** +* Invokes a function for each Unicode code point in a string, iterating from right to left. +* +* ## Notes +* +* - When invoked, the provided function is provided three arguments: +* +* - **value**: code point. +* - **index**: starting code point index. +* - **str**: input string. +* +* @param str - input string +* @param clbk - function to invoke +* @param thisArg - execution context +* @returns input string +* +* @example +* function log( value, index ) { +* console.log( '%d: %s', index, value ); +* } +* +* forEachRight( 'Hello, World!', log ); +*/ +declare function forEachRight( str: string, clbk: Callback, thisArg?: ThisParameterType> ): string; + + +// EXPORTS // + +export = forEachRight; diff --git a/base/for-each-code-point-right/docs/types/test.ts b/base/for-each-code-point-right/docs/types/test.ts new file mode 100644 index 0000000..588678e --- /dev/null +++ b/base/for-each-code-point-right/docs/types/test.ts @@ -0,0 +1,86 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import forEachRight = require( './index' ); + +/** +* Callback function. +* +* @param v - argument +* @returns result +*/ +function clbk( v: string ): string { + return v; +} + + +// TESTS // + +// The function returns a string... +{ + forEachRight( 'presidential election', clbk ); // $ExpectType string + forEachRight( 'Iñtërnâtiônàlizætiøn', clbk, {} ); // $ExpectType string +} + +// The compiler throws an error if the function is provided a first argument which is not a string... +{ + forEachRight( 1, clbk ); // $ExpectError + forEachRight( false, clbk ); // $ExpectError + forEachRight( true, clbk ); // $ExpectError + forEachRight( null, clbk ); // $ExpectError + forEachRight( [], clbk ); // $ExpectError + forEachRight( {}, clbk ); // $ExpectError + forEachRight( ( x: number ): number => x, clbk ); // $ExpectError + + forEachRight( 1, clbk, {} ); // $ExpectError + forEachRight( false, clbk, {} ); // $ExpectError + forEachRight( true, clbk, {} ); // $ExpectError + forEachRight( null, clbk, {} ); // $ExpectError + forEachRight( [], clbk, {} ); // $ExpectError + forEachRight( {}, clbk, {} ); // $ExpectError + forEachRight( ( x: number ): number => x, clbk, {} ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a function having a supported signature... +{ + forEachRight( 'presidential election', 'abc' ); // $ExpectError + forEachRight( 'presidential election', 2 ); // $ExpectError + forEachRight( 'presidential election', true ); // $ExpectError + forEachRight( 'presidential election', false ); // $ExpectError + forEachRight( 'presidential election', null ); // $ExpectError + forEachRight( 'presidential election', {} ); // $ExpectError + forEachRight( 'presidential election', [] ); // $ExpectError + + forEachRight( 'presidential election', 'abc', {} ); // $ExpectError + forEachRight( 'presidential election', 2, {} ); // $ExpectError + forEachRight( 'presidential election', true, {} ); // $ExpectError + forEachRight( 'presidential election', false, {} ); // $ExpectError + forEachRight( 'presidential election', null, {} ); // $ExpectError + forEachRight( 'presidential election', {}, {} ); // $ExpectError + forEachRight( 'presidential election', [], {} ); // $ExpectError + + forEachRight( 'presidential election', ( x: number ): number => x ); // $ExpectError + forEachRight( 'presidential election', ( x: number ): number => x, {} ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + forEachRight(); // $ExpectError + forEachRight( 'presidential election' ); // $ExpectError + forEachRight( 'presidential election', clbk, {}, 3 ); // $ExpectError +} diff --git a/base/for-each-code-point-right/examples/index.js b/base/for-each-code-point-right/examples/index.js new file mode 100644 index 0000000..43983ae --- /dev/null +++ b/base/for-each-code-point-right/examples/index.js @@ -0,0 +1,30 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var forEachCodePointRight = require( './../lib' ); + +function log( value, index ) { + console.log( '%d: %s', index, value ); +} + +forEachCodePointRight( 'presidential election', log ); +forEachCodePointRight( 'Iñtërnâtiônàlizætiøn', log ); +forEachCodePointRight( '🌷🍕', log ); +forEachCodePointRight( '\uD834\uDD1E', log ); diff --git a/base/for-each-code-point-right/lib/index.js b/base/for-each-code-point-right/lib/index.js new file mode 100644 index 0000000..d6c94e1 --- /dev/null +++ b/base/for-each-code-point-right/lib/index.js @@ -0,0 +1,43 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Invoke a function for each Unicode code point in a string, iterating from right to left. +* +* @module @stdlib/string/base/for-each-code-point-right +* +* @example +* var forEachRight = require( '@stdlib/string/base/for-each-code-point-right' ); +* +* function log( value, index ) { +* console.log( '%d: %s', index, value ); +* } +* +* forEachRight( 'Hello', log ); +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/for-each-code-point-right/lib/main.js b/base/for-each-code-point-right/lib/main.js new file mode 100644 index 0000000..7459adf --- /dev/null +++ b/base/for-each-code-point-right/lib/main.js @@ -0,0 +1,81 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// VARIABLES // + +var RE_UTF16_LOW_SURROGATE = /[\uDC00-\uDFFF]/; // TODO: replace with stdlib pkg +var RE_UTF16_HIGH_SURROGATE = /[\uD800-\uDBFF]/; // TODO: replace with stdlib pkg + + +// MAIN // + +/** +* Invokes a function for each Unicode code point in a string, iterating from right to left. +* +* @param {string} str - input string +* @param {Function} clbk - function to invoke +* @param {*} [thisArg] - execution context +* @returns {string} input string +* +* @example +* function log( value, index ) { +* console.log( '%d: %s', index, value ); +* } +* +* forEachRight( 'Hello', log ); +*/ +function forEachRight( str, clbk, thisArg ) { + var len; + var ch1; + var ch2; + var idx; + var ch; + var i; + + len = str.length; + + // Process the string one Unicode code unit at a time and handle UTF-16 surrogate pairs as a single Unicode code point... + for ( i = len-1; i >= 0; i-- ) { + ch1 = str[ i ]; + idx = i; + ch = ch1; + + // Check for a UTF-16 surrogate pair... + if ( i > 0 && RE_UTF16_LOW_SURROGATE.test( ch1 ) ) { + // Check whether the low surrogate is preceded by a high surrogate... + ch2 = str[ i-1 ]; + if ( RE_UTF16_HIGH_SURROGATE.test( ch2 ) ) { + // We found a surrogate pair: + ch = ch2 + ch1; + i -= 1; // decrement the index to process the next code unit + } + } + // Note: `ch` may be a lone surrogate (e.g., a high surrogate without a following low surrogate or a low surrogate at the start of the input string). + + // Invoke the callback with the code point: + clbk.call( thisArg, ch, idx, str ); + } + return str; +} + + +// EXPORTS // + +module.exports = forEachRight; diff --git a/base/for-each-code-point-right/package.json b/base/for-each-code-point-right/package.json new file mode 100644 index 0000000..c82f548 --- /dev/null +++ b/base/for-each-code-point-right/package.json @@ -0,0 +1,69 @@ +{ + "name": "@stdlib/string/base/for-each-code-point-right", + "version": "0.0.0", + "description": "Invoke a function for each Unicode code point in a string, iterating from right to left.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdutils", + "stdutil", + "utilities", + "utility", + "utils", + "util", + "for", + "each", + "foreach", + "iterate", + "stdstring", + "string", + "str", + "unicode", + "reverse" + ] +} diff --git a/base/for-each-code-point-right/test/test.js b/base/for-each-code-point-right/test/test.js new file mode 100644 index 0000000..3f3f0c7 --- /dev/null +++ b/base/for-each-code-point-right/test/test.js @@ -0,0 +1,165 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var noop = require( '@stdlib/utils/noop' ); +var forEachRight = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof forEachRight, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'if provided an empty string, the function never invokes a provided function', function test( t ) { + var out = forEachRight( '', fcn ); + t.strictEqual( out, '', 'returns expected value' ); + t.end(); + + function fcn() { + t.fail( 'should not be invoked' ); + } +}); + +tape( 'the function returns a provided string', function test( t ) { + var str; + var out; + + str = 'Hello, world'; + + out = forEachRight( str, noop ); + t.strictEqual( out, str, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function invokes a provided function for each Unicode code point of a provided string', function test( t ) { + var expected; + var actual; + var str; + + str = 'Hello, world'; + expected = [ + 'd', + 'l', + 'r', + 'o', + 'w', + ' ', + ',', + 'o', + 'l', + 'l', + 'e', + 'H' + ]; + + actual = []; + forEachRight( str, copy ); + + t.deepEqual( actual, expected, 'returns expected value' ); + t.end(); + + function copy( value ) { + actual.push( value ); + } +}); + +tape( 'the function invokes a provided function for each Unicode code point of the string (Unicode)', function test( t ) { + var expected; + var actual; + var str; + + str = 'Hello, world \uD834\uDD1E'; + expected = [ + '\uD834\uDD1E', + ' ', + 'd', + 'l', + 'r', + 'o', + 'w', + ' ', + ',', + 'o', + 'l', + 'l', + 'e', + 'H' + ]; + + actual = []; + forEachRight( str, copy ); + + t.deepEqual( actual, expected, 'returns expected value' ); + t.end(); + + function copy( value ) { + actual.push( value ); + } +}); + +tape( 'the function invokes a provided function for each Unicode code point of the string (emoji)', function test( t ) { + var expected; + var actual; + var str; + + str = '🌷🍕👉🏿'; + expected = [ + '🏿', + '👉', + '🍕', + '🌷' + ]; + + actual = []; + forEachRight( str, copy ); + + t.deepEqual( actual, expected, 'returns expected value' ); + t.end(); + + function copy( value ) { + actual.push( value ); + } +}); + +tape( 'the function supports providing an execution context', function test( t ) { + var ctx; + var str; + + str = 'Hello, world'; + ctx = { + 'count': 0 + }; + + forEachRight( str, count, ctx ); + + t.strictEqual( ctx.count, 12, 'returns expected value' ); + t.end(); + + function count() { + this.count += 1; // eslint-disable-line no-invalid-this + } +});