Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:55:36

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 // ============================================================================
0012 #ifndef GAUDIPROPERTYPARSERS_PARSERVALUETOSTREAM_H
0013 #define GAUDIPROPERTYPARSERS_PARSERVALUETOSTREAM_H 1
0014 // ============================================================================
0015 // Include files
0016 // ============================================================================
0017 // STD & STL
0018 // ============================================================================
0019 #include <array>
0020 #include <iomanip>
0021 #include <iostream>
0022 #include <list>
0023 #include <map>
0024 #include <set>
0025 #include <sstream>
0026 #include <string>
0027 #include <unordered_set>
0028 #include <vector>
0029 // ============================================================================
0030 // GaudiKernel
0031 // ============================================================================
0032 #include <GaudiKernel/HashMap.h>
0033 #include <GaudiKernel/Map.h>
0034 #include <GaudiKernel/SerializeSTL.h>
0035 #include <GaudiKernel/VectorMap.h>
0036 // ============================================================================
0037 /** @file GaudiKernel/ToStream.h
0038  *  implementation of various functions for streaming.
0039  *  this functionality is essential for usage of various types as property for
0040  *  the various Gaudi components
0041  *  @attention the implementation of the specific specializations must be done
0042  *                    before the inclusion of this file
0043  *  @todo ToStream.h : reimplement in terms of functors, to allow
0044  *                     easier specializations
0045  */
0046 // ============================================================================
0047 namespace Gaudi {
0048   // ==========================================================================
0049   namespace Utils {
0050     // ========================================================================
0051     /** the generic implementation of the printout to the std::ostream
0052      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0053      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0054      *  @date 2006-05-12
0055      */
0056     template <class TYPE>
0057     std::ostream& toStream( const TYPE& obj, std::ostream& s );
0058     // ========================================================================
0059     /** the helper function to print the sequence
0060      *  @param first (INPUT)  begin-iterator for the sequence
0061      *  @param last  (INPUT)  end-iterator for the sequence
0062      *  @param s     (UPDATE) the stream itself
0063      *  @param open  (INPUT)  "open"-symbol
0064      *  @param close (INPUT)  "close"-symbol
0065      *  @param delim (INPUT)  "delimiter"-symbol
0066      *  @return the stream
0067      *  @author Vanya BELYAEV Ivan.BElyaev@nikhef.nl
0068      *  @date 2009-09-15
0069      */
0070     template <class ITERATOR>
0071     inline std::ostream& toStream( ITERATOR           first,   // begin of the sequence
0072                                    ITERATOR           last,    //   end of the sequence
0073                                    std::ostream&      s,       //            the stream
0074                                    const std::string& open,    //               opening
0075                                    const std::string& close,   //               closing
0076                                    const std::string& delim ); //             delimiter
0077     // ========================================================================
0078     /** the printtout of the strings.
0079      *  the string is printed a'la Python using the quotes
0080      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0081      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0082      *  @date 2006-05-12
0083      */
0084     inline std::ostream& toStream( const std::string& obj, std::ostream& s ) { return s << std::quoted( obj, '\'' ); }
0085     /** the printout of boolean values "a'la Python"
0086      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0087      *  @date 2006-09-09
0088      */
0089     inline std::ostream& toStream( const bool obj, std::ostream& s ) { return s << ( obj ? "True" : "False" ); }
0090     /** the printout of float values with the reasonable precision
0091      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0092      *  @date 2006-09-09
0093      */
0094     inline std::ostream& toStream( const float obj, std::ostream& s, const int prec = 6 ) {
0095       const int p = static_cast<int>( s.precision() );
0096       return s << std::setprecision( prec ) << obj << std::setprecision( p );
0097     }
0098     /** the printout of double values with the reasonable precision
0099      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0100      *  @date 2006-09-09
0101      */
0102     inline std::ostream& toStream( const double obj, std::ostream& s, const int prec = 8 ) {
0103       const int p = static_cast<int>( s.precision() );
0104       return s << std::setprecision( prec ) << obj << std::setprecision( p );
0105     }
0106     /** the printout of long double values with the reasonable precision
0107      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0108      *  @date 2006-09-09
0109      */
0110     inline std::ostream& toStream( const long double obj, std::ostream& s, const int prec = 10 ) {
0111       const int p = static_cast<int>( s.precision() );
0112       return s << std::setprecision( prec ) << obj << std::setprecision( p );
0113     }
0114     // ========================================================================
0115     /** the partial template specialization of
0116      *  <c>std::pair<KTYPE,VTYPE></c> printout
0117      *  the pair is printed a'la Python tuple: " ( a , b )"
0118      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0119      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0120      *  @date 2006-05-12
0121      */
0122     template <class KTYPE, class VTYPE>
0123     inline std::ostream& toStream( const std::pair<KTYPE, VTYPE>& obj, std::ostream& s ) {
0124       return toStream( obj.second, toStream( obj.first, s << "( " ) << " , " ) << " )";
0125     }
0126 
0127     template <typename... Args>
0128     inline std::ostream& toStream( const std::tuple<Args...>& tuple, std::ostream& s );
0129 
0130     // ========================================================================
0131     /** the partial template specialization of <c>std::vector<TYPE,ALLOCATOR></c>
0132      *  printout. The vector is printed a'la Python list: "[ a, b, c ]"
0133      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0134      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0135      *  @date 2006-05-12
0136      */
0137     template <class TYPE, class ALLOCATOR>
0138     inline std::ostream& toStream( const std::vector<TYPE, ALLOCATOR>& obj, std::ostream& s ) {
0139       return toStream( obj.begin(), obj.end(), s, "[ ", " ]", " , " );
0140     }
0141     // ========================================================================
0142     /** the partial template specialization of <c>std::list<TYPE,ALLOCATOR></c>
0143      *  printout. The vector is printed a'la Python list: "[ a, b, c ]"
0144      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0145      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0146      *  @date 2007-04-08
0147      */
0148     template <class TYPE, class ALLOCATOR>
0149     inline std::ostream& toStream( const std::list<TYPE, ALLOCATOR>& obj, std::ostream& s ) {
0150       return toStream( obj.begin(), obj.end(), s, "[ ", " ]", " , " );
0151     }
0152     // ========================================================================
0153     /** the partial template specialization of <c>std::set<TYPE,CMP,ALLOCATOR></c>
0154      *  printout. The vector is printed a'la Python list: "[ a, b, c ]"
0155      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0156      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0157      *  @date 2006-05-12
0158      */
0159     template <class TYPE, class CMP, class ALLOCATOR>
0160     inline std::ostream& toStream( const std::set<TYPE, CMP, ALLOCATOR>& obj, std::ostream& s ) {
0161       return toStream( obj.begin(), obj.end(), s, "[ ", " ]", " , " );
0162     }
0163     // ========================================================================
0164     /** the partial template specialization of <c>std::unordered_set<TYPE,HASH,CMP,ALLOCATOR></c>
0165      *  printout. The set is printed a'la Python set: "{ a, b, c }"
0166      */
0167     template <class TYPE, class HASH, class CMP, class ALLOCATOR>
0168     inline std::ostream& toStream( const std::unordered_set<TYPE, HASH, CMP, ALLOCATOR>& obj, std::ostream& s ) {
0169       auto ordered = std::set( obj.begin(), obj.end() ); // ensure reproducible printout
0170       return obj.empty() ? s << "set()" : toStream( ordered.begin(), ordered.end(), s, "{ ", " }", " , " );
0171     }
0172     // ========================================================================
0173     /** the partial template specialization of
0174      *  <c>std::map<KTYPE,VTYPE,CMP,ALLOCATOR></c> printout
0175      *  the map is printed a'la Python dict: " ( a : b , c: d , e : f )"
0176      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0177      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0178      *  @date 2006-05-12
0179      */
0180     template <class KTYPE, class VTYPE, class CMP, class ALLOCATOR>
0181     inline std::ostream& toStream( const std::map<KTYPE, VTYPE, CMP, ALLOCATOR>& obj, std::ostream& s ) {
0182       using GaudiUtils::details::ostream_joiner;
0183       return ostream_joiner( s << "{ ", obj, " , ",
0184                              []( std::ostream& os, const std::pair<const KTYPE, VTYPE>& i ) -> std::ostream& {
0185                                return toStream( i.second, toStream( i.first, os ) << " : " );
0186                              } )
0187              << " }";
0188     }
0189     // ========================================================================
0190     /** the partial template specialization of
0191      *  <c>GaudiUtils::VectorMap<KTYPE,VTYPE,CMP,ALLOCATOR></c> printout
0192      *  the map is printed a'la Python dict: " ( a : b , c: d , e : f )"
0193      *  @see GaudiUtils::VectorMap
0194      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0195      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0196      *  @date 2006-05-12
0197      */
0198     template <class KTYPE, class VTYPE, class CMP, class ALLOCATOR>
0199     inline std::ostream& toStream( const GaudiUtils::VectorMap<KTYPE, VTYPE, CMP, ALLOCATOR>& obj, std::ostream& s ) {
0200       using GaudiUtils::details::ostream_joiner;
0201       return ostream_joiner( s << "{ ", obj, " , ",
0202                              []( std::ostream& os, const std::pair<const KTYPE, VTYPE>& i ) -> std::ostream& {
0203                                return toStream( i.second, toStream( i.first, os ) << " : " );
0204                              } )
0205              << " }";
0206     }
0207     // ========================================================================
0208     /** the partial template specialization of
0209      *  <c>GaudiUtils::Map<KTYPE,VTYPE,MAP></c> printout
0210      *  the map is printed a'la Python dict: " ( a : b , c: d , e : f )"
0211      *  @see GaudiUtils::VectorMap
0212      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0213      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0214      *  @date 2006-05-12
0215      */
0216     template <class KTYPE, class VTYPE, class MAP>
0217     inline std::ostream& toStream( const GaudiUtils::Map<KTYPE, VTYPE, MAP>& obj, std::ostream& s ) {
0218       using GaudiUtils::details::ostream_joiner;
0219       return ostream_joiner( s << "{ ", obj, " , ",
0220                              []( std::ostream& os, const std::pair<const KTYPE, VTYPE>& i ) -> std::ostream& {
0221                                return toStream( i.second, toStream( i.first, os ) << " : " );
0222                              } )
0223              << " }";
0224     }
0225     // ========================================================================
0226     /** the partial template specialization of
0227      *  <c>GaudiUtils::HashMap<KTYPE,VTYPE,HASH,MAP></c> printout
0228      *  the map is printed a'la Python dict: " ( a : b , c: d , e : f )"
0229      *  @see GaudiUtils::VectorMap
0230      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0231      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0232      *  @date 2006-05-12
0233      */
0234     template <class KTYPE, class VTYPE, class HASH, class MAP>
0235     inline std::ostream& toStream( const GaudiUtils::HashMap<KTYPE, VTYPE, HASH, MAP>& obj, std::ostream& s ) {
0236       // Copy the hash map into a map to have it ordered by key.
0237       return toStream( GaudiUtils::Map<KTYPE, VTYPE>{ obj.begin(), obj.end() }, s );
0238     }
0239     // ========================================================================
0240     /** the specialization for C-arrays, a'la python tuple
0241      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0242      *  @date 2009-10-05
0243      */
0244     template <class TYPE, unsigned int N>
0245     std::ostream& toStream( const TYPE ( &obj )[N], std::ostream& s ) {
0246       if constexpr ( N == 1 ) {
0247         return toStream( obj[0], s << "( " ) << " , )";
0248       } else {
0249         return toStream( obj, obj + N, s, "( ", " )", " , " );
0250       }
0251     }
0252     // ========================================================================
0253     /** the specialization for std::array, a'la python tuple
0254      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0255      *  @date 2009-09-16
0256      */
0257     template <class TYPE, std::size_t N>
0258     std::ostream& toStream( const std::array<TYPE, N>& obj, std::ostream& s ) {
0259       if constexpr ( N == 1 ) {
0260         return toStream( obj[0], s << "( " ) << " , )";
0261       } else {
0262         return toStream( begin( obj ), end( obj ), s, "( ", " )", " , " );
0263       }
0264     }
0265     // ========================================================================
0266     /** the specialization for C-string, a'la python tuple
0267      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0268      *  @date 2009-10-05
0269      */
0270     template <unsigned int N>
0271     std::ostream& toStream( const char ( &obj )[N], std::ostream& s ) {
0272       return toStream( std::string( obj, obj + N ), s );
0273     }
0274     // ========================================================================
0275     /** the specialization for C-string, a'la python tuple
0276      *  @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl
0277      *  @date 2009-10-05
0278      */
0279     inline std::ostream& toStream( const char* obj, std::ostream& s ) { return toStream( std::string( obj ), s ); }
0280     // ========================================================================
0281     /** the generic implementation of the printout to the std::ostream
0282      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0283      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0284      *  @date 2006-05-12
0285      */
0286     template <class TYPE>
0287     inline std::ostream& toStream( const TYPE& obj, std::ostream& s ) {
0288       return s << obj;
0289     }
0290     // ========================================================================
0291     // helper function to print a tuple of any size
0292     template <class Tuple, std::size_t N>
0293     struct TuplePrinter {
0294       static std::ostream& toStream( const Tuple& t, std::ostream& s ) {
0295         TuplePrinter<Tuple, N - 1>::toStream( t, s ) << " , ";
0296         return Gaudi::Utils::toStream( std::get<N - 1>( t ), s );
0297       }
0298     };
0299 
0300     template <class Tuple>
0301     struct TuplePrinter<Tuple, 1> {
0302       static std::ostream& toStream( const Tuple& t, std::ostream& s ) {
0303         return Gaudi::Utils::toStream( std::get<0>( t ), s );
0304       }
0305     };
0306 
0307     /** the helper function to print the tuple
0308      *  @param tuple (INPUT)  tuple
0309      *  @return the stream
0310      *  @author Aleander Mazurov alexander.mazurov@cern.ch
0311      *  @date 2015-03-21
0312      */
0313     template <typename... Args>
0314     inline std::ostream& toStream( const std::tuple<Args...>& tuple, std::ostream& s ) {
0315       auto& out = TuplePrinter<decltype( tuple ), sizeof...( Args )>::toStream( tuple, s << " ( " );
0316       if constexpr ( std::tuple_size_v<std::tuple<Args...>> == 1 ) { // this is a special case in Python
0317         out << " ,";
0318       }
0319       return out << " ) ";
0320     }
0321     // ========================================================================
0322     /** the helper function to print the sequence
0323      *  @param first (INPUT)  begin-iterator for the sequence
0324      *  @param last  (INPUT)  end-iterator for the sequence
0325      *  @param s     (UPDATE) the stream itself
0326      *  @param open  (INPUT)  "open"-symbol
0327      *  @param close (INPUT)  "close"-symbol
0328      *  @param delim (INPUT)  "delimiter"-symbol
0329      *  @return the stream
0330      *  @author Vanya BELYAEV Ivan.BElyaev@nikhef.nl
0331      *  @date 2009-09-15
0332      */
0333     template <class ITERATOR>
0334     inline std::ostream& toStream( ITERATOR           first,  // begin of the sequence
0335                                    ITERATOR           last,   //   end of the sequence
0336                                    std::ostream&      s,      //            the stream
0337                                    const std::string& open,   //               opening
0338                                    const std::string& close,  //               closing
0339                                    const std::string& delim ) //             delimiter
0340     {
0341       using ref_t = typename std::iterator_traits<ITERATOR>::reference;
0342       using GaudiUtils::details::ostream_joiner;
0343       return ostream_joiner( s << open, first, last, delim,
0344                              []( std::ostream& os, ref_t i ) -> std::ostream& { return toStream( i, os ); } )
0345              << close;
0346     }
0347 
0348     // ========================================================================
0349     /** the generic implementation of the type conversion to the string
0350      *  @author Alexander MAZUROV Alexander.Mazurov@gmail.com
0351      *  @author Vanya BELYAEV ibelyaev@physics.syr.edu
0352      *  @date 2006-05-12
0353      *  @see Gaudi::Utils::toStream
0354      *  @todo need to be compared with boost::lexical_cast
0355      */
0356     template <class TYPE>
0357     inline std::string toString( const TYPE& obj ) {
0358       std::ostringstream s;
0359       std::ios::fmtflags orig_flags = s.flags();
0360       s.setf( std::ios::showpoint ); // to display correctly floats
0361       toStream( obj, s );
0362       s.flags( orig_flags );
0363       return s.str();
0364     }
0365     // ========================================================================
0366   } // namespace Utils
0367   // ==========================================================================
0368 } //                                                     end of namespace Gaudi
0369 // ============================================================================
0370 // The END
0371 // ============================================================================
0372 #endif