core: turn C dive-table into an owning table

This is a humongous commit, because it touches all parts of the
code. It removes the last user of our horrible TABLE macros, which
simulate std::vector<> in a very clumsy way.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-06-07 10:25:09 +02:00 committed by bstoeger
parent f00c30ad4a
commit b95ac3f79c
73 changed files with 1030 additions and 1230 deletions

View file

@ -190,9 +190,9 @@ static std::unique_ptr<dive> uemis_start_dive(uint32_t deviceid)
static struct dive *get_dive_by_uemis_diveid(device_data_t *devdata, uint32_t object_id)
{
for (int i = 0; i < devdata->log->dives->nr; i++) {
if (object_id == devdata->log->dives->dives[i]->dcs[0].diveid)
return devdata->log->dives->dives[i];
for (auto &d: devdata->log->dives) {
if (object_id == d->dcs[0].diveid)
return d.get();
}
return NULL;
}
@ -767,27 +767,13 @@ static void parse_tag(struct dive *dive, std::string_view tag, std::string_view
static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid)
{
struct dive *dive = NULL;
auto it = std::find_if(devdata->log->dives.begin(), devdata->log->dives.end(),
[diveid] (auto &d) { return d->dcs[0].diveid == diveid; });
if (it == devdata->log->dives.end())
return false;
if (devdata->log->dives->dives[devdata->log->dives->nr - 1]->dcs[0].diveid == diveid) {
/* we hit the last one in the array */
dive = devdata->log->dives->dives[devdata->log->dives->nr - 1];
} else {
for (int i = 0; i < devdata->log->dives->nr - 1; i++) {
if (devdata->log->dives->dives[i]->dcs[0].diveid == diveid) {
dive = devdata->log->dives->dives[i];
for (int x = i; x < devdata->log->dives->nr - 1; x++)
devdata->log->dives->dives[i] = devdata->log->dives->dives[x + 1];
}
}
}
if (dive) {
devdata->log->dives->dives[--devdata->log->dives->nr] = NULL;
delete dive;
return true;
}
return false;
devdata->log->dives.erase(it);
return true;
}
/* This function is called for both dive log and dive information that we get
@ -914,7 +900,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
bp = bp.substr(1);
if (bp[0] != '{' && bp.find("{{") != std::string::npos) {
done = false;
record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
devdata->log->dives.record_dive(std::move(owned_dive));
owned_dive = uemis_start_dive(deviceid);
}
}
@ -947,7 +933,7 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, std::s
}
if (is_log) {
if (owned_dive->dcs[0].diveid)
record_dive_to_table(owned_dive.release(), devdata->log->dives.get());
devdata->log->dives.record_dive(std::move(owned_dive));
else /* partial dive */
return false;
}
@ -959,7 +945,6 @@ static std::pair<uint32_t, uint32_t> uemis_get_divenr(uint32_t deviceid, struct
{
uint32_t maxdiveid = 0;
uint32_t mindiveid = 0xFFFFFFFF;
int i;
/*
* If we are are retrying after a disconnect/reconnect, we
@ -971,11 +956,10 @@ static std::pair<uint32_t, uint32_t> uemis_get_divenr(uint32_t deviceid, struct
*
* Otherwise, use the global dive table.
*/
if (!force && !table->nr)
table = divelog.dives.get();
if (!force && table->empty())
table = &divelog.dives;
for (i = 0; i < table->nr; i++) {
struct dive *d = table->dives[i];
for (auto &d: *table) {
if (!d)
continue;
for (auto &dc: d->dcs) {
@ -1037,19 +1021,19 @@ static bool do_dump_buffer_to_file(std::string_view buf, const char *prefix)
* return : ok if there is enough memory for a full round
* full if the memory is exhausted
*/
static uemis_mem_status get_memory(struct dive_table *td, uemis_checkpoint checkpoint)
static uemis_mem_status get_memory(struct dive_table &td, uemis_checkpoint checkpoint)
{
if (td->nr <= 0)
if (td.empty())
return uemis_mem_status::ok;
switch (checkpoint) {
case uemis_checkpoint::log:
if (filenr / td->nr > max_mem_used)
max_mem_used = filenr / td->nr;
if (filenr / static_cast<int>(td.size()) > max_mem_used)
max_mem_used = filenr / static_cast<int>(td.size());
/* check if a full block of dive logs + dive details and dive spot fit into the UEMIS buffer */
#if UEMIS_DEBUG & 4
report_info("max_mem_used %d (from td->nr %d) * block_size %d > max_files %d - filenr %d?\n", max_mem_used, td->nr, uemis_log_block_size, uemis_max_files, filenr);
report_info("max_mem_used %d (from td.size() %d) * block_size %d > max_files %d - filenr %d?\n", max_mem_used, static_cast<int>(td.size()), uemis_log_block_size, uemis_max_files, filenr);
#endif
if (max_mem_used * uemis_log_block_size > uemis_max_files - filenr)
return uemis_mem_status::full;
@ -1069,10 +1053,10 @@ static uemis_mem_status get_memory(struct dive_table *td, uemis_checkpoint check
/* we misuse the hidden_by_filter flag to mark a dive as deleted.
* this will be picked up by some cleaning statement later. */
static void do_delete_dives(struct dive_table *td, int idx)
static void do_delete_dives(struct dive_table &td, size_t idx)
{
for (int x = idx; x < td->nr; x++)
td->dives[x]->hidden_by_filter = true;
for (auto it = td.begin() + idx; it != td.end(); ++it)
(*it)->hidden_by_filter = true;
}
static bool load_uemis_divespot(const std::string &mountpath, int divespot_id)
@ -1128,9 +1112,9 @@ static void get_uemis_divespot(device_data_t *devdata, const std::string &mountp
}
}
static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status, device_data_t *data, const std::string &mountpath, const char deviceidnr)
static bool get_matching_dive(size_t idx, int &newmax, uemis_mem_status &mem_status, device_data_t *data, const std::string &mountpath, const char deviceidnr)
{
struct dive *dive = data->log->dives->dives[idx];
auto &dive = data->log->dives[idx];
char log_file_no_to_find[20];
bool found = false;
bool found_below = false;
@ -1151,7 +1135,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
#if UEMIS_DEBUG & 16
do_dump_buffer_to_file(mbuf, "Dive");
#endif
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::single_dive);
mem_status = get_memory(data->log->dives, uemis_checkpoint::single_dive);
if (mem_status == uemis_mem_status::ok) {
/* if the memory isn's completely full we can try to read more dive log vs. dive details
* and the dive spots should fit into the UEMIS memory
@ -1174,7 +1158,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
#endif
int divespot_id = uemis_obj.get_divespot_id_by_diveid(dive->dcs[0].diveid);
if (divespot_id >= 0)
get_uemis_divespot(data, mountpath, divespot_id, dive);
get_uemis_divespot(data, mountpath, divespot_id, dive.get());
} else {
/* in this case we found a deleted file, so let's increment */
@ -1215,7 +1199,7 @@ static bool get_matching_dive(int idx, int &newmax, uemis_mem_status &mem_status
} else {
/* At this point the memory of the UEMIS is full, let's cleanup all dive log files were
* we could not match the details to. */
do_delete_dives(data->log->dives.get(), idx);
do_delete_dives(data->log->dives, idx);
return false;
}
}
@ -1236,7 +1220,6 @@ std::string do_uemis_import(device_data_t *data)
std::string deviceid;
std::string result;
bool once = true;
int match_dive_and_log = 0;
int dive_offset = 0;
uemis_mem_status mem_status = uemis_mem_status::ok;
@ -1274,7 +1257,7 @@ std::string do_uemis_import(device_data_t *data)
param_buff[1] = "notempty";
{
auto [mindiveid, maxdiveid] = uemis_get_divenr(deviceidnr, data->log->dives.get(), force_download);
auto [mindiveid, maxdiveid] = uemis_get_divenr(deviceidnr, &data->log->dives, force_download);
newmax = maxdiveid;
if (verbose)
report_info("Uemis downloader: start looking at dive nr %d", newmax);
@ -1292,13 +1275,13 @@ std::string do_uemis_import(device_data_t *data)
report_info("d_u_i inner loop start %d end %d newmax %d\n", start, end, newmax);
#endif
/* start at the last filled download table index */
match_dive_and_log = data->log->dives->nr;
size_t match_dive_and_log = data->log->dives.size();
newmax = start;
std::string newmax_str = std::to_string(newmax);
param_buff[2] = newmax_str.c_str();
param_buff[3].clear();
std::string mbuf = uemis_get_answer(mountpath, "getDivelogs", 3, 0, result);
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::details);
mem_status = get_memory(data->log->dives, uemis_checkpoint::details);
/* first, remove any leading garbage... this needs to start with a '{' */
std::string_view realmbuf = mbuf;
size_t pos = realmbuf.find('{');
@ -1341,7 +1324,7 @@ std::string do_uemis_import(device_data_t *data)
* What the following part does is to optimize the mapping by using
* dive_to_read = the dive details entry that need to be read using the object_id
* logFileNoToFind = map the logfilenr of the dive details with the object_id = diveid from the get dive logs */
for (int i = match_dive_and_log; i < data->log->dives->nr; i++) {
for (size_t i = match_dive_and_log; i < data->log->dives.size(); i++) {
if (!get_matching_dive(i, newmax, mem_status, data, mountpath, deviceidnr))
break;
if (import_thread_cancelled)
@ -1351,7 +1334,7 @@ std::string do_uemis_import(device_data_t *data)
start = end;
/* Do some memory checking here */
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::log);
mem_status = get_memory(data->log->dives, uemis_checkpoint::log);
if (mem_status != uemis_mem_status::ok) {
#if UEMIS_DEBUG & 4
report_info("d_u_i out of memory, bailing\n");
@ -1365,7 +1348,7 @@ std::string do_uemis_import(device_data_t *data)
// Resetting to original state
filenr = 0;
max_mem_used = -1;
mem_status = get_memory(data->log->dives.get(), uemis_checkpoint::details);
mem_status = get_memory(data->log->dives, uemis_checkpoint::details);
if (uemis_get_answer(mountpath, "getDeviceId", 0, 1, result).empty())
goto bail;
if (deviceid != param_buff[0]) {
@ -1408,7 +1391,7 @@ std::string do_uemis_import(device_data_t *data)
* be deleted from the download_table.
*/
if (mem_status == uemis_mem_status::full)
do_delete_dives(data->log->dives.get(), match_dive_and_log);
do_delete_dives(data->log->dives, match_dive_and_log);
#if UEMIS_DEBUG & 4
report_info("d_u_i out of memory, bailing instead of processing\n");
#endif
@ -1425,9 +1408,9 @@ std::string do_uemis_import(device_data_t *data)
/* Regardless on where we are with the memory situation, it's time now
* to see if we have to clean some dead bodies from our download table */
for (int next_table_index = 0; next_table_index < data->log->dives->nr; ) {
if (data->log->dives->dives[next_table_index]->hidden_by_filter)
uemis_delete_dive(data, data->log->dives->dives[next_table_index]->dcs[0].diveid);
for (size_t next_table_index = 0; next_table_index < data->log->dives.size(); ) {
if (data->log->dives[next_table_index]->hidden_by_filter)
uemis_delete_dive(data, data->log->dives[next_table_index]->dcs[0].diveid);
else
next_table_index++;
}
@ -1446,7 +1429,7 @@ bail:
else
result = param_buff[2];
}
if (!data->log->dives->nr)
if (data->log->dives.empty())
result = translate("gettextFromC", ERR_NO_FILES);
return result;
}