[wpiutil] StringExtras: Add substr() (#3742)

Unlike std::string and std::string_view, this substr() allows a start
greater than the length of the string, in which case an empty string
is returned.  This matches llvm::StringRef behavior.
This commit is contained in:
Peter Johnson
2021-11-27 21:31:40 -08:00
committed by GitHub
parent 6f51cb3b98
commit ae208d2b17
18 changed files with 118 additions and 77 deletions

View File

@@ -181,21 +181,6 @@ public:
}
/// @}
/// @name Substring Operations
/// @{
/// Return a reference to the substring from [Start, Start + N).
///
/// \param Start The index of the starting character in the substring; if
/// the index is npos or greater than the length of the string then the
/// empty substring will be returned.
///
/// \param N The number of characters to included in the substring. If \p N
/// exceeds the number of characters remaining in the string, the string
/// suffix (starting with \p Start) will be returned.
std::string_view substr(size_t Start, size_t N = std::string_view::npos) const {
return str().substr(Start, N);
}
// Extra methods.

View File

@@ -207,12 +207,31 @@ inline std::string_view::size_type rfind_lower(std::string_view str,
return rfind_lower(str, std::string_view{other});
}
/**
* Returns the substring of @p str from [start, start + n).
*
* @param start The index of the starting character in the substring; if
* the index is npos or greater than the length of the string then the
* empty substring will be returned.
*
* @param n The number of characters to included in the substring. If n
* exceeds the number of characters remaining in the string, the string
* suffix (starting with @p start) will be returned.
*/
constexpr std::string_view substr(
std::string_view str, std::string_view::size_type start,
std::string_view::size_type n = std::string_view::npos) noexcept {
auto length = str.size();
start = (std::min)(start, length);
return {str.data() + start, (std::min)(n, length - start)};
}
/**
* Checks if @p str starts with the given @p prefix.
*/
constexpr bool starts_with(std::string_view str,
std::string_view prefix) noexcept {
return str.substr(0, prefix.size()) == prefix;
return substr(str, 0, prefix.size()) == prefix;
}
/**
@@ -354,6 +373,34 @@ constexpr std::string_view drop_back(
return str;
}
/**
* Returns a view equal to @p str but with only the first @p n
* elements remaining. If @p n is greater than the length of the
* string, the entire string is returned.
*/
constexpr std::string_view take_front(
std::string_view str, std::string_view::size_type n = 1) noexcept {
auto length = str.size();
if (n >= length) {
return str;
}
return drop_back(str, length - n);
}
/**
* Returns a view equal to @p str but with only the last @p n
* elements remaining. If @p n is greater than the length of the
* string, the entire string is returned.
*/
constexpr std::string_view take_back(
std::string_view str, std::string_view::size_type n = 1) noexcept {
auto length = str.size();
if (n >= length) {
return str;
}
return drop_front(str, length - n);
}
/**
* Returns a reference to the substring of @p str from [start, end).
*

View File

@@ -7,6 +7,7 @@
#include <string_view>
#include "wpi/StringExtras.h"
#include "wpi/http_parser.h"
namespace wpi {
@@ -52,35 +53,35 @@ class UrlParser {
}
std::string_view GetSchema() const {
return m_data.substr(m_url.field_data[UF_SCHEMA].off,
m_url.field_data[UF_SCHEMA].len);
return wpi::substr(m_data, m_url.field_data[UF_SCHEMA].off,
m_url.field_data[UF_SCHEMA].len);
}
std::string_view GetHost() const {
return m_data.substr(m_url.field_data[UF_HOST].off,
m_url.field_data[UF_HOST].len);
return wpi::substr(m_data, m_url.field_data[UF_HOST].off,
m_url.field_data[UF_HOST].len);
}
unsigned int GetPort() const { return m_url.port; }
std::string_view GetPath() const {
return m_data.substr(m_url.field_data[UF_PATH].off,
m_url.field_data[UF_PATH].len);
return wpi::substr(m_data, m_url.field_data[UF_PATH].off,
m_url.field_data[UF_PATH].len);
}
std::string_view GetQuery() const {
return m_data.substr(m_url.field_data[UF_QUERY].off,
m_url.field_data[UF_QUERY].len);
return wpi::substr(m_data, m_url.field_data[UF_QUERY].off,
m_url.field_data[UF_QUERY].len);
}
std::string_view GetFragment() const {
return m_data.substr(m_url.field_data[UF_FRAGMENT].off,
m_url.field_data[UF_FRAGMENT].len);
return wpi::substr(m_data, m_url.field_data[UF_FRAGMENT].off,
m_url.field_data[UF_FRAGMENT].len);
}
std::string_view GetUserInfo() const {
return m_data.substr(m_url.field_data[UF_USERINFO].off,
m_url.field_data[UF_USERINFO].len);
return wpi::substr(m_data, m_url.field_data[UF_USERINFO].off,
m_url.field_data[UF_USERINFO].len);
}
private: