diff --git a/include/stdex/html.hpp b/include/stdex/html.hpp index 619e988db..d849d3e46 100644 --- a/include/stdex/html.hpp +++ b/include/stdex/html.hpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #ifdef _WIN32 @@ -286,10 +288,10 @@ namespace stdex /// \param[in,out] dst String to append to /// \param[in] src Source string /// - template, class _Alloc_dst = std::allocator, class _Traits_src = std::char_traits, class _Alloc_src = std::allocator> + template, class _Alloc_dst = std::allocator> void url_unescape( _Inout_ std::basic_string& dst, - _In_ const std::basic_string& src) + _In_ const std::string_view src) { url_unescape(dst, src.data(), src.size()); } @@ -365,10 +367,10 @@ namespace stdex /// \param[in,out] dst String to append to /// \param[in] src Source string /// - template, class _Alloc_dst = std::allocator, class _Traits_src = std::char_traits, class _Alloc_src = std::allocator> + template, class _Alloc_dst = std::allocator> void url_escape( _Inout_ std::basic_string& dst, - _In_ const std::basic_string& src) + _In_ const std::string_view src) { url_escape(dst, src.data(), src.size()); } @@ -1678,13 +1680,13 @@ namespace stdex if (m_condition_start.match(source, i, num_chars)) { auto condition_src(replace_entities(source + m_condition_start.condition.start, m_condition_start.condition.size())); - if (!stdex::strcmp(condition_src.c_str(), "CDATA")) + if (condition_src == "CDATA") m_is_cdata = true; - else if (!stdex::strcmp(condition_src.c_str(), "RCDATA")) + else if (condition_src == "RCDATA") m_is_rcdata = true; if (m_num_invalid_conditions) m_num_invalid_conditions++; - else if (!stdex::strcmp(condition_src.c_str(), "IGNORE")) + else if (condition_src == "IGNORE") m_num_invalid_conditions++; else m_num_valid_conditions++; @@ -1776,7 +1778,7 @@ namespace stdex str.reserve(content.charset.size()); for (size_t j = content.charset.start; j < content.charset.end; ++j) str.push_back(static_cast(source[j])); - m_charset = stdex::charset_from_name(str.c_str()); + m_charset = stdex::charset_from_name(str); } } } diff --git a/include/stdex/sgml.hpp b/include/stdex/sgml.hpp index 2d8f8e814..c42af098f 100644 --- a/include/stdex/sgml.hpp +++ b/include/stdex/sgml.hpp @@ -11,6 +11,7 @@ #include "string.hpp" #include #include +#include #include namespace stdex @@ -229,7 +230,7 @@ namespace stdex skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0, skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0; - size_t j = wcsnlen(dst, count_dst); + size_t j = strnlen(dst, count_dst); count_src = strnlen(src, count_src); for (size_t i = 0; i < count_src;) { if (src[i] == '&') { @@ -410,7 +411,7 @@ namespace stdex _In_ const mapping& offset = mapping(0, 0), _Inout_opt_ mapping_vector* map = nullptr) { - return sgml2str(src.c_str(), src.size(), skip, offset, map); + return sgml2str(src.data(), src.size(), skip, offset, map); } /// \cond internal @@ -471,7 +472,7 @@ namespace stdex do_lcub_rcub = (what & sgml_lcub_rcub) == 0, do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0; - count_src = wcsnlen(src, count_src); + count_src = strnlen(src, count_src); dst.reserve(dst.size() + count_src); for (size_t i = 0; i < count_src;) { size_t n = glyphlen(src + i, count_src - i); @@ -552,12 +553,13 @@ namespace stdex /// \param[in] src Unicode string /// \param[in] what Bitwise flag of stdex::sgml_* constants that force extra characters otherwise not converted to SGML /// - inline void str2sgmlcat( - _Inout_ std::string& dst, - _In_ const std::wstring& src, + template , class _Ax = std::allocator> + void str2sgmlcat( + _Inout_ std::basic_string& dst, + _In_ const std::wstring_view src, _In_ int what = 0) { - str2sgmlcat(dst, src.c_str(), src.size(), what); + str2sgmlcat(dst, src.data(), src.size(), what); } /// @@ -595,7 +597,7 @@ namespace stdex do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0; size_t j = strnlen(dst, count_dst); - count_src = wcsnlen(src, count_src); + count_src = strnlen(src, count_src); for (size_t i = 0; i < count_src;) { size_t n = glyphlen(src + i, count_src - i); if (n == 1 && @@ -716,9 +718,10 @@ namespace stdex /// \param[in] src Unicode string /// \param[in] what Bitwise flag of stdex::sgml_* constants that force extra characters otherwise not converted to SGML /// - inline void str2sgmlcpy( - _Inout_ std::string& dst, - _In_ const std::wstring& src, + template , class _Ax = std::allocator> + void str2sgmlcpy( + _Inout_ std::basic_string& dst, + _In_ const std::wstring_view src, _In_ int what = 0) { str2sgmlcpy(dst, src.data(), src.size(), what); @@ -773,9 +776,9 @@ namespace stdex /// \return SGML string /// inline std::string str2sgml( - _In_ const std::wstring& src, + _In_ const std::wstring_view src, _In_ int what = 0) { - return str2sgml(src.c_str(), src.size(), what); + return str2sgml(src.data(), src.size(), what); } } diff --git a/include/stdex/string.hpp b/include/stdex/string.hpp index 762894a1c..a1fe9d597 100644 --- a/include/stdex/string.hpp +++ b/include/stdex/string.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace stdex { @@ -71,8 +72,8 @@ namespace stdex { _Assume_(is_surrogate_pair(str)); return - ((char32_t)(str[0] - 0xd800) << 10) + - (char32_t)(str[1] - 0xdc00) + + (static_cast(str[0] - 0xd800) << 10) + + static_cast(str[1] - 0xdc00) + 0x10000; } @@ -85,8 +86,8 @@ namespace stdex { _Assume_(chr >= 0x10000); chr -= 0x10000; - str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff); - str[1] = 0xdc00 + (char32_t)(chr & 0x3ff); + str[0] = 0xd800 + static_cast((chr >> 10) & 0x3ff); + str[1] = 0xdc00 + static_cast(chr & 0x3ff); } /// @@ -281,13 +282,26 @@ namespace stdex return strnlen(str, SIZE); } + /// + /// Calculate zero-terminated string length. + /// + /// \param[in] str String + /// + /// \return Number of code units excluding zero terminator in the string. + /// + template + inline size_t strnlen(_In_ const std::basic_string_view> str) + { + return strnlen(str.data(), str.size()); + } + constexpr auto npos{ static_cast(-1) }; /// /// Find a code unit in a string. /// - /// \param[in] str String - /// \param[in] chr Code unit to search for + /// \param[in] str String + /// \param[in] chr Code unit to search for /// /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. /// @@ -300,20 +314,6 @@ namespace stdex return npos; } - /// - /// Find a code unit in a string. - /// - /// \param[in] str String - /// \param[in] chr Code unit to search for - /// - /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. - /// - template , class _Ax = std::allocator> - inline size_t strrchr(_In_ const std::basic_string& str, _In_ T chr) - { - return strrnchr(str.data(), str.size(), chr); - } - /// /// Find a code unit in a string. /// @@ -335,6 +335,58 @@ namespace stdex return npos; } + /// + /// Find a code unit in a string. + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strnchr( + _In_ const T (&str)[SIZE], + _In_ T chr) + { + return strnchr(str, SIZE, chr); + } + + /// + /// Find a code unit in a string. + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strnchr( + _In_ const std::basic_string_view> str, + _In_ T chr) + { + return strchr(str.data(), str.size(), chr); + } + + /// + /// Find a code unit in a string. + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrchr( + _In_z_ const T* str, + _In_ T chr) + { + _Assume_(str); + size_t z = npos; + for (size_t i = 0; str[i]; ++i) + if (str[i] == chr) z = i; + return z; + } + /// /// Find a code unit in a string. /// @@ -358,46 +410,76 @@ namespace stdex } /// - /// Checks if string contains all ASCII-white-space + /// Find a code unit in a string. /// - /// \param[in] str String - /// \param[in] count Code unit count limit + /// \param[in] str String + /// \param[in] chr Code unit to search for /// - /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. /// - template - inline bool isblank( - _In_reads_or_z_opt_(count) const T* str, - _In_ size_t count) + template + inline size_t strrnchr( + _In_ const T (&str)[SIZE], + _In_ T chr) { - _Assume_(str || !count); - for (size_t i = 0; i < count && str[i]; ++i) - if (!isspace(str[i])) - return false; - return true; + return strrnchr(str, SIZE, chr); } /// - /// Checks if string contains all white-space + /// Find a code unit in a string. /// - /// \param[in] str String - /// \param[in] count Code unit count limit - /// \param[in] locale C++ locale to use + /// \param[in] str String + /// \param[in] chr Code unit to search for /// - /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. /// template - inline bool isblank( - _In_reads_or_z_opt_(count) const T* str, - _In_ size_t count, + inline size_t strrnchr(_In_ const std::basic_string_view> str, _In_ T chr) + { + return strrnchr(str.data(), str.size(), chr); + } + + /// + /// Find a code unit in a string ASCII-case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strichr( + _In_z_ const T* str, + _In_ T chr) + { + _Assume_(str); + chr = tolower(chr); + for (size_t i = 0; str[i]; ++i) + if (tolower(str[i]) == chr) return i; + return npos; + } + + /// + /// Find a code unit in a string case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strichr( + _In_z_ const T* str, + _In_ T chr, _In_ const std::locale& locale) { - _Assume_(str || !count); + _Assume_(str); const auto& ctype = std::use_facet>(locale); - for (size_t i = 0; i < count && str[i]; ++i) - if (!ctype.is(ctype.space, str[i])) - return false; - return true; + chr = ctype.tolower(chr); + for (size_t i = 0; str[i]; ++i) + if (ctype.tolower(str[i]) == chr) return i; + return npos; } /// @@ -447,6 +529,119 @@ namespace stdex return npos; } + /// + /// Find a code unit in a string ASCII-case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strnichr( + _In_ const T (&str)[SIZE], + _In_ T chr) + { + return strnichr(str, SIZE, chr); + } + + /// + /// Find a code unit in a string case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strnichr( + _In_ const T (&str)[SIZE], + _In_ T chr, + _In_ const std::locale& locale) + { + return strnichr(str, SIZE, chr, locale); + } + + /// + /// Find a code unit in a string ASCII-case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strnichr( + _In_ const std::basic_string_view> str, + _In_ T chr) + { + return strichr(str.data(), str.size(), chr); + } + + /// + /// Find a code unit in a string case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset to the first occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strnichr( + _In_ const std::basic_string_view> str, + _In_ T chr, + _In_ const std::locale& locale) + { + return strichr(str.data(), str.size(), chr, locale); + } + + /// + /// Find a code unit in a string ASCII-case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrichr( + _In_z_ const T* str, + _In_ T chr) + { + _Assume_(str); + chr = tolower(chr); + size_t z = npos; + for (size_t i = 0; str[i]; ++i) + if (tolower(str[i]) == chr) z = i; + return z; + } + + /// + /// Find a code unit in a string case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrichr( + _In_reads_or_z_opt_(count) const T* str, + _In_ T chr, + _In_ const std::locale& locale) + { + _Assume_(str); + const auto& ctype = std::use_facet>(locale); + chr = ctype.tolower(chr); + size_t z = npos; + for (size_t i = 0; str[i]; ++i) + if (ctype.tolower(str[i]) == chr) z = i; + return z; + } + /// /// Find a code unit in a string ASCII-case-insensitive /// @@ -496,23 +691,258 @@ namespace stdex return z; } + /// + /// Find a code unit in a string ASCII-case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrnichr( + _In_ const T (&str)[SIZE], + _In_ T chr) + { + return strrnichr(str, SIZE, chr); + } + + /// + /// Find a code unit in a string case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrnichr( + _In_ const T (&str)[SIZE], + _In_ T chr, + _In_ const std::locale& locale) + { + return strrnichr(str, SIZE, chr, locale); + } + + /// + /// Find a code unit in a string ASCII-case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrnichr( + _In_ const std::basic_string_view> str, + _In_ T chr) + { + return strrnichr(str.data(), str.size(), chr); + } + + /// + /// Find a code unit in a string case-insensitive + /// + /// \param[in] str String + /// \param[in] chr Code unit to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset to the last occurence of chr code unit or stdex::npos if not found. + /// + template + inline size_t strrnichr( + _In_ const std::basic_string_view> str, + _In_ T chr, + _In_ const std::locale& locale) + { + return strrnichr(str.data(), str.size(), chr, locale); + } + + ///// + ///// Checks if string contains all ASCII-white-space + ///// + ///// \param[in] str String + ///// + ///// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + ///// + //template + //inline bool isblank(_In_z_ const T* str) + //{ + // _Assume_(str); + // for (size_t i = 0; str[i]; ++i) + // if (!isspace(str[i])) + // return false; + // return true; + //} + + ///// + ///// Checks if string contains all white-space + ///// + ///// \param[in] str String + ///// \param[in] locale C++ locale to use + ///// + ///// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + ///// + //template + //inline bool isblank( + // _In_z_ const T* str, + // _In_ const std::locale& locale) + //{ + // _Assume_(str); + // const auto& ctype = std::use_facet>(locale); + // for (size_t i = 0; str[i]; ++i) + // if (!ctype.is(ctype.space, str[i])) + // return false; + // return true; + //} + + /// + /// Checks if string contains all ASCII-white-space + /// + /// \param[in] str String + /// \param[in] count Code unit count limit + /// + /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// + template + inline bool isblank( + _In_reads_or_z_opt_(count) const T* str, + _In_ size_t count) + { + _Assume_(str || !count); + for (size_t i = 0; i < count && str[i]; ++i) + if (!isspace(str[i])) + return false; + return true; + } + + /// + /// Checks if string contains all white-space + /// + /// \param[in] str String + /// \param[in] count Code unit count limit + /// \param[in] locale C++ locale to use + /// + /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// + template + inline bool isblank( + _In_reads_or_z_opt_(count) const T* str, + _In_ size_t count, + _In_ const std::locale& locale) + { + _Assume_(str || !count); + const auto& ctype = std::use_facet>(locale); + for (size_t i = 0; i < count && str[i]; ++i) + if (!ctype.is(ctype.space, str[i])) + return false; + return true; + } + + /// + /// Checks if string contains all ASCII-white-space + /// + /// \param[in] str String + /// + /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// + template + inline bool isblank(_In_ const T (&str)[SIZE]) + { + return isblank(str, SIZE); + } + + /// + /// Checks if string contains all white-space + /// + /// \param[in] str String + /// \param[in] locale C++ locale to use + /// + /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// + template + inline bool isblank( + _In_ const T (&str)[SIZE], + _In_ const std::locale& locale) + { + return isblank(str, SIZE, locale); + } + + /// + /// Checks if string contains all ASCII-white-space + /// + /// \param[in] str String + /// + /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// + template + inline bool isblank(_In_ const std::basic_string_view> str) + { + return isblank(str.data(), str.size()); + } + + /// + /// Checks if string contains all white-space + /// + /// \param[in] str String + /// \param[in] locale C++ locale to use + /// + /// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string. + /// + template + inline bool isblank( + _In_ const std::basic_string_view> str, + _In_ size_t count, + _In_ const std::locale& locale) + { + return isblank(str.data(), str.size(), locale); + } + /// /// Binary compare two strings /// - /// \param[in] str1 String 1 - /// \param[in] str2 String 2 + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 /// /// \return Negative if str1str2; zero if str1==str2 /// template - inline int strcmp(const T1* str1, const T2* str2) + inline int strcmp(_In_z_ const T1* str1, _In_z_ const T2* str2) { - _Assume_(str1 && str2); - T1 a; T2 b; - for (size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) { + _Assume_(str1); + _Assume_(str2); + size_t i; T1 a; T2 b; + for (i = 0; (a = str1[i]) | (b = str2[i]); ++i) { if (a > b) return +1; if (a < b) return -1; } + if (str1[i]) return +1; + if (str2[i]) return -1; + return 0; + } + + /// + /// Binary compare two strings + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] count String 1 and 2 code unit count limit + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strncmp(_In_reads_or_z_opt_(count) const T1* str1, _In_reads_or_z_opt_(count) const T2* str2, _In_ size_t count) + { + _Assume_(str1 || !count); + _Assume_(str2 || !count); + size_t i; T1 a; T2 b; + for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) { + if (a > b) return +1; + if (a < b) return -1; + } + if (i < count && str1[i]) return +1; + if (i < count && str2[i]) return -1; return 0; } @@ -546,47 +976,31 @@ namespace stdex /// /// Binary compare two strings /// - /// \param[in] str1 String 1 - /// \param[in] str2 String 2 - /// \param[in] count String 1 and 2 code unit count limit + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strncmp( + _In_ const T1 (&str1)[SIZE1], + _In_ const T2 (&str2)[SIZE2]) + { + return strncmp(str1, SIZE, str2, SIZE); + } + + /// + /// Binary compare two strings + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 /// /// \return Negative if str1str2; zero if str1==str2 /// template - inline int strncmp(_In_reads_or_z_opt_(count) const T1* str1, _In_reads_or_z_opt_(count) const T2* str2, _In_ size_t count) + inline int strncmp(_In_ const std::basic_string_view str1, _In_ const std::basic_string_view str2) { - _Assume_((str1 && str2) || !count); - size_t i; T1 a; T2 b; - for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) { - if (a > b) return +1; - if (a < b) return -1; - } - if (i < count && str1[i]) return +1; - if (i < count && str2[i]) return -1; - return 0; - } - - /// - /// Lexigraphically compare two strings - /// - /// \param[in] str1 String 1 - /// \param[in] count1 String 1 code unit count limit - /// \param[in] str2 String 2 - /// \param[in] count2 String 2 code unit count limit - /// \param[in] locale C++ locale to use - /// - /// \return Negative if str1str2; zero if str1==str2 - /// - template - inline int strncoll( - _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1, - _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2, - _In_ const std::locale& locale) - { - _Assume_(str1 || !count1); - _Assume_(str2 || !count2); - auto& collate = std::use_facet>(locale); - return collate.compare(str1, str1 + count1, str2, str2 + count2); + return strncmp(str1.data(), str1.size(), str2.data(), str2.size()); } /// @@ -603,7 +1017,7 @@ namespace stdex _Assume_(str1); _Assume_(str2); size_t i; T1 a; T2 b; - for (i = 0; (a = tolower(str1[i])) | (b = tolower(str2[i])); i++) { + for (i = 0; (a = tolower(str1[i])) | (b = tolower(str2[i])); ++i) { if (a > b) return +1; if (a < b) return -1; } @@ -612,22 +1026,6 @@ namespace stdex return 0; } - /// - /// Binary compare two strings ASCII-case-insensitive - /// - /// \param[in] str1 String 1 - /// \param[in] str2 String 2 - /// - /// \return Negative if str1str2; zero if str1==str2 - /// - template , class _Ax1 = std::allocator, class T2, class _Traits2 = std::char_traits, class _Ax2 = std::allocator> - inline int stricmp( - _In_ const std::basic_string& str1, - _In_ const std::basic_string& str2) - { - return strnicmp(str1.data(), str1.size(), str2.data(), str2.size()); - } - /// /// Binary compare two strings case-insensitive /// @@ -645,7 +1043,7 @@ namespace stdex size_t i; T1 a; T2 b; const auto& ctype1 = std::use_facet>(locale); const auto& ctype2 = std::use_facet>(locale); - for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) { + for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); ++i) { if (a > b) return +1; if (a < b) return -1; } @@ -657,27 +1055,9 @@ namespace stdex /// /// Binary compare two strings ASCII-case-insensitive /// - /// \param[in] str1 String 1 - /// \param[in] str2 String 2 - /// \param[in] locale C++ locale to use - /// - /// \return Negative if str1str2; zero if str1==str2 - /// - template , class _Ax1 = std::allocator, class T2, class _Traits2 = std::char_traits, class _Ax2 = std::allocator> - inline int stricmp( - _In_ const std::basic_string& str1, - _In_ const std::basic_string& str2, - _In_ const std::locale& locale) - { - return strnicmp(str1.data(), str1.size(), str2.data(), str2.size(), locale); - } - - /// - /// Binary compare two strings ASCII-case-insensitive - /// - /// \param[in] str1 String 1 - /// \param[in] str2 String 2 - /// \param[in] count Code unit count limit + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] count Code unit count limit /// /// \return Negative if str1str2; zero if str1==str2 /// @@ -687,7 +1067,7 @@ namespace stdex _Assume_(str1 || !count); _Assume_(str2 || !count); size_t i; T1 a; T2 b; - for (i = 0; i < count && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); i++) { + for (i = 0; i < count && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); ++i) { if (a > b) return +1; if (a < b) return -1; } @@ -714,7 +1094,7 @@ namespace stdex size_t i; T1 a; T2 b; const auto& ctype1 = std::use_facet>(locale); const auto& ctype2 = std::use_facet>(locale); - for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) { + for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); ++i) { if (a > b) return +1; if (a < b) return -1; } @@ -741,7 +1121,7 @@ namespace stdex _Assume_(str1 || !count1); _Assume_(str2 || !count2); size_t i; T1 a; T2 b; - for (i = 0; i < count1 && i < count2 && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); i++) { + for (i = 0; i < count1 && i < count2 && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); ++i) { if (a > b) return +1; if (a < b) return -1; } @@ -772,7 +1152,7 @@ namespace stdex size_t i; T1 a; T2 b; const auto& ctype1 = std::use_facet>(locale); const auto& ctype2 = std::use_facet>(locale); - for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) { + for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); ++i) { if (a > b) return +1; if (a < b) return -1; } @@ -781,6 +1161,152 @@ namespace stdex return 0; } + /// + /// Binary compare two strings ASCII-case-insensitive + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strnicmp( + _In_ const T1 (&str1)[SIZE1], + _In_ const T2 (&str2)[SIZE2]) + { + strnicmp(str1, SIZE, str2, SIZE2); + } + + /// + /// Binary compare two strings case-insensitive + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] locale C++ locale to use + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strnicmp( + _In_ const T1 (&str1)[SIZE1], + _In_ const T2 (&str2)[SIZE2], + _In_ const std::locale& locale) + { + strnicmp(str1, SIZE, str2, SIZE2, locale); + } + + /// + /// Binary compare two strings case-insensitive + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strnicmp(_In_ const std::basic_string_view str1, _In_ const std::basic_string_view str2) + { + return strnicmp(str1.data(), str1.size(), str2.data(), str2.size()); + } + + /// + /// Binary compare two strings ASCII-case-insensitive + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] locale C++ locale to use + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strnicmp( + _In_ const std::basic_string_view str1, + _In_ const std::basic_string_view str2, + _In_ const std::locale& locale) + { + return strnicmp(str1.data(), str1.size(), str2.data(), str2.size(), locale); + } + + /// + /// Lexigraphically compare two strings + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] locale C++ locale to use + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strcoll( + _In_z_ const T* str1, + _In_z_ const T* str2, + _In_ const std::locale& locale) + { + _Assume_(str1); + _Assume_(str2); + auto& collate = std::use_facet>(locale); + return collate.compare(str1, str1 + strlen(str1), str2, str2 + strlen(str2)); + } + + /// + /// Lexigraphically compare two strings + /// + /// \param[in] str1 String 1 + /// \param[in] count1 String 1 code unit count limit + /// \param[in] str2 String 2 + /// \param[in] count2 String 2 code unit count limit + /// \param[in] locale C++ locale to use + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strncoll( + _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1, + _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2, + _In_ const std::locale& locale) + { + _Assume_(str1 || !count1); + _Assume_(str2 || !count2); + auto& collate = std::use_facet>(locale); + return collate.compare(str1, str1 + count1, str2, str2 + count2); + } + + /// + /// Lexigraphically compare two strings + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] locale C++ locale to use + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strncoll( + _In_ const T (&str1)[SIZE1], + _In_ const T (&str2)[SIZE2], + _In_ const std::locale& locale) + { + return strncoll(str1, SIZE1, str2, SIZE2, locale); + } + + /// + /// Lexigraphically compare two strings + /// + /// \param[in] str1 String 1 + /// \param[in] str2 String 2 + /// \param[in] locale C++ locale to use + /// + /// \return Negative if str1str2; zero if str1==str2 + /// + template + inline int strncoll( + _In_ const std::basic_string_view> str1, + _In_ const std::basic_string_view> str2, + _In_ const std::locale& locale) + { + return strncoll(str1.data(), str1.size(), str2.data(), str2.size(), locale); + } + /// /// Search for a substring /// @@ -819,8 +1345,7 @@ namespace stdex /// template inline size_t strnstr( - _In_reads_or_z_opt_(count) const T1* str, - _In_ size_t count, + _In_reads_or_z_opt_(count) const T1* str, _In_ size_t count, _In_z_ const T2* sample) { _Assume_(str || !count); @@ -837,6 +1362,38 @@ namespace stdex } } + /// + /// Search for a substring + /// + /// \param[in] str String to search in + /// \param[in] sample Substring to search for + /// + /// \return Offset inside str where sample string is found; stdex::npos if not found + /// + template + inline size_t strnstr( + _In_ const T1 (&str)[SIZE1], + _In_z_ const T2* sample) + { + return strnstr(str, SIZE, sample); + } + + /// + /// Search for a substring + /// + /// \param[in] str String to search in + /// \param[in] sample Substring to search for + /// + /// \return Offset inside str where sample string is found; stdex::npos if not found + /// + template + inline size_t strnstr( + _In_ const std::basic_string_view str, + _In_z_ const T2* sample) + { + return strnstr(str.data(), str.size(), sample); + } + /// /// Search for a substring ASCII-case-insensitive /// @@ -957,11 +1514,79 @@ namespace stdex } } + /// + /// Search for a substring ASCII-case-insensitive + /// + /// \param[in] str String to search in + /// \param[in] sample Substring to search for + /// + /// \return Offset inside str where sample string is found; stdex::npos if not found + /// + template + inline size_t strnistr( + _In_ const T1 (&str)[SIZE1], + _In_z_ const T2* sample) + { + return strnistr(str, SIZE1, sample); + } + + /// + /// Search for a substring case-insensitive + /// + /// \param[in] str String to search in + /// \param[in] sample Substring to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset inside str where sample string is found; stdex::npos if not found + /// + template + inline size_t strnistr( + _In_ const T1 (&str)[SIZE1], + _In_z_ const T2* sample, + _In_ const std::locale& locale) + { + return strnistr(str, SIZE1, sample, locale); + } + + /// + /// Search for a substring ASCII-case-insensitive + /// + /// \param[in] str String to search in + /// \param[in] sample Substring to search for + /// + /// \return Offset inside str where sample string is found; stdex::npos if not found + /// + template + inline size_t strnistr( + _In_ const std::basic_string_view str, + _In_z_ const T2* sample) + { + return strnistr(str.data(), str.size(), sample); + } + + /// + /// Search for a substring case-insensitive + /// + /// \param[in] str String to search in + /// \param[in] sample Substring to search for + /// \param[in] locale C++ locale to use + /// + /// \return Offset inside str where sample string is found; stdex::npos if not found + /// + template + inline size_t strnistr( + _In_ const std::basic_string_view str, + _In_z_ const T2* sample, + _In_ const std::locale& locale) + { + return strnistr(str.data(), str.size(), sample, locale); + } + /// /// Copy zero-terminated string /// - /// \param[in] dst Destination string - /// \param[in] src Source 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. /// @@ -970,7 +1595,8 @@ namespace stdex _Out_writes_z_(_String_length_(src) + 1) T1* dst, _In_z_ const T2* src) { - _Assume_(dst && src); + _Assume_(dst); + _Assume_(src); for (size_t i = 0; ; ++i) { if ((dst[i] = src[i]) == 0) return i; @@ -991,7 +1617,8 @@ namespace stdex _Out_writes_(count) _Post_maybez_ T1* dst, _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count) { - _Assume_(dst && src || !count); + _Assume_(dst || !count); + _Assume_(src || !count); for (size_t i = 0; ; ++i) { if (i >= count) return i; @@ -1033,8 +1660,8 @@ namespace stdex /// /// Append zero-terminated string /// - /// \param[in] dst Destination string - /// \param[in] src Source 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. /// @@ -1043,7 +1670,8 @@ namespace stdex _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst, _In_z_ const T2* src) { - _Assume_(dst && src); + _Assume_(dst); + _Assume_(src); for (size_t i = 0, j = stdex::strlen(dst); ; ++i, ++j) { if ((dst[j] = src[i]) == 0) return j; @@ -1064,7 +1692,8 @@ namespace stdex _Inout_z_ T1* dst, _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count) { - _Assume_(dst && src || !count); + _Assume_(dst || !count); + _Assume_(src || !count); for (size_t i = 0, j = stdex::strlen(dst); ; ++i, ++j) { if (i >= count) return j; @@ -1145,6 +1774,38 @@ namespace stdex return dst; } + /// + /// Returns duplicated string on the heap + /// + /// In contrast with the stdlib C strdup, the memory is allocated using operator new T[]. + /// This allows returned string to be fed into std::unique_ptr for auto release. + /// + /// \param[in] str String to duplicate. Must be zero-terminated. + /// + /// \return Pointer to duplicated string; or nullptr if str is nullptr. Use delete operator to free the memory. + /// + template + inline _Check_return_ _Ret_maybenull_z_ T* strndup(_In_ const T (&str)[SIZE]) + { + return strndup(str, SIZE); + } + + /// + /// Returns duplicated string on the heap + /// + /// In contrast with the stdlib C strdup, the memory is allocated using operator new T[]. + /// This allows returned string to be fed into std::unique_ptr for auto release. + /// + /// \param[in] str String to duplicate. Must be zero-terminated. + /// + /// \return Pointer to duplicated string; or nullptr if str is nullptr. Use delete operator to free the memory. + /// + template + inline _Check_return_ _Ret_maybenull_z_ T* strndup(_In_ const std::basic_string_view> str) + { + return strndup(str.data(), str.size()); + } + /// /// Convert CRLF to LF /// Source and destination strings may point to the same buffer for inline conversion. @@ -1155,7 +1816,7 @@ namespace stdex /// \return Number of code units excluding zero terminator in the dst string after the operation. /// template - inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src) + inline size_t crlf2nl(_Out_writes_z_(_String_length_(src) + 1) T* dst, _In_z_ const T* src) { _Assume_(dst); _Assume_(src); @@ -1176,13 +1837,13 @@ namespace stdex /// Convert CRLF to LF /// /// \param[in] dst Destination string - /// \param[in] src Source string. Must not be dst.c_str(). + /// \param[in] src Source string. Must not be dst.data(). /// template, class _Ax = std::allocator<_Elem>> inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& dst, _In_z_ const _Elem* src) { _Assume_(src); - _Assume_(src != dst.c_str()); + _Assume_(src != dst.data()); dst.clear(); dst.reserve(strlen(src)); for (size_t j = 0; src[j];) { @@ -1374,6 +2035,42 @@ namespace stdex } } + /// + /// Parse string for a signed integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + T_bin strtoint( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtoint(str, SIZE, end, radix); + } + + /// + /// Parse string for a signed integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + T_bin strtoint( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtoint(str.data(), str.size(), end, radix); + } + /// /// Parse string for an unsigned integer /// @@ -1407,6 +2104,42 @@ namespace stdex (flags & 0x01) ? ~value : value; } + /// + /// Parse string for an unsigned integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline T_bin strtouint( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtouint(str, SIZE, end, radix); + } + + /// + /// Parse string for an unsigned integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline T_bin strtouint( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtouint(str.data(), str.size(), end, radix); + } + /// /// Parse string for a signed 32-bit integer /// @@ -1426,6 +2159,42 @@ namespace stdex return strtoint(str, count, end, radix); } + /// + /// Parse string for a signed 32-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline int32_t strto32( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strto32(str, SIZE, end, radix); + } + + /// + /// Parse string for a signed 32-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline int32_t strto32( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strto32(str.data(), str.size(), end, radix); + } + /// /// Parse string for a signed 64-bit integer /// @@ -1445,6 +2214,42 @@ namespace stdex return strtoint(str, count, end, radix); } + /// + /// Parse string for a signed 64-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline int64_t strto64( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strto64(str, SIZE, end, radix); + } + + /// + /// Parse string for a signed 64-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline int64_t strto64( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strto64(str.data(), str.size(), end, radix); + } + /// /// Parse string for a signed 32/64-bit integer /// Dependent on platform CPU architecture @@ -1463,12 +2268,50 @@ namespace stdex _In_ int radix) { #if defined(_WIN64) || defined(__LP64__) - return (intptr_t)strto64(str, count, end, radix); + return static_cast(strto64(str, count, end, radix)); #else - return (intptr_t)strto32(str, count, end, radix); + return static_cast(strto32(str, count, end, radix)); #endif } + /// + /// Parse string for a signed 32/64-bit integer + /// Dependent on platform CPU architecture + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline intptr_t strtoi( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtoi(str, SIZE, end, radix); + } + + /// + /// Parse string for a signed 32/64-bit integer + /// Dependent on platform CPU architecture + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline intptr_t strtoi( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtoi(str.data(), str.size(), end, radix); + } + /// /// Parse string for an unsigned 32-bit integer /// @@ -1488,6 +2331,42 @@ namespace stdex return strtouint(str, count, end, radix); } + /// + /// Parse string for an unsigned 32-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline uint32_t strtou32( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtou32(str, SIZE, end, radix); + } + + /// + /// Parse string for an unsigned 32-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline uint32_t strtou32( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtou32(str.data(), str.size(), end, radix); + } + /// /// Parse string for an unsigned 64-bit integer /// @@ -1507,6 +2386,42 @@ namespace stdex return strtouint(str, count, end, radix); } + /// + /// Parse string for an unsigned 64-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline uint64_t strtou64( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtou64(str, SIZE, end, radix); + } + + /// + /// Parse string for an unsigned 64-bit integer + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline uint64_t strtou64( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtou64(str.data(), str.size(), end, radix); + } + /// /// Parse string for an unsigned 32/64-bit integer /// Dependent on platform CPU architecture @@ -1525,12 +2440,50 @@ namespace stdex _In_ int radix) { #if defined(_WIN64) || defined(__LP64__) - return (size_t)strtou64(str, count, end, radix); + return static_cast(strtou64(str, count, end, radix)); #else - return (size_t)strtou32(str, count, end, radix); + return static_cast(strtou32(str, count, end, radix)); #endif } + /// + /// Parse string for an unsigned 32/64-bit integer + /// Dependent on platform CPU architecture + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline size_t strtoui( + _In_ const T (&str)[SIZE], + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtoui(str, SIZE, end, radix); + } + + /// + /// Parse string for an unsigned 32/64-bit integer + /// Dependent on platform CPU architecture + /// + /// \param[in] str String + /// \param[out] end On return, count of code units processed + /// \param[in] radix Number radix (0 - autodetect; 2..36) + /// + /// \return Binary integer value + /// + template + inline size_t strtoui( + _In_ const std::basic_string_view> str, + _Out_opt_ size_t* end, + _In_ int radix) + { + return strtoui(str.data(), str.size(), end, radix); + } + /// \cond internal inline int vsnprintf(_Out_z_cap_(capacity) char* str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list arg) { @@ -1776,39 +2729,39 @@ namespace stdex return str; } - /// - /// Convert string to ASCII-lower-case character-by-character - /// - /// \param[in,out] str String - /// - template - inline void strlwr(_Inout_z_ T* str) - { - _Assume_(str); - for (size_t i = 0; str[i]; ++i) - str[i] = tolower(str[i]); - } + ///// + ///// Convert string to ASCII-lower-case character-by-character + ///// + ///// \param[in,out] str String + ///// + //template + //inline void strlwr(_Inout_z_ T* str) + //{ + // _Assume_(str); + // for (size_t i = 0; str[i]; ++i) + // str[i] = tolower(str[i]); + //} - /// - /// Convert string to lower-case character-by-character - /// - /// \param[in,out] str String - /// \param[in] locale C++ locale to use - /// - template - inline void strlwr(_Inout_z_ T* str, _In_ const std::locale& locale) - { - _Assume_(str); - const auto& ctype = std::use_facet>(locale); - for (size_t i = 0; str[i]; ++i) - str[i] = ctype.tolower(str[i]); - } + ///// + ///// Convert string to lower-case character-by-character + ///// + ///// \param[in,out] str String + ///// \param[in] locale C++ locale to use + ///// + //template + //inline void strlwr(_Inout_z_ T* str, _In_ const std::locale& locale) + //{ + // _Assume_(str); + // const auto& ctype = std::use_facet>(locale); + // for (size_t i = 0; str[i]; ++i) + // str[i] = ctype.tolower(str[i]); + //} /// /// Convert string to ASCII-lower-case character-by-character /// - /// \param[in,out] str String - /// \param[in] count Code unit limit + /// \param[in,out] str String + /// \param[in] count Code unit limit /// template inline void strlwr(_Inout_updates_z_(count) T* str, _In_ size_t count) @@ -1818,18 +2771,6 @@ namespace stdex str[i] = tolower(str[i]); } - /// - /// Convert string to lower-case character-by-character - /// - /// \param[in,out] str String - /// - template, class _Ax = std::allocator<_Elem>> - inline void strlwr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str) - { - for (auto& c : str) - c = tolower(c); - } - /// /// Convert string to lower-case character-by-character /// @@ -1846,6 +2787,41 @@ namespace stdex str[i] = ctype.tolower(str[i]); } + /// + /// Convert string to lower-case character-by-character + /// + /// \param[in,out] str String + /// + template + inline void strlwr(_Inout_ T (&str)[SIZE]) + { + strlwr(str, count); + } + + /// + /// Convert string to lower-case character-by-character + /// + /// \param[in,out] str String + /// \param[in] locale C++ locale to use + /// + template + inline void strlwr(_Inout_ T (&str)[SIZE], _In_ const std::locale& locale) + { + strlwr(str, count, locale); + } + + /// + /// Convert string to lower-case character-by-character + /// + /// \param[in,out] str String + /// + template, class _Ax = std::allocator<_Elem>> + inline void strlwr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str) + { + for (auto& c : str) + c = tolower(c); + } + /// /// Convert string to lower-case character-by-character /// @@ -1860,33 +2836,33 @@ namespace stdex c = ctype.tolower(c); } - /// - /// Convert string to ASCII-upper-case character-by-character - /// - /// \param[in,out] str String - /// - template - inline void strupr(_Inout_z_ T* str) - { - _Assume_(str); - for (size_t i = 0; str[i]; ++i) - str[i] = toupper(str[i]); - } + ///// + ///// Convert string to ASCII-upper-case character-by-character + ///// + ///// \param[in,out] str String + ///// + //template + //inline void strupr(_Inout_z_ T* str) + //{ + // _Assume_(str); + // for (size_t i = 0; str[i]; ++i) + // str[i] = toupper(str[i]); + //} - /// - /// Convert string to upper-case character-by-character - /// - /// \param[in,out] str String - /// \param[in] locale C++ locale to use - /// - template - inline void strupr(_Inout_z_ T* str, _In_ const std::locale& locale) - { - _Assume_(str); - const auto& ctype = std::use_facet>(locale); - for (size_t i = 0; str[i]; ++i) - str[i] = ctype.toupper(str[i]); - } + ///// + ///// Convert string to upper-case character-by-character + ///// + ///// \param[in,out] str String + ///// \param[in] locale C++ locale to use + ///// + //template + //inline void strupr(_Inout_z_ T* str, _In_ const std::locale& locale) + //{ + // _Assume_(str); + // const auto& ctype = std::use_facet>(locale); + // for (size_t i = 0; str[i]; ++i) + // str[i] = ctype.toupper(str[i]); + //} /// /// Convert string to ASCII-upper-case character-by-character @@ -1918,6 +2894,29 @@ namespace stdex str[i] = ctype.toupper(str[i]); } + /// + /// Convert string to upper-case character-by-character + /// + /// \param[in,out] str String + /// + template + inline void strupr(_Inout_ T (&str)[SIZE]) + { + return strupr(str, SIZE); + } + + /// + /// Convert string to upper-case character-by-character + /// + /// \param[in,out] str String + /// \param[in] locale C++ locale to use + /// + template + inline void strupr(_Inout_ T (&str)[SIZE], _In_ const std::locale& locale) + { + return strupr(str, SIZE, locale); + } + /// /// Convert string to ASCII-upper-case character-by-character /// @@ -1933,7 +2932,7 @@ namespace stdex /// /// Convert string to upper-case character-by-character /// - /// \param[in,out] str String + /// \param[in,out] str String /// \param[in] locale C++ locale to use /// template, class _Ax = std::allocator<_Elem>> diff --git a/include/stdex/system.hpp b/include/stdex/system.hpp index 5f9b82b21..cb0129bc0 100644 --- a/include/stdex/system.hpp +++ b/include/stdex/system.hpp @@ -22,6 +22,7 @@ #endif #include #include +#include #include #if defined(_WIN32) @@ -81,6 +82,11 @@ namespace stdex /// using sys_string = sstring; + /// + /// String view for system functions + /// + using sstring_view = std::basic_string_view>; + /// /// Regular expressions for system strings /// diff --git a/include/stdex/unicode.hpp b/include/stdex/unicode.hpp index b897a3bc3..4d41e38bb 100644 --- a/include/stdex/unicode.hpp +++ b/include/stdex/unicode.hpp @@ -72,7 +72,7 @@ namespace stdex struct charset_less { bool operator()(_In_z_ const char* a, _In_z_ const char* b) const { - return stdex::stricmp(a, b) < 0; + return stricmp(a, b) < 0; } }; static const std::map charsets = { @@ -172,7 +172,7 @@ namespace stdex _In_reads_or_z_opt_(count_src) const T_from* src, _In_ size_t count_src) { _Assume_(src || !count_src); - count_src = stdex::strnlen(src, count_src); + count_src = strnlen(src, count_src); if (!count_src) _Unlikely_ return; @@ -511,7 +511,7 @@ namespace stdex #endif inline void strcat( _Inout_ std::wstring& dst, - _In_ const std::string& src, + _In_ const std::string_view src, _In_ charset_id charset = charset_id::system) { strcat(dst, src.data(), src.size(), charset); @@ -520,7 +520,7 @@ namespace stdex _Deprecated_("Use stdex::strcat") inline void str2wstr( _Inout_ std::wstring& dst, - _In_ const std::string& src, + _In_ const std::string_view src, _In_ charset_id charset = charset_id::system) { strcat(dst, src, charset); @@ -562,7 +562,7 @@ namespace stdex #endif inline void strcpy( _Inout_ std::wstring& dst, - _In_ const std::string& src, + _In_ const std::string_view src, _In_ charset_id charset = charset_id::system) { strcpy(dst, src.data(), src.size(), charset); @@ -627,10 +627,10 @@ namespace stdex _Deprecated_("For better performance, consider a reusable charset_encoder") #endif inline std::wstring str2wstr( - _In_ const std::string& src, + _In_ const std::string_view src, _In_ charset_id charset = charset_id::system) { - return str2wstr(src.c_str(), src.size(), charset); + return str2wstr(src.data(), src.size(), charset); } /// @@ -677,16 +677,16 @@ namespace stdex #endif inline void strcat( _Inout_ std::string& dst, - _In_ const std::wstring& src, + _In_ const std::wstring_view src, _In_ charset_id charset = charset_id::system) { - strcat(dst, src.c_str(), src.size(), charset); + strcat(dst, src.data(), src.size(), charset); } _Deprecated_("Use stdex::strcat") inline void wstr2str( _Inout_ std::string& dst, - _In_ const std::wstring& src, + _In_ const std::wstring_view src, _In_ charset_id charset = charset_id::system) { strcat(dst, src, charset); @@ -728,7 +728,7 @@ namespace stdex #endif inline void strcpy( _Inout_ std::string& dst, - _In_ const std::wstring& src, + _In_ const std::wstring_view src, _In_ charset_id charset = charset_id::system) { strcpy(dst, src.data(), src.size(), charset); @@ -793,10 +793,10 @@ namespace stdex _Deprecated_("For better performance, consider a reusable charset_encoder") #endif inline std::string wstr2str( - _In_ const std::wstring& src, + _In_ const std::wstring_view src, _In_ charset_id charset = charset_id::system) { - return wstr2str(src.c_str(), src.size(), charset); + return wstr2str(src.data(), src.size(), charset); } #ifdef _WIN32 @@ -814,7 +814,7 @@ namespace stdex _Inout_ std::basic_string& dst, _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src) { - count_src = stdex::strnlen(src, count_src); + count_src = strnlen(src, count_src); size_t count_dst = dst.size(); dst.resize(count_dst + count_src); _Assume_(count_src + 1 < INT_MAX); @@ -852,10 +852,10 @@ namespace stdex /// /// \return Number of code units excluding zero terminator in the dst string after the operation. /// - template , class _Alloc_dst = std::allocator, class _Traits_src = std::char_traits, class _Alloc_src = std::allocator> + template , class _Alloc_dst = std::allocator> size_t normalizecat( _Inout_ std::basic_string& dst, - _In_ const std::basic_string& src) + _In_ const std::wstring_view src) { return normalizecat(dst, src.data(), src.size()); } @@ -902,10 +902,10 @@ namespace stdex /// /// \return Number of code units excluding zero terminator in the dst string after the operation. /// - template , class _Alloc_dst = std::allocator, class _Traits_src = std::char_traits, class _Alloc_src = std::allocator> + template , class _Alloc_dst = std::allocator> size_t normalize( _Inout_ std::basic_string& dst, - _In_ const std::basic_string& src) + _In_ const std::wstring_view src) { return normalize(dst, src.data(), src.size()); } @@ -947,8 +947,7 @@ namespace stdex /// /// \return Normalized string /// - template , class _Alloc = std::allocator> - std::wstring normalize(_In_ const std::basic_string& src) + inline std::wstring normalize(_In_ const std::wstring_view src) { std::wstring dst; normalizecat(dst, src.data(), src.size());