diff options
Diffstat (limited to 'smtk-import/smartrak.c')
-rw-r--r-- | smtk-import/smartrak.c | 244 |
1 files changed, 170 insertions, 74 deletions
diff --git a/smtk-import/smartrak.c b/smtk-import/smartrak.c index 826ad6a9d..ed4717287 100644 --- a/smtk-import/smartrak.c +++ b/smtk-import/smartrak.c @@ -506,16 +506,16 @@ static void merge_cylinder_type(cylinder_type_t *src, cylinder_type_t *dst) } } -static void merge_cylinder_mix(struct gasmix *src, struct gasmix *dst) +static void merge_cylinder_mix(struct gasmix src, struct gasmix *dst) { if (!dst->o2.permille) - *dst = *src; + *dst = src; } static void merge_cylinder_info(cylinder_t *src, cylinder_t *dst) { merge_cylinder_type(&src->type, &dst->type); - merge_cylinder_mix(&src->gasmix, &dst->gasmix); + merge_cylinder_mix(src->gasmix, &dst->gasmix); MERGE_MAX(dst, dst, src, start.mbar); MERGE_MIN(dst, dst, src, end.mbar); if (!dst->cylinder_use) @@ -550,63 +550,127 @@ static int smtk_clean_cylinders(struct dive *d) } /* - * Parses a relation table and fills a list with the relations for a dive idx. - * Returns the number of relations found for a given dive idx. + * List related functions + */ +struct types_list { + int idx; + char *text; + struct types_list *next; +}; + +/* Head insert types_list items in a list */ +static void smtk_head_insert(struct types_list **head, int index, char *txt) +{ + struct types_list *item = (struct types_list *) malloc(sizeof(struct types_list)); + + item->next = *head; + item->idx = index; + item->text = txt; + *head = item; + item = NULL; + free(item); +} + +/* Clean types_list lists */ +static void smtk_list_free(struct types_list *head) +{ + struct types_list *p = head; + while (p) { + struct types_list *nxt = p->next; + free(p->text); + free(p); + p = nxt; + } +} + +/* + * Build a list from a given table_name (Type, Gear, etc) + * Managed tables formats: Just consider Idx and Text + * Type: + * | Idx | Text | Default (bool) + * Activity: + * | Idx | Text | Default (bool) + * Gear: + * | Idx | Text | Vendor | Type | Typenum | Notes | Default (bool) | TrakId + * Fish: + * | Idx | Text | Name | Latin name | Typelength | Maxlength | Picture | Default (bool)| TrakId + * TODO: Although all divelogs I've seen use *only* the Text field, a concerned diver could + * be using some other like Vendor (in Gear) or Latin name (in Fish). I'll take a look at this + * in the future, may be something like Buddy table... + */ +static void smtk_build_list(MdbHandle *mdb, char *table_name, struct types_list **head) +{ + MdbTableDef *table; + MdbColumn *col[MDB_MAX_COLS]; + char *bound_values[MDB_MAX_COLS]; + struct types_list *p = NULL; + + table = smtk_open_table(mdb, table_name, col, bound_values); + if (!table) + return; + + /* Read the table items into an structured list */ + while (mdb_fetch_row(table)) + smtk_head_insert(&p, atoi(col[0]->bind_ptr), copy_string(col[1]->bind_ptr)); + *head = p; + + /* clean up and exit */ + p = NULL; + free(p); + smtk_free(bound_values, table->num_cols); + mdb_free_tabledef(table); +} + +/* + * Parses a relation table and returns a list with the relations for a dive idx. + * Use types_list items with text set to NULL. + * Returns a pointer to the list head. * Table relation format: * | Diveidx | Idx | */ -static int smtk_index_list(MdbHandle *mdb, char *table_name, char *dive_idx, int idx_list[]) +static struct types_list *smtk_index_list(MdbHandle *mdb, char *table_name, char *dive_idx) { - int n = 0, i = 0; MdbTableDef *table; MdbColumn *cols[MDB_MAX_COLS]; char *bounders[MDB_MAX_COLS]; + struct types_list *item, *head = NULL; table = smtk_open_table(mdb, table_name, cols, bounders); /* Sanity check */ if (!table) - return 0; + return NULL; /* Parse the table searching for dive_idx */ while (mdb_fetch_row(table)) { - if (!strcmp(dive_idx, cols[0]->bind_ptr)) { - idx_list[n] = atoi(cols[1]->bind_ptr); - n++; - } + if (!strcmp(dive_idx, cols[0]->bind_ptr)) + smtk_head_insert(&head, atoi(cols[1]->bind_ptr), NULL); } /* Clean up and exit */ smtk_free(bounders, table->num_cols); mdb_free_tabledef(table); - return n; + return head; } /* - * Returns string with buddies names as registered in smartrak (may be a nickname). + * "Buddy" is a bit special table that needs some extra work, so we can't just use smtk_build_list. * "Buddy" table is a buddies relation with lots and lots and lots of data (even buddy mother's * maiden name ;-) ) most of them useless for a dive log. Let's just consider the nickname as main * field and the full name if this exists and its construction is different from the nickname. * Buddy table format: * | Idx | Text (nickname) | Name | Firstname | Middlename | Title | Picture | Phone | ... */ -static char *smtk_locate_buddy(MdbHandle *mdb, char *dive_idx) -{ - char *str = NULL, *fullname = NULL, *bounder[MDB_MAX_COLS] = { NULL }, *buddies[256] = { NULL }; +static void smtk_build_buddies(MdbHandle *mdb, struct types_list **buddies_head) { MdbTableDef *table; MdbColumn *col[MDB_MAX_COLS]; - int i, n, rel[256] = { 0 }; + char *bound_values[MDB_MAX_COLS], *fullname = NULL, *str = NULL; + struct types_list *p = NULL; - n = smtk_index_list(mdb, "BuddyRelation", dive_idx, rel); - if (!n) - return str; - table = smtk_open_table(mdb, "Buddy", col, bounder); + table = smtk_open_table(mdb, "Buddy", col, bound_values); if (!table) - return str; - /* - * Buddies in a single dive aren't (usually) a big number, so probably - * it's not a good idea to use a complex data structure and algorithm. - */ + return; + while (mdb_fetch_row(table)) { if (!empty_string(col[3]->bind_ptr)) fullname = smtk_concat_str(fullname, " ", "%s", col[3]->bind_ptr); @@ -615,19 +679,46 @@ static char *smtk_locate_buddy(MdbHandle *mdb, char *dive_idx) if (!empty_string(col[2]->bind_ptr)) fullname = smtk_concat_str(fullname, " ", "%s", col[2]->bind_ptr); if (fullname && !same_string(col[1]->bind_ptr, fullname)) - buddies[atoi(col[0]->bind_ptr)] = smtk_concat_str(buddies[atoi(col[0]->bind_ptr)], "", "%s (%s)", col[1]->bind_ptr, fullname); + smtk_head_insert(&p, atoi(col[0]->bind_ptr), smtk_concat_str(str, "", "%s (%s)", col[1]->bind_ptr, fullname)); else - buddies[atoi(col[0]->bind_ptr)] = smtk_concat_str(buddies[atoi(col[0]->bind_ptr)], "", "%s", col[1]->bind_ptr); + smtk_head_insert(&p, atoi(col[0]->bind_ptr), smtk_concat_str(str, "", "%s", col[1]->bind_ptr)); free(fullname); fullname = NULL; } - for (i = 0; i < n; i++) - str = smtk_concat_str(str, ", ", "%s", buddies[rel[i]]); + *buddies_head = p; - /* Clean up and exit */ - smtk_free(buddies, 256); - smtk_free(bounder, MDB_MAX_COLS); + p = NULL; + free(p); + free(str); + smtk_free(bound_values, table->num_cols); mdb_free_tabledef(table); +} + +/* + * Returns string with buddies names as registered in smartrak (may be a nickname). + */ +static char *smtk_locate_buddy(MdbHandle *mdb, char *dive_idx, struct types_list *buddies_head) +{ + char *str = NULL; + struct types_list *rel, *rel_head, *bud; + + rel_head = smtk_index_list(mdb, "BuddyRelation", dive_idx); + if (!rel_head) + return str; + + for (rel = rel_head; rel; ) { + for (bud = buddies_head; bud; ) { + if (bud->idx == rel->idx) { + str = smtk_concat_str(str, ", ", "%s", bud->text); + break; + } + bud = bud->next; + } + rel = rel->next; + } + + /* Clean up and exit */ + smtk_list_free(rel_head); return str; } @@ -636,50 +727,37 @@ static char *smtk_locate_buddy(MdbHandle *mdb, char *dive_idx) * (SCR, CCR or so), set the dive mode too. * The "tag" parameter is used to mark if we want this table to be imported * into tags or into notes. - * Managed tables formats: Just consider Idx and Text - * Type: - * | Idx | Text | Default (bool) - * Activity: - * | Idx | Text | Default (bool) - * Gear: - * | Idx | Text | Vendor | Type | Typenum | Notes | Default (bool) | TrakId - * Fish: - * | Idx | Text | Name | Latin name | Typelength | Maxlength | Picture | Default (bool)| TrakId */ -static void smtk_parse_relations(MdbHandle *mdb, struct dive *dive, char *dive_idx, char *table_name, char *rel_table_name, bool tag) +static void smtk_parse_relations(MdbHandle *mdb, struct dive *dive, char *dive_idx, char *table_name, char *rel_table_name, struct types_list *list, bool tag) { - MdbTableDef *table; - MdbColumn *col[MDB_MAX_COLS]; - char *bound_values[MDB_MAX_COLS], *tmp = NULL, *types[64] = { NULL }; - int i = 0, n = 0, rels[256] = { 0 }; + char *tmp = NULL; + struct types_list *diverel_head, *d_runner, *t_runner; - n = smtk_index_list(mdb, rel_table_name, dive_idx, rels); - if (!n) - return; - table = smtk_open_table(mdb, table_name, col, bound_values); - if (!table) + diverel_head = smtk_index_list(mdb, rel_table_name, dive_idx); + if (!diverel_head) return; - while (mdb_fetch_row(table)) - types[atoi(col[0]->bind_ptr)] = copy_string(col[1]->bind_ptr); - for (i = 0; i < n; i++) { - if (tag) - taglist_add_tag(&dive->tag_list, types[rels[i]]); - else - tmp = smtk_concat_str(tmp, ", ", "%s", types[rels[i]]); - if (strstr(types[rels[i]], "SCR")) - dive->dc.divemode = PSCR; - else if (strstr(types[rels[i]], "CCR")) - dive->dc.divemode = CCR; + /* Get the text associated with the relations */ + for (d_runner = diverel_head; d_runner; ) { + for (t_runner = list; t_runner; ) { + if (t_runner->idx == d_runner->idx) { + if (tag) + taglist_add_tag(&dive->tag_list, t_runner->text); + else + tmp = smtk_concat_str(tmp, ", ", "%s", t_runner->text); + if (strstr(t_runner->text, "SCR")) + dive->dc.divemode = PSCR; + else if (strstr(t_runner->text, "CCR")) + dive->dc.divemode = CCR; + break; + } + t_runner = t_runner->next; + } + d_runner = d_runner->next; } if (tmp) dive->notes = smtk_concat_str(dive->notes, "\n", "Smartrak %s: %s", table_name, tmp); free(tmp); - - /* clean up and exit */ - smtk_free(types, 64); - smtk_free(bound_values, table->num_cols); - mdb_free_tabledef(table); } /* @@ -840,6 +918,7 @@ void smartrak_import(const char *file, struct dive_table *divetable) MdbColumn *col[MDB_MAX_COLS]; char *bound_values[MDB_MAX_COLS], *ver; int i, dc_model; + struct types_list *type_list = NULL, *activity_list = NULL, *gear_list = NULL, *fish_list = NULL, *buddy_list=NULL; // Set an european style locale to work date/time conversion setlocale(LC_TIME, "POSIX"); @@ -861,6 +940,13 @@ void smartrak_import(const char *file, struct dive_table *divetable) free(ver); tanks = (smtk_version < 10213) ? 3 : 10; + /* Load auxiliary tables into lists */ + smtk_build_list(mdb_clon, "Type", &type_list); + smtk_build_list(mdb_clon, "Activity", &activity_list); + smtk_build_list(mdb_clon, "Gear", &gear_list); + smtk_build_list(mdb_clon, "Fish", &fish_list); + smtk_build_buddies(mdb_clon, &buddy_list); + mdb_table = smtk_open_table(mdb, "Dives", col, bound_values); if (!mdb_table) { report_error("[Error][smartrak_import]\tFile %s does not seem to be an SmartTrak file.", file); @@ -973,17 +1059,27 @@ void smartrak_import(const char *file, struct dive_table *divetable) smtkdive->weightsystem[0].weight.grams = lrint(strtod(col[coln(WEIGHT)]->bind_ptr, NULL) * 1000); smtkdive->suit = smtk_value_by_idx(mdb_clon, "Suit", 1, col[coln(SUITIDX)]->bind_ptr); smtk_build_location(mdb_clon, col[coln(SITEIDX)]->bind_ptr, smtkdive->when, &smtkdive->dive_site_uuid); - smtkdive->buddy = smtk_locate_buddy(mdb_clon, col[0]->bind_ptr); - smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Type", "TypeRelation", true); - smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Activity", "ActivityRelation", false); - smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Gear", "GearRelation", false); - smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Fish", "FishRelation", false); + if (buddy_list) + smtkdive->buddy = smtk_locate_buddy(mdb_clon, col[0]->bind_ptr, buddy_list); + if (type_list) + smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Type", "TypeRelation", type_list, true); + if (activity_list) + smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Activity", "ActivityRelation", activity_list, false); + if (gear_list) + smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Gear", "GearRelation", gear_list, false); + if (fish_list) + smtk_parse_relations(mdb_clon, smtkdive, col[0]->bind_ptr, "Fish", "FishRelation", fish_list, false); smtk_parse_bookmarks(mdb_clon, smtkdive, col[0]->bind_ptr); smtkdive->notes = smtk_concat_str(smtkdive->notes, "\n", "%s", col[coln(REMARKS)]->bind_ptr); record_dive_to_table(smtkdive, divetable); free(devdata); } + smtk_list_free(type_list); + smtk_list_free(activity_list); + smtk_list_free(gear_list); + smtk_list_free(fish_list); + smtk_list_free(buddy_list); smtk_free(bound_values, mdb_table->num_cols); mdb_free_tabledef(mdb_table); mdb_free_catalog(mdb_clon); |