/Src/Dependencies/Boost/boost/spirit/home/karma/string/lit.hpp

http://hadesmem.googlecode.com/ · C++ Header · 334 lines · 255 code · 41 blank · 38 comment · 11 complexity · 8e69ed380993cb7db463aa7254b635cb MD5 · raw file

  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2010 Bryce Lelbach
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(BOOST_SPIRIT_KARMA_LIT_FEB_22_2007_0534PM)
  7. #define BOOST_SPIRIT_KARMA_LIT_FEB_22_2007_0534PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/support/common_terminals.hpp>
  12. #include <boost/spirit/home/support/string_traits.hpp>
  13. #include <boost/spirit/home/support/info.hpp>
  14. #include <boost/spirit/home/support/char_class.hpp>
  15. #include <boost/spirit/home/support/container.hpp>
  16. #include <boost/spirit/home/support/handles_container.hpp>
  17. #include <boost/spirit/home/support/detail/get_encoding.hpp>
  18. #include <boost/spirit/home/karma/domain.hpp>
  19. #include <boost/spirit/home/karma/meta_compiler.hpp>
  20. #include <boost/spirit/home/karma/delimit_out.hpp>
  21. #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
  22. #include <boost/spirit/home/karma/detail/get_casetag.hpp>
  23. #include <boost/spirit/home/karma/detail/extract_from.hpp>
  24. #include <boost/spirit/home/karma/detail/string_generate.hpp>
  25. #include <boost/spirit/home/karma/detail/string_compare.hpp>
  26. #include <boost/spirit/home/karma/detail/enable_lit.hpp>
  27. #include <boost/fusion/include/at.hpp>
  28. #include <boost/fusion/include/vector.hpp>
  29. #include <boost/fusion/include/cons.hpp>
  30. #include <boost/mpl/if.hpp>
  31. #include <boost/mpl/or.hpp>
  32. #include <boost/mpl/assert.hpp>
  33. #include <boost/mpl/bool.hpp>
  34. #include <boost/utility/enable_if.hpp>
  35. #include <string>
  36. ///////////////////////////////////////////////////////////////////////////////
  37. namespace boost { namespace spirit
  38. {
  39. ///////////////////////////////////////////////////////////////////////////
  40. // Enablers
  41. ///////////////////////////////////////////////////////////////////////////
  42. template <typename CharEncoding>
  43. struct use_terminal<karma::domain
  44. , tag::char_code<tag::string, CharEncoding> > // enables string
  45. : mpl::true_ {};
  46. template <typename T>
  47. struct use_terminal<karma::domain, T
  48. , typename enable_if<traits::is_string<T> >::type> // enables string literals
  49. : mpl::true_ {};
  50. template <typename CharEncoding, typename A0>
  51. struct use_terminal<karma::domain
  52. , terminal_ex<
  53. tag::char_code<tag::string, CharEncoding> // enables string(str)
  54. , fusion::vector1<A0> >
  55. > : traits::is_string<A0> {};
  56. template <typename CharEncoding> // enables string(f)
  57. struct use_lazy_terminal<
  58. karma::domain
  59. , tag::char_code<tag::string, CharEncoding>
  60. , 1 /*arity*/
  61. > : mpl::true_ {};
  62. // enables lit(str)
  63. template <typename A0>
  64. struct use_terminal<karma::domain
  65. , terminal_ex<tag::lit, fusion::vector1<A0> >
  66. , typename enable_if<traits::is_string<A0> >::type>
  67. : mpl::true_ {};
  68. }}
  69. ///////////////////////////////////////////////////////////////////////////////
  70. namespace boost { namespace spirit { namespace karma
  71. {
  72. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  73. using spirit::lit;
  74. #endif
  75. using spirit::lit_type;
  76. ///////////////////////////////////////////////////////////////////////////
  77. // generate literal strings from a given parameter
  78. ///////////////////////////////////////////////////////////////////////////
  79. template <typename CharEncoding, typename Tag>
  80. struct any_string
  81. : primitive_generator<any_string<CharEncoding, Tag> >
  82. {
  83. typedef typename CharEncoding::char_type char_type;
  84. typedef CharEncoding char_encoding;
  85. template <typename Context, typename Unused = unused_type>
  86. struct attribute
  87. {
  88. typedef std::basic_string<char_type> type;
  89. };
  90. // lit has an attached attribute
  91. template <typename OutputIterator, typename Context, typename Delimiter
  92. , typename Attribute>
  93. static bool
  94. generate(OutputIterator& sink, Context& context, Delimiter const& d,
  95. Attribute const& attr)
  96. {
  97. if (!traits::has_optional_value(attr))
  98. return false;
  99. typedef typename attribute<Context>::type attribute_type;
  100. return
  101. karma::detail::string_generate(sink
  102. , traits::extract_from<attribute_type>(attr, context)
  103. , char_encoding(), Tag()) &&
  104. karma::delimit_out(sink, d); // always do post-delimiting
  105. }
  106. // this lit has no attribute attached, it needs to have been
  107. // initialized from a direct literal
  108. template <typename OutputIterator, typename Context, typename Delimiter>
  109. static bool generate(OutputIterator&, Context&, Delimiter const&,
  110. unused_type const&)
  111. {
  112. // It is not possible (doesn't make sense) to use string without
  113. // providing any attribute, as the generator doesn't 'know' what
  114. // character to output. The following assertion fires if this
  115. // situation is detected in your code.
  116. BOOST_SPIRIT_ASSERT_MSG(false, string_not_usable_without_attribute, ());
  117. return false;
  118. }
  119. template <typename Context>
  120. static info what(Context const& /*context*/)
  121. {
  122. return info("any-string");
  123. }
  124. };
  125. ///////////////////////////////////////////////////////////////////////////
  126. // generate literal strings
  127. ///////////////////////////////////////////////////////////////////////////
  128. template <typename String, typename CharEncoding, typename Tag, bool no_attribute>
  129. struct literal_string
  130. : primitive_generator<literal_string<String, CharEncoding, Tag, no_attribute> >
  131. {
  132. typedef CharEncoding char_encoding;
  133. typedef typename
  134. remove_const<typename traits::char_type_of<String>::type>::type
  135. char_type;
  136. typedef std::basic_string<char_type> string_type;
  137. template <typename Context, typename Unused = unused_type>
  138. struct attribute
  139. : mpl::if_c<no_attribute, unused_type, string_type>
  140. {};
  141. literal_string(typename add_reference<String>::type str)
  142. : str_(str)
  143. {}
  144. // A string("...") which additionally has an associated attribute emits
  145. // its immediate literal only if it matches the attribute, otherwise
  146. // it fails.
  147. template <
  148. typename OutputIterator, typename Context, typename Delimiter
  149. , typename Attribute>
  150. bool generate(OutputIterator& sink, Context& context
  151. , Delimiter const& d, Attribute const& attr) const
  152. {
  153. if (!traits::has_optional_value(attr))
  154. return false;
  155. // fail if attribute isn't matched by immediate literal
  156. typedef typename attribute<Context>::type attribute_type;
  157. typedef typename spirit::result_of::extract_from<attribute_type, Attribute>::type
  158. extracted_string_type;
  159. using spirit::traits::get_c_string;
  160. if (!detail::string_compare(
  161. get_c_string(
  162. traits::extract_from<attribute_type>(attr, context))
  163. , get_c_string(str_), char_encoding(), Tag()))
  164. {
  165. return false;
  166. }
  167. return detail::string_generate(sink, str_, char_encoding(), Tag()) &&
  168. karma::delimit_out(sink, d); // always do post-delimiting
  169. }
  170. // A string("...") without any associated attribute just emits its
  171. // immediate literal
  172. template <typename OutputIterator, typename Context, typename Delimiter>
  173. bool generate(OutputIterator& sink, Context&, Delimiter const& d
  174. , unused_type) const
  175. {
  176. return detail::string_generate(sink, str_, char_encoding(), Tag()) &&
  177. karma::delimit_out(sink, d); // always do post-delimiting
  178. }
  179. template <typename Context>
  180. info what(Context const& /*context*/) const
  181. {
  182. return info("literal-string", str_);
  183. }
  184. string_type str_;
  185. };
  186. ///////////////////////////////////////////////////////////////////////////
  187. // Generator generators: make_xxx function (objects)
  188. ///////////////////////////////////////////////////////////////////////////
  189. // string
  190. template <typename CharEncoding, typename Modifiers>
  191. struct make_primitive<
  192. tag::char_code<tag::string, CharEncoding>
  193. , Modifiers>
  194. {
  195. static bool const lower =
  196. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  197. static bool const upper =
  198. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  199. typedef any_string<
  200. typename spirit::detail::get_encoding_with_case<
  201. Modifiers, CharEncoding, lower || upper>::type
  202. , typename detail::get_casetag<Modifiers, lower || upper>::type
  203. > result_type;
  204. result_type operator()(unused_type, unused_type) const
  205. {
  206. return result_type();
  207. }
  208. };
  209. // string literal
  210. template <typename T, typename Modifiers>
  211. struct make_primitive<T, Modifiers
  212. , typename enable_if<traits::is_string<T> >::type>
  213. {
  214. static bool const lower =
  215. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  216. static bool const upper =
  217. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  218. typedef typename add_const<T>::type const_string;
  219. typedef literal_string<
  220. const_string
  221. , typename spirit::detail::get_encoding_with_case<
  222. Modifiers, unused_type, lower || upper>::type
  223. , typename detail::get_casetag<Modifiers, lower || upper>::type
  224. , true
  225. > result_type;
  226. result_type operator()(
  227. typename add_reference<const_string>::type str, unused_type) const
  228. {
  229. return result_type(str);
  230. }
  231. };
  232. ///////////////////////////////////////////////////////////////////////////
  233. namespace detail
  234. {
  235. template <typename CharEncoding, typename Modifiers, typename A0
  236. , bool no_attribute>
  237. struct make_string_direct
  238. {
  239. static bool const lower =
  240. has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
  241. static bool const upper =
  242. has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
  243. typedef typename add_const<A0>::type const_string;
  244. typedef literal_string<
  245. const_string
  246. , typename spirit::detail::get_encoding_with_case<
  247. Modifiers, unused_type, lower || upper>::type
  248. , typename detail::get_casetag<Modifiers, lower || upper>::type
  249. , no_attribute
  250. > result_type;
  251. template <typename Terminal>
  252. result_type operator()(Terminal const& term, unused_type) const
  253. {
  254. return result_type(fusion::at_c<0>(term.args));
  255. }
  256. };
  257. }
  258. // string("..."), lit("...")
  259. template <typename CharEncoding, typename Modifiers, typename A0>
  260. struct make_primitive<
  261. terminal_ex<
  262. tag::char_code<tag::string, CharEncoding>
  263. , fusion::vector1<A0> >
  264. , Modifiers>
  265. : detail::make_string_direct<CharEncoding, Modifiers, A0, false>
  266. {};
  267. template <typename Modifiers, typename A0>
  268. struct make_primitive<
  269. terminal_ex<tag::lit, fusion::vector1<A0> >
  270. , Modifiers
  271. , typename enable_if<traits::is_string<A0> >::type>
  272. : detail::make_string_direct<
  273. typename traits::char_encoding_from_char<
  274. typename traits::char_type_of<A0>::type>::type
  275. , Modifiers, A0, true>
  276. {};
  277. }}} // namespace boost::spirit::karma
  278. namespace boost { namespace spirit { namespace traits
  279. {
  280. ///////////////////////////////////////////////////////////////////////////
  281. template <typename CharEncoding, typename Tag, typename Attribute
  282. , typename Context, typename Iterator>
  283. struct handles_container<karma::any_string<CharEncoding, Tag>, Attribute
  284. , Context, Iterator>
  285. : mpl::false_ {};
  286. template <typename String, typename CharEncoding, typename Tag
  287. , bool no_attribute, typename Attribute, typename Context
  288. , typename Iterator>
  289. struct handles_container<karma::literal_string<String, CharEncoding, Tag
  290. , no_attribute>, Attribute, Context, Iterator>
  291. : mpl::false_ {};
  292. }}}
  293. #endif