// GzipReader.cpp #if defined(_WIN32) || defined(_WIN64) // C4290 - the compiler ignores exception specifications #pragma warning(disable: 4290) #elif defined(linux) || defined(__linux) #include #include #include #include "SystemError.hpp" #endif #include #include #include #include #include "GzipReader.hpp" namespace NGBW { // GzipReader GzipReader::GzipReader(const char *file_name) throw(std::bad_alloc, std::runtime_error) : m_eof(false), m_inflated(NULL), m_max_length(READ_SIZE), m_inflated_length(READ_SIZE), m_line_end(READ_SIZE - 1) { #if defined(linux) || defined(__linux) int file = ::open(file_name, O_RDONLY | O_LARGEFILE); if (file < 0) throw SystemError("GzipReader", "open failed", errno); if ((m_gzip_file = ::gzdopen(file, "r")) == NULL) throw std::runtime_error("gzdopen failed"); #else if ((m_gzip_file = ::gzopen(file_name, "r")) == NULL) throw std::runtime_error("gzopen failed"); #endif m_inflated = new char[m_max_length + 1]; } char GzipReader::GetChar() { if (m_eof) return '\0'; m_line_end += 1; if (m_line_end == m_inflated_length) { InflateData(m_line_end); if (m_eof) return '\0'; } return m_inflated[m_line_end]; } const char *GzipReader::GetLine() { if (m_eof) return NULL; m_line_end += 1; size_t line_begin = m_line_end; while (m_inflated[m_line_end] != '\n') { if (m_line_end < m_inflated_length) m_line_end += 1; else { InflateData(line_begin); if (m_eof) return NULL; line_begin = 0; } } m_inflated[m_line_end] = '\0'; return m_inflated + line_begin; } void GzipReader::InflateData(size_t line_begin) throw(std::bad_alloc, std::runtime_error) { size_t line_length = m_inflated_length - line_begin; if (m_max_length >= (line_length + READ_SIZE)) std::memmove(m_inflated, m_inflated + line_begin, line_length); else { m_max_length += READ_SIZE; char *new_buffer = new char[m_max_length + 1]; std::memcpy(new_buffer, m_inflated + line_begin, line_length); delete[] m_inflated; m_inflated = new_buffer; } int read_length = ::gzread(m_gzip_file, m_inflated + line_length, READ_SIZE); if (read_length == 0) m_eof = true; else if(read_length < 0) { int error_code; std::string message("gzread: "); message.append(::gzerror(m_gzip_file, &error_code)); throw std::runtime_error(message); } else { m_inflated_length = read_length + line_length; m_line_end = line_length; } } } // namespace NGBW