winlin

fix the conf_line bug of parse config directive.

... ... @@ -154,8 +154,8 @@ int SrsConfDirective::parse_conf(_srs_internal::SrsConfigBuffer* buffer, SrsDire
while (true) {
std::vector<string> args;
ret = read_token(buffer, args);
int line_start = 0;
ret = read_token(buffer, args, line_start);
/**
* ret maybe:
... ... @@ -170,14 +170,14 @@ int SrsConfDirective::parse_conf(_srs_internal::SrsConfigBuffer* buffer, SrsDire
}
if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) {
if (type != parse_block) {
srs_error("line %d: unexpected \"}\", ret=%d", buffer->line + 1, ret);
srs_error("line %d: unexpected \"}\", ret=%d", buffer->line, ret);
return ret;
}
return ERROR_SUCCESS;
}
if (ret == ERROR_SYSTEM_CONFIG_EOF) {
if (type == parse_block) {
srs_error("line %d: unexpected end of file, expecting \"}\", ret=%d", conf_line + 1, ret);
srs_error("line %d: unexpected end of file, expecting \"}\", ret=%d", conf_line, ret);
return ret;
}
return ERROR_SUCCESS;
... ... @@ -185,14 +185,14 @@ int SrsConfDirective::parse_conf(_srs_internal::SrsConfigBuffer* buffer, SrsDire
if (args.empty()) {
ret = ERROR_SYSTEM_CONFIG_INVALID;
srs_error("line %d: empty directive. ret=%d", conf_line + 1, ret);
srs_error("line %d: empty directive. ret=%d", conf_line, ret);
return ret;
}
// build directive tree.
SrsConfDirective* directive = new SrsConfDirective();
directive->conf_line = buffer->line;
directive->conf_line = line_start;
directive->name = args[0];
args.erase(args.begin());
directive->args.swap(args);
... ... @@ -210,7 +210,7 @@ int SrsConfDirective::parse_conf(_srs_internal::SrsConfigBuffer* buffer, SrsDire
}
// see: ngx_conf_read_token
int SrsConfDirective::read_token(_srs_internal::SrsConfigBuffer* buffer, vector<string>& args)
int SrsConfDirective::read_token(_srs_internal::SrsConfigBuffer* buffer, vector<string>& args, int& line_start)
{
int ret = ERROR_SUCCESS;
... ... @@ -260,7 +260,7 @@ int SrsConfDirective::read_token(_srs_internal::SrsConfigBuffer* buffer, vector<
if (ch == '{') {
return ERROR_SYSTEM_CONFIG_BLOCK_START;
}
srs_error("line %d: unexpected '%c'", buffer->line + 1, ch);
srs_error("line %d: unexpected '%c'", buffer->line, ch);
return ERROR_SYSTEM_CONFIG_INVALID;
}
... ... @@ -273,19 +273,19 @@ int SrsConfDirective::read_token(_srs_internal::SrsConfigBuffer* buffer, vector<
switch (ch) {
case ';':
if (args.size() == 0) {
srs_error("line %d: unexpected ';'", buffer->line + 1);
srs_error("line %d: unexpected ';'", buffer->line);
return ERROR_SYSTEM_CONFIG_INVALID;
}
return ERROR_SYSTEM_CONFIG_DIRECTIVE;
case '{':
if (args.size() == 0) {
srs_error("line %d: unexpected '{'", buffer->line + 1);
srs_error("line %d: unexpected '{'", buffer->line);
return ERROR_SYSTEM_CONFIG_INVALID;
}
return ERROR_SYSTEM_CONFIG_BLOCK_START;
case '}':
if (args.size() != 0) {
srs_error("line %d: unexpected '}'", buffer->line + 1);
srs_error("line %d: unexpected '}'", buffer->line);
return ERROR_SYSTEM_CONFIG_INVALID;
}
return ERROR_SYSTEM_CONFIG_BLOCK_END;
... ... @@ -308,6 +308,10 @@ int SrsConfDirective::read_token(_srs_internal::SrsConfigBuffer* buffer, vector<
}
} else {
// last charecter is not space
if (line_start == 0) {
line_start = buffer->line;
}
bool found = false;
if (d_quoted) {
if (ch == '"') {
... ... @@ -2847,7 +2851,7 @@ namespace _srs_internal
{
SrsConfigBuffer::SrsConfigBuffer()
{
line = 0;
line = 1;
pos = last = start = NULL;
end = start;
... ...
... ... @@ -215,9 +215,10 @@ private:
* read a token from buffer.
* a token, is the directive args and a flag indicates whether has child-directives.
* @param args, the output directive args, the first is the directive name, left is the args.
* @param line_start, the actual start line of directive.
* @return, an error code indicates error or has child-directives.
*/
virtual int read_token(_srs_internal::SrsConfigBuffer* buffer, std::vector<std::string>& args);
virtual int read_token(_srs_internal::SrsConfigBuffer* buffer, std::vector<std::string>& args, int& line_start);
};
/**
... ...
... ... @@ -663,3 +663,117 @@ VOID TEST(ConfigDirectiveTest, ParseInvalidEmptyDirective)
EXPECT_EQ(0, (int)dir0.args.size());
EXPECT_EQ(0, (int)dir0.directives.size());
}
VOID TEST(ConfigDirectiveTest, ParseLine)
{
MockSrsConfigBuffer buf("dir0 {}");
SrsConfDirective conf;
EXPECT_TRUE(ERROR_SUCCESS == conf.parse(&buf));
EXPECT_EQ(0, (int)conf.name.length());
EXPECT_EQ(0, (int)conf.args.size());
EXPECT_EQ(1, (int)conf.directives.size());
SrsConfDirective& dir0 = *conf.directives.at(0);
EXPECT_STREQ("dir0", dir0.name.c_str());
EXPECT_EQ(0, (int)dir0.args.size());
EXPECT_EQ(0, (int)dir0.directives.size());
EXPECT_EQ(1, (int)dir0.conf_line);
}
VOID TEST(ConfigDirectiveTest, ParseLine2)
{
MockSrsConfigBuffer buf("\n\ndir0 {}");
SrsConfDirective conf;
EXPECT_TRUE(ERROR_SUCCESS == conf.parse(&buf));
EXPECT_EQ(0, (int)conf.name.length());
EXPECT_EQ(0, (int)conf.args.size());
EXPECT_EQ(1, (int)conf.directives.size());
SrsConfDirective& dir0 = *conf.directives.at(0);
EXPECT_STREQ("dir0", dir0.name.c_str());
EXPECT_EQ(0, (int)dir0.args.size());
EXPECT_EQ(0, (int)dir0.directives.size());
EXPECT_EQ(3, (int)dir0.conf_line);
}
VOID TEST(ConfigDirectiveTest, ParseLine3)
{
MockSrsConfigBuffer buf("dir0 {\n\ndir1 arg0;}");
SrsConfDirective conf;
EXPECT_TRUE(ERROR_SUCCESS == conf.parse(&buf));
EXPECT_EQ(0, (int)conf.name.length());
EXPECT_EQ(0, (int)conf.args.size());
EXPECT_EQ(1, (int)conf.directives.size());
SrsConfDirective& dir0 = *conf.directives.at(0);
EXPECT_STREQ("dir0", dir0.name.c_str());
EXPECT_EQ(0, (int)dir0.args.size());
EXPECT_EQ(1, (int)dir0.directives.size());
EXPECT_EQ(1, (int)dir0.conf_line);
SrsConfDirective& dir1 = *dir0.directives.at(0);
EXPECT_STREQ("dir1", dir1.name.c_str());
EXPECT_EQ(1, (int)dir1.args.size());
EXPECT_STREQ("arg0", dir1.arg0().c_str());
EXPECT_EQ(0, (int)dir1.directives.size());
EXPECT_EQ(3, (int)dir1.conf_line);
}
VOID TEST(ConfigDirectiveTest, ParseLine4)
{
MockSrsConfigBuffer buf("dir0 {\n\ndir1 \n\narg0;dir2 arg1;}");
SrsConfDirective conf;
EXPECT_TRUE(ERROR_SUCCESS == conf.parse(&buf));
EXPECT_EQ(0, (int)conf.name.length());
EXPECT_EQ(0, (int)conf.args.size());
EXPECT_EQ(1, (int)conf.directives.size());
SrsConfDirective& dir0 = *conf.directives.at(0);
EXPECT_STREQ("dir0", dir0.name.c_str());
EXPECT_EQ(0, (int)dir0.args.size());
EXPECT_EQ(2, (int)dir0.directives.size());
EXPECT_EQ(1, (int)dir0.conf_line);
SrsConfDirective& dir1 = *dir0.directives.at(0);
EXPECT_STREQ("dir1", dir1.name.c_str());
EXPECT_EQ(1, (int)dir1.args.size());
EXPECT_STREQ("arg0", dir1.arg0().c_str());
EXPECT_EQ(0, (int)dir1.directives.size());
EXPECT_EQ(3, (int)dir1.conf_line);
SrsConfDirective& dir2 = *dir0.directives.at(1);
EXPECT_STREQ("dir2", dir2.name.c_str());
EXPECT_EQ(1, (int)dir2.args.size());
EXPECT_STREQ("arg1", dir2.arg0().c_str());
EXPECT_EQ(0, (int)dir2.directives.size());
EXPECT_EQ(5, (int)dir2.conf_line);
}
VOID TEST(ConfigDirectiveTest, ParseLineNormal)
{
MockSrsConfigBuffer buf("dir0 {\ndir1 {\ndir2 arg2;\n}\n}");
SrsConfDirective conf;
EXPECT_TRUE(ERROR_SUCCESS == conf.parse(&buf));
EXPECT_EQ(0, (int)conf.name.length());
EXPECT_EQ(0, (int)conf.args.size());
EXPECT_EQ(1, (int)conf.directives.size());
SrsConfDirective& dir0 = *conf.directives.at(0);
EXPECT_STREQ("dir0", dir0.name.c_str());
EXPECT_EQ(0, (int)dir0.args.size());
EXPECT_EQ(1, (int)dir0.directives.size());
EXPECT_EQ(1, (int)dir0.conf_line);
SrsConfDirective& dir1 = *dir0.directives.at(0);
EXPECT_STREQ("dir1", dir1.name.c_str());
EXPECT_EQ(0, (int)dir1.args.size());
EXPECT_EQ(1, (int)dir1.directives.size());
EXPECT_EQ(2, (int)dir1.conf_line);
SrsConfDirective& dir2 = *dir1.directives.at(0);
EXPECT_STREQ("dir2", dir2.name.c_str());
EXPECT_EQ(1, (int)dir2.args.size());
EXPECT_STREQ("arg2", dir2.arg0().c_str());
EXPECT_EQ(0, (int)dir2.directives.size());
EXPECT_EQ(3, (int)dir2.conf_line);
}
... ...