diff --git a/doc/src/refmanual/IntegralConstant.rst b/doc/src/refmanual/IntegralConstant.rst index ed09ed8..3788129 100644 --- a/doc/src/refmanual/IntegralConstant.rst +++ b/doc/src/refmanual/IntegralConstant.rst @@ -71,6 +71,7 @@ Models * |bool_| * |int_| * |long_| +* |char_| * |integral_c| diff --git a/doc/src/refmanual/LIMIT_STRING_SIZE.rst b/doc/src/refmanual/LIMIT_STRING_SIZE.rst new file mode 100644 index 0000000..4754e90 --- /dev/null +++ b/doc/src/refmanual/LIMIT_STRING_SIZE.rst @@ -0,0 +1,52 @@ +.. Macros/Configuration//BOOST_MPL_LIMIT_STRING_SIZE |65 + +.. 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) + +BOOST_MPL_LIMIT_STRING_SIZE +=========================== + +Synopsis +-------- + +.. parsed-literal:: + + #if !defined(BOOST_MPL_LIMIT_STRING_SIZE) + # define BOOST_MPL_LIMIT_STRING_SIZE \\ + |idic| \\ + /\*\*/ + #endif + + +Description +----------- + +``BOOST_MPL_LIMIT_STRING_SIZE`` is an overridable configuration macro regulating +the maximum arity of the ``string``\ 's |variadic forms|. In this +implementation of the library, ``BOOST_MPL_LIMIT_STRING_SIZE`` has a default value +of 32. To override the default limit, define ``BOOST_MPL_LIMIT_STRING_SIZE`` to +the desired maximum arity before including any library header. + + +Example +------- + +.. parsed-literal:: + + #define BOOST_MPL_LIMIT_STRING_SIZE 8 + ``#``\ include + + using namespace boost::mpl; + + typedef string<'a'> s_1; + typedef string<'abcd','efgh'> s_8; + // typedef string<'abcd','efgh','i'> s_9; // error! + + +See also +-------- + +|Configuration|, |BOOST_MPL_LIMIT_VECTOR_SIZE| + diff --git a/doc/src/refmanual/c_str.rst b/doc/src/refmanual/c_str.rst new file mode 100644 index 0000000..8f0ea4e --- /dev/null +++ b/doc/src/refmanual/c_str.rst @@ -0,0 +1,108 @@ +.. Metafunctions/String Operations//c_str |10 + +.. 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) + +c_str +===== + +Synopsis +-------- + +.. parsed-literal:: + + template< + typename Sequence + > + struct c_str + { + typedef |unspecified| type; + static char const value[]; + }; + + +Description +----------- + +``c_str`` converts the |Forward Sequence| of |Integral Constant|\ s ``Sequence`` +into a null-terminated byte string containing an equivalent sequence. + + +Header +------ + +.. parsed-literal:: + + #include + + +Model of +-------- + +|Metafunction| + + +Parameters +---------- + ++---------------+---------------------------+-----------------------------------------------+ +| Parameter | Requirement | Description | ++===============+===========================+===============================================+ +| ``Sequence`` | |Forward Sequence| of | A sequence to be converted into a | +| | |Integral Constant|\ s | null-terminated byte string. | ++---------------+---------------------------+-----------------------------------------------+ + + +Expression semantics +-------------------- + +.. compound:: + :class: expression-semantics + + For any |Forward Sequence| of |Integral Constant|\ s ``s``, + + .. parsed-literal:: + + c_str::value; + + :Return type: + A null-terminated byte string. + + :Precondition: + ``size::value <= BOOST_MPL_STRING_MAX_LENGTH``. + + :Semantics: + Equivalent to + + .. parsed-literal:: + + char const value[] = { + at::type::value + , ... + , at::value-1>::type::value + , '\\0' + }; + +Complexity +---------- + ++-------------------------------+-----------------------------------+ +| Sequence archetype | Complexity | ++===============================+===================================+ +| |Forward Sequence| | Linear. | ++-------------------------------+-----------------------------------+ + +Example +------- + +.. parsed-literal:: + + typedef vector_c hello; + assert( 0 == std::strcmp( c_str::value, "hello" ) ); + +See also +-------- + +|Forward Sequence|, |Integral Constant|, |string| diff --git a/doc/src/refmanual/char_.rst b/doc/src/refmanual/char_.rst new file mode 100644 index 0000000..c74b334 --- /dev/null +++ b/doc/src/refmanual/char_.rst @@ -0,0 +1,89 @@ +.. Data Types/Numeric//char_ |60 + +.. 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) + +char\_ +====== + +Synopsis +-------- + +.. parsed-literal:: + + template< + char N + > + struct char\_ + { + // |unspecified| + // ... + }; + + +Description +----------- + +An |Integral Constant| wrapper for ``char``. + + +Header +------ + +.. parsed-literal:: + + #include + + +Model of +-------- + +|Integral Constant| + + +Parameters +---------- + ++---------------+-------------------------------+---------------------------+ +| Parameter | Requirement | Description | ++===============+===============================+===========================+ +| ``N`` | A character constant | A value to wrap. | ++---------------+-------------------------------+---------------------------+ + +Expression semantics +-------------------- + +|Semantics disclaimer...| |Integral Constant|. + +For arbitrary character constant ``c``: + ++-------------------+-----------------------------------------------------------+ +| Expression | Semantics | ++===================+===========================================================+ +| ``char_`` | An |Integral Constant| ``x`` such that ``x::value == c`` | +| | and ``x::value_type`` is identical to ``char``. | ++-------------------+-----------------------------------------------------------+ + + +Example +------- + +.. parsed-literal:: + + typedef char_<'c'> c; + + BOOST_MPL_ASSERT(( is_same< c::value_type, char > )); + BOOST_MPL_ASSERT(( is_same< c::type, c > )); + BOOST_MPL_ASSERT(( is_same< next< c >::type, char_<'d'> > )); + BOOST_MPL_ASSERT(( is_same< prior< c >::type, char_<'b'> > )); + BOOST_MPL_ASSERT_RELATION( (c::value), ==, 'c' ); + assert( c() == 'c' ); + + +See also +-------- + +|Data Types|, |Integral Constant|, |int_|, |size_t|, |integral_c| + diff --git a/doc/src/refmanual/refmanual.toc b/doc/src/refmanual/refmanual.toc index caad192..93b115a 100644 --- a/doc/src/refmanual/refmanual.toc +++ b/doc/src/refmanual/refmanual.toc @@ -23,6 +23,7 @@ Metafunctions/Comparisons Metafunctions/Logical Operations Metafunctions/Bitwise Operations Metafunctions/Trivial +Metafunctions/String Operations Metafunctions/Miscellaneous Data Types Data Types/Concepts diff --git a/doc/src/refmanual/string.rst b/doc/src/refmanual/string.rst new file mode 100644 index 0000000..7264041 --- /dev/null +++ b/doc/src/refmanual/string.rst @@ -0,0 +1,135 @@ +.. Sequences/Classes//string |100 + +.. 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) + +string +====== + +Description +----------- + +``string`` is a |variadic|, `bidirectional`__, `extensible`__ |Integral Sequence Wrapper| of +characters that supports amortized constant-time insertion and removal of elements at both ends, +and linear-time insertion and removal of elements in the middle. The parameters to ``string`` +are multi-character literals, giving a somewhat readable syntax for compile-time strings. +``string`` can also be an argument to the ``c_str`` metafunction, which generates a +null-terminated character array that facilitates interoperability with runtime string +processing routines. + +__ `Bidirectional Sequence`_ +__ `Extensible Sequence`_ + +Header +------ + ++-------------------+-------------------------------------------------------+ +| Sequence form | Header | ++===================+=======================================================+ +| Variadic | ``#include `` | ++-------------------+-------------------------------------------------------+ + +Model of +-------- + +* |Integral Sequence Wrapper| +* |Variadic Sequence| +* |Bidirectional Sequence| +* |Extensible Sequence| +* |Back Extensible Sequence| +* |Front Extensible Sequence| + +Expression semantics +-------------------- + +In the following table, ``s`` is an instance of ``string``, ``pos`` and ``last`` are iterators +into ``s``, ``r`` is a |Forward Sequence| of characters, ``n`` and ``x`` are |Integral Constant|\ s, +and |c1...cn| are arbitrary (multi-)characters. + ++---------------------------------------+-----------------------------------------------------------+ +| Expression | Semantics | ++=======================================+===========================================================+ +| .. parsed-literal:: | ``string`` of characters |c1...cn|; see | +| | |Variadic Sequence|. | +| string<|c1...cn|> | | ++---------------------------------------+-----------------------------------------------------------+ +| .. parsed-literal:: | Identical to ``string<``\ |c1...cn|\ ``>``; | +| | see |Variadic Sequence|. | +| string<|c1...cn|>::type | | ++---------------------------------------+-----------------------------------------------------------+ +| ``begin::type`` | An iterator pointing to the beginning of ``s``; | +| | see |Bidirectional Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``end::type`` | An iterator pointing to the end of ``s``; | +| | see |Bidirectional Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``size::type`` | The size of ``s``; see |Bidirectional Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``empty::type`` | |true if and only if| the sequence is empty; | +| | see |Bidirectional Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``front::type`` | The first element in ``s``; see | +| | |Bidirectional Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``back::type`` | The last element in ``s``; see | +| | |Bidirectional Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``insert::type`` | A new ``string`` of following elements: | +| | [``begin::type``, ``pos``), ``x``, | +| | [``pos``, ``end::type``); see |Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``insert_range::type`` | A new ``string`` of following elements: | +| | [``begin::type``, ``pos``), | +| | [``begin::type``, ``end::type``) | +| | [``pos``, ``end::type``); see |Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``erase::type`` | A new ``string`` of following elements: | +| | [``begin::type``, ``pos``), | +| | [``next::type``, ``end::type``); see | +| | |Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``erase::type`` | A new ``string`` of following elements: | +| | [``begin::type``, ``pos``), | +| | [``last``, ``end::type``); see |Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``clear::type`` | An empty ``string``; see |Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``push_back::type`` | A new ``string`` of following elements: | +| | |begin/end|, ``x``; | +| | see |Back Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``pop_back::type`` | A new ``string`` of following elements: | +| | [``begin::type``, ``prior< end::type >::type``); | +| | see |Back Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``push_front::type`` | A new ``string`` of following elements: | +| | |begin/end|, ``x``; see |Front Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``pop_front::type`` | A new ``string`` of following elements: | +| | [``next< begin::type >::type``, ``end::type``); | +| | see |Front Extensible Sequence|. | ++---------------------------------------+-----------------------------------------------------------+ +| ``c_str::value`` | A null-terminated byte string such that | +| | ``c_str::value[``\ *n*\ ``]`` is equal to the *n*\ -th | +| | character in ``s``, and | +| | ``c_str::value[size::type::value]`` is ``'\0'``. | ++---------------------------------------+-----------------------------------------------------------+ + + +Example +------- + +.. parsed-literal:: + + typedef mpl::string<'hell','o wo','rld'> hello; + typedef mpl::push_back >::type hello2; + + BOOST_ASSERT(0 == std::strcmp(mpl::c_str::value, "hello world!")); + + +See also +-------- + +|Sequences|, |Variadic Sequence|, |Bidirectional Sequence|, |Extensible Sequence|, |Integral Sequence Wrapper|, |char_|, |c_str| diff --git a/include/boost/mpl/char.hpp b/include/boost/mpl/char.hpp new file mode 100644 index 0000000..08828c2 --- /dev/null +++ b/include/boost/mpl/char.hpp @@ -0,0 +1,22 @@ + +#ifndef BOOST_MPL_CHAR_HPP_INCLUDED +#define BOOST_MPL_CHAR_HPP_INCLUDED + +// Copyright Eric Niebler 2008 +// +// 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. + +// $Source$ +// $Date: 2008-06-14 08:41:37 -0700 (Sat, 16 Jun 2008) $ +// $Revision: 24874 $ + +#include + +#define AUX_WRAPPER_VALUE_TYPE char +#include + +#endif // BOOST_MPL_CHAR_HPP_INCLUDED diff --git a/include/boost/mpl/char_fwd.hpp b/include/boost/mpl/char_fwd.hpp new file mode 100644 index 0000000..442d0a1 --- /dev/null +++ b/include/boost/mpl/char_fwd.hpp @@ -0,0 +1,27 @@ + +#ifndef BOOST_MPL_CHAR_FWD_HPP_INCLUDED +#define BOOST_MPL_CHAR_FWD_HPP_INCLUDED + +// Copyright Eric Niebler 2008 +// +// 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. + +// $Source$ +// $Date: 2008-06-14 08:41:37 -0700 (Sat, 16 Jun 2008) $ +// $Revision: 24874 $ + +#include +#include + +BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN + +template< BOOST_MPL_AUX_NTTP_DECL(char, N) > struct char_; + +BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE +BOOST_MPL_AUX_ADL_BARRIER_DECL(char_) + +#endif // BOOST_MPL_CHAR_FWD_HPP_INCLUDED diff --git a/include/boost/mpl/limits/string.hpp b/include/boost/mpl/limits/string.hpp new file mode 100644 index 0000000..eb85aa3 --- /dev/null +++ b/include/boost/mpl/limits/string.hpp @@ -0,0 +1,21 @@ + +#ifndef BOOST_MPL_LIMITS_STRING_HPP_INCLUDED +#define BOOST_MPL_LIMITS_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 $ + +#if !defined(BOOST_MPL_LIMIT_STRING_SIZE) +# define BOOST_MPL_LIMIT_STRING_SIZE 32 +#endif + +#endif // BOOST_MPL_LIMITS_STRING_HPP_INCLUDED diff --git a/include/boost/mpl/string.hpp b/include/boost/mpl/string.hpp new file mode 100644 index 0000000..ce7c782 --- /dev/null +++ b/include/boost/mpl/string.hpp @@ -0,0 +1,555 @@ + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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>0xffffff)+(c>0xffff)+(c>0xff)+1) + + #if defined(BOOST_LITTLE_ENDIAN) && defined(__SUNPRO_CC) + + #define BOOST_MPL_MULTICHAR_AT(c,i) \ + (char)(0xff&(c>>(8*(std::size_t)(i)))) + + #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \ + ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(c)) + + #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \ + (((c)<<8)|(unsigned char)(i)) + + #define BOOST_MPL_MULTICHAR_POP_BACK(c) \ + (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(c)) + + #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \ + ((c)>>8) + + #else + + #define BOOST_MPL_MULTICHAR_AT(c,i) \ + (char)(0xff&(c>>(8*(BOOST_MPL_MULTICHAR_LENGTH(c)-(std::size_t)(i)-1)))) + + #define BOOST_MPL_MULTICHAR_PUSH_BACK(c,i) \ + (((c)<<8)|(unsigned char)(i)) + + #define BOOST_MPL_MULTICHAR_PUSH_FRONT(c,i) \ + ((((unsigned char)(i))<<(BOOST_MPL_MULTICHAR_LENGTH(c)*8))|(c)) + + #define BOOST_MPL_MULTICHAR_POP_BACK(c) \ + ((c)>>8) + + #define BOOST_MPL_MULTICHAR_POP_FRONT(c) \ + (((1<<((BOOST_MPL_MULTICHAR_LENGTH(c)-1)*8))-1)&(c)) + + #endif + + struct string_tag; + struct string_iterator_tag; + + template + struct string; + + template + struct string_iterator; + + template + struct sequence_tag; + + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply; + + #define M0(z, n, data) \ + + BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C,n)) + + #define M1(z, n, data) \ + template \ + struct apply > \ + : 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::apply > + : mpl::size_t<0> + {}; + + template + struct begin_impl; + + template<> + struct begin_impl + { + template + struct apply + { + typedef mpl::string_iterator type; + }; + }; + + template + struct end_impl; + + template<> + struct end_impl + { + template + struct apply; + + #define M0(z,n,data) \ + template \ + struct apply > \ + { \ + typedef mpl::string_iterator, n, 0> type; \ + }; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_MPL_STRING_MAX_PARAMS), M0, ~) + #undef M0 + }; + + template<> + struct end_impl::apply > + { + typedef mpl::string_iterator, 0, 0> type; + }; + + template + struct push_back_impl; + + template<> + struct push_back_impl + { + template + struct apply + { + BOOST_MPL_ASSERT_MSG( + (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size::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 > + >::type + , Value + >::type + type; + }; + + template + struct apply, Value, false> + { + typedef mpl::string<(char)Value::value> type; + }; + + #define M0(z,n,data) \ + template \ + struct apply, Value, false> \ + { \ + typedef \ + mpl::string< \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), C) \ + BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + (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) \ + , (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 + struct apply, 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 + struct pop_back_impl; + + template<> + struct pop_back_impl + { + template + struct apply; + + #define M0(z,n,data) \ + template \ + struct apply > \ + { \ + 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 + struct push_front_impl; + + template<> + struct push_front_impl + { + template + struct apply + { + BOOST_MPL_ASSERT_MSG( + (BOOST_MPL_LIMIT_STRING_SIZE != mpl::size::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 > + >::type + , Value + >::type + type; + }; + + #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + template + struct apply, Value, false> + { + typedef mpl::string<(char)Value::value> type; + }; + #endif + + #define M0(z,n,data) \ + template \ + struct apply, 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 + struct apply, 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<(char)Value::value> + , type0 + >::type + type; + #else + typedef type0 type; + #endif + }; + }; + + template + struct pop_front_impl; + + template<> + struct pop_front_impl + { + template + struct apply; + + #define M0(z,n,data) \ + template \ + struct apply, true> \ + { \ + BOOST_MPL_ASSERT_MSG((C0 != 0), POP_FRONT_FAILED_MPL_STRING_IS_EMPTY, (mpl::string<>)); \ + typedef \ + mpl::string \ + type; \ + }; + + BOOST_PP_REPEAT_FROM_TO(1, BOOST_MPL_STRING_MAX_PARAMS, M0, ~) + #undef M0 + + template + struct apply, false> + { + typedef + mpl::string< + BOOST_MPL_MULTICHAR_POP_FRONT(C0) + , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_MPL_STRING_MAX_PARAMS, C) + > + type; + }; + }; + + template + struct insert_range_impl; + + template<> + struct insert_range_impl + { + template + struct apply + : mpl::copy< + mpl::joint_view< + mpl::iterator_range< + mpl::string_iterator + , Pos + > + , mpl::joint_view< + Range + , mpl::iterator_range< + Pos + , typename mpl::end::type + > + > + > + , mpl::back_inserter > + > + {}; + }; + + template + struct insert_impl; + + template<> + struct insert_impl + { + template + struct apply + : mpl::insert_range > + {}; + }; + + template + struct erase_impl; + + template<> + struct erase_impl + { + template + struct apply + : mpl::copy< + mpl::joint_view< + mpl::iterator_range< + mpl::string_iterator + , First + > + , mpl::iterator_range< + typename mpl::if_na::type>::type + , typename mpl::end::type + > + > + , mpl::back_inserter > + > + {}; + }; + + template + struct clear_impl; + + template<> + struct clear_impl + { + template + struct apply + { + typedef mpl::string<> type; + }; + }; + + #define M0(z, n, data) \ + template \ + struct string_iterator, n, J> \ + { \ + enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == J + 1) }; \ + typedef mpl::string string; \ + typedef std::bidirectional_iterator_tag category; \ + typedef \ + mpl::string_iterator \ + next; \ + typedef \ + mpl::string_iterator \ + prior; \ + typedef mpl::char_ type; \ + }; \ + template \ + struct string_iterator, n, 0> \ + { \ + enum { eomc_ = (BOOST_MPL_MULTICHAR_LENGTH(BOOST_PP_CAT(C, n)) == 1) }; \ + typedef mpl::string string; \ + typedef std::bidirectional_iterator_tag category; \ + typedef \ + mpl::string_iterator \ + 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_ type; \ + }; + + BOOST_PP_REPEAT(BOOST_MPL_STRING_MAX_PARAMS, M0, ~) + #undef M0 + + template + struct string + { + /// INTERNAL ONLY + enum + { + front_ = C0 + , back_ = BOOST_PP_CAT(C, BOOST_PP_DEC(BOOST_MPL_STRING_MAX_PARAMS)) + }; + + typedef string type; + typedef string_tag tag; + }; + + namespace aux_ + { + template + struct next_unless + : mpl::next + {}; + + template + struct next_unless + { + typedef End type; + }; + + template + struct deref_unless + : mpl::deref + {}; + + template + struct deref_unless + { + typedef mpl::char_<'\0'> type; + }; + } + + template + struct c_str + { + typedef typename mpl::end::type iend; + typedef typename mpl::begin::type i0; + #define M0(z, n, data) \ + typedef \ + typename mpl::aux_::next_unless::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 char const value[]; + }; + + template + char const c_str::value[] = + { + #define M0(z, n, data) \ + mpl::aux_::deref_unless::type::value, + BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~) + #undef M0 + '\0' + }; + +}} // namespace boost + +#endif // BOOST_MPL_STRING_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 71c5727..d8a14d3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -44,6 +44,7 @@ compile inherit.cpp ; compile insert.cpp ; compile insert_range.cpp ; run int.cpp ; +run char.cpp ; run integral_c.cpp : : : vacpp:-qchars=signed ; compile is_placeholder.cpp ; compile is_sequence.cpp ; @@ -90,3 +91,4 @@ compile upper_bound.cpp ; compile vector.cpp ; compile vector_c.cpp ; compile zip_view.cpp ; +run string.cpp ; diff --git a/test/char.cpp b/test/char.cpp new file mode 100644 index 0000000..39f61e7 --- /dev/null +++ b/test/char.cpp @@ -0,0 +1,24 @@ + +// Copyright Eric Niebler 2008 +// +// 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: char.cpp 49240 2009-04-01 09:21:07Z eric_niebler $ +// $Date: 2009-04-01 02:21:07 -0700 (Wed, 1 Apr 2009) $ +// $Revision: 49240 $ + +#include +#include + +#include "integral_wrapper_test.hpp" + + +MPL_TEST_CASE() +{ +# define WRAPPER(T, i) char_ + BOOST_PP_REPEAT(10, INTEGRAL_WRAPPER_TEST, char) +} diff --git a/test/string.cpp b/test/string.cpp new file mode 100644 index 0000000..f50073b --- /dev/null +++ b/test/string.cpp @@ -0,0 +1,475 @@ + +// 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.cpp 49240 2009-04-01 09:21:07Z eric_niebler $ +// $Date: 2009-04-01 02:21:07 -0700 (Wed, 1 Apr 2009) $ +// $Revision: 49240 $ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mpl = boost::mpl; + +// Accept a string as a template parameter! +template +struct greeting +{ + std::string say_hello() const + { + return sz; + } +}; + +struct push_char +{ + push_char(std::string &str) + : str_(&str) + {} + + void operator()(char ch) const + { + this->str_->push_back(ch); + } + + std::string *str_; +}; + +int main() +{ + // Test mpl::size of strings + { + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full; + + BOOST_MPL_ASSERT_RELATION(0, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(1, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(2, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(2, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(4, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(5, ==, (mpl::size >::value)); + BOOST_MPL_ASSERT_RELATION(31, ==, (mpl::size::value)); + BOOST_MPL_ASSERT_RELATION(32, ==, (mpl::size::value)); + } + + // Test mpl::begin and mpl::end with strings + { + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> full; + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin >::type + , mpl::end >::type + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin >::type + , mpl::string_iterator, 0, 0> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::end >::type + , mpl::string_iterator, 1, 0> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin::type + , mpl::string_iterator + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::end::type + , mpl::string_iterator + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::begin::type + , mpl::string_iterator + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::end::type + , mpl::string_iterator + > + )); + } + + // testing push_back + { + typedef mpl::push_back, mpl::char_<'a'> >::type t1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::push_back >::type t6; + BOOST_MPL_ASSERT((boost::is_same >)); + } + + // Test mpl::next + { + typedef mpl::string<'a','bc','def','ghij'> s; + + typedef mpl::begin::type i0; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i7; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i8; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i9; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::next::type i10; + BOOST_MPL_ASSERT((boost::is_same >)); + + BOOST_MPL_ASSERT((boost::is_same::type>)); + } + + // Test mpl::prior + { + typedef mpl::string<'a','bc','def','ghij'> s; + + typedef mpl::end::type i10; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i9; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i8; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i7; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::prior::type i0; + BOOST_MPL_ASSERT((boost::is_same >)); + + BOOST_MPL_ASSERT((boost::is_same::type>)); + } + + // Test mpl::deref + { + typedef mpl::string<'a','bc','def','ghij'> s; + + typedef mpl::begin::type i0; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'a'> >)); + + typedef mpl::next::type i1; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'b'> >)); + + typedef mpl::next::type i2; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'c'> >)); + + typedef mpl::next::type i3; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'d'> >)); + + typedef mpl::next::type i4; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'e'> >)); + + typedef mpl::next::type i5; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'f'> >)); + + typedef mpl::next::type i6; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'g'> >)); + + typedef mpl::next::type i7; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'h'> >)); + + typedef mpl::next::type i8; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'i'> >)); + + typedef mpl::next::type i9; + BOOST_MPL_ASSERT((boost::is_same::type, mpl::char_<'j'> >)); + } + + // testing push_back + { + typedef mpl::push_back, mpl::char_<'a'> >::type t1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_back >::type t5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> almost_full; + typedef mpl::push_back >::type t6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'a','a','a','a','a','a','a','aaaa'> must_repack; + typedef mpl::push_back >::type t7; + BOOST_MPL_ASSERT((boost::is_same >)); + } + + BOOST_MPL_ASSERT((mpl::empty >)); + BOOST_MPL_ASSERT_NOT((mpl::empty >)); + + // testing push_front + { + typedef mpl::push_front, mpl::char_<'a'> >::type t1; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t2; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t3; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t4; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::push_front >::type t5; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> almost_full; + typedef mpl::push_front >::type t6; + BOOST_MPL_ASSERT((boost::is_same >)); + + typedef mpl::string<'aaaa','a','a','a','a','a','a','a'> must_repack; + typedef mpl::push_front >::type t7; + BOOST_MPL_ASSERT((boost::is_same >)); + } + + // Test c_str<> + BOOST_TEST(0 == std::strcmp( + mpl::c_str >::value + , "" + )); + + BOOST_TEST(0 == std::strcmp( + mpl::c_str >::value + , "Hell" "o wo" "rld!" + )); + + BOOST_TEST(0 == std::strcmp( + mpl::c_str >::value + , "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaa" "aaaX" + )); + + // test using a string as a template parameter + greeting >::value> g; + BOOST_TEST("Hello world!" == g.say_hello()); + + std::string result; + mpl::for_each >(push_char(result)); + BOOST_TEST("Hello world!" == result); + + BOOST_TEST(('h' == mpl::front >::type())); + BOOST_TEST(('!' == mpl::back >::type())); + + // back-inserter with copy + typedef mpl::vector_c rgc; + BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str::value)); + typedef mpl::copy > >::type str; + BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str::value)); + + // test insert_range and erase + { + typedef mpl::string<'Hell','o wo','rld!'> hello; + typedef mpl::advance_c::type, 5>::type where; + typedef mpl::string<' cru','el'> cruel; + typedef mpl::insert_range::type hello_cruel; + BOOST_TEST(0 == std::strcmp("Hello cruel world!", mpl::c_str::value)); + + typedef mpl::erase::type, where>::type erased1; + BOOST_TEST(0 == std::strcmp(" world!", mpl::c_str::value)); + } + + // test pop_front + { + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'b'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'bc'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'bcd'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'bcd','e'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'e'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_front >::type + , mpl::string<'aaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa'> + > + )); + } + + // test pop_back + { + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'a'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'ab'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'abc'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'abcd'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'d'> + > + )); + + BOOST_MPL_ASSERT(( + boost::is_same< + mpl::pop_back >::type + , mpl::string<'aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaaa','aaa'> + > + )); + } + + return boost::report_errors(); +}