Created
March 9, 2013 03:02
-
-
Save eahydra/5122298 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef ERROR_CODE_HPP_ | |
#define ERROR_CODE_HPP_ | |
// define self error code | |
namespace base { | |
enum system_error_t { | |
kAccessDenied = ERROR_ACCESS_DENIED, | |
}; | |
class system_category_t : public std::error_category { | |
public: | |
system_category_t() { } | |
virtual ~system_category_t() { } | |
virtual const char *name() const throw() { | |
return "system error"; | |
} | |
virtual std::string message(int error_value) const { | |
char* msg = nullptr; | |
DWORD length = FormatMessageA( | |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, error_value, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, nullptr); | |
if (msg == nullptr) { | |
return std::string("unknown error"); | |
} | |
if (length && msg[length - 1] == '\n') | |
msg[--length] = '\0'; | |
if (length && msg[length - 1] == '\r') | |
msg[--length] = '\0'; | |
struct msg_deleter_t { | |
void operator()(void* addr) { | |
LocalFree(addr); | |
} | |
}; | |
std::unique_ptr<char, msg_deleter_t> msg_ptr(msg); | |
return std::string(msg); | |
} | |
// the function is used to resolve next problem: | |
// std::error_code errc; | |
// create_dir("c:\\windows\\sss", errc); | |
// if (errc == std::errc::permission_denied) { ... } | |
// when std::error_code compare with enum std::errc that it will be | |
// implicit conver std::permission_denied to std::error_condition. | |
// | |
virtual std::error_condition default_error_condition(int error_value) const throw() { | |
// you can optimize next switch to table-lookup | |
switch (error_value) | |
{ | |
case base::kAccessDenied: | |
return std::errc::permission_denied; | |
break; | |
default: | |
break; | |
} | |
return std::error_condition(error_value, *this); | |
} | |
}; | |
// used to resolve next problem: | |
// const std::error_category& cat1 = error_code.category(); | |
// const std::error_category& cat2 = error_code.category(); | |
// if (cat1 == cat2) { ...} | |
// | |
const std::error_category& base_system_category() { | |
static system_category_t category_; | |
return category_; | |
} | |
} | |
namespace std { | |
// used to implicit construct std::error_code | |
template<> | |
struct is_error_code_enum<base::system_error_t> : public true_type { }; | |
// used to construct std::error_code | |
// if you use implicit construct std::error_code, must implement the funtion. | |
error_code make_error_code(base::system_error_t error) { | |
return error_code(static_cast<int>(error), base::base_system_category()); | |
} | |
} | |
#if TEST | |
void test_system_error() { | |
auto create_dir = [=]()->std::error_code { | |
return std::make_error_code(base::system_error_t::kAccessDenied); | |
}; | |
std::error_code err = create_dir(); | |
std::cout<<"err message=["<<err.message()<<"]"<<std::endl; | |
// it will be implicit convert std::errc::permission_denied to std::error_code | |
if (err == std::errc::permission_denied) { | |
std::cout<<"err == std::errc::permission_denied"<<std::endl; | |
} | |
if (err == base::system_error_t::kAccessDenied) { | |
std::cout<<"err == base::system_error_t::kAccessDenied"<<std::endl; | |
} | |
// must implement convert base::io_error_t to base::system_error_t code. | |
// if (err == base::io_error_t::kXXXXX) | |
// std::cout<<"err == base::io_error_t::kXXXXX"<<std::endl; | |
} | |
#endif | |
#endif // ERROR_CODE_HPP_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment