tags:

views:

787

answers:

5

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.

  • Any suggestions what STL features I can use?
  • Any sample code will work, I will build on top of it.

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

A: 

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.

MighMoS
A: 

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;
}
strager
Better yet, use ret.m_part*.assign(buffer,start,len), which avoids creating, copying, and destroying a temporary. And no, the compiler would not be allowed to optimize it out, since it can't see how to combine the constructor and operator =
puetzk
I am confused, I am new to c++ One can define Datacontainer class and then assign ret to that class type ?
@unknown, I'm sorry, I forgot to include 'static' in my example. I will include sample usage.
strager
What this statement do ?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)
@unknown, That's call an initialization list. See: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
strager
I could not get how the stuff will get put in to data structure ? I am thinking in terms of plain C. Also I never came across Constructor using some Variables followed by ':' an dthen followed by variable list. What is that ?
@unknown, Again, that's called an initialization list. It's not in C. If you need a C solution I can post one. If you need a non-OOP one with C++, I can post that too. I think it is best to learn OOP when learning C++ and not stick to C-style code. (Pick up a good C++ book if you please.)
strager
+1  A: 

If "buffer" is made of char then:

string abcd = string(buffer,0,4);
string xxxx = string(buffer,4,8);
etc.
Jimmy J
+1  A: 

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.

Max Lybbert
+1  A: 

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.

Edouard A.