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