diff options
author | Max Kellermann <max@duempel.org> | 2015-12-16 11:34:26 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2015-12-16 11:34:26 +0100 |
commit | 51168169e73528d388b39b826afe1df3370bd10a (patch) | |
tree | f0fcdd175e57a03365b3d3522dd9f50a69f75d0d /src | |
parent | d256a0e98f587c0af714c74038ff75903c0903fe (diff) |
util/Tokenizer: use std::runtime_error on syntax error
Diffstat (limited to 'src')
-rw-r--r-- | src/command/AllCommands.cxx | 48 | ||||
-rw-r--r-- | src/config/ConfigFile.cxx | 65 | ||||
-rw-r--r-- | src/util/Tokenizer.cxx | 64 | ||||
-rw-r--r-- | src/util/Tokenizer.hxx | 44 |
4 files changed, 80 insertions, 141 deletions
diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx index 9dd1b0a94..8cc8f40c5 100644 --- a/src/command/AllCommands.cxx +++ b/src/command/AllCommands.cxx @@ -361,7 +361,7 @@ command_checked_lookup(Response &r, unsigned permission, CommandResult command_process(Client &client, unsigned num, char *line) -{ +try { Response r(client, num); Error error; @@ -371,13 +371,17 @@ command_process(Client &client, unsigned num, char *line) Tokenizer tokenizer(line); - const char *const cmd_name = tokenizer.NextWord(error); - if (cmd_name == nullptr) { - if (tokenizer.IsEnd()) - r.FormatError(ACK_ERROR_UNKNOWN, "No command given"); - else - r.Error(ACK_ERROR_UNKNOWN, error.GetMessage()); - + const char *cmd_name; + try { + cmd_name = tokenizer.NextWord(); + if (cmd_name == nullptr) { + r.Error(ACK_ERROR_UNKNOWN, "No command given"); + /* this client does not speak the MPD + protocol; kick the connection */ + return CommandResult::FINISH; + } + } catch (const std::exception &e) { + r.Error(ACK_ERROR_UNKNOWN, e.what()); /* this client does not speak the MPD protocol; kick the connection */ return CommandResult::FINISH; @@ -394,14 +398,9 @@ command_process(Client &client, unsigned num, char *line) return CommandResult::ERROR; } - char *a = tokenizer.NextParam(error); - if (a == nullptr) { - if (tokenizer.IsEnd()) - break; - - r.Error(ACK_ERROR_UNKNOWN, error.GetMessage()); - return CommandResult::ERROR; - } + char *a = tokenizer.NextParam(); + if (a == nullptr) + break; argv[args.size++] = a; } @@ -412,14 +411,13 @@ command_process(Client &client, unsigned num, char *line) command_checked_lookup(r, client.GetPermission(), cmd_name, args); - try { - CommandResult ret = cmd - ? cmd->handler(client, args, r) - : CommandResult::ERROR; + CommandResult ret = cmd + ? cmd->handler(client, args, r) + : CommandResult::ERROR; - return ret; - } catch (const std::exception &e) { - PrintError(r, e); - return CommandResult::ERROR; - } + return ret; +} catch (const std::exception &e) { + Response r(client, num); + PrintError(r, e); + return CommandResult::ERROR; } diff --git a/src/config/ConfigFile.cxx b/src/config/ConfigFile.cxx index 4a33efee8..844dc5bb9 100644 --- a/src/config/ConfigFile.cxx +++ b/src/config/ConfigFile.cxx @@ -41,26 +41,17 @@ static constexpr char CONF_COMMENT = '#'; static constexpr Domain config_file_domain("config_file"); -static bool -config_read_name_value(ConfigBlock &block, char *input, unsigned line, - Error &error) +static void +config_read_name_value(ConfigBlock &block, char *input, unsigned line) { Tokenizer tokenizer(input); - const char *name = tokenizer.NextWord(error); - if (name == nullptr) { - assert(!tokenizer.IsEnd()); - return false; - } + const char *name = tokenizer.NextWord(); + assert(name != nullptr); - const char *value = tokenizer.NextString(error); - if (value == nullptr) { - if (tokenizer.IsEnd()) - throw std::runtime_error("Value missing"); - - assert(error.IsDefined()); - return false; - } + const char *value = tokenizer.NextString(); + if (value == nullptr) + throw std::runtime_error("Value missing"); if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) throw std::runtime_error("Unknown tokens after value"); @@ -71,7 +62,6 @@ config_read_name_value(ConfigBlock &block, char *input, unsigned line, name, bp->line); block.AddBlockParam(name, value, line); - return true; } static ConfigBlock * @@ -104,13 +94,8 @@ try { /* parse name and value */ - if (!config_read_name_value(*block, line, - reader.GetLineNumber(), - error)) { - assert(*line != 0); - error.FormatPrefix("line %u: ", reader.GetLineNumber()); - return nullptr; - } + config_read_name_value(*block, line, + reader.GetLineNumber()); } } catch (...) { std::throw_with_nested(FormatRuntimeError("Error in line %u", reader.GetLineNumber())); @@ -179,11 +164,10 @@ Append(config_param *&head, config_param *p) *i = p; } -static bool +static void ReadConfigParam(ConfigData &config_data, BufferedReader &reader, const char *name, ConfigOption o, - Tokenizer &tokenizer, - Error &error) + Tokenizer &tokenizer) { const unsigned i = unsigned(o); const ConfigTemplate &option = config_param_templates[i]; @@ -199,15 +183,10 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader, /* now parse the block or the value */ - const char *value = tokenizer.NextString(error); - if (value == nullptr) { - if (tokenizer.IsEnd()) - throw FormatRuntimeError("line %u: Value missing", - reader.GetLineNumber()); - - error.FormatPrefix("line %u: ", reader.GetLineNumber()); - return false; - } + const char *value = tokenizer.NextString(); + if (value == nullptr) + throw FormatRuntimeError("line %u: Value missing", + reader.GetLineNumber()); if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) throw FormatRuntimeError("line %u: Unknown tokens after value", @@ -215,7 +194,6 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader, auto *param = new config_param(value, reader.GetLineNumber()); Append(head, param); - return true; } static bool @@ -234,12 +212,8 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error) by either the value or '{' */ Tokenizer tokenizer(line); - const char *name = tokenizer.NextWord(error); - if (name == nullptr) { - assert(!tokenizer.IsEnd()); - error.FormatPrefix("line %u: ", reader.GetLineNumber()); - return false; - } + const char *name = tokenizer.NextWord(); + assert(name != nullptr); /* get the definition of that option, and check the "repeatable" flag */ @@ -247,9 +221,8 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error) const ConfigOption o = ParseConfigOptionName(name); ConfigBlockOption bo; if (o != ConfigOption::MAX) { - if (!ReadConfigParam(config_data, reader, name, o, - tokenizer, error)) - return false; + ReadConfigParam(config_data, reader, name, o, + tokenizer); } else if ((bo = ParseConfigBlockOptionName(name)) != ConfigBlockOption::MAX) { if (!ReadConfigBlock(config_data, reader, name, bo, tokenizer, error)) diff --git a/src/util/Tokenizer.cxx b/src/util/Tokenizer.cxx index 19322b70d..e065ab6e0 100644 --- a/src/util/Tokenizer.cxx +++ b/src/util/Tokenizer.cxx @@ -31,10 +31,8 @@ #include "Tokenizer.hxx" #include "CharUtil.hxx" #include "StringUtil.hxx" -#include "Error.hxx" -#include "Domain.hxx" -static constexpr Domain tokenizer_domain("tokenizer"); +#include <stdexcept> static inline bool valid_word_first_char(char ch) @@ -49,7 +47,7 @@ valid_word_char(char ch) } char * -Tokenizer::NextWord(Error &error) +Tokenizer::NextWord() { char *const word = input; @@ -58,10 +56,8 @@ Tokenizer::NextWord(Error &error) /* check the first character */ - if (!valid_word_first_char(*input)) { - error.Set(tokenizer_domain, "Letter expected"); - return nullptr; - } + if (!valid_word_first_char(*input)) + throw std::runtime_error("Letter expected"); /* now iterate over the other characters until we find a whitespace or end-of-string */ @@ -75,10 +71,8 @@ Tokenizer::NextWord(Error &error) break; } - if (!valid_word_char(*input)) { - error.Set(tokenizer_domain, "Invalid word character"); - return nullptr; - } + if (!valid_word_char(*input)) + throw std::runtime_error("Invalid word character"); } /* end of string: the string is already null-terminated @@ -94,7 +88,7 @@ valid_unquoted_char(char ch) } char * -Tokenizer::NextUnquoted(Error &error) +Tokenizer::NextUnquoted() { char *const word = input; @@ -103,10 +97,8 @@ Tokenizer::NextUnquoted(Error &error) /* check the first character */ - if (!valid_unquoted_char(*input)) { - error.Set(tokenizer_domain, "Invalid unquoted character"); - return nullptr; - } + if (!valid_unquoted_char(*input)) + throw std::runtime_error("Invalid unquoted character"); /* now iterate over the other characters until we find a whitespace or end-of-string */ @@ -120,11 +112,8 @@ Tokenizer::NextUnquoted(Error &error) break; } - if (!valid_unquoted_char(*input)) { - error.Set(tokenizer_domain, - "Invalid unquoted character"); - return nullptr; - } + if (!valid_unquoted_char(*input)) + throw std::runtime_error("Invalid unquoted character"); } /* end of string: the string is already null-terminated @@ -134,7 +123,7 @@ Tokenizer::NextUnquoted(Error &error) } char * -Tokenizer::NextString(Error &error) +Tokenizer::NextString() { char *const word = input, *dest = input; @@ -144,10 +133,8 @@ Tokenizer::NextString(Error &error) /* check for the opening " */ - if (*input != '"') { - error.Set(tokenizer_domain, "'\"' expected"); - return nullptr; - } + if (*input != '"') + throw std::runtime_error("'\"' expected"); ++input; @@ -159,14 +146,8 @@ Tokenizer::NextString(Error &error) character */ ++input; - if (*input == 0) { - /* return input-1 so the caller can see the - difference between "end of line" and - "error" */ - --input; - error.Set(tokenizer_domain, "Missing closing '\"'"); - return nullptr; - } + if (*input == 0) + throw std::runtime_error("Missing closing '\"'"); /* copy one character */ *dest++ = *input++; @@ -176,11 +157,8 @@ Tokenizer::NextString(Error &error) line) */ ++input; - if (!IsWhitespaceFast(*input)) { - error.Set(tokenizer_domain, - "Space expected after closing '\"'"); - return nullptr; - } + if (!IsWhitespaceFast(*input)) + throw std::runtime_error("Space expected after closing '\"'"); /* finish the string and return it */ @@ -190,10 +168,10 @@ Tokenizer::NextString(Error &error) } char * -Tokenizer::NextParam(Error &error) +Tokenizer::NextParam() { if (*input == '"') - return NextString(error); + return NextString(); else - return NextUnquoted(error); + return NextUnquoted(); } diff --git a/src/util/Tokenizer.hxx b/src/util/Tokenizer.hxx index 3f3448d52..01e4db762 100644 --- a/src/util/Tokenizer.hxx +++ b/src/util/Tokenizer.hxx @@ -30,8 +30,6 @@ #ifndef TOKENIZER_HXX #define TOKENIZER_HXX -class Error; - class Tokenizer { char *input; @@ -58,50 +56,42 @@ public: } /** - * Reads the next word. + * Reads the next word. Throws std::runtime_error on error. * - * @param error if this function returns nullptr and - * **input_p!=0, it provides an #Error object in - * this argument * @return a pointer to the null-terminated word, or nullptr - * on error or end of line + * on end of line */ - char *NextWord(Error &error); + char *NextWord(); /** - * Reads the next unquoted word from the input string. + * Reads the next unquoted word from the input string. Throws + * std::runtime_error on error. * - * @param error if this function returns nullptr and **input_p!=0, it - * provides an #Error object in this argument * @return a pointer to the null-terminated word, or nullptr - * on error or end of line + * on end of line */ - char *NextUnquoted(Error &error); + char *NextUnquoted(); /** - * Reads the next quoted string from the input string. A backslash - * escapes the following character. This function modifies the input - * string. + * Reads the next quoted string from the input string. A + * backslash escapes the following character. This function + * modifies the input string. Throws std::runtime_error on + * error. * - * @param error if this function returns nullptr and **input_p!=0, it - * provides an #Error object in this argument - * @return a pointer to the null-terminated string, or nullptr on error - * or end of line + * @return a pointer to the null-terminated string, or nullptr + * end of line */ - char *NextString(Error &error); + char *NextString(); /** * Reads the next unquoted word or quoted string from the * input. This is a wrapper for NextUnquoted() and - * NextString(). + * NextString(). Throws std::runtime_error on error. * - * @param error if this function returns nullptr and - * **input_p!=0, it provides an #Error object in - * this argument * @return a pointer to the null-terminated string, or nullptr - * on error or end of line + * on end of line */ - char *NextParam(Error &error); + char *NextParam(); }; #endif |