1 //  boost/io/quoted_manip.hpp  ---------------------------------------------------------//
2 
3 //  Copyright Beman Dawes 2010
4 
5 //  Distributed under the Boost Software License, Version 1.0.
6 //  See http://www.boost.org/LICENSE_1_0.txt
7 
8 //  Library home page http://www.boost.org/libs/io
9 
10 //--------------------------------------------------------------------------------------//
11 
12 #ifndef BOOST_IO_QUOTED_MANIP
13 #define BOOST_IO_QUOTED_MANIP
14 
15 #include <iosfwd>
16 #include <ios>
17 #include <string>
18 #include <iterator>
19 #include <boost/io/ios_state.hpp>
20 
21 namespace pdalboost
22 {
23   namespace io
24   {
25     namespace detail { template <class String, class Char> struct quoted_proxy; }
26 
27     //  ------------  public interface  ------------------------------------------------//
28 
29     //  manipulator for const std::basic_string&
30     template <class Char, class Traits, class Alloc>
31       detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char>
32         quoted(const std::basic_string<Char, Traits, Alloc>& s,
33                Char escape='\\', Char delim='\"');
34 
35     //  manipulator for non-const std::basic_string&
36     template <class Char, class Traits, class Alloc>
37       detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> &, Char>
38         quoted(std::basic_string<Char, Traits, Alloc>& s,
39                Char escape='\\', Char delim='\"');
40 
41     //  manipulator for const C-string*
42     template <class Char>
43       detail::quoted_proxy<const Char*, Char>
44         quoted(const Char* s, Char escape='\\', Char delim='\"');
45 
46     //  -----------  implementation details  -------------------------------------------//
47 
48     namespace detail
49     {
50       //  proxy used as an argument pack
51       template <class String, class Char>
52       struct quoted_proxy
53       {
54         String  string;
55         Char    escape;
56         Char    delim;
57 
quoted_proxypdalboost::io::detail::quoted_proxy58         quoted_proxy(String s_, Char escape_, Char delim_)
59           : string(s_), escape(escape_), delim(delim_) {}
60       private:
61         // String may be a const type, so disable the assignment operator
62         quoted_proxy& operator=(const quoted_proxy&);  // = deleted
63       };
64 
65       //  abstract away difference between proxies with const or non-const basic_strings
66       template <class Char, class Traits, class Alloc>
67       std::basic_ostream<Char, Traits>&
basic_string_inserter_imp(std::basic_ostream<Char,Traits> & os,std::basic_string<Char,Traits,Alloc> const & string,Char escape,Char delim)68       basic_string_inserter_imp(std::basic_ostream<Char, Traits>& os,
69         std::basic_string<Char, Traits, Alloc> const & string, Char escape, Char delim)
70       {
71         os << delim;
72         typename std::basic_string<Char, Traits, Alloc>::const_iterator
73           end_it = string.end();
74         for (typename std::basic_string<Char, Traits, Alloc>::const_iterator
75           it = string.begin();
76           it != end_it;
77           ++it )
78         {
79           if (*it == delim || *it == escape)
80             os << escape;
81           os << *it;
82         }
83         os << delim;
84         return os;
85       }
86 
87       //  inserter for const std::basic_string& proxies
88       template <class Char, class Traits, class Alloc>
89       inline
operator <<(std::basic_ostream<Char,Traits> & os,const quoted_proxy<std::basic_string<Char,Traits,Alloc> const &,Char> & proxy)90       std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,
91         const quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char>& proxy)
92       {
93         return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim);
94       }
95 
96       //  inserter for non-const std::basic_string& proxies
97       template <class Char, class Traits, class Alloc>
98       inline
operator <<(std::basic_ostream<Char,Traits> & os,const quoted_proxy<std::basic_string<Char,Traits,Alloc> &,Char> & proxy)99       std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,
100         const quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>& proxy)
101       {
102         return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim);
103       }
104 
105       //  inserter for const C-string* proxies
106       template <class Char, class Traits>
operator <<(std::basic_ostream<Char,Traits> & os,const quoted_proxy<const Char *,Char> & proxy)107       std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os,
108         const quoted_proxy<const Char*, Char>& proxy)
109       {
110         os << proxy.delim;
111         for (const Char* it = proxy.string;
112           *it;
113           ++it )
114         {
115           if (*it == proxy.delim || *it == proxy.escape)
116             os << proxy.escape;
117           os << *it;
118         }
119         os << proxy.delim;
120         return os;
121       }
122 
123       //  extractor for non-const std::basic_string& proxies
124       template <class Char, class Traits, class Alloc>
operator >>(std::basic_istream<Char,Traits> & is,const quoted_proxy<std::basic_string<Char,Traits,Alloc> &,Char> & proxy)125       std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& is,
126         const quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>& proxy)
127       {
128         proxy.string.clear();
129         Char c;
130         is >> c;
131         if (c != proxy.delim)
132         {
133           is.unget();
134           is >> proxy.string;
135           return is;
136         }
137         {
138           pdalboost::io::ios_flags_saver ifs(is);
139           is >> std::noskipws;
140           for (;;)
141           {
142             is >> c;
143             if (!is.good())  // cope with I/O errors or end-of-file
144               break;
145             if (c == proxy.escape)
146             {
147               is >> c;
148               if (!is.good())  // cope with I/O errors or end-of-file
149                 break;
150             }
151             else if (c == proxy.delim)
152               break;
153             proxy.string += c;
154           }
155         }
156         return is;
157       }
158 
159     }  // namespace detail
160 
161     //  manipulator implementation for const std::basic_string&
162     template <class Char, class Traits, class Alloc>
163     inline detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char>
quoted(const std::basic_string<Char,Traits,Alloc> & s,Char escape,Char delim)164     quoted(const std::basic_string<Char, Traits, Alloc>& s, Char escape, Char delim)
165     {
166       return detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char>
167         (s, escape, delim);
168     }
169 
170     //  manipulator implementation for non-const std::basic_string&
171     template <class Char, class Traits, class Alloc>
172     inline detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> &, Char>
quoted(std::basic_string<Char,Traits,Alloc> & s,Char escape,Char delim)173     quoted(std::basic_string<Char, Traits, Alloc>& s, Char escape, Char delim)
174     {
175       return detail::quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>
176         (s, escape, delim);
177     }
178 
179     //  manipulator implementation for const C-string*
180     template <class Char>
181     inline detail::quoted_proxy<const Char*, Char>
quoted(const Char * s,Char escape,Char delim)182     quoted(const Char* s, Char escape, Char delim)
183     {
184       return detail::quoted_proxy<const Char*, Char> (s, escape, delim);
185     }
186 
187   }  // namespace io
188 }  // namespace pdalboost
189 
190 #endif // BOOST_IO_QUOTED_MANIP
191