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 ⁢ 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 ⁢ 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 ¶meters, 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 + -
显示快捷键?