I have the following parser,
#define PRICE_MULT 10000
qi::uint_parser<uint32_t, 10, 1, 6> int_part;
qi::uint_parser<uint32_t, 10, 1, 6> dec_part;
qi::rule<Iterator, uint64_t()> fixed_point =
(int_part >> "." >> dec_part )[qi::_val = qi::_1 * PRICE_MULT + qi::_2];
m_wire_msg = ( qi::as_string[*qi::alpha] >> "," // symbol
>> qi::ulong_long >> "," // symbol seq num
>> qi::ulong_long >> "," // order id
>> (fixed_point | qi::ulong_) >> ","
>> qi::uint_ >> "," // volume
>> qi::char_ >> "," // side
>> +qi::space >> "," // firm id
>> qi::ushort_ // parity split
But it fails to parse,
"AAPL,1192544,16044086616349464,157.47,100,S, ,0"
Specifically, the 157.47 can sometimes be whole numbers, for eg. 157 on its own, which is why i'm using "(fixed_point | qi::ulong_)".
But parsing fails, which I don't quite understand. Ideally is should also parse the following correctly,
"AAPL,1192544,16044086616349464,157,100,S, ,0"
Any help is much appreciated!
Use optional parser to not fail if there is no fractional part.
Also you had PRICE_MULT
with 4 zeros, but dec_part
was allowed up to 6 digits.
#define PRICE_MULT 10000
qi::uint_parser<std::uint32_t, 10, 1, 6> int_part;
qi::uint_parser<std::uint32_t, 10, 1, 4> dec_part;
qi::rule<Iterator, std::uint64_t()> fixed_point =
int_part[qi::_val = qi::_1 * PRICE_MULT]
>> -('.' >> dec_part[qi::_val += qi::_1]);
https://wandbox.org/permlink/H46ujDgJ57gyE69I
The right fixed point parser can look like this:
constexpr std::uint64_t lut[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
constexpr int frac_digits = 6;
qi::uint_parser<std::uint32_t, 10, 1, 6> const int_part;
qi::uint_parser<std::uint32_t, 10, 1, frac_digits> const dec_part;
qi::rule<Iterator, std::uint64_t()> fixed_point
= int_part[qi::_val = qi::_1 * lut[frac_digits]] // parse integer part and save multiplied by lut[frac_digits]
>> ( !qi::lit('.') // do not fail on missing fractional part
| ('.' >> qir::iter_pos >> dec_part >> qir::iter_pos)[ // parse fraction and save/syntesize iterators before and after
qi::_val += qi::_2 * phx::ref(lut)[ // multiple fraction by lookuped pow10 value
frac_digits - (qi::_3 - qi::_1)]]
>> *qi::digit); // consume unparsed digits
https://wandbox.org/permlink/mtdMDPzB2RjPxQlD
input result
===== ======
123 123000000
123.0 123000000
123.4 123400000
123.45 123450000
123.456 123456000
123.4567 123456700
123.45678 123456780
123.456789 123456789
123.456789123 123456789
123. fail
.123 fail