Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
51168169
Commit
51168169
authored
Dec 16, 2015
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
util/Tokenizer: use std::runtime_error on syntax error
parent
d256a0e9
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
80 additions
and
141 deletions
+80
-141
AllCommands.cxx
src/command/AllCommands.cxx
+23
-25
ConfigFile.cxx
src/config/ConfigFile.cxx
+19
-46
Tokenizer.cxx
src/util/Tokenizer.cxx
+21
-43
Tokenizer.hxx
src/util/Tokenizer.hxx
+17
-27
No files found.
src/command/AllCommands.cxx
View file @
51168169
...
...
@@ -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
;
}
src/config/ConfigFile.cxx
View file @
51168169
...
...
@@ -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
))
...
...
src/util/Tokenizer.cxx
View file @
51168169
...
...
@@ -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
();
}
src/util/Tokenizer.hxx
View file @
51168169
...
...
@@ -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 e
rror or e
nd 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 e
rror or e
nd 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 e
rror or e
nd of line
* on end of line
*/
char
*
NextParam
(
Error
&
error
);
char
*
NextParam
();
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment