An Encoder class derived from a stream






3.05/5 (7 votes)
Sep 2, 2004
2 min read

37062

674
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 char
s 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