blob: 5bfe9436ea1e576b83884a3c465df90e049797b7 [file] [log] [blame]
part of strings;
const int _ASCII_END = 0x7f;
const int _ASCII_START = 0x0;
const int _C0_END = 0x1f;
const int _C0_START = 0x00;
const int _UNICODE_END = 0x10ffff;
const int _DIGIT = 0x1;
const int _LOWER = 0x2;
const int _UNDERSCORE = 0x4;
const int _UPPER = 0x8;
const int _ALPHA = _LOWER | _UPPER;
const int _ALPHA_NUM = _ALPHA | _DIGIT;
final List<int> _ascii = <int>[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
0,
0,
0,
0,
4,
0,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
0,
0,
0,
0,
0
];
/// Returns a string in the form "UpperCamelCase" or "lowerCamelCase".
///
/// Example:
/// print(camelize("dart_vm"));
/// => DartVm
String camelize(String string, [bool lower = false]) {
if (string.isEmpty) {
return string;
}
string = string.toLowerCase();
var capitlize = true;
var position = 0;
var remove = false;
var sb = StringBuffer();
final characters = Characters(string);
for (final s in characters) {
final runes = s.runes;
var flag = 0;
if (runes.length == 1) {
var c = runes.first;
if (c <= _ASCII_END) {
flag = _ascii[c];
}
}
if (capitlize && flag & _ALPHA != 0) {
if (lower && position == 0) {
sb.write(s);
} else {
sb.write(s.toUpperCase());
}
capitlize = false;
remove = true;
position++;
} else {
if (flag & _UNDERSCORE != 0) {
if (!remove) {
sb.write(s);
remove = true;
}
capitlize = true;
} else {
if (flag & _ALPHA_NUM != 0) {
capitlize = false;
remove = true;
} else {
capitlize = true;
remove = false;
position = 0;
}
sb.write(s);
}
}
}
return sb.toString();
}
/// Returns a string with capitalized first character.
///
/// Example:
/// print(capitalize("dart"));
/// => Dart
String capitalize(String string) {
if (string.isEmpty) {
return string;
}
return string[0].toUpperCase() + string.substring(1);
}
/// Returns an escaped string.
///
/// Example:
/// print(escape("Hello 'world' \n"));
/// => Hello \'world\' \n
String escape(String string, [String Function(int charCode)? encode]) {
if (string.isEmpty) {
return string;
}
encode ??= toUnicode;
final sb = StringBuffer();
final characters = Characters(string);
for (final s in characters) {
final runes = s.runes;
if (runes.length == 1) {
final c = runes.first;
if (c >= _C0_START && c <= _C0_END) {
switch (c) {
case 9:
sb.write('\\t');
break;
case 10:
sb.write('\\n');
break;
case 13:
sb.write('\\r');
break;
default:
sb.write(encode(c));
}
} else if (c >= _ASCII_START && c <= _ASCII_END) {
switch (c) {
case 34:
sb.write('\\\"');
break;
case 36:
sb.write('\\\$');
break;
case 39:
sb.write("\\\'");
break;
case 92:
sb.write('\\\\');
break;
default:
sb.write(s);
}
} else if (_isPrintable(c)) {
sb.write(s);
} else {
sb.write(encode(c));
}
} else {
// Experimental: Assuming that all clusters does not need to be escaped
sb.write(s);
}
}
return sb.toString();
}
/// Returns true if the string does not contain upper case letters; otherwise
/// false;
///
/// Example:
/// print(isLowerCase("camelCase"));
/// => false
///
/// print(isLowerCase("dart"));
/// => true
///
/// print(isLowerCase(""));
/// => false
bool isLowerCase(String string) {
if (string.isEmpty) {
return true;
}
final characters = Characters(string);
for (final s in characters) {
final runes = s.runes;
if (runes.length == 1) {
var c = runes.first;
var flag = 0;
if (c <= _ASCII_END) {
flag = _ascii[c];
}
if (c <= _ASCII_END) {
if (flag & _UPPER != 0) {
return false;
}
} else {
if (s == s.toUpperCase()) {
return false;
}
}
}
}
return true;
}
/// Returns true if the string does not contain lower case letters; otherwise
/// false;
///
/// Example:
/// print(isUpperCase("CamelCase"));
/// => false
///
/// print(isUpperCase("DART"));
/// => true
///
/// print(isUpperCase(""));
/// => false
bool isUpperCase(String string) {
if (string.isEmpty) {
return true;
}
final characters = Characters(string);
for (final s in characters) {
final runes = s.runes;
if (runes.length == 1) {
var c = runes.first;
var flag = 0;
if (c <= _ASCII_END) {
flag = _ascii[c];
}
if (c <= _ASCII_END) {
if (flag & _LOWER != 0) {
return false;
}
} else {
if (s == s.toLowerCase()) {
return false;
}
}
}
}
return true;
}
/// Returns the joined elements of the list if the list is not null; otherwise
/// null.
///
/// Example:
/// print(join(null));
/// => null
///
/// print(join([1, 2]));
/// => 12
String join(List list, [String separator = '']) {
// if (list == null) {
// return null;
// }
return list.join(separator);
}
/// Returns a string with reversed order of characters.
///
/// Example:
/// print(reverse("hello"));
/// => olleh
String reverse(String string) {
if (string.length < 2) {
return string;
}
final characters = Characters(string);
return characters.toList().reversed.join();
}
/// Returns true if the string starts with the lower case character; otherwise
/// false;
///
/// Example:
/// print(startsWithLowerCase("camelCase"));
/// => true
///
/// print(startsWithLowerCase(""));
/// => false
bool startsWithLowerCase(String string) {
if (string.isEmpty) {
return false;
}
final characters = Characters(string);
final s = characters.first;
final runes = s.runes;
if (runes.length == 1) {
var c = runes.first;
var flag = 0;
if (c <= _ASCII_END) {
flag = _ascii[c];
}
if (c <= _ASCII_END) {
if (flag & _LOWER != 0) {
return true;
}
} else {
if (s == s.toLowerCase()) {
return true;
}
}
}
return false;
}
/// Returns true if the string starts with the upper case character; otherwise
/// false;
///
/// Example:
/// print(startsWithUpperCase("Dart"));
/// => true
///
/// print(startsWithUpperCase(""));
/// => false
bool startsWithUpperCase(String string) {
if (string.isEmpty) {
return false;
}
final characters = Characters(string);
final s = characters.first;
final runes = s.runes;
if (runes.length == 1) {
var c = runes.first;
var flag = 0;
if (c <= _ASCII_END) {
flag = _ascii[c];
}
if (c <= _ASCII_END) {
if (flag & _UPPER != 0) {
return true;
}
} else {
if (s == s.toUpperCase()) {
return true;
}
}
}
return false;
}
/// Returns an unescaped printable string.
///
/// Example:
/// print(toPrintable("Hello 'world' \n"));
/// => Hello 'world' \n
String toPrintable(String string) {
if (string.isEmpty) {
return string;
}
final sb = StringBuffer();
final characters = Characters(string);
for (final s in characters) {
final runes = s.runes;
if (runes.length == 1) {
final c = runes.first;
if (c >= _C0_START && c <= _C0_END) {
switch (c) {
case 9:
sb.write('\\t');
break;
case 10:
sb.write('\\n');
break;
case 13:
sb.write('\\r');
break;
default:
sb.write(toUnicode(c));
}
} else if (_isPrintable(c)) {
sb.write(s);
} else {
sb.write(toUnicode(c));
}
} else {
// Experimental: Assuming that all clusters can be printed
sb.write(s);
}
}
return sb.toString();
}
/// Returns an Unicode representation of the character code.
///
/// Example:
/// print(toUnicode(48));
/// => \u0030
String toUnicode(int charCode) {
if (charCode < 0 || charCode > _UNICODE_END) {
throw RangeError.range(charCode, 0, _UNICODE_END, 'charCode');
}
var hex = charCode.toRadixString(16);
var length = hex.length;
if (length < 4) {
hex = hex.padLeft(4, '0');
}
return '\\u$hex';
}
/// Returns an underscored string.
///
/// Example:
/// print(underscore("DartVM DartCore"));
/// => dart_vm dart_core
String underscore(String string) {
if (string.isEmpty) {
return string;
}
var sb = StringBuffer();
var separate = false;
final characters = Characters(string);
for (final s in characters) {
final runes = s.runes;
var flag = 0;
if (runes.length == 1) {
var c = runes.first;
if (c <= _ASCII_END) {
flag = _ascii[c];
}
}
if (separate && flag & _UPPER != 0) {
sb.write('_');
sb.write(s.toLowerCase());
separate = true;
} else {
if (flag & _ALPHA_NUM != 0) {
separate = true;
} else if (flag & _UNDERSCORE != 0 && separate) {
separate = true;
} else {
separate = false;
}
sb.write(s.toLowerCase());
}
}
return sb.toString();
}
// TODO: Optimize via table
// TODO: Improve list of printable characters
bool _isPrintable(int character) {
switch (unicode.generalCategories[character]) {
case unicode.CONTROL:
case unicode.FORMAT:
case unicode.LINE_SEPARATOR:
case unicode.NOT_ASSIGNED:
case unicode.PARAGRAPH_SEPARATOR:
case unicode.PRIVATE_USE:
case unicode.SURROGATE:
return false;
default:
return true;
}
}