core: use std::vector<> to store divecomputer samples

This is a hairy one, because the sample code is rather tricky.

There was a pattern of looping through pairs of adjacent samples,
for interpolation purposes. Add an range adapter to generalize
such loops.

Removes the finish_sample() function: The code would call
prepare_sample() to start parsing of samples and then
finish_sample() to actuall add it. I.e. a kind of commit().

Since, with one exception, all users of prepare_sample()
called finish_sample() in all code paths, we might just add
the sample in the first place. The exception was sample_end()
in parse.cpp. This brings a small change: samples are now
added, even if they could only be parsed partially. I doubt
that this makes any difference, since it will only happen
for broken divelogs anyway.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-19 12:38:38 +02:00 committed by bstoeger
parent bc761344d4
commit f120fecccb
28 changed files with 588 additions and 715 deletions

View file

@ -32,7 +32,79 @@ void move_in_range(Range &v, int rangeBegin, int rangeEnd, int destination)
std::rotate(it + destination, it + rangeBegin, it + rangeEnd);
}
// A rudimentary adaptor for looping over ranges with an index:
// Small helper base class for iterator adapters.
template <typename Base>
class iterator_adapter {
protected:
Base it;
public:
iterator_adapter(Base it) : it(it)
{
}
bool operator==(const iterator_adapter &it2) const {
return it == it2.it;
}
bool operator!=(const iterator_adapter &it2) const
{
return it != it2.it;
}
};
// A rudimentary adapter for looping over pairs of elements in ranges:
// for (auto [it1, it2]: pairwise_range(v)) ...
// The pairs are overlapping, i.e. there is one less pair than elements:
// { 1, 2, 3, 4 } -> (1,2), (2,3), (3,4)
template <typename Range>
class pairwise_range
{
Range &base;
public:
using base_iterator = decltype(std::begin(std::declval<Range &>()));
using item_type = decltype(*std::begin(base));
class iterator : public iterator_adapter<base_iterator> {
public:
using iterator_adapter<base_iterator>::iterator_adapter;
std::pair<item_type &, item_type &> operator*() const
{
return { *this->it, *std::next(this->it) };
}
iterator &operator++()
{
++this->it;
return *this;
}
iterator &operator--()
{
--this->it;
return *this;
}
iterator operator++(int)
{
return iterator(this->it++);
}
iterator operator--(int)
{
return iterator(this->it--);
}
};
iterator begin()
{
return iterator(std::begin(base));
}
iterator end()
{
return std::begin(base) == std::end(base) ?
iterator(std::begin(base)) :
iterator(std::prev(std::end(base)));
}
pairwise_range(Range &base): base(base)
{
}
};
// A rudimentary adapter for looping over ranges with an index:
// for (auto [idx, item]: enumerated_range(v)) ...
// The index is a signed integer, since this is what we use more often.
template <typename Range>
@ -41,30 +113,31 @@ class enumerated_range
Range &base;
public:
using base_iterator = decltype(std::begin(std::declval<Range &>()));
class iterator {
class iterator : public iterator_adapter<base_iterator>{
int idx;
base_iterator it;
public:
std::pair<int, decltype(*it)> operator*() const
using iterator_adapter<base_iterator>::iterator_adapter;
using item_type = decltype(*std::begin(base));
std::pair<int, item_type &> operator*() const
{
return { idx, *it };
return { idx, *this->it };
}
iterator &operator++()
{
++idx;
++it;
++this->it;
return *this;
}
iterator(int idx, base_iterator it) : idx(idx), it(it)
iterator &operator--()
{
--idx;
--this->it;
return *this;
}
bool operator==(const iterator &it2) const
iterator &operator++(int) = delete; // Postfix increment/decrement not supported for now
iterator &operator--(int) = delete; // Postfix increment/decrement not supported for now
iterator(int idx, base_iterator it) : iterator_adapter<base_iterator>(it), idx(idx)
{
return it == it2.it;
}
bool operator!=(const iterator &it2) const
{
return it != it2.it;
}
};
@ -82,6 +155,7 @@ public:
}
};
// Find the index of an element in a range. Return -1 if not found
// Range must have a random access iterator.
template <typename Range, typename Element>