blob: bb1edd245d2a14b791ac7170d73c95e52c0fcce9 [file] [log] [blame]
Jamie Madill8c5aeb62015-05-21 08:17:18 -04001//
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
Sami Väisänen46eaa942016-06-29 10:26:37 +030012#include <algorithm>
David Landell9146bfa2016-06-22 10:13:45 +020013#include <stdlib.h>
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include <string.h>
Jamie Madill8c5aeb62015-05-21 08:17:18 -040015#include <fstream>
16#include <sstream>
17
Jamie Madill8b9b7922016-05-19 13:13:37 -040018#include "common/platform.h"
19
Jamie Madill8c5aeb62015-05-21 08:17:18 -040020namespace angle
21{
22
Corentin Wallez47ac69c2015-11-24 11:15:57 -050023const char kWhitespaceASCII[] = " \f\n\r\t\v";
Jamie Madill8c5aeb62015-05-21 08:17:18 -040024
Corentin Wallez47ac69c2015-11-24 11:15:57 -050025std::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())
Jamie Madill8c5aeb62015-05-21 08:17:18 -040032 {
Corentin Wallez47ac69c2015-11-24 11:15:57 -050033 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)
Jamie Madill8c5aeb62015-05-21 08:17:18 -040043 {
Corentin Wallez47ac69c2015-11-24 11:15:57 -050044 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);
Jamie Madill8c5aeb62015-05-21 08:17:18 -040061 }
62 }
Corentin Wallez47ac69c2015-11-24 11:15:57 -050063
64 return result;
Jamie Madill8c5aeb62015-05-21 08:17:18 -040065}
66
67void SplitStringAlongWhitespace(const std::string &input,
68 std::vector<std::string> *tokensOut)
69{
Jamie Madill8c5aeb62015-05-21 08:17:18 -040070
71 std::istringstream stream(input);
72 std::string line;
73
74 while (std::getline(stream, line))
75 {
76 size_t prev = 0, pos;
Corentin Wallez47ac69c2015-11-24 11:15:57 -050077 while ((pos = line.find_first_of(kWhitespaceASCII, prev)) != std::string::npos)
Jamie Madill8c5aeb62015-05-21 08:17:18 -040078 {
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
Corentin Wallez47ac69c2015-11-24 11:15:57 -050088std::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
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400105bool HexStringToUInt(const std::string &input, unsigned int *uintOut)
106{
Jamie Madillc7be82a2015-06-01 14:14:04 -0400107 unsigned int offset = 0;
108
109 if (input.size() >= 2 && input[0] == '0' && input[1] == 'x')
110 {
111 offset = 2u;
112 }
113
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400114 // Simple validity check
Jamie Madillc7be82a2015-06-01 14:14:04 -0400115 if (input.find_first_not_of("0123456789ABCDEFabcdef", offset) != std::string::npos)
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400116 {
117 return false;
118 }
119
120 std::stringstream inStream(input);
121 inStream >> std::hex >> *uintOut;
122 return !inStream.fail();
123}
124
125bool ReadFileToString(const std::string &path, std::string *stringOut)
126{
127 std::ifstream inFile(path.c_str());
Jamie Madillc7be82a2015-06-01 14:14:04 -0400128 if (inFile.fail())
129 {
130 return false;
131 }
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400132
133 inFile.seekg(0, std::ios::end);
Jamie Madillc7be82a2015-06-01 14:14:04 -0400134 stringOut->reserve(static_cast<std::string::size_type>(inFile.tellg()));
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400135 inFile.seekg(0, std::ios::beg);
136
Jamie Madillc7be82a2015-06-01 14:14:04 -0400137 stringOut->assign(std::istreambuf_iterator<char>(inFile), std::istreambuf_iterator<char>());
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400138 return !inFile.fail();
139}
140
Jamie Madill8b9b7922016-05-19 13:13:37 -0400141Optional<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);
Jamie Madill8c5aeb62015-05-21 08:17:18 -0400159}
Jamie Madill8b9b7922016-05-19 13:13:37 -0400160
Sami Väisänen46eaa942016-06-29 10:26:37 +0300161bool BeginsWith(const std::string &str, const char *prefix)
162{
163 return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
164}
165
166bool BeginsWith(const char *str, const char *prefix)
167{
168 return strncmp(str, prefix, strlen(prefix)) == 0;
169}
170
171bool 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
Jamie Madill8b9b7922016-05-19 13:13:37 -0400182} // namespace angle