cpp_macromap_utils.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 555 行 · 第 1/2 页

HPP
555
字号
/*=============================================================================    Boost.Wave: A Standard compliant C++ preprocessor library    Token sequence analysis and transformation helper functions        http://www.boost.org/    Copyright (c) 2001-2008 Hartmut Kaiser. Distributed under the Boost    Software License, Version 1.0. (See accompanying file    LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)=============================================================================*/#if !defined(CPP_MACROMAP_UTIL_HPP_HK041119)#define CPP_MACROMAP_UTIL_HPP_HK041119#include <boost/assert.hpp>#include <boost/wave/wave_config.hpp>#include <boost/wave/token_ids.hpp>#include <boost/wave/util/unput_queue_iterator.hpp> // this must occur after all of the includes and before any code appears#ifdef BOOST_HAS_ABI_HEADERS#include BOOST_ABI_PREFIX#endif/////////////////////////////////////////////////////////////////////////////////// This file contains the definition of several token sequence analyze // and transformation utility functions needed during macro handling.////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////namespace boost {namespace wave {namespace util {///////////////////////////////////////////////////////////////////////////////namespace on_exit {    ///////////////////////////////////////////////////////////////////////////    //    //  On destruction pop the first element of the list given as the argument     //    ///////////////////////////////////////////////////////////////////////////    template <typename ContainerT>    class pop_front {    public:        pop_front(ContainerT &list_) : list(list_) {}        ~pop_front() { list.pop_front(); }        private:        ContainerT &list;    };    ///////////////////////////////////////////////////////////////////////////    //    //  Append a given list to the list given as argument     //  On destruction pop the first element of the list given as argument     //    ///////////////////////////////////////////////////////////////////////////    template <typename ContainerT>    class splice_pop_front {    public:        splice_pop_front(ContainerT &list_, ContainerT &queue)         :   list(list_)         {            list.splice(list.end(), queue);        }        ~splice_pop_front() { list.pop_front(); }    private:        ContainerT &list;    };    ///////////////////////////////////////////////////////////////////////////    //    //  On destruction reset a referenced value to its initial state    //    ///////////////////////////////////////////////////////////////////////////    template <typename TypeT>    class reset {    public:        reset(TypeT &target_value_, TypeT new_value)        :   target_value(target_value_), old_value(target_value_)        {            target_value_ = new_value;        }        ~reset() { target_value = old_value; }    private:        TypeT &target_value;        TypeT old_value;    };    ///////////////////////////////////////////////////////////////////////////    //    //  On destruction assign the given iterator back    //    ///////////////////////////////////////////////////////////////////////////    template <typename IteratorT, typename UnputIteratorT>    class assign    {    public:        assign(IteratorT &it_, UnputIteratorT const &uit_)         :   it(it_), uit(uit_) {}        ~assign() { it = uit.base(); }    private:        IteratorT &it;        UnputIteratorT const &uit;    };    template <typename IteratorT>    class assign<IteratorT, IteratorT> {    public:        assign(IteratorT &it_, IteratorT const &uit_)         :   it(it_), uit(uit_) {}        ~assign() { it = uit; }    private:        IteratorT &it;        IteratorT const &uit;    };///////////////////////////////////////////////////////////////////////////////}   // namespace on_exit///////////////////////////////////////////////////////////////////////////////namespace impl {///////////////////////////////////////////////////////////////////////////////////  Test, whether a given identifier resolves to a predefined name/////////////////////////////////////////////////////////////////////////////////template <typename StringT>inline bool is_special_macroname (StringT const &name){    if (name.size() < 7)        return false;            if ("defined" == name)        return true;            if ('_' == name[0] && '_' == name[1]) {    StringT str = name.substr(2);            if (str == "cplusplus"  || str == "STDC__" ||             str == "TIME__"     || str == "DATE__" ||            str == "LINE__"     || str == "FILE__" ||            str == "INCLUDE_LEVEL__")        {            return true;        }    }    return false;}///////////////////////////////////////////////////////////////////////////////////  Test, whether two tokens are to be considered equal (different sequences//  of whitespace are considered to be equal)/////////////////////////////////////////////////////////////////////////////////template <typename TokenT>inline bool token_equals(TokenT const &left, TokenT const &right){    using namespace boost::wave;        if (IS_CATEGORY(left, ParameterTokenType)) {    //  if the existing token is of type T_PARAMETERBASE, then the right token     //  must be of type T_IDENTIFIER or a keyword    token_id id = token_id(right);             return (T_IDENTIFIER == id ||                 IS_CATEGORY(id, KeywordTokenType) ||                IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||                IS_CATEGORY(id, BoolLiteralTokenType)) &&             left.get_value() == right.get_value();    }    // if the left token has whitespace, the value is irrelevant    return token_id(left) == token_id(right) && (            IS_CATEGORY(left, WhiteSpaceTokenType) ||            left.get_value() == right.get_value()        );}///////////////////////////////////////////////////////////////////////////////////  Tests, whether two macro definitions are equal/////////////////////////////////////////////////////////////////////////////////template <typename ContainerT>inline bool definition_equals(ContainerT const &definition,     ContainerT const &new_definition){    typedef typename ContainerT::const_iterator const_iterator_type;    const_iterator_type first1 = definition.begin();const_iterator_type last1 = definition.end();const_iterator_type first2 = new_definition.begin();const_iterator_type last2 = new_definition.end();        while (first1 != last1 && first2 != last2 && token_equals(*first1, *first2))     {    // skip whitespace, if both sequences have a whitespace next    token_id id1 = next_token<const_iterator_type>::peek(first1, last1, false);    token_id id2 = next_token<const_iterator_type>::peek(first2, last2, false);        if (IS_CATEGORY(id1, WhiteSpaceTokenType) &&             IS_CATEGORY(id2, WhiteSpaceTokenType))         {        // all consecutive whitespace tokens count as one whitespace        // adjust first1 and first2 accordingly            skip_whitespace(first1, last1);            skip_whitespace(first2, last2);        }        else if (!IS_CATEGORY(id1, WhiteSpaceTokenType) &&                  !IS_CATEGORY(id2, WhiteSpaceTokenType))         {            ++first1;            ++first2;        }        else {        // the sequences differ            break;        }    }    return (first1 == last1 && first2 == last2) ? true : false;}///////////////////////////////////////////////////////////////////////////////////  Tests, whether two given sets of macro parameters are equal/////////////////////////////////////////////////////////////////////////////////template <typename ContainerT>inline bool parameters_equal(ContainerT const &parameters, ContainerT const &new_parameters){    if (parameters.size() != new_parameters.size())        return false;   // different parameter count    typedef typename ContainerT::const_iterator const_iterator_type;    const_iterator_type first1 = parameters.begin();const_iterator_type last1 = parameters.end();const_iterator_type first2 = new_parameters.begin();const_iterator_type last2 = new_parameters.end();    while (first1 != last1 && first2 != last2) {    // parameters are different, if the corresponding tokens are different        using namespace boost::wave;        if (token_id(*first1) != token_id(*first2) ||            (*first1).get_value() != (*first2).get_value())        {            break;        }        ++first1;        ++first2;    }    return (first1 == last1 && first2 == last2) ? true : false;}///////////////////////////////////////////////////////////////////////////////////  Strip leading and trailing whitespace from the given token sequence/////////////////////////////////////////////////////////////////////////////////template <typename ContainerT>inline voidtrim_replacement_list (ContainerT &replacement_list)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?