2 Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
5 #ifndef ASGTOOLS_TPROPERTY_ICC
6 #define ASGTOOLS_TPROPERTY_ICC
8 #include <AsgTools/MessageCheckAsgTools.h>
12 #include <type_traits>
18 /// \brief pack a single string into a property string
19 StatusCode packStringSingle (const std::string& value,
22 /// \brief pack a vector of strings into a property string
23 StatusCode packStringVector (const std::vector<std::string>& value,
26 /// \brief pack a vector of strings into a property string
27 StatusCode packStringMap (const std::map<std::string,std::string>& value,
30 /// \brief unpack a single string from a property string
31 StatusCode unpackStringSingle (const std::string& value,
34 /// \brief unpack a vector of strings from a property string
35 StatusCode unpackStringVector (const std::string& value,
36 std::vector<std::string>& result);
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);
42 /// \brief check for the existence of an output streamer
49 template <typename C> static one test( decltype(&(*(std::ostream*)0 << *(C*)0)));
50 template <typename C> static two test(...);
53 enum { value = sizeof(test<T>(0)) == sizeof(char) };
56 /// \brief check for the existence of conversion to string
58 class HasOStringConvert
63 template <typename C> static one test( decltype((std::string (*(C*)0)))*);
64 template <typename C> static two test(...);
67 enum { value = sizeof(test<T>(0)) == sizeof(char) };
71 /// \brief base class for getting the string content using
72 /// streamers/default conversions
74 bool hasOStreamer = HasOStreamer<T>::value,
75 bool hasOConvert = HasOStringConvert<T>::value>
76 struct GetStringHelperBase
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;
85 template<typename T> struct GetStringHelperBase<T,true,false>
87 static StatusCode get (const T& value, std::string& result) {
88 using namespace msgProperty;
89 std::ostringstream str;
93 return StatusCode::SUCCESS;
96 ANA_MSG_ERROR ("failed to write type " << typeid(T).name() << " to string");
97 return StatusCode::FAILURE;
102 template<typename T,bool X> struct GetStringHelperBase<T,X,true>
104 static StatusCode get (const T& value, std::string& result) {
105 return packStringSingle (std::string (value), result);
109 /// \brief helper class for converting properties to strings
110 template<typename T> struct GetStringHelper : GetStringHelperBase<T>
114 template<typename T> struct GetStringHelper<std::vector<T> >
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);
125 ANA_CHECK (packStringVector (subresult, result));
126 return StatusCode::SUCCESS;
130 template<typename T1,typename T2> struct GetStringHelper<std::map<T1,T2> >
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);
142 ANA_CHECK (packStringMap (subresult, result));
143 return StatusCode::SUCCESS;
149 /// \brief the template overloads for \ref TProperty::getCastString
150 template <typename T>
151 struct GetCastStringHelper
153 static inline StatusCode get (const T& value, std::string& result) {
154 return GetStringHelper<T>::get (value, result);}
158 struct GetCastStringHelper<std::string>
160 static inline StatusCode get (const std::string& value, std::string& result) {
161 result = value; return StatusCode::SUCCESS;}
167 /// \brief check for the existence of an output streamer
168 template <typename T>
174 template <typename C> static one test( decltype(&(*(std::istream*)0 >> *(C*)0)));
175 template <typename C> static two test(...);
178 enum { value = sizeof(test<T>(0)) == sizeof(char) };
181 /// \brief check for the existence of conversion to string
182 template <typename T>
183 class HasIStringConvert
188 template <typename C> static one test( decltype(C (std::string ()))*);
189 template <typename C> static two test(...);
192 enum { value = sizeof(test<T>(0)) == sizeof(char) };
196 /// \brief base class for setting the string content using
197 /// streamers/default conversions
199 bool hasIStreamer = HasIStreamer<T>::value,
200 bool hasOConvert = HasIStringConvert<T>::value,
201 bool isEnum = std::is_enum<T>::value>
202 struct SetStringHelperBase
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;
211 template<typename T> struct SetStringHelperBase<T,true,false,false>
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())
218 return StatusCode::SUCCESS;
221 ANA_MSG_ERROR ("failed to read type " << typeid(T).name() << " from string " << value);
222 return StatusCode::FAILURE;
227 template<typename T,bool X> struct SetStringHelperBase<T,X,true,false>
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;
235 return StatusCode::SUCCESS;
239 template<typename T,bool X,bool Y> struct SetStringHelperBase<T,X,Y,true>
241 static StatusCode set (const std::string& value, T& result) {
242 using namespace msgProperty;
244 if (SetStringHelperBase<int>::set (value, subvalue).isFailure())
245 return StatusCode::FAILURE;
246 result = T (subvalue);
247 return StatusCode::SUCCESS;
251 /// \brief helper class for getting property values from strings
252 // cppcheck-suppress syntaxError
253 template<typename T> struct SetStringHelper : SetStringHelperBase<T>
257 template<typename T> struct SetStringHelper<std::vector<T> >
259 static StatusCode set (const std::string& value, std::vector<T>& result) {
260 using namespace msgProperty;
261 std::vector<std::string> myvalue;
262 ANA_CHECK (unpackStringVector (value, myvalue));
263 std::vector<T> myresult;
264 for (const std::string& subvalue : myvalue) {
266 ANA_CHECK (SetStringHelper<T>::set (subvalue, subresult));
267 myresult.push_back (subresult);
269 swap (myresult, result);
270 return StatusCode::SUCCESS;
274 template<typename T1,typename T2> struct SetStringHelper<std::map<T1,T2> >
276 static StatusCode set (const std::string& value, std::map<T1,T2>& result) {
277 using namespace msgProperty;
278 std::map<std::string,std::string> myvalue;
279 ANA_CHECK (unpackStringMap (value, myvalue));
280 std::map<T1,T2> myresult;
281 for (const auto& subvalue : myvalue) {
284 ANA_CHECK (SetStringHelper<T1>::set (subvalue.first, subresult1));
285 ANA_CHECK (SetStringHelper<T2>::set (subvalue.second, subresult2));
286 myresult.emplace (subresult1, subresult2);
288 swap (myresult, result);
289 return StatusCode::SUCCESS;
295 template< typename T >
296 TProperty< T >::TProperty( T& val, Type type )
297 : Property( type ), m_ptr( &val ) {
301 template< typename T >
302 const T* TProperty< T >::pointer() const {
307 template< typename T >
308 int TProperty< T >::setFrom( const Property& rhs ) {
310 // Check that we have a valid pointer:
311 if( ! this->pointer() ) {
315 // Check if the other object is of the same type:
316 const TProperty< T >* pprop = dynamic_cast< const TProperty< T >* >( &rhs );
318 // Check that the other object has a valid pointer:
319 if( ! pprop->pointer() ) {
323 // Do the assignment:
324 *m_ptr = *( pprop->pointer() );
327 std::string asString;
328 if (rhs.getCastString (asString).isFailure())
330 return this->setString (asString).isFailure();
334 template< typename T >
335 StatusCode TProperty< T >::getString (std::string& result) const {
336 using namespace asg::msgProperty;
337 if( ! this->pointer() ) {
338 ANA_MSG_ERROR ("property does not have a pointer associated");
339 return StatusCode::FAILURE;
341 ANA_CHECK (asg::detail::GetStringHelper<T>::get (*m_ptr, result));
342 return StatusCode::SUCCESS;
345 template< typename T >
346 StatusCode TProperty< T >::getCastString (std::string& result) const {
347 using namespace asg::msgProperty;
348 if( ! this->pointer() ) {
349 ANA_MSG_ERROR ("property does not have a pointer associated");
350 return StatusCode::FAILURE;
352 ANA_CHECK (asg::detail::GetCastStringHelper<T>::get (*m_ptr, result));
353 return StatusCode::SUCCESS;
356 template< typename T >
357 StatusCode TProperty< T >::setString (const std::string& value) {
358 using namespace asg::msgProperty;
359 if( ! this->pointer() ) {
360 ANA_MSG_ERROR ("property does not have a pointer associated");
361 return StatusCode::FAILURE;
363 ANA_CHECK (asg::detail::SetStringHelper<T>::set (value, *m_ptr));
364 return StatusCode::SUCCESS;
367 template< typename T >
368 Property* createProperty( const T& rval ) {
370 return new TProperty< T >( const_cast< T& >( rval ), Property::UNKNOWNTYPE );
373 #endif // ASGTOOLS_TPROPERTY_ICC