From 5c7bd327077ecf94f0b4cd033775c0d3531e6fe7 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 1 Jul 2023 08:27:19 -0700 Subject: [PATCH] remove boilerplate Signed-off-by: Rosen Penev --- src/image.cpp | 2 - unitTests/test_slice.cpp | 124 ++++++++++----------------------------- 2 files changed, 30 insertions(+), 96 deletions(-) diff --git a/src/image.cpp b/src/image.cpp index bfe1e1a53b..3452a241b3 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -461,10 +461,8 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct const size_t restore = io.tell(); io.seekOrThrow(offset, BasicIo::beg, ErrorCode::kerCorruptedMetadata); // position std::vector bytes(count); // allocate memory - // TODO: once we have C++11 use bytes.data() io.readOrThrow(bytes.data(), count, ErrorCode::kerCorruptedMetadata); io.seekOrThrow(restore, BasicIo::beg, ErrorCode::kerCorruptedMetadata); - // TODO: once we have C++11 use bytes.data() IptcData::printStructure(out, makeSliceUntil(bytes.data(), count), depth); } } else if (option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { diff --git a/unitTests/test_slice.cpp b/unitTests/test_slice.cpp index 086c4b3067..de758c3efd 100644 --- a/unitTests/test_slice.cpp +++ b/unitTests/test_slice.cpp @@ -11,42 +11,6 @@ using namespace Exiv2; template class slice; -/*! - * This namespace contains the helper-function get_test_data. It is intended - * to be used for test with the slice fixture: it returns the appropriate - * data to the constructor of slice. For (const) T==std::vector it returns the - * fixtures member vec_, for (const) T==int* it returns vec_.data() - * - * Due to C++98's limitations, this requires a separate traits class, that - * specifies the return type *and* a specialization of get_test_data for each - * case (maybe some can be reduced with SFINAE, but that ain't improving - * readability either). - * - * Unfortunately, C++11 will probably only make the return_type_traits go away, - * but not the template specializations of get_test_data (for that we need - * C++17, so see you in 2025). - */ -namespace cpp_98_boilerplate { -template -struct return_type_traits { - using type = T; -}; - -template -struct return_type_traits> { - using type = typename std::vector&; -}; - -template -struct return_type_traits> { - using type = const typename std::vector&; -}; - -template -typename return_type_traits::type get_test_data(slice& st); - -} // namespace cpp_98_boilerplate - /*! * Fixture for slice testing. Has one public vector of ints with size vec_size * that is filled with the numbers from 0 to vec_size - 1. @@ -63,45 +27,26 @@ class slice : public ::testing::Test { public: static const size_t vec_size = 10; - void SetUp() override { - vec_.reserve(vec_size); - for (unsigned int i = 0; i < vec_size; ++i) { - vec_.push_back(i); - } - } - Slice getTestSlice(size_t begin = 1, size_t end = vec_size - 1) { - return Slice(cpp_98_boilerplate::get_test_data(*this), begin, end); + return {getTestData(), begin, end}; } - // TODO: once we have C++11: use initializer list - std::vector vec_; + std::vector vec_{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + private: + auto getTestData() { + if constexpr (std::is_same_v>) { + return std::ref(vec_); + } else if constexpr (std::is_same_v>) { + return std::cref(vec_); + } else if constexpr (std::is_same_v) { + return vec_.data(); + } else if constexpr (std::is_same_v) { + return static_cast(vec_.data()); + } + } }; -// specializations of get_test_data are provided here, since they must have the -// full definition of slice available -namespace cpp_98_boilerplate { -template <> -int* get_test_data(slice& st) { - return st.vec_.data(); -} - -template <> -const int* get_test_data(slice& st) { - return st.vec_.data(); -} - -template <> -std::vector& get_test_data>(slice>& st) { - return st.vec_; -} - -template <> -const std::vector& get_test_data>(slice>& st) { - return st.vec_; -} -} // namespace cpp_98_boilerplate - /*! * Fixture to run test for mutable slices. * @@ -118,7 +63,7 @@ TYPED_TEST_P(slice, atAccess) { // typedef Slice slice_t; // const size_t begin = 1; // const size_t end = this->vec_.size() - 1; - Slice sl = this->getTestSlice(); + auto sl = this->getTestSlice(); ASSERT_EQ(this->vec_.size() - 2, sl.size()); @@ -129,7 +74,7 @@ TYPED_TEST_P(slice, atAccess) { // TODO C++11: test range based for loop TYPED_TEST_P(slice, iteratorAccess) { - Slice sl = this->getTestSlice(); + auto sl = this->getTestSlice(); auto vec_it = this->vec_.begin() + 1; for (auto it = sl.cbegin(); it < sl.cend(); ++it, ++vec_it) { @@ -172,7 +117,7 @@ TYPED_TEST_P(slice, subSliceFunctions) { TYPED_TEST_P(slice, subSliceFailedConstruction) { // 0 1 2 3 4 5 6 7 8 9 // | | middle - Slice middle = this->getTestSlice(4, 6); + auto middle = this->getTestSlice(4, 6); ASSERT_THROW(auto t = middle.subSlice(1, 5), std::out_of_range); ASSERT_THROW(auto t = middle.subSlice(2, 1), std::out_of_range); @@ -181,7 +126,7 @@ TYPED_TEST_P(slice, subSliceFailedConstruction) { /*! try to cause integer overflows in a sub-optimal implementation */ TYPED_TEST_P(slice, subSliceConstructionOverflowResistance) { - Slice center_vals = this->getTestSlice(3, 7); + auto center_vals = this->getTestSlice(3, 7); ASSERT_THROW(auto t = center_vals.subSlice(std::numeric_limits::max() - 2, 3), std::out_of_range); ASSERT_THROW(auto t = center_vals.subSlice(2, std::numeric_limits::max() - 1), std::out_of_range); @@ -292,16 +237,16 @@ TEST(containerSlice, failedConstructionFromContainer) { TEST(containerSlice, makeSlice) { std::string str = "this is a sentence"; - Slice is = makeSlice(str, 5, 7); + auto is = makeSlice(str, 5, 7); ASSERT_TRUE(std::equal(is.begin(), is.end(), "is")); - Slice sl_this = makeSliceUntil(str, 4); + auto sl_this = makeSliceUntil(str, 4); ASSERT_TRUE(std::equal(sl_this.begin(), sl_this.end(), "this")); - Slice sl_sentence = makeSliceFrom(str, 10); + auto sl_sentence = makeSliceFrom(str, 10); ASSERT_TRUE(std::equal(sl_sentence.begin(), sl_sentence.end(), "sentence")); - Slice sl_full = makeSlice(str); + auto sl_full = makeSlice(str); ASSERT_TRUE(std::equal(sl_full.begin(), sl_full.end(), str.c_str())); } @@ -314,27 +259,25 @@ struct stringSlice : public ::testing::Test { }; TEST_F(stringSlice, at) { - const Slice is_a = makeSlice(static_cast(this->sentence), 5, 10); + auto is_a = makeSlice(static_cast(this->sentence), 5, 10); ASSERT_EQ(is_a.at(0), 'i'); ASSERT_EQ(is_a.at(4), ' '); } TEST_F(stringSlice, atFailure) { - const Slice is_a = makeSlice(static_cast(this->sentence), 5, 10); + auto is_a = makeSlice(static_cast(this->sentence), 5, 10); ASSERT_THROW(is_a.at(5), std::out_of_range); } TEST_F(stringSlice, size) { - const Slice is_a = makeSlice(static_cast(this->sentence), 5, 10); + auto is_a = makeSlice(static_cast(this->sentence), 5, 10); ASSERT_EQ(is_a.size(), static_cast(5)); } TEST_F(stringSlice, mutateString) { - Slice is_a_mutable = makeSlice(this->sentence, 5, 10); - - for (auto it = is_a_mutable.begin(); it < is_a_mutable.end(); ++it) { - *it = ' '; + for (auto& m : makeSlice(this->sentence, 5, 10)) { + m = ' '; } ASSERT_STREQ(this->sentence.c_str(), "this sentence"); @@ -342,17 +285,10 @@ TEST_F(stringSlice, mutateString) { template struct dataBufSlice : public ::testing::Test { - static byte data[4]; // = {0xde, 0xad, 0xbe, 0xef}; - DataBuf buf; - - void SetUp() override { - buf = DataBuf(data, sizeof(data)); - } + static constexpr byte data[4] = {0xde, 0xad, 0xbe, 0xef}; + DataBuf buf = DataBuf(data, sizeof(data)); }; -template -byte dataBufSlice::data[4] = {0xde, 0xad, 0xbe, 0xef}; - TYPED_TEST_SUITE_P(dataBufSlice); TYPED_TEST_P(dataBufSlice, successfulConstruction) {