You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
320 lines
15 KiB
320 lines
15 KiB
/*============================================================================= |
|
Copyright (c) 1999-2003 Jeremiah Willcock |
|
Copyright (c) 1999-2003 Jaakko Jarvi |
|
Copyright (c) 2001-2011 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
|
|
|