Click here to Skip to main content
Click here to Skip to main content

An Encoder class derived from a stream

, 1 Sep 2004
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

Andrea Cacciarru
Engineer
Italy Italy
See Andrea's profile on Linkedin
Follow on   Twitter

Comments and Discussions

 
QuestionTraditional Chinese characters aren’t being read from network stream PinmemberMember 864850821-Mar-12 19:58 
GeneralHello! PinsussCode Inspector2-Sep-04 8:59 
GeneralRe: Hello! PinmemberAndrea Cacciarru2-Sep-04 22:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140814.1 | Last Updated 2 Sep 2004
Article Copyright 2004 by Andrea Cacciarru
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid