From d3a12f45b1179e2fd03da849962436f61afd20e7 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 26 Jul 2023 12:17:47 +0200 Subject: [PATCH] string: Add strcpy, strcat, strncat Signed-off-by: Simon Rozman --- include/stdex/string.hpp | 95 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/include/stdex/string.hpp b/include/stdex/string.hpp index c288561c1..3c0ff9ea7 100644 --- a/include/stdex/string.hpp +++ b/include/stdex/string.hpp @@ -134,7 +134,7 @@ namespace stdex /// \param[in] glyph Start of a glyph /// \param[in] count Code unit limit /// - inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, size_t count) + inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count) { _Analysis_assume_(glyph || !count); if (count) { @@ -416,6 +416,26 @@ namespace stdex } } + /// + /// Copy zero-terminated string + /// + /// \param[in] dst Destination string + /// \param[in] src Source string + /// + /// \return Number of code units excluding zero terminator in the dst string after the operation. + /// + template + inline size_t strcpy( + _Out_writes_z_(_String_length_(src) + 1) T1* dst, + _In_z_ const T2* src) + { + assert(dst && src); + for (size_t i = 0; ; ++i) { + if ((dst[i] = src[i]) == 0) + return i; + } + } + /// /// Copy zero-terminated string /// @@ -469,6 +489,79 @@ namespace stdex } } + /// + /// Append zero-terminated string + /// + /// \param[in] dst Destination string + /// \param[in] src Source string + /// + /// \return Number of code units excluding zero terminator in the dst string after the operation. + /// + template + inline size_t strcat( + _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst, + _In_z_ const T2* src) + { + assert(dst && src); + for (size_t i = 0, j = stdex::strlen(dst); ; ++i, ++j) { + if ((dst[j] = src[i]) == 0) + return j; + } + } + + /// + /// Append zero-terminated string + /// + /// \param[in] dst Destination string + /// \param[in] src Source string + /// \param[in] count String code unit count limit + /// + /// \return Number of code units excluding zero terminator in the dst string after the operation. + /// + template + inline size_t strncat( + _Out_writes_(count) _Post_maybez_ T1* dst, + _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count) + { + assert(dst && src || !count); + for (size_t i = 0, j = stdex::strlen(dst); ; ++i, ++j) { + if (i >= count) + return j; + if ((dst[j] = src[i]) == 0) + return j; + } + } + + /// + /// Append zero-terminated string + /// + /// \param[in] dst Destination string + /// \param[in] count_dst Destination string code unit buffer limit + /// \param[in] src Source string + /// \param[in] count_src Source string code unit count limit + /// + /// \return Number of code units excluding zero terminator in the dst string after the operation. + /// + template + inline size_t strncat( + _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst, + _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src) + { + assert(dst || !count_dst); + assert(src || !count_src); + for (size_t i = 0, j = stdex::strnlen(dst, count_dst); ; ++i, ++j) + { + if (j > count_dst) + return j; + if (i > count_src) { + dst[j] = 0; + return j; + } + if ((dst[j] = src[i]) == 0) + return j; + } + } + /// /// Convert CRLF to LF /// Source and destination strings may point to the same buffer for inline conversion.