summaryrefslogtreecommitdiff
path: root/src/common/string_util.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2016-09-21 11:29:48 -0700
committerGravatar GitHub2016-09-21 11:29:48 -0700
commitd5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a (patch)
tree8a22ca73ff838f3f0090b29a548ae81087fc90ed /src/common/string_util.cpp
parentREADME: Specify master branch for Travis CI badge (diff)
parentFix Travis clang-format check (diff)
downloadyuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.tar.gz
yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.tar.xz
yuzu-d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a.zip
Merge pull request #2086 from linkmauve/clang-format
Add clang-format as part of our {commit,travis}-time checks
Diffstat (limited to 'src/common/string_util.cpp')
-rw-r--r--src/common/string_util.cpp193
1 files changed, 75 insertions, 118 deletions
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index f0aa072db..596ae01bf 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -8,17 +8,15 @@
8#include <cstdlib> 8#include <cstdlib>
9#include <cstring> 9#include <cstring>
10#include <boost/range/algorithm/transform.hpp> 10#include <boost/range/algorithm/transform.hpp>
11
12#include "common/common_paths.h" 11#include "common/common_paths.h"
13#include "common/logging/log.h" 12#include "common/logging/log.h"
14#include "common/string_util.h" 13#include "common/string_util.h"
15
16#ifdef _MSC_VER 14#ifdef _MSC_VER
17 #include <Windows.h> 15#include <codecvt>
18 #include <codecvt> 16#include <Windows.h>
19 #include "common/common_funcs.h" 17#include "common/common_funcs.h"
20#else 18#else
21 #include <iconv.h> 19#include <iconv.h>
22#endif 20#endif
23 21
24namespace Common { 22namespace Common {
@@ -36,9 +34,8 @@ std::string ToUpper(std::string str) {
36} 34}
37 35
38// faster than sscanf 36// faster than sscanf
39bool AsciiToHex(const char* _szValue, u32& result) 37bool AsciiToHex(const char* _szValue, u32& result) {
40{ 38 char* endptr = nullptr;
41 char *endptr = nullptr;
42 const u32 value = strtoul(_szValue, &endptr, 16); 39 const u32 value = strtoul(_szValue, &endptr, 16);
43 40
44 if (!endptr || *endptr) 41 if (!endptr || *endptr)
@@ -48,8 +45,7 @@ bool AsciiToHex(const char* _szValue, u32& result)
48 return true; 45 return true;
49} 46}
50 47
51bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args) 48bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args) {
52{
53 int writtenCount; 49 int writtenCount;
54 50
55#ifdef _MSC_VER 51#ifdef _MSC_VER
@@ -84,22 +80,18 @@ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list ar
84 writtenCount = vsnprintf(out, outsize, format, args); 80 writtenCount = vsnprintf(out, outsize, format, args);
85#endif 81#endif
86 82
87 if (writtenCount > 0 && writtenCount < outsize) 83 if (writtenCount > 0 && writtenCount < outsize) {
88 {
89 out[writtenCount] = '\0'; 84 out[writtenCount] = '\0';
90 return true; 85 return true;
91 } 86 } else {
92 else
93 {
94 out[outsize - 1] = '\0'; 87 out[outsize - 1] = '\0';
95 return false; 88 return false;
96 } 89 }
97} 90}
98 91
99std::string StringFromFormat(const char* format, ...) 92std::string StringFromFormat(const char* format, ...) {
100{
101 va_list args; 93 va_list args;
102 char *buf = nullptr; 94 char* buf = nullptr;
103#ifdef _WIN32 95#ifdef _WIN32
104 int required = 0; 96 int required = 0;
105 97
@@ -124,21 +116,17 @@ std::string StringFromFormat(const char* format, ...)
124} 116}
125 117
126// For Debugging. Read out an u8 array. 118// For Debugging. Read out an u8 array.
127std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces) 119std::string ArrayToString(const u8* data, u32 size, int line_len, bool spaces) {
128{
129 std::ostringstream oss; 120 std::ostringstream oss;
130 oss << std::setfill('0') << std::hex; 121 oss << std::setfill('0') << std::hex;
131 122
132 for (int line = 0; size; ++data, --size) 123 for (int line = 0; size; ++data, --size) {
133 {
134 oss << std::setw(2) << (int)*data; 124 oss << std::setw(2) << (int)*data;
135 125
136 if (line_len == ++line) 126 if (line_len == ++line) {
137 {
138 oss << '\n'; 127 oss << '\n';
139 line = 0; 128 line = 0;
140 } 129 } else if (spaces)
141 else if (spaces)
142 oss << ' '; 130 oss << ' ';
143 } 131 }
144 132
@@ -146,8 +134,7 @@ std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces)
146} 134}
147 135
148// Turns " hej " into "hej". Also handles tabs. 136// Turns " hej " into "hej". Also handles tabs.
149std::string StripSpaces(const std::string &str) 137std::string StripSpaces(const std::string& str) {
150{
151 const size_t s = str.find_first_not_of(" \t\r\n"); 138 const size_t s = str.find_first_not_of(" \t\r\n");
152 139
153 if (str.npos != s) 140 if (str.npos != s)
@@ -159,17 +146,15 @@ std::string StripSpaces(const std::string &str)
159// "\"hello\"" is turned to "hello" 146// "\"hello\"" is turned to "hello"
160// This one assumes that the string has already been space stripped in both 147// This one assumes that the string has already been space stripped in both
161// ends, as done by StripSpaces above, for example. 148// ends, as done by StripSpaces above, for example.
162std::string StripQuotes(const std::string& s) 149std::string StripQuotes(const std::string& s) {
163{
164 if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) 150 if (s.size() && '\"' == s[0] && '\"' == *s.rbegin())
165 return s.substr(1, s.size() - 2); 151 return s.substr(1, s.size() - 2);
166 else 152 else
167 return s; 153 return s;
168} 154}
169 155
170bool TryParse(const std::string &str, u32 *const output) 156bool TryParse(const std::string& str, u32* const output) {
171{ 157 char* endptr = nullptr;
172 char *endptr = nullptr;
173 158
174 // Reset errno to a value other than ERANGE 159 // Reset errno to a value other than ERANGE
175 errno = 0; 160 errno = 0;
@@ -183,8 +168,7 @@ bool TryParse(const std::string &str, u32 *const output)
183 return false; 168 return false;
184 169
185#if ULONG_MAX > UINT_MAX 170#if ULONG_MAX > UINT_MAX
186 if (value >= 0x100000000ull 171 if (value >= 0x100000000ull && value <= 0xFFFFFFFF00000000ull)
187 && value <= 0xFFFFFFFF00000000ull)
188 return false; 172 return false;
189#endif 173#endif
190 174
@@ -192,8 +176,7 @@ bool TryParse(const std::string &str, u32 *const output)
192 return true; 176 return true;
193} 177}
194 178
195bool TryParse(const std::string &str, bool *const output) 179bool TryParse(const std::string& str, bool* const output) {
196{
197 if ("1" == str || "true" == ToLower(str)) 180 if ("1" == str || "true" == ToLower(str))
198 *output = true; 181 *output = true;
199 else if ("0" == str || "false" == ToLower(str)) 182 else if ("0" == str || "false" == ToLower(str))
@@ -204,22 +187,21 @@ bool TryParse(const std::string &str, bool *const output)
204 return true; 187 return true;
205} 188}
206 189
207std::string StringFromBool(bool value) 190std::string StringFromBool(bool value) {
208{
209 return value ? "True" : "False"; 191 return value ? "True" : "False";
210} 192}
211 193
212bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension) 194bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename,
213{ 195 std::string* _pExtension) {
214 if (full_path.empty()) 196 if (full_path.empty())
215 return false; 197 return false;
216 198
217 size_t dir_end = full_path.find_last_of("/" 199 size_t dir_end = full_path.find_last_of("/"
218 // windows needs the : included for something like just "C:" to be considered a directory 200// windows needs the : included for something like just "C:" to be considered a directory
219#ifdef _WIN32 201#ifdef _WIN32
220 ":" 202 ":"
221#endif 203#endif
222 ); 204 );
223 if (std::string::npos == dir_end) 205 if (std::string::npos == dir_end)
224 dir_end = 0; 206 dir_end = 0;
225 else 207 else
@@ -241,8 +223,8 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
241 return true; 223 return true;
242} 224}
243 225
244void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename) 226void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path,
245{ 227 const std::string& _Filename) {
246 _CompleteFilename = _Path; 228 _CompleteFilename = _Path;
247 229
248 // check for seperator 230 // check for seperator
@@ -253,8 +235,7 @@ void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _P
253 _CompleteFilename += _Filename; 235 _CompleteFilename += _Filename;
254} 236}
255 237
256void SplitString(const std::string& str, const char delim, std::vector<std::string>& output) 238void SplitString(const std::string& str, const char delim, std::vector<std::string>& output) {
257{
258 std::istringstream iss(str); 239 std::istringstream iss(str);
259 output.resize(1); 240 output.resize(1);
260 241
@@ -264,8 +245,7 @@ void SplitString(const std::string& str, const char delim, std::vector<std::stri
264 output.pop_back(); 245 output.pop_back();
265} 246}
266 247
267std::string TabsToSpaces(int tab_size, const std::string &in) 248std::string TabsToSpaces(int tab_size, const std::string& in) {
268{
269 const std::string spaces(tab_size, ' '); 249 const std::string spaces(tab_size, ' ');
270 std::string out(in); 250 std::string out(in);
271 251
@@ -276,15 +256,13 @@ std::string TabsToSpaces(int tab_size, const std::string &in)
276 return out; 256 return out;
277} 257}
278 258
279std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) 259std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) {
280{
281 size_t pos = 0; 260 size_t pos = 0;
282 261
283 if (src == dest) 262 if (src == dest)
284 return result; 263 return result;
285 264
286 while ((pos = result.find(src, pos)) != std::string::npos) 265 while ((pos = result.find(src, pos)) != std::string::npos) {
287 {
288 result.replace(pos, src.size(), dest); 266 result.replace(pos, src.size(), dest);
289 pos += dest.length(); 267 pos += dest.length();
290 } 268 }
@@ -294,8 +272,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
294 272
295#ifdef _MSC_VER 273#ifdef _MSC_VER
296 274
297std::string UTF16ToUTF8(const std::u16string& input) 275std::string UTF16ToUTF8(const std::u16string& input) {
298{
299#if _MSC_VER >= 1900 276#if _MSC_VER >= 1900
300 // Workaround for missing char16_t/char32_t instantiations in MSVC2015 277 // Workaround for missing char16_t/char32_t instantiations in MSVC2015
301 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert; 278 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert;
@@ -307,8 +284,7 @@ std::string UTF16ToUTF8(const std::u16string& input)
307#endif 284#endif
308} 285}
309 286
310std::u16string UTF8ToUTF16(const std::string& input) 287std::u16string UTF8ToUTF16(const std::string& input) {
311{
312#if _MSC_VER >= 1900 288#if _MSC_VER >= 1900
313 // Workaround for missing char16_t/char32_t instantiations in MSVC2015 289 // Workaround for missing char16_t/char32_t instantiations in MSVC2015
314 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert; 290 std::wstring_convert<std::codecvt_utf8_utf16<__int16>, __int16> convert;
@@ -320,57 +296,56 @@ std::u16string UTF8ToUTF16(const std::string& input)
320#endif 296#endif
321} 297}
322 298
323static std::wstring CPToUTF16(u32 code_page, const std::string& input) 299static std::wstring CPToUTF16(u32 code_page, const std::string& input) {
324{ 300 auto const size =
325 auto const size = MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); 301 MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0);
326 302
327 std::wstring output; 303 std::wstring output;
328 output.resize(size); 304 output.resize(size);
329 305
330 if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()))) 306 if (size == 0 ||
307 size != MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()),
308 &output[0], static_cast<int>(output.size())))
331 output.clear(); 309 output.clear();
332 310
333 return output; 311 return output;
334} 312}
335 313
336std::string UTF16ToUTF8(const std::wstring& input) 314std::string UTF16ToUTF8(const std::wstring& input) {
337{ 315 auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()),
338 auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), nullptr, 0, nullptr, nullptr); 316 nullptr, 0, nullptr, nullptr);
339 317
340 std::string output; 318 std::string output;
341 output.resize(size); 319 output.resize(size);
342 320
343 if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), &output[0], static_cast<int>(output.size()), nullptr, nullptr)) 321 if (size == 0 ||
322 size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()),
323 &output[0], static_cast<int>(output.size()), nullptr, nullptr))
344 output.clear(); 324 output.clear();
345 325
346 return output; 326 return output;
347} 327}
348 328
349std::wstring UTF8ToUTF16W(const std::string &input) 329std::wstring UTF8ToUTF16W(const std::string& input) {
350{
351 return CPToUTF16(CP_UTF8, input); 330 return CPToUTF16(CP_UTF8, input);
352} 331}
353 332
354std::string SHIFTJISToUTF8(const std::string& input) 333std::string SHIFTJISToUTF8(const std::string& input) {
355{
356 return UTF16ToUTF8(CPToUTF16(932, input)); 334 return UTF16ToUTF8(CPToUTF16(932, input));
357} 335}
358 336
359std::string CP1252ToUTF8(const std::string& input) 337std::string CP1252ToUTF8(const std::string& input) {
360{
361 return UTF16ToUTF8(CPToUTF16(1252, input)); 338 return UTF16ToUTF8(CPToUTF16(1252, input));
362} 339}
363 340
364#else 341#else
365 342
366template <typename T> 343template <typename T>
367static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input) 344static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input) {
368{
369 std::string result; 345 std::string result;
370 346
371 iconv_t const conv_desc = iconv_open("UTF-8", fromcode); 347 iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
372 if ((iconv_t)(-1) == conv_desc) 348 if ((iconv_t)(-1) == conv_desc) {
373 {
374 LOG_ERROR(Common, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno)); 349 LOG_ERROR(Common, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
375 iconv_close(conv_desc); 350 iconv_close(conv_desc);
376 return {}; 351 return {};
@@ -388,24 +363,18 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
388 auto dst_buffer = &out_buffer[0]; 363 auto dst_buffer = &out_buffer[0];
389 size_t dst_bytes = out_buffer.size(); 364 size_t dst_bytes = out_buffer.size();
390 365
391 while (0 != src_bytes) 366 while (0 != src_bytes) {
392 { 367 size_t const iconv_result =
393 size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, 368 iconv(conv_desc, (char**)(&src_buffer), &src_bytes, &dst_buffer, &dst_bytes);
394 &dst_buffer, &dst_bytes);
395 369
396 if (static_cast<size_t>(-1) == iconv_result) 370 if (static_cast<size_t>(-1) == iconv_result) {
397 { 371 if (EILSEQ == errno || EINVAL == errno) {
398 if (EILSEQ == errno || EINVAL == errno)
399 {
400 // Try to skip the bad character 372 // Try to skip the bad character
401 if (0 != src_bytes) 373 if (0 != src_bytes) {
402 {
403 --src_bytes; 374 --src_bytes;
404 ++src_buffer; 375 ++src_buffer;
405 } 376 }
406 } 377 } else {
407 else
408 {
409 LOG_ERROR(Common, "iconv failure [%s]: %s", fromcode, strerror(errno)); 378 LOG_ERROR(Common, "iconv failure [%s]: %s", fromcode, strerror(errno));
410 break; 379 break;
411 } 380 }
@@ -420,13 +389,11 @@ static std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>&
420 return result; 389 return result;
421} 390}
422 391
423std::u16string UTF8ToUTF16(const std::string& input) 392std::u16string UTF8ToUTF16(const std::string& input) {
424{
425 std::u16string result; 393 std::u16string result;
426 394
427 iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8"); 395 iconv_t const conv_desc = iconv_open("UTF-16LE", "UTF-8");
428 if ((iconv_t)(-1) == conv_desc) 396 if ((iconv_t)(-1) == conv_desc) {
429 {
430 LOG_ERROR(Common, "Iconv initialization failure [UTF-8]: %s", strerror(errno)); 397 LOG_ERROR(Common, "Iconv initialization failure [UTF-8]: %s", strerror(errno));
431 iconv_close(conv_desc); 398 iconv_close(conv_desc);
432 return {}; 399 return {};
@@ -444,24 +411,18 @@ std::u16string UTF8ToUTF16(const std::string& input)
444 char* dst_buffer = (char*)(&out_buffer[0]); 411 char* dst_buffer = (char*)(&out_buffer[0]);
445 size_t dst_bytes = out_buffer.size(); 412 size_t dst_bytes = out_buffer.size();
446 413
447 while (0 != src_bytes) 414 while (0 != src_bytes) {
448 { 415 size_t const iconv_result =
449 size_t const iconv_result = iconv(conv_desc, &src_buffer, &src_bytes, 416 iconv(conv_desc, &src_buffer, &src_bytes, &dst_buffer, &dst_bytes);
450 &dst_buffer, &dst_bytes);
451 417
452 if (static_cast<size_t>(-1) == iconv_result) 418 if (static_cast<size_t>(-1) == iconv_result) {
453 { 419 if (EILSEQ == errno || EINVAL == errno) {
454 if (EILSEQ == errno || EINVAL == errno)
455 {
456 // Try to skip the bad character 420 // Try to skip the bad character
457 if (0 != src_bytes) 421 if (0 != src_bytes) {
458 {
459 --src_bytes; 422 --src_bytes;
460 ++src_buffer; 423 ++src_buffer;
461 } 424 }
462 } 425 } else {
463 else
464 {
465 LOG_ERROR(Common, "iconv failure [UTF-8]: %s", strerror(errno)); 426 LOG_ERROR(Common, "iconv failure [UTF-8]: %s", strerror(errno));
466 break; 427 break;
467 } 428 }
@@ -476,32 +437,28 @@ std::u16string UTF8ToUTF16(const std::string& input)
476 return result; 437 return result;
477} 438}
478 439
479std::string UTF16ToUTF8(const std::u16string& input) 440std::string UTF16ToUTF8(const std::u16string& input) {
480{
481 return CodeToUTF8("UTF-16LE", input); 441 return CodeToUTF8("UTF-16LE", input);
482} 442}
483 443
484std::string CP1252ToUTF8(const std::string& input) 444std::string CP1252ToUTF8(const std::string& input) {
485{ 445 // return CodeToUTF8("CP1252//TRANSLIT", input);
486 //return CodeToUTF8("CP1252//TRANSLIT", input); 446 // return CodeToUTF8("CP1252//IGNORE", input);
487 //return CodeToUTF8("CP1252//IGNORE", input);
488 return CodeToUTF8("CP1252", input); 447 return CodeToUTF8("CP1252", input);
489} 448}
490 449
491std::string SHIFTJISToUTF8(const std::string& input) 450std::string SHIFTJISToUTF8(const std::string& input) {
492{ 451 // return CodeToUTF8("CP932", input);
493 //return CodeToUTF8("CP932", input);
494 return CodeToUTF8("SJIS", input); 452 return CodeToUTF8("SJIS", input);
495} 453}
496 454
497#endif 455#endif
498 456
499std::string StringFromFixedZeroTerminatedBuffer(const char * buffer, size_t max_len) { 457std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_len) {
500 size_t len = 0; 458 size_t len = 0;
501 while (len < max_len && buffer[len] != '\0') 459 while (len < max_len && buffer[len] != '\0')
502 ++len; 460 ++len;
503 461
504 return std::string(buffer, len); 462 return std::string(buffer, len);
505} 463}
506
507} 464}