Skip to content

Instantly share code, notes, and snippets.

@eahydra
Created March 9, 2013 03:02
Show Gist options
  • Save eahydra/5122298 to your computer and use it in GitHub Desktop.
Save eahydra/5122298 to your computer and use it in GitHub Desktop.
#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