| |
| #ifndef BOOST_MPL_STRING_HPP_INCLUDED |
| #define BOOST_MPL_STRING_HPP_INCLUDED |
| |
| // Copyright Eric Niebler 2009 |
| // |
| // 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) |
| // |
| // See http://www.boost.org/libs/mpl for documentation. |
| |
| // $Id: string.hpp 49239 2009-04-01 09:10:26Z eric_niebler $ |
| // $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $ |
| // $Revision: 49239 $ |
| // |
| // Thanks to: |
| // Dmitry Goncharov for porting this to the Sun compiler |
| |
| #include <boost/config.hpp> |
| #include <boost/detail/workaround.hpp> |
| #include <boost/detail/endian.hpp> |
| #include <boost/mpl/limits/string.hpp> |
| #include <boost/mpl/if.hpp> |
| #include <boost/mpl/char.hpp> |
| #include <boost/mpl/copy.hpp> |
| #include <boost/mpl/size.hpp> |
| #include <boost/mpl/empty.hpp> |
| #include <boost/mpl/assert.hpp> |
| #include <boost/mpl/size_t.hpp> |
| #include <boost/mpl/begin_end.hpp> |
| #include <boost/mpl/joint_view.hpp> |
| #include <boost/mpl/insert_range.hpp> |
| #include <boost/mpl/back_inserter.hpp> |
| #include <boost/mpl/front_inserter.hpp> |
| #include <boost/mpl/iterator_range.hpp> |
| #include <boost/preprocessor/arithmetic/dec.hpp> |
| #include <boost/preprocessor/arithmetic/add.hpp> |
| #include <boost/preprocessor/arithmetic/div.hpp> |
| #include <boost/preprocessor/punctuation/comma_if.hpp> |
| #include <boost/preprocessor/repetition/repeat.hpp> |
| #include <boost/preprocessor/repetition/enum_params.hpp> |
| #include <boost/preprocessor/repetition/repeat_from_to.hpp> |
| #include <boost/preprocessor/repetition/enum_shifted_params.hpp> |
| #include <boost/preprocessor/repetition/enum_trailing_params.hpp> |
| #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> |
| |
| #include <iterator> // for bidirectional_iterator_tag |
| #include <climits> |
| |
| namespace boost { namespace mpl |
| { |
| #define BOOST_MPL_STRING_MAX_PARAMS \ |
| BOOST_PP_DIV(BOOST_PP_ADD(BOOST_MPL_LIMIT_STRING_SIZE, 3), 4) |
| |
| // Low-level bit-twiddling is done by macros. Any implementation-defined behavior of |
| // multi-character literals should be localized to these macros. |
| |
| #define BOOST_MPL_MULTICHAR_LENGTH(c) \ |
| (std::size_t)((c<CHAR_MIN) ? 4 : ((c>0xffffff)+(c>0xffff)+(c>0xff)+1)) |
| |
| #if defined(BOOST_LITTLE_ENDIAN) && defined(__SUNPRO_CC) |
| |
| #define BOOST_MPL_MULTICHAR_AT(c,i) \ |
| (char)(0xff&((unsigned)(c)>>(8*(std::size_t)(i)))) |
| |
| #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \ |
| ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c)) |
| |
| #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \ |
| (((unsigned)(c)<<8)|(unsigned char)(i)) |
| |
| #define BOOST_MPL_MULTICHAR_POP_BACK(c) \ |
| (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c)) |
| |
| #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \ |
| ((unsigned)(c)>>8) |
| |
| #else |
| |
| #define BOOST_MPL_MULTICHAR_AT(c,i) \ |
| (char)(0xff&((unsigned)(c)>>(8*(BOOST_MPL_MULTICHAR_LENGTH(c)-(std::size_t)(i)-1)))) |
| |
| #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \ |
| (((unsigned)(c)<<8)|(unsigned char)(i)) |
| |
| #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \ |
| ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c)) |
| |
| #define BOOST_MPL_MULTICHAR_POP_BACK(c) \ |
| ((unsigned)(c)>>8) |
| |
| #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \ |
| (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c)) |
| |
| #endif |
| |
| struct string_tag; |
| struct string_iterator_tag; |
| |
| template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_STRING_MAX_PARAMS, int C, 0)> |
| struct string; |
| |
| template<typename Sequence, int I, int J> |
| struct string_iterator; |
| |
| template<typename Sequence> |
| struct sequence_tag; |
| |
| template<typename Tag> |
| struct size_impl; |
| |
| template<> |
| struct size_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply; |
| |
| #define M0(z, n, data) \ |
| + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n)) |
| |
| #define M1(z, n, data) \ |
| template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \ |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \ |
| : mpl::size_t<(0 BOOST_PP_REPEAT_ ## z(n, M0, ~))> \ |
| {}; |
| |
| BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M1, ~) |
| #undef M0 |
| #undef M1 |
| }; |
| |
| template<> |
| struct size_impl<mpl::string_tag>::apply<mpl::string<> > |
| : mpl::size_t<0> |
| {}; |
| |
| template<typename Tag> |
| struct begin_impl; |
| |
| template<> |
| struct begin_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply |
| { |
| typedef mpl::string_iterator<Sequence, 0, 0> type; |
| }; |
| }; |
| |
| template<typename Tag> |
| struct end_impl; |
| |
| template<> |
| struct end_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply; |
| |
| #define M0(z,n,data) \ |
| template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \ |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \ |
| { \ |
| typedef mpl::string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, n, 0> type; \ |
| }; |
| |
| BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) |
| #undef M0 |
| }; |
| |
| template<> |
| struct end_impl<mpl::string_tag>::apply<mpl::string<> > |
| { |
| typedef mpl::string_iterator<mpl::string<>, 0, 0> type; |
| }; |
| |
| template<typename Tag> |
| struct push_back_impl; |
| |
| template<> |
| struct push_back_impl<mpl::string_tag> |
| { |
| template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::back_))> |
| struct apply |
| { |
| BOOST_MPL_ASSERT_MSG( |
| (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value) |
| , PUSH_BACK_FAILED_MPL_STRING_IS_FULL |
| , (Sequence) |
| ); |
| // If the above assertion didn't fire, then the string is sparse. |
| // Repack the string and retry the push_back |
| typedef |
| typename mpl::push_back< |
| typename mpl::copy< |
| Sequence |
| , mpl::back_inserter<mpl::string<> > |
| >::type |
| , Value |
| >::type |
| type; |
| }; |
| |
| template<typename Value> |
| struct apply<mpl::string<>, Value, false> |
| { |
| typedef mpl::string<(char)Value::value> type; |
| }; |
| |
| #define M0(z,n,data) \ |
| template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value> \ |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, false> \ |
| { \ |
| typedef \ |
| mpl::string< \ |
| BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ |
| BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ |
| ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ |
| ?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \ |
| :BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n)), Value::value) \ |
| , ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \ |
| ?(char)Value::value \ |
| :0 \ |
| > \ |
| type; \ |
| }; |
| |
| BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~) |
| #undef M0 |
| |
| template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value> |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false> |
| { |
| typedef |
| mpl::string< |
| BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C) |
| , BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)), Value::value) |
| > |
| type; |
| }; |
| }; |
| |
| template<typename Tag> |
| struct has_push_back_impl; |
| |
| template<> |
| struct has_push_back_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::true_ |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct pop_back_impl; |
| |
| template<> |
| struct pop_back_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply; |
| |
| #define M0(z,n,data) \ |
| template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \ |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \ |
| { \ |
| BOOST_MPL_ASSERT_MSG((C0 != 0), POP_BACK_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \ |
| typedef \ |
| mpl::string< \ |
| BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ |
| BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ |
| BOOST_MPL_MULTICHAR_POP_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n))) \ |
| > \ |
| type; \ |
| }; |
| |
| BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) |
| #undef M0 |
| }; |
| |
| template<typename Tag> |
| struct has_pop_back_impl; |
| |
| template<> |
| struct has_pop_back_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::true_ |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct push_front_impl; |
| |
| template<> |
| struct push_front_impl<mpl::string_tag> |
| { |
| template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))> |
| struct apply |
| { |
| BOOST_MPL_ASSERT_MSG( |
| (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value) |
| , PUSH_FRONT_FAILED_MPL_STRING_IS_FULL |
| , (Sequence) |
| ); |
| // If the above assertion didn't fire, then the string is sparse. |
| // Repack the string and retry the push_front. |
| typedef |
| typename mpl::push_front< |
| typename mpl::reverse_copy< |
| Sequence |
| , mpl::front_inserter<string<> > |
| >::type |
| , Value |
| >::type |
| type; |
| }; |
| |
| #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) |
| template<typename Value> |
| struct apply<mpl::string<>, Value, false> |
| { |
| typedef mpl::string<(char)Value::value> type; |
| }; |
| #endif |
| |
| #define M0(z,n,data) \ |
| template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value> \ |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, true> \ |
| { \ |
| typedef \ |
| mpl::string< \ |
| (char)Value::value \ |
| BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C) \ |
| > \ |
| type; \ |
| }; |
| |
| BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~) |
| #undef M0 |
| |
| template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value> |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false> |
| { |
| typedef |
| mpl::string< |
| BOOST_MPL_MULTICHAR_PUSH_FRONT(C0, Value::value) |
| , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) |
| > |
| type0; |
| |
| #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) |
| typedef |
| typename mpl::if_< |
| mpl::empty<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> > |
| , mpl::string<(char)Value::value> |
| , type0 |
| >::type |
| type; |
| #else |
| typedef type0 type; |
| #endif |
| }; |
| }; |
| |
| template<typename Tag> |
| struct has_push_front_impl; |
| |
| template<> |
| struct has_push_front_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::true_ |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct pop_front_impl; |
| |
| template<> |
| struct pop_front_impl<mpl::string_tag> |
| { |
| template<typename Sequence, bool B = (1==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))> |
| struct apply; |
| |
| #define M0(z,n,data) \ |
| template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \ |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, true> \ |
| { \ |
| BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \ |
| typedef \ |
| mpl::string<BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, n, C)> \ |
| type; \ |
| }; |
| |
| BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~) |
| #undef M0 |
| |
| template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)> |
| struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, false> |
| { |
| typedef |
| mpl::string< |
| BOOST_MPL_MULTICHAR_POP_FRONT(C0) |
| , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) |
| > |
| type; |
| }; |
| }; |
| |
| template<typename Tag> |
| struct has_pop_front_impl; |
| |
| template<> |
| struct has_pop_front_impl<mpl::string_tag> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::true_ |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct insert_range_impl; |
| |
| template<> |
| struct insert_range_impl<mpl::string_tag> |
| { |
| template<typename Sequence, typename Pos, typename Range> |
| struct apply |
| : mpl::copy< |
| mpl::joint_view< |
| mpl::iterator_range< |
| mpl::string_iterator<Sequence, 0, 0> |
| , Pos |
| > |
| , mpl::joint_view< |
| Range |
| , mpl::iterator_range< |
| Pos |
| , typename mpl::end<Sequence>::type |
| > |
| > |
| > |
| , mpl::back_inserter<mpl::string<> > |
| > |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct insert_impl; |
| |
| template<> |
| struct insert_impl<mpl::string_tag> |
| { |
| template<typename Sequence, typename Pos, typename Value> |
| struct apply |
| : mpl::insert_range<Sequence, Pos, mpl::string<(char)Value::value> > |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct erase_impl; |
| |
| template<> |
| struct erase_impl<mpl::string_tag> |
| { |
| template<typename Sequence, typename First, typename Last> |
| struct apply |
| : mpl::copy< |
| mpl::joint_view< |
| mpl::iterator_range< |
| mpl::string_iterator<Sequence, 0, 0> |
| , First |
| > |
| , mpl::iterator_range< |
| typename mpl::if_na<Last, typename mpl::next<First>::type>::type |
| , typename mpl::end<Sequence>::type |
| > |
| > |
| , mpl::back_inserter<mpl::string<> > |
| > |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct clear_impl; |
| |
| template<> |
| struct clear_impl<mpl::string_tag> |
| { |
| template<typename> |
| struct apply |
| { |
| typedef mpl::string<> type; |
| }; |
| }; |
| |
| #define M0(z, n, data) \ |
| template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), int J> \ |
| struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, J> \ |
| { \ |
| enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) }; \ |
| typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \ |
| typedef std::bidirectional_iterator_tag category; \ |
| typedef \ |
| mpl::string_iterator<string, n + eomc_, eomc_ ? 0 : J + 1> \ |
| next; \ |
| typedef \ |
| mpl::string_iterator<string, n, J - 1> \ |
| prior; \ |
| typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), J)> type; \ |
| }; \ |
| template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)> \ |
| struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, 0> \ |
| { \ |
| enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == 1) }; \ |
| typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \ |
| typedef std::bidirectional_iterator_tag category; \ |
| typedef \ |
| mpl::string_iterator<string, n + eomc_, !eomc_> \ |
| next; \ |
| typedef \ |
| mpl::string_iterator< \ |
| string \ |
| , n - 1 \ |
| , BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, BOOST_PP_DEC(n))) - 1 \ |
| > \ |
| prior; \ |
| typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), 0)> type; \ |
| }; |
| |
| BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~) |
| #undef M0 |
| |
| template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)> |
| struct string |
| { |
| /// INTERNAL ONLY |
| enum |
| { |
| front_ = C0 |
| , back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)) |
| }; |
| |
| typedef char value_type; |
| typedef string type; |
| typedef string_tag tag; |
| }; |
| |
| namespace aux_ |
| { |
| template<typename It, typename End> |
| struct next_unless |
| : mpl::next<It> |
| {}; |
| |
| template<typename End> |
| struct next_unless<End, End> |
| { |
| typedef End type; |
| }; |
| |
| template<typename It, typename End> |
| struct deref_unless |
| : mpl::deref<It> |
| {}; |
| |
| template<typename End> |
| struct deref_unless<End, End> |
| { |
| typedef mpl::char_<'\0'> type; |
| }; |
| } |
| |
| template<typename Sequence> |
| struct c_str |
| { |
| typedef typename mpl::end<Sequence>::type iend; |
| typedef typename mpl::begin<Sequence>::type i0; |
| #define M0(z, n, data) \ |
| typedef \ |
| typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::type \ |
| BOOST_PP_CAT(i, BOOST_PP_INC(n)); |
| BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~) |
| #undef M0 |
| |
| typedef c_str type; |
| static typename Sequence::value_type const value[BOOST_MPL_LIMIT_STRING_SIZE+1]; |
| }; |
| |
| template<typename Sequence> |
| typename Sequence::value_type const c_str<Sequence>::value[BOOST_MPL_LIMIT_STRING_SIZE+1] = |
| { |
| #define M0(z, n, data) \ |
| mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value, |
| BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~) |
| #undef M0 |
| '\0' |
| }; |
| |
| }} // namespace boost |
| |
| #endif // BOOST_MPL_STRING_HPP_INCLUDED |