Imported Upstream version 0.12.7
[bowtie.git] / SeqAn-1.1 / seqan / file / file_base.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_base.h,v 1.2 2009/02/19 01:51:23 langmead Exp $
19  ==========================================================================*/
20
21 #ifndef SEQAN_HEADER_FILE_BASE_H
22 #define SEQAN_HEADER_FILE_BASE_H
23
24
25 //////////////////////////////////////////////////////////////////////////////
26
27 namespace SEQAN_NAMESPACE_MAIN
28 {
29
30         // To override the system's default temporary directory use the following:
31         //#define SEQAN_DEFAULT_TMPDIR "/var/tmp"
32
33         // To use direct I/O access define SEQAN_DIRECTIO (not completely tested yet)
34         //#define SEQAN_DIRECTIO
35
36
37 /**
38 .Spec.Sync:
39 ..cat:Files
40 ..general:Class.File
41 ..summary:File structure supporting synchronous input/output access.
42 ..signature:File<Sync<> >
43 ..remarks:This class suports pseudo-asynchronous access methods, i.e. the methods to initiate a I/O request return after request completion.
44 */
45
46         template <typename TSpec = void>
47     struct Sync;
48
49 /**
50 .Spec.Async:
51 ..cat:Files
52 ..general:Class.File
53 ..summary:File structure supporting synchronous and asynchronous input/output access.
54 ..signature:File<Async<> >
55 */
56
57         template <typename TSpec = void>
58     struct Async;
59
60
61 /**
62 .Class.File:
63 ..cat:Input/Output
64 ..summary:Represents a file.
65 ..signature:File<TSpec>
66 ..param.TSpec:The specializing type.
67 ...default:$Async<>$, see @Spec.Async@.
68 */
69
70         template <typename TSpec = Async<> >
71     class File;
72
73 /**
74 .Spec.Chained:
75 ..cat:Files
76 ..general:Class.File
77 ..summary:Splits a large file into a chain of smaller files.
78 ..signature:File<Chained<FileSize, TFile> >
79 ..param.FileSize:The maximal split file size in byte.
80 ...default:2^31-1 (~2GB)
81 ..param.TFile:Underlying @Class.File@ type.
82 ...default:$File<>$, see @Class.File@.
83 ..remarks:This file type uses a chain of $TFile$ files, whose file sizes are at most $FileSize$ bytes.
84 Chained Files should be used for file systems or $TFile$ types that don't support large files (e.g. FAT32, C-style FILE*).
85 ..remarks:The chain can be used as if it were one contiguous file.
86 */
87
88         // chained file's default filesize is 2gb-1byte (fat16 filesize limitation)
89         template < __int64 _FileSize = ~(((__int64)1) << 63), typename TFile = File<> >
90         struct Chained;
91
92 /**
93 .Spec.Striped:
94 ..cat:Files
95 ..general:Class.File
96 ..summary:Stripes a file across multiple files.
97 ..signature:File<Chained<FileCount, TFile> >
98 ..param.FileCount:The number of files used for striping.
99 ...default:2
100 ..param.TFile:Underlying @Class.File@ type.
101 ...default:$File<>$, see @Class.File@.
102 ..remarks:This file type uses a software striping without redundance (see RAID0) to accelerate I/O access when using more than one disks.
103 ..remarks:Striped files should only be used in @Class.Pool@s or external Strings as they only support block operations and no random accesses.
104 */
105
106         template < unsigned _FileCount = 2, typename TFile = File<> >
107         struct Striped;
108
109     enum FileOpenMode {
110         OPEN_RDONLY     = 1,
111         OPEN_WRONLY     = 2,
112         OPEN_RDWR       = 3,
113         OPEN_MASK       = 3,
114         OPEN_CREATE     = 4,
115         OPEN_APPEND     = 8,
116         OPEN_ASYNC      = 16,
117                 OPEN_TEMPORARY  = 32,
118                 OPEN_QUIET              = 128
119     };
120
121         template <typename T>
122         struct DefaultOpenMode {
123                 enum { VALUE = (OPEN_RDWR + OPEN_CREATE) | OPEN_APPEND };
124         };
125
126         template <typename T>
127         struct DefaultOpenTempMode {
128                 enum { VALUE = OPEN_RDWR + OPEN_CREATE };
129         };
130
131     enum FileSeekMode {
132         SEEK_BEGIN   = 0,
133         SEEK_CURRENT = 1
134 #ifndef SEEK_END
135       , SEEK_END     = 2
136 #endif
137     };
138
139
140     //////////////////////////////////////////////////////////////////////////////
141     // result type of asynch. functions
142     // you have to call release(aRequest<T>) after a finished *event based* transfer
143         struct aDummyRequest {};
144
145 /**
146 .Class.aRequest:
147 ..cat:Input/Output
148 ..summary:Associated with an asynchronous I/O request.
149 ..signature:aRequest<TFile>
150 ..param.TFile:A File type.
151 ..remarks:This structure is used to identify asynchronous requests after their initiation.
152 */
153
154     template < typename T >
155     struct aRequest
156     {
157         typedef aDummyRequest Type;
158     };
159 /*
160     //////////////////////////////////////////////////////////////////////////////
161     // event to represent asynchronous transfers
162     // you can wait for it or test it
163     template < typename T >
164     struct aEvent
165     {
166         typedef DummyEvent Type;
167     };
168
169     ////////////////////////////////////////////////////////////////////////////////
170     // callback hint parameter type
171     // hint lets you recognize the finished asynch. transfer in your own callback routine
172     template < typename T >
173     struct aHint
174     {
175         typedef void Type;
176     };
177
178     //////////////////////////////////////////////////////////////////////////////
179     // callback function interface
180     template < typename T >
181     struct aCallback
182     {
183         typedef void Type(aHint<T> *);
184     };
185
186     //////////////////////////////////////////////////////////////////////////////
187     // file queue interface
188     template < typename T >
189     struct aQueue
190     {
191         typedef Nothing Type;
192     };
193 */
194
195     //////////////////////////////////////////////////////////////////////////////
196     // generic open/close interface
197
198 /**
199 .Function.open:
200 ..summary:Opens a file.
201 ..cat:Input/Output
202 ..signature:open(file, fileName[, openMode])
203 ..param.file:A File object.
204 ...type:Class.File
205 ..param.fileName:C-style character string containing the file name.
206 ..param.openMode:The combination of flags defining how the file should be opened.
207 ...remarks:To open a file read-only, write-only or to read and write use $OPEN_RDONLY$, $OPEN_WRONLY$, or $OPEN_RDWR$.
208 ...remarks:To create or overwrite a file add $OPEN_CREATE$.
209 ...remarks:To append a file if existing add $OPEN_APPEND$.
210 ...default:$OPEN_RDWR | OPEN_CREATE | OPEN_APPEND$
211 ..returns:A $bool$ which is $true$ on success.
212 */
213
214     template < typename TSpec >
215     inline bool open(File<TSpec> &me, const char *fileName, int openMode) {
216         return me.open(fileName, openMode);
217     }
218
219     template < typename TSpec >
220     inline bool open(File<TSpec> &me, const char *fileName) {
221                 return open(me, fileName, DefaultOpenMode<File<TSpec> >::VALUE);
222     }
223
224 /**
225 .Function.openTemp:
226 ..summary:Opens a temporary file.
227 ..cat:Input/Output
228 ..signature:openTemp(file)
229 ..param.file:A File object.
230 ...type:Class.File
231 ..remarks:After closing this file will automatically be deleted.
232 ..remarks:The openmode (see @Function.open@) is $OPEN_RDWR | OPEN_CREATE$.
233 ..returns:A $bool$ which is $true$ on success.
234 */
235
236     template < typename TSpec >
237     inline bool openTemp(File<TSpec> &me) {
238         return me.openTemp();
239     }
240
241     template < typename TSpec >
242     inline bool openTemp(File<TSpec> &me, int openMode) {
243         return me.openTemp(openMode);
244     }
245
246     template < typename File >
247     inline void reopen(File &, int) {
248         }
249
250 /**
251 .Function.close:
252 ..cat:Input/Output
253 ..summary:Closes a file.
254 ..signature:close(file)
255 ..param.file:A File object.
256 ...type:Class.File
257 ..returns:A $bool$ which is $true$ on success.
258 */
259
260     template < typename TSpec >
261     inline bool close(File<TSpec> & me) {
262         return me.close();
263     }
264
265     template < typename TSpec >
266     inline unsigned sectorSize(File<TSpec> const & /*me*/) {
267         return 4096;
268     }
269
270
271     //////////////////////////////////////////////////////////////////////////////
272     // generic read(At)/write(At) interface
273
274 /**
275 .Function.read:
276 ..cat:Input/Output
277 ..summary:Loads records from a file.
278 ..signature:read(file, memPtr, count)
279 ..param.file:A File object.
280 ...type:Class.File
281 ..param.memPtr:A pointer to the first destination record in memory.
282 ..param.count:The amount of records to be read.
283 ..returns:A $bool$ which is $true$ on success.
284 ..remarks:The records are read from the position pointed by the current file pointer (see @Function.seek@).
285 */
286
287         template < typename TSpec, typename TValue, typename TSize >
288     inline bool read(File<TSpec> & me, TValue *memPtr, TSize const count) {
289                 return me.read(memPtr, count * sizeof(TValue));
290     }
291
292 /**
293 .Function.write:
294 ..cat:Input/Output
295 ..summary:Saves records to a file.
296 ..signature:write(file, memPtr, count)
297 ..param.file:A File object.
298 ...type:Class.File
299 ..param.memPtr:A pointer to the first source record in memory.
300 ..param.count:The amount of records to be written.
301 ..returns:A $bool$ which is $true$ on success.
302 ..remarks:The records are written at the position pointed by the current file pointer (see @Function.seek@).
303 */
304
305         template < typename TSpec, typename TValue, typename TSize >
306     inline bool write(File<TSpec> & me, TValue const *memPtr, TSize const count) {
307                 return me.write(memPtr, count * sizeof(TValue));
308     }
309
310 /**
311 .Function.readAt:
312 ..summary:Loads records from a specific position in a file.
313 ..cat:Input/Output
314 ..signature:readAt(file, memPtr, count, fileOfs)
315 ..param.file:A File object.
316 ...type:Class.File
317 ..param.memPtr:A pointer to the first destination record in memory.
318 ..param.count:The amount of records to be read.
319 ..param.fileOfs:The absolute file position in bytes measured from the beginning.
320 ..returns:A $bool$ which is $true$ on success.
321 */
322
323     template < typename TFile, typename TValue, typename TSize, typename TPos >
324     inline bool readAt(TFile & me, TValue *memPtr, TSize const count, TPos const fileOfs) {
325                 typedef typename Position<TFile>::Type pos_t;
326                 seek(me, (pos_t)fileOfs * (pos_t)sizeof(TValue));
327                 return read(me, memPtr, count);
328     }
329
330 /**
331 .Function.writeAt:
332 ..summary:Saves records to a specific position in a file.
333 ..cat:Input/Output
334 ..signature:writeAt(file, memPtr, count, fileOfs)
335 ..param.file:A File object.
336 ...type:Class.File
337 ..param.memPtr:A pointer to the first source record in memory.
338 ..param.count:The amount of records to be written.
339 ..param.fileOfs:The absolute file position in bytes measured from the beginning.
340 ..returns:A $bool$ which is $true$ on success.
341 */
342
343     template < typename TFile, typename TValue, typename TSize, typename TPos >
344     inline bool writeAt(TFile & me, TValue const *memPtr, TSize const count, TPos const fileOfs) {
345                 typedef typename Position<TFile>::Type pos_t;
346                 seek(me, (pos_t)fileOfs * (pos_t)sizeof(TValue));
347                 return write(me, memPtr, count);
348     }
349
350
351
352     //////////////////////////////////////////////////////////////////////////////
353     // generic seek/tell/size/resize interface
354
355 /**
356 .Function.seek:
357 ..summary:Changes the current file pointer.
358 ..cat:Input/Output
359 ..signature:seek(file, fileOfs[, origin])
360 ..param.file:A File object.
361 ...type:Class.File
362 ..param.fileOfs:A file offset measured in bytes relative to $origin$.
363 ..param.origin:Selects the origin from where to calculate the new position.
364 ...default:$SEEK_BEGIN$
365 ...remarks:For $SEEK_BEGIN$, $SEEK_CURRENT$, or $SEEK_END$ the origin is the beginning, the current pointer, or the end of the file.
366 ..returns:The new file position measured in bytes from the beginning.
367 */
368
369         template < typename TSpec, typename TPos >
370     inline typename Position< File<TSpec> >::Type seek(File<TSpec> &me, TPos const fileOfs, int origin) {
371                 typedef typename Position< File<TSpec> >::Type TFilePos;
372                 TFilePos newOfs = me.seek(fileOfs, origin);
373         #ifdef SEQAN_DEBUG_OR_TEST_
374                         if (origin == SEEK_BEGIN && newOfs != (TFilePos)fileOfs) {
375                                 ::std::cerr << "seek returned " << ::std::hex << newOfs << " instead of " << fileOfs << ::std::dec << ::std::endl;
376                         }
377         #endif
378         return newOfs;
379     }
380
381         template < typename TSpec, typename TPos >
382     inline typename Position< File<TSpec> >::Type seek(File<TSpec> &me, TPos const fileOfs) {
383                 return seek(me, fileOfs, SEEK_BEGIN);
384         }
385 /**
386 .Function.tell:
387 ..summary:Gets the current file pointer.
388 ..cat:Input/Output
389 ..signature:tell(file)
390 ..param.file:A File object.
391 ...type:Class.File
392 ..returns:The current file position measured in bytes from the beginning.
393 */
394
395     template < typename TSpec >
396     inline typename Position< File<TSpec> >::Type tell(File<TSpec> &me) {
397         return me.tell();
398     }
399
400 /**
401 .Function.rewind:
402 ..summary:Sets the current file pointer to the beginning.
403 ..cat:Input/Output
404 ..signature:rewind(file)
405 ..param.file:A File object.
406 ...type:Class.File
407 ..remarks:Calls @Function.seek@$(file, 0)$ by default.
408 */
409
410     template < typename File >
411     inline void rewind(File &me) {
412                 seek(me, 0);
413     }
414
415 /**
416 .Function.size:
417 ..summary:Gets the file size.
418 ..cat:Input/Output
419 ..signature:size(file)
420 ..param.file:A File object.
421 ...type:Class.File
422 ..returns:The file size measured in bytes.
423 */
424
425     template < typename TSpec >
426     inline typename Size<File<TSpec> >::Type size(File<TSpec> &me) {
427         typename Size<File<TSpec> >::Type old_pos = tell(me);
428         typename Size<File<TSpec> >::Type result = seek(me, 0, SEEK_END);
429         seek(me, old_pos, SEEK_BEGIN);
430         return result;
431     }
432
433 /**
434 .Function.resize:
435 ..cat:Input/Output
436 ..signature:resize(file, new_length)
437 ..param.file:A File object.
438 ...type:Class.File
439 ..param.new_length:The new file size measured in bytes.
440 */
441
442     template < typename TSpec, typename TSize >
443     inline void resize(File<TSpec> &me, TSize new_length) {
444         typename Size<File<TSpec> >::Type old_pos = tell(me);
445         seek(me, new_length, SEEK_BEGIN);
446         setEOF(me);
447         seek(me, old_pos, SEEK_BEGIN);
448     }
449
450 /**
451 .Function.setEOF:
452 ..summary:Sets the file end to the current pointer.
453 ..cat:Input/Output
454 ..signature:setEOF(file)
455 ..param.file:A File object.
456 ...type:Class.File
457 */
458
459     template < typename TSpec >
460     inline bool setEOF(File<TSpec> &/*me*/) {
461                 return true;
462         }
463
464
465     //////////////////////////////////////////////////////////////////////
466     // Pseudo asynchronous Methods
467     //////////////////////////////////////////////////////////////////////
468
469     //////////////////////////////////////////////////////////////////////
470     // callback based read/write
471 /*
472     template < typename File, typename TValue, typename TSize,
473                typename aCallback, typename aHint >
474     inline typename aRequest<File>::Type
475     aread(File & me, TValue *memPtr, TSize const count,
476         aCallback* cb, aHint* hint)
477     {
478         result = read(me, memPtr, count);
479         cb(hint);
480         return NULL;
481     }
482
483     template < typename File, typename TValue, typename TSize,
484                typename aCallback, typename aHint >
485     inline typename aRequest<File>::Type
486     awrite(File & me, TValue const *memPtr, TSize const count,
487         aCallback* cb, aHint* hint)
488     {
489         write(me, memPtr, count);
490         cb(hint);
491         return NULL;
492     }
493
494     template < typename File, typename TValue, typename TSize, typename TPos,
495                typename aCallback, typename aHint >
496     inline typename aRequest<File>::Type
497     areadAt(File & me, TValue *memPtr, TSize const count, TPos const fileOfs,
498         aCallback* cb, aHint* hint)
499     {
500         readAt(me, memPtr, count, fileOfs);
501         cb(hint);
502         return NULL;
503     }
504
505     template < typename File, typename TValue, typename TSize, typename TPos,
506                typename aCallback, typename aHint >
507     inline typename aRequest<File>::Type
508     awriteAt(File & me, TValue const *memPtr, TSize const count, TPos const fileOfs,
509         aCallback* cb, aHint* hint)
510     {
511         result = writeAt(me, memPtr, count, fileOfs);
512         cb(hint);
513         return NULL;
514     }
515
516
517     //////////////////////////////////////////////////////////////////////
518     // event based read/write
519
520     template < typename File, typename TValue, typename TSize,
521                typename aEvent >
522     inline typename aRequest<File>::Type
523     aread(File & me, TValue *memPtr, TSize const count,
524         aEvent &event)
525     {
526         read(me, memPtr, count);
527         event.signal();
528         return NULL;
529     }
530
531     template < typename File, typename TValue, typename TSize,
532                typename aEvent >
533     inline typename aRequest<File>::Type
534     awrite(File & me, TValue const *memPtr, TSize const count,
535         aEvent &event)
536     {
537         write(me, memPtr, count);
538         event.signal();
539         return NULL;
540     }
541
542     template < typename File, typename TValue, typename TSize, typename TPos,
543                typename aEvent >
544     inline typename aRequest<File>::Type
545     areadAt(File & me, TValue *memPtr, TSize const count, TPos const fileOfs,
546         aEvent &event)
547     {
548         readAt(me, memPtr, count, fileOfs);
549         event.signal();
550         return NULL;
551     }
552
553     template < typename File, typename TValue, typename TSize, typename TPos,
554                typename aEvent >
555     inline typename aRequest<File>::Type
556     awriteAt(File & me, TValue const *memPtr, TSize const count, TPos const fileOfs,
557         aEvent &event)
558     {
559         writeAt(me, memPtr, count, fileOfs);
560         event.signal();
561         return NULL;
562     }
563 */
564
565     //////////////////////////////////////////////////////////////////////
566     // queue-less request based pseudo asychronous read/write
567
568 /**
569 .Function.areadAt:
570 ..summary:Asynchronously loads records from a specific position in a file.
571 ..cat:Input/Output
572 ..signature:areadAt(file, memPtr, count, fileOfs, request)
573 ..param.file:A File object.
574 ...type:Class.File
575 ..param.memPtr:A pointer to the first destination record in memory.
576 ..param.count:The amount of records to be read.
577 ..param.fileOfs:The absolute file position in bytes measured from the beginning.
578 ..param.request:Reference to a structure that will be associated with this asynchronous request.
579 ...type:Class.aRequest
580 ..returns:A $bool$ which is $true$ on success.
581 */
582
583     template < typename File, typename TValue, typename TSize, typename TPos,
584                typename aRequest >
585     inline bool
586         areadAt(File & me, TValue *memPtr, TSize const count, TPos const fileOfs,
587         aRequest &request)
588     {
589         return readAt(me, memPtr, count, fileOfs);
590     }
591
592 /**
593 .Function.awriteAt:
594 ..summary:Asynchronously saves records to a specific position in a file.
595 ..cat:Input/Output
596 ..signature:awriteAt(file, memPtr, count, fileOfs, request)
597 ..param.file:A File object.
598 ...type:Class.File
599 ..param.memPtr:A pointer to the first source record in memory.
600 ..param.count:The amount of records to be written.
601 ..param.fileOfs:The absolute file position in bytes measured from the beginning.
602 ..param.request:Reference to a structure that will be associated with this asynchronous request.
603 ...type:Class.aRequest
604 ..returns:A $bool$ which is $true$ on success.
605 */
606
607     template < typename File, typename TValue, typename TSize, typename TPos,
608                typename aRequest >
609     inline bool
610         awriteAt(File & me, TValue const *memPtr, TSize const count, TPos const fileOfs,
611         aRequest &request)
612     {
613         return writeAt(me, memPtr, count, fileOfs);
614     }
615
616
617         //////////////////////////////////////////////////////////////////////
618     // pseudo queue specific functions
619
620 /**
621 .Function.flush:
622 ..summary:Waits for all open requests to complete.
623 ..cat:Input/Output
624 ..signature:flush(file)
625 ..param.file:A File object.
626 ...type:Class.File
627 ..remarks:$flush$ returns after all pending requests are completed.
628 */
629
630     template < typename TSpec >
631     inline void flush(File<TSpec> &) {
632         }
633
634 /**
635 .Function.waitFor:
636 ..summary:Waits for an asynchronous request to complete.
637 ..cat:Input/Output
638 ..signature:waitFor(request[, timeout_millis])
639 ..param.request:Reference to an aRequest object.
640 ...type:Class.aRequest
641 ..param.timeout_millis:Timout value in milliseconds.
642 ...remarks:A value of 0 can be used to test for completion without waiting.
643 ...default:Infinity.
644 ..returns:A $bool$ which is $true$ on completion and $false$ on timeout.
645 ..remarks:$waitFor$ suspends the calling process until $request$ is completed or after $timeout_millis$ milliseconds.
646 */
647
648     inline bool waitFor(aDummyRequest &) {
649                 return true;
650         }
651
652         template < typename TTime >
653     inline bool waitFor(aDummyRequest &, TTime) {
654                 return true;
655         }
656
657         // deprecated
658         template < typename TSpec, typename aRequest >
659     inline void release(File<TSpec> &, aRequest &) {
660         }
661
662 /**
663 .Function.cancel:
664 ..summary:Cancels an asynchronous request.
665 ..cat:Input/Output
666 ..signature:cancel(file, request)
667 ..param.file:A File object.
668 ...type:Class.File
669 ..param.request:Reference to an aRequest object.
670 ...type:Class.aRequest
671 ..returns:A $bool$ which is $true$ on success.
672 */
673
674     template < typename TSpec, typename aRequest >
675     inline bool cancel(File<TSpec> &, aRequest &) {
676                 return true;
677         }
678
679
680         // little helpers
681
682         template <typename T1, typename T2> inline
683         T1 enclosingBlocks(T1 _size, T2 _blockSize) {
684                 return (_size + _blockSize - 1) / _blockSize;
685         }
686
687         template <typename T1, typename T2> inline
688         T1 alignSize(T1 _size, T2 _aligning) {
689         if (_size < _aligning)
690             return _aligning;
691         else
692                     return (_size / _aligning) * (T1)_aligning;
693         }
694
695 }
696
697 #endif