core: port tag.c to C++

Let taglist_get_tagstring() return an std::string, since all callers
are C++ anyway.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-03-10 17:20:59 +01:00 committed by bstoeger
parent 84b7ffafd2
commit 422f693f5b
7 changed files with 47 additions and 66 deletions

View file

@ -93,7 +93,7 @@ SOURCES += subsurface-mobile-main.cpp \
core/sha1.c \ core/sha1.c \
core/string-format.cpp \ core/string-format.cpp \
core/strtod.c \ core/strtod.c \
core/tag.c \ core/tag.cpp \
core/taxonomy.c \ core/taxonomy.c \
core/time.cpp \ core/time.cpp \
core/trip.c \ core/trip.c \

View file

@ -177,7 +177,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
subsurfacestartup.h subsurfacestartup.h
subsurfacesysinfo.cpp subsurfacesysinfo.cpp
subsurfacesysinfo.h subsurfacesysinfo.h
tag.c tag.cpp
tag.h tag.h
taxonomy.c taxonomy.c
taxonomy.h taxonomy.h

View file

@ -1220,10 +1220,8 @@ QStringList get_dive_gas_list(const struct dive *d)
QString get_taglist_string(struct tag_entry *tag_list) QString get_taglist_string(struct tag_entry *tag_list)
{ {
char *buffer = taglist_get_tagstring(tag_list); std::string tags = taglist_get_tagstring(tag_list);
QString ret = QString::fromUtf8(buffer); return QString::fromStdString(tags);
free(buffer);
return ret;
} }
QStringList stringToList(const QString &s) QStringList stringToList(const QString &s)

View file

@ -7,6 +7,7 @@
#include "gettext.h" #include "gettext.h"
#include <stdlib.h> #include <stdlib.h>
#include <QtGlobal> // for QT_TRANSLATE_NOOP
struct tag_entry *g_tag_list = NULL; struct tag_entry *g_tag_list = NULL;
@ -23,7 +24,7 @@ static const char *default_tags[] = {
/* copy an element in a list of tags */ /* copy an element in a list of tags */
static void copy_tl(struct tag_entry *st, struct tag_entry *dt) static void copy_tl(struct tag_entry *st, struct tag_entry *dt)
{ {
dt->tag = malloc(sizeof(struct divetag)); dt->tag = (divetag *)malloc(sizeof(struct divetag));
dt->tag->name = copy_string(st->tag->name); dt->tag->name = copy_string(st->tag->name);
dt->tag->source = copy_string(st->tag->source); dt->tag->source = copy_string(st->tag->source);
} }
@ -39,7 +40,7 @@ static bool tag_seen_before(struct tag_entry *start, struct tag_entry *before)
} }
/* remove duplicates and empty nodes */ /* remove duplicates and empty nodes */
void taglist_cleanup(struct tag_entry **tag_list) extern "C" void taglist_cleanup(struct tag_entry **tag_list)
{ {
struct tag_entry **tl = tag_list; struct tag_entry **tl = tag_list;
while (*tl) { while (*tl) {
@ -52,27 +53,21 @@ void taglist_cleanup(struct tag_entry **tag_list)
} }
} }
char *taglist_get_tagstring(struct tag_entry *tag_list) std::string taglist_get_tagstring(struct tag_entry *tag_list)
{ {
bool first_tag = true; bool first_tag = true;
struct membuffer b = { 0 }; std::string res;
struct tag_entry *tmp = tag_list; struct tag_entry *tmp = tag_list;
while (tmp != NULL) { while (tmp != NULL) {
if (!empty_string(tmp->tag->name)) { if (!empty_string(tmp->tag->name)) {
if (first_tag) { if (!first_tag)
put_format(&b, "%s", tmp->tag->name); res += ", ";
first_tag = false; res += tmp->tag->name;
} else { first_tag = false;
put_format(&b, ", %s", tmp->tag->name);
}
} }
tmp = tmp->next; tmp = tmp->next;
} }
/* Ensures we do return null terminated empty string for: return strdup(res.c_str());
* - empty tag list
* - tag list with empty tag only
*/
return detach_cstring(&b);
} }
static inline void taglist_free_divetag(struct divetag *tag) static inline void taglist_free_divetag(struct divetag *tag)
@ -103,22 +98,22 @@ static struct divetag *taglist_add_divetag(struct tag_entry **tag_list, struct d
} }
/* Insert in front of it */ /* Insert in front of it */
entry = malloc(sizeof(struct tag_entry)); entry = (tag_entry *)malloc(sizeof(struct tag_entry));
entry->next = next; entry->next = next;
entry->tag = tag; entry->tag = tag;
*tag_list = entry; *tag_list = entry;
return tag; return tag;
} }
struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag) extern "C" struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag)
{ {
size_t i = 0; size_t i = 0;
int is_default_tag = 0; int is_default_tag = 0;
struct divetag *ret_tag, *new_tag; struct divetag *ret_tag, *new_tag;
const char *translation; const char *translation;
new_tag = malloc(sizeof(struct divetag)); new_tag = (divetag *)malloc(sizeof(struct divetag));
for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) { for (i = 0; i < std::size(default_tags); i++) {
if (strcmp(default_tags[i], tag) == 0) { if (strcmp(default_tags[i], tag) == 0) {
is_default_tag = 1; is_default_tag = 1;
break; break;
@ -127,13 +122,13 @@ struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag)
/* Only translate default tags */ /* Only translate default tags */
if (is_default_tag) { if (is_default_tag) {
translation = translate("gettextFromC", tag); translation = translate("gettextFromC", tag);
new_tag->name = malloc(strlen(translation) + 1); new_tag->name = (char *)malloc(strlen(translation) + 1);
memcpy(new_tag->name, translation, strlen(translation) + 1); memcpy(new_tag->name, translation, strlen(translation) + 1);
new_tag->source = malloc(strlen(tag) + 1); new_tag->source = (char *)malloc(strlen(tag) + 1);
memcpy(new_tag->source, tag, strlen(tag) + 1); memcpy(new_tag->source, tag, strlen(tag) + 1);
} else { } else {
new_tag->source = NULL; new_tag->source = NULL;
new_tag->name = malloc(strlen(tag) + 1); new_tag->name = (char *)malloc(strlen(tag) + 1);
memcpy(new_tag->name, tag, strlen(tag) + 1); memcpy(new_tag->name, tag, strlen(tag) + 1);
} }
/* Try to insert new_tag into g_tag_list if we are not operating on it */ /* Try to insert new_tag into g_tag_list if we are not operating on it */
@ -151,12 +146,12 @@ struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag)
return ret_tag; return ret_tag;
} }
void taglist_free(struct tag_entry *entry) extern "C" void taglist_free(struct tag_entry *entry)
{ {
STRUCTURED_LIST_FREE(struct tag_entry, entry, free) STRUCTURED_LIST_FREE(struct tag_entry, entry, free)
} }
struct tag_entry *taglist_copy(struct tag_entry *s) extern "C" struct tag_entry *taglist_copy(struct tag_entry *s)
{ {
struct tag_entry *res; struct tag_entry *res;
STRUCTURED_LIST_COPY(struct tag_entry, s, res, copy_tl); STRUCTURED_LIST_COPY(struct tag_entry, s, res, copy_tl);
@ -164,7 +159,7 @@ struct tag_entry *taglist_copy(struct tag_entry *s)
} }
/* Merge src1 and src2, write to *dst */ /* Merge src1 and src2, write to *dst */
void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2) extern "C" void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2)
{ {
struct tag_entry *entry; struct tag_entry *entry;
@ -174,10 +169,10 @@ void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_en
taglist_add_divetag(dst, entry->tag); taglist_add_divetag(dst, entry->tag);
} }
void taglist_init_global() extern "C" void taglist_init_global()
{ {
size_t i; size_t i;
for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) for (i = 0; i < std::size(default_tags); i++)
taglist_add_tag(&g_tag_list, default_tags[i]); taglist_add_tag(&g_tag_list, default_tags[i]);
} }

View file

@ -36,15 +36,6 @@ extern struct tag_entry *g_tag_list;
struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag); struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag);
/*
* Writes all divetags form tag_list into internally allocated buffer
* Function returns pointer to allocated buffer
* Buffer contains comma separated list of tags names or null terminated string
*
* NOTE! The returned buffer must be freed once used.
*/
char *taglist_get_tagstring(struct tag_entry *tag_list);
/* cleans up a list: removes empty tags and duplicates */ /* cleans up a list: removes empty tags and duplicates */
void taglist_cleanup(struct tag_entry **tag_list); void taglist_cleanup(struct tag_entry **tag_list);
@ -55,6 +46,14 @@ void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_en
#ifdef __cplusplus #ifdef __cplusplus
} }
// C++ only functions
#include <string>
/* Comma separated list of tags names or null terminated string */
std::string taglist_get_tagstring(struct tag_entry *tag_list);
#endif #endif
#endif #endif

View file

@ -1766,11 +1766,9 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c
case MAXCNS: case MAXCNS:
return lessThanHelper(d1->maxcns - d2->maxcns, row_diff); return lessThanHelper(d1->maxcns - d2->maxcns, row_diff);
case TAGS: { case TAGS: {
char *s1 = taglist_get_tagstring(d1->tag_list); std::string s1 = taglist_get_tagstring(d1->tag_list);
char *s2 = taglist_get_tagstring(d2->tag_list); std::string s2 = taglist_get_tagstring(d2->tag_list);
int diff = strCmp(s1, s2); int diff = strCmp(s1.c_str(), s2.c_str());
free(s1);
free(s2);
return lessThanHelper(diff, row_diff); return lessThanHelper(diff, row_diff);
} }
case PHOTOS: case PHOTOS:

View file

@ -17,19 +17,16 @@ void TestTagList::cleanupTestCase()
void TestTagList::testGetTagstringNoTags() void TestTagList::testGetTagstringNoTags()
{ {
struct tag_entry *tag_list = NULL; struct tag_entry *tag_list = NULL;
char *tagstring = taglist_get_tagstring(tag_list); std::string tagstring = taglist_get_tagstring(tag_list);
QVERIFY(tagstring != NULL); QVERIFY(tagstring.empty());
QCOMPARE(*tagstring, '\0');
} }
void TestTagList::testGetTagstringSingleTag() void TestTagList::testGetTagstringSingleTag()
{ {
struct tag_entry *tag_list = NULL; struct tag_entry *tag_list = NULL;
taglist_add_tag(&tag_list, "A new tag"); taglist_add_tag(&tag_list, "A new tag");
char *tagstring = taglist_get_tagstring(tag_list); std::string tagstring = taglist_get_tagstring(tag_list);
QVERIFY(tagstring != NULL); QCOMPARE(QString::fromStdString(tagstring), QString::fromUtf8("A new tag"));
QCOMPARE(QString::fromUtf8(tagstring), QString::fromUtf8("A new tag"));
free(tagstring);
} }
void TestTagList::testGetTagstringMultipleTags() void TestTagList::testGetTagstringMultipleTags()
@ -41,9 +38,8 @@ void TestTagList::testGetTagstringMultipleTags()
taglist_add_tag(&tag_list, "A new tag 3"); taglist_add_tag(&tag_list, "A new tag 3");
taglist_add_tag(&tag_list, "A new tag 4"); taglist_add_tag(&tag_list, "A new tag 4");
taglist_add_tag(&tag_list, "A new tag 5"); taglist_add_tag(&tag_list, "A new tag 5");
char *tagstring = taglist_get_tagstring(tag_list); std::string tagstring = taglist_get_tagstring(tag_list);
QVERIFY(tagstring != NULL); QCOMPARE(QString::fromStdString(tagstring),
QCOMPARE(QString::fromUtf8(tagstring),
QString::fromUtf8( QString::fromUtf8(
"A new tag, " "A new tag, "
"A new tag 1, " "A new tag 1, "
@ -51,7 +47,6 @@ void TestTagList::testGetTagstringMultipleTags()
"A new tag 3, " "A new tag 3, "
"A new tag 4, " "A new tag 4, "
"A new tag 5")); "A new tag 5"));
free(tagstring);
} }
void TestTagList::testGetTagstringWithAnEmptyTag() void TestTagList::testGetTagstringWithAnEmptyTag()
@ -60,24 +55,20 @@ void TestTagList::testGetTagstringWithAnEmptyTag()
taglist_add_tag(&tag_list, "A new tag"); taglist_add_tag(&tag_list, "A new tag");
taglist_add_tag(&tag_list, "A new tag 1"); taglist_add_tag(&tag_list, "A new tag 1");
taglist_add_tag(&tag_list, ""); taglist_add_tag(&tag_list, "");
char *tagstring = taglist_get_tagstring(tag_list); std::string tagstring = taglist_get_tagstring(tag_list);
QVERIFY(tagstring != NULL); QCOMPARE(QString::fromStdString(tagstring),
QCOMPARE(QString::fromUtf8(tagstring),
QString::fromUtf8( QString::fromUtf8(
"A new tag, " "A new tag, "
"A new tag 1")); "A new tag 1"));
free(tagstring);
} }
void TestTagList::testGetTagstringEmptyTagOnly() void TestTagList::testGetTagstringEmptyTagOnly()
{ {
struct tag_entry *tag_list = NULL; struct tag_entry *tag_list = NULL;
taglist_add_tag(&tag_list, ""); taglist_add_tag(&tag_list, "");
char *tagstring = taglist_get_tagstring(tag_list); std::string tagstring = taglist_get_tagstring(tag_list);
QVERIFY(tagstring != NULL); QCOMPARE(QString::fromStdString(tagstring),
QCOMPARE(QString::fromUtf8(tagstring),
QString::fromUtf8("")); QString::fromUtf8(""));
free(tagstring);
} }
QTEST_GUILESS_MAIN(TestTagList) QTEST_GUILESS_MAIN(TestTagList)