mardi 21 juin 2016

Spirit Grammar To break Up a String by Number of Characters

I am working on learning to write spirit grammars and I am trying to create a basic base 16 to base 64 converter that takes in a string representing hex, for example:

49276d206b696c

parse out 6 or less characters (less if the string isn't a perfect multiple of 6) and generate a base 64 encoded string from the input. One grammar I figured would probably work is something like this:

// 6 characters 
`(qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >> 
 qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >>
 qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F")[/*action*/]) | 


// or 5 characters
(qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >> 
qi::char_("0-9a-fA-F") >> qi::char_("0-9a-fA-F") >> 
qi::char_("0-9a-fA-F")[/*action*/]) | ...`

etc.... all the way down to one character, Or having a different rule defined for each number of characters, but I think there must be a better way to specify the grammar. I read about spirit repeat and was thinking maybe I could do something like +(boost::spirit::repeat(1, 6)[qi::char_("0-9a-fA-F")][/*action on characters*/]) however the compiler throws an error on this, because of the sematic action portion of the grammar. Is there a simpler way to specify a grammar to operate on exactly 6 or less characters at a time?

Edit Here is what I have done so far... base16convertergrammar.hpp

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>    

#include <string>
#include <iostream>

namespace grammar {
    namespace qi = boost::spirit::qi;

    void toBase64(const std::string& p_input, std::string& p_output)
    {   
        if (p_input.length() < 6)
        {   
            // pad length
        }   

        // use back inserter and generator to append to end of p_output.
    }   

    template <typename Iterator>
    struct Base16Grammar : qi::grammar<Iterator, std::string()>
    {
        Base16Grammar() : Base16Grammar::base_type(start, "base16grammar"),
            m_base64String()
        {
            // get six characters at a time and send them off to be encoded
            // if there is less than six characters just parse what we have
            start = +(boost::spirit::repeat(1, 6)[qi::char_("0-9a-fA-F")][boost::phoenix::bind(toBase64, qi::_1,
                boost::phoenix::ref(m_base64String))]);
        }

        qi::rule<Iterator, std::string()> start;

        std::string m_base64String;
    };
}

And here is the usage... base16converter.cpp

#include "base16convertergrammar.hpp"

const std::string& convertHexToBase64(const std::string& p_hexString)
{
    grammar::Base16Grammar<std::string::const_iterator> g;
    bool r = boost::spirit::qi::parse(p_hexString.begin(), p_hexString.end(), g); 
}


int main(int argc, char** argv)
{
    std::string test("49276d206b696c6c");
    convertHexToBase64(test);
}

Aucun commentaire:

Enregistrer un commentaire