1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 #ifndef BOOST_IOSTREAMS_SEEK_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_SEEK_HPP_INCLUDED
10 
11 #if defined(_MSC_VER)
12 # pragma once
13 #endif
14 
15 #include <boost/config.hpp>  // DEDUCED_TYPENAME, MSVC.
16 #include <boost/integer_traits.hpp>
17 #include <boost/iostreams/categories.hpp>
18 #include <boost/iostreams/detail/dispatch.hpp>
19 #include <boost/iostreams/detail/ios.hpp>       // streamsize, seekdir, openmode.
20 #include <boost/iostreams/detail/streambuf.hpp>
21 #include <boost/iostreams/detail/wrap_unwrap.hpp>
22 #include <boost/iostreams/operations_fwd.hpp>
23 #include <boost/iostreams/positioning.hpp>
24 #include <boost/mpl/if.hpp>
25 
26 // Must come last.
27 #include <boost/iostreams/detail/config/disable_warnings.hpp>
28 
29 namespace boost { namespace iostreams {
30 
31 namespace detail {
32 
33 template<typename T>
34 struct seek_device_impl;
35 
36 template<typename T>
37 struct seek_filter_impl;
38 
39 } // End namespace detail.
40 
41 template<typename T>
42 inline std::streampos
seek(T & t,stream_offset off,BOOST_IOS::seekdir way,BOOST_IOS::openmode which=BOOST_IOS::in|BOOST_IOS::out)43 seek( T& t, stream_offset off, BOOST_IOS::seekdir way,
44       BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out )
45 {
46     using namespace detail;
47     return seek_device_impl<T>::seek(detail::unwrap(t), off, way, which);
48 }
49 
50 template<typename T, typename Device>
51 inline std::streampos
seek(T & t,Device & dev,stream_offset off,BOOST_IOS::seekdir way,BOOST_IOS::openmode which=BOOST_IOS::in|BOOST_IOS::out)52 seek( T& t, Device& dev, stream_offset off, BOOST_IOS::seekdir way,
53       BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out )
54 {
55     using namespace detail;
56     return seek_filter_impl<T>::seek(detail::unwrap(t), dev, off, way, which);
57 }
58 
59 namespace detail {
60 
61 //------------------Definition of seek_device_impl----------------------------//
62 
63 template<typename T>
64 struct seek_device_impl
65     : mpl::if_<
66           is_custom<T>,
67           operations<T>,
68           seek_device_impl<
69               BOOST_DEDUCED_TYPENAME
70               dispatch<
71                   T, iostream_tag, istream_tag, ostream_tag,
72                   streambuf_tag, two_head, any_tag
73               >::type
74           >
75       >::type
76     { };
77 
78 struct seek_impl_basic_ios {
79     template<typename T>
seekboost::iostreams::detail::seek_impl_basic_ios80     static std::streampos seek( T& t, stream_offset off,
81                                 BOOST_IOS::seekdir way,
82                                 BOOST_IOS::openmode which )
83     {
84         if ( way == BOOST_IOS::beg &&
85              ( off < integer_traits<std::streamoff>::const_min ||
86                off > integer_traits<std::streamoff>::const_max ) )
87         {
88             return t.rdbuf()->pubseekpos(offset_to_position(off));
89         } else {
90             return t.rdbuf()->pubseekoff(off, way, which);
91         }
92     }
93 };
94 
95 template<>
96 struct seek_device_impl<iostream_tag> : seek_impl_basic_ios { };
97 
98 template<>
99 struct seek_device_impl<istream_tag> : seek_impl_basic_ios { };
100 
101 template<>
102 struct seek_device_impl<ostream_tag> : seek_impl_basic_ios { };
103 
104 template<>
105 struct seek_device_impl<streambuf_tag> {
106     template<typename T>
seekboost::iostreams::detail::seek_device_impl107     static std::streampos seek( T& t, stream_offset off,
108                                 BOOST_IOS::seekdir way,
109                                 BOOST_IOS::openmode which )
110     {
111         if ( way == BOOST_IOS::beg &&
112              ( off < integer_traits<std::streamoff>::const_min ||
113                off > integer_traits<std::streamoff>::const_max ) )
114         {
115             return t.BOOST_IOSTREAMS_PUBSEEKPOS(offset_to_position(off));
116         } else {
117             return t.BOOST_IOSTREAMS_PUBSEEKOFF(off, way, which);
118         }
119     }
120 };
121 
122 template<>
123 struct seek_device_impl<two_head> {
124     template<typename T>
seekboost::iostreams::detail::seek_device_impl125     static std::streampos seek( T& t, stream_offset off,
126                                 BOOST_IOS::seekdir way,
127                                 BOOST_IOS::openmode which )
128     { return t.seek(off, way, which); }
129 };
130 
131 template<>
132 struct seek_device_impl<any_tag> {
133     template<typename T>
seekboost::iostreams::detail::seek_device_impl134     static std::streampos seek( T& t, stream_offset off,
135                                 BOOST_IOS::seekdir way,
136                                 BOOST_IOS::openmode )
137     { return t.seek(off, way); }
138 };
139 
140 //------------------Definition of seek_filter_impl----------------------------//
141 
142 template<typename T>
143 struct seek_filter_impl
144     : mpl::if_<
145           is_custom<T>,
146           operations<T>,
147           seek_filter_impl<
148               BOOST_DEDUCED_TYPENAME
149               dispatch<T, two_head, any_tag>::type
150           >
151       >::type
152     { };
153 
154 template<>
155 struct seek_filter_impl<two_head> {
156     template<typename T, typename Device>
seekboost::iostreams::detail::seek_filter_impl157     static std::streampos seek( T& t, Device& d,
158                                 stream_offset off,
159                                 BOOST_IOS::seekdir way,
160                                 BOOST_IOS::openmode which )
161     { return t.seek(d, off, way, which); }
162 };
163 
164 template<>
165 struct seek_filter_impl<any_tag> {
166     template<typename T, typename Device>
seekboost::iostreams::detail::seek_filter_impl167     static std::streampos seek( T& t, Device& d,
168                                 stream_offset off,
169                                 BOOST_IOS::seekdir way,
170                                 BOOST_IOS::openmode )
171     { return t.seek(d, off, way); }
172 };
173 
174 } // End namespace detail.
175 
176 } } // End namespaces iostreams, boost.
177 
178 #include <boost/iostreams/detail/config/enable_warnings.hpp>
179 
180 #endif // #ifndef BOOST_IOSTREAMS_SEEK_HPP_INCLUDED
181