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

This commit is contained in:
Branimir Karadžić
2017-01-19 11:30:48 -08:00
parent b31f3507f2
commit 4cb7362e99
4 changed files with 86 additions and 39 deletions

View File

@@ -116,29 +116,29 @@ namespace bx
bool toBool(const char* _str);
/// 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.
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);
/// Copy _num characters from string _src to _dst buffer of maximum _dstSize capacity
/// 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.
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.
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.
const char* strnl(const char* _str);

View File

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

View File

@@ -52,12 +52,12 @@ namespace bx
char toLower(char _ch)
{
return _ch - (isUpper(_ch) ? 0x20 : 0);
return _ch + (isUpper(_ch) ? 0x20 : 0);
}
char toUpper(char _ch)
{
return _ch + (isLower(_ch) ? 0x20 : 0);
return _ch - (isLower(_ch) ? 0x20 : 0);
}
bool toBool(const char* _str)
@@ -73,14 +73,14 @@ namespace bx
; ++_lhs, ++_rhs, --_max
)
{
if (*_lhs != '\0'
|| *_rhs != '\0')
if (*_lhs == '\0'
|| *_rhs == '\0')
{
break;
}
}
return *_lhs - *_rhs;
return 0 == _max ? 0 : *_lhs - *_rhs;
}
int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max)
@@ -90,14 +90,14 @@ namespace bx
; ++_lhs, ++_rhs, --_max
)
{
if (*_lhs != '\0'
|| *_rhs != '\0')
if (*_lhs == '\0'
|| *_rhs == '\0')
{
break;
}
}
return *_lhs - *_rhs;
return 0 == _max ? 0 : *_lhs - *_rhs;
}
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)
{
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;
}
}
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)

View File

@@ -10,6 +10,19 @@
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", "")
{
const char* test = "test";
@@ -45,6 +58,7 @@ TEST_CASE("strincmp", "")
REQUIRE(0 == bx::strincmp("test", "test") );
REQUIRE(0 == bx::strincmp("test", "testestes", 4) );
REQUIRE(0 == bx::strincmp("testestes", "test", 4) );
REQUIRE(0 != bx::strincmp("preprocess", "platform") );
}
TEST_CASE("strnchr", "")
@@ -63,6 +77,31 @@ TEST_CASE("strnrchr", "")
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", "")
{
bx::StringView sv("test");