diff options
Diffstat (limited to '3rdparty/bx/src/string.cpp')
-rw-r--r-- | 3rdparty/bx/src/string.cpp | 407 |
1 files changed, 319 insertions, 88 deletions
diff --git a/3rdparty/bx/src/string.cpp b/3rdparty/bx/src/string.cpp index dbb59e5090a..5fe272548d0 100644 --- a/3rdparty/bx/src/string.cpp +++ b/3rdparty/bx/src/string.cpp @@ -3,6 +3,7 @@ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ +#include "bx_p.h" #include <bx/allocator.h> #include <bx/hash.h> #include <bx/readerwriter.h> @@ -10,10 +11,16 @@ #if !BX_CRT_NONE # include <stdio.h> // vsnprintf, vsnwprintf +# include <wchar.h> // vswprintf #endif // !BX_CRT_NONE namespace bx { + inline bool isInRange(char _ch, char _from, char _to) + { + return unsigned(_ch - _from) <= unsigned(_to-_from); + } + bool isSpace(char _ch) { return ' ' == _ch @@ -27,12 +34,12 @@ namespace bx bool isUpper(char _ch) { - return _ch >= 'A' && _ch <= 'Z'; + return isInRange(_ch, 'A', 'Z'); } bool isLower(char _ch) { - return _ch >= 'a' && _ch <= 'z'; + return isInRange(_ch, 'a', 'z'); } bool isAlpha(char _ch) @@ -42,7 +49,7 @@ namespace bx bool isNumeric(char _ch) { - return _ch >= '0' && _ch <= '9'; + return isInRange(_ch, '0', '9'); } bool isAlphaNum(char _ch) @@ -52,7 +59,60 @@ namespace bx bool isPrint(char _ch) { - return isAlphaNum(_ch) || isSpace(_ch); + return isInRange(_ch, ' ', '~'); + } + + typedef bool (*CharTestFn)(char _ch); + + template<CharTestFn fn> + inline bool isCharTest(const StringView& _str) + { + bool result = true; + + for (const char* ptr = _str.getPtr(), *term = _str.getTerm() + ; ptr != term && result + ; ++ptr + ) + { + result &= fn(*ptr); + } + + return result; + } + + bool isSpace(const StringView& _str) + { + return isCharTest<isSpace>(_str); + } + + bool isUpper(const StringView& _str) + { + return isCharTest<isUpper>(_str); + } + + bool isLower(const StringView& _str) + { + return isCharTest<isLower>(_str); + } + + bool isAlpha(const StringView& _str) + { + return isCharTest<isAlpha>(_str); + } + + bool isNumeric(const StringView& _str) + { + return isCharTest<isNumeric>(_str); + } + + bool isAlphaNum(const StringView& _str) + { + return isCharTest<isAlphaNum>(_str); + } + + bool isPrint(const StringView& _str) + { + return isCharTest<isPrint>(_str); } char toLower(char _ch) @@ -70,7 +130,7 @@ namespace bx void toLower(char* _inOutStr, int32_t _max) { - const int32_t len = strnlen(_inOutStr, _max); + const int32_t len = strLen(_inOutStr, _max); toLowerUnsafe(_inOutStr, len); } @@ -89,16 +149,10 @@ namespace bx void toUpper(char* _inOutStr, int32_t _max) { - const int32_t len = strnlen(_inOutStr, _max); + const int32_t len = strLen(_inOutStr, _max); toUpperUnsafe(_inOutStr, len); } - bool toBool(const char* _str) - { - char ch = toLower(_str[0]); - return ch == 't' || ch == '1'; - } - typedef char (*CharFn)(char _ch); inline char toNoop(char _ch) @@ -107,11 +161,13 @@ namespace bx } template<CharFn fn> - int32_t strCmp(const char* _lhs, const char* _rhs, int32_t _max) + inline int32_t strCmp(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax) { + int32_t max = min(_lhsMax, _rhsMax); + for ( - ; 0 < _max && fn(*_lhs) == fn(*_rhs) - ; ++_lhs, ++_rhs, --_max + ; 0 < max && fn(*_lhs) == fn(*_rhs) + ; ++_lhs, ++_rhs, --max ) { if (*_lhs == '\0' @@ -121,20 +177,105 @@ namespace bx } } - return 0 == _max ? 0 : fn(*_lhs) - fn(*_rhs); + return 0 == max && _lhsMax == _rhsMax ? 0 : fn(*_lhs) - fn(*_rhs); } - int32_t strncmp(const char* _lhs, const char* _rhs, int32_t _max) + int32_t strCmp(const StringView& _lhs, const StringView& _rhs, int32_t _max) { - return strCmp<toNoop>(_lhs, _rhs, _max); + return strCmp<toNoop>( + _lhs.getPtr() + , min(_lhs.getLength(), _max) + , _rhs.getPtr() + , min(_rhs.getLength(), _max) + ); } - int32_t strincmp(const char* _lhs, const char* _rhs, int32_t _max) + int32_t strCmpI(const StringView& _lhs, const StringView& _rhs, int32_t _max) { - return strCmp<toLower>(_lhs, _rhs, _max); + return strCmp<toLower>( + _lhs.getPtr() + , min(_lhs.getLength(), _max) + , _rhs.getPtr() + , min(_rhs.getLength(), _max) + ); } - int32_t strnlen(const char* _str, int32_t _max) + inline int32_t strCmpV(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax) + { + int32_t max = min(_lhsMax, _rhsMax); + int32_t ii = 0; + int32_t idx = 0; + bool zero = true; + + for ( + ; 0 < max && _lhs[ii] == _rhs[ii] + ; ++ii, --max + ) + { + const uint8_t ch = _lhs[ii]; + if ('\0' == ch + || '\0' == _rhs[ii]) + { + break; + } + + if (!isNumeric(ch) ) + { + idx = ii+1; + zero = true; + } + else if ('0' != ch) + { + zero = false; + } + } + + if (0 == max) + { + return _lhsMax == _rhsMax ? 0 : _lhs[ii] - _rhs[ii]; + } + + if ('0' != _lhs[idx] + && '0' != _rhs[idx]) + { + int32_t jj = 0; + for (jj = ii + ; 0 < max && isNumeric(_lhs[jj]) + ; ++jj, --max + ) + { + if (!isNumeric(_rhs[jj]) ) + { + return 1; + } + } + + if (isNumeric(_rhs[jj])) + { + return -1; + } + } + else if (zero + && idx < ii + && (isNumeric(_lhs[ii]) || isNumeric(_rhs[ii]) ) ) + { + return (_lhs[ii] - '0') - (_rhs[ii] - '0'); + } + + return 0 == max && _lhsMax == _rhsMax ? 0 : _lhs[ii] - _rhs[ii]; + } + + int32_t strCmpV(const StringView& _lhs, const StringView& _rhs, int32_t _max) + { + return strCmpV( + _lhs.getPtr() + , min(_lhs.getLength(), _max) + , _rhs.getPtr() + , min(_rhs.getLength(), _max) + ); + } + + int32_t strLen(const char* _str, int32_t _max) { if (NULL == _str) { @@ -146,13 +287,18 @@ namespace bx return int32_t(ptr - _str); } - int32_t strlncpy(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) + int32_t strLen(const StringView& _str, int32_t _max) + { + return strLen(_str.getPtr(), min(_str.getLength(), _max) ); + } + + inline int32_t strCopy(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) { BX_CHECK(NULL != _dst, "_dst can't be NULL!"); BX_CHECK(NULL != _src, "_src can't be NULL!"); BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); - const int32_t len = strnlen(_src, _num); + const int32_t len = strLen(_src, _num); const int32_t max = _dstSize-1; const int32_t num = (len < max ? len : max); memCopy(_dst, _src, num); @@ -161,20 +307,30 @@ namespace bx return num; } - int32_t strlncat(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) + int32_t strCopy(char* _dst, int32_t _dstSize, const StringView& _str, int32_t _num) + { + return strCopy(_dst, _dstSize, _str.getPtr(), min(_str.getLength(), _num) ); + } + + inline int32_t strCat(char* _dst, int32_t _dstSize, const char* _src, int32_t _num) { BX_CHECK(NULL != _dst, "_dst can't be NULL!"); BX_CHECK(NULL != _src, "_src can't be NULL!"); BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); const int32_t max = _dstSize; - const int32_t len = strnlen(_dst, max); - return strlncpy(&_dst[len], max-len, _src, _num); + const int32_t len = strLen(_dst, max); + return strCopy(&_dst[len], max-len, _src, _num); + } + + int32_t strCat(char* _dst, int32_t _dstSize, const StringView& _str, int32_t _num) + { + return strCat(_dst, _dstSize, _str.getPtr(), min(_str.getLength(), _num) ); } - const char* strnchr(const char* _str, char _ch, int32_t _max) + inline const char* strFindUnsafe(const char* _str, int32_t _len, char _ch) { - for (int32_t ii = 0, len = strnlen(_str, _max); ii < len; ++ii) + for (int32_t ii = 0; ii < _len; ++ii) { if (_str[ii] == _ch) { @@ -185,9 +341,19 @@ namespace bx return NULL; } - const char* strnrchr(const char* _str, char _ch, int32_t _max) + inline const char* strFind(const char* _str, int32_t _max, char _ch) { - for (int32_t ii = strnlen(_str, _max); 0 < ii; --ii) + return strFindUnsafe(_str, strLen(_str, _max), _ch); + } + + const char* strFind(const StringView& _str, char _ch) + { + return strFind(_str.getPtr(), _str.getLength(), _ch); + } + + inline const char* strRFindUnsafe(const char* _str, int32_t _len, char _ch) + { + for (int32_t ii = _len; 0 <= ii; --ii) { if (_str[ii] == _ch) { @@ -198,13 +364,23 @@ namespace bx return NULL; } + inline const char* strRFind(const char* _str, int32_t _max, char _ch) + { + return strRFindUnsafe(_str, strLen(_str, _max), _ch); + } + + const char* strRFind(const StringView& _str, char _ch) + { + return strRFind(_str.getPtr(), _str.getLength(), _ch); + } + template<CharFn fn> - static const char* strStr(const char* _str, int32_t _strMax, const char* _find, int32_t _findMax) + inline const char* strFind(const char* _str, int32_t _strMax, const char* _find, int32_t _findMax) { const char* ptr = _str; - int32_t stringLen = strnlen(_str, _strMax); - const int32_t findLen = strnlen(_find, _findMax); + int32_t stringLen = strLen(_str, _strMax); + const int32_t findLen = strLen(_find, _findMax); for (; stringLen >= findLen; ++ptr, --stringLen) { @@ -239,27 +415,81 @@ namespace bx return NULL; } - const char* strnstr(const char* _str, const char* _find, int32_t _max) + const char* strFind(const StringView& _str, const StringView& _find, int32_t _num) + { + return strFind<toNoop>( + _str.getPtr() + , _str.getLength() + , _find.getPtr() + , min(_find.getLength(), _num) + ); + } + + const char* strFindI(const StringView& _str, const StringView& _find, int32_t _num) + { + return strFind<toLower>( + _str.getPtr() + , _str.getLength() + , _find.getPtr() + , min(_find.getLength(), _num) + ); + } + + StringView strLTrim(const StringView& _str, const StringView& _chars) { - return strStr<toNoop>(_str, _max, _find, INT32_MAX); + const char* ptr = _str.getPtr(); + const char* chars = _chars.getPtr(); + const uint32_t charsLen = _chars.getLength(); + + for (uint32_t ii = 0, len = _str.getLength(); ii < len; ++ii) + { + if (NULL == strFindUnsafe(chars, charsLen, ptr[ii]) ) + { + return StringView(ptr + ii, len-ii); + } + } + + return StringView(); } - const char* stristr(const char* _str, const char* _find, int32_t _max) + StringView strRTrim(const StringView& _str, const StringView& _chars) { - return strStr<toLower>(_str, _max, _find, INT32_MAX); + if (_str.isEmpty() ) + { + return StringView(); + } + + const char* ptr = _str.getPtr(); + const char* chars = _chars.getPtr(); + const uint32_t charsLen = _chars.getLength(); + + for (int32_t len = _str.getLength(), ii = len-1; 0 <= ii; --ii) + { + if (NULL == strFindUnsafe(chars, charsLen, ptr[ii]) ) + { + return StringView(ptr, ii+1); + } + } + + return StringView(); + } + + StringView strTrim(const StringView& _str, const StringView& _chars) + { + return strLTrim(strRTrim(_str, _chars), _chars); } const char* strnl(const char* _str) { - for (; '\0' != *_str; _str += strnlen(_str, 1024) ) + for (; '\0' != *_str; _str += strLen(_str, 1024) ) { - const char* eol = strnstr(_str, "\r\n", 1024); + const char* eol = strFind(StringView(_str, 1024), "\r\n"); if (NULL != eol) { return eol + 2; } - eol = strnstr(_str, "\n", 1024); + eol = strFind(StringView(_str, 1024), "\n"); if (NULL != eol) { return eol + 1; @@ -271,15 +501,15 @@ namespace bx const char* streol(const char* _str) { - for (; '\0' != *_str; _str += strnlen(_str, 1024) ) + for (; '\0' != *_str; _str += strLen(_str, 1024) ) { - const char* eol = strnstr(_str, "\r\n", 1024); + const char* eol = strFind(StringView(_str, 1024), "\r\n"); if (NULL != eol) { return eol; } - eol = strnstr(_str, "\n", 1024); + eol = strFind(StringView(_str, 1024), "\n"); if (NULL != eol) { return eol; @@ -348,9 +578,9 @@ namespace bx const char* findIdentifierMatch(const char* _str, const char* _word) { - int32_t len = strnlen(_word); - const char* ptr = strnstr(_str, _word); - for (; NULL != ptr; ptr = strnstr(ptr + len, _word) ) + int32_t len = strLen(_word); + const char* ptr = strFind(_str, _word); + for (; NULL != ptr; ptr = strFind(ptr + len, _word) ) { if (ptr != _str) { @@ -418,7 +648,7 @@ namespace bx static int32_t write(WriterI* _writer, const char* _str, int32_t _len, const Param& _param, Error* _err) { int32_t size = 0; - int32_t len = (int32_t)strnlen(_str, _len); + int32_t len = (int32_t)strLen(_str, _len); int32_t padding = _param.width > len ? _param.width - len : 0; bool sign = _param.sign && len > 1 && _str[0] != '-'; padding = padding > 0 ? padding - sign : 0; @@ -534,7 +764,7 @@ namespace bx toUpperUnsafe(str, len); } - const char* dot = strnchr(str, '.'); + const char* dot = strFind(str, INT32_MAX, '.'); if (NULL != dot) { const int32_t precLen = int32_t( @@ -574,7 +804,7 @@ namespace bx int32_t write(WriterI* _writer, const char* _format, va_list _argList, Error* _err) { - MemoryReader reader(_format, uint32_t(strnlen(_format) ) ); + MemoryReader reader(_format, uint32_t(strLen(_format) ) ); int32_t size = 0; @@ -793,9 +1023,9 @@ namespace bx { va_list argList; va_start(argList, _format); - int32_t size = write(_writer, _format, argList, _err); + int32_t total = write(_writer, _format, argList, _err); va_end(argList); - return size; + return total; } int32_t vsnprintfRef(char* _out, int32_t _max, const char* _format, va_list _argList) @@ -829,8 +1059,11 @@ namespace bx int32_t vsnprintf(char* _out, int32_t _max, const char* _format, va_list _argList) { + va_list argList; + va_copy(argList, _argList); + int32_t total = 0; #if BX_CRT_NONE - return vsnprintfRef(_out, _max, _format, _argList); + total = vsnprintfRef(_out, _max, _format, argList); #elif BX_CRT_MSVC int32_t len = -1; if (NULL != _out) @@ -840,26 +1073,30 @@ namespace bx len = ::vsnprintf_s(_out, _max, size_t(-1), _format, argListCopy); va_end(argListCopy); } - return -1 == len ? ::_vscprintf(_format, _argList) : len; + total = -1 == len ? ::_vscprintf(_format, argList) : len; #else - return ::vsnprintf(_out, _max, _format, _argList); + total = ::vsnprintf(_out, _max, _format, argList); #endif // BX_COMPILER_MSVC + va_end(argList); + return total; } int32_t snprintf(char* _out, int32_t _max, const char* _format, ...) { va_list argList; va_start(argList, _format); - int32_t len = vsnprintf(_out, _max, _format, argList); + int32_t total = vsnprintf(_out, _max, _format, argList); va_end(argList); - return len; + return total; } int32_t vsnwprintf(wchar_t* _out, int32_t _max, const wchar_t* _format, va_list _argList) { + va_list argList; + va_copy(argList, _argList); + int32_t total = 0; #if BX_CRT_NONE - BX_UNUSED(_out, _max, _format, _argList); - return 0; + BX_UNUSED(_out, _max, _format, argList); #elif BX_CRT_MSVC int32_t len = -1; if (NULL != _out) @@ -869,12 +1106,14 @@ namespace bx len = ::_vsnwprintf_s(_out, _max, size_t(-1), _format, argListCopy); va_end(argListCopy); } - return -1 == len ? ::_vscwprintf(_format, _argList) : len; + total = -1 == len ? ::_vscwprintf(_format, _argList) : len; #elif BX_CRT_MINGW - return ::vsnwprintf(_out, _max, _format, _argList); + total = ::vsnwprintf(_out, _max, _format, argList); #else - return ::vswprintf(_out, _max, _format, _argList); + total = ::vswprintf(_out, _max, _format, argList); #endif // BX_COMPILER_MSVC + va_end(argList); + return total; } int32_t swnprintf(wchar_t* _out, int32_t _max, const wchar_t* _format, ...) @@ -886,44 +1125,36 @@ namespace bx return len; } - const char* baseName(const char* _filePath) - { - const char* bs = strnrchr(_filePath, '\\'); - const char* fs = strnrchr(_filePath, '/'); - const char* slash = (bs > fs ? bs : fs); - const char* colon = strnrchr(_filePath, ':'); - const char* basename = slash > colon ? slash : colon; - if (NULL != basename) - { - return basename+1; - } - - return _filePath; - } + static const char s_units[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' }; - void prettify(char* _out, int32_t _count, uint64_t _size) + template<uint32_t Kilo, char KiloCh0, char KiloCh1> + inline int32_t prettify(char* _out, int32_t _count, uint64_t _value) { uint8_t idx = 0; - double size = double(_size); - while (_size != (_size&0x7ff) - && idx < 9) + double value = double(_value); + while (_value != (_value&0x7ff) + && idx < BX_COUNTOF(s_units) ) { - _size >>= 10; - size *= 1.0/1024.0; + _value /= Kilo; + value *= 1.0/double(Kilo); ++idx; } - snprintf(_out, _count, "%0.2f %c%c", size, "BkMGTPEZY"[idx], idx > 0 ? 'B' : '\0'); + return snprintf(_out, _count, "%0.2f %c%c%c", value + , s_units[idx] + , idx > 0 ? KiloCh0 : '\0' + , KiloCh1 + ); } - int32_t strlcpy(char* _dst, const char* _src, int32_t _max) + int32_t prettify(char* _out, int32_t _count, uint64_t _value, Units::Enum _units) { - return strlncpy(_dst, _max, _src); - } + if (Units::Kilo == _units) + { + return prettify<1000, 'B', '\0'>(_out, _count, _value); + } - int32_t strlcat(char* _dst, const char* _src, int32_t _max) - { - return strlncat(_dst, _max, _src); + return prettify<1024, 'i', 'B'>(_out, _count, _value); } } // namespace bx |