A escala em boost :: assign_a do espírito
-
06-07-2019 - |
Pergunta
Estou mergulhando em boost :: espírito, a fim de analisar uma protocoll baseado em ASCII. I mananged para extrair valores a partir da linha usando as regras como esta:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_a(buffer.speed)];
Eu também ter sucesso para conectar essas regras de forma significativa. O que está faltando para um dia perfeito é o seguinte: Os valores dos dados são inteiros que precisam ser transformados em valores de ponto flutuante usando um fator de conversão fixa (geralmente potências de 10).
O que eu faço agora é apenas appying esses fatores escaladas após análise. No entanto, eu realmente apprechiate para incluir o fator de escala apenas dentro da definição de regras para o campo. Imagino algo como isto:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_a(buffer.speed,100)];
Todas as sugestões?
Obrigado antecipadamente Arne
Solução
Uma maneira de fazer isso é usar Boost.Phoenix . Incluir esses cabeçalhos:
#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
e, em seguida, usar algo como:
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
];
Embora, acho Phoenix um pouco complicado de usar e geralmente apenas escrever a minha própria ação :
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;
}
};
E usá-lo como este:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_scaled(buffer.speed, 100)];
Isto pode ser mais detalhado, mas acho que é mais fácil de manter.
Outras dicas
Com Spirit.Qi você pode usar [ref(buffer.speed) = _1 * 100]