From 2502c188629b08014eff1938ac80a70b5753f426 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sun, 3 Aug 2014 12:08:08 -0400 Subject: [PATCH] c++11 error_code for mpw errno --- mpw/CMakeLists.txt | 2 +- mpw/mpw_errno.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++++ mpw/mpw_errno.h | 34 ++++++- 3 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 mpw/mpw_errno.cpp diff --git a/mpw/CMakeLists.txt b/mpw/CMakeLists.txt index 2f59d5b..2174801 100644 --- a/mpw/CMakeLists.txt +++ b/mpw/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -g") add_definitions(-I ${CMAKE_SOURCE_DIR}/) -set(MPW_SRC mpw.cpp mpw_io.cpp mpw_close.cpp mpw_access.cpp mpw_ioctl.cpp +set(MPW_SRC mpw.cpp mpw_io.cpp mpw_close.cpp mpw_access.cpp mpw_ioctl.cpp mpw_errno.cpp environment.cpp) # add_custom_command( diff --git a/mpw/mpw_errno.cpp b/mpw/mpw_errno.cpp new file mode 100644 index 0000000..0271aa8 --- /dev/null +++ b/mpw/mpw_errno.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2014, Kelvin W Sherlock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include "mpw_errno.h" + +namespace MPW { + + namespace { + + + class __system_category : public std::error_category + { + public: + virtual const char* name() const noexcept; + virtual std::string message(int ev) const; + virtual std::error_condition default_error_condition(int ev) const noexcept; + + private: + static int remap(mpw_errno e); + + }; + + + const char *__system_category::name() const noexcept + { + return "mpw/errno"; + } + + std::string __system_category::message(int ev) const + { + + switch (ev) + { + case kEPERM: return "Permission denied"; + case kENOENT: return "No such file or directory"; + case kENORSRC: return "No such resource"; + case kEINTR: return "Interrupted system service"; + case kEIO: return "I/O error"; + case kENXIO: return "No such device or address"; + case kE2BIG: return "Argument list too long"; + case kENOEXEC: return "Exec format error"; + case kEBADF: return "Bad file number"; + case kECHILD: return "No children processes"; + case kEAGAIN: return "Resource temporarily unavailable, try again later"; + case kENOMEM: return "Not enough space"; + case kEACCES: return "Permission denied"; + case kEFAULT: return "Bad address"; + case kENOTBLK: return "Block device required"; + case kEBUSY: return "Device or resource busy"; + case kEEXIST: return "File exists"; + case kEXDEV: return "Cross-device link"; + case kENODEV: return "No such device"; + case kENOTDIR: return "Not a directory"; + case kEISDIR: return "Is a directory"; + case kEINVAL: return "Invalid argument"; + case kENFILE: return "File table overflow"; + case kEMFILE: return "Too many open files"; + case kENOTTY: return "Not a character device"; + case kETXTBSY: return "Text file busy"; + case kEFBIG: return "File too large"; + case kENOSPC: return "No space left on device"; + case kESPIPE: return "Illegal seek"; + case kEROFS: return "Read only file system"; + case kEMLINK: return "Too many links"; + case kEPIPE: return "Broken pipe"; + case kEDOM: return "Math arg out of domain of func"; + case kERANGE: return "Math result not representable"; + } + + std::string tmp("Unknown error: "); + tmp += std::to_string(ev); + return tmp; + } + + std::error_condition __system_category::default_error_condition(int ev) const noexcept + { + + int x = remap(static_cast(ev)); + if (x >= 0) return std::error_condition(x, std::generic_category()); + + return std::error_condition(ev, mpw_system_category()); + } + + int __system_category::remap(mpw_errno e) + { + switch(e) + { + case kEPERM: return EPERM; + case kENOENT: return ENOENT; + #ifdef ENORSRC + case kENORSRC: return ENORSRC; + #endif + case kEINTR: return EINTR; + case kEIO: return EIO; + case kENXIO: return ENXIO; + case kE2BIG: return E2BIG; + case kENOEXEC: return ENOEXEC; + case kEBADF: return EBADF; + case kECHILD: return ECHILD; + case kEAGAIN: return EAGAIN; + case kENOMEM: return ENOMEM; + case kEACCES: return EACCES; + case kEFAULT: return EFAULT; + case kENOTBLK: return ENOTBLK; + case kEBUSY: return EBUSY; + case kEEXIST: return EEXIST; + case kEXDEV: return EXDEV; + case kENODEV: return ENODEV; + case kENOTDIR: return ENOTDIR; + case kEISDIR: return EISDIR; + case kEINVAL: return EINVAL; + case kENFILE: return ENFILE; + case kEMFILE: return EMFILE; + case kENOTTY: return ENOTTY; + case kETXTBSY: return ETXTBSY; + case kEFBIG: return EFBIG; + case kENOSPC: return ENOSPC; + case kESPIPE: return ESPIPE; + case kEROFS: return EROFS; + case kEMLINK: return EMLINK; + case kEPIPE: return EPIPE; + case kEDOM: return EDOM; + case kERANGE: return ERANGE; + + default: return -1; + } + + } + + } + + const std::error_category& mpw_system_category() + { + static __system_category s; + return s; + } + + + mpw_errno mpw_errno_from_errno() + { + return mpw_errno_from_errno(errno); + } + + mpw_errno mpw_errno_from_errno(int error) + { + + switch(error) + { + case 0: return static_cast(0); + + case EPERM: return kEPERM; + case ENOENT: return kENOENT; + + #ifdef ENORSRC + case ENORSRC: return kENORSRC; + #endif + + case EINTR: return kEINTR; + case EIO: return kEIO; + case ENXIO: return kENXIO; + case E2BIG: return kE2BIG; + case ENOEXEC: return kENOEXEC; + case EBADF: return kEBADF; + case ECHILD: return kECHILD; + case EAGAIN: return kEAGAIN; + case ENOMEM: return kENOMEM; + case EACCES: return kEACCES; + case EFAULT: return kEFAULT; + case ENOTBLK: return kENOTBLK; + case EBUSY: return kEBUSY; + case EEXIST: return kEEXIST; + case EXDEV: return kEXDEV; + case ENODEV: return kENODEV; + case ENOTDIR: return kENOTDIR; + case EISDIR: return kEISDIR; + case EINVAL: return kEINVAL; + case ENFILE: return kENFILE; + case EMFILE: return kEMFILE; + case ENOTTY: return kENOTTY; + case ETXTBSY: return kETXTBSY; + case EFBIG: return kEFBIG; + case ENOSPC: return kENOSPC; + case ESPIPE: return kESPIPE; + case EROFS: return kEROFS; + case EMLINK: return kEMLINK; + case EPIPE: return kEPIPE; + case EDOM: return kEDOM; + case ERANGE: return kERANGE; + + default: + return kEINVAL; + } + + + } + + +} diff --git a/mpw/mpw_errno.h b/mpw/mpw_errno.h index 118a356..dba0266 100644 --- a/mpw/mpw_errno.h +++ b/mpw/mpw_errno.h @@ -1,10 +1,12 @@ #ifndef __mpw_errno_h__ #define __mpw_errno_h__ +#include + namespace MPW { // from MPW errno.h - enum { + enum mpw_errno { kEPERM = 1, /* Permission denied */ kENOENT = 2, /* No such file or directory */ kENORSRC = 3, /* No such resource */ @@ -41,6 +43,34 @@ namespace MPW { kERANGE = 34, /* Math result not representable */ }; + + mpw_errno mpw_errno_from_errno(); + mpw_errno mpw_errno_from_errno(int error); + + // c++11 error stuff + const std::error_category& mpw_system_category(); + + inline std::error_code make_error_code(mpw_errno e) noexcept + { + return std::error_code(static_cast(e), mpw_system_category()); + } + + inline std::error_condition make_error_condition(mpw_errno e) noexcept + { + return std::error_condition(static_cast(e), mpw_system_category()); + } + + + } -#endif \ No newline at end of file +namespace std { + + template<> + struct is_error_code_enum : public true_type {}; + + template<> + struct is_error_condition_enum : public true_type {}; +} + +#endif