Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions src/support/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,92 @@

namespace wasm::String {

Split::Split(const std::string& input, const NewLineOr& newLineOrDelim) {
auto first = input.find("\n", 0);
if (first != std::string::npos && first != input.length() - 1) {
split(input, "\n");
} else {
split(input, newLineOrDelim.delim);
}
}

void Split::split(const std::string& input, const std::string& delim) {
size_t lastEnd = 0;
while (lastEnd < input.size()) {
auto nextDelim = input.find(delim, lastEnd);
if (nextDelim == std::string::npos) {
nextDelim = input.size();
}
(*this).push_back(input.substr(lastEnd, nextDelim - lastEnd));
lastEnd = nextDelim + delim.size();
}
needToHandleBracketingOperations = delim != "\n";
}

Split handleBracketingOperators(Split split) {
if (!split.needToHandleBracketingOperations) {
return split;
}

Split ret;
std::string last;
int nesting = 0;
auto handlePart = [&](std::string part) {
if (part.empty()) {
return;
}
for (const char c : part) {
if (c == '(' || c == '<' || c == '[' || c == '{') {
nesting++;
} else if (c == ')' || c == '>' || c == ']' || c == '}') {
nesting--;
}
}
if (last.empty()) {
last = part;
} else {
last += ',' + part;
}
if (nesting == 0) {
ret.push_back(last);
last.clear();
}
};
for (auto& part : split) {
handlePart(part);
}
handlePart("");
if (nesting != 0) {
Fatal() << "Asyncify: failed to parse lists";
}
return ret;
}

bool wildcardMatch(const std::string& pattern, const std::string& value) {
for (size_t i = 0; i < pattern.size(); i++) {
if (pattern[i] == '*') {
return wildcardMatch(pattern.substr(i + 1), value.substr(i)) ||
(value.size() > 0 &&
wildcardMatch(pattern.substr(i), value.substr(i + 1)));
}
if (i >= value.size()) {
return false;
}
if (pattern[i] != value[i]) {
return false;
}
}
return value.size() == pattern.size();
}

std::string trim(const std::string& input) {
size_t size = input.size();
while (size > 0 && (isspace(input[size - 1]) || input[size - 1] == '\0')) {
size--;
}
return input.substr(0, size);
}

std::ostream& printEscaped(std::ostream& os, std::string_view str) {
os << '"';
for (unsigned char c : str) {
Expand Down
90 changes: 6 additions & 84 deletions src/support/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,8 @@ class Split : public std::vector<std::string> {
// "bar".
bool needToHandleBracketingOperations = true;

void split(const std::string& input, const std::string& delim) {
size_t lastEnd = 0;
while (lastEnd < input.size()) {
auto nextDelim = input.find(delim, lastEnd);
if (nextDelim == std::string::npos) {
nextDelim = input.size();
}
(*this).push_back(input.substr(lastEnd, nextDelim - lastEnd));
lastEnd = nextDelim + delim.size();
}
needToHandleBracketingOperations = delim != "\n";
}
friend String::Split handleBracketingOperators(String::Split split);
void split(const std::string& input, const std::string& delim);
friend Split handleBracketingOperators(Split split);

public:
// This can be used when we want to split on newlines if there are any, and if
Expand All @@ -63,15 +52,7 @@ class Split : public std::vector<std::string> {

Split() = default;

Split(const std::string& input, const NewLineOr& newLineOrDelim) {
auto first = input.find("\n", 0);
if (first != std::string::npos && first != input.length() - 1) {
split(input, "\n");
} else {
split(input, newLineOrDelim.delim);
}
}

Split(const std::string& input, const NewLineOr& newLineOrDelim);
Split(const std::string& input, const std::string& delim) {
split(input, delim);
}
Expand All @@ -82,72 +63,13 @@ class Split : public std::vector<std::string> {
// void foo(int, double)
// must be kept together because of the "(". Likewise, "{", "<", "[" are
// handled.
inline String::Split handleBracketingOperators(String::Split split) {
if (!split.needToHandleBracketingOperations) {
return split;
}

String::Split ret;
std::string last;
int nesting = 0;
auto handlePart = [&](std::string part) {
if (part.empty()) {
return;
}
for (const char c : part) {
if (c == '(' || c == '<' || c == '[' || c == '{') {
nesting++;
} else if (c == ')' || c == '>' || c == ']' || c == '}') {
nesting--;
}
}
if (last.empty()) {
last = part;
} else {
last += ',' + part;
}
if (nesting == 0) {
ret.push_back(last);
last.clear();
}
};
for (auto& part : split) {
handlePart(part);
}
handlePart("");
if (nesting != 0) {
Fatal() << "Asyncify: failed to parse lists";
}
return ret;
}
Split handleBracketingOperators(Split split);

// Does a simple '*' wildcard match between a pattern and a value.
inline bool wildcardMatch(const std::string& pattern,
const std::string& value) {
for (size_t i = 0; i < pattern.size(); i++) {
if (pattern[i] == '*') {
return wildcardMatch(pattern.substr(i + 1), value.substr(i)) ||
(value.size() > 0 &&
wildcardMatch(pattern.substr(i), value.substr(i + 1)));
}
if (i >= value.size()) {
return false;
}
if (pattern[i] != value[i]) {
return false;
}
}
return value.size() == pattern.size();
}
bool wildcardMatch(const std::string& pattern, const std::string& value);

// Removes any extra whitespace or \0.
inline std::string trim(const std::string& input) {
size_t size = input.size();
while (size > 0 && (isspace(input[size - 1]) || input[size - 1] == '\0')) {
size--;
}
return input.substr(0, size);
}
std::string trim(const std::string& input);

inline bool isNumber(const std::string& str) {
return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
Expand Down