Boost 属性 树解析自定义配置格式
Boost property tree to parse custom configuration format
在这个postBoost_option to parse a configuration file中@sehe提供的这个link之后,我需要解析可能有注释的配置文件
但是既然有注释(#前导),那么除了read_info(),还要用一个grammer_spirit来去掉注释吗?我指的是 /property_tree/examples 文件夹中的 info_grammar_spirit.cpp
你最好避免依赖于实现细节,所以我建议预处理你的配置文件只是为了去掉注释。
将 "//"
简单替换为 "; "
可能就足够了。
基于之前的答案:
std::string tmp;
{
std::ifstream ifs(file_name.c_str());
tmp.assign(std::istreambuf_iterator<char>(ifs), {});
} // closes file
boost::algorithm::replace_all(tmp, "//", ";");
std::istringstream preprocessed(tmp);
read_info(preprocessed, pt);
现在,如果您将输入更改为包含评论:
Resnet50 {
Layer CONV1 {
Type: CONV // this is a comment
Stride { X: 2, Y: 2 } ; this too
Dimensions { K: 64, C: 3, R: 7, S: 7, Y:224, X:224 }
}
// don't forget the CONV2_1_1 layer
Layer CONV2_1_1 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 64, R: 1, S: 1, Y: 56, X: 56 }
}
}
它仍然按预期解析,如果我们也扩展调试输出来验证:
ptree const& resnet50 = pt.get_child("Resnet50");
for (auto& entry : resnet50) {
std::cout << entry.first << " " << entry.second.get_value("") << "\n";
std::cout << " --- Echoing the complete subtree:\n";
write_info(std::cout, entry.second);
}
版画
Layer CONV1
--- Echoing the complete subtree:
Type: CONV
Stride
{
X: 2,
Y: 2
}
Dimensions
{
K: 64,
C: 3,
R: 7,
S: 7,
Y:224, X:224
}
Layer CONV2_1_1
--- Echoing the complete subtree:
Type: CONV
Stride
{
X: 1,
Y: 1
}
Dimensions
{
K: 64,
C: 64,
R: 1,
S: 1,
Y: 56,
X: 56
}
是的,但是...?
如果 '//' 出现在字符串文字中怎么办?不会也被换掉吧。是的。
这不是图书馆质量的解决方案。你不应该期待一个,因为你不必付出任何努力来解析你定制的配置文件格式。
您是唯一可以判断这种方法的缺点是否对您有问题的一方。
然而,除了复制和修改 Boost 的解析器或从头开始实现您自己的解析器之外,我们能做的事情并不多。
受虐狂
如果您不想重新实现整个解析器,但仍希望“智能”跳过字符串文字,这里有一个 pre_process
函数可以完成所有这些工作。这一次,是真正用上了Boost Spirit
#include <boost/spirit/home/x3.hpp>
std::string pre_process(std::string const& input) {
std::string result;
using namespace boost::spirit::x3;
auto static string_literal
= raw[ '"' >> *('\'>> char_ | ~char_('"')) >> '"' ];
auto static comment
= char_(';') >> *~char_("\r\n")
| "//" >> attr(';') >> *~char_("\r\n")
| omit["/*" >> *(char_ - "*/") >> "*/"];
auto static other
= +(~char_(";\"") - "//" - "/*");
auto static content
= *(string_literal | comment | other) >> eoi;
if (!parse(begin(input), end(input), content, result)) {
throw std::invalid_argument("pre_process");
}
return result;
}
如您所见,它识别字符串文字(带有转义符),它处理“//”和“;”将行注释样式设置为等价。为了“炫耀”,我加入了 /block comments/ ,它不能用正确的 INFO 语法表示,所以我们只是 omit[]
它们。
现在让我们用一个时髦的例子来测试(从文档中的 "Complicated example demonstrating all INFO features" 扩展而来):
#include <boost/property_tree/info_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
int main() {
boost::property_tree::ptree pt;
std::istringstream iss(
pre_process(R"~~( ; A comment
key1 value1 // Another comment
key2 "value with /* no problem */ special // characters in it {};#\n\t\"[=15=]"
{
subkey "value split "\
"over three"\
"lines"
{
a_key_without_value ""
"a key with special characters in it {};#\n\t\"[=15=]" ""
"" value /* Empty key with a value */
"" /*also empty value: */ "" ; Empty key with empty value!
}
})~~"));
read_info(iss, pt);
std::cout << " --- Echoing the parsed tree:\n";
write_info(std::cout, pt);
}
打印 (Live On Coliru)
--- Echoing the parsed tree:
key1 value1
key2 "value with /* no problem */ special // characters in it {};#\n \"[=16=]"
{
subkey "value split over threelines"
{
a_key_without_value ""
"a key with special characters in it {};#\n \"[=16=]" ""
"" value
"" ""
}
}
在这个postBoost_option to parse a configuration file中@sehe提供的这个link之后,我需要解析可能有注释的配置文件
但是既然有注释(#前导),那么除了read_info(),还要用一个grammer_spirit来去掉注释吗?我指的是 /property_tree/examples 文件夹中的 info_grammar_spirit.cpp
你最好避免依赖于实现细节,所以我建议预处理你的配置文件只是为了去掉注释。
将 "//"
简单替换为 "; "
可能就足够了。
基于之前的答案:
std::string tmp;
{
std::ifstream ifs(file_name.c_str());
tmp.assign(std::istreambuf_iterator<char>(ifs), {});
} // closes file
boost::algorithm::replace_all(tmp, "//", ";");
std::istringstream preprocessed(tmp);
read_info(preprocessed, pt);
现在,如果您将输入更改为包含评论:
Resnet50 {
Layer CONV1 {
Type: CONV // this is a comment
Stride { X: 2, Y: 2 } ; this too
Dimensions { K: 64, C: 3, R: 7, S: 7, Y:224, X:224 }
}
// don't forget the CONV2_1_1 layer
Layer CONV2_1_1 {
Type: CONV
Stride { X: 1, Y: 1 }
Dimensions { K: 64, C: 64, R: 1, S: 1, Y: 56, X: 56 }
}
}
它仍然按预期解析,如果我们也扩展调试输出来验证:
ptree const& resnet50 = pt.get_child("Resnet50");
for (auto& entry : resnet50) {
std::cout << entry.first << " " << entry.second.get_value("") << "\n";
std::cout << " --- Echoing the complete subtree:\n";
write_info(std::cout, entry.second);
}
版画
Layer CONV1
--- Echoing the complete subtree:
Type: CONV
Stride
{
X: 2,
Y: 2
}
Dimensions
{
K: 64,
C: 3,
R: 7,
S: 7,
Y:224, X:224
}
Layer CONV2_1_1
--- Echoing the complete subtree:
Type: CONV
Stride
{
X: 1,
Y: 1
}
Dimensions
{
K: 64,
C: 64,
R: 1,
S: 1,
Y: 56,
X: 56
}
是的,但是...?
如果 '//' 出现在字符串文字中怎么办?不会也被换掉吧。是的。
这不是图书馆质量的解决方案。你不应该期待一个,因为你不必付出任何努力来解析你定制的配置文件格式。
您是唯一可以判断这种方法的缺点是否对您有问题的一方。
然而,除了复制和修改 Boost 的解析器或从头开始实现您自己的解析器之外,我们能做的事情并不多。
受虐狂
如果您不想重新实现整个解析器,但仍希望“智能”跳过字符串文字,这里有一个 pre_process
函数可以完成所有这些工作。这一次,是真正用上了Boost Spirit
#include <boost/spirit/home/x3.hpp>
std::string pre_process(std::string const& input) {
std::string result;
using namespace boost::spirit::x3;
auto static string_literal
= raw[ '"' >> *('\'>> char_ | ~char_('"')) >> '"' ];
auto static comment
= char_(';') >> *~char_("\r\n")
| "//" >> attr(';') >> *~char_("\r\n")
| omit["/*" >> *(char_ - "*/") >> "*/"];
auto static other
= +(~char_(";\"") - "//" - "/*");
auto static content
= *(string_literal | comment | other) >> eoi;
if (!parse(begin(input), end(input), content, result)) {
throw std::invalid_argument("pre_process");
}
return result;
}
如您所见,它识别字符串文字(带有转义符),它处理“//”和“;”将行注释样式设置为等价。为了“炫耀”,我加入了 /block comments/ ,它不能用正确的 INFO 语法表示,所以我们只是 omit[]
它们。
现在让我们用一个时髦的例子来测试(从文档中的 "Complicated example demonstrating all INFO features" 扩展而来):
#include <boost/property_tree/info_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
int main() {
boost::property_tree::ptree pt;
std::istringstream iss(
pre_process(R"~~( ; A comment
key1 value1 // Another comment
key2 "value with /* no problem */ special // characters in it {};#\n\t\"[=15=]"
{
subkey "value split "\
"over three"\
"lines"
{
a_key_without_value ""
"a key with special characters in it {};#\n\t\"[=15=]" ""
"" value /* Empty key with a value */
"" /*also empty value: */ "" ; Empty key with empty value!
}
})~~"));
read_info(iss, pt);
std::cout << " --- Echoing the parsed tree:\n";
write_info(std::cout, pt);
}
打印 (Live On Coliru)
--- Echoing the parsed tree:
key1 value1
key2 "value with /* no problem */ special // characters in it {};#\n \"[=16=]"
{
subkey "value split over threelines"
{
a_key_without_value ""
"a key with special characters in it {};#\n \"[=16=]" ""
"" value
"" ""
}
}