2 #ifndef BOOST_MPL_STRING_HPP_INCLUDED
\r
3 #define BOOST_MPL_STRING_HPP_INCLUDED
\r
5 // Copyright Eric Niebler 2009
\r
7 // Distributed under the Boost Software License, Version 1.0.
\r
8 // (See accompanying file LICENSE_1_0.txt or copy at
\r
9 // http://www.boost.org/LICENSE_1_0.txt)
\r
11 // See http://www.boost.org/libs/mpl for documentation.
\r
13 // $Id: string.hpp 49239 2009-04-01 09:10:26Z eric_niebler $
\r
14 // $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $
\r
15 // $Revision: 49239 $
\r
18 // Dmitry Goncharov for porting this to the Sun compiler
\r
20 #include <boost/config.hpp>
\r
21 #include <boost/detail/workaround.hpp>
\r
22 #include <boost/detail/endian.hpp>
\r
23 #include <boost/mpl/limits/string.hpp>
\r
24 #include <boost/mpl/if.hpp>
\r
25 #include <boost/mpl/char.hpp>
\r
26 #include <boost/mpl/copy.hpp>
\r
27 #include <boost/mpl/size.hpp>
\r
28 #include <boost/mpl/empty.hpp>
\r
29 #include <boost/mpl/assert.hpp>
\r
30 #include <boost/mpl/size_t.hpp>
\r
31 #include <boost/mpl/begin_end.hpp>
\r
32 #include <boost/mpl/joint_view.hpp>
\r
33 #include <boost/mpl/insert_range.hpp>
\r
34 #include <boost/mpl/back_inserter.hpp>
\r
35 #include <boost/mpl/front_inserter.hpp>
\r
36 #include <boost/mpl/iterator_range.hpp>
\r
37 #include <boost/preprocessor/arithmetic/dec.hpp>
\r
38 #include <boost/preprocessor/arithmetic/add.hpp>
\r
39 #include <boost/preprocessor/arithmetic/div.hpp>
\r
40 #include <boost/preprocessor/punctuation/comma_if.hpp>
\r
41 #include <boost/preprocessor/repetition/repeat.hpp>
\r
42 #include <boost/preprocessor/repetition/enum_params.hpp>
\r
43 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
\r
44 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
\r
45 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
\r
46 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
\r
48 #include <iterator> // for bidirectional_iterator_tag
\r
51 namespace boost { namespace mpl
\r
53 #define BOOST_MPL_STRING_MAX_PARAMS \
\r
54 BOOST_PP_DIV(BOOST_PP_ADD(BOOST_MPL_LIMIT_STRING_SIZE, 3), 4)
\r
56 // Low-level bit-twiddling is done by macros. Any implementation-defined behavior of
\r
57 // multi-character literals should be localized to these macros.
\r
59 #define BOOST_MPL_MULTICHAR_LENGTH(c) \
\r
60 (std::size_t)((c<CHAR_MIN) ? 4 : ((c>0xffffff)+(c>0xffff)+(c>0xff)+1))
\r
62 #if defined(BOOST_LITTLE_ENDIAN) && defined(__SUNPRO_CC)
\r
64 #define BOOST_MPL_MULTICHAR_AT(c,i) \
\r
65 (char)(0xff&((unsigned)(c)>>(8*(std::size_t)(i))))
\r
67 #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \
\r
68 ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c))
\r
70 #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \
\r
71 (((unsigned)(c)<<8)|(unsigned char)(i))
\r
73 #define BOOST_MPL_MULTICHAR_POP_BACK(c) \
\r
74 (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c))
\r
76 #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \
\r
81 #define BOOST_MPL_MULTICHAR_AT(c,i) \
\r
82 (char)(0xff&((unsigned)(c)>>(8*(BOOST_MPL_MULTICHAR_LENGTH(c)-(std::size_t)(i)-1))))
\r
84 #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \
\r
85 (((unsigned)(c)<<8)|(unsigned char)(i))
\r
87 #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \
\r
88 ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c))
\r
90 #define BOOST_MPL_MULTICHAR_POP_BACK(c) \
\r
93 #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \
\r
94 (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c))
\r
99 struct string_iterator_tag;
\r
101 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_STRING_MAX_PARAMS, int C, 0)>
\r
104 template<typename Sequence, int I, int J>
\r
105 struct string_iterator;
\r
107 template<typename Sequence>
\r
108 struct sequence_tag;
\r
110 template<typename Tag>
\r
114 struct size_impl<mpl::string_tag>
\r
116 template<typename Sequence>
\r
119 #define M0(z, n, data) \
\r
120 + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n))
\r
122 #define M1(z, n, data) \
\r
123 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
\r
124 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
\r
125 : mpl::size_t<(0 BOOST_PP_REPEAT_ ## z(n, M0, ~))> \
\r
128 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M1, ~)
\r
134 struct size_impl<mpl::string_tag>::apply<mpl::string<> >
\r
138 template<typename Tag>
\r
142 struct begin_impl<mpl::string_tag>
\r
144 template<typename Sequence>
\r
147 typedef mpl::string_iterator<Sequence, 0, 0> type;
\r
151 template<typename Tag>
\r
155 struct end_impl<mpl::string_tag>
\r
157 template<typename Sequence>
\r
160 #define M0(z,n,data) \
\r
161 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
\r
162 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
\r
164 typedef mpl::string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, n, 0> type; \
\r
167 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
\r
172 struct end_impl<mpl::string_tag>::apply<mpl::string<> >
\r
174 typedef mpl::string_iterator<mpl::string<>, 0, 0> type;
\r
177 template<typename Tag>
\r
178 struct push_back_impl;
\r
181 struct push_back_impl<mpl::string_tag>
\r
183 template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::back_))>
\r
186 BOOST_MPL_ASSERT_MSG(
\r
187 (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value)
\r
188 , PUSH_BACK_FAILED_MPL_STRING_IS_FULL
\r
191 // If the above assertion didn't fire, then the string is sparse.
\r
192 // Repack the string and retry the push_back
\r
194 typename mpl::push_back<
\r
195 typename mpl::copy<
\r
197 , mpl::back_inserter<mpl::string<> >
\r
204 template<typename Value>
\r
205 struct apply<mpl::string<>, Value, false>
\r
207 typedef mpl::string<(char)Value::value> type;
\r
210 #define M0(z,n,data) \
\r
211 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value> \
\r
212 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, false> \
\r
216 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \
\r
217 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \
\r
218 ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \
\r
219 ?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \
\r
220 :BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n)), Value::value) \
\r
221 , ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \
\r
222 ?(char)Value::value \
\r
228 BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
\r
231 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value>
\r
232 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
\r
236 BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C)
\r
237 , BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)), Value::value)
\r
243 template<typename Tag>
\r
244 struct pop_back_impl;
\r
247 struct pop_back_impl<mpl::string_tag>
\r
249 template<typename Sequence>
\r
252 #define M0(z,n,data) \
\r
253 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
\r
254 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
\r
256 BOOST_MPL_ASSERT_MSG((C0 != 0), POP_BACK_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \
\r
259 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \
\r
260 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \
\r
261 BOOST_MPL_MULTICHAR_POP_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n))) \
\r
266 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
\r
270 template<typename Tag>
\r
271 struct push_front_impl;
\r
274 struct push_front_impl<mpl::string_tag>
\r
276 template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
\r
279 BOOST_MPL_ASSERT_MSG(
\r
280 (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value)
\r
281 , PUSH_FRONT_FAILED_MPL_STRING_IS_FULL
\r
284 // If the above assertion didn't fire, then the string is sparse.
\r
285 // Repack the string and retry the push_front.
\r
287 typename mpl::push_front<
\r
288 typename mpl::reverse_copy<
\r
290 , mpl::front_inserter<string<> >
\r
297 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
\r
298 template<typename Value>
\r
299 struct apply<mpl::string<>, Value, false>
\r
301 typedef mpl::string<(char)Value::value> type;
\r
305 #define M0(z,n,data) \
\r
306 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value> \
\r
307 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, true> \
\r
311 (char)Value::value \
\r
312 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C) \
\r
317 BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
\r
320 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value>
\r
321 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
\r
325 BOOST_MPL_MULTICHAR_PUSH_FRONT(C0, Value::value)
\r
326 , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
\r
330 #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
\r
333 mpl::empty<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> >
\r
334 , mpl::string<(char)Value::value>
\r
339 typedef type0 type;
\r
344 template<typename Tag>
\r
345 struct pop_front_impl;
\r
348 struct pop_front_impl<mpl::string_tag>
\r
350 template<typename Sequence, bool B = (1==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
\r
353 #define M0(z,n,data) \
\r
354 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
\r
355 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, true> \
\r
357 BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \
\r
359 mpl::string<BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, n, C)> \
\r
363 BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
\r
366 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>
\r
367 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, false>
\r
371 BOOST_MPL_MULTICHAR_POP_FRONT(C0)
\r
372 , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
\r
378 template<typename Tag>
\r
379 struct insert_range_impl;
\r
382 struct insert_range_impl<mpl::string_tag>
\r
384 template<typename Sequence, typename Pos, typename Range>
\r
388 mpl::iterator_range<
\r
389 mpl::string_iterator<Sequence, 0, 0>
\r
394 , mpl::iterator_range<
\r
396 , typename mpl::end<Sequence>::type
\r
400 , mpl::back_inserter<mpl::string<> >
\r
405 template<typename Tag>
\r
406 struct insert_impl;
\r
409 struct insert_impl<mpl::string_tag>
\r
411 template<typename Sequence, typename Pos, typename Value>
\r
413 : mpl::insert_range<Sequence, Pos, mpl::string<(char)Value::value> >
\r
417 template<typename Tag>
\r
421 struct erase_impl<mpl::string_tag>
\r
423 template<typename Sequence, typename First, typename Last>
\r
427 mpl::iterator_range<
\r
428 mpl::string_iterator<Sequence, 0, 0>
\r
431 , mpl::iterator_range<
\r
432 typename mpl::if_na<Last, typename mpl::next<First>::type>::type
\r
433 , typename mpl::end<Sequence>::type
\r
436 , mpl::back_inserter<mpl::string<> >
\r
441 template<typename Tag>
\r
445 struct clear_impl<mpl::string_tag>
\r
450 typedef mpl::string<> type;
\r
454 #define M0(z, n, data) \
\r
455 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), int J> \
\r
456 struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, J> \
\r
458 enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) }; \
\r
459 typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \
\r
460 typedef std::bidirectional_iterator_tag category; \
\r
462 mpl::string_iterator<string, n + eomc_, eomc_ ? 0 : J + 1> \
\r
465 mpl::string_iterator<string, n, J - 1> \
\r
467 typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), J)> type; \
\r
469 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)> \
\r
470 struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, 0> \
\r
472 enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == 1) }; \
\r
473 typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \
\r
474 typedef std::bidirectional_iterator_tag category; \
\r
476 mpl::string_iterator<string, n + eomc_, !eomc_> \
\r
479 mpl::string_iterator< \
\r
482 , BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, BOOST_PP_DEC(n))) - 1 \
\r
485 typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), 0)> type; \
\r
488 BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
\r
491 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>
\r
498 , back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))
\r
501 typedef char value_type;
\r
502 typedef string type;
\r
503 typedef string_tag tag;
\r
508 template<typename It, typename End>
\r
513 template<typename End>
\r
514 struct next_unless<End, End>
\r
519 template<typename It, typename End>
\r
520 struct deref_unless
\r
524 template<typename End>
\r
525 struct deref_unless<End, End>
\r
527 typedef mpl::char_<'\0'> type;
\r
531 template<typename Sequence>
\r
534 typedef typename mpl::end<Sequence>::type iend;
\r
535 typedef typename mpl::begin<Sequence>::type i0;
\r
536 #define M0(z, n, data) \
\r
538 typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::type \
\r
539 BOOST_PP_CAT(i, BOOST_PP_INC(n));
\r
540 BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
\r
543 typedef c_str type;
\r
544 static typename Sequence::value_type const value[BOOST_MPL_LIMIT_STRING_SIZE+1];
\r
547 template<typename Sequence>
\r
548 typename Sequence::value_type const c_str<Sequence>::value[BOOST_MPL_LIMIT_STRING_SIZE+1] =
\r
550 #define M0(z, n, data) \
\r
551 mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value,
\r
552 BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
\r
557 }} // namespace boost
\r
559 #endif // BOOST_MPL_STRING_HPP_INCLUDED
\r