summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2015-12-16 11:34:26 +0100
committerMax Kellermann <max@duempel.org>2015-12-16 11:34:26 +0100
commit51168169e73528d388b39b826afe1df3370bd10a (patch)
treef0fcdd175e57a03365b3d3522dd9f50a69f75d0d /src
parentd256a0e98f587c0af714c74038ff75903c0903fe (diff)
util/Tokenizer: use std::runtime_error on syntax error
Diffstat (limited to 'src')
-rw-r--r--src/command/AllCommands.cxx48
-rw-r--r--src/config/ConfigFile.cxx65
-rw-r--r--src/util/Tokenizer.cxx64
-rw-r--r--src/util/Tokenizer.hxx44
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