quoted_manip.hpp 6.3 KB

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