From 716dae97eac5c00671da8643f8544aef5519827f Mon Sep 17 00:00:00 2001 From: Amarghosh Vadakkoot Date: Wed, 21 Aug 2024 15:40:04 +0100 Subject: [PATCH] Add strip, stripLeft, stripRight methods to String Add an extension to the string class that adds strip, stripLeft, and stripRight methods that are functionally similar to the strip, lstrip and rstrip functions in python's string class. --- lib/src/StringUtils.dart | 55 ++++++++++++++++ test/string_utils_test.dart | 123 ++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/lib/src/StringUtils.dart b/lib/src/StringUtils.dart index f9ee957..330b779 100644 --- a/lib/src/StringUtils.dart +++ b/lib/src/StringUtils.dart @@ -541,3 +541,58 @@ class StringUtils { return false; } } + +extension Strip on String { + /// Implementation of strip, stripLeft and stripRight + String _strip( + String stripChars, { + bool left = true, + bool right = true, + }) { + if (!left && !right) { + throw ArgumentError('either left or right shall be true in _strip: <$this>'); + } + int start = 0; + int end = length; + List sourceChars = runes.toList(); + List searchChars = stripChars.runes.toList(); + if (left) { + for (int i = 0; i < sourceChars.length; i++) { + if (searchChars.contains(sourceChars[i])) { + start++; + } else { + break; + } + } + } + if (right) { + for (int i = sourceChars.length - 1; i >= 0; i--) { + if (searchChars.contains(sourceChars[i])) { + end--; + } else { + break; + } + } + } + + if (start >= end) { + return ''; + } + return substring(start, end); + } + + /// Return a string after removing any leading and trailing characters specified in [chars] + /// + /// '@£^£Some @£^ Thing@@£@^'.strip('@£^') => 'Some @£^ Thing' + String strip(String chars) => _strip(chars, left: true, right: true); + + /// Return a string after removing any leading characters specified in [chars] + /// + /// '@£^£Some @£^ Thing@@£@^'.stripLeft('@£^') => 'Some @£^ Thing@@£@^' + String stripLeft(String chars) => _strip(chars, left: true, right: false); + + /// Return a string after removing any trailing characters specified in [chars] + /// + /// '@£^£Some @£^ Thing@@£@^'.strip('@£^') => '@£^£Some @£^ Thing' + String stripRight(String chars) => _strip(chars, left: false, right: true); +} diff --git a/test/string_utils_test.dart b/test/string_utils_test.dart index bdb3a16..66b5e9b 100644 --- a/test/string_utils_test.dart +++ b/test/string_utils_test.dart @@ -219,4 +219,127 @@ void main() { expect(StringUtils.isIP('0.0.0.256'), false); expect(StringUtils.isIP('26.0.0.256'), false); }); + + group('strip extension', () { + test('strip', () { + // tested function's comment + expect('@£^£Some @£^ Thing@@£@^'.strip('@£^'), 'Some @£^ Thing'); + + // edge cases that doesn't modify the string + expect('something'.strip('@'), 'something'); + expect('something'.strip('@£^'), 'something'); + expect('something'.strip(''), 'something'); + + // remove a single character at either end from the source + expect('@something'.strip('@'), 'something'); + expect('@something@'.strip('@'), 'something'); + expect('something@'.strip('@'), 'something'); + + // remove more than one character at either end from the source + expect('@@@something'.strip('@'), 'something'); + expect('@@something@@@'.strip('@'), 'something'); + expect('something@@@'.strip('@'), 'something'); + + // search-string with multiple characters in it + expect('@£something'.strip('@£'), 'something'); + expect('@£something@£^'.strip('@£^'), 'something'); + expect('something@£^'.strip('@£^'), 'something'); + + // source string with strip-chars in the middle + expect('@£some@£^thing'.strip('@£'), 'some@£^thing'); + expect('@£some@£^thing@£@'.strip('@£'), 'some@£^thing'); + expect('some@£^thing@£@'.strip('@£'), 'some@£^thing'); + + // strip returns an empty string + expect('@@@@@£^^£@£'.strip('@£^'), ''); + expect(''.strip('@£^'), ''); + expect(''.strip(''), ''); + expect('2'.strip('2'), ''); + + // results in a string with one character in it + expect('£@£@£@£@3@££££@^'.strip('£@^'), '3'); + + // ensure that strip works with unicode chars: this text in in the script "Malayalam" + expect('വ മലയാളം'.strip(''), 'വ മലയാളം'); + expect('വ മലയാളം'.strip('വ'), ' മലയാളം'); + expect('വ മലയാളംx'.strip('xവ'), ' മലയാളം'); + expect('kമലയാളംx'.strip('xk'), 'മലയാളം'); + }); + test('stripLeft', () { + // tested function's comment + expect('@£^£Some @£^ Thing@@£@^'.stripLeft('@£^'), 'Some @£^ Thing@@£@^'); + + // edge cases that doesn't modify the string + expect('something'.stripLeft('@'), 'something'); + expect('something'.stripLeft('@£^'), 'something'); + expect('something'.stripLeft(''), 'something'); + + // remove a single character at the beginning + expect('@something'.stripLeft('@'), 'something'); + expect('@something@'.stripLeft('@'), 'something@'); + expect('something@'.stripLeft('@'), 'something@'); + + // remove more than one character from the beginning + expect('@@@something'.stripLeft('@'), 'something'); + expect('@@something@@@'.stripLeft('@'), 'something@@@'); + expect('something@@@'.stripLeft('@'), 'something@@@'); + + // search-string with multiple characters in it + expect('@£something'.stripLeft('@£'), 'something'); + expect('@£something@£@'.stripLeft('@£'), 'something@£@'); + expect('something@£@'.stripLeft('@£'), 'something@£@'); + + // source string with strip-chars in the middle + expect('@£some@£^thing'.stripLeft('@£'), 'some@£^thing'); + expect('@£some@£^thing@£@'.stripLeft('@£'), 'some@£^thing@£@'); + expect('some@£^thing@£@'.stripLeft('@£'), 'some@£^thing@£@'); + + // strip returns an empty string + expect('@@@@@£^£@£'.stripLeft('@£^'), ''); + expect(''.stripLeft('@£^'), ''); + expect(''.stripLeft(''), ''); + expect('2'.stripLeft('2'), ''); + + // results in a string with one character in it + expect('£@£@£@£@3'.stripLeft('£@^'), '3'); + }); + test('stripRight', () { + // tested function's comment + expect('@£^£Some @£^ Thing@@£@^'.stripRight('@£^'),'@£^£Some @£^ Thing'); + + // edge cases that doesn't modify the string + expect('something'.stripRight('@'), 'something'); + expect('something'.stripRight('@£^'), 'something'); + expect('something'.stripRight(''), 'something'); + + // remove a single character at the end + expect('@something'.stripRight('@'), '@something'); + expect('@something@'.stripRight('@'), '@something'); + expect('something@'.stripRight('@'), 'something'); + + // remove more than one character from the end + expect('@@@something'.stripRight('@'), '@@@something'); + expect('@@something@@@'.stripRight('@'), '@@something'); + expect('something@@@'.stripRight('@'), 'something'); + + // search-string with multiple characters in it + expect('@£something'.stripRight('£@'), '@£something'); + expect('@£something@£@'.stripRight('@£'), '@£something'); + expect('something@£@'.stripRight('@£'), 'something'); + + // source string with strip-chars in the middle + expect('@£some@£^thing'.stripRight('@£'), '@£some@£^thing'); + expect('@£some@£^thing@£@'.stripRight('@£'), '@£some@£^thing'); + expect('some@£^thing@£@'.stripRight('@£'), 'some@£^thing'); + + // strip returns an empty string + expect('@@@@@£^£@£'.stripRight('@£^'), ''); + expect(''.stripRight('@£^'), ''); + expect(''.stripRight(''), ''); + expect('2'.stripRight('2'), ''); + + // results in a string with one character in it + expect('3@££££@^'.strip('£@^'), '3'); + }); + }); }