00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "GZCSVFileReader.h"
00010
00011 #include <fcntl.h>
00012
00013 using namespace sella::file;
00014
00022 GZCSVFileReader::GZCSVFileReader(const std::string & file, char delimiter, char seperator) THROWS(IOException) :
00023 filename(file),
00024
00025 delimiter(delimiter),
00026 seperator(seperator),
00027
00028 descriptor(::open(file.c_str(), O_RDONLY | O_LARGEFILE))
00029 {
00030
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
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 }
00045
00050 GZCSVFileReader::~GZCSVFileReader() NO_EXCEPTIONS {
00051 if (this->descriptor != 0) {
00052 ::inflateEnd(&(this->stream));
00053
00054 this->close();
00055 }
00056 }
00057
00065 void GZCSVFileReader::read(std::vector<std::vector<std::string>> & data) THROWS(IOException) {
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 }
00077
00089 bool GZCSVFileReader::read(std::vector<std::string> & data) THROWS(IOException) {
00090
00091 while (this->read(data, std::string()) == false) {
00092
00093 }
00094 return data.empty() ? false : true;
00095 }
00096
00104 void GZCSVFileReader::close(bool unlink) NO_EXCEPTIONS {
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 }
00113
00131 bool GZCSVFileReader::read(std::vector<std::string> & data, std::string prepend) THROWS(IOException) {
00132 uint8_t * head = this->stream.next_out - (sizeof(this->buffer[1]) - this->stream.avail_out);
00133
00134
00135 if (this->stream.avail_out == sizeof(this->buffer[1])) {
00136
00137 if (this->stream.avail_in == 0) {
00138
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;
00143 }
00144 this->stream.next_in = this->buffer[0];
00145 }
00146
00147
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
00168 for (uint8_t * i = head; i != this->stream.next_out; i++) {
00169 if ((*i) == this->seperator) {
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;
00174 } else if (*(i) == this->delimiter) {
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;
00179 }
00180 }
00181 this->stream.avail_out = sizeof(this->buffer[1]);
00182
00183
00184 return this->read(data, std::string(reinterpret_cast<char *>(head), this->stream.next_out - head));
00185 }
00186
00187
00188
00189