Boost logo

Boost Users :

Subject: [Boost-users] boost serialization stream error question
From: Gabe Sibley (gabe.sibley_at_[hidden])
Date: 2010-01-31 10:38:39


Dear All,

I'm using boost serialization and have come across issues with "steam error"
when I try to deseriailze from an xml or text archive. Binary archives are
fine, but I can't use binary because my users need xml archives.

The problem is caused by double values less than DBL_MIN. Apparently,
streaming such values in causes the input stream fail_bit to be set, which
causes the serialization lib to throw an exception.

One work around is to make sure all double values are clamped and finite
when the archive is created. I can live with this, esp. since I have
algorithms that will from time to time produce non-finite results.

So far what I've done is just replace BOOST_SERIALIZATION_NVP macro with the
following MAKE_NVP macro that calls "FixReal":

#define BOOST_SERIALIZATION_NVP(name) \
   boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), name )

// Use this macro instead of BOOST_SERIALIZATION_NVP because it fixes
doubles that are not streamable.
// That is, it fixes double values that cause streaming errors.
#define MAKE_NVP(name) \
   boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), FixReal(name) )
// note the call to FixReal

// does nothing -- just pass all non-double types through
template<class T> inline T& FixReal( T& t ) { return t; }

/// Routine to make sure doubles are streamable -- Nan, Inf, etc. cause
stream errors, so we prevent them.
inline double& FixReal( double& d )
{
   if( d < DBL_MIN ) {
       d = DBL_MIN;
   }
   if( d > DBL_MAX ) {
       d = DBL_MAX;
   }
   if( std::isnan(d) ) {
       d = 0;
   }
   if( std::isinf(d) ){
       d = DBL_MAX;
   }
   return d;
}

/// We also need to fix double arrays. The ugly syntax is because
// we have to pass and return a reference to an array.
inline double (&FixReal( double (&d)[2] ))[2]
{
   for( size_t ii = 0; ii < 2; ii++ ){
       FixReal(d[ii]);
   }
   return d;
}

Ok, here's my question: How can I get the "FixReal" functionality above
without having to write a specialized function for every possible double
signature?

For instance, I don't want to have to write

inline double (&FixReal( double (&d)[3] ))[3]
inline double (&FixReal( double (&d)[4] ))[4]
...
etc.

or any of the other POD double signatures possible.

I just want the serialization library to fix the errant double values when I
create the archive.

I guess I could modify the "void save(const double t)" function in
basic_text_oprimitive.hpp to check all doubles, but that seems like a bad
plan.

Any suggestions?

thanks for your help,
Gabe



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net