/* * Copyright 2019-2021 Diligent Graphics LLC * Copyright 2015-2019 Egor Yusov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * In no event and under no legal theory, whether in tort (including negligence), * contract, or otherwise, unless required by applicable law (such as deliberate * and grossly negligent acts) or agreed to in writing, shall any Contributor be * liable for any damages, including any direct, indirect, special, incidental, * or consequential damages of any character arising as a result of this License or * out of the use or inability to use the software (including but not limited to damages * for loss of goodwill, work stoppage, computer failure or malfunction, or any and * all other commercial damages or losses), even if such Contributor has been advised * of the possibility of such damages. */ #pragma once #include #include #include #include #include #include #include "../../Platforms/Basic/interface/DebugUtilities.hpp" namespace Diligent { inline std::string NarrowString(const std::wstring& WideStr) { std::string NarrowStr; const std::ctype& ctfacet = std::use_facet>(std::wstringstream().getloc()); for (std::wstring::const_iterator CurrWChar = WideStr.begin(); CurrWChar != WideStr.end(); CurrWChar++) NarrowStr.push_back(ctfacet.narrow(*CurrWChar, 0)); return NarrowStr; } inline std::string NarrowString(const wchar_t* WideStr) { std::string NarrowStr; const std::ctype& ctfacet = std::use_facet>(std::wstringstream().getloc()); for (auto CurrWChar = WideStr; *CurrWChar != 0; ++CurrWChar) NarrowStr.push_back(ctfacet.narrow(*CurrWChar, 0)); return NarrowStr; } inline std::wstring WidenString(const char* Str) { std::wstring WideStr; const std::ctype& ctfacet = std::use_facet>(std::wstringstream().getloc()); for (auto CurrChar = Str; *CurrChar != 0; ++CurrChar) WideStr.push_back(ctfacet.widen(*CurrChar)); return WideStr; } inline std::wstring WidenString(const std::string& Str) { std::wstring WideStr; const std::ctype& ctfacet = std::use_facet>(std::wstringstream().getloc()); for (std::string::const_iterator CurrChar = Str.begin(); CurrChar != Str.end(); CurrChar++) WideStr.push_back(ctfacet.widen(*CurrChar)); return WideStr; } inline int StrCmpNoCase(const char* Str1, const char* Str2, size_t NumChars) { #if PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MACOS || PLATFORM_IOS # define _strnicmp strncasecmp #endif return _strnicmp(Str1, Str2, NumChars); } inline int StrCmpNoCase(const char* Str1, const char* Str2) { #if PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MACOS || PLATFORM_IOS # define _stricmp strcasecmp #endif return _stricmp(Str1, Str2); } // Returns true if RefStr == Str + Suff // If Suff == nullptr or NoSuffixAllowed == true, also returns true if RefStr == Str inline bool StreqSuff(const char* RefStr, const char* Str, const char* Suff, bool NoSuffixAllowed = false) { VERIFY_EXPR(RefStr != nullptr && Str != nullptr); if (RefStr == nullptr) return false; const auto* r = RefStr; const auto* s = Str; // abc_def abc // ^ ^ // r s for (; *r != 0 && *s != 0; ++r, ++s) { if (*r != *s) { // abc_def abx // ^ ^ // r s return false; } } if (*s != 0) { // ab abc // ^ ^ // r s VERIFY_EXPR(*r == 0); return false; } else { // abc_def abc // ^ ^ // r s if (NoSuffixAllowed && *r == 0) { // abc abc _def // ^ ^ // r s return true; } if (Suff != nullptr) { // abc_def abc _def // ^ ^ ^ // r s Suff return strcmp(r, Suff) == 0; } else { // abc abc abc_def abc // ^ ^ or ^ ^ // r s r s return *r == 0; } } } inline void StrToLowerInPlace(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), // http://en.cppreference.com/w/cpp/string/byte/tolower [](unsigned char c) { return static_cast(std::tolower(c)); }); } inline std::string StrToLower(std::string str) { StrToLowerInPlace(str); return str; } inline bool IsNum(char c) { return c >= '0' && c <= '9'; } /// Returns the number of chararcters at the beginning of the string that form a /// floating point number. inline size_t CountFloatNumberChars(const char* str) { if (str == nullptr) return 0; const auto* num_end = str; const auto* c = str; if (*c == 0) return 0; if (*c == '+' || *c == '-') ++c; if (*c == 0) return 0; if (*c == '0' && IsNum(*(c + 1))) { // 01 is invalid return c - str + 1; } while (IsNum(*c)) num_end = ++c; if (*c == '.') { if (c != str && IsNum(c[-1])) { // . as well as +. or -. are not valid numbers, however 0., +0., and -0. are. num_end = c + 1; } ++c; while (IsNum(*c)) num_end = ++c; if (*c == 'e' || *c == 'E') { if (c - str < 2 || !IsNum(c[-2])) { // .e as well as +.e are invalid return num_end - str; } } } else if (*c == 'e' || *c == 'E') { if (c - str < 1 || !IsNum(c[-1])) { // e as well as e+1 are invalid return num_end - str; } } if (*c == 'e' || *c == 'E') { ++c; if (*c != '+' && *c != '-') return num_end - str; ++c; while (IsNum(*c)) num_end = ++c; } return num_end - str; } } // namespace Diligent