sella::file::GZCSVFileReader Class Reference

#include <GZCSVFileReader.h>

List of all members.

Public Member Functions

 STANDARD_TYPEDEF (sella::file::GZCSVFileReader)
 GZCSVFileReader (const std::string &file, char delimiter=DefaultDelimiter, char seperator=DefaultSeperator) THROWS(IOException)
virtual ~GZCSVFileReader () NO_EXCEPTIONS
void read (std::vector< std::vector< std::string >> &data) THROWS(IOException)
void close (bool unlink=false) NO_EXCEPTIONS

Static Public Attributes

static const char DefaultDelimiter = 0x1e
 The default delimiter used between the fields of a record; the ASCII record seperator character.
static const char DefaultSeperator = 0x1d
 The default seperator used between the records of a file; the ASCII group seperator character.

Protected Member Functions

bool read (std::vector< std::string > &data, std::string prepend) THROWS(IOException)
bool read (std::vector< std::string > &data) THROWS(IOException)

Detailed Description

A GZIP compressed CSV reader.

Definition at line 31 of file GZCSVFileReader.h.


Constructor & Destructor Documentation

GZCSVFileReader::GZCSVFileReader ( const std::string &  file,
char  delimiter = DefaultDelimiter,
char  seperator = DefaultSeperator 
)

The base constructor for a file reader.

Parameters:
[in] file The name of the database file to read.
Exceptions:
IOException if the file cannot be opened for reading.

Definition at line 22 of file GZCSVFileReader.cpp.

00022                                                                                                            :
00023         filename(file),
00024 
00025         delimiter(delimiter),
00026         seperator(seperator),
00027 
00028         descriptor(::open(file.c_str(), O_RDONLY | O_LARGEFILE))
00029 {
00030         /* Ensure the file was opened for reading, and zero all buffers and state machines. */
00031         if (this->descriptor <= 0) {
00032                 THROW(IOException, "failed to open file '%s' for reading", this->filename.c_str());
00033         }
00034         memset(&(this->stream), 0, sizeof(this->stream));
00035         memset(&(this->buffer), 0, sizeof(this->buffer));
00036 
00037         /* Initialize for the reading of GZIP compressed files. */
00038         if (::inflateInit2(&(this->stream), 16 + MAX_WBITS) != Z_OK) {
00039 		::close(this->descriptor);
00040 
00041                 THROW(IOException, "failed to initilize zlib instance for reading file '%s'", this->filename.c_str());
00042         }
00043         this->stream.avail_out = sizeof(this->buffer[1]);
00044 }

GZCSVFileReader::~GZCSVFileReader (  )  [virtual]

The class destructor; this destructor closes the file opened by this instance if it was not explicitly closed by the class user.

Definition at line 50 of file GZCSVFileReader.cpp.

References close().

00050                                                 {
00051         if (this->descriptor != 0) {
00052                 ::inflateEnd(&(this->stream));
00053 
00054                 this->close();
00055         }
00056 }


Member Function Documentation

void GZCSVFileReader::close ( bool  unlink = false  ) 

Close the file opened by this instance. Failure to explicitly call this function will not cause a file descriptor leak if the class destructor is called: the destructor will call close() automatically if necessary.

Parameters:
[in] unlink When set to true, the file will be unlinked on close.

Definition at line 104 of file GZCSVFileReader.cpp.

Referenced by sella::file::GZCSVPathReader::read(), and ~GZCSVFileReader().

00104                                                      {
00105 	::close(this->descriptor);
00106 
00107         if (unlink == true) {
00108                 ::unlink(this->filename.c_str());
00109         }
00110         this->filename.clear();
00111         this->descriptor = 0;
00112 }

bool GZCSVFileReader::read ( std::vector< std::string > &  data  )  [protected]

Read the next record from the file and return all fields.

Parameters:
[out] data The vector in which to store all fields from the returned record.
Exceptions:
IOException if unabled to read the next record for any reason.
Returns:
true if the next record was returned, or false if no more records area available in the file.

Definition at line 89 of file GZCSVFileReader.cpp.

00089                                                                           {
00090         /* Read field entries from the memory buffer, and as necessary fall back to reading from the disk. */
00091         while (this->read(data, std::string()) == false) {
00092                 /* EMPTY LOOP */
00093         }
00094         return data.empty() ? false : true;
00095 }

bool GZCSVFileReader::read ( std::vector< std::string > &  data,
std::string  prepend 
) [protected]

Read the next field from the file. If required, this function will obtain additional data from the file and/or decompress additional data from the compressed data buffer.

Parameters:
[out] data The vector in which to store all fields from the returned record; if not empty when called, the function will clear the vector before writing the next set of fields to it.
[in] prepend A text value to prepend the the next field value; this is used for recursive calls on long or broken up (due to buffer size) fields.
Exceptions:
IOException if unabled to read the next field for any reason.
Returns:
true if the end of the record was reached, else returns false.

Definition at line 131 of file GZCSVFileReader.cpp.

00131                                                                                              {
00132         uint8_t * head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out);
00133 
00134         /* Determine if there is decopmressed data available. */
00135         if (this->stream.avail_out == sizeof(this->buffer[1])) {
00136                 /* There is no decopressed data available, so determine if there is compressed data available in memory. */
00137                 if (this->stream.avail_in == 0) {
00138                         /* There is no compressed data available, so read data from file into the compressed data buffer. */
00139                         if ((this->stream.avail_in = ::read(this->descriptor, this->buffer[0], sizeof(this->buffer[0]))) < 0) {
00140                                 THROW(IOException, "failed to read from file '%s'", this->filename.c_str());
00141                         } else if (this->stream.avail_in == 0) {
00142                                 return true; /* The end of the file was reached, and no more data could be read. */
00143                         }
00144                         this->stream.next_in = this->buffer[0];
00145                 }
00146 
00147                 /* Decompress data from the compressed buffer into the uncompressed buffer. */
00148                 this->stream.avail_out = sizeof(this->buffer[1]);
00149                 this->stream.next_out = this->buffer[1];
00150 
00151                 switch (::inflate(&(this->stream), Z_SYNC_FLUSH)) {
00152                         case Z_STREAM_ERROR:
00153                                 THROW(IOException, "zlib decompression state was destroyed");
00154 
00155                         case Z_NEED_DICT:
00156                                 THROW(IOException, "zlib decompression failed due to missing dictionary");
00157 
00158                         case Z_DATA_ERROR:
00159                                 THROW(IOException, "zlib decompression failed due to bad data in stream");
00160 
00161                         case Z_MEM_ERROR:
00162                                 THROW(IOException, "zlib decompression failed due to a memory error");
00163                 }
00164                 head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out);
00165         }
00166 
00167         /* Adjust the limits of the decompressed memory buffer. */
00168         for (uint8_t * i = head; i != this->stream.next_out; i++) {
00169                 if ((*i) == this->seperator) { /* The end of the record has been reached; store the last field and return success. */
00170                         data.push_back(prepend.append(std::string(reinterpret_cast<char *>(head), i - head)));
00171                         this->stream.avail_out += (i - head + 1);
00172 
00173                         return true; /* The record request has been fullfilled. */
00174                 } else if (*(i) == this->delimiter) { /* A record delimiter has been identified. */
00175                         data.push_back(prepend.append(std::string(reinterpret_cast<char *>(head), i - head)));
00176                         this->stream.avail_out += (i - head + 1);
00177 
00178                         return false; /* The record request has not yet been fullfilled. */
00179                 }
00180         }
00181         this->stream.avail_out = sizeof(this->buffer[1]);
00182 
00183         /* Recursively call this function with a prepend value supplied to account for a field which is too long for the buffers. */
00184         return this->read(data, std::string(reinterpret_cast<char *>(head), this->stream.next_out - head));
00185 }

void GZCSVFileReader::read ( std::vector< std::vector< std::string >> &  data  ) 

Read the all fields from the file.

Parameters:
[out] data The vector in which to store all data from the file.
Exceptions:
IOException if unabled to read the file for any reason.

Definition at line 65 of file GZCSVFileReader.cpp.

Referenced by sella::file::GZCSVPathReader::read().

00065                                                                                      {
00066         do {
00067                 if ((data.empty() == false) && data.back().empty()) {
00068                         data.pop_back();
00069                 }
00070                 data.push_back(std::vector<std::string>());
00071         } while (this->read(data.back()) == true);
00072 
00073         if ((data.empty() == false) && data.back().empty()) {
00074                 data.pop_back();
00075         }
00076 }


The documentation for this class was generated from the following files:
 All Classes Functions Variables

Generated on 20 Nov 2014 for libutil++ by  doxygen 1.6.1