user79292
user79292

Reputation: 815

Parsing buffer in C++ using OOP and STL

I want to use OOP and STL etc to parse a buffer.

My Buffer contains

ABCDXXXX333$$$$YYYY

I need to separate ABCD XXXX 333 $$$$ YYY and move them to struct. I have their offset defined in one of the rule table and how many elements are in the buffer. A few of the fields are delimited also.

I will be using this on an AIX (Unix) Box.

Upvotes: 0

Views: 2162

Answers (5)

Max Lybbert
Max Lybbert

Reputation: 20041

Read a line at a time with std::getline(), which stuffs the line into a std::string (your buffer). Then use std::string methods to parse the data according to your data format. Or use something like Lex/Yacc when you have a real grammar to deal with and the std::string methods are getting to hard to read sober.

Upvotes: 0

Edouard A.
Edouard A.

Reputation: 6128

I would really recommend using a regular expressions for your problem, boost::regex is available for C++.

Regular expression will protect you against a lot of technical problems that generally turn into nasty security problems.

Upvotes: 1

strager
strager

Reputation: 90012

You would probably have your class which contains all the data have a static function which creates the object given your serialized string. How it works depending on your data. You say you have defined offsets for fields, but also say they are delimited. This poses a problem as both need to be handled differently.

Simple case for your example:

class DataContainer
{
    using namespace std; // FIXME Is this legal?

    public:
        DataContainer(string part1, string part2, string part3, string part4, string part5) :
            m_part1(part1), m_part2(part2), m_part3(part3), m_part4(part4), m_part5(part5)
        {
        }

        static DataContainer readFromStream(istream &stream)
        {
            DataContainer ret;
            char tmp[16];

            stream.get(tmp, 4);
            ret.m_part1 = string(tmp, 4);

            stream.get(tmp, 4);
            ret.m_part2 = string(tmp, 4);

            stream.get(tmp, 3);
            ret.m_part3 = string(tmp, 3);

            stream.get(tmp, 4);
            ret.m_part4 = string(tmp, 4);

            stream.get(tmp, 3);
            ret.m_part5 = string(tmp, 3);

            return ret;
        }

    private:
        DataContainer()
        {
        }

        string m_part1, m_part2, m_part3, m_part4, m_part5;  // Put these in an array if they belong in an array.
};

Note: I have inlined all my functions. You should probably put your functions in their own .cpp file.

Use it like so:

DataContainer dc = DataContainer::readFromStream(std::cin);

This reads your data from cin (stdin) and puts the data structure in dc.

If you already have the data read, you can use STL iterators (which are basically pointers to elements of a container) quite easily. You can also use classic indexing, which is simpler for your given case. For example:

static DataContainer readFromBuffer(string buffer)
{
    DataContainer ret;
    ret.m_part1 = string(buffer, 0, 4);
    ret.m_part2 = string(buffer, 4, 4);
    ret.m_part3 = string(buffer, 8, 3);
    ret.m_part4 = string(buffer, 11, 4);
    ret.m_part5 = string(buffer, 15, 3);
    return ret;
}

Upvotes: 1

Jimmy J
Jimmy J

Reputation: 1985

If "buffer" is made of char then:

string abcd = string(buffer,0,4);
string xxxx = string(buffer,4,8);
etc.

Upvotes: 1

MighMoS
MighMoS

Reputation: 1254

You can use cin.peek () to see if its a character you want to get (note this will not remove it from the stream). Perhaps three classes / functions to extract what they take using this technique and stopping when they reach a character they shouldn't hold.

Upvotes: 0

Related Questions