string: Revise searching
POSIX C strchr and strstr implementations return pointers and pointer arithmetic is error prone. Switch to std C++ index search offsets. Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
a6c1c6c7ae
commit
1dda8cde86
@ -173,49 +173,98 @@ namespace stdex
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr auto npos{ static_cast<size_t>(-1) };
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Find a code unit in a string.
|
/// Find a code unit in a string.
|
||||||
///
|
///
|
||||||
/// \param[in] str String
|
/// \param[in] str String
|
||||||
/// \param[in] chr Code unit to search for
|
|
||||||
/// \param[in] count Code unit count limit
|
/// \param[in] count Code unit count limit
|
||||||
|
/// \param[in] chr Code unit to search for
|
||||||
///
|
///
|
||||||
/// \return Pointer to the first occurence of chr code unit or nullptr if not found.
|
/// \return Offset to the first occurence of chr code unit or stdex::npos if not found.
|
||||||
///
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
inline const T* strnchr(
|
inline size_t strnchr(
|
||||||
_In_reads_or_z_opt_(count) const T* str,
|
_In_reads_or_z_opt_(count) const T* str,
|
||||||
_In_ T chr,
|
_In_ size_t count,
|
||||||
_In_ size_t count)
|
_In_ T chr)
|
||||||
{
|
{
|
||||||
assert(str || !count);
|
assert(str || !count);
|
||||||
for (size_t i = 0; i < count && str[i]; ++i)
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
if (str[i] == chr) return str + i;
|
if (str[i] == chr) return i;
|
||||||
return nullptr;
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Find a code unit in a string.
|
||||||
|
///
|
||||||
|
/// \param[in] str String
|
||||||
|
/// \param[in] count Code unit count limit
|
||||||
|
/// \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 <class T>
|
||||||
|
inline size_t strrnchr(
|
||||||
|
_In_reads_or_z_opt_(count) const T* str,
|
||||||
|
_In_ size_t count,
|
||||||
|
_In_ T chr)
|
||||||
|
{
|
||||||
|
assert(str || !count);
|
||||||
|
size_t z = npos;
|
||||||
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
|
if (str[i] == chr) z = i;
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Find a code unit in a string case-insensitive
|
/// Find a code unit in a string case-insensitive
|
||||||
///
|
///
|
||||||
/// \param[in] str String
|
/// \param[in] str String
|
||||||
/// \param[in] chr Code unit to search for
|
|
||||||
/// \param[in] count Code unit count limit
|
/// \param[in] count Code unit count limit
|
||||||
|
/// \param[in] chr Code unit to search for
|
||||||
///
|
///
|
||||||
/// \return Pointer to the first occurence of chr code unit or nullptr if not found.
|
/// \return Offset to the first occurence of chr code unit or stdex::npos if not found.
|
||||||
///
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
inline const T* strnichr(
|
inline size_t strnichr(
|
||||||
_In_reads_or_z_opt_(count) const T* str,
|
_In_reads_or_z_opt_(count) const T* str,
|
||||||
_In_ T chr,
|
|
||||||
_In_ size_t count,
|
_In_ size_t count,
|
||||||
|
_In_ T chr,
|
||||||
_In_ const std::locale& locale)
|
_In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
assert(str || !count);
|
assert(str || !count);
|
||||||
const auto& ctype = std::use_facet<std::ctype<T>>(locale);
|
const auto& ctype = std::use_facet<std::ctype<T>>(locale);
|
||||||
chr = ctype.tolower(chr);
|
chr = ctype.tolower(chr);
|
||||||
for (size_t i = 0; i < count && str[i]; ++i)
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
if (ctype.tolower(str[i]) == chr) return str + i;
|
if (ctype.tolower(str[i]) == chr) return i;
|
||||||
return nullptr;
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Find a code unit in a string case-insensitive
|
||||||
|
///
|
||||||
|
/// \param[in] str String
|
||||||
|
/// \param[in] count Code unit count limit
|
||||||
|
/// \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 <class T>
|
||||||
|
inline size_t strrnichr(
|
||||||
|
_In_reads_or_z_opt_(count) const T* str,
|
||||||
|
_In_ size_t count,
|
||||||
|
_In_ T chr,
|
||||||
|
_In_ const std::locale& locale)
|
||||||
|
{
|
||||||
|
assert(str || !count);
|
||||||
|
const auto& ctype = std::use_facet<std::ctype<T>>(locale);
|
||||||
|
chr = ctype.tolower(chr);
|
||||||
|
size_t z = npos;
|
||||||
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
|
if (ctype.tolower(str[i]) == chr) z = i;
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -279,25 +328,25 @@ namespace stdex
|
|||||||
/// Binary search for a substring
|
/// Binary search for a substring
|
||||||
///
|
///
|
||||||
/// \param[in] str String to search in
|
/// \param[in] str String to search in
|
||||||
/// \param[in] sample Substring to search for
|
|
||||||
/// \param[in] count String code unit count limit
|
/// \param[in] count String code unit count limit
|
||||||
|
/// \param[in] sample Substring to search for
|
||||||
///
|
///
|
||||||
/// \return Pointer inside str where sample string is found; nullptr if not found
|
/// \return Offset inside str where sample string is found; stdex::npos if not found
|
||||||
///
|
///
|
||||||
template <class T1, class T2>
|
template <class T1, class T2>
|
||||||
const T1* strnstr(
|
inline size_t strnstr(
|
||||||
_In_reads_or_z_opt_(count) const T1* str,
|
_In_reads_or_z_opt_(count) const T1* str,
|
||||||
_In_z_ const T2* sample,
|
_In_ size_t count,
|
||||||
_In_ size_t count)
|
_In_z_ const T2* sample)
|
||||||
{
|
{
|
||||||
assert(str || !count);
|
assert(str || !count);
|
||||||
assert(sample);
|
assert(sample);
|
||||||
for (size_t offset = 0;; ++offset) {
|
for (size_t offset = 0;; ++offset) {
|
||||||
for (size_t i = offset, j = 0;; ++i, ++j) {
|
for (size_t i = offset, j = 0;; ++i, ++j) {
|
||||||
if (!sample[j])
|
if (!sample[j])
|
||||||
return str + offset;
|
return offset;
|
||||||
if (i >= count || !str[i])
|
if (i >= count || !str[i])
|
||||||
return nullptr;
|
return npos;
|
||||||
if (str[i] != sample[j])
|
if (str[i] != sample[j])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -308,16 +357,16 @@ namespace stdex
|
|||||||
/// Binary search for a substring case-insensitive
|
/// Binary search for a substring case-insensitive
|
||||||
///
|
///
|
||||||
/// \param[in] str String to search in
|
/// \param[in] str String to search in
|
||||||
/// \param[in] sample Substring to search for
|
|
||||||
/// \param[in] count String code unit count limit
|
/// \param[in] count String code unit count limit
|
||||||
|
/// \param[in] sample Substring to search for
|
||||||
///
|
///
|
||||||
/// \return Pointer inside str where sample string is found; nullptr if not found
|
/// \return Offset inside str where sample string is found; stdex::npos if not found
|
||||||
///
|
///
|
||||||
template <class T1, class T2>
|
template <class T1, class T2>
|
||||||
inline const T1* strnistr(
|
inline size_t strnistr(
|
||||||
_In_reads_or_z_opt_(count) const T1* str,
|
_In_reads_or_z_opt_(count) const T1* str,
|
||||||
_In_z_ const T2* sample,
|
|
||||||
_In_ size_t count,
|
_In_ size_t count,
|
||||||
|
_In_z_ const T2* sample,
|
||||||
_In_ const std::locale& locale)
|
_In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
assert(str || !count);
|
assert(str || !count);
|
||||||
@ -327,9 +376,9 @@ namespace stdex
|
|||||||
for (size_t offset = 0;; ++offset) {
|
for (size_t offset = 0;; ++offset) {
|
||||||
for (size_t i = offset, j = 0;; ++i, ++j) {
|
for (size_t i = offset, j = 0;; ++i, ++j) {
|
||||||
if (!sample[j])
|
if (!sample[j])
|
||||||
return str + offset;
|
return offset;
|
||||||
if (i >= count || !str[i])
|
if (i >= count || !str[i])
|
||||||
return nullptr;
|
return npos;
|
||||||
if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
|
if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user