diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2019-08-19 13:42:48 +0200 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2019-08-19 18:56:58 +0200 |
| commit | 177c2d8c1ed33391711524948fef5313c8624c75 (patch) | |
| tree | 6bf8d0e17b2f6c2d69d77b611213139adbc74b9d /src | |
| parent | 228bce0f6612044a18569919798d7e89e18a29c8 (diff) | |
| download | cc4group-177c2d8c1ed33391711524948fef5313c8624c75.tar.gz cc4group-177c2d8c1ed33391711524948fef5313c8624c75.zip | |
Allow the warning handling callback to be set to a custom callback
Diffstat (limited to 'src')
| -rw-r--r-- | src/cc4group.c | 16 | ||||
| -rw-r--r-- | src/cc4group.h | 15 | ||||
| -rw-r--r-- | src/cppc4group.cpp | 32 | ||||
| -rw-r--r-- | src/cppc4group.hpp | 5 |
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 |
