1
2#ifndef BOOST_MPL_STRING_HPP_INCLUDED
3#define BOOST_MPL_STRING_HPP_INCLUDED
4
5// Copyright Eric Niebler 2009
6//
7// Distributed under the Boost Software License, Version 1.0.
8// (See accompanying file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// See http://www.boost.org/libs/mpl for documentation.
12
13// $Id: string.hpp 49239 2009-04-01 09:10:26Z eric_niebler $
14// $Date: 2009-04-01 02:10:26 -0700 (Wed, 1 Apr 2009) $
15// $Revision: 49239 $
16//
17// Thanks to:
18// Dmitry Goncharov for porting this to the Sun compiler
19
20#include <boost/config.hpp>
21#include <boost/detail/workaround.hpp>
22#include <boost/predef/other/endian.h>
23#include <boost/mpl/limits/string.hpp>
24#include <boost/mpl/if.hpp>
25#include <boost/mpl/char.hpp>
26#include <boost/mpl/copy.hpp>
27#include <boost/mpl/size.hpp>
28#include <boost/mpl/empty.hpp>
29#include <boost/mpl/assert.hpp>
30#include <boost/mpl/size_t.hpp>
31#include <boost/mpl/begin_end.hpp>
32#include <boost/mpl/joint_view.hpp>
33#include <boost/mpl/insert_range.hpp>
34#include <boost/mpl/back_inserter.hpp>
35#include <boost/mpl/front_inserter.hpp>
36#include <boost/mpl/iterator_range.hpp>
37#include <boost/preprocessor/arithmetic/dec.hpp>
38#include <boost/preprocessor/arithmetic/add.hpp>
39#include <boost/preprocessor/arithmetic/div.hpp>
40#include <boost/preprocessor/punctuation/comma_if.hpp>
41#include <boost/preprocessor/repetition/repeat.hpp>
42#include <boost/preprocessor/repetition/enum_params.hpp>
43#include <boost/preprocessor/repetition/repeat_from_to.hpp>
44#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
45#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
46#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
47
48#include <iterator> // for bidirectional_iterator_tag
49#include <climits>
50
51namespace boost { namespace mpl
52{
53 #define BOOST_MPL_STRING_MAX_PARAMS \
54 BOOST_PP_DIV(BOOST_PP_ADD(BOOST_MPL_LIMIT_STRING_SIZE, 3), 4)
55
56 // Low-level bit-twiddling is done by macros. Any implementation-defined behavior of
57 // multi-character literals should be localized to these macros.
58
59 #define BOOST_MPL_MULTICHAR_LENGTH(c) \
60 (std::size_t)((c<CHAR_MIN) ? 4 : ((c>0xffffff)+(c>0xffff)+(c>0xff)+1))
61
62 #if BOOST_ENDIAN_LITTLE_BYTE && defined(__SUNPRO_CC)
63
64 #define BOOST_MPL_MULTICHAR_AT(c,i) \
65 (char)(0xff&((unsigned)(c)>>(8*(std::size_t)(i))))
66
67 #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \
68 ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c))
69
70 #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \
71 (((unsigned)(c)<<8)|(unsigned char)(i))
72
73 #define BOOST_MPL_MULTICHAR_POP_BACK(c) \
74 (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c))
75
76 #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \
77 ((unsigned)(c)>>8)
78
79 #else
80
81 #define BOOST_MPL_MULTICHAR_AT(c,i) \
82 (char)(0xff&((unsigned)(c)>>(8*(BOOST_MPL_MULTICHAR_LENGTH(c)-(std::size_t)(i)-1))))
83
84 #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \
85 (((unsigned)(c)<<8)|(unsigned char)(i))
86
87 #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \
88 ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(unsigned)(c))
89
90 #define BOOST_MPL_MULTICHAR_POP_BACK(c) \
91 ((unsigned)(c)>>8)
92
93 #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \
94 (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(unsigned)(c))
95
96 #endif
97
98 struct string_tag;
99 struct string_iterator_tag;
100
101 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_STRING_MAX_PARAMS, int C, 0)>
102 struct string;
103
104 template<typename Sequence, int I, int J>
105 struct string_iterator;
106
107 template<typename Sequence>
108 struct sequence_tag;
109
110 template<typename Tag>
111 struct size_impl;
112
113 template<>
114 struct size_impl<mpl::string_tag>
115 {
116 template<typename Sequence>
117 struct apply;
118
119 #define M0(z, n, data) \
120 + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n))
121
122 #define M1(z, n, data) \
123 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
124 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
125 : mpl::size_t<(0 BOOST_PP_REPEAT_ ## z(n, M0, ~))> \
126 {};
127
128 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M1, ~)
129 #undef M0
130 #undef M1
131 };
132
133 template<>
134 struct size_impl<mpl::string_tag>::apply<mpl::string<> >
135 : mpl::size_t<0>
136 {};
137
138 template<typename Tag>
139 struct begin_impl;
140
141 template<>
142 struct begin_impl<mpl::string_tag>
143 {
144 template<typename Sequence>
145 struct apply
146 {
147 typedef mpl::string_iterator<Sequence, 0, 0> type;
148 };
149 };
150
151 template<typename Tag>
152 struct end_impl;
153
154 template<>
155 struct end_impl<mpl::string_tag>
156 {
157 template<typename Sequence>
158 struct apply;
159
160 #define M0(z,n,data) \
161 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
162 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
163 { \
164 typedef mpl::string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, n, 0> type; \
165 };
166
167 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
168 #undef M0
169 };
170
171 template<>
172 struct end_impl<mpl::string_tag>::apply<mpl::string<> >
173 {
174 typedef mpl::string_iterator<mpl::string<>, 0, 0> type;
175 };
176
177 template<typename Tag>
178 struct push_back_impl;
179
180 template<>
181 struct push_back_impl<mpl::string_tag>
182 {
183 template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::back_))>
184 struct apply
185 {
186 BOOST_MPL_ASSERT_MSG(
187 (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value)
188 , PUSH_BACK_FAILED_MPL_STRING_IS_FULL
189 , (Sequence)
190 );
191 // If the above assertion didn't fire, then the string is sparse.
192 // Repack the string and retry the push_back
193 typedef
194 typename mpl::push_back<
195 typename mpl::copy<
196 Sequence
197 , mpl::back_inserter<mpl::string<> >
198 >::type
199 , Value
200 >::type
201 type;
202 };
203
204 template<typename Value>
205 struct apply<mpl::string<>, Value, false>
206 {
207 typedef mpl::string<(char)Value::value> type;
208 };
209
210 #define M0(z,n,data) \
211 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value> \
212 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, false> \
213 { \
214 typedef \
215 mpl::string< \
216 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \
217 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \
218 ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \
219 ?BOOST_PP_CAT(C,BOOST_PP_DEC(n)) \
220 :BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n)), Value::value) \
221 , ((unsigned)BOOST_PP_CAT(C,BOOST_PP_DEC(n))>0xffffff) \
222 ?(char)Value::value \
223 :0 \
224 > \
225 type; \
226 };
227
228 BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
229 #undef M0
230
231 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value>
232 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
233 {
234 typedef
235 mpl::string<
236 BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS), C)
237 , BOOST_MPL_MULTICHAR_PUSH_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)), Value::value)
238 >
239 type;
240 };
241 };
242
243 template<typename Tag>
244 struct has_push_back_impl;
245
246 template<>
247 struct has_push_back_impl<mpl::string_tag>
248 {
249 template<typename Sequence>
250 struct apply
251 : mpl::true_
252 {};
253 };
254
255 template<typename Tag>
256 struct pop_back_impl;
257
258 template<>
259 struct pop_back_impl<mpl::string_tag>
260 {
261 template<typename Sequence>
262 struct apply;
263
264 #define M0(z,n,data) \
265 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
266 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)> > \
267 { \
268 BOOST_MPL_ASSERT_MSG((C0 != 0), POP_BACK_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \
269 typedef \
270 mpl::string< \
271 BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \
272 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \
273 BOOST_MPL_MULTICHAR_POP_BACK(BOOST_PP_CAT(C,BOOST_PP_DEC(n))) \
274 > \
275 type; \
276 };
277
278 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~)
279 #undef M0
280 };
281
282 template<typename Tag>
283 struct has_pop_back_impl;
284
285 template<>
286 struct has_pop_back_impl<mpl::string_tag>
287 {
288 template<typename Sequence>
289 struct apply
290 : mpl::true_
291 {};
292 };
293
294 template<typename Tag>
295 struct push_front_impl;
296
297 template<>
298 struct push_front_impl<mpl::string_tag>
299 {
300 template<typename Sequence, typename Value, bool B = (4==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
301 struct apply
302 {
303 BOOST_MPL_ASSERT_MSG(
304 (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size<Sequence>::type::value)
305 , PUSH_FRONT_FAILED_MPL_STRING_IS_FULL
306 , (Sequence)
307 );
308 // If the above assertion didn't fire, then the string is sparse.
309 // Repack the string and retry the push_front.
310 typedef
311 typename mpl::push_front<
312 typename mpl::reverse_copy<
313 Sequence
314 , mpl::front_inserter<string<> >
315 >::type
316 , Value
317 >::type
318 type;
319 };
320
321 #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
322 template<typename Value>
323 struct apply<mpl::string<>, Value, false>
324 {
325 typedef mpl::string<(char)Value::value> type;
326 };
327 #endif
328
329 #define M0(z,n,data) \
330 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C), typename Value> \
331 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, Value, true> \
332 { \
333 typedef \
334 mpl::string< \
335 (char)Value::value \
336 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, C) \
337 > \
338 type; \
339 };
340
341 BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
342 #undef M0
343
344 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), typename Value>
345 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, Value, false>
346 {
347 typedef
348 mpl::string<
349 BOOST_MPL_MULTICHAR_PUSH_FRONT(C0, Value::value)
350 , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
351 >
352 type0;
353
354 #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
355 typedef
356 typename mpl::if_<
357 mpl::empty<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> >
358 , mpl::string<(char)Value::value>
359 , type0
360 >::type
361 type;
362 #else
363 typedef type0 type;
364 #endif
365 };
366 };
367
368 template<typename Tag>
369 struct has_push_front_impl;
370
371 template<>
372 struct has_push_front_impl<mpl::string_tag>
373 {
374 template<typename Sequence>
375 struct apply
376 : mpl::true_
377 {};
378 };
379
380 template<typename Tag>
381 struct pop_front_impl;
382
383 template<>
384 struct pop_front_impl<mpl::string_tag>
385 {
386 template<typename Sequence, bool B = (1==BOOST_MPL_MULTICHAR_LENGTH(Sequence::front_))>
387 struct apply;
388
389 #define M0(z,n,data) \
390 template<BOOST_PP_ENUM_PARAMS_Z(z, n, int C)> \
391 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS_Z(z, n, C)>, true> \
392 { \
393 BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \
394 typedef \
395 mpl::string<BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, n, C)> \
396 type; \
397 };
398
399 BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
400 #undef M0
401
402 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>
403 struct apply<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, false>
404 {
405 typedef
406 mpl::string<
407 BOOST_MPL_MULTICHAR_POP_FRONT(C0)
408 , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)
409 >
410 type;
411 };
412 };
413
414 template<typename Tag>
415 struct has_pop_front_impl;
416
417 template<>
418 struct has_pop_front_impl<mpl::string_tag>
419 {
420 template<typename Sequence>
421 struct apply
422 : mpl::true_
423 {};
424 };
425
426 template<typename Tag>
427 struct insert_range_impl;
428
429 template<>
430 struct insert_range_impl<mpl::string_tag>
431 {
432 template<typename Sequence, typename Pos, typename Range>
433 struct apply
434 : mpl::copy<
435 mpl::joint_view<
436 mpl::iterator_range<
437 mpl::string_iterator<Sequence, 0, 0>
438 , Pos
439 >
440 , mpl::joint_view<
441 Range
442 , mpl::iterator_range<
443 Pos
444 , typename mpl::end<Sequence>::type
445 >
446 >
447 >
448 , mpl::back_inserter<mpl::string<> >
449 >
450 {};
451 };
452
453 template<typename Tag>
454 struct insert_impl;
455
456 template<>
457 struct insert_impl<mpl::string_tag>
458 {
459 template<typename Sequence, typename Pos, typename Value>
460 struct apply
461 : mpl::insert_range<Sequence, Pos, mpl::string<(char)Value::value> >
462 {};
463 };
464
465 template<typename Tag>
466 struct erase_impl;
467
468 template<>
469 struct erase_impl<mpl::string_tag>
470 {
471 template<typename Sequence, typename First, typename Last>
472 struct apply
473 : mpl::copy<
474 mpl::joint_view<
475 mpl::iterator_range<
476 mpl::string_iterator<Sequence, 0, 0>
477 , First
478 >
479 , mpl::iterator_range<
480 typename mpl::if_na<Last, typename mpl::next<First>::type>::type
481 , typename mpl::end<Sequence>::type
482 >
483 >
484 , mpl::back_inserter<mpl::string<> >
485 >
486 {};
487 };
488
489 template<typename Tag>
490 struct clear_impl;
491
492 template<>
493 struct clear_impl<mpl::string_tag>
494 {
495 template<typename>
496 struct apply
497 {
498 typedef mpl::string<> type;
499 };
500 };
501
502 #define M0(z, n, data) \
503 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C), int J> \
504 struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, J> \
505 { \
506 enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) }; \
507 typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \
508 typedef std::bidirectional_iterator_tag category; \
509 typedef \
510 mpl::string_iterator<string, n + eomc_, eomc_ ? 0 : J + 1> \
511 next; \
512 typedef \
513 mpl::string_iterator<string, n, J - 1> \
514 prior; \
515 typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), J)> type; \
516 }; \
517 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)> \
518 struct string_iterator<mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)>, n, 0> \
519 { \
520 enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == 1) }; \
521 typedef mpl::string<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C)> string; \
522 typedef std::bidirectional_iterator_tag category; \
523 typedef \
524 mpl::string_iterator<string, n + eomc_, !eomc_> \
525 next; \
526 typedef \
527 mpl::string_iterator< \
528 string \
529 , n - 1 \
530 , BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, BOOST_PP_DEC(n))) - 1 \
531 > \
532 prior; \
533 typedef mpl::char_<BOOST_MPL_MULTICHAR_AT(BOOST_PP_CAT(C, n), 0)> type; \
534 };
535
536 BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~)
537 #undef M0
538
539 template<BOOST_PP_ENUM_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, int C)>
540 struct string
541 {
542 /// INTERNAL ONLY
543 enum
544 {
545 front_ = C0
546 , back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS))
547 };
548
549 typedef char value_type;
550 typedef string type;
551 typedef string_tag tag;
552 };
553
554 namespace aux_
555 {
556 template<typename It, typename End>
557 struct next_unless
558 : mpl::next<It>
559 {};
560
561 template<typename End>
562 struct next_unless<End, End>
563 {
564 typedef End type;
565 };
566
567 template<typename It, typename End>
568 struct deref_unless
569 : mpl::deref<It>
570 {};
571
572 template<typename End>
573 struct deref_unless<End, End>
574 {
575 typedef mpl::char_<'\0'> type;
576 };
577 }
578
579 template<typename Sequence>
580 struct c_str
581 {
582 typedef typename mpl::end<Sequence>::type iend;
583 typedef typename mpl::begin<Sequence>::type i0;
584 #define M0(z, n, data) \
585 typedef \
586 typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::type \
587 BOOST_PP_CAT(i, BOOST_PP_INC(n));
588 BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
589 #undef M0
590
591 typedef c_str type;
592 static typename Sequence::value_type const value[BOOST_MPL_LIMIT_STRING_SIZE+1];
593 };
594
595 template<typename Sequence>
596 typename Sequence::value_type const c_str<Sequence>::value[BOOST_MPL_LIMIT_STRING_SIZE+1] =
597 {
598 #define M0(z, n, data) \
599 mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value,
600 BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
601 #undef M0
602 '\0'
603 };
604
605}} // namespace boost
606
607#endif // BOOST_MPL_STRING_HPP_INCLUDED
608

source code of boost/boost/mpl/string.hpp