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 "string_utils.h"
11 
12 #include <algorithm>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <fstream>
16 #include <sstream>
17 
18 #include "common/platform.h"
19 
20 namespace angle
21 {
22 
23 const char kWhitespaceASCII[] = " \f\n\r\t\v";
24 
SplitString(const std::string & input,const std::string & delimiters,WhitespaceHandling whitespace,SplitResult resultType)25 std::vector<std::string> SplitString(const std::string &input,
26                                      const std::string &delimiters,
27                                      WhitespaceHandling whitespace,
28                                      SplitResult resultType)
29 {
30     std::vector<std::string> result;
31     if (input.empty())
32     {
33         return result;
34     }
35 
36     std::string::size_type start = 0;
37     while (start != std::string::npos)
38     {
39         auto end = input.find_first_of(delimiters, start);
40 
41         std::string piece;
42         if (end == std::string::npos)
43         {
44             piece = input.substr(start);
45             start = std::string::npos;
46         }
47         else
48         {
49             piece = input.substr(start, end - start);
50             start = end + 1;
51         }
52 
53         if (whitespace == TRIM_WHITESPACE)
54         {
55             piece = TrimString(piece, kWhitespaceASCII);
56         }
57 
58         if (resultType == SPLIT_WANT_ALL || !piece.empty())
59         {
60             result.push_back(piece);
61         }
62     }
63 
64     return result;
65 }
66 
SplitStringAlongWhitespace(const std::string & input,std::vector<std::string> * tokensOut)67 void SplitStringAlongWhitespace(const std::string &input,
68                                 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 
HexStringToUInt(const std::string & input,unsigned int * uintOut)105 bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
106 {
107     unsigned int offset = 0;
108 
109     if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
110     {
111         offset = 2u;
112     }
113 
114     // Simple validity check
115     if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
116     {
117         return false;
118     }
119 
120     std::stringstream inStream(input);
121     inStream >> std::hex >> *uintOut;
122     return !inStream.fail();
123 }
124 
ReadFileToString(const std::string & path,std::string * stringOut)125 bool ReadFileToString(const std::string &path, std::string *stringOut)
126 {
127     std::ifstream inFile(path.c_str());
128     if (inFile.fail())
129     {
130         return false;
131     }
132 
133     inFile.seekg(0, std::ios::end);
134     stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
135     inFile.seekg(0, std::ios::beg);
136 
137     stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
138     return !inFile.fail();
139 }
140 
WidenString(size_t length,const char * cString)141 Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString)
142 {
143     std::vector<wchar_t> wcstring(length + 1);
144 #if !defined(ANGLE_PLATFORM_WINDOWS)
145     size_t written = mbstowcs(wcstring.data(), cString, length + 1);
146     if (written == 0)
147     {
148         return Optional<std::vector<wchar_t>>::Invalid();
149     }
150 #else
151     size_t convertedChars = 0;
152     errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, cString, _TRUNCATE);
153     if (err != 0)
154     {
155         return Optional<std::vector<wchar_t>>::Invalid();
156     }
157 #endif
158     return Optional<std::vector<wchar_t>>(wcstring);
159 }
160 
BeginsWith(const std::string & str,const char * prefix)161 bool BeginsWith(const std::string &str, const char *prefix)
162 {
163     return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
164 }
165 
BeginsWith(const char * str,const char * prefix)166 bool BeginsWith(const char *str, const char *prefix)
167 {
168     return strncmp(str, prefix, strlen(prefix)) == 0;
169 }
170 
EndsWith(const std::string & str,const char * suffix)171 bool EndsWith(const std::string &str, const char *suffix)
172 {
173     const auto len = strlen(suffix);
174     if (len > str.size())
175         return false;
176 
177     const char *end = str.c_str() + str.size() - len;
178 
179     return memcmp(end, suffix, len) == 0;
180 }
181 
182 }  // namespace angle
183