remove boilerplate

Signed-off-by: Rosen Penev <rosenp@gmail.com>
main
Rosen Penev 2 years ago
parent 3f083197fd
commit 6b4732365b

@ -481,10 +481,8 @@ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStruct
const size_t restore = io.tell(); const size_t restore = io.tell();
io.seekOrThrow(offset, BasicIo::beg, ErrorCode::kerCorruptedMetadata); // position io.seekOrThrow(offset, BasicIo::beg, ErrorCode::kerCorruptedMetadata); // position
std::vector<byte> bytes(count); // allocate memory std::vector<byte> bytes(count); // allocate memory
// TODO: once we have C++11 use bytes.data()
io.readOrThrow(bytes.data(), count, ErrorCode::kerCorruptedMetadata); io.readOrThrow(bytes.data(), count, ErrorCode::kerCorruptedMetadata);
io.seekOrThrow(restore, BasicIo::beg, 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); IptcData::printStructure(out, makeSliceUntil(bytes.data(), count), depth);
} }
} else if (option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { } else if (option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) {

@ -11,42 +11,6 @@ using namespace Exiv2;
template <typename T> template <typename T>
class slice; 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 <typename T>
struct return_type_traits {
using type = T;
};
template <typename U>
struct return_type_traits<std::vector<U>> {
using type = typename std::vector<U>&;
};
template <typename U>
struct return_type_traits<const std::vector<U>> {
using type = const typename std::vector<U>&;
};
template <typename T>
typename return_type_traits<T>::type get_test_data(slice<T>& st);
} // namespace cpp_98_boilerplate
/*! /*!
* Fixture for slice testing. Has one public vector of ints with size vec_size * 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. * that is filled with the numbers from 0 to vec_size - 1.
@ -63,44 +27,25 @@ class slice : public ::testing::Test {
public: public:
static const size_t vec_size = 10; 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<T> getTestSlice(size_t begin = 1, size_t end = vec_size - 1) { Slice<T> getTestSlice(size_t begin = 1, size_t end = vec_size - 1) {
return Slice<T>(cpp_98_boilerplate::get_test_data<T>(*this), begin, end); return {getTestData(), begin, end};
}
// TODO: once we have C++11: use initializer list
std::vector<int> vec_;
};
// 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<int*>(slice<int*>& st) {
return st.vec_.data();
} }
template <> std::vector<int> vec_{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
const int* get_test_data<const int*>(slice<const int*>& st) {
return st.vec_.data();
}
template <> private:
std::vector<int>& get_test_data<std::vector<int>>(slice<std::vector<int>>& st) { auto getTestData() {
return st.vec_; if constexpr (std::is_same_v<T, std::vector<int>>) {
return std::ref(vec_);
} else if constexpr (std::is_same_v<T, const std::vector<int>>) {
return std::cref(vec_);
} else if constexpr (std::is_same_v<T, int*>) {
return vec_.data();
} else if constexpr (std::is_same_v<T, const int*>) {
return static_cast<const int*>(vec_.data());
} }
template <>
const std::vector<int>& get_test_data<const std::vector<int>>(slice<const std::vector<int>>& st) {
return st.vec_;
} }
} // namespace cpp_98_boilerplate };
/*! /*!
* Fixture to run test for mutable slices. * Fixture to run test for mutable slices.
@ -118,7 +63,7 @@ TYPED_TEST_P(slice, atAccess) {
// typedef Slice<TypeParam> slice_t; // typedef Slice<TypeParam> slice_t;
// const size_t begin = 1; // const size_t begin = 1;
// const size_t end = this->vec_.size() - 1; // const size_t end = this->vec_.size() - 1;
Slice<TypeParam> sl = this->getTestSlice(); auto sl = this->getTestSlice();
ASSERT_EQ(this->vec_.size() - 2, sl.size()); 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 // TODO C++11: test range based for loop
TYPED_TEST_P(slice, iteratorAccess) { TYPED_TEST_P(slice, iteratorAccess) {
Slice<TypeParam> sl = this->getTestSlice(); auto sl = this->getTestSlice();
auto vec_it = this->vec_.begin() + 1; auto vec_it = this->vec_.begin() + 1;
for (auto it = sl.cbegin(); it < sl.cend(); ++it, ++vec_it) { for (auto it = sl.cbegin(); it < sl.cend(); ++it, ++vec_it) {
@ -174,7 +119,7 @@ TYPED_TEST_P(slice, subSliceFunctions) {
TYPED_TEST_P(slice, subSliceFailedConstruction) { TYPED_TEST_P(slice, subSliceFailedConstruction) {
// 0 1 2 3 4 5 6 7 8 9 // 0 1 2 3 4 5 6 7 8 9
// | | middle // | | middle
Slice<TypeParam> middle = this->getTestSlice(4, 6); auto middle = this->getTestSlice(4, 6);
ASSERT_THROW(middle.subSlice(1, 5), std::out_of_range); ASSERT_THROW(middle.subSlice(1, 5), std::out_of_range);
ASSERT_THROW(middle.subSlice(2, 1), std::out_of_range); ASSERT_THROW(middle.subSlice(2, 1), std::out_of_range);
@ -183,7 +128,7 @@ TYPED_TEST_P(slice, subSliceFailedConstruction) {
/*! try to cause integer overflows in a sub-optimal implementation */ /*! try to cause integer overflows in a sub-optimal implementation */
TYPED_TEST_P(slice, subSliceConstructionOverflowResistance) { TYPED_TEST_P(slice, subSliceConstructionOverflowResistance) {
Slice<TypeParam> center_vals = this->getTestSlice(3, 7); auto center_vals = this->getTestSlice(3, 7);
ASSERT_THROW(center_vals.subSlice(std::numeric_limits<size_t>::max() - 2, 3), std::out_of_range); ASSERT_THROW(center_vals.subSlice(std::numeric_limits<size_t>::max() - 2, 3), std::out_of_range);
ASSERT_THROW(center_vals.subSlice(2, std::numeric_limits<size_t>::max() - 1), std::out_of_range); ASSERT_THROW(center_vals.subSlice(2, std::numeric_limits<size_t>::max() - 1), std::out_of_range);
@ -294,16 +239,16 @@ TEST(containerSlice, failedConstructionFromContainer) {
TEST(containerSlice, makeSlice) { TEST(containerSlice, makeSlice) {
std::string str = "this is a sentence"; std::string str = "this is a sentence";
Slice<std::string> is = makeSlice(str, 5, 7); auto is = makeSlice(str, 5, 7);
ASSERT_TRUE(std::equal(is.begin(), is.end(), "is")); ASSERT_TRUE(std::equal(is.begin(), is.end(), "is"));
Slice<std::string> sl_this = makeSliceUntil(str, 4); auto sl_this = makeSliceUntil(str, 4);
ASSERT_TRUE(std::equal(sl_this.begin(), sl_this.end(), "this")); ASSERT_TRUE(std::equal(sl_this.begin(), sl_this.end(), "this"));
Slice<std::string> sl_sentence = makeSliceFrom(str, 10); auto sl_sentence = makeSliceFrom(str, 10);
ASSERT_TRUE(std::equal(sl_sentence.begin(), sl_sentence.end(), "sentence")); ASSERT_TRUE(std::equal(sl_sentence.begin(), sl_sentence.end(), "sentence"));
Slice<std::string> sl_full = makeSlice(str); auto sl_full = makeSlice(str);
ASSERT_TRUE(std::equal(sl_full.begin(), sl_full.end(), str.c_str())); ASSERT_TRUE(std::equal(sl_full.begin(), sl_full.end(), str.c_str()));
} }
@ -316,27 +261,25 @@ struct stringSlice : public ::testing::Test {
}; };
TEST_F(stringSlice, at) { TEST_F(stringSlice, at) {
const Slice<const std::string> is_a = makeSlice(static_cast<const std::string&>(this->sentence), 5, 10); auto is_a = makeSlice(static_cast<const std::string&>(this->sentence), 5, 10);
ASSERT_EQ(is_a.at(0), 'i'); ASSERT_EQ(is_a.at(0), 'i');
ASSERT_EQ(is_a.at(4), ' '); ASSERT_EQ(is_a.at(4), ' ');
} }
TEST_F(stringSlice, atFailure) { TEST_F(stringSlice, atFailure) {
const Slice<const std::string> is_a = makeSlice(static_cast<const std::string&>(this->sentence), 5, 10); auto is_a = makeSlice(static_cast<const std::string&>(this->sentence), 5, 10);
ASSERT_THROW(is_a.at(5), std::out_of_range); ASSERT_THROW(is_a.at(5), std::out_of_range);
} }
TEST_F(stringSlice, size) { TEST_F(stringSlice, size) {
const Slice<const std::string> is_a = makeSlice(static_cast<const std::string&>(this->sentence), 5, 10); auto is_a = makeSlice(static_cast<const std::string&>(this->sentence), 5, 10);
ASSERT_EQ(is_a.size(), static_cast<size_t>(5)); ASSERT_EQ(is_a.size(), static_cast<size_t>(5));
} }
TEST_F(stringSlice, mutateString) { TEST_F(stringSlice, mutateString) {
Slice<std::string> is_a_mutable = makeSlice(this->sentence, 5, 10); for (auto& m : makeSlice(this->sentence, 5, 10)) {
m = ' ';
for (auto it = is_a_mutable.begin(); it < is_a_mutable.end(); ++it) {
*it = ' ';
} }
ASSERT_STREQ(this->sentence.c_str(), "this sentence"); ASSERT_STREQ(this->sentence.c_str(), "this sentence");
@ -344,17 +287,10 @@ TEST_F(stringSlice, mutateString) {
template <typename T> template <typename T>
struct dataBufSlice : public ::testing::Test { struct dataBufSlice : public ::testing::Test {
static byte data[4]; // = {0xde, 0xad, 0xbe, 0xef}; static constexpr byte data[4] = {0xde, 0xad, 0xbe, 0xef};
DataBuf buf; DataBuf buf = DataBuf(data, sizeof(data));
void SetUp() override {
buf = DataBuf(data, sizeof(data));
}
}; };
template <typename T>
byte dataBufSlice<T>::data[4] = {0xde, 0xad, 0xbe, 0xef};
TYPED_TEST_SUITE_P(dataBufSlice); TYPED_TEST_SUITE_P(dataBufSlice);
TYPED_TEST_P(dataBufSlice, successfulConstruction) { TYPED_TEST_P(dataBufSlice, successfulConstruction) {

Loading…
Cancel
Save