libc_error.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. //
  2. // $Id$
  3. //
  4. #include<__vic/error.h>
  5. #include<cstdio>
  6. #include<cstring>
  7. #if defined __linux__ || defined __FreeBSD__ || defined __sun || defined _AIX
  8. #include<string.h> // for strerror_r
  9. #define __VIC_USE_STRERROR_R 1
  10. #endif
  11. namespace __vic {
  12. #ifdef __VIC_USE_STRERROR_R
  13. namespace {
  14. //----------------------------------------------------------------------------
  15. // Redirector to POSIX-variant
  16. inline const char *call(int (*strerror_r)(int, char *, size_t),
  17. int errnum, char *buf, size_t buflen)
  18. {
  19. if(strerror_r(errnum, buf, buflen))
  20. {
  21. std::sprintf(buf, "strerror_r: <Couldn't get message for %d>", errnum);
  22. }
  23. buf[buflen - 1] = '\x0';
  24. return buf;
  25. }
  26. //----------------------------------------------------------------------------
  27. // Redirector to GNU-variant
  28. inline const char *call(char *(*strerror_r)(int, char *, size_t),
  29. int errnum, char *buf, size_t buflen)
  30. {
  31. return strerror_r(errnum, buf, buflen);
  32. }
  33. //----------------------------------------------------------------------------
  34. } // namespace
  35. #endif // __VIC_USE_STRERROR_R
  36. //----------------------------------------------------------------------------
  37. libc_error::libc_error(int no)
  38. : code_(no), formatted(false)
  39. {
  40. }
  41. //----------------------------------------------------------------------------
  42. libc_error::libc_error(const char *prompt, int no)
  43. : code_(no), formatted(false), msg(prompt)
  44. {
  45. }
  46. //----------------------------------------------------------------------------
  47. const char *libc_error::what() const noexcept
  48. {
  49. try
  50. {
  51. if(!formatted)
  52. {
  53. const char *err_msg;
  54. #ifdef __VIC_USE_STRERROR_R
  55. char err_msg_buf[256];
  56. err_msg = call(strerror_r, code(), err_msg_buf, sizeof err_msg_buf);
  57. #else // Windows, HP-UX, etc...
  58. err_msg = std::strerror(code());
  59. #endif
  60. if(msg.empty()) msg = err_msg;
  61. else
  62. {
  63. size_t n = std::strlen(msg) + std::strlen(err_msg) + 3; // 3 is ": " + '\0'
  64. readonly_cstring tmp;
  65. std::sprintf(tmp.reserve(n), "%s: %s",
  66. static_cast<const char *>(msg), err_msg);
  67. msg.swap(tmp);
  68. }
  69. formatted = true;
  70. }
  71. return msg;
  72. }
  73. catch(...)
  74. {
  75. return "libc_error::what(): <Couldn't format error message>";
  76. }
  77. }
  78. //----------------------------------------------------------------------------
  79. } // namespace