libutil++  1.9.3
 All Classes Functions Variables
Public Member Functions | Static Public Attributes | Protected Member Functions | List of all members
sella::file::GZCSVFileReader Class Reference

A GZIP compressed CSV reader. More...

#include <GZCSVFileReader.h>

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]fileThe name of the database file to read.
Exceptions
IOExceptionif the file cannot be opened for reading.

Definition at line 24 of file GZCSVFileReader.cpp.

24  :
25  filename(file),
26 
27  delimiter(delimiter),
28  seperator(seperator),
29 
30  descriptor(::open(file.c_str(), O_RDONLY | O_LARGEFILE))
31 {
32  /* Ensure the file was opened for reading, and zero all buffers and state machines. */
33  if (this->descriptor <= 0) {
34  THROW(IOException, "failed to open file '%s' for reading", this->filename.c_str());
35  }
36  memset(&(this->stream), 0, sizeof(this->stream));
37  memset(&(this->buffer), 0, sizeof(this->buffer));
38 
39  /* Initialize for the reading of GZIP compressed files. */
40  if (::inflateInit2(&(this->stream), 16 + MAX_WBITS) != Z_OK) {
41  ::close(this->descriptor);
42 
43  THROW(IOException, "failed to initilize zlib instance for reading file '%s'", this->filename.c_str());
44  }
45  this->stream.avail_out = sizeof(this->buffer[1]);
46 }
void close(bool unlink=false) NO_EXCEPTIONS
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 52 of file GZCSVFileReader.cpp.

References close().

52  {
53  if (this->descriptor != 0) {
54  ::inflateEnd(&(this->stream));
55 
56  this->close();
57  }
58 }
void close(bool unlink=false) NO_EXCEPTIONS

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]unlinkWhen set to true, the file will be unlinked on close.

Definition at line 106 of file GZCSVFileReader.cpp.

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

106  {
107  ::close(this->descriptor);
108 
109  if (unlink == true) {
110  ::unlink(this->filename.c_str());
111  }
112  this->filename.clear();
113  this->descriptor = 0;
114 }
void close(bool unlink=false) NO_EXCEPTIONS
void GZCSVFileReader::read ( std::vector< std::vector< std::string >> &  data)

Read the all fields from the file.

Parameters
[out]dataThe vector in which to store all data from the file.
Exceptions
IOExceptionif unabled to read the file for any reason.

Definition at line 67 of file GZCSVFileReader.cpp.

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

67  {
68  do {
69  if ((data.empty() == false) && data.back().empty()) {
70  data.pop_back();
71  }
72  data.push_back(std::vector<std::string>());
73  } while (this->read(data.back()) == true);
74 
75  if ((data.empty() == false) && data.back().empty()) {
76  data.pop_back();
77  }
78 }
void read(std::vector< std::vector< std::string >> &data) THROWS(IOException)
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]dataThe 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]prependA 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
IOExceptionif 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 133 of file GZCSVFileReader.cpp.

133  {
134  uint8_t * head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out);
135 
136  /* Determine if there is decopmressed data available. */
137  if (this->stream.avail_out == sizeof(this->buffer[1])) {
138  /* There is no decopressed data available, so determine if there is compressed data available in memory. */
139  if (this->stream.avail_in == 0) {
140  /* There is no compressed data available, so read data from file into the compressed data buffer. */
141  if ((this->stream.avail_in = ::read(this->descriptor, this->buffer[0], sizeof(this->buffer[0]))) < 0) {
142  THROW(IOException, "failed to read from file '%s'", this->filename.c_str());
143  } else if (this->stream.avail_in == 0) {
144  return true; /* The end of the file was reached, and no more data could be read. */
145  }
146  this->stream.next_in = this->buffer[0];
147  }
148 
149  /* Decompress data from the compressed buffer into the uncompressed buffer. */
150  this->stream.avail_out = sizeof(this->buffer[1]);
151  this->stream.next_out = this->buffer[1];
152 
153  switch (::inflate(&(this->stream), Z_SYNC_FLUSH)) {
154  case Z_STREAM_ERROR:
155  THROW(IOException, "zlib decompression state was destroyed");
156 
157  case Z_NEED_DICT:
158  THROW(IOException, "zlib decompression failed due to missing dictionary");
159 
160  case Z_DATA_ERROR:
161  THROW(IOException, "zlib decompression failed due to bad data in stream");
162 
163  case Z_MEM_ERROR:
164  THROW(IOException, "zlib decompression failed due to a memory error");
165  }
166  head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out);
167  }
168 
169  /* Adjust the limits of the decompressed memory buffer. */
170  for (uint8_t * i = head; i != this->stream.next_out; i++) {
171  if ((*i) == this->seperator) { /* The end of the record has been reached; store the last field and return success. */
172  data.push_back(prepend.append(std::string(reinterpret_cast<char *>(head), i - head)));
173  this->stream.avail_out += (i - head + 1);
174 
175  return true; /* The record request has been fullfilled. */
176  } else if (*(i) == this->delimiter) { /* A record delimiter has been identified. */
177  data.push_back(prepend.append(std::string(reinterpret_cast<char *>(head), i - head)));
178  this->stream.avail_out += (i - head + 1);
179 
180  return false; /* The record request has not yet been fullfilled. */
181  }
182  }
183  this->stream.avail_out = sizeof(this->buffer[1]);
184 
185  /* Recursively call this function with a prepend value supplied to account for a field which is too long for the buffers. */
186  return this->read(data, std::string(reinterpret_cast<char *>(head), this->stream.next_out - head));
187 }
void read(std::vector< std::vector< std::string >> &data) THROWS(IOException)
bool GZCSVFileReader::read ( std::vector< std::string > &  data)
protected

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

Parameters
[out]dataThe vector in which to store all fields from the returned record.
Exceptions
IOExceptionif 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 91 of file GZCSVFileReader.cpp.

91  {
92  /* Read field entries from the memory buffer, and as necessary fall back to reading from the disk. */
93  while (this->read(data, std::string()) == false) {
94  /* EMPTY LOOP */
95  }
96  return data.empty() ? false : true;
97 }
void read(std::vector< std::vector< std::string >> &data) THROWS(IOException)

The documentation for this class was generated from the following files: