ATLAS Offline Software
Loading...
Searching...
No Matches
TProperty.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef ASGTOOLS_TPROPERTY_ICC
6#define ASGTOOLS_TPROPERTY_ICC
7
8#include <AsgTools/MessageCheckAsgTools.h>
9#include <map>
10#include <sstream>
11#include <typeinfo>
12#include <type_traits>
13
14namespace asg
15{
16 namespace detail
17 {
18 /// \brief pack a single string into a property string
19 StatusCode packStringSingle (const std::string& value,
20 std::string& result);
21
22 /// \brief pack a vector of strings into a property string
23 StatusCode packStringVector (const std::vector<std::string>& value,
24 std::string& result);
25
26 /// \brief pack a vector of strings into a property string
27 StatusCode packStringMap (const std::map<std::string,std::string>& value,
28 std::string& result);
29
30 /// \brief unpack a single string from a property string
31 StatusCode unpackStringSingle (const std::string& value,
32 std::string& result);
33
34 /// \brief unpack a vector of strings from a property string
35 StatusCode unpackStringVector (const std::string& value,
36 std::vector<std::string>& result);
37
38 /// \brief unpack a vector of strings from a property string
39 StatusCode unpackStringMap (const std::string& value,
40 std::map<std::string,std::string>& result);
41
42 /// \brief check for the existence of an output streamer
43 template <typename T>
44 class HasOStreamer
45 {
46 typedef char one;
47 typedef long two;
48
49 template <typename C> static one test( decltype(&(*(std::ostream*)0 << *(C*)0)));
50 template <typename C> static two test(...);
51
52 public:
53 enum { value = sizeof(test<T>(0)) == sizeof(char) };
54 };
55
56 /// \brief check for the existence of conversion to string
57 template <typename T>
58 class HasOStringConvert
59 {
60 typedef char one;
61 typedef long two;
62
63 template <typename C> static one test( decltype((std::string (*(C*)0)))*);
64 template <typename C> static two test(...);
65
66 public:
67 enum { value = sizeof(test<T>(0)) == sizeof(char) };
68 };
69
70
71 /// \brief base class for getting the string content using
72 /// streamers/default conversions
73 template<typename T,
74 bool hasOStreamer = HasOStreamer<T>::value,
75 bool hasOConvert = HasOStringConvert<T>::value>
76 struct GetStringHelperBase
77 {
78 static StatusCode get (const T& /*value*/, std::string& /*result*/) {
79 using namespace msgProperty;
80 ANA_MSG_ERROR ("GetStringHelper: not implemented for " << typeid (T).name());
81 return StatusCode::FAILURE;
82 }
83 };
84
85 template<typename T> struct GetStringHelperBase<T,true,false>
86 {
87 static StatusCode get (const T& value, std::string& result) {
88 using namespace msgProperty;
89 std::ostringstream str;
90 if (str << value)
91 {
92 result = str.str();
93 return StatusCode::SUCCESS;
94 } else
95 {
96 ANA_MSG_ERROR ("failed to write type " << typeid(T).name() << " to string");
97 return StatusCode::FAILURE;
98 }
99 }
100 };
101
102 template<typename T,bool X> struct GetStringHelperBase<T,X,true>
103 {
104 static StatusCode get (const T& value, std::string& result) {
105 return packStringSingle (std::string (value), result);
106 }
107 };
108
109 /// \brief helper class for converting properties to strings
110 template<typename T> struct GetStringHelper : GetStringHelperBase<T>
111 {
112 };
113
114 template<typename T> struct GetStringHelper<std::vector<T> >
115 {
116 static StatusCode get (const std::vector<T>& value,
117 std::string& result) {
118 using namespace msgProperty;
119 std::vector<std::string> subresult;
120 for (const auto& subvalue : value) {
121 std::string myresult;
122 ANA_CHECK (GetStringHelper<T>::get (subvalue, myresult));
123 subresult.push_back (myresult);
124 }
125 ANA_CHECK (packStringVector (subresult, result));
126 return StatusCode::SUCCESS;
127 }
128 };
129
130 template<typename T1,typename T2> struct GetStringHelper<std::map<T1,T2> >
131 {
132 static StatusCode get (const std::map<T1,T2>& value,
133 std::string& result) {
134 using namespace msgProperty;
135 std::map<std::string,std::string> subresult;
136 for (const auto& subvalue : value) {
137 std::string myresult1, myresult2;
138 ANA_CHECK (GetStringHelper<T1>::get (subvalue.first, myresult1));
139 ANA_CHECK (GetStringHelper<T2>::get (subvalue.second, myresult2));
140 subresult.emplace (myresult1, myresult2);
141 }
142 ANA_CHECK (packStringMap (subresult, result));
143 return StatusCode::SUCCESS;
144 }
145 };
146
147
148
149 /// \brief the template overloads for \ref TProperty::getCastString
150 template <typename T>
151 struct GetCastStringHelper
152 {
153 static inline StatusCode get (const T& value, std::string& result) {
154 return GetStringHelper<T>::get (value, result);}
155 };
156
157 template <>
158 struct GetCastStringHelper<std::string>
159 {
160 static inline StatusCode get (const std::string& value, std::string& result) {
161 result = value; return StatusCode::SUCCESS;}
162 };
163
164
165
166
167 /// \brief check for the existence of an output streamer
168 template <typename T>
169 class HasIStreamer
170 {
171 typedef char one;
172 typedef long two;
173
174 template <typename C> static one test( decltype(&(*(std::istream*)0 >> *(C*)0)));
175 template <typename C> static two test(...);
176
177 public:
178 enum { value = sizeof(test<T>(0)) == sizeof(char) };
179 };
180
181 /// \brief check for the existence of conversion to string
182 template <typename T>
183 class HasIStringConvert
184 {
185 typedef char one;
186 typedef long two;
187
188 template <typename C> static one test( decltype(C (std::string ()))*);
189 template <typename C> static two test(...);
190
191 public:
192 enum { value = sizeof(test<T>(0)) == sizeof(char) };
193 };
194
195
196 /// \brief base class for setting the string content using
197 /// streamers/default conversions
198 template<typename T,
199 bool hasIStreamer = HasIStreamer<T>::value,
200 bool hasOConvert = HasIStringConvert<T>::value,
201 bool isEnum = std::is_enum<T>::value>
202 struct SetStringHelperBase
203 {
204 static StatusCode set (const std::string& /*value*/, T& /*result*/) {
205 using namespace msgProperty;
206 ANA_MSG_ERROR ("SetStringHelper: not implemented for " << typeid (T).name());
207 return StatusCode::FAILURE;
208 }
209 };
210
211 template<typename T> struct SetStringHelperBase<T,true,false,false>
212 {
213 static StatusCode set (const std::string& value, T& result) {
214 using namespace msgProperty;
215 std::istringstream str (value);
216 if (str >> result && str.eof())
217 {
218 return StatusCode::SUCCESS;
219 } else
220 {
221 ANA_MSG_ERROR ("failed to read type " << typeid(T).name() << " from string " << value);
222 return StatusCode::FAILURE;
223 }
224 }
225 };
226
227 template<typename T,bool X> struct SetStringHelperBase<T,X,true,false>
228 {
229 static StatusCode set (const std::string& value, T& result) {
230 using namespace msgProperty;
231 std::string subvalue;
232 if (unpackStringSingle (value, subvalue).isFailure())
233 return StatusCode::FAILURE;
234 result = subvalue;
235 return StatusCode::SUCCESS;
236 }
237 };
238
239 template<typename T,bool X,bool Y> struct SetStringHelperBase<T,X,Y,true>
240 {
241 static StatusCode set (const std::string& value, T& result) {
242 using namespace msgProperty;
243 int subvalue = 0;
244 if (SetStringHelperBase<int>::set (value, subvalue).isFailure())
245 return StatusCode::FAILURE;
246 result = T (subvalue);
247 return StatusCode::SUCCESS;
248 }
249 };
250
251 /// \brief helper class for getting property values from strings
252 template<typename T> struct SetStringHelper : SetStringHelperBase<T>
253 {
254 };
255
256 template<typename T> struct SetStringHelper<std::vector<T> >
257 {
258 static StatusCode set (const std::string& value, std::vector<T>& result) {
259 using namespace msgProperty;
260 std::vector<std::string> myvalue;
261 ANA_CHECK (unpackStringVector (value, myvalue));
262 std::vector<T> myresult;
263 for (const std::string& subvalue : myvalue) {
264 T subresult {};
265 ANA_CHECK (SetStringHelper<T>::set (subvalue, subresult));
266 myresult.push_back (subresult);
267 }
268 swap (myresult, result);
269 return StatusCode::SUCCESS;
270 }
271 };
272
273 template<typename T1,typename T2> struct SetStringHelper<std::map<T1,T2> >
274 {
275 static StatusCode set (const std::string& value, std::map<T1,T2>& result) {
276 using namespace msgProperty;
277 std::map<std::string,std::string> myvalue;
278 ANA_CHECK (unpackStringMap (value, myvalue));
279 std::map<T1,T2> myresult;
280 for (const auto& subvalue : myvalue) {
281 T1 subresult1 {};
282 T2 subresult2 {};
283 ANA_CHECK (SetStringHelper<T1>::set (subvalue.first, subresult1));
284 ANA_CHECK (SetStringHelper<T2>::set (subvalue.second, subresult2));
285 myresult.emplace (subresult1, subresult2);
286 }
287 swap (myresult, result);
288 return StatusCode::SUCCESS;
289 }
290 };
291 }
292}
293
294template< typename T >
295TProperty< T >::TProperty( T& val, Type type )
296 : Property( type ), m_ptr( &val ) {
297
298}
299
300template< typename T >
301const T* TProperty< T >::pointer() const {
302
303 return m_ptr;
304}
305
306template< typename T >
307int TProperty< T >::setFrom( const Property& rhs ) {
308
309 // Check that we have a valid pointer:
310 if( ! this->pointer() ) {
311 return 1;
312 }
313
314 // Check if the other object is of the same type:
315 const TProperty< T >* pprop = dynamic_cast< const TProperty< T >* >( &rhs );
316 if( pprop ) {
317 // Check that the other object has a valid pointer:
318 if( ! pprop->pointer() ) {
319 return 1;
320 }
321
322 // Do the assignment:
323 *m_ptr = *( pprop->pointer() );
324 return 0;
325 } else {
326 std::string asString;
327 if (rhs.getCastString (asString).isFailure())
328 return 1;
329 return this->setString (asString).isFailure();
330 }
331}
332
333template< typename T >
334StatusCode TProperty< T >::getString (std::string& result) const {
335 using namespace asg::msgProperty;
336 if( ! this->pointer() ) {
337 ANA_MSG_ERROR ("property does not have a pointer associated");
338 return StatusCode::FAILURE;
339 }
340 ANA_CHECK (asg::detail::GetStringHelper<T>::get (*m_ptr, result));
341 return StatusCode::SUCCESS;
342}
343
344template< typename T >
345StatusCode TProperty< T >::getCastString (std::string& result) const {
346 using namespace asg::msgProperty;
347 if( ! this->pointer() ) {
348 ANA_MSG_ERROR ("property does not have a pointer associated");
349 return StatusCode::FAILURE;
350 }
351 ANA_CHECK (asg::detail::GetCastStringHelper<T>::get (*m_ptr, result));
352 return StatusCode::SUCCESS;
353}
354
355template< typename T >
356StatusCode TProperty< T >::setString (const std::string& value) {
357 using namespace asg::msgProperty;
358 if( ! this->pointer() ) {
359 ANA_MSG_ERROR ("property does not have a pointer associated");
360 return StatusCode::FAILURE;
361 }
362 ANA_CHECK (asg::detail::SetStringHelper<T>::set (value, *m_ptr));
363 return StatusCode::SUCCESS;
364}
365
366template< typename T >
367Property* createProperty( const T& rval ) {
368
369 return new TProperty< T >( const_cast< T& >( rval ), Property::UNKNOWNTYPE );
370}
371
372#endif // ASGTOOLS_TPROPERTY_ICC