Boost logo

Boost Users :

Subject: Re: [Boost-users] Can boost help me organize/parse lots of binary data?
From: Larry Evans (cppljevans_at_[hidden])
Date: 2013-02-22 09:38:33


On 02/22/13 00:16, Antony Polukhin wrote:
> 2013/2/21 Larry Evans <cppljevans_at_[hidden]>:
>
>> I haven't a clear idea how this would work because I assumed that
>> the binary input stream would have to have something that
>> 1st would be decoded into the tag for the variant.

That "something" looks like the 'S' or 'D' or 'P' character
returned by the Stream.getc() call in the EmployeePacket::Decode
method you provided below.

>> Then, if your variant visitor solution is used, some
>> code (not shown) would create some default constructed value for
>> the bounded type corresponding to that tag and then call the visitor.
>>
>> All the above is just off the top of my head, but, as I said,
>> I'm not real sure the variant visitor solution would work.
>>
>> Could you provide more pseudo code to clarify.
>
> Here is some more pseudo code, may be it will help you.

Yes, Anthony, it helps a lot. I was confused by your earlier code,
the one that appeared to use a variant visitor to do the decoding of
Chris' binary input stream:

  http://article.gmane.org/gmane.comp.lib.boost.user/77401

In the example code from your last post, which is quoted below, the
variant visitor is not used to decode this input stream, it's only
used to perform some operaton on the variant. Quoting from Chris' OP:

  I will be decoding many of these "packets" and doing various things
  with them like printing their values to console, etc.

That quote mentions two purposes:

  1) Decoding packets
  2) Operating on the decoded packets

The code quoted below does 2); however, the 1) is done by the Decode
methods shown below, the most complicated of which is the
EmployeePacket::Decode. This EmployeePacket::Decode is somewhat like
a very simple Spirit alternative parser:

http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/spirit/qi/reference/operator/alternative.html

So, I think *both* variant and spirit could solve both of Chris'
problems; however, I don't think using variant with its visitor is
sufficient to solve both problems.

>
> #include <boost/variant.hpp>
>
> struct name_visitor: public boost::static_visitor<std::string> {
> template <class T>
> const std::string& opertor()(const T& val) const {
> return val.name;
> }
>
> // Specific visitor for Person
> std::string opertor()(const Person& val) const {
> return val.first_name + " " + val.second_name;
> }
>
> // Specific visitor for Something
> std::string opertor()(const Something& val) const {
> throw std::logic_error("Class Something has no name!");
> }
>
> };
>
> class EmployeePacket
> {
> typedef boost::variant<String, Double, Person, Something> variant_t;
> std::vector<variant_t> Items;
>
> EmployeePacket()
> {
> // copying variants is not as fast as copying pointers,
> // so it is better to reserve some space first
> Items.reserve(200);
> }
>
> void Decode(istream& Stream)
> {
> while (Stream) {
> switch (Stream.getc()) {
> case 'S': Items.push_back(String(Stream)); break;
> case 'D': Items.push_back(Double(Stream)); break;
> case 'P': Items.push_back(Person(Stream)); break;
> }
> }
> }
>
> double GetSalary(std::size_t index) const
> {
> // Will throw if at 'index' is not a Double type
> return boost::get<Double>(Items[index]).value;
> }
>
> std::string GetName(std::size_t index) const {
> return boost::apply_visitor(name_visitor(), Items[index]);
> }
>
> }
> // All the folloving classes must have a constructor that accepts an
istream&
> class Double
> {
> string name;
> string units;
> // double decode_conversion_scale;
> // double decode_conversion_translate;
> // unsigned number_of_bits_used_to_encode
> // double scale_factor
> double value;
> void Decode(istream& Stream) // Will be called from constructor
> {
> Stream.read(&value, 8);
> value = value * decode_conversion_scale +
decode_conversion_translate;
> }
>
> class String
> {
> string name;
> string value;
> void Decode(istream& Stream); // Will be called from constructor
> }
>
> class Person
> {
> string first_name;
> string second_name;
> void Decode(istream& Stream); // Will be called from constructor
> }
>
> class Something
> {
> /*string name; Has NO name! */
> void Decode(istream& Stream);
> }
>
>
[snip]

-Best Regards,
Larry


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net