diff --git a/src/error.cc b/src/error.cc index 9448836..5831a43 100644 --- a/src/error.cc +++ b/src/error.cc @@ -5,7 +5,7 @@ static const char* messages[] = { "Need to exit", "Bad command-line arguments", "Integer overflow", - "Standard error", + nullptr, /* standard error: call stderror */ "End of file", "libogg error", "Bad magic number", @@ -19,8 +19,10 @@ static const char* messages[] = { const char* ot::error_message(ot::status code) { -if (code >= ot::status::sentinel) - return nullptr; -auto index = static_cast(code); -return messages[index]; + if (code == ot::status::standard_error) + return strerror(errno); + if (code >= ot::status::sentinel) + return nullptr; + auto index = static_cast(code); + return messages[index]; } diff --git a/src/opustags.h b/src/opustags.h index 0639bb5..dbc3ab0 100644 --- a/src/opustags.h +++ b/src/opustags.h @@ -22,6 +22,8 @@ namespace ot { * The overflowing error family means that the end of packet was reached when attempting to read the * overflowing value. For example, overflowing_comment_count means that after reading the vendor * string, less than 4 bytes were left in the packet. + * + * When adding new status codes, make sure you update #error_message. */ enum class status { ok = 0, @@ -47,6 +49,14 @@ enum class status { sentinel, }; +/** + * Return an error message to show to user. + * + * For #ot::status::standard_error, the message is generated by strerror. + * + * The message is static, and must not be freed or modified. It is valid until the next call to + * #error_message, because of stderror. + */ const char* error_message(status code); /** diff --git a/t/error.cc b/t/error.cc index 3b5e555..bf58ada 100644 --- a/t/error.cc +++ b/t/error.cc @@ -9,6 +9,24 @@ static void check_message() throw failure("unexpected message for overflowing_comment_data"); } +static void check_errno() +{ + /* copy the messages in case strerror changes something */ + std::string got, expected; + + errno = EINVAL; + got = ot::error_message(ot::status::standard_error); + expected = strerror(errno); + if (got != expected) + throw failure("unexpected message for errno EINVAL"); + + errno = 0; + got = ot::error_message(ot::status::standard_error); + expected = strerror(errno); + if (got != expected) + throw failure("unexpected message for errno 0"); +} + static void check_sentinel() { if (ot::error_message(ot::status::sentinel) != nullptr) @@ -20,8 +38,9 @@ static void check_sentinel() int main() { - std::cout << "1..2\n"; + std::cout << "1..3\n"; run(check_message, "check a few error messages"); + run(check_errno, "check the message for standard errors"); run(check_sentinel, "ensure the sentinel is respected"); return 0; }