Skip to content

Commit b75dfd3

Browse files
committed
Added comparison operators and tests for them
1 parent 46860b5 commit b75dfd3

File tree

8 files changed

+149
-0
lines changed

8 files changed

+149
-0
lines changed

include/boost/stacktrace.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,27 @@ class stacktrace {
119119
return !size();
120120
}
121121

122+
/// @brief Allows to check that capturing stack trace was successful.
123+
/// @returns `true` if `this->size() != 0`
124+
///
125+
/// @b Complexity: O(1)
122126
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
127+
128+
/// @brief Compares stacktraces for less, order is platform dependant.
129+
///
130+
/// @b Complexity: Amortized O(1); worst case O(size())
131+
BOOST_STACKTRACE_FUNCTION bool operator< (const stacktrace& rhs) const BOOST_NOEXCEPT;
132+
133+
/// @brief Compares stacktraces for equality.
134+
///
135+
/// @b Complexity: Amortized O(1); worst case O(size())
136+
BOOST_STACKTRACE_FUNCTION bool operator==(const stacktrace& rhs) const BOOST_NOEXCEPT;
123137
};
124138

139+
inline bool operator> (const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return rhs < lhs; }
140+
inline bool operator<=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs > rhs); }
141+
inline bool operator>=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs < rhs); }
142+
inline bool operator!=(const stacktrace& lhs, const stacktrace& rhs) BOOST_NOEXCEPT { return !(lhs == rhs); }
125143

126144
/// Outputs stacktrace in a human readable format to output stream.
127145
template <class CharT, class TraitsT>

include/boost/stacktrace/detail/backtrace_holder_libunwind.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,32 @@ struct backtrace_holder {
7676

7777
return res;
7878
}
79+
80+
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
81+
if (frames_count != rhs.frames_count) {
82+
return frames_count < rhs.frames_count;
83+
} else if (frames.get() == rhs.frames.get()) {
84+
return false;
85+
}
86+
87+
return std::lexicographical_compare(
88+
frames.get(), frames.get() + frames_count,
89+
rhs.frames.get(), rhs.frames.get() + rhs.frames_count
90+
);
91+
}
92+
93+
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
94+
if (frames_count != rhs.frames_count) {
95+
return false;
96+
} else if (frames.get() == rhs.frames.get()) {
97+
return true;
98+
}
99+
100+
return std::equal(
101+
frames.get(), frames.get() + frames_count,
102+
rhs.frames.get()
103+
);
104+
}
79105
};
80106

81107
}}} // namespace boost::stacktrace::detail

include/boost/stacktrace/detail/backtrace_holder_linux.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,32 @@ struct backtrace_holder {
5050

5151
return res;
5252
}
53+
54+
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
55+
if (frames_count != rhs.frames_count) {
56+
return frames_count < rhs.frames_count;
57+
} else if (this == &rhs) {
58+
return false;
59+
}
60+
61+
return std::lexicographical_compare(
62+
buffer, buffer + frames_count,
63+
rhs.buffer, rhs.buffer + rhs.frames_count
64+
);
65+
}
66+
67+
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
68+
if (frames_count != rhs.frames_count) {
69+
return false;
70+
} else if (this == &rhs) {
71+
return true;
72+
}
73+
74+
return std::equal(
75+
buffer, buffer + frames_count,
76+
rhs.buffer
77+
);
78+
}
5379
};
5480

5581
}}} // namespace boost::stacktrace::detail

include/boost/stacktrace/detail/backtrace_holder_noop.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ struct backtrace_holder {
2323
inline std::string get_frame(std::size_t /*frame*/) const {
2424
return std::string();
2525
}
26+
27+
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
28+
return false;
29+
}
30+
31+
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
32+
return true;
33+
}
2634
};
2735

2836
}}} // namespace boost::stacktrace::detail

include/boost/stacktrace/detail/backtrace_holder_windows.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,32 @@ struct backtrace_holder {
7979
}
8080
return res;
8181
}
82+
83+
inline bool operator< (const backtrace_holder& rhs) const BOOST_NOEXCEPT {
84+
if (frames_count != rhs.frames_count) {
85+
return frames_count < rhs.frames_count;
86+
} else if (this == &rhs) {
87+
return false;
88+
}
89+
90+
return std::lexicographical_compare(
91+
buffer, buffer + frames_count,
92+
rhs.buffer, rhs.buffer + rhs.frames_count
93+
);
94+
}
95+
96+
inline bool operator==(const backtrace_holder& rhs) const BOOST_NOEXCEPT {
97+
if (frames_count != rhs.frames_count) {
98+
return false;
99+
} else if (this == &rhs) {
100+
return true;
101+
}
102+
103+
return std::equal(
104+
buffer, buffer + frames_count,
105+
rhs.buffer
106+
);
107+
}
82108
};
83109

84110
}}} // namespace boost::stacktrace::detail

include/boost/stacktrace/detail/stacktrace.ipp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ std::string stacktrace::operator[](std::size_t frame) const {
5353
return impl_.get_frame(frame);
5454
}
5555

56+
bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT {
57+
return impl_ < rhs.impl_;
58+
}
59+
60+
bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT {
61+
return impl_ == rhs.impl_;
62+
}
5663

5764
}}
5865

src/stacktrace_src.ipp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ std::string stacktrace::operator[](std::size_t frame) const {
6767
return boost::stacktrace::detail::to_bt(impl_).get_frame(frame);
6868
}
6969

70+
bool stacktrace::operator< (const stacktrace& rhs) const BOOST_NOEXCEPT {
71+
return boost::stacktrace::detail::to_bt(impl_) < boost::stacktrace::detail::to_bt(rhs.impl_);
72+
}
73+
74+
bool stacktrace::operator==(const stacktrace& rhs) const BOOST_NOEXCEPT {
75+
return boost::stacktrace::detail::to_bt(impl_) == boost::stacktrace::detail::to_bt(rhs.impl_);
76+
}
7077

7178
}}
7279

test/test.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ void test_deeply_nested_namespaces() {
3232
#if defined(BOOST_STACKTRACE_DYN_LINK) || !defined(BOOST_STACKTRACE_USE_BACKTRACE)
3333
BOOST_TEST(ss.str().find("get_backtrace_from_nested_namespaces") != std::string::npos);
3434
#endif
35+
36+
// TODO: BOOST_TEST(return_from_nested_namespaces() != return_from_nested_namespaces());
3537
}
3638

3739
void test_nested() {
@@ -61,10 +63,39 @@ void test_nested() {
6163
#endif
6264
}
6365

66+
void test_comparisons() {
67+
stacktrace nst = return_from_nested_namespaces();
68+
stacktrace st;
69+
stacktrace cst(st);
70+
71+
BOOST_TEST(nst);
72+
BOOST_TEST(st);
73+
74+
BOOST_TEST(nst != st);
75+
BOOST_TEST(st != nst);
76+
BOOST_TEST(st == st);
77+
BOOST_TEST(nst == nst);
78+
79+
BOOST_TEST(nst != cst);
80+
BOOST_TEST(cst != nst);
81+
BOOST_TEST(cst == st);
82+
BOOST_TEST(cst == cst);
83+
84+
BOOST_TEST(nst < st || nst > st);
85+
BOOST_TEST(st < nst || nst < st);
86+
BOOST_TEST(st <= st);
87+
BOOST_TEST(nst <= nst);
88+
BOOST_TEST(st >= st);
89+
BOOST_TEST(nst >= nst);
90+
91+
BOOST_TEST(nst < cst || cst < nst);
92+
BOOST_TEST(nst > cst || cst > nst);
93+
}
6494

6595
int main() {
6696
test_deeply_nested_namespaces();
6797
test_nested();
98+
test_comparisons();
6899

69100
return boost::report_errors();
70101
}

0 commit comments

Comments
 (0)