core: use std::string in error_callback

No naked free().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-06-08 23:32:17 +02:00 committed by bstoeger
parent 71f3189a31
commit d05e289507
8 changed files with 40 additions and 74 deletions

View file

@ -1,50 +1,44 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#ifdef __clang__
// Clang has a bug on zero-initialization of C structs.
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#endif
#include <stdarg.h>
#include "errorhelper.h" #include "errorhelper.h"
#include "membuffer.h" #include "format.h"
#include <stdarg.h>
#if !defined(Q_OS_ANDROID) && !defined(__ANDROID__) #if !defined(Q_OS_ANDROID) && !defined(__ANDROID__)
#define LOG_MSG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) #define LOG_MSG(fmt, s) fprintf(stderr, fmt, s)
#else #else
#include <android/log.h> #include <android/log.h>
#define LOG_MSG(fmt, ...) __android_log_print(ANDROID_LOG_INFO, "Subsurface", fmt, ##__VA_ARGS__); #define LOG_MSG(fmt, s) __android_log_print(ANDROID_LOG_INFO, "Subsurface", fmt, s);
#endif #endif
#define VA_BUF(b, fmt) do { va_list args; va_start(args, fmt); put_vformat(b, fmt, args); va_end(args); } while (0)
int verbose; int verbose;
void report_info(const char *fmt, ...) void report_info(const char *fmt, ...)
{ {
membuffer buf; va_list args;
va_start(args, fmt);
VA_BUF(&buf, fmt); std::string s = vformat_string_std(fmt, args);
strip_mb(&buf); va_end(args);
LOG_MSG("INFO: %s\n", mb_cstring(&buf)); LOG_MSG("INFO: %s\n", s.c_str());
} }
static void (*error_cb)(char *) = NULL; static void (*error_cb)(std::string) = NULL;
int report_error(const char *fmt, ...) int report_error(const char *fmt, ...)
{ {
membuffer buf; va_list args;
va_start(args, fmt);
VA_BUF(&buf, fmt); std::string s = vformat_string_std(fmt, args);
strip_mb(&buf); va_end(args);
LOG_MSG("ERROR: %s\n", mb_cstring(&buf)); LOG_MSG("ERROR: %s\n", s.c_str());
/* if there is no error callback registered, don't produce errors */ /* if there is no error callback registered, don't produce errors */
if (!error_cb) if (error_cb)
return -1; error_cb(std::move(s));
error_cb(detach_cstring(&buf));
return -1; return -1;
} }
void set_error_cb(void(*cb)(char *)) void set_error_cb(void(*cb)(std::string))
{ {
error_cb = cb; error_cb = cb;
} }

View file

@ -4,6 +4,8 @@
// error reporting functions // error reporting functions
#include <string>
#ifdef __GNUC__ #ifdef __GNUC__
#define __printf(x, y) __attribute__((__format__(__printf__, x, y))) #define __printf(x, y) __attribute__((__format__(__printf__, x, y)))
#else #else
@ -13,6 +15,6 @@
extern int verbose; extern int verbose;
extern int __printf(1, 2) report_error(const char *fmt, ...); extern int __printf(1, 2) report_error(const char *fmt, ...);
extern void __printf(1, 2) report_info(const char *fmt, ...); extern void __printf(1, 2) report_info(const char *fmt, ...);
extern void set_error_cb(void(*cb)(char *)); // Callback takes ownership of passed string extern void set_error_cb(void(*cb)(std::string s)); // Callback takes ownership of passed string
#endif #endif

View file

@ -18,35 +18,17 @@ membuffer::membuffer()
membuffer::~membuffer() membuffer::~membuffer()
{ {
free_buffer(this); free(buffer);
}
/* Only for internal use */
static char *detach_buffer(struct membuffer *b)
{
char *result = b->buffer;
b->buffer = NULL;
b->len = 0;
b->alloc = 0;
return result;
}
char *detach_cstring(struct membuffer *b)
{
mb_cstring(b);
return detach_buffer(b);
}
void free_buffer(struct membuffer *b)
{
free(detach_buffer(b));
} }
void flush_buffer(struct membuffer *b, FILE *f) void flush_buffer(struct membuffer *b, FILE *f)
{ {
if (b->len) { if (b->len) {
fwrite(b->buffer, 1, b->len, f); fwrite(b->buffer, 1, b->len, f);
free_buffer(b); free(b->buffer);
b->buffer = NULL;
b->len = 0;
b->alloc = 0;
} }
} }

View file

@ -19,10 +19,6 @@
* *
* "something, something else" * "something, something else"
* *
* Unless ownership to the buffer is given away by using "detach_cstring()":
*
* ptr = detach_cstring();
*
* where the caller now has a C string and is supposed to free it. * where the caller now has a C string and is supposed to free it.
*/ */
#ifndef MEMBUFFER_H #ifndef MEMBUFFER_H
@ -46,8 +42,6 @@ struct membuffer {
#define __printf(x, y) #define __printf(x, y)
#endif #endif
extern char *detach_cstring(struct membuffer *b);
extern void free_buffer(struct membuffer *);
extern void make_room(struct membuffer *b, unsigned int size); extern void make_room(struct membuffer *b, unsigned int size);
extern void flush_buffer(struct membuffer *, FILE *); extern void flush_buffer(struct membuffer *, FILE *);
extern void put_bytes(struct membuffer *, const char *, int); extern void put_bytes(struct membuffer *, const char *, int);

View file

@ -440,12 +440,11 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
// this breaks an "else if" across lines... not happy... // this breaks an "else if" across lines... not happy...
#endif #endif
if (data->vendor() == "Uemis") { if (data->vendor() == "Uemis") {
char *colon; QString devname = ui.device->currentText();
char *devname = copy_qstring(ui.device->currentText()); auto colon = devname.indexOf(":\\ (UEMISSDA)");
if (colon >= 0) {
if ((colon = strstr(devname, ":\\ (UEMISSDA)")) != NULL) { devname.resize(colon + 2);
*(colon + 2) = '\0'; report_info("shortened devname to \"%s\"", qPrintable(devname));
report_info("shortened devname to \"%s\"", devname);
} }
data->setDevName(devname); data->setDevName(devname);
} else { } else {

View file

@ -107,11 +107,9 @@ int updateProgress(const char *text)
MainWindow *MainWindow::m_Instance = nullptr; MainWindow *MainWindow::m_Instance = nullptr;
void showErrorFromC(char *buf) static void showError(std::string err)
{ {
QString error(buf); emit MainWindow::instance()->showError(QString::fromStdString(err));
free(buf);
emit MainWindow::instance()->showError(error);
} }
MainWindow::MainWindow() : MainWindow::MainWindow() :
@ -242,7 +240,7 @@ MainWindow::MainWindow() :
setupSocialNetworkMenu(); setupSocialNetworkMenu();
set_git_update_cb(&updateProgress); set_git_update_cb(&updateProgress);
set_error_cb(&showErrorFromC); set_error_cb(&::showError);
// full screen support is buggy on Windows and Ubuntu. // full screen support is buggy on Windows and Ubuntu.
// require the FULLSCREEN_SUPPORT macro to enable it! // require the FULLSCREEN_SUPPORT macro to enable it!

View file

@ -66,10 +66,9 @@ bool noCloudToCloud = false;
#define RED_FONT QLatin1String("<font color=\"red\">") #define RED_FONT QLatin1String("<font color=\"red\">")
#define END_FONT QLatin1String("</font>") #define END_FONT QLatin1String("</font>")
void showErrorFromC(char *buf) static void showError(std::string s)
{ {
QString error(buf); QString error = QString::fromStdString(s);
free(buf);
// By using invokeMethod with Qt:AutoConnection, the error string is safely // By using invokeMethod with Qt:AutoConnection, the error string is safely
// transported across thread boundaries, if not called from the UI thread. // transported across thread boundaries, if not called from the UI thread.
QMetaObject::invokeMethod(QMLManager::instance(), "registerError", Qt::AutoConnection, Q_ARG(QString, error)); QMetaObject::invokeMethod(QMLManager::instance(), "registerError", Qt::AutoConnection, Q_ARG(QString, error));
@ -271,7 +270,7 @@ QMLManager::QMLManager() :
appendTextToLog("No writeable location found, in-memory log only and no libdivecomputer log"); appendTextToLog("No writeable location found, in-memory log only and no libdivecomputer log");
} }
#endif #endif
set_error_cb(&showErrorFromC); set_error_cb(&showError);
uiNotificationCallback = showProgress; uiNotificationCallback = showProgress;
appendTextToLog("Starting " + getUserAgent()); appendTextToLog("Starting " + getUserAgent());
appendTextToLog(QStringLiteral("built with libdivecomputer v%1").arg(dc_version(NULL))); appendTextToLog(QStringLiteral("built with libdivecomputer v%1").arg(dc_version(NULL)));

View file

@ -15,11 +15,9 @@ QStringList inputFiles;
QString outputFile; QString outputFile;
QString error_buf; QString error_buf;
void getErrorFromC(char *buf) void getErrorFromC(std::string buf)
{ {
QString error(buf); error_buf = QString::fromStdString(std::move(buf));
free(buf);
error_buf = error;
} }
Smrtk2ssrfcWindow::Smrtk2ssrfcWindow(QWidget *parent) : Smrtk2ssrfcWindow::Smrtk2ssrfcWindow(QWidget *parent) :