📄 cpp_macromap_utils.hpp
字号:
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Token sequence analysis and transformation helper functions
http://www.boost.org/
Copyright (c) 2001-2005 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>
///////////////////////////////////////////////////////////////////////////////
//
// This file contains the definition of several token sequence analyse
// 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 a given identifier resolves to a operator name
//
///////////////////////////////////////////////////////////////////////////////
//template <typename StringT>
//inline bool
//is_operator_macroname (StringT const &name)
//{
// if (name.size() < 2 || name.size() > 6)
// return false;
//
// if (str == "and" || str == "and_eq" ||
// str == "bitand" || str == "bitor" ||
// str == "compl" ||
// str == "not" || str == "not_eq" ||
// str == "or" || str == "or_eq" ||
// str == "xor" || str == "xor_eq")
// {
// 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 BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
if (T_PARAMETERBASE == token_id(left) ||
T_EXTPARAMETERBASE == token_id(left))
#else
if (T_PARAMETERBASE == token_id(left))
#endif
{
// 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)) &&
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 && 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
//
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -