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