diff --git a/include/bx/string.h b/include/bx/string.h index 4815c9c..ea438a9 100644 --- a/include/bx/string.h +++ b/include/bx/string.h @@ -131,6 +131,9 @@ namespace bx /// including zero terminator. Copy will be terminated with '\0'. size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num = INT32_MAX); + /// + size_t strlncat(char* _dst, size_t _dstSize, const char* _src, size_t _num = INT32_MAX); + /// const char* strnchr(const char* _str, char _ch, size_t _max = INT32_MAX); @@ -207,14 +210,14 @@ namespace bx /// Copy src to string dst of size siz. At most siz-1 characters /// will be copied. Always NUL terminates (unless siz == 0). /// Returns strlen(src); if retval >= siz, truncation occurred. - size_t strlcpy(char* _dst, const char* _src, size_t _siz); + size_t strlcpy(char* _dst, const char* _src, size_t _max); /// Appends src to string dst of size siz (unlike strncat, siz is the /// full size of dst, not space left). At most siz-1 characters /// will be copied. Always NUL terminates (unless siz <= strlen(dst)). /// Returns strlen(src) + MIN(siz, strlen(initial dst)). /// If retval >= siz, truncation occurred. - size_t strlcat(char* _dst, const char* _src, size_t _siz); + size_t strlcat(char* _dst, const char* _src, size_t _max); /// uint32_t hashMurmur2A(const StringView& _data); diff --git a/src/string.cpp b/src/string.cpp index 4496366..d27baad 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -127,6 +127,17 @@ namespace bx return num; } + size_t strlncat(char* _dst, size_t _dstSize, const char* _src, size_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 size_t max = _dstSize; + const size_t len = strnlen(_dst, max); + return strlncpy(&_dst[len], max-len, _src, _num); + } + const char* strnchr(const char* _str, char _ch, size_t _max) { for (size_t ii = 0, len = strnlen(_str, _max); ii < len; ++ii) @@ -455,88 +466,14 @@ namespace bx snprintf(_out, _count, "%0.2f %c%c", size, "BkMGTPEZY"[idx], idx > 0 ? 'B' : '\0'); } - /* - * Copyright (c) 1998 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - size_t strlcpy(char* _dst, const char* _src, size_t _siz) + size_t strlcpy(char* _dst, const char* _src, size_t _max) { - char* dd = _dst; - const char* ss = _src; - size_t nn = _siz; - - /* Copy as many bytes as will fit */ - if (nn != 0) - { - while (--nn != 0) - { - if ( (*dd++ = *ss++) == '\0') - { - break; - } - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (nn == 0) - { - if (_siz != 0) - { - *dd = '\0'; /* NUL-terminate dst */ - } - - while (*ss++) - { - } - } - - return(ss - _src - 1); /* count does not include NUL */ + return strlncpy(_dst, _max, _src); } - size_t strlcat(char* _dst, const char* _src, size_t _siz) + size_t strlcat(char* _dst, const char* _src, size_t _max) { - char* dd = _dst; - const char *s = _src; - size_t nn = _siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (nn-- != 0 && *dd != '\0') - { - dd++; - } - - dlen = dd - _dst; - nn = _siz - dlen; - - if (nn == 0) - { - return(dlen + strnlen(s)); - } - - while (*s != '\0') - { - if (nn != 1) - { - *dd++ = *s; - nn--; - } - s++; - } - *dd = '\0'; - - return(dlen + (s - _src)); /* count does not include NUL */ + return strlncat(_dst, _max, _src); } } // namespace bx diff --git a/tests/string_test.cpp b/tests/string_test.cpp index 20e3c39..a61c7cc 100644 --- a/tests/string_test.cpp +++ b/tests/string_test.cpp @@ -53,6 +53,21 @@ TEST_CASE("strlncpy", "") REQUIRE(num == 4); } +TEST_CASE("strlncat", "") +{ + char dst[128] = { '\0' }; + + REQUIRE(0 == bx::strlncat(dst, 1, "cat") ); + + REQUIRE(4 == bx::strlncpy(dst, 5, "copy") ); + REQUIRE(3 == bx::strlncat(dst, 8, "cat") ); + REQUIRE(0 == bx::strncmp(dst, "copycat") ); + + REQUIRE(1 == bx::strlncat(dst, BX_COUNTOF(dst), "------", 1) ); + REQUIRE(3 == bx::strlncat(dst, BX_COUNTOF(dst), "cat") ); + REQUIRE(0 == bx::strncmp(dst, "copycat-cat") ); +} + TEST_CASE("strincmp", "") { REQUIRE(0 == bx::strincmp("test", "test") );