vendredi 19 août 2022

Own kind of system_error for Win32

Some time ago I mentioned here that system_category() doesn't have a name() method that translates the error-code according to the current thread's locale under Win32. I also wrote that in the Microsoft developer forum and they said that they will fix this except for WinRT apps.
So I wrote my own class xsystem_category but I'm not sure if I did everything correctly. Maybe someone here more experienced with the innards of exception-hanling in C++ will check that:

#include <Windows.h>
#include <iostream>
#include <system_error>

struct xsystem_category : public std::error_category
{
    xsystem_category() = default;
    xsystem_category( xsystem_category const & ) = delete;
    virtual ~xsystem_category() override = default;
    void operator =( xsystem_category const & ) = delete;
    virtual char const *name() const noexcept override;
    virtual std::error_condition default_error_condition( int code ) const noexcept override;
    virtual bool equivalent( int code, std::error_condition const &condition ) const noexcept override;
    virtual bool equivalent( std::error_code const &code, int condition ) const noexcept override;
    virtual std::string message( int condition ) const override;
};

char const *xsystem_category::name() const noexcept
{
    return "xsystem_category";
}

std::error_condition xsystem_category::default_error_condition( int code ) const noexcept
{
    return std::error_condition( code, xsystem_category() );
}

inline bool xsystem_category::equivalent( int code, std::error_condition const &condition ) const noexcept
{
    return default_error_condition( code ) == condition;
}

inline bool xsystem_category::equivalent( std::error_code const &code, int condition ) const noexcept
{
    return *this == code.category() && code.value() == condition;
}

std::string xsystem_category::message( int condition ) const
{
    using namespace std;
    LCID lcid = GetThreadLocale();
    string errStr( 64, '\0' );
    while( !FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, nullptr, condition, lcid, errStr.data(), (DWORD)errStr.size(), nullptr ) )
        if( DWORD dwFmErr = GetLastError(); dwFmErr == ERROR_INSUFFICIENT_BUFFER )
            errStr.resize( 2 * errStr.size(), '\0' );
        else
            throw system_error( (int)dwFmErr, system_category(), "FormatMessage() failed" );
    errStr.resize( strlen( errStr.data() ) );
    return errStr;
}

Aucun commentaire:

Enregistrer un commentaire