aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-04-08 23:51:39 +0200
committerMax Kellermann <max@duempel.org>2013-04-08 23:51:39 +0200
commit450c26c4713a2de440296260e8d0be8e6b283d75 (patch)
tree21ad06ced3adbe9c79e47c7b759a9d6f64f6dd02
parent7ec1121cc832086f533dd0adfcb581e16c1e312d (diff)
downloadmpd-450c26c4713a2de440296260e8d0be8e6b283d75.tar.gz
mpd-450c26c4713a2de440296260e8d0be8e6b283d75.tar.xz
mpd-450c26c4713a2de440296260e8d0be8e6b283d75.zip
tokenizer: convert to C++
-rw-r--r--Makefile.am32
-rw-r--r--src/AllCommands.cxx14
-rw-r--r--src/ConfigFile.cxx30
-rw-r--r--src/tokenizer.h83
-rw-r--r--src/util/Tokenizer.cxx (renamed from src/tokenizer.c)71
-rw-r--r--src/util/Tokenizer.hxx99
6 files changed, 163 insertions, 166 deletions
diff --git a/Makefile.am b/Makefile.am
index 5e3dbb3c8..84ca7e491 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -98,7 +98,6 @@ mpd_headers = \
src/tag_ape.h \
src/tag_id3.h \
src/tag_rva2.h \
- src/tokenizer.h \
src/utils.h \
src/string_util.h \
src/timer.h \
@@ -242,7 +241,6 @@ src_mpd_SOURCES = \
src/TagSave.cxx src/TagSave.hxx \
src/tag_handler.c src/tag_handler.h \
src/TagFile.cxx src/TagFile.hxx \
- src/tokenizer.c \
src/TextFile.cxx src/TextFile.hxx \
src/text_input_stream.c \
src/utils.c \
@@ -290,6 +288,7 @@ endif
# Generic utility library
libutil_a_SOURCES = \
+ src/util/Tokenizer.cxx src/util/Tokenizer.hxx \
src/util/UriUtil.cxx src/util/UriUtil.hxx \
src/util/Manual.hxx \
src/util/RefCount.hxx \
@@ -1055,10 +1054,11 @@ endif
test_read_conf_LDADD = \
libconf.a \
+ libutil.a \
libfs.a \
$(GLIB_LIBS)
test_read_conf_SOURCES = test/read_conf.cxx \
- src/tokenizer.c src/utils.c src/string_util.c
+ src/utils.c src/string_util.c
test_run_resolver_LDADD = \
$(GLIB_LIBS)
@@ -1081,7 +1081,7 @@ test_DumpDatabase_SOURCES = test/DumpDatabase.cxx \
src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagSave.cxx \
src/SongFilter.cxx \
src/TextFile.cxx \
- src/tokenizer.c src/utils.c src/string_util.c
+ src/utils.c src/string_util.c
test_run_input_LDADD = \
$(INPUT_LIBS) \
@@ -1094,7 +1094,7 @@ test_run_input_LDADD = \
test_run_input_SOURCES = test/run_input.cxx \
test/stdbin.h \
src/IOThread.cxx \
- src/tokenizer.c src/utils.c src/string_util.c\
+ src/utils.c src/string_util.c\
src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagSave.cxx \
src/fd_util.c
@@ -1111,7 +1111,7 @@ test_visit_archive_LDADD = \
test_visit_archive_SOURCES = test/visit_archive.cxx \
src/IOThread.cxx \
src/InputStream.cxx \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/fd_util.c
@@ -1132,7 +1132,7 @@ test_dump_text_file_LDADD = \
test_dump_text_file_SOURCES = test/dump_text_file.cxx \
test/stdbin.h \
src/IOThread.cxx \
- src/tokenizer.c src/utils.c src/string_util.c\
+ src/utils.c src/string_util.c\
src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/text_input_stream.c \
src/fd_util.c
@@ -1152,7 +1152,7 @@ test_dump_playlist_LDADD = \
test_dump_playlist_SOURCES = test/dump_playlist.cxx \
$(DECODER_SRC) \
src/IOThread.cxx \
- src/tokenizer.c src/utils.c src/string_util.c\
+ src/utils.c src/string_util.c\
src/Song.cxx src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagSave.cxx \
src/tag_handler.c src/TagFile.cxx \
src/audio_check.c src/pcm_buffer.c \
@@ -1180,7 +1180,7 @@ test_run_decoder_LDADD = \
test_run_decoder_SOURCES = test/run_decoder.cxx \
test/stdbin.h \
src/IOThread.cxx \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/Tag.cxx src/TagNames.c src/TagPool.cxx src/tag_handler.c \
src/ReplayGainInfo.cxx \
src/fd_util.c \
@@ -1204,7 +1204,7 @@ test_read_tags_LDADD = \
$(GLIB_LIBS)
test_read_tags_SOURCES = test/read_tags.cxx \
src/IOThread.cxx \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/Tag.cxx src/TagNames.c src/TagPool.cxx src/tag_handler.c \
src/ReplayGainInfo.cxx \
src/fd_util.c \
@@ -1225,13 +1225,14 @@ endif
test_run_filter_LDADD = \
$(FILTER_LIBS) \
libconf.a \
+ libutil.a \
libfs.a \
$(GLIB_LIBS)
test_run_filter_SOURCES = test/run_filter.cxx \
test/FakeReplayGainConfig.cxx \
test/stdbin.h \
src/FilterPlugin.cxx src/FilterRegistry.cxx \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/audio_check.c \
src/audio_format.c \
src/AudioParser.cxx \
@@ -1250,7 +1251,7 @@ if ENABLE_ENCODER
noinst_PROGRAMS += test/run_encoder
test_run_encoder_SOURCES = test/run_encoder.cxx \
test/stdbin.h \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/audio_check.c \
src/audio_format.c \
@@ -1269,7 +1270,7 @@ if ENABLE_VORBIS_ENCODER
noinst_PROGRAMS += test/test_vorbis_encoder
test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \
test/stdbin.h \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/Tag.cxx src/TagNames.c src/TagPool.cxx \
src/audio_check.c \
src/audio_format.c \
@@ -1325,7 +1326,7 @@ test_run_output_LDADD = $(MPD_LIBS) \
test_run_output_SOURCES = test/run_output.cxx \
test/FakeReplayGainConfig.cxx \
test/stdbin.h \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/IOThread.cxx \
src/audio_check.c \
src/audio_format.c \
@@ -1351,11 +1352,12 @@ test_read_mixer_LDADD = \
libmixer_plugins.a \
$(OUTPUT_LIBS) \
libconf.a \
+ libutil.a \
libevent.a \
libfs.a \
$(GLIB_LIBS)
test_read_mixer_SOURCES = test/read_mixer.cxx \
- src/tokenizer.c src/utils.c src/string_util.c \
+ src/utils.c src/string_util.c \
src/MixerControl.cxx \
src/MixerInternal.cxx \
src/FilterPlugin.cxx \
diff --git a/src/AllCommands.cxx b/src/AllCommands.cxx
index 58dcf4dba..f3243915b 100644
--- a/src/AllCommands.cxx
+++ b/src/AllCommands.cxx
@@ -31,10 +31,7 @@
#include "tag.h"
#include "protocol/Result.hxx"
#include "Client.hxx"
-
-extern "C" {
-#include "tokenizer.h"
-}
+#include "util/Tokenizer.hxx"
#ifdef ENABLE_SQLITE
#include "StickerCommands.hxx"
@@ -329,10 +326,11 @@ command_process(Client *client, unsigned num, char *line)
/* get the command name (first word on the line) */
- argv[0] = tokenizer_next_word(&line, &error);
+ Tokenizer tokenizer(line);
+ argv[0] = tokenizer.NextWord(&error);
if (argv[0] == NULL) {
current_command = "";
- if (*line == 0)
+ if (tokenizer.IsEnd())
command_error(client, ACK_ERROR_UNKNOWN,
"No command given");
else {
@@ -351,7 +349,7 @@ command_process(Client *client, unsigned num, char *line)
while (argc < (int)G_N_ELEMENTS(argv) &&
(argv[argc] =
- tokenizer_next_param(&line, &error)) != NULL)
+ tokenizer.NextParam(&error)) != NULL)
++argc;
/* some error checks; we have to set current_command because
@@ -365,7 +363,7 @@ command_process(Client *client, unsigned num, char *line)
return COMMAND_RETURN_ERROR;
}
- if (*line != 0) {
+ if (!tokenizer.IsEnd()) {
command_error(client, ACK_ERROR_ARG,
"%s", error->message);
current_command = NULL;
diff --git a/src/ConfigFile.cxx b/src/ConfigFile.cxx
index e94f3f238..f7f525096 100644
--- a/src/ConfigFile.cxx
+++ b/src/ConfigFile.cxx
@@ -23,10 +23,10 @@
#include "ConfigData.hxx"
#include "ConfigTemplates.hxx"
#include "conf.h"
+#include "util/Tokenizer.hxx"
extern "C" {
#include "string_util.h"
-#include "tokenizer.h"
}
#include "fs/Path.hxx"
@@ -50,15 +50,17 @@ static bool
config_read_name_value(struct config_param *param, char *input, unsigned line,
GError **error_r)
{
- const char *name = tokenizer_next_word(&input, error_r);
+ Tokenizer tokenizer(input);
+
+ const char *name = tokenizer.NextWord(error_r);
if (name == NULL) {
- assert(*input != 0);
+ assert(!tokenizer.IsEnd());
return false;
}
- const char *value = tokenizer_next_string(&input, error_r);
+ const char *value = tokenizer.NextString(error_r);
if (value == NULL) {
- if (*input == 0) {
+ if (tokenizer.IsEnd()) {
assert(error_r == NULL || *error_r == NULL);
g_set_error(error_r, config_quark(), 0,
"Value missing");
@@ -69,7 +71,7 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
return false;
}
- if (*input != 0 && *input != CONF_COMMENT) {
+ if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0,
"Unknown tokens after value");
return false;
@@ -173,9 +175,10 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
/* the first token in each line is the name, followed
by either the value or '{' */
- name = tokenizer_next_word(&line, &error);
+ Tokenizer tokenizer(line);
+ name = tokenizer.NextWord(&error);
if (name == NULL) {
- assert(*line != 0);
+ assert(!tokenizer.IsEnd());
g_propagate_prefixed_error(error_r, error,
"line %i: ", count);
return false;
@@ -210,13 +213,13 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
if (option.block) {
/* it's a block, call config_read_block() */
- if (*line != '{') {
+ if (tokenizer.CurrentChar() != '{') {
g_set_error(error_r, config_quark(), 0,
"line %i: '{' expected", count);
return false;
}
- line = strchug_fast(line + 1);
+ line = strchug_fast(tokenizer.Rest() + 1);
if (*line != 0 && *line != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after '{'",
@@ -231,9 +234,9 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
} else {
/* a string value */
- value = tokenizer_next_string(&line, &error);
+ value = tokenizer.NextString(&error);
if (value == NULL) {
- if (*line == 0)
+ if (tokenizer.IsEnd())
g_set_error(error_r, config_quark(), 0,
"line %i: Value missing",
count);
@@ -247,7 +250,8 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
return false;
}
- if (*line != 0 && *line != CONF_COMMENT) {
+ if (!tokenizer.IsEnd() &&
+ tokenizer.CurrentChar() != CONF_COMMENT) {
g_set_error(error_r, config_quark(), 0,
"line %i: Unknown tokens after value",
count);
diff --git a/src/tokenizer.h b/src/tokenizer.h
deleted file mode 100644
index 2026e5ad6..000000000
--- a/src/tokenizer.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPD_TOKENIZER_H
-#define MPD_TOKENIZER_H
-
-#include "gerror.h"
-
-/**
- * Reads the next word from the input string. This function modifies
- * the input string.
- *
- * @param input_p the input string; this function returns a pointer to
- * the first non-whitespace character of the following token
- * @param error_r if this function returns NULL and **input_p!=0, it
- * optionally provides a GError object in this argument
- * @return a pointer to the null-terminated word, or NULL on error or
- * end of line
- */
-char *
-tokenizer_next_word(char **input_p, GError **error_r);
-
-/**
- * Reads the next unquoted word from the input string. This function
- * modifies the input string.
- *
- * @param input_p the input string; this function returns a pointer to
- * the first non-whitespace character of the following token
- * @param error_r if this function returns NULL and **input_p!=0, it
- * optionally provides a GError object in this argument
- * @return a pointer to the null-terminated word, or NULL on error or
- * end of line
- */
-char *
-tokenizer_next_unquoted(char **input_p, GError **error_r);
-
-/**
- * Reads the next quoted string from the input string. A backslash
- * escapes the following character. This function modifies the input
- * string.
- *
- * @param input_p the input string; this function returns a pointer to
- * the first non-whitespace character of the following token
- * @param error_r if this function returns NULL and **input_p!=0, it
- * optionally provides a GError object in this argument
- * @return a pointer to the null-terminated string, or NULL on error
- * or end of line
- */
-char *
-tokenizer_next_string(char **input_p, GError **error_r);
-
-/**
- * Reads the next unquoted word or quoted string from the input. This
- * is a wrapper for tokenizer_next_unquoted() and
- * tokenizer_next_string().
- *
- * @param input_p the input string; this function returns a pointer to
- * the first non-whitespace character of the following token
- * @param error_r if this function returns NULL and **input_p!=0, it
- * optionally provides a GError object in this argument
- * @return a pointer to the null-terminated string, or NULL on error
- * or end of line
- */
-char *
-tokenizer_next_param(char **input_p, GError **error_r);
-
-#endif
diff --git a/src/tokenizer.c b/src/util/Tokenizer.cxx
index 4a98e882f..9ade0d1b1 100644
--- a/src/tokenizer.c
+++ b/src/util/Tokenizer.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,7 +18,7 @@
*/
#include "config.h"
-#include "tokenizer.h"
+#include "Tokenizer.hxx"
#include "string_util.h"
#include <glib.h>
@@ -47,24 +47,19 @@ valid_word_char(char ch)
}
char *
-tokenizer_next_word(char **input_p, GError **error_r)
+Tokenizer::NextWord(GError **error_r)
{
- char *word, *input;
-
- assert(input_p != NULL);
- assert(*input_p != NULL);
-
- word = input = *input_p;
+ char *const word = input;
if (*input == 0)
- return NULL;
+ return nullptr;
/* check the first character */
if (!valid_word_first_char(*input)) {
g_set_error(error_r, tokenizer_quark(), 0,
"Letter expected");
- return NULL;
+ return nullptr;
}
/* now iterate over the other characters until we find a
@@ -80,17 +75,15 @@ tokenizer_next_word(char **input_p, GError **error_r)
}
if (!valid_word_char(*input)) {
- *input_p = input;
g_set_error(error_r, tokenizer_quark(), 0,
"Invalid word character");
- return NULL;
+ return nullptr;
}
}
/* end of string: the string is already null-terminated
here */
- *input_p = input;
return word;
}
@@ -101,24 +94,19 @@ valid_unquoted_char(char ch)
}
char *
-tokenizer_next_unquoted(char **input_p, GError **error_r)
+Tokenizer::NextUnquoted(GError **error_r)
{
- char *word, *input;
-
- assert(input_p != NULL);
- assert(*input_p != NULL);
-
- word = input = *input_p;
+ char *const word = input;
if (*input == 0)
- return NULL;
+ return nullptr;
/* check the first character */
if (!valid_unquoted_char(*input)) {
g_set_error(error_r, tokenizer_quark(), 0,
"Invalid unquoted character");
- return NULL;
+ return nullptr;
}
/* now iterate over the other characters until we find a
@@ -134,40 +122,33 @@ tokenizer_next_unquoted(char **input_p, GError **error_r)
}
if (!valid_unquoted_char(*input)) {
- *input_p = input;
g_set_error(error_r, tokenizer_quark(), 0,
"Invalid unquoted character");
- return NULL;
+ return nullptr;
}
}
/* end of string: the string is already null-terminated
here */
- *input_p = input;
return word;
}
char *
-tokenizer_next_string(char **input_p, GError **error_r)
+Tokenizer::NextString(GError **error_r)
{
- char *word, *dest, *input;
-
- assert(input_p != NULL);
- assert(*input_p != NULL);
-
- word = dest = input = *input_p;
+ char *const word = input, *dest = input;
if (*input == 0)
/* end of line */
- return NULL;
+ return nullptr;
/* check for the opening " */
if (*input != '"') {
g_set_error(error_r, tokenizer_quark(), 0,
"'\"' expected");
- return NULL;
+ return nullptr;
}
++input;
@@ -184,10 +165,10 @@ tokenizer_next_string(char **input_p, GError **error_r)
/* return input-1 so the caller can see the
difference between "end of line" and
"error" */
- *input_p = input - 1;
+ --input;
g_set_error(error_r, tokenizer_quark(), 0,
"Missing closing '\"'");
- return NULL;
+ return nullptr;
}
/* copy one character */
@@ -199,27 +180,23 @@ tokenizer_next_string(char **input_p, GError **error_r)
++input;
if (*input != 0 && !g_ascii_isspace(*input)) {
- *input_p = input;
g_set_error(error_r, tokenizer_quark(), 0,
"Space expected after closing '\"'");
- return NULL;
+ return nullptr;
}
/* finish the string and return it */
*dest = 0;
- *input_p = strchug_fast(input);
+ input = strchug_fast(input);
return word;
}
char *
-tokenizer_next_param(char **input_p, GError **error_r)
+Tokenizer::NextParam(GError **error_r)
{
- assert(input_p != NULL);
- assert(*input_p != NULL);
-
- if (**input_p == '"')
- return tokenizer_next_string(input_p, error_r);
+ if (*input == '"')
+ return NextString(error_r);
else
- return tokenizer_next_unquoted(input_p, error_r);
+ return NextUnquoted(error_r);
}
diff --git a/src/util/Tokenizer.hxx b/src/util/Tokenizer.hxx
new file mode 100644
index 000000000..da45348d4
--- /dev/null
+++ b/src/util/Tokenizer.hxx
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_TOKENIZER_HXX
+#define MPD_TOKENIZER_HXX
+
+#include "gerror.h"
+
+class Tokenizer {
+ char *input;
+
+public:
+ /**
+ * @param _input the input string; the contents will be
+ * modified by this class
+ */
+ constexpr Tokenizer(char *_input):input(_input) {}
+
+ Tokenizer(const Tokenizer &) = delete;
+ Tokenizer &operator=(const Tokenizer &) = delete;
+
+ char *Rest() {
+ return input;
+ }
+
+ char CurrentChar() const {
+ return *input;
+ }
+
+ bool IsEnd() const {
+ return CurrentChar() == 0;
+ }
+
+ /**
+ * Reads the next word.
+ *
+ * @param error_r if this function returns nullptr and
+ * **input_p!=0, it optionally provides a GError object in
+ * this argument
+ * @return a pointer to the null-terminated word, or nullptr
+ * on error or end of line
+ */
+ char *NextWord(GError **error_r);
+
+ /**
+ * Reads the next unquoted word from the input string.
+ *
+ * @param error_r if this function returns nullptr and **input_p!=0, it
+ * optionally provides a GError object in this argument
+ * @return a pointer to the null-terminated word, or nullptr
+ * on error or end of line
+ */
+ char *NextUnquoted(GError **error_r);
+
+ /**
+ * Reads the next quoted string from the input string. A backslash
+ * escapes the following character. This function modifies the input
+ * string.
+ *
+ * @param input_p the input string; this function returns a pointer to
+ * the first non-whitespace character of the following token
+ * @param error_r if this function returns nullptr and **input_p!=0, it
+ * optionally provides a GError object in this argument
+ * @return a pointer to the null-terminated string, or nullptr on error
+ * or end of line
+ */
+ char *NextString(GError **error_r);
+
+ /**
+ * Reads the next unquoted word or quoted string from the
+ * input. This is a wrapper for NextUnquoted() and
+ * NextString().
+ *
+ * @param error_r if this function returns nullptr and
+ * **input_p!=0, it optionally provides a GError object in
+ * this argument
+ * @return a pointer to the null-terminated string, or nullptr
+ * on error or end of line
+ */
+ char *NextParam(GError **error_r);
+};
+
+#endif