libStatGen Software 1
GlfFile.cpp
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#include <stdexcept>
18#include <stdlib.h>
19#include "GlfFile.h"
20#include "GlfException.h"
21
22// Constructor, init variables.
24 : myFilePtr(NULL),
25 myEndMarker()
26{
27 resetFile();
28}
29
30
31// Constructor, init variables and open the specified file based on the
32// specified mode (READ/WRITE). Default is READ..
33GlfFile::GlfFile(const char* filename, OpenType mode)
34 : myFilePtr(NULL),
35 myEndMarker()
36{
37 resetFile();
38
39 bool openStatus = true;
40 if(mode == READ)
41 {
42 // open the file for read.
43 openStatus = openForRead(filename);
44 }
45 else
46 {
47 // open the file for write.
48 openStatus = openForWrite(filename);
49 }
50 if(!openStatus)
51 {
52 // Failed to open the file - print error and abort.
53 fprintf(stderr, "%s\n", getStatusMessage());
54 std::cerr << "FAILURE - EXITING!!!" << std::endl;
55 exit(-1);
56 }
57}
58
60{
61 resetFile();
62}
63
64
65// Open a glf file for reading with the specified filename.
66bool GlfFile::openForRead(const char * filename)
67{
68 // Reset for any previously operated on files.
69 resetFile();
70
71 myFilePtr = ifopen(filename, "rb");
72
73 if (myFilePtr == NULL)
74 {
75 std::string errorMessage = "Failed to Open ";
76 errorMessage += filename;
77 errorMessage += " for reading";
78 myStatus.setStatus(GlfStatus::FAIL_IO, errorMessage.c_str());
79 throw(GlfException(myStatus));
80 return(false);
81 }
82
83 myIsOpenForRead = true;
84 // Successfully opened the file.
85 myStatus = GlfStatus::SUCCESS;
86 return(true);
87}
88
89
90// Open a glf file for reading with the specified filename and read the
91// header into the specified header.
92bool GlfFile::openForRead(const char * filename, GlfHeader& header)
93{
94 if(!openForRead(filename))
95 {
96 return(false);
97 }
98
99 // Read the header
100 if(!readHeader(header))
101 {
102 return(false);
103 }
104 return(true);
105}
106
107
108// Open a glf file for writing with the specified filename.
109bool GlfFile::openForWrite(const char * filename, bool compressed)
110{
111 // Reset for any previously operated on files.
112 resetFile();
113
114 if(compressed)
115 {
116 myFilePtr = ifopen(filename, "wb", InputFile::BGZF);
117 }
118 else
119 {
120 myFilePtr = ifopen(filename, "wb", InputFile::UNCOMPRESSED);
121 }
122
123 if (myFilePtr == NULL)
124 {
125 std::string errorMessage = "Failed to Open ";
126 errorMessage += filename;
127 errorMessage += " for writing";
128 myStatus.setStatus(GlfStatus::FAIL_IO, errorMessage.c_str());
129 throw(GlfException(myStatus));
130 return(false);
131 }
132
133 myIsOpenForWrite = true;
134
135 // Successfully opened the file.
136 myStatus = GlfStatus::SUCCESS;
137 return(true);
138}
139
140
141// Close the file if there is one open.
143{
144 // Resetting the file will close it if it is open, and
145 // will reset all other variables.
146 resetFile();
147}
148
149
150// Returns whether or not the end of the file has been reached.
151// return: int - true = EOF; false = not eof.
153{
154 if (myFilePtr != NULL)
155 {
156 // File Pointer is set, so return if eof.
157 return(ifeof(myFilePtr));
158 }
159 // File pointer is not set, so return true, eof.
160 return true;
161}
162
163
164// Read the header from the currently opened file.
166{
167 if(myIsOpenForRead == false)
168 {
169 // File is not open for read
171 "Cannot read header since the file is not open for reading");
172 throw(GlfException(myStatus));
173 return(false);
174 }
175
176 if(myNextSection != HEADER)
177 {
178 // The header has already been read.
180 "Cannot read header since it has already been read.");
181 throw(GlfException(myStatus));
182 return(false);
183 }
184
185 if(header.read(myFilePtr))
186 {
187 // The header has now been successfully read.
188 myNextSection = REF_SECTION;
189 myStatus = GlfStatus::SUCCESS;
190 return(true);
191 }
193 "Failed to read the header.");
194 throw(GlfException(myStatus));
195 return(false);
196}
197
198
199// Write the header to the currently opened file.
201{
202 if(myIsOpenForWrite == false)
203 {
204 // File is not open for write
205 // -OR-
206 // The header has already been written.
208 "Cannot write header since the file is not open for writing");
209 throw(GlfException(myStatus));
210 return(false);
211 }
212
213 if(myNextSection != HEADER)
214 {
215 // The header has already been written.
217 "Cannot write header since it has already been written");
218 throw(GlfException(myStatus));
219 return(false);
220 }
221
222 if(header.write(myFilePtr))
223 {
224 // The header has now been successfully written.
225 myNextSection = REF_SECTION;
226 myStatus = GlfStatus::SUCCESS;
227 return(true);
228 }
229
230 // return the status.
232 "Failed to write the header.");
233 throw(GlfException(myStatus));
234 return(false);
235}
236
237
238// Gets the next reference section from the file & stores it in the
239// passed in section. It will read until a new section is found.
241{
242 if(myIsOpenForRead == false)
243 {
244 // File is not open for read
246 "Cannot read reference section since the file is not open for reading");
247 throw(GlfException(myStatus));
248 return(false);
249 }
250
251 if(myNextSection == HEADER)
252 {
253 // The header has not yet been read.
254 // TODO - maybe just read the header.
256 "Cannot read reference section since the header has not been read.");
257 throw(GlfException(myStatus));
258 return(false);
259 }
260
261 // Keep reading until the next section is found.
262 if(myNextSection == RECORD)
263 {
264 GlfRecord record;
265 while(getNextRecord(record))
266 {
267 // Nothing to do, with the record.
268 }
269 }
270
271 // Check for end of file. If end of file, return false.
272 if(isEOF())
273 {
274 return(false);
275 }
276
277 if(myNextSection != REF_SECTION)
278 {
279 // Failed reading all the records, so throw exception.
281 "Failed to get to a reference section.");
282 throw(GlfException(myStatus));
283 return(false);
284 }
285
286 // Ready to read the section:
287 if(refSection.read(myFilePtr))
288 {
289 myStatus = GlfStatus::SUCCESS;
290 // Next a record should be read.
291 myNextSection = RECORD;
292 return(true);
293 }
294
295 // If it is the EOF, just return false.
296 if(isEOF())
297 {
298 return(false);
299 }
301 "Failed reading a reference section from the file.");
302 throw(GlfException(myStatus));
303 return(false);
304}
305
306
307// Write the reference section to the file.
309{
310 if(myIsOpenForWrite == false)
311 {
312 // File is not open for write
314 "Cannot write reference section since the file is not open for writing");
315 throw(GlfException(myStatus));
316 return(false);
317 }
318
319 if(myNextSection == HEADER)
320 {
321 // The header has not been written.
323 "Cannot write reference section since the header has not been written");
324 throw(GlfException(myStatus));
325 return(false);
326 }
327
328 if(myNextSection == RECORD)
329 {
330 // did not write a end marker record, so write one now.
331 if(!writeRecord(myEndMarker))
332 {
333 // Failed to write the end marker record.
335 "Failed to write end of chromosome/section marker.");
336 throw(GlfException(myStatus));
337 return(false);
338 }
339 }
340
341 if(myNextSection != REF_SECTION)
342 {
343 // Not ready to write a reference section.
345 "Not ready for a chromosome/section header.");
346 throw(GlfException(myStatus));
347 return(false);
348 }
349
350 if(refSection.write(myFilePtr))
351 {
352 myStatus = GlfStatus::SUCCESS;
353 // A reference section has now been successfully written.
354 myNextSection = RECORD;
355 return(true);
356 }
357
358 // return the status.
360 "Failed writing a reference section to the file.");
361 throw(GlfException(myStatus));
362 return(false);
363}
364
365
366// Gets the next reference section from the file & stores it in the
367// passed in record.
369{
370 if(myIsOpenForRead == false)
371 {
372 // File is not open for read
374 "Cannot read reference section since the file is not open for reading");
375 throw(GlfException(myStatus));
376 return(false);
377 }
378
379 if(myNextSection == HEADER)
380 {
381 // The header has not yet been read.
383 "Cannot read reference section since the header has not been read.");
384 throw(GlfException(myStatus));
385 return(false);
386 }
387
388 if(myNextSection == REF_SECTION)
389 {
390 // The reference section has not yet been read.
391 // TODO - maybe just read the reference section.
393 "Cannot read record since a reference section has not been read.");
394 throw(GlfException(myStatus));
395 return(false);
396 }
397
398 // Check for end of file. If end of file, return false.
399 if(isEOF())
400 {
401 return(false);
402 }
403
404 // Read the record.
405 if(record.read(myFilePtr))
406 {
407 myStatus = GlfStatus::SUCCESS;
408 if(record.getRecordType() != 0)
409 {
410 return(true);
411 }
412 else
413 {
414 // Not an error, so no exception thrown, but no more records.
415 // The next thing is a reference section.
416 myNextSection = REF_SECTION;
417 return(false);
418 }
419 }
420
422 "Failed reading a record from the file.");
423 throw(GlfException(myStatus));
424 return(false);
425}
426
427
428// Write the reference section to the file.
430{
431 if(myIsOpenForWrite == false)
432 {
433 // File is not open for write
434 // -OR-
435 // The header has already been written.
437 "Cannot write record since the file is not open for writing");
438 throw(GlfException(myStatus));
439 return(false);
440 }
441
442 if(myNextSection == HEADER)
443 {
444 // The header has not been written.
446 "Cannot write record since the header has not been written");
447 throw(GlfException(myStatus));
448 return(false);
449 }
450
451 if(myNextSection != RECORD)
452 {
453 // The header has not been written.
455 "Cannot write record since a reference section has not been written");
456 throw(GlfException(myStatus));
457 return(false);
458 }
459
460 if(record.write(myFilePtr))
461 {
462 myStatus = GlfStatus::SUCCESS;
463 // The record has now been successfully written.
464
465 // Check if it was the end marker - if so, set that next a
466 // reference section is expected.
467 if(record.getRecordType() == 0)
468 {
469 myNextSection = REF_SECTION;
470 }
471 return(true);
472 }
473
474 // return the status.
476 "Failed writing a record to the file.");
477 throw(GlfException(myStatus));
478 return(false);
479}
480
481
482// Return the number of records that have been read/written so far.
484{
485 return(myRecordCount);
486}
487
488
489// Reset variables for each file.
490void GlfFile::resetFile()
491{
492 // Close the file.
493 if (myFilePtr != NULL)
494 {
495 // If we already have an open file, close it.
496
497 // First check if this is a write file and an end record needs to
498 // be written, which is the case if the state is RECORD.
499 if(myIsOpenForWrite && (myNextSection == RECORD))
500 {
501 if(!writeRecord(myEndMarker))
502 {
503 // Failed to write the end marker record.
505 "Failed to write end of chromosome/section marker.");
506 throw(GlfException(myStatus));
507 }
508 }
509 ifclose(myFilePtr);
510 myFilePtr = NULL;
511 }
512
513 myIsOpenForRead = false;
514 myIsOpenForWrite = false;
515 myRecordCount = 0;
516 myStatus = GlfStatus::SUCCESS;
517 myNextSection = HEADER;
518}
519
520
521// Default Constructor.
523{
524}
525
526
527// Constructor that opens the specified file for read.
528GlfFileReader::GlfFileReader(const char* filename)
529{
530 if(!openForRead(filename))
531 {
532 // Failed to open for reading - print error and abort.
533 fprintf(stderr, "%s\n", getStatusMessage());
534 std::cerr << "FAILURE - EXITING!!!" << std::endl;
535 exit(-1);
536 }
537}
538
539
540GlfFileReader::~GlfFileReader()
541{
542}
543
544
545// Default Constructor.
547{
548}
549
550
551// Constructor that opens the specified file for write.
552GlfFileWriter::GlfFileWriter(const char* filename)
553{
554 if(!openForWrite(filename))
555 {
556 // Failed to open for reading - print error and abort.
557 fprintf(stderr, "%s\n", getStatusMessage());
558 std::cerr << "FAILURE - EXITING!!!" << std::endl;
559 exit(-1);
560 }
561}
562
563
564GlfFileWriter::~GlfFileWriter()
565{
566}
int ifeof(IFILE file)
Check to see if we have reached the EOF (returns 0 if not EOF).
Definition: InputFile.h:654
IFILE ifopen(const char *filename, const char *mode, InputFile::ifileCompression compressionMode=InputFile::DEFAULT)
Open a file with the specified name and mode, using a filename of "-" to indicate stdin/stdout.
Definition: InputFile.h:562
int ifclose(IFILE &file)
Close the file.
Definition: InputFile.h:580
GlfException objects should be thrown by functions that operate on Glf files for exceptions.
Definition: GlfException.h:28
GlfFileReader()
Default Constructor.
Definition: GlfFile.cpp:522
GlfFileWriter()
Default Constructor.
Definition: GlfFile.cpp:546
bool getNextRefSection(GlfRefSection &refSection)
Gets the next reference section from the file & stores it in the passed in section,...
Definition: GlfFile.cpp:240
virtual ~GlfFile()
Closes the file if there is one open, adding an end marker record if there is a previous section and ...
Definition: GlfFile.cpp:59
const char * getStatusMessage()
Get the Status of the last call that sets status.
Definition: GlfFile.h:135
bool writeRefSection(const GlfRefSection &refSection)
Write the reference section to the file, adding an end marker record if there is a previous section a...
Definition: GlfFile.cpp:308
bool openForWrite(const char *filename, bool compressed=true)
Open a glf file for writing with the specified filename.
Definition: GlfFile.cpp:109
bool getNextRecord(GlfRecord &record)
Gets the nextrecord from the file & stores it in the passed in record.
Definition: GlfFile.cpp:368
OpenType
Enum for indicating whether to open the file for read or write.
Definition: GlfFile.h:33
@ READ
open for reading.
Definition: GlfFile.h:34
GlfFile()
Default Constructor.
Definition: GlfFile.cpp:23
bool openForRead(const char *filename)
Open a glf file for reading with the specified filename.
Definition: GlfFile.cpp:66
void close()
Close the file if there is one open, adding an end marker record if there is a previous section and o...
Definition: GlfFile.cpp:142
bool writeHeader(GlfHeader &header)
Writes the specified header into the file.
Definition: GlfFile.cpp:200
bool readHeader(GlfHeader &header)
Reads the header section from the file and stores it in the passed in header.
Definition: GlfFile.cpp:165
uint32_t getCurrentRecordCount()
Return the number of records that have been read/written so far.
Definition: GlfFile.cpp:483
bool isEOF()
Returns whether or not the end of the file has been reached.
Definition: GlfFile.cpp:152
bool writeRecord(const GlfRecord &record)
Writes the specified record into the file.
Definition: GlfFile.cpp:429
This class allows a user to easily get/set the fields in a GLF header.
Definition: GlfHeader.h:30
bool read(IFILE filePtr)
Read the header from the specified file (file MUST be in the correct position for reading the header)...
Definition: GlfHeader.cpp:80
bool write(IFILE filePtr) const
Write the header to the specified file.
Definition: GlfHeader.cpp:141
This class allows a user to easily get/set the fields in a GLF record.
Definition: GlfRecord.h:29
int getRecordType() const
Return the record type.
Definition: GlfRecord.h:126
bool write(IFILE filePtr) const
Write the record to the specified file.
Definition: GlfRecord.cpp:113
bool read(IFILE filePtr)
Read the record from the specified file (file MUST be in the correct position for reading a record).
Definition: GlfRecord.cpp:65
This class allows a user to easily get/set the fields in a GLF section/chromosome header.
Definition: GlfRefSection.h:32
bool read(IFILE filePtr)
Read the refSection from the specified file (file MUST be in the correct position for reading a refSe...
bool write(IFILE filePtr) const
Write the refSection to the specified file.
void setStatus(Status newStatus, const char *newMessage)
Set the status with the specified values.
Definition: GlfStatus.cpp:74
@ FAIL_ORDER
method failed because it was called out of order, like trying to read a file without opening it for r...
Definition: GlfStatus.h:35
@ UNKNOWN
unknown result (default value should never be used)
Definition: GlfStatus.h:33
@ SUCCESS
method completed successfully.
Definition: GlfStatus.h:32
@ FAIL_IO
method failed due to an I/O issue.
Definition: GlfStatus.h:34
@ BGZF
bgzf file.
Definition: InputFile.h:48
@ UNCOMPRESSED
uncompressed file.
Definition: InputFile.h:46