/*============================================================================= | |
Copyright (c) 1999-2003 Jeremiah Willcock | |
Copyright (c) 1999-2003 Jaakko Jarvi | |
Copyright (c) 2001-2006 Joel de Guzman | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
==============================================================================*/ | |
#if !defined(FUSION_MANIP_05052005_1200) | |
#define FUSION_MANIP_05052005_1200 | |
#include <boost/config.hpp> | |
#include <string> | |
#include <vector> | |
#include <cctype> | |
// Tuple I/O manipulators | |
#define FUSION_GET_CHAR_TYPE(T) typename T::char_type | |
#define FUSION_GET_TRAITS_TYPE(T) typename T::traits_type | |
#if defined (BOOST_NO_TEMPLATED_STREAMS) | |
#define FUSION_STRING_OF_STREAM(Stream) std::string | |
#else | |
#define FUSION_STRING_OF_STREAM(Stream) \ | |
std::basic_string< \ | |
FUSION_GET_CHAR_TYPE(Stream) \ | |
, FUSION_GET_TRAITS_TYPE(Stream) \ | |
> | |
#endif | |
//$$$ these should be part of the public API$$$ | |
//$$$ rename tuple_open, tuple_close and tuple_delimiter to | |
// open, close and delimeter and add these synonyms to the | |
// TR1 tuple module. | |
namespace boost { namespace fusion | |
{ | |
namespace detail | |
{ | |
template <typename Tag> | |
int get_xalloc_index(Tag* = 0) | |
{ | |
// each Tag will have a unique index | |
static int index = std::ios::xalloc(); | |
return index; | |
} | |
template <typename Stream, typename Tag, typename T> | |
struct stream_data | |
{ | |
struct arena | |
{ | |
~arena() | |
{ | |
for ( | |
typename std::vector<T*>::iterator i = data.begin() | |
; i != data.end() | |
; ++i) | |
{ | |
delete *i; | |
} | |
} | |
std::vector<T*> data; | |
}; | |
static void attach(Stream& stream, T const& data) | |
{ | |
static arena ar; // our arena | |
ar.data.push_back(new T(data)); | |
stream.pword(get_xalloc_index<Tag>()) = ar.data.back(); | |
} | |
static T const* get(Stream& stream) | |
{ | |
return (T const*)stream.pword(get_xalloc_index<Tag>()); | |
} | |
}; | |
template <typename Tag, typename Stream> | |
class string_ios_manip | |
{ | |
public: | |
typedef FUSION_STRING_OF_STREAM(Stream) string_type; | |
typedef stream_data<Stream, Tag, string_type> stream_data_t; | |
string_ios_manip(Stream& str_) | |
: stream(str_) | |
{} | |
void | |
set(string_type const& s) | |
{ | |
stream_data_t::attach(stream, s); | |
} | |
void | |
print(char const* default_) const | |
{ | |
// print a delimiter | |
string_type const* p = stream_data_t::get(stream); | |
if (p) | |
stream << *p; | |
else | |
stream << default_; | |
} | |
void | |
read(char const* default_) const | |
{ | |
// read a delimiter | |
string_type const* p = stream_data_t::get(stream); | |
using namespace std; | |
ws(stream); | |
if (p) | |
{ | |
typedef typename string_type::const_iterator iterator; | |
for (iterator i = p->begin(); i != p->end(); ++i) | |
check_delim(*i); | |
} | |
else | |
{ | |
while (*default_) | |
check_delim(*default_++); | |
} | |
} | |
private: | |
template <typename Char> | |
void | |
check_delim(Char c) const | |
{ | |
if (!isspace(c)) | |
{ | |
if (stream.get() != c) | |
{ | |
stream.unget(); | |
stream.setstate(std::ios::failbit); | |
} | |
} | |
} | |
Stream& stream; | |
private: | |
// silence MSVC warning C4512: assignment operator could not be generated | |
string_ios_manip& operator= (string_ios_manip const&); | |
}; | |
} // detail | |
#if defined (BOOST_NO_TEMPLATED_STREAMS) | |
#define STD_TUPLE_DEFINE_MANIPULATOR(name) \ | |
namespace detail \ | |
{ \ | |
struct name##_tag; \ | |
\ | |
struct name##_type \ | |
{ \ | |
typedef std::string string_type; \ | |
string_type data; \ | |
name##_type(const string_type& d): data(d) {} \ | |
}; \ | |
\ | |
template <typename Stream> \ | |
Stream& operator>>(Stream& s, const name##_type& m) \ | |
{ \ | |
string_ios_manip<name##_tag, Stream>(s).set(m.data); \ | |
return s; \ | |
} \ | |
\ | |
template <typename Stream> \ | |
Stream& operator<<(Stream& s, const name##_type& m) \ | |
{ \ | |
string_ios_manip<name##_tag, Stream>(s).set(m.data); \ | |
return s; \ | |
} \ | |
} | |
#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \ | |
inline detail::name##_type \ | |
name(const std::string& s) \ | |
{ \ | |
return detail::name##_type(s); \ | |
} \ | |
\ | |
inline detail::name##_type \ | |
name(const char* s) \ | |
{ \ | |
return detail::name##_type(std::string(s)); \ | |
} \ | |
\ | |
inline detail::name##_type \ | |
name(char c) \ | |
{ \ | |
return detail::name##_type(std::string(1, c)); \ | |
} | |
#else // defined(BOOST_NO_TEMPLATED_STREAMS) | |
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) | |
#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \ | |
template <typename Char, typename Traits> \ | |
inline detail::name##_type<Char, Traits> \ | |
name(const std::basic_string<Char, Traits>& s) \ | |
{ \ | |
return detail::name##_type<Char, Traits>(s); \ | |
} \ | |
\ | |
inline detail::name##_type<char> \ | |
name(char const* s) \ | |
{ \ | |
return detail::name##_type<char>(std::basic_string<char>(s)); \ | |
} \ | |
\ | |
inline detail::name##_type<wchar_t> \ | |
name(wchar_t const* s) \ | |
{ \ | |
return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s)); \ | |
} \ | |
\ | |
inline detail::name##_type<char> \ | |
name(char c) \ | |
{ \ | |
return detail::name##_type<char>(std::basic_string<char>(1, c)); \ | |
} \ | |
\ | |
inline detail::name##_type<wchar_t> \ | |
name(wchar_t c) \ | |
{ \ | |
return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c)); \ | |
} | |
#else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) | |
#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \ | |
template <typename Char, typename Traits> \ | |
inline detail::name##_type<Char, Traits> \ | |
name(const std::basic_string<Char, Traits>& s) \ | |
{ \ | |
return detail::name##_type<Char, Traits>(s); \ | |
} \ | |
\ | |
template <typename Char> \ | |
inline detail::name##_type<Char> \ | |
name(Char s[]) \ | |
{ \ | |
return detail::name##_type<Char>(std::basic_string<Char>(s)); \ | |
} \ | |
\ | |
template <typename Char> \ | |
inline detail::name##_type<Char> \ | |
name(Char const s[]) \ | |
{ \ | |
return detail::name##_type<Char>(std::basic_string<Char>(s)); \ | |
} \ | |
\ | |
template <typename Char> \ | |
inline detail::name##_type<Char> \ | |
name(Char c) \ | |
{ \ | |
return detail::name##_type<Char>(std::basic_string<Char>(1, c)); \ | |
} | |
#endif | |
#define STD_TUPLE_DEFINE_MANIPULATOR(name) \ | |
namespace detail \ | |
{ \ | |
struct name##_tag; \ | |
\ | |
template <typename Char, typename Traits = std::char_traits<Char> > \ | |
struct name##_type \ | |
{ \ | |
typedef std::basic_string<Char, Traits> string_type; \ | |
string_type data; \ | |
name##_type(const string_type& d): data(d) {} \ | |
}; \ | |
\ | |
template <typename Stream, typename Char, typename Traits> \ | |
Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m) \ | |
{ \ | |
string_ios_manip<name##_tag, Stream>(s).set(m.data); \ | |
return s; \ | |
} \ | |
\ | |
template <typename Stream, typename Char, typename Traits> \ | |
Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m) \ | |
{ \ | |
string_ios_manip<name##_tag, Stream>(s).set(m.data); \ | |
return s; \ | |
} \ | |
} \ | |
#endif // defined(BOOST_NO_TEMPLATED_STREAMS) | |
STD_TUPLE_DEFINE_MANIPULATOR(tuple_open) | |
STD_TUPLE_DEFINE_MANIPULATOR(tuple_close) | |
STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter) | |
STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open) | |
STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close) | |
STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter) | |
#undef STD_TUPLE_DEFINE_MANIPULATOR | |
#undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS | |
#undef FUSION_STRING_OF_STREAM | |
#undef FUSION_GET_CHAR_TYPE | |
#undef FUSION_GET_TRAITS_TYPE | |
}} | |
#endif |