libStatGen Software 1
Loading...
Searching...
No Matches
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.
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.
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.
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.
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.
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.
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