Commit d638d634 by Maarten L. Hekkelman

Remove gxrio and replace it with stripped down version

parent 35196789
build/ build/
.vscode/ .vscode/
.vs/ .vs/
.pc/
tools/symop-map-generator
test/unit-test
test/pdb2cif-test
test/rename-compound-test
tools/update-libcifpp-data tools/update-libcifpp-data
data/components.cif* data/components.cif*
CMakeSettings.json CMakeSettings.json
msvc/ msvc/
Testing/
rsrc/feature-request.txt
test/test-create_sugar_?.cif
test/oprofile_data/
test/perf.data*
src/revision.hpp src/revision.hpp
...@@ -133,14 +133,19 @@ if(GXX_LIBSTDCPP) ...@@ -133,14 +133,19 @@ if(GXX_LIBSTDCPP)
if(STD_REGEX_RUNNING STREQUAL FAILED_TO_RUN) if(STD_REGEX_RUNNING STREQUAL FAILED_TO_RUN)
message(STATUS "You are probably trying to compile using the g++ standard library which contains a crashing std::regex implementation. Will try to use boost::regex instead") message(STATUS "You are probably trying to compile using the g++ standard library which contains a crashing std::regex implementation. Will try to use boost::regex instead")
set(BOOST_REGEX_STANDALONE ON) find_package(Boost COMPONENTS regex QUIET)
find_package(Boost 1.77 COMPONENTS regex QUIET)
if(Boost_FOUND) if(Boost_FOUND)
set(BOOST_REGEX_INCLUDE ${Boost_INCLUDE_DIRS}) if(Boost_VERSION VERSION_GREATER_EQUAL 1.77)
set(BOOST_REGEX_STANDALONE ON)
set(BOOST_REGEX_INCLUDE ${Boost_INCLUDE_DIRS})
else()
list(APPEND CIFPP_REQUIRED_LIBRARIES Boost::regex)
set(BOOST_REGEX_SYSTEM ON)
endif()
else() else()
add_git_submodule(regex EXCLUDE_FROM_ALL) add_git_submodule("https://github.com/boostorg/regex" regex EXCLUDE_FROM_ALL)
set(BOOST_REGEX_STANDALONE ON)
set(BOOST_REGEX_INCLUDE regex/include) set(BOOST_REGEX_INCLUDE regex/include)
endif() endif()
endif() endif()
...@@ -151,7 +156,6 @@ set(THREADS_PREFER_PTHREAD_FLAG) ...@@ -151,7 +156,6 @@ set(THREADS_PREFER_PTHREAD_FLAG)
find_package(Threads) find_package(Threads)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
find_package(LibLZMA REQUIRED)
include(FindFilesystem) include(FindFilesystem)
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY}) list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
...@@ -159,14 +163,6 @@ list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY}) ...@@ -159,14 +163,6 @@ list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
include(FindAtomic) include(FindAtomic)
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY}) list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPATOMIC_LIBRARY})
if(NOT PDB_REDO_META)
find_package(gxrio QUIET)
if(NOT gxrio_FOUND)
add_git_submodule(gxrio EXCLUDE_FROM_ALL)
endif()
endif()
# Create a revision file, containing the current git version info # Create a revision file, containing the current git version info
include(VersionString) include(VersionString)
write_version_header(${PROJECT_SOURCE_DIR}/src/ "LibCIFPP") write_version_header(${PROJECT_SOURCE_DIR}/src/ "LibCIFPP")
...@@ -250,7 +246,9 @@ add_library(cifpp::cifpp ALIAS cifpp) ...@@ -250,7 +246,9 @@ add_library(cifpp::cifpp ALIAS cifpp)
set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(BOOST_REGEX_STANDALONE) if(BOOST_REGEX_STANDALONE)
target_compile_definitions(cifpp PUBLIC USE_BOOST_REGEX=1 BOOST_REGEX_STANDALONE=1) target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1 BOOST_REGEX_STANDALONE=1)
elseif(BOOST_REGEX_SYSTEM)
target_compile_definitions(cifpp PRIVATE USE_BOOST_REGEX=1)
endif() endif()
target_include_directories(cifpp target_include_directories(cifpp
...@@ -259,14 +257,7 @@ target_include_directories(cifpp ...@@ -259,14 +257,7 @@ target_include_directories(cifpp
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
) )
target_link_libraries(cifpp PUBLIC target_link_libraries(cifpp PUBLIC Threads::Threads ZLIB::ZLIB ${CIFPP_REQUIRED_LIBRARIES})
Threads::Threads
ZLIB::ZLIB
LibLZMA::LibLZMA
${CIFPP_REQUIRED_LIBRARIES})
get_target_property(GXRIO_INCLUDE_DIR gxrio::gxrio INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(cifpp PRIVATE ${GXRIO_INCLUDE_DIR})
if(BOOST_REGEX_STANDALONE) if(BOOST_REGEX_STANDALONE)
target_include_directories(cifpp PRIVATE ${BOOST_REGEX_INCLUDE}) target_include_directories(cifpp PRIVATE ${BOOST_REGEX_INCLUDE})
...@@ -356,8 +347,14 @@ install(FILES ...@@ -356,8 +347,14 @@ install(FILES
DESTINATION ${CIFPP_DATA_DIR} DESTINATION ${CIFPP_DATA_DIR}
) )
if(BOOST_REGEX_STANDALONE)
set(CONFIG_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/cmake/cifppConfig.cmake.in)
else()
set(CONFIG_TEMPLATE_FILE ${PROJECT_SOURCE_DIR}/cmake/cifppConfig-boost-regex.cmake.in)
endif()
configure_package_config_file( configure_package_config_file(
${PROJECT_SOURCE_DIR}/cmake/cifppConfig.cmake.in ${CONFIG_TEMPLATE_FILE}
${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/cifpp/cifppConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cifpp
PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR SHARE_INSTALL_DIR PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR SHARE_INSTALL_DIR
...@@ -463,7 +460,7 @@ set(CPACK_SOURCE_TGZ ON) ...@@ -463,7 +460,7 @@ set(CPACK_SOURCE_TGZ ON)
set(CPACK_SOURCE_TBZ2 OFF) set(CPACK_SOURCE_TBZ2 OFF)
set(CPACK_SOURCE_TXZ OFF) set(CPACK_SOURCE_TXZ OFF)
set(CPACK_SOURCE_TZ OFF) set(CPACK_SOURCE_TZ OFF)
set(CPACK_SOURCE_IGNORE_FILES "/data/components.cif;/build;/.vscode;/.git;/test;/.pc;/tools/symop-map-generator;/regex/doc;/regex/example;/regex/meta;/regex/performance;/regex/test") set(CPACK_SOURCE_IGNORE_FILES "/data/components.cif;/build;/.vscode;/.git;/regex")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME}) set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
include(CPack) include(CPack)
cmake_minimum_required(VERSION 3.16..3.19) cmake_minimum_required(VERSION 3.16..3.19)
function(add_git_submodule dir) function(add_git_submodule repo dir)
# add a Git submodule directory to CMake, assuming the # add a Git submodule directory to CMake, assuming the
# Git submodule directory is a CMake project. # Git submodule directory is a CMake project.
# #
...@@ -11,9 +11,9 @@ function(add_git_submodule dir) ...@@ -11,9 +11,9 @@ function(add_git_submodule dir)
find_package(Git QUIET) find_package(Git QUIET)
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${dir}/CMakeLists.txt") if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${dir}/CMakeLists.txt")
if(NOT (GIT_FOUND AND IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")) if(NOT(GIT_FOUND))
message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR} is not a git repository and the submodule ${dir} is not complete. Cannot continue.") message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR} is not a git repository and the submodule ${dir} is not complete. Cannot continue.")
else() elseif(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") # We're in a git repo, we can use submodules
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${dir} execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${dir}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
...@@ -22,10 +22,19 @@ function(add_git_submodule dir) ...@@ -22,10 +22,19 @@ function(add_git_submodule dir)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${dir} execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${dir}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
endif() endif()
else()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
execute_process(COMMAND ${GIT_EXECUTABLE} clone "${repo}" --recursive -- ${dir}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND_ERROR_IS_FATAL ANY)
else()
execute_process(COMMAND ${GIT_EXECUTABLE} clone "${repo}" --recursive -- ${dir}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
endif()
endif() endif()
endif() endif()
set(ENABLE_TESTING OFF) set(ENABLE_TESTING OFF)
add_subdirectory(${dir} ${ARGV}) add_subdirectory(${dir} ${ARGV2})
endfunction(add_git_submodule) endfunction(add_git_submodule)
\ No newline at end of file
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(Threads)
find_dependency(ZLIB REQUIRED)
find_dependency(LibLZMA REQUIRED)
find_dependency(Boost COMPONENTS regex)
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/cifppTargets.cmake")
set_and_check(CIFPP_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(CIFPP_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@")
set_and_check(CIFPP_SHARE_DIR "@PACKAGE_SHARE_INSTALL_DIR@")
check_required_components(cifpp)
Subproject commit a7bb5b5c4b6612215a78267b89e05c39a45429b5
// Copyright Maarten L. Hekkelman, 2022
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#pragma once
#include <array>
#include <filesystem>
#include <fstream>
#include <memory>
#include <utility>
#include <zlib.h>
/// \file gzio.hpp
///
/// Single header file for the implementation of stream classes
/// that can transparently read and write compressed files.
///
/// The gzio::istream_buf class sniffs the input and decides whether to use
/// a decompressor if a signature was recognized.
///
/// There's also an ifstream and ofstream class here that can
/// read and write compressed files. In this case the decission
/// whether to use a compressions/decompression algorithm is
/// based on the extension of the \a filename argument.
// This is a stripped down version of the gzio library from
// https://github.com/mhekkel/gzio.git
// Most notably, the lzma support has been removed since getting
// that to work in Windows proved to be too much work.
namespace cif::gzio
{
const size_t kDefaultBufferSize = 256;
// --------------------------------------------------------------------
/// \brief A base class for the streambuf classes in gzio
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
///
/// The base class for all streambuf classes in this library.
/// It maintains the pointer to the upstream streambuf.
template <typename CharT, typename Traits>
class basic_streambuf : public std::basic_streambuf<CharT, Traits>
{
public:
using char_type = CharT;
using traits_type = Traits;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
using streambuf_type = std::basic_streambuf<CharT, Traits>;
basic_streambuf() = default;
basic_streambuf(const basic_streambuf &) = delete;
basic_streambuf(basic_streambuf &&rhs)
: streambuf_type(std::move(rhs))
{
m_upstream = std::exchange(rhs.m_upstream, nullptr);
}
basic_streambuf &operator=(const basic_streambuf &) = delete;
basic_streambuf &operator=(basic_streambuf &&rhs)
{
m_upstream = std::exchange(rhs.m_upstream, nullptr);
return *this;
}
void set_upstream(streambuf_type *upstream)
{
m_upstream = upstream;
}
virtual basic_streambuf *init(streambuf_type *sb) = 0;
virtual basic_streambuf *close() = 0;
protected:
/// \brief The upstream streambuf object, usually this is a basic_filebuf
streambuf_type *m_upstream = nullptr;
};
// --------------------------------------------------------------------
/// \brief A streambuf class that can be used to decompress gzipped data
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
/// \tparam BufferSize The size of the internal buffers.
///
/// This implementation of streambuf can decompress (inflate) data compressed
/// using zlib.
template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSize>
class basic_igzip_streambuf : public basic_streambuf<CharT, Traits>
{
public:
static_assert(sizeof(CharT) == 1, "Unfortunately, support for wide characters is not implemented yet.");
using char_type = CharT;
using traits_type = Traits;
using streambuf_type = std::basic_streambuf<char_type, traits_type>;
using base_type = basic_streambuf<CharT, Traits>;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
basic_igzip_streambuf() = default;
basic_igzip_streambuf(const basic_igzip_streambuf &) = delete;
/// \brief Move constructor
basic_igzip_streambuf(basic_igzip_streambuf &&rhs)
: base_type(std::move(rhs))
{
std::swap(m_zstream, rhs.m_zstream);
std::swap(m_gzheader, rhs.m_gzheader);
auto p = std::copy(rhs.gptr(), rhs.egptr(), m_out_buffer.begin());
this->setg(m_out_buffer.begin(), m_out_buffer.begin(), p);
if (m_zstream and m_zstream->avail_in > 0)
{
auto next_in_offset = m_zstream->next_in - rhs.m_in_buffer.data();
std::copy(rhs.m_in_buffer.begin() + next_in_offset,
rhs.m_in_buffer.begin() + next_in_offset + m_zstream->avail_in,
m_in_buffer.begin());
m_zstream->next_in = m_in_buffer.begin();
}
}
basic_igzip_streambuf &operator=(const basic_igzip_streambuf &) = delete;
/// \brief Move operator= implementation
basic_igzip_streambuf &operator=(basic_igzip_streambuf &&rhs)
{
base_type::operator=(std::move(rhs));
std::swap(m_zstream, rhs.m_zstream);
std::swap(m_gzheader, rhs.m_gzheader);
auto p = std::copy(rhs.gptr(), rhs.egptr(), m_out_buffer.begin());
this->setg(m_out_buffer.begin(), m_out_buffer.begin(), p);
if (m_zstream and m_zstream->avail_in > 0)
{
auto next_in_offset = m_zstream->next_in - reinterpret_cast<unsigned char *>(rhs.m_in_buffer.data());
std::copy(rhs.m_in_buffer.begin() + next_in_offset,
rhs.m_in_buffer.begin() + next_in_offset + m_zstream->avail_in,
m_in_buffer.begin());
m_zstream->next_in = reinterpret_cast<unsigned char *>(m_in_buffer.begin());
}
return *this;
}
~basic_igzip_streambuf()
{
close();
}
/// \brief This closes the zlib stream and sets the get pointers to null.
base_type *close() override
{
if (m_zstream)
{
::inflateEnd(m_zstream.get());
m_zstream.reset(nullptr);
m_gzheader.reset(nullptr);
}
this->setg(nullptr, nullptr, nullptr);
return this;
}
/// \brief Initialize a zlib stream and set the upstream.
///
/// \param upstream The upstream streambuf
///
/// The zstream is constructed and an optional header is
/// read from upstream. The contents of the header are ignored
/// but we must maintain that structure.
base_type *init(streambuf_type *upstream) override
{
this->set_upstream(upstream);
close();
m_zstream.reset(new z_stream_s);
m_gzheader.reset(new gz_header_s);
auto &zstream = *m_zstream.get();
zstream = z_stream_s{};
auto &header = *m_gzheader.get();
header = gz_header_s{};
int err = ::inflateInit2(&zstream, 47);
if (err == Z_OK)
{
zstream.next_in = reinterpret_cast<unsigned char *>(m_in_buffer.data());
zstream.avail_in = this->m_upstream->sgetn(m_in_buffer.data(), m_in_buffer.size());
err = ::inflateGetHeader(&zstream, &header);
if (err != Z_OK)
::inflateEnd(&zstream);
}
if (err != Z_OK)
zstream = z_stream_s{};
return err == Z_OK ? this : nullptr;
}
private:
/// \brief The actual work is done here.
int_type underflow() override
{
if (m_zstream and this->m_upstream)
{
auto &zstream = *m_zstream.get();
const std::streamsize kBufferByteSize = m_out_buffer.size();
while (this->gptr() == this->egptr())
{
zstream.next_out = reinterpret_cast<unsigned char *>(m_out_buffer.data());
zstream.avail_out = kBufferByteSize;
if (zstream.avail_in == 0)
{
zstream.next_in = reinterpret_cast<unsigned char *>(m_in_buffer.data());
zstream.avail_in = this->m_upstream->sgetn(m_in_buffer.data(), m_in_buffer.size());
}
int err = ::inflate(&zstream, Z_SYNC_FLUSH);
std::streamsize n = kBufferByteSize - zstream.avail_out;
if (err == Z_STREAM_END or (err == Z_OK and n > 0))
{
this->setg(
m_out_buffer.begin(),
m_out_buffer.begin(),
m_out_buffer.begin() + n);
break;
}
if (err < Z_OK)
break;
}
}
return this->gptr() != this->egptr() ? traits_type::to_int_type(*this->gptr()) : traits_type::eof();
}
private:
/// \brief The zlib internal structures are mainained as pointers to avoid having
/// to copy their content in move constructors.
std::unique_ptr<z_stream_s> m_zstream;
/// \brief The zlib internal structures are mainained as pointers to avoid having
/// to copy their content in move constructors.
std::unique_ptr<gz_header> m_gzheader;
/// \brief Input buffer, this is the input for zlib
std::array<char_type, BufferSize> m_in_buffer;
/// \brief Output buffer, where the ostream finds the data
std::array<char_type, BufferSize> m_out_buffer;
};
// --------------------------------------------------------------------
/// \brief A streambuf class that can be used to compress data using zlib
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
/// \tparam BufferSize The size of the internal buffers.
///
/// This implementation of streambuf can compress (deflate) data using zlib.
template <typename CharT, typename Traits, size_t BufferSize = kDefaultBufferSize>
class basic_ogzip_streambuf : public basic_streambuf<CharT, Traits>
{
public:
static_assert(sizeof(CharT) == 1, "Unfortunately, support for wide characters is not implemented yet.");
using char_type = CharT;
using traits_type = Traits;
using streambuf_type = std::basic_streambuf<char_type, traits_type>;
using base_type = basic_streambuf<CharT, Traits>;
using int_type = typename traits_type::int_type;
using pos_type = typename traits_type::pos_type;
using off_type = typename traits_type::off_type;
basic_ogzip_streambuf() = default;
basic_ogzip_streambuf(const basic_ogzip_streambuf &) = delete;
/// \brief Move constructor
basic_ogzip_streambuf(basic_ogzip_streambuf &&rhs)
: base_type(std::move(rhs))
{
std::swap(m_zstream, rhs.m_zstream);
std::swap(m_gzheader, rhs.m_gzheader);
this->setp(m_in_buffer.begin(), m_in_buffer.end());
this->sputn(rhs.pbase(), rhs.pptr() - rhs.pbase());
rhs.setp(nullptr, nullptr);
}
basic_ogzip_streambuf &operator=(const basic_ogzip_streambuf &) = delete;
/// \brief Move operator=
basic_ogzip_streambuf &operator=(basic_ogzip_streambuf &&rhs)
{
base_type::operator=(std::move(rhs));
std::swap(m_zstream, rhs.m_zstream);
std::swap(m_gzheader, rhs.m_gzheader);
this->setp(m_in_buffer.begin(), m_in_buffer.end());
this->sputn(rhs.pbase(), rhs.pptr() - rhs.pbase());
rhs.setp(nullptr, nullptr);
return *this;
}
~basic_ogzip_streambuf()
{
close();
}
/// \brief This closes the zlib stream and sets the put pointers to null.
base_type *close() override
{
if (m_zstream)
{
overflow(traits_type::eof());
::deflateEnd(m_zstream.get());
m_zstream.reset(nullptr);
m_gzheader.reset(nullptr);
}
this->setp(nullptr, nullptr);
return this;
}
/// \brief Initialize the internal zlib structures
///
/// \param upstream The upstream streambuf
///
/// The zlib stream is initialized as one that can accept
/// a gzip header.
base_type *init(streambuf_type *upstream) override
{
this->set_upstream(upstream);
close();
m_zstream.reset(new z_stream_s);
m_gzheader.reset(new gz_header_s);
auto &zstream = *m_zstream.get();
zstream = z_stream_s{};
auto &header = *m_gzheader.get();
header = gz_header_s{};
const int WINDOW_BITS = 15, GZIP_ENCODING = 16;
int err = deflateInit2(&zstream, Z_BEST_COMPRESSION, Z_DEFLATED,
WINDOW_BITS | GZIP_ENCODING, Z_DEFLATED, Z_DEFAULT_STRATEGY);
if (err == Z_OK)
err = ::deflateSetHeader(&zstream, &header);
if (err == Z_OK)
this->setp(this->m_in_buffer.begin(), this->m_in_buffer.end());
else
zstream = z_stream_s{};
return err == Z_OK ? this : nullptr;
}
private:
/// \brief The actual work is done here
///
/// \param ch The character that did not fit, in case it is eof we need to flush
///
int_type overflow(int_type ch) override
{
if (not m_zstream)
return traits_type::eof();
auto &zstream = *m_zstream;
zstream.next_in = reinterpret_cast<unsigned char *>(this->pbase());
zstream.avail_in = this->pptr() - this->pbase();
char_type buffer[BufferSize];
for (;;)
{
zstream.next_out = reinterpret_cast<unsigned char *>(buffer);
zstream.avail_out = sizeof(buffer);
int err = ::deflate(&zstream, ch == traits_type::eof() ? Z_FINISH : Z_NO_FLUSH);
std::streamsize n = sizeof(buffer) - zstream.avail_out;
if (n > 0)
{
auto r = this->m_upstream->sputn(reinterpret_cast<char_type *>(buffer), n);
if (r != n)
return traits_type::eof();
}
if (zstream.avail_out == 0)
continue;
if (err == Z_OK and ch == traits_type::eof())
continue;
break;
}
this->setp(this->m_in_buffer.begin(), this->m_in_buffer.end());
if (not traits_type::eq_int_type(ch, traits_type::eof()))
{
*this->pptr() = traits_type::to_char_type(ch);
this->pbump(1);
}
return ch;
}
private:
/// \brief The zlib internal structures are mainained as pointers to avoid having
/// to copy their content in move constructors.
std::unique_ptr<z_stream_s> m_zstream;
/// \brief The zlib internal structures are mainained as pointers to avoid having
/// to copy their content in move constructors.
std::unique_ptr<gz_header> m_gzheader;
/// \brief Input buffer, this is the input for zlib
std::array<char_type, BufferSize> m_in_buffer;
};
// --------------------------------------------------------------------
/// \brief An istream implementation that wraps a streambuf with a decompressing streambuf
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
///
/// This is an istream implementation that can take a source streambuf and then wraps
/// this streambuf with a decompressing streambuf class defined above.
/// The class inherits from std::basic_istream and offers all the associated functionality.
template <typename CharT, typename Traits>
class basic_istream : public std::basic_istream<CharT, Traits>
{
public:
using base_type = std::basic_istream<CharT, Traits>;
using traits_type = Traits;
using char_type = typename traits_type::char_type;
using int_type = typename traits_type::int_type;
using z_streambuf_type = basic_streambuf<char_type, traits_type>;
using upstreambuf_type = std::basic_streambuf<char_type, traits_type>;
using gzip_streambuf_type = basic_igzip_streambuf<char_type, traits_type>;
/// \brief Regular move constructor
basic_istream(basic_istream &&rhs)
: base_type(std::move(rhs))
{
m_gziobuf = std::move(rhs.m_gziobuf);
if (m_gziobuf)
this->rdbuf(m_gziobuf.get());
else
this->rdbuf(nullptr);
}
/// \brief Regular move operator=
basic_istream &operator=(basic_istream &&rhs)
{
base_type::operator=(std::move(rhs));
m_gziobuf = std::move(rhs.m_gziobuf);
if (m_gziobuf)
this->rdbuf(m_gziobuf.get());
else
this->rdbuf(nullptr);
return *this;
}
/// \brief Construct an istream with the passed in streambuf \a buf
///
/// \param buf The streambuf that provides the compressed data
///
/// This constructor will initialize the zlib code with the \a buf streambuf.
explicit basic_istream(upstreambuf_type *buf)
: base_type(nullptr)
{
init_z(buf);
}
protected:
basic_istream()
: base_type(nullptr) {}
/// \brief Initialise internals with streambuf \a sb
/// \param sb The upstream streambuf class
///
/// This will sniff the content in \a sb and decide upon what is found
/// what implementation is used. If it doesn't look like compressed data
/// the \a sb streambuf is used without any decompression being done.
void init_z(upstreambuf_type *sb)
{
int_type ch = sb->sgetc();
if (ch == 0x1f)
{
sb->sbumpc();
ch = sb->sgetc();
sb->sungetc();
if (ch == 0x8b) // Read gzip header
m_gziobuf.reset(new gzip_streambuf_type);
}
if (m_gziobuf)
{
if (not m_gziobuf->init(sb))
this->setstate(std::ios_base::failbit);
else
this->init(m_gziobuf.get());
}
else
this->init(sb);
}
protected:
/// \brief Our streambuf class
std::unique_ptr<z_streambuf_type> m_gziobuf;
};
// --------------------------------------------------------------------
/// \brief Control input from files compressed with gzip.
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
///
/// This is an ifstream implementation that can read from named files compressed with
/// gzip directly. The class inherits from std::basic_istream and offers all the
/// associated functionality.
template <typename CharT, typename Traits>
class basic_ifstream : public basic_istream<CharT, Traits>
{
public:
using base_type = basic_istream<CharT, Traits>;
using char_type = CharT;
using traits_type = Traits;
using filebuf_type = std::basic_filebuf<char_type, traits_type>;
using gzip_streambuf_type = typename base_type::gzip_streambuf_type;
/// \brief Default constructor, does not open a file since none is specified
basic_ifstream() = default;
~basic_ifstream()
{
close();
}
/// \brief Construct an ifstream
/// \param filename Null terminated string specifying the file to open
/// \param mode The mode in which to open the file
explicit basic_ifstream(const char *filename, std::ios_base::openmode mode = std::ios_base::in)
{
open(filename, mode);
}
/// \brief Construct an ifstream
/// \param filename std::string specifying the file to open
/// \param mode The mode in which to open the file
explicit basic_ifstream(const std::string &filename, std::ios_base::openmode mode = std::ios_base::in)
{
open(filename, mode);
}
/// \brief Construct an ifstream
/// \param filename std::filesystem::path specifying the file to open
/// \param mode The mode in which to open the file
explicit basic_ifstream(const std::filesystem::path &filename, std::ios_base::openmode mode = std::ios_base::in)
{
open(filename, mode);
}
/// \brief Move constructor
basic_ifstream(basic_ifstream &&rhs)
: base_type(std::move(rhs))
{
m_filebuf = std::move(rhs.m_filebuf);
if (this->m_gziobuf)
this->m_gziobuf->set_upstream(&m_filebuf);
else
this->rdbuf(&m_filebuf);
}
basic_ifstream(const basic_ifstream &) = delete;
basic_ifstream &operator=(const basic_ifstream &) = delete;
/// \brief Move version of operator=
basic_ifstream &operator=(basic_ifstream &&rhs)
{
base_type::operator=(std::move(rhs));
m_filebuf = std::move(rhs.m_filebuf);
if (this->m_gziobuf)
this->m_gziobuf->set_upstream(&m_filebuf);
else
this->rdbuf(&m_filebuf);
return *this;
}
/// \brief Open the file \a filename with mode \a mode
/// \param filename std::filesystem::path specifying the file to open
/// \param mode The mode in which to open the file
void open(const std::filesystem::path &filename, std::ios_base::openmode mode = std::ios_base::in)
{
if (not m_filebuf.open(filename, mode | std::ios::binary))
this->setstate(std::ios_base::failbit);
else
{
if (filename.extension() == ".gz")
this->m_gziobuf.reset(new gzip_streambuf_type);
if (not this->m_gziobuf)
{
this->rdbuf(&m_filebuf);
this->clear();
}
else if (not this->m_gziobuf->init(&m_filebuf))
this->setstate(std::ios_base::failbit);
else
{
this->rdbuf(this->m_gziobuf.get());
this->clear();
}
}
}
/// \brief Open the file \a filename with mode \a mode
/// \param filename std::string specifying the file to open
/// \param mode The mode in which to open the file
void open(const std::string &filename, std::ios_base::openmode mode = std::ios_base::in)
{
open(std::filesystem::path{filename}, mode);
}
/// \brief Open the file \a filename with mode \a mode
/// \param filename Null terminated string specifying the file to open
/// \param mode The mode in which to open the file
void open(const char *filename, std::ios_base::openmode mode = std::ios_base::in)
{
open(std::filesystem::path{filename}, mode);
}
/// \brief Return true if the file is open
/// \return m_filebuf.is_open()
bool is_open() const
{
return m_filebuf.is_open();
}
/// \brief Close the file
///
/// Calls m_filebuf.close(). If that fails, the failbit is set.
void close()
{
if (this->m_gziobuf and not this->m_gziobuf->close())
this->setstate(std::ios_base::failbit);
if (not m_filebuf.close())
this->setstate(std::ios_base::failbit);
}
/// \brief Swap the contents with those of \a rhs
/// \param rhs The ifstream to swap with
void swap(basic_ifstream &rhs)
{
base_type::swap(rhs);
m_filebuf.swap(rhs.m_filebuf);
if (this->m_gziobuf)
{
this->m_gziobuf.set_upstream(&m_filebuf);
this->rdbuf(this->m_gziobuf.get());
}
else
this->rdbuf(&m_filebuf);
if (rhs.m_gziobuf)
{
rhs.m_gziobuf.set_upstream(&rhs.m_filebuf);
rhs.rdbuf(rhs.m_gziobuf.get());
}
else
rhs.rdbuf(&rhs.m_filebuf);
}
private:
/// \brief The filebuf
filebuf_type m_filebuf;
};
// --------------------------------------------------------------------
/// \brief An ostream implementation that wraps a streambuf with a compressing streambuf
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
///
/// This is an ostream implementation that can take an upstream streambuf and then wraps
/// this streambuf with a compressing streambuf class defined above.
/// The class inherits from std::basic_ostream and offers all the associated functionality.
template <typename CharT, typename Traits>
class basic_ostream : public std::basic_ostream<CharT, Traits>
{
public:
using base_type = std::basic_ostream<CharT, Traits>;
using char_type = CharT;
using traits_type = Traits;
using z_streambuf_type = basic_streambuf<char_type, traits_type>;
using upstreambuf_type = std::basic_streambuf<char_type, traits_type>;
/// \brief Regular move constructor
basic_ostream(basic_ostream &&rhs)
: base_type(std::move(rhs))
{
m_gziobuf = std::move(rhs.m_gziobuf);
this->rdbuf(m_gziobuf.get());
}
/// \brief Regular move operator=
basic_ostream &operator=(basic_ostream &&rhs)
{
base_type::operator=(std::move(rhs));
m_gziobuf = std::move(rhs.m_gziobuf);
this->rdbuf(m_gziobuf.get());
return *this;
}
// One might expect a constructor taking a streambuf pointer
// as the regular std::ostream class does. However, that's not
// going to work since no information is known at this time
// what compression to use.
//
// explicit basic_ostream(upstreambuf_type *buf)
// {
// init_z(buf);
// this->init(m_gziobuf.get());
// }
protected:
basic_ostream()
: base_type(nullptr) {}
/// \brief Initialise internals with streambuf \a sb
void init_z(std::streambuf *sb)
{
if (not m_gziobuf->init(sb))
this->setstate(std::ios_base::failbit);
}
protected:
/// \brief Our streambuf class
std::unique_ptr<z_streambuf_type> m_gziobuf;
};
// --------------------------------------------------------------------
/// \brief Control output to files compressing the contents with gzip.
///
/// \tparam CharT Type of the character stream.
/// \tparam Traits Traits for character type, defaults to char_traits<_CharT>.
///
/// This is an ofstream implementation that can writeto named files compressing the content
/// with gzip directly. The class inherits from std::basic_ostream and offers all the
/// associated functionality.
template <typename CharT, typename Traits>
class basic_ofstream : public basic_ostream<CharT, Traits>
{
public:
using base_type = basic_ostream<CharT, Traits>;
using char_type = CharT;
using traits_type = Traits;
using filebuf_type = std::basic_filebuf<char_type, traits_type>;
using gzip_streambuf_type = basic_ogzip_streambuf<char_type, traits_type>;
basic_ofstream() = default;
~basic_ofstream()
{
close();
}
/// \brief Construct an ofstream
/// \param filename Null terminated string specifying the file to open
/// \param mode The mode in which to open the file
explicit basic_ofstream(const char *filename, std::ios_base::openmode mode = std::ios_base::out)
{
open(filename, mode);
}
/// \brief Construct an ofstream
/// \param filename std::string specifying the file to open
/// \param mode The mode in which to open the file
explicit basic_ofstream(const std::string &filename, std::ios_base::openmode mode = std::ios_base::out)
{
open(filename, mode);
}
/// \brief Construct an ofstream
/// \param filename std::filesystem::path specifying the file to open
/// \param mode The mode in which to open the file
explicit basic_ofstream(const std::filesystem::path &filename, std::ios_base::openmode mode = std::ios_base::out)
{
open(filename, mode);
}
/// \brief Move constructor
basic_ofstream(basic_ofstream &&rhs)
: base_type(std::move(rhs))
{
m_filebuf = std::move(rhs.m_filebuf);
if (this->m_gziobuf)
this->m_gziobuf->set_upstream(&m_filebuf);
else
this->rdbuf(&m_filebuf);
}
basic_ofstream(const basic_ofstream &) = delete;
basic_ofstream &operator=(const basic_ofstream &) = delete;
/// \brief Move operator=
basic_ofstream &operator=(basic_ofstream &&rhs)
{
base_type::operator=(std::move(rhs));
m_filebuf = std::move(rhs.m_filebuf);
if (this->m_gziobuf)
this->m_gziobuf->set_upstream(&m_filebuf);
else
this->rdbuf(&m_filebuf);
return *this;
}
/// \brief Open the file \a filename with mode \a mode
/// \param filename std::filesystem::path specifying the file to open
/// \param mode The mode in which to open the file
///
/// A compression algorithm is chosen upon the contents of the
/// extension() of \a filename with .gz mapping to gzip compression
/// and .xz to xz compression.
void open(const std::filesystem::path &filename, std::ios_base::openmode mode = std::ios_base::out)
{
if (not m_filebuf.open(filename, mode | std::ios::binary))
this->setstate(std::ios_base::failbit);
else
{
if (filename.extension() == ".gz")
this->m_gziobuf.reset(new gzip_streambuf_type);
else
this->m_gziobuf.reset(nullptr);
if (this->m_gziobuf)
{
if (not this->m_gziobuf->init(&m_filebuf))
this->setstate(std::ios_base::failbit);
else
{
this->rdbuf(this->m_gziobuf.get());
this->clear();
}
}
else
{
this->rdbuf(&m_filebuf);
this->clear();
}
}
}
/// \brief Open the file \a filename with mode \a mode
/// \param filename std::string specifying the file to open
/// \param mode The mode in which to open the file
///
/// A compression algorithm is chosen upon the contents of the
/// extension of \a filename with .gz mapping to gzip compression
/// and .xz to xz compression.
void open(const std::string &filename, std::ios_base::openmode mode = std::ios_base::out)
{
open(std::filesystem::path{filename}, mode);
}
/// \brief Open the file \a filename with mode \a mode
/// \param filename Null terminated string specifying the file to open
/// \param mode The mode in which to open the file
///
/// A compression algorithm is chosen upon the contents of the
/// extension of \a filename with .gz mapping to gzip compression
/// and .xz to xz compression.
void open(const char *filename, std::ios_base::openmode mode = std::ios_base::out)
{
open(std::filesystem::path{filename}, mode);
}
/// \brief Return true if the file is open
/// \return m_filebuf.is_open()
bool is_open() const
{
return m_filebuf.is_open();
}
/// \brief Close the file
///
/// Calls m_filebuf.close(). If that fails, the failbit is set.
void close()
{
if (this->m_gziobuf and not this->m_gziobuf->close())
this->setstate(std::ios_base::failbit);
if (not m_filebuf.close())
this->setstate(std::ios_base::failbit);
}
/// \brief Swap the contents with those of \a rhs
/// \param rhs The ifstream to swap with
void swap(basic_ofstream &rhs)
{
base_type::swap(rhs);
m_filebuf.swap(rhs.m_filebuf);
if (this->m_gziobuf)
{
this->m_gziobuf.set_upstream(&m_filebuf);
this->rdbuf(this->m_gziobuf.get());
}
else
this->rdbuf(&m_filebuf);
if (rhs.m_gziobuf)
{
rhs.m_gziobuf.set_upstream(&rhs.m_filebuf);
rhs.rdbuf(rhs.m_gziobuf.get());
}
else
rhs.rdbuf(&rhs.m_filebuf);
}
private:
/// \brief The filebuf
filebuf_type m_filebuf;
};
// --------------------------------------------------------------------
/// \brief Convenience typedefs
using istream = basic_istream<char, std::char_traits<char>>;
using ifstream = basic_ifstream<char, std::char_traits<char>>;
// using ostream = basic_ostream<char, std::char_traits<char>>;
using ofstream = basic_ofstream<char, std::char_traits<char>>;
} // namespace gzio
...@@ -24,9 +24,8 @@ ...@@ -24,9 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <gxrio.hpp>
#include <cif++/file.hpp> #include <cif++/file.hpp>
#include <cif++/gzio.hpp>
namespace cif namespace cif
{ {
...@@ -185,7 +184,7 @@ void file::load(const std::filesystem::path &p) ...@@ -185,7 +184,7 @@ void file::load(const std::filesystem::path &p)
{ {
try try
{ {
gxrio::ifstream in(p); gzio::ifstream in(p);
if (not in.is_open()) if (not in.is_open())
throw std::runtime_error("Could not open file " + p.string()); throw std::runtime_error("Could not open file " + p.string());
...@@ -213,7 +212,7 @@ void file::load(std::istream &is) ...@@ -213,7 +212,7 @@ void file::load(std::istream &is)
void file::save(const std::filesystem::path &p) const void file::save(const std::filesystem::path &p) const
{ {
gxrio::ofstream outFile(p); gzio::ofstream outFile(p);
save(outFile); save(outFile);
} }
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#include <iomanip> #include <iomanip>
#include <numeric> #include <numeric>
#include <gxrio.hpp>
namespace fs = std::filesystem; namespace fs = std::filesystem;
extern int VERBOSE; extern int VERBOSE;
...@@ -1193,42 +1191,6 @@ float branch::weight() const ...@@ -1193,42 +1191,6 @@ float branch::weight() const
return sum; }); return sum; });
} }
// // --------------------------------------------------------------------
// // File
// void File::load(const std::filesystem::path &path)
// {
// gxrio::ifstream in(path);
// auto ext = path.extension().string();
// if (ext == ".gz" or ext = ".xz")
// ext = path.stem().extension().string();
// if (ext == ".pdb" or ext == ".ent")
// ReadPDBFile(in, *this);
// else
// file::load(in);
// // validate, otherwise lots of functionality won't work
// loadDictionary("mmcif_pdbx");
// if (not isValid() and VERBOSE >= 0)
// std::cerr << "Invalid mmCIF file" << (VERBOSE > 0 ? "." : " use --verbose option to see errors") << std::endl;
// }
// void File::save(const std::filesystem::path &path)
// {
// gxrio::ostream outFile(path);
// auto ext = path.extension().string();
// if (ext == ".gz" or ext = ".xz")
// ext = path.stem().extension().string();
// if (ext == ".pdb" or ext == ".ent")
// WritePDBFile(outFile, data());
// else
// file::save(outFile);
// }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// structure // structure
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
#include <regex> #include <regex>
#include <set> #include <set>
#include <gxrio.hpp>
#include <cif++.hpp> #include <cif++.hpp>
#include <cif++/pdb/cif2pdb.hpp> #include <cif++/pdb/cif2pdb.hpp>
#include <cif++/gzio.hpp>
namespace cif::pdb namespace cif::pdb
{ {
...@@ -3731,7 +3731,7 @@ void write(std::ostream &os, const datablock &db) ...@@ -3731,7 +3731,7 @@ void write(std::ostream &os, const datablock &db)
void write(const std::filesystem::path &p, const datablock &db) void write(const std::filesystem::path &p, const datablock &db)
{ {
gxrio::ofstream out(p); gzio::ofstream out(p);
bool writePDB = false; bool writePDB = false;
if (p.extension() == ".gz") if (p.extension() == ".gz")
......
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
#include <stack> #include <stack>
#include <cif++.hpp> #include <cif++.hpp>
#include <gxrio.hpp>
#include <cif++/pdb/pdb2cif.hpp> #include <cif++/pdb/pdb2cif.hpp>
#include <cif++/pdb/pdb2cif_remark_3.hpp> #include <cif++/pdb/pdb2cif_remark_3.hpp>
#include <cif++/gzio.hpp>
using cif::category; using cif::category;
using cif::datablock; using cif::datablock;
...@@ -6225,7 +6225,7 @@ file read(const std::filesystem::path &file) ...@@ -6225,7 +6225,7 @@ file read(const std::filesystem::path &file)
{ {
try try
{ {
gxrio::ifstream in(file); gzio::ifstream in(file);
if (not in.is_open()) if (not in.is_open())
throw std::runtime_error("Could not open file " + file.string() + " for input"); throw std::runtime_error("Could not open file " + file.string() + " for input");
......
...@@ -41,12 +41,11 @@ using boost::regex; ...@@ -41,12 +41,11 @@ using boost::regex;
using std::regex; using std::regex;
#endif #endif
#include <gxrio.hpp>
#include <cif++/dictionary_parser.hpp> #include <cif++/dictionary_parser.hpp>
#include <cif++/validate.hpp> #include <cif++/validate.hpp>
#include <cif++/utilities.hpp> #include <cif++/utilities.hpp>
#include <cif++/gzio.hpp>
namespace cif namespace cif
{ {
...@@ -472,7 +471,7 @@ const validator &validator_factory::operator[](std::string_view dictionary_name) ...@@ -472,7 +471,7 @@ const validator &validator_factory::operator[](std::string_view dictionary_name)
if (std::filesystem::exists(p, ec) and not ec) if (std::filesystem::exists(p, ec) and not ec)
{ {
gxrio::ifstream in(p); gzio::ifstream in(p);
if (not in.is_open()) if (not in.is_open())
throw std::runtime_error("Could not open dictionary (" + p.string() + ")"); throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment