xref: /aosp_15_r20/external/angle/src/common/string_utils.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // string_utils:
7*8975f5c5SAndroid Build Coastguard Worker //   String helper functions.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include <stdlib.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <string.h>
14*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
15*8975f5c5SAndroid Build Coastguard Worker #include <cctype>
16*8975f5c5SAndroid Build Coastguard Worker #include <fstream>
17*8975f5c5SAndroid Build Coastguard Worker #include <sstream>
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker #include "common/platform.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker namespace
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker 
EndsWithSuffix(const char * str,const size_t strLen,const char * suffix,const size_t suffixLen)25*8975f5c5SAndroid Build Coastguard Worker bool EndsWithSuffix(const char *str,
26*8975f5c5SAndroid Build Coastguard Worker                     const size_t strLen,
27*8975f5c5SAndroid Build Coastguard Worker                     const char *suffix,
28*8975f5c5SAndroid Build Coastguard Worker                     const size_t suffixLen)
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker     return suffixLen <= strLen && strncmp(str + strLen - suffixLen, suffix, suffixLen) == 0;
31*8975f5c5SAndroid Build Coastguard Worker }
32*8975f5c5SAndroid Build Coastguard Worker 
33*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
34*8975f5c5SAndroid Build Coastguard Worker 
35*8975f5c5SAndroid Build Coastguard Worker namespace angle
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker 
38*8975f5c5SAndroid Build Coastguard Worker const char kWhitespaceASCII[] = " \f\n\r\t\v";
39*8975f5c5SAndroid Build Coastguard Worker 
SplitString(const std::string & input,const std::string & delimiters,WhitespaceHandling whitespace,SplitResult resultType)40*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> SplitString(const std::string &input,
41*8975f5c5SAndroid Build Coastguard Worker                                      const std::string &delimiters,
42*8975f5c5SAndroid Build Coastguard Worker                                      WhitespaceHandling whitespace,
43*8975f5c5SAndroid Build Coastguard Worker                                      SplitResult resultType)
44*8975f5c5SAndroid Build Coastguard Worker {
45*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> result;
46*8975f5c5SAndroid Build Coastguard Worker     if (input.empty())
47*8975f5c5SAndroid Build Coastguard Worker     {
48*8975f5c5SAndroid Build Coastguard Worker         return result;
49*8975f5c5SAndroid Build Coastguard Worker     }
50*8975f5c5SAndroid Build Coastguard Worker 
51*8975f5c5SAndroid Build Coastguard Worker     std::string::size_type start = 0;
52*8975f5c5SAndroid Build Coastguard Worker     while (start != std::string::npos)
53*8975f5c5SAndroid Build Coastguard Worker     {
54*8975f5c5SAndroid Build Coastguard Worker         auto end = input.find_first_of(delimiters, start);
55*8975f5c5SAndroid Build Coastguard Worker 
56*8975f5c5SAndroid Build Coastguard Worker         std::string piece;
57*8975f5c5SAndroid Build Coastguard Worker         if (end == std::string::npos)
58*8975f5c5SAndroid Build Coastguard Worker         {
59*8975f5c5SAndroid Build Coastguard Worker             piece = input.substr(start);
60*8975f5c5SAndroid Build Coastguard Worker             start = std::string::npos;
61*8975f5c5SAndroid Build Coastguard Worker         }
62*8975f5c5SAndroid Build Coastguard Worker         else
63*8975f5c5SAndroid Build Coastguard Worker         {
64*8975f5c5SAndroid Build Coastguard Worker             piece = input.substr(start, end - start);
65*8975f5c5SAndroid Build Coastguard Worker             start = end + 1;
66*8975f5c5SAndroid Build Coastguard Worker         }
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker         if (whitespace == TRIM_WHITESPACE)
69*8975f5c5SAndroid Build Coastguard Worker         {
70*8975f5c5SAndroid Build Coastguard Worker             piece = TrimString(piece, kWhitespaceASCII);
71*8975f5c5SAndroid Build Coastguard Worker         }
72*8975f5c5SAndroid Build Coastguard Worker 
73*8975f5c5SAndroid Build Coastguard Worker         if (resultType == SPLIT_WANT_ALL || !piece.empty())
74*8975f5c5SAndroid Build Coastguard Worker         {
75*8975f5c5SAndroid Build Coastguard Worker             result.push_back(std::move(piece));
76*8975f5c5SAndroid Build Coastguard Worker         }
77*8975f5c5SAndroid Build Coastguard Worker     }
78*8975f5c5SAndroid Build Coastguard Worker 
79*8975f5c5SAndroid Build Coastguard Worker     return result;
80*8975f5c5SAndroid Build Coastguard Worker }
81*8975f5c5SAndroid Build Coastguard Worker 
SplitStringAlongWhitespace(const std::string & input,std::vector<std::string> * tokensOut)82*8975f5c5SAndroid Build Coastguard Worker void SplitStringAlongWhitespace(const std::string &input, std::vector<std::string> *tokensOut)
83*8975f5c5SAndroid Build Coastguard Worker {
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker     std::istringstream stream(input);
86*8975f5c5SAndroid Build Coastguard Worker     std::string line;
87*8975f5c5SAndroid Build Coastguard Worker 
88*8975f5c5SAndroid Build Coastguard Worker     while (std::getline(stream, line))
89*8975f5c5SAndroid Build Coastguard Worker     {
90*8975f5c5SAndroid Build Coastguard Worker         size_t prev = 0, pos;
91*8975f5c5SAndroid Build Coastguard Worker         while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
92*8975f5c5SAndroid Build Coastguard Worker         {
93*8975f5c5SAndroid Build Coastguard Worker             if (pos > prev)
94*8975f5c5SAndroid Build Coastguard Worker                 tokensOut->push_back(line.substr(prev, pos - prev));
95*8975f5c5SAndroid Build Coastguard Worker             prev = pos + 1;
96*8975f5c5SAndroid Build Coastguard Worker         }
97*8975f5c5SAndroid Build Coastguard Worker         if (prev < line.length())
98*8975f5c5SAndroid Build Coastguard Worker             tokensOut->push_back(line.substr(prev, std::string::npos));
99*8975f5c5SAndroid Build Coastguard Worker     }
100*8975f5c5SAndroid Build Coastguard Worker }
101*8975f5c5SAndroid Build Coastguard Worker 
TrimString(const std::string & input,const std::string & trimChars)102*8975f5c5SAndroid Build Coastguard Worker std::string TrimString(const std::string &input, const std::string &trimChars)
103*8975f5c5SAndroid Build Coastguard Worker {
104*8975f5c5SAndroid Build Coastguard Worker     auto begin = input.find_first_not_of(trimChars);
105*8975f5c5SAndroid Build Coastguard Worker     if (begin == std::string::npos)
106*8975f5c5SAndroid Build Coastguard Worker     {
107*8975f5c5SAndroid Build Coastguard Worker         return "";
108*8975f5c5SAndroid Build Coastguard Worker     }
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker     std::string::size_type end = input.find_last_not_of(trimChars);
111*8975f5c5SAndroid Build Coastguard Worker     if (end == std::string::npos)
112*8975f5c5SAndroid Build Coastguard Worker     {
113*8975f5c5SAndroid Build Coastguard Worker         return input.substr(begin);
114*8975f5c5SAndroid Build Coastguard Worker     }
115*8975f5c5SAndroid Build Coastguard Worker 
116*8975f5c5SAndroid Build Coastguard Worker     return input.substr(begin, end - begin + 1);
117*8975f5c5SAndroid Build Coastguard Worker }
118*8975f5c5SAndroid Build Coastguard Worker 
GetPrefix(const std::string & input,size_t offset,const char * delimiter)119*8975f5c5SAndroid Build Coastguard Worker std::string GetPrefix(const std::string &input, size_t offset, const char *delimiter)
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker     size_t match = input.find(delimiter, offset);
122*8975f5c5SAndroid Build Coastguard Worker     if (match == std::string::npos)
123*8975f5c5SAndroid Build Coastguard Worker     {
124*8975f5c5SAndroid Build Coastguard Worker         return input.substr(offset);
125*8975f5c5SAndroid Build Coastguard Worker     }
126*8975f5c5SAndroid Build Coastguard Worker     return input.substr(offset, match - offset);
127*8975f5c5SAndroid Build Coastguard Worker }
128*8975f5c5SAndroid Build Coastguard Worker 
GetPrefix(const std::string & input,size_t offset,char delimiter)129*8975f5c5SAndroid Build Coastguard Worker std::string GetPrefix(const std::string &input, size_t offset, char delimiter)
130*8975f5c5SAndroid Build Coastguard Worker {
131*8975f5c5SAndroid Build Coastguard Worker     size_t match = input.find(delimiter, offset);
132*8975f5c5SAndroid Build Coastguard Worker     if (match == std::string::npos)
133*8975f5c5SAndroid Build Coastguard Worker     {
134*8975f5c5SAndroid Build Coastguard Worker         return input.substr(offset);
135*8975f5c5SAndroid Build Coastguard Worker     }
136*8975f5c5SAndroid Build Coastguard Worker     return input.substr(offset, match - offset);
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker 
HexStringToUInt(const std::string & input,unsigned int * uintOut)139*8975f5c5SAndroid Build Coastguard Worker bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker     unsigned int offset = 0;
142*8975f5c5SAndroid Build Coastguard Worker 
143*8975f5c5SAndroid Build Coastguard Worker     if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
144*8975f5c5SAndroid Build Coastguard Worker     {
145*8975f5c5SAndroid Build Coastguard Worker         offset = 2u;
146*8975f5c5SAndroid Build Coastguard Worker     }
147*8975f5c5SAndroid Build Coastguard Worker 
148*8975f5c5SAndroid Build Coastguard Worker     // Simple validity check
149*8975f5c5SAndroid Build Coastguard Worker     if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
150*8975f5c5SAndroid Build Coastguard Worker     {
151*8975f5c5SAndroid Build Coastguard Worker         return false;
152*8975f5c5SAndroid Build Coastguard Worker     }
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker     std::stringstream inStream(input);
155*8975f5c5SAndroid Build Coastguard Worker     inStream >> std::hex >> *uintOut;
156*8975f5c5SAndroid Build Coastguard Worker     return !inStream.fail();
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker 
ReadFileToString(const std::string & path,std::string * stringOut)159*8975f5c5SAndroid Build Coastguard Worker bool ReadFileToString(const std::string &path, std::string *stringOut)
160*8975f5c5SAndroid Build Coastguard Worker {
161*8975f5c5SAndroid Build Coastguard Worker     std::ifstream inFile(path.c_str(), std::ios::binary);
162*8975f5c5SAndroid Build Coastguard Worker     if (inFile.fail())
163*8975f5c5SAndroid Build Coastguard Worker     {
164*8975f5c5SAndroid Build Coastguard Worker         return false;
165*8975f5c5SAndroid Build Coastguard Worker     }
166*8975f5c5SAndroid Build Coastguard Worker 
167*8975f5c5SAndroid Build Coastguard Worker     inFile.seekg(0, std::ios::end);
168*8975f5c5SAndroid Build Coastguard Worker     auto size = static_cast<std::string::size_type>(inFile.tellg());
169*8975f5c5SAndroid Build Coastguard Worker     stringOut->resize(size);
170*8975f5c5SAndroid Build Coastguard Worker     inFile.seekg(0, std::ios::beg);
171*8975f5c5SAndroid Build Coastguard Worker 
172*8975f5c5SAndroid Build Coastguard Worker     inFile.read(stringOut->data(), size);
173*8975f5c5SAndroid Build Coastguard Worker     return !inFile.fail();
174*8975f5c5SAndroid Build Coastguard Worker }
175*8975f5c5SAndroid Build Coastguard Worker 
BeginsWith(const std::string & str,const std::string & prefix)176*8975f5c5SAndroid Build Coastguard Worker bool BeginsWith(const std::string &str, const std::string &prefix)
177*8975f5c5SAndroid Build Coastguard Worker {
178*8975f5c5SAndroid Build Coastguard Worker     return strncmp(str.c_str(), prefix.c_str(), prefix.length()) == 0;
179*8975f5c5SAndroid Build Coastguard Worker }
180*8975f5c5SAndroid Build Coastguard Worker 
BeginsWith(const std::string & str,const char * prefix)181*8975f5c5SAndroid Build Coastguard Worker bool BeginsWith(const std::string &str, const char *prefix)
182*8975f5c5SAndroid Build Coastguard Worker {
183*8975f5c5SAndroid Build Coastguard Worker     return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
184*8975f5c5SAndroid Build Coastguard Worker }
185*8975f5c5SAndroid Build Coastguard Worker 
BeginsWith(const char * str,const char * prefix)186*8975f5c5SAndroid Build Coastguard Worker bool BeginsWith(const char *str, const char *prefix)
187*8975f5c5SAndroid Build Coastguard Worker {
188*8975f5c5SAndroid Build Coastguard Worker     return strncmp(str, prefix, strlen(prefix)) == 0;
189*8975f5c5SAndroid Build Coastguard Worker }
190*8975f5c5SAndroid Build Coastguard Worker 
BeginsWith(const std::string & str,const std::string & prefix,const size_t prefixLength)191*8975f5c5SAndroid Build Coastguard Worker bool BeginsWith(const std::string &str, const std::string &prefix, const size_t prefixLength)
192*8975f5c5SAndroid Build Coastguard Worker {
193*8975f5c5SAndroid Build Coastguard Worker     return strncmp(str.c_str(), prefix.c_str(), prefixLength) == 0;
194*8975f5c5SAndroid Build Coastguard Worker }
195*8975f5c5SAndroid Build Coastguard Worker 
EndsWith(const std::string & str,const std::string & suffix)196*8975f5c5SAndroid Build Coastguard Worker bool EndsWith(const std::string &str, const std::string &suffix)
197*8975f5c5SAndroid Build Coastguard Worker {
198*8975f5c5SAndroid Build Coastguard Worker     return EndsWithSuffix(str.c_str(), str.length(), suffix.c_str(), suffix.length());
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker 
EndsWith(const std::string & str,const char * suffix)201*8975f5c5SAndroid Build Coastguard Worker bool EndsWith(const std::string &str, const char *suffix)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker     return EndsWithSuffix(str.c_str(), str.length(), suffix, strlen(suffix));
204*8975f5c5SAndroid Build Coastguard Worker }
205*8975f5c5SAndroid Build Coastguard Worker 
EndsWith(const char * str,const char * suffix)206*8975f5c5SAndroid Build Coastguard Worker bool EndsWith(const char *str, const char *suffix)
207*8975f5c5SAndroid Build Coastguard Worker {
208*8975f5c5SAndroid Build Coastguard Worker     return EndsWithSuffix(str, strlen(str), suffix, strlen(suffix));
209*8975f5c5SAndroid Build Coastguard Worker }
210*8975f5c5SAndroid Build Coastguard Worker 
ContainsToken(const std::string & tokenStr,char delimiter,const std::string & token)211*8975f5c5SAndroid Build Coastguard Worker bool ContainsToken(const std::string &tokenStr, char delimiter, const std::string &token)
212*8975f5c5SAndroid Build Coastguard Worker {
213*8975f5c5SAndroid Build Coastguard Worker     if (token.empty())
214*8975f5c5SAndroid Build Coastguard Worker     {
215*8975f5c5SAndroid Build Coastguard Worker         return false;
216*8975f5c5SAndroid Build Coastguard Worker     }
217*8975f5c5SAndroid Build Coastguard Worker     // Compare token with all sub-strings terminated by delimiter or end of string
218*8975f5c5SAndroid Build Coastguard Worker     std::string::size_type start = 0u;
219*8975f5c5SAndroid Build Coastguard Worker     do
220*8975f5c5SAndroid Build Coastguard Worker     {
221*8975f5c5SAndroid Build Coastguard Worker         std::string::size_type end = tokenStr.find(delimiter, start);
222*8975f5c5SAndroid Build Coastguard Worker         if (end == std::string::npos)
223*8975f5c5SAndroid Build Coastguard Worker         {
224*8975f5c5SAndroid Build Coastguard Worker             end = tokenStr.length();
225*8975f5c5SAndroid Build Coastguard Worker         }
226*8975f5c5SAndroid Build Coastguard Worker         const std::string::size_type length = end - start;
227*8975f5c5SAndroid Build Coastguard Worker         if (length == token.length() && tokenStr.compare(start, length, token) == 0)
228*8975f5c5SAndroid Build Coastguard Worker         {
229*8975f5c5SAndroid Build Coastguard Worker             return true;
230*8975f5c5SAndroid Build Coastguard Worker         }
231*8975f5c5SAndroid Build Coastguard Worker         start = end + 1u;
232*8975f5c5SAndroid Build Coastguard Worker     } while (start < tokenStr.size());
233*8975f5c5SAndroid Build Coastguard Worker     return false;
234*8975f5c5SAndroid Build Coastguard Worker }
235*8975f5c5SAndroid Build Coastguard Worker 
ToLower(std::string * str)236*8975f5c5SAndroid Build Coastguard Worker void ToLower(std::string *str)
237*8975f5c5SAndroid Build Coastguard Worker {
238*8975f5c5SAndroid Build Coastguard Worker     for (char &ch : *str)
239*8975f5c5SAndroid Build Coastguard Worker     {
240*8975f5c5SAndroid Build Coastguard Worker         ch = static_cast<char>(::tolower(ch));
241*8975f5c5SAndroid Build Coastguard Worker     }
242*8975f5c5SAndroid Build Coastguard Worker }
243*8975f5c5SAndroid Build Coastguard Worker 
ToUpper(std::string * str)244*8975f5c5SAndroid Build Coastguard Worker void ToUpper(std::string *str)
245*8975f5c5SAndroid Build Coastguard Worker {
246*8975f5c5SAndroid Build Coastguard Worker     for (char &ch : *str)
247*8975f5c5SAndroid Build Coastguard Worker     {
248*8975f5c5SAndroid Build Coastguard Worker         ch = static_cast<char>(::toupper(ch));
249*8975f5c5SAndroid Build Coastguard Worker     }
250*8975f5c5SAndroid Build Coastguard Worker }
251*8975f5c5SAndroid Build Coastguard Worker 
ReplaceSubstring(std::string * str,const std::string & substring,const std::string & replacement)252*8975f5c5SAndroid Build Coastguard Worker bool ReplaceSubstring(std::string *str,
253*8975f5c5SAndroid Build Coastguard Worker                       const std::string &substring,
254*8975f5c5SAndroid Build Coastguard Worker                       const std::string &replacement)
255*8975f5c5SAndroid Build Coastguard Worker {
256*8975f5c5SAndroid Build Coastguard Worker     size_t replacePos = str->find(substring);
257*8975f5c5SAndroid Build Coastguard Worker     if (replacePos == std::string::npos)
258*8975f5c5SAndroid Build Coastguard Worker     {
259*8975f5c5SAndroid Build Coastguard Worker         return false;
260*8975f5c5SAndroid Build Coastguard Worker     }
261*8975f5c5SAndroid Build Coastguard Worker     str->replace(replacePos, substring.size(), replacement);
262*8975f5c5SAndroid Build Coastguard Worker     return true;
263*8975f5c5SAndroid Build Coastguard Worker }
264*8975f5c5SAndroid Build Coastguard Worker 
ReplaceAllSubstrings(std::string * str,const std::string & substring,const std::string & replacement)265*8975f5c5SAndroid Build Coastguard Worker int ReplaceAllSubstrings(std::string *str,
266*8975f5c5SAndroid Build Coastguard Worker                          const std::string &substring,
267*8975f5c5SAndroid Build Coastguard Worker                          const std::string &replacement)
268*8975f5c5SAndroid Build Coastguard Worker {
269*8975f5c5SAndroid Build Coastguard Worker     int count = 0;
270*8975f5c5SAndroid Build Coastguard Worker     while (ReplaceSubstring(str, substring, replacement))
271*8975f5c5SAndroid Build Coastguard Worker     {
272*8975f5c5SAndroid Build Coastguard Worker         count++;
273*8975f5c5SAndroid Build Coastguard Worker     }
274*8975f5c5SAndroid Build Coastguard Worker     return count;
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker 
ToCamelCase(const std::string & str)277*8975f5c5SAndroid Build Coastguard Worker std::string ToCamelCase(const std::string &str)
278*8975f5c5SAndroid Build Coastguard Worker {
279*8975f5c5SAndroid Build Coastguard Worker     std::string result;
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker     bool lastWasUnderscore = false;
282*8975f5c5SAndroid Build Coastguard Worker     for (char c : str)
283*8975f5c5SAndroid Build Coastguard Worker     {
284*8975f5c5SAndroid Build Coastguard Worker         if (c == '_')
285*8975f5c5SAndroid Build Coastguard Worker         {
286*8975f5c5SAndroid Build Coastguard Worker             lastWasUnderscore = true;
287*8975f5c5SAndroid Build Coastguard Worker             continue;
288*8975f5c5SAndroid Build Coastguard Worker         }
289*8975f5c5SAndroid Build Coastguard Worker 
290*8975f5c5SAndroid Build Coastguard Worker         if (lastWasUnderscore)
291*8975f5c5SAndroid Build Coastguard Worker         {
292*8975f5c5SAndroid Build Coastguard Worker             c                 = static_cast<char>(std::toupper(c));
293*8975f5c5SAndroid Build Coastguard Worker             lastWasUnderscore = false;
294*8975f5c5SAndroid Build Coastguard Worker         }
295*8975f5c5SAndroid Build Coastguard Worker         result += c;
296*8975f5c5SAndroid Build Coastguard Worker     }
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker     return result;
299*8975f5c5SAndroid Build Coastguard Worker }
300*8975f5c5SAndroid Build Coastguard Worker 
GetStringsFromEnvironmentVarOrAndroidProperty(const char * varName,const char * propertyName,const char * separator)301*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> GetStringsFromEnvironmentVarOrAndroidProperty(const char *varName,
302*8975f5c5SAndroid Build Coastguard Worker                                                                        const char *propertyName,
303*8975f5c5SAndroid Build Coastguard Worker                                                                        const char *separator)
304*8975f5c5SAndroid Build Coastguard Worker {
305*8975f5c5SAndroid Build Coastguard Worker     std::string environment = GetEnvironmentVarOrAndroidProperty(varName, propertyName);
306*8975f5c5SAndroid Build Coastguard Worker     return SplitString(environment, separator, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
307*8975f5c5SAndroid Build Coastguard Worker }
308*8975f5c5SAndroid Build Coastguard Worker 
GetCachedStringsFromEnvironmentVarOrAndroidProperty(const char * varName,const char * propertyName,const char * separator)309*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> GetCachedStringsFromEnvironmentVarOrAndroidProperty(
310*8975f5c5SAndroid Build Coastguard Worker     const char *varName,
311*8975f5c5SAndroid Build Coastguard Worker     const char *propertyName,
312*8975f5c5SAndroid Build Coastguard Worker     const char *separator)
313*8975f5c5SAndroid Build Coastguard Worker {
314*8975f5c5SAndroid Build Coastguard Worker     std::string environment = GetEnvironmentVarOrAndroidProperty(varName, propertyName);
315*8975f5c5SAndroid Build Coastguard Worker     return SplitString(environment, separator, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
316*8975f5c5SAndroid Build Coastguard Worker }
317*8975f5c5SAndroid Build Coastguard Worker 
318*8975f5c5SAndroid Build Coastguard Worker // glob can have * as wildcard
NamesMatchWithWildcard(const char * glob,const char * name)319*8975f5c5SAndroid Build Coastguard Worker bool NamesMatchWithWildcard(const char *glob, const char *name)
320*8975f5c5SAndroid Build Coastguard Worker {
321*8975f5c5SAndroid Build Coastguard Worker     // Find the first * in glob.
322*8975f5c5SAndroid Build Coastguard Worker     const char *firstWildcard = strchr(glob, '*');
323*8975f5c5SAndroid Build Coastguard Worker 
324*8975f5c5SAndroid Build Coastguard Worker     // If there are no wildcards, match the strings precisely.
325*8975f5c5SAndroid Build Coastguard Worker     if (firstWildcard == nullptr)
326*8975f5c5SAndroid Build Coastguard Worker     {
327*8975f5c5SAndroid Build Coastguard Worker         return strcmp(glob, name) == 0;
328*8975f5c5SAndroid Build Coastguard Worker     }
329*8975f5c5SAndroid Build Coastguard Worker 
330*8975f5c5SAndroid Build Coastguard Worker     // Otherwise, match up to the wildcard first.
331*8975f5c5SAndroid Build Coastguard Worker     size_t preWildcardLen = firstWildcard - glob;
332*8975f5c5SAndroid Build Coastguard Worker     if (strncmp(glob, name, preWildcardLen) != 0)
333*8975f5c5SAndroid Build Coastguard Worker     {
334*8975f5c5SAndroid Build Coastguard Worker         return false;
335*8975f5c5SAndroid Build Coastguard Worker     }
336*8975f5c5SAndroid Build Coastguard Worker 
337*8975f5c5SAndroid Build Coastguard Worker     const char *postWildcardRef = glob + preWildcardLen + 1;
338*8975f5c5SAndroid Build Coastguard Worker 
339*8975f5c5SAndroid Build Coastguard Worker     // As a small optimization, if the wildcard is the last character in glob, accept the match
340*8975f5c5SAndroid Build Coastguard Worker     // already.
341*8975f5c5SAndroid Build Coastguard Worker     if (postWildcardRef[0] == '\0')
342*8975f5c5SAndroid Build Coastguard Worker     {
343*8975f5c5SAndroid Build Coastguard Worker         return true;
344*8975f5c5SAndroid Build Coastguard Worker     }
345*8975f5c5SAndroid Build Coastguard Worker 
346*8975f5c5SAndroid Build Coastguard Worker     // Try to match the wildcard with a number of characters.
347*8975f5c5SAndroid Build Coastguard Worker     for (size_t matchSize = 0; name[matchSize] != '\0'; ++matchSize)
348*8975f5c5SAndroid Build Coastguard Worker     {
349*8975f5c5SAndroid Build Coastguard Worker         if (NamesMatchWithWildcard(postWildcardRef, name + matchSize))
350*8975f5c5SAndroid Build Coastguard Worker         {
351*8975f5c5SAndroid Build Coastguard Worker             return true;
352*8975f5c5SAndroid Build Coastguard Worker         }
353*8975f5c5SAndroid Build Coastguard Worker     }
354*8975f5c5SAndroid Build Coastguard Worker 
355*8975f5c5SAndroid Build Coastguard Worker     return false;
356*8975f5c5SAndroid Build Coastguard Worker }
357*8975f5c5SAndroid Build Coastguard Worker 
358*8975f5c5SAndroid Build Coastguard Worker }  // namespace angle
359