diff --git a/module/common/include/oops/str.h b/module/common/include/oops/str.h index 56a8774..6c11689 100644 --- a/module/common/include/oops/str.h +++ b/module/common/include/oops/str.h @@ -7,8 +7,22 @@ namespace oops { constexpr std::string_view SPACE{" \t\n\r\v\f"}; -std::string Repeat(const std::string &str, std::size_t n); -std::string SplitBack(const std::string &str, const std::string &delim); + +// 字符操作 +constexpr bool IsUpper(char c) noexcept { return 'A' <= c && c <= 'Z'; } +constexpr bool IsLower(char c) noexcept { return 'a' <= c && c <= 'z'; } +constexpr bool IsAlpha(char c) noexcept { return IsUpper(c) || IsLower(c); } +constexpr bool IsDigit(char c) noexcept { return '0' <= c && c <= '9'; } +constexpr bool IsAlnum(char c) noexcept { return IsAlpha(c) || IsDigit(c); } +constexpr bool IsSpace(char c) noexcept { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f'; +} + +constexpr char ToUpper(char c) noexcept { return IsLower(c) ? (c - 'a' + 'A') : c; } +constexpr char ToLower(char c) noexcept { return IsUpper(c) ? (c - 'A' + 'a') : c; } + +// 字符串读操作 +std::string SplitBack(const std::string &str, const std::string &delim); // SplitView实现逆序迭代器后合并到Split中 class SplitView { public: @@ -73,6 +87,7 @@ class SplitView { Iterator end() const { return Iterator(); } std::string_view Front() const { return *begin(); } + bool Empty() const { return begin() == end(); } SplitView &AnyOfDelims(bool b = true) { any_of_delims_ = b; @@ -106,19 +121,47 @@ inline SplitView Split(std::string_view s) { return SplitView(s); } inline SplitView Split(std::string_view s, char delim) { return SplitView(s, delim); } inline SplitView Split(std::string_view s, std::string_view delim) { return SplitView(s, delim); } -constexpr bool IsUpper(char c) noexcept { return 'A' <= c && c <= 'Z'; } -constexpr bool IsLower(char c) noexcept { return 'a' <= c && c <= 'z'; } -constexpr bool IsAlpha(char c) noexcept { return IsUpper(c) || IsLower(c); } -constexpr bool IsDigit(char c) noexcept { return '0' <= c && c <= '9'; } -constexpr bool IsAlnum(char c) noexcept { return IsAlpha(c) || IsDigit(c); } -constexpr bool IsSpace(char c) noexcept { - return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f'; +constexpr std::string_view StripLeft(std::string_view s, std::string_view chars = SPACE) { + std::size_t pos{s.find_first_not_of(chars)}; + if (pos == std::string_view::npos) { + pos = s.size(); + } + s.remove_prefix(pos); + return s; } -constexpr char ToUpper(char c) noexcept { return IsLower(c) ? (c - 'a' + 'A') : c; } -constexpr char ToLower(char c) noexcept { return IsUpper(c) ? (c - 'A' + 'a') : c; } +constexpr std::string_view StripRight(std::string_view s, std::string_view chars = SPACE) { + std::size_t pos{s.find_last_not_of(chars) + 1}; + if (pos == std::string_view::npos) { + pos = s.size(); + } + s.remove_suffix(s.size() - pos); + return s; +} -std::string ToLower(std::string_view s) noexcept; +constexpr std::string_view Strip(std::string_view s, std::string_view chars = SPACE) { + return StripLeft(StripRight(s, chars), chars); +} + +constexpr bool StartsWith(std::string_view s, std::string_view prefix) { + if (prefix.empty()) { + return true; + } + if (prefix.size() > s.size()) { + return false; + } + return s.substr(0, prefix.size()) == prefix; +} + +constexpr bool EndsWith(std::string_view s, std::string_view suffix) { + if (suffix.empty()) { + return true; + } + if (suffix.size() > s.size()) { + return false; + } + return s.substr(s.size() - suffix.size()) == suffix; +} constexpr bool Equal(std::string_view lhs, std::string_view rhs) noexcept { return lhs == rhs; } @@ -137,18 +180,18 @@ constexpr bool Equal(std::string_view lhs, std::string_view rhs, CharEqual &&cha template constexpr bool Equal(std::string_view lhs, std::string_view rhs, CharEqual &&char_equal, Filter &&filter) noexcept { - for (std::size_t i{0}, j{0}; true; ++i, ++j) { - while (i < lhs.size() && !filter(lhs[i])) { + for (std::size_t i{0}, j{0};; ++i, ++j) { + while ((i < lhs.size()) && (!filter(lhs[i]))) { ++i; } - while (j < rhs.size() && !filter(rhs[j])) { + while ((j < rhs.size()) && (!filter(rhs[j]))) { ++j; } - if (i == lhs.size() && j == rhs.size()) { - return true; + if ((i == lhs.size()) ^ (j == rhs.size())) { + return false; // 一个查找到末尾,另一个没有 } - if (i == lhs.size() || j == rhs.size()) { - return false; + if (i == lhs.size()) { + return true; } if (!char_equal(lhs[i], rhs[j])) { return false; @@ -156,40 +199,14 @@ constexpr bool Equal(std::string_view lhs, std::string_view rhs, CharEqual &&cha } } -constexpr bool StartsWith(std::string_view s, std::string_view prefix) { - if (prefix.empty()) { - return true; - } - if (prefix.size() > s.size()) { - return false; - } - return s.substr(0, prefix.size()) == prefix; -} - -constexpr bool EndsWith(std::string_view s, std::string_view suffix) { - if (suffix.empty()) { - return true; - } - if (suffix.size() > s.size()) { - return false; - } - return s.substr(s.size() - suffix.size()) == suffix; -} - -constexpr std::string_view Strip(std::string_view s, std::string_view chars = SPACE) { - if (s.empty()) { - return s; - } - std::size_t pos{s.find_first_not_of(chars)}; - if (pos == std::string_view::npos) { - return {}; - } - return s.substr(pos, s.find_last_not_of(chars) - pos + 1); -} +// 字符串写操作 +std::string ToLower(std::string_view s) noexcept; +std::string ToUpper(std::string_view s) noexcept; +std::string Repeat(const std::string &str, std::size_t n); std::string Elide(std::string_view s, std::size_t n); -// 后续替换成lexcial_cast +// 后续使用lexcial_cast替代 template ::std::string ToStr(const T &t) { ::std::ostringstream oss; diff --git a/module/common/include/oops/view.h b/module/common/include/oops/view.h index d64b793..dae9602 100644 --- a/module/common/include/oops/view.h +++ b/module/common/include/oops/view.h @@ -80,7 +80,50 @@ class RangeView { static_assert(std::is_same_v || !std::is_integral_v); public: - class Iterator; + class Iterator { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = const T *; + using reference = const T &; + + constexpr explicit Iterator(T t, T step) : t_{t}, step_{step} {} + constexpr T operator*() const noexcept { return t_; } + + constexpr Iterator &operator++() noexcept { + auto res{AddOverflow(t_, step_)}; + t_ = res.value; + overflow_ = res.overflow; + return *this; + } + + constexpr Iterator operator++(int) noexcept { + auto iter{*this}; + ++(*this); + return iter; + } + + bool Overflow() const { return overflow_; } + T Step() const { return step_; } + + constexpr bool operator==(Stop stop) const { + if constexpr (std::is_integral_v) { + if (step_ > 0) { + return stop <= t_; + } + return stop >= t_; + } else { + return stop == (*this); + } + } + constexpr bool operator!=(Stop stop) const { return !operator==(stop); } + + private: + T t_, step_; + bool overflow_{false}; + }; + constexpr RangeView(Stop stop) : stop_{stop} {} constexpr RangeView(T start, Stop stop, T step = 1) : start_{start}, stop_{stop}, step_{step} { if (step == 0) { @@ -97,51 +140,6 @@ class RangeView { T step_{1}; }; -template -class RangeView::Iterator { -public: - using iterator_category = std::forward_iterator_tag; - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = const T *; - using reference = const T &; - - constexpr explicit Iterator(T t, T step) : t_{t}, step_{step} {} - constexpr T operator*() const noexcept { return t_; } - - constexpr Iterator &operator++() noexcept { - auto res{AddOverflow(t_, step_)}; - t_ = res.value; - overflow_ = res.overflow; - return *this; - } - - constexpr Iterator operator++(int) noexcept { - auto iter{*this}; - ++(*this); - return iter; - } - - bool Overflow() const { return overflow_; } - T Step() const { return step_; } - - constexpr bool operator==(Stop stop) const { - if constexpr (std::is_integral_v) { - if (step_ > 0) { - return stop <= t_; - } - return stop >= t_; - } else { - return stop == (*this); - } - } - constexpr bool operator!=(Stop stop) const { return !operator==(stop); } - -protected: - T t_, step_; - bool overflow_{false}; -}; - template constexpr auto Range(T start, Stop stop, T step = 1) { if constexpr (std::is_integral_v) { diff --git a/module/common/src/str.cpp b/module/common/src/str.cpp index 96e9278..bfb89a3 100644 --- a/module/common/src/str.cpp +++ b/module/common/src/str.cpp @@ -1,21 +1,10 @@ #include "oops/str.h" +#include #include #include namespace oops { -std::string Repeat(const std::string &str, std::size_t n) { - if (n == 0 || str.empty()) { - return {}; - } - std::string res; - res.reserve(n * str.size()); - for (std::size_t i{0}; i < n; ++i) { - res.append(str); - } - return res; -} - std::string SplitBack(const std::string &str, const std::string &delim) { return str.substr(str.rfind(delim) + delim.size()); } @@ -54,11 +43,28 @@ void SplitView::Iterator::NextToken() { } while (skip_empty_ && token_.empty() && s_.data() != nullptr); } +std::string ToUpper(std::string_view s) noexcept { + std::string res; + res.reserve(s.size()); + std::transform(s.begin(), s.end(), std::back_inserter(res), (char (*)(char)){ToUpper}); + return res; +} + std::string ToLower(std::string_view s) noexcept { std::string res; res.reserve(s.size()); - for (char ch : s) { - res.push_back(ToLower(ch)); + std::transform(s.begin(), s.end(), std::back_inserter(res), (char (*)(char)){ToLower}); + return res; +} + +std::string Repeat(const std::string &str, std::size_t n) { + if (n == 0 || str.empty()) { + return {}; + } + std::string res; + res.reserve(n * str.size()); + for (std::size_t i{0}; i < n; ++i) { + res.append(str); } return res; } diff --git a/module/profiling/src/system_info.cpp b/module/profiling/src/system_info.cpp index 73a140e..18b3693 100644 --- a/module/profiling/src/system_info.cpp +++ b/module/profiling/src/system_info.cpp @@ -71,15 +71,15 @@ std::string FormatField(const Storage &storage, std::string_view ctx = "{} // proc::smaps::VmaExt::VmFlags特化 struct VmFlagsEntry { + using VmFlags = proc::smaps::VmaExt::VmFlags; std::string_view key; - void (*set)(proc::smaps::VmaExt::VmFlags &); - bool (*get)(const proc::smaps::VmaExt::VmFlags &); + void (*set)(VmFlags &); + bool (*get)(const VmFlags &); }; -#define ENTRY(flag) \ - { \ - #flag, [](proc::smaps::VmaExt::VmFlags &f) { f.flag = true; }, \ - [](const proc::smaps::VmaExt::VmFlags &f) { return f.flag; } \ +#define ENTRY(f) \ + { \ + #f, [](auto &f) { f.rd = true; }, [](auto &f) { return f.rd; } \ } constexpr VmFlagsEntry VM_FLAGS_TABLE[]{ENTRY(rd), ENTRY(wr), ENTRY(ex), ENTRY(sh), ENTRY(mr), ENTRY(mw), ENTRY(me), ENTRY(ms), ENTRY(gd), ENTRY(pf), ENTRY(dw), ENTRY(lo), ENTRY(io), ENTRY(sr), @@ -106,7 +106,7 @@ bool ParseField(std::string_view s, proc::smaps::VmaExt::VmFlags &vm_flags, std: template <> std::string FormatField(const proc::smaps::VmaExt::VmFlags &vm_flags, std::string_view) { std::string s; - s.reserve(64); + s.reserve(64); // one cache line for (const auto &item : VM_FLAGS_TABLE) { if (item.get(vm_flags)) { s += item.key; diff --git a/module/profiling/tool/monitor/monitor.cpp b/module/profiling/tool/monitor/monitor.cpp index eea36c0..8908675 100644 --- a/module/profiling/tool/monitor/monitor.cpp +++ b/module/profiling/tool/monitor/monitor.cpp @@ -261,7 +261,6 @@ void SearchValidInput() { template auto ParseValueAfterPrefix(std::string_view s, std::string_view prefix, T &value) noexcept { - s = oops::Strip(s); struct { explicit operator bool() const noexcept { return matched && parsed; } std::string_view remain; @@ -269,12 +268,13 @@ auto ParseValueAfterPrefix(std::string_view s, std::string_view prefix, T &value bool parsed{false}; } res; + s = oops::Strip(s); auto pos{s.find(prefix)}; if (pos == std::string_view::npos) { return res; } s.remove_prefix(pos + prefix.size()); - s = oops::Strip(s); // 使用StripLeft优化 + s = oops::StripLeft(s); res.matched = true; res.remain = s;