diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f3960e2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,17 @@ +BasedOnStyle: LLVM + +ObjCBlockIndentWidth: 4 +IndentWidth: 4 +TabWidth: 4 +AccessModifierOffset: -4 +ColumnLimit: 120 + +#模板声明后换行 +AlwaysBreakTemplateDeclarations: true + +# 是否允许短if单行 If true, if (a) return; 可以放到同一行 +AllowShortIfStatementsOnASingleLine: true + +#短句 while (true) continue; 能被放到单行。 +AllowShortLoopsOnASingleLine: true +AllowShortFunctionsOnASingleLine: false \ No newline at end of file diff --git a/Universal/CMakeLists.txt b/Universal/CMakeLists.txt index 396d6e6..b50ee15 100644 --- a/Universal/CMakeLists.txt +++ b/Universal/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(Universal MessageManager.h MessageManager.inl MessageManager.cpp Singleton.h StreamFormat.h StreamFormat.inl StreamFormat.cpp + StringUtility.h StringUtility.cpp ) target_include_directories(Universal diff --git a/Universal/StringUtility.cpp b/Universal/StringUtility.cpp new file mode 100644 index 0000000..756d618 --- /dev/null +++ b/Universal/StringUtility.cpp @@ -0,0 +1,86 @@ +#include "StringUtility.h" +#include "BoostLog.h" +#include +#include +#include + +namespace Amass { + +namespace StringUtility { + +std::string &replace(std::string &string, const std::string &before, const std::string &after) { + for (size_t pos = 0; pos != std::string::npos; pos += after.length()) { + pos = string.find(before, pos); + if (pos != std::string::npos) + string.replace(pos, before.length(), after); + else + break; + } + return string; +} + +size_t utf8Length(const std::string &text) { + size_t ret = 0; + for (uint32_t i = 0; i < text.length();) { + uint32_t byte_length = utf8CharacterByteSize(text.c_str() + i); + ret++; + i += byte_length; + } + return ret; +} + +std::string_view utf8At(const std::string &text, size_t index) { + const char *ret = text.c_str(); + for (uint32_t i = 0; i < index; i++) { + uint32_t byte_length = utf8CharacterByteSize(ret); + ret += byte_length; + } + return std::string_view(ret, utf8CharacterByteSize(ret)); +} + +size_t utf8CharacterByteSize(const char *character) { + if (character == nullptr) return 0; + uint32_t ret = 0; + uint8_t temp = character[0]; + while (temp & 0x80) { + ret++; + temp <<= 1; + } + return ret > 0 ? ret : 1; +} + +std::wstring stringToWString(const std::string &string) { + std::wstring_convert> converter; + return converter.from_bytes(string); +} + +bool equal(std::string_view lhs, std::string_view rhs, bool caseSensitivity) { + auto n = lhs.size(); + if (rhs.size() != n) return false; + auto p1 = lhs.data(); + auto p2 = rhs.data(); + char a, b; + + while (n--) { // fast loop + a = *p1++; + b = *p2++; + if (a != b) { + if (caseSensitivity) { + return false; + } else { + goto slow; + } + } + } + return true; +slow: + do { + if (std::tolower(a) != std::tolower(b)) return false; + a = *p1++; + b = *p2++; + } while (n--); + return true; +} + +} // namespace StringUtility +} // namespace Amass diff --git a/Universal/StringUtility.h b/Universal/StringUtility.h new file mode 100644 index 0000000..70d7a10 --- /dev/null +++ b/Universal/StringUtility.h @@ -0,0 +1,68 @@ +#ifndef STRINGUTILITY_H +#define STRINGUTILITY_H + +#include +#include + +namespace std { + +template +std::basic_string to_string(const std::basic_string_view &str) { + return std::basic_string(str.begin(), str.end()); +} + +} // namespace std + +namespace Amass { + +namespace StringUtility { + +template +std::vector> split(const std::basic_string &string, + const std::basic_string_view &delimiter) { + std::vector> ret; + if (delimiter.empty() || string.empty()) return ret; + auto buf = string; + size_t pos = std::string::npos; + size_t delimiterLength = delimiter.length(); + while (true) { + pos = buf.find(delimiter); + if (pos != std::basic_string::npos) { + auto substr = buf.substr(0, pos); + if (!substr.empty()) ret.push_back(substr); + buf = buf.substr(pos + delimiterLength); + } else { + if (!buf.empty()) ret.push_back(buf); + break; + } + } + return ret; +} + +inline std::vector split(const std::string &string, const std::string_view &delimiter) { + return split(string, delimiter); +} + +std::string &replace(std::string &string, const std::string &before, const std::string &after); + +template +std::basic_string trimmed(const std::basic_string &string) { + static const CharT *whitespace = std::is_same_v ? reinterpret_cast("\t\n\v\f\r ") + : reinterpret_cast(L"\t\n\v\f\r "); + auto begin = string.find_first_not_of(whitespace); + if (begin == std::basic_string::npos) return std::basic_string(); + auto end = string.find_last_not_of(whitespace); + if (end == std::basic_string::npos) return std::basic_string(); + return string.substr(begin, end - begin + 1); +} +bool equal(std::string_view lhs, std::string_view rhs, bool caseSensitivity = true); +size_t utf8Length(const std::string &text); +std::string_view utf8At(const std::string &text, size_t index); +size_t utf8CharacterByteSize(const char *character); +std::wstring stringToWString(const std::string &string); + +} // namespace StringUtility + +} // namespace Amass + +#endif // STRINGUTILITY_H