1 //////////////////////////////////////////////////////////////////////// 2 // valarray.hpp: s11n algos/proxies for handling std::valarray objects. 3 // This header is not included by default: clients who want to de/serialize 4 // valarrays must include it themselves. 5 //////////////////////////////////////////////////////////////////////// 6 #ifndef s11n_VALARRAY_HPP_INCLUDED 7 #define s11n_VALARRAY_HPP_INCLUDED 1 8 9 #include <stdio.h> // snprintf() 10 #include <valarray> 11 #include <s11n.net/s11n/variant.hpp> // for lexical casting 12 13 namespace s11n { 14 15 /** 16 s11n::va encapsulates de/serialization operators for 17 std::valarray objects. 18 */ 19 namespace va { 20 21 /** 22 Serializes src to dest. Returns true on success, 23 false on error. VAT must be a std::valarray type 24 with a numeric value_type. 25 26 Always returns true. 27 28 Each entry is stored as a key/value pair in src, 29 which means this algorithm works with all 30 iostreamable contained types. Since valarray is 31 intended for use with numbers, this should be 32 appropriate for all cases. 33 34 To avoid entering numeric keys into dest, which don't 35 work with XML serializers, and to keep proper ordering of 36 the keys, it synthesizes sequential numbers, preceded by 37 an 'x', for use as keys. The number of digits in the keys 38 is calculated based off of src.size(). 39 40 This function never returns false, but will throw if 41 src has more than some arbitrarily large number of items 42 (at least 64 bits worth), due to a minor detail you can 43 read about in the source code. 44 45 ACHTUNG: precision of doubles in limited to 46 whatever default is used by s11n for lexical 47 casting via iostreams. 48 */ 49 template <typename NodeT, typename VAT> serialize_valarray(NodeT & dest,const VAT & src)50 bool serialize_valarray( NodeT & dest, const VAT & src ) 51 { 52 typedef s11n::node_traits<NodeT> TR; 53 TR::class_name( dest, ::s11n::s11n_traits<VAT>::class_name(&src) ); 54 const int buffsize = 9; // leaves us with 8 hex digits, which is more than your system can hold in one valarray, i would think. 55 char num[buffsize]; 56 char fmt[buffsize]; 57 size_t sz = src.size(); 58 int places = 1; // # of digits to use 59 for( ; sz >= 0x0f; sz = (size_t)(sz/0x0f)) { ++places; } 60 if( places > (buffsize-1) ) 61 { 62 throw ::s11n::s11n_exception( "%s:%d: Internal error: overflow in serialize_valarray(). Too many items in valarray.", __FILE__,__LINE__); 63 } 64 snprintf( fmt, buffsize, "x%%0%dx", places ); // e.g. 5 digits evals to "x%05x" 65 sz = src.size(); 66 TR::set( dest, "size", sz ); 67 for( size_t i = 0 ; i < sz; i++ ) 68 { 69 snprintf( num, buffsize, fmt, i ); 70 TR::set( dest, num, src[i] ); 71 } 72 return true; 73 } 74 75 /** 76 Deserializes dest from src. Returns true on 77 success, false on error. VAT must be a 78 std::valarray type with a numeric value_type. 79 80 Always returns true. 81 */ 82 template <typename NodeT, typename VAT> deserialize_valarray(const NodeT & src,VAT & dest)83 bool deserialize_valarray( const NodeT & src, VAT & dest ) 84 { 85 typedef ::s11n::node_traits<NodeT> TR; 86 typedef typename VAT::value_type VT; 87 typename TR::property_map_type::const_iterator it = TR::properties(src).begin(); 88 typename TR::property_map_type::const_iterator et = TR::properties(src).end(); 89 const static std::string szkey = "size"; 90 size_t size = TR::get( src, szkey, dest.size() ); 91 VT defaultval; 92 dest.resize( size, defaultval ); 93 size_t i = 0; 94 for( ; et != it; ++it ) 95 { 96 if( szkey == (*it).first ) continue; 97 dest[i++] = ::s11n::Detail::variant( (*it).second ).template cast_to<VT>( defaultval ); 98 } 99 return true; 100 } 101 102 /** 103 A Serializable proxy for valarray types. 104 */ 105 struct valarray_serializable_proxy 106 { 107 valarray_serializable_proxys11n::va::valarray_serializable_proxy108 valarray_serializable_proxy() 109 {} 110 111 /** 112 see serialize_valarray(). 113 114 */ 115 template <typename NodeType, typename SerType> operator ()s11n::va::valarray_serializable_proxy116 bool operator()( NodeType & dest, const SerType & src ) const 117 { 118 return serialize_valarray( dest, src ); 119 } 120 121 /** see deserialize_valarray(). */ 122 template <typename NodeType, typename SerType> operator ()s11n::va::valarray_serializable_proxy123 bool operator()( const NodeType & src, SerType & dest ) const 124 { 125 return deserialize_valarray( src, dest ); 126 } 127 }; 128 129 } // namespace va 130 131 132 133 /** 134 s11n_traits<> specialization for std::valarray types. 135 */ 136 template <typename ValueType> 137 struct s11n_traits < std::valarray<ValueType> > 138 { 139 typedef std::valarray<ValueType> serializable_type; 140 typedef ::s11n::va::valarray_serializable_proxy serialize_functor; 141 typedef serialize_functor deserialize_functor; 142 typedef ::s11n::cl::object_factory<serializable_type> factory_type; 143 typedef ::s11n::default_cleanup_functor<serializable_type> cleanup_functor; 144 static bool cl_reg_placeholder; class_names11n::s11n_traits145 static std::string class_name( const serializable_type * instance_hint ) 146 { 147 if( cl_reg_placeholder == true ); // just to reference it. w/o this cl reg never happens :( 148 return "valarray"; 149 } 150 }; 151 152 template <typename VT> 153 bool s11n_traits< std::valarray< VT > >::cl_reg_placeholder = 154 ( 155 ::s11n::cl::classloader_register_base<std::valarray< VT > >( s11n_traits< std::valarray< VT > >::class_name(0) ) 156 , 0 ); 157 158 159 } // namespace s11n 160 161 162 163 #endif // s11n_VALARRAY.HPP_HPP_INCLUDED 164