From b75dfd361c55cbde3b2a3d3cd1390bb94150ac4a Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 12 Oct 2016 20:22:24 +0300 Subject: [PATCH] Added comparison operators and tests for them --- include/boost/stacktrace.hpp | 18 +++++++++++ .../detail/backtrace_holder_libunwind.hpp | 26 ++++++++++++++++ .../detail/backtrace_holder_linux.hpp | 26 ++++++++++++++++ .../detail/backtrace_holder_noop.hpp | 8 +++++ .../detail/backtrace_holder_windows.hpp | 26 ++++++++++++++++ .../boost/stacktrace/detail/stacktrace.ipp | 7 +++++ src/stacktrace_src.ipp | 7 +++++ test/test.cpp | 31 +++++++++++++++++++ 8 files changed, 149 insertions(+) diff --git a/include/boost/stacktrace.hpp b/include/boost/stacktrace.hpp index e27859e..d01cc29 100644 --- a/include/boost/stacktrace.hpp +++ b/include/boost/stacktrace.hpp @@ -119,9 +119,27 @@ public: return !size(); } + /// @brief Allows to check that capturing stack trace was successful. + /// @returns `true` if `this->size() != 0` + /// + /// @b Complexity: O(1) BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + /// @brief Compares stacktraces for less, order is platform dependant. + /// + /// @b Complexity: Amortized O(1); worst case O(size()) + BOOST_STACKTRACE_FUNCTION bool operator< (const stacktrace& rhs) const BOOST_NOEXCEPT; + + /// @brief Compares stacktraces for equality. + /// + /// @b Complexity: Amortized O(1); worst case O(size()) + BOOST_STACKTRACE_FUNCTION bool operator==(const stacktrace& rhs) const BOOST_NOEXCEPT; }; +inline bool operator> (const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return rhs < lhs; } +inline bool operator<=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs > rhs); } +inline bool operator>=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs < rhs); } +inline bool operator!=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); } /// Outputs stacktrace in a human readable format to output stream. template diff --git a/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp b/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp index 621cc86..99a7d90 100644 --- a/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp +++ b/include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp @@ -76,6 +76,32 @@ struct backtrace_holder { return res; } + + inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT { + if (frames_count != rhs.frames_count) { + return frames_count < rhs.frames_count; + } else if (frames.get() == rhs.frames.get()) { + return false; + } + + return std::lexicographical_compare( + frames.get(), frames.get() + frames_count, + rhs.frames.get(), rhs.frames.get() + rhs.frames_count + ); + } + + inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT { + if (frames_count != rhs.frames_count) { + return false; + } else if (frames.get() == rhs.frames.get()) { + return true; + } + + return std::equal( + frames.get(), frames.get() + frames_count, + rhs.frames.get() + ); + } }; }}} // namespace boost::stacktrace::detail diff --git a/include/boost/stacktrace/detail/backtrace_holder_linux.hpp b/include/boost/stacktrace/detail/backtrace_holder_linux.hpp index d7397e6..ab0bf04 100644 --- a/include/boost/stacktrace/detail/backtrace_holder_linux.hpp +++ b/include/boost/stacktrace/detail/backtrace_holder_linux.hpp @@ -50,6 +50,32 @@ struct backtrace_holder { return res; } + + inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT { + if (frames_count != rhs.frames_count) { + return frames_count < rhs.frames_count; + } else if (this == &rhs) { + return false; + } + + return std::lexicographical_compare( + buffer, buffer + frames_count, + rhs.buffer, rhs.buffer + rhs.frames_count + ); + } + + inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT { + if (frames_count != rhs.frames_count) { + return false; + } else if (this == &rhs) { + return true; + } + + return std::equal( + buffer, buffer + frames_count, + rhs.buffer + ); + } }; }}} // namespace boost::stacktrace::detail diff --git a/include/boost/stacktrace/detail/backtrace_holder_noop.hpp b/include/boost/stacktrace/detail/backtrace_holder_noop.hpp index 39be629..9903a03 100644 --- a/include/boost/stacktrace/detail/backtrace_holder_noop.hpp +++ b/include/boost/stacktrace/detail/backtrace_holder_noop.hpp @@ -23,6 +23,14 @@ struct backtrace_holder { inline std::string get_frame(std::size_t /*frame*/) const { return std::string(); } + + inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT { + return false; + } + + inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT { + return true; + } }; }}} // namespace boost::stacktrace::detail diff --git a/include/boost/stacktrace/detail/backtrace_holder_windows.hpp b/include/boost/stacktrace/detail/backtrace_holder_windows.hpp index 82043b8..3c1655a 100644 --- a/include/boost/stacktrace/detail/backtrace_holder_windows.hpp +++ b/include/boost/stacktrace/detail/backtrace_holder_windows.hpp @@ -79,6 +79,32 @@ struct backtrace_holder { } return res; } + + inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT { + if (frames_count != rhs.frames_count) { + return frames_count < rhs.frames_count; + } else if (this == &rhs) { + return false; + } + + return std::lexicographical_compare( + buffer, buffer + frames_count, + rhs.buffer, rhs.buffer + rhs.frames_count + ); + } + + inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT { + if (frames_count != rhs.frames_count) { + return false; + } else if (this == &rhs) { + return true; + } + + return std::equal( + buffer, buffer + frames_count, + rhs.buffer + ); + } }; }}} // namespace boost::stacktrace::detail diff --git a/include/boost/stacktrace/detail/stacktrace.ipp b/include/boost/stacktrace/detail/stacktrace.ipp index 3464692..e16f9e1 100644 --- a/include/boost/stacktrace/detail/stacktrace.ipp +++ b/include/boost/stacktrace/detail/stacktrace.ipp @@ -53,6 +53,13 @@ std::string stacktrace::operator[](std::size_t frame) const { return impl_.get_frame(frame); } +bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT { + return impl_ < rhs.impl_; +} + +bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT { + return impl_ == rhs.impl_; +} }} diff --git a/src/stacktrace_src.ipp b/src/stacktrace_src.ipp index 6f463b2..42a2380 100644 --- a/src/stacktrace_src.ipp +++ b/src/stacktrace_src.ipp @@ -67,6 +67,13 @@ std::string stacktrace::operator[](std::size_t frame) const { return boost::stacktrace::detail::to_bt(impl_).get_frame(frame); } +bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT { + return boost::stacktrace::detail::to_bt(impl_) < boost::stacktrace::detail::to_bt(rhs.impl_); +} + +bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT { + return boost::stacktrace::detail::to_bt(impl_) == boost::stacktrace::detail::to_bt(rhs.impl_); +} }} diff --git a/test/test.cpp b/test/test.cpp index 16daf5b..e601893 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -32,6 +32,8 @@ void test_deeply_nested_namespaces() { #if defined(BOOST_STACKTRACE_DYN_LINK) || !defined(BOOST_STACKTRACE_USE_BACKTRACE) BOOST_TEST(ss.str().find("get_backtrace_from_nested_namespaces") != std::string::npos); #endif + + // TODO: BOOST_TEST(return_from_nested_namespaces() != return_from_nested_namespaces()); } void test_nested() { @@ -61,10 +63,39 @@ void test_nested() { #endif } +void test_comparisons() { + stacktrace nst = return_from_nested_namespaces(); + stacktrace st; + stacktrace cst(st); + + BOOST_TEST(nst); + BOOST_TEST(st); + + BOOST_TEST(nst != st); + BOOST_TEST(st != nst); + BOOST_TEST(st == st); + BOOST_TEST(nst == nst); + + BOOST_TEST(nst != cst); + BOOST_TEST(cst != nst); + BOOST_TEST(cst == st); + BOOST_TEST(cst == cst); + + BOOST_TEST(nst < st || nst > st); + BOOST_TEST(st < nst || nst < st); + BOOST_TEST(st <= st); + BOOST_TEST(nst <= nst); + BOOST_TEST(st >= st); + BOOST_TEST(nst >= nst); + + BOOST_TEST(nst < cst || cst < nst); + BOOST_TEST(nst > cst || cst > nst); +} int main() { test_deeply_nested_namespaces(); test_nested(); + test_comparisons(); return boost::report_errors(); }