1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,768 @@ |
1 |
+// ========================================================================== |
|
2 |
+// SeqAn - The Library for Sequence Analysis |
|
3 |
+// ========================================================================== |
|
4 |
+// Copyright (c) 2006-2018, Knut Reinert, FU Berlin |
|
5 |
+// All rights reserved. |
|
6 |
+// |
|
7 |
+// Redistribution and use in source and binary forms, with or without |
|
8 |
+// modification, are permitted provided that the following conditions are met: |
|
9 |
+// |
|
10 |
+// * Redistributions of source code must retain the above copyright |
|
11 |
+// notice, this list of conditions and the following disclaimer. |
|
12 |
+// * Redistributions in binary form must reproduce the above copyright |
|
13 |
+// notice, this list of conditions and the following disclaimer in the |
|
14 |
+// documentation and/or other materials provided with the distribution. |
|
15 |
+// * Neither the name of Knut Reinert or the FU Berlin nor the names of |
|
16 |
+// its contributors may be used to endorse or promote products derived |
|
17 |
+// from this software without specific prior written permission. |
|
18 |
+// |
|
19 |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
20 |
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
21 |
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
22 |
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE |
|
23 |
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
24 |
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
25 |
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
26 |
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
27 |
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
28 |
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|
29 |
+// DAMAGE. |
|
30 |
+// |
|
31 |
+// ========================================================================== |
|
32 |
+// Author: David Weese <david.weese@fu-berlin.de> |
|
33 |
+// Author: Enrico Siragusa <enrico.siragusa@fu-berlin.de> |
|
34 |
+// ========================================================================== |
|
35 |
+// Our own implementation of a streambuf_iterator. We could not use the STL's |
|
36 |
+// iterator as we need to have access to the underlying streambuf which is a |
|
37 |
+// private member of the STL iterator. |
|
38 |
+// ========================================================================== |
|
39 |
+// TODO(esiragusa): tests |
|
40 |
+ |
|
41 |
+#ifndef SEQAN_INCLUDE_SEQAN_STREAM_ITER_STREAM_H_ |
|
42 |
+#define SEQAN_INCLUDE_SEQAN_STREAM_ITER_STREAM_H_ |
|
43 |
+ |
|
44 |
+namespace seqan { |
|
45 |
+ |
|
46 |
+// ============================================================================ |
|
47 |
+// Tags |
|
48 |
+// ============================================================================ |
|
49 |
+ |
|
50 |
+template <typename TDirection> |
|
51 |
+struct StreamIterator {}; |
|
52 |
+ |
|
53 |
+// ============================================================================ |
|
54 |
+// Classes |
|
55 |
+// ============================================================================ |
|
56 |
+ |
|
57 |
+// ---------------------------------------------------------------------------- |
|
58 |
+// Class StreamBuffer |
|
59 |
+// ---------------------------------------------------------------------------- |
|
60 |
+ |
|
61 |
+/*! |
|
62 |
+ * @class StreamBuffer |
|
63 |
+ * @headerfile <seqan/stream.h> |
|
64 |
+ * @brief Reinterprets the std::basic_streambuf to grant access to protected member functions. |
|
65 |
+ * |
|
66 |
+ * @signature template <typename TValue[, typenam TTraits]> |
|
67 |
+ * class StreamBuffer : public std::basic_streambuf<TValue, TTraits>; |
|
68 |
+ * |
|
69 |
+ * @tparam TValue The value type of the stream buffer. |
|
70 |
+ * @tparam TTraits The traits to use, defaults to <tt>std::char_traits<TValue></tt>. |
|
71 |
+ */ |
|
72 |
+// TODO(holtgrew): Add documentation for member functions. |
|
73 |
+ |
|
74 |
+ // Unfortunately some of the most useful members of basic_streambuf are |
|
75 |
+ // protected, so we define a subclass to cast and access them |
|
76 |
+template <typename TValue, typename TTraits_ = std::char_traits<TValue>> |
|
77 |
+struct StreamBuffer : public std::basic_streambuf<TValue, TTraits_> |
|
78 |
+{ |
|
79 |
+ using TTraits = TTraits_; |
|
80 |
+ using TBasicStream = std::basic_streambuf<TValue, TTraits_>; |
|
81 |
+ |
|
82 |
+ using TBasicStream::eback; |
|
83 |
+ using TBasicStream::gptr; |
|
84 |
+ using TBasicStream::egptr; |
|
85 |
+ using TBasicStream::gbump; |
|
86 |
+ using TBasicStream::underflow; |
|
87 |
+ |
|
88 |
+ using TBasicStream::pbase; |
|
89 |
+ using TBasicStream::pptr; |
|
90 |
+ using TBasicStream::epptr; |
|
91 |
+ using TBasicStream::pbump; |
|
92 |
+ using TBasicStream::overflow; |
|
93 |
+}; |
|
94 |
+ |
|
95 |
+// NOTE(rrahn): This is a wrapper for the StreamBuffer class. |
|
96 |
+// Since we usually work with std::basic_iostreams and their derivatives, we cannot simply cast a pointer to |
|
97 |
+// std::basic_filebuf to StreamBuffer to expose it's protected member functions. |
|
98 |
+// To do so, we only use the StreamBuffer to inherit from basic_streambuf (the base class of all buffer implementations.) |
|
99 |
+// and only expose the protected member functions as public functions. We then store the original basic_streambuf |
|
100 |
+// in this wrapper class and whenever access to the protected members is required we use a reinterpret_cast to convert |
|
101 |
+// basic_streambuf* into the public StreamBuffer*. The reinterpret_cast has zero overhead. |
|
102 |
+// This fixes an undetected error reported w/ the sanitizer option of gcc (https://github.com/seqan/seqan/issues/2104). |
|
103 |
+template <typename TValue, typename TTraits_ = std::char_traits<TValue>> |
|
104 |
+class StreamBufferWrapper |
|
105 |
+{ |
|
106 |
+public: |
|
107 |
+ |
|
108 |
+ typedef std::basic_streambuf<TValue, TTraits_> TBasicStreamBuffer; |
|
109 |
+ typedef StreamBuffer<TValue, TTraits_> TPubStreamBuffer_; |
|
110 |
+ typedef typename TPubStreamBuffer_::TTraits TTraits; |
|
111 |
+ |
|
112 |
+ TBasicStreamBuffer * streamBuf{nullptr}; |
|
113 |
+ |
|
114 |
+ StreamBufferWrapper() = default; |
|
115 |
+ |
|
116 |
+ explicit StreamBufferWrapper(TBasicStreamBuffer * _basicStreamBuf) : streamBuf(_basicStreamBuf) |
|
117 |
+ {} |
|
118 |
+ |
|
119 |
+ size_t chunkSize(Input) |
|
120 |
+ { |
|
121 |
+ return baseBuf()->egptr() - baseBuf()->gptr(); |
|
122 |
+ } |
|
123 |
+ |
|
124 |
+ size_t chunkSize(Output) |
|
125 |
+ { |
|
126 |
+ return baseBuf()->epptr() - baseBuf()->pptr(); |
|
127 |
+ } |
|
128 |
+ |
|
129 |
+ template <typename TOffset> |
|
130 |
+ void advanceChunk(TOffset ofs, Input) |
|
131 |
+ { |
|
132 |
+ baseBuf()->gbump(ofs); |
|
133 |
+ } |
|
134 |
+ |
|
135 |
+ template <typename TOffset> |
|
136 |
+ void advanceChunk(TOffset ofs, Output) |
|
137 |
+ { |
|
138 |
+ baseBuf()->pbump(ofs); |
|
139 |
+ } |
|
140 |
+ |
|
141 |
+ void reserveChunk(Input) |
|
142 |
+ { |
|
143 |
+ if (baseBuf()->gptr() == baseBuf()->egptr()) |
|
144 |
+ baseBuf()->underflow(); |
|
145 |
+ } |
|
146 |
+ |
|
147 |
+ void reserveChunk(Output) |
|
148 |
+ { |
|
149 |
+ if (baseBuf()->pptr() == baseBuf()->epptr()) |
|
150 |
+ baseBuf()->overflow(EOF); |
|
151 |
+ } |
|
152 |
+ |
|
153 |
+ template <typename TOffset> |
|
154 |
+ typename std::streampos |
|
155 |
+ seekoff(TOffset ofs, std::ios_base::seekdir way, std::ios_base::openmode which) |
|
156 |
+ { |
|
157 |
+ return streamBuf->pubseekoff(ofs, way, which); |
|
158 |
+ } |
|
159 |
+ |
|
160 |
+ template <typename TOffset, typename TDirection> |
|
161 |
+ void goFurther(TOffset ofs, TDirection dir) |
|
162 |
+ { |
|
163 |
+ size_t left = chunkSize(dir); |
|
164 |
+ if (SEQAN_LIKELY((size_t)ofs <= left)) |
|
165 |
+ { |
|
166 |
+ advanceChunk(ofs, dir); |
|
167 |
+ return; |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ while (true) |
|
171 |
+ { |
|
172 |
+ size_t adv = std::min((size_t)ofs, left); |
|
173 |
+ advanceChunk(adv, dir); |
|
174 |
+ ofs -= adv; |
|
175 |
+ if (ofs == 0) |
|
176 |
+ return; |
|
177 |
+ |
|
178 |
+ SEQAN_IF_CONSTEXPR (IsSameType<TDirection, Input>::VALUE) |
|
179 |
+ baseBuf()->underflow(); |
|
180 |
+ else |
|
181 |
+ baseBuf()->overflow(); |
|
182 |
+ left = chunkSize(dir); |
|
183 |
+ |
|
184 |
+ if (SEQAN_UNLIKELY(left == 0)) |
|
185 |
+ { |
|
186 |
+ // if chunking isn't available try to seek |
|
187 |
+ typename TTraits::pos_type res = seekoff(ofs, |
|
188 |
+ std::ios_base::cur, |
|
189 |
+ (IsSameType<TDirection, Input>::VALUE)? std::ios_base::in: std::ios_base::out); |
|
190 |
+ |
|
191 |
+ // if seek doesn't work manually skip characters (when reading) |
|
192 |
+ if (res == typename TTraits::pos_type(typename TTraits::off_type(-1))) |
|
193 |
+ { |
|
194 |
+ SEQAN_IF_CONSTEXPR (IsSameType<TDirection, Input>::VALUE) |
|
195 |
+ { |
|
196 |
+ for (; ofs != 0; --ofs) |
|
197 |
+ baseBuf()->sbumpc(); |
|
198 |
+ } |
|
199 |
+ SEQAN_IF_CONSTEXPR (IsSameType<TDirection, Output>::VALUE) |
|
200 |
+ { |
|
201 |
+ for (; ofs != 0; --ofs) |
|
202 |
+ baseBuf()->sputc('\0'); |
|
203 |
+ } |
|
204 |
+ } |
|
205 |
+ return; |
|
206 |
+ } |
|
207 |
+ } |
|
208 |
+ } |
|
209 |
+ |
|
210 |
+ TPubStreamBuffer_* baseBuf() const |
|
211 |
+ { |
|
212 |
+ return reinterpret_cast<TPubStreamBuffer_ *>(streamBuf); |
|
213 |
+ } |
|
214 |
+}; |
|
215 |
+ |
|
216 |
+// ---------------------------------------------------------------------------- |
|
217 |
+// Class StreamIterator |
|
218 |
+// ---------------------------------------------------------------------------- |
|
219 |
+ |
|
220 |
+/*! |
|
221 |
+ * @class StreamIterator |
|
222 |
+ * @extends Iter |
|
223 |
+ * @brief Abstract base class for input and output stream iterators. |
|
224 |
+ * |
|
225 |
+ * @signature template <typename TStream, typename TDirection> |
|
226 |
+ * class Iter<TStream, StreamIterator<TDirection> >; |
|
227 |
+ * |
|
228 |
+ * @tparam TStream The @link StreamConcept @endlink to iterate over. |
|
229 |
+ * @tparam TDirection The iterator direction, one of the @link DirectionTags @endlink. |
|
230 |
+ */ |
|
231 |
+ |
|
232 |
+// ---------------------------------------------------------------------------- |
|
233 |
+// Class Input StreamIterator |
|
234 |
+// ---------------------------------------------------------------------------- |
|
235 |
+ |
|
236 |
+/*! |
|
237 |
+ * @class InputStreamIterator Input StreamIterator |
|
238 |
+ * @extends StreamIterator |
|
239 |
+ * @brief @link Iter @endlink specialiazion for reading from @link StreamConcept streams @endlink. |
|
240 |
+ * |
|
241 |
+ * @signature template <typename TStream> |
|
242 |
+ * class Iter<TStream, StreamIterator<Input> >; |
|
243 |
+ * |
|
244 |
+ * @tparam TStream The @link StreamConcept @endlink to iterate over. |
|
245 |
+ */ |
|
246 |
+ |
|
247 |
+template <typename TStream> |
|
248 |
+class Iter<TStream, StreamIterator<Input> > |
|
249 |
+{ |
|
250 |
+public: |
|
251 |
+ typedef typename Value<TStream>::Type TValue; |
|
252 |
+ typedef std::basic_istream<TValue> TIStream; |
|
253 |
+ typedef std::basic_streambuf<TValue> TBasicBuffer; |
|
254 |
+ typedef StreamBufferWrapper<TValue> TStreamBufferWrapper; |
|
255 |
+ typedef typename TStreamBufferWrapper::TPubStreamBuffer_ TStreamBuffer; |
|
256 |
+ |
|
257 |
+ TStreamBufferWrapper streamBufWrapper{nullptr}; |
|
258 |
+ |
|
259 |
+ /*! |
|
260 |
+ * @fn InputStreamIterator::Iter |
|
261 |
+ * @brief The constructors. |
|
262 |
+ * |
|
263 |
+ * @signature Iter::Iter(); |
|
264 |
+ * @signature Iter::Iter(stream); |
|
265 |
+ * @signature Iter::Iter(streamBuffer); |
|
266 |
+ * |
|
267 |
+ * @param[in] stream The <tt>TStream</tt> to read from. |
|
268 |
+ * @param[in] streamBuf A @link StreamBuffer @endlink to read from. |
|
269 |
+ * |
|
270 |
+ * Allows default construction, construction from stream, as well as from a @link StreamBuffer @endlink. |
|
271 |
+ */ |
|
272 |
+ Iter() = default; |
|
273 |
+ |
|
274 |
+ Iter(TIStream & stream) : streamBufWrapper(stream.rdbuf()) |
|
275 |
+ { |
|
276 |
+ // printf("streamBuf: %p\n", streamBuf); |
|
277 |
+ stream.exceptions(std::ios_base::badbit); |
|
278 |
+ } |
|
279 |
+ |
|
280 |
+ Iter(TBasicBuffer * buf) : streamBufWrapper(buf) |
|
281 |
+ {} |
|
282 |
+}; |
|
283 |
+ |
|
284 |
+// ---------------------------------------------------------------------------- |
|
285 |
+// Class StreamIterator |
|
286 |
+// ---------------------------------------------------------------------------- |
|
287 |
+ |
|
288 |
+/*! |
|
289 |
+ * @class OutputStreamIterator Output StreamIterator |
|
290 |
+ * @extends StreamIterator |
|
291 |
+ * @brief @link Iter @endlink specialiazion for writing to @link StreamConcept streams @endlink. |
|
292 |
+ * |
|
293 |
+ * @signature template <typename TStream> |
|
294 |
+ * class Iter<TStream, StreamIterator<Output> >; |
|
295 |
+ * |
|
296 |
+ * @tparam TStream The @link StreamConcept @endlink to iterate over. |
|
297 |
+ */ |
|
298 |
+template <typename TStream> |
|
299 |
+class Iter<TStream, StreamIterator<Output> > |
|
300 |
+{ |
|
301 |
+public: |
|
302 |
+ typedef typename Value<TStream>::Type TValue; |
|
303 |
+ typedef std::basic_ostream<TValue> TOStream; |
|
304 |
+ typedef std::basic_streambuf<TValue> TBasicBuffer; |
|
305 |
+ typedef StreamBufferWrapper<TValue> TStreamBufferWrapper; |
|
306 |
+ typedef typename TStreamBufferWrapper::TPubStreamBuffer_ TStreamBuffer; |
|
307 |
+ |
|
308 |
+ TStreamBufferWrapper streamBufWrapper{nullptr}; |
|
309 |
+ |
|
310 |
+ /*! |
|
311 |
+ * @fn Iter::Iter |
|
312 |
+ * @brief Constructor. |
|
313 |
+ * |
|
314 |
+ * @signature Iter::Iter() |
|
315 |
+ * @signature Iter::Iter(stream) |
|
316 |
+ * @signature Iter::Iter(streamBuf) |
|
317 |
+ * |
|
318 |
+ * @param[in] stream The <tt>TStream</tt> to write to. |
|
319 |
+ * @param[in] streamBuf A @link StreamBuffer @endlink to write to. |
|
320 |
+ * |
|
321 |
+ * Allows default construction, construction from stream, as well as from a @link StreamBuffer @endlink. |
|
322 |
+ */ |
|
323 |
+ Iter() = default; |
|
324 |
+ |
|
325 |
+ Iter(TOStream & stream) : streamBufWrapper(stream.rdbuf()) |
|
326 |
+ { |
|
327 |
+ stream.exceptions(std::ios_base::badbit); |
|
328 |
+ } |
|
329 |
+ |
|
330 |
+ Iter(TBasicBuffer * buf) : streamBufWrapper(buf) |
|
331 |
+ {} |
|
332 |
+ |
|
333 |
+ template <typename TValue2> |
|
334 |
+ TValue2 & operator=(TValue2 &val) |
|
335 |
+ { |
|
336 |
+ setValue(*this, val); |
|
337 |
+ return val; |
|
338 |
+ } |
|
339 |
+ |
|
340 |
+ template <typename TValue2> |
|
341 |
+ TValue2 const & operator=(TValue2 const &val) |
|
342 |
+ { |
|
343 |
+ setValue(*this, val); |
|
344 |
+ return val; |
|
345 |
+ } |
|
346 |
+}; |
|
347 |
+ |
|
348 |
+ |
|
349 |
+// ============================================================================ |
|
350 |
+// Metafunctions |
|
351 |
+// ============================================================================ |
|
352 |
+ |
|
353 |
+// ---------------------------------------------------------------------------- |
|
354 |
+// Metafunction Chunk |
|
355 |
+// ---------------------------------------------------------------------------- |
|
356 |
+ |
|
357 |
+/*! |
|
358 |
+ * @mfn StreamBuffer#Chunk |
|
359 |
+ * @brief Return chunk type for StreamBuffer |
|
360 |
+ * |
|
361 |
+ * @signature Chunk<TStreamBuffer>::Type; |
|
362 |
+ * |
|
363 |
+ * @tparam TStreamBuffer The StreamBuffer to query for its chunk type. |
|
364 |
+ * @return Type The chunk type of the stream buffer. |
|
365 |
+ */ |
|
366 |
+ |
|
367 |
+template <typename TValue, typename TTraits> |
|
368 |
+struct Chunk<StreamBuffer<TValue, TTraits> > |
|
369 |
+{ |
|
370 |
+ typedef Range<TValue*> Type; |
|
371 |
+}; |
|
372 |
+ |
|
373 |
+template <typename TStream, typename TDirection> |
|
374 |
+struct Chunk<Iter<TStream, StreamIterator<Tag<TDirection> > > >: |
|
375 |
+ Chunk<typename Iter<TStream, StreamIterator<Tag<TDirection> > >::TStreamBuffer> {}; |
|
376 |
+ |
|
377 |
+// ---------------------------------------------------------------------------- |
|
378 |
+// Metafunction Reference |
|
379 |
+// ---------------------------------------------------------------------------- |
|
380 |
+ |
|
381 |
+/*! |
|
382 |
+ * @mfn StreamBuffer#Reference |
|
383 |
+ * @brief Return reference for StreamBuffer. |
|
384 |
+ * |
|
385 |
+ * @signature Reference<TStreamBuffer>::Type; |
|
386 |
+ * |
|
387 |
+ * @tparam TStreamBuffer The StreamBuffer to query for its reference type. |
|
388 |
+ * @return Type The reference type of the stream buffer. |
|
389 |
+ */ |
|
390 |
+ |
|
391 |
+template <typename TStream> |
|
392 |
+struct Reference<Iter<TStream, StreamIterator<Input> > >: |
|
393 |
+ Value<Iter<TStream, StreamIterator<Input> > > {}; |
|
394 |
+ |
|
395 |
+template <typename TStream> |
|
396 |
+struct Reference<Iter<TStream, StreamIterator<Input> > const>: |
|
397 |
+ Value<Iter<TStream, StreamIterator<Input> > > {}; |
|
398 |
+ |
|
399 |
+template <typename TStream> |
|
400 |
+struct Reference<Iter<TStream, StreamIterator<Output> > > |
|
401 |
+{ |
|
402 |
+ typedef Iter<TStream, StreamIterator<Output> > Type; |
|
403 |
+}; |
|
404 |
+ |
|
405 |
+// ---------------------------------------------------------------------------- |
|
406 |
+// Metafunction GetValue |
|
407 |
+// ---------------------------------------------------------------------------- |
|
408 |
+ |
|
409 |
+/*! |
|
410 |
+ * @mfn StreamBuffer#GetValue |
|
411 |
+ * @brief Return get value for StreamBuffer. |
|
412 |
+ * |
|
413 |
+ * @signature GetValue<TStreamBuffer>::Type; |
|
414 |
+ * |
|
415 |
+ * @tparam TStreamBuffer The StreamBuffer to query for its get value type. |
|
416 |
+ * @return Type The get value type of the stream buffer. |
|
417 |
+ */ |
|
418 |
+ |
|
419 |
+template <typename TStream> |
|
420 |
+struct GetValue<Iter<TStream, StreamIterator<Input> > >: |
|
421 |
+ Reference<Iter<TStream, StreamIterator<Input> > const> {}; |
|
422 |
+ |
|
423 |
+// ---------------------------------------------------------------------------- |
|
424 |
+// Metafunction Position |
|
425 |
+// ---------------------------------------------------------------------------- |
|
426 |
+ |
|
427 |
+/*! |
|
428 |
+ * @mfn StreamBuffer#Position |
|
429 |
+ * @brief Return position for StreamBuffer. |
|
430 |
+ * |
|
431 |
+ * @signature Position<TStreamBuffer>::Type; |
|
432 |
+ * |
|
433 |
+ * @tparam TStreamBuffer The StreamBuffer to query for its position type. |
|
434 |
+ * @return Type The position type of the stream buffer. |
|
435 |
+ */ |
|
436 |
+ |
|
437 |
+template <typename TStream, typename TDirection> |
|
438 |
+struct Position<Iter<TStream, StreamIterator<TDirection> > > : Position<TStream> {}; |
|
439 |
+ |
|
440 |
+// ---------------------------------------------------------------------------- |
|
441 |
+// Metafunction Difference |
|
442 |
+// ---------------------------------------------------------------------------- |
|
443 |
+ |
|
444 |
+/*! |
|
445 |
+ * @mfn StreamBuffer#Difference |
|
446 |
+ * @brief Return difference for StreamBuffer. |
|
447 |
+ * |
|
448 |
+ * @signature Difference<TStreamBuffer>::Type; |
|
449 |
+ * |
|
450 |
+ * @tparam TStreamBuffer The StreamBuffer to query for its difference type. |
|
451 |
+ * @return Type The difference type of the stream buffer. |
|
452 |
+ */ |
|
453 |
+ |
|
454 |
+template <typename TStream, typename TDirection> |
|
455 |
+struct Difference<Iter<TStream, StreamIterator<TDirection> > > : Difference<TStream> {}; |
|
456 |
+ |
|
457 |
+// ---------------------------------------------------------------------------- |
|
458 |
+// Metafunction Size |
|
459 |
+// ---------------------------------------------------------------------------- |
|
460 |
+ |
|
461 |
+/*! |
|
462 |
+ * @mfn StreamBuffer#Size |
|
463 |
+ * @brief Return size for StreamBuffer. |
|
464 |
+ * |
|
465 |
+ * @signature Size<TStreamBuffer>::Type; |
|
466 |
+ * |
|
467 |
+ * @tparam TStreamBuffer The StreamBuffer to query for its size type. |
|
468 |
+ * @return Type The size type of the stream buffer. |
|
469 |
+ */ |
|
470 |
+ |
|
471 |
+template <typename TStream, typename TDirection> |
|
472 |
+struct Size<Iter<TStream, StreamIterator<TDirection> > > : Size<TStream> {}; |
|
473 |
+ |
|
474 |
+// ============================================================================ |
|
475 |
+// Functions |
|
476 |
+// ============================================================================ |
|
477 |
+ |
|
478 |
+// ---------------------------------------------------------------------------- |
|
479 |
+// Function directionIterator() |
|
480 |
+// ---------------------------------------------------------------------------- |
|
481 |
+ |
|
482 |
+/*! |
|
483 |
+ * @fn StreamConcept#directionIterator |
|
484 |
+ * @brief Returns direction iterator for Stream. |
|
485 |
+ * |
|
486 |
+ * @signature TDirIter directionIterator(stream, dirTag); |
|
487 |
+ * |
|
488 |
+ * @param[in] stream The @link StreamConcept @endlink object to compute iterator for. |
|
489 |
+ * @param[in] dirTag Direction tag, one of the @link DirectionTags @endlink. |
|
490 |
+ */ |
|
491 |
+ |
|
492 |
+template <typename TStream, typename TDirection> |
|
493 |
+inline SEQAN_FUNC_ENABLE_IF(Is<StreamConcept<TStream> >, Iter<TStream, StreamIterator<TDirection> >) |
|
494 |
+directionIterator(TStream &stream, TDirection const &) |
|
495 |
+{ |
|
496 |
+ return Iter<TStream, StreamIterator<TDirection> >(stream); |
|
497 |
+} |
|
498 |
+ |
|
499 |
+/*! |
|
500 |
+ * @fn ContainerConcept#directionIterator |
|
501 |
+ * @brief Returns direction iterator for a container. |
|
502 |
+ * |
|
503 |
+ * @signature TDirIter directionIterator(streamBuf, dirTag); |
|
504 |
+ * |
|
505 |
+ * @param[in] streamBuf The @link ContainerConcept container @endlink object to compute iterator for. |
|
506 |
+ * @param[in] dirTag Direction tag, one of the @link DirectionTags @endlink. |
|
507 |
+ * |
|
508 |
+ * @return TDirIter The resulting @link ContainerConcept#DirectionIterator @endlink. |
|
509 |
+ */ |
|
510 |
+ |
|
511 |
+template <typename TContainer, typename TDirection> |
|
512 |
+inline SEQAN_FUNC_DISABLE_IF(Is<StreamConcept<TContainer> >, typename Iterator<TContainer, Rooted>::Type) |
|
513 |
+directionIterator(TContainer &cont, TDirection const &) |
|
514 |
+{ |
|
515 |
+ return begin(cont, Rooted()); |
|
516 |
+} |
|
517 |
+ |
|
518 |
+// ---------------------------------------------------------------------------- |
|
519 |
+// Function reserveChunk() |
|
520 |
+// ---------------------------------------------------------------------------- |
|
521 |
+ |
|
522 |
+/*! |
|
523 |
+ * @fn StreamIterator#reserveChunk |
|
524 |
+ * @brief Reserve a chunk in the host of the StreamIterator |
|
525 |
+ * |
|
526 |
+ * @signature void reserveChunk(iter, len, dirTag); |
|
527 |
+ * |
|
528 |
+ * @param[in] iter The @link StreamIterator @endlink object to reserve chunks for. |
|
529 |
+ * @param[in] len The length of the chunk to reserve. |
|
530 |
+ * @param[in] dirTag Direction tag, one of @link DirectionTags#Input Input @endlink and @link |
|
531 |
+ * DirectionTags#Input Output @endlink . |
|
532 |
+ */ |
|
533 |
+ |
|
534 |
+template <typename TStream, typename TDirection, typename TSize> |
|
535 |
+inline void reserveChunk(Iter<TStream, StreamIterator<TDirection> > &iter, TSize, Input dir) |
|
536 |
+{ |
|
537 |
+ iter.streamBufWrapper.reserveChunk(dir); |
|
538 |
+} |
|
539 |
+ |
|
540 |
+template <typename TStream, typename TDirection, typename TSize> |
|
541 |
+inline void reserveChunk(Iter<TStream, StreamIterator<TDirection> > &iter, TSize, Output dir) |
|
542 |
+{ |
|
543 |
+ iter.streamBufWrapper.reserveChunk(dir); |
|
544 |
+} |
|
545 |
+ |
|
546 |
+// ---------------------------------------------------------------------------- |
|
547 |
+// Function advanceChunk() |
|
548 |
+// ---------------------------------------------------------------------------- |
|
549 |
+ |
|
550 |
+// TODO(holtgrew): Documentation missing below here. |
|
551 |
+ |
|
552 |
+template <typename TStream, typename TDirection, typename TSize> |
|
553 |
+inline void advanceChunk(Iter<TStream, StreamIterator<TDirection> > &iter, TSize size) |
|
554 |
+{ |
|
555 |
+ iter.streamBufWrapper.advanceChunk(size, TDirection()); |
|
556 |
+} |
|
557 |
+ |
|
558 |
+// ---------------------------------------------------------------------------- |
|
559 |
+// Function getChunk() |
|
560 |
+// ---------------------------------------------------------------------------- |
|
561 |
+ |
|
562 |
+// StreamBuffer |
|
563 |
+template <typename TChunk, typename TValue, typename TTraits> |
|
564 |
+inline void |
|
565 |
+getChunk(TChunk &result, StreamBuffer<TValue, TTraits> &buf, Input) |
|
566 |
+{ |
|
567 |
+ return assignRange(result, buf.gptr(), buf.egptr()); |
|
568 |
+} |
|
569 |
+ |
|
570 |
+template <typename TChunk, typename TValue, typename TTraits> |
|
571 |
+inline void |
|
572 |
+getChunk(TChunk &result, StreamBuffer<TValue, TTraits> &buf, Output) |
|
573 |
+{ |
|
574 |
+ return assignRange(result, buf.pptr(), buf.epptr()); |
|
575 |
+} |
|
576 |
+ |
|
577 |
+// StreamIterator |
|
578 |
+template <typename TChunk, typename TStream, typename TDirection> |
|
579 |
+inline void |
|
580 |
+getChunk(TChunk &result, Iter<TStream, StreamIterator<Tag<TDirection> > > &iter, Tag<TDirection>) |
|
581 |
+{ |
|
582 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
583 |
+ getChunk(result, *iter.streamBufWrapper.baseBuf(), Tag<TDirection>()); |
|
584 |
+} |
|
585 |
+ |
|
586 |
+// ---------------------------------------------------------------------------- |
|
587 |
+// Function value() - Input |
|
588 |
+// ---------------------------------------------------------------------------- |
|
589 |
+ |
|
590 |
+template <typename TStream> |
|
591 |
+inline typename Reference<Iter<TStream, StreamIterator<Input> > >::Type |
|
592 |
+value(Iter<TStream, StreamIterator<Input> > &iter) |
|
593 |
+{ |
|
594 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
595 |
+ return iter.streamBufWrapper.baseBuf()->sgetc(); |
|
596 |
+} |
|
597 |
+template <typename TStream> |
|
598 |
+inline typename Reference<Iter<TStream, StreamIterator<Input> > const>::Type |
|
599 |
+value(Iter<TStream, StreamIterator<Input> > const &iter) |
|
600 |
+{ |
|
601 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
602 |
+ return iter.streamBufWrapper.baseBuf()->sgetc(); |
|
603 |
+} |
|
604 |
+ |
|
605 |
+// ---------------------------------------------------------------------------- |
|
606 |
+// Function value() - Ouput |
|
607 |
+// ---------------------------------------------------------------------------- |
|
608 |
+ |
|
609 |
+template <typename TStream> |
|
610 |
+inline Iter<TStream, StreamIterator<Output> > & |
|
611 |
+value(Iter<TStream, StreamIterator<Output> > & iter) |
|
612 |
+{ |
|
613 |
+ return iter; |
|
614 |
+} |
|
615 |
+template <typename TStream> |
|
616 |
+inline Iter<TStream, StreamIterator<Output> > const & |
|
617 |
+value(Iter<TStream, StreamIterator<Output> > const & iter) |
|
618 |
+{ |
|
619 |
+ return iter; |
|
620 |
+} |
|
621 |
+ |
|
622 |
+// ---------------------------------------------------------------------------- |
|
623 |
+// Function setValue() |
|
624 |
+// ---------------------------------------------------------------------------- |
|
625 |
+ |
|
626 |
+template <typename TStream, typename TValue> |
|
627 |
+inline void |
|
628 |
+setValue(Iter<TStream, StreamIterator<Output> > & iter, TValue const &val) |
|
629 |
+{ |
|
630 |
+ return setValue(const_cast<Iter<TStream, StreamIterator<Output> > const &>(iter), val); |
|
631 |
+} |
|
632 |
+ |
|
633 |
+template <typename TStream, typename TValue> |
|
634 |
+inline void |
|
635 |
+setValue(Iter<TStream, StreamIterator<Output> > const & iter, TValue const &val) |
|
636 |
+{ |
|
637 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
638 |
+ iter.streamBufWrapper.baseBuf()->sputc((typename Value<Iter<TStream, StreamIterator<Output> > >::Type)val); |
|
639 |
+} |
|
640 |
+ |
|
641 |
+// ---------------------------------------------------------------------------- |
|
642 |
+// Function writeValue() |
|
643 |
+// ---------------------------------------------------------------------------- |
|
644 |
+ |
|
645 |
+// streams |
|
646 |
+template <typename TContainer, typename TValue> |
|
647 |
+inline void writeValue(Iter<TContainer, StreamIterator<Output> > &iter, TValue val) |
|
648 |
+{ |
|
649 |
+ setValue(iter, val); |
|
650 |
+ //goNext(iter); // implicitly done by setValue above |
|
651 |
+} |
|
652 |
+ |
|
653 |
+// ---------------------------------------------------------------------------- |
|
654 |
+// Function goNext() |
|
655 |
+// ---------------------------------------------------------------------------- |
|
656 |
+ |
|
657 |
+template <typename TStream> |
|
658 |
+inline void |
|
659 |
+goNext(Iter<TStream, StreamIterator<Input> > & iter) |
|
660 |
+{ |
|
661 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
662 |
+ iter.streamBufWrapper.baseBuf()->sbumpc(); |
|
663 |
+} |
|
664 |
+ |
|
665 |
+template <typename TStream> |
|
666 |
+inline void |
|
667 |
+goNext(Iter<TStream, StreamIterator<Output> > &) |
|
668 |
+{ |
|
669 |
+ // We do nothing here, as the stream is advanced by sputc whenever you assign |
|
670 |
+ // a value to the iterator with *iter= or setValue |
|
671 |
+} |
|
672 |
+ |
|
673 |
+// we intentionally don't return an iterator here, as the copied iterator wouldn't |
|
674 |
+// point to the position before the increment. |
|
675 |
+template <typename TContainer, typename TSpec> |
|
676 |
+inline void |
|
677 |
+operator++(Iter<TContainer, StreamIterator<Input> > & iter, int) |
|
678 |
+{ |
|
679 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
680 |
+ iter.streamBufWrapper.baseBuf()->sbumpc(); |
|
681 |
+} |
|
682 |
+ |
|
683 |
+// ---------------------------------------------------------------------------- |
|
684 |
+// Function goFurther() |
|
685 |
+// ---------------------------------------------------------------------------- |
|
686 |
+ |
|
687 |
+template <typename TStream, typename TOffset, typename TDirection> |
|
688 |
+inline void |
|
689 |
+goFurther(Iter<TStream, StreamIterator<TDirection> > &iter, TOffset ofs) |
|
690 |
+{ |
|
691 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
692 |
+ iter.streamBufWrapper.goFurther(ofs, TDirection()); |
|
693 |
+} |
|
694 |
+ |
|
695 |
+// ---------------------------------------------------------------------------- |
|
696 |
+// Function position() |
|
697 |
+// ---------------------------------------------------------------------------- |
|
698 |
+ |
|
699 |
+template <typename TStream, typename TDirection> |
|
700 |
+inline typename Position<Iter<TStream, StreamIterator<TDirection> > const>::Type |
|
701 |
+position(Iter<TStream, StreamIterator<TDirection> > const & iter) |
|
702 |
+{ |
|
703 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
704 |
+ return iter.streamBufWrapper.baseBuf()->pubseekoff(0, std::ios_base::cur, |
|
705 |
+ (IsSameType<TDirection, Input>::VALUE)? std::ios_base::in: std::ios_base::out); |
|
706 |
+} |
|
707 |
+ |
|
708 |
+// ---------------------------------------------------------------------------- |
|
709 |
+// Function setPosition() |
|
710 |
+// ---------------------------------------------------------------------------- |
|
711 |
+ |
|
712 |
+template <typename TStream, typename TDirection, typename TPosition> |
|
713 |
+inline void |
|
714 |
+setPosition(Iter<TStream, StreamIterator<TDirection> > const & iter, TPosition pos) |
|
715 |
+{ |
|
716 |
+ SEQAN_ASSERT(iter.streamBufWrapper.baseBuf() != nullptr); |
|
717 |
+ iter.streamBufWrapper.baseBuf()->pubseekpos(pos, (IsSameType<TDirection, Input>::VALUE)? std::ios_base::in: std::ios_base::out); |
|
718 |
+} |
|
719 |
+ |
|
720 |
+// ---------------------------------------------------------------------------- |
|
721 |
+// Function atEnd() |
|
722 |
+// ---------------------------------------------------------------------------- |
|
723 |
+ |
|
724 |
+template <typename TStream> |
|
725 |
+inline bool |
|
726 |
+atEnd(Iter<TStream, StreamIterator<Input> > const & iter) |
|
727 |
+{ |
|
728 |
+ typedef typename Value<Iter<TStream, StreamIterator<Input> > >::Type TValue; |
|
729 |
+ typedef StreamBuffer<TValue> TStreamBuffer; |
|
730 |
+ |
|
731 |
+ if (SEQAN_UNLIKELY(iter.streamBufWrapper.baseBuf() == nullptr)) |
|
732 |
+ { |
|
733 |
+ return true; |
|
734 |
+ } |
|
735 |
+ else |
|
736 |
+ { |
|
737 |
+ TStreamBuffer * const buf = iter.streamBufWrapper.baseBuf(); |
|
738 |
+ if (SEQAN_LIKELY(buf->gptr() < buf->egptr())) |
|
739 |
+ return false; |
|
740 |
+ else |
|
741 |
+ return TStreamBuffer::TTraits::eq_int_type(buf->sgetc(), TStreamBuffer::TTraits::eof()); |
|
742 |
+ } |
|
743 |
+} |
|
744 |
+ |
|
745 |
+template <typename TStream> |
|
746 |
+inline bool |
|
747 |
+atEnd(Iter<TStream, StreamIterator<Output> > const & iter) |
|
748 |
+{ |
|
749 |
+ typedef typename Value<Iter<TStream, StreamIterator<Input> > >::Type TValue; |
|
750 |
+ typedef StreamBuffer<TValue> TStreamBuffer; |
|
751 |
+ |
|
752 |
+ if (SEQAN_UNLIKELY(iter.streamBufWrapper.baseBuf() == nullptr)) |
|
753 |
+ { |
|
754 |
+ return true; |
|
755 |
+ } |
|
756 |
+ else |
|
757 |
+ { |
|
758 |
+ TStreamBuffer * const buf = iter.streamBufWrapper.baseBuf(); |
|
759 |
+ if (SEQAN_LIKELY(buf->pptr() < buf->epptr())) |
|
760 |
+ return false; |
|
761 |
+ else |
|
762 |
+ return TStreamBuffer::TTraits::eq_int_type(buf->overflow(), TStreamBuffer::TTraits::eof()); |
|
763 |
+ } |
|
764 |
+} |
|
765 |
+ |
|
766 |
+} // namespace seqan |
|
767 |
+ |
|
768 |
+#endif // #ifndef SEQAN_INCLUDE_SEQAN_STREAM_ITER_STREAM_H_ |