0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-25 23:14:13 +01:00

ircd::fpe: Add floating point environment suite; error scoping device.

This commit is contained in:
Jason Volk 2018-11-11 15:53:25 -08:00
parent c0de9b2e76
commit 6967ad1faa
6 changed files with 138 additions and 0 deletions

View file

@ -583,6 +583,7 @@ RB_CHK_SYSHEADER(functional, [FUNCTIONAL])
RB_CHK_SYSHEADER(algorithm, [ALGORITHM])
RB_CHK_SYSHEADER(numeric, [NUMERIC])
RB_CHK_SYSHEADER(cmath, [CMATH])
RB_CHK_SYSHEADER(cfenv, [CFENV])
RB_CHK_SYSHEADER(memory, [MEMORY])
RB_CHK_SYSHEADER(exception, [EXCEPTION])
RB_CHK_SYSHEADER(cerrno, [CERRNO])

34
include/ircd/fpe.h Normal file
View 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);
};

View file

@ -36,6 +36,7 @@ namespace ircd
#include "allocator.h"
#include "util/util.h"
#include "exception.h"
#include "fpe.h"
#include "demangle.h"
#include "localee.h"
#include "date.h"

View file

@ -59,6 +59,7 @@ extern "C"
#include <RB_INC_ALGORITHM
#include <RB_INC_NUMERIC
#include <RB_INC_CMATH
#include <RB_INC_CFENV
#include <RB_INC_MEMORY
#include <RB_INC_EXCEPTION
#include <RB_INC_SYSTEM_ERROR

View file

@ -91,6 +91,7 @@ libircd_la_SOURCES = \
allocator.cc \
exception.cc \
util.cc \
fpe.cc \
ios.cc \
lexical.cc \
tokens.cc \

100
ircd/fpe.cc Normal file
View 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 "?????";
}