From abfc3c787865a394864eb250c9087ffb516615d6 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 18 Dec 2017 15:46:52 +1100 Subject: [PATCH] except: move posix/win32 exceptions to own units --- posix/except.cpp | 99 +++++++++++++++++++++++++++++++++++++++ posix/except.hpp | 55 ++++++++++++++++++++++ win32/except.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++++ win32/except.hpp | 47 +++++++++++++++++++ 4 files changed, 320 insertions(+) create mode 100644 posix/except.cpp create mode 100644 posix/except.hpp create mode 100644 win32/except.cpp create mode 100644 win32/except.hpp diff --git a/posix/except.cpp b/posix/except.cpp new file mode 100644 index 00000000..40b73638 --- /dev/null +++ b/posix/except.cpp @@ -0,0 +1,99 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2010, 2017, + * Danny Robson + */ + +#include "except.hpp" + +#include "../debug.hpp" + +#include + +using util::posix::error; + + +/////////////////////////////////////////////////////////////////////////////// +/// Construct an exception object from a given error value. +/// +/// The error value MUST be an error at construction time. +error::error (int _code): + std::runtime_error (::strerror (_code)), + m_code (_code) +{ + CHECK_NEQ (_code, 0); +} + + +///---------------------------------------------------------------------------- +/// Construct an exception object from the current value of errno. +/// +/// errno MUST signal an error at construction time. +error::error (): + error (last_code ()) +{ + CHECK_NEQ (m_code, 0); +} + + +/////////////////////////////////////////////////////////////////////////////// +int +error::last_code (void) +{ + return errno; +} + + +//----------------------------------------------------------------------------- +int +error::code (void) const +{ + return m_code; +} + + +/////////////////////////////////////////////////////////////////////////////// +/// Throw an exception object if errno currently signals an error. +void +error::try_code (void) +{ + try_code (last_code ()); +} + + +///---------------------------------------------------------------------------- +/// Throw an exception object if 'code' represents an error. +void +error::try_code (int code) +{ + if (__builtin_expect (code != 0, false)) + throw error (code); +} + + +///---------------------------------------------------------------------------- +void +error::throw_code (void) +{ + throw_code (last_code ()); +} + + +///---------------------------------------------------------------------------- +void +error::throw_code (int code) +{ + CHECK_NEQ (code, 0); + throw error (code); +} diff --git a/posix/except.hpp b/posix/except.hpp new file mode 100644 index 00000000..a9a6ce8e --- /dev/null +++ b/posix/except.hpp @@ -0,0 +1,55 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2010, 2017, + * Danny Robson + */ + +#ifndef CRUFT_UTIL_POSIX_EXCEPT_HPP +#define CRUFT_UTIL_POSIX_EXCEPT_HPP + +#include + +namespace util::posix { + /// An exception class used for reporting errors signalled by errno. + /// + /// Ideally this would be named `errno' but that symbol is permitted to + /// be a macro and significantly complicates symbol resolution either way. + class error : public std::runtime_error { + public: + explicit error (int code); + error (); + + int code (void) const; + static int last_code (void); + + static void try_code (void); + static void try_code (int code); + + static void throw_code [[gnu::noreturn]] (void); + static void throw_code [[gnu::noreturn]] (int code); + + template + static T try_value (T value) + { + if (value < 0) + throw_code (); + return value; + } + + private: + int m_code; + }; +} + +#endif diff --git a/win32/except.cpp b/win32/except.cpp new file mode 100644 index 00000000..9b92673c --- /dev/null +++ b/win32/except.cpp @@ -0,0 +1,119 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2010, 2017 + * Danny Robson + */ + +#include "except.hpp" + +#include "../debug.hpp" + +using util::win32::error; + + +/////////////////////////////////////////////////////////////////////////////// +error::error (DWORD _code): + runtime_error (code_string (_code)), + m_code (_code) +{ + CHECK_NEQ (m_code, (DWORD)ERROR_SUCCESS); +} + + +//----------------------------------------------------------------------------- +error::error (void): + error (last_code ()) +{ ; } + + +/////////////////////////////////////////////////////////////////////////////// +DWORD +error::code (void) const +{ + return m_code; +} + + +//----------------------------------------------------------------------------- +DWORD +error::last_code (void) +{ + return GetLastError (); +} + + +/////////////////////////////////////////////////////////////////////////////// +void +error::try_code (void) +{ + try_code (last_code ()); +} + + +//----------------------------------------------------------------------------- +void +error::try_code (DWORD id) +{ + if (__builtin_expect (id != ERROR_SUCCESS, false)) + throw_code (id); +} + + +//----------------------------------------------------------------------------- +void +error::throw_code (void) +{ + throw_code (last_code ()); +} + + +//----------------------------------------------------------------------------- +void +error::throw_code (DWORD code) +{ + CHECK_NEQ (code, (DWORD)ERROR_SUCCESS); + throw error (code); +} + + +//----------------------------------------------------------------------------- +std::string +error::code_string (void) +{ + return code_string (last_code ()); +} + + +//----------------------------------------------------------------------------- +std::string +error::code_string (DWORD code) +{ + char message[256]; + + auto res = FormatMessage ( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + code, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + message, + std::size (message), + NULL + ); + + if (res == 0) { + error::throw_code (); + } + + return std::string (message, message + res); +} diff --git a/win32/except.hpp b/win32/except.hpp new file mode 100644 index 00000000..5d43ac82 --- /dev/null +++ b/win32/except.hpp @@ -0,0 +1,47 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2010, 2017 + * Danny Robson + */ + +#ifndef CRUFT_UTIL_WIN32_EXCEPT_HPP +#define CRUFT_UTIL_WIN32_EXCEPT_HPP + +#include +#include + +namespace util::win32 { + class error : public std::runtime_error { + public: + explicit error (DWORD _code); + error (); + + DWORD code (void) const; + static DWORD last_code (void); + + static void try_code (void); + static void try_code (DWORD); + + static void throw_code [[gnu::noreturn]] (void); + static void throw_code [[gnu::noreturn]] (DWORD); + + static std::string code_string (void); + static std::string code_string (DWORD); + + private: + DWORD m_code; + }; +} + +#endif