Масштабирование в boost::spirit's assign_a
Я углубляюсь в boost::spirit, чтобы разобрать протокол на основе ASCII. Мне удалось извлечь значения из строки, используя такие правила:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_a(buffer.speed)];
Мне также удается соединить эти правила в значимой манере. Для идеального дня не хватает следующего: значения данных являются целыми числами, которые необходимо преобразовать в значения с плавающей запятой, используя фиксированный коэффициент преобразования (обычно степени 10).
То, что я делаю прямо сейчас, - это просто применяю эти факторы масштабирования после разбора. Однако я бы с радостью включил масштабный коэффициент прямо в определение правила для поля. Я представляю что-то вроде этого:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_a(buffer.speed,100)];
Какие-либо предложения?
Заранее спасибо Арне
2 ответа
Один из способов сделать это - использовать Boost.Phoenix. Включить эти заголовки:
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_object.hpp> // For static_cast_
#include <boost/spirit/include/phoenix_operator.hpp> // For multiplication
а затем использовать что-то вроде:
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
rule<> Speed = uint_parser<unsigned int,10,3,3>()[
ref(buffer.speed) = static_cast_<double>(arg1) * 100
];
Хотя я нахожу Феникса немного хитрым в использовании и вообще просто пишу свое собственное действие:
struct assign_scaled
{
double& result;
double scale;
assign_with_scale(double& r, double scale) : result(r), scale(scale) {}
void operator()(unsigned int x) const
{
result = static_cast<double>(x) * scale;
}
};
И используйте это так:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_scaled(buffer.speed, 100)];
Это может быть более многословным, но мне легче поддерживать.
С Spirit.Qi вы можете использовать [ref(buffer.speed) = _1 * 100]