core: convert save-xml.c to C++

This includes using the C++ version of membuffer. There appears
to not have been a leak, because the buffer is freed in
flush_buffer(), but usage was somewhat inconsistent and hard to
follow.

Also, convert some string handling to std::string to avoid free()
madness.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-02-28 06:36:48 +01:00
parent be3a497885
commit b060df91e7
3 changed files with 30 additions and 46 deletions

View file

@ -82,7 +82,7 @@ SOURCES += subsurface-mobile-main.cpp \
core/datatrak.c \ core/datatrak.c \
core/ostctools.c \ core/ostctools.c \
core/planner.c \ core/planner.c \
core/save-xml.c \ core/save-xml.cpp \
core/cochran.c \ core/cochran.c \
core/deco.c \ core/deco.c \
core/divesite.c \ core/divesite.c \

View file

@ -159,7 +159,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
save-html.c save-html.c
save-html.h save-html.h
save-profiledata.c save-profiledata.c
save-xml.c save-xml.cpp
selection.cpp selection.cpp
selection.h selection.h
sha1.c sha1.c

View file

@ -54,7 +54,6 @@ static void quote(struct membuffer *b, const char *text, int is_attribute)
static void show_utf8(struct membuffer *b, const char *text, const char *pre, const char *post, int is_attribute) static void show_utf8(struct membuffer *b, const char *text, const char *pre, const char *post, int is_attribute)
{ {
int len; int len;
char *cleaned;
if (!text) if (!text)
return; return;
@ -69,27 +68,25 @@ static void show_utf8(struct membuffer *b, const char *text, const char *pre, co
return; return;
while (len && isascii(text[len - 1]) && isspace(text[len - 1])) while (len && isascii(text[len - 1]) && isspace(text[len - 1]))
len--; len--;
cleaned = strndup(text, len); std::string cleaned(text, len);
put_string(b, pre); put_string(b, pre);
quote(b, cleaned, is_attribute); quote(b, cleaned.c_str(), is_attribute);
put_string(b, post); put_string(b, post);
free(cleaned);
} }
static void blankout(char *c) static void blankout(std::string &s)
{ {
while(*c) { for(char &c: s) {
switch (*c) { switch (c) {
case 'A'...'Z': case 'A'...'Z':
*c = 'X'; c = 'X';
break; break;
case 'a'...'z': case 'a'...'z':
*c = 'x'; c = 'x';
break; break;
default: default:
; ;
} }
++c;
} }
} }
@ -97,12 +94,11 @@ static void show_utf8_blanked(struct membuffer *b, const char *text, const char
{ {
if (!text) if (!text)
return; return;
char *copy = strdup(text); std::string copy(text);
if (anonymize) if (anonymize)
blankout(copy); blankout(copy);
show_utf8(b, copy, pre, post, is_attribute); show_utf8(b, copy.c_str(), pre, post, is_attribute);
free(copy);
} }
static void save_depths(struct membuffer *b, struct divecomputer *dc) static void save_depths(struct membuffer *b, struct divecomputer *dc)
@ -432,7 +428,7 @@ static void save_samples(struct membuffer *b, struct dive *dive, struct divecomp
int nr; int nr;
int o2sensor; int o2sensor;
struct sample *s; struct sample *s;
struct sample dummy = { .bearing.degrees = -1, .ndl.seconds = -1 }; struct sample dummy;
/* Set up default pressure sensor indices */ /* Set up default pressure sensor indices */
o2sensor = legacy_format_o2pressures(dive, dc); o2sensor = legacy_format_o2pressures(dive, dc);
@ -464,9 +460,9 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
if (dc->duration.seconds && dc->duration.seconds != dive->dc.duration.seconds) if (dc->duration.seconds && dc->duration.seconds != dive->dc.duration.seconds)
put_duration(b, dc->duration, " duration='", " min'"); put_duration(b, dc->duration, " duration='", " min'");
if (dc->divemode != OC) { if (dc->divemode != OC) {
for (enum divemode_t i = 0; i < NUM_DIVEMODE; i++) int i = (int)dc->divemode;
if (dc->divemode == i) if (i >= 0 && i < NUM_DIVEMODE)
show_utf8(b, divemode_text[i], " dctype='", "'", 1); show_utf8(b, divemode_text[i], " dctype='", "'", 1);
if (dc->no_o2sensors) if (dc->no_o2sensors)
put_format(b," no_o2sensors='%d'", dc->no_o2sensors); put_format(b," no_o2sensors='%d'", dc->no_o2sensors);
} }
@ -502,7 +498,7 @@ static void save_picture(struct membuffer *b, struct picture *pic)
put_string(b, "/>\n"); put_string(b, "/>\n");
} }
void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize) extern "C" void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
{ {
struct divecomputer *dc; struct divecomputer *dc;
pressure_t surface_pressure = un_fixup_surface_pressure(dive); pressure_t surface_pressure = un_fixup_surface_pressure(dive);
@ -561,9 +557,9 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
put_format(b, "</dive>\n"); put_format(b, "</dive>\n");
} }
int save_dive(FILE *f, struct dive *dive, bool anonymize) extern "C" int save_dive(FILE *f, struct dive *dive, bool anonymize)
{ {
struct membuffer buf = { 0 }; struct membufferpp buf;
save_one_dive_to_mb(&buf, dive, anonymize); save_one_dive_to_mb(&buf, dive, anonymize);
flush_buffer(&buf, f); flush_buffer(&buf, f);
@ -634,7 +630,7 @@ static void save_one_fingerprint(struct membuffer *b, int i)
free(data); free(data);
} }
int save_dives(const char *filename) extern "C" int save_dives(const char *filename)
{ {
return save_dives_logic(filename, false, false); return save_dives_logic(filename, false, false);
} }
@ -780,8 +776,7 @@ static void save_dives_buffer(struct membuffer *b, bool select_only, bool anonym
static void save_backup(const char *name, const char *ext, const char *new_ext) static void save_backup(const char *name, const char *ext, const char *new_ext)
{ {
int len = strlen(name); int len = strlen(name);
int a = strlen(ext), b = strlen(new_ext); int a = strlen(ext);
char *newname;
/* len up to and including the final '.' */ /* len up to and including the final '.' */
len -= a; len -= a;
@ -793,20 +788,15 @@ static void save_backup(const char *name, const char *ext, const char *new_ext)
if (strncasecmp(name + len, ext, a)) if (strncasecmp(name + len, ext, a))
return; return;
newname = malloc(len + b + 1); std::string newname(name, len);
if (!newname) newname += new_ext;
return;
memcpy(newname, name, len);
memcpy(newname + len, new_ext, b + 1);
/* /*
* Ignore errors. Maybe we can't create the backup file, * Ignore errors. Maybe we can't create the backup file,
* maybe no old file existed. Regardless, we'll write the * maybe no old file existed. Regardless, we'll write the
* new file. * new file.
*/ */
(void) subsurface_rename(name, newname); (void) subsurface_rename(name, newname.c_str());
free(newname);
} }
static void try_to_backup(const char *filename) static void try_to_backup(const char *filename)
@ -820,11 +810,8 @@ static void try_to_backup(const char *filename)
int elen = strlen(extension[i]); int elen = strlen(extension[i]);
if (strcasecmp(filename + flen - elen, extension[i]) == 0) { if (strcasecmp(filename + flen - elen, extension[i]) == 0) {
if (last_xml_version < DATAFORMAT_VERSION) { if (last_xml_version < DATAFORMAT_VERSION) {
int se_len = strlen(extension[i]) + 5; std::string special_ext = std::string(extension[i]) + ".v" + std::to_string(last_xml_version);
char *special_ext = malloc(se_len); save_backup(filename, extension[i], special_ext.c_str());
snprintf(special_ext, se_len, "%s.v%d", extension[i], last_xml_version);
save_backup(filename, extension[i], special_ext);
free(special_ext);
} else { } else {
save_backup(filename, extension[i], "bak"); save_backup(filename, extension[i], "bak");
} }
@ -834,9 +821,9 @@ static void try_to_backup(const char *filename)
} }
} }
int save_dives_logic(const char *filename, const bool select_only, bool anonymize) extern "C" int save_dives_logic(const char *filename, const bool select_only, bool anonymize)
{ {
struct membuffer buf = { 0 }; struct membufferpp buf;
struct git_info info; struct git_info info;
FILE *f; FILE *f;
int error = 0; int error = 0;
@ -863,7 +850,6 @@ int save_dives_logic(const char *filename, const bool select_only, bool anonymiz
if (error) if (error)
report_error(translate("gettextFromC", "Failed to save dives to %s (%s)"), filename, strerror(errno)); report_error(translate("gettextFromC", "Failed to save dives to %s (%s)"), filename, strerror(errno));
free_buffer(&buf);
return error; return error;
} }
@ -880,7 +866,7 @@ int export_dives_xslt(const char *filename, const bool selected, const int units
static int export_dives_xslt_doit(const char *filename, struct xml_params *params, bool selected, int units, const char *export_xslt, bool anonymize) static int export_dives_xslt_doit(const char *filename, struct xml_params *params, bool selected, int units, const char *export_xslt, bool anonymize)
{ {
FILE *f; FILE *f;
struct membuffer buf = { 0 }; struct membufferpp buf;
xmlDoc *doc; xmlDoc *doc;
xsltStylesheetPtr xslt = NULL; xsltStylesheetPtr xslt = NULL;
xmlDoc *transformed; xmlDoc *transformed;
@ -901,7 +887,6 @@ static int export_dives_xslt_doit(const char *filename, struct xml_params *param
* the XML into a character buffer. * the XML into a character buffer.
*/ */
doc = xmlReadMemory(buf.buffer, buf.len, "divelog", NULL, XML_PARSE_HUGE | XML_PARSE_RECOVER); doc = xmlReadMemory(buf.buffer, buf.len, "divelog", NULL, XML_PARSE_HUGE | XML_PARSE_RECOVER);
free_buffer(&buf);
if (!doc) if (!doc)
return report_error("Failed to read XML memory"); return report_error("Failed to read XML memory");
@ -961,9 +946,9 @@ static void save_dive_sites_buffer(struct membuffer *b, const struct dive_site *
put_format(b, "</divesites>\n"); put_format(b, "</divesites>\n");
} }
int save_dive_sites_logic(const char *filename, const struct dive_site *sites[], int nr_sites, bool anonymize) extern "C" int save_dive_sites_logic(const char *filename, const struct dive_site *sites[], int nr_sites, bool anonymize)
{ {
struct membuffer buf = { 0 }; struct membufferpp buf;
FILE *f; FILE *f;
int error = 0; int error = 0;
@ -983,6 +968,5 @@ int save_dive_sites_logic(const char *filename, const struct dive_site *sites[],
if (error) if (error)
report_error(translate("gettextFromC", "Failed to save divesites to %s (%s)"), filename, strerror(errno)); report_error(translate("gettextFromC", "Failed to save divesites to %s (%s)"), filename, strerror(errno));
free_buffer(&buf);
return error; return error;
} }