Commit da6bf118 authored by Dominik Charousset's avatar Dominik Charousset

Fix handling of vector<bool>

parent d4e9f99b
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <functional> #include <functional>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector>
#include "caf/detail/append_hex.hpp" #include "caf/detail/append_hex.hpp"
#include "caf/detail/apply_args.hpp" #include "caf/detail/apply_args.hpp"
...@@ -80,26 +81,23 @@ public: ...@@ -80,26 +81,23 @@ public:
void consume(const char* cstr); void consume(const char* cstr);
void consume(float x); void consume(const std::vector<bool>& xs);
void consume(double x); template <class T>
enable_if_t<std::is_floating_point<T>::value> consume(T x) {
void consume(long double x); result_ += std::to_string(x);
}
void consume(int64_t x);
void consume(uint64_t x);
template <class T> template <class T>
enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value> enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value>
consume(T x) { consume(T x) {
consume(static_cast<int64_t>(x)); consume_int(static_cast<int64_t>(x));
} }
template <class T> template <class T>
enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value> enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value>
consume(T x) { consume(T x) {
consume(static_cast<uint64_t>(x)); consume_int(static_cast<uint64_t>(x));
} }
template <class Clock, class Duration> template <class Clock, class Duration>
...@@ -165,6 +163,16 @@ public: ...@@ -165,6 +163,16 @@ public:
result_ += '}'; result_ += '}';
} }
template <class Iterator>
void consume_range(Iterator first, Iterator last) {
result_ += '[';
while (first != last) {
sep();
consume(*first++);
}
result_ += ']';
}
template <class T> template <class T>
enable_if_t<is_iterable<T>::value && !is_map_like<T>::value enable_if_t<is_iterable<T>::value && !is_map_like<T>::value
&& !is_inspectable<stringification_inspector, T>::value && !is_inspectable<stringification_inspector, T>::value
...@@ -172,14 +180,12 @@ public: ...@@ -172,14 +180,12 @@ public:
&& !is_inspectable<stringification_inspector, T>::value && !is_inspectable<stringification_inspector, T>::value
&& !has_to_string<T>::value> && !has_to_string<T>::value>
consume(const T& xs) { consume(const T& xs) {
result_ += '['; consume_range(xs.begin(), xs.end());
// use a hand-written for loop instead of for-each to avoid
// range-loop-analysis warnings when using this function with vector<bool>
for (auto i = xs.begin(); i != xs.end(); ++i) {
sep();
consume(*i);
} }
result_ += ']';
template <class T, size_t S>
void consume(const T (&xs)[S]) {
return consume_range(xs, xs + S);
} }
template <class T> template <class T>
...@@ -193,26 +199,6 @@ public: ...@@ -193,26 +199,6 @@ public:
result_ += ']'; result_ += ']';
} }
template <class T>
void consume(const T* xs, size_t n) {
result_ += '(';
for (size_t i = 0; i < n; ++i) {
sep();
consume(xs[i]);
}
result_ += ')';
}
template <class T, size_t S>
void consume(const std::array<T, S>& xs) {
return consume(xs.data(), S);
}
template <class T, size_t S>
void consume(const T (&xs)[S]) {
return consume(xs, S);
}
template <class T> template <class T>
enable_if_t< enable_if_t<
std::is_pointer<T>::value std::is_pointer<T>::value
...@@ -304,6 +290,10 @@ public: ...@@ -304,6 +290,10 @@ public:
} }
private: private:
void consume_int(int64_t x);
void consume_int(uint64_t x);
std::string& result_; std::string& result_;
}; };
......
...@@ -173,21 +173,18 @@ void stringification_inspector::consume(const char* cstr) { ...@@ -173,21 +173,18 @@ void stringification_inspector::consume(const char* cstr) {
result_ += '"'; result_ += '"';
} }
void stringification_inspector::consume(float x) { void stringification_inspector::consume(const std::vector<bool>& xs) {
result_ += std::to_string(x); result_ += '[';
} for (bool x : xs) {
sep();
void stringification_inspector::consume(double x) { consume(x);
result_ += std::to_string(x); }
} result_ += ']';
void stringification_inspector::consume(long double x) {
result_ += std::to_string(x);
} }
void stringification_inspector::consume(int64_t x) { void stringification_inspector::consume_int(int64_t x) {
if (x >= 0) if (x >= 0)
return consume(static_cast<uint64_t>(x)); return consume_int(static_cast<uint64_t>(x));
result_ += '-'; result_ += '-';
auto begin = result_.size(); auto begin = result_.size();
result_ += -(x % 10) + '0'; result_ += -(x % 10) + '0';
...@@ -199,7 +196,7 @@ void stringification_inspector::consume(int64_t x) { ...@@ -199,7 +196,7 @@ void stringification_inspector::consume(int64_t x) {
std::reverse(result_.begin() + begin, result_.end()); std::reverse(result_.begin() + begin, result_.end());
} }
void stringification_inspector::consume(uint64_t x) { void stringification_inspector::consume_int(uint64_t x) {
auto begin = result_.size(); auto begin = result_.size();
result_ += (x % 10) + '0'; result_ += (x % 10) + '0';
x /= 10; x /= 10;
......
...@@ -32,16 +32,38 @@ void foobar() { ...@@ -32,16 +32,38 @@ void foobar() {
} // namespace <anonymous> } // namespace <anonymous>
#define CHECK_DEEP_TO_STRING(val, str) CAF_CHECK_EQUAL(deep_to_string(val), str)
CAF_TEST(timespans) { CAF_TEST(timespans) {
CAF_CHECK_EQUAL(deep_to_string(timespan{1}), "1ns"); CHECK_DEEP_TO_STRING(timespan{1}, "1ns");
CAF_CHECK_EQUAL(deep_to_string(timespan{1000}), "1us"); CHECK_DEEP_TO_STRING(timespan{1000}, "1us");
CAF_CHECK_EQUAL(deep_to_string(timespan{1000000}), "1ms"); CHECK_DEEP_TO_STRING(timespan{1000000}, "1ms");
CAF_CHECK_EQUAL(deep_to_string(timespan{1000000000}), "1s"); CHECK_DEEP_TO_STRING(timespan{1000000000}, "1s");
CAF_CHECK_EQUAL(deep_to_string(timespan{60000000000}), "1min"); CHECK_DEEP_TO_STRING(timespan{60000000000}, "1min");
}
CAF_TEST(integer lists) {
int carray[] = {1, 2, 3, 4};
using array_type = std::array<int, 4>;
CHECK_DEEP_TO_STRING(std::list<int>({1, 2, 3, 4}), "[1, 2, 3, 4]");
CHECK_DEEP_TO_STRING(std::vector<int>({1, 2, 3, 4}), "[1, 2, 3, 4]");
CHECK_DEEP_TO_STRING(std::set<int>({1, 2, 3, 4}), "[1, 2, 3, 4]");
CHECK_DEEP_TO_STRING(array_type({{1, 2, 3, 4}}), "[1, 2, 3, 4]");
CHECK_DEEP_TO_STRING(carray, "[1, 2, 3, 4]");
}
CAF_TEST(boolean lists) {
bool carray[] = {false, true};
using array_type = std::array<bool, 2>;
CHECK_DEEP_TO_STRING(std::list<bool>({false, true}), "[false, true]");
CHECK_DEEP_TO_STRING(std::vector<bool>({false, true}), "[false, true]");
CHECK_DEEP_TO_STRING(std::set<bool>({false, true}), "[false, true]");
CHECK_DEEP_TO_STRING(array_type({{false, true}}), "[false, true]");
CHECK_DEEP_TO_STRING(carray, "[false, true]");
} }
CAF_TEST(pointers) { CAF_TEST(pointers) {
auto i = 42; auto i = 42;
CAF_CHECK_EQUAL(deep_to_string(&i), "*42"); CHECK_DEEP_TO_STRING(&i, "*42");
CAF_CHECK_EQUAL(deep_to_string(foobar), "<fun>"); CHECK_DEEP_TO_STRING(foobar, "<fun>");
} }
...@@ -272,10 +272,10 @@ CAF_TEST(tuples_to_string) { ...@@ -272,10 +272,10 @@ CAF_TEST(tuples_to_string) {
} }
CAF_TEST(arrays_to_string) { CAF_TEST(arrays_to_string) {
CAF_CHECK_EQUAL(msg_as_string(s1{}), "((10, 20, 30))"); CAF_CHECK_EQUAL(msg_as_string(s1{}), "([10, 20, 30])");
auto msg2 = make_message(s2{}); auto msg2 = make_message(s2{});
s2 tmp; s2 tmp;
tmp.value[0][1] = 100; tmp.value[0][1] = 100;
CAF_CHECK_EQUAL(to_string(msg2), "(((1, 10), (2, 20), (3, 30), (4, 40)))"); CAF_CHECK_EQUAL(to_string(msg2), "([[1, 10], [2, 20], [3, 30], [4, 40]])");
CAF_CHECK_EQUAL(msg_as_string(s3{}), "((1, 2, 3, 4))"); CAF_CHECK_EQUAL(msg_as_string(s3{}), "([1, 2, 3, 4])");
} }
...@@ -554,7 +554,7 @@ SERIALIZATION_TEST(bool_vector_size_0) { ...@@ -554,7 +554,7 @@ SERIALIZATION_TEST(bool_vector_size_0) {
SERIALIZATION_TEST(bool_vector_size_1) { SERIALIZATION_TEST(bool_vector_size_1) {
std::vector<bool> xs{true}; std::vector<bool> xs{true};
CAF_CHECK_EQUAL(deep_to_string(xs), "[1]"); CAF_CHECK_EQUAL(deep_to_string(xs), "[true]");
CAF_CHECK_EQUAL(xs, roundtrip(xs)); CAF_CHECK_EQUAL(xs, roundtrip(xs));
CAF_CHECK_EQUAL(xs, msg_roundtrip(xs)); CAF_CHECK_EQUAL(xs, msg_roundtrip(xs));
} }
...@@ -563,11 +563,14 @@ SERIALIZATION_TEST(bool_vector_size_63) { ...@@ -563,11 +563,14 @@ SERIALIZATION_TEST(bool_vector_size_63) {
std::vector<bool> xs; std::vector<bool> xs;
for (int i = 0; i < 63; ++i) for (int i = 0; i < 63; ++i)
xs.push_back(i % 3 == 0); xs.push_back(i % 3 == 0);
CAF_CHECK_EQUAL(deep_to_string(xs), CAF_CHECK_EQUAL(
"[1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, " deep_to_string(xs),
"0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, " "[true, false, false, true, false, false, true, false, false, true, false, "
"1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, " "false, true, false, false, true, false, false, true, false, false, true, "
"0, 1, 0, 0]"); "false, false, true, false, false, true, false, false, true, false, false, "
"true, false, false, true, false, false, true, false, false, true, false, "
"false, true, false, false, true, false, false, true, false, false, true, "
"false, false, true, false, false, true, false, false]");
CAF_CHECK_EQUAL(xs, roundtrip(xs)); CAF_CHECK_EQUAL(xs, roundtrip(xs));
CAF_CHECK_EQUAL(xs, msg_roundtrip(xs)); CAF_CHECK_EQUAL(xs, msg_roundtrip(xs));
} }
...@@ -577,10 +580,14 @@ SERIALIZATION_TEST(bool_vector_size_64) { ...@@ -577,10 +580,14 @@ SERIALIZATION_TEST(bool_vector_size_64) {
for (int i = 0; i < 64; ++i) for (int i = 0; i < 64; ++i)
xs.push_back(i % 5 == 0); xs.push_back(i % 5 == 0);
CAF_CHECK_EQUAL(deep_to_string(xs), CAF_CHECK_EQUAL(deep_to_string(xs),
"[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, " "[true, false, false, false, false, true, false, false, "
"0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, " "false, false, true, false, false, false, false, true, "
"0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, " "false, false, false, false, true, false, false, false, "
"0, 1, 0, 0, 0]"); "false, true, false, false, false, false, true, false, "
"false, false, false, true, false, false, false, false, "
"true, false, false, false, false, true, false, false, "
"false, false, true, false, false, false, false, true, "
"false, false, false, false, true, false, false, false]");
CAF_CHECK_EQUAL(xs, roundtrip(xs)); CAF_CHECK_EQUAL(xs, roundtrip(xs));
CAF_CHECK_EQUAL(xs, msg_roundtrip(xs)); CAF_CHECK_EQUAL(xs, msg_roundtrip(xs));
} }
...@@ -589,11 +596,14 @@ SERIALIZATION_TEST(bool_vector_size_65) { ...@@ -589,11 +596,14 @@ SERIALIZATION_TEST(bool_vector_size_65) {
std::vector<bool> xs; std::vector<bool> xs;
for (int i = 0; i < 65; ++i) for (int i = 0; i < 65; ++i)
xs.push_back(!(i % 7 == 0)); xs.push_back(!(i % 7 == 0));
CAF_CHECK_EQUAL(deep_to_string(xs), CAF_CHECK_EQUAL(
"[0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, " deep_to_string(xs),
"1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, " "[false, true, true, true, true, true, true, false, true, true, true, "
"1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, " "true, true, true, false, true, true, true, true, true, true, false, true, "
"1, 1, 1, 1, 0, 1]"); "true, true, true, true, true, false, true, true, true, true, true, true, "
"false, true, true, true, true, true, true, false, true, true, true, true, "
"true, true, false, true, true, true, true, true, true, false, true, true, "
"true, true, true, true, false, true]");
CAF_CHECK_EQUAL(xs, roundtrip(xs)); CAF_CHECK_EQUAL(xs, roundtrip(xs));
CAF_CHECK_EQUAL(xs, msg_roundtrip(xs)); CAF_CHECK_EQUAL(xs, msg_roundtrip(xs));
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment