tokenizer: convert to C++
This commit is contained in:
parent
7ec1121cc8
commit
450c26c471
32
Makefile.am
32
Makefile.am
@ -98,7 +98,6 @@ mpd_headers = \
|
|||||||
src/tag_ape.h \
|
src/tag_ape.h \
|
||||||
src/tag_id3.h \
|
src/tag_id3.h \
|
||||||
src/tag_rva2.h \
|
src/tag_rva2.h \
|
||||||
src/tokenizer.h \
|
|
||||||
src/utils.h \
|
src/utils.h \
|
||||||
src/string_util.h \
|
src/string_util.h \
|
||||||
src/timer.h \
|
src/timer.h \
|
||||||
@ -242,7 +241,6 @@ src_mpd_SOURCES = \
|
|||||||
src/TagSave.cxx src/TagSave.hxx \
|
src/TagSave.cxx src/TagSave.hxx \
|
||||||
src/tag_handler.c src/tag_handler.h \
|
src/tag_handler.c src/tag_handler.h \
|
||||||
src/TagFile.cxx src/TagFile.hxx \
|
src/TagFile.cxx src/TagFile.hxx \
|
||||||
src/tokenizer.c \
|
|
||||||
src/TextFile.cxx src/TextFile.hxx \
|
src/TextFile.cxx src/TextFile.hxx \
|
||||||
src/text_input_stream.c \
|
src/text_input_stream.c \
|
||||||
src/utils.c \
|
src/utils.c \
|
||||||
@ -290,6 +288,7 @@ endif
|
|||||||
# Generic utility library
|
# Generic utility library
|
||||||
|
|
||||||
libutil_a_SOURCES = \
|
libutil_a_SOURCES = \
|
||||||
|
src/util/Tokenizer.cxx src/util/Tokenizer.hxx \
|
||||||
src/util/UriUtil.cxx src/util/UriUtil.hxx \
|
src/util/UriUtil.cxx src/util/UriUtil.hxx \
|
||||||
src/util/Manual.hxx \
|
src/util/Manual.hxx \
|
||||||
src/util/RefCount.hxx \
|
src/util/RefCount.hxx \
|
||||||
@ -1055,10 +1054,11 @@ endif
|
|||||||
|
|
||||||
test_read_conf_LDADD = \
|
test_read_conf_LDADD = \
|
||||||
libconf.a \
|
libconf.a \
|
||||||
|
libutil.a \
|
||||||
libfs.a \
|
libfs.a \
|
||||||
$(GLIB_LIBS)
|
$(GLIB_LIBS)
|
||||||
test_read_conf_SOURCES = test/read_conf.cxx \
|
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 = \
|
test_run_resolver_LDADD = \
|
||||||
$(GLIB_LIBS)
|
$(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/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagSave.cxx \
|
||||||
src/SongFilter.cxx \
|
src/SongFilter.cxx \
|
||||||
src/TextFile.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 = \
|
test_run_input_LDADD = \
|
||||||
$(INPUT_LIBS) \
|
$(INPUT_LIBS) \
|
||||||
@ -1094,7 +1094,7 @@ test_run_input_LDADD = \
|
|||||||
test_run_input_SOURCES = test/run_input.cxx \
|
test_run_input_SOURCES = test/run_input.cxx \
|
||||||
test/stdbin.h \
|
test/stdbin.h \
|
||||||
src/IOThread.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/TagSave.cxx \
|
src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagSave.cxx \
|
||||||
src/fd_util.c
|
src/fd_util.c
|
||||||
|
|
||||||
@ -1111,7 +1111,7 @@ test_visit_archive_LDADD = \
|
|||||||
test_visit_archive_SOURCES = test/visit_archive.cxx \
|
test_visit_archive_SOURCES = test/visit_archive.cxx \
|
||||||
src/IOThread.cxx \
|
src/IOThread.cxx \
|
||||||
src/InputStream.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/Tag.cxx src/TagNames.c src/TagPool.cxx \
|
||||||
src/fd_util.c
|
src/fd_util.c
|
||||||
|
|
||||||
@ -1132,7 +1132,7 @@ test_dump_text_file_LDADD = \
|
|||||||
test_dump_text_file_SOURCES = test/dump_text_file.cxx \
|
test_dump_text_file_SOURCES = test/dump_text_file.cxx \
|
||||||
test/stdbin.h \
|
test/stdbin.h \
|
||||||
src/IOThread.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.cxx src/TagNames.c src/TagPool.cxx \
|
||||||
src/text_input_stream.c \
|
src/text_input_stream.c \
|
||||||
src/fd_util.c
|
src/fd_util.c
|
||||||
@ -1152,7 +1152,7 @@ test_dump_playlist_LDADD = \
|
|||||||
test_dump_playlist_SOURCES = test/dump_playlist.cxx \
|
test_dump_playlist_SOURCES = test/dump_playlist.cxx \
|
||||||
$(DECODER_SRC) \
|
$(DECODER_SRC) \
|
||||||
src/IOThread.cxx \
|
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/Song.cxx src/Tag.cxx src/TagNames.c src/TagPool.cxx src/TagSave.cxx \
|
||||||
src/tag_handler.c src/TagFile.cxx \
|
src/tag_handler.c src/TagFile.cxx \
|
||||||
src/audio_check.c src/pcm_buffer.c \
|
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_run_decoder_SOURCES = test/run_decoder.cxx \
|
||||||
test/stdbin.h \
|
test/stdbin.h \
|
||||||
src/IOThread.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/Tag.cxx src/TagNames.c src/TagPool.cxx src/tag_handler.c \
|
||||||
src/ReplayGainInfo.cxx \
|
src/ReplayGainInfo.cxx \
|
||||||
src/fd_util.c \
|
src/fd_util.c \
|
||||||
@ -1204,7 +1204,7 @@ test_read_tags_LDADD = \
|
|||||||
$(GLIB_LIBS)
|
$(GLIB_LIBS)
|
||||||
test_read_tags_SOURCES = test/read_tags.cxx \
|
test_read_tags_SOURCES = test/read_tags.cxx \
|
||||||
src/IOThread.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/Tag.cxx src/TagNames.c src/TagPool.cxx src/tag_handler.c \
|
||||||
src/ReplayGainInfo.cxx \
|
src/ReplayGainInfo.cxx \
|
||||||
src/fd_util.c \
|
src/fd_util.c \
|
||||||
@ -1225,13 +1225,14 @@ endif
|
|||||||
test_run_filter_LDADD = \
|
test_run_filter_LDADD = \
|
||||||
$(FILTER_LIBS) \
|
$(FILTER_LIBS) \
|
||||||
libconf.a \
|
libconf.a \
|
||||||
|
libutil.a \
|
||||||
libfs.a \
|
libfs.a \
|
||||||
$(GLIB_LIBS)
|
$(GLIB_LIBS)
|
||||||
test_run_filter_SOURCES = test/run_filter.cxx \
|
test_run_filter_SOURCES = test/run_filter.cxx \
|
||||||
test/FakeReplayGainConfig.cxx \
|
test/FakeReplayGainConfig.cxx \
|
||||||
test/stdbin.h \
|
test/stdbin.h \
|
||||||
src/FilterPlugin.cxx src/FilterRegistry.cxx \
|
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_check.c \
|
||||||
src/audio_format.c \
|
src/audio_format.c \
|
||||||
src/AudioParser.cxx \
|
src/AudioParser.cxx \
|
||||||
@ -1250,7 +1251,7 @@ if ENABLE_ENCODER
|
|||||||
noinst_PROGRAMS += test/run_encoder
|
noinst_PROGRAMS += test/run_encoder
|
||||||
test_run_encoder_SOURCES = test/run_encoder.cxx \
|
test_run_encoder_SOURCES = test/run_encoder.cxx \
|
||||||
test/stdbin.h \
|
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/Tag.cxx src/TagNames.c src/TagPool.cxx \
|
||||||
src/audio_check.c \
|
src/audio_check.c \
|
||||||
src/audio_format.c \
|
src/audio_format.c \
|
||||||
@ -1269,7 +1270,7 @@ if ENABLE_VORBIS_ENCODER
|
|||||||
noinst_PROGRAMS += test/test_vorbis_encoder
|
noinst_PROGRAMS += test/test_vorbis_encoder
|
||||||
test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \
|
test_test_vorbis_encoder_SOURCES = test/test_vorbis_encoder.cxx \
|
||||||
test/stdbin.h \
|
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/Tag.cxx src/TagNames.c src/TagPool.cxx \
|
||||||
src/audio_check.c \
|
src/audio_check.c \
|
||||||
src/audio_format.c \
|
src/audio_format.c \
|
||||||
@ -1325,7 +1326,7 @@ test_run_output_LDADD = $(MPD_LIBS) \
|
|||||||
test_run_output_SOURCES = test/run_output.cxx \
|
test_run_output_SOURCES = test/run_output.cxx \
|
||||||
test/FakeReplayGainConfig.cxx \
|
test/FakeReplayGainConfig.cxx \
|
||||||
test/stdbin.h \
|
test/stdbin.h \
|
||||||
src/tokenizer.c src/utils.c src/string_util.c \
|
src/utils.c src/string_util.c \
|
||||||
src/IOThread.cxx \
|
src/IOThread.cxx \
|
||||||
src/audio_check.c \
|
src/audio_check.c \
|
||||||
src/audio_format.c \
|
src/audio_format.c \
|
||||||
@ -1351,11 +1352,12 @@ test_read_mixer_LDADD = \
|
|||||||
libmixer_plugins.a \
|
libmixer_plugins.a \
|
||||||
$(OUTPUT_LIBS) \
|
$(OUTPUT_LIBS) \
|
||||||
libconf.a \
|
libconf.a \
|
||||||
|
libutil.a \
|
||||||
libevent.a \
|
libevent.a \
|
||||||
libfs.a \
|
libfs.a \
|
||||||
$(GLIB_LIBS)
|
$(GLIB_LIBS)
|
||||||
test_read_mixer_SOURCES = test/read_mixer.cxx \
|
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/MixerControl.cxx \
|
||||||
src/MixerInternal.cxx \
|
src/MixerInternal.cxx \
|
||||||
src/FilterPlugin.cxx \
|
src/FilterPlugin.cxx \
|
||||||
|
@ -31,10 +31,7 @@
|
|||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "protocol/Result.hxx"
|
#include "protocol/Result.hxx"
|
||||||
#include "Client.hxx"
|
#include "Client.hxx"
|
||||||
|
#include "util/Tokenizer.hxx"
|
||||||
extern "C" {
|
|
||||||
#include "tokenizer.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
#include "StickerCommands.hxx"
|
#include "StickerCommands.hxx"
|
||||||
@ -329,10 +326,11 @@ command_process(Client *client, unsigned num, char *line)
|
|||||||
|
|
||||||
/* get the command name (first word on the 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) {
|
if (argv[0] == NULL) {
|
||||||
current_command = "";
|
current_command = "";
|
||||||
if (*line == 0)
|
if (tokenizer.IsEnd())
|
||||||
command_error(client, ACK_ERROR_UNKNOWN,
|
command_error(client, ACK_ERROR_UNKNOWN,
|
||||||
"No command given");
|
"No command given");
|
||||||
else {
|
else {
|
||||||
@ -351,7 +349,7 @@ command_process(Client *client, unsigned num, char *line)
|
|||||||
|
|
||||||
while (argc < (int)G_N_ELEMENTS(argv) &&
|
while (argc < (int)G_N_ELEMENTS(argv) &&
|
||||||
(argv[argc] =
|
(argv[argc] =
|
||||||
tokenizer_next_param(&line, &error)) != NULL)
|
tokenizer.NextParam(&error)) != NULL)
|
||||||
++argc;
|
++argc;
|
||||||
|
|
||||||
/* some error checks; we have to set current_command because
|
/* 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;
|
return COMMAND_RETURN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*line != 0) {
|
if (!tokenizer.IsEnd()) {
|
||||||
command_error(client, ACK_ERROR_ARG,
|
command_error(client, ACK_ERROR_ARG,
|
||||||
"%s", error->message);
|
"%s", error->message);
|
||||||
current_command = NULL;
|
current_command = NULL;
|
||||||
|
@ -23,10 +23,10 @@
|
|||||||
#include "ConfigData.hxx"
|
#include "ConfigData.hxx"
|
||||||
#include "ConfigTemplates.hxx"
|
#include "ConfigTemplates.hxx"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "util/Tokenizer.hxx"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "tokenizer.h"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
@ -50,15 +50,17 @@ static bool
|
|||||||
config_read_name_value(struct config_param *param, char *input, unsigned line,
|
config_read_name_value(struct config_param *param, char *input, unsigned line,
|
||||||
GError **error_r)
|
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) {
|
if (name == NULL) {
|
||||||
assert(*input != 0);
|
assert(!tokenizer.IsEnd());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *value = tokenizer_next_string(&input, error_r);
|
const char *value = tokenizer.NextString(error_r);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
if (*input == 0) {
|
if (tokenizer.IsEnd()) {
|
||||||
assert(error_r == NULL || *error_r == NULL);
|
assert(error_r == NULL || *error_r == NULL);
|
||||||
g_set_error(error_r, config_quark(), 0,
|
g_set_error(error_r, config_quark(), 0,
|
||||||
"Value missing");
|
"Value missing");
|
||||||
@ -69,7 +71,7 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*input != 0 && *input != CONF_COMMENT) {
|
if (!tokenizer.IsEnd() && tokenizer.CurrentChar() != CONF_COMMENT) {
|
||||||
g_set_error(error_r, config_quark(), 0,
|
g_set_error(error_r, config_quark(), 0,
|
||||||
"Unknown tokens after value");
|
"Unknown tokens after value");
|
||||||
return false;
|
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
|
/* the first token in each line is the name, followed
|
||||||
by either the value or '{' */
|
by either the value or '{' */
|
||||||
|
|
||||||
name = tokenizer_next_word(&line, &error);
|
Tokenizer tokenizer(line);
|
||||||
|
name = tokenizer.NextWord(&error);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
assert(*line != 0);
|
assert(!tokenizer.IsEnd());
|
||||||
g_propagate_prefixed_error(error_r, error,
|
g_propagate_prefixed_error(error_r, error,
|
||||||
"line %i: ", count);
|
"line %i: ", count);
|
||||||
return false;
|
return false;
|
||||||
@ -210,13 +213,13 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
|
|||||||
if (option.block) {
|
if (option.block) {
|
||||||
/* it's a block, call config_read_block() */
|
/* it's a block, call config_read_block() */
|
||||||
|
|
||||||
if (*line != '{') {
|
if (tokenizer.CurrentChar() != '{') {
|
||||||
g_set_error(error_r, config_quark(), 0,
|
g_set_error(error_r, config_quark(), 0,
|
||||||
"line %i: '{' expected", count);
|
"line %i: '{' expected", count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = strchug_fast(line + 1);
|
line = strchug_fast(tokenizer.Rest() + 1);
|
||||||
if (*line != 0 && *line != CONF_COMMENT) {
|
if (*line != 0 && *line != CONF_COMMENT) {
|
||||||
g_set_error(error_r, config_quark(), 0,
|
g_set_error(error_r, config_quark(), 0,
|
||||||
"line %i: Unknown tokens after '{'",
|
"line %i: Unknown tokens after '{'",
|
||||||
@ -231,9 +234,9 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
|
|||||||
} else {
|
} else {
|
||||||
/* a string value */
|
/* a string value */
|
||||||
|
|
||||||
value = tokenizer_next_string(&line, &error);
|
value = tokenizer.NextString(&error);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
if (*line == 0)
|
if (tokenizer.IsEnd())
|
||||||
g_set_error(error_r, config_quark(), 0,
|
g_set_error(error_r, config_quark(), 0,
|
||||||
"line %i: Value missing",
|
"line %i: Value missing",
|
||||||
count);
|
count);
|
||||||
@ -247,7 +250,8 @@ ReadConfigFile(ConfigData &config_data, FILE *fp, GError **error_r)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*line != 0 && *line != CONF_COMMENT) {
|
if (!tokenizer.IsEnd() &&
|
||||||
|
tokenizer.CurrentChar() != CONF_COMMENT) {
|
||||||
g_set_error(error_r, config_quark(), 0,
|
g_set_error(error_r, config_quark(), 0,
|
||||||
"line %i: Unknown tokens after value",
|
"line %i: Unknown tokens after value",
|
||||||
count);
|
count);
|
||||||
|
@ -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
|
|
@ -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
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "tokenizer.h"
|
#include "Tokenizer.hxx"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@ -47,24 +47,19 @@ valid_word_char(char ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
tokenizer_next_word(char **input_p, GError **error_r)
|
Tokenizer::NextWord(GError **error_r)
|
||||||
{
|
{
|
||||||
char *word, *input;
|
char *const word = input;
|
||||||
|
|
||||||
assert(input_p != NULL);
|
|
||||||
assert(*input_p != NULL);
|
|
||||||
|
|
||||||
word = input = *input_p;
|
|
||||||
|
|
||||||
if (*input == 0)
|
if (*input == 0)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
/* check the first character */
|
/* check the first character */
|
||||||
|
|
||||||
if (!valid_word_first_char(*input)) {
|
if (!valid_word_first_char(*input)) {
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"Letter expected");
|
"Letter expected");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now iterate over the other characters until we find a
|
/* 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)) {
|
if (!valid_word_char(*input)) {
|
||||||
*input_p = input;
|
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"Invalid word character");
|
"Invalid word character");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of string: the string is already null-terminated
|
/* end of string: the string is already null-terminated
|
||||||
here */
|
here */
|
||||||
|
|
||||||
*input_p = input;
|
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,24 +94,19 @@ valid_unquoted_char(char ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
tokenizer_next_unquoted(char **input_p, GError **error_r)
|
Tokenizer::NextUnquoted(GError **error_r)
|
||||||
{
|
{
|
||||||
char *word, *input;
|
char *const word = input;
|
||||||
|
|
||||||
assert(input_p != NULL);
|
|
||||||
assert(*input_p != NULL);
|
|
||||||
|
|
||||||
word = input = *input_p;
|
|
||||||
|
|
||||||
if (*input == 0)
|
if (*input == 0)
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
/* check the first character */
|
/* check the first character */
|
||||||
|
|
||||||
if (!valid_unquoted_char(*input)) {
|
if (!valid_unquoted_char(*input)) {
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"Invalid unquoted character");
|
"Invalid unquoted character");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now iterate over the other characters until we find a
|
/* 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)) {
|
if (!valid_unquoted_char(*input)) {
|
||||||
*input_p = input;
|
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"Invalid unquoted character");
|
"Invalid unquoted character");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of string: the string is already null-terminated
|
/* end of string: the string is already null-terminated
|
||||||
here */
|
here */
|
||||||
|
|
||||||
*input_p = input;
|
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
tokenizer_next_string(char **input_p, GError **error_r)
|
Tokenizer::NextString(GError **error_r)
|
||||||
{
|
{
|
||||||
char *word, *dest, *input;
|
char *const word = input, *dest = input;
|
||||||
|
|
||||||
assert(input_p != NULL);
|
|
||||||
assert(*input_p != NULL);
|
|
||||||
|
|
||||||
word = dest = input = *input_p;
|
|
||||||
|
|
||||||
if (*input == 0)
|
if (*input == 0)
|
||||||
/* end of line */
|
/* end of line */
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
/* check for the opening " */
|
/* check for the opening " */
|
||||||
|
|
||||||
if (*input != '"') {
|
if (*input != '"') {
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"'\"' expected");
|
"'\"' expected");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
++input;
|
++input;
|
||||||
@ -184,10 +165,10 @@ tokenizer_next_string(char **input_p, GError **error_r)
|
|||||||
/* return input-1 so the caller can see the
|
/* return input-1 so the caller can see the
|
||||||
difference between "end of line" and
|
difference between "end of line" and
|
||||||
"error" */
|
"error" */
|
||||||
*input_p = input - 1;
|
--input;
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"Missing closing '\"'");
|
"Missing closing '\"'");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy one character */
|
/* copy one character */
|
||||||
@ -199,27 +180,23 @@ tokenizer_next_string(char **input_p, GError **error_r)
|
|||||||
|
|
||||||
++input;
|
++input;
|
||||||
if (*input != 0 && !g_ascii_isspace(*input)) {
|
if (*input != 0 && !g_ascii_isspace(*input)) {
|
||||||
*input_p = input;
|
|
||||||
g_set_error(error_r, tokenizer_quark(), 0,
|
g_set_error(error_r, tokenizer_quark(), 0,
|
||||||
"Space expected after closing '\"'");
|
"Space expected after closing '\"'");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finish the string and return it */
|
/* finish the string and return it */
|
||||||
|
|
||||||
*dest = 0;
|
*dest = 0;
|
||||||
*input_p = strchug_fast(input);
|
input = strchug_fast(input);
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
tokenizer_next_param(char **input_p, GError **error_r)
|
Tokenizer::NextParam(GError **error_r)
|
||||||
{
|
{
|
||||||
assert(input_p != NULL);
|
if (*input == '"')
|
||||||
assert(*input_p != NULL);
|
return NextString(error_r);
|
||||||
|
|
||||||
if (**input_p == '"')
|
|
||||||
return tokenizer_next_string(input_p, error_r);
|
|
||||||
else
|
else
|
||||||
return tokenizer_next_unquoted(input_p, error_r);
|
return NextUnquoted(error_r);
|
||||||
}
|
}
|
99
src/util/Tokenizer.hxx
Normal file
99
src/util/Tokenizer.hxx
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user