string_traits.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Copyright (c) 2010 Bryce Lelbach
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ================================================_==============================*/
  8. #if !defined(BOOST_SPIRIT_STRING_TRAITS_OCTOBER_2008_1252PM)
  9. #define BOOST_SPIRIT_STRING_TRAITS_OCTOBER_2008_1252PM
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/spirit/home/support/container.hpp>
  14. #include <string>
  15. #include <boost/mpl/bool.hpp>
  16. #include <boost/mpl/identity.hpp>
  17. #include <boost/mpl/if.hpp>
  18. #include <boost/proto/proto_fwd.hpp>
  19. #include <boost/type_traits/is_const.hpp>
  20. #if defined(__GNUC__) && (__GNUC__ < 4)
  21. #include <boost/type_traits/add_const.hpp>
  22. #endif
  23. namespace boost { namespace spirit { namespace traits
  24. {
  25. ///////////////////////////////////////////////////////////////////////////
  26. // Determine if T is a character type
  27. ///////////////////////////////////////////////////////////////////////////
  28. template <typename T>
  29. struct is_char : mpl::false_ {};
  30. template <typename T>
  31. struct is_char<T const> : is_char<T> {};
  32. template <>
  33. struct is_char<char> : mpl::true_ {};
  34. template <>
  35. struct is_char<wchar_t> : mpl::true_ {};
  36. ///////////////////////////////////////////////////////////////////////////
  37. // Determine if T is a string
  38. ///////////////////////////////////////////////////////////////////////////
  39. template <typename T>
  40. struct is_string : mpl::false_ {};
  41. template <typename T>
  42. struct is_string<T const> : is_string<T> {};
  43. template <>
  44. struct is_string<char const*> : mpl::true_ {};
  45. template <>
  46. struct is_string<wchar_t const*> : mpl::true_ {};
  47. template <>
  48. struct is_string<char*> : mpl::true_ {};
  49. template <>
  50. struct is_string<wchar_t*> : mpl::true_ {};
  51. template <std::size_t N>
  52. struct is_string<char[N]> : mpl::true_ {};
  53. template <std::size_t N>
  54. struct is_string<wchar_t[N]> : mpl::true_ {};
  55. template <std::size_t N>
  56. struct is_string<char const[N]> : mpl::true_ {};
  57. template <std::size_t N>
  58. struct is_string<wchar_t const[N]> : mpl::true_ {};
  59. template <std::size_t N>
  60. struct is_string<char(&)[N]> : mpl::true_ {};
  61. template <std::size_t N>
  62. struct is_string<wchar_t(&)[N]> : mpl::true_ {};
  63. template <std::size_t N>
  64. struct is_string<char const(&)[N]> : mpl::true_ {};
  65. template <std::size_t N>
  66. struct is_string<wchar_t const(&)[N]> : mpl::true_ {};
  67. template <typename T, typename Traits, typename Allocator>
  68. struct is_string<std::basic_string<T, Traits, Allocator> > : mpl::true_ {};
  69. ///////////////////////////////////////////////////////////////////////////
  70. // Get the underlying char type of a string
  71. ///////////////////////////////////////////////////////////////////////////
  72. template <typename T>
  73. struct char_type_of;
  74. template <typename T>
  75. struct char_type_of<T const> : char_type_of<T> {};
  76. template <>
  77. struct char_type_of<char> : mpl::identity<char> {};
  78. template <>
  79. struct char_type_of<wchar_t> : mpl::identity<wchar_t> {};
  80. template <>
  81. struct char_type_of<char const*> : mpl::identity<char const> {};
  82. template <>
  83. struct char_type_of<wchar_t const*> : mpl::identity<wchar_t const> {};
  84. template <>
  85. struct char_type_of<char*> : mpl::identity<char> {};
  86. template <>
  87. struct char_type_of<wchar_t*> : mpl::identity<wchar_t> {};
  88. template <std::size_t N>
  89. struct char_type_of<char[N]> : mpl::identity<char> {};
  90. template <std::size_t N>
  91. struct char_type_of<wchar_t[N]> : mpl::identity<wchar_t> {};
  92. template <std::size_t N>
  93. struct char_type_of<char const[N]> : mpl::identity<char const> {};
  94. template <std::size_t N>
  95. struct char_type_of<wchar_t const[N]> : mpl::identity<wchar_t const> {};
  96. template <std::size_t N>
  97. struct char_type_of<char(&)[N]> : mpl::identity<char> {};
  98. template <std::size_t N>
  99. struct char_type_of<wchar_t(&)[N]> : mpl::identity<wchar_t> {};
  100. template <std::size_t N>
  101. struct char_type_of<char const(&)[N]> : mpl::identity<char const> {};
  102. template <std::size_t N>
  103. struct char_type_of<wchar_t const(&)[N]> : mpl::identity<wchar_t const> {};
  104. template <typename T, typename Traits, typename Allocator>
  105. struct char_type_of<std::basic_string<T, Traits, Allocator> >
  106. : mpl::identity<T> {};
  107. ///////////////////////////////////////////////////////////////////////////
  108. // Get the C string from a string
  109. ///////////////////////////////////////////////////////////////////////////
  110. template <typename String>
  111. struct extract_c_string;
  112. template <typename String>
  113. struct extract_c_string
  114. {
  115. typedef typename char_type_of<String>::type char_type;
  116. template <typename T>
  117. static T const* call (T* str)
  118. {
  119. return (T const*)str;
  120. }
  121. template <typename T>
  122. static T const* call (T const* str)
  123. {
  124. return str;
  125. }
  126. };
  127. // Forwarder that strips const
  128. template <typename T>
  129. struct extract_c_string<T const>
  130. {
  131. typedef typename extract_c_string<T>::char_type char_type;
  132. static typename extract_c_string<T>::char_type const* call (T const str)
  133. {
  134. return extract_c_string<T>::call(str);
  135. }
  136. };
  137. // Forwarder that strips references
  138. template <typename T>
  139. struct extract_c_string<T&>
  140. {
  141. typedef typename extract_c_string<T>::char_type char_type;
  142. static typename extract_c_string<T>::char_type const* call (T& str)
  143. {
  144. return extract_c_string<T>::call(str);
  145. }
  146. };
  147. // Forwarder that strips const references
  148. template <typename T>
  149. struct extract_c_string<T const&>
  150. {
  151. typedef typename extract_c_string<T>::char_type char_type;
  152. static typename extract_c_string<T>::char_type const* call (T const& str)
  153. {
  154. return extract_c_string<T>::call(str);
  155. }
  156. };
  157. template <typename T, typename Traits, typename Allocator>
  158. struct extract_c_string<std::basic_string<T, Traits, Allocator> >
  159. {
  160. typedef T char_type;
  161. typedef std::basic_string<T, Traits, Allocator> string;
  162. static T const* call (string const& str)
  163. {
  164. return str.c_str();
  165. }
  166. };
  167. template <typename T>
  168. typename extract_c_string<T*>::char_type const*
  169. get_c_string (T* str)
  170. {
  171. return extract_c_string<T*>::call(str);
  172. }
  173. template <typename T>
  174. typename extract_c_string<T const*>::char_type const*
  175. get_c_string (T const* str)
  176. {
  177. return extract_c_string<T const*>::call(str);
  178. }
  179. template <typename String>
  180. typename extract_c_string<String>::char_type const*
  181. get_c_string (String& str)
  182. {
  183. return extract_c_string<String>::call(str);
  184. }
  185. template <typename String>
  186. typename extract_c_string<String>::char_type const*
  187. get_c_string (String const& str)
  188. {
  189. return extract_c_string<String>::call(str);
  190. }
  191. ///////////////////////////////////////////////////////////////////////////
  192. // Get the begin/end iterators from a string
  193. ///////////////////////////////////////////////////////////////////////////
  194. // Implementation for C-style strings.
  195. // gcc 3.x.x has problems resolving ambiguities here
  196. #if defined(__GNUC__) && (__GNUC__ < 4)
  197. template <typename T>
  198. inline typename add_const<T>::type * get_begin(T* str) { return str; }
  199. template <typename T>
  200. inline typename add_const<T>::type* get_end(T* str)
  201. {
  202. T* last = str;
  203. while (*last)
  204. last++;
  205. return last;
  206. }
  207. #else
  208. template <typename T>
  209. inline T const* get_begin(T const* str) { return str; }
  210. template <typename T>
  211. inline T* get_begin(T* str) { return str; }
  212. template <typename T>
  213. inline T const* get_end(T const* str)
  214. {
  215. T const* last = str;
  216. while (*last)
  217. last++;
  218. return last;
  219. }
  220. template <typename T>
  221. inline T* get_end(T* str)
  222. {
  223. T* last = str;
  224. while (*last)
  225. last++;
  226. return last;
  227. }
  228. #endif
  229. // Implementation for containers (includes basic_string).
  230. template <typename T, typename Str>
  231. inline typename Str::const_iterator get_begin(Str const& str)
  232. { return str.begin(); }
  233. template <typename T, typename Str>
  234. inline typename Str::iterator
  235. get_begin(Str& str BOOST_PROTO_DISABLE_IF_IS_CONST(Str))
  236. { return str.begin(); }
  237. template <typename T, typename Str>
  238. inline typename Str::const_iterator get_end(Str const& str)
  239. { return str.end(); }
  240. template <typename T, typename Str>
  241. inline typename Str::iterator
  242. get_end(Str& str BOOST_PROTO_DISABLE_IF_IS_CONST(Str))
  243. { return str.end(); }
  244. // Default implementation for other types: try a C-style string
  245. // conversion.
  246. // These overloads are explicitly disabled for containers,
  247. // as they would be ambiguous with the previous ones.
  248. template <typename T, typename Str>
  249. inline typename disable_if<is_container<Str>
  250. , T const*>::type get_begin(Str const& str)
  251. { return str; }
  252. template <typename T, typename Str>
  253. inline typename disable_if<is_container<Str>
  254. , T const*>::type get_end(Str const& str)
  255. { return get_end(get_begin<T>(str)); }
  256. }
  257. namespace result_of
  258. {
  259. template <typename Char, typename T, typename Enable = void>
  260. struct get_begin
  261. {
  262. typedef typename traits::char_type_of<T>::type char_type;
  263. typedef typename mpl::if_<
  264. is_const<char_type>
  265. , char_type const
  266. , char_type
  267. >::type* type;
  268. };
  269. template <typename Char, typename Str>
  270. struct get_begin<Char, Str
  271. , typename enable_if<traits::is_container<Str> >::type>
  272. {
  273. typedef typename mpl::if_<
  274. is_const<Str>
  275. , typename Str::const_iterator
  276. , typename Str::iterator
  277. >::type type;
  278. };
  279. template <typename Char, typename T>
  280. struct get_end : get_begin<Char, T> {};
  281. }
  282. }}
  283. #endif