Skip to content

Commit 027449d

Browse files
committed
C++ API for message processors
1 parent 08567c4 commit 027449d

3 files changed

Lines changed: 162 additions & 8 deletions

File tree

Source/FreeImage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ DLL_API void DLL_CALLCONV FreeImage_ProcessMessage(const FIMESSAGE* msg);
937937

938938

939939
DLL_API FIMESSAGE* DLL_CALLCONV FreeImage_CreateMessage(FREE_IMAGE_FORMAT scope, FREE_IMAGE_SEVERITY severity, const char* what);
940-
DLL_API void DLL_CALLCONV FreeImage_DeleteMessage(const FIMESSAGE* msg);
940+
DLL_API void DLL_CALLCONV FreeImage_DeleteMessage(FIMESSAGE* msg);
941941
DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetMessageScope(const FIMESSAGE* msg);
942942
DLL_API FREE_IMAGE_SEVERITY DLL_CALLCONV FreeImage_GetMessageSeverity(const FIMESSAGE* msg);
943943
DLL_API const char* DLL_CALLCONV FreeImage_GetMessageString(const FIMESSAGE* msg);

Source/FreeImage.hpp

Lines changed: 160 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <cassert>
1414
#include <filesystem>
15+
#include <functional>
1516
#include <limits>
1617
#include <memory>
1718
#include <optional>
@@ -250,6 +251,15 @@ namespace fi
250251
eSrcAlpha = FIAO_SrcAlpha
251252
};
252253

254+
enum class Severity
255+
{
256+
eVerbose = FISEV_VERBOSE,
257+
eInfo = FISEV_INFO,
258+
eWarning = FISEV_WARNING,
259+
eError = FISEV_ERROR,
260+
eNone = FISEV_NONE
261+
};
262+
253263

254264
class ImageError
255265
: public std::runtime_error
@@ -325,6 +335,148 @@ namespace fi
325335
}
326336

327337

338+
/**
339+
* Const access to a message allocated inside FreeImage
340+
*/
341+
class MessageView
342+
{
343+
public:
344+
explicit
345+
MessageView(const FIMESSAGE* handle)
346+
: mHandle(handle)
347+
{ }
348+
349+
MessageView(const MessageView&) = default;
350+
MessageView(MessageView&&) noexcept = default;
351+
352+
// no need to release
353+
~MessageView() = default;
354+
355+
MessageView& operator=(const MessageView&) = default;
356+
MessageView& operator=(MessageView&&) noexcept = default;
357+
358+
operator bool() const {
359+
return (mHandle != nullptr);
360+
}
361+
362+
const char* GetCString() const {
363+
return FreeImage_GetMessageString(mHandle);
364+
}
365+
366+
std::string GetString() const {
367+
const char* str = FreeImage_GetMessageString(mHandle);
368+
return str ? std::string(str) : std::string();
369+
}
370+
371+
Severity GetSeverity() const {
372+
return static_cast<Severity>(FreeImage_GetMessageSeverity(mHandle));
373+
}
374+
375+
ImageFormat GetScope() const {
376+
return static_cast<ImageFormat>(FreeImage_GetMessageScope(mHandle));
377+
}
378+
379+
protected:
380+
const FIMESSAGE* mHandle;
381+
};
382+
383+
384+
/**
385+
* Mutable user allocated message instance
386+
*/
387+
class Message
388+
: public MessageView
389+
{
390+
public:
391+
Message(ImageFormat scope, Severity severity, const char* what)
392+
: MessageView(FREEIMAGERE_CHECKED_CALL(FreeImage_CreateMessage, static_cast<FREE_IMAGE_FORMAT>(scope), static_cast<FREE_IMAGE_SEVERITY>(severity), what))
393+
{ }
394+
395+
Message(ImageFormat scope, Severity severity, const std::string& what)
396+
: Message(scope, severity, what.c_str())
397+
{ }
398+
399+
Message(const Message&) = delete;
400+
401+
Message(Message&& other) noexcept
402+
: MessageView(other.mHandle)
403+
{
404+
other.mHandle = nullptr;
405+
}
406+
407+
// not virtual, just reusing methods MessageView
408+
~Message() {
409+
FreeImage_DeleteMessage(GetMutable());
410+
}
411+
412+
Message& operator=(const Message&) = delete;
413+
414+
Message& operator=(Message&& other) noexcept
415+
{
416+
if (this != &other) {
417+
FreeImage_DeleteMessage(GetMutable());
418+
mHandle = other.mHandle;
419+
other.mHandle = nullptr;
420+
}
421+
return *this;
422+
}
423+
424+
private:
425+
FIMESSAGE* GetMutable() {
426+
// Message created by FreeImage_CreateMessage() is actually a dynamic object, so can safely remove const
427+
return const_cast<FIMESSAGE*>(mHandle);
428+
}
429+
};
430+
431+
432+
using MessageProcessFunction = std::function<void(const MessageView&)>;
433+
434+
435+
/**
436+
* Registers a message processor for life time of this guard instance
437+
*/
438+
class MessageProcessFunctionGuard
439+
{
440+
public:
441+
MessageProcessFunctionGuard(MessageProcessFunction func)
442+
: mFunc(std::move(func))
443+
{
444+
mProcId = FREEIMAGERE_CHECKED_CALL(FreeImage_AddProcessMessageFunction, this, &MessageProcessFunctionGuard::Wrapper);
445+
}
446+
447+
MessageProcessFunctionGuard(const MessageProcessFunctionGuard&) = delete;
448+
MessageProcessFunctionGuard(MessageProcessFunctionGuard&& other) noexcept = delete;
449+
450+
~MessageProcessFunctionGuard()
451+
{
452+
if (mProcId) {
453+
FreeImage_RemoveProcessMessageFunction(mProcId);
454+
}
455+
}
456+
457+
MessageProcessFunctionGuard& operator=(const MessageProcessFunctionGuard&) = delete;
458+
MessageProcessFunctionGuard& operator=(MessageProcessFunctionGuard&& other) noexcept = delete;
459+
460+
/**
461+
* Do not call FreeImage_RemoveProcessMessageFunction() in destcrutor
462+
*/
463+
uint32_t Release() {
464+
const uint32_t tmp = mProcId;
465+
mProcId = 0;
466+
return tmp;
467+
}
468+
469+
private:
470+
static
471+
void DLL_CALLCONV Wrapper(void* thiz, const FIMESSAGE* msg) {
472+
static_cast<MessageProcessFunctionGuard*>(thiz)->mFunc(MessageView(msg));
473+
}
474+
475+
MessageProcessFunction mFunc;
476+
uint32_t mProcId{ 0 };
477+
};
478+
479+
328480

329481
class Tag
330482
{
@@ -359,13 +511,15 @@ namespace fi
359511

360512
Tag& operator=(Tag&& other) noexcept
361513
{
362-
if (mCallDelete && mHandle) {
363-
FreeImage_DeleteTag(mHandle);
514+
if (this != &other) {
515+
if (mCallDelete) {
516+
FreeImage_DeleteTag(mHandle);
517+
}
518+
mHandle = other.mHandle;
519+
mCallDelete = other.mCallDelete;
520+
other.mHandle = nullptr;
521+
other.mCallDelete = false;
364522
}
365-
mHandle = other.mHandle;
366-
mCallDelete = other.mCallDelete;
367-
other.mHandle = nullptr;
368-
other.mCallDelete = false;
369523
return *this;
370524
}
371525

Source/FreeImage/FreeImage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ FIMESSAGE* FreeImage_CreateMessage(FREE_IMAGE_FORMAT scope, FREE_IMAGE_SEVERITY
354354
}
355355

356356

357-
void FreeImage_DeleteMessage(const FIMESSAGE* msg)
357+
void FreeImage_DeleteMessage(FIMESSAGE* msg)
358358
{
359359
if (msg) {
360360
delete msg;

0 commit comments

Comments
 (0)