From dc33d6905a10bd84ef42b645a8643e25f23c040d Mon Sep 17 00:00:00 2001 From: Alexander Hoen Date: Tue, 14 May 2024 10:16:12 +0200 Subject: [PATCH 1/4] remove gzstream --- CHANGELOG | 3 + examples/TSP/CMakeLists.txt | 3 +- examples/TSP/Makefile | 3 +- examples/TSP/src/ReaderTSP.h | 4 +- examples/TSP/src/external/zstr/License.txt | 21 + examples/TSP/src/external/zstr/README | 2 + .../TSP/src/external/zstr/strict_fstream.hpp | 236 +++++++++ examples/TSP/src/external/zstr/zstr.hpp | 472 ++++++++++++++++++ examples/TSP/src/gzstream.cpp | 208 -------- examples/TSP/src/gzstream.h | 290 ----------- 10 files changed, 738 insertions(+), 504 deletions(-) create mode 100644 examples/TSP/src/external/zstr/License.txt create mode 100644 examples/TSP/src/external/zstr/README create mode 100644 examples/TSP/src/external/zstr/strict_fstream.hpp create mode 100644 examples/TSP/src/external/zstr/zstr.hpp delete mode 100644 examples/TSP/src/gzstream.cpp delete mode 100644 examples/TSP/src/gzstream.h diff --git a/CHANGELOG b/CHANGELOG index 84803c9859..f2d66e8769 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,9 @@ Fixed bugs Examples and applications ------------------------- +- TSP: remove `gzstream.h/hpp` (L-GPL) and replace it with `zstr` (MIT License) for `.gz` file handling + + Interface changes ----------------- diff --git a/examples/TSP/CMakeLists.txt b/examples/TSP/CMakeLists.txt index 45f15a6123..bc612f1b27 100644 --- a/examples/TSP/CMakeLists.txt +++ b/examples/TSP/CMakeLists.txt @@ -20,8 +20,7 @@ add_executable(sciptsp src/HeurFarthestInsert.cpp src/HeurFrats.cpp src/ProbDataTSP.cpp - src/ReaderTSP.cpp - src/gzstream.cpp) + src/ReaderTSP.cpp) target_link_libraries(sciptsp ${SCIP_LIBRARIES}) diff --git a/examples/TSP/Makefile b/examples/TSP/Makefile index 3501294837..4055ea5a0b 100644 --- a/examples/TSP/Makefile +++ b/examples/TSP/Makefile @@ -80,8 +80,7 @@ MAINOBJ = cppmain.o \ EventhdlrNewSol.o \ HeurFarthestInsert.o \ HeurFrats.o \ - Heur2opt.o \ - gzstream.o + Heur2opt.o MAINSRC = $(addprefix $(SRCDIR)/,$(MAINOBJ:.o=.cpp)) MAIN = $(MAINNAME).$(BASE).$(LPS)$(EXEEXTENSION) diff --git a/examples/TSP/src/ReaderTSP.h b/examples/TSP/src/ReaderTSP.h index 07fba7450a..5fc88e0e26 100644 --- a/examples/TSP/src/ReaderTSP.h +++ b/examples/TSP/src/ReaderTSP.h @@ -40,8 +40,8 @@ #include "scip/def.h" #ifdef SCIP_WITH_ZLIB -#include "gzstream.h" -typedef gzstream::igzstream tspifstream; +#include "external/zstr/zstr.hpp" +typedef zstr::ifstream tspifstream; #else typedef std::ifstream tspifstream; #endif diff --git a/examples/TSP/src/external/zstr/License.txt b/examples/TSP/src/external/zstr/License.txt new file mode 100644 index 0000000000..3c33ea696e --- /dev/null +++ b/examples/TSP/src/external/zstr/License.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Matei David, Ontario Institute for Cancer Research + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/examples/TSP/src/external/zstr/README b/examples/TSP/src/external/zstr/README new file mode 100644 index 0000000000..ff801cad91 --- /dev/null +++ b/examples/TSP/src/external/zstr/README @@ -0,0 +1,2 @@ +This directory contains zstr 1.0.5 form https://github.com/mateidavid/zstr. +The code is licensed under MIT license, see ../../LICENSE. diff --git a/examples/TSP/src/external/zstr/strict_fstream.hpp b/examples/TSP/src/external/zstr/strict_fstream.hpp new file mode 100644 index 0000000000..007e0f6c23 --- /dev/null +++ b/examples/TSP/src/external/zstr/strict_fstream.hpp @@ -0,0 +1,236 @@ +#pragma once + +#include +#include +#include +#include +#include + +/** + * This namespace defines wrappers for std::ifstream, std::ofstream, and + * std::fstream objects. The wrappers perform the following steps: + * - check the open modes make sense + * - check that the call to open() is successful + * - (for input streams) check that the opened file is peek-able + * - turn on the badbit in the exception mask + */ +namespace strict_fstream +{ + +// Help people out a bit, it seems like this is a common recommenation since +// musl breaks all over the place. +#if defined(__NEED_size_t) && !defined(__MUSL__) +#warning "It seems to be recommended to patch in a define for __MUSL__ if you use musl globally: https://www.openwall.com/lists/musl/2013/02/10/5" +#define __MUSL__ +#endif + +// Workaround for broken musl implementation +// Since musl insists that they are perfectly compatible, ironically enough, +// they don't officially have a __musl__ or similar. But __NEED_size_t is defined in their +// relevant header (and not in working implementations), so we can use that. +#ifdef __MUSL__ +#warning "Working around broken strerror_r() implementation in musl, remove when musl is fixed" +#endif + +// Non-gnu variants of strerror_* don't necessarily null-terminate if +// truncating, so we have to do things manually. +inline std::string trim_to_null(const std::vector &buff) +{ + std::string ret(buff.begin(), buff.end()); + + const std::string::size_type pos = ret.find('\0'); + if (pos == std::string::npos) { + ret += " [...]"; // it has been truncated + } else { + ret.resize(pos); + } + return ret; +} + +/// Overload of error-reporting function, to enable use with VS and non-GNU +/// POSIX libc's +/// Ref: +/// - http://stackoverflow.com/a/901316/717706 +static std::string strerror() +{ + // Can't use std::string since we're pre-C++17 + std::vector buff(256, '\0'); + +#ifdef _WIN32 + // Since strerror_s might set errno itself, we need to store it. + const int err_num = errno; + if (strerror_s(buff.data(), buff.size(), err_num) != 0) { + return trim_to_null(buff); + } else { + return "Unknown error (" + std::to_string(err_num) + ")"; + } +#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__APPLE__) || defined(__FreeBSD__)) && ! _GNU_SOURCE) || defined(__MUSL__) +// XSI-compliant strerror_r() + const int err_num = errno; // See above + if (strerror_r(err_num, buff.data(), buff.size()) == 0) { + return trim_to_null(buff); + } else { + return "Unknown error (" + std::to_string(err_num) + ")"; + } +#else +// GNU-specific strerror_r() + char * p = strerror_r(errno, &buff[0], buff.size()); + return std::string(p, std::strlen(p)); +#endif +} + +/// Exception class thrown by failed operations. +class Exception + : public std::exception +{ +public: + Exception(const std::string& msg) : _msg(msg) {} + const char * what() const noexcept { return _msg.c_str(); } +private: + std::string _msg; +}; // class Exception + +namespace detail +{ + +struct static_method_holder +{ + static std::string mode_to_string(std::ios_base::openmode mode) + { + static const int n_modes = 6; + static const std::ios_base::openmode mode_val_v[n_modes] = + { + std::ios_base::in, + std::ios_base::out, + std::ios_base::app, + std::ios_base::ate, + std::ios_base::trunc, + std::ios_base::binary + }; + + static const char * mode_name_v[n_modes] = + { + "in", + "out", + "app", + "ate", + "trunc", + "binary" + }; + std::string res; + for (int i = 0; i < n_modes; ++i) + { + if (mode & mode_val_v[i]) + { + res += (! res.empty()? "|" : ""); + res += mode_name_v[i]; + } + } + if (res.empty()) res = "none"; + return res; + } + static void check_mode(const std::string& filename, std::ios_base::openmode mode) + { + if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out)) + { + throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out"); + } + else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out)) + { + throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out"); + } + else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app)) + { + throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app"); + } + } + static void check_open(std::ios * s_p, const std::string& filename, std::ios_base::openmode mode) + { + if (s_p->fail()) + { + throw Exception(std::string("strict_fstream: open('") + + filename + "'," + mode_to_string(mode) + "): open failed: " + + strerror()); + } + } + static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode) + { + bool peek_failed = true; + try + { + is_p->peek(); + peek_failed = is_p->fail(); + } + catch (const std::ios_base::failure &) {} + if (peek_failed) + { + throw Exception(std::string("strict_fstream: open('") + + filename + "'," + mode_to_string(mode) + "): peek failed: " + + strerror()); + } + is_p->clear(); + } +}; // struct static_method_holder + +} // namespace detail + +class ifstream + : public std::ifstream +{ +public: + ifstream() = default; + ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) + { + open(filename, mode); + } + void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) + { + mode |= std::ios_base::in; + exceptions(std::ios_base::badbit); + detail::static_method_holder::check_mode(filename, mode); + std::ifstream::open(filename, mode); + detail::static_method_holder::check_open(this, filename, mode); + detail::static_method_holder::check_peek(this, filename, mode); + } +}; // class ifstream + +class ofstream + : public std::ofstream +{ +public: + ofstream() = default; + ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out) + { + open(filename, mode); + } + void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out) + { + mode |= std::ios_base::out; + exceptions(std::ios_base::badbit); + detail::static_method_holder::check_mode(filename, mode); + std::ofstream::open(filename, mode); + detail::static_method_holder::check_open(this, filename, mode); + } +}; // class ofstream + +class fstream + : public std::fstream +{ +public: + fstream() = default; + fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) + { + open(filename, mode); + } + void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) + { + if (! (mode & std::ios_base::out)) mode |= std::ios_base::in; + exceptions(std::ios_base::badbit); + detail::static_method_holder::check_mode(filename, mode); + std::fstream::open(filename, mode); + detail::static_method_holder::check_open(this, filename, mode); + detail::static_method_holder::check_peek(this, filename, mode); + } +}; // class fstream + +} // namespace strict_fstream diff --git a/examples/TSP/src/external/zstr/zstr.hpp b/examples/TSP/src/external/zstr/zstr.hpp new file mode 100644 index 0000000000..239909f9e7 --- /dev/null +++ b/examples/TSP/src/external/zstr/zstr.hpp @@ -0,0 +1,472 @@ +//--------------------------------------------------------- +// Copyright 2015 Ontario Institute for Cancer Research +// Written by Matei David (matei@cs.toronto.edu) +//--------------------------------------------------------- + +// Reference: +// http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c + +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "strict_fstream.hpp" + +namespace zstr { + +static const std::size_t default_buff_size = static_cast(1 << 20); + +/// Exception class thrown by failed zlib operations. +class Exception : public std::ios_base::failure { + public: + static std::string error_to_message(z_stream* zstrm_p, int ret) { + std::string msg = "zlib: "; + switch (ret) { + case Z_STREAM_ERROR: + msg += "Z_STREAM_ERROR: "; + break; + case Z_DATA_ERROR: + msg += "Z_DATA_ERROR: "; + break; + case Z_MEM_ERROR: + msg += "Z_MEM_ERROR: "; + break; + case Z_VERSION_ERROR: + msg += "Z_VERSION_ERROR: "; + break; + case Z_BUF_ERROR: + msg += "Z_BUF_ERROR: "; + break; + default: + std::ostringstream oss; + oss << ret; + msg += "[" + oss.str() + "]: "; + break; + } + if (zstrm_p->msg) { + msg += zstrm_p->msg; + } + msg += + " (" + "next_in: " + + std::to_string(uintptr_t(zstrm_p->next_in)) + + ", avail_in: " + std::to_string(uintptr_t(zstrm_p->avail_in)) + + ", next_out: " + std::to_string(uintptr_t(zstrm_p->next_out)) + + ", avail_out: " + std::to_string(uintptr_t(zstrm_p->avail_out)) + ")"; + return msg; + } + + Exception(z_stream* zstrm_p, int ret) + : std::ios_base::failure(error_to_message(zstrm_p, ret)) {} +}; // class Exception + +namespace detail { + +class z_stream_wrapper : public z_stream { + public: + z_stream_wrapper(bool _is_input, int _level, int _window_bits) + : is_input(_is_input) { + this->zalloc = nullptr; // Z_NULL + this->zfree = nullptr; // Z_NULL + this->opaque = nullptr; // Z_NULL + int ret; + if (is_input) { + this->avail_in = 0; + this->next_in = nullptr; // Z_NULL + ret = inflateInit2(this, _window_bits ? _window_bits : 15 + 32); + } else { + ret = deflateInit2(this, _level, Z_DEFLATED, + _window_bits ? _window_bits : 15 + 16, 8, + Z_DEFAULT_STRATEGY); + } + if (ret != Z_OK) throw Exception(this, ret); + } + ~z_stream_wrapper() { + if (is_input) { + inflateEnd(this); + } else { + deflateEnd(this); + } + } + + private: + bool is_input; +}; // class z_stream_wrapper + +} // namespace detail + +class istreambuf : public std::streambuf { + public: + istreambuf(std::streambuf* _sbuf_p, + std::size_t _buff_size = default_buff_size, + bool _auto_detect = true, int _window_bits = 0) + : sbuf_p(_sbuf_p), + in_buff(), + in_buff_start(nullptr), + in_buff_end(nullptr), + out_buff(), + zstrm_p(nullptr), + buff_size(_buff_size), + auto_detect(_auto_detect), + auto_detect_run(false), + is_text(false), + window_bits(_window_bits) { + assert(sbuf_p); + in_buff = std::unique_ptr(new char[buff_size]); + in_buff_start = in_buff.get(); + in_buff_end = in_buff.get(); + out_buff = std::unique_ptr(new char[buff_size]); + setg(out_buff.get(), out_buff.get(), out_buff.get()); + } + + istreambuf(const istreambuf&) = delete; + istreambuf& operator=(const istreambuf&) = delete; + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode which) override { + if (off != 0 || dir != std::ios_base::cur) { + return std::streambuf::seekoff(off, dir, which); + } + + if (!zstrm_p) { + return 0; + } + + return static_cast(zstrm_p->total_out - + static_cast(in_avail())); + } + + std::streambuf::int_type underflow() override { + if (this->gptr() == this->egptr()) { + // pointers for free region in output buffer + char* out_buff_free_start = out_buff.get(); + int tries = 0; + do { + if (++tries > 1000) { + throw std::ios_base::failure( + "Failed to fill buffer after 1000 tries"); + } + + // read more input if none available + if (in_buff_start == in_buff_end) { + // empty input buffer: refill from the start + in_buff_start = in_buff.get(); + std::streamsize sz = sbuf_p->sgetn( + in_buff.get(), static_cast(buff_size)); + in_buff_end = in_buff_start + sz; + if (in_buff_end == in_buff_start) break; // end of input + } + // auto detect if the stream contains text or deflate data + if (auto_detect && !auto_detect_run) { + auto_detect_run = true; + unsigned char b0 = *reinterpret_cast(in_buff_start); + unsigned char b1 = + *reinterpret_cast(in_buff_start + 1); + // Ref: + // http://en.wikipedia.org/wiki/Gzip + // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like + is_text = !(in_buff_start + 2 <= in_buff_end && + ((b0 == 0x1F && b1 == 0x8B) // gzip header + || (b0 == 0x78 && (b1 == 0x01 // zlib header + || b1 == 0x9C || b1 == 0xDA)))); + } + if (is_text) { + // simply swap in_buff and out_buff, and adjust pointers + assert(in_buff_start == in_buff.get()); + std::swap(in_buff, out_buff); + out_buff_free_start = in_buff_end; + in_buff_start = in_buff.get(); + in_buff_end = in_buff.get(); + } else { + // run inflate() on input + if (!zstrm_p) + zstrm_p = std::unique_ptr( + new detail::z_stream_wrapper(true, Z_DEFAULT_COMPRESSION, + window_bits)); + zstrm_p->next_in = + reinterpret_castnext_in)>(in_buff_start); + zstrm_p->avail_in = uint32_t(in_buff_end - in_buff_start); + zstrm_p->next_out = reinterpret_castnext_out)>( + out_buff_free_start); + zstrm_p->avail_out = + uint32_t((out_buff.get() + buff_size) - out_buff_free_start); + int ret = inflate(zstrm_p.get(), Z_NO_FLUSH); + // process return code + if (ret != Z_OK && ret != Z_STREAM_END) + throw Exception(zstrm_p.get(), ret); + // update in&out pointers following inflate() + in_buff_start = + reinterpret_cast(zstrm_p->next_in); + in_buff_end = in_buff_start + zstrm_p->avail_in; + out_buff_free_start = reinterpret_cast( + zstrm_p->next_out); + assert(out_buff_free_start + zstrm_p->avail_out == + out_buff.get() + buff_size); + + if (ret == Z_STREAM_END) { + // if stream ended, deallocate inflator + zstrm_p.reset(); + } + } + } while (out_buff_free_start == out_buff.get()); + // 2 exit conditions: + // - end of input: there might or might not be output available + // - out_buff_free_start != out_buff: output available + this->setg(out_buff.get(), out_buff.get(), out_buff_free_start); + } + return this->gptr() == this->egptr() + ? traits_type::eof() + : traits_type::to_int_type(*this->gptr()); + } + + private: + std::streambuf* sbuf_p; + std::unique_ptr in_buff; + char* in_buff_start; + char* in_buff_end; + std::unique_ptr out_buff; + std::unique_ptr zstrm_p; + std::size_t buff_size; + bool auto_detect; + bool auto_detect_run; + bool is_text; + int window_bits; + +}; // class istreambuf + +class ostreambuf : public std::streambuf { + public: + ostreambuf(std::streambuf* _sbuf_p, + std::size_t _buff_size = default_buff_size, + int _level = Z_DEFAULT_COMPRESSION, int _window_bits = 0) + : sbuf_p(_sbuf_p), + in_buff(), + out_buff(), + zstrm_p(new detail::z_stream_wrapper(false, _level, _window_bits)), + buff_size(_buff_size) { + assert(sbuf_p); + in_buff = std::unique_ptr(new char[buff_size]); + out_buff = std::unique_ptr(new char[buff_size]); + setp(in_buff.get(), in_buff.get() + buff_size); + } + + ostreambuf(const ostreambuf&) = delete; + ostreambuf& operator=(const ostreambuf&) = delete; + + int deflate_loop(int flush) { + while (true) { + zstrm_p->next_out = + reinterpret_castnext_out)>(out_buff.get()); + zstrm_p->avail_out = uint32_t(buff_size); + int ret = deflate(zstrm_p.get(), flush); + if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) { + failed = true; + throw Exception(zstrm_p.get(), ret); + } + std::streamsize sz = sbuf_p->sputn( + out_buff.get(), + reinterpret_cast(zstrm_p->next_out) - + out_buff.get()); + if (sz != reinterpret_cast(zstrm_p->next_out) - + out_buff.get()) { + // there was an error in the sink stream + return -1; + } + if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0) { + break; + } + } + return 0; + } + + virtual ~ostreambuf() { + // flush the zlib stream + // + // NOTE: Errors here (sync() return value not 0) are ignored, because we + // cannot throw in a destructor. This mirrors the behaviour of + // std::basic_filebuf::~basic_filebuf(). To see an exception on error, + // close the ofstream with an explicit call to close(), and do not rely + // on the implicit call in the destructor. + // + if (!failed) try { + sync(); + } catch (...) { + } + } + std::streambuf::int_type overflow( + std::streambuf::int_type c = traits_type::eof()) override { + zstrm_p->next_in = reinterpret_castnext_in)>(pbase()); + zstrm_p->avail_in = uint32_t(pptr() - pbase()); + while (zstrm_p->avail_in > 0) { + int r = deflate_loop(Z_NO_FLUSH); + if (r != 0) { + setp(nullptr, nullptr); + return traits_type::eof(); + } + } + setp(in_buff.get(), in_buff.get() + buff_size); + return traits_type::eq_int_type(c, traits_type::eof()) + ? traits_type::eof() + : sputc(char_type(c)); + } + int sync() override { + // first, call overflow to clear in_buff + overflow(); + if (!pptr()) return -1; + // then, call deflate asking to finish the zlib stream + zstrm_p->next_in = nullptr; + zstrm_p->avail_in = 0; + if (deflate_loop(Z_FINISH) != 0) return -1; + deflateReset(zstrm_p.get()); + return 0; + } + + private: + std::streambuf* sbuf_p = nullptr; + std::unique_ptr in_buff; + std::unique_ptr out_buff; + std::unique_ptr zstrm_p; + std::size_t buff_size; + bool failed = false; + +}; // class ostreambuf + +class istream : public std::istream { + public: + istream(std::istream& is, std::size_t _buff_size = default_buff_size, + bool _auto_detect = true, int _window_bits = 0) + : std::istream(new istreambuf(is.rdbuf(), _buff_size, _auto_detect, + _window_bits)) { + exceptions(std::ios_base::badbit); + } + explicit istream(std::streambuf* sbuf_p) + : std::istream(new istreambuf(sbuf_p)) { + exceptions(std::ios_base::badbit); + } + virtual ~istream() { delete rdbuf(); } +}; // class istream + +class ostream : public std::ostream { + public: + ostream(std::ostream& os, std::size_t _buff_size = default_buff_size, + int _level = Z_DEFAULT_COMPRESSION, int _window_bits = 0) + : std::ostream( + new ostreambuf(os.rdbuf(), _buff_size, _level, _window_bits)) { + exceptions(std::ios_base::badbit); + } + explicit ostream(std::streambuf* sbuf_p) + : std::ostream(new ostreambuf(sbuf_p)) { + exceptions(std::ios_base::badbit); + } + virtual ~ostream() { delete rdbuf(); } +}; // class ostream + +namespace detail { + +template +struct strict_fstream_holder { + strict_fstream_holder(const std::string& filename, + std::ios_base::openmode mode = std::ios_base::in) + : _fs(filename, mode) {} + strict_fstream_holder() = default; + FStream_Type _fs{}; +}; // class strict_fstream_holder + +} // namespace detail + +class ifstream + : private detail::strict_fstream_holder, + public std::istream { + public: + explicit ifstream(const std::string filename, + std::ios_base::openmode mode = std::ios_base::in, + size_t buff_size = default_buff_size) + : detail::strict_fstream_holder( + filename, mode +#ifdef _WIN32 // to avoid problems with conversion of \r\n, only windows as + // otherwise there are problems on mac + | std::ios_base::binary +#endif + ), + std::istream(new istreambuf(_fs.rdbuf(), buff_size)) { + exceptions(std::ios_base::badbit); + } + explicit ifstream() + : detail::strict_fstream_holder(), + std::istream(new istreambuf(_fs.rdbuf())) {} + void close() { _fs.close(); } + void open(const std::string filename, + std::ios_base::openmode mode = std::ios_base::in) { + _fs.open(filename, mode +#ifdef _WIN32 // to avoid problems with conversion of \r\n, only windows as + // otherwise there are problems on mac + | std::ios_base::binary +#endif + ); + // make sure the previous buffer is deleted by putting it into a unique_ptr + // and set a new one after opening file + std::unique_ptr oldbuf(rdbuf(new istreambuf(_fs.rdbuf()))); + // call move assignment operator on istream which does not alter the stream + // buffer + std::istream::operator=(std::istream(rdbuf())); + } + bool is_open() const { return _fs.is_open(); } + virtual ~ifstream() { + if (_fs.is_open()) close(); + if (rdbuf()) delete rdbuf(); + } + + /// Return the position within the compressed file (wrapped filestream) + std::streampos compressed_tellg() { return _fs.tellg(); } +}; // class ifstream + +class ofstream + : private detail::strict_fstream_holder, + public std::ostream { + public: + explicit ofstream(const std::string filename, + std::ios_base::openmode mode = std::ios_base::out, + int level = Z_DEFAULT_COMPRESSION, + size_t buff_size = default_buff_size) + : detail::strict_fstream_holder( + filename, mode | std::ios_base::binary), + std::ostream(new ostreambuf(_fs.rdbuf(), buff_size, level)) { + exceptions(std::ios_base::badbit); + } + explicit ofstream() + : detail::strict_fstream_holder(), + std::ostream(new ostreambuf(_fs.rdbuf())) {} + void close() { + std::ostream::flush(); + _fs.close(); + } + void open(const std::string filename, + std::ios_base::openmode mode = std::ios_base::out, + int level = Z_DEFAULT_COMPRESSION) { + flush(); + _fs.open(filename, mode | std::ios_base::binary); + std::ostream::operator=( + std::ostream(new ostreambuf(_fs.rdbuf(), default_buff_size, level))); + } + bool is_open() const { return _fs.is_open(); } + ofstream& flush() { + std::ostream::flush(); + _fs.flush(); + return *this; + } + virtual ~ofstream() { + if (_fs.is_open()) close(); + if (rdbuf()) delete rdbuf(); + } + + // Return the position within the compressed file (wrapped filestream) + std::streampos compressed_tellp() { return _fs.tellp(); } +}; // class ofstream + +} // namespace zstr diff --git a/examples/TSP/src/gzstream.cpp b/examples/TSP/src/gzstream.cpp deleted file mode 100644 index 8f832b2d65..0000000000 --- a/examples/TSP/src/gzstream.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include "scip/def.h" - -#ifdef SCIP_WITH_ZLIB - -// ============================================================================ -// gzstream, C++ iostream classes wrapping the zlib compression library. -// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// ============================================================================ -// -// File : gzstream.C -// Revision : $Revision: 1.8 $ -// Revision_date : $Date: 2005/12/07 18:03:25 $ -// Author(s) : Deepak Bandyopadhyay, Lutz Kettner -// -// Standard streambuf implementation following Nicolai Josuttis, "The -// Standard C++ Library". -// ============================================================================ - -#include "gzstream.h" -#include -#include // for memcpy - -#ifdef GZSTREAM_NAMESPACE -namespace GZSTREAM_NAMESPACE -{ -#endif - -// ---------------------------------------------------------------------------- -// Internal classes to implement gzstream. See header file for user classes. -// ---------------------------------------------------------------------------- - -// -------------------------------------- -// class gzstreambuf: -// -------------------------------------- - -gzstreambuf* gzstreambuf::open(const char* _name, int _open_mode) -{ - if(is_open()) - return 0; - - mode = static_cast(_open_mode); - - // no append nor read/write mode - if((mode & std::ios::ate) || (mode & std::ios::app) - || ((mode & std::ios::in) && (mode & std::ios::out))) - return 0; - - char fmode[10]; - char* fmodeptr = fmode; - - if(mode & std::ios::in) - *fmodeptr++ = 'r'; - else if(mode & std::ios::out) - *fmodeptr++ = 'w'; - - *fmodeptr++ = 'b'; - *fmodeptr = '\0'; - file = gzopen(_name, fmode); - - if(file == 0) - return 0; - - opened = 1; - return this; -} - -gzstreambuf* gzstreambuf::close() -{ - if(is_open()) - { - sync(); - opened = 0; - - if(gzclose(file) == Z_OK) - return this; - } - - return 0; -} - -int gzstreambuf::underflow() // used for input buffer only -{ - if(gptr() && (gptr() < egptr())) - return * reinterpret_cast(gptr()); - - if(!(mode & std::ios::in) || ! opened) - return EOF; - - // Josuttis' implementation of inbuf - size_t n_putback = (size_t)(gptr() - eback()); - - if(n_putback > 4) - n_putback = 4; - - memcpy(buffer + (4 - n_putback), gptr() - n_putback, n_putback); - - int num = gzread(file, buffer + 4, bufferSize - 4); - - if(num <= 0) // ERROR or EOF - return EOF; - - // reset buffer pointers - setg(buffer + (4 - n_putback), // beginning of putback area - buffer + 4, // read position - buffer + 4 + num); // end of buffer - - // return next character - return * reinterpret_cast(gptr()); -} - -int gzstreambuf::flush_buffer() -{ - // Separate the writing of the buffer from overflow() and - // sync() operation. - int w = static_cast(pptr() - pbase()); - - if(gzwrite(file, pbase(), (unsigned int) w) != w) - return EOF; - - pbump(-w); - return w; -} - -int gzstreambuf::overflow(int c) // used for output buffer only -{ - if(!(mode & std::ios::out) || ! opened) - return EOF; - - if(c != EOF) - { - *pptr() = static_cast(c); - pbump(1); - } - - if(flush_buffer() == EOF) - return EOF; - - return c; -} - -int gzstreambuf::sync() -{ - // Changed to use flush_buffer() instead of overflow( EOF) - // which caused improper behavior with std::endl and flush(), - // bug reported by Vincent Ricard. - if(pptr() && pptr() > pbase()) - { - if(flush_buffer() == EOF) - return -1; - } - - return 0; -} - -// -------------------------------------- -// class gzstreambase: -// -------------------------------------- - -gzstreambase::gzstreambase(const char* name, int mode) -{ - init(&buf); - open(name, mode); -} - -gzstreambase::~gzstreambase() -{ - buf.close(); -} - -void gzstreambase::open(const char* _name, int _open_mode) -{ - if(! buf.open(_name, _open_mode)) - setstate(std::ios::badbit); - - // clear( rdstate() | std::ios::badbit); -} - -void gzstreambase::close() -{ - if(buf.is_open()) - if(! buf.close()) - setstate(std::ios::badbit); - - // clear( rdstate() | std::ios::badbit); -} - -#ifdef GZSTREAM_NAMESPACE -} // namespace GZSTREAM_NAMESPACE -#endif - -// ============================================================================ -// EOF // - -#endif diff --git a/examples/TSP/src/gzstream.h b/examples/TSP/src/gzstream.h deleted file mode 100644 index 05d79491a8..0000000000 --- a/examples/TSP/src/gzstream.h +++ /dev/null @@ -1,290 +0,0 @@ -#include "scip/def.h" - -#ifdef SCIP_WITH_ZLIB - -// ============================================================================ -// gzstream, C++ iostream classes wrapping the zlib compression library. -// Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// ============================================================================ -// -// File : gzstream.h -// Revision : $Revision: 1.8 $ -// Revision_date : $Date: 2005/11/09 13:53:50 $ -// Author(s) : Deepak Bandyopadhyay, Lutz Kettner -// -// Standard streambuf implementation following Nicolai Josuttis, "The -// Standard C++ Library". -// ============================================================================ - -/**@file gzstream.h - * @brief Utilities for handling gzipped input and output streams. - */ -#ifndef GZSTREAM_H -#define GZSTREAM_H 1 - -// standard C++ with new header file names and std:: namespace -#include -#include -#include - -#define GZSTREAM_NAMESPACE gzstream - -#ifdef GZSTREAM_NAMESPACE -namespace GZSTREAM_NAMESPACE -{ -#endif - -// ---------------------------------------------------------------------------- -// Internal classes to implement gzstream. See below for user classes. -// ---------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -// class gzstreambuf -// ---------------------------------------------------------------------------- - -/**@class gzstreambuf - @brief Internal class to implement gzstream. -*/ -class gzstreambuf - : public std::streambuf -{ -private: - - //------------------------------------ - /**@name Types */ - //@{ - /// - static const int bufferSize = 47 + 256; ///< size of data buff - // totals 512 bytes under g++ for igzstream at the end. - //@} - - //------------------------------------ - /**@name Data */ - //@{ - gzFile file; ///< file handle for compressed file - char buffer[bufferSize]; ///< data buffer - char opened; ///< open/close state of stream - unsigned int mode; ///< I/O mode - //@} - - //------------------------------------ - /**@name Internal helpers */ - //@{ - /// - int flush_buffer(); - //@} - -public: - - //------------------------------------ - /**@name Construction / destruction */ - //@{ - /// default constructor - gzstreambuf() - : file(0) - , opened(0) - , mode(0) - { - setp(buffer, buffer + (bufferSize - 1)); - setg(buffer + 4, // beginning of putback area - buffer + 4, // read position - buffer + 4); // end position - // ASSERT: both input & output capabilities will not be used together - } - /// destructor - ~gzstreambuf() - { - (void) close(); - } - //@} - - //------------------------------------ - /**@name Interface */ - //@{ - /// - int is_open() - { - return opened; - } - /// - gzstreambuf* open(const char* name, int open_mode); - /// - gzstreambuf* close(); - /// - virtual int overflow(int c = EOF); - /// - virtual int underflow(); - /// - virtual int sync(); - //@} -}; - -// ---------------------------------------------------------------------------- -// class gzstreambase -// ---------------------------------------------------------------------------- - -/**@class gzstreambase - @brief Internal class to implement gzstream. -*/ -class gzstreambase - : virtual public std::ios -{ -protected: - - //------------------------------------ - /**@name Data */ - //@{ - /// - gzstreambuf buf; - //@} - -public: - - //------------------------------------ - /**@name Construction / destruction */ - //@{ - /// default constructor - gzstreambase() - { - init(&buf); - } - /// full constructor - gzstreambase(const char* _name, int _open_mode); - /// destructor - ~gzstreambase(); - //@} - - //------------------------------------ - /**@name Interface */ - //@{ - /// - void open(const char* _name, int _open_mode); - /// - void close(); - /// - gzstreambuf* rdbuf() - { - return &buf; - } - //@} -}; - -// ---------------------------------------------------------------------------- -// User classes. Use igzstream and ogzstream analogously to ifstream and -// ofstream respectively. They read and write files based on the gz* -// function interface of the zlib. Files are compatible with gzip compression. -// ---------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -// class igzstream -// ---------------------------------------------------------------------------- - -/**@class igzstream - @brief Class to implement a gzip'd input stream. -*/ -class igzstream - : public std::istream - , public gzstreambase -{ -public: - - //------------------------------------ - /**@name Construction / destruction */ - //@{ - /// default constructor - igzstream() - : std::istream(&buf) - {} - /// full constructor - igzstream(const char* _name, - int _open_mode = std::ios::in) - : std::istream(&buf) - , gzstreambase(_name, _open_mode) - {} - //@} - - //------------------------------------ - /**@name Interface */ - //@{ - /// - gzstreambuf* rdbuf() - { - return gzstreambase::rdbuf(); - } - /// - void open(const char* _name, - int _open_mode = std::ios::in) - { - gzstreambase::open(_name, _open_mode); - } - //@} -}; - -// ---------------------------------------------------------------------------- -// class ogzstream -// ---------------------------------------------------------------------------- - -/**@class ogzstream - @brief Class to implement a gzip'd output stream. -*/ -class ogzstream - : public gzstreambase - , public std::ostream -{ -public: - - //------------------------------------ - /**@name Construction / destruction */ - //@{ - /// default constructor - ogzstream() - : std::ostream(&buf) - {} - /// full constructor - explicit - ogzstream(const char* _name, - int _open_mode = std::ios::out) - : gzstreambase(_name, _open_mode) - , std::ostream(&buf) - {} - //@} - - //------------------------------------ - /**@name Interface */ - //@{ - /// - gzstreambuf* rdbuf() - { - return gzstreambase::rdbuf(); - } - /// - void open(const char* _name, - int _open_mode = std::ios::out) - { - gzstreambase::open(_name, _open_mode); - } -}; - -#ifdef GZSTREAM_NAMESPACE -} // namespace GZSTREAM_NAMESPACE -#endif - -#endif // GZSTREAM_H -// ============================================================================ -// EOF // - -#endif From da4741c2b0fba6444a2562397a27d516a2573b77 Mon Sep 17 00:00:00 2001 From: Marc Pfetsch Date: Tue, 14 May 2024 14:56:36 +0200 Subject: [PATCH 2/4] rewrite reading using SCIP functions --- examples/TSP/src/ReaderTSP.cpp | 108 ++++++++++++++++++++++++--------- examples/TSP/src/ReaderTSP.h | 17 ++---- 2 files changed, 84 insertions(+), 41 deletions(-) diff --git a/examples/TSP/src/ReaderTSP.cpp b/examples/TSP/src/ReaderTSP.cpp index faaf46412f..a0a1248302 100644 --- a/examples/TSP/src/ReaderTSP.cpp +++ b/examples/TSP/src/ReaderTSP.cpp @@ -30,13 +30,13 @@ /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ #include -#include #include #include #include "objscip/objscip.h" #include "scip/cons_linear.h" +#include "scip/pub_fileio.h" #include #include "ReaderTSP.h" @@ -50,23 +50,66 @@ using namespace std; #define NINT(x) (floor(x+0.5)) +/** get token */ +string getToken(char*& str) +{ + string token; + + // skip spaces and ':' + while( *str != '\0' && ( isspace(*str) || *str == ':') ) + ++str; + + // collect token + while( *str != '\0' && *str != ':' && ! isspace(*str) ) + { + token += *str; + ++str; + } + + // skip spaces and ':' + while( *str != '\0' && ( isspace(*str) || *str == ':') ) + ++str; + + return token; +} /** parses the node list */ -void ReaderTSP::getNodesFromFile( - tspifstream& filedata, /**< filestream containing the data to extract */ +SCIP_RETCODE ReaderTSP::getNodesFromFile( + SCIP_FILE* file, /**< file containing the data to extract */ double* x_coords, /**< double array to be filled with the x-coordinates of the nodes */ double* y_coords, /**< same for y-coordinates */ GRAPH* graph /**< the graph which is to be generated by the nodes */ ) { + char str[SCIP_MAXSTRLEN]; int i = 0; int nodenumber; GRAPHNODE* node = &(graph->nodes[0]); // extract every node out of the filestream - while ( i < graph->nnodes && !filedata.eof() ) + while ( i < graph->nnodes && ! SCIPfeof(file) ) { - filedata >> nodenumber >> x_coords[i] >> y_coords[i]; + // read next line + (void) SCIPfgets(str, SCIP_MAXSTRLEN, file); + char* s = str; + + if ( ! SCIPstrToIntValue(str, &nodenumber, &s) ) + { + SCIPerrorMessage("Could not read node number:\n%s\n", str); + return SCIP_INVALIDDATA; + } + + if ( ! SCIPstrToRealValue(s, &x_coords[i], &s) ) + { + SCIPerrorMessage("Could not read x coordinate:\n%s\n", str); + return SCIP_INVALIDDATA; + } + + if ( ! SCIPstrToRealValue(s, &y_coords[i], &s) ) + { + SCIPerrorMessage("Could not read x coordinate:\n%s\n", str); + return SCIP_INVALIDDATA; + } // assign everything node->id = i; @@ -74,6 +117,7 @@ void ReaderTSP::getNodesFromFile( { cout << "warning: nodenumber <" << nodenumber << "> does not match its index in node list <" << i+1 << ">. Node will get number " << i+1 << " when naming variables and constraints!" << endl; + return SCIP_INVALIDDATA; } node->x = x_coords[i]; node->y = y_coords[i]; @@ -82,6 +126,8 @@ void ReaderTSP::getNodesFromFile( i++; } assert( i == graph->nnodes ); + + return SCIP_OKAY; } /*lint !e1762*/ /** adds a variable to both halfedges and captures it for usage in the graph */ @@ -198,37 +244,35 @@ SCIP_DECL_READERREAD(ReaderTSP::scip_read) *result = SCIP_DIDNOTRUN; // open the file - tspifstream filedata(filename); - if( !filedata ) + SCIP_FILE* file = SCIPfopen(filename, "r"); + if( !file ) return SCIP_READERROR; - filedata.clear(); // read the first lines of information - filedata >> token; - while( ! filedata.eof() ) + char str[SCIP_MAXSTRLEN]; + (void) SCIPfgets(str, SCIP_MAXSTRLEN, file); + + // get first token + char* s = str; + token = getToken(s); + + while( ! SCIPfeof(file) ) { - if( token == "NAME:" ) - filedata >> name; - else if( token == "NAME" ) - filedata >> token >> name; - else if( token == "TYPE:" ) - filedata >> type; + if( token == "NAME" ) + name = getToken(s); else if( token == "TYPE" ) - filedata >> token >> type; - else if( token == "DIMENSION:" ) - { - filedata >> nnodes; - nedges = nnodes * (nnodes-1); - } + type = getToken(s); else if( token == "DIMENSION" ) { - filedata >> token >> nnodes; + if ( ! SCIPstrToIntValue(s, &nnodes, &s) ) + { + SCIPerrorMessage("Could not read number of nodes:\n%s\n", s); + return SCIP_INVALIDDATA; + } nedges = nnodes * (nnodes-1); } - else if( token == "EDGE_WEIGHT_TYPE:" ) - filedata >> edgeweighttype; else if( token == "EDGE_WEIGHT_TYPE" ) - filedata >> token >> edgeweighttype; + edgeweighttype = getToken(s); else if( token == "NODE_COORD_SECTION" || token == "DISPLAY_DATA_SECTION" ) { // there should be some nodes to construct a graph @@ -245,7 +289,7 @@ SCIP_DECL_READERREAD(ReaderTSP::scip_read) x_coords = new double[nnodes]; y_coords = new double[nnodes]; - getNodesFromFile(filedata, x_coords, y_coords, graph); + SCIP_CALL( getNodesFromFile(file, x_coords, y_coords, graph) ); } else { @@ -254,7 +298,9 @@ SCIP_DECL_READERREAD(ReaderTSP::scip_read) } } else if( token == "COMMENT:" || token == "COMMENT" || token == "DISPLAY_DATA_TYPE" || token == "DISPLAY_DATA_TYPE:" ) - (void) getline( filedata, token ); + { + // do nothing + } else if( token == "EOF" ) break; else if( token == "" ) @@ -264,9 +310,13 @@ SCIP_DECL_READERREAD(ReaderTSP::scip_read) cout << "parse error in file <" << name << "> unknown keyword <" << token << ">" << endl; return SCIP_READERROR; } - filedata >> token; + (void) SCIPfgets(str, SCIP_MAXSTRLEN, file); + s = str; + token = getToken(s); }// finished parsing the input + SCIPfclose(file); + // check whether the input data was valid if( ! checkValid(graph, name, type, edgeweighttype, nnodes) ) retcode = SCIP_READERROR; diff --git a/examples/TSP/src/ReaderTSP.h b/examples/TSP/src/ReaderTSP.h index 5fc88e0e26..ac1b52ed43 100644 --- a/examples/TSP/src/ReaderTSP.h +++ b/examples/TSP/src/ReaderTSP.h @@ -32,19 +32,12 @@ #ifndef __TSPREADER_H__ #define __TSPREADER_H__ -#include -#include + #include -#include "GomoryHuTree.h" #include "objscip/objscip.h" #include "scip/def.h" - -#ifdef SCIP_WITH_ZLIB -#include "external/zstr/zstr.hpp" -typedef zstr::ifstream tspifstream; -#else -typedef std::ifstream tspifstream; -#endif +#include "GomoryHuTree.h" // for GRAPH +#include "scip/pub_fileio.h" namespace tsp @@ -101,8 +94,8 @@ class ReaderTSP : public scip::ObjReader private: /** parses the node list */ - void getNodesFromFile( - tspifstream& filedata, /**< filestream containing the data to extract */ + SCIP_RETCODE getNodesFromFile( + SCIP_FILE* file, /**< file containing the data to extract */ double* x_coords, /**< double array to be filled with the x-coordinates of the nodes */ double* y_coords, /**< same for y-coordinates */ GRAPH* graph /**< the graph which is to be generated by the nodes */ From 6ddd4fe58f4786bcefc144655b2366d5806d4502 Mon Sep 17 00:00:00 2001 From: Marc Pfetsch Date: Tue, 14 May 2024 14:58:13 +0200 Subject: [PATCH 3/4] remove zstr again --- examples/TSP/src/external/zstr/License.txt | 21 - examples/TSP/src/external/zstr/README | 2 - .../TSP/src/external/zstr/strict_fstream.hpp | 236 --------- examples/TSP/src/external/zstr/zstr.hpp | 472 ------------------ 4 files changed, 731 deletions(-) delete mode 100644 examples/TSP/src/external/zstr/License.txt delete mode 100644 examples/TSP/src/external/zstr/README delete mode 100644 examples/TSP/src/external/zstr/strict_fstream.hpp delete mode 100644 examples/TSP/src/external/zstr/zstr.hpp diff --git a/examples/TSP/src/external/zstr/License.txt b/examples/TSP/src/external/zstr/License.txt deleted file mode 100644 index 3c33ea696e..0000000000 --- a/examples/TSP/src/external/zstr/License.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Matei David, Ontario Institute for Cancer Research - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/TSP/src/external/zstr/README b/examples/TSP/src/external/zstr/README deleted file mode 100644 index ff801cad91..0000000000 --- a/examples/TSP/src/external/zstr/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains zstr 1.0.5 form https://github.com/mateidavid/zstr. -The code is licensed under MIT license, see ../../LICENSE. diff --git a/examples/TSP/src/external/zstr/strict_fstream.hpp b/examples/TSP/src/external/zstr/strict_fstream.hpp deleted file mode 100644 index 007e0f6c23..0000000000 --- a/examples/TSP/src/external/zstr/strict_fstream.hpp +++ /dev/null @@ -1,236 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -/** - * This namespace defines wrappers for std::ifstream, std::ofstream, and - * std::fstream objects. The wrappers perform the following steps: - * - check the open modes make sense - * - check that the call to open() is successful - * - (for input streams) check that the opened file is peek-able - * - turn on the badbit in the exception mask - */ -namespace strict_fstream -{ - -// Help people out a bit, it seems like this is a common recommenation since -// musl breaks all over the place. -#if defined(__NEED_size_t) && !defined(__MUSL__) -#warning "It seems to be recommended to patch in a define for __MUSL__ if you use musl globally: https://www.openwall.com/lists/musl/2013/02/10/5" -#define __MUSL__ -#endif - -// Workaround for broken musl implementation -// Since musl insists that they are perfectly compatible, ironically enough, -// they don't officially have a __musl__ or similar. But __NEED_size_t is defined in their -// relevant header (and not in working implementations), so we can use that. -#ifdef __MUSL__ -#warning "Working around broken strerror_r() implementation in musl, remove when musl is fixed" -#endif - -// Non-gnu variants of strerror_* don't necessarily null-terminate if -// truncating, so we have to do things manually. -inline std::string trim_to_null(const std::vector &buff) -{ - std::string ret(buff.begin(), buff.end()); - - const std::string::size_type pos = ret.find('\0'); - if (pos == std::string::npos) { - ret += " [...]"; // it has been truncated - } else { - ret.resize(pos); - } - return ret; -} - -/// Overload of error-reporting function, to enable use with VS and non-GNU -/// POSIX libc's -/// Ref: -/// - http://stackoverflow.com/a/901316/717706 -static std::string strerror() -{ - // Can't use std::string since we're pre-C++17 - std::vector buff(256, '\0'); - -#ifdef _WIN32 - // Since strerror_s might set errno itself, we need to store it. - const int err_num = errno; - if (strerror_s(buff.data(), buff.size(), err_num) != 0) { - return trim_to_null(buff); - } else { - return "Unknown error (" + std::to_string(err_num) + ")"; - } -#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__APPLE__) || defined(__FreeBSD__)) && ! _GNU_SOURCE) || defined(__MUSL__) -// XSI-compliant strerror_r() - const int err_num = errno; // See above - if (strerror_r(err_num, buff.data(), buff.size()) == 0) { - return trim_to_null(buff); - } else { - return "Unknown error (" + std::to_string(err_num) + ")"; - } -#else -// GNU-specific strerror_r() - char * p = strerror_r(errno, &buff[0], buff.size()); - return std::string(p, std::strlen(p)); -#endif -} - -/// Exception class thrown by failed operations. -class Exception - : public std::exception -{ -public: - Exception(const std::string& msg) : _msg(msg) {} - const char * what() const noexcept { return _msg.c_str(); } -private: - std::string _msg; -}; // class Exception - -namespace detail -{ - -struct static_method_holder -{ - static std::string mode_to_string(std::ios_base::openmode mode) - { - static const int n_modes = 6; - static const std::ios_base::openmode mode_val_v[n_modes] = - { - std::ios_base::in, - std::ios_base::out, - std::ios_base::app, - std::ios_base::ate, - std::ios_base::trunc, - std::ios_base::binary - }; - - static const char * mode_name_v[n_modes] = - { - "in", - "out", - "app", - "ate", - "trunc", - "binary" - }; - std::string res; - for (int i = 0; i < n_modes; ++i) - { - if (mode & mode_val_v[i]) - { - res += (! res.empty()? "|" : ""); - res += mode_name_v[i]; - } - } - if (res.empty()) res = "none"; - return res; - } - static void check_mode(const std::string& filename, std::ios_base::openmode mode) - { - if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out)) - { - throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out"); - } - else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out)) - { - throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out"); - } - else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app)) - { - throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app"); - } - } - static void check_open(std::ios * s_p, const std::string& filename, std::ios_base::openmode mode) - { - if (s_p->fail()) - { - throw Exception(std::string("strict_fstream: open('") - + filename + "'," + mode_to_string(mode) + "): open failed: " - + strerror()); - } - } - static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode) - { - bool peek_failed = true; - try - { - is_p->peek(); - peek_failed = is_p->fail(); - } - catch (const std::ios_base::failure &) {} - if (peek_failed) - { - throw Exception(std::string("strict_fstream: open('") - + filename + "'," + mode_to_string(mode) + "): peek failed: " - + strerror()); - } - is_p->clear(); - } -}; // struct static_method_holder - -} // namespace detail - -class ifstream - : public std::ifstream -{ -public: - ifstream() = default; - ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) - { - open(filename, mode); - } - void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) - { - mode |= std::ios_base::in; - exceptions(std::ios_base::badbit); - detail::static_method_holder::check_mode(filename, mode); - std::ifstream::open(filename, mode); - detail::static_method_holder::check_open(this, filename, mode); - detail::static_method_holder::check_peek(this, filename, mode); - } -}; // class ifstream - -class ofstream - : public std::ofstream -{ -public: - ofstream() = default; - ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out) - { - open(filename, mode); - } - void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out) - { - mode |= std::ios_base::out; - exceptions(std::ios_base::badbit); - detail::static_method_holder::check_mode(filename, mode); - std::ofstream::open(filename, mode); - detail::static_method_holder::check_open(this, filename, mode); - } -}; // class ofstream - -class fstream - : public std::fstream -{ -public: - fstream() = default; - fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) - { - open(filename, mode); - } - void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in) - { - if (! (mode & std::ios_base::out)) mode |= std::ios_base::in; - exceptions(std::ios_base::badbit); - detail::static_method_holder::check_mode(filename, mode); - std::fstream::open(filename, mode); - detail::static_method_holder::check_open(this, filename, mode); - detail::static_method_holder::check_peek(this, filename, mode); - } -}; // class fstream - -} // namespace strict_fstream diff --git a/examples/TSP/src/external/zstr/zstr.hpp b/examples/TSP/src/external/zstr/zstr.hpp deleted file mode 100644 index 239909f9e7..0000000000 --- a/examples/TSP/src/external/zstr/zstr.hpp +++ /dev/null @@ -1,472 +0,0 @@ -//--------------------------------------------------------- -// Copyright 2015 Ontario Institute for Cancer Research -// Written by Matei David (matei@cs.toronto.edu) -//--------------------------------------------------------- - -// Reference: -// http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c - -#pragma once - -#include - -#include -#include -#include -#include -#include - -#include "strict_fstream.hpp" - -namespace zstr { - -static const std::size_t default_buff_size = static_cast(1 << 20); - -/// Exception class thrown by failed zlib operations. -class Exception : public std::ios_base::failure { - public: - static std::string error_to_message(z_stream* zstrm_p, int ret) { - std::string msg = "zlib: "; - switch (ret) { - case Z_STREAM_ERROR: - msg += "Z_STREAM_ERROR: "; - break; - case Z_DATA_ERROR: - msg += "Z_DATA_ERROR: "; - break; - case Z_MEM_ERROR: - msg += "Z_MEM_ERROR: "; - break; - case Z_VERSION_ERROR: - msg += "Z_VERSION_ERROR: "; - break; - case Z_BUF_ERROR: - msg += "Z_BUF_ERROR: "; - break; - default: - std::ostringstream oss; - oss << ret; - msg += "[" + oss.str() + "]: "; - break; - } - if (zstrm_p->msg) { - msg += zstrm_p->msg; - } - msg += - " (" - "next_in: " + - std::to_string(uintptr_t(zstrm_p->next_in)) + - ", avail_in: " + std::to_string(uintptr_t(zstrm_p->avail_in)) + - ", next_out: " + std::to_string(uintptr_t(zstrm_p->next_out)) + - ", avail_out: " + std::to_string(uintptr_t(zstrm_p->avail_out)) + ")"; - return msg; - } - - Exception(z_stream* zstrm_p, int ret) - : std::ios_base::failure(error_to_message(zstrm_p, ret)) {} -}; // class Exception - -namespace detail { - -class z_stream_wrapper : public z_stream { - public: - z_stream_wrapper(bool _is_input, int _level, int _window_bits) - : is_input(_is_input) { - this->zalloc = nullptr; // Z_NULL - this->zfree = nullptr; // Z_NULL - this->opaque = nullptr; // Z_NULL - int ret; - if (is_input) { - this->avail_in = 0; - this->next_in = nullptr; // Z_NULL - ret = inflateInit2(this, _window_bits ? _window_bits : 15 + 32); - } else { - ret = deflateInit2(this, _level, Z_DEFLATED, - _window_bits ? _window_bits : 15 + 16, 8, - Z_DEFAULT_STRATEGY); - } - if (ret != Z_OK) throw Exception(this, ret); - } - ~z_stream_wrapper() { - if (is_input) { - inflateEnd(this); - } else { - deflateEnd(this); - } - } - - private: - bool is_input; -}; // class z_stream_wrapper - -} // namespace detail - -class istreambuf : public std::streambuf { - public: - istreambuf(std::streambuf* _sbuf_p, - std::size_t _buff_size = default_buff_size, - bool _auto_detect = true, int _window_bits = 0) - : sbuf_p(_sbuf_p), - in_buff(), - in_buff_start(nullptr), - in_buff_end(nullptr), - out_buff(), - zstrm_p(nullptr), - buff_size(_buff_size), - auto_detect(_auto_detect), - auto_detect_run(false), - is_text(false), - window_bits(_window_bits) { - assert(sbuf_p); - in_buff = std::unique_ptr(new char[buff_size]); - in_buff_start = in_buff.get(); - in_buff_end = in_buff.get(); - out_buff = std::unique_ptr(new char[buff_size]); - setg(out_buff.get(), out_buff.get(), out_buff.get()); - } - - istreambuf(const istreambuf&) = delete; - istreambuf& operator=(const istreambuf&) = delete; - - pos_type seekoff(off_type off, std::ios_base::seekdir dir, - std::ios_base::openmode which) override { - if (off != 0 || dir != std::ios_base::cur) { - return std::streambuf::seekoff(off, dir, which); - } - - if (!zstrm_p) { - return 0; - } - - return static_cast(zstrm_p->total_out - - static_cast(in_avail())); - } - - std::streambuf::int_type underflow() override { - if (this->gptr() == this->egptr()) { - // pointers for free region in output buffer - char* out_buff_free_start = out_buff.get(); - int tries = 0; - do { - if (++tries > 1000) { - throw std::ios_base::failure( - "Failed to fill buffer after 1000 tries"); - } - - // read more input if none available - if (in_buff_start == in_buff_end) { - // empty input buffer: refill from the start - in_buff_start = in_buff.get(); - std::streamsize sz = sbuf_p->sgetn( - in_buff.get(), static_cast(buff_size)); - in_buff_end = in_buff_start + sz; - if (in_buff_end == in_buff_start) break; // end of input - } - // auto detect if the stream contains text or deflate data - if (auto_detect && !auto_detect_run) { - auto_detect_run = true; - unsigned char b0 = *reinterpret_cast(in_buff_start); - unsigned char b1 = - *reinterpret_cast(in_buff_start + 1); - // Ref: - // http://en.wikipedia.org/wiki/Gzip - // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like - is_text = !(in_buff_start + 2 <= in_buff_end && - ((b0 == 0x1F && b1 == 0x8B) // gzip header - || (b0 == 0x78 && (b1 == 0x01 // zlib header - || b1 == 0x9C || b1 == 0xDA)))); - } - if (is_text) { - // simply swap in_buff and out_buff, and adjust pointers - assert(in_buff_start == in_buff.get()); - std::swap(in_buff, out_buff); - out_buff_free_start = in_buff_end; - in_buff_start = in_buff.get(); - in_buff_end = in_buff.get(); - } else { - // run inflate() on input - if (!zstrm_p) - zstrm_p = std::unique_ptr( - new detail::z_stream_wrapper(true, Z_DEFAULT_COMPRESSION, - window_bits)); - zstrm_p->next_in = - reinterpret_castnext_in)>(in_buff_start); - zstrm_p->avail_in = uint32_t(in_buff_end - in_buff_start); - zstrm_p->next_out = reinterpret_castnext_out)>( - out_buff_free_start); - zstrm_p->avail_out = - uint32_t((out_buff.get() + buff_size) - out_buff_free_start); - int ret = inflate(zstrm_p.get(), Z_NO_FLUSH); - // process return code - if (ret != Z_OK && ret != Z_STREAM_END) - throw Exception(zstrm_p.get(), ret); - // update in&out pointers following inflate() - in_buff_start = - reinterpret_cast(zstrm_p->next_in); - in_buff_end = in_buff_start + zstrm_p->avail_in; - out_buff_free_start = reinterpret_cast( - zstrm_p->next_out); - assert(out_buff_free_start + zstrm_p->avail_out == - out_buff.get() + buff_size); - - if (ret == Z_STREAM_END) { - // if stream ended, deallocate inflator - zstrm_p.reset(); - } - } - } while (out_buff_free_start == out_buff.get()); - // 2 exit conditions: - // - end of input: there might or might not be output available - // - out_buff_free_start != out_buff: output available - this->setg(out_buff.get(), out_buff.get(), out_buff_free_start); - } - return this->gptr() == this->egptr() - ? traits_type::eof() - : traits_type::to_int_type(*this->gptr()); - } - - private: - std::streambuf* sbuf_p; - std::unique_ptr in_buff; - char* in_buff_start; - char* in_buff_end; - std::unique_ptr out_buff; - std::unique_ptr zstrm_p; - std::size_t buff_size; - bool auto_detect; - bool auto_detect_run; - bool is_text; - int window_bits; - -}; // class istreambuf - -class ostreambuf : public std::streambuf { - public: - ostreambuf(std::streambuf* _sbuf_p, - std::size_t _buff_size = default_buff_size, - int _level = Z_DEFAULT_COMPRESSION, int _window_bits = 0) - : sbuf_p(_sbuf_p), - in_buff(), - out_buff(), - zstrm_p(new detail::z_stream_wrapper(false, _level, _window_bits)), - buff_size(_buff_size) { - assert(sbuf_p); - in_buff = std::unique_ptr(new char[buff_size]); - out_buff = std::unique_ptr(new char[buff_size]); - setp(in_buff.get(), in_buff.get() + buff_size); - } - - ostreambuf(const ostreambuf&) = delete; - ostreambuf& operator=(const ostreambuf&) = delete; - - int deflate_loop(int flush) { - while (true) { - zstrm_p->next_out = - reinterpret_castnext_out)>(out_buff.get()); - zstrm_p->avail_out = uint32_t(buff_size); - int ret = deflate(zstrm_p.get(), flush); - if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) { - failed = true; - throw Exception(zstrm_p.get(), ret); - } - std::streamsize sz = sbuf_p->sputn( - out_buff.get(), - reinterpret_cast(zstrm_p->next_out) - - out_buff.get()); - if (sz != reinterpret_cast(zstrm_p->next_out) - - out_buff.get()) { - // there was an error in the sink stream - return -1; - } - if (ret == Z_STREAM_END || ret == Z_BUF_ERROR || sz == 0) { - break; - } - } - return 0; - } - - virtual ~ostreambuf() { - // flush the zlib stream - // - // NOTE: Errors here (sync() return value not 0) are ignored, because we - // cannot throw in a destructor. This mirrors the behaviour of - // std::basic_filebuf::~basic_filebuf(). To see an exception on error, - // close the ofstream with an explicit call to close(), and do not rely - // on the implicit call in the destructor. - // - if (!failed) try { - sync(); - } catch (...) { - } - } - std::streambuf::int_type overflow( - std::streambuf::int_type c = traits_type::eof()) override { - zstrm_p->next_in = reinterpret_castnext_in)>(pbase()); - zstrm_p->avail_in = uint32_t(pptr() - pbase()); - while (zstrm_p->avail_in > 0) { - int r = deflate_loop(Z_NO_FLUSH); - if (r != 0) { - setp(nullptr, nullptr); - return traits_type::eof(); - } - } - setp(in_buff.get(), in_buff.get() + buff_size); - return traits_type::eq_int_type(c, traits_type::eof()) - ? traits_type::eof() - : sputc(char_type(c)); - } - int sync() override { - // first, call overflow to clear in_buff - overflow(); - if (!pptr()) return -1; - // then, call deflate asking to finish the zlib stream - zstrm_p->next_in = nullptr; - zstrm_p->avail_in = 0; - if (deflate_loop(Z_FINISH) != 0) return -1; - deflateReset(zstrm_p.get()); - return 0; - } - - private: - std::streambuf* sbuf_p = nullptr; - std::unique_ptr in_buff; - std::unique_ptr out_buff; - std::unique_ptr zstrm_p; - std::size_t buff_size; - bool failed = false; - -}; // class ostreambuf - -class istream : public std::istream { - public: - istream(std::istream& is, std::size_t _buff_size = default_buff_size, - bool _auto_detect = true, int _window_bits = 0) - : std::istream(new istreambuf(is.rdbuf(), _buff_size, _auto_detect, - _window_bits)) { - exceptions(std::ios_base::badbit); - } - explicit istream(std::streambuf* sbuf_p) - : std::istream(new istreambuf(sbuf_p)) { - exceptions(std::ios_base::badbit); - } - virtual ~istream() { delete rdbuf(); } -}; // class istream - -class ostream : public std::ostream { - public: - ostream(std::ostream& os, std::size_t _buff_size = default_buff_size, - int _level = Z_DEFAULT_COMPRESSION, int _window_bits = 0) - : std::ostream( - new ostreambuf(os.rdbuf(), _buff_size, _level, _window_bits)) { - exceptions(std::ios_base::badbit); - } - explicit ostream(std::streambuf* sbuf_p) - : std::ostream(new ostreambuf(sbuf_p)) { - exceptions(std::ios_base::badbit); - } - virtual ~ostream() { delete rdbuf(); } -}; // class ostream - -namespace detail { - -template -struct strict_fstream_holder { - strict_fstream_holder(const std::string& filename, - std::ios_base::openmode mode = std::ios_base::in) - : _fs(filename, mode) {} - strict_fstream_holder() = default; - FStream_Type _fs{}; -}; // class strict_fstream_holder - -} // namespace detail - -class ifstream - : private detail::strict_fstream_holder, - public std::istream { - public: - explicit ifstream(const std::string filename, - std::ios_base::openmode mode = std::ios_base::in, - size_t buff_size = default_buff_size) - : detail::strict_fstream_holder( - filename, mode -#ifdef _WIN32 // to avoid problems with conversion of \r\n, only windows as - // otherwise there are problems on mac - | std::ios_base::binary -#endif - ), - std::istream(new istreambuf(_fs.rdbuf(), buff_size)) { - exceptions(std::ios_base::badbit); - } - explicit ifstream() - : detail::strict_fstream_holder(), - std::istream(new istreambuf(_fs.rdbuf())) {} - void close() { _fs.close(); } - void open(const std::string filename, - std::ios_base::openmode mode = std::ios_base::in) { - _fs.open(filename, mode -#ifdef _WIN32 // to avoid problems with conversion of \r\n, only windows as - // otherwise there are problems on mac - | std::ios_base::binary -#endif - ); - // make sure the previous buffer is deleted by putting it into a unique_ptr - // and set a new one after opening file - std::unique_ptr oldbuf(rdbuf(new istreambuf(_fs.rdbuf()))); - // call move assignment operator on istream which does not alter the stream - // buffer - std::istream::operator=(std::istream(rdbuf())); - } - bool is_open() const { return _fs.is_open(); } - virtual ~ifstream() { - if (_fs.is_open()) close(); - if (rdbuf()) delete rdbuf(); - } - - /// Return the position within the compressed file (wrapped filestream) - std::streampos compressed_tellg() { return _fs.tellg(); } -}; // class ifstream - -class ofstream - : private detail::strict_fstream_holder, - public std::ostream { - public: - explicit ofstream(const std::string filename, - std::ios_base::openmode mode = std::ios_base::out, - int level = Z_DEFAULT_COMPRESSION, - size_t buff_size = default_buff_size) - : detail::strict_fstream_holder( - filename, mode | std::ios_base::binary), - std::ostream(new ostreambuf(_fs.rdbuf(), buff_size, level)) { - exceptions(std::ios_base::badbit); - } - explicit ofstream() - : detail::strict_fstream_holder(), - std::ostream(new ostreambuf(_fs.rdbuf())) {} - void close() { - std::ostream::flush(); - _fs.close(); - } - void open(const std::string filename, - std::ios_base::openmode mode = std::ios_base::out, - int level = Z_DEFAULT_COMPRESSION) { - flush(); - _fs.open(filename, mode | std::ios_base::binary); - std::ostream::operator=( - std::ostream(new ostreambuf(_fs.rdbuf(), default_buff_size, level))); - } - bool is_open() const { return _fs.is_open(); } - ofstream& flush() { - std::ostream::flush(); - _fs.flush(); - return *this; - } - virtual ~ofstream() { - if (_fs.is_open()) close(); - if (rdbuf()) delete rdbuf(); - } - - // Return the position within the compressed file (wrapped filestream) - std::streampos compressed_tellp() { return _fs.tellp(); } -}; // class ofstream - -} // namespace zstr From 0a74043b1d2abe48d4293372bb95807de3778e8c Mon Sep 17 00:00:00 2001 From: Alexander Hoen Date: Tue, 14 May 2024 15:53:48 +0200 Subject: [PATCH 4/4] Apply 1 suggestion(s) to 1 file(s) --- CHANGELOG | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f2d66e8769..477b300abc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,8 +17,7 @@ Fixed bugs Examples and applications ------------------------- -- TSP: remove `gzstream.h/hpp` (L-GPL) and replace it with `zstr` (MIT License) for `.gz` file handling - +- TSP: remove `gzstream.h/hpp` and parse gzipped file differently Interface changes -----------------