mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
core: turn trip-table into our own sorted_owning_table
Since the sorted_owning_table depends on the fact that different elements never compare as equal, make the comparison function safer in that respect. If all failes, compare the pointers. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
1cebafb08f
commit
eacad89531
21 changed files with 217 additions and 305 deletions
177
core/trip.cpp
177
core/trip.cpp
|
@ -12,22 +12,19 @@
|
|||
#ifdef DEBUG_TRIP
|
||||
void dump_trip_list()
|
||||
{
|
||||
dive_trip *trip;
|
||||
int i = 0;
|
||||
timestamp_t last_time = 0;
|
||||
|
||||
for (i = 0; i < divelog.trips->nr; ++i) {
|
||||
for (auto &trip: divelog.trips) {
|
||||
struct tm tm;
|
||||
trip = divelog.trips->trips[i];
|
||||
utc_mkdate(trip_date(trip), &tm);
|
||||
if (trip_date(trip) < last_time)
|
||||
utc_mkdate(trip_date(*trip), &tm);
|
||||
if (trip_date(*trip) < last_time)
|
||||
printf("\n\ntrip_table OUT OF ORDER!!!\n\n\n");
|
||||
printf("%s trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u (%d dives - %p)\n",
|
||||
trip->autogen ? "autogen " : "",
|
||||
i + 1, trip->location.c_str(),
|
||||
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||
trip->dives.nr, trip);
|
||||
last_time = trip_date(trip);
|
||||
trip->dives.nr, trip.get());
|
||||
last_time = trip_date(*trip);
|
||||
}
|
||||
printf("-----\n");
|
||||
}
|
||||
|
@ -42,35 +39,18 @@ dive_trip::~dive_trip()
|
|||
free(dives.dives);
|
||||
}
|
||||
|
||||
/* free resources associated with a trip structure */
|
||||
void free_trip(dive_trip *trip)
|
||||
timestamp_t trip_date(const struct dive_trip &trip)
|
||||
{
|
||||
delete trip;
|
||||
if (trip.dives.nr == 0)
|
||||
return 0;
|
||||
return trip.dives.dives[0]->when;
|
||||
}
|
||||
|
||||
/* Trip table functions */
|
||||
static MAKE_GET_IDX(trip_table, struct dive_trip *, trips)
|
||||
static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips)
|
||||
static MAKE_GET_INSERTION_INDEX(trip_table, struct dive_trip *, trips, trip_less_than)
|
||||
static MAKE_ADD_TO(trip_table, struct dive_trip *, trips)
|
||||
static MAKE_REMOVE_FROM(trip_table, trips)
|
||||
MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips)
|
||||
MAKE_REMOVE(trip_table, struct dive_trip *, trip)
|
||||
MAKE_CLEAR_TABLE(trip_table, trips, trip)
|
||||
MAKE_MOVE_TABLE(trip_table, trips)
|
||||
|
||||
timestamp_t trip_date(const struct dive_trip *trip)
|
||||
static timestamp_t trip_enddate(const struct dive_trip &trip)
|
||||
{
|
||||
if (!trip || trip->dives.nr == 0)
|
||||
if (trip.dives.nr == 0)
|
||||
return 0;
|
||||
return trip->dives.dives[0]->when;
|
||||
}
|
||||
|
||||
timestamp_t trip_enddate(const struct dive_trip *trip)
|
||||
{
|
||||
if (!trip || trip->dives.nr == 0)
|
||||
return 0;
|
||||
return dive_endtime(trip->dives.dives[trip->dives.nr - 1]);
|
||||
return dive_endtime(trip.dives.dives[trip.dives.nr - 1]);
|
||||
}
|
||||
|
||||
/* check if we have a trip right before / after this dive */
|
||||
|
@ -117,39 +97,9 @@ struct dive_trip *unregister_dive_from_trip(struct dive *dive)
|
|||
return trip;
|
||||
}
|
||||
|
||||
static void delete_trip(dive_trip *trip, struct trip_table *trip_table_arg)
|
||||
std::unique_ptr<dive_trip> create_trip_from_dive(const struct dive *dive)
|
||||
{
|
||||
remove_trip(trip, trip_table_arg);
|
||||
free_trip(trip);
|
||||
}
|
||||
|
||||
void remove_dive_from_trip(struct dive *dive, struct trip_table *trip_table_arg)
|
||||
{
|
||||
struct dive_trip *trip = unregister_dive_from_trip(dive);
|
||||
if (trip && trip->dives.nr == 0)
|
||||
delete_trip(trip, trip_table_arg);
|
||||
}
|
||||
|
||||
dive_trip *alloc_trip()
|
||||
{
|
||||
return new dive_trip;
|
||||
}
|
||||
|
||||
/* insert the trip into the trip table */
|
||||
void insert_trip(struct dive_trip *dive_trip, struct trip_table *trip_table_arg)
|
||||
{
|
||||
int idx = trip_table_get_insertion_index(trip_table_arg, dive_trip);
|
||||
add_to_trip_table(trip_table_arg, idx, dive_trip);
|
||||
#ifdef DEBUG_TRIP
|
||||
dump_trip_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
dive_trip *create_trip_from_dive(struct dive *dive)
|
||||
{
|
||||
dive_trip *trip;
|
||||
|
||||
trip = alloc_trip();
|
||||
auto trip = std::make_unique<dive_trip>();
|
||||
trip->location = get_dive_location(dive);
|
||||
|
||||
return trip;
|
||||
|
@ -162,13 +112,12 @@ dive_trip *create_trip_from_dive(struct dive *dive)
|
|||
|
||||
/*
|
||||
* Find a trip a new dive should be autogrouped with. If no such trips
|
||||
* exist, allocate a new trip. The bool "*allocated" is set to true
|
||||
* if a new trip was allocated.
|
||||
* exist, allocate a new trip. A unique_ptr is returned if a new trip
|
||||
* was allocated. The caller has to store it.
|
||||
*/
|
||||
dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated)
|
||||
std::pair<dive_trip *, std::unique_ptr<dive_trip>> get_trip_for_new_dive(const struct dive *new_dive)
|
||||
{
|
||||
struct dive *d;
|
||||
dive_trip *trip;
|
||||
dive *d;
|
||||
int i;
|
||||
|
||||
/* Find dive that is within TRIP_THRESHOLD of current dive */
|
||||
|
@ -177,35 +126,30 @@ dive_trip *get_trip_for_new_dive(struct dive *new_dive, bool *allocated)
|
|||
if (d->when >= new_dive->when + TRIP_THRESHOLD)
|
||||
break;
|
||||
|
||||
if (d->when + TRIP_THRESHOLD >= new_dive->when && d->divetrip) {
|
||||
/* Found a dive with trip in the range */
|
||||
*allocated = false;
|
||||
return d->divetrip;
|
||||
}
|
||||
if (d->when + TRIP_THRESHOLD >= new_dive->when && d->divetrip)
|
||||
return { d->divetrip, nullptr }; /* Found a dive with trip in the range */
|
||||
}
|
||||
|
||||
/* Didn't find a trip -> allocate a new one */
|
||||
trip = create_trip_from_dive(new_dive);
|
||||
auto trip = create_trip_from_dive(new_dive);
|
||||
trip->autogen = true;
|
||||
*allocated = true;
|
||||
return trip;
|
||||
auto t = trip.get();
|
||||
return { t, std::move(trip) };
|
||||
}
|
||||
|
||||
/* lookup of trip in main trip_table based on its id */
|
||||
dive_trip *get_trip_by_uniq_id(int tripId)
|
||||
{
|
||||
for (int i = 0; i < divelog.trips->nr; i++) {
|
||||
if (divelog.trips->trips[i]->id == tripId)
|
||||
return divelog.trips->trips[i];
|
||||
}
|
||||
return NULL;
|
||||
auto it = std::find_if(divelog.trips->begin(), divelog.trips->end(),
|
||||
[tripId](auto &t) { return t->id == tripId; });
|
||||
return it != divelog.trips->end() ? it->get() : nullptr;
|
||||
}
|
||||
|
||||
/* Check if two trips overlap time-wise up to trip threshold. */
|
||||
bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2)
|
||||
bool trips_overlap(const struct dive_trip &t1, const struct dive_trip &t2)
|
||||
{
|
||||
/* First, handle the empty-trip cases. */
|
||||
if (t1->dives.nr == 0 || t2->dives.nr == 0)
|
||||
if (t1.dives.nr == 0 || t2.dives.nr == 0)
|
||||
return 0;
|
||||
|
||||
if (trip_date(t1) < trip_date(t2))
|
||||
|
@ -217,21 +161,22 @@ bool trips_overlap(const struct dive_trip *t1, const struct dive_trip *t2)
|
|||
/*
|
||||
* Collect dives for auto-grouping. Pass in first dive which should be checked.
|
||||
* Returns range of dives that should be autogrouped and trip it should be
|
||||
* associated to. If the returned trip was newly allocated, the last bool
|
||||
* associated to. If the returned trip was newly allocated, a std::unique_ptr<>
|
||||
* to the trip is returned.
|
||||
* is set to true. Caller still has to register it in the system. Note
|
||||
* whereas this looks complicated - it is needed by the undo-system, which
|
||||
* manually injects the new trips. If there are no dives to be autogrouped,
|
||||
* return NULL.
|
||||
*/
|
||||
dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from, int *to, bool *allocated)
|
||||
std::vector<dives_to_autogroup_result> get_dives_to_autogroup(struct dive_table *table)
|
||||
{
|
||||
int i;
|
||||
std::vector<dives_to_autogroup_result> res;
|
||||
struct dive *lastdive = NULL;
|
||||
|
||||
/* Find first dive that should be merged and remember any previous
|
||||
* dive that could be merged into.
|
||||
*/
|
||||
for (i = start; i < table->nr; i++) {
|
||||
for (int i = 0; i < table->nr; ++i) {
|
||||
struct dive *dive = table->dives[i];
|
||||
dive_trip *trip;
|
||||
|
||||
|
@ -248,22 +193,22 @@ dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from
|
|||
}
|
||||
|
||||
/* We found a dive, let's see if we have to allocate a new trip */
|
||||
std::unique_ptr<dive_trip> allocated;
|
||||
if (!lastdive || dive->when >= lastdive->when + TRIP_THRESHOLD) {
|
||||
/* allocate new trip */
|
||||
trip = create_trip_from_dive(dive);
|
||||
trip->autogen = true;
|
||||
*allocated = true;
|
||||
allocated = create_trip_from_dive(dive);
|
||||
allocated->autogen = true;
|
||||
trip = allocated.get();
|
||||
} else {
|
||||
/* use trip of previous dive */
|
||||
trip = lastdive->divetrip;
|
||||
*allocated = false;
|
||||
}
|
||||
|
||||
// Now, find all dives that will be added to this trip
|
||||
lastdive = dive;
|
||||
*from = i;
|
||||
for (*to = *from + 1; *to < table->nr; (*to)++) {
|
||||
dive = table->dives[*to];
|
||||
int to;
|
||||
for (to = i + 1; to < table->nr; to++) {
|
||||
dive = table->dives[to];
|
||||
if (dive->divetrip || dive->notrip ||
|
||||
dive->when >= lastdive->when + TRIP_THRESHOLD)
|
||||
break;
|
||||
|
@ -271,11 +216,11 @@ dive_trip *get_dives_to_autogroup(struct dive_table *table, int start, int *from
|
|||
trip->location = get_dive_location(dive);
|
||||
lastdive = dive;
|
||||
}
|
||||
return trip;
|
||||
res.push_back({ i, to, trip, std::move(allocated) });
|
||||
i = to - 1;
|
||||
}
|
||||
|
||||
/* Did not find anyhting - mark as end */
|
||||
return NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Out of two strings, get the string that is not empty (if any). */
|
||||
|
@ -286,11 +231,10 @@ static std::string non_empty_string(const std::string &a, const std::string &b)
|
|||
|
||||
/* This combines the information of two trips, generating a
|
||||
* new trip. To support undo, we have to preserve the old trips. */
|
||||
dive_trip *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
|
||||
std::unique_ptr<dive_trip> combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
|
||||
{
|
||||
dive_trip *trip;
|
||||
auto trip = std::make_unique<dive_trip>();
|
||||
|
||||
trip = alloc_trip();
|
||||
trip->location = non_empty_string(trip_a->location, trip_b->location);
|
||||
trip->notes = non_empty_string(trip_a->notes, trip_b->notes);
|
||||
|
||||
|
@ -298,20 +242,19 @@ dive_trip *combine_trips(struct dive_trip *trip_a, struct dive_trip *trip_b)
|
|||
}
|
||||
|
||||
/* Trips are compared according to the first dive in the trip. */
|
||||
int comp_trips(const struct dive_trip *a, const struct dive_trip *b)
|
||||
int comp_trips(const struct dive_trip &a, const struct dive_trip &b)
|
||||
{
|
||||
/* This should never happen, nevertheless don't crash on trips
|
||||
* with no (or worse a negative number of) dives. */
|
||||
if (a->dives.nr <= 0)
|
||||
return b->dives.nr <= 0 ? 0 : -1;
|
||||
if (b->dives.nr <= 0)
|
||||
// To make sure that trips never compare equal, compare by
|
||||
// address if both are empty.
|
||||
if (&a == &b)
|
||||
return 0; // reflexivity. shouldn't happen.
|
||||
if (a.dives.nr <= 0 && b.dives.nr <= 0)
|
||||
return &a < &b ? -1 : 1;
|
||||
if (a.dives.nr <= 0)
|
||||
return -1;
|
||||
if (b.dives.nr <= 0)
|
||||
return 1;
|
||||
return comp_dives(a->dives.dives[0], b->dives.dives[0]);
|
||||
}
|
||||
|
||||
bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
|
||||
{
|
||||
return comp_trips(a, b) < 0;
|
||||
return comp_dives(a.dives.dives[0], b.dives.dives[0]);
|
||||
}
|
||||
|
||||
static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when)
|
||||
|
@ -330,12 +273,12 @@ static bool is_same_day(timestamp_t trip_when, timestamp_t dive_when)
|
|||
return (tmd.tm_mday == tmt.tm_mday) && (tmd.tm_mon == tmt.tm_mon) && (tmd.tm_year == tmt.tm_year);
|
||||
}
|
||||
|
||||
bool trip_is_single_day(const struct dive_trip *trip)
|
||||
bool trip_is_single_day(const struct dive_trip &trip)
|
||||
{
|
||||
if (trip->dives.nr <= 1)
|
||||
if (trip.dives.nr <= 1)
|
||||
return true;
|
||||
return is_same_day(trip->dives.dives[0]->when,
|
||||
trip->dives.dives[trip->dives.nr - 1]->when);
|
||||
return is_same_day(trip.dives.dives[0]->when,
|
||||
trip.dives.dives[trip.dives.nr - 1]->when);
|
||||
}
|
||||
|
||||
int trip_shown_dives(const struct dive_trip *trip)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue