Advanced Tools Module User’s Guide : PART II Advanced Tools Module Packages : Chapter 4 Using Streams : Examples : Creating and Using Stream Adapter Classes
Creating and Using Stream Adapter Classes
The stream adapter classes adapt other streaming interfaces to the Advanced Tools Module streaming interface. This means that an application designed to use a streaming library such as iostreams can instantly use the Advanced Tools Module Streams package by using an adapter class as the first streaming element.
The Streams package contains adapter classes for both the iostreams library and the Essential Tools Module virtual streams.
The iostreams Adapter Classes
The Streams package has four adapter classes that implement the iostreams streambuf interface:
RWStreambufToByteOutputStream, which implements the iostreams streambuf interface and forwards to an Advanced Tools Module binary output stream
RWStreambufFromByteInputStream, which implements the iostreams streambuf interface and forwards to an Advanced Tools Module binary input stream
RWStreambufToCharOutputStream, which implements the iostreams streambuf interface and forwards to an Advanced Tools Module narrow character output stream
RWStreambufFromCharInputStream, which implements the iostreams streambuf interface and forwards to an Advanced Tools Module narrow character input stream
The iostreams adapter classes support both the Standard (as described in the C++ standard) and classic iostreams libraries.
Virtual Streams Adapter Classes in the Essential Tools Module
The Streams package has two adapter classes that implement the Essential Tools Module virtual input/output stream interface:
RWvostreamToDataOutputStream, which implements the Essential Tools Module vostream interface and forwards to an Advanced Tools Module data output stream
RWvistreamFromDataInputStream, which implements the Essential Tools Module vistream interface and forwards to an Advanced Tools Module data input stream
Architecture of the Adapter Classes
The main architectural difference between the stream adapter classes and the other stream concrete classes is that the adapter classes are not constructed using a public static make() function, and they are not manipulated using a handle class. The adapter classes provide a public constructor that takes a handle to the stream element to which they forward a request.
Using the Adapter Classes for Output
The first example of the Streams package’s adapter classes creates a RWStreambufToCharOutputStream object that connects to an instance of class RWCharToStreambufOutputStreamImp, which in turn uses an iostreams filebuf as a sink of narrow characters. The instance of the adapter class RWStreambufToCharOutputStream is used to construct an iostreams object of type ostream, which is used as the sink of data in the rest of the example.
Figure 17 is a representation of the chain of streaming elements used in this example.
Figure 17 – Streaming with adapter classes—output
The complete example is located in directory ...\examples\stream in the file adapterWrite.cpp. Only part of the code is presented below.
 
filebuf fbuf; // 1
fbuf.open("adaptorWrite.dat", ios::out);
 
RWCharOutputStream charOutputStream =
RWCharToStreambufOutputStreamImp::make(fbuf); // 2
 
RWStreambufToCharOutputStream streambufAdaptor(charOutputStream);// 3
 
ostream os(&streambufAdaptor); // 4
 
try {
double f= 3.14159;
int i= 567;
char* text="Wagabunga";
 
// insert a bunch of things
os << f << ' ' << i << ' ' << text; // 5
}
catch(const RWIncompleteStreamOperation& e) { // 6
cout << e.why() << endl;
cout << e.elementsProcessed() << endl;
}
catch(const RWExternalStreamException& e) {
cout << e.why() << endl;
}
//1 Creates an iostreams file buffer, and opens it in output mode. If you built the Advanced Tools Module with the Standard iostreams library, you need to qualify filebuf and other iostreams elements with std::, or you need to include using declarations. The complete example code makes use of macros defined by the Essential Tools Module in order to support both the classic and Standard iostreams.
//2 Creates an instance of class RWCharToStreambufOutputStreamImp. The class is created by calling its static member function make(), which creates an instance of self and returns it as a narrow character output stream handle. In this example the make() function takes a reference to an iostreams streambuf object that is used as the sink of bytes.
//3 Creates the adapter class that implements the iostreams streambuf interface and forwards request to an Advanced Tools Module narrow character output stream.
//4 Creates an iostreams ostream object that uses the previously created adapter class as the sink of narrow characters.
//5 Uses the ostream object.
//6 Catches exceptions potentially thrown by the stream. The Streams package defines two exception classes: RWExternalStreamException and RWIncompleteStreamOperation. Class RWExternalStreamException returns an error message and an error code. Class RWIncompleteStreamOperation inherits from class RWExternalStreamException, and is thrown when an operation partially succeeds. An instance of class RWIncompleteStreamOperation can be queried for the number of elements successfully written. For more information on exceptions, see “Error Handling.”
Using the Adapter Classes for Input
The following example implements the previous example’s corresponding input operation. It creates a RWStreambufFromCharInputStream object that connects to an instance of class RWCharFromStreambufInputStreamImp, which in turn uses an iostreams filebuf as a source of narrow characters. The instance of the adapter class RWStreambufFromCharInputStream is used to construct an iostreams object of type istream, which is used as the source of data in the rest of the example.
Figure 18 is a representation of the chain of streaming elements used in this example.
Figure 18 – Streaming with adapter classes—input
The complete example is located in directory ...\examples\stream in the file adapterRead.cpp. Only part of the code is presented below.
 
filebuf fbuf; // 1
fbuf.open("adaptorWrite.dat", ios::in);
 
RWCharInputStream charInputStream =
RWCharFromStreambufInputStreamImp::make(fbuf); // 2
 
RWStreambufFromCharInputStream streambufAdaptor(charInputStream);// 3
 
istream is(&streambufAdaptor); // 4
 
try {
double f;
int i;
char text[40];
 
// extract a bunch of things
is >> f >> i >> text; // 5
 
cout << '\n' << f << '\n' << i << '\n' << text << '\n' << endl;
}
catch(const RWIncompleteStreamOperation& e) { // 6
cout << e.why() << endl;
cout << e.elementsProcessed() << endl;
}
catch(const RWExternalStreamException& e) {
cout << e.why() << endl;
}
//1 Creates an iostreams file buffer, and opens it in input mode. If you built the Advanced Tools Module with the Standard iostreams library, you need to qualify filebuf and other iostreams elements with std::, or you need to include using declarations. The complete example makes use of macros defined by the Essential Tools Module in order to support both the classic and Standard iostreams.
//2 Creates an instance of class RWCharFromStreambufInputStreamImp. The class is created by calling its static member function make(), which creates an instance of self and returns it as a narrow character input stream handle. In this example the make() function takes a reference to an iostreams streambuf object that is used as the source of narrow characters.
//3 Creates the adapter class that implement the iostreams streambuf interface and forwards a request to an Advanced Tools Module narrow character input stream.
//4 Creates an iostreams istream object that uses the previously created adapter class as the source of narrow characters.
//5 Uses the istream object.
//6 Catches exceptions potentially thrown by the stream. The Streams package defines two exception classes: RWExternalStreamException and RWIncompleteStreamOperation. Class RWExternalStreamException returns an error message and an error code. Class RWIncompleteStreamOperation inherits from class RWExternalStreamException and is thrown when an operation partially succeeds. An instance of class RWIncompleteStreamOperation can be queried for the number of elements successfully read. For more information on exceptions, see “Error Handling.”