From 35e4f6c6344d1e0adabbc3d3822b5847640e8e37 Mon Sep 17 00:00:00 2001
From: valerio <valerio@5a81b35b-ba03-0410-adc8-b2c5c5119f08>
Date: Fri, 19 Mar 2010 14:32:50 +0000
Subject: [PATCH] Slight refactoring of io handlers and support for map.gz
 files

git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@1847 5a81b35b-ba03-0410-adc8-b2c5c5119f08
---
 modules/io/src/CMakeLists.txt                 |   7 +-
 modules/io/src/img/map_io_dat_handler.cc      |   4 +-
 modules/io/src/img/map_io_dat_handler.hh      |   2 +-
 modules/io/src/img/map_io_dm3_handler.cc      |   4 +-
 modules/io/src/img/map_io_dm3_handler.hh      |   2 +-
 modules/io/src/img/map_io_dx_handler.cc       |   4 +-
 modules/io/src/img/map_io_dx_handler.hh       |   2 +-
 modules/io/src/img/map_io_handler.hh          |   7 +-
 modules/io/src/img/map_io_jpk_handler.cc      |   4 +-
 modules/io/src/img/map_io_jpk_handler.hh      |   2 +-
 modules/io/src/img/map_io_mrc_handler.cc      | 211 +++++++++++++-----
 modules/io/src/img/map_io_mrc_handler.hh      |   7 +-
 .../io/src/img/map_io_nanoscope_handler.cc    |   4 +-
 .../io/src/img/map_io_nanoscope_handler.hh    |   2 +-
 modules/io/src/img/map_io_png_handler.cc      |   4 +-
 modules/io/src/img/map_io_png_handler.hh      |   2 +-
 modules/io/src/img/map_io_situs_handler.cc    |   4 +-
 modules/io/src/img/map_io_situs_handler.hh    |   2 +-
 modules/io/src/img/map_io_spi_handler.cc      |   4 +-
 modules/io/src/img/map_io_spi_handler.hh      |   2 +-
 modules/io/src/img/map_io_tiff_handler.cc     |   4 +-
 modules/io/src/img/map_io_tiff_handler.hh     |   2 +-
 modules/io/src/io_manager.cc                  |  19 +-
 modules/io/src/io_manager.hh                  |   2 +
 modules/io/src/io_utils.cc                    |  30 +++
 modules/io/src/io_utils.hh                    |  31 +++
 modules/io/src/mol/entity_io_crd_handler.cc   |   3 +-
 modules/io/src/mol/entity_io_handler.hh       |   1 +
 modules/io/src/mol/entity_io_pdb_handler.cc   |   5 +-
 modules/io/src/mol/entity_io_sdf_handler.cc   |   3 +-
 modules/io/src/seq/clustal_io_handler.cc      |   3 +-
 modules/io/src/seq/fasta_io_handler.cc        |  11 +-
 modules/io/src/seq/promod_io_handler.cc       |   3 +-
 modules/io/src/seq/sequence_io_handler.hh     |   1 +
 34 files changed, 271 insertions(+), 127 deletions(-)
 create mode 100644 modules/io/src/io_utils.cc
 create mode 100644 modules/io/src/io_utils.hh

diff --git a/modules/io/src/CMakeLists.txt b/modules/io/src/CMakeLists.txt
index 3dafdc92e..e77cfda20 100644
--- a/modules/io/src/CMakeLists.txt
+++ b/modules/io/src/CMakeLists.txt
@@ -9,6 +9,7 @@ binary_data_source.hh
 module_config.hh
 container_serialization.hh	
 swap_util.hh
+io_utils.hh
 io_exception.hh
 convert.hh
 converting_streams.hh
@@ -17,6 +18,7 @@ converting_streams.hh
 set(OST_IO_SOURCES
 io_manager.cc
 convert.cc
+io_utils.cc
 )
 
 
@@ -47,7 +49,6 @@ foreach(fname ${OST_IO_SEQ_HEADERS})
 endforeach(fname ${OST_IO_SEQ_HEADERS})
 
 
-
 set(OST_IO_DEPENDENCIES base;conop;seq)
 if (ENABLE_IMG)
   set(OST_IO_DEPENDENCIES ${OST_IO_DEPENDENCIES};img;img_alg)
@@ -55,8 +56,8 @@ endif()
 module(NAME io SOURCES "${OST_IO_SOURCES}" 
        HEADERS ${OST_IO_MOL_HEADERS} IN_DIR mol
                ${OST_IO_IMG_HEADERS} IN_DIR img
-               ${OST_IO_SEQ_HEADERS} IN_DIR seq
-               ${OST_IO_HEADERS}
+               ${OST_IO_SEQ_HEADERS} IN_DIR seq            
+               ${OST_IO_HEADERS} 
        DEPENDS_ON ${OST_IO_DEPENDENCIES})
 if (NOT WIN32)
   # see note in modules/gui/src/CMakeLists.txt
diff --git a/modules/io/src/img/map_io_dat_handler.cc b/modules/io/src/img/map_io_dat_handler.cc
index dc375df8e..e9642373c 100644
--- a/modules/io/src/img/map_io_dat_handler.cc
+++ b/modules/io/src/img/map_io_dat_handler.cc
@@ -74,9 +74,9 @@ bool MapIODatHandler::MatchType(const ImageFormatBase& type)
   return false;
 }
 
-bool MapIODatHandler::MatchSuffix(const String& suffix)
+bool MapIODatHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".dat" || suffix==".img") {
+    if(detail::FilenameEndsWith(loc.string(),".dat") || detail::FilenameEndsWith(loc.string(),".img") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_dat_handler.hh b/modules/io/src/img/map_io_dat_handler.hh
index f501d0b2e..e6964f819 100644
--- a/modules/io/src/img/map_io_dat_handler.hh
+++ b/modules/io/src/img/map_io_dat_handler.hh
@@ -60,7 +60,7 @@ class DLLEXPORT_OST_IO MapIODatHandler: public MapIOHandler
     virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
     static bool MatchContent(unsigned char* header);
     static bool MatchType(const ImageFormatBase& type);
-    static bool MatchSuffix(const String& suffix);
+    static bool MatchSuffix(const boost::filesystem::path& loc);
     static String GetFormatName() { return String("Dat"); }
     static String GetFormatDescription() {return String("Simple binary format for square images");}
 };
diff --git a/modules/io/src/img/map_io_dm3_handler.cc b/modules/io/src/img/map_io_dm3_handler.cc
index 4c0816a38..2ff70625d 100644
--- a/modules/io/src/img/map_io_dm3_handler.cc
+++ b/modules/io/src/img/map_io_dm3_handler.cc
@@ -636,9 +636,9 @@ bool MapIODm3Handler::MatchType(const ImageFormatBase& type)
   }
   return false;
 }
-bool MapIODm3Handler::MatchSuffix(const String& suffix)
+bool MapIODm3Handler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".dm3") {
+	if(detail::FilenameEndsWith(loc.string(),".dm3") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_dm3_handler.hh b/modules/io/src/img/map_io_dm3_handler.hh
index b1c5e09fc..c09832a5a 100644
--- a/modules/io/src/img/map_io_dm3_handler.hh
+++ b/modules/io/src/img/map_io_dm3_handler.hh
@@ -48,7 +48,7 @@ class DLLEXPORT_OST_IO MapIODm3Handler: public MapIOHandler
     virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
     static bool MatchContent(unsigned char* header);
     static bool MatchType(const ImageFormatBase& type);
-    static bool MatchSuffix(const String& suffix);
+    static bool MatchSuffix(const boost::filesystem::path& loc);
     static String GetFormatName() { return String("Dm3"); }
     static String GetFormatDescription() {return String("Format used by Gatan Inc.'s  Digital Micrograph software");}
 
diff --git a/modules/io/src/img/map_io_dx_handler.cc b/modules/io/src/img/map_io_dx_handler.cc
index 4d5b50c48..7c564eaab 100644
--- a/modules/io/src/img/map_io_dx_handler.cc
+++ b/modules/io/src/img/map_io_dx_handler.cc
@@ -264,9 +264,9 @@ bool MapIODxHandler::MatchType(const ImageFormatBase& formatstruct)
   }
   return false;
 }
-bool MapIODxHandler::MatchSuffix(const String& suffix)
+bool MapIODxHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".dx") {
+	if(detail::FilenameEndsWith(loc.string(),".dx") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_dx_handler.hh b/modules/io/src/img/map_io_dx_handler.hh
index f0933aa1c..f54c6ca86 100644
--- a/modules/io/src/img/map_io_dx_handler.hh
+++ b/modules/io/src/img/map_io_dx_handler.hh
@@ -62,7 +62,7 @@ class DLLEXPORT_OST_IO MapIODxHandler: public MapIOHandler
                       std::ostream& loc, const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& locx);
   static String GetFormatName() { return String("Dx"); };
   static String GetFormatDescription()  { return String("Format used by the OpenDX software package"); };
 
diff --git a/modules/io/src/img/map_io_handler.hh b/modules/io/src/img/map_io_handler.hh
index 295492b4d..3be88313a 100644
--- a/modules/io/src/img/map_io_handler.hh
+++ b/modules/io/src/img/map_io_handler.hh
@@ -26,6 +26,7 @@
 #include <ost/img/map.hh>
 #include <ost/img/alg/normalizer.hh>
 #include <ost/io/img/image_format.hh>
+#include <ost/io/io_utils.hh>
 
 namespace ost { namespace io {
 
@@ -45,7 +46,7 @@ public:
   virtual ~MapIOHandlerFactoryBase() {}
   virtual bool MatchContent(unsigned char* header) const = 0;
   virtual bool MatchType(const ImageFormatBase& type) const = 0;
-  virtual bool MatchSuffix(const String& suffix) const =0 ;
+  virtual bool MatchSuffix(const boost::filesystem::path& loc) const =0 ;
   virtual MapIOHandlerPtr Create() const = 0 ;
   virtual String GetFormatName() const =0;
   virtual String GetFormatDescription() const =0;
@@ -66,8 +67,8 @@ class MapIOHandlerFactory: public MapIOHandlerFactoryBase
     return HANDLER::MatchType(type);
   }
 
-  virtual bool MatchSuffix(const String& suffix) const {
-    return HANDLER::MatchSuffix(suffix);
+  virtual bool MatchSuffix(const boost::filesystem::path& loc) const {
+    return HANDLER::MatchSuffix(loc);
   }
 
   virtual String GetFormatName() const {
diff --git a/modules/io/src/img/map_io_jpk_handler.cc b/modules/io/src/img/map_io_jpk_handler.cc
index 5122ab3c3..f941c37df 100644
--- a/modules/io/src/img/map_io_jpk_handler.cc
+++ b/modules/io/src/img/map_io_jpk_handler.cc
@@ -300,9 +300,9 @@ bool MapIOJpkHandler::MatchType(const ImageFormatBase& formatstruct)
   return false;
 }
 
-bool MapIOJpkHandler::MatchSuffix(const String& suffix)
+bool MapIOJpkHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".jpk") {
+    if(detail::FilenameEndsWith(loc.string(),".jpk") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_jpk_handler.hh b/modules/io/src/img/map_io_jpk_handler.hh
index 1191924a4..074c632de 100644
--- a/modules/io/src/img/map_io_jpk_handler.hh
+++ b/modules/io/src/img/map_io_jpk_handler.hh
@@ -48,7 +48,7 @@ class DLLEXPORT_OST_IO MapIOJpkHandler: public MapIOTiffHandler
   void Export(const img::MapHandle& image, std::ostream& loc,const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& loc);
   static String GetFormatName() { return String("Jpk");}
   static String GetFormatDescription() { return String("Format used by JPK Instruments AG's software (Customized Tiff format)"); }
 
diff --git a/modules/io/src/img/map_io_mrc_handler.cc b/modules/io/src/img/map_io_mrc_handler.cc
index 7590eefb7..80ee60250 100644
--- a/modules/io/src/img/map_io_mrc_handler.cc
+++ b/modules/io/src/img/map_io_mrc_handler.cc
@@ -57,10 +57,16 @@ u v w x . . .     d*c*b*a b c d   3
 #include <cstdio>
 #include <iostream>
 #include <sstream>
+#include <streambuf>
 
 #include <boost/scoped_array.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/filesystem/fstream.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_streambuf.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
 #include <boost/format.hpp>
 
 #include <ost/base.hh>
@@ -76,6 +82,7 @@ u v w x . . .     d*c*b*a b c d   3
 #include <ost/io/img/image_format.hh>
 #include <ost/io/swap_util.hh>
 #include <ost/io/converting_streams.hh>
+#include <ost/io/io_utils.hh>
 
 
 #include "map_io_mrc_handler.hh"
@@ -132,6 +139,67 @@ CCP4::CCP4(bool normalize_on_save, Endianess endianess_on_save):
 
 namespace detail{
 
+class ptristream : public std::istream
+{
+  class ptrinbuf : public std::streambuf
+  {
+  protected:
+    char *      ptr;
+    std::size_t len;
+
+  public:
+    ptrinbuf(char * _ptr, std::size_t _len) : ptr(_ptr), len(_len) {
+      assert(ptr);
+      if (*ptr && len == 0)
+        len = std::strlen(ptr);
+
+      setg(ptr,               // beginning of putback area
+           ptr,               // read position
+           ptr+len);          // end position
+    }
+
+  protected:
+    virtual int_type underflow() {
+      // is read position before end of buffer?
+      if (gptr() < egptr())
+        return traits_type::to_int_type(*gptr());
+      else
+        return EOF;
+    }
+
+    virtual pos_type seekoff(off_type off, ios_base::seekdir way,
+                             ios_base::openmode mode =
+                             ios_base::in | ios_base::out)
+    {
+      switch (way) {
+      case std::ios::cur:
+        setg(ptr, gptr()+off, ptr+len);
+        break;
+      case std::ios::beg:
+        setg(ptr, ptr+off, ptr+len);
+        break;
+      case std::ios::end:
+        setg(ptr, egptr()+off, ptr+len);
+        break;
+
+      default:
+        assert(false);
+        break;
+      }
+      return pos_type(gptr() - ptr);
+    }
+  };
+
+protected:
+  ptrinbuf buf;
+public:
+ ptristream(char * ptr, std::size_t len = 0)
+    : std::istream(0), buf(ptr, len) {
+    rdbuf(&buf);
+  }
+};
+
+
 class header_base {
 public:
   header_base():
@@ -331,8 +399,9 @@ BinaryOStream<CONVERSIONTYPE>& operator<< (BinaryOStream<CONVERSIONTYPE>& out, c
 template<int CONVERSIONTYPE>
 BinaryIStream<CONVERSIONTYPE>& operator>> (BinaryIStream<CONVERSIONTYPE>& in, mrc_header& h)
 {
+  char dummy[116];
   h.ReadCommonData(in);
-  in.seekg(116,std::ios::cur);
+  in.read(dummy,116);
   in >> h.xorigin >> h.yorigin;
   h.ReadLabel(in);
 
@@ -342,7 +411,9 @@ BinaryIStream<CONVERSIONTYPE>& operator>> (BinaryIStream<CONVERSIONTYPE>& in, mr
 
   // skip symm info, seek to start of actual data
   if(h.nsymbt>0){
-    in.seekg(h.nsymbt,std::ios::cur);
+	for (int counter=0;counter<h.nsymbt;++counter){
+	  in.read(dummy,1);
+	}
   }
   return in;
 }
@@ -382,39 +453,39 @@ public:
     arms = 0.1;
   }
 
-static int DetermineDataFormat( std::istream& f)
-{
-  char machst[4];
-  // from the ccp4 documentation
-  // The machine stamp is a 32-bit quantity containing a set of four `nibbles'
-  // (half-bytes)---only half the space is used. Each nibble is a number
-  // specifying the representation of (in C terms) double (d) , float (f),
-  // int (i) and unsigned char (c) types. Thus each stamp is of the form
-  // 0xdfic0000. The values for the floating point nibbles may be taken from the
-  // list (following HDF):
-  // 1        Big-endian ieee
-  // 2        VAX
-  // 3        Cray
-  // 4        Little-endian ieee
-  // 5        Convex native
-  // 6        Fijitsu VP
-  f.seekg(53*4,std::ios::beg); // seek to machine stamp
-  f.read(machst,4);
-  f.seekg(0,std::ios::beg); // seek to beginning
-  char float_machst= machst[0] & 0x0f;
-  if(float_machst == 1){
-    LOGN_DEBUG("CCP4Import: reading big endian data");
-    return OST_BIG_ENDIAN;
-  }else if(float_machst == 2){
-    LOGN_DEBUG("CCP4Import: reading vax data");
-    return OST_VAX_DATA;
-  }else if(float_machst == 4){
-    LOGN_DEBUG("CCP4Import: reading little endian data");
-    return OST_LITTLE_ENDIAN;
-  } else{
-    throw(IOException("CCP4Import: Cray, Convex native and Fijitsu VP formats are not supported."));
+  static int DetermineDataFormat(std::istream& f)
+  {
+    char machst[4];
+    // from the ccp4 documentation
+    // The machine stamp is a 32-bit quantity containing a set of four `nibbles'
+    // (half-bytes)---only half the space is used. Each nibble is a number
+    // specifying the representation of (in C terms) double (d) , float (f),
+    // int (i) and unsigned char (c) types. Thus each stamp is of the form
+    // 0xdfic0000. The values for the floating point nibbles may be taken from the
+    // list (following HDF):
+    // 1        Big-endian ieee
+    // 2        VAX
+    // 3        Cray
+    // 4        Little-endian ieee
+    // 5        Convex native
+    // 6        Fijitsu VP
+    f.seekg(53*4,std::ios::beg); // seek to machine stamp
+    f.read(machst,4);
+    f.seekg(0,std::ios::beg); // seek to beginning
+    char float_machst= machst[0] & 0x0f;
+    if(float_machst == 1){
+      LOGN_DEBUG("CCP4Import: reading big endian data");
+      return OST_BIG_ENDIAN;
+    }else if(float_machst == 2){
+      LOGN_DEBUG("CCP4Import: reading vax data");
+      return OST_VAX_DATA;
+    }else if(float_machst == 4){
+      LOGN_DEBUG("CCP4Import: reading little endian data");
+      return OST_LITTLE_ENDIAN;
+    } else{
+      throw(IOException("CCP4Import: Cray, Convex native and Fijitsu VP formats are not supported."));
+    }
   }
-}
 
 	
   void Print()
@@ -440,15 +511,16 @@ static int DetermineDataFormat( std::istream& f)
 template <int CONVERSIONTYPE>
 BinaryIStream<CONVERSIONTYPE>& operator>> (BinaryIStream<CONVERSIONTYPE>& in, ccp4_header& header)
 {
+  char dummy[48];
   header.ReadCommonData(in);
   in >> header.lskflag;
   in >> header.skwmat[0] >> header.skwmat[1] >> header.skwmat[2];
   in >> header.skwmat[3] >> header.skwmat[4] >> header.skwmat[5];
   in >> header.skwmat[6] >> header.skwmat[7] >> header.skwmat[8];
   in >> header.skwtrn[0] >> header.skwtrn[1] >> header.skwtrn[2];
-  in.seekg(48,std::ios::cur);
+  in.read(dummy,48);
   in >> header.ox >> header.oy >> header.oz;
-  in.seekg(8,std::ios::cur); // skip map and machst
+  in.read(dummy,8);
   in >> header.arms;
   header.ReadLabel(in);
 
@@ -457,8 +529,11 @@ BinaryIStream<CONVERSIONTYPE>& operator>> (BinaryIStream<CONVERSIONTYPE>& in, cc
   if(header.nz<1) header.nz=1;
 
   // skip symm info, seek to start of actual data
-  if(header.nsymbt>0)
-    in.seekg(header.nsymbt,std::ios::cur);
+  if(header.nsymbt>0) {
+	for (int counter=0;counter<header.nsymbt;++counter){
+      in.read(dummy,1);
+	}
+  }
   return in;
 }
 template <int CONVERSIONTYPE>
@@ -693,7 +768,7 @@ void complex_dumper(BinaryOStream<CONVERSIONTYPE>& f,
 }
 
 template<class HEADER,int CONVERSIONTYPE>
-void import_helper(img::MapHandle& image, std::istream& in, const MRC& formatmrc)
+void import_helper(img::MapHandle& image, std::istream& in,const MRC& formatmrc)
 {
   BinaryIStream<CONVERSIONTYPE> f(in);
   HEADER header;
@@ -756,9 +831,10 @@ void import_helper(img::MapHandle& image, std::istream& in, const MRC& formatmrc
 template<class HEADER>
 void import_endianess_switcher(img::MapHandle& image,
                              std::istream& f,
+                             std::istream& header_str,
                              const MRC& formatmrc)
 {
-  switch(HEADER::DetermineDataFormat(f)){
+  switch(HEADER::DetermineDataFormat(header_str)){
   case OST_BIG_ENDIAN:
    import_helper<HEADER,OST_BIG_ENDIAN>(image,f,formatmrc);
    break;
@@ -799,8 +875,7 @@ void export_endianess_switcher(const img::MapHandle& image,
                                 std::ostream& f,
                                 const MRC& formatmrc)
 {
-
-switch(formatmrc.GetEndianessOnSave()){
+  switch(formatmrc.GetEndianessOnSave()){
   case OST_BIG_ENDIAN:
     export_helper<HEADER,OST_BIG_ENDIAN>(image,f,formatmrc);
     break;
@@ -819,15 +894,22 @@ namespace bf = boost::filesystem;
 
 void MapIOMrcHandler::Import(img::MapHandle& sh, const boost::filesystem::path& loc,const ImageFormatBase& formatstruct )
 {
-  boost::filesystem::
-  ifstream infile(loc, std::ios::binary);
+  boost::filesystem::ifstream infile(loc, std::ios::binary);
   if(!infile)
   {
     throw IOException("could not open "+loc.string());
   }
+  boost::iostreams::filtering_stream<boost::iostreams::input> in;
+  if (detail::FilenameEndsWith(loc.string(),".map.gz")) {
+    in.push(boost::iostreams::gzip_decompressor());
+  }
+  in.push(boost::iostreams::file_source(loc.string()));
+  in.read(reinterpret_cast<char*>(&header_),256);
+  in.pop();
+  in.push(boost::iostreams::file_source(loc.string()));
   is_file_=true;
-  extension_=extension(loc);
-  this->Import(sh,infile,formatstruct);
+  filename_=loc.string();
+  this->Import(sh,in,formatstruct);
   infile.close();
 }
 
@@ -840,26 +922,32 @@ void MapIOMrcHandler::Import(img::MapHandle& sh, std::istream& loc, const ImageF
    } else {
      assert (formatstruct.GetFormatString()==UndefinedImageFormat::FORMAT_STRING);
    }
-
+   if (is_file_ == false){
+     loc.read(reinterpret_cast<char*>(&header_),256);
+     loc.seekg(0,std::ios::beg);
+   }
+   char* headerptr=(char*)&header_;
+   boost::iostreams::filtering_streambuf<boost::iostreams::input> head_strbuf;
+   std::istream head_str(&head_strbuf);
+   head_strbuf.push(boost::iostreams::basic_array_source<char>(headerptr,sizeof(header_)));
    if (formatmrc.GetSubformat()==MRC_OLD_FORMAT) {
      LOGN_DEBUG("mrc io: importing old style format");
-     detail::import_endianess_switcher<detail::mrc_header>(sh,loc,formatmrc);
+     detail::import_endianess_switcher<detail::mrc_header>(sh,loc,head_str,formatmrc);
    } else if (formatmrc.GetSubformat()==MRC_NEW_FORMAT) {
      LOGN_DEBUG("mrc io: importing new style format");
-     detail::import_endianess_switcher<detail::ccp4_header>(sh,loc,formatmrc);
-   } else if (is_file_ && ( extension_==".ccp4" || extension_==".map")) {
+     detail::import_endianess_switcher<detail::ccp4_header>(sh,loc,head_str,formatmrc);
+   } else if (is_file_ && (detail::FilenameEndsWith(filename_,".ccp4") || detail::FilenameEndsWith(filename_,".map") || detail::FilenameEndsWith(filename_,".map.gz"))) {
      LOGN_DEBUG("mrc io: importing new style format");
-     detail::import_endianess_switcher<detail::ccp4_header>(sh,loc,formatmrc);
+     detail::import_endianess_switcher<detail::ccp4_header>(sh,loc,head_str,formatmrc);
    } else {
-     unsigned char header[256];
-     loc.read(reinterpret_cast<char*>(&header),256);
-     loc.seekg(0, std::ios::beg);
-     if (MatchContent(header) == true) {
+	 unsigned char header_content[256];
+	 memcpy(&header_content,&header_,256*sizeof(char));
+     if (MatchContent(header_content) == true) {
        LOGN_DEBUG("mrc io: importing new style format");
-       detail::import_endianess_switcher<detail::ccp4_header>(sh,loc,formatmrc);
+       detail::import_endianess_switcher<detail::ccp4_header>(sh,loc,head_str,formatmrc);
      } else {
        LOGN_DEBUG("mrc io: importing old style format");
-       detail::import_endianess_switcher<detail::mrc_header>(sh,loc,formatmrc);
+       detail::import_endianess_switcher<detail::mrc_header>(sh,loc,head_str,formatmrc);
      }
   }
 }
@@ -873,7 +961,7 @@ void MapIOMrcHandler::Export(const img::MapHandle& image,
     throw IOException("could not open "+loc.string());
   }
   is_file_=true;
-  extension_=extension(loc);
+  filename_=loc.string();
   Export(image,outfile,formatstruct);
   outfile.close();
 }
@@ -915,10 +1003,11 @@ bool MapIOMrcHandler::MatchType(const ImageFormatBase& type)
   return false;
 }
 
-bool MapIOMrcHandler::MatchSuffix(const String& suffix)
+bool MapIOMrcHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-  if(suffix==".mrc" || suffix==".map" || suffix==".ccp4") {
-    return true;
+  if(detail::FilenameEndsWith(loc.string(),".mrc") || detail::FilenameEndsWith(loc.string(),".map") ||
+     detail::FilenameEndsWith(loc.string(),".ccp4") || detail::FilenameEndsWith(loc.string(),".map.gz")) {
+     return true;
   }
   return false;
 }
diff --git a/modules/io/src/img/map_io_mrc_handler.hh b/modules/io/src/img/map_io_mrc_handler.hh
index d5f96b6f9..76a6b9d36 100644
--- a/modules/io/src/img/map_io_mrc_handler.hh
+++ b/modules/io/src/img/map_io_mrc_handler.hh
@@ -62,7 +62,7 @@ public:
 
   MapIOMrcHandler():
    is_file_(false),
-   extension_("") {}
+   filename_("") {}
 
   /// \brief Map IO handler to read/write mrc and ccp4 map files
   ///
@@ -74,14 +74,15 @@ public:
   virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& loc);
   static String GetFormatName() { return String("Mrc"); };
   static String GetFormatDescription() { return String("Format used by the MRC software package"); };
 
 private:
 
   mutable bool is_file_;
-  mutable String extension_;
+  mutable String filename_;
+  char header_[256];
 
 };
 
diff --git a/modules/io/src/img/map_io_nanoscope_handler.cc b/modules/io/src/img/map_io_nanoscope_handler.cc
index 7288f703b..32ce6ccd1 100644
--- a/modules/io/src/img/map_io_nanoscope_handler.cc
+++ b/modules/io/src/img/map_io_nanoscope_handler.cc
@@ -234,9 +234,9 @@ bool MapIONanoscopeHandler::MatchType(const ImageFormatBase& type)
   return false;
 }
 
-bool MapIONanoscopeHandler::MatchSuffix(const String& suffix)
+bool MapIONanoscopeHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".mod") {
+    if(detail::FilenameEndsWith(loc.string(),".mod") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_nanoscope_handler.hh b/modules/io/src/img/map_io_nanoscope_handler.hh
index e9dda75c7..675889769 100644
--- a/modules/io/src/img/map_io_nanoscope_handler.hh
+++ b/modules/io/src/img/map_io_nanoscope_handler.hh
@@ -57,7 +57,7 @@ public:
   virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& loc);
   static String GetFormatName() { return String("Nanoscope"); }
   static String GetFormatDescription() { return String("Format used by software from Veeco"); }
 };
diff --git a/modules/io/src/img/map_io_png_handler.cc b/modules/io/src/img/map_io_png_handler.cc
index f11e472b3..38d88be66 100644
--- a/modules/io/src/img/map_io_png_handler.cc
+++ b/modules/io/src/img/map_io_png_handler.cc
@@ -311,9 +311,9 @@ bool MapIOPngHandler::MatchType(const ImageFormatBase& type)
   }
   return false;
 }
-bool MapIOPngHandler::MatchSuffix(const String& suffix)
+bool MapIOPngHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".png") {
+    if(detail::FilenameEndsWith(loc.string(),".png") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_png_handler.hh b/modules/io/src/img/map_io_png_handler.hh
index 0f3b54543..d5267a6da 100644
--- a/modules/io/src/img/map_io_png_handler.hh
+++ b/modules/io/src/img/map_io_png_handler.hh
@@ -52,7 +52,7 @@ public:
   virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& loc);
   static String GetFormatName() { return String("Png");}
   static String GetFormatDescription()  { return String("Portable Network Graphic image format");}
 };
diff --git a/modules/io/src/img/map_io_situs_handler.cc b/modules/io/src/img/map_io_situs_handler.cc
index 33a0391fa..f31444b30 100644
--- a/modules/io/src/img/map_io_situs_handler.cc
+++ b/modules/io/src/img/map_io_situs_handler.cc
@@ -272,9 +272,9 @@ bool MapIOSitusHandler::MatchType(const ImageFormatBase& type)
   return false;
 }
 
-bool MapIOSitusHandler::MatchSuffix(const String& suffix)
+bool MapIOSitusHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-  if(suffix==".situs" || suffix==".sit") {
+  if(detail::FilenameEndsWith(loc.string(),".situs") || detail::FilenameEndsWith(loc.string(),".sit") ) {
     return true;
   }
   return false;
diff --git a/modules/io/src/img/map_io_situs_handler.hh b/modules/io/src/img/map_io_situs_handler.hh
index 05933c552..a5d64a727 100644
--- a/modules/io/src/img/map_io_situs_handler.hh
+++ b/modules/io/src/img/map_io_situs_handler.hh
@@ -54,7 +54,7 @@ class DLLEXPORT_OST_IO MapIOSitusHandler: public MapIOHandler
   virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& loc);
   static String GetFormatName() { return "Situs"; };
   static String GetFormatDescription() { return "Format used by the Situs software package"; };
 };
diff --git a/modules/io/src/img/map_io_spi_handler.cc b/modules/io/src/img/map_io_spi_handler.cc
index 4a2f0a18f..6e10c30cc 100644
--- a/modules/io/src/img/map_io_spi_handler.cc
+++ b/modules/io/src/img/map_io_spi_handler.cc
@@ -512,9 +512,9 @@ bool MapIOSpiHandler::MatchType(const ImageFormatBase& type)
   }
   return false;
 }
-bool MapIOSpiHandler::MatchSuffix(const String& suffix)
+bool MapIOSpiHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-    if(suffix==".spi") {
+    if (detail::FilenameEndsWith(loc.string(),".spi") ) {
       return true;
     }
     return false;
diff --git a/modules/io/src/img/map_io_spi_handler.hh b/modules/io/src/img/map_io_spi_handler.hh
index 91eccb979..df2d61526 100644
--- a/modules/io/src/img/map_io_spi_handler.hh
+++ b/modules/io/src/img/map_io_spi_handler.hh
@@ -64,7 +64,7 @@ class DLLEXPORT_OST_IO MapIOSpiHandler: public MapIOHandler
   virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
   static bool MatchContent(unsigned char* header);
   static bool MatchType(const ImageFormatBase& type);
-  static bool MatchSuffix(const String& suffix);
+  static bool MatchSuffix(const boost::filesystem::path& loc);
   static String GetFormatName() { return String("Spider"); };
   static String GetFormatDescription() { return String("Format sued by the Spider software package"); };
 
diff --git a/modules/io/src/img/map_io_tiff_handler.cc b/modules/io/src/img/map_io_tiff_handler.cc
index 7203d99b0..863013dd0 100644
--- a/modules/io/src/img/map_io_tiff_handler.cc
+++ b/modules/io/src/img/map_io_tiff_handler.cc
@@ -427,9 +427,9 @@ bool MapIOTiffHandler::MatchType(const ImageFormatBase& type)
   return (type.GetFormatString()=="defined_tiff");
 }
 
-bool MapIOTiffHandler::MatchSuffix(const String& suffix)
+bool MapIOTiffHandler::MatchSuffix(const boost::filesystem::path& loc)
 {
-  return (suffix==".tif" || suffix==".tiff");
+  return (detail::FilenameEndsWith(loc.string(),".tif") || detail::FilenameEndsWith(loc.string(),".tiff") );
 }
 
 
diff --git a/modules/io/src/img/map_io_tiff_handler.hh b/modules/io/src/img/map_io_tiff_handler.hh
index 2ae42d7f2..8d9a9e3a6 100644
--- a/modules/io/src/img/map_io_tiff_handler.hh
+++ b/modules/io/src/img/map_io_tiff_handler.hh
@@ -90,7 +90,7 @@ class DLLEXPORT_OST_IO MapIOTiffHandler: public MapIOHandler
     virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
     static bool MatchContent(unsigned char* header);
     static bool MatchType(const ImageFormatBase& type);
-    static bool MatchSuffix(const String& suffix);
+    static bool MatchSuffix(const boost::filesystem::path& loc);
     static String GetFormatName() { return String( "Tiff"); }
     static String GetFormatDescription() { return String("Tagged Image File Format"); }
 
diff --git a/modules/io/src/io_manager.cc b/modules/io/src/io_manager.cc
index b48b67953..d64358ffa 100644
--- a/modules/io/src/io_manager.cc
+++ b/modules/io/src/io_manager.cc
@@ -140,16 +140,9 @@ MapIOHandlerPtr IOManager::FindMapImportHandlerFile(const boost::filesystem::pat
     }
     throw IOException("Unsupported type in FindMapImportHandle.");
   }else{
-    String filename = loc.string();
-    String::size_type pos = filename.rfind(".");
-    String::size_type spos = filename.rfind("/");
-    if (pos != String::npos && (spos==String::npos || spos<pos)){
-      String ext=filename.substr(pos);
-      std::transform(ext.begin(),ext.end(),ext.begin(),tolower);
-      for(MapIOFList::const_iterator it=map_io_list_.begin(); it!=map_io_list_.end();++it) {
-        if((*it)->MatchSuffix(ext)) {
-          return (*it)->Create();
-        }
+    for(MapIOFList::const_iterator it=map_io_list_.begin(); it!=map_io_list_.end();++it) {
+      if((*it)->MatchSuffix(loc)) {
+        return (*it)->Create();
       }
     }
     unsigned char header[256];
@@ -167,7 +160,7 @@ MapIOHandlerPtr IOManager::FindMapImportHandlerFile(const boost::filesystem::pat
         return (*it)->Create();
       }
     }
-    throw IOException("No file suffix given for " + filename+", and could not detect automatically, please indicate file type.");    
+    throw IOException("No file suffix given for " + loc.string()+", and could not detect automatically, please indicate file type.");
   }
   return MapIOHandlerPtr();  // removes warning
 }
@@ -213,10 +206,8 @@ MapIOHandlerPtr IOManager::FindMapExportHandlerFile(const boost::filesystem::pat
     if (pos == String::npos){
       throw IOException("No file suffix given for " + filename+", please indicate file type.");
     }
-    String ext=filename.substr(pos);
-    std::transform(ext.begin(),ext.end(),ext.begin(),tolower);
     for(MapIOFList::const_iterator it=map_io_list_.begin(); it!=map_io_list_.end();++it) {
-      if((*it)->MatchSuffix(ext)) {
+      if((*it)->MatchSuffix(loc)) {
         return(*it)->Create();
       }
     }
diff --git a/modules/io/src/io_manager.hh b/modules/io/src/io_manager.hh
index a320f01ce..cccc37575 100644
--- a/modules/io/src/io_manager.hh
+++ b/modules/io/src/io_manager.hh
@@ -145,6 +145,8 @@ private:
 #endif
 };
 
+
+
 }}
 
 #endif
diff --git a/modules/io/src/io_utils.cc b/modules/io/src/io_utils.cc
new file mode 100644
index 000000000..905c5545c
--- /dev/null
+++ b/modules/io/src/io_utils.cc
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2003-2010 by the IPLT authors
+// Copyright (C) 2008-2010 by the OpenStructure authors
+//
+// 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 3.0 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <algorithm>
+#include "io_utils.hh"
+
+namespace ost { namespace io { namespace detail {
+
+bool FilenameEndsWith(const String& target,const String& probe) {
+  return std::mismatch( probe.rbegin(), probe.rend(), target.rbegin() ).first == probe.rend();
+}
+
+}}}
diff --git a/modules/io/src/io_utils.hh b/modules/io/src/io_utils.hh
new file mode 100644
index 000000000..677b3024a
--- /dev/null
+++ b/modules/io/src/io_utils.hh
@@ -0,0 +1,31 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2003-2010 by the IPLT authors
+// Copyright (C) 2008-2010 by the OpenStructure authors
+//
+// 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 3.0 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_IO_UTIL_HH
+#define OST_IO_UTIL_HH
+
+#include <ost/base.hh>
+
+namespace ost { namespace io { namespace detail {
+
+bool FilenameEndsWith(const String& target,const String& probe);
+
+}}} // ns
+
+#endif // OST_IO_UTIL_HH 
diff --git a/modules/io/src/mol/entity_io_crd_handler.cc b/modules/io/src/mol/entity_io_crd_handler.cc
index 7ff0dc0f2..5d730787a 100644
--- a/modules/io/src/mol/entity_io_crd_handler.cc
+++ b/modules/io/src/mol/entity_io_crd_handler.cc
@@ -181,8 +181,7 @@ namespace {
 bool crd_handler_is_responsible_for(const boost::filesystem::path& loc,
                                     const String& type) {
   if(type=="auto") {
-    String ext=extension(loc);
-    if(boost::iequals(ext,".crd") || boost::iequals(ext, ".crd.gz")) {
+    if( detail::FilenameEndsWith(loc.string(),".crd") || detail::FilenameEndsWith(loc.string(),".crd.gz") ) {
       return true;
     }
   } else if(type=="crd") {
diff --git a/modules/io/src/mol/entity_io_handler.hh b/modules/io/src/mol/entity_io_handler.hh
index 8885a1d91..c1a64703d 100644
--- a/modules/io/src/mol/entity_io_handler.hh
+++ b/modules/io/src/mol/entity_io_handler.hh
@@ -24,6 +24,7 @@
 
 
 #include <ost/io/module_config.hh>
+#include <ost/io/io_utils.hh>
 #include <ost/mol/mol.hh>
 
 namespace ost { namespace io {
diff --git a/modules/io/src/mol/entity_io_pdb_handler.cc b/modules/io/src/mol/entity_io_pdb_handler.cc
index d3dceb0ff..8ec58b26c 100644
--- a/modules/io/src/mol/entity_io_pdb_handler.cc
+++ b/modules/io/src/mol/entity_io_pdb_handler.cc
@@ -76,9 +76,8 @@ namespace {
 bool pdb_handler_is_responsible_for(const boost::filesystem::path& loc,
                                     const String& type) {
   if(type=="auto") {
-    String ext=extension(loc);
-    if(boost::iequals(ext,".pdb") || boost::iequals(ext, ".ent")||
-       boost::iequals(ext, ".gz") || boost::iequals(ext, ".pqr")) {
+    if(detail::FilenameEndsWith(loc.string(),".pdb") || detail::FilenameEndsWith(loc.string(),".ent") ||
+       detail::FilenameEndsWith(loc.string(),".pdb.gz") || detail::FilenameEndsWith(loc.string(),".par") ){
       return true;
     }
 
diff --git a/modules/io/src/mol/entity_io_sdf_handler.cc b/modules/io/src/mol/entity_io_sdf_handler.cc
index d3d0bda1d..49b699024 100644
--- a/modules/io/src/mol/entity_io_sdf_handler.cc
+++ b/modules/io/src/mol/entity_io_sdf_handler.cc
@@ -409,8 +409,7 @@ namespace {
 bool sdf_handler_is_responsible_for(const boost::filesystem::path& loc,
                                     const String& type) {
   if(type=="auto") {
-    String ext=extension(loc);
-    if(boost::iequals(ext,".sdf")) {
+    if(detail::FilenameEndsWith(loc.string(),".sdf")) {
       return true;
     }
 
diff --git a/modules/io/src/seq/clustal_io_handler.cc b/modules/io/src/seq/clustal_io_handler.cc
index 9c56a05fa..3456befad 100644
--- a/modules/io/src/seq/clustal_io_handler.cc
+++ b/modules/io/src/seq/clustal_io_handler.cc
@@ -51,8 +51,7 @@ void ClustalIOHandler::Export(const seq::ConstSequenceList& msa,
 bool ClustalIOHandler::ProvidesImport(const boost::filesystem::path& loc, 
                                     const String& format) {
   if (format=="auto") {
-   String ext=extension(loc);
-   if (boost::iequals(ext,".aln")) {
+   if (detail::FilenameEndsWith(loc.string(),".aln")) {
      return true;
    }
   } else if(format=="clustal") {
diff --git a/modules/io/src/seq/fasta_io_handler.cc b/modules/io/src/seq/fasta_io_handler.cc
index 5bb0e9797..af2b2db50 100644
--- a/modules/io/src/seq/fasta_io_handler.cc
+++ b/modules/io/src/seq/fasta_io_handler.cc
@@ -56,11 +56,12 @@ void FastaIOHandler::Export(const seq::ConstSequenceList& msa,
 bool FastaIOHandler::ProvidesImport(const boost::filesystem::path& loc, 
                                     const String& format) {
   if (format=="auto") {
-   String ext=extension(loc);
-   if (boost::iequals(ext,".fasta") || boost::iequals(ext, ".fa") ||
-       boost::iequals(ext, ".fna") || boost::iequals(ext, ".fsa") || 
-       boost::iequals(ext, ".fas")) {
-     return true;
+
+
+   if (detail::FilenameEndsWith(loc.string(),".fasta") || detail::FilenameEndsWith(loc.string(),".fa") ||
+       detail::FilenameEndsWith(loc.string(),".fnaa") || detail::FilenameEndsWith(loc.string(),".fsa") ||
+       detail::FilenameEndsWith(loc.string(),".fas") )  {
+	return true;
    }
   } else if(format=="fasta") {
     return true;
diff --git a/modules/io/src/seq/promod_io_handler.cc b/modules/io/src/seq/promod_io_handler.cc
index 8851d885e..518c6b34e 100644
--- a/modules/io/src/seq/promod_io_handler.cc
+++ b/modules/io/src/seq/promod_io_handler.cc
@@ -52,8 +52,7 @@ void PromodIOHandler::Export(const seq::ConstSequenceList& msa,
 bool PromodIOHandler::ProvidesImport(const boost::filesystem::path& loc, 
                                     const String& format) {
   if (format=="auto") {
-   String ext=extension(loc);
-   if (boost::iequals(ext,".ali")) {
+   if (detail::FilenameEndsWith(loc.string(),".ali")) {
      return true;
    }
   } else if(format=="promod") {
diff --git a/modules/io/src/seq/sequence_io_handler.hh b/modules/io/src/seq/sequence_io_handler.hh
index 84249c4fc..cc918478a 100644
--- a/modules/io/src/seq/sequence_io_handler.hh
+++ b/modules/io/src/seq/sequence_io_handler.hh
@@ -25,6 +25,7 @@
 
 #include <ost/io/module_config.hh>
 #include <ost/seq/sequence_list.hh>
+#include <ost/io/io_utils.hh>
 
 namespace ost { namespace io {
 
-- 
GitLab