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