diff --git a/CHANGELOG b/CHANGELOG index 8f607f83c8..7236736e79 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,8 @@ Fixed bugs Examples and applications ------------------------- +- TSP: remove `gzstream.h/hpp` and parse gzipped file differently + 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.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 07fba7450a..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 "gzstream.h" -typedef gzstream::igzstream 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 */ 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