// 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(const char *file_name) throw(std::runtime_error) : m_eof(false), 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 } 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::runtime_error) { size_t line_length = READ_SIZE - line_begin; // if this condition is true, then we've filled the buffer without finding any newline // characters. This could be handled by reallocating a larger buffer, but I've never // encountered this situation using real-world data. assert(line_length < READ_SIZE); std::memmove(&m_inflated[0], &m_inflated[line_begin], line_length); int read_length = ::gzread(m_gzip_file, &m_inflated[line_length], READ_SIZE - line_length); 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