Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

An Encoder class derived from a stream

0.00/5 (No votes)
1 Sep 2004 1  
How to implement a class that derives from a Xstream class and how to serialize from and to it.

Introduction

Very often you want to add special features to a stream class (istream, ostream or iostream). A way to do this, is to create a specialized streambuf class and to overload stream base class methods.

A Xstream class constructor has a streambuf parameter that is attached to the stream. For example, to write to a file, you can do:

filebuf fb; 
fb.open ("test.txt",ios::out); 
ostream os(&fb); //... 

But if your objective isn't to write to a file, but to a generic memory buffer, you can construct your ostream derived class like that:

class MyStreamBuf : public streambuf { 
// ... you can overload streambuf methods here

}; 
class MyOutputStream : public ostream { 
public: 
MyOutputStream() : ostream(&stBuf) {} 
// ... you can overload ostream methods here

private: 
MyStreamBuf stBuf; 
};

The same for istream and iostream classes. Overloading of Xstream methods permit you to create a specialized stream class.

If you want to serialize primitive types or other objects to MyOutputStream, you must create a method that returns a MyOutputStream reference object, so you can write something like that:

MyOutputStream mos; 
mos << "hello";

We now see an example where this technique is applied to an Encoder class where the encode operation can be performed in this way:

Encoder obj;
obj << "Hello"; //encode the "Hello" string e put it into an Encoder stream

and the decode operation can be performed so
string str;
obj >> str; //decoding in str

Using the code

Here, we will see an example that allows to manipulate a string through the operators << and >> of a derived class from ostream. Furthermore, we create a specialized streamuf class that encodes and decodes a string buffer.

In this example code, like we have explained before, a string can be encoded and decoded in this way:

Encoder y; 
y << "Hello" //encode a string into a stream 

y >> str;  //decode stream into a string

The Encode method simply consists of an ASCII conversion of chars within the string and Decode reverses this manipulation.

#include <string>

#include <fstream>

#include <iostream> 


using namespace std;

class BufferEncoder: public streambuf {
private:
string buffer; //encoded string

int numCar; //chars number of encoded string

public:

BufferEncoder() : streambuf(), numCar(0) {}
~BufferEncoder() {}

//encode a string and put it into BufferEncoder buffer

void Encode(const string& s){
    char tmp[10];
    for (unsigned int i=0; i< s.length(); ++i){
        itoa(s[i],tmp,10);
        buffer+= (string)tmp + (string)" "; //encode in an ASCII value

        numCar +=strlen(tmp)+1;
    }
}

//decode BufferEncoder buffer and return it into s

void Decode(string& s){
    string decodeStr;
    for (int i=0; i< numCar;++i){
        string tokenStr;
        while ((buffer.at(i) != ' ')&& (buffer.at(i)!='\n') && (i< numCar)){
            tokenStr += buffer.at(i);
            i++;
        }
        int v = atoi(tokenStr.c_str());
        decodeStr += (char) v; //decoded char

    }
    s = decodeStr;
}

//add and end of line into buffer 

void EndOfLine() {
   buffer += '\n';
   numCar ++;
}

//return buffer pointer

char* GetBuffer() {return ((char*) buffer.c_str());}
};

class Encoder : public ostream {
private:
    BufferEncoder myStrBuf; 
public: 
    //constructors

    Encoder(filebuf* fb) : ostream(fb),ios(0) {}
    Encoder() : ostream(&myStrBuf),ios(0) {}

    //endl manipulator serialization

    _Myt& operator<<(_Myt&(__cdecl *_Pfn )(_Myt&) ){
        // call basic_ostream manipulator

        //... no others manipulators than endl

        myStrBuf.EndOfLine();
        return ((*_Pfn)(*this));
    }

    //from Encoder to ostream serialization

    friend ostream& operator<<(ostream & s, Encoder& c) {
        s << c.myStrBuf.GetBuffer();
        return s;
    }

    //from const char* to Encoder serialization

    Encoder& operator<<(const char * s) {
        myStrBuf.Encode(s);
        return *this;
    }

    //from Encoder to string serialization

    Encoder& operator>>(string& s) {
        myStrBuf.Decode(s);
        return *this;
    } 
}; 

int main ()
{
    Encoder y;

    //encoding

    y <<"Hello World!";
    cout <<"ENCODED: "<< y << endl;

    //decoding

    string s ;
    y >> s;
    cout << "DECODED: " << s << endl;
    return 0;
}

Points of Interest

This code can help you to learn how to serialize an object (primitive or used defined), to or from an object stream, like predefined objects cin and cout. In fact, like a istream object, cin, and ostream object cout, in C++, you can define derived and user- defined objects from these classes and create methods to or from these objects.

History

  • v 1.1 fixed some code style tricks
  • v 1.0

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here