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: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>
34 // ==========================================================================
35 
36 // TODO(holtgrew): Split into modified_string_mod_view.h and modified_iterator_mod_view.h.
37 // TODO(holtgrew): Move out convert()
38 
39 #ifndef SEQAN_MODIFIER_MODIFIER_VIEW_H_
40 #define SEQAN_MODIFIER_MODIFIER_VIEW_H_
41 
42 namespace seqan
43 {
44 
45 // ==========================================================================
46 // Forwards
47 // ==========================================================================
48 
49 // ==========================================================================
50 // Classes
51 // ==========================================================================
52 
53 // --------------------------------------------------------------------------
54 // Class ModView
55 // --------------------------------------------------------------------------
56 
57 /*!
58  * @class ModViewModifiedIterator
59  * @extends ModifiedIterator
60  * @headerfile <seqan/modifier.h>
61  *
62  * @brief Transforms the character of a host using a custom functor.
63  *
64  * @signature template <typename THost, typename TFunctor>
65  *            class ModifiedIterator<THost, ModView<TFunctor> >;
66  *
67  * @tparam THost    The host iterator.
68  * @tparam TFunctor A unary functor type.
69  */
70 
71 /*!
72  * @class ModViewModifiedString
73  * @extends ModifiedString
74  * @headerfile <seqan/modifier.h>
75  *
76  * @brief Transforms the character of a host using a custom functor.
77  *
78  * @signature template <typename THost, typename TFunctor>
79  *            class ModifiedString<THost, ModView<TFunctor> >;
80  *
81  * @tparam THost    The host iterator.
82  * @tparam TFunctor A unary functor type.
83  */
84 
85 template <typename TFunctor>
86 struct ModView {};
87 
88 template <typename TFunctor>
89 struct ModViewCargo
90 {
91     TFunctor    func;
92 
ModViewCargoModViewCargo93     ModViewCargo() : func()
94     {}
95 };
96 
97 template <typename THost, typename TFunctor>
98 class ModifiedIterator<THost, ModView<TFunctor> >
99 {
100 public:
101     typedef typename Cargo<ModifiedIterator>::Type TCargo_;
102 
103     THost _host;
104     TCargo_ _cargo;
105 
106     mutable typename Value<ModifiedIterator>::Type tmp_value;
107 
ModifiedIterator()108     ModifiedIterator() : _host(), tmp_value()
109     {}
110 
111     template <typename TOtherHost>
ModifiedIterator(ModifiedIterator<TOtherHost,ModView<TFunctor>> & origin)112     ModifiedIterator(ModifiedIterator<TOtherHost, ModView<TFunctor> > & origin) :
113         _host(origin._host), _cargo(origin._cargo), tmp_value()
114     {}
115 
116     explicit
ModifiedIterator(THost const & host)117     ModifiedIterator(THost const & host) :
118         _host(host), tmp_value()
119     {}
120 
ModifiedIterator(THost const & host,TFunctor const & functor)121     ModifiedIterator(THost const & host, TFunctor const & functor):
122         _host(host), tmp_value()
123     {
124         cargo(*this).func = functor;
125     }
126 };
127 
128 // --------------------------------------------------------------------------
129 // Class ModifiedString
130 // --------------------------------------------------------------------------
131 
132 template <typename THost, typename TFunctor>
133 class ModifiedString<THost, ModView<TFunctor> >
134 {
135 public:
136     typedef typename Pointer_<THost>::Type       THostPointer_;
137     typedef typename Cargo<ModifiedString>::Type TCargo_;
138 
139     mutable THostPointer_ _host;
140     TCargo_ _cargo;
141 
142     mutable typename Value<ModifiedString>::Type tmp_value;
143 
144     // Default constructor.
ModifiedString()145     ModifiedString() : _host(), tmp_value()
146     {}
147 
148     // Construct with the actual host.
149     explicit
ModifiedString(typename Parameter_<THost>::Type host)150     ModifiedString(typename Parameter_<THost>::Type host):
151         _host(_toPointer(host)), tmp_value()
152     {}
153 
154     // Construct with the functor.
155     explicit
ModifiedString(TFunctor const & functor)156     ModifiedString(TFunctor const & functor):
157         _host(), tmp_value()
158     {
159         cargo(*this).func = functor;
160     }
161 
162     // Constructor for creating a ModifiedString with const host from a non-const host.
163     template <typename THost_>
164     explicit
ModifiedString(THost_ & host,SEQAN_CTOR_ENABLE_IF (IsConstructible<THost,THost_>))165     ModifiedString(THost_ & host,
166                    SEQAN_CTOR_ENABLE_IF(IsConstructible<THost, THost_>)) :
167             _host(_toPointer(host)), tmp_value()
168     {
169         ignoreUnusedVariableWarning(dummy);
170     }
171 
172     // Construct with the actual host; variant with functor.
ModifiedString(typename Parameter_<THost>::Type host,TFunctor const & functor)173     ModifiedString(typename Parameter_<THost>::Type host, TFunctor const & functor) :
174             _host(_toPointer(host)), tmp_value()
175     {
176         cargo(*this).func = functor;
177     }
178 
179     // Constructor for creating a ModifiedString with const host with a non-const host; variant with functor.
180     template <typename THost_>
181     explicit
ModifiedString(THost_ & host,TFunctor const & functor,SEQAN_CTOR_ENABLE_IF (IsConstructible<THost,THost_>))182     ModifiedString(THost_ & host,
183                    TFunctor const & functor,
184                    SEQAN_CTOR_ENABLE_IF(IsConstructible<THost, THost_>)) :
185             _host(_toPointer(host)), tmp_value()
186     {
187         ignoreUnusedVariableWarning(dummy);
188         cargo(*this).func = functor;
189     }
190 
191     // Constructor for innermost type; hand down to _host which is a ModifiedString itself.
192     template <typename THost_>
193     explicit
ModifiedString(THost_ && host,SEQAN_CTOR_ENABLE_IF (IsAnInnerHost<typename RemoveReference<THost>::Type,typename RemoveReference<THost_>::Type>))194     ModifiedString(THost_ && host,
195                    SEQAN_CTOR_ENABLE_IF(IsAnInnerHost<
196                                             typename RemoveReference<THost>::Type,
197                                             typename RemoveReference<THost_>::Type >)) :
198             _host(std::forward<THost_>(host)), tmp_value()
199     {
200         ignoreUnusedVariableWarning(dummy);
201     }
202 
203     // Constructor for innermost type; hand down to _host which is a ModifiedString itself.  Variant with functor.
204     template <typename THost_>
205     explicit
ModifiedString(THost_ && host,TFunctor const & functor,SEQAN_CTOR_ENABLE_IF (IsAnInnerHost<typename RemoveReference<THost>::Type,typename RemoveReference<THost_>::Type>))206     ModifiedString(THost_ && host,
207                    TFunctor const & functor,
208                    SEQAN_CTOR_ENABLE_IF(IsAnInnerHost<
209                                             typename RemoveReference<THost>::Type,
210                                             typename RemoveReference<THost_>::Type >)) :
211             _host(std::forward<THost_>(host)), tmp_value()
212     {
213         ignoreUnusedVariableWarning(dummy);
214         cargo(*this).func = functor;
215     }
216 
217     template <typename TPos>
218     inline typename Reference<ModifiedString>::Type
219     operator[](TPos pos)
220     {
221         return value(*this, pos);
222     }
223 
224     template <typename TPos>
225     inline typename Reference<ModifiedString const>::Type
226     operator[](TPos pos) const
227     {
228         return value(*this, pos);
229     }
230 };
231 
232 // ==========================================================================
233 // Metafunctions
234 // ==========================================================================
235 
236 // --------------------------------------------------------------------------
237 // Metafunction Cargo                                      [ModifiedIterator]
238 // --------------------------------------------------------------------------
239 
240 template <typename THost, typename TFunctor>
241 struct Cargo<ModifiedIterator<THost, ModView<TFunctor> > >
242 {
243     typedef ModViewCargo<TFunctor>    Type;
244 };
245 
246 // --------------------------------------------------------------------------
247 // Metafunction Value                                      [ModifiedIterator]
248 // --------------------------------------------------------------------------
249 
250 template <typename THost, typename TFunctor>
251 struct Value<ModifiedIterator<THost, ModView<TFunctor> > >
252 {
253     typedef typename TFunctor::result_type            TResult_;
254     typedef typename RemoveConst_<TResult_>::Type   Type;
255 };
256 
257 template <typename THost, typename TFunctor>
258 struct Value<ModifiedIterator<THost, ModView<TFunctor> > const> :
259     Value<ModifiedIterator<THost, ModView<TFunctor> > >
260 {};
261 
262 // --------------------------------------------------------------------------
263 // Metafunction GetValue                                   [ModifiedIterator]
264 // --------------------------------------------------------------------------
265 
266 template <typename THost, typename TFunctor>
267 struct GetValue<ModifiedIterator<THost, ModView<TFunctor> > > :
268     Value<ModifiedIterator<THost, ModView<TFunctor> > >
269 {};
270 
271 template <typename THost, typename TFunctor>
272 struct GetValue<ModifiedIterator<THost, ModView<TFunctor> > const> :
273     Value<ModifiedIterator<THost, ModView<TFunctor> > >
274 {};
275 
276 // --------------------------------------------------------------------------
277 // Metafunction Reference                                  [ModifiedIterator]
278 // --------------------------------------------------------------------------
279 
280 template <typename THost, typename TFunctor>
281 struct Reference<ModifiedIterator<THost, ModView<TFunctor> > > :
282     Value<ModifiedIterator<THost, ModView<TFunctor> > >
283 {};
284 
285 template <typename THost, typename TFunctor>
286 struct Reference<ModifiedIterator<THost, ModView<TFunctor> > const> :
287     Value<ModifiedIterator<THost, ModView<TFunctor> > >
288 {};
289 
290 // NOTE(h-2): ModView element access is always by copy never by reference
291 // This is a workaround for dangling references to the stack when
292 // combining infixes and modified views, more precisely:
293 //  if you iterate over an infix of a modview then value() on the iterator
294 //  will return reference to the tmp_value inside the moditerator
295 //  which might have been destructed.
296 // This is a more general problem that stems from the fact that
297 // "virtual strings" of the same type (infixes, modstrings) can be
298 // automatically compacted into one layer, but combinations cannot.
299 // This workaround happens in ModView, because it is used less frequently
300 // then Infixes.
301 
302 // --------------------------------------------------------------------------
303 // Metafunction Cargo                                        [ModifiedString]
304 // --------------------------------------------------------------------------
305 
306 template <typename THost, typename TFunctor>
307 struct Cargo< ModifiedString<THost, ModView<TFunctor> > >
308 {
309     typedef ModViewCargo<TFunctor>    Type;
310 };
311 
312 // ==========================================================================
313 // Functions
314 // ==========================================================================
315 
316 // --------------------------------------------------------------------------
317 // Function getValue()                                     [ModifiedIterator]
318 // --------------------------------------------------------------------------
319 
320 template <typename THost, typename TFunctor>
321 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > >::Type
322 getValue(ModifiedIterator<THost, ModView<TFunctor> > & me)
323 {
324     return cargo(me).func(*host(me));
325 }
326 
327 template <typename THost, typename TFunctor>
328 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > const>::Type
329 getValue(ModifiedIterator<THost, ModView<TFunctor> > const & me)
330 {
331     return cargo(me).func(*host(me));
332 }
333 
334 // --------------------------------------------------------------------------
335 // Function value()                                        [ModifiedIterator]
336 // --------------------------------------------------------------------------
337 
338 template <typename THost, typename TFunctor>
339 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > >::Type
340 value(ModifiedIterator<THost, ModView<TFunctor> > & me)
341 {
342     return getValue(me);
343 }
344 
345 template <typename THost, typename TFunctor>
346 inline typename GetValue<ModifiedIterator<THost, ModView<TFunctor> > const>::Type
347 value(ModifiedIterator<THost, ModView<TFunctor> > const & me)
348 {
349     return getValue(me);
350 }
351 
352 // --------------------------------------------------------------------------
353 // Function getValue()                                       [ModifiedString]
354 // --------------------------------------------------------------------------
355 
356 template <typename THost, typename TFunctor, typename TPos>
357 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > >::Type
358 getValue(ModifiedString<THost, ModView<TFunctor> > & me, TPos pos)
359 {
360     return cargo(me).func(getValue(host(me), pos));
361 }
362 
363 template <typename THost, typename TFunctor, typename TPos>
364 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > const>::Type
365 getValue(ModifiedString<THost, ModView<TFunctor> > const & me, TPos pos)
366 {
367     return cargo(me).func(getValue(host(me), pos));
368 }
369 
370 // --------------------------------------------------------------------------
371 // Function value()                                          [ModifiedString]
372 // --------------------------------------------------------------------------
373 
374 template <typename THost, typename TFunctor, typename TPos>
375 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > >::Type
376 value(ModifiedString<THost, ModView<TFunctor> > & me, TPos pos)
377 {
378     return getValue(me, pos);
379 }
380 
381 template <typename THost, typename TFunctor, typename TPos>
382 inline typename GetValue<ModifiedString<THost, ModView<TFunctor> > const>::Type
383 value(ModifiedString<THost, ModView<TFunctor> > const & me, TPos pos)
384 {
385     return getValue(me, pos);
386 }
387 
388 // --------------------------------------------------------------------------
389 // Function assignModViewFunctor()
390 // --------------------------------------------------------------------------
391 
392 template <typename THost, typename TFunctor>
393 inline void
394 assignModViewFunctor(ModifiedString<THost, ModView<TFunctor> > & me, TFunctor const & functor)
395 {
396     cargo(me).func = functor;
397 }
398 
399 // --------------------------------------------------------------------------
400 // Function convert()
401 // --------------------------------------------------------------------------
402 
403 template < typename TSequence, typename TFunctor >
404 inline void
405 convert(TSequence & sequence, TFunctor const &F)
406 {
407 #if defined (_OPENMP) && defined (SEQAN_PARALLEL)
408     // OpenMP does not support for loop with iterators. Therefore use index variables.
409     typedef typename Position<TSequence>::Type    TPos;
410     typedef typename MakeSigned_<TPos>::Type    TSignedPos;
411 
412     #pragma omp parallel for if(length(sequence) > 1000000)
413     for(TSignedPos p = 0; p < (TSignedPos)length(sequence); ++p)
414         sequence[p] = F(sequence[p]);
415 
416 #else
417     typedef typename Iterator<TSequence, Standard>::Type    TIter;
418 
419     TIter it = begin(sequence, Standard());
420     TIter itEnd = end(sequence, Standard());
421     for(; it != itEnd; ++it)
422         *it = F(*it);
423 #endif
424 }
425 
426 template < typename TSequence, typename TFunctor >
427 inline void
428 convert(TSequence const & sequence, TFunctor const &F)
429 {
430 #if defined (_OPENMP) && defined (SEQAN_PARALLEL)
431     // OpenMP does not support for loop with iterators. Therefore use index variables.
432     typedef typename Position<TSequence>::Type    TPos;
433     typedef typename MakeSigned_<TPos>::Type    TSignedPos;
434 
435     #pragma omp parallel for if(length(sequence) > 1000000)
436     for(TSignedPos p = 0; p < (TSignedPos)length(sequence); ++p)
437         sequence[p] = F(sequence[p]);
438 
439 #else
440     typedef typename Iterator<TSequence const, Standard>::Type    TIter;
441 
442     TIter it = begin(sequence, Standard());
443     TIter itEnd = end(sequence, Standard());
444     for(; it != itEnd; ++it)
445         *it = F(*it);
446 #endif
447 }
448 
449 }  // namespace seqan
450 
451 #endif  // SEQAN_MODIFIER_MODIFIER_VIEW_H_
452