Skip to content

Commit

Permalink
v3.2.3
Browse files Browse the repository at this point in the history
- sdk: '>=3.4.0 <4.0.0'

- lints: ^4.0.0
- test: ^1.25.14
- dependency_validator: ^4.1.2
- coverage: ^1.11.1
  • Loading branch information
gmpassos committed Dec 21, 2024
1 parent 4eed720 commit cbbe5ad
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 87 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 3.2.3

- Optimize `toFlatListOfStrings`.
- Added `trimListOfStrings`.

- sdk: '>=3.4.0 <4.0.0'

- lints: ^4.0.0
- test: ^1.25.14
- dependency_validator: ^4.1.2
- coverage: ^1.11.1

## 3.2.2

- `MimeType`:
Expand Down
192 changes: 115 additions & 77 deletions lib/src/collections.dart
Original file line number Diff line number Diff line change
Expand Up @@ -732,54 +732,83 @@ final RegExp _toListOfStringsDelimiter = RegExp(r'\s+');
/// Converts any collection to a flat list of strings.
List<String> toFlatListOfStrings(Object? s,
{Pattern? delimiter, bool trim = true, bool ignoreEmpty = true}) {
if (s == null) return [];
if (s == null) {
return <String>[];
} else if (s is String) {
return _toFlatListOfStringsFromString(
s, delimiter ?? _toListOfStringsDelimiter, trim, ignoreEmpty);
} else if (s is Iterable) {
return _toFlatListOfStringsFromIterable(
s, delimiter ?? _toListOfStringsDelimiter, trim, ignoreEmpty);
} else {
return _toFlatListOfStringsFromString(
'$s', delimiter ?? _toListOfStringsDelimiter, trim, ignoreEmpty);
}
}

List<String> _toFlatListOfStringsFromString(
String s, Pattern delimiter, bool trim, bool ignoreEmpty) {
var list = s.split(delimiter);

delimiter ??= _toListOfStringsDelimiter;
if (trim) {
trimListOfStrings(list);
}

List<String> list;
if (ignoreEmpty) {
list.removeWhere((e) => e.isEmpty);
}

if (s is String) {
list = s.split(delimiter);
} else if (s is Iterable) {
list = <String>[];

for (var e in s) {
if (e == null) continue;

if (e is String) {
var l2 = toFlatListOfStrings(e,
delimiter: delimiter, trim: trim, ignoreEmpty: ignoreEmpty);
list.addAll(l2);
} else if (e is Iterable) {
var l2 = toFlatListOfStrings(e,
delimiter: delimiter, trim: trim, ignoreEmpty: ignoreEmpty);
list.addAll(l2);
} else {
var str = '$e';
var l2 = toFlatListOfStrings(str,
delimiter: delimiter, trim: trim, ignoreEmpty: ignoreEmpty);
list.addAll(l2);
}
return list;
}

List<String> _toFlatListOfStringsFromIterable(
Iterable s, Pattern delimiter, bool trim, bool ignoreEmpty) {
var list = <String>[];

for (var e in s) {
if (e == null) continue;

if (e is String) {
var l2 = _toFlatListOfStringsFromString(e, delimiter, trim, ignoreEmpty);
list.addAll(l2);
} else if (e is Iterable) {
var l2 =
_toFlatListOfStringsFromIterable(e, delimiter, trim, ignoreEmpty);
list.addAll(l2);
} else {
var l2 =
_toFlatListOfStringsFromString('$e', delimiter, trim, ignoreEmpty);
list.addAll(l2);
}
} else {
list = <String>[];
}

if (list.isEmpty) return list;

if (trim) {
for (var i = 0; i < list.length; ++i) {
var e = list[i];
var e2 = e.trim();
if (e2.length != e.length) {
list[i] = e2;
}
}
trimListOfStrings(list);
}

list.removeWhere((e) => (ignoreEmpty && e.isEmpty));
if (ignoreEmpty) {
list.removeWhere((e) => e.isEmpty);
}

return list;
}

/// Apply [String.trim] to each [String] of [list].
/// Returns the same [list] instance without change it's length.
List<String> trimListOfStrings(List<String> list) {
final length = list.length;
for (var i = 0; i < length; ++i) {
var e = list[i];
var e2 = e.trim();
if (e2.length != e.length) {
list[i] = e2;
}
}
return list;
}

/// Returns [true] if [list] elements are all of type [String].
bool isListOfString(Iterable? list) {
if (list == null) return false;
Expand Down Expand Up @@ -978,7 +1007,9 @@ bool isMapOfStringKeysAndListValues(Map? map) {
if (map.isEmpty) return false;

if (listNotMatchesAll<MapEntry>(
map.entries, (e) => (e.key is String) && (e.value is List))) return false;
map.entries, (e) => (e.key is String) && (e.value is List))) {
return false;
}

return true;
}
Expand All @@ -990,7 +1021,9 @@ bool isMapOfStringKeysAndNumValues(Map? map) {
if (map.isEmpty) return false;

if (listNotMatchesAll<MapEntry>(
map.entries, (e) => (e.key is String) && (e.value is num))) return false;
map.entries, (e) => (e.key is String) && (e.value is num))) {
return false;
}

return true;
}
Expand Down Expand Up @@ -2517,22 +2550,20 @@ class TreeReferenceMap<K, V> implements Map<K, V> {
}

/// Returns [true] if [key] is valid (in the tree).
bool isValidEntry(K key, V value) {
return isInTree(key);
}
bool isValidEntry(K key, V value) => isInTree(key);

/// Returns [true] if [key] is in the tree.
bool isInTree(K? key) {
if (key == null) return false;
if (identical(root, key)) return true;

var cursor = key;
while (true) {
K? cursor = key;
while (cursor != null) {
var parent = getParentOf(cursor);
if (parent == null) return false;
if (identical(parent, root)) return true;
cursor = parent;
}

return false;
}

/// Returns the parent of [key].
Expand Down Expand Up @@ -2704,9 +2735,11 @@ class TreeReferenceMap<K, V> implements Map<K, V> {

/// Removed purged entries over [maxPurgedEntries] limit.
void checkPurgeEntriesLimit() {
if (_purged != null && maxPurgedEntries != null && maxPurgedEntries! > 0) {
var purged = _purged!;
var needToRemove = purged.length - maxPurgedEntries!;
var purged = _purged;
var maxPurgedEntries = this.maxPurgedEntries;

if (purged != null && maxPurgedEntries != null && maxPurgedEntries > 0) {
var needToRemove = purged.length - maxPurgedEntries;
if (needToRemove > 0) {
var del = <K>[];
for (var k in purged.keys) {
Expand All @@ -2726,16 +2759,18 @@ class TreeReferenceMap<K, V> implements Map<K, V> {

/// Remove expired purged entries. Only relevant if [purgedEntriesTimeout] is not null.
void checkPurgedEntriesTimeout() {
if (_purged != null &&
var purged = _purged;
var purgedEntriesTimeout = this.purgedEntriesTimeout;

if (purged != null &&
purgedEntriesTimeout != null &&
purgedEntriesTimeout!.inMilliseconds > 0) {
var purged = _purged!;
var timeoutMs = purgedEntriesTimeout!.inMilliseconds;
purgedEntriesTimeout.inMilliseconds > 0) {
var timeoutMs = purgedEntriesTimeout.inMilliseconds;
var now = DateTime.now().millisecondsSinceEpoch;
var expired = purged.entries
.where((e) => (now - e.value.key.millisecondsSinceEpoch) > timeoutMs)
.map((e) => e.key)
.toList();
.toList(growable: false);

if (expired.isNotEmpty) {
for (var k in expired) {
Expand All @@ -2752,24 +2787,28 @@ class TreeReferenceMap<K, V> implements Map<K, V> {

/// Restore purged entries that are currently valid. Only relevant if [keepPurgedEntries] is true.
int revalidatePurgedEntries() {
if (_purged != null) {
var purged = _purged!;
var validPurged = purged.entries
.where((e) => isValidEntry(e.key, e.value.value))
.toList();

if (validPurged.isNotEmpty) {
for (var e in validPurged) {
_map[e.key] = e.value.value;
purged.remove(e.key);
}
_expireCache();
var purged = _purged;
if (purged == null) return 0;

var revalidateCount = 0;

purged.removeWhere((k, v) {
var value = v.value;
if (isValidEntry(k, value)) {
++revalidateCount;
_map[k] = value;
return true;
} else {
return false;
}
});

_revalidatedPurgedEntriesCount += validPurged.length;
return validPurged.length;
if (revalidateCount > 0) {
_expireCache();
}
return 0;

_revalidatedPurgedEntriesCount += revalidateCount;
return revalidateCount;
}

/// Returns the valid entries.
Expand All @@ -2781,12 +2820,12 @@ class TreeReferenceMap<K, V> implements Map<K, V> {
_map.entries.where((e) => !isValidEntry(e.key, e.value)).toList();

/// Returns the purged entries. Only relevant if [keepPurgedEntries] is true.
List<MapEntry<K, V>> get purgedEntries => _purged != null
? _purged!.entries.map((e) => MapEntry(e.key, e.value.value)).toList()
: <MapEntry<K, V>>[];
List<MapEntry<K, V>> get purgedEntries =>
_purged?.entries.map((e) => MapEntry(e.key, e.value.value)).toList() ??
<MapEntry<K, V>>[];

/// Returns the purged keys. Only relevant if [keepPurgedEntries] is true.
List<K> get purgedKeys => _purged != null ? _purged!.keys.toList() : <K>[];
List<K> get purgedKeys => _purged?.keys.toList() ?? <K>[];

/// Returns the valid keys.
List<K> get validKeys => _map.entries
Expand All @@ -2807,7 +2846,6 @@ class TreeReferenceMap<K, V> implements Map<K, V> {

R? _walkTreeImpl<R>(K node, R Function(K node) walker) {
var children = getChildrenOf(node);
if (children.isEmpty) return null;

for (var child in children) {
R? ret = walker(child);
Expand Down Expand Up @@ -2879,17 +2917,17 @@ class TreeReferenceMap<K, V> implements Map<K, V> {

/// Returns [keys] reversed (unmodifiable);
List<K> get keysReversed {
_keysReversedList ??= _map.keys.toList().reversed.toList();
return UnmodifiableListView(_keysReversedList!);
var keys = _keysReversedList ??= _map.keys.toList().reversed.toList();
return UnmodifiableListView(keys);
}

List<K>? _purgedKeysReversedList;

/// Returns [purgedKeys] reversed (unmodifiable);
List<K> get purgedKeysReversed {
_purgedKeysReversedList ??=
_purged != null ? _purged!.keys.toList().reversed.toList() : [];
return UnmodifiableListView(_purgedKeysReversedList!);
var keys = _purgedKeysReversedList ??=
_purged?.keys.toList().reversed.toList() ?? [];
return UnmodifiableListView(keys);
}

void _expireCache() {
Expand Down
4 changes: 0 additions & 4 deletions lib/src/date.dart
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,6 @@ int? getDateTimeWeekDayIndex(DateTimeWeekDay? weekDay) {
return 6;
case DateTimeWeekDay.sunday:
return 7;
default:
return null;
}
}

Expand Down Expand Up @@ -747,8 +745,6 @@ Pair<DateTime> getDateTimeRange(DateRangeType rangeType,
return getDateTimeLastMonth(time);
case DateRangeType.thisMonth:
return getDateTimeThisMonth(time);
default:
throw UnsupportedError("Can't handle: $rangeType");
}
}

Expand Down
12 changes: 6 additions & 6 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
name: swiss_knife
description: Dart Useful Tools - collections, math, date, uri, json, events, resources, regexp, etc...
version: 3.2.2
version: 3.2.3
homepage: https://github.com/gmpassos/swiss_knife

environment:
sdk: '>=3.3.0 <4.0.0'
sdk: '>=3.4.0 <4.0.0'

dependencies:
intl: ^0.19.0
resource_portable: ^3.1.0

dev_dependencies:
lints: ^3.0.0
test: ^1.25.8
dependency_validator: ^3.2.3
lints: ^4.0.0
test: ^1.25.14
dependency_validator: ^4.1.2
collection: ^1.18.0
coverage: ^1.9.2
coverage: ^1.11.1

#dependency_overrides:
# resource_portable:
Expand Down
16 changes: 16 additions & 0 deletions test/swiss_knife_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,22 @@ void main() {
toFlatListOfStrings([' a ', ' b ', 'c_d'],
delimiter: '_', trim: false),
equals([' a ', ' b ', 'c', 'd']));

expect(
toFlatListOfStrings([
1,
DateTime.utc(2000, 1, 1, 1, 1, 1, 1, 1),
[
2,
3,
[4, [], 5]
]
]),
equals(['1', '2000-01-01', '01:01:01.001001Z', '2', '3', '4', '5']));
});

test('trimListOfStrings', () {
expect(trimListOfStrings([' a ', 'b', ' ']), equals(['a', 'b', '']));
});

test('listMatchesAll/listNotMatchesAll', () {
Expand Down

0 comments on commit cbbe5ad

Please sign in to comment.