diff --git a/runtime/Cpp/runtime/src/ANTLRInputStream.h b/runtime/Cpp/runtime/src/ANTLRInputStream.h index e904ff9b7..e9850504d 100755 --- a/runtime/Cpp/runtime/src/ANTLRInputStream.h +++ b/runtime/Cpp/runtime/src/ANTLRInputStream.h @@ -16,11 +16,7 @@ namespace antlr4 { protected: /// The data being scanned. // UTF-32 -#if defined(_MSC_VER) && _MSC_VER == 1900 - i32string _data; // Custom type for VS 2015. -#else - std::u32string _data; -#endif + UTF32String _data; /// 0..n-1 index into string of next char size_t p; diff --git a/runtime/Cpp/runtime/src/antlr4-common.h b/runtime/Cpp/runtime/src/antlr4-common.h index 9272d1958..85477d813 100644 --- a/runtime/Cpp/runtime/src/antlr4-common.h +++ b/runtime/Cpp/runtime/src/antlr4-common.h @@ -55,11 +55,13 @@ typedef __int32 ssize_t; #endif - #if _MSC_VER == 1900 + #if _MSC_VER >= 1900 && _MSC_VER < 2000 // VS 2015 has a known bug when using std::codecvt_utf8 // so we have to temporarily use __int32 instead. // https://connect.microsoft.com/VisualStudio/feedback/details/1403302/unresolved-external-when-using-codecvt-utf8 typedef std::basic_string<__int32> i32string; + + typedef i32string UTF32String; #endif #ifdef ANTLR4CPP_EXPORTS @@ -72,11 +74,11 @@ #endif #endif -#ifdef _MSC_VER class ANTLR4CPP_PUBLIC std::exception; // Needed for VS 2015. -#endif #elif __APPLE__ + typedef std::u32string UTF32String; + #define GUID_CFUUID #if __GNUC__ >= 4 #define ANTLR4CPP_PUBLIC __attribute__ ((visibility ("default"))) @@ -84,6 +86,8 @@ #define ANTLR4CPP_PUBLIC #endif #else + typedef std::u32string UTF32String; + #define GUID_LIBUUID #if __GNUC__ >= 6 #define ANTLR4CPP_PUBLIC __attribute__ ((visibility ("default"))) diff --git a/runtime/Cpp/runtime/src/support/StringUtils.cpp b/runtime/Cpp/runtime/src/support/StringUtils.cpp index 5f4a0bce7..552f1031a 100644 --- a/runtime/Cpp/runtime/src/support/StringUtils.cpp +++ b/runtime/Cpp/runtime/src/support/StringUtils.cpp @@ -7,29 +7,29 @@ namespace antlrcpp { -void replaceAll(std::string& str, const std::string& from, const std::string& to) +void replaceAll(std::string& str, std::string const& from, std::string const& to) { - if(from.empty()) { + if (from.empty()) return; - } + size_t start_pos = 0; - while((start_pos = str.find(from, start_pos)) != std::string::npos) { + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'. } } -std::string ws2s(const std::wstring &wstr) { +std::string ws2s(std::wstring const& wstr) { std::wstring_convert> converter; - std::string narrow = converter.to_bytes(wstr); + return narrow; } std::wstring s2ws(const std::string &str) { std::wstring_convert> converter; - std::wstring wide = converter.from_bytes(str); + return wide; } diff --git a/runtime/Cpp/runtime/src/support/StringUtils.h b/runtime/Cpp/runtime/src/support/StringUtils.h index cd4d81c1d..ac0fcc765 100644 --- a/runtime/Cpp/runtime/src/support/StringUtils.h +++ b/runtime/Cpp/runtime/src/support/StringUtils.h @@ -8,40 +8,47 @@ #include "antlr4-common.h" namespace antlrcpp { - // For all conversions utf8 <-> utf32. - // VS 2015 and VS 2017 have different bugs in std::codecvt_utf8 (VS 2013 works fine). + +// For all conversions utf8 <-> utf32. +// VS 2015 and VS 2017 have different bugs in std::codecvt_utf8 (VS 2013 works fine). #if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000 - static std::wstring_convert, __int32> utfConverter; + typedef std::wstring_convert, __int32> UTF32Converter; #else - static std::wstring_convert, char32_t> utfConverter; + typedef std::wstring_convert, char32_t> UTF32Converter; #endif - //the conversion functions fails in VS2017, so we explicitly use a workaround + // The conversion functions fails in VS2017, so we explicitly use a workaround. template - inline std::string utf32_to_utf8(T _data) + inline std::string utf32_to_utf8(T const& data) { + // Don't make the converter static or we have to serialize access to it. + UTF32Converter converter; + #if _MSC_VER > 1900 && _MSC_VER < 2000 - auto p = reinterpret_cast(_data.data()); - return antlrcpp::utfConverter.to_bytes(p, p + _data.size()); + auto p = reinterpret_cast(data.data()); + return converter.to_bytes(p, p + data.size()); #else - return antlrcpp::utfConverter.to_bytes(_data); + return converter.to_bytes(data); #endif } - inline auto utf8_to_utf32(const char* first, const char* last) + inline UTF32String utf8_to_utf32(const char* first, const char* last) { + UTF32Converter converter; + #if _MSC_VER > 1900 && _MSC_VER < 2000 - auto r = antlrcpp::utfConverter.from_bytes(first, last); - std::u32string s = reinterpret_cast(r.data()); - return s; + auto r = converter.from_bytes(first, last); + i32string s = reinterpret_cast(r.data()); #else - return antlrcpp::utfConverter.from_bytes(first, last); + std::u32string s = converter.from_bytes(first, last); #endif + + return s; } - void replaceAll(std::string& str, const std::string& from, const std::string& to); + void replaceAll(std::string &str, std::string const& from, std::string const& to); // string <-> wstring conversion (UTF-16), e.g. for use with Window's wide APIs. - ANTLR4CPP_PUBLIC std::string ws2s(const std::wstring &wstr); - ANTLR4CPP_PUBLIC std::wstring s2ws(const std::string &str); + ANTLR4CPP_PUBLIC std::string ws2s(std::wstring const& wstr); + ANTLR4CPP_PUBLIC std::wstring s2ws(std::string const& str); }