mirror of
https://github.com/matrix-construct/construct
synced 2024-09-27 19:28:52 +02:00
ircd::fpe: Add floating point environment suite; error scoping device.
This commit is contained in:
parent
c0de9b2e76
commit
6967ad1faa
6 changed files with 138 additions and 0 deletions
|
@ -583,6 +583,7 @@ RB_CHK_SYSHEADER(functional, [FUNCTIONAL])
|
||||||
RB_CHK_SYSHEADER(algorithm, [ALGORITHM])
|
RB_CHK_SYSHEADER(algorithm, [ALGORITHM])
|
||||||
RB_CHK_SYSHEADER(numeric, [NUMERIC])
|
RB_CHK_SYSHEADER(numeric, [NUMERIC])
|
||||||
RB_CHK_SYSHEADER(cmath, [CMATH])
|
RB_CHK_SYSHEADER(cmath, [CMATH])
|
||||||
|
RB_CHK_SYSHEADER(cfenv, [CFENV])
|
||||||
RB_CHK_SYSHEADER(memory, [MEMORY])
|
RB_CHK_SYSHEADER(memory, [MEMORY])
|
||||||
RB_CHK_SYSHEADER(exception, [EXCEPTION])
|
RB_CHK_SYSHEADER(exception, [EXCEPTION])
|
||||||
RB_CHK_SYSHEADER(cerrno, [CERRNO])
|
RB_CHK_SYSHEADER(cerrno, [CERRNO])
|
||||||
|
|
34
include/ircd/fpe.h
Normal file
34
include/ircd/fpe.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Matrix Construct
|
||||||
|
//
|
||||||
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||||
|
// Copyright (C) 2016-2018 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_FPE_H
|
||||||
|
|
||||||
|
namespace ircd::fpe
|
||||||
|
{
|
||||||
|
struct errors_handle;
|
||||||
|
|
||||||
|
string_view reflect(const ushort &flag);
|
||||||
|
string_view reflect(const mutable_buffer &, const ushort &flags);
|
||||||
|
void throw_errors(const ushort &flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ircd::fpe::errors_handle
|
||||||
|
{
|
||||||
|
fexcept_t theirs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ushort pending() const;
|
||||||
|
void throw_pending() const;
|
||||||
|
void clear_pending();
|
||||||
|
|
||||||
|
errors_handle();
|
||||||
|
~errors_handle() noexcept(false);
|
||||||
|
};
|
|
@ -36,6 +36,7 @@ namespace ircd
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "fpe.h"
|
||||||
#include "demangle.h"
|
#include "demangle.h"
|
||||||
#include "localee.h"
|
#include "localee.h"
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
|
|
|
@ -59,6 +59,7 @@ extern "C"
|
||||||
#include <RB_INC_ALGORITHM
|
#include <RB_INC_ALGORITHM
|
||||||
#include <RB_INC_NUMERIC
|
#include <RB_INC_NUMERIC
|
||||||
#include <RB_INC_CMATH
|
#include <RB_INC_CMATH
|
||||||
|
#include <RB_INC_CFENV
|
||||||
#include <RB_INC_MEMORY
|
#include <RB_INC_MEMORY
|
||||||
#include <RB_INC_EXCEPTION
|
#include <RB_INC_EXCEPTION
|
||||||
#include <RB_INC_SYSTEM_ERROR
|
#include <RB_INC_SYSTEM_ERROR
|
||||||
|
|
|
@ -91,6 +91,7 @@ libircd_la_SOURCES = \
|
||||||
allocator.cc \
|
allocator.cc \
|
||||||
exception.cc \
|
exception.cc \
|
||||||
util.cc \
|
util.cc \
|
||||||
|
fpe.cc \
|
||||||
ios.cc \
|
ios.cc \
|
||||||
lexical.cc \
|
lexical.cc \
|
||||||
tokens.cc \
|
tokens.cc \
|
||||||
|
|
100
ircd/fpe.cc
Normal file
100
ircd/fpe.cc
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// Matrix Construct
|
||||||
|
//
|
||||||
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||||
|
// Copyright (C) 2016-2018 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.
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#pragma STDC FENV_ACCESS on
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ircd::fpe::errors_handle::errors_handle()
|
||||||
|
{
|
||||||
|
syscall(std::fegetexceptflag, &theirs, FE_ALL_EXCEPT);
|
||||||
|
clear_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::fpe::errors_handle::~errors_handle()
|
||||||
|
noexcept(false)
|
||||||
|
{
|
||||||
|
const auto pending(this->pending());
|
||||||
|
syscall(std::fesetexceptflag, &theirs, FE_ALL_EXCEPT);
|
||||||
|
throw_errors(pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::fpe::errors_handle::clear_pending()
|
||||||
|
{
|
||||||
|
syscall(std::feclearexcept, FE_ALL_EXCEPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::fpe::errors_handle::throw_pending()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
throw_errors(pending());
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort
|
||||||
|
ircd::fpe::errors_handle::pending()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return std::fetestexcept(FE_ALL_EXCEPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// util
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::fpe::throw_errors(const ushort &flags)
|
||||||
|
{
|
||||||
|
if(!flags)
|
||||||
|
return;
|
||||||
|
|
||||||
|
thread_local char buf[128];
|
||||||
|
throw std::domain_error
|
||||||
|
{
|
||||||
|
reflect(buf, flags)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::string_view
|
||||||
|
ircd::fpe::reflect(const mutable_buffer &buf,
|
||||||
|
const ushort &flags)
|
||||||
|
{
|
||||||
|
window_buffer wb{buf};
|
||||||
|
const auto append{[&wb](const auto &flag)
|
||||||
|
{
|
||||||
|
wb([&flag](const mutable_buffer &buf)
|
||||||
|
{
|
||||||
|
return strlcpy(buf, reflect(flag));
|
||||||
|
});
|
||||||
|
}};
|
||||||
|
|
||||||
|
for(size_t i(0); i < sizeof(flags) * 8; ++i)
|
||||||
|
if(flags & (1 << i))
|
||||||
|
append(1 << i);
|
||||||
|
|
||||||
|
return wb.completed();
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::string_view
|
||||||
|
ircd::fpe::reflect(const ushort &flag)
|
||||||
|
{
|
||||||
|
switch(flag)
|
||||||
|
{
|
||||||
|
case 0: return "";
|
||||||
|
case FE_INVALID: return "INVALID";
|
||||||
|
case FE_DIVBYZERO: return "DIVBYZERO";
|
||||||
|
case FE_UNDERFLOW: return "UNDERFLOW";
|
||||||
|
case FE_OVERFLOW: return "OVERFLOW";
|
||||||
|
case FE_INEXACT: return "INEXACT";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "?????";
|
||||||
|
}
|
Loading…
Reference in a new issue