0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-03-13 21:10:32 +01:00

ircd::magick: Start a central header; add interface support infrastructure.

This commit is contained in:
Jason Volk 2019-05-28 22:08:46 -07:00
parent 582cecccec
commit 16f6fbc352
3 changed files with 211 additions and 7 deletions

View file

@ -62,6 +62,7 @@
#include "m/m.h"
#include "resource/resource.h"
#include "client.h"
#include "magick.h"
/// \brief Internet Relay Chat daemon. This is the principal namespace for IRCd.
///

20
include/ircd/magick.h Normal file
View file

@ -0,0 +1,20 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_MAGICK_H
/// GraphicsMagick Library Interface
namespace ircd::magick
{
IRCD_EXCEPTION(ircd::error, error)
std::tuple<ulong, string_view> version();
}

View file

@ -12,8 +12,20 @@
namespace ircd::magick
{
static void handle_exception(const ::ExceptionType, const char *, const char *);
static void handle_fatal(const ::ExceptionType, const char *, const char *) noexcept;
static void handle_error(const ::ExceptionType, const char *, const char *) noexcept;
static void handle_warning(const ::ExceptionType, const char *, const char *) noexcept;
static void handle_log(const ::ExceptionType, const char *) noexcept;
template<class R, class F, class... A> static R call(F&&, A&&...);
template<class R, class F, class... A> static R callex(F&&, A&&...);
template<class F, class... A> static void callpf(F&&, A&&...);
static void init();
static void fini();
extern log::log log;
}
ircd::mapi::header
@ -24,6 +36,12 @@ IRCD_MODULE
ircd::magick::fini
};
decltype(ircd::magick::log)
ircd::magick::log
{
"magick"
};
//
// init
//
@ -31,10 +49,9 @@ IRCD_MODULE
void
ircd::magick::init()
{
ulong lib_version(0);
const char *const lib_version_text
const auto version
{
::GetMagickVersion(&lib_version)
magick::version()
};
log::debug
@ -42,19 +59,20 @@ ircd::magick::init()
"Initializing Magick Library include:%lu [%s] library:%lu [%s]",
ulong(MagickLibVersion),
MagickLibVersionText,
lib_version,
lib_version_text,
std::get<0>(version),
std::get<1>(version),
};
if(lib_version != ulong(MagickLibVersion))
if(std::get<0>(version) != ulong(MagickLibVersion))
log::warning
{
"Magick Library version mismatch headers:%lu library:%lu",
ulong(MagickLibVersion),
lib_version,
std::get<0>(version),
};
::InitializeMagick(nullptr);
::SetLogMethod(handle_log); //XXX assuming global
}
void
@ -67,3 +85,168 @@ ircd::magick::fini()
::DestroyMagick();
}
std::tuple<ulong, ircd::string_view>
ircd::magick::version()
{
ulong number(0);
const char *const string
{
::GetMagickVersion(&number)
};
return { number, string };
}
//
// util
//
template<class return_t,
class function,
class... args>
return_t
ircd::magick::callex(function&& f,
args&&... a)
{
const auto warning_handler(::SetWarningHandler(handle_warning));
const auto fatal_handler(::SetFatalErrorHandler(handle_fatal));
const auto error_handler(::SetErrorHandler(handle_exception));
const unwind reset{[&]
{
::SetFatalErrorHandler(fatal_handler);
::SetErrorHandler(error_handler);
::SetWarningHandler(warning_handler);
}};
::ExceptionInfo ei;
GetExceptionInfo(&ei); // initializer
const unwind destroy{[&ei]
{
::DestroyExceptionInfo(&ei);
}};
const auto ret
{
f(std::forward<args>(a)..., &ei)
};
// exception comes out of here; if this is not safe we'll have to
// convey with a global or inspect ExceptionInfo manually.
::CatchException(&ei);
return ret;
}
template<class function,
class... args>
void
ircd::magick::callpf(function&& f,
args&&... a)
{
const auto warning_handler(::SetWarningHandler(handle_warning));
const auto fatal_handler(::SetFatalErrorHandler(handle_fatal));
const auto error_handler(::SetErrorHandler(handle_error));
const unwind reset{[&]
{
::SetFatalErrorHandler(fatal_handler);
::SetErrorHandler(error_handler);
::SetWarningHandler(warning_handler);
}};
if(!call(f, std::forward<args>(a)...))
throw error{};
}
template<class return_t,
class function,
class... args>
return_t
ircd::magick::call(function&& f,
args&&... a)
{
const auto warning_handler(::SetWarningHandler(handle_warning));
const auto fatal_handler(::SetFatalErrorHandler(handle_fatal));
const auto error_handler(::SetErrorHandler(handle_error));
const unwind reset{[&]
{
::SetFatalErrorHandler(fatal_handler);
::SetErrorHandler(error_handler);
::SetWarningHandler(warning_handler);
}};
return f(std::forward<args>(a)...);
}
void
ircd::magick::handle_log(const ::ExceptionType type,
const char *const message)
noexcept
{
log::debug
{
log, "%s :%s",
::GetLocaleExceptionMessage(type, nullptr),
message
};
}
void
ircd::magick::handle_warning(const ::ExceptionType type,
const char *const reason,
const char *const description)
noexcept
{
log::warning
{
log, "%s %s :%s",
::GetLocaleExceptionMessage(type, nullptr),
reason,
description
};
}
void
ircd::magick::handle_error(const ::ExceptionType type,
const char *const reason,
const char *const description)
noexcept
{
log::error
{
log, "%s %s :%s",
::GetLocaleExceptionMessage(type, nullptr),
reason,
description
};
}
[[noreturn]] void
ircd::magick::handle_fatal(const ::ExceptionType type,
const char *const reason,
const char *const description)
noexcept
{
log::critical
{
log, "%s %s :%s",
::GetLocaleExceptionMessage(type, nullptr),
reason,
description
};
ircd::terminate();
}
[[noreturn]] void
ircd::magick::handle_exception(const ::ExceptionType type,
const char *const reason,
const char *const description)
{
throw error
{
"%s %s :%s",
::GetLocaleExceptionMessage(type, nullptr),
reason,
description
};
}