1 /*
2 * Copyright 2019 WebAssembly Community Group participants
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //
18 // String helpers.
19 //
20
21 #ifndef wasm_support_string_h
22 #define wasm_support_string_h
23
24 #include <cctype>
25 #include <string>
26 #include <vector>
27
28 namespace wasm {
29
30 namespace String {
31
32 // Creates a vector of the split parts of a string, by a delimiter.
33 class Split : public std::vector<std::string> {
34 public:
35 Split() = default;
36
Split(const std::string & input,const std::string & delim)37 Split(const std::string& input, const std::string& delim) {
38 size_t lastEnd = 0;
39 while (lastEnd < input.size()) {
40 auto nextDelim = input.find(delim, lastEnd);
41 if (nextDelim == std::string::npos) {
42 nextDelim = input.size();
43 }
44 (*this).push_back(input.substr(lastEnd, nextDelim - lastEnd));
45 lastEnd = nextDelim + delim.size();
46 }
47 }
48 };
49
50 // Handles bracketing in a list initially split by ",", but the list may
51 // contain nested ","s. For example,
52 // void foo(int, double)
53 // must be kept together because of the "(". Likewise, "{", "<", "[" are
54 // handled.
handleBracketingOperators(String::Split split)55 inline String::Split handleBracketingOperators(String::Split split) {
56 String::Split ret;
57 std::string last;
58 int nesting = 0;
59 auto handlePart = [&](std::string part) {
60 if (part.empty()) {
61 return;
62 }
63 for (const char c : part) {
64 if (c == '(' || c == '<' || c == '[' || c == '{') {
65 nesting++;
66 } else if (c == ')' || c == '>' || c == ']' || c == '}') {
67 nesting--;
68 }
69 }
70 if (last.empty()) {
71 last = part;
72 } else {
73 last += ',' + part;
74 }
75 if (nesting == 0) {
76 ret.push_back(last);
77 last.clear();
78 }
79 };
80 for (auto& part : split) {
81 handlePart(part);
82 }
83 handlePart("");
84 if (nesting != 0) {
85 Fatal() << "Asyncify: failed to parse lists";
86 }
87 return ret;
88 }
89
90 // Does a simple '*' wildcard match between a pattern and a value.
wildcardMatch(const std::string & pattern,const std::string & value)91 inline bool wildcardMatch(const std::string& pattern,
92 const std::string& value) {
93 for (size_t i = 0; i < pattern.size(); i++) {
94 if (pattern[i] == '*') {
95 return wildcardMatch(pattern.substr(i + 1), value.substr(i)) ||
96 (value.size() > 0 &&
97 wildcardMatch(pattern.substr(i), value.substr(i + 1)));
98 }
99 if (i >= value.size()) {
100 return false;
101 }
102 if (pattern[i] != value[i]) {
103 return false;
104 }
105 }
106 return value.size() == pattern.size();
107 }
108
109 // Removes any extra whitespace or \0.
trim(const std::string & input)110 inline std::string trim(const std::string& input) {
111 size_t size = input.size();
112 while (size > 0 && (isspace(input[size - 1]) || input[size - 1] == '\0')) {
113 size--;
114 }
115 return input.substr(0, size);
116 }
117
118 } // namespace String
119
120 } // namespace wasm
121
122 #endif // wasm_support_string_h
123