From bd59ec8bef7a9d21a05a2638651e212a1d46941e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Tue, 25 Oct 2016 21:51:27 +0300 Subject: [PATCH] Strted implmenting the iterators and frame class --- include/boost/stacktrace.hpp | 89 +++++++++++++++++++++++++++++++++++- test/test.cpp | 63 +++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/include/boost/stacktrace.hpp b/include/boost/stacktrace.hpp index 93d0ecf..a51c9ab 100644 --- a/include/boost/stacktrace.hpp +++ b/include/boost/stacktrace.hpp @@ -14,6 +14,10 @@ #include #include + +#include +#include + #include #include @@ -78,6 +82,71 @@ namespace boost { namespace stacktrace { +class stacktrace; + +class frame { + void* frame_no_; +public: +}; + +//typedef std::string frame; + +/// @cond +namespace detail { + +class iterator : public boost::iterator_facade< + iterator, + const frame, + boost::random_access_traversal_tag> +{ + typedef boost::iterator_facade< + iterator, + const frame, + boost::random_access_traversal_tag + > base_t; + + const stacktrace* impl_; + std::size_t frame_no_; + + iterator(const stacktrace* impl, std::size_t frame_no) BOOST_NOEXCEPT + : impl_(impl) + , frame_no_(frame_no) + {} + + friend class ::boost::stacktrace::stacktrace; + friend class ::boost::iterators::iterator_core_access; + + const frame& dereference() const; /* { + return (*impl_)[frame_no_]; + }*/ + + bool equal(const iterator& it) const BOOST_NOEXCEPT { + return impl_ == it.impl_ && frame_no_ == it.frame_no_; + } + + void increment() BOOST_NOEXCEPT { + ++frame_no_; + } + + void decrement() BOOST_NOEXCEPT { + --frame_no_; + } + + void advance(std::size_t n) BOOST_NOEXCEPT { + frame_no_ += n; + } + + base_t::difference_type distance_to(const iterator& it) const { + BOOST_ASSERT(impl_ == it.impl_); + return it.frame_no_ - frame_no_; + } +public: + +}; + +} // namespace detail +/// @endcond + class stacktrace { #ifdef BOOST_STACKTRACE_LINK BOOST_STATIC_CONSTEXPR std::size_t max_implementation_size = sizeof(void*) * 110u; @@ -89,6 +158,22 @@ class stacktrace { std::size_t hash_code_; public: + typedef frame value_type; + typedef boost::stacktrace::detail::iterator iterator; + typedef iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(this, 0); } + const_iterator cbegin() const BOOST_NOEXCEPT { return const_iterator(this, 0); } + const_iterator end() const BOOST_NOEXCEPT { return const_iterator(this, size()); } + const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(this, size()); } + + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, 0) ); } + const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, 0) ); } + const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, size()) ); } + const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator( const_iterator(this, size()) ); } + /// @brief Stores the current function call sequence inside the class. /// /// @b Complexity: O(N) where N is call seaquence length, O(1) for noop backend. @@ -108,14 +193,14 @@ public: /// @b Complexity: O(1) BOOST_STACKTRACE_FUNCTION std::size_t size() const BOOST_NOEXCEPT; - /// @param frame Zero based index of function to return. 0 + /// @param frame_no Zero based index of function to return. 0 /// is the function index where stacktrace was constructed and /// index close to this->size() contains function `main()`. /// @returns Function name in a human readable form. /// @throws std::bad_alloc if not enough memory to construct resulting string. /// /// @b Complexity: Amortized O(1), O(1) for noop backend. - BOOST_STACKTRACE_FUNCTION std::string operator[](std::size_t frame) const; + BOOST_STACKTRACE_FUNCTION std::string operator[](std::size_t frame_no) const; /// @cond bool operator!() const BOOST_NOEXCEPT { diff --git a/test/test.cpp b/test/test.cpp index acd8453..3b5347f 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -100,10 +100,73 @@ void test_comparisons() { BOOST_TEST(hash_value(st) != hash_value(nst)); } +void test_iterators() { + stacktrace nst = return_from_nested_namespaces(); + stacktrace st; + + BOOST_TEST(nst.begin() != st.begin()); + BOOST_TEST(nst.cbegin() != st.cbegin()); + BOOST_TEST(nst.crbegin() != st.crbegin()); + BOOST_TEST(nst.rbegin() != st.rbegin()); + + BOOST_TEST(st.begin() == st.begin()); + BOOST_TEST(st.cbegin() == st.cbegin()); + BOOST_TEST(st.crbegin() == st.crbegin()); + BOOST_TEST(st.rbegin() == st.rbegin()); + + BOOST_TEST(++st.begin() == ++st.begin()); + BOOST_TEST(++st.cbegin() == ++st.cbegin()); + BOOST_TEST(++st.crbegin() == ++st.crbegin()); + BOOST_TEST(++st.rbegin() == ++st.rbegin()); + + BOOST_TEST(st.begin() + 1 == st.begin() + 1); + BOOST_TEST(st.cbegin() + 1 == st.cbegin() + 1); + BOOST_TEST(st.crbegin() + 1 == st.crbegin() + 1); + BOOST_TEST(st.rbegin() + 1 == st.rbegin() + 1); + + BOOST_TEST(nst.end() != st.end()); + BOOST_TEST(nst.cend() != st.cend()); + BOOST_TEST(nst.crend() != st.crend()); + BOOST_TEST(nst.rend() != st.rend()); + + BOOST_TEST(st.end() == st.end()); + BOOST_TEST(st.cend() == st.cend()); + BOOST_TEST(st.crend() == st.crend()); + BOOST_TEST(st.rend() == st.rend()); + + BOOST_TEST(--st.end() == --st.end()); + BOOST_TEST(--st.cend() == --st.cend()); + BOOST_TEST(--st.crend() == --st.crend()); + BOOST_TEST(--st.rend() == --st.rend()); + + + BOOST_TEST(st.end() > st.begin()); + BOOST_TEST(st.end() > st.cbegin()); + BOOST_TEST(st.cend() > st.cbegin()); + BOOST_TEST(st.cend() > st.begin()); + + + BOOST_TEST(st.size() == static_cast(st.end() - st.begin())); + BOOST_TEST(st.size() == static_cast(st.end() - st.cbegin())); + BOOST_TEST(st.size() == static_cast(st.cend() - st.cbegin())); + BOOST_TEST(st.size() == static_cast(st.cend() - st.begin())); + + BOOST_TEST(st.size() == static_cast(std::distance(st.rend(), st.rbegin()))); + BOOST_TEST(st.size() == static_cast(std::distance(st.rend(), st.crbegin()))); + BOOST_TEST(st.size() == static_cast(std::distance(st.crend(), st.crbegin()))); + BOOST_TEST(st.size() == static_cast(std::distance(st.crend(), st.rbegin()))); + + + boost::stacktrace::stacktrace::iterator it = st.begin(); + ++ it; + BOOST_TEST(it == st.begin() + 1); +} + int main() { test_deeply_nested_namespaces(); test_nested(); test_comparisons(); + test_iterators(); return boost::report_errors(); }