mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
parse divecomputer model nickname/firmware/serial information
This was the final piece we didn't read. I can now read my XML file, write it to a git repository, read it back, and write it to a new XML file, and the final XML file is bit-for-bit identical with the original one. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
6f3be56d8d
commit
4312b155e1
1 changed files with 107 additions and 0 deletions
107
load-git.c
107
load-git.c
|
@ -559,6 +559,89 @@ static void parse_trip_location(char *line, struct membuffer *str, void *_trip)
|
||||||
static void parse_trip_notes(char *line, struct membuffer *str, void *_trip)
|
static void parse_trip_notes(char *line, struct membuffer *str, void *_trip)
|
||||||
{ dive_trip_t *trip = _trip; trip->notes = get_utf8(str); }
|
{ dive_trip_t *trip = _trip; trip->notes = get_utf8(str); }
|
||||||
|
|
||||||
|
static void parse_settings_autogroup(char *line, struct membuffer *str, void *_unused)
|
||||||
|
{ set_autogroup(1); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our versioning is a joke right now, but this is more of an example of what we
|
||||||
|
* *can* do some day. And if we do change the version, this warning will show if
|
||||||
|
* you read with a version of subsurface that doesn't know about it.
|
||||||
|
*/
|
||||||
|
#define VERSION 2
|
||||||
|
static void parse_settings_version(char *line, struct membuffer *str, void *_unused)
|
||||||
|
{
|
||||||
|
int version = atoi(line);
|
||||||
|
if (version > VERSION)
|
||||||
|
report_error("Git save file version %d is newer than version %d I know about", version, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The string in the membuffer is the version string of subsurface that saved things, just FYI */
|
||||||
|
static void parse_settings_subsurface(char *line, struct membuffer *str, void *_unused)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
struct divecomputerid {
|
||||||
|
const char *model;
|
||||||
|
const char *nickname;
|
||||||
|
const char *firmware;
|
||||||
|
const char *serial;
|
||||||
|
const char *cstr;
|
||||||
|
unsigned int deviceid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void parse_divecomputerid_keyvalue(void *_cid, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
struct divecomputerid *cid = _cid;
|
||||||
|
|
||||||
|
if (*value == '"') {
|
||||||
|
value = cid->cstr;
|
||||||
|
cid->cstr += strlen(cid->cstr)+1;
|
||||||
|
}
|
||||||
|
if (!strcmp(key, "deviceid")) {
|
||||||
|
cid->deviceid = get_hex(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strcmp(key, "serial")) {
|
||||||
|
cid->serial = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strcmp(key, "firmware")) {
|
||||||
|
cid->firmware = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!strcmp(key, "nickname")) {
|
||||||
|
cid->nickname = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
report_error("Unknow divecomputerid key/value pair (%s/%s)", key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'divecomputerid' is a bit harder to parse than some other things, because
|
||||||
|
* it can have multiple strings (but see the tag parsing for another example of
|
||||||
|
* that) in addition to the non-string entries.
|
||||||
|
*
|
||||||
|
* We keep the "next" string in "id.cstr" and update it as we use it.
|
||||||
|
*/
|
||||||
|
static void parse_settings_divecomputerid(char *line, struct membuffer *str, void *_unused)
|
||||||
|
{
|
||||||
|
struct divecomputerid id = { mb_cstring(str) };
|
||||||
|
|
||||||
|
id.cstr = id.model + strlen(id.model) + 1;
|
||||||
|
|
||||||
|
/* Skip the '"' that stood for the model string */
|
||||||
|
line++;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char c;
|
||||||
|
while (isspace(c = *line))
|
||||||
|
line++;
|
||||||
|
if (!c)
|
||||||
|
break;
|
||||||
|
line = parse_keyvalue_entry(parse_divecomputerid_keyvalue, &id, line);
|
||||||
|
}
|
||||||
|
create_device_node(id.model, id.deviceid, id.serial, id.firmware, id.nickname);
|
||||||
|
}
|
||||||
|
|
||||||
/* These need to be sorted! */
|
/* These need to be sorted! */
|
||||||
struct keyword_action dc_action[] = {
|
struct keyword_action dc_action[] = {
|
||||||
#undef D
|
#undef D
|
||||||
|
@ -603,6 +686,18 @@ static void trip_parser(char *line, struct membuffer *str, void *_trip)
|
||||||
match_action(line, str, _trip, trip_action, ARRAY_SIZE(trip_action));
|
match_action(line, str, _trip, trip_action, ARRAY_SIZE(trip_action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* These need to be sorted! */
|
||||||
|
static struct keyword_action settings_action[] = {
|
||||||
|
#undef D
|
||||||
|
#define D(x) { #x, parse_settings_ ## x }
|
||||||
|
D(autogroup), D(divecomputerid), D(subsurface), D(version),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void settings_parser(char *line, struct membuffer *str, void *_unused)
|
||||||
|
{
|
||||||
|
match_action(line, str, NULL, settings_action, ARRAY_SIZE(settings_action));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a very simple line-based interface, with the small
|
* We have a very simple line-based interface, with the small
|
||||||
* complication that lines can have strings in the middle, and
|
* complication that lines can have strings in the middle, and
|
||||||
|
@ -1028,6 +1123,16 @@ static int parse_trip_entry(git_repository *repo, const git_tree_entry *entry)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_settings_entry(git_repository *repo, const git_tree_entry *entry)
|
||||||
|
{
|
||||||
|
git_blob *blob = git_tree_entry_blob(repo, entry);
|
||||||
|
if (!blob)
|
||||||
|
return report_error("Unable to read settings file");
|
||||||
|
for_each_line(blob, settings_parser, NULL);
|
||||||
|
git_blob_free(blob);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int walk_tree_file(const char *root, const git_tree_entry *entry, git_repository *repo)
|
static int walk_tree_file(const char *root, const git_tree_entry *entry, git_repository *repo)
|
||||||
{
|
{
|
||||||
struct dive *dive = active_dive;
|
struct dive *dive = active_dive;
|
||||||
|
@ -1040,6 +1145,8 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, git_rep
|
||||||
return parse_dive_entry(repo, entry, name+4);
|
return parse_dive_entry(repo, entry, name+4);
|
||||||
if (trip && !strcmp(name, "00-Trip"))
|
if (trip && !strcmp(name, "00-Trip"))
|
||||||
return parse_trip_entry(repo, entry);
|
return parse_trip_entry(repo, entry);
|
||||||
|
if (!strcmp(name, "00-Subsurface"))
|
||||||
|
return parse_settings_entry(repo, entry);
|
||||||
report_error("Unknown file %s%s (%p %p)", root, name, dive, trip);
|
report_error("Unknown file %s%s (%p %p)", root, name, dive, trip);
|
||||||
return GIT_WALK_SKIP;
|
return GIT_WALK_SKIP;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue