diff options
author | Max Kellermann <max@duempel.org> | 2015-12-18 09:50:48 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2015-12-18 09:53:02 +0100 |
commit | e939d667d9cbe459add98790c5c8b92d6aa5fa36 (patch) | |
tree | abb4fda3a28dd153439ccb544fabed33a2c438f1 /src/protocol | |
parent | 8bb5a565cd9060b3b98bb7b9853fe99703fc18da (diff) |
protocol/Ack: add exception class wrapping enum ack
Diffstat (limited to 'src/protocol')
-rw-r--r-- | src/protocol/Ack.hxx | 25 | ||||
-rw-r--r-- | src/protocol/ArgParser.cxx | 218 | ||||
-rw-r--r-- | src/protocol/ArgParser.hxx | 51 |
3 files changed, 142 insertions, 152 deletions
diff --git a/src/protocol/Ack.hxx b/src/protocol/Ack.hxx index c8457c5b4..d2d0c0aa0 100644 --- a/src/protocol/Ack.hxx +++ b/src/protocol/Ack.hxx @@ -20,6 +20,10 @@ #ifndef MPD_ACK_H #define MPD_ACK_H +#include <stdexcept> + +#include <stdio.h> + class Domain; enum ack { @@ -40,4 +44,25 @@ enum ack { extern const Domain ack_domain; +class ProtocolError : public std::runtime_error { + enum ack code; + +public: + ProtocolError(enum ack _code, const char *msg) + :std::runtime_error(msg), code(_code) {} + + enum ack GetCode() const { + return code; + } +}; + +template<typename... Args> +static inline ProtocolError +FormatProtocolError(enum ack code, const char *fmt, Args&&... args) noexcept +{ + char buffer[256]; + snprintf(buffer, sizeof(buffer), fmt, std::forward<Args>(args)...); + return ProtocolError(code, buffer); +} + #endif diff --git a/src/protocol/ArgParser.cxx b/src/protocol/ArgParser.cxx index 31756f53e..29266a387 100644 --- a/src/protocol/ArgParser.cxx +++ b/src/protocol/ArgParser.cxx @@ -19,199 +19,155 @@ #include "config.h" #include "ArgParser.hxx" +#include "Ack.hxx" #include "Chrono.hxx" -#include "client/Response.hxx" #include <stdlib.h> -bool -ParseCommandArg32(Response &r, uint32_t &value_r, const char *s) +uint32_t +ParseCommandArgU32(const char *s) { char *test; + auto value = strtoul(s, &test, 10); + if (test == s || *test != '\0') + throw FormatProtocolError(ACK_ERROR_ARG, + "Integer expected: %s", s); - value_r = strtoul(s, &test, 10); - if (test == s || *test != '\0') { - r.FormatError(ACK_ERROR_ARG, "Integer expected: %s", s); - return false; - } - return true; + return value; } -bool -ParseCommandArg(Response &r, int &value_r, const char *s, - int min_value, int max_value) +int +ParseCommandArgInt(const char *s, int min_value, int max_value) { char *test; - long value; + auto value = strtol(s, &test, 10); + if (test == s || *test != '\0') + throw FormatProtocolError(ACK_ERROR_ARG, + "Integer expected: %s", s); - value = strtol(s, &test, 10); - if (test == s || *test != '\0') { - r.FormatError(ACK_ERROR_ARG, "Integer expected: %s", s); - return false; - } + if (value < min_value || value > max_value) + throw FormatProtocolError(ACK_ERROR_ARG, + "Number too large: %s", s); - if (value < min_value || value > max_value) { - r.FormatError(ACK_ERROR_ARG, "Number too large: %s", s); - return false; - } - - value_r = (int)value; - return true; + return (int)value; } -bool -ParseCommandArg(Response &r, int &value_r, const char *s) +int +ParseCommandArgInt(const char *s) { - return ParseCommandArg(r, value_r, s, - std::numeric_limits<int>::min(), - std::numeric_limits<int>::max()); + return ParseCommandArgInt(s, + std::numeric_limits<int>::min(), + std::numeric_limits<int>::max()); } -bool -ParseCommandArg(Response &r, RangeArg &value_r, const char *s) +RangeArg +ParseCommandArgRange(const char *s) { char *test, *test2; - long value; - - value = strtol(s, &test, 10); - if (test == s || (*test != '\0' && *test != ':')) { - r.FormatError(ACK_ERROR_ARG, - "Integer or range expected: %s", s); - return false; - } + auto value = strtol(s, &test, 10); + if (test == s || (*test != '\0' && *test != ':')) + throw FormatProtocolError(ACK_ERROR_ARG, + "Integer or range expected: %s", s); - if (value == -1 && *test == 0) { + if (value == -1 && *test == 0) /* compatibility with older MPD versions: specifying "-1" makes MPD display the whole list */ - value_r.start = 0; - value_r.end = std::numeric_limits<int>::max(); - return true; - } + return RangeArg::All(); - if (value < 0) { - r.FormatError(ACK_ERROR_ARG, "Number is negative: %s", s); - return false; - } + if (value < 0) + throw FormatProtocolError(ACK_ERROR_ARG, + "Number is negative: %s", s); - if (unsigned(value) > std::numeric_limits<unsigned>::max()) { - r.FormatError(ACK_ERROR_ARG, "Number too large: %s", s); - return false; - } + if (unsigned(value) > std::numeric_limits<unsigned>::max()) + throw FormatProtocolError(ACK_ERROR_ARG, + "Number too large: %s", s); - value_r.start = (unsigned)value; + RangeArg range; + range.start = (unsigned)value; if (*test == ':') { value = strtol(++test, &test2, 10); - if (*test2 != '\0') { - r.FormatError(ACK_ERROR_ARG, - "Integer or range expected: %s", s); - return false; - } + if (*test2 != '\0') + throw FormatProtocolError(ACK_ERROR_ARG, + "Integer or range expected: %s", + s); if (test == test2) value = std::numeric_limits<int>::max(); - if (value < 0) { - r.FormatError(ACK_ERROR_ARG, - "Number is negative: %s", s); - return false; - } + if (value < 0) + throw FormatProtocolError(ACK_ERROR_ARG, + "Number is negative: %s", s); - if (unsigned(value) > std::numeric_limits<unsigned>::max()) { - r.FormatError(ACK_ERROR_ARG, - "Number too large: %s", s); - return false; - } + if (unsigned(value) > std::numeric_limits<unsigned>::max()) + throw FormatProtocolError(ACK_ERROR_ARG, + "Number too large: %s", s); - value_r.end = (unsigned)value; + range.end = (unsigned)value; } else { - value_r.end = (unsigned)value + 1; + range.end = (unsigned)value + 1; } - return true; + return range; } -bool -ParseCommandArg(Response &r, unsigned &value_r, const char *s, - unsigned max_value) +unsigned +ParseCommandArgUnsigned(const char *s, unsigned max_value) { - unsigned long value; char *endptr; + auto value = strtoul(s, &endptr, 10); + if (endptr == s || *endptr != 0) + throw FormatProtocolError(ACK_ERROR_ARG, + "Integer expected: %s", s); - value = strtoul(s, &endptr, 10); - if (endptr == s || *endptr != 0) { - r.FormatError(ACK_ERROR_ARG, "Integer expected: %s", s); - return false; - } - - if (value > max_value) { - r.FormatError(ACK_ERROR_ARG, - "Number too large: %s", s); - return false; - } + if (value > max_value) + throw FormatProtocolError(ACK_ERROR_ARG, + "Number too large: %s", s); - value_r = (unsigned)value; - return true; + return (unsigned)value; } -bool -ParseCommandArg(Response &r, unsigned &value_r, const char *s) +unsigned +ParseCommandArgUnsigned(const char *s) { - return ParseCommandArg(r, value_r, s, - std::numeric_limits<unsigned>::max()); + return ParseCommandArgUnsigned(s, + std::numeric_limits<unsigned>::max()); } bool -ParseCommandArg(Response &r, bool &value_r, const char *s) +ParseCommandArgBool(const char *s) { - long value; char *endptr; + auto value = strtol(s, &endptr, 10); + if (endptr == s || *endptr != 0 || (value != 0 && value != 1)) + throw FormatProtocolError(ACK_ERROR_ARG, + "Boolean (0/1) expected: %s", s); - value = strtol(s, &endptr, 10); - if (endptr == s || *endptr != 0 || (value != 0 && value != 1)) { - r.FormatError(ACK_ERROR_ARG, - "Boolean (0/1) expected: %s", s); - return false; - } - - value_r = !!value; - return true; + return !!value; } -bool -ParseCommandArg(Response &r, float &value_r, const char *s) +float +ParseCommandArgFloat(const char *s) { - float value; char *endptr; + auto value = strtof(s, &endptr); + if (endptr == s || *endptr != 0) + throw FormatProtocolError(ACK_ERROR_ARG, + "Float expected: %s", s); - value = strtof(s, &endptr); - if (endptr == s || *endptr != 0) { - r.FormatError(ACK_ERROR_ARG, "Float expected: %s", s); - return false; - } - - value_r = value; - return true; + return value; } -bool -ParseCommandArg(Response &r, SongTime &value_r, const char *s) +SongTime +ParseCommandArgSongTime(const char *s) { - float value; - bool success = ParseCommandArg(r, value, s) && value >= 0; - if (success) - value_r = SongTime::FromS(value); - - return success; + auto value = ParseCommandArgFloat(s); + return SongTime::FromS(value); } -bool -ParseCommandArg(Response &r, SignedSongTime &value_r, const char *s) +SignedSongTime +ParseCommandArgSignedSongTime(const char *s) { - float value; - bool success = ParseCommandArg(r, value, s); - if (success) - value_r = SignedSongTime::FromS(value); - - return success; + auto value = ParseCommandArgFloat(s); + return SongTime::FromS(value); } diff --git a/src/protocol/ArgParser.hxx b/src/protocol/ArgParser.hxx index f60dbdf50..83c9934b0 100644 --- a/src/protocol/ArgParser.hxx +++ b/src/protocol/ArgParser.hxx @@ -21,6 +21,7 @@ #define MPD_PROTOCOL_ARGPARSER_HXX #include "check.h" +#include "Compiler.h" #include <limits> @@ -30,15 +31,17 @@ class Response; class SongTime; class SignedSongTime; -bool -ParseCommandArg32(Response &r, uint32_t &value_r, const char *s); +gcc_pure +uint32_t +ParseCommandArgU32(const char *s); -bool -ParseCommandArg(Response &r, int &value_r, const char *s, - int min_value, int max_value); +gcc_pure +int +ParseCommandArgInt(const char *s, int min_value, int max_value); -bool -ParseCommandArg(Response &r, int &value_r, const char *s); +gcc_pure +int +ParseCommandArgInt(const char *s); struct RangeArg { unsigned start, end; @@ -53,26 +56,32 @@ struct RangeArg { } }; -bool -ParseCommandArg(Response &r, RangeArg &value_r, const char *s); +gcc_pure +RangeArg +ParseCommandArgRange(const char *s); -bool -ParseCommandArg(Response &r, unsigned &value_r, const char *s, - unsigned max_value); +gcc_pure +unsigned +ParseCommandArgUnsigned(const char *s, unsigned max_value); -bool -ParseCommandArg(Response &r, unsigned &value_r, const char *s); +gcc_pure +unsigned +ParseCommandArgUnsigned(const char *s); +gcc_pure bool -ParseCommandArg(Response &r, bool &value_r, const char *s); +ParseCommandArgBool(const char *s); -bool -ParseCommandArg(Response &r, float &value_r, const char *s); +gcc_pure +float +ParseCommandArgFloat(const char *s); -bool -ParseCommandArg(Response &r, SongTime &value_r, const char *s); +gcc_pure +SongTime +ParseCommandArgSongTime(const char *s); -bool -ParseCommandArg(Response &r, SignedSongTime &value_r, const char *s); +gcc_pure +SignedSongTime +ParseCommandArgSignedSongTime(const char *s); #endif |