Imported Upstream version 0.12.7
[bowtie.git] / SeqAn-1.1 / seqan / file / file_format_fasta.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: file_format_fasta.h,v 1.1 2008/08/25 16:20:03 langmead Exp $
19  ==========================================================================*/
20
21 #ifndef SEQAN_HEADER_FILE_FASTA_H
22 #define SEQAN_HEADER_FILE_FASTA_H
23
24 namespace SEQAN_NAMESPACE_MAIN
25 {
26
27 //////////////////////////////////////////////////////////////////////////////
28 // File Formats - Fasta
29 //////////////////////////////////////////////////////////////////////////////
30
31 /**
32 .Tag.File Format.tag.Fasta:
33         FASTA file format for sequences.
34 */
35 struct TagFasta_;
36 typedef Tag<TagFasta_> const Fasta;
37
38 //////////////////////////////////////////////////////////////////////////////
39 // Filereader
40 //////////////////////////////////////////////////////////////////////////////
41
42 template <typename TFile, typename TFile2, typename TSpec>
43 inline void
44 goBegin(Iter<TFile, FileReader<Fasta, TFile2, TSpec> > & it, bool skip_meta)
45 {
46         if (_streamEOF(host(it)))
47         {
48                 it.data_eof = true;
49                 return;
50         }
51
52         if (skip_meta && (it.data_char == '>'))
53         {
54                 //skip meta line
55                 _stream_skipLine(host(it), it.data_char);
56         }
57
58         //eliminate linebreaks
59         while ((it.data_char == '\n') || (it.data_char == '\r'))
60         {
61                 if (_streamEOF(host(it)))
62                 {
63                         it.data_eof = true;
64                         return;
65                 }
66                 it.data_char = _streamGet(host(it));
67         }
68
69         if (it.data_char == '>')
70         {//end of record
71                 it.data_eof = true;
72                 _streamUnget(host(it));
73                 return;
74         }
75
76         it.data_file_pos = _streamTellG(host(it)) - 1;
77         it.data_eof = _streamEOF(host(it));
78 }
79 template <typename TFile, typename TFile2, typename TSpec>
80 inline void
81 goBegin(Iter<TFile, FileReader<Fasta, TFile2, TSpec> > & it)
82 {
83         goBegin(it, true);
84 }
85
86
87 template <typename TFile, typename TFile2, typename TSpec>
88 inline void
89 goNext(Iter<TFile, FileReader<Fasta, TFile2, TSpec> > & it)
90 {
91 /*
92         if (_streamEOF(host(it)))
93         {
94                 it.data_eof = true;
95                 return;
96         }
97 */
98         it.data_char = _streamGet(host(it));
99         ++it.data_file_pos;
100
101         if (_streamEOF(host(it)))
102         {
103                 it.data_eof = true;
104                 return;
105         }
106
107         if ((it.data_char == '\n') || (it.data_char == '\r'))
108         {//linebreak detected: find begin of next line
109                 do
110                 {
111                         it.data_char = _streamGet(host(it));
112                         if (_streamEOF(host(it)))
113                         {
114                                 it.data_eof = true;
115                                 return;
116                         }
117                         ++it.data_file_pos;
118                 } while ((it.data_char == '\n') || (it.data_char == '\r'));
119
120                 if (it.data_char == '>')
121                 {//end of record
122                         _streamUnget(host(it));
123                         it.data_eof = true;
124                 }
125         }
126 }
127
128 //////////////////////////////////////////////////////////////////////////////
129 // FileFormat Interface
130 //////////////////////////////////////////////////////////////////////////////
131
132
133
134 /////////////////////////////////////////////////////////////////////////
135 //count_valid: zaehlt die nicht-Zeilenumbrueche (input/output)
136 //count_all: zaehlt alle Zeichen incl. Zeilenumbrueche (input/output)
137 //returns: zuletzt gelesenes Zeichen = das erste hinter dem Zeilenumbruch bzw. eof
138 //the last read char is not counted!
139 //count_valid and count_all are not resetted but counted up
140 template <typename TFile, typename TSize>
141 inline typename Value<TFile>::Type
142 _fasta_scan_line(TFile & file,
143                                  TSize & count_valid,
144                                  TSize & count_all)
145 {
146 SEQAN_CHECKPOINT
147         SEQAN_ASSERT(!_streamEOF(file))
148
149         TSize count = 0;
150
151         while (true)
152         {
153                 typename Value<TFile>::Type c = _streamGet(file);
154
155                 if (_streamEOF(file))
156                 {
157                         count_valid += count;
158                         count_all += count;
159                         return c;
160                 }
161
162                 if ((c == '\n') || (c == '\r'))
163                 {
164                         do
165                         {
166                                 ++count_all;
167                                 c = _streamGet(file);
168                         } while ((c == '\n') || (c == '\r'));
169
170                         count_valid += count;
171                         count_all += count;
172                         return c;
173                 }
174
175                 if (c != '\r')
176                 {
177                         ++count;
178                 }
179         }
180 }
181
182
183 /////////////////////////////////////////////////////////////////////////
184 template <typename TFile, typename TSize>
185 inline void
186 _read_n_chars_from_file(TFile & file, TSize count)
187 {
188 SEQAN_CHECKPOINT
189         for (TSize i = 0; i < count; ++i)
190         {
191                 _streamGet(file);
192         }
193 }
194
195
196 //////////////////////////////////////////////////////////////////////////////
197 // read
198 //////////////////////////////////////////////////////////////////////////////
199
200 template <typename TFile, typename TData, typename TSize>
201 void
202 read(TFile & file,
203          TData & data,
204          TSize limit,
205          Fasta)
206 {
207 SEQAN_CHECKPOINT
208
209         SEQAN_ASSERT(!_streamEOF(file))
210         clear(data);
211
212         //determine begin position
213         typename Value<TFile>::Type c_first = _streamGet(file);
214         SEQAN_ASSERT(!_streamEOF(file))
215
216         typename Position<TFile>::Type begin_pos = _streamTellG(file);
217         typename Size<TData>::Type count_valid = 1; //"valid" characters read (without line breaks)
218         typename Size<TData>::Type count_all = 1;       //all characters read (with line breaks)
219
220         if (_streamEOF(file))
221         {
222                 return;
223         }       
224
225         if (c_first == '>')
226         {//there is an id line: skip it
227                 c_first = _fasta_scan_line(file, count_valid, count_all);
228         }
229
230         if ((c_first == '>') || _streamEOF(file)) 
231         {//another id line = empty entry
232                 _streamSeekG(file, begin_pos);
233                 _read_n_chars_from_file(file, count_all);
234                 return;
235         }
236
237         begin_pos = _streamTellG(file);
238
239         count_valid = 1;
240         count_all = 1;
241         typename Value<TFile>::Type c;
242         bool eof_reached = false;
243         //determine length
244         while (true)
245         {
246                 c = _fasta_scan_line(file, count_valid, count_all);
247                 if (_streamEOF(file)) 
248                 {//end of file: stop searching
249                         eof_reached = true;
250                         break;
251                 }
252                 if (c == '>')
253                 {//next entry found: stop seaching
254                         break;
255                 }
256                 if ((c != '\n') && (c != '\r'))
257                 {
258                         ++count_valid; //count c
259                 }
260                 ++count_all;
261         }
262
263         //reserve space
264         typename Size<TData>::Type count = count_valid;
265         if (count > limit)
266         {
267                 count = limit;
268         }
269         resize(data, count);
270         if (length(data) < count)
271         {
272                 count = length(data);
273         }
274
275         //read sequence
276         _streamSeekG(file, begin_pos);
277
278         typename Position<TData>::Type pos = 0;
279         c = c_first;
280         while (true)
281         {
282                 if ((c != '\n') && (c != '\r'))
283                 {
284                         data[pos] = c;
285                         ++pos;
286                 }
287                 if (pos >= count) break;
288
289                 c =  _streamGet(file);
290                 --count_all;
291         }
292
293         //move file ptr to next entry
294         _read_n_chars_from_file(file, count_all - 1);
295         if(eof_reached)
296                 _streamGet(file);
297 }
298
299 //____________________________________________________________________________
300
301 template <typename TFile, typename TData>
302 void
303 read(TFile & file,
304          TData & data,
305          Fasta tag)
306 {
307 SEQAN_CHECKPOINT
308         typedef typename Size<TData>::Type TSize;
309         read(file, data, supremumValue<TSize>(), tag);
310 }
311
312
313 //////////////////////////////////////////////////////////////////////////////
314 // readID
315 //////////////////////////////////////////////////////////////////////////////
316  
317 //the ID is the complete first line (without the leading '>'-sign)
318
319 template <typename TFile, typename TString>
320 void
321 readID(TFile & file,
322            TString & id,
323            Fasta)
324 {
325 SEQAN_CHECKPOINT
326         SEQAN_ASSERT(!_streamEOF(file))
327
328         typename Position<TFile>::Type start_pos = _streamTellG(file);
329
330         typename Value<TFile>::Type c = _streamGet(file);
331         if (c != '>')
332         {
333                 clear(id);
334         }
335         else
336         {
337                 typename Size<TString>::Type count_valid = 0;
338                 typename Size<TString>::Type count_all = 0;
339                 _fasta_scan_line(file, count_valid, count_all);
340
341                 if (! count_valid)
342                 {
343                         clear(id);
344                 }
345                 else
346                 {
347                         resize(id, count_valid);
348                         if (length(id) < count_valid)
349                         {
350                                 count_valid = length(id);
351                         }
352
353                         _streamSeekG(file, start_pos);
354                         c = _streamGet(file); //pop the '>' character
355                         for (typename Position<TString>::Type pos = 0; count_valid; --count_valid)
356                         {
357                                 id[pos] = _streamGet(file);
358                                 ++pos;
359                         }
360                 }
361         }
362         _streamSeekG(file, start_pos);
363 }
364
365 //////////////////////////////////////////////////////////////////////////////
366 // readMeta
367 //////////////////////////////////////////////////////////////////////////////
368
369 //Fasta file records have no meta data
370
371 template <typename TFile, typename TMeta>
372 void
373 readMeta(TFile & file,
374                  TMeta & meta,
375                  Fasta)
376 {
377 SEQAN_CHECKPOINT
378         readID(file, meta, Fasta());
379 }
380
381
382 //////////////////////////////////////////////////////////////////////////////
383 // goNext
384 //////////////////////////////////////////////////////////////////////////////
385
386 template <typename TFile>
387 void
388 goNext(TFile & file,
389            Fasta)
390 {
391 SEQAN_CHECKPOINT
392         SEQAN_ASSERT(!_streamEOF(file))
393
394         bool found_data = false;
395         while (true)
396         {
397                 typename Value<TFile>::Type c = _streamGet(file);
398
399                 if (_streamEOF(file)) return;
400
401                 if (c == '\n' || c == '\r')
402                 {
403                         do {
404                                 c = _streamGet(file);
405                                 if (_streamEOF(file)) return;
406                         } while (c == '\n' || c == '\r');
407
408                         if (c != '>')
409                         {
410                                 found_data = true;
411                         }
412                         else if (found_data)
413                         {
414                                 _streamUnget(file);
415                                 return;
416                         }
417                 }
418         }
419 }
420
421
422
423 //////////////////////////////////////////////////////////////////////////////
424 // write
425 //////////////////////////////////////////////////////////////////////////////
426
427
428 template <typename TFile, typename TString, typename TData>
429 void
430 _write_impl(TFile & file,
431                         TData & data,
432                         TString & id,
433                         Fasta)
434 {
435 SEQAN_CHECKPOINT
436         _streamPut(file, '>');
437         _streamWrite(file, id);
438         _streamPut(file, '\n');
439
440         //typename Iterator<TData, Standard>::Type it = begin(data, Standard());
441         //typename Iterator<TData, Standard>::Type it_end = end(data, Standard());
442         typename Iterator<TData>::Type it = begin(data);
443         typename Iterator<TData>::Type it_end = end(data);
444
445         int i = 0;
446
447         for (; it < it_end; ++it)
448         {
449                 if (i == 60)
450                 {
451                         _streamPut(file, '\n');
452                         i = 0;
453                 }
454                 ++i;
455
456                 _streamPut(file, *it);
457         }
458         _streamPut(file, '\n');
459 }
460
461 //____________________________________________________________________________
462
463 template <typename TFile, typename TString, typename TData, typename TMeta>
464 void
465 write(TFile & file,
466           TData & data,
467           Fasta)
468 {
469 SEQAN_CHECKPOINT
470         _write_impl(file, data, "", Fasta());
471 }
472
473 //____________________________________________________________________________
474
475 template <typename TFile, typename TString, typename TData>
476 void
477 write(TFile & file,
478           TData & data,
479           TString & id,
480           Fasta)
481 {
482 SEQAN_CHECKPOINT
483         _write_impl(file, data, id, Fasta());
484 }
485
486
487 //VisualC++ const array bug workaround
488 template <typename TFile, typename TString, typename TDataValue>
489 void
490 write(TFile & file,
491           TDataValue * data,
492           TString & id,
493           Fasta)
494 {
495 SEQAN_CHECKPOINT
496         _write_impl(file, data, id, Fasta());
497
498 }
499
500 //____________________________________________________________________________
501
502 template <typename TFile, typename TString, typename TData, typename TMeta>
503 void
504 write(TFile & file,
505           TData & data,
506           TString & id,
507           TMeta &,
508           Fasta)
509 {
510 SEQAN_CHECKPOINT
511         _write_impl(file, data, id, Fasta());
512 }
513
514
515 //////////////////////////////////////////////////////////////////////////////
516 } //namespace SEQAN_NAMESPACE_MAIN
517
518 //////////////////////////////////////////////////////////////////////////////
519
520 #endif //#ifndef SEQAN_HEADER_...