1 /*
2  *  Copyright (C) 2010  Regents of the University of Michigan
3  *
4  *   This program is free software: you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation, either version 3 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef __BGZFFILETYPE_H__
19 #define __BGZFFILETYPE_H__
20 
21 #ifdef __ZLIB_AVAILABLE__
22 
23 #include <stdexcept> // stdexcept header file
24 #include "bgzf.h"
25 #include "FileType.h"
26 
27 class BgzfFileType : public FileType
28 {
29 public:
BgzfFileType()30     BgzfFileType()
31     {
32         bgzfHandle = NULL;
33         myEOF = false;
34     }
35 
~BgzfFileType()36     virtual ~BgzfFileType()
37     {
38         bgzfHandle = NULL;
39     }
40 
41     BgzfFileType(const char * filename, const char * mode);
42 
43     virtual bool operator == (void * rhs)
44     {
45         // No two file pointers are the same, so if rhs is not NULL, then
46         // the two pointers are different (false).
47         if (rhs != NULL)
48             return false;
49         return (bgzfHandle == rhs);
50     }
51 
52     virtual bool operator != (void * rhs)
53     {
54         // No two file pointers are the same, so if rhs is not NULL, then
55         // the two pointers are different (true).
56         if (rhs != NULL)
57             return true;
58         return (bgzfHandle != rhs);
59     }
60 
61     // Close the file.
close()62     virtual inline int close()
63     {
64         int result = bgzf_close(bgzfHandle);
65         bgzfHandle = NULL;
66         return result;
67     }
68 
69 
70     // Reset to the beginning of the file.
rewind()71     virtual inline void rewind()
72     {
73         // Just call rewind to move to the beginning of the file.
74         seek(myStartPos, SEEK_SET);
75     }
76 
77     // Check to see if we have reached the EOF.
eof()78     virtual inline int eof()
79     {
80         //  check the file for eof.
81         return myEOF;
82     }
83 
84     // Check to see if the file is open.
isOpen()85     virtual inline bool isOpen()
86     {
87         if (bgzfHandle != NULL)
88         {
89             // bgzfHandle is not null, so the file is open.
90             return(true);
91         }
92         return(false);
93     }
94 
95     // Write to the file
write(const void * buffer,unsigned int size)96     virtual inline unsigned int write(const void * buffer, unsigned int size)
97     {
98         return bgzf_write(bgzfHandle, buffer, size);
99     }
100 
101     // Read into a buffer from the file.  Since the buffer is passed in and
102     // this would bypass the fileBuffer used by this class, this method must
103     // be protected.
read(void * buffer,unsigned int size)104     virtual inline int read(void * buffer, unsigned int size)
105     {
106         int bytesRead = bgzf_read(bgzfHandle, buffer, size);
107         if ((bytesRead == 0) && (size != 0))
108         {
109             myEOF = true;
110         }
111         else if((bytesRead != (int)size) & (bytesRead >= 0))
112         {
113             // Less then the requested size was read
114             // and an error was not returned (bgzf_read returns -1 on error).
115             myEOF = true;
116         }
117         else
118         {
119             myEOF = false;
120         }
121         return bytesRead;
122     }
123 
124 
125     // Get current position in the file.
126     // -1 return value indicates an error.
tell()127     virtual inline int64_t tell()
128     {
129         if(myUsingBuffer)
130         {
131             throw std::runtime_error("IFILE: CANNOT use buffered reads and tell for BGZF files");
132         }
133         return bgzf_tell(bgzfHandle);
134     }
135 
136 
137     // Seek to the specified offset from the origin.
138     // origin can be any of the following:
139     // Note: not all are valid for all filetypes.
140     //   SEEK_SET - Beginning of file
141     //   SEEK_CUR - Current position of the file pointer
142     //   SEEK_END - End of file
143     // Returns true on successful seek and false on a failed seek.
seek(int64_t offset,int origin)144     virtual inline bool seek(int64_t offset, int origin)
145     {
146         int64_t returnVal = bgzf_seek(bgzfHandle, offset, origin);
147         // Check for failure.
148         if (returnVal == -1)
149         {
150             return false;
151         }
152         // Successful.
153         // Reset EOF, assuming no longer at eof - first read will indicate
154         // eof if it is at the end.
155         myEOF = false;
156         return true;
157     }
158 
159     // Set whether or not to require the EOF block at the end of the
160     // file.  True - require the block.  False - do not require the block.
161     static void setRequireEofBlock(bool requireEofBlock);
162 
163 protected:
164     // A bgzfFile is used.
165     BGZF* bgzfHandle;
166 
167     // Flag indicating EOF since there isn't one on the handle.
168     bool myEOF;
169 
170     int64_t myStartPos;
171 
172     // Static variable to track whether or not to require the EOF Block
173     // at the end of the file.  If the block is required, but not on the file,
174     // the constructor fails to open the file.
175     static bool ourRequireEofBlock;
176 };
177 
178 #endif
179 #endif
180