Add beginsWith/endsWith to deStringUtil.hpp.

Change-Id: Id538b11e6cd8b717f814166a6497c500e12a675b
diff --git a/framework/delibs/decpp/deStringUtil.cpp b/framework/delibs/decpp/deStringUtil.cpp
index c5e0166..14fccaa 100644
--- a/framework/delibs/decpp/deStringUtil.cpp
+++ b/framework/delibs/decpp/deStringUtil.cpp
@@ -22,6 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "deStringUtil.hpp"
+#include "deString.h"
 
 #include <algorithm>
 #include <iterator>
@@ -113,6 +114,22 @@
 	return s.str();
 }
 
+bool beginsWith (const std::string& s, const std::string& prefix)
+{
+	return deStringBeginsWith(s.c_str(), prefix.c_str());
+}
+
+bool endsWith (const std::string& s, const std::string& suffix)
+{
+	if (suffix.length() > s.length())
+		return false;
+	else
+	{
+		const std::string::size_type offset = s.length() - suffix.length();
+		return s.find(suffix, offset) == offset;
+	}
+}
+
 char toUpper (char c)
 {
 	return std::toupper(c, std::locale::classic());
@@ -156,6 +173,25 @@
 
 	DE_TEST_ASSERT(floatToString(4, 1) == "4.0");
 
+	DE_TEST_ASSERT(beginsWith("foobar", "foobar"));
+	DE_TEST_ASSERT(beginsWith("foobar", "foo"));
+	DE_TEST_ASSERT(beginsWith("foobar", "f"));
+	DE_TEST_ASSERT(beginsWith("foobar", ""));
+	DE_TEST_ASSERT(beginsWith("", ""));
+	DE_TEST_ASSERT(!beginsWith("foobar", "bar"));
+	DE_TEST_ASSERT(!beginsWith("foobar", "foobarbaz"));
+	DE_TEST_ASSERT(!beginsWith("", "foo"));
+
+	DE_TEST_ASSERT(endsWith("foobar", "foobar"));
+	DE_TEST_ASSERT(endsWith("foobar", "bar"));
+	DE_TEST_ASSERT(endsWith("foobar", "r"));
+	DE_TEST_ASSERT(endsWith("foobar", ""));
+	DE_TEST_ASSERT(endsWith("", ""));
+	DE_TEST_ASSERT(!endsWith("foobar", "foo"));
+	DE_TEST_ASSERT(!endsWith("foobar", "bazfoobar"));
+	DE_TEST_ASSERT(!endsWith("foobar", "foobarbaz"));
+	DE_TEST_ASSERT(!endsWith("", "foo"));
+
 	DE_TEST_ASSERT(toUpper('a') == 'A');
 	DE_TEST_ASSERT(toUpper('A') == 'A');
 	DE_TEST_ASSERT(toLower('a') == 'a');
diff --git a/framework/delibs/decpp/deStringUtil.hpp b/framework/delibs/decpp/deStringUtil.hpp
index 68614d8..343619c 100644
--- a/framework/delibs/decpp/deStringUtil.hpp
+++ b/framework/delibs/decpp/deStringUtil.hpp
@@ -47,6 +47,8 @@
 std::string					capitalize		(const std::string& s);
 std::vector<std::string>	splitString		(const std::string& s, char delim='\0');
 std::string					floatToString	(float val, int precision);
+bool						beginsWith		(const std::string& s, const std::string& prefix);
+bool						endsWith		(const std::string& s, const std::string& suffix);
 char						toUpper			(char c);
 char						toLower			(char c);
 bool						isUpper			(char c);
diff --git a/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp b/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp
index 88ae724..6d8f737 100644
--- a/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp
@@ -26,6 +26,7 @@
 #include "gluVarType.hpp"
 #include "gluShaderProgram.hpp"
 #include "deSTLUtil.hpp"
+#include "deStringUtil.hpp"
 #include "glwEnums.hpp"
 
 #include <set>
@@ -634,7 +635,7 @@
 	for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx)
 	{
 		// user-defined
-		if (m_xfbVaryings[ndx].find("gl_") != 0)
+		if (!de::beginsWith(m_xfbVaryings[ndx], "gl_"))
 		{
 			std::vector<ProgramInterfaceDefinition::VariablePathComponent> path;
 			if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx], VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(this), glu::STORAGE_OUT)))
diff --git a/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp b/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
index 15c6431..778ef6f 100644
--- a/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
@@ -46,14 +46,6 @@
 using ProgramInterfaceDefinition::VariablePathComponent;
 using ProgramInterfaceDefinition::VariableSearchFilter;
 
-static bool stringEndsWith (const std::string& str, const std::string& suffix)
-{
-	if (suffix.length() > str.length())
-		return false;
-	else
-		return str.substr(str.length() - suffix.length()) == suffix;
-}
-
 static glw::GLenum getProgramDefaultBlockInterfaceFromStorage (glu::Storage storage)
 {
 	switch (storage)
@@ -1966,7 +1958,7 @@
 
 			if (recoveryStrategies[strategyNdx].removeTrailingArray)
 			{
-				if (stringEndsWith(resourceName, "[0]"))
+				if (de::endsWith(resourceName, "[0]"))
 					simplifiedResourceName = resourceName.substr(0, resourceName.length() - 3);
 				else
 					continue;
diff --git a/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp b/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
index 0bc1efc..bfc85d9 100644
--- a/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
@@ -52,14 +52,6 @@
 namespace
 {
 
-static bool stringEndsWith (const std::string& str, const std::string& suffix)
-{
-	if (suffix.length() > str.length())
-		return false;
-	else
-		return str.substr(str.length() - suffix.length()) == suffix;
-}
-
 static int getTypeSize (glu::DataType type)
 {
 	if (type == glu::TYPE_FLOAT)
@@ -1106,7 +1098,7 @@
 	{
 		for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx)
 		{
-			if (stringEndsWith(referenceResources[ndx], "[0]"))
+			if (de::endsWith(referenceResources[ndx], "[0]"))
 			{
 				const std::string	queryString	= referenceResources[ndx].substr(0, referenceResources[ndx].length()-3);
 				const glw::GLuint	index		= gl.getProgramResourceIndex(program, programInterface, queryString.c_str());
@@ -1233,7 +1225,7 @@
 				if (arrayedInterface && isImplicitlySizedArray)
 				{
 					// omit implicit arrayness from name, i.e. remove trailing "_array"
-					DE_ASSERT(stringEndsWith(buf, "_array"));
+					DE_ASSERT(de::endsWith(buf, "_array"));
 					buf = buf.substr(0, buf.length() - 6);
 				}