diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/iostreams | |
parent | Initial commit. (diff) | |
download | ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/iostreams')
115 files changed, 19620 insertions, 0 deletions
diff --git a/src/boost/libs/iostreams/Jamfile b/src/boost/libs/iostreams/Jamfile new file mode 100644 index 00000000..afe2fcf1 --- /dev/null +++ b/src/boost/libs/iostreams/Jamfile @@ -0,0 +1,11 @@ +# Boost.Iostreams Library Jamfile +# +# Copyright (c) 2018 James E. King III +# +# Use, modification, and distribution are subject to 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) + +# please order by name to ease maintenance +build-project example ; +build-project test ; diff --git a/src/boost/libs/iostreams/LICENSE b/src/boost/libs/iostreams/LICENSE new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/src/boost/libs/iostreams/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/boost/libs/iostreams/README.md b/src/boost/libs/iostreams/README.md new file mode 100644 index 00000000..5bdc70d4 --- /dev/null +++ b/src/boost/libs/iostreams/README.md @@ -0,0 +1,39 @@ +Iostreams, part of collection of the [Boost C++ Libraries](http://github.com/boostorg), provides: + +* Tools to make it easy to create standard C++ streams and stream buffers for accessing new Sources and Sinks. +* A framework for defining filters and attaching them to standard streams and stream buffers. +* A collection of ready-to-use Filters, Sources and Sinks. +* Utilities to save and restore stream state. + +### License + +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). + +### Properties + +* C++03 +* Requires a Link Library + +### Build Status + +Branch | Travis | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests | +:-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- | +[`master`](https://github.com/boostorg/iostreams/tree/master) | [![Build Status](https://travis-ci.org/boostorg/iostreams.svg?branch=master)](https://travis-ci.org/boostorg/iostreams) | [![Build status](https://ci.appveyor.com/api/projects/status/github/boostorg/iostreams?branch=master&svg=true)](https://ci.appveyor.com/project/eldiener/iostreams/branch/master) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/16463/badge.svg)](https://scan.coverity.com/projects/boostorg-iostreams) | [![codecov](https://codecov.io/gh/boostorg/iostreams/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/iostreams/branch/master)| [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/iostreams.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/iostreams.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/iostreams.html) +[`develop`](https://github.com/boostorg/iostreams/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/iostreams.svg?branch=develop)](https://travis-ci.org/boostorg/iostreams) | [![Build status](https://ci.appveyor.com/api/projects/status/github/boostorg/iostreams?branch=develop&svg=true)](https://ci.appveyor.com/project/eldiener/iostreams/branch/develop) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/16463/badge.svg)](https://scan.coverity.com/projects/boostorg-iostreams) | [![codecov](https://codecov.io/gh/boostorg/iostreams/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/iostreams/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/iostreams.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/doc/html/iostreams.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/iostreams.html) + +### Directories + +| Name | Purpose | +| ----------- | ------------------------------ | +| `doc` | documentation | +| `example` | examples | +| `include` | headers | +| `test` | unit tests | + +### More information + +* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-iostreams) +* [Report bugs](https://github.com/boostorg/iostreams/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). +* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[iostreams]` tag at the beginning of the subject line. + diff --git a/src/boost/libs/iostreams/build/Jamfile.v2 b/src/boost/libs/iostreams/build/Jamfile.v2 new file mode 100644 index 00000000..7ea8a968 --- /dev/null +++ b/src/boost/libs/iostreams/build/Jamfile.v2 @@ -0,0 +1,129 @@ +# Boost.Iostreams Library Build Jamfile + +# (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +# (C) Copyright 2004-2007 Jonathan Turkanis +# 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.) + +# See http://www.boost.org/libs/iostreams for documentation. + +project /boost/iostreams : source-location ../src ; + +# The biggest trick in this Jamfile is to link to zlib and bzip2 when +# needed. To configure that, a number of variables are used, which must +# be set by user with 'path-constant' either in Boost's root Jamfile, or +# in user-config.jam. + +# For each library with either link to existing binary, or build +# a library from the sources. + +import modules ; +import os ; +import path ; +import ac ; +local debug = [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] ; + +local libraries-to-install = boost_iostreams ; + +for local v in NO_COMPRESSION + NO_ZLIB + NO_BZIP2 + NO_LZMA + NO_ZSTD +{ + $(v) = [ modules.peek : $(v) ] ; +} + +if $(NO_COMPRESSION) != 1 && $(NO_ZLIB) != 1 +{ + using zlib : : <build-name>boost_zlib <tag>@tag ; + zlib-requirements = + [ ac.check-library /zlib//zlib : <library>/zlib//zlib + <source>zlib.cpp <source>gzip.cpp ] ; + + if [ os.environ ZLIB_SOURCE ] + { + alias boost_zlib : /zlib//zlib ; + libraries-to-install += boost_zlib ; + } +} +else +{ + if $(debug) + { + ECHO "notice: iostreams: not using zlib compression " ; + } +} + +if $(NO_COMPRESSION) != 1 && $(NO_BZIP2) != 1 +{ + using bzip2 : : <build-name>boost_bzip2 <tag>@tag ; + bzip2-requirements = + [ ac.check-library /bzip2//bzip2 : <library>/bzip2//bzip2 + <source>bzip2.cpp ] ; + + if [ os.environ BZIP2_SOURCE ] + { + alias boost_bzip2 : /bzip2//bzip2 ; + libraries-to-install += boost_bzip2 ; + } +} +else +{ + if $(debug) + { + ECHO "notice: iostreams: not using bzip compression " ; + } +} + +if $(NO_COMPRESSION) != 1 && $(NO_LZMA) != 1 +{ + using lzma ; + + exe has_lzma_cputhreads : ../build/has_lzma_cputhreads.cpp /lzma//lzma ; + explicit has_lzma_cputhreads ; + + lzma-requirements = + [ ac.check-library /lzma//lzma : <library>/lzma//lzma + <source>lzma.cpp ] + [ check-target-builds has_lzma_cputhreads + : : <define>BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED=1 ] ; +} +else +{ + if $(debug) + { + ECHO "notice: iostreams: not using lzma compression " ; + } +} + +if $(NO_COMPRESSION) != 1 && $(NO_ZSTD) != 1 +{ + using zstd ; + zstd-requirements = + [ ac.check-library /zstd//zstd : <library>/zstd//zstd + <source>zstd.cpp ] ; +} +else +{ + if $(debug) + { + ECHO "notice: iostreams: not using zstd compression " ; + } +} + +local sources = file_descriptor.cpp mapped_file.cpp ; + +lib boost_iostreams + : $(sources) + : <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1 + <define>BOOST_IOSTREAMS_USE_DEPRECATED + $(zlib-requirements) + $(bzip2-requirements) + $(lzma-requirements) + $(zstd-requirements) + : + : <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1 + ; + +boost-install $(libraries-to-install) ; diff --git a/src/boost/libs/iostreams/build/has_lzma_cputhreads.cpp b/src/boost/libs/iostreams/build/has_lzma_cputhreads.cpp new file mode 100644 index 00000000..7b5a4ccd --- /dev/null +++ b/src/boost/libs/iostreams/build/has_lzma_cputhreads.cpp @@ -0,0 +1,10 @@ +// Copyright 2019 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +#include <lzma.h> + +int main() +{ + return lzma_cputhreads(); +} diff --git a/src/boost/libs/iostreams/example/Jamfile.v2 b/src/boost/libs/iostreams/example/Jamfile.v2 new file mode 100644 index 00000000..43fd0884 --- /dev/null +++ b/src/boost/libs/iostreams/example/Jamfile.v2 @@ -0,0 +1,25 @@ +# Boost.Iostreams Library example Jamfile +# +# Copyright (c) 2008 James E. King III +# +# Distributed under the Boost Software License, Version 1.0. (See accompany- +# ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +import testing ; + +project + : requirements + <library>/boost/iostreams//boost_iostreams + <define>BOOST_ALL_NO_LIB=1 + # <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + ; + +test-suite "iostreams-examples" + : [ run boost_back_inserter_example.cpp ] + [ run container_sink_example.cpp ] + [ run container_source_example.cpp ] + [ run iterator_range_example.cpp ] + [ run std_back_inserter_example.cpp ] + [ run container_device_example.cpp ] + ; + diff --git a/src/boost/libs/iostreams/example/boost_back_inserter_example.cpp b/src/boost/libs/iostreams/example/boost_back_inserter_example.cpp new file mode 100644 index 00000000..5625c376 --- /dev/null +++ b/src/boost/libs/iostreams/example/boost_back_inserter_example.cpp @@ -0,0 +1,24 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cassert> +#include <string> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filtering_stream.hpp> + +namespace io = boost::iostreams; + +int main() +{ + using namespace std; + + string result; + io::filtering_ostream out(io::back_inserter(result)); + out << "Hello World!"; + out.flush(); + assert(result == "Hello World!"); +} diff --git a/src/boost/libs/iostreams/example/container_device.hpp b/src/boost/libs/iostreams/example/container_device.hpp new file mode 100644 index 00000000..cb9d537f --- /dev/null +++ b/src/boost/libs/iostreams/example/container_device.hpp @@ -0,0 +1,160 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_EXAMPLE_CONTAINTER_DEVICE_HPP_INCLUDED +#define BOOST_IOSTREAMS_EXAMPLE_CONTAINTER_DEVICE_HPP_INCLUDED + +#include <algorithm> // copy, min. +#include <cassert> +#include <boost/config.hpp> // BOOST_NO_STDC_NAMESPACE. +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/detail/ios.hpp> // failure. + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> + +namespace boost { namespace iostreams { namespace example { + +// +// Model of Source which reads from an STL-compatible sequence +// whose iterators are random-access iterators. +// +template<typename Container> +class container_source { +public: + typedef typename Container::value_type char_type; + typedef source_tag category; + container_source(Container& container) + : container_(container), pos_(0) + { } + std::streamsize read(char_type* s, std::streamsize n) + { + using namespace std; + std::streamsize amt = + static_cast<std::streamsize>(container_.size() - pos_); + std::streamsize result = (min)(n, amt); + if (result != 0) { + std::copy( container_.begin() + pos_, + container_.begin() + pos_ + result, + s ); + pos_ += result; + return result; + } else { + return -1; // EOF + } + } + Container& container() { return container_; } +private: + container_source operator=(const container_source&); + typedef typename Container::size_type size_type; + Container& container_; + size_type pos_; +}; + +// +// Model of Sink which appends to an STL-compatible sequence. +// +template<typename Container> +class container_sink { +public: + typedef typename Container::value_type char_type; + typedef sink_tag category; + container_sink(Container& container) : container_(container) { } + std::streamsize write(const char_type* s, std::streamsize n) + { + container_.insert(container_.end(), s, s + n); + return n; + } + Container& container() { return container_; } +private: + container_sink operator=(const container_sink&); + Container& container_; +}; + +// +// Model of SeekableDevice which accessS an TL-compatible sequence +// whose iterators are random-access iterators. +// +template<typename Container> +class container_device { +public: + typedef typename Container::value_type char_type; + typedef seekable_device_tag category; + container_device(Container& container) + : container_(container), pos_(0) + { } + + std::streamsize read(char_type* s, std::streamsize n) + { + using namespace std; + std::streamsize amt = + static_cast<std::streamsize>(container_.size() - pos_); + std::streamsize result = (min)(n, amt); + if (result != 0) { + std::copy( container_.begin() + pos_, + container_.begin() + pos_ + result, + s ); + pos_ += result; + return result; + } else { + return -1; // EOF + } + } + std::streamsize write(const char_type* s, std::streamsize n) + { + using namespace std; + std::streamsize result = 0; + if (pos_ != container_.size()) { + std::streamsize amt = + static_cast<std::streamsize>(container_.size() - pos_); + result = (min)(n, amt); + std::copy(s, s + result, container_.begin() + pos_); + pos_ += result; + } + if (result < n) { + container_.insert(container_.end(), s, s + n); + pos_ = container_.size(); + } + return n; + } + stream_offset seek(stream_offset off, BOOST_IOS::seekdir way) + { + using namespace std; + + // Determine new value of pos_ + stream_offset next; + if (way == BOOST_IOS::beg) { + next = off; + } else if (way == BOOST_IOS::cur) { + next = pos_ + off; + } else if (way == BOOST_IOS::end) { + next = container_.size() + off - 1; + } else { + throw BOOST_IOSTREAMS_FAILURE("bad seek direction"); + } + + // Check for errors + if (next < 0 || next > static_cast<stream_offset>(container_.size())) + throw BOOST_IOSTREAMS_FAILURE("bad seek offset"); + + pos_ = next; + return pos_; + } + + Container& container() { return container_; } +private: + container_device operator=(const container_device&); + typedef typename Container::size_type size_type; + Container& container_; + size_type pos_; +}; + +} } } // End namespaces example, iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +#endif // #ifndef BOOST_IOSTREAMS_EXAMPLE_CONTAINTER_DEVICE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/example/container_device_example.cpp b/src/boost/libs/iostreams/example/container_device_example.cpp new file mode 100644 index 00000000..4487e2fe --- /dev/null +++ b/src/boost/libs/iostreams/example/container_device_example.cpp @@ -0,0 +1,30 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cassert> +#include <string> +#include <boost/iostreams/stream.hpp> +#include <boost/iostreams/detail/ios.hpp> // ios_base::beg. +#include <libs/iostreams/example/container_device.hpp> + +namespace io = boost::iostreams; +namespace ex = boost::iostreams::example; + +int main() +{ + using namespace std; + typedef ex::container_device<string> string_device; + + string one, two; + io::stream<string_device> io(one); + io << "Hello World!"; + io.flush(); + io.seekg(0, BOOST_IOS::beg); + getline(io, two); + assert(one == "Hello World!"); + assert(two == "Hello World!"); +} diff --git a/src/boost/libs/iostreams/example/container_sink_example.cpp b/src/boost/libs/iostreams/example/container_sink_example.cpp new file mode 100644 index 00000000..fdbd8fb6 --- /dev/null +++ b/src/boost/libs/iostreams/example/container_sink_example.cpp @@ -0,0 +1,26 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cassert> +#include <string> +#include <boost/iostreams/stream.hpp> +#include <libs/iostreams/example/container_device.hpp> + +namespace io = boost::iostreams; +namespace ex = boost::iostreams::example; + +int main() +{ + using namespace std; + typedef ex::container_sink<string> string_sink; + + string result; + io::stream<string_sink> out(result); + out << "Hello World!"; + out.flush(); + assert(result == "Hello World!"); +} diff --git a/src/boost/libs/iostreams/example/container_source_example.cpp b/src/boost/libs/iostreams/example/container_source_example.cpp new file mode 100644 index 00000000..e8aff8b8 --- /dev/null +++ b/src/boost/libs/iostreams/example/container_source_example.cpp @@ -0,0 +1,26 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cassert> +#include <string> +#include <boost/iostreams/stream.hpp> +#include <libs/iostreams/example/container_device.hpp> + +namespace io = boost::iostreams; +namespace ex = boost::iostreams::example; + +int main() +{ + using namespace std; + typedef ex::container_source<string> string_source; + + string input = "Hello World!"; + string output; + io::stream<string_source> in(input); + getline(in, output); + assert(input == output); +} diff --git a/src/boost/libs/iostreams/example/dictionary_filter.hpp b/src/boost/libs/iostreams/example/dictionary_filter.hpp new file mode 100644 index 00000000..ac391db5 --- /dev/null +++ b/src/boost/libs/iostreams/example/dictionary_filter.hpp @@ -0,0 +1,221 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED + +#include <algorithm> // swap. +#include <cassert> +#include <cstdio> // EOF. +#include <iostream> // cin, cout. +#include <cctype> +#include <map> +#include <boost/config.hpp> // BOOST_NO_STDC_NAMESPACE. +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/operations.hpp> + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { + using ::isalpha; + using ::isupper; + using ::toupper; + using ::tolower; +} +#endif + +namespace boost { namespace iostreams { namespace example { + +class dictionary { +public: + void add(std::string key, const std::string& value); + void replace(std::string& key); +private: + typedef std::map<std::string, std::string> map_type; + void tolower(std::string& str); + map_type map_; +}; + +class dictionary_stdio_filter : public stdio_filter { +public: + dictionary_stdio_filter(dictionary& d) : dictionary_(d) { } +private: + void do_filter() + { + using namespace std; + while (true) { + int c = std::cin.get(); + if (c == EOF || !std::isalpha((unsigned char) c)) { + dictionary_.replace(current_word_); + cout.write( current_word_.data(), + static_cast<std::streamsize>(current_word_.size()) ); + current_word_.erase(); + if (c == EOF) + break; + cout.put(c); + } else { + current_word_ += c; + } + } + } + dictionary& dictionary_; + std::string current_word_; +}; + +class dictionary_input_filter : public input_filter { +public: + dictionary_input_filter(dictionary& d) + : dictionary_(d), off_(std::string::npos), eof_(false) + { } + + template<typename Source> + int get(Source& src) + { + // Handle unfinished business. + if (off_ != std::string::npos && off_ < current_word_.size()) + return current_word_[off_++]; + if (off_ == current_word_.size()) { + current_word_.erase(); + off_ = std::string::npos; + } + if (eof_) + return EOF; + + // Compute curent word. + while (true) { + int c; + if ((c = iostreams::get(src)) == WOULD_BLOCK) + return WOULD_BLOCK; + + if (c == EOF || !std::isalpha((unsigned char) c)) { + dictionary_.replace(current_word_); + off_ = 0; + if (c == EOF) + eof_ = true; + else + current_word_ += c; + break; + } else { + current_word_ += c; + } + } + + return this->get(src); // Note: current_word_ is not empty. + } + + template<typename Source> + void close(Source&) + { + current_word_.erase(); + off_ = std::string::npos; + eof_ = false; + } +private: + dictionary& dictionary_; + std::string current_word_; + std::string::size_type off_; + bool eof_; +}; + +class dictionary_output_filter : public output_filter { +public: + typedef std::map<std::string, std::string> map_type; + dictionary_output_filter(dictionary& d) + : dictionary_(d), off_(std::string::npos) + { } + + template<typename Sink> + bool put(Sink& dest, int c) + { + if (off_ != std::string::npos && !write_current_word(dest)) + return false; + if (!std::isalpha((unsigned char) c)) { + dictionary_.replace(current_word_); + off_ = 0; + } + + current_word_ += c; + return true; + } + + template<typename Sink> + void close(Sink& dest) + { + // Reset current_word_ and off_, saving old values. + std::string current_word; + std::string::size_type off = 0; + current_word.swap(current_word_); + std::swap(off, off_); + + // Write remaining characters to dest. + if (off == std::string::npos) { + dictionary_.replace(current_word); + off = 0; + } + if (!current_word.empty()) + iostreams::write( + dest, + current_word.data() + off, + static_cast<std::streamsize>(current_word.size() - off) + ); + } +private: + template<typename Sink> + bool write_current_word(Sink& dest) + { + using namespace std; + std::streamsize amt = + static_cast<std::streamsize>(current_word_.size() - off_); + std::streamsize result = + iostreams::write(dest, current_word_.data() + off_, amt); + if (result == amt) { + current_word_.erase(); + off_ = string::npos; + return true; + } else { + off_ += static_cast<string::size_type>(result); + return false; + } + } + + dictionary& dictionary_; + std::string current_word_; + std::string::size_type off_; +}; + +//------------------Implementation of dictionary------------------------------// + +inline void dictionary::add(std::string key, const std::string& value) +{ + tolower(key); + map_[key] = value; +} + +inline void dictionary::replace(std::string& key) +{ + using namespace std; + string copy(key); + tolower(copy); + map_type::iterator it = map_.find(key); + if (it == map_.end()) + return; + string& value = it->second; + if (!value.empty() && !key.empty() && std::isupper((unsigned char) key[0])) + value[0] = std::toupper((unsigned char) value[0]); + key = value; + return; +} + +inline void dictionary::tolower(std::string& str) +{ + for (std::string::size_type z = 0, len = str.size(); z < len; ++z) + str[z] = std::tolower((unsigned char) str[z]); +} + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/example/finite_state_filter.hpp b/src/boost/libs/iostreams/example/finite_state_filter.hpp new file mode 100644 index 00000000..c43d86f3 --- /dev/null +++ b/src/boost/libs/iostreams/example/finite_state_filter.hpp @@ -0,0 +1,365 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Peter Dimov. +// See https://web.archive.org/web/20041222094942/http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED + +#include <cassert> +#include <cstdio> // EOF. +#include <iostream> // cin, cout. +#include <locale> +#include <string> +#include <boost/config.hpp> // JOIN, member template friends. +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/char_traits.hpp> +#include <boost/iostreams/checked_operations.hpp> // put_if. +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/detail/ios.hpp> // openmode. +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/mpl/begin_end.hpp> +#include <boost/mpl/deref.hpp> +#include <boost/preprocessor/control/expr_if.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> + +namespace boost { namespace iostreams { + +//------------------Definition of basic character classes---------------------// + +struct finite_state_machine_base { + + static const int initial_state = 0; + + // All-inclusive character class. + + struct is_any { + template<typename Ch> + static bool test(Ch, const std::locale&) { return true; } + }; + + // Locale-sensitive character classes. + + #define BOOST_IOSTREAMS_CHARACTER_CLASS(class) \ + struct BOOST_JOIN(is_, class) { \ + template<typename Ch> \ + static bool test(Ch event, const std::locale& loc) \ + { return std::BOOST_JOIN(is, class)(event, loc); } \ + }; \ + /**/ + + BOOST_IOSTREAMS_CHARACTER_CLASS(alnum) + BOOST_IOSTREAMS_CHARACTER_CLASS(alpha) + BOOST_IOSTREAMS_CHARACTER_CLASS(cntrl) + BOOST_IOSTREAMS_CHARACTER_CLASS(digit) + BOOST_IOSTREAMS_CHARACTER_CLASS(graph) + BOOST_IOSTREAMS_CHARACTER_CLASS(lower) + BOOST_IOSTREAMS_CHARACTER_CLASS(print) + BOOST_IOSTREAMS_CHARACTER_CLASS(punct) + BOOST_IOSTREAMS_CHARACTER_CLASS(space) + BOOST_IOSTREAMS_CHARACTER_CLASS(upper) + BOOST_IOSTREAMS_CHARACTER_CLASS(xdigit) + + #undef BOOST_IOSTREAMS_CHARACTER_CLASS +}; + +template<typename Ch> +struct finite_state_machine_base_ex : finite_state_machine_base { + template<Ch C> + struct is { + static bool test(Ch event, const std::locale&) + { + return event == C; + } + }; +}; + +//------------------Definition of base class for finite state filters---------// + +namespace detail { + +template<typename FiniteStateMachine> +class finite_state_filter_impl; + +} // End namespace detail. + +template<typename Derived, typename Ch = char> +class finite_state_machine : public finite_state_machine_base_ex<Ch> { +public: + typedef Ch char_type; + typedef typename char_traits<Ch>::int_type int_type; + void imbue(const std::locale& loc) { loc_ = loc; } + const std::locale& getloc() const { return loc_; } +protected: + finite_state_machine() : off_(0) { } + + // Template whose instantiations make up transition table. + + template< int State, + typename CharacterClass, + int NextState, + void (Derived::*Action)(char_type) > + struct row { + typedef CharacterClass character_class; + static const int state = State; + static const int next_state = NextState; + static void execute(Derived& d, char_type event) + { + (d.*Action)(event); + } + }; + + // Stack interface. + + bool empty() const + { + return off_ == buf_.size(); + } + void push(char c) { buf_ += c; } + char_type pop() + { + char_type result = buf_[off_++]; + if (off_ == buf_.size()) + clear(); + return result; + } + char_type& top() { return buf_[off_]; } + void clear() + { + buf_.clear(); + off_ = 0; + } + + // Default event handlers. + + void on_eof() { } + void skip(char_type) { } + +#if BOOST_WORKAROUND(__MWERKS__, <= 0x3206) + template<typename Ch> + void _push_impl(Ch c) { push(c); } +#endif + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template<typename FiniteStateFilter> + friend class detail::finite_state_filter_impl; +#else + public: +#endif + void on_any(char_type) { } +private: + typedef std::basic_string<char_type> string_type; + typedef typename string_type::size_type size_type; + std::locale loc_; + string_type buf_; + size_type off_; +}; + +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x3206) +# define BOOST_IOSTREAMS_FSM(fsm) \ + template<typename Ch> \ + void push(Ch c) \ + { ::boost::iostreams::finite_state_machine<fsm, Ch>::push(c); } \ + template<typename Ch> \ + void skip(Ch c) { (void) c; } \ + /**/ +#else // #ifndef __MWERKS__ +# define BOOST_IOSTREAMS_FSM(fsm) \ + void push(char c) { this->_push_impl(c); } \ + void push(wchar_t c) { this->_push_impl(c); } \ + void skip(char c) { (void) c; } \ + void skip(wchar_t c) { (void) c; } \ + /**/ +#endif + +//------------------Definition of finite_state_filter_impl--------------------// + +namespace detail { + +template<typename FiniteStateMachine> +class finite_state_filter_impl : protected FiniteStateMachine +{ +private: + template<typename First, typename Last> + struct process_event_impl; +public: + typedef typename char_type_of<FiniteStateMachine>::type char_type; + + finite_state_filter_impl() : state_(FiniteStateMachine::initial_state) { } + + template<typename T0> + explicit finite_state_filter_impl(const T0& t0) + : FiniteStateMachine(t0), state_(FiniteStateMachine::initial_state) + { } + + template<typename T0, typename T1> + finite_state_filter_impl(const T0& t0, const T1& t1) + : FiniteStateMachine(t0, t1), state_(FiniteStateMachine::initial_state) + { } + + template<typename T0, typename T1, typename T2> + finite_state_filter_impl(const T0& t0, const T1& t1, const T2& t2) + : FiniteStateMachine(t0, t1, t2), + state_(FiniteStateMachine::initial_state) + { } +protected: + void process_event(char_type c) + { + typedef typename FiniteStateMachine::transition_table transitions; + typedef typename mpl::begin<transitions>::type first; + typedef typename mpl::end<transitions>::type last; + state_ = process_event_impl<first, last>::execute(*this, state_, c); + } + int& state() { return state_; } + void reset() + { + state_ = FiniteStateMachine::initial_state; + this->clear(); + } +private: + template<typename First, typename Last> + struct process_event_impl { + static int execute(FiniteStateMachine& fsm, int state, char_type event) + { + typedef typename mpl::deref<First>::type rule; + typedef typename mpl::next<First>::type next; + typedef typename rule::character_class character_class; + + if ( state == rule::state && + character_class::test(event, fsm.getloc()) ) + { + // Rule applies. + rule::execute(fsm, event); + return rule::next_state; + } + + // Rule is inapplicable: try next rule. + return process_event_impl<next, Last>::execute(fsm, state, event); + } + }; + + template<typename Last> + struct process_event_impl<Last, Last> { + static int execute(FiniteStateMachine& fsm, int state, char_type c) + { + on_any(fsm, c); + return state; + } + }; +#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) /* Tru64 */ \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) /* CW9.4 */ + public: +#endif + template<typename FSM> + static void on_any(FSM& fsm, char_type c) { fsm.on_any(c); } +private: + int state_; +}; + +} // End namespace detail. + +//------------------Definition of finite_state_filter-------------------------// + +template<typename FiniteStateMachine> +class finite_state_filter + : public detail::finite_state_filter_impl<FiniteStateMachine> +{ +private: + typedef detail::finite_state_filter_impl<FiniteStateMachine> base_type; +public: + typedef typename base_type::char_type char_type; + typedef char_traits<char_type> traits_type; + typedef typename base_type::int_type int_type; + struct category + : dual_use, filter_tag, closable_tag, localizable_tag + { }; + + finite_state_filter() : flags_(0) { } + + template<typename T0> + finite_state_filter(const T0& t0) + : base_type(t0), flags_(0) + { } + + template<typename T0, typename T1> + finite_state_filter(const T0& t0, const T1& t1) + : base_type(t0, t1), flags_(0) + { } + + template<typename T0, typename T1, typename T2> + finite_state_filter(const T0& t0, const T1& t1, const T2& t2) + : base_type(t0, t1, t2), flags_(0) + { } + + template<typename Source> + int_type get(Source& src) + { + assert((flags_ & f_write) == 0); + flags_ |= f_read; + + while (true) { + if ((flags_ & f_eof) == 0) { + + // Read a character and process it. + int_type c; + if (traits_type::is_eof(c = iostreams::get(src))) { + flags_ |= f_eof; + this->on_eof(); + } else if (!traits_type::would_block(c)) { + this->process_event(c); + } + } + + // Return a character, if available. + if (!this->empty()) + return this->pop(); + else if ((flags_ & f_eof) != 0) + return traits_type::eof(); + } + } + + template<typename Sink> + bool put(Sink& dest, char_type c) + { + assert((flags_ & f_read) == 0); + flags_ |= f_write; + + this->process_event(c); + while (!this->empty() && iostreams::put(dest, this->top())) + this->pop(); + + return true; + } + + template<typename Device> + void close(Device& dev, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::out) { + if (flags_ & f_write) + while (!this->empty()) + iostreams::put_if(dev, this->pop()); + this->reset(); + flags_ = 0; + } + } +private: + enum flags { + f_read = 1, + f_write = f_read << 1, + f_eof = f_write << 1 + }; + + int flags_; +}; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/example/iterator_range_example.cpp b/src/boost/libs/iostreams/example/iterator_range_example.cpp new file mode 100644 index 00000000..00ed87b2 --- /dev/null +++ b/src/boost/libs/iostreams/example/iterator_range_example.cpp @@ -0,0 +1,24 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cassert> +#include <string> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/range/iterator_range.hpp> + +namespace io = boost::iostreams; + +int main() +{ + using namespace std; + + string input = "Hello World!"; + string output; + io::filtering_istream in(boost::make_iterator_range(input)); + getline(in, output); + assert(input == output); +} diff --git a/src/boost/libs/iostreams/example/line_wrapping_filter.hpp b/src/boost/libs/iostreams/example/line_wrapping_filter.hpp new file mode 100644 index 00000000..24ee56ff --- /dev/null +++ b/src/boost/libs/iostreams/example/line_wrapping_filter.hpp @@ -0,0 +1,131 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// Adapted from an example of James Kanze. See +// https://web.archive.org/web/20041222094942/http://www.gabi-soft.fr/codebase-en.html. + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_LINE_WRAPPING_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_LINE_WRAPPING_FILTER_HPP_INCLUDED + +#include <cstdio> // EOF. +#include <boost/iostreams/concepts.hpp> // output_filter. +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/operations.hpp> // boost::iostreams::put. + +namespace boost { namespace iostreams { namespace example { + +class line_wrapping_stdio_filter : public stdio_filter { +public: + explicit line_wrapping_stdio_filter(int line_length = 80) + : line_length_(line_length), col_no_(0) + { } +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + if (c != '\n' && col_no_ >= line_length_) + put_char('\n'); + put_char(c); + } + } + void do_close() { col_no_ = 0; } + void put_char(int c) + { + std::cout.put(c); + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + } + int line_length_; + int col_no_; +}; + +class line_wrapping_input_filter : public input_filter { +public: + explicit line_wrapping_input_filter(int line_length = 80) + : line_length_(line_length), col_no_(0), next_(0), has_next_(false) + { } + + template<typename Source> + int get(Source& src) + { + if (has_next_) { + has_next_ = false; + return get_char(next_); + } + + int c; + if ((c = iostreams::get(src)) == EOF || c == WOULD_BLOCK) + return c; + + if (c != '\n' && col_no_ >= line_length_) { + next_ = c; + has_next_ = true; + return get_char('\n'); + } + + return get_char(c); + } + + template<typename Sink> + void close(Sink&) + { + col_no_ = 0; + has_next_ = false; + } +private: + int get_char(int c) + { + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + return c; + } + int line_length_; + int col_no_; + int next_; + bool has_next_; +}; + +class line_wrapping_output_filter : public output_filter { +public: + explicit line_wrapping_output_filter(int line_length = 80) + : line_length_(line_length), col_no_(0) + { } + + template<typename Sink> + bool put(Sink& dest, int c) + { + if (c != '\n' && col_no_ >= line_length_ && !put_char(dest, '\n')) + return false; + return put_char(dest, c); + } + + template<typename Sink> + void close(Sink&) { col_no_ = 0; } +private: + template<typename Sink> + bool put_char(Sink& dest, int c) + { + if (!iostreams::put(dest, c)) + return false; + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + return true; + } + int line_length_; + int col_no_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_LINE_WRAPPING_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/example/shell_comments_filter.hpp b/src/boost/libs/iostreams/example/shell_comments_filter.hpp new file mode 100644 index 00000000..41581c9e --- /dev/null +++ b/src/boost/libs/iostreams/example/shell_comments_filter.hpp @@ -0,0 +1,222 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Peter Dimov. +// See https://web.archive.org/web/20041222094942/http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_SHELL_COMMENTS_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_SHELL_COMMENTS_FILTER_HPP_INCLUDED + +#include <cassert> +#include <cstdio> // EOF. +#include <iostream> // cin, cout. +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/detail/ios.hpp> // BOOST_IOS. +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/operations.hpp> + +namespace boost { namespace iostreams { namespace example { + +class shell_comments_stdio_filter : public stdio_filter { +public: + explicit shell_comments_stdio_filter(char comment_char = '#') + : comment_char_(comment_char) + { } +private: + void do_filter() + { + bool skip = false; + int c; + while ((c = std::cin.get()) != EOF) { + skip = c == comment_char_ ? + true : + c == '\n' ? + false : + skip; + if (!skip) + std::cout.put(c); + } + } + char comment_char_; +}; + +class shell_comments_input_filter : public input_filter { +public: + explicit shell_comments_input_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template<typename Source> + int get(Source& src) + { + int c; + while (true) { + if ((c = boost::iostreams::get(src)) == EOF || c == WOULD_BLOCK) + break; + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + if (!skip_) + break; + } + return c; + } + + template<typename Source> + void close(Source&) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +class shell_comments_output_filter : public output_filter { +public: + explicit shell_comments_output_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template<typename Sink> + bool put(Sink& dest, int c) + { + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + + if (skip_) + return true; + + return iostreams::put(dest, c); + } + + template<typename Source> + void close(Source&) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +class shell_comments_dual_use_filter : public dual_use_filter { +public: + explicit shell_comments_dual_use_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template<typename Source> + int get(Source& src) + { + int c; + while (true) { + if ((c = boost::iostreams::get(src)) == EOF || c == WOULD_BLOCK) + break; + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + if (!skip_) + break; + } + return c; + } + + template<typename Sink> + bool put(Sink& dest, int c) + { + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + + if (skip_) + return true; + + return iostreams::put(dest, c); + } + + template<typename Device> + void close(Device&, BOOST_IOS::openmode) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +class shell_comments_multichar_input_filter : public multichar_input_filter { +public: + explicit shell_comments_multichar_input_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template<typename Source> + std::streamsize read(Source& src, char* s, std::streamsize n) + { + for (std::streamsize z = 0; z < n; ++z) { + int c; + while (true) { + if ((c = boost::iostreams::get(src)) == EOF) + return z != 0 ? z : -1; + else if (c == WOULD_BLOCK) + return z; + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + if (!skip_) + break; + } + s[z] = c; + } + return n; + } + + template<typename Source> + void close(Source&) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +class shell_comments_multichar_output_filter : public multichar_output_filter { +public: + explicit shell_comments_multichar_output_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template<typename Sink> + std::streamsize write(Sink& dest, const char* s, std::streamsize n) + { + std::streamsize z; + for (z = 0; z < n; ++z) { + int c = s[z]; + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + if (skip_) + continue; + if (!iostreams::put(dest, c)) + break; + } + return z; + } + + template<typename Source> + void close(Source&) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_SHELL_COMMENTS_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/example/std_back_inserter_example.cpp b/src/boost/libs/iostreams/example/std_back_inserter_example.cpp new file mode 100644 index 00000000..6ad61c5e --- /dev/null +++ b/src/boost/libs/iostreams/example/std_back_inserter_example.cpp @@ -0,0 +1,24 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cassert> +#include <iterator> // back_inserter +#include <string> +#include <boost/iostreams/filtering_stream.hpp> + +namespace io = boost::iostreams; + +int main() +{ + using namespace std; + + string result; + io::filtering_ostream out(std::back_inserter(result)); + out << "Hello World!"; + out.flush(); + assert(result == "Hello World!"); +} diff --git a/src/boost/libs/iostreams/example/tab_expanding_filter.hpp b/src/boost/libs/iostreams/example/tab_expanding_filter.hpp new file mode 100644 index 00000000..9a1b7d4c --- /dev/null +++ b/src/boost/libs/iostreams/example/tab_expanding_filter.hpp @@ -0,0 +1,155 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Rob Stewart. +// See https://web.archive.org/web/20041222094942/http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_TAB_EXPANDING_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_TAB_EXPANDING_FILTER_HPP_INCLUDED + +#include <cassert> +#include <cstdio> // EOF. +#include <iostream> // cin, cout. +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/operations.hpp> + +namespace boost { namespace iostreams { namespace example { + +class tab_expanding_stdio_filter : public stdio_filter { +public: + explicit tab_expanding_stdio_filter(int tab_size = 8) + : tab_size_(tab_size), col_no_(0) + { + assert(tab_size > 0); + } +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + if (c == '\t') { + int spaces = tab_size_ - (col_no_ % tab_size_); + for (; spaces > 0; --spaces) + put_char(' '); + } else { + put_char(c); + } + } + } + void do_close() { col_no_ = 0; } + void put_char(int c) + { + std::cout.put(c); + if (c == '\n') { + col_no_ = 0; + } else { + ++col_no_; + } + } + int tab_size_; + int col_no_; +}; + +class tab_expanding_input_filter : public input_filter { +public: + explicit tab_expanding_input_filter(int tab_size = 8) + : tab_size_(tab_size), col_no_(0), spaces_(0) + { + assert(tab_size > 0); + } + + template<typename Source> + int get(Source& src) + { + if (spaces_ > 0) { + --spaces_; + return get_char(' '); + } + + int c; + if ((c = iostreams::get(src)) == EOF || c == WOULD_BLOCK) + return c; + + if (c != '\t') + return get_char(c); + + // Found a tab. Call this filter recursively. + spaces_ = tab_size_ - (col_no_ % tab_size_); + return this->get(src); + } + + template<typename Source> + void close(Source&) + { + col_no_ = 0; + spaces_ = 0; + } +private: + int get_char(int c) + { + if (c == '\n') { + col_no_ = 0; + } else { + ++col_no_; + } + return c; + } + int tab_size_; + int col_no_; + int spaces_; +}; + +class tab_expanding_output_filter : public output_filter { +public: + explicit tab_expanding_output_filter(int tab_size = 8) + : tab_size_(tab_size), col_no_(0), spaces_(0) + { + assert(tab_size > 0); + } + + template<typename Sink> + bool put(Sink& dest, int c) + { + for (; spaces_ > 0; --spaces_) + if (!put_char(dest, ' ')) + return false; + + if (c == '\t') { + spaces_ = tab_size_ - (col_no_ % tab_size_) - 1; + return this->put(dest, ' '); + } + + return put_char(dest, c); + } + + template<typename Sink> + void close(Sink&) + { + col_no_ = 0; + spaces_ = 0; + } +private: + template<typename Sink> + bool put_char(Sink& dest, int c) + { + if (!iostreams::put(dest, c)) + return false; + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + return true; + } + int tab_size_; + int col_no_; + int spaces_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TAB_EXPANDING_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/example/unix2dos_filter.hpp b/src/boost/libs/iostreams/example/unix2dos_filter.hpp new file mode 100644 index 00000000..55180ac3 --- /dev/null +++ b/src/boost/libs/iostreams/example/unix2dos_filter.hpp @@ -0,0 +1,99 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_UNIX2DOS_FILTER_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_UNIX2DOS_FILTER_FILTER_HPP_INCLUDED + +#include <cassert> +#include <cstdio> // EOF. +#include <iostream> // cin, cout. +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/operations.hpp> + +namespace boost { namespace iostreams { namespace example { + +class unix2dos_stdio_filter : public stdio_filter { +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + if (c == '\n') + std::cout.put('\r'); + std::cout.put(c); + } + } +}; + +class unix2dos_input_filter : public input_filter { +public: + unix2dos_input_filter() : has_linefeed_(false) { } + + template<typename Source> + int get(Source& src) + { + if (has_linefeed_) { + has_linefeed_ = false; + return '\n'; + } + + int c; + if ((c = iostreams::get(src)) == '\n') { + has_linefeed_ = true; + return '\r'; + } + + return c; + } + + template<typename Source> + void close(Source&) { has_linefeed_ = false; } +private: + bool has_linefeed_; +}; + +class unix2dos_output_filter : public output_filter { +public: + unix2dos_output_filter() : has_linefeed_(false) { } + + template<typename Sink> + bool put(Sink& dest, int c) + { + if (c == '\n') + return has_linefeed_ ? + put_char(dest, '\n') : + put_char(dest, '\r') ? + this->put(dest, '\n') : + false; + return iostreams::put(dest, c); + } + + template<typename Sink> + void close(Sink&) { has_linefeed_ = false; } +private: + template<typename Sink> + bool put_char(Sink& dest, int c) + { + bool result; + if ((result = iostreams::put(dest, c)) == true) { + has_linefeed_ = + c == '\r' ? + true : + c == '\n' ? + false : + has_linefeed_; + } + return result; + } + + bool has_linefeed_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_UNIX2DOS_FILTER_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/index.html b/src/boost/libs/iostreams/index.html new file mode 100644 index 00000000..8ba23781 --- /dev/null +++ b/src/boost/libs/iostreams/index.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<HTML> +<HEAD> +<META HTTP-EQUIV="refresh" CONTENT="0; URL=doc/index.html"> +</HEAD> +<BODY> +<P>Please visit our new location at <A HREF="doc/index.html">doc/index.html</A>. </P> +<hr> +<p>© Copyright Beman Dawes, 2001</p> +<p>Distributed under the Boost Software License, Version 1.0. (See accompanying +file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy +at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/boost/libs/iostreams/meta/libraries.json b/src/boost/libs/iostreams/meta/libraries.json new file mode 100644 index 00000000..505f888e --- /dev/null +++ b/src/boost/libs/iostreams/meta/libraries.json @@ -0,0 +1,15 @@ +{ + "key": "iostreams", + "name": "Iostreams", + "authors": [ + "Jonathan Turkanis" + ], + "description": "Boost.IOStreams provides a framework for defining streams, stream buffers and i/o filters.", + "category": [ + "IO", + "String" + ], + "maintainers": [ + "Jonathan Turkanis <turkanis -at- coderage.com>" + ] +} diff --git a/src/boost/libs/iostreams/src/bzip2.cpp b/src/boost/libs/iostreams/src/bzip2.cpp new file mode 100644 index 00000000..195b57d8 --- /dev/null +++ b/src/boost/libs/iostreams/src/bzip2.cpp @@ -0,0 +1,171 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// To configure Boost to work with libbz2, see the +// installation instructions here: +// http://boost.org/libs/iostreams/doc/index.html?path=7 + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <boost/throw_exception.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/filter/bzip2.hpp> +#include "bzlib.h" // Julian Seward's "bzip.h" header. + // To configure Boost to work with libbz2, see the + // installation instructions here: + // http://boost.org/libs/iostreams/doc/index.html?path=7 + +namespace boost { namespace iostreams { + +namespace bzip2 { + + // Status codes + +const int ok = BZ_OK; +const int run_ok = BZ_RUN_OK; +const int flush_ok = BZ_FLUSH_OK; +const int finish_ok = BZ_FINISH_OK; +const int stream_end = BZ_STREAM_END; +const int sequence_error = BZ_SEQUENCE_ERROR; +const int param_error = BZ_PARAM_ERROR; +const int mem_error = BZ_MEM_ERROR; +const int data_error = BZ_DATA_ERROR; +const int data_error_magic = BZ_DATA_ERROR_MAGIC; +const int io_error = BZ_IO_ERROR; +const int unexpected_eof = BZ_UNEXPECTED_EOF; +const int outbuff_full = BZ_OUTBUFF_FULL; +const int config_error = BZ_CONFIG_ERROR; + + // Action codes + +const int finish = BZ_FINISH; +const int run = BZ_RUN; + +} // End namespace bzip2. + +//------------------Implementation of bzip2_error-----------------------------// + +bzip2_error::bzip2_error(int error) + : BOOST_IOSTREAMS_FAILURE("bzip2 error"), error_(error) + { } + +void bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error) +{ + switch (error) { + case BZ_OK: + case BZ_RUN_OK: + case BZ_FLUSH_OK: + case BZ_FINISH_OK: + case BZ_STREAM_END: + return; + case BZ_MEM_ERROR: + boost::throw_exception(std::bad_alloc()); + default: + boost::throw_exception(bzip2_error(error)); + } +} + +//------------------Implementation of bzip2_base------------------------------// + +namespace detail { + +bzip2_base::bzip2_base(const bzip2_params& params) + : params_(params), stream_(new bz_stream), ready_(false) + { } + +bzip2_base::~bzip2_base() { delete static_cast<bz_stream*>(stream_); } + +void bzip2_base::before( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end ) +{ + bz_stream* s = static_cast<bz_stream*>(stream_); + s->next_in = const_cast<char*>(src_begin); + s->avail_in = static_cast<unsigned>(src_end - src_begin); + s->next_out = reinterpret_cast<char*>(dest_begin); + s->avail_out= static_cast<unsigned>(dest_end - dest_begin); +} + +void bzip2_base::after(const char*& src_begin, char*& dest_begin) +{ + bz_stream* s = static_cast<bz_stream*>(stream_); + src_begin = const_cast<char*>(s->next_in); + dest_begin = s->next_out; +} + +int bzip2_base::check_end(const char* src_begin, const char* dest_begin) +{ + bz_stream* s = static_cast<bz_stream*>(stream_); + if( src_begin == s->next_in && + s->avail_in == 0 && + dest_begin == s->next_out) { + return bzip2::unexpected_eof; + } else { + return bzip2::ok; + } +} + +int bzip2_base::end(bool compress, std::nothrow_t) +{ + if (!ready_) return bzip2::ok; + ready_ = false; + bz_stream* s = static_cast<bz_stream*>(stream_); + return compress ? BZ2_bzCompressEnd(s) : BZ2_bzDecompressEnd(s); +} + +void bzip2_base::end(bool compress) +{ + bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + end(compress, std::nothrow) + ); +} + +int bzip2_base::compress(int action) +{ + return BZ2_bzCompress(static_cast<bz_stream*>(stream_), action); +} + +int bzip2_base::decompress() +{ + return BZ2_bzDecompress(static_cast<bz_stream*>(stream_)); +} + +void bzip2_base::do_init + ( bool compress, + bzip2::alloc_func /* alloc */, + bzip2::free_func /* free */, + void* derived ) +{ + bz_stream* s = static_cast<bz_stream*>(stream_); + + // Current interface for customizing memory management + // is non-conforming and has been disabled: + // s->bzalloc = alloc; + // s->bzfree = free; + s->bzalloc = 0; + s->bzfree = 0; + s->opaque = derived; + bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + compress ? + BZ2_bzCompressInit( s, + params_.block_size, + 0, + params_.work_factor ) : + BZ2_bzDecompressInit( s, + 0, + params_.small ) + ); + ready_ = true; +} + +} // End namespace detail. + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/src/file_descriptor.cpp b/src/boost/libs/iostreams/src/file_descriptor.cpp new file mode 100644 index 00000000..288e2c64 --- /dev/null +++ b/src/boost/libs/iostreams/src/file_descriptor.cpp @@ -0,0 +1,619 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <cassert> +#include <cerrno> +#include <cstdio> // SEEK_SET, etc. +#include <boost/config.hpp> // BOOST_JOIN +#include <boost/iostreams/detail/error.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/detail/config/rtl.hpp> // BOOST_IOSTREAMS_FD_XXX +#include <boost/iostreams/detail/config/windows_posix.hpp> +#include <boost/iostreams/detail/system_failure.hpp> +#include <boost/iostreams/detail/ios.hpp> // openmodes, failure. +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/integer_traits.hpp> +#include <boost/throw_exception.hpp> + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> + + // OS-specific headers for low-level i/o. + +#include <fcntl.h> // file opening flags. +#include <sys/stat.h> // file access permissions. +#ifdef BOOST_IOSTREAMS_WINDOWS +# include <io.h> // low-level file i/o. +# define WINDOWS_LEAN_AND_MEAN +# include <windows.h> +# ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +# endif +#else +# include <sys/types.h> // mode_t. +# include <unistd.h> // low-level file i/o. +#endif + +namespace boost { namespace iostreams { + +//------------------Definition of file_descriptor_impl------------------------// + +namespace detail { + +// Contains the platform dependant implementation +struct file_descriptor_impl { + // Note: These need to match file_desciptor_flags + enum flags { + never_close = 0, + close_on_exit = 1, + close_on_close = 2, + close_always = 3 + }; + + file_descriptor_impl(); + ~file_descriptor_impl(); + void open(file_handle fd, flags); +#ifdef BOOST_IOSTREAMS_WINDOWS + void open(int fd, flags); +#endif + void open(const detail::path&, BOOST_IOS::openmode); + bool is_open() const; + void close(); + void close_impl(bool close_flag, bool throw_); + std::streamsize read(char* s, std::streamsize n); + std::streamsize write(const char* s, std::streamsize n); + std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); + static file_handle invalid_handle(); + file_handle handle_; + int flags_; +}; + +//------------------Implementation of file_descriptor_impl--------------------// + +file_descriptor_impl::file_descriptor_impl() + : handle_(invalid_handle()), flags_(0) + { } + +file_descriptor_impl::~file_descriptor_impl() +{ + close_impl(flags_ & close_on_exit, false); +} + +void file_descriptor_impl::open(file_handle fd, flags f) +{ + // Using 'close' to close the existing handle so that it will throw an + // exception if it fails. + // + // Only closing after assigning the new handle, so that the class will + // take ownership of the handle regardless of whether close throws. + + file_descriptor_impl tmp; + tmp.handle_ = handle_; + tmp.flags_ = flags_ & close_on_exit ? close_on_close : never_close; + + handle_ = fd; + flags_ = f; + + tmp.close(); +} + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +void file_descriptor_impl::open(int fd, flags f) +{ open(reinterpret_cast<file_handle>(_get_osfhandle(fd)), f); } + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +void file_descriptor_impl::open(const detail::path& p, BOOST_IOS::openmode mode) +{ + close_impl(flags_ & close_on_exit, true); + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + DWORD dwDesiredAccess; + DWORD dwCreationDisposition; + + if ( !(mode & (BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app)) || + ((mode & BOOST_IOS::trunc) && + ((mode & BOOST_IOS::app) || !(mode & BOOST_IOS::out))) ) { + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode")); + } + else if ( mode & BOOST_IOS::in ) { + if ( mode & BOOST_IOS::app ) + { + dwCreationDisposition = OPEN_ALWAYS; + dwDesiredAccess = + GENERIC_READ | + FILE_APPEND_DATA | + FILE_WRITE_ATTRIBUTES | + FILE_WRITE_EA | + STANDARD_RIGHTS_WRITE | + SYNCHRONIZE; + } + else if ( mode & BOOST_IOS::trunc ) + { + dwCreationDisposition = CREATE_ALWAYS; + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + } + else if ( mode & BOOST_IOS::out ) + { + dwCreationDisposition = OPEN_EXISTING; + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + } + else + { + dwCreationDisposition = OPEN_EXISTING; + dwDesiredAccess = GENERIC_READ; + } + } + else { + if ( mode & BOOST_IOS::app ) + { + dwCreationDisposition = OPEN_ALWAYS; + dwDesiredAccess = + FILE_APPEND_DATA | + FILE_WRITE_ATTRIBUTES | + FILE_WRITE_EA | + STANDARD_RIGHTS_WRITE | + SYNCHRONIZE; + } + else + { + dwCreationDisposition = CREATE_ALWAYS; + dwDesiredAccess = GENERIC_WRITE; + } + } + + + HANDLE handle = p.is_wide() ? + ::CreateFileW( p.c_wstr(), + dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // lpSecurityAttributes + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, + NULL ) : // hTemplateFile + ::CreateFileA( p.c_str(), + dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // lpSecurityAttributes + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, + NULL ); // hTemplateFile + if (handle != INVALID_HANDLE_VALUE) { + handle_ = handle; + flags_ = close_always; + } else { + flags_ = 0; + throw_system_failure("failed opening file"); + } +#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------// + + // Calculate oflag argument to open. + + int oflag = 0; + if ( !(mode & (BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app)) || + ((mode & BOOST_IOS::trunc) && + ((mode & BOOST_IOS::app) || !(mode & BOOST_IOS::out))) ) { + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode")); + } + else if ( mode & BOOST_IOS::in ) { + if ( mode & BOOST_IOS::app ) + oflag |= O_CREAT | O_APPEND | O_RDWR; + else if ( mode & BOOST_IOS::trunc ) + oflag |= O_CREAT | O_TRUNC | O_RDWR; + else if ( mode & BOOST_IOS::out ) + oflag |= O_RDWR; + else + oflag |= O_RDONLY; + } + else { + if ( mode & BOOST_IOS::app ) + oflag |= O_CREAT | O_APPEND | O_WRONLY; + else + oflag |= O_CREAT | O_TRUNC | O_WRONLY; + } + #ifdef _LARGEFILE64_SOURCE + oflag |= O_LARGEFILE; + #endif + + // Calculate pmode argument to open. + + mode_t pmode = S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH; + + // Open file. + + int fd = BOOST_IOSTREAMS_FD_OPEN(p.c_str(), oflag, pmode); + if (fd == -1) { + boost::throw_exception(system_failure("failed opening file")); + } else { + if ( mode & BOOST_IOS::ate ) { + if (BOOST_IOSTREAMS_FD_SEEK(fd, 0, SEEK_END) == -1) { + BOOST_IOSTREAMS_FD_CLOSE(fd); + boost::throw_exception(system_failure("failed opening file")); + } + } + handle_ = fd; + flags_ = close_always; + } +#endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------// +} + +bool file_descriptor_impl::is_open() const +{ return handle_ != invalid_handle(); } + +void file_descriptor_impl::close() +{ + close_impl((flags_ & close_on_close) != 0, true); +} + +void file_descriptor_impl::close_impl(bool close_flag, bool throw_) { + if (handle_ != invalid_handle()) { + if (close_flag) { + bool success = + #ifdef BOOST_IOSTREAMS_WINDOWS + ::CloseHandle(handle_) == 1; + #else + BOOST_IOSTREAMS_FD_CLOSE(handle_) != -1; + #endif + if (!success && throw_) + throw_system_failure("failed closing file"); + } + handle_ = invalid_handle(); + flags_ = 0; + } +} + +std::streamsize file_descriptor_impl::read(char* s, std::streamsize n) +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + DWORD result; + if (!::ReadFile(handle_, s, static_cast<DWORD>(n), &result, NULL)) + { + // report EOF if the write-side of a pipe has been closed + if (GetLastError() == ERROR_BROKEN_PIPE) + { + result = 0; + } + else + throw_system_failure("failed reading"); + } + return result == 0 ? -1 : static_cast<std::streamsize>(result); +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + errno = 0; + std::streamsize result = BOOST_IOSTREAMS_FD_READ(handle_, s, n); + if (errno != 0) + throw_system_failure("failed reading"); + return result == 0 ? -1 : result; +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +std::streamsize file_descriptor_impl::write(const char* s, std::streamsize n) +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + DWORD ignore; + if (!::WriteFile(handle_, s, static_cast<DWORD>(n), &ignore, NULL)) + throw_system_failure("failed writing"); + return n; +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + int amt = BOOST_IOSTREAMS_FD_WRITE(handle_, s, n); + if (amt < n) // Handles blocking fd's only. + throw_system_failure("failed writing"); + return n; +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +std::streampos file_descriptor_impl::seek + (stream_offset off, BOOST_IOS::seekdir way) +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff); + LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32); + DWORD dwResultLow = + ::SetFilePointer( handle_, + lDistanceToMove, + &lDistanceToMoveHigh, + way == BOOST_IOS::beg ? + FILE_BEGIN : + way == BOOST_IOS::cur ? + FILE_CURRENT : + FILE_END ); + if ( dwResultLow == INVALID_SET_FILE_POINTER && + ::GetLastError() != NO_ERROR ) + { + boost::throw_exception(system_failure("failed seeking")); + } else { + return offset_to_position( + (stream_offset(lDistanceToMoveHigh) << 32) + dwResultLow + ); + } +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + if ( off > integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_max || + off < integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_min ) + { + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad offset")); + } + stream_offset result = + BOOST_IOSTREAMS_FD_SEEK( + handle_, + static_cast<BOOST_IOSTREAMS_FD_OFFSET>(off), + ( way == BOOST_IOS::beg ? + SEEK_SET : + way == BOOST_IOS::cur ? + SEEK_CUR : + SEEK_END ) + ); + if (result == -1) + boost::throw_exception(system_failure("failed seeking")); + return offset_to_position(result); +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +// Returns the value stored in a file_handle variable when no file is open +file_handle file_descriptor_impl::invalid_handle() +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + return INVALID_HANDLE_VALUE; +#else + return -1; +#endif +} + +} // End namespace detail. + +//------------------Implementation of file_descriptor-------------------------// + +file_descriptor::file_descriptor() : pimpl_(new impl_type) { } + +file_descriptor::file_descriptor(handle_type fd, file_descriptor_flags f) + : pimpl_(new impl_type) +{ open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +file_descriptor::file_descriptor(handle_type fd, bool close_on_exit) + : pimpl_(new impl_type) +{ open(fd, close_on_exit); } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +file_descriptor::file_descriptor(int fd, file_descriptor_flags f) + : pimpl_(new impl_type) +{ open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +file_descriptor::file_descriptor(int fd, bool close_on_exit) + : pimpl_(new impl_type) +{ open(fd, close_on_exit); } +#endif + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +file_descriptor::file_descriptor( const std::string& path, + BOOST_IOS::openmode mode ) + : pimpl_(new impl_type) +{ open(path, mode); } + +file_descriptor::file_descriptor( const char* path, + BOOST_IOS::openmode mode ) + : pimpl_(new impl_type) +{ open(path, mode); } + +file_descriptor::file_descriptor(const file_descriptor& other) + : pimpl_(other.pimpl_) + { } + +void file_descriptor::open(handle_type fd, file_descriptor_flags f) +{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +void file_descriptor::open(handle_type fd, bool close_on_exit) +{ pimpl_->open(fd, close_on_exit ? + detail::file_descriptor_impl::close_always : + detail::file_descriptor_impl::close_on_close); } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +void file_descriptor::open(int fd, file_descriptor_flags f) +{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +void file_descriptor::open(int fd, bool close_on_exit) +{ pimpl_->open(fd, close_on_exit ? + detail::file_descriptor_impl::close_always : + detail::file_descriptor_impl::close_on_close); } +#endif + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +void file_descriptor::open(const std::string& path, BOOST_IOS::openmode mode) +{ open(detail::path(path), mode); } + +void file_descriptor::open(const char* path, BOOST_IOS::openmode mode) +{ open(detail::path(path), mode); } + +bool file_descriptor::is_open() const { return pimpl_->is_open(); } + +void file_descriptor::close() { pimpl_->close(); } + +std::streamsize file_descriptor::read(char_type* s, std::streamsize n) +{ return pimpl_->read(s, n); } + +std::streamsize file_descriptor::write(const char_type* s, std::streamsize n) +{ return pimpl_->write(s, n); } + +std::streampos file_descriptor::seek(stream_offset off, BOOST_IOS::seekdir way) +{ return pimpl_->seek(off, way); } + +detail::file_handle file_descriptor::handle() const { return pimpl_->handle_; } + +void file_descriptor::init() { pimpl_.reset(new impl_type); } + +void file_descriptor::open( + const detail::path& path, + BOOST_IOS::openmode mode, + BOOST_IOS::openmode base ) +{ + mode |= base; + pimpl_->open(path, mode); +} + +//------------------Implementation of file_descriptor_source------------------// + +file_descriptor_source::file_descriptor_source( + handle_type fd, file_descriptor_flags f) +{ open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +file_descriptor_source::file_descriptor_source( + handle_type fd, bool close_on_exit) +{ open(fd, close_on_exit); } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +file_descriptor_source::file_descriptor_source(int fd, file_descriptor_flags f) +{ open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +file_descriptor_source::file_descriptor_source(int fd, bool close_on_exit) +{ open(fd, close_on_exit); } +#endif + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +file_descriptor_source::file_descriptor_source( + const std::string& path, BOOST_IOS::openmode mode) +{ open(path, mode); } + +file_descriptor_source::file_descriptor_source( + const char* path, BOOST_IOS::openmode mode) +{ open(path, mode); } + +file_descriptor_source::file_descriptor_source( + const file_descriptor_source& other) + : file_descriptor(static_cast<const file_descriptor&>(other)) + { } + +void file_descriptor_source::open(handle_type fd, file_descriptor_flags f) +{ file_descriptor::open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +void file_descriptor_source::open(handle_type fd, bool close_on_exit) +{ file_descriptor::open(fd, close_on_exit); } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +void file_descriptor_source::open(int fd, file_descriptor_flags f) +{ file_descriptor::open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +void file_descriptor_source::open(int fd, bool close_on_exit) +{ file_descriptor::open(fd, close_on_exit); } +#endif + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +void file_descriptor_source::open( + const std::string& path, BOOST_IOS::openmode mode) +{ open(detail::path(path), mode); } + +void file_descriptor_source::open( + const char* path, BOOST_IOS::openmode mode) +{ open(detail::path(path), mode); } + +void file_descriptor_source::open( + const detail::path& path, BOOST_IOS::openmode mode) +{ + if (mode & (BOOST_IOS::out | BOOST_IOS::trunc)) + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode")); + file_descriptor::open(path, mode, BOOST_IOS::in); +} + +//------------------Implementation of file_descriptor_sink--------------------// + +file_descriptor_sink::file_descriptor_sink( + handle_type fd, file_descriptor_flags f) +{ open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +file_descriptor_sink::file_descriptor_sink( + handle_type fd, bool close_on_exit) +{ open(fd, close_on_exit); } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +file_descriptor_sink::file_descriptor_sink(int fd, file_descriptor_flags f) +{ open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +file_descriptor_sink::file_descriptor_sink(int fd, bool close_on_exit) +{ open(fd, close_on_exit); } +#endif + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +file_descriptor_sink::file_descriptor_sink( + const std::string& path, BOOST_IOS::openmode mode) +{ open(path, mode); } + +file_descriptor_sink::file_descriptor_sink( + const char* path, BOOST_IOS::openmode mode) +{ open(path, mode); } + +file_descriptor_sink::file_descriptor_sink(const file_descriptor_sink& other) + : file_descriptor(static_cast<const file_descriptor&>(other)) + { } + +void file_descriptor_sink::open(handle_type fd, file_descriptor_flags f) +{ file_descriptor::open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +void file_descriptor_sink::open(handle_type fd, bool close_on_exit) +{ file_descriptor::open(fd, close_on_exit); } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------// + +void file_descriptor_sink::open(int fd, file_descriptor_flags f) +{ file_descriptor::open(fd, f); } + +#if defined(BOOST_IOSTREAMS_USE_DEPRECATED) +void file_descriptor_sink::open(int fd, bool close_on_exit) +{ file_descriptor::open(fd, close_on_exit); } +#endif + +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------// + +void file_descriptor_sink::open( + const std::string& path, BOOST_IOS::openmode mode) +{ open(detail::path(path), mode); } + +void file_descriptor_sink::open( + const char* path, BOOST_IOS::openmode mode) +{ open(detail::path(path), mode); } + +void file_descriptor_sink::open( + const detail::path& path, BOOST_IOS::openmode mode) +{ + if (mode & BOOST_IOS::in) + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode")); + file_descriptor::open(path, mode, BOOST_IOS::out); +} + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/src/gzip.cpp b/src/boost/libs/iostreams/src/gzip.cpp new file mode 100644 index 00000000..94830e5b --- /dev/null +++ b/src/boost/libs/iostreams/src/gzip.cpp @@ -0,0 +1,174 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// To configure Boost to work with libbz2, see the +// installation instructions here: +// http://boost.org/libs/iostreams/doc/index.html?path=7 + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/filter/gzip.hpp> +#include <boost/throw_exception.hpp> + +namespace boost { namespace iostreams { + +//------------------Implementation of gzip_header-----------------------------// + +namespace detail { + +void gzip_header::process(char c) +{ + uint8_t value = static_cast<uint8_t>(c); + switch (state_) { + case s_id1: + if (value != gzip::magic::id1) + boost::throw_exception(gzip_error(gzip::bad_header)); + state_ = s_id2; + break; + case s_id2: + if (value != gzip::magic::id2) + boost::throw_exception(gzip_error(gzip::bad_header)); + state_ = s_cm; + break; + case s_cm: + if (value != gzip::method::deflate) + boost::throw_exception(gzip_error(gzip::bad_method)); + state_ = s_flg; + break; + case s_flg: + flags_ = value; + state_ = s_mtime; + break; + case s_mtime: + mtime_ += value << (offset_ * 8); + if (offset_ == 3) { + state_ = s_xfl; + offset_ = 0; + } else { + ++offset_; + } + break; + case s_xfl: + state_ = s_os; + break; + case s_os: + os_ = value; + if (flags_ & gzip::flags::extra) { + state_ = s_xlen; + } else if (flags_ & gzip::flags::name) { + state_ = s_name; + } else if (flags_ & gzip::flags::comment) { + state_ = s_comment; + } else if (flags_ & gzip::flags::header_crc) { + state_ = s_hcrc; + } else { + state_ = s_done; + } + break; + case s_xlen: + xlen_ += value << (offset_ * 8); + if (offset_ == 1) { + state_ = s_extra; + offset_ = 0; + } else { + ++offset_; + } + break; + case s_extra: + if (--xlen_ == 0) { + if (flags_ & gzip::flags::name) { + state_ = s_name; + } else if (flags_ & gzip::flags::comment) { + state_ = s_comment; + } else if (flags_ & gzip::flags::header_crc) { + state_ = s_hcrc; + } else { + state_ = s_done; + } + } + break; + case s_name: + if (c != 0) { + file_name_ += c; + } else if (flags_ & gzip::flags::comment) { + state_ = s_comment; + } else if (flags_ & gzip::flags::header_crc) { + state_ = s_hcrc; + } else { + state_ = s_done; + } + break; + case s_comment: + if (c != 0) { + comment_ += c; + } else if (flags_ & gzip::flags::header_crc) { + state_ = s_hcrc; + } else { + state_ = s_done; + } + break; + case s_hcrc: + if (offset_ == 1) { + state_ = s_done; + offset_ = 0; + } else { + ++offset_; + } + break; + default: + BOOST_ASSERT(0); + } +} + +void gzip_header::reset() +{ + file_name_.clear(); + comment_.clear(); + os_ = flags_ = offset_ = xlen_ = 0; + mtime_ = 0; + state_ = s_id1; +} + +//------------------Implementation of gzip_footer-----------------------------// + +void gzip_footer::process(char c) +{ + uint8_t value = static_cast<uint8_t>(c); + if (state_ == s_crc) { + crc_ += value << (offset_ * 8); + if (offset_ == 3) { + state_ = s_isize; + offset_ = 0; + } else { + ++offset_; + } + } else if (state_ == s_isize) { + isize_ += value << (offset_ * 8); + if (offset_ == 3) { + state_ = s_done; + offset_ = 0; + } else { + ++offset_; + } + } else { + BOOST_ASSERT(0); + } +} + +void gzip_footer::reset() +{ + crc_ = isize_ = offset_ = 0; + state_ = s_crc; +} + +} // End namespace boost::iostreams::detail. + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/src/lzma.cpp b/src/boost/libs/iostreams/src/lzma.cpp new file mode 100644 index 00000000..9376c23d --- /dev/null +++ b/src/boost/libs/iostreams/src/lzma.cpp @@ -0,0 +1,171 @@ +// (C) Copyright Milan Svoboda 2008. +// Originally developed under the fusecompress project. +// Based on bzip2.cpp by: +// (C) Copyright Jonathan Turkanis 2003. +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <lzma.h> + +#include <boost/throw_exception.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/filter/lzma.hpp> + + +#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED + #if LZMA_VERSION < 50020002 + #define BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED + #endif +#endif + +namespace boost { namespace iostreams { + +namespace lzma { + + // Compression levels + +const uint32_t no_compression = 0; +const uint32_t best_speed = 1; +const uint32_t best_compression = 9; +const uint32_t default_compression = 2; + + // Status codes + +const int okay = LZMA_OK; +const int stream_end = LZMA_STREAM_END; +const int unsupported_check = LZMA_UNSUPPORTED_CHECK; +const int mem_error = LZMA_MEM_ERROR; +const int options_error = LZMA_OPTIONS_ERROR; +const int data_error = LZMA_DATA_ERROR; +const int buf_error = LZMA_BUF_ERROR; +const int prog_error = LZMA_PROG_ERROR; + + // Flush codes + +const int finish = LZMA_FINISH; +const int full_flush = LZMA_FULL_FLUSH; +const int sync_flush = LZMA_SYNC_FLUSH; +const int run = LZMA_RUN; + + // Code for current OS + +} // End namespace lzma. + +//------------------Implementation of lzma_error------------------------------// + +lzma_error::lzma_error(int error) + : BOOST_IOSTREAMS_FAILURE("lzma error"), error_(error) + { } + +void lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error) +{ + switch (error) { + case LZMA_OK: + case LZMA_STREAM_END: + return; + case LZMA_MEM_ERROR: + boost::throw_exception(std::bad_alloc()); + default: + boost::throw_exception(lzma_error(error)); + } +} + +//------------------Implementation of lzma_base-------------------------------// + +namespace detail { + +lzma_base::lzma_base() + : stream_(new lzma_stream), level_(lzma::default_compression), threads_(1) + { } + +lzma_base::~lzma_base() { delete static_cast<lzma_stream*>(stream_); } + +void lzma_base::before( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end ) +{ + lzma_stream* s = static_cast<lzma_stream*>(stream_); + s->next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(src_begin)); + s->avail_in = static_cast<size_t>(src_end - src_begin); + s->next_out = reinterpret_cast<uint8_t*>(dest_begin); + s->avail_out= static_cast<size_t>(dest_end - dest_begin); +} + +void lzma_base::after(const char*& src_begin, char*& dest_begin, bool) +{ + lzma_stream* s = static_cast<lzma_stream*>(stream_); + src_begin = const_cast<const char*>(reinterpret_cast<const char*>(s->next_in)); + dest_begin = reinterpret_cast<char*>(s->next_out); +} + +int lzma_base::deflate(int action) +{ + return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action)); +} + +int lzma_base::inflate(int action) +{ + return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action)); +} + +void lzma_base::reset(bool compress, bool realloc) +{ + lzma_stream* s = static_cast<lzma_stream*>(stream_); + lzma_end(s); + if (realloc) + { + init_stream(compress); + } +} + +void lzma_base::do_init + ( const lzma_params& p, bool compress, + lzma::alloc_func, lzma::free_func, + void* ) +{ + + level_ = p.level; + threads_ = p.threads; + +#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED + if (threads_ == 0) { + threads_ = lzma_cputhreads(); + } +#endif + + init_stream(compress); +} + +void lzma_base::init_stream(bool compress) +{ + lzma_stream* s = static_cast<lzma_stream*>(stream_); + + memset(s, 0, sizeof(*s)); + +#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED + const lzma_mt opt = { 0, threads_, 0, 1000, level_, NULL, LZMA_CHECK_CRC32 }; +#endif + + lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + compress ? +#ifdef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED + lzma_easy_encoder(s, level_, LZMA_CHECK_CRC32) : +#else + lzma_stream_encoder_mt(s, &opt) : +#endif + lzma_stream_decoder(s, 100 * 1024 * 1024, LZMA_CONCATENATED) + ); +} + + +} // End namespace detail. + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/src/mapped_file.cpp b/src/boost/libs/iostreams/src/mapped_file.cpp new file mode 100644 index 00000000..918a5d4c --- /dev/null +++ b/src/boost/libs/iostreams/src/mapped_file.cpp @@ -0,0 +1,499 @@ +// (C) Copyright Craig Henderson 2002 'boost/memmap.hpp' from sandbox +// (C) Copyright Jonathan Turkanis 2004. +// (C) Copyright Jonathan Graehl 2004. +// (C) Copyright Jorge Lodos 2008. +// 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.) + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <cassert> +#include <stdexcept> +#include <boost/iostreams/detail/config/rtl.hpp> +#include <boost/iostreams/detail/config/windows_posix.hpp> +#include <boost/iostreams/detail/file_handle.hpp> +#include <boost/iostreams/detail/system_failure.hpp> +#include <boost/iostreams/device/mapped_file.hpp> +#include <boost/throw_exception.hpp> +#include <boost/numeric/conversion/cast.hpp> + +#ifdef BOOST_IOSTREAMS_WINDOWS +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +# include <windows.h> +#else +# include <errno.h> +# include <fcntl.h> +# include <sys/mman.h> // mmap, munmap. +# include <sys/stat.h> +# include <sys/types.h> // struct stat. +# include <unistd.h> // sysconf. +#endif + +namespace boost { namespace iostreams { + +namespace detail { + +// Class containing the platform-sepecific implementation +// Invariant: The members params_, data_, size_, handle_ (and mapped_handle_ +// on Windows) either +// - all have default values (or INVALID_HANDLE_VALUE for +// Windows handles), or +// - all have values reflecting a successful mapping. +// In the first case, error_ may be true, reflecting a recent unsuccessful +// open or close attempt; in the second case, error_ is always false. +class mapped_file_impl { +public: + typedef mapped_file_source::size_type size_type; + typedef mapped_file_source::param_type param_type; + typedef mapped_file_source::mapmode mapmode; + BOOST_STATIC_CONSTANT( + size_type, max_length = mapped_file_source::max_length); + mapped_file_impl(); + ~mapped_file_impl(); + void open(param_type p); + bool is_open() const { return data_ != 0; } + void close(); + bool error() const { return error_; } + mapmode flags() const { return params_.flags; } + std::size_t size() const { return static_cast<std::size_t>(size_); } + char* data() const { return data_; } + void resize(stream_offset new_size); + static int alignment(); +private: + void open_file(param_type p); + void try_map_file(param_type p); + void map_file(param_type& p); + bool unmap_file(); + void clear(bool error); + void cleanup_and_throw(const char* msg); + param_type params_; + char* data_; + stream_offset size_; + file_handle handle_; +#ifdef BOOST_IOSTREAMS_WINDOWS + file_handle mapped_handle_; +#endif + bool error_; +}; + +mapped_file_impl::mapped_file_impl() { clear(false); } + +mapped_file_impl::~mapped_file_impl() +{ try { close(); } catch (...) { } } + +void mapped_file_impl::open(param_type p) +{ + if (is_open()) + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("file already open")); + p.normalize(); + open_file(p); + map_file(p); // May modify p.hint + params_ = p; +} + +void mapped_file_impl::close() +{ + if (data_ == 0) + return; + bool error = false; + error = !unmap_file() || error; + error = + #ifdef BOOST_IOSTREAMS_WINDOWS + !::CloseHandle(handle_) + #else + ::close(handle_) != 0 + #endif + || error; + clear(error); + if (error) + throw_system_failure("failed closing mapped file"); +} + +void mapped_file_impl::resize(stream_offset new_size) +{ + if (!is_open()) + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("file is closed")); + if (flags() & mapped_file::priv) + boost::throw_exception( + BOOST_IOSTREAMS_FAILURE("can't resize private mapped file") + ); + if (!(flags() & mapped_file::readwrite)) + boost::throw_exception( + BOOST_IOSTREAMS_FAILURE("can't resize readonly mapped file") + ); + if (params_.offset >= new_size) + boost::throw_exception( + BOOST_IOSTREAMS_FAILURE("can't resize below mapped offset") + ); + if (!unmap_file()) + cleanup_and_throw("failed unmapping file"); +#ifdef BOOST_IOSTREAMS_WINDOWS + stream_offset offset = ::SetFilePointer(handle_, 0, NULL, FILE_CURRENT); + if (offset == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR) + cleanup_and_throw("failed querying file pointer"); + LONG sizehigh = (new_size >> (sizeof(LONG) * 8)); + LONG sizelow = (new_size & 0xffffffff); + DWORD result = ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN); + if ((result == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR) + || !::SetEndOfFile(handle_)) + cleanup_and_throw("failed resizing mapped file"); + sizehigh = (offset >> (sizeof(LONG) * 8)); + sizelow = (offset & 0xffffffff); + ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN); +#else + if (BOOST_IOSTREAMS_FD_TRUNCATE(handle_, new_size) == -1) + cleanup_and_throw("failed resizing mapped file"); +#endif + size_ = new_size; + param_type p(params_); + map_file(p); // May modify p.hint + params_ = p; +} + +int mapped_file_impl::alignment() +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + SYSTEM_INFO info; + ::GetSystemInfo(&info); + return static_cast<int>(info.dwAllocationGranularity); +#else + return static_cast<int>(sysconf(_SC_PAGESIZE)); +#endif +} + +void mapped_file_impl::open_file(param_type p) +{ + bool readonly = p.flags != mapped_file::readwrite; +#ifdef BOOST_IOSTREAMS_WINDOWS + + // Open file + DWORD dwDesiredAccess = + readonly ? + GENERIC_READ : + (GENERIC_READ | GENERIC_WRITE); + DWORD dwCreationDisposition = (p.new_file_size != 0 && !readonly) ? + CREATE_ALWAYS : + OPEN_EXISTING; + DWORD dwFlagsandAttributes = + readonly ? + FILE_ATTRIBUTE_READONLY : + FILE_ATTRIBUTE_TEMPORARY; + handle_ = p.path.is_wide() ? + ::CreateFileW( + p.path.c_wstr(), + dwDesiredAccess, + FILE_SHARE_READ, + NULL, + dwCreationDisposition, + dwFlagsandAttributes, + NULL ) : + ::CreateFileA( + p.path.c_str(), + dwDesiredAccess, + FILE_SHARE_READ, + NULL, + dwCreationDisposition, + dwFlagsandAttributes, + NULL ); + if (handle_ == INVALID_HANDLE_VALUE) + cleanup_and_throw("failed opening file"); + + // Set file size + if (p.new_file_size != 0 && !readonly) { + LONG sizehigh = (p.new_file_size >> (sizeof(LONG) * 8)); + LONG sizelow = (p.new_file_size & 0xffffffff); + DWORD result = ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN); + if ((result == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR) + || !::SetEndOfFile(handle_)) + cleanup_and_throw("failed setting file size"); + } + + // Determine file size. Dynamically locate GetFileSizeEx for compatibility + // with old Platform SDK (thanks to Pavel Vozenilik). + typedef BOOL (WINAPI *func)(HANDLE, PLARGE_INTEGER); + HMODULE hmod = ::GetModuleHandleA("kernel32.dll"); + func get_size = + reinterpret_cast<func>(::GetProcAddress(hmod, "GetFileSizeEx")); + if (get_size) { + LARGE_INTEGER info; + if (get_size(handle_, &info)) { + boost::intmax_t size = + ( (static_cast<boost::intmax_t>(info.HighPart) << 32) | + info.LowPart ); + size_ = + static_cast<std::size_t>( + p.length != max_length ? + std::min<boost::intmax_t>(p.length, size) : + size + ); + } else { + cleanup_and_throw("failed querying file size"); + return; + } + } else { + DWORD hi; + DWORD low; + if ( (low = ::GetFileSize(handle_, &hi)) + != + INVALID_FILE_SIZE ) + { + boost::intmax_t size = + (static_cast<boost::intmax_t>(hi) << 32) | low; + size_ = + static_cast<std::size_t>( + p.length != max_length ? + std::min<boost::intmax_t>(p.length, size) : + size + ); + } else { + cleanup_and_throw("failed querying file size"); + return; + } + } +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + + // Open file + int flags = (readonly ? O_RDONLY : O_RDWR); + if (p.new_file_size != 0 && !readonly) + flags |= (O_CREAT | O_TRUNC); + #ifdef _LARGEFILE64_SOURCE + flags |= O_LARGEFILE; + #endif + errno = 0; + if (p.path.is_wide()) { errno = EINVAL; cleanup_and_throw("wide path not supported here"); } // happens on CYGWIN + handle_ = ::open(p.path.c_str(), flags, S_IRWXU); + if (errno != 0) + cleanup_and_throw("failed opening file"); + + //--------------Set file size---------------------------------------------// + + if (p.new_file_size != 0 && !readonly) + if (BOOST_IOSTREAMS_FD_TRUNCATE(handle_, p.new_file_size) == -1) + cleanup_and_throw("failed setting file size"); + + //--------------Determine file size---------------------------------------// + + bool success = true; + if (p.length != max_length) { + size_ = p.length; + } else { + struct BOOST_IOSTREAMS_FD_STAT info; + success = ::BOOST_IOSTREAMS_FD_FSTAT(handle_, &info) != -1; + size_ = info.st_size; + } + if (!success) + cleanup_and_throw("failed querying file size"); +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +void mapped_file_impl::try_map_file(param_type p) +{ + bool priv = p.flags == mapped_file::priv; + bool readonly = p.flags == mapped_file::readonly; +#ifdef BOOST_IOSTREAMS_WINDOWS + + // Create mapping + DWORD protect = priv ? + PAGE_WRITECOPY : + readonly ? + PAGE_READONLY : + PAGE_READWRITE; + mapped_handle_ = + ::CreateFileMappingA( + handle_, + NULL, + protect, + 0, + 0, + NULL ); + if (mapped_handle_ == NULL) + cleanup_and_throw("failed create mapping"); + + // Access data + DWORD access = priv ? + FILE_MAP_COPY : + readonly ? + FILE_MAP_READ : + FILE_MAP_WRITE; + void* data = + ::MapViewOfFileEx( + mapped_handle_, + access, + (DWORD) (p.offset >> 32), + (DWORD) (p.offset & 0xffffffff), + (SIZE_T) (numeric_cast<size_type>(size_) != max_length ? size_ : 0), + (LPVOID) p.hint ); + if (!data) + cleanup_and_throw("failed mapping view"); +#else + void* data = + ::BOOST_IOSTREAMS_FD_MMAP( + const_cast<char*>(p.hint), + size_, + readonly ? PROT_READ : (PROT_READ | PROT_WRITE), + priv ? MAP_PRIVATE : MAP_SHARED, + handle_, + p.offset ); + if (data == MAP_FAILED) + cleanup_and_throw("failed mapping file"); +#endif + data_ = static_cast<char*>(data); +} + +void mapped_file_impl::map_file(param_type& p) +{ + try { + try_map_file(p); + } catch (const std::exception&) { + if (p.hint) { + p.hint = 0; + try_map_file(p); + } else { + throw; + } + } +} + +bool mapped_file_impl::unmap_file() +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + bool error = false; + error = !::UnmapViewOfFile(data_) || error; + error = !::CloseHandle(mapped_handle_) || error; + mapped_handle_ = NULL; + return !error; +#else + return ::munmap(data_, size_) == 0; +#endif +} + +void mapped_file_impl::clear(bool error) +{ + params_ = param_type(); + data_ = 0; + size_ = 0; +#ifdef BOOST_IOSTREAMS_WINDOWS + handle_ = INVALID_HANDLE_VALUE; + mapped_handle_ = NULL; +#else + handle_ = 0; +#endif + error_ = error; +} + +// Called when an error is encountered during the execution of open_file or +// map_file +void mapped_file_impl::cleanup_and_throw(const char* msg) +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + DWORD error = GetLastError(); + if (mapped_handle_ != NULL) + ::CloseHandle(mapped_handle_); + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + SetLastError(error); +#else + int error = errno; + if (handle_ != 0) + ::close(handle_); + errno = error; +#endif + clear(true); + boost::iostreams::detail::throw_system_failure(msg); +} + +//------------------Implementation of mapped_file_params_base-----------------// + +void mapped_file_params_base::normalize() +{ + if (mode && flags) + boost::throw_exception(BOOST_IOSTREAMS_FAILURE( + "at most one of 'mode' and 'flags' may be specified" + )); + if (flags) { + switch (flags) { + case mapped_file::readonly: + case mapped_file::readwrite: + case mapped_file::priv: + break; + default: + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid flags")); + } + } else { + flags = (mode & BOOST_IOS::out) ? + mapped_file::readwrite : + mapped_file::readonly; + mode = BOOST_IOS::openmode(); + } + if (offset < 0) + boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid offset")); + if (new_file_size < 0) + boost::throw_exception( + BOOST_IOSTREAMS_FAILURE("invalid new file size") + ); +} + +} // End namespace detail. + +//------------------Implementation of mapped_file_source----------------------// + +mapped_file_source::mapped_file_source() + : pimpl_(new impl_type) + { } + +mapped_file_source::mapped_file_source(const mapped_file_source& other) + : pimpl_(other.pimpl_) + { } + +bool mapped_file_source::is_open() const +{ return pimpl_->is_open(); } + +void mapped_file_source::close() { pimpl_->close(); } + +// safe_bool is explicitly qualified below to please msvc 7.1 +mapped_file_source::operator mapped_file_source::safe_bool() const +{ return pimpl_->error() ? &safe_bool_helper::x : 0; } + +bool mapped_file_source::operator!() const +{ return pimpl_->error(); } + +mapped_file_source::mapmode mapped_file_source::flags() const +{ return pimpl_->flags(); } + +mapped_file_source::size_type mapped_file_source::size() const +{ return pimpl_->size(); } + +const char* mapped_file_source::data() const { return pimpl_->data(); } + +const char* mapped_file_source::begin() const { return data(); } + +const char* mapped_file_source::end() const { return data() + size(); } +int mapped_file_source::alignment() +{ return detail::mapped_file_impl::alignment(); } + +void mapped_file_source::init() { pimpl_.reset(new impl_type); } + +void mapped_file_source::open_impl(const param_type& p) +{ pimpl_->open(p); } + +//------------------Implementation of mapped_file-----------------------------// + +mapped_file::mapped_file(const mapped_file& other) + : delegate_(other.delegate_) + { } + +void mapped_file::resize(stream_offset new_size) +{ delegate_.pimpl_->resize(new_size); } + +//------------------Implementation of mapped_file_sink------------------------// + +mapped_file_sink::mapped_file_sink(const mapped_file_sink& other) + : mapped_file(static_cast<const mapped_file&>(other)) + { } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/src/zlib.cpp b/src/boost/libs/iostreams/src/zlib.cpp new file mode 100644 index 00000000..66380689 --- /dev/null +++ b/src/boost/libs/iostreams/src/zlib.cpp @@ -0,0 +1,188 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// To configure Boost to work with zlib, see the +// installation instructions here: +// http://boost.org/libs/iostreams/doc/index.html?path=7 + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <boost/throw_exception.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/filter/zlib.hpp> +#include "zlib.h" // Jean-loup Gailly's and Mark Adler's "zlib.h" header. + // To configure Boost to work with zlib, see the + // installation instructions here: + // http://boost.org/libs/iostreams/doc/index.html?path=7 + +namespace boost { namespace iostreams { + +namespace zlib { + + // Compression levels + +const int no_compression = Z_NO_COMPRESSION; +const int best_speed = Z_BEST_SPEED; +const int best_compression = Z_BEST_COMPRESSION; +const int default_compression = Z_DEFAULT_COMPRESSION; + + // Compression methods + +const int deflated = Z_DEFLATED; + + // Compression strategies + +const int default_strategy = Z_DEFAULT_STRATEGY; +const int filtered = Z_FILTERED; +const int huffman_only = Z_HUFFMAN_ONLY; + + // Status codes + +const int okay = Z_OK; +const int stream_end = Z_STREAM_END; +const int stream_error = Z_STREAM_ERROR; +const int version_error = Z_VERSION_ERROR; +const int data_error = Z_DATA_ERROR; +const int mem_error = Z_MEM_ERROR; +const int buf_error = Z_BUF_ERROR; + + // Flush codes + +const int finish = Z_FINISH; +const int no_flush = Z_NO_FLUSH; +const int sync_flush = Z_SYNC_FLUSH; + + // Code for current OS + +//const int os_code = OS_CODE; + +} // End namespace zlib. + +//------------------Implementation of zlib_error------------------------------// + +zlib_error::zlib_error(int error) + : BOOST_IOSTREAMS_FAILURE("zlib error"), error_(error) + { } + +void zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error) +{ + switch (error) { + case Z_OK: + case Z_STREAM_END: + //case Z_BUF_ERROR: + return; + case Z_MEM_ERROR: + boost::throw_exception(std::bad_alloc()); + default: + boost::throw_exception(zlib_error(error)); + ; + } +} + +//------------------Implementation of zlib_base-------------------------------// + +namespace detail { + +zlib_base::zlib_base() + : stream_(new z_stream), calculate_crc_(false), crc_(0), crc_imp_(0), + total_in_(0), total_out_(0) + { } + +zlib_base::~zlib_base() { delete static_cast<z_stream*>(stream_); } + +void zlib_base::before( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end ) +{ + z_stream* s = static_cast<z_stream*>(stream_); + s->next_in = reinterpret_cast<zlib::byte*>(const_cast<char*>(src_begin)); + s->avail_in = static_cast<zlib::uint>(src_end - src_begin); + s->next_out = reinterpret_cast<zlib::byte*>(dest_begin); + s->avail_out= static_cast<zlib::uint>(dest_end - dest_begin); +} + +void zlib_base::after(const char*& src_begin, char*& dest_begin, bool compress) +{ + z_stream* s = static_cast<z_stream*>(stream_); + const char* next_in = reinterpret_cast<const char*>(s->next_in); + char* next_out = reinterpret_cast<char*>(s->next_out); + if (calculate_crc_) { + const zlib::byte* buf = compress ? + reinterpret_cast<const zlib::byte*>(src_begin) : + reinterpret_cast<const zlib::byte*>( + const_cast<const char*>(dest_begin) + ); + zlib::uint length = compress ? + static_cast<zlib::uint>(next_in - src_begin) : + static_cast<zlib::uint>(next_out - dest_begin); + crc_ = crc_imp_ = crc32(crc_imp_, buf, length); + } + total_in_ = s->total_in; + total_out_ = s->total_out; + src_begin = next_in; + dest_begin = next_out; +} + +int zlib_base::xdeflate(int flush) +{ + return ::deflate(static_cast<z_stream*>(stream_), flush); +} + +int zlib_base::xinflate(int flush) +{ + return ::inflate(static_cast<z_stream*>(stream_), flush); +} + +void zlib_base::reset(bool compress, bool realloc) +{ + z_stream* s = static_cast<z_stream*>(stream_); + // Undiagnosed bug: + // deflateReset(), etc., return Z_DATA_ERROR + //zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + realloc ? + (compress ? deflateReset(s) : inflateReset(s)) : + (compress ? deflateEnd(s) : inflateEnd(s)) + ; + //); + crc_imp_ = 0; +} + +void zlib_base::do_init + ( const zlib_params& p, bool compress, + zlib::xalloc_func /* alloc */, zlib::xfree_func /* free*/, + void* derived ) +{ + calculate_crc_ = p.calculate_crc; + z_stream* s = static_cast<z_stream*>(stream_); + + // Current interface for customizing memory management + // is non-conforming and has been disabled: + // s->zalloc = alloc; + // s->zfree = free; + s->zalloc = 0; + s->zfree = 0; + s->opaque = derived; + int window_bits = p.noheader? -p.window_bits : p.window_bits; + zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + compress ? + deflateInit2( s, + p.level, + p.method, + window_bits, + p.mem_level, + p.strategy ) : + inflateInit2(s, window_bits) + ); +} + +} // End namespace detail. + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/src/zstd.cpp b/src/boost/libs/iostreams/src/zstd.cpp new file mode 100644 index 00000000..20cc0098 --- /dev/null +++ b/src/boost/libs/iostreams/src/zstd.cpp @@ -0,0 +1,166 @@ +// (C) Copyright Reimar Döffinger 2018. +// Based on zstd.cpp by: +// (C) Copyright Milan Svoboda 2008. +// (C) Copyright Jonathan Turkanis 2003. +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> +// knows that we are building the library (possibly exporting code), rather +// than using it (possibly importing code). +#define BOOST_IOSTREAMS_SOURCE + +#include <zstd.h> + +#include <boost/throw_exception.hpp> +#include <boost/iostreams/detail/config/dyn_link.hpp> +#include <boost/iostreams/filter/zstd.hpp> + +namespace boost { namespace iostreams { + +namespace zstd { + // Compression levels + +const uint32_t best_speed = 1; +const uint32_t best_compression = 19; +const uint32_t default_compression = 3; + + // Status codes + +const int okay = 0; +const int stream_end = 1; + + // Flush codes + +const int finish = 0; +const int flush = 1; +const int run = 2; +} // End namespace zstd. + +//------------------Implementation of zstd_error------------------------------// + +zstd_error::zstd_error(size_t error) + : BOOST_IOSTREAMS_FAILURE(ZSTD_getErrorName(error)), error_(error) + { } + +void zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(size_t error) +{ + if (ZSTD_isError(error)) + boost::throw_exception(zstd_error(error)); +} + +//------------------Implementation of zstd_base-------------------------------// + +namespace detail { + +zstd_base::zstd_base() + : cstream_(ZSTD_createCStream()), dstream_(ZSTD_createDStream()), in_(new ZSTD_inBuffer), out_(new ZSTD_outBuffer), eof_(0) + { } + +zstd_base::~zstd_base() +{ + ZSTD_freeCStream(static_cast<ZSTD_CStream *>(cstream_)); + ZSTD_freeDStream(static_cast<ZSTD_DStream *>(dstream_)); + delete static_cast<ZSTD_inBuffer*>(in_); + delete static_cast<ZSTD_outBuffer*>(out_); +} + +void zstd_base::before( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end ) +{ + ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); + ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); + in->src = src_begin; + in->size = static_cast<size_t>(src_end - src_begin); + in->pos = 0; + out->dst = dest_begin; + out->size = static_cast<size_t>(dest_end - dest_begin); + out->pos = 0; +} + +void zstd_base::after(const char*& src_begin, char*& dest_begin, bool) +{ + ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); + ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); + src_begin = reinterpret_cast<const char*>(in->src) + in->pos; + dest_begin = reinterpret_cast<char*>(out->dst) + out->pos; +} + +int zstd_base::deflate(int action) +{ + ZSTD_CStream *s = static_cast<ZSTD_CStream *>(cstream_); + ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); + ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); + // Ignore spurious extra calls. + // Note size > 0 will trigger an error in this case. + if (eof_ && in->size == 0) return zstd::stream_end; + size_t result = ZSTD_compressStream(s, out, in); + zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); + if (action != zstd::run) + { + result = action == zstd::finish ? ZSTD_endStream(s, out) : ZSTD_flushStream(s, out); + zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); + eof_ = action == zstd::finish && result == 0; + return result == 0 ? zstd::stream_end : zstd::okay; + } + return zstd::okay; +} + +int zstd_base::inflate(int action) +{ + ZSTD_DStream *s = static_cast<ZSTD_DStream *>(dstream_); + ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); + ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); + // need loop since iostream code cannot handle short reads + do { + size_t result = ZSTD_decompressStream(s, out, in); + zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result); + } while (in->pos < in->size && out->pos < out->size); + return action == zstd::finish && in->size == 0 && out->pos == 0 ? zstd::stream_end : zstd::okay; +} + +void zstd_base::reset(bool compress, bool realloc) +{ + ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); + ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); + if (realloc) + { + memset(in, 0, sizeof(*in)); + memset(out, 0, sizeof(*out)); + eof_ = 0; + + zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + compress ? + ZSTD_initCStream(static_cast<ZSTD_CStream *>(cstream_), level) : + ZSTD_initDStream(static_cast<ZSTD_DStream *>(dstream_)) + ); + } +} + +void zstd_base::do_init + ( const zstd_params& p, bool compress, + zstd::alloc_func, zstd::free_func, + void* ) +{ + ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_); + ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_); + + memset(in, 0, sizeof(*in)); + memset(out, 0, sizeof(*out)); + eof_ = 0; + + level = p.level; + zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION( + compress ? + ZSTD_initCStream(static_cast<ZSTD_CStream *>(cstream_), level) : + ZSTD_initDStream(static_cast<ZSTD_DStream *>(dstream_)) + ); +} + +} // End namespace detail. + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. diff --git a/src/boost/libs/iostreams/test/Jamfile.v2 b/src/boost/libs/iostreams/test/Jamfile.v2 new file mode 100644 index 00000000..e13ff8f9 --- /dev/null +++ b/src/boost/libs/iostreams/test/Jamfile.v2 @@ -0,0 +1,175 @@ +# Boost.Iostreams Library test Jamfile + +# (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +# (C) Copyright 2004-2007 Jonathan Turkanis +# 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.) + +# See http://www.boost.org/libs/iostreams for documentation. + +import stlport ; +import modules ; +import ac ; + +local NO_BZIP2 = [ modules.peek : NO_BZIP2 ] ; +local NO_ZLIB = [ modules.peek : NO_ZLIB ] ; +local NO_LZMA = [ modules.peek : NO_LZMA ] ; +local NO_ZSTD = [ modules.peek : NO_ZSTD ] ; +local LARGE_FILE_TEMP = [ modules.peek : LARGE_FILE_TEMP ] ; +local LARGE_FILE_KEEP = [ modules.peek : LARGE_FILE_KEEP ] ; + +rule test-iostreams ( sources * : requirements * : target-name ? ) { + return [ + run + $(sources) + /boost/test//boost_unit_test_framework/<link>static + /boost/filesystem//boost_filesystem/<link>static + : # command + : # input files + : # build requirements + <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE + <toolset>cw-9.3,<os>darwin:<runtime-link>static + <define>BOOST_IOSTREAMS_NO_LIB + <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1 + $(requirements) + : $(target-name) + ] ; +} + +rule compile-fail-iostreams ( sources * : requirements * : target-name ? ) { + return [ + compile-fail + $(sources) + /boost/test//boost_unit_test_framework/<link>static + /boost/filesystem//boost_filesystem/<link>static + : # build requirements + <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE + <toolset>cw-9.3,<os>darwin:<runtime-link>static + <define>BOOST_IOSTREAMS_NO_LIB + <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1 + $(requirements) + : $(target-name) + ] ; +} + + + local all-tests = + [ test-iostreams array_test.cpp ] + [ test-iostreams auto_close_test.cpp ] + [ test-iostreams buffer_size_test.cpp ] + [ test-iostreams close_test.cpp ] + [ test-iostreams + code_converter_test.cpp + detail/utf8_codecvt_facet.cpp ] + [ test-iostreams combine_test.cpp ] + [ test-iostreams compose_test.cpp ] + [ test-iostreams component_access_test.cpp ] + [ test-iostreams copy_test.cpp ] + [ test-iostreams counter_test.cpp ] + [ test-iostreams direct_adapter_test.cpp ] + [ test-iostreams dual_seekable_test.cpp ] + [ test-iostreams example_test.cpp ] + [ test-iostreams execute_test.cpp ] + [ test-iostreams file_test.cpp ] + [ test-iostreams file_descriptor_test.cpp + ../build//boost_iostreams ] + [ test-iostreams deprecated_file_descriptor_test.cpp + ../build//boost_iostreams + : <define>BOOST_IOSTREAMS_USE_DEPRECATED ] + [ compile-fail-iostreams deprecated_file_descriptor_test.cpp + : + : deprecated_file_descriptor_fail ] + [ test-iostreams filtering_stream_test.cpp ] + [ test-iostreams finite_state_filter_test.cpp ] + [ test-iostreams flush_test.cpp ] + [ test-iostreams + grep_test.cpp + /boost/regex//boost_regex ] + [ test-iostreams invert_test.cpp ] + [ test-iostreams line_filter_test.cpp ] + [ test-iostreams mapped_file_test.cpp + ../build//boost_iostreams ] + [ test-iostreams path_test.cpp ] + [ test-iostreams newline_test.cpp ] + [ test-iostreams null_test.cpp ] + [ test-iostreams operation_sequence_test.cpp ] + [ test-iostreams pipeline_test.cpp ] + [ test-iostreams read_nonblocking_test.cpp ] + [ test-iostreams + regex_filter_test.cpp + /boost/regex//boost_regex ] + [ test-iostreams restrict_test.cpp ] + [ test-iostreams seekable_file_test.cpp ] + [ test-iostreams seekable_filter_test.cpp ] + [ test-iostreams sequence_test.cpp ] + [ test-iostreams slice_test.cpp ] + [ test-iostreams stdio_filter_test.cpp ] + [ test-iostreams stream_offset_32bit_test.cpp ] + [ test-iostreams stream_offset_64bit_test.cpp ] + [ test-iostreams stream_state_test.cpp ] + [ test-iostreams symmetric_filter_test.cpp ] + [ test-iostreams tee_test.cpp ] + [ test-iostreams wide_stream_test.cpp ] + [ test-iostreams windows_pipe_test.cpp + ../build//boost_iostreams + : <build>no <target-os>windows:<build>yes ] + ; + + if $(LARGE_FILE_KEEP) + { + all-tests += + [ test-iostreams + large_file_test.cpp + ../src/file_descriptor.cpp + ../src/mapped_file.cpp + : <define>LARGE_FILE_KEEP=$(LARGE_FILE_KEEP) + <link>static ] ; + } + if $(LARGE_FILE_TEMP) + { + all-tests += + [ test-iostreams + large_file_test.cpp + ../src/file_descriptor.cpp + ../src/mapped_file.cpp + : <define>LARGE_FILE_TEMP=$(LARGE_FILE_TEMP) + <link>static ] ; + } + if ! $(NO_BZIP2) + { + all-tests += [ test-iostreams + bzip2_test.cpp ../build//boost_iostreams : + [ ac.check-library /bzip2//bzip2 : : <build>no ] ] ; + } + if ! $(NO_ZLIB) + { + all-tests += + [ test-iostreams + write_failure_test.cpp ../build//boost_iostreams : + [ ac.check-library /zlib//zlib : : <build>no ] ] + [ test-iostreams + gzip_test.cpp ../build//boost_iostreams : + [ ac.check-library /zlib//zlib : : <build>no ] ] + [ test-iostreams + zlib_test.cpp ../build//boost_iostreams : + [ ac.check-library /zlib//zlib : : <build>no ] ] ; + } + if ! $(NO_LZMA) + { + using lzma : : <build-name>boost_lzma <tag>@tag : : true ; + all-tests += [ test-iostreams + lzma_test.cpp ../build//boost_iostreams : + [ ac.check-library /lzma//lzma : : <build>no ] ] ; + } + if ! $(NO_ZSTD) + { + using zstd ; + all-tests += [ test-iostreams + zstd_test.cpp ../build//boost_iostreams : + [ ac.check-library /zstd//zstd : : <build>no ] ] ; + } + + test-suite "iostreams" : $(all-tests) ; + diff --git a/src/boost/libs/iostreams/test/array_test.cpp b/src/boost/libs/iostreams/test/array_test.cpp new file mode 100644 index 00000000..bd69f00c --- /dev/null +++ b/src/boost/libs/iostreams/test/array_test.cpp @@ -0,0 +1,99 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/detail/fstream.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using boost::unit_test::test_suite; + +void array_test() +{ + using namespace std; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + //--------------stream<array_source>-------------------------------// + + { + test_sequence<> seq; + stream<array_source> first(&seq[0], &seq[0] + seq.size()); + ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from stream<array_source> in chars" + ); + } + + { + test_sequence<> seq; + stream<array_source> first(&seq[0], &seq[0] + seq.size()); + ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from stream<array_source> in chunks" + ); + } + + //--------------stream<array_sink>---------------------------------// + + { + vector<char> first(data_reps * data_length(), '?'); + stream<array_sink> out(&first[0], &first[0] + first.size()); + write_data_in_chars(out); + ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to stream<array_sink> in chars" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + stream<array_sink> out(&first[0], &first[0] + first.size()); + write_data_in_chunks(out); + ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to stream<array_sink> in chunks" + ); + } + + //--------------random access---------------------------------------------// + + { + vector<char> first(data_reps * data_length(), '?'); + stream<boost::iostreams::array> io(&first[0], &first[0] + first.size()); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within stream<array>, in chars" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + stream<boost::iostreams::array> io(&first[0], &first[0] + first.size()); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within stream<array>, in chunks" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("array test"); + test->add(BOOST_TEST_CASE(&array_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/auto_close_test.cpp b/src/boost/libs/iostreams/test/auto_close_test.cpp new file mode 100644 index 00000000..fb680225 --- /dev/null +++ b/src/boost/libs/iostreams/test/auto_close_test.cpp @@ -0,0 +1,184 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cstdio> // EOF. +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +class closable_source : public source { +public: + closable_source() : open_(new bool(true)) { } + std::streamsize read(char*, std::streamsize) { return 0; } + void open() { *open_ = true; } + void close() { *open_ = false; } + bool is_open() const { return *open_; } +private: + boost::shared_ptr<bool> open_; +}; + +class closable_input_filter : public input_filter { +public: + closable_input_filter() : open_(new bool(true)) { } + + template<typename Source> + int get(Source&) { return EOF; } + + void open() { *open_ = true; } + + template<typename Source> + void close(Source&) { *open_ = false; } + + bool is_open() const { return *open_; } +private: + boost::shared_ptr<bool> open_; +}; + +void auto_close_source() +{ + // Rely on auto_close to close source. + closable_source src; + { + stream<closable_source> in(src); + BOOST_CHECK(src.is_open()); + BOOST_CHECK(in.auto_close()); + } + BOOST_CHECK(!src.is_open()); + + // Use close() to close components. + src.open(); + { + stream<closable_source> in(src); + BOOST_CHECK(src.is_open()); + BOOST_CHECK(in.auto_close()); + in.close(); + BOOST_CHECK(!src.is_open()); + } + + // Use close() to close components, with auto_close disabled. + src.open(); + { + stream<closable_source> in(src); + BOOST_CHECK(src.is_open()); + in.set_auto_close(false); + in.close(); + BOOST_CHECK(!src.is_open()); + } + + // Disable auto_close. + src.open(); + { + stream<closable_source> in(src); + BOOST_CHECK(src.is_open()); + in.set_auto_close(false); + BOOST_CHECK(!in.auto_close()); + } + BOOST_CHECK(src.is_open()); +} + +void auto_close_filter() +{ + closable_source src; + closable_input_filter flt; + + // Rely on auto_close to close components. + { + filtering_istream in; + in.push(flt); + in.push(src); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + BOOST_CHECK(in.auto_close()); + } + BOOST_CHECK(!flt.is_open()); + BOOST_CHECK(!src.is_open()); + + // Use reset() to close components. + flt.open(); + src.open(); + { + filtering_istream in; + in.push(flt); + in.push(src); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + BOOST_CHECK(in.auto_close()); + in.reset(); + BOOST_CHECK(!flt.is_open()); + BOOST_CHECK(!src.is_open()); + } + + // Use reset() to close components, with auto_close disabled. + flt.open(); + src.open(); + { + filtering_istream in; + in.push(flt); + in.push(src); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + in.set_auto_close(false); + in.reset(); + BOOST_CHECK(!flt.is_open()); + BOOST_CHECK(!src.is_open()); + } + + // Disable auto_close. + flt.open(); + src.open(); + { + filtering_istream in; + in.push(flt); + in.push(src); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + in.set_auto_close(false); + BOOST_CHECK(!in.auto_close()); + in.pop(); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + } + BOOST_CHECK(!flt.is_open()); + BOOST_CHECK(src.is_open()); + + // Disable auto_close; disconnect and reconnect resource. + flt.open(); + src.open(); + { + filtering_istream in; + in.push(flt); + in.push(src); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + in.set_auto_close(false); + BOOST_CHECK(!in.auto_close()); + in.pop(); + BOOST_CHECK(flt.is_open()); + BOOST_CHECK(src.is_open()); + in.push(src); + } + BOOST_CHECK(!flt.is_open()); + BOOST_CHECK(!src.is_open()); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("auto_close test"); + test->add(BOOST_TEST_CASE(&auto_close_source)); + test->add(BOOST_TEST_CASE(&auto_close_filter)); + return test; +} diff --git a/src/boost/libs/iostreams/test/bool_trait_test.cpp b/src/boost/libs/iostreams/test/bool_trait_test.cpp new file mode 100644 index 00000000..46bca21d --- /dev/null +++ b/src/boost/libs/iostreams/test/bool_trait_test.cpp @@ -0,0 +1,252 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Tests the boolean type traits defined in boost/iostreams/traits.hpp. + * + * File: libs/iostreams/test/bool_trait_test.cpp + * Date: Sun Feb 17 17:52:59 MST 2008 + * Copyright: 2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#include <fstream> +#include <sstream> +#include <boost/iostreams/detail/iostream.hpp> +#include <boost/iostreams/detail/streambuf/linked_streambuf.hpp> +#include <boost/iostreams/detail/iostream.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filtering_streambuf.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/iostreams/stream_buffer.hpp> +#include <boost/iostreams/traits.hpp> +#include <boost/test/unit_test.hpp> + +using namespace boost::iostreams; +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +typedef stream<array_source> array_istream; +typedef stream<warray_source> array_wistream; +typedef stream<array_sink> array_ostream; +typedef stream<warray_sink> array_wostream; +typedef stream<array> array_stream; +typedef stream<warray> array_wstream; +typedef stream_buffer<array> array_streambuf; +typedef stream_buffer<warray> array_wstreambuf; + +typedef io::filtering_stream<seekable> filtering_iostream; +typedef io::filtering_stream<seekable, wchar_t> filtering_wiostream; + +typedef io::detail::linked_streambuf<char> linkedbuf; +typedef io::detail::linked_streambuf<wchar_t> wlinkedbuf; + +#define BOOST_CHECK_BOOL_TRAIT(trait, type, status) \ + BOOST_CHECK(trait< type >::value == status) + /**/ + +#define BOOST_CHECK_STREAM_TRAIT( \ + trait, \ + istream_, wistream_, ostream_, wostream_, \ + iostream_, wiostream_, streambuf_, wstreambuf_, \ + ifstream_, wifstream_, ofstream_, wofstream_, \ + fstream_, wfstream_, filebuf_, wfilebuf_, \ + istringstream_, wistringstream_, ostringstream_, wostringstream_, \ + stringstream_, wstringstream_, stringbuf_, wstringbuf_, \ + array_istream_, array_wistream_, array_ostream_, array_wostream_, \ + array_stream_, array_wstream_, array_streambuf_, array_wstreambuf_, \ + filtering_istream_, filtering_wistream_, \ + filtering_ostream_, filtering_wostream_, \ + filtering_iostream_, filtering_wiostream_, \ + filtering_istreambuf_, filtering_wistreambuf_, \ + linkedbuf_, wlinkedbuf_ ) \ + BOOST_CHECK_BOOL_TRAIT(trait, std::istream, istream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wistream, wistream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::ostream, ostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wostream, wostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::iostream, iostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wiostream, wiostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::streambuf, streambuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wstreambuf, wstreambuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wifstream, wifstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::ofstream, ofstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wofstream, wofstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::fstream, fstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wfstream, wfstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::filebuf, filebuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wfilebuf, wfilebuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::istringstream, istringstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wistringstream, wistringstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::ostringstream, ostringstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wostringstream, wostringstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::stringstream, stringstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wstringstream, wstringstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::stringbuf, stringbuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, std::wstringbuf, wstringbuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_istream, array_istream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_wistream, array_wistream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_ostream, array_ostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_wostream, array_wostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_stream, array_stream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_wstream, array_wstream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_streambuf, array_streambuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, array_wstreambuf, array_wstreambuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_istream, filtering_istream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_wistream, filtering_wistream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_ostream, filtering_ostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_wostream, filtering_wostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, filtering_iostream, filtering_iostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, filtering_wiostream, filtering_wiostream_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_istreambuf, filtering_istreambuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_wistreambuf, filtering_wistreambuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, linkedbuf, linkedbuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, wlinkedbuf, wlinkedbuf_); \ + BOOST_CHECK_BOOL_TRAIT(trait, io::array, false); \ + BOOST_CHECK_BOOL_TRAIT(trait, int, false); + /**/ + +void bool_trait_test() +{ + // Test is_istream + BOOST_CHECK_STREAM_TRAIT( + io::is_istream, + true, true, false, false, true, true, false, false, + true, true, false, false, true, true, false, false, + true, true, false, false, true, true, false, false, + true, true, false, false, true, true, false, false, + true, true, false, false, true, true, false, false, + false, false + ); + + // Test is_ostream + BOOST_CHECK_STREAM_TRAIT( + io::is_ostream, + false, false, true, true, true, true, false, false, + false, false, true, true, true, true, false, false, + false, false, true, true, true, true, false, false, + false, false, true, true, true, true, false, false, + false, false, true, true, true, true, false, false, + false, false + ); + + // Test is_iostream + BOOST_CHECK_STREAM_TRAIT( + io::is_iostream, + false, false, false, false, true, true, false, false, + false, false, false, false, true, true, false, false, + false, false, false, false, true, true, false, false, + false, false, false, false, true, true, false, false, + false, false, false, false, true, true, false, false, + false, false + ); + + // Test is_streambuf + BOOST_CHECK_STREAM_TRAIT( + io::is_streambuf, + false, false, false, false, false, false, true, true, + false, false, false, false, false, false, true, true, + false, false, false, false, false, false, true, true, + false, false, false, false, false, false, true, true, + false, false, false, false, false, false, true, true, + true, true + ); + + // Test is_std_io + BOOST_CHECK_STREAM_TRAIT( + io::is_std_io, + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, + true, true + ); + + // Test is_std_file_device + BOOST_CHECK_STREAM_TRAIT( + io::is_std_file_device, + false, false, false, false, false, false, false, false, + true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false + ); + + // Test is_std_string_device + BOOST_CHECK_STREAM_TRAIT( + io::is_std_string_device, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false + ); + + // Test is_boost_stream + BOOST_CHECK_STREAM_TRAIT( + io::detail::is_boost_stream, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + true, true, true, true, true, true, false, false, + false, false, false, false, false, false, false, false, + false, false + ); + + // Test is_boost_stream_buffer + BOOST_CHECK_STREAM_TRAIT( + io::detail::is_boost_stream_buffer, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, true, true, + false, false, false, false, false, false, false, false, + false, false + ); + + // Test is_filtering_stream + BOOST_CHECK_STREAM_TRAIT( + io::detail::is_filtering_stream, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + true, true, true, true, true, true, false, false, + false, false + ); + + // Test is_filtering_streambuf + BOOST_CHECK_STREAM_TRAIT( + io::detail::is_filtering_streambuf, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, true, true, + false, false + ); + + // Test is_boost + BOOST_CHECK_STREAM_TRAIT( + io::detail::is_boost, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, + false, false + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("bool trait test"); + test->add(BOOST_TEST_CASE(&bool_trait_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/buffer_size_test.cpp b/src/boost/libs/iostreams/test/buffer_size_test.cpp new file mode 100644 index 00000000..83be295e --- /dev/null +++ b/src/boost/libs/iostreams/test/buffer_size_test.cpp @@ -0,0 +1,82 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include "detail/filters.hpp" // Must come before operations.hpp for VC6. +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/constants.hpp> +#include <boost/iostreams/device/null.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +using namespace std; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +struct optimally_buffered_filter { + typedef char char_type; + struct category + : input_filter_tag, + optimally_buffered_tag + { }; + std::streamsize optimal_buffer_size() const + { return default_filter_buffer_size + 1; } +}; + +void buffer_size_test() +{ + // Test device buffer sizes. + + BOOST_CHECK_MESSAGE( + optimal_buffer_size(null_source()) == default_device_buffer_size, + "wrong buffer size for sourcer" + ); + BOOST_CHECK_MESSAGE( + optimal_buffer_size(null_sink()) == default_device_buffer_size, + "wrong buffer size for sink" + ); + + // Test filter buffer sizes. + + BOOST_CHECK_MESSAGE( + optimal_buffer_size(toupper_filter()) == default_filter_buffer_size, + "wrong buffer size for input filter" + ); + BOOST_CHECK_MESSAGE( + optimal_buffer_size(tolower_filter()) == default_filter_buffer_size, + "wrong buffer size for output filter" + ); + BOOST_CHECK_MESSAGE( + optimal_buffer_size(toupper_multichar_filter()) + == + default_filter_buffer_size, + "wrong buffer size for multi-character input filter" + ); + BOOST_CHECK_MESSAGE( + optimal_buffer_size(tolower_multichar_filter()) + == + default_filter_buffer_size, + "wrong buffer size for multi-character output filter" + ); + + // Test custom buffer size. + + BOOST_CHECK_MESSAGE( + optimal_buffer_size(optimally_buffered_filter()) + == + optimally_buffered_filter().optimal_buffer_size(), + "wrong buffer size for multi-character output filter" + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("buffer_size test"); + test->add(BOOST_TEST_CASE(&buffer_size_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/bzip2_test.cpp b/src/boost/libs/iostreams/test/bzip2_test.cpp new file mode 100644 index 00000000..ceffeba7 --- /dev/null +++ b/src/boost/libs/iostreams/test/bzip2_test.cpp @@ -0,0 +1,98 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <string> +#include <boost/iostreams/filter/bzip2.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +struct bzip2_alloc : std::allocator<char> { }; + +void bzip2_test() +{ + text_sequence data; + BOOST_CHECK( + test_filter_pair( bzip2_compressor(), + bzip2_decompressor(), + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK( + test_filter_pair( basic_bzip2_compressor<bzip2_alloc>(), + basic_bzip2_decompressor<bzip2_alloc>(), + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK( + test_filter_pair( bzip2_compressor(), + bzip2_decompressor(), + std::string() ) + ); + { + filtering_istream strm; + strm.push( bzip2_compressor() ); + strm.push( null_source() ); + } + { + filtering_istream strm; + strm.push( bzip2_decompressor() ); + strm.push( null_source() ); + } +} + +void multiple_member_test() +{ + const int num_sequences = 10; + text_sequence data; + std::vector<char> temp, dest; + + // Write compressed data to temp, several times in succession + filtering_ostream out; + out.push(bzip2_compressor()); + for(int i = 0; i < num_sequences; ++i) + { + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + } + + // Read compressed data from temp into dest + filtering_istream in; + in.push(bzip2_decompressor()); + in.push(array_source(&temp[0], temp.size())); + io::copy(in, io::back_inserter(dest)); + + // Check that dest consists of as many copies of data as were provided + BOOST_REQUIRE_EQUAL(data.size() * num_sequences, dest.size()); + for(int i = 0; i < num_sequences; ++i) + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + i * dest.size() / num_sequences)); + + dest.clear(); + io::copy( + array_source(&temp[0], temp.size()), + io::compose(bzip2_decompressor(), io::back_inserter(dest))); + + // Check that dest consists of as many copies of data as were provided + BOOST_REQUIRE_EQUAL(data.size() * num_sequences, dest.size()); + for(int i = 0; i < num_sequences; ++i) + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + i * dest.size() / num_sequences)); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("bzip2 test"); + test->add(BOOST_TEST_CASE(&bzip2_test)); + test->add(BOOST_TEST_CASE(&multiple_member_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/close_test.cpp b/src/boost/libs/iostreams/test/close_test.cpp new file mode 100644 index 00000000..4c24057e --- /dev/null +++ b/src/boost/libs/iostreams/test/close_test.cpp @@ -0,0 +1,651 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Verifies that the close() member functions of filters and devices + * are called with the correct arguments in the correct order when + * used with chains and streams. + * + * File: libs/iostreams/test/close_test.cpp + * Date: Sun Dec 09 16:12:23 MST 2007 + * Copyright: 2007 CodeRage + * Author: Jonathan Turkanis + */ + +#include <boost/iostreams/chain.hpp> +#include <boost/iostreams/filtering_streambuf.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/operation_sequence.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +void input_chain_test() +{ + // Test input filter and device + { + operation_sequence seq; + filtering_streambuf<input> ch; + + // Test chain::pop() + ch.push(closable_filter<input>(seq.new_operation(2))); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test bidirectional filter and device + { + operation_sequence seq; + filtering_streambuf<input> ch; + + // Test chain::pop() + ch.push( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test seekable filter and device + { + operation_sequence seq; + filtering_streambuf<input> ch; + + // Test chain::pop() + ch.push(closable_filter<seekable>(seq.new_operation(1))); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test dual-user filter + { + operation_sequence seq; + filtering_streambuf<input> ch; + operation dummy; + + // Test chain::pop() + ch.push( + closable_filter<dual_use>( + seq.new_operation(2), + dummy + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct source + { + operation_sequence seq; + filtering_streambuf<input> ch; + + // Test chain::pop() + ch.push(closable_filter<input>(seq.new_operation(2))); + ch.push(closable_device<direct_input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<direct_input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<direct_input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct bidirectional device + { + operation_sequence seq; + filtering_streambuf<input> ch; + + // Test chain::pop() + ch.push(closable_filter<input>(seq.new_operation(2))); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(3) + ) + ); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(3) + ) + ); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(3) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct seekable device + { + operation_sequence seq; + filtering_streambuf<input> ch; + + // Test chain::pop() + ch.push(closable_filter<input>(seq.new_operation(1))); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void output_chain_test() +{ + // Test output filter and device + { + operation_sequence seq; + filtering_streambuf<output> ch; + + // Test chain::pop() + ch.push(closable_filter<output>(seq.new_operation(1))); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test bidirectional filter and device + { + operation_sequence seq; + filtering_streambuf<output> ch; + + // Test chain::pop() + ch.push( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test seekable filter and device + { + operation_sequence seq; + filtering_streambuf<output> ch; + + // Test chain::pop() + ch.push(closable_filter<seekable>(seq.new_operation(1))); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test dual-user filter + { + operation_sequence seq; + filtering_streambuf<output> ch; + operation dummy; + + // Test chain::pop() + ch.push( + closable_filter<dual_use>( + dummy, + seq.new_operation(1) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct sink + { + operation_sequence seq; + filtering_streambuf<output> ch; + + // Test chain::pop() + ch.push(closable_filter<output>(seq.new_operation(1))); + ch.push(closable_device<direct_output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<direct_output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<direct_output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct bidirectional device + { + operation_sequence seq; + filtering_streambuf<output> ch; + + // Test chain::pop() + ch.push(closable_filter<output>(seq.new_operation(2))); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(3) + ) + ); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(3) + ) + ); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(3) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct seekable device + { + operation_sequence seq; + filtering_streambuf<output> ch; + + // Test chain::pop() + ch.push(closable_filter<output>(seq.new_operation(1))); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void bidirectional_chain_test() +{ + // Test bidirectional filter and device + { + operation_sequence seq; + filtering_streambuf<bidirectional> ch; + + // Test chain::pop() + ch.push( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct bidirectional device + { + operation_sequence seq; + filtering_streambuf<bidirectional> ch; + + // Test chain::pop() + ch.push( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ) + ); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push( + closable_device<direct_bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void seekable_chain_test() +{ + // Test seekable filter and device + { + operation_sequence seq; + filtering_streambuf<seekable> ch; + + // Test chain::pop() + ch.push(closable_filter<seekable>(seq.new_operation(1))); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test direct seekable device + { + operation_sequence seq; + filtering_streambuf<seekable> ch; + + // Test chain::pop() + ch.push(closable_filter<seekable>(seq.new_operation(1))); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.pop()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and io::close() + seq.reset(); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(io::close(ch)); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + + // Test filter reuse and chain::reset() + seq.reset(); + ch.push(closable_device<direct_seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void stream_test() +{ + // Test source + { + operation_sequence seq; + stream< closable_device<input> > str; + str.open(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(str.close()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test sink + { + operation_sequence seq; + stream< closable_device<output> > str; + str.open(closable_device<output>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(str.close()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test bidirectional device + { + operation_sequence seq; + stream< closable_device<bidirectional> > str; + str.open( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(2) + ) + ); + BOOST_CHECK_NO_THROW(str.close()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test seekable device + { + operation_sequence seq; + stream< closable_device<seekable> > str; + str.open(closable_device<seekable>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(str.close()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("execute test"); + test->add(BOOST_TEST_CASE(&input_chain_test)); + test->add(BOOST_TEST_CASE(&output_chain_test)); + test->add(BOOST_TEST_CASE(&bidirectional_chain_test)); + test->add(BOOST_TEST_CASE(&seekable_chain_test)); + test->add(BOOST_TEST_CASE(&stream_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/code_converter_test.cpp b/src/boost/libs/iostreams/test/code_converter_test.cpp new file mode 100644 index 00000000..35554a10 --- /dev/null +++ b/src/boost/libs/iostreams/test/code_converter_test.cpp @@ -0,0 +1,387 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/detail/config/wide_streams.hpp> +#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS +# error wide streams not supported on this platform +#endif + +#include <algorithm> // equal. +#include <locale> +#include <string> +#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME. +#include <boost/iostreams/code_converter.hpp> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/detail/add_facet.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/detail/config/windows_posix.hpp> +#include <boost/iostreams/device/file.hpp> +#if !defined(__COMO__) || !defined(BOOST_COMO_STRICT) +# if defined(BOOST_IOSTREAMS_NO_LIB) || defined(BOOST_ALL_NO_LIB) +# include "../src/file_descriptor.cpp" +# else +# include <boost/iostreams/device/file_descriptor.hpp> +# endif +#endif +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/operation_sequence.hpp" +#include "detail/temp_file.hpp" + + // Include codevct facets + +#include "detail/null_padded_codecvt.hpp" +#include "detail/utf8_codecvt_facet.hpp" +#ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX +# include <codecvt/8859_1> +# include <codecvt/8859_10> +# include <codecvt/8859_13> +# include <codecvt/8859_14> +# include <codecvt/8859_15> +# include <codecvt/8859_16> +# include <codecvt/8859_2> +# include <codecvt/8859_3> +# include <codecvt/8859_4> +# include <codecvt/8859_5> +# include <codecvt/8859_6> +# include <codecvt/8859_7> +# include <codecvt/8859_8> +# include <codecvt/8859_9> +# include <codecvt/baltic> +# include <codecvt/big5> +# include <codecvt/cp037> +# include <codecvt/cp1006> +# include <codecvt/cp1026> +# include <codecvt/cp1250> +# include <codecvt/cp1251> +# include <codecvt/cp1252> +# include <codecvt/cp1253> +# include <codecvt/cp1254> +# include <codecvt/cp1255> +# include <codecvt/cp1256> +# include <codecvt/cp1257> +# include <codecvt/cp1258> +# include <codecvt/cp424> +# include <codecvt/cp437> +# include <codecvt/cp500> +# include <codecvt/cp737> +# include <codecvt/cp775> +# include <codecvt/cp850> +# include <codecvt/cp852> +# include <codecvt/cp855> +# include <codecvt/cp856> +# include <codecvt/cp857> +# include <codecvt/cp860> +# include <codecvt/cp861> +# include <codecvt/cp862> +# include <codecvt/cp863> +# include <codecvt/cp864> +# include <codecvt/cp865> +# include <codecvt/cp866> +# include <codecvt/cp869> +# include <codecvt/cp874> +# include <codecvt/cp875> +# include <codecvt/cp932> +# include <codecvt/cp936> +# include <codecvt/cp949> +# include <codecvt/cp950> +# include <codecvt/cyrillic> +# include <codecvt/ebcdic> +# include <codecvt/euc> +# include <codecvt/euc_0208> +# include <codecvt/gb12345> +# include <codecvt/gb2312> +# include <codecvt/greek> +# include <codecvt/iceland> +# include <codecvt/jis> +# include <codecvt/jis_0208> +# include <codecvt/jis0201> +# include <codecvt/ksc5601> +# include <codecvt/latin2> +# include <codecvt/one_one> +# include <codecvt/roman> +# include <codecvt/sjis> +# include <codecvt/sjis_0208> +# include <codecvt/turkish> +# include <codecvt/utf16> +# include <codecvt/utf8> +# include <codecvt/utf8_utf16> +# include <codecvt/xjis> +#endif // #ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX] + +#include <iostream> + +using namespace std; +using namespace boost::iostreams; +using namespace boost::iostreams::detail; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +const int max_length = 30; +const unsigned int pattern_length = 100; +const unsigned int pattern_reps = 100; + +template<typename Codecvt> +bool valid_char(typename codecvt_intern<Codecvt>::type c) +{ + typedef typename codecvt_state<Codecvt>::type state_type; + typedef typename codecvt_intern<Codecvt>::type intern_type; + Codecvt cvt; + state_type state = state_type(); + const intern_type* nint; + char* next; + char buf[max_length]; + + return cvt.out( state, &c, &c + 1, nint, + buf, buf + max_length, next ) + == + codecvt_base::ok; +} + +template<typename Codecvt> +basic_string< + BOOST_DEDUCED_TYPENAME + codecvt_intern<Codecvt>::type +> +test_string() +{ + typedef typename codecvt_intern<Codecvt>::type intern_type; + std::basic_string<intern_type> pattern, result; + for (intern_type c = 255; pattern.size() < pattern_length; --c) + if (valid_char<Codecvt>(c)) + pattern += c; + result.reserve(pattern.size() * pattern_reps); + for (unsigned int w = 0; w < pattern_reps; ++w) + result += pattern; + return result; +} + +// Como can't compile file_descriptor.cpp in strict mode; this failure +// is detected by file_descriptor_test.cpp. +#if !defined(__COMO__) || !defined(BOOST_COMO_STRICT) + typedef io::file_descriptor_source classic_file_source; + typedef io::file_descriptor_sink classic_file_sink; +#else + struct classic_file_source : io::source { + classic_file_source(const std::string& path) + : file_(new filebuf) + { + file_->pubimbue(locale::classic()); + file_->open(path.c_str(), BOOST_IOS::in | BOOST_IOS::binary); + } + streamsize read(char* s, streamsize n) { return file_->sgetn(s, n); } + boost::shared_ptr<filebuf> file_; + }; + + struct classic_file_sink : io::sink { + classic_file_sink(const std::string& path) + : file_(new filebuf) + { + file_->pubimbue(locale::classic()); + file_->open(path.c_str(), BOOST_IOS::out | BOOST_IOS::binary); + } + streamsize write(const char* s, streamsize n) { return file_->sputn(s, n); } + boost::shared_ptr<filebuf> file_; + }; +#endif + +template<typename Codecvt> +bool codecvt_test1() +{ + typedef basic_string< + BOOST_DEDUCED_TYPENAME + codecvt_intern<Codecvt>::type + > string_type; + typedef code_converter<classic_file_source, Codecvt> wide_file_source; + typedef code_converter<classic_file_sink, Codecvt> wide_file_sink; + + BOOST_CHECK(Codecvt().max_length() <= max_length); + temp_file temp; + string_type test = test_string<Codecvt>(); + stream<wide_file_sink> out(temp.name()); + out.write(test.data(), static_cast<streamsize>(test.size())); + out.close(); + + stream<wide_file_source> in(temp.name()); + string_type test2; + io::copy(in, io::back_inserter(test2)); + + return test == test2; +} + +template<typename Codecvt> +bool codecvt_test2() +{ + typedef basic_string< + BOOST_DEDUCED_TYPENAME + codecvt_intern<Codecvt>::type + > string_type; + typedef code_converter<classic_file_source> wide_file_source; + typedef code_converter<classic_file_sink> wide_file_sink; + + // Set global locale. + locale loc = add_facet(locale(), new Codecvt); + locale::global(loc); + + temp_file temp; + string_type test = test_string<Codecvt>(); + stream<wide_file_sink> out(temp.name()); + out.write(test.data(), static_cast<streamsize>(test.size())); + out.close(); + + stream<wide_file_source> in(temp.name()); + string_type test2; + io::copy(in, io::back_inserter(test2)); + + return test == test2; +} + +template<typename Codecvt> +bool codecvt_test() +{ + return codecvt_test1<Codecvt>() && codecvt_test2<Codecvt>(); +} + +void code_converter_test() +{ + BOOST_CHECK((codecvt_test<utf8_codecvt_facet<wchar_t, char> >())); + BOOST_CHECK(codecvt_test<null_padded_codecvt>()); + BOOST_CHECK(codecvt_test<stateless_null_padded_codecvt>()); +#ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX + using namespace Dinkum::conversions; + BOOST_CHECK(codecvt_test< codecvt_8859_1<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_10<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_13<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_14<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_15<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_16<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_2<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_3<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_4<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_5<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_6<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_7<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_8<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_8859_9<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_baltic<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_big5<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp037<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1006<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1026<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1250<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1251<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1252<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1253<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1254<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1255<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1256<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1257<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp1258<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp424<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp437<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp500<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp737<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp775<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp850<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp852<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp855<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp856<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp857<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp860<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp861<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp862<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp863<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp864<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp865<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp866<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp869<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp874<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp875<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp932<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp936<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp949<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cp950<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_cyrillic<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_ebcdic<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_euc<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_euc_0208<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_gb12345<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_gb2312<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_greek<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_iceland<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_jis<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_jis_0208<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_jis0201<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_ksc5601<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_latin2<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_one_one<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_roman<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_sjis<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_sjis_0208<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_turkish<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_utf16<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_utf8<wchar_t> >()); + BOOST_CHECK(codecvt_test< codecvt_utf8_utf16<wchar_t> >()); +#endif +} + +/* Defer pending further testing +void close_test() +{ + typedef utf8_codecvt_facet<wchar_t, char> codecvt_type; + + // Test code converter based on a source + { + operation_sequence seq; + io::wchain<input> ch; + ch.push( + code_converter<closable_device<input>, codecvt_type>( + seq.new_operation(1) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test code converter based on a sink + { + operation_sequence seq; + io::wchain<output> ch; + ch.push( + code_converter<closable_device<output>, codecvt_type>( + seq.new_operation(1) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test code converter based on a bidirectional device + { + operation_sequence seq; + io::wchain<bidirectional> ch; + ch.push( + code_converter<closable_device<bidirectional>, codecvt_type>( + seq.new_operation(1), + seq.new_operation(2) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +}*/ + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("code_converter test"); + test->add(BOOST_TEST_CASE(&code_converter_test)); + //test->add(BOOST_TEST_CASE(&close_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/combine_test.cpp b/src/boost/libs/iostreams/test/combine_test.cpp new file mode 100644 index 00000000..e22f4d59 --- /dev/null +++ b/src/boost/libs/iostreams/test/combine_test.cpp @@ -0,0 +1,227 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Verifies that the close() member functions of filters and devices + * are called with the correct arguments in the correct order when + * they are combined using combine(). + * + * File: libs/iostreams/test/combine_test.cpp + * Date: Sun Jan 06 01:37:37 MST 2008 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#include <boost/iostreams/chain.hpp> +#include <boost/iostreams/combine.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/operation_sequence.hpp" + +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +void combine_test() +{ + // Combine a source and a sink + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::combine( + closable_device<input>(seq.new_operation(1)), + closable_device<output>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine two bidirectional devices + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::combine( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(2) + ), + closable_device<bidirectional>( + seq.new_operation(3), + seq.new_operation(4) + ) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine two seekable devices + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::combine( + closable_device<seekable>(seq.new_operation(1)), + closable_device<seekable>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine an input filter and an output filter + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::combine( + closable_filter<input>(seq.new_operation(2)), + closable_filter<output>(seq.new_operation(3)) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine two bidirectional filters + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::combine( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ), + closable_filter<bidirectional>( + seq.new_operation(4), + seq.new_operation(5) + ) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(6) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine two seekable filters + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::combine( + closable_filter<seekable>(seq.new_operation(2)), + closable_filter<seekable>(seq.new_operation(3)) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine a dual-use filter and an input filter + { + operation_sequence seq; + chain<bidirectional> ch; + operation dummy; + ch.push( + io::combine( + closable_filter<input>(seq.new_operation(2)), + closable_filter<dual_use>( + dummy, + seq.new_operation(3) + ) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine a dual-use filter and an output filter + { + operation_sequence seq; + chain<bidirectional> ch; + operation dummy; + ch.push( + io::combine( + closable_filter<dual_use>( + seq.new_operation(2), + dummy + ), + closable_filter<output>(seq.new_operation(3)) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Combine two dual-use filters + { + operation_sequence seq; + chain<bidirectional> ch; + operation dummy; + ch.push( + io::combine( + closable_filter<dual_use>( + seq.new_operation(2), + dummy + ), + closable_filter<dual_use>( + dummy, + seq.new_operation(3) + ) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("combine test"); + test->add(BOOST_TEST_CASE(&combine_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/component_access_test.cpp b/src/boost/libs/iostreams/test/component_access_test.cpp new file mode 100644 index 00000000..47c4317a --- /dev/null +++ b/src/boost/libs/iostreams/test/component_access_test.cpp @@ -0,0 +1,173 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <stdexcept> // out_of_range. +#include <utility> // pair. +#include <boost/config.hpp> // BOOST_MSVC. +#include <boost/detail/workaround.hpp> +#include <boost/core/typeinfo.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/iostreams/stream_buffer.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/constants.hpp" +#include "detail/filters.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +#define COMPARE_TYPE_ID(x, y) BOOST_IOSTREAMS_COMPARE_TYPE_ID(x, y) + +struct indirect_source : io::source { + void foo() { } + std::streamsize read(char*, std::streamsize) { return 0; } +}; + +struct direct_source { + typedef char char_type; + struct category + : io::input, io::device_tag, io::direct_tag + { }; + void foo() { } + std::pair<char*, char*> input_sequence() + { + return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0));; + } +}; + +void compile_time_test() +{ + using namespace io; + + stream_buffer<indirect_source> indirect_buf; + indirect_buf.open(indirect_source()); + indirect_buf->foo(); + + stream_buffer<direct_source> direct_buf; + direct_buf.open(direct_source()); + direct_buf->foo(); + + stream<indirect_source> indirect_stream; + indirect_stream.open(indirect_source()); + indirect_stream->foo(); + + stream<direct_source> direct_stream; + direct_stream.open(direct_source()); + direct_stream->foo(); +} + +void component_type_test() +{ + using namespace std; + using namespace io; + using namespace boost::iostreams::test; + + temp_file dest; + lowercase_file lower; + + filtering_ostream out; + out.push(tolower_filter()); + out.push(tolower_multichar_filter()); + out.push(file_sink(dest.name(), out_mode)); + + // Check index 0. + BOOST_CHECK(COMPARE_TYPE_ID( + out.component_type(0), + BOOST_CORE_TYPEID(tolower_filter) + )); + BOOST_CHECK(COMPARE_TYPE_ID( + BOOST_IOSTREAMS_COMPONENT_TYPE(out, 0), + BOOST_CORE_TYPEID(tolower_filter) + )); + BOOST_CHECK_NO_THROW(( + BOOST_IOSTREAMS_COMPONENT(out, 0, tolower_filter) + )); +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + BOOST_CHECK_NO_THROW(( + out.component<tolower_filter>(0) + )); + BOOST_CHECK_NO_THROW(( + out.component<0, tolower_filter>() + )); +#endif + + // Check index 1. + BOOST_CHECK(COMPARE_TYPE_ID( + out.component_type(1), + BOOST_CORE_TYPEID(tolower_multichar_filter) + )); + BOOST_CHECK(COMPARE_TYPE_ID( + BOOST_IOSTREAMS_COMPONENT_TYPE(out, 1), + BOOST_CORE_TYPEID(tolower_multichar_filter) + )); + BOOST_CHECK_NO_THROW(( + BOOST_IOSTREAMS_COMPONENT(out, 1, tolower_multichar_filter) + )); +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + BOOST_CHECK_NO_THROW(( + out.component<tolower_multichar_filter>(1) + )); + BOOST_CHECK_NO_THROW(( + out.component<1, tolower_multichar_filter>() + )); +#endif + + // Check index 2. + BOOST_CHECK(COMPARE_TYPE_ID( + out.component_type(2), + BOOST_CORE_TYPEID(file_sink) + )); + BOOST_CHECK(COMPARE_TYPE_ID( + BOOST_IOSTREAMS_COMPONENT_TYPE(out, 2), + BOOST_CORE_TYPEID(file_sink) + )); + BOOST_CHECK_NO_THROW(( + BOOST_IOSTREAMS_COMPONENT(out, 2, file_sink) + )); +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + BOOST_CHECK_NO_THROW(( + out.component<file_sink>(2) + )); + BOOST_CHECK_NO_THROW(( + out.component<2, file_sink>() + )); +#endif + + // Check index 3. + BOOST_CHECK_THROW( + out.component_type(3), + std::out_of_range + ); + BOOST_CHECK_THROW( + BOOST_IOSTREAMS_COMPONENT_TYPE(out, 3), + std::out_of_range + ); + + // Check components. + + filtering_ostream out2; + out2.push(*(BOOST_IOSTREAMS_COMPONENT(out, 0, tolower_filter))); + out2.push(*(BOOST_IOSTREAMS_COMPONENT(out, 1, tolower_multichar_filter))); + out2.push(*(BOOST_IOSTREAMS_COMPONENT(out, 2, file_sink))); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed accessing components of chain" + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("component_type test"); + test->add(BOOST_TEST_CASE(&component_type_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/compose_test.cpp b/src/boost/libs/iostreams/test/compose_test.cpp new file mode 100644 index 00000000..9d26d48a --- /dev/null +++ b/src/boost/libs/iostreams/test/compose_test.cpp @@ -0,0 +1,504 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cctype> +#include <boost/iostreams/compose.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/operation_sequence.hpp" +#include "detail/filters.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x. + +using namespace std; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +void read_composite() +{ + test_file src1, src2; + filtering_istream first, second; + + // Test composite device + first.push(toupper_filter()); + first.push(padding_filter('a')); + first.push(file_source(src1.name(), in_mode)); + second.push( compose( toupper_filter(), + compose( padding_filter('a'), + file_source(src1.name(), in_mode) ) ) ); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a stdio_filter" + ); + + // Test composite filter + first.reset(); + second.reset(); + first.push(toupper_filter()); + first.push(padding_filter('a')); + first.push(file_source(src1.name(), in_mode)); + second.push( compose( compose( toupper_filter(), + padding_filter('a') ), + file_source(src1.name(), in_mode) ) ); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a stdio_filter" + ); +} + +void write_composite() +{ + temp_file dest1, dest2; + filtering_ostream out1, out2; + + // Test composite device + out1.push(tolower_filter()); + out1.push(padding_filter('a')); + out1.push(file_sink(dest1.name(), in_mode)); + out2.push( compose( tolower_filter(), + compose( padding_filter('a'), + file_sink(dest2.name(), in_mode) ) ) ); + write_data_in_chunks(out1); + write_data_in_chunks(out2); + out1.reset(); + out2.reset(); + + { + ifstream first(dest1.name().c_str()); + ifstream second(dest2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to a stdio_filter" + ); + } + + // Test composite filter + out1.push(tolower_filter()); + out1.push(padding_filter('a')); + out1.push(file_sink(dest1.name(), in_mode)); + out2.push( compose( compose( tolower_filter(), + padding_filter('a') ), + file_sink(dest2.name(), in_mode) ) ); + write_data_in_chunks(out1); + write_data_in_chunks(out2); + out1.reset(); + out2.reset(); + + { + ifstream first(dest1.name().c_str()); + ifstream second(dest2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to a stdio_filter" + ); + } +} + +void close_composite_device() +{ + // Compose an input filter with a source + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::compose( + closable_filter<input>(seq.new_operation(2)), + closable_device<input>(seq.new_operation(1)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a bidirectional filter with a source + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::compose( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ), + closable_device<input>(seq.new_operation(1)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a seekable filter with a source + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::compose( + closable_filter<seekable>(seq.new_operation(2)), + closable_device<input>(seq.new_operation(1)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a dual-use filter with a source + { + operation_sequence seq; + chain<input> ch; + operation dummy; + ch.push( + io::compose( + closable_filter<dual_use>( + seq.new_operation(2), + dummy + ), + closable_device<input>(seq.new_operation(1)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose an output filter with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::compose( + closable_filter<output>(seq.new_operation(1)), + closable_device<output>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a bidirectional filter with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::compose( + closable_filter<bidirectional>( + seq.new_operation(1), + seq.new_operation(2) + ), + closable_device<output>(seq.new_operation(3)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a seekable filter with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::compose( + closable_filter<seekable>(seq.new_operation(1)), + closable_device<output>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a dual-use filter with a sink + { + operation_sequence seq; + chain<output> ch; + operation dummy; + ch.push( + io::compose( + closable_filter<dual_use>( + dummy, + seq.new_operation(1) + ), + closable_device<output>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a bidirectional filter with a bidirectional device + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::compose( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ), + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a seekable filter with a seekable device + { + operation_sequence seq; + chain<seekable> ch; + ch.push( + io::compose( + closable_filter<seekable>(seq.new_operation(1)), + closable_device<seekable>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void close_composite_filter() +{ + // Compose two input filters + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::compose( + closable_filter<input>(seq.new_operation(3)), + closable_filter<input>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a bidirectional filter with an input filter + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::compose( + closable_filter<bidirectional>( + seq.new_operation(3), + seq.new_operation(4) + ), + closable_filter<input>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_MESSAGE(seq.is_success(), seq.message()); + } + + // Compose a seekable filter with an input filter + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::compose( + closable_filter<seekable>(seq.new_operation(3)), + closable_filter<input>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a dual-use filter with an input filter + { + operation_sequence seq; + chain<input> ch; + operation dummy; + ch.push( + io::compose( + closable_filter<dual_use>( + seq.new_operation(3), + dummy + ), + closable_filter<input>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose two output filters + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::compose( + closable_filter<output>(seq.new_operation(1)), + closable_filter<output>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a bidirectional filter with an output filter + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::compose( + closable_filter<bidirectional>( + seq.new_operation(1), + seq.new_operation(2) + ), + closable_filter<output>(seq.new_operation(3)) + ) + ); + ch.push(closable_device<output>(seq.new_operation(4))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a seekable filter with an output filter + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::compose( + closable_filter<seekable>(seq.new_operation(1)), + closable_filter<output>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose a dual-use filter with an output filter + { + operation_sequence seq; + chain<output> ch; + operation dummy; + ch.push( + io::compose( + closable_filter<dual_use>( + dummy, + seq.new_operation(1) + ), + closable_filter<output>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose two bidirectional filters + { + operation_sequence seq; + chain<bidirectional> ch; + ch.push( + io::compose( + closable_filter<bidirectional>( + seq.new_operation(3), + seq.new_operation(4) + ), + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(5) + ) + ) + ); + ch.push( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(6) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose two seekable filters + { + operation_sequence seq; + chain<seekable> ch; + ch.push( + io::compose( + closable_filter<seekable>(seq.new_operation(1)), + closable_filter<seekable>(seq.new_operation(2)) + ) + ); + ch.push(closable_device<seekable>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose two dual-use filters for input + { + operation_sequence seq; + chain<input> ch; + operation dummy; + ch.push( + io::compose( + closable_filter<dual_use>( + seq.new_operation(3), + dummy + ), + closable_filter<dual_use>( + seq.new_operation(2), + dummy + ) + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Compose two dual-use filters for output + { + operation_sequence seq; + chain<output> ch; + operation dummy; + ch.push( + io::compose( + closable_filter<dual_use>( + dummy, + seq.new_operation(1) + ), + closable_filter<dual_use>( + dummy, + seq.new_operation(2) + ) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("line_filter test"); + test->add(BOOST_TEST_CASE(&read_composite)); + test->add(BOOST_TEST_CASE(&write_composite)); + test->add(BOOST_TEST_CASE(&close_composite_device)); + test->add(BOOST_TEST_CASE(&close_composite_filter)); + return test; +} + +#include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x. diff --git a/src/boost/libs/iostreams/test/copy_test.cpp b/src/boost/libs/iostreams/test/copy_test.cpp new file mode 100644 index 00000000..84dda9f5 --- /dev/null +++ b/src/boost/libs/iostreams/test/copy_test.cpp @@ -0,0 +1,172 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <algorithm> // Equal +#include <vector> +#include <boost/config.hpp> // MSVC. +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/concepts.hpp> // sink +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "../example/container_device.hpp" +#include "detail/sequence.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::example; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +//------------------Definition of fixed_sink----------------------------------// + +/*class fixed_sink : public sink { +public: + fixed_sink(vector<char>& storage) + : storage_(storage), pos_(0) + { } + std::streamsize write(const char_type* s, std::streamsize n) + { + streamsize capacity = static_cast<streamsize>(storage_.size() - pos_); + streamsize result = (min)(n, capacity); + std::copy(s, s + result, storage_.begin() + pos_); + pos_ += result; + return result; + } +private: + fixed_sink operator=(const fixed_sink&); + typedef vector<char>::size_type size_type; + vector<char>& storage_; + size_type pos_; +};*/ + +//------------------Definition of stream types--------------------------------// + +typedef container_source< vector<char> > vector_source; +typedef container_sink< vector<char> > vector_sink; +typedef stream<vector_source> vector_istream; +typedef stream<vector_sink> vector_ostream; +//typedef stream<fixed_sink> fixed_ostream; + +//------------------Definition of copy_test-----------------------------------// + +void copy_test() +{ + // Stream to stream + { + test_sequence<> src; + vector<char> dest; + vector_istream first; + vector_ostream second; + first.open(vector_source(src)); + second.open(vector_sink(dest)); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(first, second) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from stream to stream" + ); + } + + // Stream to indirect sink + { + test_sequence<> src; + vector<char> dest; + vector_istream in; + vector_sink out(dest); + in.open(vector_source(src)); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(in, out) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from stream to indirect sink" + ); + } + + // Indirect source to stream + { + test_sequence<> src; + vector<char> dest; + vector_source in(src); + vector_ostream out; + out.open(vector_sink(dest)); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(in, out) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from indirect source to stream" + ); + } + + // Indirect source to indirect sink + { + test_sequence<> src; + vector<char> dest; + vector_source in(src); + vector_sink out(dest); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(in, out) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from indirect source to indirect sink" + ); + } + + // Direct source to direct sink + { + test_sequence<> src; + vector<char> dest(src.size(), '?'); + array_source in(&src[0], &src[0] + src.size()); + array_sink out(&dest[0], &dest[0] + dest.size()); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(in, out) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from direct source to direct sink" + ); + } + + // Direct source to indirect sink + { + test_sequence<> src; + vector<char> dest; + array_source in(&src[0], &src[0] + src.size()); + vector_ostream out(dest); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(in, out) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from direct source to indirect sink" + ); + } + + // Indirect source to direct sink + { + test_sequence<> src; + vector<char> dest(src.size(), '?'); + vector_istream in; + array_sink out(&dest[0], &dest[0] + dest.size()); + in.open(vector_source(src)); + BOOST_CHECK_MESSAGE( + boost::iostreams::copy(in, out) == + static_cast<streamsize>(src.size()) && + src == dest, + "failed copying from indirect source to direct sink" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("copy test"); + test->add(BOOST_TEST_CASE(©_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/counter_test.cpp b/src/boost/libs/iostreams/test/counter_test.cpp new file mode 100644 index 00000000..091dfe9f --- /dev/null +++ b/src/boost/libs/iostreams/test/counter_test.cpp @@ -0,0 +1,98 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cctype> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/device/null.hpp> +#include <boost/iostreams/filter/counter.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/constants.hpp" +#include "detail/filters.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void read_counter() +{ + test_file src; + filtering_istream in; + in.push(counter()); + in.push(padding_filter('a'), 0); + in.push(counter()); + in.push(file_source(src.name(), in_mode)); + + counter* first_counter = BOOST_IOSTREAMS_COMPONENT(in, 0, counter); + counter* second_counter = BOOST_IOSTREAMS_COMPONENT(in, 2, counter); + int first_count = 0; + int second_count = 0; + int line_count = 0; + int reps = data_reps < 50 ? data_reps : 25; // Keep test short. + for (int w = 0; w < reps; ++w) { + int len = data_length(); + for (int z = 0; z < len; ++z) { + in.get(); + ++first_count; + ++second_count; + BOOST_CHECK(first_counter->characters() == first_count); + BOOST_CHECK(second_counter->characters() == second_count); + in.get(); + ++first_count; + BOOST_CHECK(first_counter->characters() == first_count); + BOOST_CHECK(second_counter->characters() == second_count); + } + ++line_count; + BOOST_CHECK(first_counter->lines() == line_count); + BOOST_CHECK(first_counter->lines() == line_count); + } +} + +void write_counter() +{ + filtering_ostream out; + out.push(counter()); + out.push(padding_filter('a'), 0); + out.push(counter()); + out.push(null_sink()); + + counter* first_counter = BOOST_IOSTREAMS_COMPONENT(out, 0, counter); + counter* second_counter = BOOST_IOSTREAMS_COMPONENT(out, 2, counter); + int first_count = 0; + int second_count = 0; + int line_count = 0; + int reps = data_reps < 50 ? data_reps : 25; // Keep test short. + const char* data = narrow_data(); + for (int w = 0; w < reps; ++w) { + int len = data_length(); + for (int z = 0; z < len; ++z) { + out.put(data[z]); + out.flush(); + ++first_count; + second_count += 2; + BOOST_CHECK(first_counter->characters() == first_count); + BOOST_CHECK(second_counter->characters() == second_count); + } + ++line_count; + BOOST_CHECK(first_counter->lines() == line_count); + BOOST_CHECK(first_counter->lines() == line_count); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("counter test"); + test->add(BOOST_TEST_CASE(&read_counter)); + test->add(BOOST_TEST_CASE(&write_counter)); + return test; +} diff --git a/src/boost/libs/iostreams/test/deprecated_file_descriptor_test.cpp b/src/boost/libs/iostreams/test/deprecated_file_descriptor_test.cpp new file mode 100644 index 00000000..cb23f7d0 --- /dev/null +++ b/src/boost/libs/iostreams/test/deprecated_file_descriptor_test.cpp @@ -0,0 +1,243 @@ +// (C) Copyright 2010 Daniel James +// 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.) + +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" +#include "detail/file_handle.hpp" + +// Test file_descriptor with the depreacted constructors. + +namespace boost_ios = boost::iostreams; +namespace ios_test = boost::iostreams::test; + +template <class FileDescriptor> +void file_handle_test_impl(FileDescriptor*) +{ + ios_test::test_file test1; + ios_test::test_file test2; + + //--------------Deprecated file descriptor constructor--------------------// + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + { + FileDescriptor device1(handle); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_OPEN(handle); + ios_test::close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + { + FileDescriptor device1(handle, false); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_OPEN(handle); + ios_test::close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + { + FileDescriptor device1(handle, true); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + FileDescriptor device1(handle); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + FileDescriptor device1(handle, false); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + FileDescriptor device1(handle, true); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + //--------------Deprecated file descriptor open---------------------------// + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + { + FileDescriptor device1; + device1.open(handle); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_OPEN(handle); + ios_test::close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + { + FileDescriptor device1; + device1.open(handle, false); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_OPEN(handle); + ios_test::close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + { + FileDescriptor device1; + device1.open(handle, true); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + FileDescriptor device1; + device1.open(handle); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + FileDescriptor device1; + device1.open(handle, false); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name()); + FileDescriptor device1; + device1.open(handle, true); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + //--------------Deprecated open with existing descriptor------------------// + + { + boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name()); + + { + FileDescriptor device1(handle1); + BOOST_CHECK(device1.handle() == handle1); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + device1.open(handle2); + BOOST_CHECK(device1.handle() == handle2); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + device1.close(); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_CLOSED(handle2); + } + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_CLOSED(handle2); + + ios_test::close_file_handle(handle1); + } + + { + boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name()); + + { + FileDescriptor device1(handle1, true); + BOOST_CHECK(device1.handle() == handle1); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + device1.open(handle2); + BOOST_CHECK(device1.handle() == handle2); + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + device1.close(); + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_CLOSED(handle2); + } + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_CLOSED(handle2); + } + + { + boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name()); + + { + FileDescriptor device1(handle1, false); + BOOST_CHECK(device1.handle() == handle1); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + device1.open(handle2, false); + BOOST_CHECK(device1.handle() == handle2); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + } + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + + ios_test::close_file_handle(handle1); + ios_test::close_file_handle(handle2); + } + + { + boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name()); + + { + FileDescriptor device1(handle1, true); + BOOST_CHECK(device1.handle() == handle1); + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + device1.open(handle2, true); + BOOST_CHECK(device1.handle() == handle2); + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + } + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_CLOSED(handle2); + } +} + +void deprecated_file_descriptor_test() +{ + file_handle_test_impl((boost_ios::file_descriptor*) 0); + file_handle_test_impl((boost_ios::file_descriptor_sink*) 0); + file_handle_test_impl((boost_ios::file_descriptor_source*) 0); +} + +boost::unit_test::test_suite* init_unit_test_suite(int, char* []) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("deprecated file_descriptor test"); + test->add(BOOST_TEST_CASE(&deprecated_file_descriptor_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/detail/closable.hpp b/src/boost/libs/iostreams/test/detail/closable.hpp new file mode 100644 index 00000000..182522fa --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/closable.hpp @@ -0,0 +1,343 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Defines a large collection of closable filters and devices that + * execute instances of boost::iostreams::test::operation upon + * closre(). Used to verify that filters and devices are closed + * correctly by the iostreams library + * + * File: libs/iostreams/test/detail/closable.hpp + * Date: Sun Dec 09 16:12:23 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#ifndef BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED + +#include <boost/iostreams/categories.hpp> +#include <boost/iostreams/char_traits.hpp> // EOF +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/detail/ios.hpp> +#include "./operation_sequence.hpp" + +namespace boost { namespace iostreams { namespace test { + +template<typename Category> +class closable_device { }; + +// Source +template<> +class closable_device<input> : public source { +public: + closable_device(operation close) : close_(close) { } + std::streamsize read(char*, std::streamsize) { return -1; } + void close() { close_.execute(); } +private: + operation close_; +}; + +// Sink +template<> +class closable_device<output> : public sink { +public: + closable_device(operation close) : close_(close) { } + std::streamsize write(const char*, std::streamsize) { return 0; } + void close() { close_.execute(); } +private: + operation close_; +}; + +struct borland_output { }; + +// Copy of closable_device<output>, for Borland <= 5.8.2 +template<> +class closable_device<borland_output> : public sink { +public: + closable_device(operation close) : close_(close) { } + std::streamsize write(const char*, std::streamsize) { return 0; } + void close() { close_.execute(); } +private: + operation close_; +}; + +// Bidirectional device +template<> +class closable_device<bidirectional> : public device<bidirectional> { +public: + closable_device(operation close_input, operation close_output) + : close_input_(close_input), close_output_(close_output) + { } + std::streamsize read(char*, std::streamsize) { return -1; } + std::streamsize write(const char*, std::streamsize) { return 0; } + void close(BOOST_IOS::openmode which) + { + switch (which) { + case BOOST_IOS::in: + close_input_.execute(); + break; + case BOOST_IOS::out: + close_output_.execute(); + break; + default: + break; + } + } +private: + operation close_input_; + operation close_output_; +}; + +// Seekable device +template<> +class closable_device<seekable> : public device<seekable> { +public: + closable_device(operation close) : close_(close) { } + std::streamsize read(char*, std::streamsize) { return -1; } + std::streamsize write(const char*, std::streamsize) { return 0; } + stream_offset seek(stream_offset, BOOST_IOS::seekdir) { return 0; } + void close() { close_.execute(); } +private: + operation close_; +}; + +struct direct_input + : input, device_tag, closable_tag, direct_tag + { }; +struct direct_output + : output, device_tag, closable_tag, direct_tag + { }; +struct direct_bidirectional + : bidirectional, device_tag, closable_tag, direct_tag + { }; +struct direct_seekable + : seekable, device_tag, closable_tag, direct_tag + { }; + +// Direct source +template<> +class closable_device<direct_input> { +public: + typedef char char_type; + typedef direct_input category; + closable_device(operation close) : close_(close) { } + std::pair<char*, char*> input_sequence() + { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); } + void close() { close_.execute(); } +private: + operation close_; +}; + +// Direct sink +template<> +class closable_device<direct_output> { +public: + typedef char char_type; + typedef direct_output category; + closable_device(operation close) : close_(close) { } + std::pair<char*, char*> output_sequence() + { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); } + void close() { close_.execute(); } +private: + operation close_; +}; + +// Direct bidirectional device +template<> +class closable_device<direct_bidirectional> { +public: + typedef char char_type; + typedef direct_bidirectional category; + closable_device(operation close_input, operation close_output) + : close_input_(close_input), close_output_(close_output) + { } + std::pair<char*, char*> input_sequence() + { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); } + std::pair<char*, char*> output_sequence() + { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); } + void close(BOOST_IOS::openmode which) + { + switch (which) { + case BOOST_IOS::in: + close_input_.execute(); + break; + case BOOST_IOS::out: + close_output_.execute(); + break; + default: + break; + } + } +private: + operation close_input_; + operation close_output_; +}; + +// Direct seekable device +template<> +class closable_device<direct_seekable> { +public: + typedef char char_type; + typedef direct_seekable category; + closable_device(operation close) : close_(close) { } + std::pair<char*, char*> input_sequence() + { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); } + std::pair<char*, char*> output_sequence() + { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); } + void close() { close_.execute(); } +private: + operation close_; +}; + +template<typename Mode> +class closable_filter { }; + +// Input filter +template<> +class closable_filter<input> : public input_filter { +public: + closable_filter(operation close) : close_(close) { } + + template<typename Source> + int get(Source&) { return EOF; } + + template<typename Source> + void close(Source&) { close_.execute(); } +private: + operation close_; +}; + +// Output filter +template<> +class closable_filter<output> : public output_filter { +public: + closable_filter(operation close) : close_(close) { } + + template<typename Sink> + bool put(Sink&, char) { return true; } + + template<typename Sink> + void close(Sink&) { close_.execute(); } +private: + operation close_; +}; + +// Bidirectional filter +template<> +class closable_filter<bidirectional> : public filter<bidirectional> { +public: + closable_filter(operation close_input, operation close_output) + : close_input_(close_input), close_output_(close_output) + { } + + template<typename Source> + int get(Source&) { return EOF; } + + template<typename Sink> + bool put(Sink&, char) { return true; } + + template<typename Device> + void close(Device&, BOOST_IOS::openmode which) + { + switch (which) { + case BOOST_IOS::in: + close_input_.execute(); + break; + case BOOST_IOS::out: + close_output_.execute(); + break; + default: + break; + } + } +private: + operation close_input_; + operation close_output_; +}; + +// Seekable filter +template<> +class closable_filter<seekable> : public filter<seekable> { +public: + closable_filter(operation close) : close_(close) { } + std::streamsize read(char*, std::streamsize) { return -1; } + + template<typename Source> + int get(Source&) { return EOF; } + + template<typename Sink> + bool put(Sink&, char) { return true; } + + template<typename Device> + stream_offset seek(Device&, stream_offset, BOOST_IOS::seekdir) + { + return 0; + } + + template<typename Device> + void close(Device&) { close_.execute(); } +private: + operation close_; +}; + +// Dual-use filter +template<> +class closable_filter<dual_use> { +public: + typedef char char_type; + struct category + : filter_tag, + dual_use, + closable_tag + { }; + closable_filter(operation close_input, operation close_output) + : close_input_(close_input), close_output_(close_output) + { } + + template<typename Source> + int get(Source&) { return EOF; } + + template<typename Sink> + bool put(Sink&, char) { return true; } + + template<typename Device> + void close(Device&, BOOST_IOS::openmode which) + { + switch (which) { + case BOOST_IOS::in: + close_input_.execute(); + break; + case BOOST_IOS::out: + close_output_.execute(); + break; + default: + break; + } + } +private: + operation close_input_; + operation close_output_; +}; + +// Symmetric filter +class closable_symmetric_filter { +public: + typedef char char_type; + closable_symmetric_filter(operation close) : close_(close) { } + bool filter( const char*&, const char*, + char*&, char*, bool ) + { + return false; + } + void close() { close_.execute(); } +private: + operation close_; +}; + +} } } // End namespaces test, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/constants.hpp b/src/boost/libs/iostreams/test/detail/constants.hpp new file mode 100644 index 00000000..7705d86e --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/constants.hpp @@ -0,0 +1,67 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definitions of several constants used by the test program. + +#ifndef BOOST_IOSTREAMS_TEST_CONSTANTS_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_CONSTANTS_HPP_INCLUDED + +#include <string.h> +#include <boost/config.hpp> + +namespace boost { namespace iostreams { namespace test { + +// Note: openmode could be a class type, so this header must be included +// by just one TU. +const BOOST_IOS::openmode in_mode = BOOST_IOS::in | BOOST_IOS::binary; +const BOOST_IOS::openmode out_mode = BOOST_IOS::out | BOOST_IOS::binary; + +// Chunk size for reading or writing in chunks. +const int chunk_size = 59; + +// Chunk size for reading or writing in chunks. +const int small_buffer_size = 23; + +// Number of times data is repeated in test files. +const int data_reps = 300; + +namespace detail { + +// Returns string which is used to generate test files. +inline const char* data(char*) +{ + static const char* c = + "!\"#$%&'()*+,-./0123456879:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n"; + return c; +} + +// Returns string which is used to generate test files. +inline const wchar_t* data(wchar_t*) +{ + static const wchar_t* c = + L"!\"#$%&'()*+,-./0123456879:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + L"[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n"; + return c; +} + +} // End namespace detail. + +inline const char* narrow_data() { return detail::data((char*)0); } + +inline const wchar_t* wide_data() { return detail::data((wchar_t*)0); } + +// Length of string returned by data(). +inline int data_length() +{ + static int len = (int) strlen(narrow_data()); + return len; +} + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TEST_CONSTANTS_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/file_handle.hpp b/src/boost/libs/iostreams/test/detail/file_handle.hpp new file mode 100644 index 00000000..a9bfed52 --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/file_handle.hpp @@ -0,0 +1,108 @@ +// (C) Copyright 2010 Daniel James +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// A few methods for getting and manipulating file handles. + +#ifndef BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED +#define BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED + +#include <boost/iostreams/detail/file_handle.hpp> +#include <boost/iostreams/detail/config/rtl.hpp> +#include <boost/test/test_tools.hpp> +#include <string> + +#ifdef BOOST_IOSTREAMS_WINDOWS +# include <io.h> // low-level file i/o. +# define WINDOWS_LEAN_AND_MEAN +# include <windows.h> +#else +# include <sys/stat.h> +# include <fcntl.h> +#endif + +namespace boost { namespace iostreams { namespace test { + +#ifdef BOOST_IOSTREAMS_WINDOWS + +// Windows implementation + +boost::iostreams::detail::file_handle open_file_handle(std::string const& name) +{ + HANDLE handle = + ::CreateFileA( name.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // lpSecurityAttributes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); // hTemplateFile + + BOOST_REQUIRE (handle != INVALID_HANDLE_VALUE); + return handle; +} + +void close_file_handle(boost::iostreams::detail::file_handle handle) +{ + BOOST_REQUIRE(::CloseHandle(handle) == 1); +} + +#define BOOST_CHECK_HANDLE_CLOSED(handle) +#define BOOST_CHECK_HANDLE_OPEN(handle) + +#else // BOOST_IOSTREAMS_WINDOWS + +// Non-windows implementation + +boost::iostreams::detail::file_handle open_file_handle(std::string const& name) +{ + int oflag = O_RDWR; + + #ifdef _LARGEFILE64_SOURCE + oflag |= O_LARGEFILE; + #endif + + // Calculate pmode argument to open. + + mode_t pmode = S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH; + + // Open file. + + int fd = BOOST_IOSTREAMS_FD_OPEN(name.c_str(), oflag, pmode); + BOOST_REQUIRE (fd != -1); + + return fd; +} + +void close_file_handle(boost::iostreams::detail::file_handle handle) +{ + BOOST_REQUIRE(BOOST_IOSTREAMS_FD_CLOSE(handle) != -1); +} + +// This is pretty dubious. First you must make sure that no other +// operations that could open a descriptor are called before this +// check, otherwise it's quite likely that a closed descriptor +// could be used. Secondly, I'm not sure if it's guaranteed that +// fcntl will know that the descriptor is closed but this seems +// to work okay, and I can't see any other convenient way to check +// that a descripter has been closed. +bool is_handle_open(boost::iostreams::detail::file_handle handle) +{ + return ::fcntl(handle, F_GETFD) != -1; +} + +#define BOOST_CHECK_HANDLE_CLOSED(handle) \ + BOOST_CHECK(!::boost::iostreams::test::is_handle_open(handle)) +#define BOOST_CHECK_HANDLE_OPEN(handle) \ + BOOST_CHECK(::boost::iostreams::test::is_handle_open(handle)) + + +#endif // BOOST_IOSTREAMS_WINDOWS + +}}} + +#endif // BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/filters.hpp b/src/boost/libs/iostreams/test/detail/filters.hpp new file mode 100644 index 00000000..1c732147 --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/filters.hpp @@ -0,0 +1,185 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definitions of several constants used by the test program. + +#ifndef BOOST_IOSTREAMS_TEST_FILTERS_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_FILTERS_HPP_INCLUDED + +#include <boost/config.hpp> +#include <algorithm> // min. +#include <cctype> // to_upper, to_lower. +#include <cstdlib> // to_upper, to_lower (VC6). +#include <cstddef> // ptrdiff_t. +#include <vector> +#include <boost/iostreams/char_traits.hpp> +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/constants.hpp> +#include <boost/iostreams/detail/iostream.hpp> // seekdir, streamsize. +#include <boost/iostreams/detail/streambuf.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/iostreams/pipeline.hpp> +#include <boost/type_traits/is_convertible.hpp> +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::toupper; using ::tolower; } +#endif + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> + +namespace boost { namespace iostreams { namespace test { + +struct toupper_filter : public input_filter { + template<typename Source> + int get(Source& s) + { + int c = boost::iostreams::get(s); + return c != EOF && c != WOULD_BLOCK ? + std::toupper((unsigned char) c) : + c; + } +}; +BOOST_IOSTREAMS_PIPABLE(toupper_filter, 0) + +struct tolower_filter : public output_filter { + template<typename Sink> + bool put(Sink& s, char c) + { + return boost::iostreams::put( + s, (char) std::tolower((unsigned char) c) + ); + } +}; +BOOST_IOSTREAMS_PIPABLE(tolower_filter, 0) + +struct toupper_multichar_filter : public multichar_input_filter { + template<typename Source> + std::streamsize read(Source& s, char* buf, std::streamsize n) + { + std::streamsize result = boost::iostreams::read(s, buf, n); + if (result == -1) + return -1; + for (int z = 0; z < result; ++z) + buf[z] = (char) std::toupper((unsigned char) buf[z]); + return result; + } +}; +BOOST_IOSTREAMS_PIPABLE(toupper_multichar_filter, 0) + +struct tolower_multichar_filter : public multichar_output_filter { + template<typename Sink> + std::streamsize write(Sink& s, const char* buf, std::streamsize n) + { + std::streamsize result; + for (result = 0; result < n; ++result) { + char c = (char) std::tolower((unsigned char) buf[result]); + if (!boost::iostreams::put(s, c)) + break; + } + return result; + } +}; +BOOST_IOSTREAMS_PIPABLE(tolower_multichar_filter, 0) + +struct padding_filter : dual_use_filter { + explicit padding_filter(char pad_char) + : pad_char_(pad_char), use_pad_char_(false), eof_(false) + { } + + template<typename Source> + int get(Source& src) + { + int result; + if (use_pad_char_) { + result = eof_ ? EOF : pad_char_; + use_pad_char_ = false; + } else { + result = boost::iostreams::get(src); + if (result != EOF && result != WOULD_BLOCK) + use_pad_char_ = true; + eof_ = result == EOF; + } + return result; + } + + template<typename Sink> + bool put(Sink& s, char c) + { + if (use_pad_char_) { + if (!boost::iostreams::put(s, pad_char_)) + return false; + use_pad_char_ = false; + } + if (!boost::iostreams::put(s, c)) + return false; + if (!boost::iostreams::put(s, pad_char_)) + use_pad_char_ = true; + return true; + } + + char pad_char_; + bool use_pad_char_; + bool eof_; +}; +BOOST_IOSTREAMS_PIPABLE(padding_filter, 0) + +struct flushable_output_filter { + typedef char char_type; + struct category + : output_filter_tag, + flushable_tag + { }; + template<typename Sink> + bool put(Sink&, char c) + { + buf_.push_back(c); + return true; + } + template<typename Sink> + bool flush(Sink& s) + { + if (!buf_.empty()) { + boost::iostreams::write(s, &buf_[0], (std::streamsize) buf_.size()); + buf_.clear(); + } + return true; + } + std::vector<char> buf_; +}; +BOOST_IOSTREAMS_PIPABLE(flushable_output_filter, 0) + +struct identity_seekable_filter : filter<seekable> { + template<typename Source> + int get(Source& s) { return boost::iostreams::get(s); } + + template<typename Sink> + bool put(Sink& s, char c) { return boost::iostreams::put(s, c); } + + template<typename Device> + std::streampos seek(Device& d, stream_offset off, BOOST_IOS::seekdir way) + { return boost::iostreams::seek(d, off, way); } +}; +BOOST_IOSTREAMS_PIPABLE(identity_seekable_filter, 0) + +struct identity_seekable_multichar_filter : multichar_filter<seekable> { + template<typename Source> + std::streamsize read(Source& s, char* buf, std::streamsize n) + { return boost::iostreams::read(s, buf, n); } + template<typename Sink> + std::streamsize write(Sink& s, const char* buf, std::streamsize n) + { return boost::iostreams::write(s, buf, n); } + template<typename Device> + std::streampos seek(Device& d, stream_offset off, BOOST_IOS::seekdir way) + { return boost::iostreams::seek(d, off, way); } +}; +BOOST_IOSTREAMS_PIPABLE(identity_seekable_multichar_filter, 0) + +} } } // End namespaces detail, iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +#endif // #ifndef BOOST_IOSTREAMS_TEST_FILTERS_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/null_padded_codecvt.hpp b/src/boost/libs/iostreams/test/detail/null_padded_codecvt.hpp new file mode 100644 index 00000000..6a04e618 --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/null_padded_codecvt.hpp @@ -0,0 +1,275 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definitions of two codecvt facets useful for testing code +// conversion. Both represent the "null padded" character encoding described as +// follows. A wide character can be represented by the encoding if its value V +// is within the range of an unsigned char. The first char of the sequence +// representing V is V % 3 + 1. This is followed by V % 3 null characters, and +// finally by V itself. + +// The first codecvt facet, null_padded_codecvt, is statefull, with state_type +// equal to int. + +// The second codecvt facet, stateless_null_padded_codecvt, is stateless. At +// each point in a conversion, no characters are consumed unless there is room +// in the output sequence to write an entire multibyte sequence. + +#ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED + +#include <boost/config.hpp> // NO_STDC_NAMESPACE +#include <boost/iostreams/detail/codecvt_helper.hpp> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include <cstddef> // mbstate_t. +#include <locale> // codecvt. +#include <boost/integer_traits.hpp> // const_max. + +#ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::mbstate_t; } +#endif + +namespace boost { namespace iostreams { namespace test { + +//------------------Definition of null_padded_codecvt_state-------------------// + +class null_padded_codecvt_state { +public: + null_padded_codecvt_state(int val = 0) : val_(val) { } + operator int() const { return val_; } + int& val() { return val_; } + const int& val() const { return val_; } +private: + int val_; +}; + +} } } + +BOOST_IOSTREAMS_CODECVT_SPEC(boost::iostreams::test::null_padded_codecvt_state) + +namespace boost { namespace iostreams { namespace test { + +//------------------Definition of null_padded_codevt--------------------------// + +// +// state is initially 0. After a single character is consumed, state is set to +// the number of characters in the current multibyte sequence and decremented +// as each character is consumed until its value reaches 0 again. +// +class null_padded_codecvt + : public iostreams::detail::codecvt_helper< + wchar_t, char, null_padded_codecvt_state + > +{ +public: + typedef null_padded_codecvt_state state_type; +private: + std::codecvt_base::result + do_in( state_type& state, const char* first1, const char* last1, + const char*& next1, wchar_t* first2, wchar_t* last2, + wchar_t*& next2 ) const + { + using namespace std; + if (state < 0 || state > 3) + return codecvt_base::error; + next1 = first1; + next2 = first2; + while (next2 != last2 && next1 != last1) { + while (next1 != last1) { + if (state == 0) { + if (*next1 < 1 || *next1 > 3) + return codecvt_base::error; + state = *next1++; + } else if (state == 1) { + *next2++ = (unsigned char) *next1++; + state = 0; + break; + } else { + if (*next1++ != 0) + return codecvt_base::error; + --state.val(); + } + } + } + return next2 == last2 ? + codecvt_base::ok : + codecvt_base::partial; + } + + std::codecvt_base::result + do_out( state_type& state, const wchar_t* first1, const wchar_t* last1, + const wchar_t*& next1, char* first2, char* last2, + char*& next2 ) const + { + using namespace std; + if (state < 0 || state > 3) + return codecvt_base::error; + next1 = first1; + next2 = first2; + while (next1 != last1 && next2 != last2) { + while (next2 != last2) { + if (state == 0) { + if (*next1 > integer_traits<unsigned char>::const_max) + return codecvt_base::noconv; + state = *next1 % 3 + 1; + *next2++ = static_cast<char>(state); + } else if (state == 1) { + state = 0; + *next2++ = static_cast<unsigned char>(*next1++); + break; + } else { + --state.val(); + *next2++ = 0; + } + } + } + return next1 == last1 ? + codecvt_base::ok : + codecvt_base::partial; + } + + std::codecvt_base::result + do_unshift( state_type& state, + char* /* first2 */, + char* last2, + char*& next2 ) const + { + using namespace std; + next2 = last2; + while (state.val()-- > 0) + if (next2 != last2) + *next2++ = 0; + else + return codecvt_base::partial; + return codecvt_base::ok; + } + + bool do_always_noconv() const throw() { return false; } + + int do_max_length() const throw() { return 4; } + + int do_encoding() const throw() { return -1; } + + int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type& state, + const char* first1, const char* last1, + std::size_t len2 ) const throw() + { // Implementation should follow that of do_in(). + int st = state; + std::size_t result = 0; + const char* next1 = first1; + while (result < len2 && next1 != last1) { + while (next1 != last1) { + if (st == 0) { + if (*next1 < 1 || *next1 > 3) + return static_cast<int>(result); // error. + st = *next1++; + } else if (st == 1) { + ++result; + st = 0; + break; + } else { + if (*next1++ != 0) + return static_cast<int>(result); // error. + --st; + } + } + } + return static_cast<int>(result); + } +}; + +//------------------Definition of stateless_null_padded_codevt----------------// + +class stateless_null_padded_codecvt + : public std::codecvt<wchar_t, char, std::mbstate_t> +{ + std::codecvt_base::result + do_in( state_type&, const char* first1, const char* last1, + const char*& next1, wchar_t* first2, wchar_t* last2, + wchar_t*& next2 ) const + { + using namespace std; + for ( next1 = first1, next2 = first2; + next1 != last1 && next2 != last2; ) + { + int len = (unsigned char) *next1; + if (len < 1 || len > 3) + return codecvt_base::error; + if (last1 - next1 < len + 1) + return codecvt_base::partial; + ++next1; + while (len-- > 1) + if (*next1++ != 0) + return codecvt_base::error; + *next2++ = (unsigned char) *next1++; + } + return next1 == last1 && next2 == last2 ? + codecvt_base::ok : + codecvt_base::partial; + } + + std::codecvt_base::result + do_out( state_type&, const wchar_t* first1, const wchar_t* last1, + const wchar_t*& next1, char* first2, char* last2, + char*& next2 ) const + { + using namespace std; + for ( next1 = first1, next2 = first2; + next1 != last1 && next2 != last2; ) + { + if (*next1 > integer_traits<unsigned char>::const_max) + return codecvt_base::noconv; + int skip = *next1 % 3 + 2; + if (last2 - next2 < skip) + return codecvt_base::partial; + *next2++ = static_cast<char>(--skip); + while (skip-- > 1) + *next2++ = 0; + *next2++ = (unsigned char) *next1++; + } + return codecvt_base::ok; + } + + std::codecvt_base::result + do_unshift( state_type&, + char* /* first2 */, + char* /* last2 */, + char*& /* next2 */ ) const + { + return std::codecvt_base::ok; + } + + bool do_always_noconv() const throw() { return false; } + + int do_max_length() const throw() { return 4; } + + int do_encoding() const throw() { return -1; } + + int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type&, + const char* first1, const char* last1, + std::size_t len2 ) const throw() + { // Implementation should follow that of do_in(). + std::size_t result = 0; + for ( const char* next1 = first1; + next1 != last1 && result < len2; ++result) + { + int len = (unsigned char) *next1; + if (len < 1 || len > 3 || last1 - next1 < len + 1) + return static_cast<int>(result); // error. + ++next1; + while (len-- > 1) + if (*next1++ != 0) + return static_cast<int>(result); // error. + ++next1; + } + return static_cast<int>(result); + } +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/operation_sequence.hpp b/src/boost/libs/iostreams/test/detail/operation_sequence.hpp new file mode 100644 index 00000000..236c726f --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/operation_sequence.hpp @@ -0,0 +1,224 @@ +/* + * + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Defines the classes operation_sequence and operation, in the namespace + * boost::iostreams::test, for verifying that all elements of a sequence of + * operations are executed, and that they are executed in the correct order. + * + * File: libs/iostreams/test/detail/operation_sequence.hpp + * Date: Mon Dec 10 18:58:19 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#ifndef BOOST_IOSTREAMS_TEST_OPERATION_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_OPERATION_SEQUENCE_HPP_INCLUDED + +#include <boost/config.hpp> // make sure size_t is in namespace std +#include <cstddef> +#include <climits> +#include <map> +#include <stdexcept> +#include <string> +#include <utility> // pair +#include <vector> +#include <boost/lexical_cast.hpp> +#include <boost/preprocessor/iteration/local.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/weak_ptr.hpp> + +#ifndef BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR +# define BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR 20 +#endif + +#define BOOST_CHECK_OPERATION_SEQUENCE(seq) \ + BOOST_CHECK_MESSAGE(seq.is_success(), seq.message()) \ + /**/ + +namespace boost { namespace iostreams { namespace test { + +// Simple exception class with error code built in to type +template<int Code> +struct operation_error { }; + +class operation_sequence; + +// Represent an operation in a sequence of operations to be executed +class operation { +public: + friend class operation_sequence; + operation() : pimpl_() { } + void execute(); +private: + static void remove_operation(operation_sequence& seq, int id); + + struct impl { + impl(operation_sequence& seq, int id, int error_code = -1) + : seq(seq), id(id), error_code(error_code) + { } + ~impl() { remove_operation(seq, id); } + impl& operator=(const impl&); // Suppress VC warning 4512 + operation_sequence& seq; + int id; + int error_code; + }; + friend struct impl; + + operation(operation_sequence& seq, int id, int error_code = -1) + : pimpl_(new impl(seq, id, error_code)) + { } + + shared_ptr<impl> pimpl_; +}; + +// Represents a sequence of operations to be executed in a particular order +class operation_sequence { +public: + friend class operation; + operation_sequence() { reset(); } + + // + // Returns a new operation. + // Parameters: + // + // id - The operation id, determining the position + // of the new operation in the operation sequence + // error_code - If supplied, indicates that the new + // operation will throw operation_error<error_code> + // when executed. Must be an integer between 0 and + // BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR, + // inclusive. + // + operation new_operation(int id, int error_code = INT_MAX); + + bool is_success() const { return success_; } + bool is_failure() const { return failed_; } + std::string message() const; + void reset(); +private: + void execute(int id); + void remove_operation(int id); + operation_sequence(const operation_sequence&); + operation_sequence& operator=(const operation_sequence&); + + typedef weak_ptr<operation::impl> ptr_type; + typedef std::map<int, ptr_type> map_type; + + map_type operations_; + std::vector<int> log_; + std::size_t total_executed_; + int last_executed_; + bool success_; + bool failed_; +}; + +//--------------Implementation of operation-----------------------------------// + +void operation::execute() +{ + pimpl_->seq.execute(pimpl_->id); + switch (pimpl_->error_code) { + + // Implementation with one or more cleanup operations + #define BOOST_PP_LOCAL_MACRO(n) \ + case n: throw operation_error<n>(); \ + /**/ + + #define BOOST_PP_LOCAL_LIMITS (1, BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR) + #include BOOST_PP_LOCAL_ITERATE() + #undef BOOST_PP_LOCAL_MACRO + + default: + break; + } +} + +inline void operation::remove_operation(operation_sequence& seq, int id) +{ + seq.remove_operation(id); +} + +//--------------Implementation of operation_sequence--------------------------// + +inline operation operation_sequence::new_operation(int id, int error_code) +{ + using namespace std; + if ( error_code < 0 || + (error_code > BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR && + error_code != INT_MAX) ) + { + throw runtime_error( string("The error code ") + + lexical_cast<string>(error_code) + + " is out of range" ); + } + if (last_executed_ != INT_MIN) + throw runtime_error( "Operations in progress; call reset() " + "before creating more operations" ); + map_type::const_iterator it = operations_.find(id); + if (it != operations_.end()) + throw runtime_error( string("The operation ") + + lexical_cast<string>(id) + + " already exists" ); + operation op(*this, id, error_code); + operations_.insert(make_pair(id, ptr_type(op.pimpl_))); + return op; +} + +inline std::string operation_sequence::message() const +{ + using namespace std; + if (success_) + return "success"; + std::string msg = failed_ ? + "operations occurred out of order: " : + "operation sequence is incomplete: "; + typedef vector<int>::size_type size_type; + for (size_type z = 0, n = log_.size(); z < n; ++z) { + msg += lexical_cast<string>(log_[z]); + if (z < n - 1) + msg += ','; + } + return msg; +} + +inline void operation_sequence::reset() +{ + log_.clear(); + total_executed_ = 0; + last_executed_ = INT_MIN; + success_ = false; + failed_ = false; +} + +inline void operation_sequence::execute(int id) +{ + log_.push_back(id); + if (!failed_ && last_executed_ < id) { + if (++total_executed_ == operations_.size()) + success_ = true; + last_executed_ = id; + } else { + success_ = false; + failed_ = true; + } +} + +inline void operation_sequence::remove_operation(int id) +{ + using namespace std; + map_type::iterator it = operations_.find(id); + if (it == operations_.end()) + throw runtime_error( string("No such operation: ") + + lexical_cast<string>(id) ); + operations_.erase(it); +} + +} } } // End namespace boost::iostreams::test. + +#endif // #ifndef BOOST_IOSTREAMS_TEST_OPERATION_SEQUENCE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/sequence.hpp b/src/boost/libs/iostreams/test/detail/sequence.hpp new file mode 100644 index 00000000..0b08f7b3 --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/sequence.hpp @@ -0,0 +1,274 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_SEQUENCE_HPP_INCLUDED + +#include <algorithm> +#include <iterator> +#include <string.h> // strlen. +#include <vector> +#include <boost/iostreams/detail/default_arg.hpp> +#include "./constants.hpp" + +namespace boost { namespace iostreams { namespace test { + +template<typename Ch = BOOST_IOSTREAMS_DEFAULT_ARG(char) > +struct test_sequence : public std::vector<Ch> { + test_sequence() + { + const Ch* buf = test::detail::data((Ch*)0); + this->reserve(data_reps * data_length()); + for (int z = 0; z < data_reps; ++z) + std::copy(buf, buf + data_length(), std::back_inserter(*this)); + } +}; + +const char* text = + "The Lord spoke to Moses saying: Speak to the children of " + "Israel, and have them take for Me an offering; from every " + "person whose heart inspires him to generosity, you shall take " + "My offering. And this is the offering that you shall take " + "from them: gold, silver, and copper; blue, purple, and " + "crimson wool; linen and goat hair; ram skins dyed red, " + "tachash skins, and acacia wood; oil for lighting, spices for " + "the anointing oil and for the incense; shoham stones and " + "filling stones for the ephod and for the choshen. And they " + "shall make Me a sanctuary and I will dwell in their midst " + "according to all that I show you, the pattern of the Mishkan " + "and the pattern of all its vessels; and so shall you do. They " + "shall make an ark of acacia wood, two and a half cubits its " + "length, a cubit and a half its width, and a cubit and a half " + "its height. And you shall overlay it with pure gold; from " + "inside and from outside you shall overlay it, and you shall " + "make upon it a golden crown all around. And you shall cast " + "four golden rings for it, and you shall place them upon its " + "four corners, two rings on its one side, and two rings on its " + "other side. And you shall make poles of acacia wood and you " + "shall overlay them with gold. And you shall bring the poles " + "into the rings on the sides of the ark, to carry the ark with " + "them. The poles of the ark shall be in the rings; they shall " + "not be removed from it. And you shall place into the ark the " + "testimony, which I will give you. " + "And you shall make an ark cover of pure gold, two and a half " + "cubits its length and a cubit and a half its width. And you " + "shall make two golden cherubim; you shall make them of " + "hammered work, from the two ends of the ark cover. And make " + "one cherub from the one end and the other cherub from the " + "other end; from the ark cover you shall make the cherubim on " + "its two ends. The cherubim shall have their wings spread " + "upwards, shielding the ark cover with their wings, with their " + "faces toward one another; [turned] toward the ark cover shall " + "be the faces of the cherubim. And you shall place the ark " + "cover on the ark from above, and into the ark you shall place " + "the testimony, which I will give you. I will arrange My " + "meetings with you there, and I will speak with you from atop " + "the ark cover from between the two cherubim that are upon the " + "Ark of the Testimony, all that I will command you unto the " + "children of Israel. And you shall make a table of acacia " + "wood, two cubits its length, one cubit its width, and a cubit " + "and a half its height. And you shall overlay it with pure " + "gold, and you shall make for it a golden crown all around. " + "And you shall make for it a frame a handbreadth [wide] all " + "around, and you shall make a golden crown for its frame all " + "around. And you shall make for it four golden rings, and you " + "shall place the rings on the four corners that are on its " + "four legs. The rings shall be opposite the frame as holders " + "for the poles [with which] to carry the table. And you shall " + "make the poles of acacia wood, and you shall overlay them " + "with gold, and the table shall be carried with them. And you " + "shall make its forms, its spoons, its half pipes, and its " + "supports with which it will be covered; of pure gold you " + "shall make them. And you shall place on the table showbread " + "before Me at all times. " + "And you shall make a menorah of pure gold. The menorah shall " + "be made of hammered work; its base and its stem, its goblets, " + "its knobs, and its flowers shall [all] be [one piece] with " + "it. And six branches coming out of its sides: three menorah " + "branches from its one side and three menorah branches from " + "its second side. Three decorated goblets on one branch, a " + "knob and a flower, and three decorated goblets on one branch, " + "a knob and a flower; so for the six branches that come out of " + "the menorah. And on [the stem of] the menorah [shall be] four " + "decorated goblets, its knobs and its flowers. And a knob under " + "the two branches from it, and a knob under the two branches " + "from it, and a knob under the two branches from it; so for the " + "six branches that come out of the menorah. Their knobs and " + "their branches shall [all] be [one piece] with it; all of it " + + "[shall be] one hammered mass of pure gold. And you shall make " + "its lamps seven, and he shall kindle its lamps [so that they] " + "shed light toward its face. And its tongs and its scoops " + "[shall be] of pure gold. He shall make it of a talent of pure " + "gold, with all these implements. Now see and make according " + "to their pattern, which you are shown on the mountain. " + "And the Mishkan you shall make out of ten curtains " + "[consisting] of twisted fine linen, and blue, purple, and " + "crimson wool. A cherubim design of the work of a master " + "weaver you shall make them. The length of one curtain [shall " + "be] twenty eight cubits, and the width of one curtain [shall " + "be] four cubits; the same measure for all the curtains. Five " + "of these curtains shall be joined to one another, and [the " + "other] five curtains shall [also] be joined to one another. " + "And you shall make loops of blue wool on the edge of one " + "curtain [that is] at the edge of the [first] set, and so " + "shall you do on the edge of the outermost curtain of the " + "second set. You shall make fifty loops on [the edge of] one " + "curtain, and you shall make fifty loops on the edge of the " + "curtain in the second set; the loops shall correspond to one " + "another. And you shall make fifty golden clasps, and you " + "shall fasten the curtains to one another with the clasps; so " + "shall the Mishkan become one. And [then] you shall make " + "curtains of goat hair for a tent over the Mishkan; you shall " + "make eleven curtains. The length of one curtain [shall be] " + "thirty cubits, and the width of one curtain four cubits; the " + "same measure for the eleven curtains. And you shall join the " + "five curtains by themselves, and the [other] six curtains by " + "themselves; and you shall fold the sixth curtain before the " + "front of the tent. And you shall make fifty loops on the edge " + "of one curtain, [which is] at the edge of the [first] set, and " + "fifty loops on the edge of the [outermost] curtain of the " + "second set. And you shall make fifty copper clasps; you shall " + "bring the clasps into the loops, and you shall fasten the " + "tent together so that it will become one. And the overhanging " + "excess in the curtains of the tent half of the extra curtain " + "shall hang over the rear of the Mishkan. And the cubit from " + "here and the cubit from there of the excess in the length of " + "the curtains of the tent shall hang over the sides of the " + "Mishkan from here and from there to cover it. And you shall " + "make a covering for the tent of ram skins dyed red and a " + "covering of tachash skins above."; + +struct text_sequence : public std::vector<char> { + text_sequence() + { + const char* c = + "The Lord spoke to Moses saying: Speak to the children of " + "Israel, and have them take for Me an offering; from every " + "person whose heart inspires him to generosity, you shall take " + "My offering. And this is the offering that you shall take " + "from them: gold, silver, and copper; blue, purple, and " + "crimson wool; linen and goat hair; ram skins dyed red, " + "tachash skins, and acacia wood; oil for lighting, spices for " + "the anointing oil and for the incense; shoham stones and " + "filling stones for the ephod and for the choshen. And they " + "shall make Me a sanctuary and I will dwell in their midst " + "according to all that I show you, the pattern of the Mishkan " + "and the pattern of all its vessels; and so shall you do. They " + "shall make an ark of acacia wood, two and a half cubits its " + "length, a cubit and a half its width, and a cubit and a half " + "its height. And you shall overlay it with pure gold; from " + "inside and from outside you shall overlay it, and you shall " + "make upon it a golden crown all around. And you shall cast " + "four golden rings for it, and you shall place them upon its " + "four corners, two rings on its one side, and two rings on its " + "other side. And you shall make poles of acacia wood and you " + "shall overlay them with gold. And you shall bring the poles " + "into the rings on the sides of the ark, to carry the ark with " + "them. The poles of the ark shall be in the rings; they shall " + "not be removed from it. And you shall place into the ark the " + "testimony, which I will give you. " + "And you shall make an ark cover of pure gold, two and a half " + "cubits its length and a cubit and a half its width. And you " + "shall make two golden cherubim; you shall make them of " + "hammered work, from the two ends of the ark cover. And make " + "one cherub from the one end and the other cherub from the " + "other end; from the ark cover you shall make the cherubim on " + "its two ends. The cherubim shall have their wings spread " + "upwards, shielding the ark cover with their wings, with their " + "faces toward one another; [turned] toward the ark cover shall " + "be the faces of the cherubim. And you shall place the ark " + "cover on the ark from above, and into the ark you shall place " + "the testimony, which I will give you. I will arrange My " + "meetings with you there, and I will speak with you from atop " + "the ark cover from between the two cherubim that are upon the " + "Ark of the Testimony, all that I will command you unto the " + "children of Israel. And you shall make a table of acacia " + "wood, two cubits its length, one cubit its width, and a cubit " + "and a half its height. And you shall overlay it with pure " + "gold, and you shall make for it a golden crown all around. " + "And you shall make for it a frame a handbreadth [wide] all " + "around, and you shall make a golden crown for its frame all " + "around. And you shall make for it four golden rings, and you " + "shall place the rings on the four corners that are on its " + "four legs. The rings shall be opposite the frame as holders " + "for the poles [with which] to carry the table. And you shall " + "make the poles of acacia wood, and you shall overlay them " + "with gold, and the table shall be carried with them. And you " + "shall make its forms, its spoons, its half pipes, and its " + "supports with which it will be covered; of pure gold you " + "shall make them. And you shall place on the table showbread " + "before Me at all times. " + "And you shall make a menorah of pure gold. The menorah shall " + "be made of hammered work; its base and its stem, its goblets, " + "its knobs, and its flowers shall [all] be [one piece] with " + "it. And six branches coming out of its sides: three menorah " + "branches from its one side and three menorah branches from " + "its second side. Three decorated goblets on one branch, a " + "knob and a flower, and three decorated goblets on one branch, " + "a knob and a flower; so for the six branches that come out of " + "the menorah. And on [the stem of] the menorah [shall be] four " + "decorated goblets, its knobs and its flowers. And a knob under " + "the two branches from it, and a knob under the two branches " + "from it, and a knob under the two branches from it; so for the " + "six branches that come out of the menorah. Their knobs and " + "their branches shall [all] be [one piece] with it; all of it " + + "[shall be] one hammered mass of pure gold. And you shall make " + "its lamps seven, and he shall kindle its lamps [so that they] " + "shed light toward its face. And its tongs and its scoops " + "[shall be] of pure gold. He shall make it of a talent of pure " + "gold, with all these implements. Now see and make according " + "to their pattern, which you are shown on the mountain. " + "And the Mishkan you shall make out of ten curtains " + "[consisting] of twisted fine linen, and blue, purple, and " + "crimson wool. A cherubim design of the work of a master " + "weaver you shall make them. The length of one curtain [shall " + "be] twenty eight cubits, and the width of one curtain [shall " + "be] four cubits; the same measure for all the curtains. Five " + "of these curtains shall be joined to one another, and [the " + "other] five curtains shall [also] be joined to one another. " + "And you shall make loops of blue wool on the edge of one " + "curtain [that is] at the edge of the [first] set, and so " + "shall you do on the edge of the outermost curtain of the " + "second set. You shall make fifty loops on [the edge of] one " + "curtain, and you shall make fifty loops on the edge of the " + "curtain in the second set; the loops shall correspond to one " + "another. And you shall make fifty golden clasps, and you " + "shall fasten the curtains to one another with the clasps; so " + "shall the Mishkan become one. And [then] you shall make " + "curtains of goat hair for a tent over the Mishkan; you shall " + "make eleven curtains. The length of one curtain [shall be] " + "thirty cubits, and the width of one curtain four cubits; the " + "same measure for the eleven curtains. And you shall join the " + "five curtains by themselves, and the [other] six curtains by " + "themselves; and you shall fold the sixth curtain before the " + "front of the tent. And you shall make fifty loops on the edge " + "of one curtain, [which is] at the edge of the [first] set, and " + "fifty loops on the edge of the [outermost] curtain of the " + "second set. And you shall make fifty copper clasps; you shall " + "bring the clasps into the loops, and you shall fasten the " + "tent together so that it will become one. And the overhanging " + "excess in the curtains of the tent half of the extra curtain " + "shall hang over the rear of the Mishkan. And the cubit from " + "here and the cubit from there of the excess in the length of " + "the curtains of the tent shall hang over the sides of the " + "Mishkan from here and from there to cover it. And you shall " + "make a covering for the tent of ram skins dyed red and a " + "covering of tachash skins above."; + std::vector<char>::size_type len = strlen(c); + this->reserve(len); + this->insert(this->end(), c, c + len); + } +}; + + +//----------------------------------------------------------------------------// + +} } } // End namespaces test, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TEST_SEQUENCE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/temp_file.hpp b/src/boost/libs/iostreams/test/detail/temp_file.hpp new file mode 100644 index 00000000..e8605d0d --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/temp_file.hpp @@ -0,0 +1,92 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_FILES_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_FILES_HPP_INCLUDED + +#include <cctype> // toupper, tolower +#include <cstdio> // tmpname, TMP_MAX, remove +#include <cstdlib> // rand, toupper, tolower (VC6) +#include <fstream> +#include <string> +#include <boost/filesystem/operations.hpp> +#include "./constants.hpp" + +#ifdef BOOST_NO_STDC_NAMESPACE +# undef toupper +# undef tolower +# undef remove +# undef rand +namespace std { + using ::toupper; using ::tolower; using ::remove; using ::rand; +} +#endif + +namespace boost { namespace iostreams { namespace test { + +// Represents a temp file, deleted upon destruction. +class temp_file { +public: + + // Constructs a temp file which does not initially exist. + temp_file() { set_name(); } + ~temp_file() { (void)std::remove(name_.c_str()); } + const ::std::string name() const { return name_; } + operator const ::std::string() const { return name_; } +private: + void set_name() { + name_ = boost::filesystem::unique_path().string(); + } + + ::std::string name_; +}; + +struct test_file : public temp_file { + test_file() + { + BOOST_IOS::openmode mode = + BOOST_IOS::out | BOOST_IOS::binary; + ::std::ofstream f(name().c_str(), mode); + const ::std::string n(name()); + const char* buf = narrow_data(); + for (int z = 0; z < data_reps; ++z) + f.write(buf, data_length()); + } +}; + + +struct uppercase_file : public temp_file { + uppercase_file() + { + BOOST_IOS::openmode mode = + BOOST_IOS::out | BOOST_IOS::binary; + ::std::ofstream f(name().c_str(), mode); + const char* buf = narrow_data(); + for (int z = 0; z < data_reps; ++z) + for (int w = 0; w < data_length(); ++w) + f.put((char) std::toupper(buf[w])); + } +}; + +struct lowercase_file : public temp_file { + lowercase_file() + { + BOOST_IOS::openmode mode = + BOOST_IOS::out | BOOST_IOS::binary; + ::std::ofstream f(name().c_str(), mode); + const char* buf = narrow_data(); + for (int z = 0; z < data_reps; ++z) + for (int w = 0; w < data_length(); ++w) + f.put((char) std::tolower(buf[w])); + } +}; + +//----------------------------------------------------------------------------// + +} } } // End namespaces test, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TEST_FILES_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/detail/utf8_codecvt_facet.cpp b/src/boost/libs/iostreams/test/detail/utf8_codecvt_facet.cpp new file mode 100644 index 00000000..1e543d60 --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/utf8_codecvt_facet.cpp @@ -0,0 +1,372 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// utf8_codecvt_facet.cpp + +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/iostreams for documentation. + +//#include <cstdlib> // for multi-byte converson routines + +// Jonathan Turkanis: +// - Replaced test for BOOST_NO_STD_WSTREAMBUF with test for +// BOOST_IOSTREAMS_NO_WIDE_STREAMS; +// - Derived from codecvt_helper instead of codecvt. + +#include <boost/config.hpp> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include <boost/numeric/conversion/cast.hpp> +#ifdef BOOST_IOSTREAMS_NO_LOCALES +# error "C++ locales not supported on this platform" +#else + +#include <cassert> +#include <cstddef> + +#include <boost/detail/workaround.hpp> +#include "./utf8_codecvt_facet.hpp" + +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x600) +# pragma warn -sig // Conversion may lose significant digits +# pragma warn -rng // Constant is out of range in comparison +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation for wchar_t + +// Translate incoming UTF-8 into UCS-4 +std::codecvt_base::result utf8_codecvt_facet_wchar_t::do_in( + std::mbstate_t&, + const char * from, + const char * from_end, + const char * & from_next, + wchar_t * to, + wchar_t * to_end, + wchar_t * & to_next +) const { + // Basic algorithm: The first octet determines how many + // octets total make up the UCS-4 character. The remaining + // "continuing octets" all begin with "10". To convert, subtract + // the amount that specifies the number of octets from the first + // octet. Subtract 0x80 (1000 0000) from each continuing octet, + // then mash the whole lot together. Note that each continuing + // octet only uses 6 bits as unique values, so only shift by + // multiples of 6 to combine. + while (from != from_end && to != to_end) { + + // Error checking on the first octet + if (invalid_leading_octet(*from)){ + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + // The first octet is adjusted by a value dependent upon + // the number of "continuing octets" encoding the character + const int cont_octet_count = get_cont_octet_count(*from); + const wchar_t octet1_modifier_table[] = { + 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc + }; + + // The unsigned char conversion is necessary in case char is + // signed (I learned this the hard way) + wchar_t ucs_result = + (unsigned char)(*from++) - octet1_modifier_table[cont_octet_count]; + + // Invariants : + // 1) At the start of the loop, 'i' continuing characters have been + // processed + // 2) *from points to the next continuing character to be processed. + int i = 0; + while(i != cont_octet_count && from != from_end) { + + // Error checking on continuing characters + if (invalid_continuing_octet(*from)) { + from_next = from; + to_next = to; + return std::codecvt_base::error; + } + + ucs_result *= (1 << 6); + + // each continuing character has an extra (10xxxxxx)b attached to + // it that must be removed. + ucs_result += (unsigned char)(*from++) - 0x80; + ++i; + } + + // If the buffer ends with an incomplete unicode character... + if (from == from_end && i != cont_octet_count) { + // rewind "from" to before the current character translation + from_next = from - (i+1); + to_next = to; + return std::codecvt_base::partial; + } + *to++ = ucs_result; + } + from_next = from; + to_next = to; + + // Were we done converting or did we run out of destination space? + if(from == from_end) return std::codecvt_base::ok; + else return std::codecvt_base::partial; +} + +std::codecvt_base::result utf8_codecvt_facet_wchar_t::do_out( + std::mbstate_t &, + const wchar_t * from, + const wchar_t * from_end, + const wchar_t * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + // RG - consider merging this table with the other one + const wchar_t octet1_modifier_table[] = { + 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc + }; + + while (from != from_end && to != to_end) { + +#define BOOST_NULL // Prevent macro expansion + // Check for invalid UCS-4 character + if (*from > std::numeric_limits<wchar_t>::max BOOST_NULL ()) { + from_next = from; + to_next = to; + return std::codecvt_base::error; + } +#undef BOOST_NULL + + int cont_octet_count = get_cont_octet_out_count(*from); + + // RG - comment this formula better + int shift_exponent = (cont_octet_count) * 6; + + // Process the first character + *to++ = octet1_modifier_table[cont_octet_count] + + (unsigned char)(*from / (1 << shift_exponent)); + + // Process the continuation characters + // Invariants: At the start of the loop: + // 1) 'i' continuing octets have been generated + // 2) '*to' points to the next location to place an octet + // 3) shift_exponent is 6 more than needed for the next octet + int i = 0; + while (i != cont_octet_count && to != to_end) { + shift_exponent -= 6; + *to++ = 0x80 + ((*from / (1 << shift_exponent)) % (1 << 6)); + ++i; + } + // If we filled up the out buffer before encoding the character + if(to == to_end && i != cont_octet_count) { + from_next = from; + to_next = to - (i+1); + return std::codecvt_base::partial; + } + ++from; + } + from_next = from; + to_next = to; + // Were we done or did we run out of destination space + if(from == from_end) return std::codecvt_base::ok; + else return std::codecvt_base::partial; +} + +// How many char objects can I process to get <= max_limit +// wchar_t objects? +int utf8_codecvt_facet_wchar_t::do_length( + BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER std::mbstate_t &, + const char * from, + const char * from_end, + std::size_t max_limit +) const throw() +{ + // RG - this code is confusing! I need a better way to express it. + // and test cases. + + // Invariants: + // 1) last_octet_count has the size of the last measured character + // 2) char_count holds the number of characters shown to fit + // within the bounds so far (no greater than max_limit) + // 3) from_next points to the octet 'last_octet_count' before the + // last measured character. + int last_octet_count=0; + std::size_t char_count = 0; + const char* from_next = from; + // Use "<" because the buffer may represent incomplete characters + while (from_next+last_octet_count <= from_end && char_count <= max_limit) { + from_next += last_octet_count; + last_octet_count = (get_octet_count(*from_next)); + ++char_count; + } + return boost::numeric_cast<int>(from_next - from_end); +} + +unsigned int utf8_codecvt_facet_wchar_t::get_octet_count( + unsigned char lead_octet +){ + // if the 0-bit (MSB) is 0, then 1 character + if (lead_octet <= 0x7f) return 1; + + // Otherwise the count number of consecutive 1 bits starting at MSB + assert(0xc0 <= lead_octet && lead_octet <= 0xfd); + + if (0xc0 <= lead_octet && lead_octet <= 0xdf) return 2; + else if (0xe0 <= lead_octet && lead_octet <= 0xef) return 3; + else if (0xf0 <= lead_octet && lead_octet <= 0xf7) return 4; + else if (0xf8 <= lead_octet && lead_octet <= 0xfb) return 5; + else return 6; +} + +namespace { +template<std::size_t s> +int get_cont_octet_out_count_impl(wchar_t word){ + if (word < 0x80) { + return 0; + } + if (word < 0x800) { + return 1; + } + return 2; +} + +// note the following code will generate on some platforms where +// wchar_t is defined as UCS2. The warnings are superfluous as +// the specialization is never instantitiated with such compilers. +template<> +int get_cont_octet_out_count_impl<4>(wchar_t word) +{ + if (word < 0x80) { + return 0; + } + if (word < 0x800) { + return 1; + } + if (word < 0x10000) { + return 2; + } + if (word < 0x200000) { + return 3; + } + if (word < 0x4000000) { + return 4; + } + return 5; +} + +} // namespace anonymous + +// How many "continuing octets" will be needed for this word +// == total octets - 1. +int utf8_codecvt_facet_wchar_t::get_cont_octet_out_count( + wchar_t word +) const { + return get_cont_octet_out_count_impl<sizeof(wchar_t)>(word); +} + +#if 0 // not used? +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation for char + +std::codecvt_base::result utf8_codecvt_facet_char::do_in( + std::mbstate_t & state, + const char * from, + const char * from_end, + const char * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + while(from_next < from_end){ + wchar_t w; + wchar_t *wnext = & w; + utf8_codecvt_facet_wchar_t::result ucs4_result; + ucs4_result = base_class::do_in( + state, + from, from_end, from_next, + wnext, wnext + 1, wnext + ); + if(codecvt_base::ok != ucs4_result) + return ucs4_result; + // if the conversion succeeds. + int length = std::wctomb(to_next, w); + assert(-1 != length); + to_next += length; + } + return codecvt_base::ok; +} + +std::codecvt_base::result utf8_codecvt_facet_char::do_out( + mbstate_t & state, + const char * from, + const char * from_end, + const char * & from_next, + char * to, + char * to_end, + char * & to_next +) const +{ + while(from_next < from_end){ + wchar_t w; + int result = std::mbtowc(&w, from_next, MB_LENGTH_MAX); + assert(-1 != result); + from_next += result; + utf8_codecvt_facet_wchar_t::result ucs4_result; + + const wchar_t *wptr = & w; + ucs4_result = base_class::do_out( + state, + wptr, wptr+1, wptr, + to_next, to_end, to_next + ); + if(codecvt_base::ok != ucs4_result) + return ucs4_result; + } + return codecvt_base::ok; +} + +// How many bytes objects can I process to get <= max_limit +// char objects? +int utf8_codecvt_facet_char::do_length( + // it seems that the standard doesn't use const so these librarires + // would be in error + BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER + utf8_codecvt_facet_wchar_t::mbstate_t & initial_state, + const char * from_next, + const char * from_end, + std::size_t max_limit +) const +{ + int total_length = 0; + const char *from = from_next; + mbstate_t state = initial_state; + while(from_next < from_end){ + wchar_t w; + wchar_t *wnext = & w; + utf8_codecvt_facet_wchar_t::result ucs4_result; + ucs4_result = base_class::do_in( + state, + from_next, from_end, from_next, + wnext, wnext + 1, wnext + ); + + if(codecvt_base::ok != ucs4_result) + break; + + char carray[MB_LENGTH_MAX]; + std::size_t count = wctomb(carray, w); + if(count > max_limit) + break; + + max_limit -= count; + total_length = from_next - from; + } + return total_length; +} +#endif + +#endif //BOOST_IOSTREAMS_NO_WIDE_STREAMS diff --git a/src/boost/libs/iostreams/test/detail/utf8_codecvt_facet.hpp b/src/boost/libs/iostreams/test/detail/utf8_codecvt_facet.hpp new file mode 100644 index 00000000..3a8910bb --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/utf8_codecvt_facet.hpp @@ -0,0 +1,200 @@ +#ifndef BOOST_UTF8_CODECVT_FACET_HPP +#define BOOST_UTF8_CODECVT_FACET_HPP + +#include <boost/iostreams/detail/config/wide_streams.hpp> +#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS +# error wide streams not supported on this platform +#endif + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// utf8_codecvt_facet.hpp + +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Note:(Robert Ramey). I have made the following alterations in the original +// code. +// a) Rendered utf8_codecvt<wchar_t, char> with using templates +// b) Move longer functions outside class definition to prevent inlining +// and make code smaller +// c) added on a derived class to permit translation to/from current +// locale to utf8 + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream<OStream::char_type> but rather +// use two template parameters +// +// utf8_codecvt_facet +// This is an implementation of a std::codecvt facet for translating +// from UTF-8 externally to UCS-4. Note that this is not tied to +// any specific types in order to allow customization on platforms +// where wchar_t is not big enough. +// +// NOTES: The current implementation jumps through some unpleasant hoops in +// order to deal with signed character types. As a std::codecvt_base::result, +// it is necessary for the ExternType to be convertible to unsigned char. +// I chose not to tie the extern_type explicitly to char. But if any combination +// of types other than <wchar_t,char_t> is used, then std::codecvt must be +// specialized on those types for this to work. + +#include <locale> +#include <cstddef> // size_t +#include <cwchar> // mbstate_t +#include <boost/integer_traits.hpp> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include <boost/iostreams/detail/codecvt_helper.hpp> + +// maximum lenght of a multibyte string +#define MB_LENGTH_MAX 8 + +struct utf8_codecvt_facet_wchar_t + : public boost::iostreams::detail::codecvt_helper<wchar_t, char, std::mbstate_t> +{ +public: + explicit utf8_codecvt_facet_wchar_t(std::size_t no_locale_manage = 0) + : boost::iostreams::detail::codecvt_helper<wchar_t, char, std::mbstate_t> + (no_locale_manage) + { } +protected: + virtual std::codecvt_base::result do_in( + std::mbstate_t& state, + const char * from, + const char * from_end, + const char * & from_next, + wchar_t * to, + wchar_t * to_end, + wchar_t*& to_next + ) const; + + virtual std::codecvt_base::result do_out( + std::mbstate_t & state, const wchar_t * from, + const wchar_t * from_end, const wchar_t* & from_next, + char * to, char * to_end, char * & to_next + ) const; + + bool invalid_continuing_octet(unsigned char octet_1) const { + return (octet_1 < 0x80|| 0xbf< octet_1); + } + + bool invalid_leading_octet(unsigned char octet_1) const { + return (0x7f < octet_1 && octet_1 < 0xc0) || + (octet_1 > 0xfd); + } + + // continuing octets = octets except for the leading octet + static unsigned int get_cont_octet_count(unsigned char lead_octet) { + return get_octet_count(lead_octet) - 1; + } + + static unsigned int get_octet_count(unsigned char lead_octet); + + // How many "continuing octets" will be needed for this word + // == total octets - 1. + int get_cont_octet_out_count(wchar_t word) const ; + + virtual bool do_always_noconv() const throw() { return false; } + + // UTF-8 isn't really stateful since we rewind on partial conversions + virtual std::codecvt_base::result do_unshift( + std::mbstate_t&, + char * from, + char * /* to */, + char * & next + ) const{ + next = from; + return ok; + } + + virtual int do_encoding() const throw() { + const int variable_byte_external_encoding=0; + return variable_byte_external_encoding; + } + + // How many char objects can I process to get <= max_limit + // wchar_t objects? + virtual int do_length( + BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER std::mbstate_t &, + const char * from, + const char * from_end, + std::size_t max_limit + ) const throw(); + + // Largest possible value do_length(state,from,from_end,1) could return. + virtual int do_max_length() const throw () { + return 6; // largest UTF-8 encoding of a UCS-4 character + } +}; + +#if 0 // not used - incorrect in any case +// Robert Ramey - use the above to make a code converter from multi-byte +// char strings to utf8 encoding +struct utf8_codecvt_facet_char : public utf8_codecvt_facet_wchar_t +{ + typedef utf8_codecvt_facet_wchar_t base_class; +public: + explicit utf8_codecvt_facet_char(std::size_t no_locale_manage=0) + : base_class(no_locale_manage) + {} +protected: + virtual std::codecvt_base::result do_in( + std::mbstate_t & state, + const char * from, + const char * from_end, + const char * & from_next, + char * to, + char * to_end, + char * & to_next + ) const; + + virtual std::codecvt_base::result do_out( + std::mbstate_t & state, + const char * from, + const char * from_end, + const char* & from_next, + char * to, + char * to_end, + char * & to_next + ) const; + + // How many char objects can I process to get <= max_limit + // char objects? + virtual int do_length( + const std::mbstate_t&, + const char * from, + const char * from_end, + std::size_t max_limit + ) const; +}; +#endif + +template<class Internal, class External> +struct utf8_codecvt_facet +{}; + +template<> +struct utf8_codecvt_facet<wchar_t, char> + : public utf8_codecvt_facet_wchar_t +{}; + +#if 0 +template<> +struct utf8_codecvt_facet<char, char> + : public utf8_codecvt_facet_char +{}; +#endif + +#endif // BOOST_UTF8_CODECVT_FACET_HPP + diff --git a/src/boost/libs/iostreams/test/detail/verification.hpp b/src/boost/libs/iostreams/test/detail/verification.hpp new file mode 100644 index 00000000..6f056c2b --- /dev/null +++ b/src/boost/libs/iostreams/test/detail/verification.hpp @@ -0,0 +1,383 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + + +#ifndef BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED + +#include <iostream> +#include <exception> +#include <string> +#include <string.h> +#include <fstream> +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# include <istream> +# include <ostream> +#else +# include <iostream.h> +#endif + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/detail/char_traits.hpp> +#include <boost/iostreams/detail/config/wide_streams.hpp> +#include "./constants.hpp" + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> + +// Code generation bugs cause tests to fail with global optimization. +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# pragma optimize("g", off) +#endif + +// Included only by tests; no need to #undef. +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# define BOOST_TEMPLATE_DECL template<typename Ch, typename Tr> +# define BOOST_CHAR Ch +# define BOOST_ISTREAM std::basic_istream<Ch, Tr> +# define BOOST_OSTREAM std::basic_ostream<Ch, Tr> +#else +# define BOOST_TEMPLATE_DECL +# define BOOST_CHAR char +# define BOOST_ISTREAM std::istream +# define BOOST_OSTREAM std::ostream +#endif + +namespace boost { namespace iostreams { namespace test { + +BOOST_TEMPLATE_DECL +bool compare_streams_in_chars(BOOST_ISTREAM& first, BOOST_ISTREAM& second) +{ + for (int z = 0; z < data_reps; ++z) + for (int w = 0; w < data_length(); ++w) + if (first.eof() != second.eof() || first.get() != second.get()) + return false; + return true; +} + +BOOST_TEMPLATE_DECL +bool compare_streams_in_chunks(BOOST_ISTREAM& first, BOOST_ISTREAM& second) +{ + int i = 0; + do { + BOOST_CHAR buf_one[chunk_size]; + BOOST_CHAR buf_two[chunk_size]; + first.read(buf_one, chunk_size); + second.read(buf_two, chunk_size); + std::streamsize amt = first.gcount(); + if ( amt != static_cast<std::streamsize>(second.gcount()) || + BOOST_IOSTREAMS_CHAR_TRAITS(BOOST_CHAR):: + compare(buf_one, buf_two, static_cast<std::size_t>(amt)) != 0 ) + return false; + ++i; + } while (!first.eof()); + return true; +} + +bool compare_files(const std::string& first, const std::string& second) +{ + using namespace std; + ifstream one(first.c_str(), BOOST_IOS::in | BOOST_IOS::binary); + ifstream two(second.c_str(), BOOST_IOS::in | BOOST_IOS::binary); + return compare_streams_in_chunks(one, two); +} + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES + template<typename Container, typename Ch, typename Tr> +#else + template<typename Container> +#endif +bool compare_container_and_stream(Container& cnt, BOOST_ISTREAM& is) +{ + typename Container::iterator first = cnt.begin(); + typename Container::iterator last = cnt.end(); + do { + if ((first == last) != is.eof()) return false; + if (first != last && *first++ != is.get()) return false; + } while (first != last); + return true; +} + +template<typename Container> +bool compare_container_and_file(Container& cnt, const std::string& file) +{ + std::ifstream fstrm(file.c_str(), BOOST_IOS::in | BOOST_IOS::binary); + return compare_container_and_stream(cnt, fstrm); +} + +BOOST_TEMPLATE_DECL +void write_data_in_chars(BOOST_OSTREAM& os) +{ + for (int z = 0; z < data_reps; ++z) + for (int w = 0; w < data_length(); ++w) + os.put(detail::data((BOOST_CHAR*)0)[w]); + os.flush(); +} + +BOOST_TEMPLATE_DECL +void write_data_in_chunks(BOOST_OSTREAM& os) +{ + const BOOST_CHAR* buf = detail::data((BOOST_CHAR*)0); + for (int z = 0; z < data_reps; ++z) + os.write(buf, data_length()); + os.flush(); +} + +bool test_seekable_in_chars(std::iostream& io) +{ + int i; // old 'for' scope workaround. + + // Test seeking with ios::cur + for (i = 0; i < data_reps; ++i) { + int j; + for (j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(-chunk_size, BOOST_IOS::cur); + for (j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(-chunk_size, BOOST_IOS::cur); + for (j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + } + + // Test seeking with ios::beg + std::streamoff off = 0; + io.seekp(0, BOOST_IOS::beg); + for (i = 0; i < data_reps; ++i, off += chunk_size) { + int j; + for (j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(off, BOOST_IOS::beg); + for (j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(off, BOOST_IOS::beg); + for (j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + } + + // Test seeking with ios::end + io.seekp(0, BOOST_IOS::end); + off = io.tellp(); + io.seekp(-off, BOOST_IOS::end); + for (i = 0; i < data_reps; ++i, off -= chunk_size) { + int j; + for (j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(-off, BOOST_IOS::end); + for (j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(-off, BOOST_IOS::end); + for (j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + } + return true; +} + +bool test_seekable_in_chunks(std::iostream& io) +{ + int i; // old 'for' scope workaround. + + // Test seeking with ios::cur + for (i = 0; i < data_reps; ++i) { + io.write(narrow_data(), chunk_size); + io.seekp(-chunk_size, BOOST_IOS::cur); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + io.seekg(-chunk_size, BOOST_IOS::cur); + io.write(narrow_data(), chunk_size); + } + + // Test seeking with ios::beg + std::streamoff off = 0; + io.seekp(0, BOOST_IOS::beg); + for (i = 0; i < data_reps; ++i, off += chunk_size) { + io.write(narrow_data(), chunk_size); + io.seekp(off, BOOST_IOS::beg); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + io.seekg(off, BOOST_IOS::beg); + io.write(narrow_data(), chunk_size); + } + + // Test seeking with ios::end + io.seekp(0, BOOST_IOS::end); + off = io.tellp(); + io.seekp(-off, BOOST_IOS::end); + for (i = 0; i < data_reps; ++i, off -= chunk_size) { + io.write(narrow_data(), chunk_size); + io.seekp(-off, BOOST_IOS::end); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + io.seekg(-off, BOOST_IOS::end); + io.write(narrow_data(), chunk_size); + } + return true; +} + +bool test_input_seekable(std::istream& io) +{ + int i; // old 'for' scope workaround. + + // Test seeking with ios::cur + for (i = 0; i < data_reps; ++i) { + for (int j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(-chunk_size, BOOST_IOS::cur); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + } + + // Test seeking with ios::beg + std::streamoff off = 0; + io.seekg(0, BOOST_IOS::beg); + for (i = 0; i < data_reps; ++i, off += chunk_size) { + for (int j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(off, BOOST_IOS::beg); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + } + + // Test seeking with ios::end + io.seekg(0, BOOST_IOS::end); + off = io.tellg(); + io.seekg(-off, BOOST_IOS::end); + for (i = 0; i < data_reps; ++i, off -= chunk_size) { + for (int j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(-off, BOOST_IOS::end); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + } + return true; +} + +bool test_output_seekable(std::ostream& io) +{ + int i; // old 'for' scope workaround. + + // Test seeking with ios::cur + for (i = 0; i < data_reps; ++i) { + for (int j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(-chunk_size, BOOST_IOS::cur); + io.write(narrow_data(), chunk_size); + } + + // Test seeking with ios::beg + std::streamoff off = 0; + io.seekp(0, BOOST_IOS::beg); + for (i = 0; i < data_reps; ++i, off += chunk_size) { + for (int j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(off, BOOST_IOS::beg); + io.write(narrow_data(), chunk_size); + } + + // Test seeking with ios::end + io.seekp(0, BOOST_IOS::end); + off = io.tellp(); + io.seekp(-off, BOOST_IOS::end); + for (i = 0; i < data_reps; ++i, off -= chunk_size) { + for (int j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(-off, BOOST_IOS::end); + io.write(narrow_data(), chunk_size); + } + return true; +} + +bool test_dual_seekable(std::iostream& io) +{ + int i; // old 'for' scope workaround. + + // Test seeking with ios::cur + for (i = 0; i < data_reps; ++i) { + for (int j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(-chunk_size, BOOST_IOS::cur); + for (int j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(-chunk_size, BOOST_IOS::cur); + io.write(narrow_data(), chunk_size); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + } + + // Test seeking with ios::beg + std::streamoff off = 0; + io.seekp(0, BOOST_IOS::beg); + io.seekg(0, BOOST_IOS::beg); + for (i = 0; i < data_reps; ++i, off += chunk_size) { + for (int j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(off, BOOST_IOS::beg); + for (int j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(off, BOOST_IOS::beg); + io.write(narrow_data(), chunk_size); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + } + + // Test seeking with ios::end + io.seekp(0, BOOST_IOS::end); + io.seekg(0, BOOST_IOS::end); + off = io.tellp(); + io.seekp(-off, BOOST_IOS::end); + io.seekg(-off, BOOST_IOS::end); + for (i = 0; i < data_reps; ++i, off -= chunk_size) { + for (int j = 0; j < chunk_size; ++j) + io.put(narrow_data()[j]); + io.seekp(-off, BOOST_IOS::end); + for (int j = 0; j < chunk_size; ++j) + if (io.get() != narrow_data()[j]) + return false; + io.seekg(-off, BOOST_IOS::end); + io.write(narrow_data(), chunk_size); + char buf[chunk_size]; + io.read(buf, chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + } + return true; +} + +} } } // End namespaces test, iostreams, boost. + +#include <boost/iostreams/detail/config/enable_warnings.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# pragma optimize("", on) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/direct_adapter_test.cpp b/src/boost/libs/iostreams/test/direct_adapter_test.cpp new file mode 100644 index 00000000..ec84329c --- /dev/null +++ b/src/boost/libs/iostreams/test/direct_adapter_test.cpp @@ -0,0 +1,111 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <algorithm> // equal. +#include <fstream> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/detail/adapter/direct_adapter.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void direct_adapter_test() +{ + + typedef boost::iostreams::detail::direct_adapter<array_source> + indirect_array_source; + typedef boost::iostreams::detail::direct_adapter<array_sink> + indirect_array_sink; + typedef boost::iostreams::detail::direct_adapter<boost::iostreams::array> + indirect_array; + typedef stream<indirect_array_source> + indirect_array_istream; + typedef stream<indirect_array_sink> + indirect_array_ostream; + typedef stream<indirect_array> + indirect_array_stream; + + test_file test; + test_sequence<> seq; + + //--------------indirect_array_istream------------------------------------// + + { + indirect_array_istream first(&seq[0], &seq[0] + seq.size()); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from indirect_array_istream in chars" + ); + } + + { + indirect_array_istream first(&seq[0], &seq[0] + seq.size()); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from indirect_array_istream in chunks" + ); + } + + //--------------indirect_array_ostream------------------------------------// + + { + vector<char> dest(data_reps * data_length(), '?'); + indirect_array_ostream out(&dest[0], &dest[0] + dest.size()); + write_data_in_chars(out); + BOOST_CHECK_MESSAGE( + std::equal(seq.begin(), seq.end(), dest.begin()), + "failed writing to indirect_array_ostream in chunks" + ); + } + + { + vector<char> dest(data_reps * data_length(), '?'); + indirect_array_ostream out(&dest[0], &dest[0] + dest.size()); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + std::equal(seq.begin(), seq.end(), dest.begin()), + "failed writing to indirect_array_ostream in chunks" + ); + } + + //--------------indirect_array_stream-------------------------------------// + + { + vector<char> test(data_reps * data_length(), '?'); + indirect_array_stream io(&test[0], &test[0] + test.size()); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within indirect_array_stream, in chars" + ); + } + + { + vector<char> test(data_reps * data_length(), '?'); + indirect_array_stream io(&test[0], &test[0] + test.size()); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within indirect_array_stream, in chunks" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("direct_adapter test"); + test->add(BOOST_TEST_CASE(&direct_adapter_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/dual_seekable_test.cpp b/src/boost/libs/iostreams/test/dual_seekable_test.cpp new file mode 100644 index 00000000..c0b9c66f --- /dev/null +++ b/src/boost/libs/iostreams/test/dual_seekable_test.cpp @@ -0,0 +1,178 @@ +// (C) Copyright 2014 Jorge Lodos +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <sstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void verification_function_seekable_test() +{ + { + temp_file f; + fstream io(f.name().c_str(), BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::binary | BOOST_IOS::trunc); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed using test_seekable_in_chars" + ); + io.close(); + } + + { + temp_file f; + fstream io(f.name().c_str(), BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::binary | BOOST_IOS::trunc); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed using test_seekable_in_chunks" + ); + io.close(); + } + + { + temp_file f; + fstream io(f.name().c_str(), BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::binary | BOOST_IOS::trunc); + for (int i = 0; i < data_reps; ++i) + io.write(narrow_data(), chunk_size); + io.seekg(0, BOOST_IOS::beg); + BOOST_CHECK_MESSAGE( + test_input_seekable(io), + "failed using test_input_seekable" + ); + io.close(); + } + + { + temp_file f; + fstream io(f.name().c_str(), BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::binary | BOOST_IOS::trunc); + BOOST_CHECK_MESSAGE( + test_output_seekable(io), + "failed using test_output_seekable" + ); + io.close(); + } +} + +void verification_function_dual_seekable_test() +{ + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(ss), + "failed using test_seekable_in_chars" + ); + } + + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(ss), + "failed using test_seekable_in_chunks" + ); + } + + { + string s; + for (int i = 0; i < data_reps; ++i) + s.append(narrow_data(), chunk_size); + stringstream ss(s, BOOST_IOS::in | BOOST_IOS::out); + BOOST_CHECK_MESSAGE( + test_input_seekable(ss), + "failed using test_input_seekable" + ); + } + + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + BOOST_CHECK_MESSAGE( + test_output_seekable(ss), + "failed using test_output_seekable" + ); + } + + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + BOOST_CHECK_MESSAGE( + test_dual_seekable(ss), + "failed using test_dual_seekable" + ); + } +} + +void dual_seekable_test() +{ + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + filtering_stream<dual_seekable> io(ss); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within a string, in chars" + ); + } + + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + filtering_stream<dual_seekable> io(ss); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within a string, in chunks" + ); + } + + { + string s; + for (int i = 0; i < data_reps; ++i) + s.append(narrow_data(), chunk_size); + stringstream ss(s, BOOST_IOS::in | BOOST_IOS::out); + filtering_stream<dual_seekable> io(ss); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_input_seekable(io), + "failed seeking within a string source" + ); + } + + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + filtering_stream<dual_seekable> io(ss); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_output_seekable(io), + "failed seeking within a string sink" + ); + } + + { + stringstream ss(BOOST_IOS::in | BOOST_IOS::out); + filtering_stream<dual_seekable> io(ss); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_dual_seekable(io), + "failed dual seeking within a string" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("dual seekable test"); + test->add(BOOST_TEST_CASE(&verification_function_seekable_test)); + test->add(BOOST_TEST_CASE(&verification_function_dual_seekable_test)); + test->add(BOOST_TEST_CASE(&dual_seekable_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/example_test.cpp b/src/boost/libs/iostreams/test/example_test.cpp new file mode 100644 index 00000000..24384422 --- /dev/null +++ b/src/boost/libs/iostreams/test/example_test.cpp @@ -0,0 +1,461 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <map> +#include <boost/iostreams/detail/ios.hpp> // failure. +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "../example/container_device.hpp" +#include "../example/dictionary_filter.hpp" +#include "../example/line_wrapping_filter.hpp" +#include "../example/shell_comments_filter.hpp" +#include "../example/tab_expanding_filter.hpp" +#include "../example/unix2dos_filter.hpp" +#include "./detail/verification.hpp" +#include "./detail/sequence.hpp" +#include "./detail/temp_file.hpp" + +using boost::unit_test::test_suite; +namespace io = boost::iostreams; +namespace ex = boost::iostreams::example; + +//------------------container_device test-------------------------------------// + +void container_device_test() +{ + using namespace std; + using namespace boost::iostreams::test; + + typedef vector<char> vector_type; + typedef ex::container_source<vector_type> vector_source; + typedef ex::container_sink<vector_type> vector_sink; + typedef ex::container_device<vector_type> vector_device; + + { + test_sequence<> seq; + test_file file; + io::stream<vector_source> first(seq); + io::stream<io::file_source> second(file.name(), in_mode); + BOOST_CHECK(compare_streams_in_chunks(first, second)); + } + + { + std::vector<char> first; + test_sequence<> second; + io::stream<vector_sink> out(first); + write_data_in_chunks(out); + BOOST_CHECK(first == second); + } + + { + vector<char> v; + io::stream<vector_device> io(v); + BOOST_CHECK(test_seekable_in_chunks(io)); + } +} + +//------------------dictionary_filter test------------------------------------// + +void dictionary_filter_test() +{ + using namespace std; + + io::example::dictionary d; + + // See http://english2american.com. + d.add("answerphone", "answering machine"); + d.add("bloke", "guy"); + d.add("gearbox", "transmission"); + d.add("ironmonger", "hardware shop"); + d.add("loo", "restroom"); + d.add("lorry", "truck"); + d.add("rubber", "eraser"); + d.add("spanner", "monkey wrench"); + d.add("telly", "TV"); + d.add("tyre", "tire"); + d.add("waistcoat", "vest"); + d.add("windscreen", "windshield"); + + const std::string input = // Note: last character is non-alphabetic. + "I had a message on my answerphone from the bloke at the car " + "dealership that the windscreen and tyre on my lorry were replaced. " + "However, the gearbox would not be ready until tomorrow since the " + "spanner that they needed was broken and they had to go to the " + "ironmonger to buy a replacement. Since my lorry was not ready, " + "I decided to take the bus downtown and buy a new waistcoat. I " + "also stopped at the liquor store to buy some wine. I came home " + "and watched the telly and drank my wine. I also worked on a " + "crossword puzzle. Fortunately I had a pencil with a new rubber. " + "During that evening I made frequent trips to the loo due to my " + "excessive drinking"; + + const std::string output = // Note: last character is non-alphabetic. + "I had a message on my answering machine from the guy at the car " + "dealership that the windshield and tire on my truck were replaced. " + "However, the transmission would not be ready until tomorrow since " + "the monkey wrench that they needed was broken and they had to go to " + "the hardware shop to buy a replacement. Since my truck was not ready, " + "I decided to take the bus downtown and buy a new vest. I also stopped " + "at the liquor store to buy some wine. I came home and watched the TV " + "and drank my wine. I also worked on a crossword puzzle. Fortunately I " + "had a pencil with a new eraser. During that evening I made frequent " + "trips to the restroom due to my excessive drinking"; + + BOOST_CHECK( + io::test_input_filter( io::example::dictionary_stdio_filter(d), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::dictionary_stdio_filter(d), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::dictionary_input_filter(d), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::dictionary_output_filter(d), + input, output ) + ); +} + +//------------------line_wrapping_filter test---------------------------------// + +void line_wrapping_filter_test() +{ + using namespace std; + + const std::string input = + "I had a message on my answerphone from the bloke at the car \n" + "dealership that the windscreen and tyre on my lorry were replaced. \n" + "However, the gearbox would not be ready until tomorrow since the \n" + "spanner that they needed was broken and they had to go to the \n" + "ironmonger to buy a replacement. Since my lorry was not ready, \n" + "I decided to take the bus downtown and buy a new waistcoat. I \n" + "also stopped at the liquor store to buy some wine. I came home \n" + "and watched the telly and drank my wine. I also worked on a \n" + "crossword puzzle. Fortunately I had a pencil with a new rubber. \n" + "During that evening I made frequent trips to the loo due to my \n" + "excessive drinking."; + + const std::string output = + "I had a message on my answerphone from t\n" + "he bloke at the car \n" + "dealership that the windscreen and tyre \n" + "on my lorry were replaced. \n" + "However, the gearbox would not be ready \n" + "until tomorrow since the \n" + "spanner that they needed was broken and \n" + "they had to go to the \n" + "ironmonger to buy a replacement. Since m\n" + "y lorry was not ready, \n" + "I decided to take the bus downtown and b\n" + "uy a new waistcoat. I \n" + "also stopped at the liquor store to buy \n" + "some wine. I came home \n" + "and watched the telly and drank my wine.\n" + " I also worked on a \n" + "crossword puzzle. Fortunately I had a pe\n" + "ncil with a new rubber. \n" + "During that evening I made frequent trip\n" + "s to the loo due to my \n" + "excessive drinking."; + + BOOST_CHECK( + io::test_input_filter( io::example::line_wrapping_stdio_filter(40), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::line_wrapping_stdio_filter(40), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::line_wrapping_input_filter(40), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::line_wrapping_output_filter(40), + input, output ) + ); +} + +//------------------shell_comments_filter test--------------------------------// + +void shell_comments_filter_test() +{ + using namespace std; + + const std::string input = // From <libs/filesystem/build/Jamfile>. + "lib boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : # build requirements\n" + " [ common-names ] # magic for install and auto-link features\n" + " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n" + " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n" + " : debug release # build variants\n" + " ;\n" + "\n" + "dll boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : # build requirements\n" + " [ common-names ] # magic for install and auto-link features\n" + " <define>BOOST_FILESYSTEM_DYN_LINK=1 # tell source we're building dll's\n" + " <runtime-link>dynamic # build only for dynamic runtimes\n" + " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n" + " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n" + " : debug release # build variants\n" + " ;"; + + const std::string output = + "lib boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : \n" + " [ common-names ] \n" + " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n" + " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n" + " : debug release \n" + " ;\n" + "\n" + "dll boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : \n" + " [ common-names ] \n" + " <define>BOOST_FILESYSTEM_DYN_LINK=1 \n" + " <runtime-link>dynamic \n" + " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n" + " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n" + " : debug release \n" + " ;"; + + BOOST_CHECK( + io::test_input_filter( io::example::shell_comments_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::shell_comments_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::shell_comments_input_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::shell_comments_output_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::shell_comments_dual_use_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::shell_comments_dual_use_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::shell_comments_multichar_input_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::shell_comments_multichar_output_filter(), + input, output ) + ); +} + +//------------------tab_expanding_filter test---------------------------------// + +void tab_expanding_filter_test() +{ + using namespace std; + + const std::string input = + "class tab_expanding_stdio_filter : public stdio_filter {\n" + "public:\n" + "\texplicit tab_expanding_stdio_filter(int\ttab_size = 8)\n" + "\t\t: tab_size_(tab_size), col_no_(0)\n" + "\t{\n" + "\t\tassert(tab_size\t> 0);\n" + "\t}\n" + "private:\n" + "\tvoid do_filter()\n" + "\t{\n" + "\t\tint\tc;\n" + "\t\twhile ((c = std::cin.get()) != EOF) {\n" + "\t\t\tif (c == '\\t') {\n" + "\t\t\t\tint\tspaces = tab_size_ - (col_no_ %\ttab_size_);\n" + "\t\t\t\tfor\t(; spaces >\t0; --spaces)\n" + "\t\t\t\t\tput_char(' ');\n" + "\t\t\t} else {\n" + "\t\t\t\tput_char(c);\n" + "\t\t\t}\n" + "\t\t}\n" + "\t}\n" + "\tvoid do_close()\t{ col_no_ =\t0; }\n" + "\tvoid put_char(int c)\n" + "\t{\n" + "\t\tstd::cout.put(c);\n" + "\t\tif (c == '\\n') {\n" + "\t\t\tcol_no_\t= 0;\n" + "\t\t} else {\n" + "\t\t\t++col_no_;\n" + "\t\t}\n" + "\t}\n" + "\tint\t tab_size_;\n" + "\tint\t col_no_;\n" + "};"; + + const std::string output = + "class tab_expanding_stdio_filter : public stdio_filter {\n" + "public:\n" + " explicit tab_expanding_stdio_filter(int tab_size = 8)\n" + " : tab_size_(tab_size), col_no_(0)\n" + " {\n" + " assert(tab_size > 0);\n" + " }\n" + "private:\n" + " void do_filter()\n" + " {\n" + " int c;\n" + " while ((c = std::cin.get()) != EOF) {\n" + " if (c == '\\t') {\n" + " int spaces = tab_size_ - (col_no_ % tab_size_);\n" + " for (; spaces > 0; --spaces)\n" + " put_char(' ');\n" + " } else {\n" + " put_char(c);\n" + " }\n" + " }\n" + " }\n" + " void do_close() { col_no_ = 0; }\n" + " void put_char(int c)\n" + " {\n" + " std::cout.put(c);\n" + " if (c == '\\n') {\n" + " col_no_ = 0;\n" + " } else {\n" + " ++col_no_;\n" + " }\n" + " }\n" + " int tab_size_;\n" + " int col_no_;\n" + "};"; + + BOOST_CHECK( + io::test_input_filter( io::example::tab_expanding_stdio_filter(4), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::tab_expanding_stdio_filter(4), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::tab_expanding_input_filter(4), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::tab_expanding_output_filter(4), + input, output ) + ); +} + +//------------------unix2dos_filter test--------------------------------------// + +void unix2dos_filter_test() +{ + using namespace std; + + const std::string input = + "When I was one-and-twenty\n" + "I heard a wise man say,\n" + "'Give crowns and pounds and guineas\n" + "But not your heart away;\n" + "\n" + "Give pearls away and rubies\n" + "But keep your fancy free.'\n" + "But I was one-and-twenty,\n" + "No use to talk to me.\n" + "\n" + "When I was one-and-twenty\n" + "I heard him say again,\n" + "'The heart out of the bosom\n" + "Was never given in vain;\n" + "'Tis paid with sighs a plenty\n" + "And sold for endless rue.'\n" + "And I am two-and-twenty,\n" + "And oh, 'tis true, 'tis true."; + + const std::string output = + "When I was one-and-twenty\r\n" + "I heard a wise man say,\r\n" + "'Give crowns and pounds and guineas\r\n" + "But not your heart away;\r\n" + "\r\n" + "Give pearls away and rubies\r\n" + "But keep your fancy free.'\r\n" + "But I was one-and-twenty,\r\n" + "No use to talk to me.\r\n" + "\r\n" + "When I was one-and-twenty\r\n" + "I heard him say again,\r\n" + "'The heart out of the bosom\r\n" + "Was never given in vain;\r\n" + "'Tis paid with sighs a plenty\r\n" + "And sold for endless rue.'\r\n" + "And I am two-and-twenty,\r\n" + "And oh, 'tis true, 'tis true."; + + BOOST_CHECK( + io::test_input_filter( io::example::unix2dos_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::unix2dos_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::unix2dos_input_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::unix2dos_output_filter(), + input, output ) + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("example test"); + test->add(BOOST_TEST_CASE(&container_device_test)); + test->add(BOOST_TEST_CASE(&dictionary_filter_test)); + test->add(BOOST_TEST_CASE(&tab_expanding_filter_test)); + test->add(BOOST_TEST_CASE(&line_wrapping_filter_test)); + test->add(BOOST_TEST_CASE(&shell_comments_filter_test)); + test->add(BOOST_TEST_CASE(&unix2dos_filter_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/execute_test.cpp b/src/boost/libs/iostreams/test/execute_test.cpp new file mode 100644 index 00000000..d477c679 --- /dev/null +++ b/src/boost/libs/iostreams/test/execute_test.cpp @@ -0,0 +1,660 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Tests the function templates boost::iostreams::detail::execute_all and + * boost::iostreams::detail::execute_foreach + * + * File: libs/iostreams/test/execute_test.cpp + * Date: Thu Dec 06 13:21:54 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#include <boost/iostreams/detail/execute.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::detail; +using boost::unit_test::test_suite; + +// Function object that sets a boolean flag and returns a value +// specified at construction +template<typename Result> +class operation { +public: + typedef Result result_type; + explicit operation(Result r, bool& executed) + : r_(r), executed_(executed) + { } + Result operator()() const + { + executed_ = true; + return r_; + } +private: + operation& operator=(const operation&); + Result r_; + bool& executed_; +}; + +// Specialization for void return +template<> +class operation<void> { +public: + typedef void result_type; + explicit operation(bool& executed) : executed_(executed) { } + void operator()() const { executed_ = true; } +private: + operation& operator=(const operation&); + bool& executed_; +}; + +// Simple exception class with error code built in to type +template<int Code> +struct error { }; + +// Function object that sets a boolean flag and throws an exception +template<int Code> +class thrower { +public: + typedef void result_type; + explicit thrower(bool& executed) : executed_(executed) { } + void operator()() const + { + executed_ = true; + throw error<Code>(); + } +private: + thrower& operator=(const thrower&); + bool& executed_; +}; + +// Function object for use by foreach_test +class foreach_func { +public: + typedef void result_type; + explicit foreach_func(int& count) : count_(count) { } + void operator()(int x) const + { + ++count_; + switch (x) { + case 0: throw error<0>(); + case 1: throw error<1>(); + case 2: throw error<2>(); + case 3: throw error<3>(); + case 4: throw error<4>(); + case 5: throw error<5>(); + case 6: throw error<6>(); + case 7: throw error<7>(); + case 8: throw error<8>(); + case 9: throw error<9>(); + default: + break; + } + } +private: + foreach_func& operator=(const foreach_func&); + int& count_; // Number of times operator() has been called +}; + +void success_test() +{ + // Test returning an int + { + bool executed = false; + BOOST_CHECK(execute_all(operation<int>(9, executed)) == 9); + BOOST_CHECK(executed); + } + + // Test returning void + { + bool executed = false; + execute_all(operation<void>(executed)); + BOOST_CHECK(executed); + } + + // Test returning an int with one cleanup operation + { + bool executed = false, cleaned_up = false; + BOOST_CHECK( + execute_all( + operation<int>(9, executed), + operation<void>(cleaned_up) + ) == 9 + ); + BOOST_CHECK(executed && cleaned_up); + } + + // Test returning void with one cleanup operation + { + bool executed = false, cleaned_up = false; + execute_all( + operation<void>(executed), + operation<void>(cleaned_up) + ); + BOOST_CHECK(executed && cleaned_up); + } + + // Test returning an int with two cleanup operations + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK( + execute_all( + operation<int>(9, executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2) + ) == 9 + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test returning void with two cleanup operations + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + execute_all( + operation<void>(executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2) + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test returning an int with three cleanup operations + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK( + execute_all( + operation<int>(9, executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2), + operation<void>(cleaned_up3) + ) == 9 + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test returning void with three cleanup operations + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + execute_all( + operation<void>(executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2), + operation<void>(cleaned_up3) + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } +} + +void operation_throws_test() +{ + // Test primary operation throwing with no cleanup operations + { + bool executed = false; + BOOST_CHECK_THROW( + execute_all(thrower<0>(executed)), + error<0> + ); + BOOST_CHECK(executed); + } + + // Test primary operation throwing with one cleanup operation + { + bool executed = false, cleaned_up = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + operation<void>(cleaned_up) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up); + } + + // Test primary operation throwing with two cleanup operations + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test primary operation throwing with three cleanup operations + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2), + operation<void>(cleaned_up3) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } +} + +void cleanup_throws_test() +{ + // Test single cleanup operation that throws + { + bool executed = false, cleaned_up = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up); + } + + // Test fist of two cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up1), + operation<void>(cleaned_up2) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test second of two cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + operation<void>(cleaned_up1), + thrower<2>(cleaned_up2) + ), + error<2> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test first of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up1), + operation<void>(cleaned_up2), + operation<void>(cleaned_up3) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test second of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + operation<void>(cleaned_up1), + thrower<2>(cleaned_up2), + operation<void>(cleaned_up3) + ), + error<2> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test third of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2), + thrower<3>(cleaned_up3) + ), + error<3> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } +} + +void multiple_exceptions_test() +{ + // Test primary operation and cleanup operation throwing + { + bool executed = false, cleaned_up = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + thrower<1>(cleaned_up) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up); + } + + // Test primary operation and first of two cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + thrower<1>(cleaned_up1), + operation<void>(cleaned_up2) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test primary operation and second of two cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + operation<void>(cleaned_up1), + thrower<2>(cleaned_up2) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test two cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, cleaned_up2 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up1), + thrower<2>(cleaned_up2) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2); + } + + // Test primary operation and first of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + thrower<1>(cleaned_up1), + operation<void>(cleaned_up2), + operation<void>(cleaned_up3) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test primary operation and second of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + operation<void>(cleaned_up1), + thrower<2>(cleaned_up2), + operation<void>(cleaned_up3) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test primary operation and third of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + thrower<0>(executed), + operation<void>(cleaned_up1), + operation<void>(cleaned_up2), + thrower<3>(cleaned_up3) + ), + error<0> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test first and second of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up1), + thrower<2>(cleaned_up2), + operation<void>(cleaned_up3) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test first and third of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up1), + operation<void>(cleaned_up2), + thrower<3>(cleaned_up3) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test second and third of three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + operation<void>(cleaned_up1), + thrower<2>(cleaned_up2), + thrower<3>(cleaned_up3) + ), + error<2> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } + + // Test three cleanup operations throwing + { + bool executed = false, cleaned_up1 = false, + cleaned_up2 = false, cleaned_up3 = false; + BOOST_CHECK_THROW( + execute_all( + operation<void>(executed), + thrower<1>(cleaned_up1), + thrower<2>(cleaned_up2), + thrower<3>(cleaned_up3) + ), + error<1> + ); + BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3); + } +} + +#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])) + +void foreach_test() +{ + // Test case where neither of two operations throws + { + int count = 0; + int seq[] = {-1, -1}; + BOOST_CHECK_NO_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)) + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where first of two operations throws + { + int count = 0; + int seq[] = {0, -1}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<0> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where second of two operations throws + { + int count = 0; + int seq[] = {-1, 1}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<1> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where both of two operations throw + { + int count = 0; + int seq[] = {0, 1}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<0> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where none of three operations throws + { + int count = 0; + int seq[] = {-1, -1, -1}; + BOOST_CHECK_NO_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)) + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where first of three operations throw + { + int count = 0; + int seq[] = {0, -1, -1}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<0> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where second of three operations throw + { + int count = 0; + int seq[] = {-1, 1, -1}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<1> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where third of three operations throw + { + int count = 0; + int seq[] = {-1, -1, 2}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<2> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where first and second of three operations throw + { + int count = 0; + int seq[] = {0, 1, -1}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<0> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where first and third of three operations throw + { + int count = 0; + int seq[] = {0, -1, 2}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<0> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where second and third of three operations throw + { + int count = 0; + int seq[] = {-1, 1, 2}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<1> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } + + // Test case where three of three operations throw + { + int count = 0; + int seq[] = {0, 1, 2}; + BOOST_CHECK_THROW( + execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)), + error<0> + ); + BOOST_CHECK(count == ARRAY_SIZE(seq)); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("execute test"); + test->add(BOOST_TEST_CASE(&success_test)); + test->add(BOOST_TEST_CASE(&operation_throws_test)); + test->add(BOOST_TEST_CASE(&cleanup_throws_test)); + test->add(BOOST_TEST_CASE(&multiple_exceptions_test)); + test->add(BOOST_TEST_CASE(&foreach_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/file_descriptor_test.cpp b/src/boost/libs/iostreams/test/file_descriptor_test.cpp new file mode 100644 index 00000000..79757e52 --- /dev/null +++ b/src/boost/libs/iostreams/test/file_descriptor_test.cpp @@ -0,0 +1,626 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <fstream> +#include <fcntl.h> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" +#include "detail/file_handle.hpp" + +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +namespace boost_ios = boost::iostreams; +using std::ifstream; +using boost::unit_test::test_suite; + +void file_descriptor_test() +{ + + typedef stream<file_descriptor_source> fdistream; + typedef stream<file_descriptor_sink> fdostream; + typedef stream<file_descriptor> fdstream; + + test_file test1; + test_file test2; + + //--------------Test file_descriptor_source-------------------------------// + + { + fdistream first(file_descriptor_source(test1.name()), 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from file_descriptor_source in chars with no buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + { + fdistream first(file_descriptor_source(test1.name()), 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from file_descriptor_source in chunks with no buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + { + file_descriptor_source file(test1.name()); + fdistream first(file); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from file_descriptor_source in chars with buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + { + file_descriptor_source file(test1.name()); + fdistream first(file); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from file_descriptor_source in chunks with buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + // test illegal flag combinations + { + BOOST_CHECK_THROW( + file_descriptor_source(test1.name(), + BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_source(test1.name(), + BOOST_IOS::app | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_source(test1.name(), + BOOST_IOS::out), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_source(test1.name(), + BOOST_IOS::out | BOOST_IOS::app), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_source(test1.name(), + BOOST_IOS::out | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_source(test1.name(), + BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + } + + //--------------Test file_descriptor_sink---------------------------------// + + { + temp_file temp; + file_descriptor_sink file(temp.name(), BOOST_IOS::trunc); + fdostream out(file, 0); + BOOST_CHECK(out->is_open()); + write_data_in_chars(out); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chars with no buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + file_descriptor_sink file(temp.name(), BOOST_IOS::trunc); + fdostream out(file, 0); + BOOST_CHECK(out->is_open()); + write_data_in_chunks(out); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chunks with no buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + file_descriptor_sink file(temp.name(), BOOST_IOS::trunc); + fdostream out(file); + BOOST_CHECK(out->is_open()); + write_data_in_chars(out); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chars with buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + file_descriptor_sink file(temp.name(), BOOST_IOS::trunc); + fdostream out(file); + BOOST_CHECK(out->is_open()); + write_data_in_chunks(out); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chunks with buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + // set up the tests + { + file_descriptor_sink file(temp.name(), BOOST_IOS::trunc); + fdostream out(file); + write_data_in_chunks(out); + out.close(); + file.close(); + } + // test std::ios_base::app + { + file_descriptor_sink file(temp.name(), BOOST_IOS::app); + fdostream out(file); + BOOST_CHECK(out->is_open()); + write_data_in_chars(out); + out.close(); + std::string expected(narrow_data()); + expected += narrow_data(); + BOOST_CHECK_MESSAGE( + compare_container_and_file(expected, temp.name()), + "failed writing to file_descriptor_sink in append mode" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + // test std::ios_base::trunc + { + file_descriptor_sink file(temp.name(), BOOST_IOS::trunc); + fdostream out(file); + BOOST_CHECK(out->is_open()); + write_data_in_chars(out); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in trunc mode" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + // test illegal flag combinations + { + BOOST_CHECK_THROW( + file_descriptor_sink(temp.name(), + BOOST_IOS::trunc | BOOST_IOS::app), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_sink(temp.name(), + BOOST_IOS::in), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_sink(temp.name(), + BOOST_IOS::in | BOOST_IOS::app), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_sink(temp.name(), + BOOST_IOS::in | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor_sink(temp.name(), + BOOST_IOS::in | BOOST_IOS::trunc | BOOST_IOS::app), + BOOST_IOSTREAMS_FAILURE); + } + } + + //--Test seeking with file_descriptor_source and file_descriptor_sink-----// + + test_file test3; + { + file_descriptor_sink sink(test3.name()); + fdostream out(sink); + BOOST_CHECK(out->is_open()); + BOOST_CHECK_MESSAGE( + test_output_seekable(out), + "failed seeking within a file_descriptor_sink" + ); + out->close(); + BOOST_CHECK(!out->is_open()); + + file_descriptor_source source(test3.name()); + fdistream in(source); + BOOST_CHECK(in->is_open()); + BOOST_CHECK_MESSAGE( + test_input_seekable(in), + "failed seeking within a file_descriptor_source" + ); + in->close(); + BOOST_CHECK(!in->is_open()); + } + + //--------------Test file_descriptor--------------------------------------// + + { + temp_file temp; + file_descriptor file( temp.name(), + BOOST_IOS::in | + BOOST_IOS::out | + BOOST_IOS::trunc | + BOOST_IOS::binary ); + fdstream io(file, BUFSIZ); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within a file_descriptor, in chars" + ); + } + + { + temp_file temp; + file_descriptor file( temp.name(), + BOOST_IOS::in | + BOOST_IOS::out | + BOOST_IOS::trunc | + BOOST_IOS::binary ); + fdstream io(file, BUFSIZ); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within a file_descriptor, in chunks" + ); + } + + //--------------Test read-only file_descriptor----------------------------// + + { + fdstream first(file_descriptor(test1.name(), BOOST_IOS::in), 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + write_data_in_chars(first); + BOOST_CHECK(first.fail()); + first.clear(); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from file_descriptor in chars with no buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + { + fdstream first(file_descriptor(test1.name(), BOOST_IOS::in), 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + write_data_in_chunks(first); + BOOST_CHECK(first.fail()); + first.clear(); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from file_descriptor in chunks with no buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + { + file_descriptor file(test1.name(), BOOST_IOS::in); + fdstream first(file); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + write_data_in_chars(first); + BOOST_CHECK(first.fail()); + first.clear(); + first.seekg(0, BOOST_IOS::beg); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from file_descriptor in chars with buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + { + file_descriptor file(test1.name(), BOOST_IOS::in); + fdstream first(file); + ifstream second(test2.name().c_str()); + BOOST_CHECK(first->is_open()); + write_data_in_chunks(first); + BOOST_CHECK(first.fail()); + first.clear(); + first.seekg(0, BOOST_IOS::beg); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from file_descriptor in chunks with buffer" + ); + first->close(); + BOOST_CHECK(!first->is_open()); + } + + //--------------Test write-only file_descriptor---------------------------// + { + temp_file temp; + file_descriptor file( temp.name(), + BOOST_IOS::out | + BOOST_IOS::trunc ); + fdstream out(file, 0); + BOOST_CHECK(out->is_open()); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + write_data_in_chars(out); + out.seekg(0, BOOST_IOS::beg); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor in chars with no buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + file_descriptor file( temp.name(), + BOOST_IOS::out | + BOOST_IOS::trunc ); + fdstream out(file, 0); + BOOST_CHECK(out->is_open()); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + write_data_in_chunks(out); + out.seekg(0, BOOST_IOS::beg); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chunks with no buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + file_descriptor file( temp.name(), + BOOST_IOS::out | + BOOST_IOS::trunc ); + fdstream out(file); + BOOST_CHECK(out->is_open()); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + write_data_in_chars(out); + out.seekg(0, BOOST_IOS::beg); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chars with buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + { + temp_file temp; + file_descriptor file( temp.name(), + BOOST_IOS::out | + BOOST_IOS::trunc ); + fdstream out(file); + BOOST_CHECK(out->is_open()); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + write_data_in_chunks(out); + out.seekg(0, BOOST_IOS::beg); + out.get(); + BOOST_CHECK(out.fail()); + out.clear(); + out.close(); + BOOST_CHECK_MESSAGE( + compare_files(test1.name(), temp.name()), + "failed writing to file_descriptor_sink in chunks with buffer" + ); + file.close(); + BOOST_CHECK(!file.is_open()); + } + + // test illegal flag combinations + { + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::openmode(0)), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::app | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::in | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::in | BOOST_IOS::app | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + BOOST_CHECK_THROW( + file_descriptor(test1.name(), + BOOST_IOS::in | + BOOST_IOS::out | + BOOST_IOS::app | + BOOST_IOS::trunc), + BOOST_IOSTREAMS_FAILURE); + } +} + +template <class FileDescriptor> +void file_handle_test_impl(FileDescriptor*) +{ + test_file test1; + test_file test2; + + { + boost_ios::detail::file_handle handle = open_file_handle(test1.name()); + { + FileDescriptor device1(handle, boost_ios::never_close_handle); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_OPEN(handle); + close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = open_file_handle(test1.name()); + { + FileDescriptor device1(handle, boost_ios::close_handle); + BOOST_CHECK(device1.handle() == handle); + } + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle = open_file_handle(test1.name()); + FileDescriptor device1(handle, boost_ios::never_close_handle); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_OPEN(handle); + close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = open_file_handle(test1.name()); + FileDescriptor device1(handle, boost_ios::close_handle); + BOOST_CHECK(device1.handle() == handle); + device1.close(); + BOOST_CHECK(!device1.is_open()); + BOOST_CHECK_HANDLE_CLOSED(handle); + } + + { + boost_ios::detail::file_handle handle1 = open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = open_file_handle(test2.name()); + { + FileDescriptor device1(handle1, boost_ios::never_close_handle); + BOOST_CHECK(device1.handle() == handle1); + device1.open(handle2, boost_ios::never_close_handle); + BOOST_CHECK(device1.handle() == handle2); + } + BOOST_CHECK_HANDLE_OPEN(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + close_file_handle(handle1); + close_file_handle(handle2); + } + + { + boost_ios::detail::file_handle handle1 = open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = open_file_handle(test2.name()); + { + FileDescriptor device1(handle1, boost_ios::close_handle); + BOOST_CHECK(device1.handle() == handle1); + device1.open(handle2, boost_ios::close_handle); + BOOST_CHECK(device1.handle() == handle2); + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + } + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_CLOSED(handle2); + } + + { + boost_ios::detail::file_handle handle1 = open_file_handle(test1.name()); + boost_ios::detail::file_handle handle2 = open_file_handle(test2.name()); + { + FileDescriptor device1(handle1, boost_ios::close_handle); + BOOST_CHECK(device1.handle() == handle1); + device1.open(handle2, boost_ios::never_close_handle); + BOOST_CHECK(device1.handle() == handle2); + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + } + BOOST_CHECK_HANDLE_CLOSED(handle1); + BOOST_CHECK_HANDLE_OPEN(handle2); + close_file_handle(handle2); + } + + { + boost_ios::detail::file_handle handle = open_file_handle(test1.name()); + { + FileDescriptor device1; + BOOST_CHECK(!device1.is_open()); + device1.open(handle, boost_ios::never_close_handle); + BOOST_CHECK(device1.handle() == handle); + BOOST_CHECK_HANDLE_OPEN(handle); + } + BOOST_CHECK_HANDLE_OPEN(handle); + close_file_handle(handle); + } + + { + boost_ios::detail::file_handle handle = open_file_handle(test1.name()); + { + FileDescriptor device1; + BOOST_CHECK(!device1.is_open()); + device1.open(handle, boost_ios::close_handle); + BOOST_CHECK(device1.handle() == handle); + BOOST_CHECK_HANDLE_OPEN(handle); + } + BOOST_CHECK_HANDLE_CLOSED(handle); + } +} + +void file_handle_test() +{ + file_handle_test_impl((boost_ios::file_descriptor*) 0); + file_handle_test_impl((boost_ios::file_descriptor_source*) 0); + file_handle_test_impl((boost_ios::file_descriptor_sink*) 0); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("file_descriptor test"); + test->add(BOOST_TEST_CASE(&file_descriptor_test)); + test->add(BOOST_TEST_CASE(&file_handle_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/file_test.cpp b/src/boost/libs/iostreams/test/file_test.cpp new file mode 100644 index 00000000..ac5035bf --- /dev/null +++ b/src/boost/libs/iostreams/test/file_test.cpp @@ -0,0 +1,63 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/device/file.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using std::ifstream; +using boost::unit_test::test_suite; + +void file_test() +{ + test_file test; + + //--------------Test file_source------------------------------------------// + + { + file_source f(test.name()); + BOOST_CHECK(f.is_open()); + f.close(); + BOOST_CHECK(!f.is_open()); + f.open(test.name()); + BOOST_CHECK(f.is_open()); + } + + //--------------Test file_sink--------------------------------------------// + + { + file_sink f(test.name()); + BOOST_CHECK(f.is_open()); + f.close(); + BOOST_CHECK(!f.is_open()); + f.open(test.name()); + BOOST_CHECK(f.is_open()); + } + + //--------------Test file-------------------------------------------------// + + { + file f(test.name()); + BOOST_CHECK(f.is_open()); + f.close(); + BOOST_CHECK(!f.is_open()); + f.open(test.name()); + BOOST_CHECK(f.is_open()); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("file test"); + test->add(BOOST_TEST_CASE(&file_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/filter_test.cpp b/src/boost/libs/iostreams/test/filter_test.cpp new file mode 100644 index 00000000..0f1b7089 --- /dev/null +++ b/src/boost/libs/iostreams/test/filter_test.cpp @@ -0,0 +1,98 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <string> +#include <boost/iostreams/filter/test.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/filters.hpp" + +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +const std::string lower = + "in addition to providing an abstract framework the " + "library provides a number of concrete filters, sources " + "and sinks which serve as example applications of the " + "library but are also useful in their own right. these " + "include components for accessing memory-mapped files, " + "for file access via operating system file descriptors, " + "for code conversion, for text filtering with regular " + "expressions, for line-ending conversion and for " + "compression and decompression in the zlib, gzip and " + "bzip2 formats."; + +const std::string upper = + "IN ADDITION TO PROVIDING AN ABSTRACT FRAMEWORK THE " + "LIBRARY PROVIDES A NUMBER OF CONCRETE FILTERS, SOURCES " + "AND SINKS WHICH SERVE AS EXAMPLE APPLICATIONS OF THE " + "LIBRARY BUT ARE ALSO USEFUL IN THEIR OWN RIGHT. THESE " + "INCLUDE COMPONENTS FOR ACCESSING MEMORY-MAPPED FILES, " + "FOR FILE ACCESS VIA OPERATING SYSTEM FILE DESCRIPTORS, " + "FOR CODE CONVERSION, FOR TEXT FILTERING WITH REGULAR " + "EXPRESSIONS, FOR LINE-ENDING CONVERSION AND FOR " + "COMPRESSION AND DECOMPRESSION IN THE ZLIB, GZIP AND " + "BZIP2 FORMATS."; + +struct toupper_dual_use_filter : public dual_use_filter { + template<typename Source> + int get(Source& s) + { + int c = boost::iostreams::get(s); + return c != EOF && c != WOULD_BLOCK ? + std::toupper((unsigned char) c) : + c; + } + template<typename Sink> + bool put(Sink& s, char c) + { + return boost::iostreams::put( + s, (char) std::toupper((unsigned char) c) + ); + } +}; + +struct tolower_dual_use_filter : public dual_use_filter { + template<typename Source> + int get(Source& s) + { + int c = boost::iostreams::get(s); + return c != EOF && c != WOULD_BLOCK ? + std::tolower((unsigned char) c) : + c; + } + template<typename Sink> + bool put(Sink& s, char c) + { + return boost::iostreams::put( + s, (char) std::tolower((unsigned char) c) + ); + } +}; + +void filter_test() +{ + BOOST_CHECK(test_input_filter(toupper_filter(), lower, upper)); + BOOST_CHECK(test_input_filter(toupper_multichar_filter(), lower, upper)); + BOOST_CHECK(test_input_filter(toupper_dual_use_filter(), lower, upper)); + BOOST_CHECK(test_output_filter(tolower_filter(), upper, lower)); + BOOST_CHECK(test_output_filter(tolower_multichar_filter(), upper, lower)); + BOOST_CHECK(test_output_filter(tolower_dual_use_filter(), upper, lower)); + BOOST_CHECK(test_filter_pair(tolower_filter(), toupper_filter(), upper)); + BOOST_CHECK( + test_filter_pair( tolower_multichar_filter(), + toupper_multichar_filter(), upper ) + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("filter test"); + test->add(BOOST_TEST_CASE(&filter_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/filtering_stream_flush_test.hpp b/src/boost/libs/iostreams/test/filtering_stream_flush_test.hpp new file mode 100644 index 00000000..28b29060 --- /dev/null +++ b/src/boost/libs/iostreams/test/filtering_stream_flush_test.hpp @@ -0,0 +1,36 @@ +// (C) Copyright 2011 Steven Watanabe +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <fstream> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void test_filtering_ostream_flush() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + lowercase_file lower; + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_filter()); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chars(out); + out.flush(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chars with an " + "output filter" + ); + } +} diff --git a/src/boost/libs/iostreams/test/filtering_stream_test.cpp b/src/boost/libs/iostreams/test/filtering_stream_test.cpp new file mode 100644 index 00000000..be3e5205 --- /dev/null +++ b/src/boost/libs/iostreams/test/filtering_stream_test.cpp @@ -0,0 +1,52 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/test/unit_test.hpp> +#include "read_input_test.hpp" +#include "read_bidir_test.hpp" +#include "read_seekable_test.hpp" +#include "read_bidir_streambuf_test.hpp" +#include "read_input_istream_test.hpp" +#include "write_output_test.hpp" +#include "write_bidir_test.hpp" +#include "write_seekable_test.hpp" +#include "write_output_iterator_test.hpp" +#include "write_bidir_streambuf_test.hpp" +#include "write_output_ostream_test.hpp" +#include "read_input_filter_test.hpp" +#include "read_bidir_filter_test.hpp" +#include "write_output_filter_test.hpp" +#include "write_bidir_filter_test.hpp" +#include "seek_test.hpp" +#include "putback_test.hpp" +#include "filtering_stream_flush_test.hpp" + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("filtering_stream test"); + test->add(BOOST_TEST_CASE(&read_input_test)); + test->add(BOOST_TEST_CASE(&read_bidirectional_test)); + test->add(BOOST_TEST_CASE(&read_seekable_test)); + test->add(BOOST_TEST_CASE(&read_bidirectional_streambuf_test)); + test->add(BOOST_TEST_CASE(&read_input_istream_test)); + test->add(BOOST_TEST_CASE(&write_output_test)); + test->add(BOOST_TEST_CASE(&write_bidirectional_test)); + test->add(BOOST_TEST_CASE(&write_seekable_test)); + test->add(BOOST_TEST_CASE(&write_output_iterator_test)); + test->add(BOOST_TEST_CASE(&write_bidirectional_streambuf_test)); + test->add(BOOST_TEST_CASE(&write_output_ostream_test)); + test->add(BOOST_TEST_CASE(&read_input_filter_test)); + test->add(BOOST_TEST_CASE(&read_bidirectional_filter_test)); + test->add(BOOST_TEST_CASE(&write_output_filter_test)); + test->add(BOOST_TEST_CASE(&write_bidirectional_filter_test)); + test->add(BOOST_TEST_CASE(&seek_test)); + test->add(BOOST_TEST_CASE(&putback_test)); + test->add(BOOST_TEST_CASE(&test_filtering_ostream_flush)); + return test; +} diff --git a/src/boost/libs/iostreams/test/finite_state_filter_test.cpp b/src/boost/libs/iostreams/test/finite_state_filter_test.cpp new file mode 100644 index 00000000..698fc8b7 --- /dev/null +++ b/src/boost/libs/iostreams/test/finite_state_filter_test.cpp @@ -0,0 +1,182 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_LOCALE +# error std::locale not supported on this platform +#else + +# include <map> +# include <boost/iostreams/detail/ios.hpp> // failure. +# include <boost/iostreams/filter/test.hpp> +# include <boost/mpl/vector.hpp> +# include <boost/test/test_tools.hpp> +# include <boost/test/unit_test.hpp> +# include "../example/finite_state_filter.hpp" + +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +const std::string posix = // 'unix' is sometimes a macro. + "When I was one-and-twenty\n" + "I heard a wise man say,\n" + "'Give crowns and pounds and guineas\n" + "But not your heart away;\n" + "\n" + "Give pearls away and rubies\n" + "But keep your fancy free.'\n" + "But I was one-and-twenty,\n" + "No use to talk to me.\n" + "\n" + "When I was one-and-twenty\n" + "I heard him say again,\n" + "'The heart out of the bosom\n" + "Was never given in vain;\n" + "'Tis paid with sighs a plenty\n" + "And sold for endless rue.'\n" + "And I am two-and-twenty,\n" + "And oh, 'tis true, 'tis true."; + +const std::string dos = + "When I was one-and-twenty\r\n" + "I heard a wise man say,\r\n" + "'Give crowns and pounds and guineas\r\n" + "But not your heart away;\r\n" + "\r\n" + "Give pearls away and rubies\r\n" + "But keep your fancy free.'\r\n" + "But I was one-and-twenty,\r\n" + "No use to talk to me.\r\n" + "\r\n" + "When I was one-and-twenty\r\n" + "I heard him say again,\r\n" + "'The heart out of the bosom\r\n" + "Was never given in vain;\r\n" + "'Tis paid with sighs a plenty\r\n" + "And sold for endless rue.'\r\n" + "And I am two-and-twenty,\r\n" + "And oh, 'tis true, 'tis true."; + +const std::string comments = + "When I was /*one-and-twenty\n" + "I he*/ard a wise/ man say,\n" + "'Give cr//*owns *and po**/unds and guineas\n" + "But n*/ot yo*/ur he/*a*/rt /**/away;\n"; + +const std::string no_comments = + "When I was " + "ard a wise/ man say,\n" + "'Give cr/unds and guineas\n" + "But n*/ot yo*/ur hert away;\n"; + +struct identity_fsm + : io::finite_state_machine<identity_fsm, char> +{ + void on_any(char c) { push(c); } + typedef boost::mpl::vector0<> transition_table; +}; + +struct dos2unix_fsm : io::finite_state_machine<dos2unix_fsm> { + BOOST_IOSTREAMS_FSM(dos2unix_fsm) // Define skip and push. + typedef dos2unix_fsm self; + typedef boost::mpl::vector< + row<initial_state, is<'\r'>, initial_state, &self::skip>, + row<initial_state, is_any, initial_state, &self::push> + > transition_table; +}; + +struct unix2dos_fsm : io::finite_state_machine<unix2dos_fsm> { + BOOST_IOSTREAMS_FSM(unix2dos_fsm) // Define skip and push. + typedef unix2dos_fsm self; + + void on_lf(char) { push('\r'); push('\n'); } + + typedef boost::mpl::vector< + row<initial_state, is<'\n'>, initial_state, &self::on_lf>, + row<initial_state, is_any, initial_state, &self::push> + > transition_table; +}; + +struct uncommenting_fsm : io::finite_state_machine<uncommenting_fsm> { + BOOST_IOSTREAMS_FSM(uncommenting_fsm) // Define skip and push. + typedef uncommenting_fsm self; + + static const int no_comment = initial_state; + static const int pre_comment = no_comment + 1; + static const int comment = pre_comment + 1; + static const int post_comment = comment + 1; + + void push_slash(char c) { push('/'); push(c); } + + typedef boost::mpl::vector< + row<no_comment, is<'/'>, pre_comment, &self::skip>, + row<no_comment, is_any, no_comment, &self::push>, + row<pre_comment, is<'*'>, comment, &self::skip>, + row<pre_comment, is<'/'>, pre_comment, &self::push>, + row<pre_comment, is_any, no_comment, &self::push_slash>, + row<comment, is<'*'>, post_comment, &self::skip>, + row<comment, is_any, comment, &self::skip>, + row<post_comment, is<'/'>, no_comment, &self::skip>, + row<post_comment, is<'*'>, post_comment, &self::skip>, + row<post_comment, is_any, comment, &self::skip> + > transition_table; +}; + +void finite_state_filter_test() +{ + using namespace std; + + typedef io::finite_state_filter<identity_fsm> identity_filter; + typedef io::finite_state_filter<dos2unix_fsm> dos2unix_filter; + typedef io::finite_state_filter<unix2dos_fsm> unix2dos_filter; + typedef io::finite_state_filter<uncommenting_fsm> uncommenting_filter; + + // Test identity_filter. + + BOOST_CHECK( + io::test_input_filter(identity_filter(), dos, dos) + ); + BOOST_CHECK( + io::test_output_filter(identity_filter(), dos, dos) + ); + + // Test dos2unix_filter. + + BOOST_CHECK( + io::test_input_filter(dos2unix_filter(), dos, posix) + ); + BOOST_CHECK( + io::test_output_filter(dos2unix_filter(), dos, posix) + ); + + // Test unix2dos_filter. + + BOOST_CHECK( + io::test_input_filter(unix2dos_filter(), posix, dos) + ); + BOOST_CHECK( + io::test_output_filter(unix2dos_filter(), posix, dos) + ); + + // Test uncommenting_filter. + + BOOST_CHECK( + io::test_input_filter(uncommenting_filter(), comments, no_comments) + ); + BOOST_CHECK( + io::test_output_filter(uncommenting_filter(), comments, no_comments) + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("example test"); + test->add(BOOST_TEST_CASE(&finite_state_filter_test)); + return test; +} + +#endif // #ifdef BOOST_NO_STD_LOCALE //---------------------------------------// diff --git a/src/boost/libs/iostreams/test/flush_test.cpp b/src/boost/libs/iostreams/test/flush_test.cpp new file mode 100644 index 00000000..edb72ca3 --- /dev/null +++ b/src/boost/libs/iostreams/test/flush_test.cpp @@ -0,0 +1,145 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <algorithm> // equal. +#include <fstream> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/device/null.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/iostreams/operations.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/filters.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void flush_test() +{ + { + stream_buffer<null_sink> null; + null.open(null_sink()); + BOOST_CHECK_MESSAGE( + iostreams::flush(null), + "failed flushing stream_buffer" + ); + BOOST_CHECK_MESSAGE( + null.strict_sync(), + "failed strict-syncing stream_buffer with " + "non-flushable resource" + ); + } + + { + stream<null_sink> null; + null.open(null_sink()); + BOOST_CHECK_MESSAGE( + iostreams::flush(null), + "failed flushing stream" + ); + BOOST_CHECK_MESSAGE( + null.strict_sync(), + "failed strict-syncing stream with " + "non-flushable resource" + ); + } + + { + filtering_ostream null; + null.push(null_sink()); + BOOST_CHECK_MESSAGE( + iostreams::flush(null), + "failed flushing filtering_ostream" + ); + BOOST_CHECK_MESSAGE( + null.strict_sync(), + "failed strict-syncing filtering_ostream with " + "non-flushable resource" + ); + } + + { + filtering_ostream null; + null.push(tolower_filter()); + null.push(null_sink()); + BOOST_CHECK_MESSAGE( + iostreams::flush(null), + "failed flushing filtering_ostream with non-flushable filter" + ); + BOOST_CHECK_MESSAGE( + !null.strict_sync(), + "strict-syncing filtering_ostream with " + "non-flushable filter succeeded" + ); + } + + { + vector<char> dest1; + vector<char> dest2; + filtering_ostream out; + out.set_auto_close(false); + out.push(flushable_output_filter()); + + // Write to dest1. + out.push(iostreams::back_inserter(dest1)); + write_data_in_chunks(out); + out.flush(); + + // Write to dest2. + out.pop(); + out.push(iostreams::back_inserter(dest2)); + write_data_in_chunks(out); + out.flush(); + + BOOST_CHECK_MESSAGE( + dest1.size() == dest2.size() && + std::equal(dest1.begin(), dest1.end(), dest2.begin()), + "failed flush filtering_ostream with auto_close disabled" + ); + } + + { + vector<char> dest1; + vector<char> dest2; + filtering_ostream out; + out.set_auto_close(false); + out.push(flushable_output_filter()); + out.push(flushable_output_filter()); + + // Write to dest1. + out.push(iostreams::back_inserter(dest1)); + write_data_in_chunks(out); + out.flush(); + + // Write to dest2. + out.pop(); + out.push(iostreams::back_inserter(dest2)); + write_data_in_chunks(out); + out.flush(); + + BOOST_CHECK_MESSAGE( + dest1.size() == dest2.size() && + std::equal(dest1.begin(), dest1.end(), dest2.begin()), + "failed flush filtering_ostream with two flushable filters " + "with auto_close disabled" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("flush test"); + test->add(BOOST_TEST_CASE(&flush_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/grep_test.cpp b/src/boost/libs/iostreams/test/grep_test.cpp new file mode 100644 index 00000000..f9af490d --- /dev/null +++ b/src/boost/libs/iostreams/test/grep_test.cpp @@ -0,0 +1,282 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: libs/iostreams/test/grep_test.cpp + * Date: Mon May 26 17:48:45 MDT 2008 + * Copyright: 2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Tests the class template basic_grep_filter. + */ + +#include <iostream> + +#include <boost/config.hpp> // Make sure ptrdiff_t is in std. +#include <algorithm> +#include <cstddef> // std::ptrdiff_t +#include <string> +#include <boost/iostreams/compose.hpp> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filter/grep.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/ref.hpp> +#include <boost/regex.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +using namespace boost; +using namespace boost::iostreams; +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +// List of addresses of US Appeals Courts, from uscourts.gov +std::string addresses = + "John Joseph Moakley United States Courthouse, Suite 2500\n" + "One Courthouse Way\n" + "Boston, MA 02210-3002\n" + "\n" + "Thurgood Marshall United States Courthouse, 18th Floor\n" + "40 Centre Street\n" + "New York, NY 10007-1501\n" + "\n" + "21400 James A. Byrne United States Courthouse\n" + "601 Market Street\n" + "Philadelphia, PA 19106-1729\n" + "\n" + "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n" + "1100 East Main Street\n" + "Richmond, VA 23219-3525\n" + "\n" + "F. Edward Hebert Federal Bldg\n" + "600 South Maestri Place\n" + "New Orleans, LA 70130\n" + "\n" + "Bob Casey United States Courthouse, 1st Floor\n" + "515 Rusk Street\n" + "Houston, TX 77002-2600\n" + "\n" + "Potter Stewart United States Courthouse, Suite 540\n" + "100 East Fifth Street\n" + "Cincinnati, OH 45202\n" + "\n" + "2722 Everett McKinley Dirksen United States Courthouse\n" + "219 South Dearborn Street\n" + "Chicago, IL 60604\n"; + +// Lines containing "United States Courthouse" +std::string us_courthouse = + "John Joseph Moakley United States Courthouse, Suite 2500\n" + "Thurgood Marshall United States Courthouse, 18th Floor\n" + "21400 James A. Byrne United States Courthouse\n" + "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n" + "Bob Casey United States Courthouse, 1st Floor\n" + "Potter Stewart United States Courthouse, Suite 540\n" + "2722 Everett McKinley Dirksen United States Courthouse\n"; + +// Lines not containing "United States Courthouse" +std::string us_courthouse_inv = + "One Courthouse Way\n" + "Boston, MA 02210-3002\n" + "\n" + "40 Centre Street\n" + "New York, NY 10007-1501\n" + "\n" + "601 Market Street\n" + "Philadelphia, PA 19106-1729\n" + "\n" + "1100 East Main Street\n" + "Richmond, VA 23219-3525\n" + "\n" + "F. Edward Hebert Federal Bldg\n" + "600 South Maestri Place\n" + "New Orleans, LA 70130\n" + "\n" + "515 Rusk Street\n" + "Houston, TX 77002-2600\n" + "\n" + "100 East Fifth Street\n" + "Cincinnati, OH 45202\n" + "\n" + "219 South Dearborn Street\n" + "Chicago, IL 60604\n"; + +// Lines containing a state and zip +std::string state_and_zip = + "Boston, MA 02210-3002\n" + "New York, NY 10007-1501\n" + "Philadelphia, PA 19106-1729\n" + "Richmond, VA 23219-3525\n" + "New Orleans, LA 70130\n" + "Houston, TX 77002-2600\n" + "Cincinnati, OH 45202\n" + "Chicago, IL 60604\n"; + +// Lines not containing a state and zip +std::string state_and_zip_inv = + "John Joseph Moakley United States Courthouse, Suite 2500\n" + "One Courthouse Way\n" + "\n" + "Thurgood Marshall United States Courthouse, 18th Floor\n" + "40 Centre Street\n" + "\n" + "21400 James A. Byrne United States Courthouse\n" + "601 Market Street\n" + "\n" + "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n" + "1100 East Main Street\n" + "\n" + "F. Edward Hebert Federal Bldg\n" + "600 South Maestri Place\n" + "\n" + "Bob Casey United States Courthouse, 1st Floor\n" + "515 Rusk Street\n" + "\n" + "Potter Stewart United States Courthouse, Suite 540\n" + "100 East Fifth Street\n" + "\n" + "2722 Everett McKinley Dirksen United States Courthouse\n" + "219 South Dearborn Street\n"; + +// Lines containing at least three words +std::string three_words = + "John Joseph Moakley United States Courthouse, Suite 2500\n" + "One Courthouse Way\n" + "Thurgood Marshall United States Courthouse, 18th Floor\n" + "40 Centre Street\n" + "21400 James A. Byrne United States Courthouse\n" + "601 Market Street\n" + "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n" + "1100 East Main Street\n" + "F. Edward Hebert Federal Bldg\n" + "600 South Maestri Place\n" + "Bob Casey United States Courthouse, 1st Floor\n" + "515 Rusk Street\n" + "Potter Stewart United States Courthouse, Suite 540\n" + "100 East Fifth Street\n" + "2722 Everett McKinley Dirksen United States Courthouse\n" + "219 South Dearborn Street\n"; + +// Lines containing exactly three words +std::string exactly_three_words = + "One Courthouse Way\n" + "40 Centre Street\n" + "601 Market Street\n" + "515 Rusk Street\n"; + +// Lines that don't contain exactly three words +std::string exactly_three_words_inv = + "John Joseph Moakley United States Courthouse, Suite 2500\n" + "Boston, MA 02210-3002\n" + "\n" + "Thurgood Marshall United States Courthouse, 18th Floor\n" + "New York, NY 10007-1501\n" + "\n" + "21400 James A. Byrne United States Courthouse\n" + "Philadelphia, PA 19106-1729\n" + "\n" + "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n" + "1100 East Main Street\n" + "Richmond, VA 23219-3525\n" + "\n" + "F. Edward Hebert Federal Bldg\n" + "600 South Maestri Place\n" + "New Orleans, LA 70130\n" + "\n" + "Bob Casey United States Courthouse, 1st Floor\n" + "Houston, TX 77002-2600\n" + "\n" + "Potter Stewart United States Courthouse, Suite 540\n" + "100 East Fifth Street\n" + "Cincinnati, OH 45202\n" + "\n" + "2722 Everett McKinley Dirksen United States Courthouse\n" + "219 South Dearborn Street\n" + "Chicago, IL 60604\n"; + +void test_filter( grep_filter grep, + const std::string& input, + const std::string& output ); + +void grep_filter_test() +{ + regex match_us_courthouse("\\bUnited States Courthouse\\b"); + regex match_state_and_zip("\\b[A-Z]{2}\\s+[0-9]{5}(-[0-9]{4})?\\b"); + regex match_three_words("\\b\\w+\\s+\\w+\\s+\\w+\\b"); + regex_constants::match_flag_type match_default = + regex_constants::match_default; + + { + grep_filter grep(match_us_courthouse); + test_filter(grep, addresses, us_courthouse); + } + + { + grep_filter grep(match_us_courthouse, match_default, grep::invert); + test_filter(grep, addresses, us_courthouse_inv); + } + + { + grep_filter grep(match_state_and_zip); + test_filter(grep, addresses, state_and_zip); + } + + { + grep_filter grep(match_state_and_zip, match_default, grep::invert); + test_filter(grep, addresses, state_and_zip_inv); + } + + { + grep_filter grep(match_three_words); + test_filter(grep, addresses, three_words); + } + + { + grep_filter grep(match_three_words, match_default, grep::whole_line); + test_filter(grep, addresses, exactly_three_words); + } + + { + int options = grep::whole_line | grep::invert; + grep_filter grep(match_three_words, match_default, options); + test_filter(grep, addresses, exactly_three_words_inv); + } +} + +void test_filter( grep_filter grep, + const std::string& input, + const std::string& output ) +{ + // Count lines in output + std::ptrdiff_t count = std::count(output.begin(), output.end(), '\n'); + + // Test as input filter + { + array_source src(input.data(), input.data() + input.size()); + std::string dest; + io::copy(compose(boost::ref(grep), src), io::back_inserter(dest)); + BOOST_CHECK(dest == output); + BOOST_CHECK(grep.count() == count); + } + + // Test as output filter + { + array_source src(input.data(), input.data() + input.size()); + std::string dest; + io::copy(src, compose(boost::ref(grep), io::back_inserter(dest))); + BOOST_CHECK(dest == output); + BOOST_CHECK(grep.count() == count); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("grep_filter test"); + test->add(BOOST_TEST_CASE(&grep_filter_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/gzip_test.cpp b/src/boost/libs/iostreams/test/gzip_test.cpp new file mode 100644 index 00000000..eb7d4cc3 --- /dev/null +++ b/src/boost/libs/iostreams/test/gzip_test.cpp @@ -0,0 +1,246 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cstddef> +#include <string> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filter/gzip.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/ref.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" +#include "detail/verification.hpp" + +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +struct gzip_alloc : std::allocator<char> { + gzip_alloc() { } + gzip_alloc(const gzip_alloc& other) { } + template<typename T> + gzip_alloc(const std::allocator<T>& other) { } +}; + +void compression_test() +{ + text_sequence data; + + // Test compression and decompression with metadata + for (int i = 0; i < 4; ++i) { + gzip_params params; + if (i & 1) { + params.file_name = "original file name"; + } + if (i & 2) { + params.comment = "detailed file description"; + } + gzip_compressor out(params); + gzip_decompressor in; + BOOST_CHECK( + test_filter_pair( boost::ref(out), + boost::ref(in), + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK(in.file_name() == params.file_name); + BOOST_CHECK(in.comment() == params.comment); + } + + // Test compression and decompression with custom allocator + BOOST_CHECK( + test_filter_pair( basic_gzip_compressor<gzip_alloc>(), + basic_gzip_decompressor<gzip_alloc>(), + std::string(data.begin(), data.end()) ) + ); +} + +void multiple_member_test() +{ + text_sequence data; + std::vector<char> temp, dest; + + // Write compressed data to temp, twice in succession + filtering_ostream out; + out.push(gzip_compressor()); + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + + // Read compressed data from temp into dest + filtering_istream in; + in.push(gzip_decompressor()); + in.push(array_source(&temp[0], temp.size())); + io::copy(in, io::back_inserter(dest)); + + // Check that dest consists of two copies of data + BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); + + dest.clear(); + io::copy( + array_source(&temp[0], temp.size()), + io::compose(gzip_decompressor(), io::back_inserter(dest))); + + // Check that dest consists of two copies of data + BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); +} + +void array_source_test() +{ + std::string data = "simple test string."; + std::string encoded; + + filtering_ostream out; + out.push(gzip_compressor()); + out.push(io::back_inserter(encoded)); + io::copy(make_iterator_range(data), out); + + std::string res; + io::array_source src(encoded.data(),encoded.length()); + io::copy(io::compose(io::gzip_decompressor(), src), io::back_inserter(res)); + + BOOST_CHECK_EQUAL(data, res); +} + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4309) // Truncation of constant value +#endif + +void header_test() +{ + // This test is in response to https://svn.boost.org/trac/boost/ticket/5908 + // which describes a problem parsing gzip headers with extra fields as + // defined in RFC 1952 (http://www.ietf.org/rfc/rfc1952.txt). + // The extra field data used here is characteristic of the tabix file + // format (http://samtools.sourceforge.net/tabix.shtml). + const char header_bytes[] = { + static_cast<char>(gzip::magic::id1), + static_cast<char>(gzip::magic::id2), + gzip::method::deflate, // Compression Method: deflate + gzip::flags::extra | gzip::flags::name | gzip::flags::comment, // flags + '\x22', '\x9c', '\xf3', '\x4e', // 4 byte modification time (little endian) + gzip::extra_flags::best_compression, // XFL + gzip::os_unix, // OS + 6, 0, // 2 byte length of extra field (little endian, 6 bytes) + 'B', 'C', 2, 0, 0, 0, // 6 bytes worth of extra field data + 'a', 'b', 'c', 0, // original filename, null terminated + 'n', 'o', ' ', 'c', 'o', 'm', 'm', 'e', 'n', 't', 0, // comment + }; + size_t sz = sizeof(header_bytes)/sizeof(header_bytes[0]); + + boost::iostreams::detail::gzip_header hdr; + for (size_t i = 0; i < sz; ++i) { + hdr.process(header_bytes[i]); + + // Require that we are done at the last byte, not before. + if (i == sz-1) + BOOST_REQUIRE(hdr.done()); + else + BOOST_REQUIRE(!hdr.done()); + } + + BOOST_CHECK_EQUAL("abc", hdr.file_name()); + BOOST_CHECK_EQUAL("no comment", hdr.comment()); + BOOST_CHECK_EQUAL(0x4ef39c22, hdr.mtime()); + BOOST_CHECK_EQUAL(gzip::os_unix, hdr.os()); +} + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +void empty_file_test() +{ + // This test is in response to https://svn.boost.org/trac/boost/ticket/5237 + // The previous implementation of gzip_compressor only wrote the gzip file + // header when the first bytes of uncompressed input were processed, causing + // incorrect behavior for empty files + BOOST_CHECK( + test_filter_pair( gzip_compressor(), + gzip_decompressor(), + std::string() ) + ); +} + +void multipart_test() +{ + // This test verifies that the gzip_decompressor properly handles a file + // that was written in multiple parts using Z_FULL_FLUSH, and in particular + // handles the CRC properly when one of those parts is empty. + const char multipart_file[] = { + '\x1f', '\x8b', '\x08', '\x00', '\x00', '\x00', '\x00', '\x00', '\x02', '\xff', '\xf2', '\xc9', + '\xcc', '\x4b', '\x55', '\x30', '\xe4', '\xf2', '\x01', '\x51', '\x46', '\x10', '\xca', '\x98', + '\x0b', '\x00', '\x00', '\x00', '\xff', '\xff', '\x03', '\x00', '\xdb', '\xa7', '\x83', '\xc9', + '\x15', '\x00', '\x00', '\x00', '\x1f', '\x8b', '\x08', '\x00', '\x00', '\x00', '\x00', '\x00', + '\x02', '\xff', '\xf2', '\xc9', '\xcc', '\x4b', '\x55', '\x30', '\xe1', '\xf2', '\x01', '\x51', + '\xa6', '\x10', '\xca', '\x8c', '\x0b', '\x00', '\x00', '\x00', '\xff', '\xff', '\x03', '\x00', + '\x41', '\xe3', '\xcc', '\xaa', '\x15', '\x00', '\x00', '\x00', '\x1f', '\x8b', '\x08', '\x00', + '\x00', '\x00', '\x00', '\x00', '\x02', '\xff', '\x02', '\x00', '\x00', '\x00', '\xff', '\xff', + '\x03', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x1f', '\x8b', + '\x08', '\x00', '\x00', '\x00', '\x00', '\x00', '\x02', '\xff', '\xf2', '\xc9', '\xcc', '\x4b', + '\x55', '\x30', '\xe7', '\xf2', '\x01', '\x51', '\x16', '\x10', '\xca', '\x92', '\x0b', '\x00', + '\x00', '\x00', '\xff', '\xff', '\x03', '\x00', '\x2b', '\xac', '\xd3', '\xf5', '\x15', '\x00', + '\x00', '\x00' + }; + + filtering_istream in; + std::string line; + + in.push(gzip_decompressor()); + in.push(io::array_source(multipart_file, sizeof(multipart_file))); + + // First part + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 1", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 2", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 3", line); + + // Second part immediately follows + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 4", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 5", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 6", line); + + // Then an empty part, followed by one last 3-line part. + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 7", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 8", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 9", line); + + // Check for gzip errors too. + BOOST_CHECK(!in.bad()); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("gzip test"); + test->add(BOOST_TEST_CASE(&compression_test)); + test->add(BOOST_TEST_CASE(&multiple_member_test)); + test->add(BOOST_TEST_CASE(&array_source_test)); + test->add(BOOST_TEST_CASE(&header_test)); + test->add(BOOST_TEST_CASE(&empty_file_test)); + test->add(BOOST_TEST_CASE(&multipart_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/invert_test.cpp b/src/boost/libs/iostreams/test/invert_test.cpp new file mode 100644 index 00000000..0621653f --- /dev/null +++ b/src/boost/libs/iostreams/test/invert_test.cpp @@ -0,0 +1,70 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/invert.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/filters.hpp" +#include "detail/operation_sequence.hpp" +#include "detail/temp_file.hpp" + +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +void read_write_test() +{ + + test_file test; + lowercase_file lower; + uppercase_file upper; + + BOOST_CHECK( test_input_filter( + invert(tolower_filter()), + file_source(test.name(), in_mode), + file_source(lower.name(), in_mode) ) ); + + BOOST_CHECK( test_output_filter( + invert(toupper_filter()), + file_source(test.name(), in_mode), + file_source(upper.name(), in_mode) ) ); +} + +void close_test() +{ + // Invert an output filter + { + operation_sequence seq; + chain<input> ch; + ch.push(io::invert(closable_filter<output>(seq.new_operation(2)))); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Invert an input filter + { + operation_sequence seq; + chain<output> ch; + ch.push(io::invert(closable_filter<input>(seq.new_operation(1)))); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("reverse test"); + test->add(BOOST_TEST_CASE(&read_write_test)); + test->add(BOOST_TEST_CASE(&close_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/large_file_test.cpp b/src/boost/libs/iostreams/test/large_file_test.cpp new file mode 100644 index 00000000..be18b11b --- /dev/null +++ b/src/boost/libs/iostreams/test/large_file_test.cpp @@ -0,0 +1,446 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Tests seeking with a file_descriptor using large file offsets. + * + * File: libs/iostreams/test/large_file_test.cpp + * Date: Tue Dec 25 21:34:47 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#include <cstdio> // SEEK_SET, etc. +#include <ctime> +#include <string> +#include <boost/config.hpp> // BOOST_STRINGIZE +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/detail/config/rtl.hpp> +#include <boost/iostreams/detail/config/windows_posix.hpp> +#include <boost/iostreams/detail/execute.hpp> +#include <boost/iostreams/detail/ios.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/device/mapped_file.hpp> +#include <boost/iostreams/positioning.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include <iostream> + + // OS-specific headers for low-level i/o. + +#include <fcntl.h> // file opening flags. +#include <sys/stat.h> // file access permissions. +#ifdef BOOST_IOSTREAMS_WINDOWS +# include <io.h> // low-level file i/o. +# define WINDOWS_LEAN_AND_MEAN +# include <windows.h> +# ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +# endif +#else +# include <sys/types.h> // mode_t. +# include <unistd.h> // low-level file i/o. +#endif + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using boost::unit_test::test_suite; + +//------------------Definition of constants-----------------------------------// + +const stream_offset gigabyte = 1073741824; +const stream_offset file_size = // Some compilers complain about "8589934593" + gigabyte * static_cast<stream_offset>(8) + static_cast<stream_offset>(1); +const int offset_list[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, // Seek by 1GB + 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, // Seek by 2GB + 6, 7, 5, 6, 4, 5, 3, 4, 2, 3, 1, 2, + 0, 3, 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, // Seek by 3GB + 5, 7, 4, 6, 3, 5, 2, 4, 1, + 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, // Seek by 4GB + 4, 7, 3, 6, 2, 5, 1, 4, + 0, 5, 1, 6, 2, 7, 3, 8, 3, 7, 2, 6, 1, 5, // Seek by 5GB + 0, 6, 1, 7, 2, 8, 2, 7, 1, 6, // Seek by 6GB + 0, 7, 1, 8, 1, 7, // Seek by 7GB + 0, 8, 0 }; // Seek by 8GB +const int offset_list_length = sizeof(offset_list) / sizeof(int); +#ifdef LARGE_FILE_TEMP +# define BOOST_FILE_NAME BOOST_STRINGIZE(LARGE_FILE_TEMP) +# define BOOST_KEEP_FILE false +#else +# define BOOST_FILE_NAME BOOST_STRINGIZE(LARGE_FILE_KEEP) +# define BOOST_KEEP_FILE true +#endif + +//------------------Definition of remove_large_file---------------------------// + +// Removes the large file +void remove_large_file() +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + DeleteFile(TEXT(BOOST_FILE_NAME)); +#else + unlink(BOOST_FILE_NAME); +#endif +} + +//------------------Definition of large_file_exists---------------------------// + +// Returns true if the large file exists, has the correct size, and has been +// modified since the last commit affecting this source file; if the file exists +// but is invalid, deletes the file. +bool large_file_exists() +{ + // Last mod date + time_t last_mod; + +#ifdef BOOST_IOSTREAMS_WINDOWS + + // Check existence + WIN32_FIND_DATA info; + HANDLE hnd = FindFirstFile(TEXT(BOOST_FILE_NAME), &info); + if (hnd == INVALID_HANDLE_VALUE) + return false; + + // Check size + FindClose(hnd); + stream_offset size = + (static_cast<stream_offset>(info.nFileSizeHigh) << 32) + + static_cast<stream_offset>(info.nFileSizeLow); + if (size != file_size) { + remove_large_file(); + return false; + } + + // Fetch last mod date + SYSTEMTIME stime; + if (!FileTimeToSystemTime(&info.ftLastWriteTime, &stime)) { + remove_large_file(); + return false; + } + tm ctime; + ctime.tm_year = stime.wYear - 1900; + ctime.tm_mon = stime.wMonth - 1; + ctime.tm_mday = stime.wDay; + ctime.tm_hour = stime.wHour; + ctime.tm_min = stime.wMinute; + ctime.tm_sec = stime.wSecond; + ctime.tm_isdst = 0; + last_mod = mktime(&ctime); + +#else + + // Check existence + struct BOOST_IOSTREAMS_FD_STAT info; + if (BOOST_IOSTREAMS_FD_STAT(BOOST_FILE_NAME, &info)) + return false; + + // Check size + if (info.st_size != file_size) { + remove_large_file(); + return false; + } + + // Fetch last mod date + last_mod = info.st_mtime; + +#endif + + // Fetch last mod date of this file ("large_file_test.cpp") + string timestamp = + "$Date$"; + if (timestamp.size() != 53) { // Length of auto-generated SVN timestamp + remove_large_file(); + return false; + } + tm commit; + try { + commit.tm_year = lexical_cast<int>(timestamp.substr(7, 4)) - 1900; + commit.tm_mon = lexical_cast<int>(timestamp.substr(12, 2)) - 1; + commit.tm_mday = lexical_cast<int>(timestamp.substr(15, 2)); + commit.tm_hour = lexical_cast<int>(timestamp.substr(18, 2)); + commit.tm_min = lexical_cast<int>(timestamp.substr(21, 2)); + commit.tm_sec = lexical_cast<int>(timestamp.substr(24, 2)); + } catch (const bad_lexical_cast&) { + remove_large_file(); + return false; + } + + // If last commit was two days or more before file timestamp, existing + // file is okay; otherwise, it must be regenerated (the two-day window + // compensates for time zone differences) + return difftime(last_mod, mktime(&commit)) >= 60 * 60 * 48; +} + +//------------------Definition of map_large_file------------------------------// + +// Initializes the large file by mapping it in small segments. This is an +// optimization for Win32; the straightforward implementation using WriteFile +// and SetFilePointer (see the Borland workaround below) is painfully slow. +bool map_large_file() +{ + for (stream_offset z = 0; z <= 8; ++z) { + try { + mapped_file_params params; + params.path = BOOST_FILE_NAME; + params.offset = z * gigabyte; + params.length = 1; + params.mode = BOOST_IOS::out; + mapped_file file(params); + file.begin()[0] = static_cast<char>(z + 1); + } catch (const std::exception&) { + remove_large_file(); + return false; + } + } + return true; +} + +//------------------Definition of create_large_file---------------------------// + +// Creates and initializes the large file if it does not already exist. The file +// looks like this: +// +// 0 1GB 2GB 3GB 4GB 5GB 6GB 7GB 8GB +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 1.....2.....3.....4.....5.....6.....7.....8.....9 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// where the characters 1-9 appear at offsets that are multiples of 1GB and the +// dots represent uninitialized data. +bool create_large_file() +{ + // If file exists, has correct size, and is recent, we're done + if (BOOST_KEEP_FILE && large_file_exists()) + return true; + +#ifdef BOOST_IOSTREAMS_WINDOWS + + // Create file + HANDLE hnd = + CreateFile( + TEXT(BOOST_FILE_NAME), + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (!hnd) + return false; + + // Set file pointer + LONG off_low = static_cast<LONG>(file_size & 0xffffffff); + LONG off_high = static_cast<LONG>(file_size >> 32); + if ( SetFilePointer(hnd, off_low, &off_high, FILE_BEGIN) == + INVALID_SET_FILE_POINTER && + GetLastError() != NO_ERROR ) + { + CloseHandle(hnd); + remove_large_file(); + return false; + } + + // Set file size + if (!SetEndOfFile(hnd)) { + CloseHandle(hnd); + remove_large_file(); + return false; + } + +# if !defined(__BORLANDC__) || __BORLANDC__ < 0x582 || __BORLANDC__ >= 0x592 + + // Close handle; all further access is via mapped_file + CloseHandle(hnd); + + // Initialize file data + return map_large_file(); + +# else // Borland >= 5.8.2 and Borland < 5.9.2 + + // Initialize file data (very slow, even though only 9 writes are required) + for (stream_offset z = 0; z <= 8; ++z) { + + // Seek + LONG off_low = static_cast<LONG>((z * gigabyte) & 0xffffffff); // == 0 + LONG off_high = static_cast<LONG>((z * gigabyte) >> 32); + if ( SetFilePointer(hnd, off_low, &off_high, FILE_BEGIN) == + INVALID_SET_FILE_POINTER && + GetLastError() != NO_ERROR ) + { + CloseHandle(hnd); + remove_large_file(); + return false; + } + + // Write a character + char buf[1] = { z + 1 }; + DWORD result; + BOOL success = WriteFile(hnd, buf, 1, &result, NULL); + if (!success || result != 1) { + CloseHandle(hnd); + remove_large_file(); + return false; + } + } + + // Close file + CloseHandle(hnd); + return true; + +# endif // Borland workaround +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + + // Create file + int oflag = O_WRONLY | O_CREAT; + #ifdef _LARGEFILE64_SOURCE + oflag |= O_LARGEFILE; + #endif + mode_t pmode = + S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH; + int fd = BOOST_IOSTREAMS_FD_OPEN(BOOST_FILE_NAME, oflag, pmode); + if (fd == -1) + return false; + + // Set file size + if (BOOST_IOSTREAMS_FD_TRUNCATE(fd, file_size)) { + BOOST_IOSTREAMS_FD_CLOSE(fd); + return false; + } + +# ifndef __CYGWIN__ + + // Initialize file data + for (int z = 0; z <= 8; ++z) { + + // Seek + BOOST_IOSTREAMS_FD_OFFSET off = + BOOST_IOSTREAMS_FD_SEEK( + fd, + static_cast<BOOST_IOSTREAMS_FD_OFFSET>(z * gigabyte), + SEEK_SET + ); + if (off == -1) { + BOOST_IOSTREAMS_FD_CLOSE(fd); + return false; + } + + // Write a character + char buf[1] = { z + 1 }; + if (BOOST_IOSTREAMS_FD_WRITE(fd, buf, 1) == -1) { + BOOST_IOSTREAMS_FD_CLOSE(fd); + return false; + } + } + + // Close file + BOOST_IOSTREAMS_FD_CLOSE(fd); + return true; + +# else // Cygwin + + // Close descriptor; all further access is via mapped_file + BOOST_IOSTREAMS_FD_CLOSE(fd); + + // Initialize file data + return map_large_file(); + +# endif +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +//------------------Definition of large_file----------------------------------// + +// RAII utility +class large_file { +public: + large_file() { exists_ = create_large_file(); } + ~large_file() { if (!BOOST_KEEP_FILE) remove_large_file(); } + bool exists() const { return exists_; } + const char* path() const { return BOOST_FILE_NAME; } +private: + bool exists_; +}; + +//------------------Definition of check_character-----------------------------// + +// Verify that the given file contains the given character at the current +// position +bool check_character(file_descriptor_source& file, char value) +{ + char buf[1]; + std::streamsize amt; + BOOST_CHECK_NO_THROW(amt = file.read(buf, 1)); + BOOST_CHECK_MESSAGE(amt == 1, "failed reading character"); + BOOST_CHECK_NO_THROW(file.seek(-1, BOOST_IOS::cur)); + return buf[0] == value; +} + +//------------------Definition of large_file_test-----------------------------// + +void large_file_test() +{ + BOOST_REQUIRE_MESSAGE( + sizeof(stream_offset) >= 8, + "large offsets not supported" + ); + + // Prepare file and file descriptor + large_file large; + file_descriptor_source file; + BOOST_REQUIRE_MESSAGE( + large.exists(), "failed creating file \"" << BOOST_FILE_NAME << '"' + ); + BOOST_CHECK_NO_THROW(file.open(large.path(), BOOST_IOS::binary)); + + // Test seeking using ios_base::beg + for (int z = 0; z < offset_list_length; ++z) { + char value = offset_list[z] + 1; + stream_offset off = + static_cast<stream_offset>(offset_list[z]) * gigabyte; + BOOST_CHECK_NO_THROW(file.seek(off, BOOST_IOS::beg)); + BOOST_CHECK_MESSAGE( + check_character(file, value), + "failed validating seek" + ); + } + + // Test seeking using ios_base::end + for (int z = 0; z < offset_list_length; ++z) { + char value = offset_list[z] + 1; + stream_offset off = + -static_cast<stream_offset>(8 - offset_list[z]) * gigabyte - 1; + BOOST_CHECK_NO_THROW(file.seek(off, BOOST_IOS::end)); + BOOST_CHECK_MESSAGE( + check_character(file, value), + "failed validating seek" + ); + } + + // Test seeking using ios_base::cur + for (int next, cur = 0, z = 0; z < offset_list_length; ++z, cur = next) { + next = offset_list[z]; + char value = offset_list[z] + 1; + stream_offset off = static_cast<stream_offset>(next - cur) * gigabyte; + BOOST_CHECK_NO_THROW(file.seek(off, BOOST_IOS::cur)); + BOOST_CHECK_MESSAGE( + check_character(file, value), + "failed validating seek" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("execute test"); + test->add(BOOST_TEST_CASE(&large_file_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/line_filter_test.cpp b/src/boost/libs/iostreams/test/line_filter_test.cpp new file mode 100644 index 00000000..2629daa1 --- /dev/null +++ b/src/boost/libs/iostreams/test/line_filter_test.cpp @@ -0,0 +1,99 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cctype> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filter/line.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/constants.hpp" +#include "detail/filters.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x. + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +struct toupper_line_filter : line_filter { + std::string do_filter(const std::string& line) + { + std::string result(line); + for ( std::string::size_type z = 0, len = line.size(); + z < len; + ++z ) + { + result[z] = std::toupper((unsigned char) result[z]); + } + return result; + } +}; + +bool compare_streams_in_lines(std::istream& first, std::istream& second) +{ + do { + std::string line_one; + std::string line_two; + std::getline(first, line_one); + std::getline(second, line_two); + if (line_one != line_two || first.eof() != second.eof()) + return false; + } while (!first.eof()); + return true; +} + +void read_line_filter() +{ + test_file src; + uppercase_file upper; + filtering_istream first; + first.push(toupper_line_filter()); + first.push(file_source(src.name(), in_mode)); + ifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_lines(first, second), + "failed reading from a line_filter" + ); +} + +void write_line_filter() +{ + test_file data; + temp_file dest; + uppercase_file upper; + + filtering_ostream out; + out.push(toupper_line_filter()); + out.push(file_sink(dest.name(), out_mode)); + copy(file_source(data.name(), in_mode), out); + out.reset(); + + ifstream first(dest.name().c_str()); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_lines(first, second), + "failed writing to a line_filter" + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("line_filter test"); + test->add(BOOST_TEST_CASE(&read_line_filter)); + test->add(BOOST_TEST_CASE(&write_line_filter)); + return test; +} + +#include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x. + diff --git a/src/boost/libs/iostreams/test/lzma_test.cpp b/src/boost/libs/iostreams/test/lzma_test.cpp new file mode 100644 index 00000000..94b6716a --- /dev/null +++ b/src/boost/libs/iostreams/test/lzma_test.cpp @@ -0,0 +1,258 @@ +// (C) COPYRIGHT 2017 ARM Limited +// Based on gzip_test.cpp by: +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Note: basically a copy-paste of the gzip test + +#include <cstddef> +#include <string> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filter/lzma.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/ref.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" +#include "detail/verification.hpp" + +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +struct lzma_alloc : std::allocator<char> { + lzma_alloc() { } + lzma_alloc(const lzma_alloc& other) { } + template<typename T> + lzma_alloc(const std::allocator<T>& other) { } +}; + +void compression_test() +{ + text_sequence data; + + // Test compression and decompression with custom allocator + BOOST_CHECK( + test_filter_pair( basic_lzma_compressor<lzma_alloc>(), + basic_lzma_decompressor<lzma_alloc>(), + std::string(data.begin(), data.end()) ) + ); +} + +void multiple_member_test() +{ + text_sequence data; + std::vector<char> temp, dest; + + // Write compressed data to temp, twice in succession + filtering_ostream out; + out.push(lzma_compressor()); + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + + // Read compressed data from temp into dest + filtering_istream in; + in.push(lzma_decompressor()); + in.push(array_source(&temp[0], temp.size())); + io::copy(in, io::back_inserter(dest)); + + // Check that dest consists of two copies of data + BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); + + dest.clear(); + io::copy( + array_source(&temp[0], temp.size()), + io::compose(lzma_decompressor(), io::back_inserter(dest))); + + // Check that dest consists of two copies of data + BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); +} + +void array_source_test() +{ + std::string data = "simple test string."; + std::string encoded; + + filtering_ostream out; + out.push(lzma_compressor()); + out.push(io::back_inserter(encoded)); + io::copy(make_iterator_range(data), out); + + std::string res; + io::array_source src(encoded.data(),encoded.length()); + io::copy(io::compose(io::lzma_decompressor(), src), io::back_inserter(res)); + + BOOST_CHECK_EQUAL(data, res); +} + +void empty_file_test() +{ + // This test is in response to https://svn.boost.org/trac/boost/ticket/5237 + // The previous implementation of gzip_compressor only wrote the gzip file + // header when the first bytes of uncompressed input were processed, causing + // incorrect behavior for empty files + BOOST_CHECK( + test_filter_pair( lzma_compressor(), + lzma_decompressor(), + std::string() ) + ); +} + +void multipart_test() +{ + // This test verifies that the lzma_decompressor properly handles a file + // that consists of multiple concatenated files (matches unxz behaviour) + static const char multipart_file[] = { + '\xfd', '\x37', '\x7a', '\x58', '\x5a', '\x00', '\x00', '\x04', '\xe6', '\xd6', '\xb4', '\x46', + '\x02', '\x00', '\x21', '\x01', '\x1c', '\x00', '\x00', '\x00', '\x10', '\xcf', '\x58', '\xcc', + '\xe0', '\x00', '\x14', '\x00', '\x11', '\x5d', '\x00', '\x26', '\x1a', '\x49', '\xc6', '\x67', + '\x41', '\x3f', '\x96', '\x8c', '\x25', '\x02', '\xb3', '\x4d', '\x16', '\xa8', '\xb4', '\x40', + '\x00', '\x00', '\x00', '\x00', '\xeb', '\xad', '\x3f', '\xbf', '\x8c', '\x8c', '\x72', '\x25', + '\x00', '\x01', '\x2d', '\x15', '\x2f', '\x0b', '\x71', '\x6d', '\x1f', '\xb6', '\xf3', '\x7d', + '\x01', '\x00', '\x00', '\x00', '\x00', '\x04', '\x59', '\x5a', '\xfd', '\x37', '\x7a', '\x58', + '\x5a', '\x00', '\x00', '\x04', '\xe6', '\xd6', '\xb4', '\x46', '\x02', '\x00', '\x21', '\x01', + '\x1c', '\x00', '\x00', '\x00', '\x10', '\xcf', '\x58', '\xcc', '\xe0', '\x00', '\x14', '\x00', + '\x11', '\x5d', '\x00', '\x26', '\x1a', '\x49', '\xc6', '\x67', '\x41', '\x4d', '\x84', '\x0c', + '\x25', '\x1f', '\x5e', '\x1d', '\x4a', '\x91', '\x61', '\xa0', '\x00', '\x00', '\x00', '\x00', + '\x56', '\x76', '\x71', '\xf0', '\x54', '\x21', '\xa2', '\x5b', '\x00', '\x01', '\x2d', '\x15', + '\x2f', '\x0b', '\x71', '\x6d', '\x1f', '\xb6', '\xf3', '\x7d', '\x01', '\x00', '\x00', '\x00', + '\x00', '\x04', '\x59', '\x5a', '\xfd', '\x37', '\x7a', '\x58', '\x5a', '\x00', '\x00', '\x04', + '\xe6', '\xd6', '\xb4', '\x46', '\x00', '\x00', '\x00', '\x00', '\x1c', '\xdf', '\x44', '\x21', + '\x1f', '\xb6', '\xf3', '\x7d', '\x01', '\x00', '\x00', '\x00', '\x00', '\x04', '\x59', '\x5a', + '\xfd', '\x37', '\x7a', '\x58', '\x5a', '\x00', '\x00', '\x04', '\xe6', '\xd6', '\xb4', '\x46', + '\x02', '\x00', '\x21', '\x01', '\x1c', '\x00', '\x00', '\x00', '\x10', '\xcf', '\x58', '\xcc', + '\xe0', '\x00', '\x14', '\x00', '\x11', '\x5d', '\x00', '\x26', '\x1a', '\x49', '\xc6', '\x67', + '\x41', '\x5b', '\x71', '\x8c', '\x25', '\x3c', '\x08', '\xec', '\x79', '\xa7', '\x7b', '\x60', + '\x00', '\x00', '\x00', '\x00', '\xc7', '\x62', '\xbb', '\xaa', '\x59', '\x96', '\x2b', '\xa4', + '\x00', '\x01', '\x2d', '\x15', '\x2f', '\x0b', '\x71', '\x6d', '\x1f', '\xb6', '\xf3', '\x7d', + '\x01', '\x00', '\x00', '\x00', '\x00', '\x04', '\x59', '\x5a' + }; + + filtering_istream in; + std::string line; + + in.push(lzma_decompressor()); + in.push(io::array_source(multipart_file, sizeof(multipart_file))); + + // First part + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 1", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 2", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 3", line); + + // Second part immediately follows + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 4", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 5", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 6", line); + + // Then an empty part, followed by one last 3-line part. + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 7", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 8", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 9", line); + + // Check for lzma errors too. + BOOST_CHECK(!in.bad()); +} + +void multithreaded_test() +{ + text_sequence data; + + // Get correct compressed string at level 2. + // Tests legacy capability of providing a single integer to the + // lzma_compressor constructor to be used as the "level" to initialize + // lzma_params. + std::string correct_level_2; + { + filtering_ostream out; + out.push(lzma_compressor(2)); + out.push(io::back_inserter(correct_level_2)); + io::copy(make_iterator_range(data), out); + } + + // Tests omitting the threads parameters and arriving at same compressed data. + BOOST_CHECK( + test_output_filter( lzma_compressor(lzma_params(2)), + std::string(data.begin(), data.end()), + correct_level_2 ) + ); + + // Test specifying a single thread and arriving at same compressed data. + BOOST_CHECK( + test_output_filter( lzma_compressor(lzma_params(2, 1)), + std::string(data.begin(), data.end()), + correct_level_2 ) + ); + + // Test specifying multiple threads and arriving at same compressed data. + BOOST_CHECK( + test_output_filter( lzma_compressor(lzma_params(2, 4)), + std::string(data.begin(), data.end()), + correct_level_2 ) + ); + + // Test specifying "0" threads, which is interpreted as + // using all cores, or 1 thread if such capability is missing. + BOOST_CHECK( + test_output_filter( lzma_compressor(lzma_params(2, 0)), + std::string(data.begin(), data.end()), + correct_level_2 ) + ); + + // Test that decompressor works to decompress the output with various thread values. + // Threading shouldn't affect the decompression and, in fact, isn't + // threaded in current implementation of liblzma. Both the level and + // threads options are ignored by the decompressor. + BOOST_CHECK( + test_input_filter( lzma_decompressor(lzma_params(2, 1)), + correct_level_2, + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK( + test_input_filter( lzma_decompressor(lzma_params(2, 4)), + correct_level_2, + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK( + test_input_filter( lzma_decompressor(lzma_params(2, 0)), + correct_level_2, + std::string(data.begin(), data.end()) ) + ); + +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("lzma test"); + test->add(BOOST_TEST_CASE(&compression_test)); + test->add(BOOST_TEST_CASE(&multiple_member_test)); + test->add(BOOST_TEST_CASE(&array_source_test)); + test->add(BOOST_TEST_CASE(&empty_file_test)); + test->add(BOOST_TEST_CASE(&multipart_test)); + test->add(BOOST_TEST_CASE(&multithreaded_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/mapped_file_test.cpp b/src/boost/libs/iostreams/test/mapped_file_test.cpp new file mode 100644 index 00000000..0b7bfe51 --- /dev/null +++ b/src/boost/libs/iostreams/test/mapped_file_test.cpp @@ -0,0 +1,333 @@ +// (C) Copyright Jorge Lodos 2008 +// (C) Copyright Jonathan Turkanis 2004 +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// This is the original (boost 1.34) boost::iostream test for the mapped files with the +// following modifications: +// 1. The namespace for the mapped file was changed to seglib::filemap. +// 2. Added test for privately mapped files. +// 3. The test test_writeable was added for mapped files. +// 4. The test test_resizeable was added for mapped files. +// + +#include <fstream> +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/test/unit_test.hpp> + +#include <boost/iostreams/stream.hpp> +#include <boost/iostreams/device/mapped_file.hpp> +#include <boost/filesystem/path.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +// Code generation bugs cause tests to fail with global optimization. +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# pragma optimize("g", off) +#endif + +namespace boost { namespace iostreams { namespace test { + +bool test_writeable(mapped_file& mf) +{ + // Test writing + for (int i = 0; i < data_reps; ++i) { + memcpy(mf.data(), narrow_data(), chunk_size); + char buf[chunk_size]; + memcpy(buf, mf.const_data(), chunk_size); + if (strncmp(buf, narrow_data(), chunk_size) != 0) + return false; + memset(mf.data(), 0, chunk_size); + } + return true; +} + +bool test_resizeable(mapped_file& mf) +{ + // Test resizing + mapped_file::size_type size = mf.size(); + if (size == 0) + return false; + mf.resize(size/2); + if (mf.size() != size/2) + return false; + mf.resize(size); + if (mf.size() != size) + return false; + return true; +} + +} } } // End namespaces test, iostreams, boost. + +void mapped_file_test() +{ + using namespace boost::iostreams; + BOOST_TEST_MESSAGE("about to begin"); + + //--------------Reading from a mapped_file_source-------------------------// + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a stream based on a mapped_file_source, + // in chars. + boost::iostreams::test::test_file test1, test2; + boost::iostreams::stream<mapped_file_source> first(test1.name()); + { + std::ifstream second( test2.name().c_str(), + BOOST_IOS::in | BOOST_IOS::binary ); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_streams_in_chars(first, second), + "failed reading from stream<mapped_file_source> in chars" + ); + + BOOST_TEST_MESSAGE( + "done reading from stream<mapped_file_source> in chars" + ); + } + first.close(); + + // Test reading from a stream based on a mapped_file_source, + // in chunks. (Also tests reopening the stream.) + first.open(mapped_file_source(test1.name())); + { + std::ifstream second( test2.name().c_str(), + BOOST_IOS::in | BOOST_IOS::binary ); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_streams_in_chunks(first, second), + "failed reading from stream<mapped_file_source> in chunks" + ); + + BOOST_TEST_MESSAGE( + "done reading from stream<mapped_file_source> in chunks" + ); + } + } + + //--------------Writing to a mapped_file_sink-----------------------------// + + { + // Test writing to a stream based on a mapped_file_sink, in + // chars. + boost::iostreams::test::uppercase_file first, second; // Will overwrite these. + boost::iostreams::test::test_file test; + + boost::iostreams::stream<mapped_file_sink> out; + out.open(mapped_file_sink(first.name())); + boost::iostreams::test::write_data_in_chars(out); + out.close(); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(first.name(), test.name()), + "failed writing to stream<mapped_file_sink> in chars" + ); + + BOOST_TEST_MESSAGE( + "done writing to stream<mapped_file_sink> in chars" + ); + + // Test writing to a stream based on a mapped_file_sink, in + // chunks. (Also tests reopening the stream.) + out.open(mapped_file_sink(second.name())); + boost::iostreams::test::write_data_in_chunks(out); + out.close(); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(second.name(), test.name()), + "failed writing to stream<mapped_file_sink> in chunks" + ); + + BOOST_TEST_MESSAGE( + "done writing to stream<mapped_file_sink> in chunks" + ); + } + + //--------------Writing to a newly created file---------------------------// + + { + // Test writing to a newly created mapped file. + boost::iostreams::test::temp_file first, second; + boost::iostreams::test::test_file test; + + mapped_file_params p(first.name()); + p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length(); + boost::iostreams::stream<mapped_file_sink> out; + out.open(mapped_file_sink(p)); + boost::iostreams::test::write_data_in_chars(out); + out.close(); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(first.name(), test.name()), + "failed writing to newly created mapped file in chars" + ); + + + // Test writing to a newly created mapped file. + // (Also tests reopening the stream.) + p.path = second.name(); + out.open(mapped_file_sink(p)); + boost::iostreams::test::write_data_in_chunks(out); + out.close(); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(second.name(), test.name()), + "failed writing to newly created mapped file in chunks" + ); + } + + //--------------Writing to a pre-existing file---------------------------// + { + // Test for Bug #3953 - writing to a pre-existing mapped file. + boost::iostreams::test::test_file first, test; + + mapped_file_params p(first.name()); + p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length(); + boost::iostreams::stream<mapped_file_sink> out; + out.open(mapped_file_sink(p)); + boost::iostreams::test::write_data_in_chars(out); + out.close(); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(first.name(), test.name()), + "failed writing to pre-existing mapped file in chars" + ); + } + + //--------------Random access with a mapped_file--------------------------// + + { + // Test reading, writing and seeking within a stream based on a + // mapped_file, in chars. + boost::iostreams::test::test_file test; + boost::iostreams::stream<mapped_file> io; + io.open(mapped_file(test.name())); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_seekable_in_chars(io), + "failed seeking within stream<mapped_file> in chars" + ); + + BOOST_TEST_MESSAGE( + "done seeking within stream<mapped_file> in chars" + ); + + io.close(); + + // Test reading, writing and seeking within a stream based on a + // mapped_file, in chunks. (Also tests reopening the + // stream.) + io.open(mapped_file(test.name())); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_seekable_in_chunks(io), + "failed seeking within stream<mapped_file> in chunks" + ); + + BOOST_TEST_MESSAGE( + "done seeking within stream<mapped_file> in chunks" + ); + } + + //--------------Resizing a mapped_file------------------------------------// + + { + // Test resizing a mapped_file. + boost::iostreams::test::test_file test; + mapped_file mf; + mf.open(test.name()); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_resizeable(mf), + "failed resizing a mapped_file" + ); + + BOOST_TEST_MESSAGE( + "done resizing a mapped_file" + ); + } + + //--------------Random access with a private mapped_file------------------// + + { + // Use 2 copies of the file to compare later + boost::iostreams::test::test_file orig, copy; + + // Test reading and writing within a mapped_file. + // Since the file is privately mapped, it should remain + // unchanged after writing when opened in readonly mode. + mapped_file mf; + mf.open(orig.name(), mapped_file::priv); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_writeable(mf), + "failed seeking within private mapped_file" + ); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(orig.name(), copy.name()), + "failed writing to private mapped_file" + ); + + BOOST_TEST_MESSAGE( + "done seeking within private mapped_file" + ); + + mf.close(); + + // Test reopening the mapped file. + mf.open(orig.name(), mapped_file::priv); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_writeable(mf), + "failed reopening private mapped_file" + ); + BOOST_CHECK_MESSAGE( + boost::iostreams::test::compare_files(orig.name(), copy.name()), + "failed writing to reopened private mapped_file" + ); + + BOOST_TEST_MESSAGE( + "done reopening private mapped_file" + ); + } + + //-------------Check creating opening mapped_file with char*-------------// + + { + boost::iostreams::test::test_file orig; + char name[50]; + std::strncpy(name, orig.name().c_str(), 50); + + mapped_file mf((char*) name); + + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_writeable(mf), + "failed seeking within private mapped_file" + ); + + mf.close(); + } + + // CYGWIN supports wide paths in boost::filesystem, but uses open() in the + // mapped file implementation and it is not configured to handle wide paths + // properly. See github issue https://github.com/boostorg/iostreams/issues/61 +#ifndef __CYGWIN__ + //---------Check creating opening mapped_file with filesystem3 path------// + { + boost::iostreams::test::test_file orig; + + mapped_file mf(boost::filesystem::path(orig.name())); + + BOOST_CHECK_MESSAGE( + boost::iostreams::test::test_writeable(mf), + "failed seeking within private mapped_file" + ); + + mf.close(); + } +#endif +} + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# pragma optimize("", on) +#endif + +boost::unit_test::test_suite* init_unit_test_suite(int, char* []) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test"); + test->add(BOOST_TEST_CASE(&mapped_file_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/newline_test.cpp b/src/boost/libs/iostreams/test/newline_test.cpp new file mode 100644 index 00000000..56d4cb4a --- /dev/null +++ b/src/boost/libs/iostreams/test/newline_test.cpp @@ -0,0 +1,486 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <string> +#include <boost/iostreams/compose.hpp> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/device/null.hpp> +#include <boost/iostreams/filter/newline.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/utility/base_from_member.hpp> + +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +const std::string posix = + "When I was one-and-twenty\n" + "I heard a wise man say,\n" + "'Give crowns and pounds and guineas\n" + "But not your heart away;\n" + "\n" + "Give pearls away and rubies\n" + "But keep your fancy free.'\n" + "But I was one-and-twenty,\n" + "No use to talk to me.\n" + "\n" + "When I was one-and-twenty\n" + "I heard him say again,\n" + "'The heart out of the bosom\n" + "Was never given in vain;\n" + "\n" + "'Tis paid with sighs a plenty\n" + "And sold for endless rue.'\n" + "And I am two-and-twenty,\n" + "And oh, 'tis true, 'tis true.\n"; + +const std::string dos = + "When I was one-and-twenty\r\n" + "I heard a wise man say,\r\n" + "'Give crowns and pounds and guineas\r\n" + "But not your heart away;\r\n" + "\r\n" + "Give pearls away and rubies\r\n" + "But keep your fancy free.'\r\n" + "But I was one-and-twenty,\r\n" + "No use to talk to me.\r\n" + "\r\n" + "When I was one-and-twenty\r\n" + "I heard him say again,\r\n" + "'The heart out of the bosom\r\n" + "Was never given in vain;\r\n" + "\r\n" + "'Tis paid with sighs a plenty\r\n" + "And sold for endless rue.'\r\n" + "And I am two-and-twenty,\r\n" + "And oh, 'tis true, 'tis true.\r\n"; + +const std::string mac = + "When I was one-and-twenty\r" + "I heard a wise man say,\r" + "'Give crowns and pounds and guineas\r" + "But not your heart away;\r" + "\r" + "Give pearls away and rubies\r" + "But keep your fancy free.'\r" + "But I was one-and-twenty,\r" + "No use to talk to me.\r" + "\r" + "When I was one-and-twenty\r" + "I heard him say again,\r" + "'The heart out of the bosom\r" + "Was never given in vain;\r" + "\r" + "'Tis paid with sighs a plenty\r" + "And sold for endless rue.'\r" + "And I am two-and-twenty,\r" + "And oh, 'tis true, 'tis true.\r"; + +const std::string no_final_newline = + "When I was one-and-twenty\n" + "I heard a wise man say,\n" + "'Give crowns and pounds and guineas\n" + "But not your heart away;\n" + "\n" + "Give pearls away and rubies\n" + "But keep your fancy free.'\n" + "But I was one-and-twenty,\n" + "No use to talk to me.\n" + "\n" + "When I was one-and-twenty\n" + "I heard him say again,\n" + "'The heart out of the bosom\n" + "Was never given in vain;\n" + "\n" + "'Tis paid with sighs a plenty\n" + "And sold for endless rue.'\n" + "And I am two-and-twenty,\n" + "And oh, 'tis true, 'tis true."; + +const std::string mixed = + "When I was one-and-twenty\n" + "I heard a wise man say,\r\n" + "'Give crowns and pounds and guineas\r" + "But not your heart away;\n" + "\r\n" + "Give pearls away and rubies\r" + "But keep your fancy free.'\n" + "But I was one-and-twenty,\r\n" + "No use to talk to me.\r" + "\r" + "When I was one-and-twenty\r\n" + "I heard him say again,\r" + "'The heart out of the bosom\n" + "Was never given in vain;\r\n" + "\r" + "'Tis paid with sighs a plenty\n" + "And sold for endless rue.'\r\n" + "And I am two-and-twenty,\r" + "And oh, 'tis true, 'tis true.\n"; + +struct string_source : boost::base_from_member<std::string>, io::array_source { + typedef io::array_source base_type; + typedef boost::base_from_member<std::string> pbase_type; + string_source(const std::string& src) + : pbase_type(src), base_type(member.data(), member.size()) + { } + + string_source(const string_source& src) + : pbase_type(src.member), base_type(member.data(), member.size()) + { } +}; + +void read_newline_filter() +{ + using namespace io; + + // Test converting to posix format. + + BOOST_CHECK(test_input_filter(newline_filter(newline::posix), posix, posix)); + BOOST_CHECK(test_input_filter(newline_filter(newline::posix), dos, posix)); + BOOST_CHECK(test_input_filter(newline_filter(newline::posix), mac, posix)); + BOOST_CHECK(test_input_filter(newline_filter(newline::posix), mixed, posix)); + + // Test converting to dos format. + + BOOST_CHECK(test_input_filter(newline_filter(newline::dos), posix, dos)); + BOOST_CHECK(test_input_filter(newline_filter(newline::dos), dos, dos)); + BOOST_CHECK(test_input_filter(newline_filter(newline::dos), mac, dos)); + BOOST_CHECK(test_input_filter(newline_filter(newline::dos), mixed, dos)); + + // Test converting to mac format. + + BOOST_CHECK(test_input_filter(newline_filter(newline::mac), posix, mac)); + BOOST_CHECK(test_input_filter(newline_filter(newline::mac), dos, mac)); + BOOST_CHECK(test_input_filter(newline_filter(newline::mac), mac, mac)); + BOOST_CHECK(test_input_filter(newline_filter(newline::mac), mixed, mac)); +} + +// Verify that a filter works as expected with both a non-blocking sink +// and a normal output stream. +// +// test_output_filter only tests for a non-blocking sink. +// TODO: Other tests should probably test with an output stream. + +template<typename Filter> +bool my_test_output_filter(Filter filter, + const std::string& input, + const std::string& output) +{ + const std::streamsize default_increment = 5; + + for ( int inc = default_increment; + inc < default_increment * 40; + inc += default_increment ) + { + io::array_source src(input.data(), input.data() + input.size()); + + std::ostringstream stream; + io::copy(src, compose(filter, stream)); + if (stream.str() != output ) + return false; + + } + return test_output_filter(filter, input, output); +} + +void write_newline_filter() +{ + using namespace io; + + // Test converting to posix format. + + BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), posix, posix)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), dos, posix)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), mac, posix)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), mixed, posix)); + + // Test converting to dos format. + + BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), posix, dos)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), dos, dos)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), mac, dos)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), mixed, dos)); + + // Test converting to mac format. + + BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), posix, mac)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), dos, mac)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), mac, mac)); + BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), mixed, mac)); +} + +void test_input_against_flags(int flags, const std::string& input, bool read) +{ + if (read) { + io::copy( + io::compose( + io::newline_checker(flags), + string_source(input) + ), + io::null_sink() + ); + } else { + io::copy( + string_source(input), + io::compose(io::newline_checker(flags), io::null_sink()) + ); + } +} + +void read_newline_checker() +{ + io::filtering_istream in; + io::newline_checker* checker = 0; + + // Verify properties of ::posix. + + in.push(io::newline_checker(io::newline::posix)); + in.push(string_source(::posix)); + BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink())); + checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker); + BOOST_CHECK(checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + in.pop(); // pop checker. + + // Verify properties of ::dos. + + in.push(io::newline_checker(io::newline::dos)); + in.push(string_source(::dos)); + try { + io::copy(in, io::null_sink()); + } catch (io::newline_error&) { + BOOST_CHECK_MESSAGE( + false, "failed checking for dos line endings" + ); + } + checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker); + BOOST_CHECK(!checker->is_posix()); + BOOST_CHECK(checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + in.pop(); // pop checker. + + // Verify properties of ::mac. + + in.push(io::newline_checker(io::newline::mac)); + in.push(string_source(::mac)); + BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink())); + checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker); + BOOST_CHECK(!checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + in.pop(); // pop checker. + + // Verify properties of no_final_newline. + + in.push(io::newline_checker(io::newline::posix)); + in.push(string_source(::no_final_newline)); + BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink())); + checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker); + BOOST_CHECK(checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(!checker->has_final_newline()); + in.pop(); // pop checker. + + // Verify properties of mixed. + + in.push(io::newline_checker()); + in.push(string_source(::mixed)); + BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink())); + checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker); + BOOST_CHECK(!checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(checker->is_mixed_posix()); + BOOST_CHECK(checker->is_mixed_dos()); + BOOST_CHECK(checker->is_mixed_mac()); + BOOST_CHECK(checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + in.pop(); // pop checker. + + // Verify exceptions when input does not satisfy target conditions. + + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::dos, ::posix, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::mac, ::posix, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::posix, ::dos, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::mac, ::dos, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::posix, ::mac, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::dos, ::mac, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::final_newline, ::no_final_newline, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::posix, ::mixed, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::dos, ::mixed, true), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::mac, ::mixed, true), + io::newline_error + ); +} + +void write_newline_checker() +{ + io::filtering_ostream out; + io::newline_checker* checker = 0; + + // Verify properties of ::posix. + + out.push(io::newline_checker(io::newline::posix)); + out.push(io::null_sink()); + BOOST_CHECK_NO_THROW(io::copy(string_source(::posix), out)); + checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker); + BOOST_CHECK(checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + out.pop(); // pop checker. + + // Verify properties of ::dos. + + out.push(io::newline_checker(io::newline::dos)); + out.push(io::null_sink()); + BOOST_CHECK_NO_THROW(io::copy(string_source(::dos), out)); + checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker); + BOOST_CHECK(!checker->is_posix()); + BOOST_CHECK(checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + out.pop(); // pop checker. + + // Verify properties of ::mac. + + out.push(io::newline_checker(io::newline::mac)); + out.push(io::null_sink()); + BOOST_CHECK_NO_THROW(io::copy(string_source(::mac), out)); + checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker); + BOOST_CHECK(!checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + out.pop(); // pop checker. + + // Verify properties of no_final_newline. + + out.push(io::newline_checker(io::newline::posix)); + out.push(io::null_sink()); + BOOST_CHECK_NO_THROW(io::copy(string_source(::no_final_newline), out)); + checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker); + BOOST_CHECK(checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(!checker->is_mixed()); + BOOST_CHECK(!checker->has_final_newline()); + out.pop(); // pop checker. + + // Verify properties of mixed. + + out.push(io::newline_checker()); + out.push(io::null_sink()); + BOOST_CHECK_NO_THROW(io::copy(string_source(::mixed), out)); + checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker); + BOOST_CHECK(!checker->is_posix()); + BOOST_CHECK(!checker->is_dos()); + BOOST_CHECK(!checker->is_mac()); + BOOST_CHECK(checker->is_mixed_posix()); + BOOST_CHECK(checker->is_mixed_dos()); + BOOST_CHECK(checker->is_mixed_mac()); + BOOST_CHECK(checker->is_mixed()); + BOOST_CHECK(checker->has_final_newline()); + out.pop(); // pop checker. + + // Verify exceptions when input does not satisfy target conditions. + + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::dos, ::posix, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::mac, ::posix, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::posix, ::dos, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::mac, ::dos, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::posix, ::mac, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::dos, ::mac, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::final_newline, ::no_final_newline, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::posix, ::mixed, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::dos, ::mixed, false), + io::newline_error + ); + BOOST_CHECK_THROW( + test_input_against_flags(io::newline::mac, ::mixed, false), + io::newline_error + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("newline_filter test"); + test->add(BOOST_TEST_CASE(&read_newline_filter)); + test->add(BOOST_TEST_CASE(&write_newline_filter)); + test->add(BOOST_TEST_CASE(&read_newline_checker)); + test->add(BOOST_TEST_CASE(&write_newline_checker)); + return test; +} diff --git a/src/boost/libs/iostreams/test/null_test.cpp b/src/boost/libs/iostreams/test/null_test.cpp new file mode 100644 index 00000000..e90d18f8 --- /dev/null +++ b/src/boost/libs/iostreams/test/null_test.cpp @@ -0,0 +1,44 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cctype> +#include <boost/iostreams/device/null.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void read_null_source() +{ + stream<null_source> in; + in.open(null_source()); + in.get(); + BOOST_CHECK(in.eof()); +} + +void write_null_sink() +{ + stream<null_sink> out; + out.open(null_sink()); + write_data_in_chunks(out); + BOOST_CHECK(out.good()); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("null test"); + test->add(BOOST_TEST_CASE(&read_null_source)); + test->add(BOOST_TEST_CASE(&write_null_sink)); + return test; +} diff --git a/src/boost/libs/iostreams/test/operation_sequence_test.cpp b/src/boost/libs/iostreams/test/operation_sequence_test.cpp new file mode 100644 index 00000000..b03b8e07 --- /dev/null +++ b/src/boost/libs/iostreams/test/operation_sequence_test.cpp @@ -0,0 +1,268 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Tests the facilities defined in the header + * libs/iostreams/test/detail/operation_sequence.hpp + * + * File: libs/iostreams/test/operation_sequence_test.cpp + * Date: Mon Dec 10 18:58:19 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#include <stdexcept> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/operation_sequence.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + + // Infrastructure for checking that operations are + // executed in the correct order + +void operation_sequence_test() +{ + // Test creating a duplicate operation + { + operation_sequence seq; + operation op = seq.new_operation(1); + BOOST_CHECK_THROW(seq.new_operation(1), runtime_error); + } + + // Test reusing an operation id after first operation is destroyed + { + operation_sequence seq; + seq.new_operation(1); + BOOST_CHECK_NO_THROW(seq.new_operation(1)); + } + + // Test creating operations with illegal error codes + { + operation_sequence seq; + BOOST_CHECK_THROW(seq.new_operation(1, -100), runtime_error); + BOOST_CHECK_THROW( + seq.new_operation(1, BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR + 1), + runtime_error + ); + } + + // Test two successful operations executed out of order + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op2 = seq.new_operation(2); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op2.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op1.execute()); + BOOST_CHECK(seq.is_failure()); + } + + // Test executing an operation twice without resetting the sequence + { + operation_sequence seq; + operation op = seq.new_operation(1); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op.execute()); + BOOST_CHECK(seq.is_success()); + BOOST_CHECK_NO_THROW(op.execute()); + BOOST_CHECK(seq.is_failure()); + } + + // Test creating an operation after operation execution has commenced + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op2 = seq.new_operation(2); + operation op3; + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op1.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_THROW(op3 = seq.new_operation(3), runtime_error); + BOOST_CHECK_NO_THROW(op2.execute()); + BOOST_CHECK(seq.is_success()); + } + + // Test three successful operations with consecutive ids, executed in order + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op2 = seq.new_operation(2); + operation op3 = seq.new_operation(3); + + // First pass + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + BOOST_CHECK(seq.is_success()); + + // Second pass + seq.reset(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + BOOST_CHECK(seq.is_success()); + } + + // Test three successful operations with non-consecutive ids, + // executed in order + { + operation_sequence seq; + operation op2 = seq.new_operation(2); + operation op3 = seq.new_operation(101); + operation op1 = seq.new_operation(-43); + + // First pass + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + BOOST_CHECK(seq.is_success()); + + // Second pass + seq.reset(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + BOOST_CHECK(seq.is_success()); + } + + // Test checking for success after one of three operations + // has been destroyed + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op3 = seq.new_operation(3); + + { + operation op2 = seq.new_operation(2); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + } + BOOST_CHECK(seq.is_success()); + } + + // Test executing an operation sequence twice, with one of the + // operations replaced with a new operation with the same id + // in the second pass + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op3 = seq.new_operation(3); + + // First pass + { + operation op2 = seq.new_operation(2); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + BOOST_CHECK(seq.is_success()); + } + + // Second pass + seq.reset(); + { + operation op2 = seq.new_operation(2); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op1.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op2.execute(); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + op3.execute(); + BOOST_CHECK(seq.is_success()); + } + } + + // Test three operations executed in order, the first of which throws + { + operation_sequence seq; + operation op1 = seq.new_operation(1, 1); + operation op2 = seq.new_operation(2); + operation op3 = seq.new_operation(3); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_THROW(op1.execute(), operation_error<1>); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op2.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op3.execute()); + BOOST_CHECK(seq.is_success()); + } + + // Test three operations executed in order, the second of which throws + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op2 = seq.new_operation(2, 2); + operation op3 = seq.new_operation(3); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op1.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_THROW(op2.execute(), operation_error<2>); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op3.execute()); + BOOST_CHECK(seq.is_success()); + } + + // Test three operations executed in order, the third of which throws + { + operation_sequence seq; + operation op1 = seq.new_operation(1); + operation op2 = seq.new_operation(2); + operation op3 = seq.new_operation(3, 3); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op1.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op2.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_THROW(op3.execute(), operation_error<3>); + BOOST_CHECK(seq.is_success()); + } + + // Test three operations executed in order, the first and + // third of which throw + { + operation_sequence seq; + operation op1 = seq.new_operation(1, 1); + operation op2 = seq.new_operation(2); + operation op3 = seq.new_operation(3, 3); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_THROW(op1.execute(), operation_error<1>); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_NO_THROW(op2.execute()); + BOOST_CHECK(!seq.is_failure() && !seq.is_success()); + BOOST_CHECK_THROW(op3.execute(), operation_error<3>); + BOOST_CHECK(seq.is_success()); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("execute test"); + test->add(BOOST_TEST_CASE(&operation_sequence_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/path_test.cpp b/src/boost/libs/iostreams/test/path_test.cpp new file mode 100644 index 00000000..b08d0f5f --- /dev/null +++ b/src/boost/libs/iostreams/test/path_test.cpp @@ -0,0 +1,25 @@ +// (C) Copyright Daniel James 2011. +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/detail/path.hpp> +#include <boost/filesystem/path.hpp> + +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +void path_test() +{ + boost::filesystem::path orig("a/b"); + boost::iostreams::detail::path p(orig); + p = orig; +} + +boost::unit_test::test_suite* init_unit_test_suite(int, char* []) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test"); + test->add(BOOST_TEST_CASE(&path_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/pipeline_test.cpp b/src/boost/libs/iostreams/test/pipeline_test.cpp new file mode 100644 index 00000000..2f621c7c --- /dev/null +++ b/src/boost/libs/iostreams/test/pipeline_test.cpp @@ -0,0 +1,90 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/filters.hpp" +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using boost::unit_test::test_suite; + +void pipeline_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + { + test_file src; + filtering_istream + in1( toupper_filter() | + file_source(src.name()) ); + filtering_istream + in2( toupper_filter() | + toupper_filter() | + file_source(src.name()) ); + filtering_istream + in3( toupper_filter() | + toupper_filter() | + toupper_filter() | + file_source(src.name()) ); + filtering_istream + in4( toupper_filter() | + toupper_filter() | + toupper_filter() | + toupper_filter() | + file_source(src.name()) ); + BOOST_CHECK(in1.size() == 2); + BOOST_CHECK(in2.size() == 3); + BOOST_CHECK(in3.size() == 4); + BOOST_CHECK(in4.size() == 5); + } + + { + test_file src; + uppercase_file upper; + filtering_istream + first( toupper_filter() | + toupper_multichar_filter() | + file_source(src.name(), in_mode) ); + ifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a filtering_istream in chunks with a " + "multichar input filter" + ); + } + + { + temp_file dest; + lowercase_file lower; + filtering_ostream + out( tolower_filter() | + tolower_multichar_filter() | + file_sink(dest.name(), out_mode) ); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chunks with a " + "multichar output filter with no buffer" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("pipeline test"); + test->add(BOOST_TEST_CASE(&pipeline_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/putback_test.hpp b/src/boost/libs/iostreams/test/putback_test.hpp new file mode 100644 index 00000000..05b4f5ad --- /dev/null +++ b/src/boost/libs/iostreams/test/putback_test.hpp @@ -0,0 +1,167 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams/ for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_PUTBACK_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_PUTBACK_HPP_INCLUDED + +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/putback.hpp> +#include "detail/constants.hpp" +#include "detail/temp_file.hpp" + +using boost::iostreams::test::chunk_size; + +bool putback_test_one(std::istream& is) +{ + try { + do { + char buf[chunk_size]; + is.read(buf, chunk_size); + if (is.gcount() < static_cast<std::streamsize>(chunk_size)) + break; + is.putback('a'); + if (is.get() != 'a') + return false; + } while (!is.eof()); + return true; + } catch (std::exception&) { return false; } +} + +bool putback_test_two(std::istream& is) +{ + try { + do { + char buf[chunk_size]; + is.read(buf, chunk_size); + if (is.gcount() < static_cast<std::streamsize>(chunk_size)) + break; + is.putback('a'); + is.putback('b'); + is.putback('c'); + is.putback('d'); + if ( is.get() != 'd' || is.get() != 'c' || + is.get() != 'b' || is.get() != 'a' ) + { + return false; + } + } while (!is.eof()); + return true; + } catch (std::exception&) { return false; } +} + +template<typename Source> +bool putback_test_three(Source& src) +{ + try { + while (true) { + char buf[chunk_size]; + if (boost::iostreams::read(src, buf, chunk_size) < chunk_size) + break; + boost::iostreams::putback(src, 'a'); + if (boost::iostreams::get(src) != 'a') + return false; + } + return true; + } catch (std::exception&) { return false; } +} + +template<typename Source> +bool putback_test_four(Source& src) +{ + try { + while (true) { + char buf[chunk_size]; + if (boost::iostreams::read(src, buf, chunk_size) < chunk_size) + break; + boost::iostreams::putback(src, 'a'); + boost::iostreams::putback(src, 'b'); + boost::iostreams::putback(src, 'c'); + boost::iostreams::putback(src, 'd'); + if ( boost::iostreams::get(src) != 'd' || + boost::iostreams::get(src) != 'c' || + boost::iostreams::get(src) != 'b' || + boost::iostreams::get(src) != 'a' ) + { + return false; + } + } + return true; + } catch (std::exception&) { return false; } +} + +void putback_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + filtering_istream is; + is.set_device_buffer_size(0); + is.push(file_source(test.name())); + BOOST_CHECK_MESSAGE( + putback_test_one(is), + "failed putting back to unbuffered filtering_istream" + ); + } + + { + filtering_istream is; + is.set_pback_size(4); + is.push(file_source(test.name())); + BOOST_CHECK_MESSAGE( + putback_test_two(is), + "failed putting back to buffered filtering_istream" + ); + } + + { + filtering_istream is; + is.set_device_buffer_size(0); + is.push(file_source(test.name())); + BOOST_CHECK_MESSAGE( + putback_test_three(is), + "failed putting back to unbuffered filtering_istream" + ); + } + + { + filtering_istream is; + is.set_pback_size(4); + is.push(file_source(test.name())); + BOOST_CHECK_MESSAGE( + putback_test_four(is), + "failed putting back to buffered filtering_istream" + ); + } + + { + filtering_istreambuf sb; + sb.set_device_buffer_size(0); + sb.push(file_source(test.name())); + BOOST_CHECK_MESSAGE( + putback_test_three(sb), + "failed putting back to unbuffered filtering_istream" + ); + } + + { + filtering_istreambuf sb; + sb.set_pback_size(4); + sb.push(file_source(test.name())); + BOOST_CHECK_MESSAGE( + putback_test_four(sb), + "failed putting back to buffered filtering_istream" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_PUTBACK_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_bidir_filter_test.hpp b/src/boost/libs/iostreams/test/read_bidir_filter_test.hpp new file mode 100644 index 00000000..b30a0cf0 --- /dev/null +++ b/src/boost/libs/iostreams/test/read_bidir_filter_test.hpp @@ -0,0 +1,131 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_FILTER_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/combine.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/filters.hpp" +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_bidirectional_filter_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + uppercase_file upper; + + //{ + // test_file src; + // temp_file dest; // Dummy. + // filtering_stream<bidirectional> first; + // first.push(combine(toupper_filter(), tolower_filter())); + // first.push( + // combine(file_source(src.name()), file_sink(dest.name())) + // ); + // ifstream second(upper.name().c_str()); + // BOOST_CHECK_MESSAGE( + // compare_streams_in_chars(first, second), + // "failed reading from filtering_stream<bidirectional> in chars with an " + // "input filter" + // ); + //} + + { + test_file src; + temp_file dest; // Dummy. + filtering_stream<bidirectional> first; + first.push(combine(toupper_filter(), tolower_filter())); + first.push( + combine(file_source(src.name()), file_sink(dest.name())) + ); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<bidirectional> in chunks with an " + "input filter" + ); + } + + //{ + // test_file src; + // temp_file dest; // Dummy. + // filtering_stream<bidirectional> first( + // combine(toupper_multichar_filter(), tolower_filter()), 0 + // ); + // first.push( + // combine(file_source(src.name()), file_sink(dest.name())) + // ); + // ifstream second(upper.name().c_str()); + // BOOST_CHECK_MESSAGE( + // compare_streams_in_chars(first, second), + // "failed reading from filtering_stream<bidirectional> in chars with " + // "a multichar input filter with no buffer" + // ); + //} + + //{ + // test_file src; + // temp_file dest; // Dummy. + // filtering_stream<bidirectional> first( + // combine(toupper_multichar_filter(), tolower_filter()), 0 + // ); + // first.push( + // combine(file_source(src.name()), file_sink(dest.name())) + // ); + // ifstream second(upper.name().c_str()); + // BOOST_CHECK_MESSAGE( + // compare_streams_in_chunks(first, second), + // "failed reading from filtering_stream<bidirectional> in chunks " + // "with a multichar input filter with no buffer" + // ); + //} + + //{ + // test_file src; + // temp_file dest; // Dummy. + // filtering_stream<bidirectional> first( + // combine(toupper_multichar_filter(), tolower_filter()) + // ); + // first.push( + // combine(file_source(src.name()), file_sink(dest.name())) + // ); + // ifstream second(upper.name().c_str()); + // BOOST_CHECK_MESSAGE( + // compare_streams_in_chars(first, second), + // "failed reading from filtering_stream<bidirectional> in chars with a " + // "multichar input filter" + // ); + //} + + //{ + // test_file src; + // temp_file dest; // Dummy. + // filtering_stream<bidirectional> first( + // combine(toupper_multichar_filter(), tolower_filter()) + // ); + // first.push( + // combine(file_source(src.name()), file_sink(dest.name())) + // ); + // ifstream second(upper.name().c_str()); + // BOOST_CHECK_MESSAGE( + // compare_streams_in_chunks(first, second), + // "failed reading from filtering_stream<bidirectional> in chunks " + // "with a multichar input filter" + // ); + //} +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_bidir_streambuf_test.hpp b/src/boost/libs/iostreams/test/read_bidir_streambuf_test.hpp new file mode 100644 index 00000000..4a14cad2 --- /dev/null +++ b/src/boost/libs/iostreams/test/read_bidir_streambuf_test.hpp @@ -0,0 +1,77 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_bidirectional_streambuf_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test1; + test_file test2; + + { + filebuf fb; + fb.open(test1.name().c_str(), BOOST_IOS::in); + filtering_stream<bidirectional> first(fb, 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<bidirectional> based on a" + "streambuf in chars with no buffer" + ); + } + + { + filebuf fb; + fb.open(test1.name().c_str(), BOOST_IOS::in); + filtering_stream<bidirectional> first(fb, 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<bidirectional> based on a" + "streambuf in chunks with no buffer" + ); + } + + { + filebuf fb; + fb.open(test1.name().c_str(), BOOST_IOS::in); + filtering_stream<bidirectional> first(fb); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<bidirectional> based on a" + "streambuf in chars with large buffer" + ); + } + + { + filebuf fb; + fb.open(test1.name().c_str(), BOOST_IOS::in); + filtering_stream<bidirectional> first(fb); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<bidirectional> based on a" + "streambuf in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_bidir_test.hpp b/src/boost/libs/iostreams/test/read_bidir_test.hpp new file mode 100644 index 00000000..8351bd16 --- /dev/null +++ b/src/boost/libs/iostreams/test/read_bidir_test.hpp @@ -0,0 +1,85 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/combine.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_bidirectional_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + test_file src; + temp_file dest; // Dummy. + filtering_stream<bidirectional> first( + combine(file_source(src.name()), file_sink(dest.name())), 0 + ); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<bidirectional>" + "in chars with no buffer" + ); + } + + { + test_file src; + temp_file dest; // Dummy. + filtering_stream<bidirectional> first( + combine(file_source(src.name()), file_sink(dest.name())), 0 + ); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<bidirectional>" + "in chunks with no buffer" + ); + } + + { + test_file src; + temp_file dest; // Dummy. + filtering_stream<bidirectional> first( + combine(file_source(src.name()), file_sink(dest.name())) + ); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<bidirectional>" + "in chars with large buffer" + ); + } + + { + test_file src; + temp_file dest; // Dummy. + filtering_stream<bidirectional> first( + combine(file_source(src.name()), file_sink(dest.name())) + ); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<bidirectional>" + "in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_input_filter_test.hpp b/src/boost/libs/iostreams/test/read_input_filter_test.hpp new file mode 100644 index 00000000..70575462 --- /dev/null +++ b/src/boost/libs/iostreams/test/read_input_filter_test.hpp @@ -0,0 +1,105 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_INPUT_FILTER_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/filters.hpp" +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_input_filter_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + uppercase_file upper; + + { + filtering_istream first; + first.push(toupper_filter()); + first.push(file_source(test.name())); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a filtering_istream in chars with an " + "input filter" + ); + } + + { + filtering_istream first; + first.push(toupper_filter()); + first.push(file_source(test.name())); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a filtering_istream in chunks with an " + "input filter" + ); + } + + { + filtering_istream first; + first.push(toupper_multichar_filter(), 0); + first.push(file_source(test.name())); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a filtering_istream in chars with a " + "multichar input filter with no buffer" + ); + } + + { + filtering_istream first; + first.push(toupper_multichar_filter(), 0); + first.push(file_source(test.name())); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a filtering_istream in chunks with a " + "multichar input filter with no buffer" + ); + } + + { + test_file src; + filtering_istream first; + first.push(toupper_multichar_filter()); + first.push(file_source(src.name())); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a filtering_istream in chars with a " + "multichar input filter" + ); + } + + { + test_file src; + filtering_istream first; + first.push(toupper_multichar_filter()); + first.push(file_source(src.name())); + ifstream second(upper.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a filtering_istream in chunks with a " + "multichar input filter" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_input_istream_test.hpp b/src/boost/libs/iostreams/test/read_input_istream_test.hpp new file mode 100644 index 00000000..bfc362be --- /dev/null +++ b/src/boost/libs/iostreams/test/read_input_istream_test.hpp @@ -0,0 +1,75 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_ISTREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_INPUT_ISTREAM_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_input_istream_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + test_file test2; + ifstream src(test2.name().c_str()); + filtering_istream first(src, 0); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_istream based on an istream" + "in chars with no buffer" + ); + } + + { + test_file test2; + ifstream src(test2.name().c_str()); + filtering_istream first(src, 0); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_istream based on an istream" + "in chunks with no buffer" + ); + } + + { + test_file test2; + ifstream src(test2.name().c_str()); + filtering_istream first(src); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_istream based on an istream" + "in chars with large buffer" + ); + } + + { + test_file test2; + ifstream src(test2.name().c_str()); + filtering_istream first(src); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_istream based on an istream" + "in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_ISTREAM_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_input_seq_test.hpp b/src/boost/libs/iostreams/test/read_input_seq_test.hpp new file mode 100644 index 00000000..f26f833d --- /dev/null +++ b/src/boost/libs/iostreams/test/read_input_seq_test.hpp @@ -0,0 +1,70 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_INPUT_SEQUENCE_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_input_sequence_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file file; + test_sequence<> seq; + + { + filtering_stream<input> first(make_iterator_range(seq), 0); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from range_adapter " + "in chars with no buffer" + ); + } + + { + filtering_stream<input> first(make_iterator_range(seq), 0); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from range_adapter " + "in chars with no buffer" + ); + } + + { + filtering_stream<input> first(make_iterator_range(seq)); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from range_adapter " + "in chars with large buffer" + ); + } + + { + filtering_stream<input> first(make_iterator_range(seq)); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from range_adapter " + "in chars with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_SEQUENCE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_input_test.hpp b/src/boost/libs/iostreams/test/read_input_test.hpp new file mode 100644 index 00000000..e8e0015b --- /dev/null +++ b/src/boost/libs/iostreams/test/read_input_test.hpp @@ -0,0 +1,65 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_INPUT_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_input_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test1; + test_file test2; + + { + filtering_istream first(file_source(test1.name()), 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_istream in chars with no buffer" + ); + } + + { + filtering_istream first(file_source(test1.name()), 0); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_istream in chunks with no buffer" + ); + } + + { + filtering_istream first(file_source(test1.name())); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_istream in chars with buffer" + ); + } + + { + filtering_istream first(file_source(test1.name())); + ifstream second(test2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_istream in chunks with buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_nonblocking_test.cpp b/src/boost/libs/iostreams/test/read_nonblocking_test.cpp new file mode 100644 index 00000000..64a71951 --- /dev/null +++ b/src/boost/libs/iostreams/test/read_nonblocking_test.cpp @@ -0,0 +1,74 @@ +// (C) Copyright 2018 Mario Suvajac +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/iostreams/categories.hpp> + +#include <algorithm> + +// Source that reads only one byte every time read() is called. +class read_one_source +{ +public: + typedef char char_type; + typedef boost::iostreams::source_tag category; + + template <std::size_t N> + read_one_source(const char (&data)[N]) + : data_size_m(N), data_m(data), pos_m(0) + { + } + + std::streamsize read(char* s, std::streamsize n) + { + if (pos_m < data_size_m && n > 0) + { + *s = data_m[pos_m++]; + return 1; + } + else + { + return -1; + } + } + +private: + std::size_t data_size_m; + const char* data_m; + std::size_t pos_m; +}; + +void nonblocking_read_test() +{ + static const int data_size_k = 100; + + char data[data_size_k]; + std::copy(boost::counting_iterator<char>(0), + boost::counting_iterator<char>(data_size_k), + data); + + read_one_source src(data); + boost::iostreams::non_blocking_adapter<read_one_source> nb(src); + + char read_data[data_size_k]; + std::streamsize amt = boost::iostreams::read(nb, read_data, data_size_k); + + BOOST_CHECK_EQUAL(amt, data_size_k); + + for (int i = 0; i < data_size_k; ++i) + { + BOOST_CHECK_EQUAL(std::char_traits<char>::to_int_type(read_data[i]), i); + } +} + +boost::unit_test::test_suite* init_unit_test_suite(int, char* []) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE("non-blocking read test"); + test->add(BOOST_TEST_CASE(&nonblocking_read_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/read_seekable_seq_test.hpp b/src/boost/libs/iostreams/test/read_seekable_seq_test.hpp new file mode 100644 index 00000000..185d15d8 --- /dev/null +++ b/src/boost/libs/iostreams/test/read_seekable_seq_test.hpp @@ -0,0 +1,71 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_SEEKABLE_SEQUENCE_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_seekable_sequence_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file file; + test_sequence<> seq; + + { + filtering_stream<seekable> first(make_iterator_range(seq), 0); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<seekable> based on a" + "sequence in chars with no buffer" + ); + } + + { + filtering_stream<seekable> first(make_iterator_range(seq), 0); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<seekable> based on a" + "sequence in chunks with no buffer" + ); + } + + { + filtering_stream<seekable> first(make_iterator_range(seq)); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<seekable> based on a" + "sequence in chars with large buffer" + ); + } + + { + filtering_stream<seekable> first(make_iterator_range(seq)); + ifstream second(file.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<seekable> based on a" + "sequence in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_SEQUENCE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/read_seekable_test.hpp b/src/boost/libs/iostreams/test/read_seekable_test.hpp new file mode 100644 index 00000000..f059f61d --- /dev/null +++ b/src/boost/libs/iostreams/test/read_seekable_test.hpp @@ -0,0 +1,69 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_READ_SEEKABLE_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void read_seekable_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test1; + test_file test2; + + { + filtering_stream<seekable> first(file(test1.name(), in_mode), 0); + ifstream second(test2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<seekable>" + "in chars with no buffer" + ); + } + + { + filtering_stream<seekable> first(file(test1.name(), in_mode), 0); + ifstream second(test2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<seekable>" + "in chars with no buffer" + ); + } + + { + filtering_stream<seekable> first(file(test1.name(), in_mode)); + ifstream second(test2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from filtering_stream<seekable>" + "in chars with large buffer" + ); + } + + { + filtering_stream<seekable> first(file(test1.name(), in_mode)); + ifstream second(test2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from filtering_stream<seekable>" + "in chars with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/regex_filter_test.cpp b/src/boost/libs/iostreams/test/regex_filter_test.cpp new file mode 100644 index 00000000..8fd02d67 --- /dev/null +++ b/src/boost/libs/iostreams/test/regex_filter_test.cpp @@ -0,0 +1,329 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/filter/regex.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +struct replace_lower { + std::string operator() (const boost::match_results<const char*>&) + { return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + std::wstring operator() (const boost::match_results<const wchar_t*>&) + { return L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } +#endif +}; + +void regex_filter_test() +{ + // Note: Given the basic stream and filter tests, two regex tests + // are probably sufficient: reading with a filter based on a function, + // and writing with a filter based on a format string. + + test_file test; + uppercase_file upper; + + boost::regex match_lower("[a-z]+"); + std::string fmt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a regex filter based on a function in chars. + filtering_istream + first(boost::iostreams::regex_filter(match_lower, replace_lower())); + first.push(file_source(test.name(), in_mode)); + { + ifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from function-based regex_filter in chars" + ); + } + first.pop(); + + // Test reading from a regex filter based on a function in chunks. + // (Also tests reusing the regex filter.) + first.push(file_source(test.name(), in_mode)); + { + ifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from function-based regex_filter in chunks" + ); + } + } + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a regex filter based on a format string in chars. + filtering_istream + first(boost::iostreams::regex_filter(match_lower, fmt)); + first.push(file_source(test.name(), in_mode)); + { + ifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from format-string-based regex_filter in chars" + ); + } + first.pop(); + + // Test reading from a regex filter based on a format string in chunks. + // (Also tests reusing the regex filter.) + first.push(file_source(test.name(), in_mode)); + { + ifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from format-string-based regex_filter in chunks" + ); + } + } + + { + test_file dest1; + test_file dest2; + + // Test writing to a regex filter based on a function in chars. + filtering_ostream + out(boost::iostreams::regex_filter(match_lower, replace_lower())); + out.push(file_sink(dest1.name(), out_mode)); + write_data_in_chars(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), upper.name()), + "failed writing to function-based regex_filter in chars" + ); + + // Test writing to a regex filter based on a function in chunks. + // (Also tests reusing the regex filter.) + out.push(file_sink(dest2.name(), out_mode)); + write_data_in_chunks(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest2.name(), upper.name()), + "failed writing to function-based regex_filter in chunks" + ); + } + + { + test_file dest1; + test_file dest2; + + // Test writing to a regex filter based on a format string in chars. + filtering_ostream + out(boost::iostreams::regex_filter(match_lower, fmt)); + out.push(file_sink(dest1.name(), out_mode)); + write_data_in_chars(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), upper.name()), + "failed writing to format-string-based regex_filter in chars" + ); + + // Test writing to a regex filter based on a format string in chunks. + // (Also tests reusing the regex filter.) + out.push(file_sink(dest2.name(), out_mode)); + write_data_in_chunks(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest2.name(), upper.name()), + "failed writing to format-string-based regex_filter in chunks" + ); + } + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a regex filter with no matches; this checks that + // Ticket #1139 is fixed + boost::regex match_xxx("xxx"); + test_file test2; + filtering_istream + first(boost::iostreams::regex_filter(match_xxx, replace_lower())); + first.push(file_source(test.name(), in_mode)); + { + ifstream second(test2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a regex filter with no matches" + ); + } + } +} + +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + +void wregex_filter_test() +{ + // Note: Given the basic stream and filter tests, two regex tests + // are probably sufficient: reading with a filter based on a function, + // and writing with a filter based on a format string. + + test_file test; + uppercase_file upper; + + boost::wregex match_lower(L"[a-z]+"); + std::wstring fmt = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a regex filter based on a function in chars. + filtering_wistream + first(boost::iostreams::wregex_filter(match_lower, replace_lower())); + first.push(wfile_source(test.name(), in_mode)); + { + wifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from function-based regex_filter in chars" + ); + } + first.pop(); + + // Test reading from a regex filter based on a function in chunks. + // (Also tests reusing the regex filter.) + first.push(wfile_source(test.name(), in_mode)); + { + wifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from function-based regex_filter in chunks" + ); + } + } + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a regex filter based on a format string in chars. + filtering_wistream + first(boost::iostreams::wregex_filter(match_lower, fmt)); + first.push(wfile_source(test.name(), in_mode)); + { + wifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from format-string-based regex_filter in chars" + ); + } + first.pop(); + + // Test reading from a regex filter based on a format string in chunks. + // (Also tests reusing the regex filter.) + first.push(wfile_source(test.name(), in_mode)); + { + wifstream second(upper.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from format-string-based regex_filter in chunks" + ); + } + } + + { + test_file dest1; + test_file dest2; + + // Test writing to a regex filter based on a function in chars. + filtering_wostream + out(boost::iostreams::wregex_filter(match_lower, replace_lower())); + out.push(wfile_sink(dest1.name(), out_mode)); + write_data_in_chars(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), upper.name()), + "failed writing to function-based regex_filter in chars" + ); + + // Test writing to a regex filter based on a function in chunks. + // (Also tests reusing the regex filter.) + out.push(wfile_sink(dest2.name(), out_mode)); + write_data_in_chunks(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest2.name(), upper.name()), + "failed writing to function-based regex_filter in chunks" + ); + } + + { + test_file dest1; + test_file dest2; + + // Test writing to a regex filter based on a format string in chars. + filtering_wostream + out(boost::iostreams::wregex_filter(match_lower, fmt)); + out.push(wfile_sink(dest1.name(), out_mode)); + write_data_in_chars(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), upper.name()), + "failed writing to format-string-based regex_filter in chars" + ); + + // Test writing to a regex filter based on a format string in chunks. + // (Also tests reusing the regex filter.) + out.push(wfile_sink(dest2.name(), out_mode)); + write_data_in_chunks(out); + out.pop(); + BOOST_CHECK_MESSAGE( + compare_files(dest2.name(), upper.name()), + "failed writing to format-string-based regex_filter in chunks" + ); + } + + { + // Note: the ifstream second is placed in a nested scope because + // closing and reopening a single ifstream failed for CW 9.4 on Windows. + + // Test reading from a regex filter with no matches; this checks that + // Ticket #1139 is fixed + boost::wregex match_xxx(L"xxx"); + test_file test2; + filtering_wistream + first(boost::iostreams::wregex_filter(match_xxx, replace_lower())); + first.push(wfile_source(test.name(), in_mode)); + { + wifstream second(test2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a regex filter with no matches" + ); + } + } +} + +#endif + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("regex_filter test"); + test->add(BOOST_TEST_CASE(®ex_filter_test)); +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + test->add(BOOST_TEST_CASE(&wregex_filter_test)); +#endif + return test; +} diff --git a/src/boost/libs/iostreams/test/restrict_test.cpp b/src/boost/libs/iostreams/test/restrict_test.cpp new file mode 100644 index 00000000..b844f9e6 --- /dev/null +++ b/src/boost/libs/iostreams/test/restrict_test.cpp @@ -0,0 +1,690 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Allow this file to be used by slice_test.hpp. It is important not to +// replace BOOST_IOSTREAMS_RESTRICT with BOOST_IOSTREAMS_RESTRICT here, since that +// would interfere with the oepration of the header +// <boost/iostreams/restrict.hpp> +#include <iostream> + +#if defined(BOOST_IOSTREAMS_RESTRICT_USE_SLICE) +# include <boost/iostreams/slice.hpp> +# define BOOST_IOSTREAMS_RESTRICT slice +#else +# include <boost/iostreams/restrict.hpp> +# define BOOST_IOSTREAMS_RESTRICT restrict +#endif + +#include <algorithm> // equal. +#include <cctype> +#include <iterator> // back_inserter. +#include <vector> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/device/null.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/constants.hpp" +#include "detail/filters.hpp" +#include "detail/operation_sequence.hpp" +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +const char pad_char = '\n'; +const int small_padding = 50; +const int large_padding = default_device_buffer_size + 50; + +void write_padding(std::ofstream& out, int len) +{ + for (int z = 0; z < len; ++z) + out.put(pad_char); +} + +struct restricted_test_file : public temp_file { + restricted_test_file(int padding, bool half_open = false) + { + BOOST_IOS::openmode mode = + BOOST_IOS::out | BOOST_IOS::binary; + ::std::ofstream f(name().c_str(), mode); + write_padding(f, padding); + const char* buf = narrow_data(); + for (int z = 0; z < data_reps; ++z) + f.write(buf, data_length()); + if (!half_open) + write_padding(f, padding); + } +}; + +struct restricted_test_sequence : public std::vector<char> { + restricted_test_sequence(int padding, bool half_open = false) + { + for (int z = 0; z < padding; ++z) + push_back(pad_char); + const char* buf = narrow_data(); + for (int w = 0; w < data_reps; ++w) + insert(end(), buf, buf + data_length()); + if (!half_open) + for (int x = 0; x < padding; ++x) + push_back(pad_char); + } +}; + +struct restricted_uppercase_file : public temp_file { + restricted_uppercase_file(int padding, bool half_open = false) + { + BOOST_IOS::openmode mode = + BOOST_IOS::out | BOOST_IOS::binary; + ::std::ofstream f(name().c_str(), mode); + write_padding(f, padding); + const char* buf = narrow_data(); + for (int z = 0; z < data_reps; ++z) + for (int w = 0; w < data_length(); ++w) + f.put((char) std::toupper(buf[w])); + if (!half_open) + write_padding(f, padding); + } +}; + +struct restricted_lowercase_file : public temp_file { + restricted_lowercase_file(int padding, bool half_open = false) + { + BOOST_IOS::openmode mode = + BOOST_IOS::out | BOOST_IOS::binary; + ::std::ofstream f(name().c_str(), mode); + write_padding(f, padding); + const char* buf = narrow_data(); + for (int z = 0; z < data_reps; ++z) + for (int w = 0; w < data_length(); ++w) + f.put((char) std::tolower(buf[w])); + if (!half_open) + write_padding(f, padding); + } +}; + +// Can't have a restricted view of a non-seekble output filter. +struct tolower_seekable_filter : public seekable_filter { + typedef char char_type; + struct category + : output_seekable, + filter_tag + { }; + template<typename Sink> + bool put(Sink& s, char c) + { return boost::iostreams::put(s, (char) std::tolower(c)); } + + template<typename Sink> + std::streampos seek(Sink& s, stream_offset off, BOOST_IOS::seekdir way) + { return boost::iostreams::seek(s, off, way); } +}; + +void read_device() +{ + { + restricted_test_file src1(small_padding); + test_file src2; + stream_offset off = small_padding, + len = data_reps * data_length(); + filtering_istream first( + BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off, len)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from restriction<Device> with small padding" + ); + } + + { + restricted_test_file src1(large_padding); + test_file src2; + stream_offset off = large_padding, + len = data_reps * data_length(); + filtering_istream first( + BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off, len)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from restriction<Device> with large padding" + ); + } + + { + restricted_test_file src1(small_padding, true); + test_file src2; + stream_offset off = small_padding; + filtering_istream first( + BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from half-open restriction<Device> " + "with small padding" + ); + } + + { + restricted_test_file src1(large_padding, true); + test_file src2; + stream_offset off = large_padding; + filtering_istream first( + BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from half-open restriction<Device> " + "with large padding" + ); + } +} + +void read_direct_device() +{ + { + test_sequence<char> first; + restricted_test_sequence src(small_padding); + array_source array_src(&src[0], &src[0] + src.size()); + stream_offset off = small_padding, + len = data_reps * data_length(); + filtering_istream second(BOOST_IOSTREAMS_RESTRICT(array_src, off, len)); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed reading from restriction<Direct>" + ); + } + + { + test_sequence<char> first; + restricted_test_sequence src(small_padding, true); + array_source array_src(&src[0], &src[0] + src.size()); + stream_offset off = small_padding; + filtering_istream second(BOOST_IOSTREAMS_RESTRICT(array_src, off)); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed reading from half-open restriction<Direct>" + ); + } +} + +void read_filter() +{ + { + restricted_test_file src1(small_padding); + uppercase_file src2; + stream_offset off = small_padding, + len = data_reps * data_length(); + filtering_istream first; + first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off, len)); + first.push(file_source(src1.name(), in_mode)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from restriction<Filter> with small padding" + ); + } + + { + restricted_test_file src1(large_padding); + uppercase_file src2; + stream_offset off = large_padding, + len = data_reps * data_length(); + filtering_istream first; + first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off, len)); + first.push(file_source(src1.name(), in_mode)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from restriction<Filter> with large padding" + ); + } + + { + restricted_test_file src1(small_padding, true); + uppercase_file src2; + stream_offset off = small_padding; + filtering_istream first; + first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off)); + first.push(file_source(src1.name(), in_mode)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from half-open restriction<Filter> " + "with small padding" + ); + } + + { + restricted_test_file src1(large_padding, true); + uppercase_file src2; + stream_offset off = large_padding; + filtering_istream first; + first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off)); + first.push(file_source(src1.name(), in_mode)); + ifstream second(src2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from half-open restriction<Filter> " + "with large padding" + ); + } +} + +void write_device() +{ + { + restricted_uppercase_file dest1(small_padding); + restricted_test_file dest2(small_padding); + stream_offset off = small_padding, + len = data_reps * data_length(); + filtering_ostream out( + BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off, len)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to restriction<Device> with small padding" + ); + } + + { + restricted_uppercase_file dest1(large_padding); + restricted_test_file dest2(large_padding); + stream_offset off = large_padding, + len = data_reps * data_length(); + filtering_ostream out + (BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off, len)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to restriction<Device> with large padding" + ); + } + + { + restricted_uppercase_file dest1(small_padding, true); + restricted_test_file dest2(small_padding, true); + stream_offset off = small_padding; + filtering_ostream out + (BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to half-open restriction<Device> " + "with small padding" + ); + } + + { + restricted_uppercase_file dest1(large_padding, true); + restricted_test_file dest2(large_padding, true); + stream_offset off = large_padding; + filtering_ostream out + (BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to half-open restriction<Device> " + "with large padding" + ); + } +} + +void write_direct_device() +{ + { + vector<char> dest1( data_reps * data_length() + + 2 * small_padding, + '\n' ); + restricted_test_sequence dest2(small_padding); + stream_offset off = small_padding, + len = data_reps * data_length(); + array_sink array(&dest1[0], &dest1[0] + dest1.size()); + filtering_ostream out(BOOST_IOSTREAMS_RESTRICT(array, off, len)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + std::equal(dest1.begin(), dest1.end(), dest2.begin()), + "failed writing to restriction<Direct>" + ); + } + + { + vector<char> dest1( + data_reps * data_length() + small_padding, '\n'); + restricted_test_sequence dest2(small_padding, true); + stream_offset off = small_padding; + array_sink array(&dest1[0], &dest1[0] + dest1.size()); + filtering_ostream out(BOOST_IOSTREAMS_RESTRICT(array, off)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + std::equal(dest1.begin(), dest1.end(), dest2.begin()), + "failed writing to half-open restriction<Direct>" + ); + } +} + +void write_filter() +{ + { + restricted_test_file dest1(small_padding); + restricted_lowercase_file dest2(small_padding); + stream_offset off = small_padding, + len = data_reps * data_length(); + filtering_ostream out; + out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off, len)); + out.push(file(dest1.name(), BOOST_IOS::binary)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to restriction<Filter> with small padding" + ); + } + + { + restricted_test_file dest1(large_padding); + restricted_lowercase_file dest2(large_padding); + stream_offset off = large_padding, + len = data_reps * data_length(); + filtering_ostream out; + out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off, len)); + out.push(file(dest1.name(), BOOST_IOS::binary)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to restriction<Filter> with large padding" + ); + } + + { + restricted_test_file dest1(small_padding, true); + restricted_lowercase_file dest2(small_padding, true); + stream_offset off = small_padding; + filtering_ostream out; + out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off)); + out.push(file(dest1.name(), BOOST_IOS::binary)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to restriction<Filter> with small padding" + ); + } + + { + restricted_test_file dest1(large_padding, true); + restricted_lowercase_file dest2(large_padding, true); + stream_offset off = large_padding; + filtering_ostream out; + out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off)); + out.push(file(dest1.name(), BOOST_IOS::binary)); + write_data_in_chunks(out); + out.reset(); + ifstream first(dest1.name().c_str(), in_mode); + ifstream second(dest2.name().c_str(), in_mode); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to restriction<Filter> with large padding" + ); + } +} + +void seek_device() +{ + { + restricted_test_file src(large_padding); + stream_offset off = large_padding, + len = data_reps * data_length(); + filtering_stream<seekable> io( + BOOST_IOSTREAMS_RESTRICT(file(src.name(), BOOST_IOS::binary), off, len)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within restriction<Device>" + ); + } + + { + restricted_test_file src(large_padding, true); + stream_offset off = large_padding; + filtering_stream<seekable> io( + BOOST_IOSTREAMS_RESTRICT(file(src.name(), BOOST_IOS::binary), off)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within half-open restriction<Device>" + ); + } +} + +void seek_direct_device() +{ + { + vector<char> src( + data_reps * data_length() + 2 * small_padding, '\n'); + stream_offset off = small_padding, + len = data_reps * data_length(); + io::array ar(&src[0], &src[0] + src.size()); + filtering_stream<seekable> io(BOOST_IOSTREAMS_RESTRICT(ar, off, len)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within restriction<Direct> with small padding" + ); + } + + { + vector<char> src( + data_reps * data_length() + small_padding, '\n'); + stream_offset off = small_padding; + io::array ar(&src[0], &src[0] + src.size()); + filtering_stream<seekable> io(BOOST_IOSTREAMS_RESTRICT(ar, off)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within half-open restriction<Direct> " + "with small padding" + ); + } +} + +void seek_filter() +{ + { + restricted_test_file src(small_padding); + stream_offset off = large_padding, + len = data_reps * data_length(); + filtering_stream<seekable> io; + io.push(BOOST_IOSTREAMS_RESTRICT(identity_seekable_filter(), off, len)); + io.push(file(src.name(), BOOST_IOS::binary)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within restriction<Device>" + ); + } + + { + restricted_test_file src(small_padding, true); + stream_offset off = large_padding; + filtering_stream<seekable> io; + io.push(BOOST_IOSTREAMS_RESTRICT(identity_seekable_filter(), off)); + io.push(file(src.name(), BOOST_IOS::binary)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within half-open restriction<Device>" + ); + } +} + +void close_device() +{ + // Restrict a source + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_device<input>(seq.new_operation(1)), + 0 + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Restrict a seekable device + { + operation_sequence seq; + chain<seekable> ch; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_device<seekable>(seq.new_operation(1)), + 0 + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Restrict a direct source + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_device<direct_input>(seq.new_operation(1)), + 0 + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Restrict a direct seekable device + { + operation_sequence seq; + chain<seekable> ch; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_device<direct_seekable>(seq.new_operation(1)), + 0 + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void close_filter() +{ + // Restrict an input filter + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_filter<input>(seq.new_operation(2)), + 0 + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Restrict a seekable filter + { + operation_sequence seq; + chain<seekable> ch; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_filter<seekable>(seq.new_operation(1)), + 0 + ) + ); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Restrict a dual_use filter for input + { + operation_sequence seq; + chain<input> ch; + operation dummy; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_filter<dual_use>( + seq.new_operation(2), + dummy + ), + 0 + ) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Restrict a dual_use filter for output + { + operation_sequence seq; + chain<output> ch; + operation dummy; + ch.push( + io::BOOST_IOSTREAMS_RESTRICT( + closable_filter<dual_use>( + dummy, + seq.new_operation(1) + ), + 0 + ) + ); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = + BOOST_TEST_SUITE(BOOST_STRINGIZE(BOOST_IOSTREAMS_RESTRICT) " test"); + test->add(BOOST_TEST_CASE(&read_device)); + test->add(BOOST_TEST_CASE(&read_direct_device)); + test->add(BOOST_TEST_CASE(&read_filter)); + test->add(BOOST_TEST_CASE(&write_device)); + test->add(BOOST_TEST_CASE(&write_direct_device)); + test->add(BOOST_TEST_CASE(&write_filter)); + test->add(BOOST_TEST_CASE(&seek_device)); + test->add(BOOST_TEST_CASE(&seek_direct_device)); + test->add(BOOST_TEST_CASE(&close_device)); + test->add(BOOST_TEST_CASE(&close_filter)); + return test; +} diff --git a/src/boost/libs/iostreams/test/seek_test.hpp b/src/boost/libs/iostreams/test/seek_test.hpp new file mode 100644 index 00000000..68c0aeaf --- /dev/null +++ b/src/boost/libs/iostreams/test/seek_test.hpp @@ -0,0 +1,51 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_SEEK_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_SEEK_HPP_INCLUDED + + +#include <boost/config.hpp> // BOOST_MSVC, make sure size_t is in std. +#include <cstddef> // std::size_t. +#include <string> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "../example/container_device.hpp" // We use container_device instead +#include "detail/verification.hpp" // of make_iterator_range to + // reduce dependence on Boost.Range + +void seek_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::example; + using namespace boost::iostreams::test; + + { + string test(data_reps * data_length(), '\0'); + filtering_stream<seekable> io; + io.push(container_device<string>(test)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within a filtering_stream<seekable>, in chars" + ); + } + + { + string test(data_reps * data_length(), '\0'); + filtering_stream<seekable> io; + io.push(container_device<string>(test)); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within a filtering_stream<seekable>, in chunks" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_SEEK_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/seekable_file_test.cpp b/src/boost/libs/iostreams/test/seekable_file_test.cpp new file mode 100644 index 00000000..738bc1ba --- /dev/null +++ b/src/boost/libs/iostreams/test/seekable_file_test.cpp @@ -0,0 +1,56 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void seekable_file_test() +{ + { + temp_file temp; + file f( temp.name(), + BOOST_IOS::in | BOOST_IOS::out | + BOOST_IOS::trunc | BOOST_IOS::binary); + filtering_stream<seekable> io(f); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within a file, in chars" + ); + } + + { + temp_file temp; + file f( temp.name(), + BOOST_IOS::in | BOOST_IOS::out | + BOOST_IOS::trunc | BOOST_IOS::binary); + filtering_stream<seekable> io(f); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within a file, in chunks" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("seekable file test"); + test->add(BOOST_TEST_CASE(&seekable_file_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/seekable_filter_test.cpp b/src/boost/libs/iostreams/test/seekable_filter_test.cpp new file mode 100644 index 00000000..afd0af8f --- /dev/null +++ b/src/boost/libs/iostreams/test/seekable_filter_test.cpp @@ -0,0 +1,95 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <vector> +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "../example/container_device.hpp" // We use container_device instead +#include "detail/filters.hpp" // of make_iterator_range to +#include "detail/temp_file.hpp" // reduce dependence on Boost.Range +#include "detail/verification.hpp" + + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::example; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + + +// Code generation bugs cause tests to fail with global optimization. +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# pragma optimize("g", off) +#endif + +void seekable_filter_test() +{ + { + vector<char> test(data_reps * data_length(), '0'); + filtering_stream<seekable> io; + io.push(identity_seekable_filter()); + io.push(container_device< vector<char> >(test)); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within a file, in chars" + ); + } + + { + vector<char> test(data_reps * data_length(), '0'); + filtering_stream<seekable> io; + io.push(identity_seekable_filter()); + io.push(container_device< vector<char> >(test)); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within a file, in chunks" + ); + } + + { + vector<char> test(data_reps * data_length(), '0'); + filtering_stream<seekable> io; + io.push(identity_seekable_multichar_filter()); + io.push(container_device< vector<char> >(test)); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chars(io), + "failed seeking within a file, in chars" + ); + } + + { + vector<char> test(data_reps * data_length(), '0'); + filtering_stream<seekable> io; + io.push(identity_seekable_multichar_filter()); + io.push(container_device< vector<char> >(test)); + io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit); + BOOST_CHECK_MESSAGE( + test_seekable_in_chunks(io), + "failed seeking within a file, in chunks" + ); + } +} + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# pragma optimize("", on) +#endif + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("seekable filter test"); + test->add(BOOST_TEST_CASE(&seekable_filter_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/sequence_test.cpp b/src/boost/libs/iostreams/test/sequence_test.cpp new file mode 100644 index 00000000..9dd182cc --- /dev/null +++ b/src/boost/libs/iostreams/test/sequence_test.cpp @@ -0,0 +1,24 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/test/unit_test.hpp> +#include "read_input_seq_test.hpp" +#include "read_seekable_seq_test.hpp" +#include "write_output_seq_test.hpp" +#include "write_seekable_seq_test.hpp" + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("sequence test"); + test->add(BOOST_TEST_CASE(&read_input_sequence_test)); + test->add(BOOST_TEST_CASE(&read_seekable_sequence_test)); + test->add(BOOST_TEST_CASE(&write_output_sequence_test)); + test->add(BOOST_TEST_CASE(&write_seekable_sequence_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/slice_test.cpp b/src/boost/libs/iostreams/test/slice_test.cpp new file mode 100644 index 00000000..c33be41d --- /dev/null +++ b/src/boost/libs/iostreams/test/slice_test.cpp @@ -0,0 +1,17 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: test/slice_test.hpp + * Date: Sun Jan 06 12:57:30 MST 2008 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Tests the overloaded function template boost::iostreams::slice. + */ + +#define BOOST_IOSTREAMS_RESTRICT_USE_SLICE +#include "restrict_test.cpp" diff --git a/src/boost/libs/iostreams/test/stdio_filter_test.cpp b/src/boost/libs/iostreams/test/stdio_filter_test.cpp new file mode 100644 index 00000000..6bcbe315 --- /dev/null +++ b/src/boost/libs/iostreams/test/stdio_filter_test.cpp @@ -0,0 +1,144 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <cctype> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filter/stdio.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/filters.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x. + +using namespace boost::iostreams; +using boost::unit_test::test_suite; + +struct toupper_stdio_filter : stdio_filter { + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) + std::cout.put(std::toupper((unsigned char)c)); + } +}; + +struct tolower_stdio_filter : stdio_filter { + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) + std::cout.put(std::tolower((unsigned char)c)); + } +}; + +struct padding_stdio_filter : stdio_filter { + padding_stdio_filter(char pad_char) : pad_char_(pad_char) { } + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + std::cout.put(c); + std::cout.put(pad_char_); + } + } + char pad_char_; +}; + +void read_stdio_filter() +{ + using namespace boost::iostreams::test; + + test_file src1, src2; + filtering_istream first, second; + + first.push(toupper_filter()); + first.push(padding_filter('a')); + first.push(file_source(src1.name(), in_mode)); + second.push(toupper_stdio_filter()); + second.push(padding_stdio_filter('a')); + second.push(file_source(src2.name(), in_mode)); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a stdio_filter" + ); + + first.reset(); + first.push(padding_filter('a')); + first.push(toupper_filter()); + first.push(file_source(src1.name(), in_mode)); + second.reset(); + second.push(padding_stdio_filter('a')); + second.push(toupper_stdio_filter()); + second.push(file_source(src2.name(), in_mode)); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a stdio_filter" + ); +} + +void write_stdio_filter() +{ + using namespace std; + using namespace boost::iostreams::test; + + temp_file dest1, dest2; + filtering_ostream out1, out2; + + out1.push(tolower_filter()); + out1.push(padding_filter('a')); + out1.push(file_sink(dest1.name(), in_mode)); + out2.push(tolower_stdio_filter()); + out2.push(padding_stdio_filter('a')); + out2.push(file_sink(dest2.name(), in_mode)); + write_data_in_chunks(out1); + write_data_in_chunks(out2); + out1.reset(); + out2.reset(); + + { + ifstream first(dest1.name().c_str()); + ifstream second(dest2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to a stdio_filter" + ); + } + + out1.push(padding_filter('a')); + out1.push(tolower_filter()); + out1.push(file_sink(dest1.name(), in_mode)); + out2.push(padding_stdio_filter('a')); + out2.push(tolower_stdio_filter()); + out2.push(file_sink(dest2.name(), in_mode)); + write_data_in_chunks(out1); + write_data_in_chunks(out2); + out1.reset(); + out2.reset(); + + { + ifstream first(dest1.name().c_str()); + ifstream second(dest2.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed writing to a stdio_filter" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("line_filter test"); + test->add(BOOST_TEST_CASE(&read_stdio_filter)); + test->add(BOOST_TEST_CASE(&write_stdio_filter)); + return test; +} + +#include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x. diff --git a/src/boost/libs/iostreams/test/stream_offset_32bit_test.cpp b/src/boost/libs/iostreams/test/stream_offset_32bit_test.cpp new file mode 100644 index 00000000..542e31cb --- /dev/null +++ b/src/boost/libs/iostreams/test/stream_offset_32bit_test.cpp @@ -0,0 +1,51 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: libs/iostreams/test/stream_offset_32bit_test.cpp + * Date: Sun Dec 23 21:11:23 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Tests the functions defined in the header "boost/iostreams/positioning.hpp" + * with small (32-bit) file offsets. + */ + +#include <boost/iostreams/positioning.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include <boost/type_traits/is_integral.hpp> + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using boost::unit_test::test_suite; + +void stream_offset_32bit_test() +{ + stream_offset small_file = 1000000; + stream_offset off = -small_file; + streampos pos = offset_to_position(off); + + while (off < small_file) + { + BOOST_CHECK(off == position_to_offset(offset_to_position(off))); + BOOST_CHECK(pos == offset_to_position(position_to_offset(pos))); + off += 20000; + pos += 20000; + BOOST_CHECK(off == position_to_offset(offset_to_position(off))); + BOOST_CHECK(pos == offset_to_position(position_to_offset(pos))); + off -= 10000; + pos -= 10000; + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("stream_offset 32-bit test"); + test->add(BOOST_TEST_CASE(&stream_offset_32bit_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/stream_offset_64bit_test.cpp b/src/boost/libs/iostreams/test/stream_offset_64bit_test.cpp new file mode 100644 index 00000000..6ebda4f1 --- /dev/null +++ b/src/boost/libs/iostreams/test/stream_offset_64bit_test.cpp @@ -0,0 +1,85 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: libs/iostreams/test/stream_offset_64bit_test.cpp + * Date: Sun Dec 23 21:11:23 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Tests the functions defined in the header "boost/iostreams/positioning.hpp" + * with large (64-bit) file offsets. + */ + +#include <cstdio> // fpos_t +#include <iostream> +#include <sstream> +#include <boost/config.hpp> // BOOST_MSVC +#include <boost/iostreams/detail/ios.hpp> +#include <boost/iostreams/positioning.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using boost::unit_test::test_suite; + +#ifdef BOOST_MSVC +# pragma warning(disable:4127) +#endif + +void stream_offset_64bit_test() +{ + stream_offset large_file = (stream_offset) 100 * + (stream_offset) 1024 * + (stream_offset) 1024 * + (stream_offset) 1024; + stream_offset first = -large_file - (-large_file) % 10000000; + stream_offset last = large_file - large_file % 10000000; + + for (stream_offset off = first; off < last; off += 10000000) + { + if (off != position_to_offset(offset_to_position(off))) { + cout << "****************************************\n" + << "* sizeof(fpos_t) = " << sizeof(fpos_t) << "\n" + << "* sizeof(streamoff) = " << sizeof(streamoff) << "\n" + << "* sizeof(stream_offset) = " + << sizeof(stream_offset) << "\n" + << "****************************************\n"; + stringstream s; + s << "off != position_to_offset(offset_to_position(off)) " + "failed for (off >> 32) == 0x" + << hex + << static_cast<unsigned int>(off >> 32) + << " and (off & 0xFFFFFFFF) == 0x" + << static_cast<unsigned int>(off & 0xFFFFFFFF) + << std::endl; + BOOST_REQUIRE_MESSAGE(0, s.str().c_str()); + } + } +} + +void stream_offset_64bit_test2() +{ + boost::int64_t val = boost::int64_t(1) << 31; + std::streampos pos = boost::iostreams::offset_to_position(val); + pos -= 2; + BOOST_CHECK_EQUAL(val - 2, boost::iostreams::position_to_offset(pos)); + + val = -val; + pos = boost::iostreams::offset_to_position(val); + pos += 2; + BOOST_CHECK_EQUAL(val + 2, boost::iostreams::position_to_offset(pos)); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("stream_offset 64-bit test"); + test->add(BOOST_TEST_CASE(&stream_offset_64bit_test)); + test->add(BOOST_TEST_CASE(&stream_offset_64bit_test2)); + return test; +} diff --git a/src/boost/libs/iostreams/test/stream_state_test.cpp b/src/boost/libs/iostreams/test/stream_state_test.cpp new file mode 100644 index 00000000..9b7a3da4 --- /dev/null +++ b/src/boost/libs/iostreams/test/stream_state_test.cpp @@ -0,0 +1,182 @@ +// (C) Copyright Frank Birbacher 2007 +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/config.hpp> +#include <boost/iostreams/categories.hpp> // tags. +#include <boost/iostreams/detail/ios.hpp> // openmode, seekdir, int types. +#include <boost/iostreams/detail/error.hpp> +#include <boost/iostreams/positioning.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +using boost::iostreams::detail::bad_read; +using boost::iostreams::detail::bad_seek; +using boost::iostreams::detail::bad_write; +using boost::iostreams::seekable_device_tag; +using boost::iostreams::stream; +using boost::iostreams::stream_offset; +using boost::unit_test::test_suite; + +/* + * This test unit uses a custom device to trigger errors. The device supports + * input, output, and seek according to the SeekableDevice concept. And each + * of the required functions throw a special detail::bad_xxx exception. This + * should trigger the iostreams::stream to set the badbit status flag. + * Additionally the exception can be propagated to the caller if the exception + * mask of the stream allows exceptions. + * + * The stream offers four different functions: read, write, seekg, and seekp. + * Each of them is tested with three different error reporting concepts: + * test by reading status flags, test by propagated exception, and test by + * calling std::ios_base::exceptions when badbit is already set. + * + * In each case all of the status checking functions of a stream are checked. + * + * MSVCPRT (Visual Studio 2017, at least) does not perform exception + * handling in the seek methods (confirmed by inspecting sources). + * + * CYGWIN (with gcc-7.3.0) does not behave properly on the throw_delayed cases. + */ + +//------------------Definition of error_device--------------------------------// + +// Device whose member functions throw +struct error_device { + typedef char char_type; + typedef seekable_device_tag category; + error_device(char const*) {} + std::streamsize read(char_type*, std::streamsize) + { + throw bad_read(); + } + std::streamsize write(const char_type*, std::streamsize) + { + throw bad_write(); + } + std::streampos seek(stream_offset, BOOST_IOS::seekdir) + { + throw bad_seek(); + } +}; + +typedef stream<error_device> test_stream; + +//------------------Stream state tester---------------------------------------// + +void check_stream_for_badbit(const std::iostream& str) +{ + BOOST_CHECK_MESSAGE(!str.good(), "stream still good"); + BOOST_CHECK_MESSAGE(!str.eof(), "eofbit set but not expected"); + BOOST_CHECK_MESSAGE(str.bad(), "stream did not set badbit"); + BOOST_CHECK_MESSAGE(str.fail(), "stream did not fail"); + BOOST_CHECK_MESSAGE(str.operator ! (), + "stream does not report failure by operator !"); + BOOST_CHECK_MESSAGE(false == static_cast<bool>(str), + "stream does not report failure by operator void* or bool"); +} + +//------------------Test case generators--------------------------------------// + +template<void (*const function)(std::iostream&)> +struct wrap_nothrow { + static void execute() + { + test_stream stream("foo"); + BOOST_CHECK_NO_THROW( function(stream) ); + check_stream_for_badbit(stream); + } +}; + +template<void (*const function)(std::iostream&)> +struct wrap_throw { + static void execute() + { + typedef std::ios_base ios; + test_stream stream("foo"); + + stream.exceptions(ios::failbit | ios::badbit); + BOOST_CHECK_THROW( function(stream), std::exception ); + + check_stream_for_badbit(stream); + } +}; + +template<void (*const function)(std::iostream&)> +struct wrap_throw_delayed { + static void execute() + { + typedef std::ios_base ios; + test_stream stream("foo"); + + function(stream); + BOOST_CHECK_THROW( + stream.exceptions(ios::failbit | ios::badbit), + ios::failure + ); + + check_stream_for_badbit(stream); + } +}; + +//------------------Stream operations that throw------------------------------// + +void test_read(std::iostream& str) +{ + char data[10]; + str.read(data, 10); +} + +void test_write(std::iostream& str) +{ + char data[10] = {0}; + str.write(data, 10); + //force use of streambuf + str.flush(); +} + +void test_seekg(std::iostream& str) +{ + str.seekg(10); +} + +void test_seekp(std::iostream& str) +{ + str.seekp(10); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("stream state test"); + + test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_read>::execute)); + test->add(BOOST_TEST_CASE(&wrap_throw <&test_read>::execute)); +#ifndef __CYGWIN__ + test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_read>::execute)); +#endif + + test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_write>::execute)); + test->add(BOOST_TEST_CASE(&wrap_throw <&test_write>::execute)); +#ifndef __CYGWIN__ + test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_write>::execute)); +#endif + +#ifndef BOOST_MSVC + test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_seekg>::execute)); + test->add(BOOST_TEST_CASE(&wrap_throw <&test_seekg>::execute)); +#ifndef __CYGWIN__ + test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_seekg>::execute)); +#endif + + test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_seekp>::execute)); + test->add(BOOST_TEST_CASE(&wrap_throw <&test_seekp>::execute)); +#ifndef __CYGWIN__ + test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_seekp>::execute)); +#endif +#endif // BOOST_MSVC + + return test; +} diff --git a/src/boost/libs/iostreams/test/symmetric_filter_test.cpp b/src/boost/libs/iostreams/test/symmetric_filter_test.cpp new file mode 100644 index 00000000..6f84f10c --- /dev/null +++ b/src/boost/libs/iostreams/test/symmetric_filter_test.cpp @@ -0,0 +1,182 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/detail/buffer.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filter/symmetric.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "./detail/constants.hpp" +#include "detail/operation_sequence.hpp" +#include "./detail/temp_file.hpp" +#include "./detail/verification.hpp" + +// Must come last. +#include <boost/iostreams/detail/config/disable_warnings.hpp> + +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; +namespace io = boost::iostreams; + +// Note: The filter is given an internal buffer -- unnecessary in this simple +// case -- to stress test symmetric_filter. +struct toupper_symmetric_filter_impl { + typedef char char_type; + explicit toupper_symmetric_filter_impl( + std::streamsize buffer_size = + default_filter_buffer_size + ) + : buf_(buffer_size) + { + buf_.set(0, 0); + } + bool filter( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool /* flush */ ) + { + while ( can_read(src_begin, src_end) || + can_write(dest_begin, dest_end) ) + { + if (can_read(src_begin, src_end)) + read(src_begin, src_end); + if (can_write(dest_begin, dest_end)) + write(dest_begin, dest_end); + } + bool result = buf_.ptr() != buf_.eptr(); + return result; + } + void close() { buf_.set(0, 0); } + void read(const char*& src_begin, const char* src_end) + { + std::ptrdiff_t count = + (std::min) ( src_end - src_begin, + static_cast<std::ptrdiff_t>(buf_.size()) - + (buf_.eptr() - buf_.data()) ); + while (count-- > 0) + *buf_.eptr()++ = std::toupper(*src_begin++); + } + void write(char*& dest_begin, char* dest_end) + { + std::ptrdiff_t count = + (std::min) ( dest_end - dest_begin, + buf_.eptr() - buf_.ptr() ); + while (count-- > 0) + *dest_begin++ = *buf_.ptr()++; + if (buf_.ptr() == buf_.eptr()) + buf_.set(0, 0); + } + bool can_read(const char*& src_begin, const char* src_end) + { return src_begin != src_end && buf_.eptr() != buf_.end(); } + bool can_write(char*& dest_begin, char* dest_end) + { return dest_begin != dest_end && buf_.ptr() != buf_.eptr(); } + boost::iostreams::detail::buffer<char> buf_; +}; + +typedef symmetric_filter<toupper_symmetric_filter_impl> + toupper_symmetric_filter; + +void read_symmetric_filter() +{ + test_file test; + uppercase_file upper; + BOOST_CHECK( + test_input_filter( toupper_symmetric_filter(default_filter_buffer_size), + file_source(test.name(), in_mode), + file_source(upper.name(), in_mode) ) + ); +} + +void write_symmetric_filter() +{ + test_file test; + uppercase_file upper; + BOOST_CHECK( + test_output_filter( toupper_symmetric_filter(default_filter_buffer_size), + file_source(test.name(), in_mode), + file_source(upper.name(), in_mode) ) + ); +} + +void close_symmetric_filter() +{ + // Test input + { + operation_sequence seq; + chain<input> ch; + ch.push( + io::symmetric_filter<closable_symmetric_filter> + (1, seq.new_operation(2)) + ); + ch.push(closable_device<input>(seq.new_operation(1))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Test output + { + operation_sequence seq; + chain<output> ch; + ch.push( + io::symmetric_filter<closable_symmetric_filter> + (1, seq.new_operation(1)) + ); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + +struct wcopy_filter_impl { + typedef wchar_t char_type; + bool filter( const wchar_t*& src_begin, const wchar_t* src_end, + wchar_t*& dest_begin, wchar_t* dest_end, bool /* flush */ ) + { + if(src_begin != src_end && dest_begin != dest_end) { + *dest_begin++ = *src_begin++; + } + return false; + } + void close() {} +}; + +typedef symmetric_filter<wcopy_filter_impl> wcopy_filter; + +void wide_symmetric_filter() +{ + { + warray_source src(wide_data(), wide_data() + data_length()); + std::wstring dest; + io::copy(src, io::compose(wcopy_filter(16), io::back_inserter(dest))); + BOOST_CHECK(dest == wide_data()); + } + { + warray_source src(wide_data(), wide_data() + data_length()); + std::wstring dest; + io::copy(io::compose(wcopy_filter(16), src), io::back_inserter(dest)); + BOOST_CHECK(dest == wide_data()); + } +} + +#endif + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("symmetric_filter test"); + test->add(BOOST_TEST_CASE(&read_symmetric_filter)); + test->add(BOOST_TEST_CASE(&write_symmetric_filter)); + test->add(BOOST_TEST_CASE(&close_symmetric_filter)); +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + test->add(BOOST_TEST_CASE(&wide_symmetric_filter)); +#endif + return test; +} + +#include <boost/iostreams/detail/config/enable_warnings.hpp> diff --git a/src/boost/libs/iostreams/test/tee_test.cpp b/src/boost/libs/iostreams/test/tee_test.cpp new file mode 100644 index 00000000..2ac6f332 --- /dev/null +++ b/src/boost/libs/iostreams/test/tee_test.cpp @@ -0,0 +1,426 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <fstream> +#include <boost/iostreams/compose.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/tee.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/closable.hpp" +#include "detail/operation_sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +void read_write_test() +{ + { + test_file src1, src2; + temp_file dest; + filtering_istream first, second; + first.push(tee(file_sink(dest.name(), out_mode))); + first.push(file_source(src1.name(), in_mode)); + second.push(file_source(src2.name(), in_mode)); + compare_streams_in_chars(first, second); // ignore return value + first.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), src1.name()), + "failed reading from a tee_filter in chars" + ); + } + + { + test_file src1, src2; + temp_file dest; + filtering_istream first, second; + first.push(tee(file_sink(dest.name(), out_mode))); + first.push(file_source(src1.name(), in_mode)); + second.push(file_source(src2.name(), in_mode)); + compare_streams_in_chunks(first, second); // ignore return value + first.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), src1.name()), + "failed reading from a tee_filter in chunks" + ); + } + + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + out.push(tee(file_sink(dest1.name(), out_mode))); + out.push(file_sink(dest2.name(), out_mode)); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_filter in chars" + ); + } + + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + out.push(tee(file_sink(dest1.name(), out_mode))); + out.push(file_sink(dest2.name(), out_mode)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_filter in chunks" + ); + } + + { + test_file src1, src2; + temp_file dest; + filtering_istream first, second; + first.push( tee( file_source(src1.name(), in_mode), + file_sink(dest.name(), out_mode) ) ); + second.push(file_source(src2.name(), in_mode)); + compare_streams_in_chars(first, second); // ignore return value + first.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), src1.name()), + "failed reading from a tee_device in chars" + ); + } + + { + test_file src1, src2; + temp_file dest; + filtering_istream first, second; + first.push( tee( file_source(src1.name(), in_mode), + file_sink(dest.name(), out_mode) ) ); + second.push(file_source(src2.name(), in_mode)); + compare_streams_in_chunks(first, second); // ignore return value + first.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), src1.name()), + "failed reading from a tee_device in chunks" + ); + } + + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + out.push( tee( file_sink(dest1.name(), out_mode), + file_sink(dest2.name(), out_mode) ) ); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_device in chars" + ); + } + + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + out.push( tee( file_sink(dest1.name(), out_mode), + file_sink(dest2.name(), out_mode) ) ); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_device in chunks" + ); + } +} + +void close_test() +{ + // Note: The implementation of tee_device closes the first + // sink before the second + + // Tee two sinks (Borland <= 5.8.2 needs a little help compiling this case, + // but it executes the closing algorithm correctly) + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + closable_device<output>(seq.new_operation(1)), + closable_device< + #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + borland_output + #else + output + #endif + >(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee two bidirectional devices + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(2) + ), + closable_device<bidirectional>( + seq.new_operation(3), + seq.new_operation(4) + ) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee two seekable devices + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + closable_device<seekable>(seq.new_operation(1)), + closable_device<seekable>(seq.new_operation(2)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a sink + { + operation_sequence seq; + chain<output> ch; + ch.push(boost::iostreams::tee(closable_device<output>(seq.new_operation(1)))); + ch.push(closable_device<output>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a bidirectional device + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(2) + ) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a seekable device + { + operation_sequence seq; + chain<output> ch; + ch.push(boost::iostreams::tee(closable_device<seekable>(seq.new_operation(1)))); + ch.push(closable_device<seekable>(seq.new_operation(2))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +void test_std_io() +{ + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + std::ofstream stream1(dest1.name().c_str(), out_mode); + out.push(tee(stream1)); + out.push(file_sink(dest2.name(), out_mode)); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_device in chunks" + ); + } + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + std::ofstream stream1(dest1.name().c_str(), out_mode); + out.push( tee ( stream1, + file_sink(dest2.name(), out_mode) ) ); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_device in chunks" + ); + } + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + std::ofstream stream2(dest2.name().c_str(), out_mode); + out.push( tee ( file_sink(dest1.name(), out_mode), + stream2 ) ); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_device in chunks" + ); + } + { + temp_file dest1; + temp_file dest2; + filtering_ostream out; + std::ofstream stream1(dest1.name().c_str(), out_mode); + std::ofstream stream2(dest2.name().c_str(), out_mode); + out.push(tee(stream1, stream2)); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + compare_files(dest1.name(), dest2.name()), + "failed writing to a tee_device in chunks" + ); + } +} + +void tee_composite_test() +{ + // This test is probably redundant, given the above test and the tests in + // compose_test.cpp, but it verifies that ticket #1002 is fixed + + // Tee a composite sink with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + boost::iostreams::compose( + closable_filter<output>(seq.new_operation(1)), + closable_device<output>(seq.new_operation(2)) + ), + closable_device<output>(seq.new_operation(3)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a composite bidirectional device with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + boost::iostreams::compose( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ), + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ), + closable_device<output>(seq.new_operation(5)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a composite composite seekable device with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + boost::iostreams::compose( + closable_filter<seekable>(seq.new_operation(1)), + closable_device<seekable>(seq.new_operation(2)) + ), + closable_device<output>(seq.new_operation(3)) + ) + ); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + + // Tee a composite sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + boost::iostreams::compose( + closable_filter<output>(seq.new_operation(1)), + closable_device<output>(seq.new_operation(2)) + ) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a composite bidirectional device with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + boost::iostreams::compose( + closable_filter<bidirectional>( + seq.new_operation(2), + seq.new_operation(3) + ), + closable_device<bidirectional>( + seq.new_operation(1), + seq.new_operation(4) + ) + ) + ) + ); + ch.push(closable_device<output>(seq.new_operation(5))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } + + // Tee a composite composite seekable device with a sink + { + operation_sequence seq; + chain<output> ch; + ch.push( + boost::iostreams::tee( + boost::iostreams::compose( + closable_filter<seekable>(seq.new_operation(1)), + closable_device<seekable>(seq.new_operation(2)) + ) + ) + ); + ch.push(closable_device<output>(seq.new_operation(3))); + BOOST_CHECK_NO_THROW(ch.reset()); + BOOST_CHECK_OPERATION_SEQUENCE(seq); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("tee test"); + test->add(BOOST_TEST_CASE(&read_write_test)); + test->add(BOOST_TEST_CASE(&close_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/wide_stream_test.cpp b/src/boost/libs/iostreams/test/wide_stream_test.cpp new file mode 100644 index 00000000..425485ad --- /dev/null +++ b/src/boost/libs/iostreams/test/wide_stream_test.cpp @@ -0,0 +1,145 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <boost/iostreams/detail/config/wide_streams.hpp> +#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS +# error wide streams not supported on this platform +#endif + +#include <sstream> +#include <vector> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "../example/container_device.hpp" // We use container_device instead +#include "detail/filters.hpp" // of make_iterator_range to +#include "detail/sequence.hpp" // reduce dependence on Boost.Range +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +using boost::unit_test::test_suite; + +void read_wide_input_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::example; + using namespace boost::iostreams::test; + + test_sequence<wchar_t> seq; + container_device< test_sequence<wchar_t> > source(seq); + + { + filtering_wistream first(source, 0); + basic_istringstream<wchar_t> second( + basic_string<wchar_t>(seq.begin(), seq.end()) + ); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a filter_wistream in chars with no buffer" + ); + } + + { + filtering_wistream first(source, 0); + basic_istringstream<wchar_t> second( + basic_string<wchar_t>(seq.begin(), seq.end()) + ); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a filter_wistream in chunks with no buffer" + ); + } + + { + filtering_wistream first(source); + basic_istringstream<wchar_t> second( + basic_string<wchar_t>(seq.begin(), seq.end()) + ); + BOOST_CHECK_MESSAGE( + compare_streams_in_chars(first, second), + "failed reading from a filter_wistream in chars with large buffer" + ); + } + + { + filtering_wistream first(source); + basic_istringstream<wchar_t> second( + basic_string<wchar_t>(seq.begin(), seq.end()) + ); + BOOST_CHECK_MESSAGE( + compare_streams_in_chunks(first, second), + "failed reading from a filter_wistream in chunks with large buffer" + ); + } +} + +void write_wide_output_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + { + vector<wchar_t> first; + test_sequence<wchar_t> second; + filtering_wostream out(iostreams::back_inserter(first), 0); + write_data_in_chars(out); + BOOST_CHECK_MESSAGE( + first.size() == second.size() && + std::equal(first.begin(), first.end(), second.begin()), + "failed writing to filtering_wostream in chars with no buffer" + ); + } + + { + vector<wchar_t> first; + test_sequence<wchar_t> second; + filtering_wostream out(iostreams::back_inserter(first), 0); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + first.size() == second.size() && + std::equal(first.begin(), first.end(), second.begin()), + "failed writing to filtering_wostream in chunks with no buffer" + ); + } + + { + vector<wchar_t> first; + test_sequence<wchar_t> second; + filtering_wostream out(iostreams::back_inserter(first), 0); + write_data_in_chars(out); + BOOST_CHECK_MESSAGE( + first.size() == second.size() && + std::equal(first.begin(), first.end(), second.begin()), + "failed writing to filtering_wostream in chars with large buffer" + ); + } + + { + vector<wchar_t> first; + test_sequence<wchar_t> second; + filtering_wostream out(iostreams::back_inserter(first)); + write_data_in_chunks(out); + BOOST_CHECK_MESSAGE( + first.size() == second.size() && + std::equal(first.begin(), first.end(), second.begin()), + "failed writing to filtering_wostream in chunks with large buffer" + ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("wide stream test"); + test->add(BOOST_TEST_CASE(&read_wide_input_test)); + test->add(BOOST_TEST_CASE(&write_wide_output_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/windows_pipe_test.cpp b/src/boost/libs/iostreams/test/windows_pipe_test.cpp new file mode 100644 index 00000000..f5c40f0b --- /dev/null +++ b/src/boost/libs/iostreams/test/windows_pipe_test.cpp @@ -0,0 +1,63 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// (C) Copyright 2012 Boris Schaeling +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <windows.h> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/get.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> + +using namespace boost::iostreams; +using boost::unit_test::test_suite; + +void read_from_file_descriptor_source_test() +{ + HANDLE handles[2]; + ::CreatePipe(&handles[0], &handles[1], NULL, 0); + + char buffer[2] = { 'a', 'b' }; + DWORD written; + ::WriteFile(handles[1], buffer, 2, &written, NULL); + ::CloseHandle(handles[1]); + + file_descriptor_source is(handles[0], close_handle); + + BOOST_CHECK_EQUAL('a', get(is)); + BOOST_CHECK_EQUAL('b', get(is)); + BOOST_CHECK_EQUAL(-1, get(is)); + BOOST_CHECK_EQUAL(-1, get(is)); +} + +void read_from_filtering_istream_test() +{ + HANDLE handles[2]; + ::CreatePipe(&handles[0], &handles[1], NULL, 0); + + char buffer[2] = { 'a', 'b' }; + DWORD written; + ::WriteFile(handles[1], buffer, 2, &written, NULL); + ::CloseHandle(handles[1]); + + file_descriptor_source source(handles[0], close_handle); + filtering_istream is; + is.push(source); + + BOOST_CHECK_EQUAL('a', get(is)); + BOOST_CHECK_EQUAL('b', get(is)); + BOOST_CHECK_EQUAL(-1, get(is)); + BOOST_CHECK_EQUAL(-1, get(is)); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("Windows pipe test"); + test->add(BOOST_TEST_CASE(&read_from_file_descriptor_source_test)); + test->add(BOOST_TEST_CASE(&read_from_filtering_istream_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/write_bidir_filter_test.hpp b/src/boost/libs/iostreams/test/write_bidir_filter_test.hpp new file mode 100644 index 00000000..8865ec18 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_bidir_filter_test.hpp @@ -0,0 +1,134 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_INOUT_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_INOUT_FILTER_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/combine.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/filters.hpp" +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_bidirectional_filter_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + lowercase_file lower; + BOOST_IOS::openmode mode = out_mode | BOOST_IOS::trunc; + + { + temp_file lower2; + filebuf dest; + filtering_stream<bidirectional> out; + dest.open(lower2.name().c_str(), mode); + out.push(combine(toupper_filter(), tolower_filter())); + out.push(dest); + write_data_in_chars(out); + out.reset(); + dest.close(); + BOOST_CHECK_MESSAGE( + compare_files(lower2.name(), lower.name()), + "failed writing to a filtering_stream<bidirectional> in chars with an " + "output filter" + ); + } + + { + // OutputFilter. + temp_file lower2; + filebuf dest; + filtering_stream<bidirectional> out; + out.push(combine(toupper_filter(), tolower_filter())); + dest.open(lower2.name().c_str(), mode); + out.push(dest); + write_data_in_chunks(out); + out.reset(); + dest.close(); + BOOST_CHECK_MESSAGE( + compare_files(lower2.name(), lower.name()), + "failed writing to a filtering_stream<bidirectional> in chunks with an " + "output filter" + ); + } + + { + temp_file lower2; + filebuf dest; + filtering_stream<bidirectional> out; + out.push(combine(toupper_filter(), tolower_multichar_filter()), 0); + dest.open(lower2.name().c_str(), mode); + out.push(dest); + write_data_in_chars(out); + out.reset(); + dest.close(); + BOOST_CHECK_MESSAGE( + compare_files(lower2.name(), lower.name()), + "failed writing to a filtering_stream<bidirectional> in chars " + "with a multichar output filter with no buffer" + ); + } + + { + temp_file lower2; + filebuf dest; + filtering_stream<bidirectional> out; + out.push(combine(toupper_filter(), tolower_multichar_filter()), 0); + dest.open(lower2.name().c_str(), mode); + out.push(dest); + write_data_in_chunks(out); + out.reset(); + dest.close(); + BOOST_CHECK_MESSAGE( + compare_files(lower2.name(), lower.name()), + "failed writing to a filtering_stream<bidirectional> in chunks " + "with a multichar output filter with no buffer" + ); + } + + { + temp_file lower2; + filebuf dest; + filtering_stream<bidirectional> out; + out.push(combine(toupper_filter(), tolower_multichar_filter())); + dest.open(lower2.name().c_str(), mode); + out.push(dest); + write_data_in_chars(out); + out.reset(); + dest.close(); + BOOST_CHECK_MESSAGE( + compare_files(lower2.name(), lower.name()), + "failed writing to a filtering_stream<bidirectional> in chars " + "with a multichar output filter" + ); + } + + { + temp_file lower2; + filebuf dest; + filtering_stream<bidirectional> out; + out.push(combine(toupper_filter(), tolower_multichar_filter())); + dest.open(lower2.name().c_str(), mode); + out.push(dest); + write_data_in_chunks(out); + out.reset(); + dest.close(); + BOOST_CHECK_MESSAGE( + compare_files(lower2.name(), lower.name()), + "failed writing to a filtering_stream<bidirectional> in chunks " + "with a buffered output filter" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_bidir_streambuf_test.hpp b/src/boost/libs/iostreams/test/write_bidir_streambuf_test.hpp new file mode 100644 index 00000000..7dadaca0 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_bidir_streambuf_test.hpp @@ -0,0 +1,87 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_bidirectional_streambuf_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + temp_file test2; + { + filebuf dest; + dest.open(test2.name().c_str(), out_mode); + filtering_stream<bidirectional> out(dest, 0); + write_data_in_chars(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<bidirectional> based " + "on a streambuf in chars with no buffer" + ); + } + + { + temp_file test2; + { + filebuf dest; + dest.open(test2.name().c_str(), out_mode); + filtering_stream<bidirectional> out(dest, 0); + write_data_in_chunks(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<bidirectional> based " + "on a streambuf in chunks with no buffer" + ); + } + + { + temp_file test2; + { + filebuf dest; + dest.open(test2.name().c_str(), out_mode); + filtering_stream<bidirectional> out(dest); + write_data_in_chars(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<bidirectional> based " + "on a streambuf in chars with large buffer" + ); + } + + { + temp_file test2; + { + filebuf dest; + dest.open(test2.name().c_str(), out_mode); + filtering_stream<bidirectional> out(dest); + write_data_in_chunks(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<bidirectional> based " + "on a streambuf in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_bidir_test.hpp b/src/boost/libs/iostreams/test/write_bidir_test.hpp new file mode 100644 index 00000000..12cc3ef5 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_bidir_test.hpp @@ -0,0 +1,89 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/combine.hpp> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_bidirectional_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + temp_file dest; + temp_file src; // Dummy; + filtering_stream<bidirectional> out( + combine(file_source(src.name()), file_sink(dest.name(), out_mode)), 0 + ); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), test.name()), + "failed writing to filtering_stream<bidirectional> in chars " + "with no buffer" + ); + } + + { + temp_file dest; + temp_file src; // Dummy; + filtering_stream<bidirectional> out( + combine(file_source(src.name()), file_sink(dest.name(), out_mode)), 0 + ); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), test.name()), + "failed writing to filtering_stream<bidirectional> in chunks " + "with no buffer" + ); + } + + { + temp_file dest; + temp_file src; // Dummy; + filtering_stream<bidirectional> out( + combine(file_source(src.name()), file_sink(dest.name(), out_mode)) + ); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), test.name()), + "failed writing to filtering_stream<bidirectional> in chars " + "with large buffer" + ); + } + + { + temp_file dest; + temp_file src; // Dummy; + filtering_stream<bidirectional> out( + combine(file_source(src.name()), file_sink(dest.name(), out_mode)) + ); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), test.name()), + "failed writing to filtering_stream<bidirectional> in chunks " + "with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_failure_test.cpp b/src/boost/libs/iostreams/test/write_failure_test.cpp new file mode 100644 index 00000000..f4552e88 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_failure_test.cpp @@ -0,0 +1,65 @@ +// (C) COPYRIGHT 2017 ARM Limited + +// 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.) + +#include <boost/iostreams/categories.hpp> // tags. +#include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp> +#include <boost/iostreams/filter/gzip.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/iostreams/write.hpp> +#include <boost/test/unit_test.hpp> + +using namespace boost; +using namespace boost::iostreams; +using boost::unit_test::test_suite; + +struct limit_device { + typedef char char_type; + typedef sink_tag category; + int written, overflow_count, limit; + explicit limit_device(int limit = 20) : written(0), overflow_count(0), limit(limit) {} + std::streamsize write(const char_type *, std::streamsize n) + { + if (written > limit) { + // first return partial writes, then an error + ++overflow_count; + if (overflow_count > 2 || n < 2) + { + return -1; + } + n /= 2; + } + written += n; + return n; + } +}; + +static void disk_full_test() +{ + // non_blocking_adapter used to handle write returning + // -1 correctly, usually hanging (see ticket 2557). + // As non_blocking_adapter is used for ofstream, this + // would happen for ordinary files when reaching quota, + // disk full or rlimits. + // Could be tested without gzip_compressor, + // but this tests a bit better that the whole path can handle it. + // TODO: should there be some check on error bit being set + // or should an exception be triggered? + limit_device outdev; + non_blocking_adapter<limit_device> nonblock_outdev(outdev); + filtering_ostream out; + out.push(gzip_compressor()); + out.push(nonblock_outdev); + write(out, "teststring0123456789", 20); + out.flush(); + write(out, "secondwrite123456789", 20); + close(out); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("disk full test"); + test->add(BOOST_TEST_CASE(&disk_full_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/write_output_filter_test.hpp b/src/boost/libs/iostreams/test/write_output_filter_test.hpp new file mode 100644 index 00000000..34a36731 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_output_filter_test.hpp @@ -0,0 +1,114 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_FILTER_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/filters.hpp" +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_output_filter_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + lowercase_file lower; + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_filter()); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chars with an " + "output filter" + ); + } + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_filter()); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chunks with an " + "output filter" + ); + } + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_multichar_filter(), 0); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chars with a " + "multichar output filter with no buffer" + ); + } + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_multichar_filter(), 0); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chunks with a " + "multichar output filter with no buffer" + ); + } + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_multichar_filter()); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chars with a " + "multichar output filter" + ); + } + + { + temp_file dest; + filtering_ostream out; + out.push(tolower_multichar_filter()); + out.push(file_sink(dest.name(), out_mode)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(dest.name(), lower.name()), + "failed writing to a filtering_ostream in chunks with a " + "multichar output filter" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_FILTER_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_output_iterator_test.hpp b/src/boost/libs/iostreams/test/write_output_iterator_test.hpp new file mode 100644 index 00000000..6cedc161 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_output_iterator_test.hpp @@ -0,0 +1,85 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_ITERATOR_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_ITERATOR_HPP_INCLUDED + +#include <fstream> +#include <iterator> // Back inserter. +#include <vector> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +// Note: adding raw inserter iterators to chains is not supported +// on VC6. + +void write_output_iterator_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + vector<char> first; + filtering_ostream out; + out.push(std::back_inserter(first), 0); + write_data_in_chars(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on an " + "output iterator in chars with no buffer" + ); + } + + { + vector<char> first; + filtering_ostream out; + out.push(std::back_inserter(first), 0); + write_data_in_chunks(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on an " + "output iterator in chunks with no buffer" + ); + } + + { + vector<char> first; + filtering_ostream out; + out.push(std::back_inserter(first)); + write_data_in_chars(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on an " + "output iterator in chars with large buffer" + ); + } + + { + vector<char> first; + filtering_ostream out; + out.push(std::back_inserter(first)); + write_data_in_chunks(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on an " + "output iterator in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_ITERATOR_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_output_ostream_test.hpp b/src/boost/libs/iostreams/test/write_output_ostream_test.hpp new file mode 100644 index 00000000..c6dd713f --- /dev/null +++ b/src/boost/libs/iostreams/test/write_output_ostream_test.hpp @@ -0,0 +1,84 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_OSTREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_OSTREAM_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_output_ostream_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + temp_file test2; + { + ofstream dest(test2.name().c_str(), out_mode); + filtering_ostream out(dest, 0); + write_data_in_chars(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream based on an ostream " + "in chars with no buffer" + ); + } + + { + temp_file test2; + { + ofstream dest(test2.name().c_str(), out_mode); + filtering_ostream out(dest, 0); + write_data_in_chunks(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream based on an ostream " + "in chunks with no buffer" + ); + } + + { + test_file test2; + { + ofstream dest(test2.name().c_str(), out_mode); + filtering_ostream out(dest); + write_data_in_chars(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream based on an ostream " + "in chars with large buffer" + ); + } + + { + temp_file test2; + { + ofstream dest(test2.name().c_str(), out_mode); + filtering_ostream out(dest); + write_data_in_chunks(out); + } + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream based on an ostream " + "in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_OSTREAM_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_output_seq_test.hpp b/src/boost/libs/iostreams/test/write_output_seq_test.hpp new file mode 100644 index 00000000..2ff5fb44 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_output_seq_test.hpp @@ -0,0 +1,78 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_SEQUENCE_HPP_INCLUDED + +#include <fstream> +#include <vector> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_output_sequence_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_ostream out(make_iterator_range(first), 0); + write_data_in_chars(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on a sequence " + "in chars with no buffer" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_ostream out(make_iterator_range(first), 0); + write_data_in_chunks(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on a sequence " + "in chunks with no buffer" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_ostream out(make_iterator_range(first)); + write_data_in_chars(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on a sequence " + "in chars with large buffer" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_ostream out(make_iterator_range(first)); + write_data_in_chunks(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_ostream based on a sequence " + "in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_SEQUENCE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_output_test.hpp b/src/boost/libs/iostreams/test/write_output_test.hpp new file mode 100644 index 00000000..d8e56abf --- /dev/null +++ b/src/boost/libs/iostreams/test/write_output_test.hpp @@ -0,0 +1,73 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_output_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + temp_file test2; + filtering_ostream out(file_sink(test2.name(), out_mode), 0); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream in chars with no buffer" + ); + } + + { + temp_file test2; + filtering_ostream out(file_sink(test2.name(), out_mode), 0); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream in chunks with no buffer" + ); + } + + { + temp_file test2; + filtering_ostream out(file_sink(test2.name(), out_mode)); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream in chars with buffer" + ); + } + + { + temp_file test2; + filtering_ostream out(file_sink(test2.name(), out_mode)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_ostream in chunks with buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_seekable_seq_test.hpp b/src/boost/libs/iostreams/test/write_seekable_seq_test.hpp new file mode 100644 index 00000000..5fce08fb --- /dev/null +++ b/src/boost/libs/iostreams/test/write_seekable_seq_test.hpp @@ -0,0 +1,79 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_SEQUENCE_HPP_INCLUDED + +#include <fstream> +#include <vector> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/sequence.hpp" +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_seekable_sequence_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_stream<seekable> out(make_iterator_range(first), 0); + write_data_in_chars(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_stream<seekable> based on a " + "sequence in chars with no buffer" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_stream<seekable> out(make_iterator_range(first), 0); + write_data_in_chunks(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_stream<seekable> based on a " + "sequence in chunks with no buffer" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_stream<seekable> out(make_iterator_range(first)); + write_data_in_chars(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_stream<seekable> based on a " + "sequence in chars with large buffer" + ); + } + + { + vector<char> first(data_reps * data_length(), '?'); + filtering_stream<seekable> out(make_iterator_range(first)); + write_data_in_chunks(out); + ifstream second(test.name().c_str()); + BOOST_CHECK_MESSAGE( + compare_container_and_stream(first, second), + "failed writing to filtering_stream<seekable> based on a " + "sequence in chunks with large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_SEQUENCE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/write_seekable_test.hpp b/src/boost/libs/iostreams/test/write_seekable_test.hpp new file mode 100644 index 00000000..cf83d0e8 --- /dev/null +++ b/src/boost/libs/iostreams/test/write_seekable_test.hpp @@ -0,0 +1,77 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_HPP_INCLUDED + +#include <fstream> +#include <boost/iostreams/device/file.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include "detail/temp_file.hpp" +#include "detail/verification.hpp" + +void write_seekable_test() +{ + using namespace std; + using namespace boost; + using namespace boost::iostreams; + using namespace boost::iostreams::test; + + test_file test; + BOOST_IOS::openmode mode = out_mode | BOOST_IOS::trunc; + + { + temp_file test2; + filtering_stream<seekable> out(file(test2.name(), mode), 0); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<seekable> in chars with" + "no buffer" + ); + } + + { + temp_file test2; + filtering_stream<seekable> out(file(test2.name(), mode), 0); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<seekable> in chunks with" + "no buffer" + ); + } + + { + temp_file test2; + filtering_stream<seekable> out(file(test2.name(), mode)); + write_data_in_chars(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<seekable> in chars with" + "large buffer" + ); + } + + { + temp_file test2; + filtering_stream<seekable> out(file(test2.name(), mode)); + write_data_in_chunks(out); + out.reset(); + BOOST_CHECK_MESSAGE( + compare_files(test2.name(), test.name()), + "failed writing to filtering_stream<seekable> in chunks with" + "large buffer" + ); + } +} + +#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_HPP_INCLUDED diff --git a/src/boost/libs/iostreams/test/zlib_test.cpp b/src/boost/libs/iostreams/test/zlib_test.cpp new file mode 100644 index 00000000..17ab3409 --- /dev/null +++ b/src/boost/libs/iostreams/test/zlib_test.cpp @@ -0,0 +1,60 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include <string> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/filter/zlib.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" +#include "detail/verification.hpp" + +using namespace std; +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +using boost::unit_test::test_suite; + +struct zlib_alloc : std::allocator<char> { }; + +void zlib_test() +{ + text_sequence data; + BOOST_CHECK( + test_filter_pair( zlib_compressor(), + zlib_decompressor(), + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK( + test_filter_pair( basic_zlib_compressor<zlib_alloc>(), + basic_zlib_decompressor<zlib_alloc>(), + std::string(data.begin(), data.end()) ) + ); + BOOST_CHECK( + test_filter_pair( zlib_compressor(), + zlib_decompressor(), + std::string() ) + ); + { + filtering_istream strm; + strm.push( zlib_compressor() ); + strm.push( null_source() ); + } + { + filtering_istream strm; + strm.push( zlib_decompressor() ); + strm.push( null_source() ); + } +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("zlib test"); + test->add(BOOST_TEST_CASE(&zlib_test)); + return test; +} diff --git a/src/boost/libs/iostreams/test/zstd_test.cpp b/src/boost/libs/iostreams/test/zstd_test.cpp new file mode 100644 index 00000000..4d3584b5 --- /dev/null +++ b/src/boost/libs/iostreams/test/zstd_test.cpp @@ -0,0 +1,178 @@ +// (C) COPYRIGHT 2018 Reimar Döffinger +// Based on zstd_test.cpp by: +// (C) COPYRIGHT 2017 ARM Limited +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Note: basically a copy-paste of the gzip test + +#include <cstddef> +#include <string> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/device/back_inserter.hpp> +#include <boost/iostreams/filter/zstd.hpp> +#include <boost/iostreams/filter/test.hpp> +#include <boost/iostreams/filtering_stream.hpp> +#include <boost/ref.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/test/unit_test.hpp> +#include "detail/sequence.hpp" +#include "detail/verification.hpp" + +using namespace boost; +using namespace boost::iostreams; +using namespace boost::iostreams::test; +namespace io = boost::iostreams; +using boost::unit_test::test_suite; + +struct zstd_alloc : std::allocator<char> { + zstd_alloc() { } + zstd_alloc(const zstd_alloc& other) { } + template<typename T> + zstd_alloc(const std::allocator<T>& other) { } +}; + +void compression_test() +{ + text_sequence data; + + // Test compression and decompression with custom allocator + BOOST_CHECK( + test_filter_pair( basic_zstd_compressor<zstd_alloc>(), + basic_zstd_decompressor<zstd_alloc>(), + std::string(data.begin(), data.end()) ) + ); +} + +void multiple_member_test() +{ + text_sequence data; + std::vector<char> temp, dest; + + // Write compressed data to temp, twice in succession + filtering_ostream out; + out.push(zstd_compressor()); + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + out.push(io::back_inserter(temp)); + io::copy(make_iterator_range(data), out); + BOOST_CHECK(std::equal(temp.begin(), temp.begin() + temp.size()/2, temp.begin() + temp.size()/2)); + + // Read compressed data from temp into dest + filtering_istream in; + in.push(zstd_decompressor()); + in.push(array_source(&temp[0], temp.size())); + io::copy(in, io::back_inserter(dest)); + + // Check that dest consists of two copies of data + BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); + + dest.clear(); + io::copy( + array_source(&temp[0], temp.size()), + io::compose(zstd_decompressor(), io::back_inserter(dest))); + + // Check that dest consists of two copies of data + BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size()); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin())); + BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2)); +} + +void array_source_test() +{ + std::string data = "simple test string."; + std::string encoded; + + filtering_ostream out; + out.push(zstd_compressor()); + out.push(io::back_inserter(encoded)); + io::copy(make_iterator_range(data), out); + + std::string res; + io::array_source src(encoded.data(),encoded.length()); + io::copy(io::compose(io::zstd_decompressor(), src), io::back_inserter(res)); + + BOOST_CHECK_EQUAL(data, res); +} + +void empty_file_test() +{ + // This test is in response to https://svn.boost.org/trac/boost/ticket/5237 + // The previous implementation of gzip_compressor only wrote the gzip file + // header when the first bytes of uncompressed input were processed, causing + // incorrect behavior for empty files + BOOST_CHECK( + test_filter_pair( zstd_compressor(), + zstd_decompressor(), + std::string() ) + ); +} + +void multipart_test() +{ + // This test verifies that the zstd_decompressor properly handles a file + // that consists of multiple concatenated files (matches unzstd behaviour) + static const char multipart_file[] = { + '\x28', '\xb5', '\x2f', '\xfd', '\x24', '\x15', '\x95', '\x00', '\x00', '\x50', '\x4c', '\x69', + '\x6e', '\x65', '\x20', '\x31', '\x0a', '\x32', '\x33', '\x0a', '\x02', '\x00', '\x60', '\x84', + '\xae', '\x62', '\x04', '\x19', '\xf8', '\xe1', '\x2d', '\x28', '\xb5', '\x2f', '\xfd', '\x24', + '\x15', '\x95', '\x00', '\x00', '\x50', '\x4c', '\x69', '\x6e', '\x65', '\x20', '\x34', '\x0a', + '\x35', '\x36', '\x0a', '\x02', '\x00', '\x60', '\x84', '\xae', '\x62', '\x04', '\x5f', '\xcf', + '\xd5', '\xb8', '\x28', '\xb5', '\x2f', '\xfd', '\x24', '\x00', '\x01', '\x00', '\x00', '\x99', + '\xe9', '\xd8', '\x51', '\x28', '\xb5', '\x2f', '\xfd', '\x24', '\x15', '\x95', '\x00', '\x00', + '\x50', '\x4c', '\x69', '\x6e', '\x65', '\x20', '\x37', '\x0a', '\x38', '\x39', '\x0a', '\x02', + '\x00', '\x60', '\x84', '\xae', '\x62', '\x04', '\x94', '\x13', '\xdb', '\xae' + }; + + filtering_istream in; + std::string line; + + in.push(zstd_decompressor()); + in.push(io::array_source(multipart_file, sizeof(multipart_file))); + + // First part + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 1", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 2", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 3", line); + + // Second part immediately follows + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 4", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 5", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 6", line); + + // Then an empty part, followed by one last 3-line part. + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 7", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 8", line); + std::getline(in, line); + BOOST_CHECK_EQUAL("Line 9", line); + + // Check for zstd errors too. + BOOST_CHECK(!in.bad()); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test = BOOST_TEST_SUITE("zstd test"); + test->add(BOOST_TEST_CASE(&compression_test)); + test->add(BOOST_TEST_CASE(&multiple_member_test)); + test->add(BOOST_TEST_CASE(&array_source_test)); + test->add(BOOST_TEST_CASE(&empty_file_test)); + test->add(BOOST_TEST_CASE(&multipart_test)); + return test; +} |