Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:00:28

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 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 #ifndef _ATTRIB_STRING_PARSER_H_
0012 #define _ATTRIB_STRING_PARSER_H_
0013 
0014 #include "GaudiKernel/Kernel.h"
0015 #include "GaudiKernel/System.h"
0016 #include <iterator>
0017 #ifdef __clang__
0018 #  pragma clang diagnostic push
0019 // Hide warning message:
0020 // boost/regex/v4/instances.hpp:128:17: warning: keyword is hidden by macro definition
0021 #  pragma clang diagnostic ignored "-Wkeyword-macro"
0022 #endif
0023 #include <boost/regex.hpp>
0024 #ifdef __clang__
0025 #  pragma clang diagnostic pop
0026 #endif
0027 
0028 namespace Gaudi {
0029   namespace Utils {
0030     /** Parse attribute strings allowing iteration over the various attributes.
0031      * Example of usage:
0032      * \code{.cpp}
0033      * using Parser = Gaudi::Utils::AttribStringParser;
0034      * std::string input{"key1='value1' key2='value2'"};
0035      * for(auto attrib: Parser(input)) {
0036      *   std::cout << attrib.tag << " -> " << attrib.value << std::endl;
0037      * }
0038      * \endcode
0039      */
0040     class AttribStringParser {
0041     public:
0042       /// Simple class to wrap tag/value pairs.
0043       struct Attrib {
0044         std::string tag;
0045         std::string value;
0046       };
0047 
0048       /// Iterator to loop over the tag/value pairs in the attribute string.
0049       // This class is essentially a wrapper around boost::sregex_iterator.
0050       class Iterator {
0051       public:
0052         using iterator_category = std::input_iterator_tag;
0053         using value_type        = Attrib;
0054         using difference_type   = std::ptrdiff_t;
0055         using pointer           = value_type*;
0056         using reference         = value_type&;
0057 
0058         Iterator() = default;
0059         Iterator( const boost::sregex_iterator& it, bool expand_vars ) : m_it( it ), m_expandVars( expand_vars ) {
0060           // i_setAttrib();
0061         }
0062         Iterator( const Iterator& other ) : Iterator( other.m_it, other.m_expandVars ) {}
0063         Iterator( Iterator&& other ) : m_it( std::move( other.m_it ) ), m_expandVars( other.m_expandVars ) {}
0064         Iterator operator++( int ) {
0065           ++m_it;
0066           return *this;
0067         }
0068         Iterator operator++() {
0069           auto old = *this;
0070           ++m_it;
0071           return old;
0072         }
0073         reference operator*() {
0074           i_setAttrib();
0075           return m_attrib;
0076         }
0077         bool operator==( const Iterator& other ) { return m_it == other.m_it; }
0078         bool operator!=( const Iterator& other ) { return m_it != other.m_it; }
0079 
0080       private:
0081         /// Wrapped boost::sregex_iterator instance.
0082         boost::sregex_iterator m_it;
0083         bool                   m_expandVars = false;
0084         /// Cached Attrib instance.
0085         Attrib m_attrib;
0086         /// Helper method used to update the cached Attrib instance when
0087         /// dereferencing the iterator.
0088         void i_setAttrib() {
0089           static const boost::sregex_iterator endmark;
0090           if ( m_it != endmark ) {
0091             // if we have a match, we cache the values
0092             m_attrib = Attrib{ ( *m_it )[1], ( *m_it )[2] };
0093             if ( m_expandVars && m_attrib.value.find( "${" ) != std::string::npos ) {
0094               static const boost::regex varexp{ "\\$\\{([^}]+)\\}" };
0095               auto                      i = 1;
0096               while ( i ) {
0097                 i              = 0;
0098                 m_attrib.value = boost::regex_replace(
0099                     m_attrib.value, varexp,
0100                     [&i]( const boost::smatch& m ) -> std::string {
0101                       const std::string name  = m[1];
0102                       const char*       cname = name.c_str();
0103                       if ( System::isEnvSet( cname ) ) {
0104                         ++i;
0105                         return System::getEnv( cname );
0106                       }
0107                       return m[0]; // do not expand unknown vars
0108                     },
0109                     boost::match_default | boost::format_all );
0110               }
0111             }
0112           } else {
0113             // otherwise we clean the cache
0114             m_attrib = Attrib();
0115           }
0116         }
0117       };
0118 
0119       /** Initialize the parsing of an attribute string.
0120        *
0121        * @param data: attribute string
0122        * @param expand_vars: if true (default) expand environment variables in values
0123        */
0124       AttribStringParser( std::string data, bool expand_vars = true ) : m_data( data ), m_expandVars( expand_vars ) {}
0125 
0126     private:
0127       std::string m_data;
0128       bool        m_expandVars;
0129 
0130       boost::sregex_iterator parse() const {
0131         static const boost::regex exp{ "[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*'(.*?)'" };
0132         return boost::sregex_iterator( begin( m_data ), end( m_data ), exp );
0133       }
0134       friend Iterator begin( const AttribStringParser& );
0135     };
0136     inline AttribStringParser::Iterator begin( const AttribStringParser& parser ) {
0137       return AttribStringParser::Iterator( parser.parse(), parser.m_expandVars );
0138     }
0139     inline AttribStringParser::Iterator end( const AttribStringParser& /*parser*/ ) {
0140       return AttribStringParser::Iterator();
0141     }
0142   } // namespace Utils
0143 } // namespace Gaudi
0144 
0145 #endif