Core: keep trips in table(s)

Currently, all trips are kept in a linked list. Replace the list
by a table in analogy to dive_table. Use this to keep the trip_table
sorted as suggested by dump_trip_list(). When inserting a trip into
the table do that after adding the dives, to avoid warnings coming
out of dump_trip_list().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2018-11-24 12:31:35 +01:00 committed by Dirk Hohndel
parent 54fcda4c32
commit 517fb7a462
7 changed files with 89 additions and 78 deletions

View file

@ -286,11 +286,13 @@ typedef struct dive_trip
/* Used by the io-routines to mark trips that have already been written. */
bool saved;
bool autogen;
struct dive_trip *next;
} dive_trip_t;
/* List of dive trips (sorted by date) */
extern dive_trip_t *dive_trip_list;
struct trip_table {
int nr, allocated;
struct dive_trip **trips;
};
struct picture;
struct dive {
int number;
@ -420,6 +422,7 @@ extern const struct units *get_units(void);
extern int run_survey, verbose, quit, force_root;
extern struct dive_table dive_table;
extern struct trip_table trip_table;
extern struct dive displayed_dive;
extern unsigned int dc_number;
extern struct dive *current_dive;
@ -543,6 +546,7 @@ extern bool dive_less_than(const struct dive *a, const struct dive *b);
extern bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b);
extern bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b);
extern void sort_dive_table(struct dive_table *table);
extern void sort_trip_table(struct trip_table *table);
extern struct dive *fixup_dive(struct dive *dive);
extern void fixup_dc_duration(struct divecomputer *dc);
extern int dive_getUniqID();

View file

@ -3,10 +3,10 @@
/* core logic for the dive list -
* accessed through the following interfaces:
*
* void process_loaded_dives();
* void process_imported_dives(bool prefer_imported);
* dive_trip_t *dive_trip_list;
* unsigned int amount_selected;
* struct trip_table trip_table
* void process_loaded_dives()
* void process_imported_dives(bool prefer_imported)
* unsigned int amount_selected
* void dump_selection(void)
* void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2low_p)
* char *get_dive_gas_string(const struct dive *dive)
@ -38,6 +38,7 @@
* bool trip_less_than(const struct dive_trip *a, const struct dive_trip *b)
* bool dive_or_trip_less_than(struct dive_or_trip a, struct dive_or_trip b)
* void sort_dive_table(struct dive_table *table)
* void sort_trip_table(struct trip_table *table)
* bool is_trip_before_after(const struct dive *dive, bool before)
* void delete_dive_from_table(struct dive_table *table, int idx)
* int find_next_visible_dive(timestamp_t when);
@ -69,7 +70,7 @@ static bool dive_list_changed = false;
bool autogroup = false;
dive_trip_t *dive_trip_list;
struct trip_table trip_table;
unsigned int amount_selected;
@ -748,14 +749,15 @@ void dump_trip_list(void)
int i = 0;
timestamp_t last_time = 0;
for (trip = dive_trip_list; trip; trip = trip->next) {
for (i = 0; i < trip_table.nr; ++i) {
struct tm tm;
trip = trip_table.trips[i];
utc_mkdate(trip_date(trip), &tm);
if (trip_date(trip) < last_time)
printf("\n\ndive_trip_list OUT OF ORDER!!!\n\n\n");
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, trip->location,
i + 1, trip->location,
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);
@ -764,23 +766,6 @@ void dump_trip_list(void)
}
#endif
/* insert the trip into the dive_trip_list */
void insert_trip(dive_trip_t *dive_trip)
{
dive_trip_t **p = &dive_trip_list;
dive_trip_t *trip;
/* Walk the dive trip list looking for the right location.. */
while ((trip = *p) != NULL && trip_less_than(trip, dive_trip))
p = &trip->next;
dive_trip->next = trip;
*p = dive_trip;
#ifdef DEBUG_TRIP
dump_trip_list();
#endif
}
/* free resources associated with a trip structure */
void free_trip(dive_trip_t *trip)
{
@ -791,32 +776,6 @@ void free_trip(dive_trip_t *trip)
}
}
/* remove trip from the trip-list, but don't free its memory.
* caller takes ownership of the trip. */
void unregister_trip(dive_trip_t *trip)
{
dive_trip_t **p, *tmp;
assert(!trip->dives.nr);
/* Remove the trip from the list of trips */
p = &dive_trip_list;
while ((tmp = *p) != NULL) {
if (tmp == trip) {
*p = trip->next;
break;
}
p = &tmp->next;
}
}
static void delete_trip(dive_trip_t *trip)
{
unregister_trip(trip);
free_trip(trip);
}
timestamp_t trip_date(const struct dive_trip *trip)
{
if (!trip || trip->dives.nr == 0)
@ -902,6 +861,18 @@ static int comp_dives(const struct dive *a, const struct dive *b)
return 0; /* this should not happen for a != b */
}
/* Trips are compared according to the first dive in the trip. */
static 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)
return 1;
return comp_dives(a->dives.dives[0], b->dives.dives[0]);
}
#define MAKE_GROW_TABLE(table_type, item_type, array_name) \
item_type *grow_##table_type(struct table_type *table) \
{ \
@ -920,6 +891,7 @@ static int comp_dives(const struct dive *a, const struct dive *b)
}
MAKE_GROW_TABLE(dive_table, struct dive *, dives)
static MAKE_GROW_TABLE(trip_table, struct dive_trip *, trips)
/* get the index where we want to insert an object so that everything stays
* ordered according to a comparison function() */
@ -935,6 +907,7 @@ MAKE_GROW_TABLE(dive_table, struct dive *, dives)
}
MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
static MAKE_GET_INSERTION_INDEX(trip_table, struct dive_trip *, trips, trip_less_than)
/* add object at the given index to a table. */
#define MAKE_ADD_TO(table_type, item_type, array_name) \
@ -952,6 +925,7 @@ MAKE_GET_INSERTION_INDEX(dive_table, struct dive *, dives, dive_less_than)
}
static MAKE_ADD_TO(dive_table, struct dive *, dives)
static MAKE_ADD_TO(trip_table, struct dive_trip *, trips)
#define MAKE_REMOVE_FROM(table_type, array_name) \
void remove_from_##table_type(struct table_type *table, int idx) \
@ -963,6 +937,7 @@ static MAKE_ADD_TO(dive_table, struct dive *, dives)
}
static MAKE_REMOVE_FROM(dive_table, dives)
static MAKE_REMOVE_FROM(trip_table, trips)
#define MAKE_GET_IDX(table_type, item_type, array_name) \
int get_idx_in_##table_type(const struct table_type *table, const item_type item) \
@ -975,6 +950,7 @@ static MAKE_REMOVE_FROM(dive_table, dives)
}
static MAKE_GET_IDX(dive_table, struct dive *, dives)
static MAKE_GET_IDX(trip_table, struct dive_trip *, trips)
#define MAKE_SORT(table_type, item_type, array_name, fun) \
static int sortfn_##table_type(const void *_a, const void *_b) \
@ -990,6 +966,7 @@ static MAKE_GET_IDX(dive_table, struct dive *, dives)
}
MAKE_SORT(dive_table, struct dive *, dives, comp_dives)
MAKE_SORT(trip_table, struct dive_trip *, trips, comp_trips)
/* remove a dive from the trip it's associated to, but don't delete the
* trip if this was the last dive in the trip. the caller is responsible
@ -1010,6 +987,12 @@ struct dive_trip *unregister_dive_from_trip(struct dive *dive)
return trip;
}
static void delete_trip(dive_trip_t *trip)
{
unregister_trip(trip);
free_trip(trip);
}
void remove_dive_from_trip(struct dive *dive)
{
struct dive_trip *trip = unregister_dive_from_trip(dive);
@ -1036,6 +1019,16 @@ dive_trip_t *alloc_trip(void)
return calloc(1, sizeof(dive_trip_t));
}
/* insert the trip into the trip table */
void insert_trip(dive_trip_t *dive_trip)
{
int idx = trip_table_get_insertion_index(&trip_table, dive_trip);
add_to_trip_table(&trip_table, idx, dive_trip);
#ifdef DEBUG_TRIP
dump_trip_list();
#endif
}
dive_trip_t *create_trip_from_dive(struct dive *dive)
{
dive_trip_t *trip;
@ -1051,12 +1044,22 @@ dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
dive_trip_t *dive_trip = alloc_trip();
dive_trip = create_trip_from_dive(dive);
insert_trip(dive_trip);
add_dive_to_trip(dive, dive_trip);
insert_trip(dive_trip);
return dive_trip;
}
/* remove trip from the trip-list, but don't free its memory.
* caller takes ownership of the trip. */
void unregister_trip(dive_trip_t *trip)
{
int idx = get_idx_in_trip_table(&trip_table, trip);
assert(!trip->dives.nr);
if (idx >= 0)
remove_from_trip_table(&trip_table, idx);
}
/*
* 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
@ -1153,7 +1156,7 @@ dive_trip_t *get_dives_to_autogroup(struct dive_table *table, int start, int *fr
}
/*
* Walk the dives from the oldest dive in the given tabe, and see if we
* Walk the dives from the oldest dive in the given table, and see if we
* can autogroup them. But only do this when the user selected autogrouping.
*/
static void autogroup_dives(struct dive_table *table)
@ -1167,12 +1170,13 @@ static void autogroup_dives(struct dive_table *table)
return;
for (i = 0; (trip = get_dives_to_autogroup(&dive_table, i, &from, &to, &alloc)) != NULL; i = to) {
for (j = from; j < to; ++j)
add_dive_to_trip(get_dive(j), trip);
/* If this was newly allocated, add trip to list */
if (alloc)
insert_trip(trip);
for (j = from; j < to; ++j)
add_dive_to_trip(get_dive(j), trip);
}
sort_trip_table(&trip_table);
#ifdef DEBUG_TRIP
dump_trip_list();
#endif
@ -1423,6 +1427,7 @@ void process_loaded_dives()
set_dc_nickname(dive);
sort_dive_table(&dive_table);
sort_trip_table(&trip_table);
/* Autogroup dives if desired by user. */
autogroup_dives(&dive_table);
@ -1577,6 +1582,9 @@ void process_imported_dives(struct dive_table *import_table, bool prefer_importe
/* Autogroup dives if desired by user. */
autogroup_dives(&dive_table);
/* Trips may have changed - make sure that they are still ordered */
sort_trip_table(&trip_table);
/* We might have deleted the old selected dive.
* Choose the newest dive as selected (if any) */
current_dive = dive_table.nr > 0 ? dive_table.dives[dive_table.nr - 1] : NULL;
@ -1660,6 +1668,10 @@ void clear_dive_file_data()
delete_single_dive(0);
while (dive_site_table.nr)
delete_dive_site(get_dive_site(0));
if (trip_table.nr != 0) {
fprintf(stderr, "Warning: trip table not empty in clear_dive_file_data()!\n");
trip_table.nr = 0;
}
clear_dive(&displayed_dive);
@ -1682,18 +1694,6 @@ bool dive_less_than(const struct dive *a, const struct dive *b)
return comp_dives(a, b) < 0;
}
/* Trips are compared according to the first dive in the trip. */
static 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)
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;

View file

@ -930,8 +930,8 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
save_divesites(repo, root);
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
trip->saved = 0;
for (i = 0; i < trip_table.nr; ++i)
trip_table.trips[i]->saved = 0;
/* save the dives */
git_storage_update_progress(translate("gettextFromC", "Start saving dives"));

View file

@ -439,8 +439,8 @@ void write_trips(struct membuffer *b, const char *photos_dir, bool selected_only
char sep_ = ' ';
char *sep = &sep_;
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
trip->saved = 0;
for (i = 0; i < trip_table.nr; ++i)
trip_table.trips[i]->saved = 0;
for_each_dive (i, dive) {
trip = dive->divetrip;

View file

@ -637,8 +637,8 @@ void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymi
put_format(b, "</site>\n");
}
put_format(b, "</divesites>\n<dives>\n");
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
trip->saved = 0;
for (i = 0; i < trip_table.nr; ++i)
trip_table.trips[i]->saved = 0;
/* save the dives */
for_each_dive(i, dive) {

View file

@ -81,10 +81,10 @@ DiveToAdd DiveListBase::removeDive(struct dive *d)
// Returns pointer to added dive (which is owned by the backend!)
dive *DiveListBase::addDive(DiveToAdd &d)
{
if (d.tripToAdd)
insert_trip(d.tripToAdd.release()); // Return ownership to backend
if (d.trip)
add_dive_to_trip(d.dive.get(), d.trip);
if (d.tripToAdd)
insert_trip(d.tripToAdd.release()); // Return ownership to backend
dive *res = d.dive.release(); // Give up ownership of dive
// Set the filter flag according to current filter settings
@ -530,6 +530,7 @@ void AddDive::redoit()
currentDive = current_dive;
divesToRemove = addDives(divesToAdd);
sort_trip_table(&trip_table); // Though unlikely, adding a dive may reorder trips
mark_divelist_changed(true);
// Select the newly added dive
@ -544,6 +545,7 @@ void AddDive::undoit()
{
// Simply remove the dive that was previously added...
divesToAdd = removeDives(divesToRemove);
sort_trip_table(&trip_table); // Though unlikely, removing a dive may reorder trips
// ...and restore the selection
restoreSelection(selection, currentDive);
@ -566,6 +568,7 @@ bool DeleteDive::workToBeDone()
void DeleteDive::undoit()
{
divesToDelete = addDives(divesToAdd);
sort_trip_table(&trip_table); // Though unlikely, removing a dive may reorder trips
mark_divelist_changed(true);
// Select all re-added dives and make the first one current
@ -576,6 +579,7 @@ void DeleteDive::undoit()
void DeleteDive::redoit()
{
divesToAdd = removeDives(divesToDelete);
sort_trip_table(&trip_table); // Though unlikely, adding a dive may reorder trips
mark_divelist_changed(true);
// Deselect all dives and select dive that was close to the first deleted dive
@ -604,6 +608,7 @@ void ShiftTime::redoit()
// Changing times may have unsorted the dive table
sort_dive_table(&dive_table);
sort_trip_table(&trip_table);
// We send one time changed signal per trip (see comments in DiveListNotifier.h).
// Therefore, collect all dives in an array and sort by trip.
@ -667,6 +672,7 @@ bool TripBase::workToBeDone()
void TripBase::redoit()
{
moveDivesBetweenTrips(divesToMove);
sort_trip_table(&trip_table); // Though unlikely, moving dives may reorder trips
mark_divelist_changed(true);
}

View file

@ -1131,6 +1131,7 @@ void QMLManager::commitChanges(QString diveId, QString date, QString location, Q
// we know that the only thing that might happen in a resort is that
// this one dive moves to a different spot in the dive list
sort_dive_table(&dive_table);
sort_trip_table(&trip_table);
int newIdx = get_idx_by_uniq_id(d->id);
if (newIdx != oldIdx) {
DiveListModel::instance()->removeDive(modelIdx);