Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Core/GameEngine/Include/Common/UnicodeString.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,30 @@ class UnicodeString
*/
int compareNoCase(const WideChar* s) const;

/**
return true iff self starts with the given string.
*/
Bool startsWith(const WideChar* p) const;
inline Bool startsWith(const UnicodeString& stringSrc) const { return startsWith(stringSrc.str()); }

/**
return true iff self starts with the given string. (case insensitive)
*/
Bool startsWithNoCase(const WideChar* p) const;
inline Bool startsWithNoCase(const UnicodeString& stringSrc) const { return startsWithNoCase(stringSrc.str()); }

/**
return true iff self ends with the given string.
*/
Bool endsWith(const WideChar* p) const;
Bool endsWith(const UnicodeString& stringSrc) const { return endsWith(stringSrc.str()); }

/**
return true iff self ends with the given string. (case insensitive)
*/
Bool endsWithNoCase(const WideChar* p) const;
Bool endsWithNoCase(const UnicodeString& stringSrc) const { return endsWithNoCase(stringSrc.str()); }

/**
conceptually similar to strtok():

Expand Down
40 changes: 4 additions & 36 deletions Core/GameEngine/Source/Common/System/AsciiString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,57 +477,25 @@ void AsciiString::format_va(const char* format, va_list args)
// -----------------------------------------------------
Bool AsciiString::startsWith(const char* p) const
{
if (*p == 0)
return true; // everything starts with the empty string

int lenThis = getLength();
int lenThat = strlen(p);
if (lenThis < lenThat)
return false; // that must be smaller than this

return strncmp(peek(), p, lenThat) == 0;
return ::startsWith(peek(), p);
}

// -----------------------------------------------------
Bool AsciiString::startsWithNoCase(const char* p) const
{
if (*p == 0)
return true; // everything starts with the empty string

int lenThis = getLength();
int lenThat = strlen(p);
if (lenThis < lenThat)
return false; // that must be smaller than this

return strnicmp(peek(), p, lenThat) == 0;
return ::startsWithNoCase(peek(), p);
}

// -----------------------------------------------------
Bool AsciiString::endsWith(const char* p) const
{
if (*p == 0)
return true; // everything ends with the empty string

int lenThis = getLength();
int lenThat = strlen(p);
if (lenThis < lenThat)
return false; // that must be smaller than this

return strncmp(peek() + lenThis - lenThat, p, lenThat) == 0;
return ::endsWith(peek(), p);
}

// -----------------------------------------------------
Bool AsciiString::endsWithNoCase(const char* p) const
{
if (*p == 0)
return true; // everything ends with the empty string

int lenThis = getLength();
int lenThat = strlen(p);
if (lenThis < lenThat)
return false; // that must be smaller than this

return strnicmp(peek() + lenThis - lenThat, p, lenThat) == 0;
return ::endsWithNoCase(peek(), p);
}

//-----------------------------------------------------------------------------
Expand Down
24 changes: 24 additions & 0 deletions Core/GameEngine/Source/Common/System/UnicodeString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,30 @@ void UnicodeString::format_va(const WideChar* format, va_list args)
}
}

// -----------------------------------------------------
Bool UnicodeString::startsWith(const WideChar* p) const
{
return ::startsWith(peek(), p);
}

// -----------------------------------------------------
Bool UnicodeString::startsWithNoCase(const WideChar* p) const
{
return ::startsWithNoCase(peek(), p);
}

// -----------------------------------------------------
Bool UnicodeString::endsWith(const WideChar* p) const
{
return ::endsWith(peek(), p);
}

// -----------------------------------------------------
Bool UnicodeString::endsWithNoCase(const WideChar* p) const
{
return ::endsWithNoCase(peek(), p);
}

//-----------------------------------------------------------------------------
Bool UnicodeString::nextToken(UnicodeString* tok, UnicodeString delimiters)
{
Expand Down
118 changes: 118 additions & 0 deletions Core/Libraries/Source/WWVegas/WWLib/stringex.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "bittype.h"
#include <string.h>
#include <ctype.h>


// Declaration
Expand Down Expand Up @@ -55,6 +56,14 @@ template<size_t Size> size_t strlmove_t(char (&dst)[Size], const char *src);
template<size_t Size> size_t strlmcat_t(char (&dst)[Size], const char *src);
#endif

template<typename T> int strncmp_t(const T *str1, const T *str2, size_t maxcount);
template<typename T> int strnicmp_t(const T* str1, const T* str2, size_t maxcount);

template<typename T> bool startsWith(const T *str, const T *prefix);
template<typename T> bool startsWithNoCase(const T *str, const T *prefix);
template<typename T> bool endsWithNoCase(const T *str, const T *suffix);
template<typename T> bool endsWithNoCase(const T *str, const T *suffix);


// Implementation

Expand Down Expand Up @@ -182,3 +191,112 @@ template<size_t Size> size_t strlcat_t(char (&dst)[Size], const char *src) { ret
template<size_t Size> size_t strlmove_t(char (&dst)[Size], const char *src) { return strlmove_t(dst, src, Size); }
template<size_t Size> size_t strlmcat_t(char (&dst)[Size], const char *src) { return strlmcat_t(dst, src, Size); }
#endif

// Templated strncmp.
// Compares up to maxcount chars or a null byte is encountered, whichever comes first.
// Returns < 0 if str1 is less than str2, 0 is str1 and str2 are equal and > 0 if str2 is greater than str1.
template<typename T> int strncmp_t(const T *str1, const T *str2, const size_t maxcount)
{
for (size_t i = 0; i < maxcount; ++i)
{
const T c1 = str1[i];
const T c2 = str2[i];
const int diff = (int)c1 - (int)c2;
if (diff != 0)
{
return diff;
}
if (c1 == T(0)) // both c1 and c2 are null terminators
{
return 0;
}
}
return 0;
}

// Lower case conversion helpers
inline char tolower_t(char c)
{
// cast to unsigned char for correct behavior of tolower()
return (char)tolower((unsigned char)c);
}

inline wchar_t tolower_t(wchar_t c)
{
return (wchar_t)towlower(c);
}

// Templated strnicmp.
// Case insensitively compares up to maxcount chars or a null byte is encountered, whichever comes first.
// Returns < 0 if str1 is less than str2, 0 is str1 and str2 are equal and > 0 if str2 is greater than str1.
template<typename T> int strnicmp_t(const T *str1, const T *str2, const size_t maxcount)
{
for (size_t i = 0; i < maxcount; ++i)
{
const T c1 = tolower_t(str1[i]);
const T c2 = tolower_t(str2[i]);
const int diff = (int)c1 - (int)c2;
if (diff != 0)
{
return diff;
}
if (c1 == T(0)) // both c1 and c2 are null terminators
{
return 0;
}
}
return 0;
}

template<typename T> inline bool startsWith(const T *str, const T *prefix)
{
if (*prefix == T(0))
return true; // everything starts with the empty string

const size_t strlen = strlen_t(str);
const size_t prefixlen = strlen_t(prefix);
if (strlen < prefixlen)
return false; // prefix must be as long or shorter than str

return strncmp_t(str, prefix, prefixlen) == 0;
}

template<typename T> inline bool startsWithNoCase(const T *str, const T *prefix)
{
if (*prefix == T(0))
return true; // everything starts with the empty string

const size_t strlen = strlen_t(str);
const size_t prefixlen = strlen_t(prefix);
if (strlen < prefixlen)
return false; // prefix must be as long or shorter than str

return strnicmp_t(str, prefix, prefixlen) == 0;
}

template<typename T> inline bool endsWith(const T *str, const T *suffix)
{
if (*suffix == T(0))
return true; // everything ends with the empty string

const size_t strlen = strlen_t(str);
const size_t suffixlen = strlen_t(suffix);
if (strlen < suffixlen)
return false; // suffix must be as long or shorter than str

return strncmp_t(str + strlen - suffixlen, suffix, suffixlen) == 0;
}

template<typename T> inline bool endsWithNoCase(const T *str, const T *suffix)
{
if (*suffix == T(0))
return true; // everything ends with the empty string

const size_t strlen = strlen_t(str);
const size_t suffixlen = strlen_t(suffix);
if (strlen < suffixlen)
return false; // suffix must be as long or shorter than str

return strnicmp_t(str + strlen - suffixlen, suffix, suffixlen) == 0;
}

Loading