Here's a minor patch in case it's of use - but feel free to tell me to
shut up if it isn't.

Looking at some of the file-handling code I noticed that a lot of places
check a string for a particular prefix or suffix with this kind of pattern:

  if (
    (text.size() >= suffix.size()) &&
    (text.substr(text.size()-suffix.size()) == suffix)) {

It's a bit hard to read, and could lead to strange crashes if you forget
the length check.  For example, checking for...

  filename.substr(filename.size()-3) == ".gz"

...would crash if filename was less than 3 characters long.

If anyone's interested, I'm attaching a patch that replaces all
prefix/suffix checks that I could find with BOOST's starts_with() and
ends_with().  It's a little safer and easier to follow, and doesn't make
you count the characters in a fixed-length suffix:

  if (ends_with(text, suffix)) {
  if (ends_with(filename, ".gz")) {
  if (starts_with(item, "[") && ends_with(item, "]")) {

None of these cases looked particularly performance-sensitive, but I
checked just in case.  If anything, the BOOST code looks more
optimizer-friendly.  It compares characters in-place (so no need to copy
a substring) and seems to optimize for the known length of string
constants (so it knows at compile time that ".gz" is 3 characters long).

I haven't done any manual testing, but the unit tests pass.  Is that
considered a reasonable guarantee?


Jeroen
diff --git a/OnDiskPt/Word.cpp b/OnDiskPt/Word.cpp
index 9e6fb65..8932732 100644
--- a/OnDiskPt/Word.cpp
+++ b/OnDiskPt/Word.cpp
@@ -18,6 +18,7 @@
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  ***********************************************************************/
 
+#include <boost/algorithm/string/predicate.hpp>
 #include "moses/FactorCollection.h"
 #include "moses/Util.h"
 #include "moses/Word.h"
@@ -27,6 +28,7 @@
 #include "util/exception.hh"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace OnDiskPt
 {
@@ -41,7 +43,7 @@ Word::~Word()
 
 void Word::CreateFromString(const std::string &inString, Vocab &vocab)
 {
-  if (inString.substr(0, 1) == "[" && inString.substr(inString.size() - 1, 1) == "]") {
+  if (starts_with(inString, "[") && ends_with(inString, "]")) {
     // non-term
     m_isNonTerminal = true;
     string str = inString.substr(1, inString.size() - 2);
diff --git a/contrib/other-builds/manual-label/EnOpenNLPChunker.cpp b/contrib/other-builds/manual-label/EnOpenNLPChunker.cpp
index 67c2e9d..e2c2935 100644
--- a/contrib/other-builds/manual-label/EnOpenNLPChunker.cpp
+++ b/contrib/other-builds/manual-label/EnOpenNLPChunker.cpp
@@ -8,10 +8,12 @@
 #include <stdio.h>
 #include <algorithm>
 #include <fstream>
+#include <boost/algorithm/string/predicate.hpp>
 #include "EnOpenNLPChunker.h"
 #include "moses/Util.h"
 
 using namespace std;
+using namespace boost::algorithm;
 
 EnOpenNLPChunker::EnOpenNLPChunker(const std::string &openNLPPath)
 :m_openNLPPath(openNLPPath)
@@ -85,7 +87,7 @@ void EnOpenNLPChunker::MosesReformat(const string &line, std::ostream &out, cons
 				inLabel = true;
 			}
 		}
-		else if (tok.substr(tok.size()-1, 1) == "]") {
+		else if (ends_with(tok, "]")) {
 			// end of chunk
 			if (tok.size() > 1) {
 				if (tok.substr(1,1) == "_") {
diff --git a/moses/FF/LexicalReordering/LexicalReordering.cpp b/moses/FF/LexicalReordering/LexicalReordering.cpp
index 7be2f1d..0630d10 100644
--- a/moses/FF/LexicalReordering/LexicalReordering.cpp
+++ b/moses/FF/LexicalReordering/LexicalReordering.cpp
@@ -1,4 +1,5 @@
 #include <sstream>
+#include <boost/algorithm/string/predicate.hpp>
 
 #include "moses/FF/FFState.h"
 #include "LexicalReordering.h"
@@ -6,6 +7,7 @@
 #include "moses/StaticData.h"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -29,7 +31,7 @@ LexicalReordering::LexicalReordering(const std::string &line)
       m_factorsE =Tokenize<FactorType>(args[1]);
     } else if (args[0] == "path") {
       m_filePath = args[1];
-    } else if (args[0].substr(0,7) == "sparse-") {
+    } else if (starts_with(args[0], "sparse-")) {
       sparseArgs[args[0].substr(7)] = args[1];
     } else if (args[0] == "default-scores") {
       vector<string> tokens = Tokenize(args[1],",");
diff --git a/moses/Parameter.cpp b/moses/Parameter.cpp
index cd9d3b2..c5677b7 100644
--- a/moses/Parameter.cpp
+++ b/moses/Parameter.cpp
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #include <fstream>
 #include <sstream>
 #include <algorithm>
+#include <boost/algorithm/string/predicate.hpp>
 #include "Parameter.h"
 #include "Util.h"
 #include "InputFileStream.h"
@@ -32,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #include "util/exception.hh"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -270,8 +272,9 @@ bool Parameter::isOption(const char* token)
   if (! token) return false;
   std::string tokenString(token);
   size_t length = tokenString.size();
-  if (length > 0 && tokenString.substr(0,1) != "-") return false;
-  if (length > 1 && tokenString.substr(1,1).find_first_not_of("0123456789") == 0) return true;
+  if (length <= 1) return false;
+  if (!starts_with(tokenString, "-")) return false;
+  if (tokenString.substr(1,1).find_first_not_of("0123456789") == 0) return true;
   return false;
 }
 
@@ -975,7 +978,7 @@ void Parameter::WeightOverwrite()
   for (size_t i = 0; i < toks.size(); ++i) {
     const string &tok = toks[i];
 
-    if (tok.substr(tok.size() - 1, 1) == "=") {
+    if (starts_with(tok, "=")) {
       // start of new feature
 
       if (name != "") {
diff --git a/moses/ScoreComponentCollection.cpp b/moses/ScoreComponentCollection.cpp
index b8c93c1..a1c8646 100644
--- a/moses/ScoreComponentCollection.cpp
+++ b/moses/ScoreComponentCollection.cpp
@@ -1,5 +1,6 @@
 // $Id$
 #include <vector>
+#include <boost/algorithm/string/predicate.hpp>
 #include "util/exception.hh"
 #include "ScoreComponentCollection.h"
 #include "StaticData.h"
@@ -7,6 +8,7 @@
 #include "moses/FF/StatefulFeatureFunction.h"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -87,7 +89,7 @@ void ScoreComponentCollection::MultiplyEquals(const FeatureFunction* sp, float s
   for(FVector::FNVmap::const_iterator i = m_scores.cbegin(); i != m_scores.cend(); i++) {
     std::stringstream name;
     name << i->first;
-    if (name.str().substr( 0, prefix.length() ).compare( prefix ) == 0)
+    if (starts_with(name.str(), prefix))
       m_scores[i->first] = i->second * scalar;
   }
 }
@@ -100,7 +102,7 @@ size_t ScoreComponentCollection::GetNumberWeights(const FeatureFunction* sp)
   for(FVector::FNVmap::const_iterator i = m_scores.cbegin(); i != m_scores.cend(); i++) {
     std::stringstream name;
     name << i->first;
-    if (name.str().substr( 0, prefix.length() ).compare( prefix ) == 0)
+    if (starts_with(name.str(), prefix))
       weights++;
   }
   return weights;
@@ -285,7 +287,7 @@ FVector ScoreComponentCollection::GetVectorForProducer(const FeatureFunction* sp
   for(FVector::FNVmap::const_iterator i = m_scores.cbegin(); i != m_scores.cend(); i++) {
     std::stringstream name;
     name << i->first;
-    if (name.str().substr( 0, prefix.length() ).compare( prefix ) == 0)
+    if (starts_with(name.str(), prefix))
       fv[i->first] = i->second;
   }
   return fv;
diff --git a/moses/StaticData.cpp b/moses/StaticData.cpp
index ce6d765..94d5381 100644
--- a/moses/StaticData.cpp
+++ b/moses/StaticData.cpp
@@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 ***********************************************************************/
 
 #include <string>
+#include <boost/algorithm/string/predicate.hpp>
 
 #include "moses/FF/Factory.h"
 #include "TypeDef.h"
@@ -50,6 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #endif
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -1176,7 +1178,7 @@ void StaticData::ResetWeights(const std::string &denseWeights, const std::string
   for (size_t i = 0; i < toks.size(); ++i) {
     const string &tok = toks[i];
 
-    if (tok.substr(tok.size() - 1, 1) == "=") {
+    if (ends_with(tok, "=")) {
       // start of new feature
 
       if (name != "") {
diff --git a/moses/TranslationModel/RuleTable/LoaderStandard.cpp b/moses/TranslationModel/RuleTable/LoaderStandard.cpp
index 410a53e..95463fe 100644
--- a/moses/TranslationModel/RuleTable/LoaderStandard.cpp
+++ b/moses/TranslationModel/RuleTable/LoaderStandard.cpp
@@ -26,6 +26,7 @@
 #include <iostream>
 #include <sys/stat.h>
 #include <stdlib.h>
+#include <boost/algorithm/string/predicate.hpp>
 #include "Trie.h"
 #include "moses/FactorCollection.h"
 #include "moses/Word.h"
@@ -42,6 +43,7 @@
 #include "util/exception.hh"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -67,8 +69,7 @@ void ReformatHieroRule(int sourceTarget, string &phrase, map<size_t, pair<size_t
 
   for (size_t i = 0; i < toks.size(); ++i) {
     string &tok = toks[i];
-    size_t tokLen = tok.size();
-    if (tok.substr(0, 1) == "[" && tok.substr(tokLen - 1, 1) == "]") {
+    if (starts_with(tok, "[") && ends_with(tok, "]")) {
       // no-term
       vector<string> split = Tokenize(tok, ",");
       UTIL_THROW_IF2(split.size() != 2,
diff --git a/moses/TranslationModel/UG/generic/file_io/ug_stream.cpp b/moses/TranslationModel/UG/generic/file_io/ug_stream.cpp
index 4e0c7cb..073b64d 100644
--- a/moses/TranslationModel/UG/generic/file_io/ug_stream.cpp
+++ b/moses/TranslationModel/UG/generic/file_io/ug_stream.cpp
@@ -2,11 +2,13 @@
 // (c) 2006,2007,2008 Ulrich Germann
 // makes opening files a little more convenient
 
+#include <boost/algorithm/string/predicate.hpp>
 #include "ug_stream.h"
 
 namespace ugdiss
 {
   using namespace std;
+  using namespace boost::algorithm;
   using namespace boost::iostreams;
 
   filtering_istream* 
@@ -28,11 +30,11 @@ namespace ugdiss
   void 
   open_input_stream(string fname, filtering_istream& in)
   {
-    if (fname.size()>3 && fname.substr(fname.size()-3,3)==".gz")
+    if (ends_with(fname, ".gz"))
       {
 	in.push(gzip_decompressor());
       }
-    else if (fname.size() > 4 && fname.substr(fname.size()-4,4)==".bz2")
+    else if (ends_with(fname, "bz2"))
       {
 	in.push(bzip2_decompressor());
       }
@@ -42,13 +44,11 @@ namespace ugdiss
   void 
   open_output_stream(string fname, filtering_ostream& out)
   {
-    if ((fname.size() > 3 && fname.substr(fname.size()-3,3)==".gz") ||
-	(fname.size() > 4 && fname.substr(fname.size()-4,4)==".gz_"))
+    if (ends_with(fname, ".gz") || ends_with(fname, ".gz_"))
       {
 	out.push(gzip_compressor());
       }
-    else if ((fname.size() > 4 && fname.substr(fname.size()-4,4)==".bz2") ||
-	     (fname.size() > 5 && fname.substr(fname.size()-5,5)==".bz2_"))
+    else if (ends_with(fname, ".bz2") || ends_with(fname, ".bz2_"))
       {
 	out.push(bzip2_compressor());
       }
diff --git a/moses/TranslationModel/UG/mm/mtt-build.cc b/moses/TranslationModel/UG/mm/mtt-build.cc
index 49fd7f6..f49895e 100644
--- a/moses/TranslationModel/UG/mm/mtt-build.cc
+++ b/moses/TranslationModel/UG/mm/mtt-build.cc
@@ -4,6 +4,7 @@
 // recognized based on the number of fields per line) into memory-mapped
 // format. (c) 2007-2013 Ulrich Germann
 
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/program_options.hpp>
 #include <boost/program_options/options_description.hpp>
 #include <boost/program_options/parsers.hpp>
@@ -32,6 +33,7 @@ using namespace std;
 using namespace ugdiss;
 using namespace Moses;
 using namespace boost;
+using namespace boost::algorithm;
 namespace po=boost::program_options;
 
 int with_pfas;
@@ -200,7 +202,7 @@ process_tagged_input(ostream& out,
       vector<string> w; string f; istringstream buf(line);
       while (buf>>f) w.push_back(f);
 
-      if (w.size() == 0 || (w[0].size() >= 4 && w[0].substr(0,4) == "SID="))
+      if (w.size() == 0 || starts_with(w[0], "SID="))
         new_sent = true;
 
       else if (w.size() == 1 && w[0] == "<P>") 
diff --git a/moses/TranslationModel/UG/spe-check-coverage.cc b/moses/TranslationModel/UG/spe-check-coverage.cc
index 039b4cd..4ab2d74 100644
--- a/moses/TranslationModel/UG/spe-check-coverage.cc
+++ b/moses/TranslationModel/UG/spe-check-coverage.cc
@@ -1,6 +1,7 @@
 #include "mmsapt.h"
 #include "moses/TranslationModel/PhraseDictionaryTreeAdaptor.h"
 #include "moses/TranslationModel/UG/generic/program_options/ug_splice_arglist.h"
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/foreach.hpp>
 #include <boost/format.hpp>
 #include <boost/tokenizer.hpp>
@@ -12,6 +13,7 @@ using namespace Moses;
 using namespace bitext;
 using namespace std;
 using namespace boost;
+using namespace boost::algorithm;
 
 vector<FactorType> fo(1,FactorType(0));
 
@@ -111,7 +113,7 @@ int main(int argc, char* argv[])
       int dynprovidx = -1;
       for (size_t i = 0; i < fname.size(); ++i)
 	{
-	  if (fname[i].substr(0,7) == "prov-1.") 
+	  if (starts_with(fname[i], "prov-1."))
 	    dynprovidx = i;
 	}
       cout << endl;
@@ -189,8 +191,8 @@ int main(int argc, char* argv[])
 		      size_t j = x-idx.first;
 		      float f = (mmsapt && mmsapt->isLogVal(j)) ? exp(scores[x]) : scores[x];
 		      string fmt = (mmsapt && mmsapt->isInteger(j)) ? "%10d" : "%10.8f";
-		      if (fname[j].substr(0,3) == "lex") fmt = "%10.3e";
-		      if (fname[j].substr(0,7) == "prov-1.") 
+		      if (starts_with(fname[j], "lex")) fmt = "%10.3e";
+		      else if (starts_with(fname[j], "prov-1."))
 			{
 			  f = round(f/(1-f));
 			  fmt = "%10d";
diff --git a/moses/Util.cpp b/moses/Util.cpp
index 24323f6..5b6f16e 100644
--- a/moses/Util.cpp
+++ b/moses/Util.cpp
@@ -32,6 +32,7 @@
 #include <stdio.h>
 #include <iostream>
 #include <iomanip>
+#include <boost/algorithm/string/predicate.hpp>
 #include "TypeDef.h"
 #include "Util.h"
 #include "Timer.h"
@@ -42,6 +43,7 @@
 #include "moses/StaticData.h"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -54,7 +56,7 @@ string GetTempFolder()
 #ifdef _WIN32
   char *tmpPath = getenv("TMP");
   string str(tmpPath);
-  if (str.substr(str.size() - 1, 1) != "\\")
+  if (!ends_with(str, "\\"))
     str += "\\";
   return str;
 #else
diff --git a/moses/XmlOption.cpp b/moses/XmlOption.cpp
index 3ac4f6c..38b767d 100644
--- a/moses/XmlOption.cpp
+++ b/moses/XmlOption.cpp
@@ -24,6 +24,7 @@
 #include <vector>
 #include <string>
 #include <iostream>
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/foreach.hpp>
 #include <boost/unordered_map.hpp>
 #include "Util.h"
@@ -40,6 +41,7 @@
 namespace Moses
 {
 using namespace std;
+using namespace boost::algorithm;
 
 string ParseXmlTagAttribute(const string& tag,const string& attributeName)
 {
@@ -73,7 +75,7 @@ string TrimXml(const string& str, const std::string& lbrackStr, const std::strin
   if (str.size() < lbrackStr.length()+rbrackStr.length() ) return str;
 
   // strip first and last character
-  if (str.substr(0,lbrackStr.length()) == lbrackStr  &&  str.substr(str.size()-rbrackStr.length()) == rbrackStr) {
+  if (starts_with(str, lbrackStr) && ends_with(str, rbrackStr)) {
     return str.substr(lbrackStr.length(), str.size()-lbrackStr.length()-rbrackStr.length());
   }
   // not an xml token -> do nothing
@@ -371,7 +373,7 @@ bool ProcessAndStripXMLTags(string &line, vector<XmlOption*> &res, ReorderingCon
           vector<float> ffWeights;
           vector<string> toks = Tokenize(ParseXmlTagAttribute(tagContent,"weights"));
           BOOST_FOREACH(string const& tok, toks) {
-            if (tok.substr(tok.size() - 1, 1) == "=") {
+            if (ends_with(tok, "=")) {
               // start new feature
               if (ffName != "") {
                 // set previous feature weights
diff --git a/phrase-extract/OutputFileStream.cpp b/phrase-extract/OutputFileStream.cpp
index a61ce1a..15c2bd7 100644
--- a/phrase-extract/OutputFileStream.cpp
+++ b/phrase-extract/OutputFileStream.cpp
@@ -19,11 +19,13 @@
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  ***********************************************************************/
 
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/iostreams/filter/gzip.hpp>
 #include "OutputFileStream.h"
 #include "gzfilebuf.h"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -51,7 +53,7 @@ bool OutputFileStream::Open(const std::string &filePath)
     return false;
   }
 
-  if (filePath.size() > 3 && filePath.substr(filePath.size() - 3, 3) == ".gz") {
+  if (ends_with(filePath, ".gz")) {
     this->push(boost::iostreams::gzip_compressor());
   }
   this->push(*m_outFile);
diff --git a/phrase-extract/ScoreFeature.cpp b/phrase-extract/ScoreFeature.cpp
index c037ab5..0795ed7 100644
--- a/phrase-extract/ScoreFeature.cpp
+++ b/phrase-extract/ScoreFeature.cpp
@@ -17,11 +17,13 @@
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  ***********************************************************************/
 
+#include <boost/algorithm/string/predicate.hpp>
 #include "ScoreFeature.h"
 #include "DomainFeature.h"
 #include "InternalStructFeature.h"
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace MosesTraining
 {
@@ -41,7 +43,7 @@ void ScoreFeatureManager::configure(const std::vector<std::string> args)
   for (size_t i = 0; i < args.size(); ++i) {
     if (args[i] == "--IgnoreSentenceId") {
       m_includeSentenceId = true;
-    } else if (args[i].substr(0,8) == "--Domain") {
+    } else if (starts_with(args[i], "--Domain")) {
       string type = args[i].substr(8);
       ++i;
       UTIL_THROW_IF(i == args.size(), ScoreFeatureArgumentException, "Missing domain file");
@@ -59,7 +61,7 @@ void ScoreFeatureManager::configure(const std::vector<std::string> args)
       }
       domainAdded = true;
       m_includeSentenceId = true;
-    } else if (args[i].substr(0,14) == "--SparseDomain") {
+    } else if (starts_with(args[i], "--SparseDomain")) {
       string type = args[i].substr(14);
       ++i;
       UTIL_THROW_IF(i == args.size(), ScoreFeatureArgumentException, "Missing domain file");
diff --git a/phrase-extract/extract-mixed-syntax/InputFileStream.cpp b/phrase-extract/extract-mixed-syntax/InputFileStream.cpp
index d111903..ef77414 100644
--- a/phrase-extract/extract-mixed-syntax/InputFileStream.cpp
+++ b/phrase-extract/extract-mixed-syntax/InputFileStream.cpp
@@ -22,8 +22,10 @@
 #include "InputFileStream.h"
 #include "gzfilebuf.h"
 #include <iostream>
+#include <boost/algorithm/string/predicate.hpp>
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -31,8 +33,7 @@ InputFileStream::InputFileStream(const std::string &filePath)
   : std::istream(NULL)
   , m_streambuf(NULL)
 {
-  if (filePath.size() > 3 &&
-      filePath.substr(filePath.size() - 3, 3) == ".gz") {
+  if (ends_with(filePath, ".gz")) {
     m_streambuf = new gzfilebuf(filePath.c_str());
   } else {
     std::filebuf* fb = new std::filebuf();
diff --git a/phrase-extract/lexical-reordering/InputFileStream.cpp b/phrase-extract/lexical-reordering/InputFileStream.cpp
index 013781c..89667a6 100755
--- a/phrase-extract/lexical-reordering/InputFileStream.cpp
+++ b/phrase-extract/lexical-reordering/InputFileStream.cpp
@@ -22,8 +22,10 @@
 #include "InputFileStream.h"
 #include "gzfilebuf.h"
 #include <iostream>
+#include <boost/algorithm/string/predicate.hpp>
 
 using namespace std;
+using namespace boost::algorithm;
 
 namespace Moses
 {
@@ -41,8 +43,7 @@ InputFileStream::~InputFileStream()
 
 void InputFileStream::Open(const std::string &filePath)
 {
-  if (filePath.size() > 3 &&
-      filePath.substr(filePath.size() - 3, 3) == ".gz") {
+  if (ends_with(filePath, ".gz")) {
     m_streambuf = new gzfilebuf(filePath.c_str());
   } else {
     std::filebuf* fb = new std::filebuf();
diff --git a/phrase-extract/score-main.cpp b/phrase-extract/score-main.cpp
index bd1b54b..d652b2b 100644
--- a/phrase-extract/score-main.cpp
+++ b/phrase-extract/score-main.cpp
@@ -28,6 +28,7 @@
 #include <set>
 #include <vector>
 #include <algorithm>
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/unordered_map.hpp>
 
 #include "ScoreFeature.h"
@@ -38,6 +39,7 @@
 #include "OutputFileStream.h"
 
 using namespace std;
+using namespace boost::algorithm;
 using namespace MosesTraining;
 
 namespace MosesTraining
@@ -904,10 +906,10 @@ void loadOrientationPriors(const std::string &fileNamePhraseOrientationPriors,
 
     bool l2rFlag = false;
     bool r2lFlag = false;
-    if (!key.substr(0,4).compare("L2R_")) {
+    if (starts_with(key, "L2R_")) {
       l2rFlag = true;
     }
-    if (!key.substr(0,4).compare("R2L_")) {
+    if (starts_with(key, "R2L_")) {
       r2lFlag = true;
     }
     if (!l2rFlag && !r2lFlag) {
diff --git a/vw/ClassifierFactory.cpp b/vw/ClassifierFactory.cpp
index 286bf84..4d8ee4e 100644
--- a/vw/ClassifierFactory.cpp
+++ b/vw/ClassifierFactory.cpp
@@ -2,6 +2,9 @@
 #include "vw.h"
 #include "../moses/Util.h"
 #include <iostream>
+#include <boost/algorithm/string/predicate.hpp>
+
+using namespace boost::algorithm;
 
 namespace Discriminative
 {
@@ -15,7 +18,7 @@ ClassifierFactory::ClassifierFactory(const std::string &modelFile, const std::st
 ClassifierFactory::ClassifierFactory(const std::string &modelFilePrefix)
   : m_lastId(0), m_train(true)
 {
-  if (modelFilePrefix.size() > 3 && modelFilePrefix.substr(modelFilePrefix.size() - 3, 3) == ".gz") {
+  if (ends_with(modelFilePrefix, ".gz")) {
     m_modelFilePrefix = modelFilePrefix.substr(0, modelFilePrefix.size() - 3);
     m_gzip = true;
   } else {
diff --git a/vw/VWTrainer.cpp b/vw/VWTrainer.cpp
index dff58a1..e513de3 100644
--- a/vw/VWTrainer.cpp
+++ b/vw/VWTrainer.cpp
@@ -1,8 +1,10 @@
 #include "Util.h"
 #include "Classifier.h"
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/iostreams/device/file.hpp>
 
 using namespace std;
+using namespace boost::algorithm;
 using namespace Moses;
 
 namespace Discriminative
@@ -10,7 +12,7 @@ namespace Discriminative
 
 VWTrainer::VWTrainer(const std::string &outputFile)
 {
-  if (outputFile.size() > 3 && outputFile.substr(outputFile.size() - 3, 3) == ".gz") {
+  if (ends_with(outputFile, ".gz")) {
     m_bfos.push(boost::iostreams::gzip_compressor());
   }
   m_bfos.push(boost::iostreams::file_sink(outputFile));
_______________________________________________
Moses-support mailing list
[email protected]
http://mailman.mit.edu/mailman/listinfo/moses-support

Reply via email to