Creating and Using Chains of Streaming Elements
A chain of streaming elements is the composition of a single terminal streaming element with one or more filtered stream elements. The terminal streaming element is constructed first and then passed to a filtered stream constructor, which in turn can be passed to another filtered stream constructor. Each streaming element is responsible for a particular task and is independent of the task performed by other streaming elements. The filtered stream elements are not aware of the real type of the streaming element that is used internally. They are linked to it by a handle instance.
Output Example
The first example shows how to create and use a chain of streaming elements. It creates a Unicode character output stream that encodes UTF-16 characters using the UCS Transformation Format 8-bit form (UTF-8). The UTF-8 Unicode stream is connected to a buffered binary output stream that sends the transformed bytes to a file:
Figure 13 is a representation of the chain of streaming elements used in this example.
The complete example is located in directory ...\examples\stream in the file UnicodeCharacterFilteredWrite.cpp. Only part of the code is presented below.
RWUChar array[17]= {0x0F00, 0x0F13, 0x0F0A, 0x0F3B, 0x0F8A, 0x0F68,
0x0F35, 0x0F61, 0x0F43, 0x0F39, 0x0F7F, 0x0F1E,
0x0F86, 0x0FA4, 0x0F91, 0x0F88, 0x0F0F}; // 1
// initialize the array of UTF-16 character
filebuf fbuf; // 2
fbuf.open("UnicodeCharacterFilteredWrite.dat", ios::out |
ios::binary);
RWByteOutputStream binOutputStream =
RWByteToStreambufOutputStreamImp::make(fbuf); // 3
RWByteOutputStream bufferedBinOutputStream=
RWBufferedByteOutputStreamImp::make(binOutputStream,1024); // 4
RWUCharOutputStream UTF8OutputStream=
RWUCharToUTF8ByteOutputStreamImp::make(bufferedBinOutputStream);// 5
try {
RWSize i;
for(i=0; i<17; i++)
UTF8OutputStream << array[i]; // 6
for(i=0; i<17; i++)
UTF8OutputStream.write(array[i]); // 7
UTF8OutputStream.write(array,17); // 8
}
catch(const RWIncompleteStreamOperation& e) { // 9
cout << e.why() << endl;
cout << e.elementsProcessed() << endl;
}
catch(const RWExternalStreamException& e) {
cout << e.why() << endl;
}
UTF8OutputStream << array[0] << array[1] << array[2] << rwFlush;
Class
RWExternalStreamException returns an error message and an error code. Class
RWIncompleteStreamOperation inherits from class
RWExternalStreamException and is thrown when an operation partially succeeds. In the above example, writing an array of UTF-16 characters might fail after writing some of the characters. An instance of class
RWIncompleteStreamOperation can be queried for the number of elements successfully written. For more information on exceptions, see
“Error Handling.”Input Example
The next example implements the previous example’s corresponding input operation. It creates a UTF-16 character input stream that decodes UTF-16 characters using the UTF-8 form. The UTF-8 Unicode stream is connected to a buffered binary input stream that gets bytes from the file created in the previous example. The class
RWUCharFromUTF8ByteInputStreamImp converts the bytes into UTF-16 characters. The class
RWBufferedByteInputStreamImp is connected to class
RWByteFromStreambufInputStreamImp to provide the buffered byte input stream.
Figure 14 is a representation of the chain of streaming elements used in this example.
The complete example is located in directory ...\examples\stream in the file UnicodeCharacterFilteredRead.cpp. Only part of the code is presented below.
filebuf fbuf; // 1
fbuf.open("UnicodeCharacterFilteredWrite.dat", ios::in |
ios::binary);
RWByteInputStream binInputStream =
RWByteFromStreambufInputStreamImp::make(fbuf); // 2
RWByteInputStream bufferedBinInputStream=
RWBufferedByteInputStreamImp::make(binInputStream,1024); // 3
RWUCharInputStream UTF8InputStream=
RWUCharFromUTF8ByteInputStreamImp::make(bufferedBinInputStream);// 4
try {
RWSize i;
RWUChar theUChar; // 5
for(i=0; i<17; i++) {
UTF8InputStream >> theUChar; // 6
// do something with the UTF-16 character read
}
for(i=0; i<17; i++) {
theUChar= UTF8InputStream.read(); // 7
// do something with the value read
}
RWUChar array[17];
RWSize read_= UTF8InputStream.read(array,17); // 8
cout << "The number of Unicode character(s) read is: "
<< read_ << endl;
// do something with the array of UTF-16 characters
RWUChar until_= 0x0F7F;
read_= UTF8InputStream.readUntil(array,17,until_); // 9
if(UTF8InputStream.isGood()) //10
cout << "The operation succeeded\n";
cout << "The number of Unicode character(s) stored is: "
<< read_ << endl;
// do something with the array of UTF-16 character(s)
if (UTF8InputStream.isGood()) //10
cout << "The stream is in a valid state" << endl;
else
cout << "The stream is in error state" << endl;
if(UTF8InputStream.isEof()) //11
cout << "There is no more data available for reading"
<< endl;
else {
while(!UTF8InputStream.isEof()) //11
theUChar= UTF8InputStream.read();
// do something with the UTF-16 Character
} //end else
} // end try
catch(const RWExternalStreamException& e) { //12
cout << e.why() << endl;
}
RWUChar value1, value2, value3;
UTF8InputStream >> value1 >> value2 >> value3;