Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

FuzzyStringComparator.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Stephan Aiche $
00032 // $Authors: Clemens Groepl, Stephan Aiche $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_CONCEPT_FUZZYSTRINGCOMPARATOR_H
00036 #define OPENMS_CONCEPT_FUZZYSTRINGCOMPARATOR_H
00037 
00038 #include <OpenMS/CONCEPT/Types.h>
00039 #include <OpenMS/DATASTRUCTURES/String.h>
00040 #include <OpenMS/DATASTRUCTURES/StringList.h>
00041 
00042 #include <cstdlib> // for strtod()
00043 #include <fstream>
00044 #include <iostream>
00045 #include <cctype> // for isspace()
00046 #include <limits> // for NaN
00047 #include <sstream>
00048 #include <map>
00049 
00050 namespace OpenMS
00051 {
00052   namespace Internal
00053   {
00054     namespace ClassTest
00055     {
00056       void OPENMS_DLLAPI
00057       testStringSimilar(const char * file, int line,
00058                         const std::string & string_1,
00059                         const char * string_1_stringified,
00060                         const std::string & string_2,
00061                         const char * string_2_stringified);
00062       bool OPENMS_DLLAPI
00063       isFileSimilar(const std::string &, const std::string &);
00064     }
00065   }
00066 
00071   class OPENMS_DLLAPI FuzzyStringComparator
00072   {
00073 
00074     friend void OPENMS_DLLAPI
00075     Internal::ClassTest::testStringSimilar(
00076       const char * file,
00077       int line,
00078       const std::string & string_1,
00079       const char * string_1_stringified,
00080       const std::string & string_2,
00081       const char * string_2_stringified);
00082     friend bool OPENMS_DLLAPI
00083     Internal::ClassTest::isFileSimilar(const std::string &,
00084                                        const std::string &);
00085 
00087     struct AbortComparison
00088     {
00089     };
00090 
00091 public:
00092 
00094 
00095 
00097     FuzzyStringComparator();
00098 
00100     virtual
00101     ~FuzzyStringComparator();
00102 
00104     FuzzyStringComparator(const FuzzyStringComparator & rhs);
00105 
00107     FuzzyStringComparator &
00108     operator=(const FuzzyStringComparator & rhs);
00109 
00111 
00113     const double &
00114     getAcceptableRelative() const
00115     {
00116       return ratio_max_allowed_;
00117     }
00118 
00120     void
00121     setAcceptableRelative(const double rhs)
00122     {
00123       this->ratio_max_allowed_ = rhs;
00124       if (ratio_max_allowed_ < 1.0)
00125         ratio_max_allowed_ = 1
00126                              / ratio_max_allowed_;
00127 
00128     }
00129 
00131     const double &
00132     getAcceptableAbsolute() const
00133     {
00134       return absdiff_max_allowed_;
00135     }
00136 
00138     void
00139     setAcceptableAbsolute(const double rhs)
00140     {
00141       this->absdiff_max_allowed_ = rhs;
00142       if (absdiff_max_allowed_ < 0.0)
00143         absdiff_max_allowed_
00144           = -absdiff_max_allowed_;
00145     }
00146 
00148     const StringList &
00149     getWhitelist() const
00150     {
00151       return whitelist_;
00152     }
00153 
00155     StringList &
00156     getWhitelist()
00157     {
00158       return whitelist_;
00159     }
00160 
00162     void
00163     setWhitelist(const StringList & rhs)
00164     {
00165       whitelist_ = rhs;
00166     }
00167 
00176     const int &
00177     getVerboseLevel() const
00178     {
00179       return verbose_level_;
00180     }
00181 
00190     void
00191     setVerboseLevel(const int rhs)
00192     {
00193       this->verbose_level_ = rhs;
00194     }
00195 
00198     const int &
00199     getTabWidth() const
00200     {
00201       return tab_width_;
00202     }
00203 
00206     void
00207     setTabWidth(const int rhs)
00208     {
00209       this->tab_width_ = rhs;
00210     }
00211 
00214     const int &
00215     getFirstColumn() const
00216     {
00217       return first_column_;
00218     }
00219 
00222     void
00223     setFirstColumn(const int rhs)
00224     {
00225       this->first_column_ = rhs;
00226     }
00227 
00233     std::ostream &
00234     getLogDestination() const
00235     {
00236       return *log_dest_;
00237     }
00238 
00248     void
00249     setLogDestination(std::ostream & rhs)
00250     {
00251       this->log_dest_ = &rhs;
00252     }
00253 
00260     bool
00261     compareStrings(std::string const & lhs, std::string const & rhs);
00262 
00270     bool
00271     compareStreams(std::istream & input_1, std::istream & input_2);
00272 
00286     bool
00287     compareFiles(const std::string & filename_1,
00288                  const std::string & filename_2);
00289 
00290 protected:
00291 
00299     bool
00300     compareLines_(std::string const & line_str_1,
00301                   std::string const & line_str_2);
00302 
00304     void
00305     reportSuccess_() const;
00306 
00309     void
00310     reportFailure_(char const * const message) const;
00311 
00313     void writeWhitelistCases_(const std::string & prefix) const;
00314 
00317     void readNextLine_(std::istream & input_stream, std::string & line_string, int & line_number) const;
00318 
00320     bool openInputFileStream_(const std::string & filename, std::ifstream & input_stream) const;
00321 
00323     std::ostream * log_dest_;
00324 
00326     std::string input_1_name_;
00328     std::string input_2_name_;
00329 
00331     struct InputLine
00332     {
00333       std::stringstream line_;
00334       std::ios::pos_type line_position_;
00335 
00336       InputLine() :
00337         line_()
00338       {
00339       }
00340 
00342       void setToString(const std::string & s)
00343       {
00344         line_.str(s);
00345         line_.seekp(0);
00346         line_.clear();
00347         line_.unsetf(std::ios::skipws);
00348 
00349         line_position_ = line_.tellg();
00350       }
00351 
00353       void updatePosition()
00354       {
00355         line_position_ = (Int(line_.tellg()) != -1 ? line_.tellg() : std::ios::pos_type(line_.str().length()));             // save current reading position
00356       }
00357 
00359       void seekGToSavedPosition()
00360       {
00361         line_.clear();             // reset status
00362         line_.seekg(line_position_);             // rewind to saved position
00363       }
00364 
00372       operator void *() const
00373       {
00374         return line_.operator void *();
00375       }
00376     };
00377 
00378     InputLine input_line_1_;
00379     InputLine input_line_2_;
00380 
00381     int line_num_1_;
00382     int line_num_2_;
00383 
00384     int line_num_1_max_;
00385     int line_num_2_max_;
00386 
00387     std::string line_str_1_max_;
00388     std::string line_str_2_max_;
00389 
00391     double ratio_max_allowed_;
00392 
00394     double ratio_max_;
00395 
00397     double absdiff_max_allowed_;
00398 
00400     double absdiff_max_;
00401 
00403     struct StreamElement_
00404     {
00405       double number;
00406       unsigned char letter;
00407       bool is_number;
00408       bool is_space;
00409 
00410       StreamElement_() :
00411         number(0),
00412         letter(0),
00413         is_number(false),
00414         is_space(false)
00415       {}
00416 
00418       void reset()
00419       {
00420         is_number = false;
00421         is_space = false;
00422         letter = '\0';
00423         number = std::numeric_limits<double>::quiet_NaN();
00424       }
00425 
00427       void fillFromInputLine(InputLine & input_line)
00428       {
00429         // first reset all internal variables so we do not mess with
00430         // old values
00431         reset();
00432 
00433         input_line.updatePosition();
00434         input_line.line_ >> letter;             // read letter
00435         if ((is_space = (isspace(letter) != 0)))               // is whitespace?
00436         {
00437           input_line.line_ >> std::ws;               // skip over further whitespace
00438         }
00439         else
00440         {
00441           input_line.seekGToSavedPosition();
00442           if ((is_number = ((input_line.line_ >> number) != 0)))                    // is a number?
00443           {
00444           }
00445           else
00446           {
00447             input_line.seekGToSavedPosition();
00448             input_line.line_ >> letter;                 // read letter
00449           }
00450         }
00451       }
00452 
00453     };
00454 
00456     StreamElement_ element_1_;
00458     StreamElement_ element_2_;
00459 
00461     struct PrefixInfo_
00462     {
00463       OpenMS::String prefix;
00464       OpenMS::String prefix_whitespaces;
00465       int line_column;
00466 
00467       PrefixInfo_(const InputLine & input_line, const int tab_width_, const int first_column_) :
00468         prefix(input_line.line_.str()), line_column(0)
00469       {
00470         prefix = prefix.prefix(size_t(input_line.line_position_));
00471         prefix_whitespaces = prefix;
00472         for (String::iterator iter = prefix_whitespaces.begin(); iter != prefix_whitespaces.end(); ++iter)
00473         {
00474           if (*iter != '\t')
00475           {
00476             * iter = ' ';
00477             ++line_column;
00478           }
00479           else
00480           {
00481             line_column = (line_column / tab_width_ + 1) * tab_width_;
00482           }
00483         }
00484         line_column += first_column_;
00485       }
00486 
00487     };
00488 
00489     bool is_absdiff_small_;
00490 
00491     int verbose_level_;
00492     int tab_width_;
00493     int first_column_;
00494 
00498     bool is_status_success_;
00499 
00501     bool use_prefix_;
00502 
00503     StringList whitelist_;
00504     std::map<String, UInt> whitelist_cases_;
00505 
00506   }; // class FuzzyStringComparator
00507 
00508 } //namespace OpenMS
00509 
00510 #endif //OPENMS_CONCEPT_FUZZYSTRINGCOMPARATOR_H

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:39 using doxygen 1.7.1