diff --git a/doc/io-docinfo-footer.html b/doc/io-docinfo-footer.html new file mode 100644 index 0000000..1fcafdc --- /dev/null +++ b/doc/io-docinfo-footer.html @@ -0,0 +1,5 @@ + diff --git a/doc/io.adoc b/doc/io.adoc index 6685efe..72b200b 100644 --- a/doc/io.adoc +++ b/doc/io.adoc @@ -7,18 +7,20 @@ Distributed under the Boost Software License, Version 1.0. //// # Boost.IO -Daryle Walker, Beman Dawes +Daryle Walker, Beman Dawes, Glen Joseph Fernandes +:docinfo: private-footer :idprefix: :source-language: cpp :toc: left -The I/O sub-library of Boost helps segregate the large number of Boost headers. -This sub-library should contain various items to use with/for the standard I/O -library. +This library contains various utilities for the standard I/O library. :leveloffset: +1 include::ios_state.adoc[] +include::quoted.adoc[] +include::ostream_joiner.adoc[] +include::ostream_put.adoc[] :leveloffset: -1 diff --git a/doc/ios_state.adoc b/doc/ios_state.adoc index dec2d41..1cff15a 100644 --- a/doc/ios_state.adoc +++ b/doc/ios_state.adoc @@ -6,7 +6,7 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) //// -# ios_state, +# IO State Savers, :toc: :toc-title: :idprefix: diff --git a/doc/ostream_joiner.adoc b/doc/ostream_joiner.adoc new file mode 100644 index 0000000..beff8ab --- /dev/null +++ b/doc/ostream_joiner.adoc @@ -0,0 +1,143 @@ +//// +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +//// + +# Delimited Iterators, +:toc: +:toc-title: +:idprefix: + +## Description + +The header `` provides the class template +`boost::io::ostream_joiner` which is an output iterator that writes objects to +a `std::basic_ostream` separated by a delimiter. It is an implementation of +the Library Fundamentals TS `std::ostream_joiner` which supports {cpp}03 and +higher. + +## Example + +The following program writes the contents of a vector to standard output, with +each element separated by a comma. + +``` +#include +#include +#include +#include + +int main() +{ + std::vector v; + v.push_back(2); + v.push_back(4); + v.push_back(6); + v.push_back(8); + std::copy(v.begin(), v.end(), boost::make_ostream_joiner(std::cout, ',')); +} +``` + +## Reference + +### Header Synopsis + +``` +namespace boost { +namespace io { + +template > +class ostream_joiner { +public: + typedef Char char_type; + typedef Traits traits_type; + typedef std::basic_ostream ostream_type; + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + ostream_joiner(ostream_type& output, const Delim& delim); + ostream_joiner(ostream_type& output, Delim&& delim); + + template + ostream_joiner& operator=(const T& value); + + ostream_joiner& operator*() noexcept; + ostream_joiner& operator++() noexcept; + ostream_joiner& operator++(int) noexcept; +}; + +template +ostream_joiner, Char, Traits> +make_ostream_joiner(std::basic_ostream& output, Delim&& delim); + +} // io +} // boost +``` + +### Constructors + +``` +ostream_joiner(ostream_type& output, const Delim& delim); +``` + +[.specification] +EFfects:: Initializes the stored reference to the stream with +`std::addressof(output)` and the stored delimiter with `delim`. + +``` +ostream_joiner(ostream_type& output, Delim&& delim); +``` + +[.specification] +EFfects:: Initializes the stored reference to the stream with +`std::addressof(output)` and the stored delimiter with `std::move(delim)`. + +### Member functions + +``` +template +ostream_joiner& operator=(const T& value); +``` + +[.specification] +Effects:: +* If the is the first call to this member function, write the stored delimiter +to the stored stream reference. +* Writes `value` to the stored stream reference. +Returns:: `*this`. + +``` +ostream_joiner& operator*() noexcept; +``` +``` +ostream_joiner& operator++() noexcept; +``` +``` +ostream_joiner& operator++(int) noexcept; +``` + +[.specification] +Returns:: `*this`. + +### Free functions + +``` +template +ostream_joiner, Char, Traits> +make_ostream_joiner(std::basic_ostream& output, Delim&& delim); +``` + +[.specification] +Returns:: `ostream_joiner, Char, Traits>(output, +std::forward(delim))`. + +## Acknowledgments + +Glen Fernandes implemented `ostream_joiner` and `make_ostream_joiner`. diff --git a/doc/ostream_put.adoc b/doc/ostream_put.adoc new file mode 100644 index 0000000..74b536a --- /dev/null +++ b/doc/ostream_put.adoc @@ -0,0 +1,73 @@ +//// +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +//// + +# Insert Formatted Output, +:toc: +:toc-title: +:idprefix: + +## Description + +The header `` provides the function template +`boost::io::ostream_put` for formatted output that satisfies the requirements +of [ostream.formatted.reqmts]. + +## Example + +The inserter for class template `basic_string_view` could be implemented as +follows: + +``` +template +std::basic_ostream& +operator<<(std::basic_ostream& os, + const basic_string_view& str) +{ + return boost::io::ostream_put(os, str.data(), str.size()); +} +``` + +## Reference + +### Header Synopsis + +``` +namespace boost { +namespace io { + +template +std::basic_ostream& +ostream_put(std::basic_ostream& os, + const charT* data, std::size_t size); + +} // io +} // boost +``` + +### Free functions + +``` +template +std::basic_ostream& +ostream_put(std::basic_ostream& os, + const charT* data, std::size_t size); +``` + +[.specification] +Effects:: Behaves like a formatted inserter (as described in +[ostream.formatted.reqmts]) of `os`. Creates a character sequence `seq` of size +characters starting at `data`, each widened using `os.widen()` +([basic.ios.members]). Determines padding for `seq` as described in +[ostream.formatted.reqmts]. Inserts `seq` into `os`. Calls `width(0)`. +Returns:: `os`. + +## Acknowledgments + +Glen Fernandes updated the implementation of the `basic_string_ref` and +`basic_string_view` stream insertion operators to write directly to the +`basic_streambuf` and refactored that functionality into this common utility. diff --git a/doc/quoted.adoc b/doc/quoted.adoc index d82120c..5bc5639 100644 --- a/doc/quoted.adoc +++ b/doc/quoted.adoc @@ -6,7 +6,7 @@ Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) //// -# quoted, +# Quoted Manipulators, :toc: :toc-title: :idprefix: @@ -137,3 +137,6 @@ developers mailing list. Participants included Beman Dawes, Rob Stewart, Alexander Lamaison, Eric Niebler, Vicente Botet, Andrey Semashev, Phil Richards, and Rob Murray. Eric Niebler's suggestions provided the basis for the name and form of the templates. + +Beman Dawes started the implementation of `quoted()` as a private detail +header. Glen Fernandes updated the implementation and also made it public. diff --git a/include/boost/io/detail/quoted_manip.hpp b/include/boost/io/detail/quoted_manip.hpp index 502f422..55a1d48 100644 --- a/include/boost/io/detail/quoted_manip.hpp +++ b/include/boost/io/detail/quoted_manip.hpp @@ -1,190 +1,18 @@ -// boost/io/quoted_manip.hpp ---------------------------------------------------------// +/* +Copyright 2010 Beman Dawes -// Copyright Beman Dawes 2010 +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_QUOTED_MANIP_HPP +#define BOOST_IO_DETAIL_QUOTED_MANIP_HPP -// Library home page http://www.boost.org/libs/io +/* +The new implemenation is public in +*/ +#include -//--------------------------------------------------------------------------------------// - -#ifndef BOOST_IO_QUOTED_MANIP -#define BOOST_IO_QUOTED_MANIP - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace io - { - namespace detail { template struct quoted_proxy; } - - // ------------ public interface ------------------------------------------------// - - // manipulator for const std::basic_string& - template - detail::quoted_proxy const &, Char> - quoted(const std::basic_string& s, - Char escape='\\', Char delim='\"'); - - // manipulator for non-const std::basic_string& - template - detail::quoted_proxy &, Char> - quoted(std::basic_string& s, - Char escape='\\', Char delim='\"'); - - // manipulator for const C-string* - template - detail::quoted_proxy - quoted(const Char* s, Char escape='\\', Char delim='\"'); - - // ----------- implementation details -------------------------------------------// - - namespace detail - { - // proxy used as an argument pack - template - struct quoted_proxy - { - String string; - Char escape; - Char delim; - - quoted_proxy(String s_, Char escape_, Char delim_) - : string(s_), escape(escape_), delim(delim_) {} - private: - // String may be a const type, so disable the assignment operator - quoted_proxy& operator=(const quoted_proxy&); // = deleted - }; - - // abstract away difference between proxies with const or non-const basic_strings - template - std::basic_ostream& - basic_string_inserter_imp(std::basic_ostream& os, - std::basic_string const & string, Char escape, Char delim) - { - os << delim; - typename std::basic_string::const_iterator - end_it = string.end(); - for (typename std::basic_string::const_iterator - it = string.begin(); - it != end_it; - ++it ) - { - if (*it == delim || *it == escape) - os << escape; - os << *it; - } - os << delim; - return os; - } - - // inserter for const std::basic_string& proxies - template - inline - std::basic_ostream& operator<<(std::basic_ostream& os, - const quoted_proxy const &, Char>& proxy) - { - return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); - } - - // inserter for non-const std::basic_string& proxies - template - inline - std::basic_ostream& operator<<(std::basic_ostream& os, - const quoted_proxy&, Char>& proxy) - { - return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); - } - - // inserter for const C-string* proxies - template - std::basic_ostream& operator<<(std::basic_ostream& os, - const quoted_proxy& proxy) - { - os << proxy.delim; - for (const Char* it = proxy.string; - *it; - ++it ) - { - if (*it == proxy.delim || *it == proxy.escape) - os << proxy.escape; - os << *it; - } - os << proxy.delim; - return os; - } - - // extractor for non-const std::basic_string& proxies - template - std::basic_istream& operator>>(std::basic_istream& is, - const quoted_proxy&, Char>& proxy) - { - proxy.string.clear(); - Char c; - is >> c; - if (c != proxy.delim) - { - is.unget(); - is >> proxy.string; - return is; - } - { - boost::io::ios_flags_saver ifs(is); - is >> std::noskipws; - for (;;) - { - is >> c; - if (!is.good()) // cope with I/O errors or end-of-file - break; - if (c == proxy.escape) - { - is >> c; - if (!is.good()) // cope with I/O errors or end-of-file - break; - } - else if (c == proxy.delim) - break; - proxy.string += c; - } - } - return is; - } - - } // namespace detail - - // manipulator implementation for const std::basic_string& - template - inline detail::quoted_proxy const &, Char> - quoted(const std::basic_string& s, Char escape, Char delim) - { - return detail::quoted_proxy const &, Char> - (s, escape, delim); - } - - // manipulator implementation for non-const std::basic_string& - template - inline detail::quoted_proxy &, Char> - quoted(std::basic_string& s, Char escape, Char delim) - { - return detail::quoted_proxy&, Char> - (s, escape, delim); - } - - // manipulator implementation for const C-string* - template - inline detail::quoted_proxy - quoted(const Char* s, Char escape, Char delim) - { - return detail::quoted_proxy (s, escape, delim); - } - - } // namespace io -} // namespace boost - -#endif // BOOST_IO_QUOTED_MANIP +#endif diff --git a/include/boost/io/ostream_joiner.hpp b/include/boost/io/ostream_joiner.hpp new file mode 100644 index 0000000..a771521 --- /dev/null +++ b/include/boost/io/ostream_joiner.hpp @@ -0,0 +1,118 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_OSTREAM_JOINER_HPP +#define BOOST_IO_OSTREAM_JOINER_HPP + +#include +#include +#include +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#endif +#include +#endif + +namespace boost { +namespace io { +namespace detail { + +#if !defined(BOOST_NO_CXX11_ADDRESSOF) +template +inline T* +osj_address(T& o) +{ + return std::addressof(o); +} +#else +template +inline T* +osj_address(T& obj) +{ + return &obj; +} +#endif + +} /* detail */ + +template > +class ostream_joiner { +public: + typedef Char char_type; + typedef Traits traits_type; + typedef std::basic_ostream ostream_type; + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + ostream_joiner(ostream_type& output, const Delim& delim) + : output_(detail::osj_address(output)) + , delim_(delim) + , first_(true) { } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + ostream_joiner(ostream_type& output, Delim&& delim) + : output_(detail::osj_address(output)) + , delim_(std::move(delim)) + , first_(true) { } +#endif + + template + ostream_joiner& operator=(const T& value) { + if (!first_) { + *output_ << delim_; + } + first_ = false; + *output_ << value; + return *this; + } + + ostream_joiner& operator*() BOOST_NOEXCEPT { + return *this; + } + + ostream_joiner& operator++() BOOST_NOEXCEPT { + return *this; + } + + ostream_joiner& operator++(int) BOOST_NOEXCEPT { + return *this; + } + +private: + ostream_type* output_; + Delim delim_; + bool first_; +}; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +template +inline ostream_joiner::type, Char, Traits> +make_ostream_joiner(std::basic_ostream& output, Delim&& delim) +{ + return ostream_joiner::type, Char, + Traits>(output, std::forward(delim)); +} +#else +template +inline ostream_joiner +make_ostream_joiner(std::basic_ostream& output, + const Delim& delim) +{ + return ostream_joiner(output, delim); +} +#endif + +} /* io */ +} /* boost */ + +#endif diff --git a/include/boost/io/ostream_put.hpp b/include/boost/io/ostream_put.hpp new file mode 100644 index 0000000..5ed5753 --- /dev/null +++ b/include/boost/io/ostream_put.hpp @@ -0,0 +1,97 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_OSTREAM_PUT_HPP +#define BOOST_IO_OSTREAM_PUT_HPP + +#include +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +inline std::size_t +osp_put(std::basic_ostream& os, const charT* data, + std::size_t size) +{ + return static_cast(os.rdbuf()->sputn(data, size)); +} + +template +inline bool +osp_fill(std::basic_ostream& os, std::size_t size) +{ + charT c = os.fill(); + charT fill[] = { c, c, c, c, c, c, c, c }; + enum { + chunk = sizeof fill / sizeof(charT) + }; + for (; size > chunk; size -= chunk) { + if (boost::io::detail::osp_put(os, fill, chunk) != chunk) { + return false; + } + } + return boost::io::detail::osp_put(os, fill, size) == size; +} + +template +class osp_guard { +public: + explicit osp_guard(std::basic_ostream& os) BOOST_NOEXCEPT + : os_(&os) { } + ~osp_guard() BOOST_NOEXCEPT_IF(false) { + if (os_) { + os_->setstate(std::basic_ostream::badbit); + } + } + void release() BOOST_NOEXCEPT { + os_ = 0; + } +private: + osp_guard(const osp_guard&); + osp_guard& operator=(const osp_guard&); + std::basic_ostream* os_; +}; + +} /* detail */ + +template +inline std::basic_ostream& +ostream_put(std::basic_ostream& os, const charT* data, + std::size_t size) +{ + typedef std::basic_ostream stream; + detail::osp_guard guard(os); + typename stream::sentry entry(os); + if (entry) { + std::size_t width = static_cast(os.width()); + if (width <= size) { + if (detail::osp_put(os, data, size) != size) { + return os; + } + } else if ((os.flags() & stream::adjustfield) == stream::left) { + if (detail::osp_put(os, data, size) != size || + !detail::osp_fill(os, width - size)) { + return os; + } + } else if (!detail::osp_fill(os, width - size) || + detail::osp_put(os, data, size) != size) { + return os; + } + os.width(0); + } + guard.release(); + return os; +} + +} /* io */ +} /* boost */ + +#endif diff --git a/include/boost/io/quoted.hpp b/include/boost/io/quoted.hpp new file mode 100644 index 0000000..44570e2 --- /dev/null +++ b/include/boost/io/quoted.hpp @@ -0,0 +1,152 @@ +/* +Copyright 2010 Beman Dawes + +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_QUOTED_HPP +#define BOOST_IO_QUOTED_HPP + +#include +#include +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +class quoted_proxy { +public: + quoted_proxy(String string_, Char escape_, Char delim_) + : string(string_) + , escape(escape_) + , delim(delim_) { } + + String string; + Char escape; + Char delim; + +private: + quoted_proxy& operator=(const quoted_proxy&); +}; + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& os, + const quoted_proxy& proxy) +{ + os << proxy.delim; + for (const Char* it = proxy.string; *it; ++it) { + if (*it == proxy.delim || *it == proxy.escape) { + os << proxy.escape; + } + os << *it; + } + os << proxy.delim; + return os; +} + +template +inline std::basic_ostream& +quoted_output(std::basic_ostream& os, + const std::basic_string& string, Char escape, + Char delim) +{ + os << delim; + typename std::basic_string::const_iterator end = string.end(); + for (typename std::basic_string::const_iterator it = string.begin(); it != end; ++it) { + if (*it == delim || *it == escape) { + os << escape; + } + os << *it; + } + os << delim; + return os; +} + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& os, + const quoted_proxy&, + Char>& proxy) +{ + return boost::io::detail::quoted_output(os, proxy.string, proxy.escape, + proxy.delim); +} + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& os, + const quoted_proxy&, Char>& proxy) +{ + return boost::io::detail::quoted_output(os, proxy.string, proxy.escape, + proxy.delim); +} + +template +inline std::basic_istream& +operator>>(std::basic_istream& is, + const quoted_proxy&, Char>& proxy) +{ + proxy.string.clear(); + Char ch; + if (!(is >> ch).good()) { + return is; + } + if (ch != proxy.delim) { + is.unget(); + is >> proxy.string; + return is; + } + { + boost::io::ios_flags_saver ifs(is); + std::noskipws(is); + while ((is >> ch).good() && ch != proxy.delim) { + if (ch == proxy.escape && !(is >> ch).good()) { + break; + } + proxy.string.push_back(ch); + } + } + return is; +} + +} /* detail */ + +template +inline detail::quoted_proxy&, + Char> +quoted(const std::basic_string& s, Char escape='\\', + Char delim='\"') +{ + return detail::quoted_proxy&, + Char>(s, escape, delim); +} + +template +inline detail::quoted_proxy&, Char> +quoted(std::basic_string& s, Char escape='\\', + Char delim='\"') +{ + return detail::quoted_proxy&, + Char>(s, escape, delim); +} + +template +inline detail::quoted_proxy +quoted(const Char* s, Char escape='\\', Char delim='\"') +{ + return detail::quoted_proxy(s, escape, delim); +} + +} /* io */ +} /* boost */ + +#endif diff --git a/meta/libraries.json b/meta/libraries.json index 3259e18..280c708 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -1,15 +1,17 @@ { "key": "io", - "name": "IO State Savers", + "name": "IO", "authors": [ "Daryle Walker", - "Beman Dawes" + "Beman Dawes", + "Glen Fernandes" ], - "description": "Utilities for using the standard I/O library.", + "description": "Utilities for the standard I/O library.", + "documentation": "doc/html/io.html", "category": [ "IO" ], "maintainers": [ - "Daryle Walker " + "Glen Fernandes " ] } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8d12343..4a26c6d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -10,4 +10,7 @@ import testing ; run ios_state_unit_test.cpp ; run ios_state_test.cpp ; -run quoted_manip_test.cpp ; +run quoted_test.cpp ; +run ostream_joiner_test.cpp ; +run make_ostream_joiner_test.cpp ; +run ostream_put_test.cpp ; diff --git a/test/make_ostream_joiner_test.cpp b/test/make_ostream_joiner_test.cpp new file mode 100644 index 0000000..d262f69 --- /dev/null +++ b/test/make_ostream_joiner_test.cpp @@ -0,0 +1,21 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +int main() +{ + std::ostringstream o; + boost::io::ostream_joiner j = boost::io::make_ostream_joiner(o, ','); + *j++ = 1; + *j++ = '2'; + *j++ = "3"; + BOOST_TEST_EQ(o.str(), "1,2,3"); + return boost::report_errors(); +} diff --git a/test/ostream_joiner_test.cpp b/test/ostream_joiner_test.cpp new file mode 100644 index 0000000..aa1ea44 --- /dev/null +++ b/test/ostream_joiner_test.cpp @@ -0,0 +1,116 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +void test_char_type() +{ + BOOST_TEST_TRAIT_SAME(char, + boost::io::ostream_joiner::char_type); +} + +void test_traits_type() +{ + BOOST_TEST_TRAIT_SAME(std::char_traits, + boost::io::ostream_joiner::traits_type); +} + +void test_ostream_type() +{ + BOOST_TEST_TRAIT_SAME(std::ostream, + boost::io::ostream_joiner::ostream_type); +} + +void test_iterator_category() +{ + BOOST_TEST_TRAIT_SAME(std::output_iterator_tag, + boost::io::ostream_joiner::iterator_category); +} + +void test_value_type() +{ + BOOST_TEST_TRAIT_SAME(void, + boost::io::ostream_joiner::value_type); +} + +void test_difference_type() +{ + BOOST_TEST_TRAIT_SAME(void, + boost::io::ostream_joiner::difference_type); +} + +void test_pointer() +{ + BOOST_TEST_TRAIT_SAME(void, + boost::io::ostream_joiner::pointer); +} + +void test_reference() +{ + BOOST_TEST_TRAIT_SAME(void, + boost::io::ostream_joiner::reference); +} + +void test_construct() +{ + std::ostringstream o; + boost::io::ostream_joiner j(o, ","); + BOOST_TEST(o.str().empty()); +} + +void test_assign() +{ + std::ostringstream o; + boost::io::ostream_joiner j(o, ","); + j = 1; + BOOST_TEST_EQ(o.str(), "1"); + j = '2'; + BOOST_TEST_EQ(o.str(), "1,2"); + j = "3"; + BOOST_TEST_EQ(o.str(), "1,2,3"); +} + +void test_increment() +{ + std::ostringstream o; + boost::io::ostream_joiner j(o, ","); + BOOST_TEST_EQ(&++j, &j); +} + +void test_post_increment() +{ + std::ostringstream o; + boost::io::ostream_joiner j(o, ","); + BOOST_TEST_EQ(&j++, &j); +} + +void test_value() +{ + std::ostringstream o; + boost::io::ostream_joiner j(o, ","); + BOOST_TEST_EQ(&*j, &j); +} + +int main() +{ + test_char_type(); + test_traits_type(); + test_ostream_type(); + test_iterator_category(); + test_value_type(); + test_difference_type(); + test_pointer(); + test_reference(); + test_construct(); + test_assign(); + test_increment(); + test_post_increment(); + test_value(); + return boost::report_errors(); +} diff --git a/test/ostream_put_test.cpp b/test/ostream_put_test.cpp new file mode 100644 index 0000000..3ce978d --- /dev/null +++ b/test/ostream_put_test.cpp @@ -0,0 +1,136 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include + +int main() +{ + { + std::ostringstream os; + os.width(1); + os.fill('.'); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + boost::io::ostream_put(os, "xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == "xy"); + } + { + std::wostringstream os; + os.width(1); + os.fill('.'); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + boost::io::ostream_put(os, L"xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == L"xy"); + } + { + std::ostringstream os; + os.width(1); + os.fill('.'); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + boost::io::ostream_put(os, "xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == "xy"); + } + { + std::wostringstream os; + os.width(1); + os.fill('.'); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + boost::io::ostream_put(os, L"xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == L"xy"); + } + { + std::ostringstream os; + os.width(4); + os.fill('.'); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + boost::io::ostream_put(os, "xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == "xy.."); + } + { + std::wostringstream os; + os.width(4); + os.fill(L'.'); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + boost::io::ostream_put(os, L"xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == L"xy.."); + } + { + std::ostringstream os; + os.width(4); + os.fill('.'); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + boost::io::ostream_put(os, "xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == "..xy"); + } + { + std::wostringstream os; + os.width(4); + os.fill(L'.'); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + boost::io::ostream_put(os, L"xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == L"..xy"); + } + { + std::ostringstream os; + os.width(12); + os.fill('.'); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + boost::io::ostream_put(os, "xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == "xy.........."); + } + { + std::wostringstream os; + os.width(12); + os.fill(L'.'); + os.setf(std::ios_base::left, std::ios_base::adjustfield); + boost::io::ostream_put(os, L"xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == L"xy.........."); + } + { + std::ostringstream os; + os.width(12); + os.fill('.'); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + boost::io::ostream_put(os, "xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == "..........xy"); + } + { + std::wostringstream os; + os.width(12); + os.fill(L'.'); + os.setf(std::ios_base::right, std::ios_base::adjustfield); + boost::io::ostream_put(os, L"xy", 2); + BOOST_TEST(os.good()); + BOOST_TEST(os.width() == 0); + BOOST_TEST(os.str() == L"..........xy"); + } + return boost::report_errors(); +} diff --git a/test/quoted_manip_test.cpp b/test/quoted_manip_test.cpp deleted file mode 100644 index 80e6f78..0000000 --- a/test/quoted_manip_test.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// libs/io/test/quote_manip_test.cpp ----------------------------------------------- // - -// Copyright Beman Dawes 2010 - -// Distributed under the Boost Software License, Version 1.0. -// See http://www.boost.org/LICENSE_1_0.txt - -// Library home page: http://www.boost.org/libs/io - -// ---------------------------------------------------------------------------------- // - -#include -#include -#include -#include - -using boost::io::quoted; -using std::string; -using std::wstring; - -int main() -{ - - std::wstringstream wss; - - string r; // test results - - const string s0("foo"); - { - std::stringstream ss; - ss << quoted(s0); - ss >> r; - BOOST_TEST(r == "\"foo\""); - } - { - std::stringstream ss; - ss << quoted(s0); - ss >> quoted(r); - BOOST_TEST(r == "foo"); - } - - const string s0s("foo bar"); - { - std::stringstream ss; - ss << quoted(s0s); - ss >> r; - BOOST_TEST(r == "\"foo"); - } - { - std::stringstream ss; - ss << quoted(s0s); - ss >> quoted(r); - BOOST_TEST(r == "foo bar"); - } - - const string s1("foo\\bar, \" *"); - { - std::stringstream ss; - ss << quoted(s1); - ss >> r; - BOOST_TEST(r == "\"foo\\\\bar,"); - } - { - std::stringstream ss; - ss << quoted("foo\\bar, \" *"); - ss >> r; - BOOST_TEST(r == "\"foo\\\\bar,"); - } - { - std::stringstream ss; - ss << quoted(s1); - ss >> quoted(r); - BOOST_TEST(r == s1); - } - { - std::stringstream ss; - ss << quoted(s1.c_str()); - ss >> quoted(r); - BOOST_TEST(r == s1); - } - - string s2("'Jack & Jill'"); - { - std::stringstream ss; - ss << quoted(s2, '&', '\''); - ss >> quoted(r, '&', '\''); - BOOST_TEST(r == s2); - } - - wstring ws1(L"foo$bar, \" *"); - wstring wr; // test results - { - std::wstringstream wss; - wss << quoted(ws1, L'$'); - wss >> quoted(wr, L'$'); - BOOST_TEST(wr == ws1); - } - - const string s3("const string"); - { - std::stringstream ss; - ss << quoted(s3); - ss >> quoted(r); - BOOST_TEST(r == s3); - } - { - // missing end delimiter test - std::stringstream ss; - ss << "\"abc"; // load ss with faulty quoting - ss >> quoted(r); // this loops if istream error/eof not detected - BOOST_TEST(r == "abc"); - } - { - // no initial delmiter test - std::stringstream ss; - ss << "abc"; - ss >> quoted(r); - BOOST_TEST(r == "abc"); - } - { - // no initial delmiter, space in ss - std::stringstream ss; - ss << "abc def"; - ss >> quoted(r); - BOOST_TEST(r == "abc"); - } - - // these should fail to compile because the arguments are const: - // ss >> quoted(s1); - // ss >> quoted("foo"); - - return boost::report_errors(); -} diff --git a/test/quoted_test.cpp b/test/quoted_test.cpp new file mode 100644 index 0000000..2ca0a25 --- /dev/null +++ b/test/quoted_test.cpp @@ -0,0 +1,110 @@ +/* +Copyright 2010 Beman Dawes + +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include + +int main() +{ + const std::string s0("foo"); + std::string r; + { + std::stringstream ss; + ss << boost::io::quoted(s0); + ss >> r; + BOOST_TEST(r == "\"foo\""); + } + { + std::stringstream ss; + ss << boost::io::quoted(s0); + ss >> boost::io::quoted(r); + BOOST_TEST(r == "foo"); + } + const std::string s0s("foo bar"); + { + std::stringstream ss; + ss << boost::io::quoted(s0s); + ss >> r; + BOOST_TEST(r == "\"foo"); + } + { + std::stringstream ss; + ss << boost::io::quoted(s0s); + ss >> boost::io::quoted(r); + BOOST_TEST(r == "foo bar"); + } + const std::string s1("foo\\bar, \" *"); + { + std::stringstream ss; + ss << boost::io::quoted(s1); + ss >> r; + BOOST_TEST(r == "\"foo\\\\bar,"); + } + { + std::stringstream ss; + ss << boost::io::quoted("foo\\bar, \" *"); + ss >> r; + BOOST_TEST(r == "\"foo\\\\bar,"); + } + { + std::stringstream ss; + ss << boost::io::quoted(s1); + ss >> boost::io::quoted(r); + BOOST_TEST(r == s1); + } + { + std::stringstream ss; + ss << boost::io::quoted(s1.c_str()); + ss >> boost::io::quoted(r); + BOOST_TEST(r == s1); + } + std::string s2("'Jack & Jill'"); + { + std::stringstream ss; + ss << boost::io::quoted(s2, '&', '\''); + ss >> boost::io::quoted(r, '&', '\''); + BOOST_TEST(r == s2); + } + const std::wstring ws1(L"foo$bar, \" *"); + std::wstring wr; + { + std::wstringstream wss; + wss << boost::io::quoted(ws1, L'$'); + wss >> boost::io::quoted(wr, L'$'); + BOOST_TEST(wr == ws1); + } + const std::string s3("const string"); + { + std::stringstream ss; + ss << boost::io::quoted(s3); + ss >> boost::io::quoted(r); + BOOST_TEST(r == s3); + } + { + std::stringstream ss; + ss << "\"abc"; + ss >> boost::io::quoted(r); + BOOST_TEST(r == "abc"); + } + { + std::stringstream ss; + ss << "abc"; + ss >> boost::io::quoted(r); + BOOST_TEST(r == "abc"); + } + { + std::stringstream ss; + ss << "abc def"; + ss >> boost::io::quoted(r); + BOOST_TEST(r == "abc"); + } + return boost::report_errors(); +}