Skip to content

Commit

Permalink
remove boilerplate
Browse files Browse the repository at this point in the history
Signed-off-by: Rosen Penev <[email protected]>
  • Loading branch information
neheb committed Jul 14, 2023
1 parent cc4b0d6 commit 5c7bd32
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 96 deletions.
2 changes: 0 additions & 2 deletions src/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<byte> 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) {
Expand Down
124 changes: 30 additions & 94 deletions unitTests/test_slice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,6 @@ using namespace Exiv2;
template <typename T>
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
* that is filled with the numbers from 0 to vec_size - 1.
Expand All @@ -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<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_;
std::vector<int> vec_{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

private:
auto getTestData() {
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());
}
}
};

// 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 <>
const int* get_test_data<const int*>(slice<const int*>& st) {
return st.vec_.data();
}

template <>
std::vector<int>& get_test_data<std::vector<int>>(slice<std::vector<int>>& st) {
return st.vec_;
}

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.
*
Expand All @@ -118,7 +63,7 @@ TYPED_TEST_P(slice, atAccess) {
// typedef Slice<TypeParam> slice_t;
// const size_t begin = 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());

Expand All @@ -129,7 +74,7 @@ TYPED_TEST_P(slice, atAccess) {

// TODO C++11: test range based for loop
TYPED_TEST_P(slice, iteratorAccess) {
Slice<TypeParam> 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) {
Expand Down Expand Up @@ -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<TypeParam> 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);
Expand All @@ -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<TypeParam> center_vals = this->getTestSlice(3, 7);
auto center_vals = this->getTestSlice(3, 7);

ASSERT_THROW(auto t = center_vals.subSlice(std::numeric_limits<size_t>::max() - 2, 3), std::out_of_range);
ASSERT_THROW(auto t = center_vals.subSlice(2, std::numeric_limits<size_t>::max() - 1), std::out_of_range);
Expand Down Expand Up @@ -292,16 +237,16 @@ TEST(containerSlice, failedConstructionFromContainer) {
TEST(containerSlice, makeSlice) {
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"));

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"));

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"));

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()));
}

Expand All @@ -314,45 +259,36 @@ struct stringSlice : public ::testing::Test {
};

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(4), ' ');
}

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);
}

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));
}

TEST_F(stringSlice, mutateString) {
Slice<std::string> 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");
}

template <typename T>
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 <typename T>
byte dataBufSlice<T>::data[4] = {0xde, 0xad, 0xbe, 0xef};

TYPED_TEST_SUITE_P(dataBufSlice);

TYPED_TEST_P(dataBufSlice, successfulConstruction) {
Expand Down

0 comments on commit 5c7bd32

Please sign in to comment.