Writing Custom streamContents() Functions
For classes with complicated designs, the Serialization package includes macros that enable you to use custom code.
For example, your program might use a class that has a C++ array as a data member. You can pass C++ statements to the RW_WHEN_INPUT() macro in its body argument; the statements are executed only during an input operation. You can also pass C++ statements to the RW_WHEN_OUTPUT() macro in its body argument; these statements are executed only during an output operation.
Within custom code, the current object input stream can be referred to using the RW_INPUT_STREAM macro, and the current object output stream by the RW_OUTPUT_STREAM macro.
 
// examples\serial\other\residential.h
 
class residential : public real_property
{
RW_DECLARE_VIRTUAL_STREAM_FNS(residential)
RW_DECLARE_FRIEND_CTOR_METHOD(real_property, residential)
 
public:
residential()
: shown_(0), dates_shown_(0)
{}
 
residential(const RWCString& address, const RWCString& size,
unsigned long footage, unsigned long shown,
const RWDate* dates)
: real_property(address, size), footage_(footage),
shown_(shown), dates_shown_(0) {
shown_ = shown;
if (shown) {
dates_shown_ = new RWDate[shown];
for (size_t i = 0; i < shown; i++) {
dates_shown_[i] = dates[i];
}
}
}
 
~residential() {
delete [] dates_shown_;
}
 
bool operator== (const residential& prop) const {
return real_property::operator==(prop);
}
 
private:
long footage_;
long shown_;
RWDate *dates_shown_; // 1
};
//1 The dates_shown_ member is an array of dates. The shown_ member indicates how many elements are in the array. In this example the array passed as a parameter to the constructor is copied element by element into the newly allocated array pointed to by dates_shown_. dates_shown_ is always 0 if the array is empty.
The custom streamContents() function now looks like the following code sample:
 
// examples\serial\other\residential.cpp
 
RW_BEGIN_STREAM_CONTENTS(residential)
{
RW_STREAM_PARENT(real_property)
RW_STREAM_ATTR_MEMBER(footage, footage_)
RW_STREAM_ATTR_MEMBER(shown, shown_) //1
RW_WHEN_INPUT( {
if (shown_) {
delete dates_shown_;
dates_shown_ = new RWDate[shown_]; //2
}
 
for (unsigned long i = 0; i < shown_; i++) {
RW_INPUT_STREAM >> dates_shown_[i];
}
})
 
RW_WHEN_OUTPUT( {
for (unsigned long i = 0; i < shown_; i++) { //3
RW_OUTPUT_STREAM << dates_shown_[i];
}
})
}
RW_END_STREAM_CONTENTS
//1 Read in or write out the size of the array.
//2 Reallocate the array when reading data in. This macro produces no code for an output stream. The size is already obtained from the stream.
//3 Iterate through the array, reading or writing as appropriate for the stream. The code passed to the RW_WHEN_INPUT macro is used for input streams, and the code passed to the RW_WHEN_OUTPUT macro is used for output streams.