1 /*=============================================================================
2     Copyright (c) 1999-2003 Jeremiah Willcock
3     Copyright (c) 1999-2003 Jaakko Jarvi
4     Copyright (c) 2001-2011 Joel de Guzman
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(FUSION_MANIP_05052005_1200)
10 #define FUSION_MANIP_05052005_1200
11 
12 #include <boost/fusion/support/config.hpp>
13 #include <boost/config.hpp>
14 #include <string>
15 #include <vector>
16 #include <cctype>
17 
18 // Tuple I/O manipulators
19 
20 #define FUSION_GET_CHAR_TYPE(T) typename T::char_type
21 #define FUSION_GET_TRAITS_TYPE(T) typename T::traits_type
22 
23 #define FUSION_STRING_OF_STREAM(Stream)                                         \
24     std::basic_string<                                                          \
25         FUSION_GET_CHAR_TYPE(Stream)                                            \
26       , FUSION_GET_TRAITS_TYPE(Stream)                                          \
27     >
28 
29 //$$$ these should be part of the public API$$$
30 //$$$ rename tuple_open, tuple_close and tuple_delimiter to
31 //    open, close and delimeter and add these synonyms to the
32 //    TR1 tuple module.
33 
34 namespace boost { namespace fusion
35 {
36     namespace detail
37     {
38         template <typename Tag>
get_xalloc_index(Tag * =0)39         int get_xalloc_index(Tag* = 0)
40         {
41             // each Tag will have a unique index
42             static int index = std::ios::xalloc();
43             return index;
44         }
45 
46         template <typename Stream, typename Tag, typename T>
47         struct stream_data
48         {
49             struct arena
50             {
~arenaboost::fusion::detail::stream_data::arena51                 ~arena()
52                 {
53                     for (
54                         typename std::vector<T*>::iterator i = data.begin()
55                       ; i != data.end()
56                       ; ++i)
57                     {
58                         delete *i;
59                     }
60                 }
61 
62                 std::vector<T*> data;
63             };
64 
attachboost::fusion::detail::stream_data65             static void attach(Stream& stream, T const& data)
66             {
67                 static arena ar; // our arena
68                 ar.data.push_back(new T(data));
69                 stream.pword(get_xalloc_index<Tag>()) = ar.data.back();
70             }
71 
getboost::fusion::detail::stream_data72             static T const* get(Stream& stream)
73             {
74                 return (T const*)stream.pword(get_xalloc_index<Tag>());
75             }
76         };
77 
78         template <typename Tag, typename Stream>
79         class string_ios_manip
80         {
81         public:
82 
83             typedef FUSION_STRING_OF_STREAM(Stream) string_type;
84 
85             typedef stream_data<Stream, Tag, string_type> stream_data_t;
86 
string_ios_manip(Stream & str_)87             string_ios_manip(Stream& str_)
88                 : stream(str_)
89             {}
90 
91             void
set(string_type const & s)92             set(string_type const& s)
93             {
94                 stream_data_t::attach(stream, s);
95             }
96 
97             void
print(char const * default_) const98             print(char const* default_) const
99             {
100                 // print a delimiter
101                 string_type const* p = stream_data_t::get(stream);
102                 if (p)
103                     stream << *p;
104                 else
105                     stream << default_;
106             }
107 
108             void
read(char const * default_) const109             read(char const* default_) const
110             {
111                 // read a delimiter
112                 string_type const* p = stream_data_t::get(stream);
113                 std::ws(stream);
114 
115                 if (p)
116                 {
117                     typedef typename string_type::const_iterator iterator;
118                     for (iterator i = p->begin(); i != p->end(); ++i)
119                         check_delim(*i);
120                 }
121                 else
122                 {
123                     while (*default_)
124                         check_delim(*default_++);
125                 }
126             }
127 
128         private:
129 
130             template <typename Char>
131             void
check_delim(Char c) const132             check_delim(Char c) const
133             {
134                 using namespace std;
135                 if (!isspace(c))
136                 {
137                     if (stream.get() != c)
138                     {
139                         stream.unget();
140                         stream.setstate(std::ios::failbit);
141                     }
142                 }
143             }
144 
145             Stream& stream;
146 
147             // silence MSVC warning C4512: assignment operator could not be generated
148             BOOST_DELETED_FUNCTION(string_ios_manip& operator= (string_ios_manip const&))
149         };
150 
151     } // detail
152 
153 
154 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
155 
156 #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name)                            \
157     template <typename Char, typename Traits>                                   \
158     inline detail::name##_type<Char, Traits>                                    \
159     name(const std::basic_string<Char, Traits>& s)                              \
160     {                                                                           \
161         return detail::name##_type<Char, Traits>(s);                            \
162     }                                                                           \
163                                                                                 \
164     inline detail::name##_type<char>                                            \
165     name(char const* s)                                                         \
166     {                                                                           \
167         return detail::name##_type<char>(std::basic_string<char>(s));           \
168     }                                                                           \
169                                                                                 \
170     inline detail::name##_type<wchar_t>                                         \
171     name(wchar_t const* s)                                                      \
172     {                                                                           \
173         return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s));     \
174     }                                                                           \
175                                                                                 \
176     inline detail::name##_type<char>                                            \
177     name(char c)                                                                \
178     {                                                                           \
179         return detail::name##_type<char>(std::basic_string<char>(1, c));        \
180     }                                                                           \
181                                                                                 \
182     inline detail::name##_type<wchar_t>                                         \
183     name(wchar_t c)                                                             \
184     {                                                                           \
185         return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c));  \
186     }
187 
188 #else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
189 
190 #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name)                            \
191     template <typename Char, typename Traits>                                   \
192     inline detail::name##_type<Char, Traits>                                    \
193     name(const std::basic_string<Char, Traits>& s)                              \
194     {                                                                           \
195         return detail::name##_type<Char, Traits>(s);                            \
196     }                                                                           \
197                                                                                 \
198     template <typename Char>                                                    \
199     inline detail::name##_type<Char>                                            \
200     name(Char s[])                                                              \
201     {                                                                           \
202         return detail::name##_type<Char>(std::basic_string<Char>(s));           \
203     }                                                                           \
204                                                                                 \
205     template <typename Char>                                                    \
206     inline detail::name##_type<Char>                                            \
207     name(Char const s[])                                                        \
208     {                                                                           \
209         return detail::name##_type<Char>(std::basic_string<Char>(s));           \
210     }                                                                           \
211                                                                                 \
212     template <typename Char>                                                    \
213     inline detail::name##_type<Char>                                            \
214     name(Char c)                                                                \
215     {                                                                           \
216         return detail::name##_type<Char>(std::basic_string<Char>(1, c));        \
217     }
218 
219 #endif
220 
221 #define STD_TUPLE_DEFINE_MANIPULATOR(name)                                      \
222     namespace detail                                                            \
223     {                                                                           \
224         struct name##_tag;                                                      \
225                                                                                 \
226         template <typename Char, typename Traits = std::char_traits<Char> >     \
227         struct name##_type                                                      \
228         {                                                                       \
229             typedef std::basic_string<Char, Traits> string_type;                \
230             string_type data;                                                   \
231             name##_type(const string_type& d): data(d) {}                       \
232         };                                                                      \
233                                                                                 \
234         template <typename Stream, typename Char, typename Traits>              \
235         Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m)        \
236         {                                                                       \
237             string_ios_manip<name##_tag, Stream> manip(s);                      \
238             manip.set(m.data);                                                  \
239             return s;                                                           \
240         }                                                                       \
241                                                                                 \
242         template <typename Stream, typename Char, typename Traits>              \
243         Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m)        \
244         {                                                                       \
245             string_ios_manip<name##_tag, Stream> manip(s);                      \
246             manip.set(m.data);                                                  \
247             return s;                                                           \
248         }                                                                       \
249     }                                                                           \
250 
251 
252     STD_TUPLE_DEFINE_MANIPULATOR(tuple_open)
253     STD_TUPLE_DEFINE_MANIPULATOR(tuple_close)
254     STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter)
255 
256     STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open)
257     STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close)
258     STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter)
259 
260 #undef STD_TUPLE_DEFINE_MANIPULATOR
261 #undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS
262 #undef FUSION_STRING_OF_STREAM
263 #undef FUSION_GET_CHAR_TYPE
264 #undef FUSION_GET_TRAITS_TYPE
265 
266 }}
267 
268 #endif
269