Browse Source

Added more unit tests and fixed bugs with CRT replacement functions.

Branimir Karadžić 9 years ago
parent
commit
4cb7362e99
4 changed files with 86 additions and 39 deletions
  1. 7 7
      include/bx/string.h
  2. 7 9
      src/commandline.cpp
  3. 33 23
      src/string.cpp
  4. 39 0
      tests/string_test.cpp

+ 7 - 7
include/bx/string.h

@@ -116,29 +116,29 @@ namespace bx
 	bool toBool(const char* _str);
 	bool toBool(const char* _str);
 
 
 	/// String compare.
 	/// String compare.
-	int32_t strncmp(const char* _lhs, const char* _rhs, size_t _max = -1);
+	int32_t strncmp(const char* _lhs, const char* _rhs, size_t _max = INT32_MAX);
 
 
 	/// Case insensitive string compare.
 	/// Case insensitive string compare.
-	int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max = -1);
+	int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max = INT32_MAX);
 
 
 	///
 	///
 	size_t strnlen(const char* _str, size_t _max = -1);
 	size_t strnlen(const char* _str, size_t _max = -1);
 
 
 	/// Copy _num characters from string _src to _dst buffer of maximum _dstSize capacity
 	/// Copy _num characters from string _src to _dst buffer of maximum _dstSize capacity
 	/// including zero terminator. Copy will be terminated with '\0'.
 	/// including zero terminator. Copy will be terminated with '\0'.
-	size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num = -1);
+	size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num = INT32_MAX);
 
 
 	///
 	///
-	const char* strnchr(const char* _str, char _ch, size_t _max = -1);
+	const char* strnchr(const char* _str, char _ch, size_t _max = INT32_MAX);
 
 
 	///
 	///
-	const char* strnrchr(const char* _str, char _ch, size_t _max = -1);
+	const char* strnrchr(const char* _str, char _ch, size_t _max = INT32_MAX);
 
 
 	/// Find substring in string. Limit search to _size.
 	/// Find substring in string. Limit search to _size.
-	const char* strnstr(const char* _str, const char* _find, size_t _max = -1);
+	const char* strnstr(const char* _str, const char* _find, size_t _max = INT32_MAX);
 
 
 	/// Find substring in string. Case insensitive. Limit search to _max.
 	/// Find substring in string. Case insensitive. Limit search to _max.
-	const char* stristr(const char* _str, const char* _find, size_t _max = -1);
+	const char* stristr(const char* _str, const char* _find, size_t _max = INT32_MAX);
 
 
 	/// Find new line. Returns pointer after new line terminator.
 	/// Find new line. Returns pointer after new line terminator.
 	const char* strnl(const char* _str);
 	const char* strnl(const char* _str);

+ 7 - 9
src/commandline.cpp

@@ -5,8 +5,6 @@
 
 
 #include <bx/commandline.h>
 #include <bx/commandline.h>
 
 
-#include <ctype.h>
-
 namespace bx
 namespace bx
 {
 {
 	// Reference:
 	// Reference:
@@ -37,7 +35,7 @@ namespace bx
 			switch (state)
 			switch (state)
 			{
 			{
 				case SkipWhitespace:
 				case SkipWhitespace:
-					for (; isspace(*curr); ++curr) {}; // skip whitespace
+					for (; isSpace(*curr); ++curr) {}; // skip whitespace
 					state = SetTerm;
 					state = SetTerm;
 					break;
 					break;
 
 
@@ -68,7 +66,7 @@ namespace bx
 					{
 					{
 						sub = !sub;
 						sub = !sub;
 					}
 					}
-					else if (isspace(*curr) && !sub)
+					else if (isSpace(*curr) && !sub)
 					{
 					{
 						state = End;
 						state = End;
 					}
 					}
@@ -271,7 +269,7 @@ namespace bx
 				++arg;
 				++arg;
 				if (_short == *arg)
 				if (_short == *arg)
 				{
 				{
-					if (1 == strlen(arg) )
+					if (1 == strnlen(arg) )
 					{
 					{
 						if (0 == _skip)
 						if (0 == _skip)
 						{
 						{
@@ -280,7 +278,7 @@ namespace bx
 								return "";
 								return "";
 							}
 							}
 							else if (ii+_numParams < m_argc
 							else if (ii+_numParams < m_argc
-									&& '-' != *m_argv[ii+1] )
+								 && '-' != *m_argv[ii+1] )
 							{
 							{
 								return m_argv[ii+1];
 								return m_argv[ii+1];
 							}
 							}
@@ -293,8 +291,8 @@ namespace bx
 					}
 					}
 				}
 				}
 				else if (NULL != _long
 				else if (NULL != _long
-						&&  '-' == *arg
-						&&  0 == strincmp(arg+1, _long) )
+					 &&  '-'  == *arg
+					 &&  0 == strincmp(arg+1, _long) )
 				{
 				{
 					if (0 == _skip)
 					if (0 == _skip)
 					{
 					{
@@ -303,7 +301,7 @@ namespace bx
 							return "";
 							return "";
 						}
 						}
 						else if (ii+_numParams < m_argc
 						else if (ii+_numParams < m_argc
-								&&  '-' != *m_argv[ii+1] )
+							 &&  '-' != *m_argv[ii+1] )
 						{
 						{
 							return m_argv[ii+1];
 							return m_argv[ii+1];
 						}
 						}

+ 33 - 23
src/string.cpp

@@ -52,12 +52,12 @@ namespace bx
 
 
 	char toLower(char _ch)
 	char toLower(char _ch)
 	{
 	{
-		return _ch - (isUpper(_ch) ? 0x20 : 0);
+		return _ch + (isUpper(_ch) ? 0x20 : 0);
 	}
 	}
 
 
 	char toUpper(char _ch)
 	char toUpper(char _ch)
 	{
 	{
-		return _ch + (isLower(_ch) ? 0x20 : 0);
+		return _ch - (isLower(_ch) ? 0x20 : 0);
 	}
 	}
 
 
 	bool toBool(const char* _str)
 	bool toBool(const char* _str)
@@ -73,14 +73,14 @@ namespace bx
 			; ++_lhs, ++_rhs, --_max
 			; ++_lhs, ++_rhs, --_max
 			)
 			)
 		{
 		{
-			if (*_lhs != '\0'
-			||  *_rhs != '\0')
+			if (*_lhs == '\0'
+			||  *_rhs == '\0')
 			{
 			{
 				break;
 				break;
 			}
 			}
 		}
 		}
 
 
-		return *_lhs - *_rhs;
+		return 0 == _max ? 0 : *_lhs - *_rhs;
 	}
 	}
 
 
 	int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max)
 	int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max)
@@ -90,14 +90,14 @@ namespace bx
 			; ++_lhs, ++_rhs, --_max
 			; ++_lhs, ++_rhs, --_max
 			)
 			)
 		{
 		{
-			if (*_lhs != '\0'
-			||  *_rhs != '\0')
+			if (*_lhs == '\0'
+			||  *_rhs == '\0')
 			{
 			{
 				break;
 				break;
 			}
 			}
 		}
 		}
 
 
-		return *_lhs - *_rhs;
+		return 0 == _max ? 0 : *_lhs - *_rhs;
 	}
 	}
 
 
 	size_t strnlen(const char* _str, size_t _max)
 	size_t strnlen(const char* _str, size_t _max)
@@ -150,32 +150,42 @@ namespace bx
 
 
 	const char* strnstr(const char* _str, const char* _find, size_t _max)
 	const char* strnstr(const char* _str, const char* _find, size_t _max)
 	{
 	{
-		char first = *_find;
-		if ('\0' == first)
-		{
-			return _str;
-		}
+		const char* ptr = _str;
 
 
-		const char* cmp = _find + 1;
-		size_t len = strnlen(cmp);
-		do
+		size_t       stringLen = strnlen(_str, _max);
+		const size_t findLen   = strnlen(_find);
+
+		for (; stringLen >= findLen; ++ptr, --stringLen)
 		{
 		{
-			for (char match = *_str++; match != first && 0 < _max; match = *_str++, --_max)
+			// Find start of the string.
+			while (*ptr != *_find)
 			{
 			{
-				if ('\0' == match)
+				++ptr;
+				--stringLen;
+
+				// Search pattern lenght can't be longer than the string.
+				if (findLen > stringLen)
 				{
 				{
 					return NULL;
 					return NULL;
 				}
 				}
 			}
 			}
 
 
-			if (0 == _max)
+			// Set pointers.
+			const char* string = ptr;
+			const char* search = _find;
+
+			// Start comparing.
+			while (*string++ == *search++)
 			{
 			{
-				return NULL;
+				// If end of the 'search' string is reached, all characters match.
+				if ('\0' == *search)
+				{
+					return ptr;
+				}
 			}
 			}
+		}
 
 
-		} while (0 != strncmp(_str, cmp, len) );
-
-		return --_str;
+		return NULL;
 	}
 	}
 
 
 	const char* stristr(const char* _str, const char* _find, size_t _max)
 	const char* stristr(const char* _str, const char* _find, size_t _max)

+ 39 - 0
tests/string_test.cpp

@@ -10,6 +10,19 @@
 
 
 bx::AllocatorI* g_allocator;
 bx::AllocatorI* g_allocator;
 
 
+TEST_CASE("chars", "")
+{
+	for (char ch = 'A'; ch <= 'Z'; ++ch)
+	{
+		REQUIRE(!bx::isLower(ch) );
+		REQUIRE(!bx::isNumeric(ch) );
+		REQUIRE(bx::isUpper(ch) );
+		REQUIRE(bx::isAlpha(ch) );
+		REQUIRE(bx::isAlphaNum(ch) );
+		REQUIRE(bx::isLower(bx::toLower(ch) ) );
+	}
+}
+
 TEST_CASE("strnlen", "")
 TEST_CASE("strnlen", "")
 {
 {
 	const char* test = "test";
 	const char* test = "test";
@@ -45,6 +58,7 @@ TEST_CASE("strincmp", "")
 	REQUIRE(0 == bx::strincmp("test", "test") );
 	REQUIRE(0 == bx::strincmp("test", "test") );
 	REQUIRE(0 == bx::strincmp("test", "testestes", 4) );
 	REQUIRE(0 == bx::strincmp("test", "testestes", 4) );
 	REQUIRE(0 == bx::strincmp("testestes", "test", 4) );
 	REQUIRE(0 == bx::strincmp("testestes", "test", 4) );
+	REQUIRE(0 != bx::strincmp("preprocess", "platform") );
 }
 }
 
 
 TEST_CASE("strnchr", "")
 TEST_CASE("strnchr", "")
@@ -63,6 +77,31 @@ TEST_CASE("strnrchr", "")
 	REQUIRE(&test[2] == bx::strnrchr(test, 's') );
 	REQUIRE(&test[2] == bx::strnrchr(test, 's') );
 }
 }
 
 
+TEST_CASE("stristr", "")
+{
+	const char* test = "The Quick Brown Fox Jumps Over The Lazy Dog.";
+
+	REQUIRE(NULL == bx::stristr(test, "quick", 8) );
+	REQUIRE(NULL == bx::stristr(test, "quick1") );
+	REQUIRE(&test[4] == bx::stristr(test, "quick", 9) );
+	REQUIRE(&test[4] == bx::stristr(test, "quick") );
+}
+
+TEST_CASE("strnstr", "")
+{
+	const char* test = "The Quick Brown Fox Jumps Over The Lazy Dog.";
+
+	REQUIRE(NULL == bx::strnstr(test, "quick", 8) );
+	REQUIRE(NULL == bx::strnstr(test, "quick1") );
+	REQUIRE(NULL == bx::strnstr(test, "quick", 9) );
+	REQUIRE(NULL == bx::strnstr(test, "quick") );
+
+	REQUIRE(NULL == bx::strnstr(test, "Quick", 8) );
+	REQUIRE(NULL == bx::strnstr(test, "Quick1") );
+	REQUIRE(&test[4] == bx::strnstr(test, "Quick", 9) );
+	REQUIRE(&test[4] == bx::strnstr(test, "Quick") );
+}
+
 TEST_CASE("StringView", "")
 TEST_CASE("StringView", "")
 {
 {
 	bx::StringView sv("test");
 	bx::StringView sv("test");