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:
Linus Torvalds 2014-03-09 18:31:36 -07:00 committed by Dirk Hohndel
parent 6f3be56d8d
commit 4312b155e1

View file

@ -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)
{ 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! */
struct keyword_action dc_action[] = {
#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));
}
/* 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
* 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;
}
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)
{
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);
if (trip && !strcmp(name, "00-Trip"))
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);
return GIT_WALK_SKIP;
}