source: NonGTP/Boost/boost/spirit/fusion/sequence/detail/manip.hpp @ 857

Revision 857, 16.3 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*=============================================================================
2    Copyright (c) 1999-2003 Jeremiah Willcock
3    Copyright (c) 1999-2003 Jaakko Järvi
4    Copyright (c) 2001-2003 Joel de Guzman
5    Copyright (c) 2004 Peder Holt
6
7    Use, modification and distribution is subject to the Boost Software
8    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9    http://www.boost.org/LICENSE_1_0.txt)
10==============================================================================*/
11#ifndef FUSION_SEQUENCE_DETAIL_MANIP_HPP
12#define FUSION_SEQUENCE_DETAIL_MANIP_HPP
13
14#include <boost/config.hpp>
15#include <iostream>
16#include <string>
17#include <vector>
18#include <cctype>
19
20// Tuple I/O manipulators
21
22#include <boost/spirit/fusion/detail/config.hpp>
23
24#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
25FUSION_MSVC_ETI_WRAPPER(char_type)
26FUSION_MSVC_ETI_WRAPPER(traits_type)
27# define FUSION_GET_CHAR_TYPE(T) get_char_type<T>::type
28# define FUSION_GET_TRAITS_TYPE(T) get_traits_type<T>::type
29#else
30# define FUSION_GET_CHAR_TYPE(T) typename T::char_type
31# define FUSION_GET_TRAITS_TYPE(T) typename T::traits_type
32#endif
33
34#if defined (BOOST_NO_TEMPLATED_STREAMS)
35#define FUSION_STRING_OF_STREAM(Stream) std::string
36#else
37#define FUSION_STRING_OF_STREAM(Stream)                                         \
38    std::basic_string<                                                          \
39        FUSION_GET_CHAR_TYPE(Stream)                                            \
40      , FUSION_GET_TRAITS_TYPE(Stream)                                          \
41    >
42#endif
43
44namespace boost { namespace fusion
45{
46    namespace detail
47    {
48        template <typename Tag>
49        int get_xalloc_index(Tag* = 0)
50        {
51            // each Tag will have a unique index
52            static int index = std::ios::xalloc();
53            return index;
54        }
55
56        template <typename Stream, typename Tag, typename T>
57        struct stream_data
58        {
59            struct arena
60            {
61                ~arena()
62                {
63                    for (
64                        typename std::vector<T*>::iterator i = data.begin()
65                      ; i != data.end()
66                      ; ++i)
67                    {
68                        delete *i;
69                    }
70                }
71
72                std::vector<T*> data;
73            };
74
75            static void attach(Stream& stream, T const& data);
76            static T const* get(Stream& stream);
77        };
78
79        template <typename Stream, typename Tag, typename T>
80        void stream_data<Stream,Tag,T>::attach(Stream& stream, T const& data)
81        {
82            static arena ar; // our arena
83            ar.data.push_back(new T(data));
84            stream.pword(get_xalloc_index<Tag>()) = ar.data.back();
85        }
86
87        template <typename Stream, typename Tag, typename T>
88        T const* stream_data<Stream,Tag,T>::get(Stream& stream)
89        {
90            return (T const*)stream.pword(get_xalloc_index<Tag>());
91        }
92
93        template <class Tag, class Stream>
94        class string_ios_manip
95        {
96        public:
97
98            typedef FUSION_STRING_OF_STREAM(Stream) string_type;
99
100            typedef stream_data<Stream, Tag, string_type> stream_data_t;
101
102            string_ios_manip(Stream& str_);
103            void set(string_type const& s);
104            void print(char const* default_) const;
105            void read(char const* default_) const;
106        private:
107
108            template <typename Char>
109            void
110            check_delim(Char c) const
111            {
112                if (!isspace(c))
113                {
114                    if (stream.get() != c)
115                    {
116                        stream.unget();
117                        stream.setstate(std::ios::failbit);
118                    }
119                }
120            }
121
122            Stream& stream;
123        };
124
125        template <class Tag, class Stream>
126        string_ios_manip<Tag,Stream>::string_ios_manip(Stream& str_)
127            : stream(str_)
128        {}
129
130        template <class Tag, class Stream>
131        void
132        string_ios_manip<Tag,Stream>::set(string_type const& s)
133        {
134            stream_data_t::attach(stream, s);
135        }
136
137        template <class Tag, class Stream>
138        void
139        string_ios_manip<Tag,Stream>::print(char const* default_) const
140        {
141            // print a delimiter
142            string_type const* p = stream_data_t::get(stream);
143            if (p)
144                stream << *p;
145            else
146                stream << default_;
147        }
148
149        template <class Tag, class Stream>
150        void
151        string_ios_manip<Tag,Stream>::read(char const* default_) const
152        {
153            // read a delimiter
154            string_type const* p = stream_data_t::get(stream);
155            using namespace std;
156            ws(stream);
157
158            if (p)
159            {
160                typedef typename string_type::const_iterator iterator;
161                for (iterator i = p->begin(); i != p->end(); ++i)
162                    check_delim(*i);
163            }
164            else
165            {
166                while (*default_)
167                    check_delim(*default_++);
168            }
169        }
170
171    } // detail
172
173#if defined (BOOST_NO_TEMPLATED_STREAMS)
174
175#define STD_TUPLE_DEFINE_MANIPULATOR(name)                                      \
176    namespace detail                                                            \
177    {                                                                           \
178        struct name##_tag;                                                      \
179                                                                                \
180        struct name##_type                                                      \
181        {                                                                       \
182            typedef std::string string_type;                                    \
183            string_type data;                                                   \
184            name##_type(const string_type& d): data(d) {}                       \
185        };                                                                      \
186                                                                                \
187        template <class Stream>                                                 \
188        Stream& operator>>(Stream& s, const name##_type& m)                     \
189        {                                                                       \
190            string_ios_manip<name##_tag, Stream>(s).set(m.data);                \
191            return s;                                                           \
192        }                                                                       \
193                                                                                \
194        template <class Stream>                                                 \
195        Stream& operator<<(Stream& s, const name##_type& m)                     \
196        {                                                                       \
197            string_ios_manip<name##_tag, Stream>(s).set(m.data);                \
198            return s;                                                           \
199        }                                                                       \
200    }
201
202#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name)                            \
203    inline detail::name##_type                                                  \
204    name(const std::string& s)                                                  \
205    {                                                                           \
206        return detail::name##_type(s);                                          \
207    }                                                                           \
208                                                                                \
209    inline detail::name##_type                                                  \
210    name(const char* s)                                                         \
211    {                                                                           \
212        return detail::name##_type(std::string(s));                             \
213    }                                                                           \
214                                                                                \
215    inline detail::name##_type                                                  \
216    name(char c)                                                                \
217    {                                                                           \
218        return detail::name##_type(std::string(1, c));                          \
219    }
220
221#else // defined(BOOST_NO_TEMPLATED_STREAMS)
222
223#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
224
225#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name)                            \
226    template <class Char, class Traits>                                         \
227    inline detail::name##_type<Char, Traits>                                    \
228    name(const std::basic_string<Char, Traits>& s)                              \
229    {                                                                           \
230        return detail::name##_type<Char, Traits>(s);                            \
231    }                                                                           \
232                                                                                \
233    inline detail::name##_type<char>                                            \
234    name(char const* s)                                                         \
235    {                                                                           \
236        return detail::name##_type<char>(std::basic_string<char>(s));           \
237    }                                                                           \
238                                                                                \
239    inline detail::name##_type<wchar_t>                                         \
240    name(wchar_t const* s)                                                      \
241    {                                                                           \
242        return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s));     \
243    }                                                                           \
244                                                                                \
245    inline detail::name##_type<char>                                            \
246    name(char c)                                                                \
247    {                                                                           \
248        return detail::name##_type<char>(std::basic_string<char>(1, c));        \
249    }                                                                           \
250                                                                                \
251    inline detail::name##_type<wchar_t>                                         \
252    name(wchar_t c)                                                             \
253    {                                                                           \
254        return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c));  \
255    }
256
257#else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
258
259#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name)                            \
260    template <class Char, class Traits>                                         \
261    inline detail::name##_type<Char, Traits>                                    \
262    name(const std::basic_string<Char, Traits>& s)                              \
263    {                                                                           \
264        return detail::name##_type<Char, Traits>(s);                            \
265    }                                                                           \
266                                                                                \
267    template <class Char>                                                       \
268    inline detail::name##_type<Char>                                            \
269    name(Char s[])                                                              \
270    {                                                                           \
271        return detail::name##_type<Char>(std::basic_string<Char>(s));           \
272    }                                                                           \
273                                                                                \
274    template <class Char>                                                       \
275    inline detail::name##_type<Char>                                            \
276    name(Char const s[])                                                        \
277    {                                                                           \
278        return detail::name##_type<Char>(std::basic_string<Char>(s));           \
279    }                                                                           \
280                                                                                \
281    template <class Char>                                                       \
282    inline detail::name##_type<Char>                                            \
283    name(Char c)                                                                \
284    {                                                                           \
285        return detail::name##_type<Char>(std::basic_string<Char>(1, c));        \
286    }
287
288#endif
289
290#define STD_TUPLE_DEFINE_MANIPULATOR(name)                                      \
291    namespace detail                                                            \
292    {                                                                           \
293        struct name##_tag;                                                      \
294                                                                                \
295        template <class Char, class Traits = std::char_traits<Char> >           \
296        struct name##_type                                                      \
297        {                                                                       \
298            typedef std::basic_string<Char, Traits> string_type;                \
299            string_type data;                                                   \
300            name##_type(const string_type& d): data(d) {}                       \
301        };                                                                      \
302                                                                                \
303        template <class Stream, class Char, class Traits>                       \
304        Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m)        \
305        {                                                                       \
306            string_ios_manip<name##_tag, Stream>(s).set(m.data);                \
307            return s;                                                           \
308        }                                                                       \
309                                                                                \
310        template <class Stream, class Char, class Traits>                       \
311        Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m)        \
312        {                                                                       \
313            string_ios_manip<name##_tag, Stream>(s).set(m.data);                \
314            return s;                                                           \
315        }                                                                       \
316    }                                                                           \
317
318#endif // defined(BOOST_NO_TEMPLATED_STREAMS)
319
320    STD_TUPLE_DEFINE_MANIPULATOR(tuple_open)
321    STD_TUPLE_DEFINE_MANIPULATOR(tuple_close)
322    STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter)
323
324    STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open)
325    STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close)
326    STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter)
327
328#undef STD_TUPLE_DEFINE_MANIPULATOR
329#undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS
330#undef FUSION_STRING_OF_STREAM
331#undef FUSION_GET_CHAR_TYPE
332#undef FUSION_GET_TRAITS_TYPE
333
334}}
335
336#endif
Note: See TracBrowser for help on using the repository browser.