blob: 82c2f2337ff84972e5e0d711ec628277cedb4b17 [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/generated/interner.dart';
import 'package:analyzer/src/generated/java_core.dart';
export 'package:analyzer/exception/exception.dart';
/// A predicate is a one-argument function that returns a boolean value.
typedef Predicate<E> = bool Function(E argument);
class StringUtilities {
static const String EMPTY = '';
static const List<String> EMPTY_ARRAY = <String>[];
static Interner INTERNER = NullInterner();
/// Compute line starts for the given [content].
/// Lines end with `\r`, `\n` or `\r\n`.
static List<int> computeLineStarts(String content) {
List<int> lineStarts = <int>[0];
int length = content.length;
int unit;
for (int index = 0; index < length; index++) {
unit = content.codeUnitAt(index);
// Special-case \r\n.
if (unit == 0x0D /* \r */) {
// Peek ahead to detect a following \n.
if ((index + 1 < length) && content.codeUnitAt(index + 1) == 0x0A) {
// Line start will get registered at next index at the \n.
} else {
lineStarts.add(index + 1);
}
}
// \n
if (unit == 0x0A) {
lineStarts.add(index + 1);
}
}
return lineStarts;
}
static bool endsWith3(String str, int c1, int c2, int c3) {
var length = str.length;
return length >= 3 &&
str.codeUnitAt(length - 3) == c1 &&
str.codeUnitAt(length - 2) == c2 &&
str.codeUnitAt(length - 1) == c3;
}
static bool endsWithChar(String str, int c) {
int length = str.length;
return length > 0 && str.codeUnitAt(length - 1) == c;
}
static int indexOf1(String str, int start, int c) {
int index = start;
int last = str.length;
while (index < last) {
if (str.codeUnitAt(index) == c) {
return index;
}
index++;
}
return -1;
}
static int indexOf2(String str, int start, int c1, int c2) {
int index = start;
int last = str.length - 1;
while (index < last) {
if (str.codeUnitAt(index) == c1 && str.codeUnitAt(index + 1) == c2) {
return index;
}
index++;
}
return -1;
}
static int indexOf4(
String string, int start, int c1, int c2, int c3, int c4) {
int index = start;
int last = string.length - 3;
while (index < last) {
if (string.codeUnitAt(index) == c1 &&
string.codeUnitAt(index + 1) == c2 &&
string.codeUnitAt(index + 2) == c3 &&
string.codeUnitAt(index + 3) == c4) {
return index;
}
index++;
}
return -1;
}
static int indexOf5(
String str, int start, int c1, int c2, int c3, int c4, int c5) {
int index = start;
int last = str.length - 4;
while (index < last) {
if (str.codeUnitAt(index) == c1 &&
str.codeUnitAt(index + 1) == c2 &&
str.codeUnitAt(index + 2) == c3 &&
str.codeUnitAt(index + 3) == c4 &&
str.codeUnitAt(index + 4) == c5) {
return index;
}
index++;
}
return -1;
}
/// Return the index of the first not letter/digit character in the [string]
/// that is at or after the [startIndex]. Return the length of the [string] if
/// all characters to the end are letters/digits.
static int indexOfFirstNotLetterDigit(String string, int startIndex) {
int index = startIndex;
int last = string.length;
while (index < last) {
int c = string.codeUnitAt(index);
if (!Character.isLetterOrDigit(c)) {
return index;
}
index++;
}
return last;
}
static String intern(String string) => INTERNER.intern(string);
static bool isEmpty(String? s) {
return s == null || s.isEmpty;
}
static bool isTagName(String? s) {
if (s == null || s.isEmpty) {
return false;
}
int sz = s.length;
for (int i = 0; i < sz; i++) {
int c = s.codeUnitAt(i);
if (!Character.isLetter(c)) {
if (i == 0) {
return false;
}
if (!Character.isDigit(c) && c != 0x2D) {
return false;
}
}
}
return true;
}
/// Produce a string containing all of the names in the given array,
/// surrounded by single quotes, and separated by commas.
///
/// The list must contain at least two elements.
///
/// @param names the names to be printed
/// @return the result of printing the names
static String printListOfQuotedNames(List<String>? names) {
if (names == null) {
throw ArgumentError("The list must not be null");
}
int count = names.length;
if (count < 2) {
throw ArgumentError("The list must contain at least two names");
}
StringBuffer buffer = StringBuffer();
buffer.write("'");
buffer.write(names[0]);
buffer.write("'");
for (int i = 1; i < count - 1; i++) {
buffer.write(", '");
buffer.write(names[i]);
buffer.write("'");
}
buffer.write(" and '");
buffer.write(names[count - 1]);
buffer.write("'");
return buffer.toString();
}
static bool startsWith2(String str, int start, int c1, int c2) {
return str.length - start >= 2 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2;
}
static bool startsWith3(String str, int start, int c1, int c2, int c3) {
return str.length - start >= 3 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2 &&
str.codeUnitAt(start + 2) == c3;
}
static bool startsWith4(
String str, int start, int c1, int c2, int c3, int c4) {
return str.length - start >= 4 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2 &&
str.codeUnitAt(start + 2) == c3 &&
str.codeUnitAt(start + 3) == c4;
}
static bool startsWith5(
String str, int start, int c1, int c2, int c3, int c4, int c5) {
return str.length - start >= 5 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2 &&
str.codeUnitAt(start + 2) == c3 &&
str.codeUnitAt(start + 3) == c4 &&
str.codeUnitAt(start + 4) == c5;
}
static bool startsWith6(
String str, int start, int c1, int c2, int c3, int c4, int c5, int c6) {
return str.length - start >= 6 &&
str.codeUnitAt(start) == c1 &&
str.codeUnitAt(start + 1) == c2 &&
str.codeUnitAt(start + 2) == c3 &&
str.codeUnitAt(start + 3) == c4 &&
str.codeUnitAt(start + 4) == c5 &&
str.codeUnitAt(start + 5) == c6;
}
static String? substringBefore(String? str, String? separator) {
if (str == null || str.isEmpty) {
return str;
}
if (separator == null) {
return str;
}
int pos = str.indexOf(separator);
if (pos < 0) {
return str;
}
return str.substring(0, pos);
}
static String substringBeforeChar(String str, int c) {
if (isEmpty(str)) {
return str;
}
int pos = indexOf1(str, 0, c);
if (pos < 0) {
return str;
}
return str.substring(0, pos);
}
}
class UUID {
static const int __nextId = 0;
final String id;
UUID(this.id);
@override
String toString() => id;
static UUID randomUUID() => UUID((__nextId).toString());
}