string.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. #ifndef BOOST_METAPARSE_V1_STRING_HPP
  2. #define BOOST_METAPARSE_V1_STRING_HPP
  3. // Copyright Abel Sinkovics (abel@sinkovics.hu) 2012.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #include <boost/metaparse/config.hpp>
  8. #include <boost/metaparse/v1/fwd/string.hpp>
  9. #include <boost/metaparse/v1/string_tag.hpp>
  10. #include <boost/metaparse/v1/impl/string_iterator.hpp>
  11. #include <boost/metaparse/v1/impl/empty_string.hpp>
  12. #include <boost/metaparse/v1/impl/size.hpp>
  13. #include <boost/metaparse/v1/impl/pop_front.hpp>
  14. #include <boost/metaparse/v1/impl/push_front_c.hpp>
  15. #include <boost/metaparse/v1/impl/push_back_c.hpp>
  16. #include <boost/metaparse/v1/impl/pop_back.hpp>
  17. #include <boost/metaparse/v1/impl/assert_string_length.hpp>
  18. #include <boost/preprocessor/arithmetic/sub.hpp>
  19. #include <boost/preprocessor/punctuation/comma_if.hpp>
  20. #include <boost/preprocessor/repetition/enum.hpp>
  21. #include <boost/preprocessor/repetition/enum_params.hpp>
  22. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  23. #include <boost/preprocessor/tuple/eat.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. /*
  26. * The string type
  27. */
  28. namespace boost
  29. {
  30. namespace metaparse
  31. {
  32. namespace v1
  33. {
  34. #ifdef BOOST_METAPARSE_VARIADIC_STRING
  35. template <char... Cs>
  36. struct string
  37. {
  38. typedef string type;
  39. typedef string_tag tag;
  40. };
  41. #else
  42. template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
  43. struct string
  44. {
  45. typedef string type;
  46. typedef string_tag tag;
  47. };
  48. #endif
  49. }
  50. }
  51. }
  52. /*
  53. * Boost.MPL overloads
  54. */
  55. namespace boost
  56. {
  57. namespace mpl
  58. {
  59. // push_back
  60. template <class S>
  61. struct push_back_impl;
  62. template <>
  63. struct push_back_impl<boost::metaparse::v1::string_tag>
  64. {
  65. typedef push_back_impl type;
  66. template <class S, class C>
  67. struct apply :
  68. boost::metaparse::v1::impl::push_back_c<
  69. typename S::type,
  70. C::type::value
  71. >
  72. {};
  73. };
  74. // pop_back
  75. template <class S>
  76. struct pop_back_impl;
  77. template <>
  78. struct pop_back_impl<boost::metaparse::v1::string_tag>
  79. {
  80. typedef pop_back_impl type;
  81. template <class S>
  82. struct apply : boost::metaparse::v1::impl::pop_back<S> {};
  83. };
  84. // push_front
  85. template <class S>
  86. struct push_front_impl;
  87. template <>
  88. struct push_front_impl<boost::metaparse::v1::string_tag>
  89. {
  90. typedef push_front_impl type;
  91. template <class S, class C>
  92. struct apply :
  93. boost::metaparse::v1::impl::push_front_c<
  94. typename S::type,
  95. C::type::value
  96. >
  97. {};
  98. };
  99. // pop_front
  100. template <class S>
  101. struct pop_front_impl;
  102. template <>
  103. struct pop_front_impl<boost::metaparse::v1::string_tag>
  104. {
  105. typedef pop_front_impl type;
  106. template <class S>
  107. struct apply : boost::metaparse::v1::impl::pop_front<S> {};
  108. };
  109. // clear
  110. template <class S>
  111. struct clear_impl;
  112. template <>
  113. struct clear_impl<boost::metaparse::v1::string_tag>
  114. {
  115. typedef clear_impl type;
  116. template <class S>
  117. struct apply : boost::metaparse::v1::string<> {};
  118. };
  119. // begin
  120. template <class S>
  121. struct begin_impl;
  122. template <>
  123. struct begin_impl<boost::metaparse::v1::string_tag>
  124. {
  125. typedef begin_impl type;
  126. template <class S>
  127. struct apply :
  128. boost::metaparse::v1::impl::string_iterator<typename S::type, 0>
  129. {};
  130. };
  131. // end
  132. template <class S>
  133. struct end_impl;
  134. template <>
  135. struct end_impl<boost::metaparse::v1::string_tag>
  136. {
  137. typedef end_impl type;
  138. template <class S>
  139. struct apply :
  140. boost::metaparse::v1::impl::string_iterator<
  141. typename S::type,
  142. boost::metaparse::v1::impl::size<typename S::type>::type::value
  143. >
  144. {};
  145. };
  146. // equal_to
  147. template <class A, class B>
  148. struct equal_to_impl;
  149. template <>
  150. struct equal_to_impl<
  151. boost::metaparse::v1::string_tag,
  152. boost::metaparse::v1::string_tag
  153. >
  154. {
  155. typedef equal_to_impl type;
  156. template <class A, class B>
  157. struct apply : boost::is_same<typename A::type, typename B::type> {};
  158. };
  159. template <class T>
  160. struct equal_to_impl<boost::metaparse::v1::string_tag, T>
  161. {
  162. typedef equal_to_impl type;
  163. template <class, class>
  164. struct apply : false_ {};
  165. };
  166. template <class T>
  167. struct equal_to_impl<T, boost::metaparse::v1::string_tag> :
  168. equal_to_impl<boost::metaparse::v1::string_tag, T>
  169. {};
  170. // c_str
  171. template <class S>
  172. struct c_str;
  173. #ifdef BOOST_METAPARSE_VARIADIC_STRING
  174. template <char... Cs>
  175. struct c_str<boost::metaparse::v1::string<Cs...>>
  176. {
  177. typedef c_str type;
  178. #ifdef BOOST_NO_CONSTEXPR_C_STR
  179. static const char value[sizeof...(Cs) + 1];
  180. #else
  181. static constexpr char value[sizeof...(Cs) + 1] = {Cs..., 0};
  182. #endif
  183. };
  184. template <>
  185. struct c_str<boost::metaparse::v1::string<>> :
  186. boost::metaparse::v1::impl::empty_string<>
  187. {};
  188. #ifdef BOOST_NO_CONSTEXPR_C_STR
  189. template <char... Cs>
  190. const char c_str<boost::metaparse::v1::string<Cs...>>::value[]
  191. = {Cs..., 0};
  192. #else
  193. template <char... Cs>
  194. constexpr char c_str<boost::metaparse::v1::string<Cs...>>::value[];
  195. #endif
  196. #else
  197. template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
  198. struct c_str<
  199. boost::metaparse::v1::string<
  200. BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
  201. >
  202. >
  203. {
  204. typedef c_str type;
  205. static BOOST_CONSTEXPR const char
  206. value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
  207. #if !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
  208. = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0}
  209. #endif
  210. ;
  211. };
  212. template <BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, int C)>
  213. BOOST_CONSTEXPR const char
  214. c_str<
  215. boost::metaparse::v1::string<
  216. BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C)
  217. >
  218. >::value[BOOST_METAPARSE_LIMIT_STRING_SIZE + 1]
  219. #if defined BOOST_NO_CONSTEXPR || defined BOOST_NO_CXX11_CONSTEXPR
  220. = {BOOST_PP_ENUM_PARAMS(BOOST_METAPARSE_LIMIT_STRING_SIZE, C), 0}
  221. #endif
  222. ;
  223. template <>
  224. struct c_str<boost::metaparse::v1::string<> > :
  225. boost::metaparse::v1::impl::empty_string<>
  226. {
  227. typedef c_str type;
  228. };
  229. #ifdef BOOST_METAPARSE_DEF
  230. # error BOOST_METAPARSE_DEF already defined
  231. #endif
  232. #define BOOST_METAPARSE_DEF(n) \
  233. = {BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) 0}
  234. #ifdef BOOST_METAPARSE_STRING_DECLARE
  235. # error BOOST_METAPARSE_STRING_DECLARE already defined
  236. #endif
  237. #ifdef BOOST_METAPARSE_STRING_DEFINE
  238. # error BOOST_METAPARSE_STRING_DECLARE already defined
  239. #endif
  240. #if !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR
  241. # define BOOST_METAPARSE_STRING_DECLARE(n) BOOST_METAPARSE_DEF(n)
  242. # define BOOST_METAPARSE_STRING_DEFINE(n)
  243. #else
  244. # define BOOST_METAPARSE_STRING_DECLARE(n)
  245. # define BOOST_METAPARSE_STRING_DEFINE(n) BOOST_METAPARSE_DEF(n)
  246. #endif
  247. #ifdef BOOST_METAPARSE_STRING_CASE
  248. # error BOOST_METAPARSE_STRING_CASE is already defined
  249. #endif
  250. #define BOOST_METAPARSE_STRING_CASE(z, n, unused) \
  251. template <BOOST_PP_ENUM_PARAMS(n, int C)> \
  252. struct \
  253. c_str< \
  254. boost::metaparse::v1::string< \
  255. BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
  256. BOOST_PP_ENUM( \
  257. BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
  258. BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
  259. ~ \
  260. ) \
  261. > \
  262. > \
  263. { \
  264. typedef c_str type; \
  265. static BOOST_CONSTEXPR const char value[n + 1] \
  266. BOOST_METAPARSE_STRING_DECLARE(n); \
  267. }; \
  268. \
  269. template <BOOST_PP_ENUM_PARAMS(n, int C)> \
  270. BOOST_CONSTEXPR const char c_str< \
  271. boost::metaparse::v1::string< \
  272. BOOST_PP_ENUM_PARAMS(n, C) BOOST_PP_COMMA_IF(n) \
  273. BOOST_PP_ENUM( \
  274. BOOST_PP_SUB(BOOST_METAPARSE_LIMIT_STRING_SIZE, n), \
  275. BOOST_NO_CHAR BOOST_PP_TUPLE_EAT(3), \
  276. ~ \
  277. ) \
  278. > \
  279. >::value[n + 1] BOOST_METAPARSE_STRING_DEFINE(n);
  280. BOOST_PP_REPEAT_FROM_TO(
  281. 1,
  282. BOOST_METAPARSE_LIMIT_STRING_SIZE,
  283. BOOST_METAPARSE_STRING_CASE,
  284. ~
  285. )
  286. #undef BOOST_METAPARSE_STRING_CASE
  287. #undef BOOST_METAPARSE_STRING_DECLARE
  288. #undef BOOST_METAPARSE_STRING_DEFINE
  289. #undef BOOST_METAPARSE_DEF
  290. #endif
  291. }
  292. }
  293. /*
  294. * The BOOST_METAPARSE_STRING macro
  295. */
  296. #if \
  297. !defined BOOST_NO_CONSTEXPR && !defined BOOST_NO_CXX11_CONSTEXPR \
  298. && !defined BOOST_CONFIG_NO_BOOST_METAPARSE_STRING
  299. #include <boost/metaparse/v1/impl/remove_trailing_no_chars.hpp>
  300. namespace boost
  301. {
  302. namespace metaparse
  303. {
  304. namespace v1
  305. {
  306. namespace impl
  307. {
  308. template <int Len, class T>
  309. constexpr int string_at(const T (&s)[Len], int n)
  310. {
  311. return n >= Len - 1 ? BOOST_NO_CHAR : s[n];
  312. }
  313. }
  314. }
  315. }
  316. }
  317. #ifdef BOOST_METAPARSE_V1_STRING_N
  318. # error BOOST_METAPARSE_V1_STRING_N already defined
  319. #endif
  320. #define BOOST_METAPARSE_V1_STRING_N(z, n, s) \
  321. boost::metaparse::v1::impl::string_at((s), n)
  322. #ifdef BOOST_METAPARSE_V1_STRING
  323. # error BOOST_METAPARSE_V1_STRING already defined
  324. #endif
  325. #define BOOST_METAPARSE_V1_STRING(s) \
  326. boost::metaparse::v1::impl::assert_string_length< \
  327. sizeof(s) - 1, \
  328. boost::metaparse::v1::impl::remove_trailing_no_chars< \
  329. boost::metaparse::v1::string< \
  330. BOOST_PP_ENUM( \
  331. BOOST_METAPARSE_LIMIT_STRING_SIZE, \
  332. BOOST_METAPARSE_V1_STRING_N, \
  333. s \
  334. ) \
  335. > \
  336. > \
  337. >::type
  338. #else
  339. // Include it only when it is needed
  340. #include <boost/static_assert.hpp>
  341. #ifdef BOOST_METAPARSE_V1_STRING
  342. # error BOOST_METAPARSE_V1_STRING already defined
  343. #endif
  344. #define BOOST_METAPARSE_V1_STRING(s) \
  345. BOOST_STATIC_ASSERT_MSG(false, "BOOST_METAPARSE_STRING is not supported")
  346. #define BOOST_METAPARSE_V1_CONFIG_NO_BOOST_METAPARSE_STRING
  347. #endif
  348. #endif