/*
(c) 2004-14 Filip Stoklas, aka FipS, www.4FipS.com
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
*/
#include "fs_common.h"
#include "fs_common_os.h"
#include <stdarg.h> // va_list
#include <chrono>
// --- ASSERT ---
namespace fs { namespace assert {
namespace
{
handler_type g_handler = default_handler;
}
bool dispatch(const char *cond, const char *func, const char *file, int line) FS_NOEXCEPT
{
return handler()(cond, func, file, line);
}
handler_type set_handler(handler_type h) FS_NOEXCEPT
{
handler_type orig = g_handler;
g_handler = h;
return orig;
}
handler_type handler() FS_NOEXCEPT
{
return g_handler;
}
const char * strip_fname(const char *path) FS_NOEXCEPT
{
const char *p1 = strrchr(path, '/');
const char *p2 = strrchr(path, '\\');
return p1 > p2 ? p1 + 1 : p2 > p1 ? p2 + 1 : path;
}
bool default_handler(const char *cond, const char *func, const char *file, int line) FS_NOEXCEPT
{
char buf[1024];
FS_TRACE(("[x] ASSERTION: '%s', '%s', %s(%d)", cond, func, strip_fname(file), line));
str::snprintf_trunc(
buf, FS_COUNT_OF(buf),
"CONDITION:\n%s\n\n"
"FILE:\n%s (line=%d)\n\n"
"FUNCTION:\n%s\n\n"
"Would you like to debug now?",
cond, strip_fname(file), line, func
);
return os::show_yes_no_dialog("!!! FIPS ASSERTION !!!", buf, true);
}
}} // namespace fs::assert
// --- TRACE ---
namespace fs { namespace trace {
namespace
{
handler_type g_handler = default_handler;
}
void dispatch(const char *fmt, ...) FS_NOEXCEPT
{
char buf[1024];
va_list args;
va_start(args, fmt);
str::vsnprintf_trunc(buf, FS_COUNT_OF(buf), fmt, args);
va_end(args);
handler()(buf);
}
handler_type set_handler(handler_type h) FS_NOEXCEPT
{
handler_type orig = g_handler;
g_handler = h;
return orig;
}
handler_type handler() FS_NOEXCEPT
{
return g_handler;
}
void default_handler(const char *text) FS_NOEXCEPT
{
// we need this extra copy to be able to print text+'\n' atomically
char buf[1024];
str::snprintf_trunc(buf, FS_COUNT_OF(buf), "%s\n", text);
os::debug_print(buf);
}
}} // namespace fs::trace
// --- PROBE ---
namespace fs { namespace probe {
namespace
{
handler_type g_handler = { default_handler, nullptr };
}
void dispatch(const char *key, double val) FS_NOEXCEPT
{
const auto h = handler();
h.cb(h.ctx, key, val);
}
handler_type set_handler(handler_type h) FS_NOEXCEPT
{
handler_type orig = g_handler;
g_handler = h;
return orig;
}
handler_type handler() FS_NOEXCEPT
{
return g_handler;
}
void default_handler(void *ctx, const char *key, double val) FS_NOEXCEPT
{
FS_TRACE(("[.] PROBE: %s %g", key, val));
}
}} // namespace fs::probe
// --- ERROR ---
namespace fs { namespace error {
namespace
{
handler_type g_handler = default_handler;
bool g_debug_break_enabled = false;
}
void dispatch(const error &err) FS_NOEXCEPT
{
handler()(err);
}
handler_type set_handler(handler_type h) FS_NOEXCEPT
{
handler_type orig = g_handler;
g_handler = h;
return orig;
}
handler_type handler() FS_NOEXCEPT
{
return g_handler;
}
void default_handler(const error &err) FS_NOEXCEPT
{
FS_TRACE(("[x] ERROR: '%s' !", err.what()));
std::terminate();
}
bool enable_debug_break(bool on) FS_NOEXCEPT
{
const bool orig = g_debug_break_enabled;
g_debug_break_enabled = on;
return orig;
}
bool debug_break_enabled() FS_NOEXCEPT
{
return g_debug_break_enabled;
}
}} // namespace fs::error
// --- MISC ---
namespace fs {
double sys_time() FS_NOEXCEPT
{
using namespace std::chrono;
using res = nanoseconds;
return
duration_cast<res>(high_resolution_clock::now().time_since_epoch()).count() /
static_cast<double>(duration_cast<res>(seconds(1)).count());
}
} // namespace fs