Ridimensionamento in boost :: spirit's assegnato_a
-
06-07-2019 - |
Domanda
Mi sto tuffando in boost :: spirit per analizzare un protocollo basato su ASCII. Ho organizzato per estrarre valori dalla riga usando regole come questa:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_a(buffer.speed)];
Riesco anche a collegare queste regole in modo significativo. Ciò che manca per un giorno perfetto è il seguente: I valori dei dati sono numeri interi che devono essere trasformati in valori in virgola mobile utilizzando un fattore di conversione fisso (generalmente potenze di 10).
Quello che faccio adesso è semplicemente applicare questi fattori di ridimensionamento dopo l'analisi. Tuttavia, mi piacerebbe davvero includere il fattore di ridimensionamento proprio all'interno della definizione della regola per il campo. Immagino qualcosa del genere:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_a(buffer.speed,100)];
Qualche suggerimento?
Grazie in anticipo Arne
Soluzione
Un modo per farlo è utilizzare Boost.Phoenix . Includi queste intestazioni:
#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 quindi usa qualcosa come:
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
];
Anche se trovo che Phoenix sia un po 'difficile da usare e generalmente solo scrivi la mia azione :
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 usalo in questo modo:
rule<> Speed = uint_parser<unsigned int,10,3,3>()[assign_scaled(buffer.speed, 100)];
Potrebbe essere più dettagliato, ma trovo che sia più facile da mantenere.
Altri suggerimenti
Con Spirit.Qi puoi usare [ref (buffer.speed) = _1 * 100]