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