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
34namespace boost { namespace fusion
35{
36 namespace detail
37 {
38 template <typename Tag>
39 int get_xalloc_index(int xalloc())
40 {
41 // each Tag will have a unique index
42 static int const index = xalloc();
43 return index;
44 }
45
46 template <typename Stream, typename Tag, typename T>
47 struct stream_data
48 {
49 struct arena
50 {
51 ~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
65 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>(stream.xalloc)) = ar.data.back();
70 }
71
72 static T const* get(Stream& stream)
73 {
74 return (T const*)stream.pword(get_xalloc_index<Tag>(stream.xalloc));
75 }
76 };
77
78#ifdef _MSC_VER
79# pragma warning(push)
80# pragma warning(disable: 4512) // assignment operator could not be generated.
81#endif
82 template <typename Tag, typename Stream>
83 class string_ios_manip
84 {
85 public:
86
87 typedef FUSION_STRING_OF_STREAM(Stream) string_type;
88
89 typedef stream_data<Stream, Tag, string_type> stream_data_t;
90
91 string_ios_manip(Stream& str_)
92 : stream(str_)
93 {}
94
95 void
96 set(string_type const& s)
97 {
98 stream_data_t::attach(stream, s);
99 }
100
101 void
102 print(char const* default_) const
103 {
104 // print a delimiter
105 string_type const* p = stream_data_t::get(stream);
106 if (p)
107 stream << *p;
108 else
109 stream << default_;
110 }
111
112 void
113 read(char const* default_) const
114 {
115 // read a delimiter
116 string_type const* p = stream_data_t::get(stream);
117
118 if (p)
119 {
120 typedef typename string_type::const_iterator iterator;
121 for (iterator i = p->begin(); i != p->end(); ++i)
122 check_delim(*i);
123 }
124 else
125 {
126 while (*default_)
127 check_delim(*default_++);
128 }
129 }
130
131 private:
132
133 template <typename Char>
134 void
135 check_delim(Char c) const
136 {
137 using namespace std;
138 if (!isspace(c))
139 {
140 if (stream.get() != c)
141 {
142 stream.unget();
143 stream.setstate(Stream::failbit);
144 }
145 }
146 }
147
148 Stream& stream;
149 };
150#ifdef _MSC_VER
151# pragma warning(pop)
152#endif
153
154 } // detail
155
156
157#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
158
159#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
160 template <typename Char, typename Traits> \
161 inline detail::name##_type<Char, Traits> \
162 name(const std::basic_string<Char, Traits>& s) \
163 { \
164 return detail::name##_type<Char, Traits>(s); \
165 } \
166 \
167 inline detail::name##_type<char> \
168 name(char const* s) \
169 { \
170 return detail::name##_type<char>(std::basic_string<char>(s)); \
171 } \
172 \
173 inline detail::name##_type<wchar_t> \
174 name(wchar_t const* s) \
175 { \
176 return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s)); \
177 } \
178 \
179 inline detail::name##_type<char> \
180 name(char c) \
181 { \
182 return detail::name##_type<char>(std::basic_string<char>(1, c)); \
183 } \
184 \
185 inline detail::name##_type<wchar_t> \
186 name(wchar_t c) \
187 { \
188 return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c)); \
189 }
190
191#else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
192
193#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
194 template <typename Char, typename Traits> \
195 inline detail::name##_type<Char, Traits> \
196 name(const std::basic_string<Char, Traits>& s) \
197 { \
198 return detail::name##_type<Char, Traits>(s); \
199 } \
200 \
201 template <typename Char> \
202 inline detail::name##_type<Char> \
203 name(Char s[]) \
204 { \
205 return detail::name##_type<Char>(std::basic_string<Char>(s)); \
206 } \
207 \
208 template <typename Char> \
209 inline detail::name##_type<Char> \
210 name(Char const s[]) \
211 { \
212 return detail::name##_type<Char>(std::basic_string<Char>(s)); \
213 } \
214 \
215 template <typename Char> \
216 inline detail::name##_type<Char> \
217 name(Char c) \
218 { \
219 return detail::name##_type<Char>(std::basic_string<Char>(1, c)); \
220 }
221
222#endif
223
224#define STD_TUPLE_DEFINE_MANIPULATOR(name) \
225 namespace detail \
226 { \
227 struct name##_tag; \
228 \
229 template <typename Char, typename Traits = std::char_traits<Char> > \
230 struct name##_type \
231 { \
232 typedef std::basic_string<Char, Traits> string_type; \
233 string_type data; \
234 name##_type(const string_type& d): data(d) {} \
235 }; \
236 \
237 template <typename Stream, typename Char, typename Traits> \
238 Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m) \
239 { \
240 string_ios_manip<name##_tag, Stream> manip(s); \
241 manip.set(m.data); \
242 return s; \
243 } \
244 \
245 template <typename Stream, typename Char, typename Traits> \
246 Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m) \
247 { \
248 string_ios_manip<name##_tag, Stream> manip(s); \
249 manip.set(m.data); \
250 return s; \
251 } \
252 } \
253
254
255 STD_TUPLE_DEFINE_MANIPULATOR(tuple_open)
256 STD_TUPLE_DEFINE_MANIPULATOR(tuple_close)
257 STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter)
258
259 STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open)
260 STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close)
261 STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter)
262
263#undef STD_TUPLE_DEFINE_MANIPULATOR
264#undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS
265#undef FUSION_STRING_OF_STREAM
266#undef FUSION_GET_CHAR_TYPE
267#undef FUSION_GET_TRAITS_TYPE
268
269}}
270
271#endif
272