Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:48

0001 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
0002 // (C) Copyright 2003-2007 Jonathan Turkanis
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
0005 
0006 // See http://www.boost.org/libs/iostreams for documentation.
0007 
0008 #ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED
0009 #define BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED
0010 
0011 #if defined(_MSC_VER)
0012 # pragma once
0013 #endif
0014 
0015 #include <algorithm>                             // min.
0016 #include <boost/assert.hpp>
0017 #include <cstddef>                               // ptrdiff_t.
0018 #include <iosfwd>                                // streamsize, streamoff.
0019 #include <iterator>                              // iterator_traits.
0020 #include <boost/iostreams/categories.hpp>
0021 #include <boost/iostreams/detail/error.hpp>
0022 #include <boost/iostreams/positioning.hpp>
0023 #include <boost/mpl/if.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <boost/type_traits/is_convertible.hpp>
0026 #include <boost/core/enable_if.hpp>
0027 
0028 // Must come last.
0029 #include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
0030 
0031 namespace boost { namespace iostreams { namespace detail {
0032 
0033 // Used for simulated tag dispatch.
0034 template<typename Traversal> struct range_adapter_impl;
0035 
0036 //
0037 // Template name: range_adapter
0038 // Description: Device based on an instance of boost::iterator_range.
0039 // Template parameters:
0040 //     Mode - A mode tag.
0041 //     Range - An instance of iterator_range.
0042 //
0043 template<typename Mode, typename Range>
0044 class range_adapter {
0045 private:
0046     typedef typename Range::iterator                  iterator;
0047     typedef std::iterator_traits<iterator>            iter_traits;
0048     typedef typename iter_traits::iterator_category   iter_cat;
0049 public:
0050     typedef typename Range::value_type                char_type;
0051     struct category : Mode, device_tag { };
0052     typedef typename
0053             mpl::if_<
0054                 is_convertible<
0055                     iter_cat,
0056                     std::random_access_iterator_tag
0057                 >,
0058                 std::random_access_iterator_tag,
0059                 std::forward_iterator_tag
0060             >::type                                   tag;
0061     typedef range_adapter_impl<tag>                   impl;
0062 
0063     explicit range_adapter(const Range& rng);
0064     range_adapter(iterator first, iterator last);
0065     std::streamsize read(char_type* s, std::streamsize n);
0066     std::streamsize write(const char_type* s, std::streamsize n);
0067     std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
0068 private:
0069     iterator first_, cur_, last_;
0070 };
0071 
0072 //------------------Implementation of range_adapter---------------------------//
0073 
0074 template<typename Mode, typename Range>
0075 range_adapter<Mode, Range>::range_adapter(const Range& rng)
0076     : first_(rng.begin()), cur_(rng.begin()), last_(rng.end()) { }
0077 
0078 template<typename Mode, typename Range>
0079 range_adapter<Mode, Range>::range_adapter(iterator first, iterator last)
0080     : first_(first), cur_(first), last_(last) { }
0081 
0082 template<typename Mode, typename Range>
0083 inline std::streamsize range_adapter<Mode, Range>::read
0084     (char_type* s, std::streamsize n)
0085 { return impl::read(cur_, last_, s, n); }
0086 
0087 template<typename Mode, typename Range>
0088 inline std::streamsize range_adapter<Mode, Range>::write
0089     (const char_type* s, std::streamsize n)
0090 { return impl::write(cur_, last_, s, n); }
0091 
0092 
0093 template<typename Mode, typename Range>
0094 std::streampos range_adapter<Mode, Range>::seek
0095     (stream_offset off, BOOST_IOS::seekdir way)
0096 { 
0097     impl::seek(first_, cur_, last_, off, way); 
0098     return offset_to_position(cur_ - first_);
0099 }
0100 
0101 //------------------Implementation of range_adapter_impl----------------------//
0102 
0103 template<>
0104 struct range_adapter_impl<std::forward_iterator_tag> {
0105     template<typename Iter, typename Ch>
0106     static std::streamsize read
0107         (Iter& cur, Iter& last, Ch* s,std::streamsize n)
0108     {
0109         std::streamsize rem = n; // No. of chars remaining.
0110         while (cur != last && rem-- > 0) *s++ = *cur++;
0111         return n - rem != 0 ? n - rem : -1;
0112     }
0113 
0114     template<typename Iter, typename Ch>
0115     static std::streamsize write
0116         (Iter& cur, Iter& last, const Ch* s, std::streamsize n)
0117     {
0118         while (cur != last && n-- > 0) *cur++ = *s++;
0119         if (cur == last && n > 0)
0120             boost::throw_exception(write_area_exhausted());
0121         return n;
0122     }
0123 };
0124 
0125 template<>
0126 struct range_adapter_impl<std::random_access_iterator_tag> {
0127     template<typename Iter, typename Ch>
0128     static std::streamsize read
0129         (Iter& cur, Iter& last, Ch* s,std::streamsize n)
0130     {
0131         std::streamsize result = 
0132             (std::min)(static_cast<std::streamsize>(last - cur), n);
0133         if (result)
0134             std::copy(cur, cur + result, s);
0135         cur += result;
0136         return result != 0 ? result : -1;
0137     }
0138 
0139     template<typename Iter, typename Ch>
0140     static std::streamsize write
0141         (Iter& cur, Iter& last, const Ch* s, std::streamsize n)
0142     {
0143         std::streamsize count =
0144             (std::min)(static_cast<std::streamsize>(last - cur), n);
0145         std::copy(s, s + count, cur);
0146         cur += count;
0147         if (count < n) 
0148             boost::throw_exception(write_area_exhausted());
0149         return n;
0150     }
0151 
0152     template<typename Iter>
0153     static void seek
0154         ( Iter& first, Iter& cur, Iter& last, stream_offset off,
0155           BOOST_IOS::seekdir way )
0156     {
0157         using namespace std;
0158         switch (way) {
0159         case BOOST_IOS::beg:
0160             if (off > last - first || off < 0)
0161                 boost::throw_exception(bad_seek());
0162             cur = first + off;
0163             break;
0164         case BOOST_IOS::cur:
0165             {
0166                 std::ptrdiff_t newoff = cur - first + off;
0167                 if (newoff > last - first || newoff < 0)
0168                     boost::throw_exception(bad_seek());
0169                 cur += off;
0170                 break;
0171             }
0172         case BOOST_IOS::end:
0173             if (last - first + off < 0 || off > 0)
0174                 boost::throw_exception(bad_seek());
0175             cur = last + off;
0176             break;
0177         default:
0178             BOOST_ASSERT(0);
0179         }
0180     }
0181 };
0182 
0183 } } } // End namespaces detail, iostreams, boost.
0184 
0185 #include <boost/iostreams/detail/config/enable_warnings.hpp>  // MSVC.
0186 
0187 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED //---------------//