• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // string_utils:
7 //   String helper functions.
8 //
9 
10 #include "common/string_utils.h"
11 
12 #include <stdlib.h>
13 #include <string.h>
14 #include <algorithm>
15 #include <fstream>
16 #include <sstream>
17 
18 #include "common/platform.h"
19 #include "common/system_utils.h"
20 
21 namespace angle
22 {
23 
24 const char kWhitespaceASCII[] = " \f\n\r\t\v";
25 
SplitString(const std::string & input,const std::string & delimiters,WhitespaceHandling whitespace,SplitResult resultType)26 std::vector<std::string> SplitString(const std::string &input,
27                                      const std::string &delimiters,
28                                      WhitespaceHandling whitespace,
29                                      SplitResult resultType)
30 {
31     std::vector<std::string> result;
32     if (input.empty())
33     {
34         return result;
35     }
36 
37     std::string::size_type start = 0;
38     while (start != std::string::npos)
39     {
40         auto end = input.find_first_of(delimiters, start);
41 
42         std::string piece;
43         if (end == std::string::npos)
44         {
45             piece = input.substr(start);
46             start = std::string::npos;
47         }
48         else
49         {
50             piece = input.substr(start, end - start);
51             start = end + 1;
52         }
53 
54         if (whitespace == TRIM_WHITESPACE)
55         {
56             piece = TrimString(piece, kWhitespaceASCII);
57         }
58 
59         if (resultType == SPLIT_WANT_ALL || !piece.empty())
60         {
61             result.push_back(std::move(piece));
62         }
63     }
64 
65     return result;
66 }
67 
SplitStringAlongWhitespace(const std::string & input,std::vector<std::string> * tokensOut)68 void SplitStringAlongWhitespace(const std::string &input, std::vector<std::string> *tokensOut)
69 {
70 
71     std::istringstream stream(input);
72     std::string line;
73 
74     while (std::getline(stream, line))
75     {
76         size_t prev = 0, pos;
77         while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
78         {
79             if (pos > prev)
80                 tokensOut->push_back(line.substr(prev, pos - prev));
81             prev = pos + 1;
82         }
83         if (prev < line.length())
84             tokensOut->push_back(line.substr(prev, std::string::npos));
85     }
86 }
87 
TrimString(const std::string & input,const std::string & trimChars)88 std::string TrimString(const std::string &input, const std::string &trimChars)
89 {
90     auto begin = input.find_first_not_of(trimChars);
91     if (begin == std::string::npos)
92     {
93         return "";
94     }
95 
96     std::string::size_type end = input.find_last_not_of(trimChars);
97     if (end == std::string::npos)
98     {
99         return input.substr(begin);
100     }
101 
102     return input.substr(begin, end - begin + 1);
103 }
104 
GetPrefix(const std::string & input,size_t offset,const char * delimiter)105 std::string GetPrefix(const std::string &input, size_t offset, const char *delimiter)
106 {
107     size_t match = input.find(delimiter, offset);
108     if (match == std::string::npos)
109     {
110         return input.substr(offset);
111     }
112     return input.substr(offset, match - offset);
113 }
114 
GetPrefix(const std::string & input,size_t offset,char delimiter)115 std::string GetPrefix(const std::string &input, size_t offset, char delimiter)
116 {
117     size_t match = input.find(delimiter, offset);
118     if (match == std::string::npos)
119     {
120         return input.substr(offset);
121     }
122     return input.substr(offset, match - offset);
123 }
124 
HexStringToUInt(const std::string & input,unsigned int * uintOut)125 bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
126 {
127     unsigned int offset = 0;
128 
129     if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
130     {
131         offset = 2u;
132     }
133 
134     // Simple validity check
135     if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
136     {
137         return false;
138     }
139 
140     std::stringstream inStream(input);
141     inStream >> std::hex >> *uintOut;
142     return !inStream.fail();
143 }
144 
ReadFileToString(const std::string & path,std::string * stringOut)145 bool ReadFileToString(const std::string &path, std::string *stringOut)
146 {
147     std::ifstream inFile(path.c_str());
148     if (inFile.fail())
149     {
150         return false;
151     }
152 
153     inFile.seekg(0, std::ios::end);
154     stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
155     inFile.seekg(0, std::ios::beg);
156 
157     stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
158     return !inFile.fail();
159 }
160 
BeginsWith(const std::string & str,const std::string & prefix)161 bool BeginsWith(const std::string &str, const std::string &prefix)
162 {
163     return strncmp(str.c_str(), prefix.c_str(), prefix.length()) == 0;
164 }
165 
BeginsWith(const std::string & str,const char * prefix)166 bool BeginsWith(const std::string &str, const char *prefix)
167 {
168     return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
169 }
170 
BeginsWith(const char * str,const char * prefix)171 bool BeginsWith(const char *str, const char *prefix)
172 {
173     return strncmp(str, prefix, strlen(prefix)) == 0;
174 }
175 
BeginsWith(const std::string & str,const std::string & prefix,const size_t prefixLength)176 bool BeginsWith(const std::string &str, const std::string &prefix, const size_t prefixLength)
177 {
178     return strncmp(str.c_str(), prefix.c_str(), prefixLength) == 0;
179 }
180 
EndsWith(const std::string & str,const char * suffix)181 bool EndsWith(const std::string &str, const char *suffix)
182 {
183     const auto len = strlen(suffix);
184     if (len > str.size())
185         return false;
186 
187     const char *end = str.c_str() + str.size() - len;
188 
189     return memcmp(end, suffix, len) == 0;
190 }
191 
ToLower(std::string * str)192 void ToLower(std::string *str)
193 {
194     for (auto &ch : *str)
195     {
196         ch = static_cast<char>(::tolower(ch));
197     }
198 }
199 
ReplaceSubstring(std::string * str,const std::string & substring,const std::string & replacement)200 bool ReplaceSubstring(std::string *str,
201                       const std::string &substring,
202                       const std::string &replacement)
203 {
204     size_t replacePos = str->find(substring);
205     if (replacePos == std::string::npos)
206     {
207         return false;
208     }
209     str->replace(replacePos, substring.size(), replacement);
210     return true;
211 }
212 
GetStringsFromEnvironmentVar(const char * varName,const char * separator)213 std::vector<std::string> GetStringsFromEnvironmentVar(const char *varName, const char *separator)
214 {
215     std::string environment = GetEnvironmentVar(varName);
216     return SplitString(environment, separator, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
217 }
218 }  // namespace angle
219