[ create a new paste ] login | about

Link: http://codepad.org/pdQ6NKGQ    [ raw code | fork ]

C++, pasted on Sep 6:
#pragma once
// Copyright (c) 2011, Alf P. Steinbach

#ifdef  _MSC_VER
#   pragma warning( disable: 4373 )     // "hey, previous versions of compiler had more bugs"
#   pragma warning( disable: 4100 )     // Unreferenced formal parameter
#endif

//-------------------------------------------------- Dependencies:

#include <progrock/compiler_specific/fixups.h>      // CPPX_NOEXCEPT

#include <progrock/cppx/error_handling.h>           // cppx::throwX etc.
#include <progrock/cppx/string_building.h>          // S
#include <progrock/winapi/wrapper/windows_h.h>

#include <system_error>


//-------------------------------------------------- Interface:

#ifndef     CPPX_NOEXCEPT
#   define  CPPX_NOEXCEPT   noexcept
#endif

namespace progrock{ namespace winapi{
    using std::string;

    typedef DWORD               ErrorCode;
    typedef cppx::narrow::S     NarrowS;
    typedef unsigned char       UChar;

    namespace errorMessage {
        inline string fromApi( ErrorCode const code )
        {
            struct RawMessage
            {
                char const* p;
                RawMessage(): p(0) {}
                ~RawMessage() { ::LocalFree( const_cast<char*>( p ) ); }
            };

            RawMessage  message;
            int const stringLength    = FormatMessageA(
                0   | FORMAT_MESSAGE_ALLOCATE_BUFFER
                    | FORMAT_MESSAGE_FROM_SYSTEM
                    | FORMAT_MESSAGE_IGNORE_INSERTS,
                0,              // lpSource
                code,
                MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
                reinterpret_cast<char*>( &message.p ),
                0,              // nSize
                0
                );

            // Just in case message.p isn't set:
            if( stringLength == 0 ) { return ""; }

            // Remove trailing CR and LF control chars:
            char const* pEnd    = message.p + stringLength;
            for( ;; )
            {
                if( pEnd == message.p ) { break; }
                if( static_cast<UChar>( *(pEnd - 1) ) >= ' ' ) { break; }
                --pEnd;
            }
            return string( message.p, pEnd );
        }

        inline string withCode( ErrorCode const code, string const& text )
        {
            return NarrowS() << text << " (code " << code << ")";
        }

        inline string forUnknown( ErrorCode const code )
        {
            return errorMessage::withCode( code, "Unknown error" );
        }

        inline string explaining( ErrorCode const code )
        {
            if( code == 0 )
            {
                // ERROR_SUCCESS.
                // Instead of "The operation completed successfully.":
                return errorMessage::forUnknown( code );
            }
    
            string const    rawMessage  = fromApi( code );
            if( rawMessage.length() == 0 )
            {
                return errorMessage::forUnknown( code );
            }

            return errorMessage::withCode( code, rawMessage );
        }
    }    // namespace errorMessage

    class ErrorCategory
        : public std::error_category
    {
    public:
        virtual const char* name() const CPPX_NOEXCEPT
        {
            return "WinApiError";
        }
    
        virtual std::error_condition default_error_condition( int const code ) const CPPX_NOEXCEPT
        {
            return std::error_condition( code, *this );
        }

        virtual string message( int const code ) const
        {
            return errorMessage::explaining( code );
        }
    };

    inline std::error_category const& errorCategory()
    {
        static ErrorCategory const    theInstance;
        return theInstance;
    }

    class Error
        : public std::system_error
    {
    private:
        mutable std::string fullDescription_;

    public:
        char const* what() const CPPX_NOEXCEPT
        {
            if( fullDescription_.length() == 0 )
            {
                fullDescription_ = NarrowS()
                    << std::system_error::what() << ": " << code().message()
                    << NarrowS::toString;
            }
            return fullDescription_.c_str();
        }

        Error( int const code, std::string const& description )
            : std::system_error(
                std::error_code( code, ErrorCategory() ),
                description
                )
        {}
    
        virtual ~Error() CPPX_NOEXCEPT {}
    };

    inline HRESULT hResultFrom( std::system_error const& x )
    {
        std::error_code const&  error   = x.code();

        if( error.category() != winapi::errorCategory() )
        {
            return E_FAIL;
        }
        return HRESULT_FROM_WIN32( error.value() );     // Deals OK with HRESULT.
    }

    inline HRESULT hResultFromX()
    {
        try { throw; }
        catch( std::system_error const& x ) { return hResultFrom( x ); }
        catch( ... ) {}
        return E_FAIL;
    }

    inline bool throwX( ErrorCode const errorCode, string const& s )
    {
        throw Error( errorCode, s );
    }

} }  // namespace progrock::winapi


Create a new paste based on this one


Comments: