Geo taxonomy: correctly store / update the categories

Don't throw away data unless new data has been received. And don't store
multiple copies of the same category. And most importantly, never write
past the end of the array.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2015-07-13 15:18:52 -07:00
parent 94d3aa04dc
commit e82f8ea565
3 changed files with 37 additions and 13 deletions

View file

@ -86,8 +86,20 @@ void ReverseGeoLookupThread::run() {
if (geoNames.count() > 0) {
QVariantMap firstData = geoNames.at(0).toMap();
int ri = 0, l3 = -1, lt = -1;
if (ds->taxonomy.category == NULL)
if (ds->taxonomy.category == NULL) {
ds->taxonomy.category = alloc_taxonomy();
} else {
// clear out the data (except for the ocean data)
int ocean;
if ((ocean = taxonomy_index_for_category(&ds->taxonomy, TC_OCEAN)) > 0) {
ds->taxonomy.category[0] = ds->taxonomy.category[ocean];
ds->taxonomy.nr = 1;
} else {
// ocean is -1 if there is no such entry, and we didn't copy above
// if ocean is 0, so the following gets us the correct count
ds->taxonomy.nr = ocean + 1;
}
}
// get all the data - OCEAN is special, so start at COUNTRY
for (int j = TC_COUNTRY; j < TC_NR_CATEGORIES; j++) {
if (firstData[taxonomy_api_names[j]].isValid()) {
@ -98,12 +110,9 @@ void ReverseGeoLookupThread::run() {
ri++;
}
}
for (int j = ri - 1; j >= 0; j--) {
if (ds->taxonomy.category[j].category == TC_ADMIN_L3)
l3 = j;
else if (ds->taxonomy.category[j].category == TC_LOCALNAME)
lt = j;
}
ds->taxonomy.nr = ri;
l3 = taxonomy_index_for_category(&ds->taxonomy, TC_ADMIN_L3);
lt = taxonomy_index_for_category(&ds->taxonomy, TC_LOCALNAME);
if (l3 == -1 && lt != -1) {
// basically this means we did get a local name (what we call town), but just like most places
// we didn't get an adminName_3 - which in some regions is the actual city that town belongs to,
@ -111,9 +120,8 @@ void ReverseGeoLookupThread::run() {
ds->taxonomy.category[ri].value = copy_string(ds->taxonomy.category[lt].value);
ds->taxonomy.category[ri].origin = taxonomy::COPIED;
ds->taxonomy.category[ri].category = TC_ADMIN_L3;
ri++;
ds->taxonomy.nr++;
}
ds->taxonomy.nr = ri;
mark_divelist_changed(true);
} else {
report_error("geonames.org did not provide reverse lookup information");
@ -150,12 +158,19 @@ void ReverseGeoLookupThread::run() {
QVariant oceanObject = obj.value("ocean").toVariant();
QVariantMap oceanName = oceanObject.toMap();
if (oceanName["name"].isValid()) {
int idx;
if (ds->taxonomy.category == NULL)
ds->taxonomy.category = alloc_taxonomy();
ds->taxonomy.category[ds->taxonomy.nr].category = TC_OCEAN;
ds->taxonomy.category[ds->taxonomy.nr].origin = taxonomy::GEOCODED;
ds->taxonomy.category[ds->taxonomy.nr].value = copy_string(qPrintable(oceanName["name"].toString()));
ds->taxonomy.nr++;
idx = taxonomy_index_for_category(&ds->taxonomy, TC_OCEAN);
if (idx == -1)
idx = ds->taxonomy.nr;
if (idx < TC_NR_CATEGORIES) {
ds->taxonomy.category[idx].category = TC_OCEAN;
ds->taxonomy.category[idx].origin = taxonomy::GEOCODED;
ds->taxonomy.category[idx].value = copy_string(qPrintable(oceanName["name"].toString()));
if (idx == ds->taxonomy.nr)
ds->taxonomy.nr++;
}
mark_divelist_changed(true);
}
} else {

View file

@ -38,3 +38,11 @@ void free_taxonomy(struct taxonomy_data *t)
t->nr = 0;
}
}
int taxonomy_index_for_category(struct taxonomy_data *t, enum taxonomy_category cat)
{
for (int i = 0; i < t->nr; i++)
if (t->category[i].category == cat)
return i;
return -1;
}

View file

@ -33,6 +33,7 @@ struct taxonomy_data {
struct taxonomy *alloc_taxonomy();
void free_taxonomy(struct taxonomy_data *t);
int taxonomy_index_for_category(struct taxonomy_data *t, enum taxonomy_category cat);
#ifdef __cplusplus
}