Imported Upstream version 0.12.7
[bowtie.git] / SeqAn-1.1 / seqan / file / chunk_collector.h
1  /*==========================================================================
2                 SeqAn - The Library for Sequence Analysis
3                           http://www.seqan.de 
4  ============================================================================
5   Copyright (C) 2007
6
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10   version 3 of the License, or (at your option) any later version.
11
12   This library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17  ============================================================================
18   $Id: chunk_collector.h,v 1.1 2008/08/25 16:20:04 langmead Exp $
19  ==========================================================================*/
20
21 #ifndef SEQAN_HEADER_CHUNK_COLLECTOR_H
22 #define SEQAN_HEADER_CHUNK_COLLECTOR_H
23
24
25 namespace SEQAN_NAMESPACE_MAIN
26 {
27 //////////////////////////////////////////////////////////////////////////////
28
29 /**
30 .Internal._ChunkCollector:
31 ..cat:Classes
32 ..summary:Reads piecewise from stream, collects pieces (chunks) in a vector.
33 ..signature:_ChunkCollector<Host>
34 ..param.Host:Type of host object that is used as allocator.
35 */
36
37 //////////////////////////////////////////////////////////////////////////////
38
39 template <typename T>
40 struct ChunkLength
41 {
42         enum { VALUE = 1024 };
43 };
44
45 //////////////////////////////////////////////////////////////////////////////
46 // _StreamChunkCollector class: collects content of a stream in chunks
47 //////////////////////////////////////////////////////////////////////////////
48
49 template <typename THost>
50 class _ChunkCollector
51 {
52 protected:
53         THost * data_host;
54         typename Size<THost>::Type data_length;
55
56         typedef ::std::vector<typename Value<THost>::Type *, ToStdAllocator<THost, typename Value<THost>::Type *> > Chunk_Holder;
57         Chunk_Holder data_chunks; 
58
59 public:
60         static int const CHUNK_LENGTH = ChunkLength<_ChunkCollector>::VALUE;
61
62 public:
63         _ChunkCollector(THost & _host):
64                 data_host(& _host),
65                 data_length(0),
66                 data_chunks(typename Chunk_Holder::allocator_type(_host))
67         {
68         }
69
70         ~_ChunkCollector()
71         {
72                 clear(*this);
73         }
74
75 public:
76
77         friend inline void
78         clear(_ChunkCollector & me)
79         {
80                 typename Chunk_Holder::iterator it = me.data_chunks.begin();
81                 typename Chunk_Holder::iterator it_end = me.data_chunks.end();
82
83                 for (; it != it_end; ++it)
84                 {
85                         deallocate(me.data_host, *it, CHUNK_LENGTH);
86                 }
87
88                 me.data_chunks.clear();
89                 me.data_length = 0;
90         }
91
92         friend inline typename Size<THost>::Type
93         length(_ChunkCollector const & me)
94         {
95                 return me.data_length;
96         }
97
98         friend inline void
99         _setLength(_ChunkCollector & me, typename Size<THost>::Type new_length)
100         {
101                 me.data_length = new_length;
102         }
103
104         friend inline int
105         chunkCount(_ChunkCollector const & me)
106         {
107                 return me.data_chunks.size();
108         }
109
110         friend inline typename Value<THost>::Type *
111         getChunk(_ChunkCollector const & me, int chunk_number)
112         {
113                 return me.data_chunks[chunk_number];
114         }
115
116         friend inline typename Value<THost>::Type *
117         createChunk(_ChunkCollector & me)
118         {
119                 typename Value<THost>::Type * new_chunk;
120                 allocate(me.data_host, new_chunk, CHUNK_LENGTH);
121                 me.data_chunks.push_back(new_chunk);
122                 return new_chunk;
123         }
124 };
125
126
127 //////////////////////////////////////////////////////////////////////////////
128
129 template <typename THost>
130 struct Host<_ChunkCollector<THost> >
131 {
132         typedef THost Type;
133 };
134
135 template <typename THost>
136 struct Host<_ChunkCollector<THost> const >
137 {
138         typedef THost Type;
139 };
140
141 //////////////////////////////////////////////////////////////////////////////
142
143 template <typename THost>
144 struct Value<_ChunkCollector<THost> >
145 {
146         typedef typename Value<THost>::Type Type;
147 };
148
149 template <typename THost>
150 struct Value<_ChunkCollector<THost> const >
151 {
152         typedef typename Value<THost>::Type Type;
153 };
154
155 //////////////////////////////////////////////////////////////////////////////
156
157 template <typename THost>
158 struct GetValue<_ChunkCollector<THost> >
159 {
160         typedef typename GetValue<THost>::Type Type;
161 };
162
163 template <typename THost>
164 struct GetValue<_ChunkCollector<THost> const >
165 {
166         typedef typename GetValue<THost>::Type Type;
167 };
168
169 //////////////////////////////////////////////////////////////////////////////
170
171 template <typename THost>
172 struct Size<_ChunkCollector<THost> >
173 {
174         typedef typename Size<THost>::Type Type;
175 };
176
177 template <typename THost>
178 struct Size<_ChunkCollector<THost> const >
179 {
180         typedef typename Size<THost>::Type Type;
181 };
182
183 //////////////////////////////////////////////////////////////////////////////
184
185 struct _Assign_Stream_2_ChunkCollector
186 {
187         template <typename THost, typename TSource>
188         static inline void 
189         assign_(_ChunkCollector<THost> & target,
190                 TSource & source)
191         {
192                 clear(target);
193
194                 while (!_streamEOF(source))
195                 {
196                         typename Value<THost>::Type * chunk = createChunk(target);
197                         typename Size<THost>::Type count = _streamRead(chunk, source, ChunkLength< _ChunkCollector<THost> >::VALUE);
198                         _setLength(target, length(target) + count);
199                 }
200         }
201
202         template <typename THost, typename TSource>
203         static inline void 
204         assign_(_ChunkCollector<THost> & target,
205                 TSource & source,
206                 typename Size< _ChunkCollector<THost> >::Type limit)
207         {
208                 clear(target);
209
210                 while (!_streamEOF(source))
211                 {
212                         typename Value<THost>::Type * chunk = createChunk(target);
213                         typename Size<THost>::Type count = _streamRead(chunk, source, ChunkLength< _ChunkCollector<THost> >::VALUE);
214                         _setLength(target, length(target) + count);
215
216                         if (length(target) >= limit)
217                         {
218                                 _setLength(target, limit);
219                                 break;
220                         }
221                 }
222         }
223 };
224
225 //////////////////////////////////////////////////////////////////////////////
226
227 template <typename THost, typename TSource>
228 inline void 
229 assign(_ChunkCollector<THost> & target,
230            TSource & source)
231 {
232         _Assign_Stream_2_ChunkCollector::assign_(target, source);
233 }
234 template <typename THost, typename TSource>
235 inline void 
236 assign(_ChunkCollector<THost> & target,
237            TSource const & source)
238 {
239         _Assign_Stream_2_ChunkCollector::assign_(target, source);
240 }
241
242 template <typename THost, typename TSource, typename TSize>
243 inline void 
244 assign(_ChunkCollector<THost> & target,
245            TSource & source,
246            TSize limit)
247 {
248         _Assign_Stream_2_ChunkCollector::assign_(target, source, limit);
249 }
250 template <typename THost, typename TSource, typename TSize>
251 inline void 
252 assign(_ChunkCollector<THost> & target,
253            TSource const & source,
254            TSize limit)
255 {
256         _Assign_Stream_2_ChunkCollector::assign_(target, source, limit);
257 }
258
259 //////////////////////////////////////////////////////////////////////////////
260 //////////////////////////////////////////////////////////////////////////////
261
262 template <typename TExpand>
263 struct _Assign_ChunkCollector_2_String
264 {
265         template <typename TTarget, typename TSource>
266         static void assign_(
267                 TTarget & target, 
268                 TSource & source)
269         {
270                 typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), TExpand());
271
272                 int i_end = chunkCount(source);
273                 typename Value<TTarget>::Type * pos = begin(target);
274                 for (int i = 0; i < i_end; ++i)
275                 {
276                         bool is_last_chunk = ( part_length <= ChunkLength<TSource>::VALUE);
277                         typename Size<TTarget>::Type chunk_length = (is_last_chunk) ? part_length : ChunkLength<TSource>::VALUE;
278                         typename Value<TSource>::Type * chunk = getChunk(source, i);
279                         
280                         arrayConstructCopy(chunk, chunk + chunk_length, pos);
281                         if (is_last_chunk) break;
282                         pos += chunk_length;
283                 }
284         }
285
286         template <typename TTarget, typename TSource>
287         static void assign_(
288                 TTarget & target, 
289                 TSource & source,
290                 typename Size<TTarget>::Type limit)
291         {
292                 typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), limit, TExpand());
293
294                 int i_end = chunkCount(source);
295                 typename Value<TTarget>::Type * pos = begin(target);
296                 for (int i = 0; i < i_end; ++i)
297                 {
298                         bool is_last_chunk = ( part_length <= ChunkLength<TSource>::VALUE);
299                         typename Size<TTarget>::Type chunk_length = (is_last_chunk) ? part_length : ChunkLength<TSource>::VALUE;
300                         typename Value<TSource>::Type * chunk = getChunk(source, i);
301                         
302                         arrayConstructCopy(chunk, chunk + chunk_length, pos);
303                         if (is_last_chunk) break;
304                         pos += chunk_length;
305                 }
306         }
307 };
308
309 //////////////////////////////////////////////////////////////////////////////
310
311 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
312 inline void 
313 assign(String<TTargetValue, TTargetSpec> & target,
314            _ChunkCollector<TSourceHost> const & source,
315            Tag<TExpand> const tag)
316 {
317         _Assign_ChunkCollector_2_String<Tag<TExpand> const>::assign_(target, source);
318 }
319 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
320 inline void 
321 assign(String<TTargetValue, TTargetSpec> & target,
322            _ChunkCollector<TSourceHost> const & source,
323            typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
324            Tag<TExpand> const tag)
325 {
326         _Assign_ChunkCollector_2_String<Tag<TExpand> const>::assign_(target, source, limit);
327 }
328
329
330 //////////////////////////////////////////////////////////////////////////////
331
332 template <typename TExpand>
333 struct _Append_ChunkCollector_2_String
334 {
335         template <typename TTarget, typename TSource>
336         static void append_(
337                 TTarget & target, 
338                 TSource & source)
339         {
340                 typedef typename Size<TTarget>::Type TSize;
341                 TSize target_length_old = length(target);
342                 TSize part_length = _clearSpace(target, length(source), target_length_old, target_length_old, TExpand());
343
344                 int i_end = chunkCount(source);
345                 typename Value<TTarget>::Type * pos = begin(target) + target_length_old; //begin(target) was possibly changed by _clearSpace
346                 for (int i = 0; i < i_end; ++i)
347                 {
348                         bool is_last_chunk = ( part_length <= ChunkLength<TSource>::VALUE);
349                         typename Size<TTarget>::Type chunk_length = (is_last_chunk) ? part_length : (TSize) ChunkLength<TSource>::VALUE;
350                         typename Value<TSource>::Type * chunk = getChunk(source, i);
351                         
352                         arrayConstructCopy(chunk, chunk + chunk_length, pos);
353                         if (is_last_chunk) break;
354                         pos += chunk_length;
355                 }
356         }
357
358         template <typename TTarget, typename TSource>
359         static void append_(
360                 TTarget & target, 
361                 TSource & source,
362                 typename Size<TTarget>::Type limit)
363         {
364                 typedef typename Size<TTarget>::Type TSize;
365                 TSize target_length_old = length(target);
366                 TSize part_length = _clearSpace(target, length(source), target_length_old, target_length_old, limit, TExpand());
367
368                 int i_end = chunkCount(source);
369                 typename Value<TTarget>::Type * pos = begin(target) + target_length_old; //begin(target) was possibly changed by _clearSpace
370                 for (int i = 0; i < i_end; ++i)
371                 {
372                         bool is_last_chunk = ( part_length <= ChunkLength<TSource>::VALUE);
373                         typename Size<TTarget>::Type chunk_length = (is_last_chunk) ? part_length : (TSize) ChunkLength<TSource>::VALUE;
374                         typename Value<TSource>::Type * chunk = getChunk(source, i);
375                         
376                         arrayConstructCopy(chunk, chunk + chunk_length, pos);
377                         if (is_last_chunk) break;
378                         pos += chunk_length;
379                 }
380         }
381 };
382
383 //////////////////////////////////////////////////////////////////////////////
384
385 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
386 inline void 
387 append(String<TTargetValue, TTargetSpec> & target,
388            _ChunkCollector<TSourceHost> const & source,
389            Tag<TExpand> const )
390 {
391         _Append_ChunkCollector_2_String<Tag<TExpand> const>::append_(target, source);
392 }
393 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
394 inline void 
395 append(String<TTargetValue, TTargetSpec> & target,
396            _ChunkCollector<TSourceHost> const & source,
397            typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
398            Tag<TExpand> const )
399 {
400         _Append_ChunkCollector_2_String<Tag<TExpand> const>::append_(target, source, limit);
401 }
402
403 //////////////////////////////////////////////////////////////////////////////
404
405 template <typename TExpand>
406 struct _Replace_ChunkCollector_2_String
407 {
408         template <typename TTarget, typename TSource>
409         static void replace_(
410                 TTarget & target,
411                 typename Size<TTarget>::Type pos_begin,
412                 typename Size<TTarget>::Type pos_end,
413                 TSource & source)
414         {
415                 typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), pos_begin, pos_end, TExpand());
416
417                 int i_end = chunkCount(source);
418                 typename Value<TTarget>::Type * pos = begin(target) + pos_begin;
419                 for (int i = 0; i < i_end; ++i)
420                 {
421                         bool is_last_chunk = ( part_length <= ChunkLength<TSource>::VALUE);
422                         typename Size<TTarget>::Type chunk_length = (is_last_chunk) ? part_length : ChunkLength<TSource>::VALUE;
423                         typename Value<TSource>::Type * chunk = getChunk(source, i);
424                         
425                         arrayConstructCopy(chunk, chunk + chunk_length, pos);
426                         if (is_last_chunk) break;
427                         pos += chunk_length;
428                 }
429         }
430
431         template <typename TTarget, typename TSource>
432         static void replace_(
433                 TTarget & target, 
434                 typename Size<TTarget>::Type pos_begin,
435                 typename Size<TTarget>::Type pos_end,
436                 TSource & source,
437                 typename Size<TTarget>::Type limit)
438         {
439                 typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), pos_begin, pos_end, limit, TExpand());
440
441                 int i_end = chunkCount(source);
442                 typename Value<TTarget>::Type * pos = begin(target) + pos_begin;
443                 for (int i = 0; i < i_end; ++i)
444                 {
445                         bool is_last_chunk = ( part_length <= ChunkLength<TSource>::VALUE);
446                         typename Size<TTarget>::Type chunk_length = (is_last_chunk) ? part_length : ChunkLength<TSource>::VALUE;
447                         typename Value<TSource>::Type * chunk = getChunk(source, i);
448                         
449                         arrayConstructCopy(chunk, chunk + chunk_length, pos);
450                         if (is_last_chunk) break;
451                         pos += chunk_length;
452                 }
453         }
454 };
455
456 //////////////////////////////////////////////////////////////////////////////
457
458 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
459 inline void 
460 replace(String<TTargetValue, TTargetSpec> & target,
461                 typename Size< String<TTargetValue, TTargetSpec> >::Type pos_begin,
462                 typename Size< String<TTargetValue, TTargetSpec> >::Type pos_end,
463            _ChunkCollector<TSourceHost> const & source,
464            Tag<TExpand> const tag)
465 {
466         _Replace_ChunkCollector_2_String<Tag<TExpand> const>::replace_(target, pos_begin, pos_end, source);
467 }
468
469 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
470 inline void 
471 replace(String<TTargetValue, TTargetSpec> & target,
472                 typename Size< String<TTargetValue, TTargetSpec> >::Type pos_begin,
473                 typename Size< String<TTargetValue, TTargetSpec> >::Type pos_end,
474            _ChunkCollector<TSourceHost> const & source,
475            typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
476            Tag<TExpand> const tag)
477 {
478         _Replace_ChunkCollector_2_String<Tag<TExpand> const>::replace_(target, pos_begin, pos_end, source, limit);
479 }
480
481 //////////////////////////////////////////////////////////////////////////////
482
483 template <typename TTargetValue, typename TSourceHost, typename TExpand>
484 inline void 
485 replace(TTargetValue * target,
486                 size_t pos_begin,
487                 size_t pos_end,
488                 _ChunkCollector<TSourceHost> const & source,
489                 Tag<TExpand> const tag)
490 {
491         _Replace_ChunkCollector_2_String<Tag<TExpand> const>::replace_(target, pos_begin, pos_end, source);
492 }
493
494 template <typename TTargetValue, typename TSourceHost, typename TExpand>
495 inline void 
496 replace(TTargetValue * target,
497                 size_t pos_begin,
498                 size_t pos_end,
499                 _ChunkCollector<TSourceHost> const & source,
500                 size_t limit,
501                 Tag<TExpand> const tag)
502 {
503         _Replace_ChunkCollector_2_String<Tag<TExpand> const>::replace_(target, pos_begin, pos_end, source, limit);
504 }
505 //____________________________________________________________________________
506 /*
507 template <typename TTargetValue, typename TSourceHost, typename TExpand>
508 inline void 
509 replace(TTargetValue * target,
510                 size_t pos_begin,
511                 size_t pos_end,
512            _ChunkCollector<TSourceHost> const & source,
513            Tag<TExpand> const tag)
514 {
515         _Replace_ChunkCollector_2_String<Tag<TExpand> const>::replace_(target, pos_begin, pos_end, source);
516 }
517
518 template <typename TTargetValue, typename TTargetSpec, typename TSourceHost, typename TExpand>
519 inline void 
520 replace(String<TTargetValue, TTargetSpec> & target,
521                 typename Size< String<TTargetValue, TTargetSpec> >::Type pos_begin,
522                 typename Size< String<TTargetValue, TTargetSpec> >::Type pos_end,
523            _ChunkCollector<TSourceHost> const & source,
524            typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
525            Tag<TExpand> const tag)
526 {
527         _Replace_ChunkCollector_2_String<Tag<TExpand> const>::replace_(target, pos_begin, pos_end, source, limit);
528 }
529 */
530 //////////////////////////////////////////////////////////////////////////////
531
532 } //namespace SEQAN_NAMESPACE_MAIN
533
534 #endif //#ifndef SEQAN_HEADER_...