2024-09-26 14:29:04 +08:00
|
|
|
import 'dart:convert';
|
|
|
|
|
import 'dart:typed_data';
|
|
|
|
|
|
2025-05-02 02:24:12 +08:00
|
|
|
import 'package:crypto/crypto.dart';
|
2025-12-16 11:23:09 +08:00
|
|
|
import 'package:fl_clash/common/common.dart';
|
2024-09-26 14:29:04 +08:00
|
|
|
|
2024-04-30 23:38:49 +08:00
|
|
|
extension StringExtension on String {
|
|
|
|
|
bool get isUrl {
|
2024-07-08 17:34:14 +08:00
|
|
|
return RegExp(r'^(http|https|ftp)://').hasMatch(this);
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
2024-08-05 19:25:35 +08:00
|
|
|
|
2025-05-02 02:24:12 +08:00
|
|
|
dynamic get splitByMultipleSeparators {
|
2025-07-31 17:09:18 +08:00
|
|
|
final parts = split(
|
|
|
|
|
RegExp(r'[, ;]+'),
|
|
|
|
|
).where((part) => part.isNotEmpty).toList();
|
2025-05-02 02:24:12 +08:00
|
|
|
|
|
|
|
|
return parts.length > 1 ? parts : this;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-05 19:25:35 +08:00
|
|
|
int compareToLower(String other) {
|
2025-07-31 17:09:18 +08:00
|
|
|
return toLowerCase().compareTo(other.toLowerCase());
|
2024-08-05 19:25:35 +08:00
|
|
|
}
|
2024-09-26 14:29:04 +08:00
|
|
|
|
2025-10-14 15:13:52 +08:00
|
|
|
String safeSubstring(int start, [int? end]) {
|
|
|
|
|
if (isEmpty) return '';
|
|
|
|
|
final safeStart = start.clamp(0, length);
|
|
|
|
|
if (end == null) {
|
|
|
|
|
return substring(safeStart);
|
|
|
|
|
}
|
|
|
|
|
final safeEnd = end.clamp(safeStart, length);
|
|
|
|
|
return substring(safeStart, safeEnd);
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-26 14:29:04 +08:00
|
|
|
List<int> get encodeUtf16LeWithBom {
|
|
|
|
|
final byteData = ByteData(length * 2);
|
|
|
|
|
final bom = [0xFF, 0xFE];
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
|
int charCode = codeUnitAt(i);
|
|
|
|
|
byteData.setUint16(i * 2, charCode, Endian.little);
|
|
|
|
|
}
|
|
|
|
|
return bom + byteData.buffer.asUint8List();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Uint8List? get getBase64 {
|
|
|
|
|
final regExp = RegExp(r'base64,(.*)');
|
|
|
|
|
final match = regExp.firstMatch(this);
|
|
|
|
|
final realValue = match?.group(1) ?? '';
|
|
|
|
|
if (realValue.isEmpty) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
return base64.decode(realValue);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-02 02:24:12 +08:00
|
|
|
bool get isSvg {
|
2025-06-07 01:48:34 +08:00
|
|
|
return endsWith('.svg');
|
2025-05-02 02:24:12 +08:00
|
|
|
}
|
|
|
|
|
|
2024-09-26 14:29:04 +08:00
|
|
|
bool get isRegex {
|
|
|
|
|
try {
|
|
|
|
|
RegExp(this);
|
|
|
|
|
return true;
|
|
|
|
|
} catch (e) {
|
2025-02-09 18:39:38 +08:00
|
|
|
commonPrint.log(e.toString());
|
2024-09-26 14:29:04 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-02 02:24:12 +08:00
|
|
|
|
|
|
|
|
String toMd5() {
|
|
|
|
|
final bytes = utf8.encode(this);
|
|
|
|
|
return md5.convert(bytes).toString();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-31 17:09:18 +08:00
|
|
|
// bool containsToLower(String target) {
|
|
|
|
|
// return toLowerCase().contains(target);
|
|
|
|
|
// }
|
2025-12-16 11:23:09 +08:00
|
|
|
|
|
|
|
|
Future<T> commonToJSON<T>() async {
|
|
|
|
|
final thresholdLimit = 51200;
|
|
|
|
|
if (length < thresholdLimit) {
|
|
|
|
|
return json.decode(this);
|
|
|
|
|
} else {
|
|
|
|
|
return await decodeJSONTask<T>(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
2025-02-09 18:39:38 +08:00
|
|
|
|
2025-12-16 11:23:09 +08:00
|
|
|
extension StringNullExt on String? {
|
|
|
|
|
String takeFirstValid(List<String?> others, {String defaultValue = ''}) {
|
|
|
|
|
if (this != null && this!.trim().isNotEmpty) return this!.trim();
|
|
|
|
|
|
|
|
|
|
for (final s in others) {
|
|
|
|
|
if (s != null && s.trim().isNotEmpty) {
|
|
|
|
|
return s.trim();
|
|
|
|
|
}
|
2025-02-09 18:39:38 +08:00
|
|
|
}
|
2025-12-16 11:23:09 +08:00
|
|
|
return defaultValue;
|
2025-02-09 18:39:38 +08:00
|
|
|
}
|
|
|
|
|
}
|