summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cc4group.c16
-rw-r--r--src/cc4group.h15
-rw-r--r--src/cppc4group.cpp32
-rw-r--r--src/cppc4group.hpp5
4 files changed, 63 insertions, 5 deletions
diff --git a/src/cc4group.c b/src/cc4group.c
index df8854a..3c921e5 100644
--- a/src/cc4group.c
+++ b/src/cc4group.c
@@ -238,18 +238,20 @@ static char* cc4group_noerrorFormatter(int32_t const code, const char* const met
return strdup("No Error");
}
-// TODO: allow the user to set a warning callback with falling back to fprintf(stderr) by default
-static void cc4group_warn(const CC4Group* const this, const char* const message, ...)
+static void cc4group_printToStderrWarningCallback(const CC4Group* const this, const char* const format, ...)
{
(void)this;
va_list ap;
- va_start(ap, message);
+ va_start(ap, format);
fputs("WARNING: ", stderr);
- vfprintf(stderr, message, ap);
+ vfprintf(stderr, format, ap);
fputs("\n", stderr);
va_end (ap);
}
+static const CC4Group_WarningCallback cc4group_defaultWarningCallback = cc4group_printToStderrWarningCallback;
+static CC4Group_WarningCallback cc4group_warn = cc4group_defaultWarningCallback;
+
#define AddCleanUpJob(func, data) CleanUpJobListPrepend(this->cleanupJobs, (CC4Group_CleanupJob){(CC4Group_CleanupFunc)func, data});
static void memScrambleHeader(uint8_t* const data)
@@ -2185,6 +2187,11 @@ static void cc4group_setTmpMemoryStrategy(const CC4Group_TmpMemoryStrategy strat
cc4group_tmpMemoryStrategy = strategy;
}
+static void cc4group_setWarningCallback(const CC4Group_WarningCallback warningCallback)
+{
+ cc4group_warn = (warningCallback == NULL) ? cc4group_defaultWarningCallback : warningCallback;
+}
+
static const char* cc4group_getErrorMessage(CC4Group* const this)
{
assert(this);
@@ -3244,6 +3251,7 @@ CC4Group_API cc4group = {
},
.setTmpMemoryStrategy = cc4group_setTmpMemoryStrategy,
+ .setWarningCallback = cc4group_setWarningCallback,
.new = cc4group_new,
diff --git a/src/cc4group.h b/src/cc4group.h
index d2d978c..d81e84a 100644
--- a/src/cc4group.h
+++ b/src/cc4group.h
@@ -29,7 +29,7 @@
// the directory separator used for all entry paths in cc4group is "/" _regardless of the platform_. yes, you better watch out Windows users!
// in contrast to paths names are only the the name of the entry itself, not the whole path
// - to free all resources used by the group when it is not needed anymore, call cc4group.delete with the group pointer and discard it afterwards (i.e. don't use it anymore)
-// - all functions, except cc4group.new, cc4group.setLazy, cc4group.openAsChild, cc4group.delete and cc4group.setTmpMemoryStrategy (where the latter two can't fail) follow the same scheme
+// - all functions, except cc4group.new, cc4group.setLazy, cc4group.openAsChild, cc4group.delete, cc4group.setWarningCallback and cc4group.setTmpMemoryStrategy (where the latter three can't fail) follow the same scheme
// all of them can fail, either caused by wrong arguments or by things outside of the applications control
// they all return _true_ if everything went well and _false_ if any error occured
// information about the error (incredibly useful for debugging or asking for help with problems) can be obtained by using one the cc4group.getError* functions
@@ -173,6 +173,13 @@ typedef bool (*CC4Group_ReadSetupCallback)(void* const arg);
typedef bool (*CC4Group_WriteCallback)(const void* const data, size_t const size, void* const arg);
+
+// callback type for receiving warnings
+// whenever a warning is triggered, the callback will be called with the triggering group
+// and a format string and format arguments that are destined for some *printf function
+typedef void (*CC4Group_WarningCallback)(const CC4Group* const group, const char* const format, ...);
+
+
// this is the main API struct of cc4group
// it contains all available methods and constants
typedef struct {
@@ -212,6 +219,12 @@ typedef struct {
// for details, look at the description of CC4Group_TmpMemoryStrategy
void (*setTmpMemoryStrategy)(const CC4Group_TmpMemoryStrategy strategy);
+ // sets the global warning callback
+ // the default callback prints warnings to stderr; it can be restored by calling setWarningCallback with callback as NULL
+ // NOTE: this is a static method (i.e. it is used without any object)
+ // this will affect all groups in any state
+ void (*setWarningCallback)(const CC4Group_WarningCallback callback);
+
// allocates and initializes a new group object, like the operator new
// NULL may be returned if the memory allocation (malloc) fails; in this case errno contains additional error information
diff --git a/src/cppc4group.cpp b/src/cppc4group.cpp
index bacf1f7..99d5e41 100644
--- a/src/cppc4group.cpp
+++ b/src/cppc4group.cpp
@@ -2,6 +2,8 @@
#include "cc4group.h"
+#include <cstdarg>
+
CppC4Group::Data::Data() : data{nullptr}, size{0}
{
@@ -333,6 +335,36 @@ void CppC4Group::setTmpMemoryStrategy(const TmpMemoryCallback callback)
cc4group.setTmpMemoryStrategy(customTmpMemoryStrategy);
}
+namespace {
+
+ CppC4Group::WarningCallback cppc4group_warningCallback;
+ void CppC4Group_CustomWarningCallback(const CC4Group* const, const char* const format, ...)
+ {
+ va_list ap;
+ va_start(ap, format);
+ int size = std::vsnprintf(nullptr, 0, format, ap) + 1;
+ std::string message;
+ message.resize(size);
+ std::vsnprintf(message.data(), size, format, ap);
+ message.resize(size - 1);
+ va_end (ap);
+ cppc4group_warningCallback(message);
+ }
+}
+
+void CppC4Group::setWarningCallback(const CppC4Group::WarningCallback callback)
+{
+ if(callback == nullptr)
+ {
+ cc4group.setWarningCallback(nullptr);
+ }
+ else
+ {
+ cppc4group_warningCallback = callback;
+ cc4group.setWarningCallback(CppC4Group_CustomWarningCallback);
+ }
+}
+
bool CppC4Group::setMaker(const std::string& maker, const std::string& path, const bool recursive)
{
return cc4group.setMaker(p->g, maker.c_str(), path.c_str(), recursive);
diff --git a/src/cppc4group.hpp b/src/cppc4group.hpp
index 7f51629..e263ca4 100644
--- a/src/cppc4group.hpp
+++ b/src/cppc4group.hpp
@@ -111,6 +111,9 @@ public:
using SetupCallback = bool(*)(void* const arg);
using WriteCallback = bool(*)(const void* const data, size_t const size, void* const arg);
+ // but a more practical variant here
+ using WarningCallback = void(*)(const std::string& message);
+
// these enums are just mapped to their C-counterparts internally
enum class TmpMemoryStrategy {
Memory,
@@ -130,6 +133,8 @@ public:
// and this for your own custom strategy
static void setTmpMemoryStrategy(const TmpMemoryCallback callback);
+ static void setWarningCallback(const WarningCallback callback);
+
public:
// the constructor will automatically construct an internal CC4Group, so no new-equivalent method is needed
// may throw std::bad_alloc if the allocation and construction of the internal CC4Group object fails