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