string: add "C" locale function variants
"C"-locale is basically ASCII while (Microsoft) implementation is not quite performant to our likes. We can do faster. Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
dff646a4f8
commit
d44aed2cff
@ -1051,45 +1051,45 @@ namespace stdex
|
|||||||
{
|
{
|
||||||
_Assume_(attr_name || !num_chars);
|
_Assume_(attr_name || !num_chars);
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case element_t::a: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX, stdex::std_locale_C);
|
case element_t::a: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX);
|
||||||
case element_t::applet: return !stdex::strnicmp(attr_name, num_chars, "code", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::applet: return !stdex::strnicmp(attr_name, num_chars, "code", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "codebase", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "codebase", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX);
|
||||||
case element_t::area: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX, stdex::std_locale_C);
|
case element_t::area: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX);
|
||||||
case element_t::base: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX, stdex::std_locale_C);
|
case element_t::base: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX);
|
||||||
case element_t::bgsound: return !stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C);
|
case element_t::bgsound: return !stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX);
|
||||||
case element_t::blockquote: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX, stdex::std_locale_C);
|
case element_t::blockquote: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX);
|
||||||
case element_t::body: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX, stdex::std_locale_C);
|
case element_t::body: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX);
|
||||||
case element_t::comment: return !stdex::strnicmp(attr_name, num_chars, "data", SIZE_MAX, stdex::std_locale_C);
|
case element_t::comment: return !stdex::strnicmp(attr_name, num_chars, "data", SIZE_MAX);
|
||||||
case element_t::del: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX, stdex::std_locale_C);
|
case element_t::del: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX);
|
||||||
case element_t::embed: return !stdex::strnicmp(attr_name, num_chars, "pluginspage", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::embed: return !stdex::strnicmp(attr_name, num_chars, "pluginspage", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX);
|
||||||
case element_t::form: return !stdex::strnicmp(attr_name, num_chars, "action", SIZE_MAX, stdex::std_locale_C);
|
case element_t::form: return !stdex::strnicmp(attr_name, num_chars, "action", SIZE_MAX);
|
||||||
case element_t::frame: return !stdex::strnicmp(attr_name, num_chars, "longdesc", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::frame: return !stdex::strnicmp(attr_name, num_chars, "longdesc", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX);
|
||||||
case element_t::head: return !stdex::strnicmp(attr_name, num_chars, "profile", SIZE_MAX, stdex::std_locale_C);
|
case element_t::head: return !stdex::strnicmp(attr_name, num_chars, "profile", SIZE_MAX);
|
||||||
case element_t::iframe: return !stdex::strnicmp(attr_name, num_chars, "longdesc", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::iframe: return !stdex::strnicmp(attr_name, num_chars, "longdesc", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX);
|
||||||
case element_t::img: return !stdex::strnicmp(attr_name, num_chars, "longdesc", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::img: return !stdex::strnicmp(attr_name, num_chars, "longdesc", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "lowsrc", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "lowsrc", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "usemap", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "usemap", SIZE_MAX);
|
||||||
case element_t::input: return !stdex::strnicmp(attr_name, num_chars, "lowsrc", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::input: return !stdex::strnicmp(attr_name, num_chars, "lowsrc", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "usemap", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "usemap", SIZE_MAX);
|
||||||
case element_t::ins: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX, stdex::std_locale_C);
|
case element_t::ins: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX);
|
||||||
case element_t::link: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX, stdex::std_locale_C);
|
case element_t::link: return !stdex::strnicmp(attr_name, num_chars, "href", SIZE_MAX);
|
||||||
case element_t::object: return !stdex::strnicmp(attr_name, num_chars, "basehref", SIZE_MAX, stdex::std_locale_C) ||
|
case element_t::object: return !stdex::strnicmp(attr_name, num_chars, "basehref", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "classid", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "classid", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "code", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "code", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "codebase", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "codebase", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "data", SIZE_MAX, stdex::std_locale_C) ||
|
!stdex::strnicmp(attr_name, num_chars, "data", SIZE_MAX) ||
|
||||||
!stdex::strnicmp(attr_name, num_chars, "usemap", SIZE_MAX, stdex::std_locale_C);
|
!stdex::strnicmp(attr_name, num_chars, "usemap", SIZE_MAX);
|
||||||
case element_t::q: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX, stdex::std_locale_C);
|
case element_t::q: return !stdex::strnicmp(attr_name, num_chars, "cite", SIZE_MAX);
|
||||||
case element_t::script: return !stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX, stdex::std_locale_C);
|
case element_t::script: return !stdex::strnicmp(attr_name, num_chars, "src", SIZE_MAX);
|
||||||
case element_t::table: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX, stdex::std_locale_C);
|
case element_t::table: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX);
|
||||||
case element_t::td: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX, stdex::std_locale_C);
|
case element_t::td: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX);
|
||||||
case element_t::th: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX, stdex::std_locale_C);
|
case element_t::th: return !stdex::strnicmp(attr_name, num_chars, "background", SIZE_MAX);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1105,17 +1105,17 @@ namespace stdex
|
|||||||
static inline bool is_localizable(element_t code, const T* attr_name, size_t num_chars)
|
static inline bool is_localizable(element_t code, const T* attr_name, size_t num_chars)
|
||||||
{
|
{
|
||||||
_Assume_(attr_name || !num_chars);
|
_Assume_(attr_name || !num_chars);
|
||||||
if (!stdex::strnicmp(attr_name, num_chars, "title", SIZE_MAX, stdex::std_locale_C))
|
if (!stdex::strnicmp(attr_name, num_chars, "title", SIZE_MAX))
|
||||||
return true;
|
return true;
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case element_t::applet: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX, stdex::std_locale_C);
|
case element_t::applet: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX);
|
||||||
case element_t::area: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX, stdex::std_locale_C);
|
case element_t::area: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX);
|
||||||
case element_t::img: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX, stdex::std_locale_C);
|
case element_t::img: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX);
|
||||||
case element_t::input: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX, stdex::std_locale_C);
|
case element_t::input: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX);
|
||||||
case element_t::object: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX, stdex::std_locale_C);
|
case element_t::object: return !stdex::strnicmp(attr_name, num_chars, "alt", SIZE_MAX);
|
||||||
case element_t::table: return !stdex::strnicmp(attr_name, num_chars, "summary", SIZE_MAX, stdex::std_locale_C);
|
case element_t::table: return !stdex::strnicmp(attr_name, num_chars, "summary", SIZE_MAX);
|
||||||
case element_t::td: return !stdex::strnicmp(attr_name, num_chars, "abbr", SIZE_MAX, stdex::std_locale_C);
|
case element_t::td: return !stdex::strnicmp(attr_name, num_chars, "abbr", SIZE_MAX);
|
||||||
case element_t::th: return !stdex::strnicmp(attr_name, num_chars, "abbr", SIZE_MAX, stdex::std_locale_C);
|
case element_t::th: return !stdex::strnicmp(attr_name, num_chars, "abbr", SIZE_MAX);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1274,13 +1274,11 @@ namespace stdex
|
|||||||
// The mapping table MUST be sorted and all names in lowercase.
|
// The mapping table MUST be sorted and all names in lowercase.
|
||||||
for (size_t i = 1; i < _countof(mapping); i++)
|
for (size_t i = 1; i < _countof(mapping); i++)
|
||||||
_Assume_(stdex::strcmp(mapping[i - 1].name, mapping[i].name) <= 0);
|
_Assume_(stdex::strcmp(mapping[i - 1].name, mapping[i].name) <= 0);
|
||||||
const auto& ctype = std::use_facet<std::ctype<char>>(stdex::std_locale_C);
|
|
||||||
for (size_t i = 0; i < _countof(mapping); i++) {
|
for (size_t i = 0; i < _countof(mapping); i++) {
|
||||||
for (size_t j = 0; mapping[i].name[j]; j++)
|
for (size_t j = 0; mapping[i].name[j]; j++)
|
||||||
_Assume_(ctype.is(ctype.lower | ctype.digit, mapping[i].name[j]));
|
_Assume_(stdex::islower(mapping[i].name[j]) | stdex::isdigit(mapping[i].name[j]));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const auto& ctypeT = std::use_facet<std::ctype<T>>(stdex::std_locale_C);
|
|
||||||
for (size_t i = 0, j = _countof(mapping); i < j; ) {
|
for (size_t i = 0, j = _countof(mapping); i < j; ) {
|
||||||
size_t m = (i + j) / 2;
|
size_t m = (i + j) / 2;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@ -1294,7 +1292,7 @@ namespace stdex
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto chr = static_cast<char>(ctypeT.tolower(name[i2++]));
|
auto chr = static_cast<char>(stdex::tolower(name[i2++]));
|
||||||
if (mapping[m].name[i1] > chr) {
|
if (mapping[m].name[i1] > chr) {
|
||||||
r = 1;
|
r = 1;
|
||||||
break;
|
break;
|
||||||
@ -1594,10 +1592,10 @@ namespace stdex
|
|||||||
bool is_content_type = false;
|
bool is_content_type = false;
|
||||||
stdex::parser::html_attribute* content_attr = nullptr;
|
stdex::parser::html_attribute* content_attr = nullptr;
|
||||||
for (auto& attr : e->attributes) {
|
for (auto& attr : e->attributes) {
|
||||||
if (!stdex::strnicmp(source + attr.name.start, attr.name.size(), "http-equiv", SIZE_MAX, stdex::std_locale_C) &&
|
if (!stdex::strnicmp(source + attr.name.start, attr.name.size(), "http-equiv", SIZE_MAX) &&
|
||||||
!stdex::strnicmp(source + attr.value.start, attr.value.size(), "content-type", SIZE_MAX, stdex::std_locale_C))
|
!stdex::strnicmp(source + attr.value.start, attr.value.size(), "content-type", SIZE_MAX))
|
||||||
is_content_type = true;
|
is_content_type = true;
|
||||||
else if (!stdex::strnicmp(source + attr.name.start, attr.name.size(), "content", SIZE_MAX, stdex::std_locale_C))
|
else if (!stdex::strnicmp(source + attr.name.start, attr.name.size(), "content", SIZE_MAX))
|
||||||
content_attr = &attr;
|
content_attr = &attr;
|
||||||
}
|
}
|
||||||
if (is_content_type && content_attr) {
|
if (is_content_type && content_attr) {
|
||||||
@ -1625,7 +1623,7 @@ namespace stdex
|
|||||||
auto starting_tag = m_element_stack[j];
|
auto starting_tag = m_element_stack[j];
|
||||||
_Assume_(starting_tag && starting_tag->type == stdex::parser::html_sequence_t::element_start);
|
_Assume_(starting_tag && starting_tag->type == stdex::parser::html_sequence_t::element_start);
|
||||||
if (starting_tag->code == e->code ||
|
if (starting_tag->code == e->code ||
|
||||||
starting_tag->code == element_t::unknown && e->code == element_t::unknown && !stdex::strnicmp(source + starting_tag->name.start, starting_tag->name.size(), source + e->name.start, e->name.size(), stdex::std_locale_C))
|
starting_tag->code == element_t::unknown && e->code == element_t::unknown && !stdex::strnicmp(source + starting_tag->name.start, starting_tag->name.size(), source + e->name.start, e->name.size()))
|
||||||
{
|
{
|
||||||
e->start = starting_tag;
|
e->start = starting_tag;
|
||||||
e->parent = starting_tag->parent;
|
e->parent = starting_tag->parent;
|
||||||
@ -1640,7 +1638,7 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
case stdex::parser::html_sequence_t::declaration:
|
case stdex::parser::html_sequence_t::declaration:
|
||||||
if (m_tag.attributes.size() > 3 &&
|
if (m_tag.attributes.size() > 3 &&
|
||||||
!stdex::strnicmp(source + m_tag.attributes[0].name.start, m_tag.attributes[0].name.size(), "entity", SIZE_MAX, stdex::std_locale_C))
|
!stdex::strnicmp(source + m_tag.attributes[0].name.start, m_tag.attributes[0].name.size(), "entity", SIZE_MAX))
|
||||||
{
|
{
|
||||||
if (!stdex::strncmp(source + m_tag.attributes[1].name.start, m_tag.attributes[1].name.size(), "%", SIZE_MAX) &&
|
if (!stdex::strncmp(source + m_tag.attributes[1].name.start, m_tag.attributes[1].name.size(), "%", SIZE_MAX) &&
|
||||||
stdex::strncmp(source + m_tag.attributes[3].name.start, m_tag.attributes[3].name.size(), "SYSTEM", SIZE_MAX) &&
|
stdex::strncmp(source + m_tag.attributes[3].name.start, m_tag.attributes[3].name.size(), "SYSTEM", SIZE_MAX) &&
|
||||||
@ -2283,7 +2281,7 @@ namespace stdex
|
|||||||
stdex::sgml2strcat(token->text, m_source + s->interval.start, s->interval.size(), 0, rel, &token->mapping);
|
stdex::sgml2strcat(token->text, m_source + s->interval.start, s->interval.size(), 0, rel, &token->mapping);
|
||||||
rel.to = token->text.size();
|
rel.to = token->text.size();
|
||||||
if (!(token->text_type & has_text) &&
|
if (!(token->text_type & has_text) &&
|
||||||
!stdex::isblank(m_source + s->interval.start, s->interval.size(), stdex::std_locale_C))
|
!stdex::isblank(m_source + s->interval.start, s->interval.size()))
|
||||||
token->text_type |= has_text;
|
token->text_type |= has_text;
|
||||||
++m_offset;
|
++m_offset;
|
||||||
}
|
}
|
||||||
@ -2303,7 +2301,7 @@ namespace stdex
|
|||||||
// Copy the tag contents, but mind any attributes containing localizable text.
|
// Copy the tag contents, but mind any attributes containing localizable text.
|
||||||
for (auto& a : s_el->attributes) {
|
for (auto& a : s_el->attributes) {
|
||||||
if (a.value.empty() ||
|
if (a.value.empty() ||
|
||||||
stdex::isblank(m_source + a.value.start, a.value.size(), stdex::std_locale_C))
|
stdex::isblank(m_source + a.value.start, a.value.size()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (element_traits::is_uri(s_el->code, m_source + a.name.start, a.name.size())) {
|
if (element_traits::is_uri(s_el->code, m_source + a.name.start, a.name.size())) {
|
||||||
|
@ -109,7 +109,7 @@ namespace stdex
|
|||||||
/// \param[in] chr Code unit
|
/// \param[in] chr Code unit
|
||||||
///
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
inline size_t islbreak(_In_ T chr)
|
inline bool islbreak(_In_ T chr)
|
||||||
{
|
{
|
||||||
return chr == '\n' || chr == '\r';
|
return chr == '\n' || chr == '\r';
|
||||||
}
|
}
|
||||||
@ -120,6 +120,8 @@ namespace stdex
|
|||||||
/// \param[in] chr Pointer to the first code unit of the code point
|
/// \param[in] chr Pointer to the first code unit of the code point
|
||||||
/// \param[in] count Code unit limit
|
/// \param[in] count Code unit limit
|
||||||
///
|
///
|
||||||
|
/// \return 0 if not line break; length of line break in code units otherwise.
|
||||||
|
///
|
||||||
template <class T>
|
template <class T>
|
||||||
inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
|
inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
|
||||||
{
|
{
|
||||||
@ -131,6 +133,50 @@ namespace stdex
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Test if the given code unit is ASCII-white-space
|
||||||
|
///
|
||||||
|
/// \param[in] chr Code unit
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline bool isspace(_In_ T chr)
|
||||||
|
{
|
||||||
|
return chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' || chr == '\v' || chr == '\f';
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Test if the given code unit is ASCII-lower-case-character
|
||||||
|
///
|
||||||
|
/// \param[in] chr Code unit
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline bool islower(_In_ T chr)
|
||||||
|
{
|
||||||
|
return 'a' <= chr && chr <= 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Test if the given code unit is ASCII-upper-case-character
|
||||||
|
///
|
||||||
|
/// \param[in] chr Code unit
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline bool isupper(_In_ T chr)
|
||||||
|
{
|
||||||
|
return 'A' <= chr && chr <= 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Test if the given code unit is ASCII-digit
|
||||||
|
///
|
||||||
|
/// \param[in] chr Code unit
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline bool isdigit(_In_ T chr)
|
||||||
|
{
|
||||||
|
return '0' <= chr && chr <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Return number of code units the glyph represents
|
/// Return number of code units the glyph represents
|
||||||
///
|
///
|
||||||
@ -152,6 +198,32 @@ namespace stdex
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Convert to ASCII-lower-case
|
||||||
|
///
|
||||||
|
/// \param[in] chr Code unit
|
||||||
|
///
|
||||||
|
/// \return Lower-case code unit
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline T tolower(_In_ T chr)
|
||||||
|
{
|
||||||
|
return isupper(chr) ? chr | 0x20 : chr;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Convert to ASCII-upper-case
|
||||||
|
///
|
||||||
|
/// \param[in] chr Code unit
|
||||||
|
///
|
||||||
|
/// \return Upper-case code unit
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline T toupper(_In_ T chr)
|
||||||
|
{
|
||||||
|
return islower(chr) ? chr | ~0x20 : chr;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Calculate zero-terminated string length.
|
/// Calculate zero-terminated string length.
|
||||||
///
|
///
|
||||||
@ -248,15 +320,31 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Reusable standard C++ C-locale
|
/// Checks if string contains all ASCII-white-space
|
||||||
///
|
///
|
||||||
const inline std::locale std_locale_C("C");
|
/// \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 <class T>
|
||||||
|
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
|
/// Checks if string contains all white-space
|
||||||
///
|
///
|
||||||
/// \param[in] str String
|
/// \param[in] str String
|
||||||
/// \param[in] count Code unit count limit
|
/// \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.
|
/// \return `true` if all characters are white-space or `false` when any non-white-space character is found in string.
|
||||||
///
|
///
|
||||||
@ -274,12 +362,35 @@ namespace stdex
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Find a code unit in a string ASCII-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 first occurence of chr code unit or stdex::npos if not found.
|
||||||
|
///
|
||||||
|
template <class T>
|
||||||
|
inline size_t strnichr(
|
||||||
|
_In_reads_or_z_opt_(count) const T* str,
|
||||||
|
_In_ size_t count,
|
||||||
|
_In_ T chr)
|
||||||
|
{
|
||||||
|
_Assume_(str || !count);
|
||||||
|
chr = tolower(chr);
|
||||||
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
|
if (tolower(str[i]) == chr) return i;
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// 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] count Code unit count limit
|
/// \param[in] count Code unit count limit
|
||||||
/// \param[in] chr Code unit to search for
|
/// \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.
|
/// \return Offset to the first occurence of chr code unit or stdex::npos if not found.
|
||||||
///
|
///
|
||||||
@ -298,12 +409,36 @@ namespace stdex
|
|||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Find a code unit in a string ASCII-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)
|
||||||
|
{
|
||||||
|
_Assume_(str || !count);
|
||||||
|
chr = tolower(chr);
|
||||||
|
size_t z = npos;
|
||||||
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
|
if (tolower(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] count Code unit count limit
|
/// \param[in] count Code unit count limit
|
||||||
/// \param[in] chr Code unit to search for
|
/// \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.
|
/// \return Offset to the last occurence of chr code unit or stdex::npos if not found.
|
||||||
///
|
///
|
||||||
@ -400,6 +535,7 @@ namespace stdex
|
|||||||
/// \param[in] count1 String 1 code unit count limit
|
/// \param[in] count1 String 1 code unit count limit
|
||||||
/// \param[in] str2 String 2
|
/// \param[in] str2 String 2
|
||||||
/// \param[in] count2 String 2 code unit count limit
|
/// \param[in] count2 String 2 code unit count limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
///
|
///
|
||||||
@ -415,11 +551,35 @@ namespace stdex
|
|||||||
return collate.compare(str1, str1 + count1, str2, str2 + count2);
|
return collate.compare(str1, str1 + count1, str2, str2 + count2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Binary compare two strings ASCII-case-insensitive
|
||||||
|
///
|
||||||
|
/// \param[in] str1 String 1
|
||||||
|
/// \param[in] str2 String 2
|
||||||
|
///
|
||||||
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
|
///
|
||||||
|
template <class T1, class T2>
|
||||||
|
inline int stricmp(_In_z_ const T1* str1, _In_z_ const T2* str2)
|
||||||
|
{
|
||||||
|
_Assume_(str1);
|
||||||
|
_Assume_(str2);
|
||||||
|
size_t i; T1 a; T2 b;
|
||||||
|
for (i = 0; (a = tolower(str1[i])) | (b = tolower(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 case-insensitive
|
/// Binary compare two strings case-insensitive
|
||||||
///
|
///
|
||||||
/// \param[in] str1 String 1
|
/// \param[in] str1 String 1
|
||||||
/// \param[in] str2 String 2
|
/// \param[in] str2 String 2
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
///
|
///
|
||||||
@ -440,12 +600,37 @@ namespace stdex
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Binary compare two strings ASCII-case-insensitive
|
||||||
|
///
|
||||||
|
/// \param[in] str1 String 1
|
||||||
|
/// \param[in] str2 String 2
|
||||||
|
/// \param[in] count Code unit count limit
|
||||||
|
///
|
||||||
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
|
///
|
||||||
|
template <class T1, class T2>
|
||||||
|
inline int strnicmp(_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 = tolower(str1[i])) | (b = tolower(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;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Binary compare two strings case-insensitive
|
/// Binary compare two strings case-insensitive
|
||||||
///
|
///
|
||||||
/// \param[in] str1 String 1
|
/// \param[in] str1 String 1
|
||||||
/// \param[in] str2 String 2
|
/// \param[in] str2 String 2
|
||||||
/// \param[in] count Code unit count limit
|
/// \param[in] count Code unit count limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
///
|
///
|
||||||
@ -466,6 +651,33 @@ namespace stdex
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Binary compare two strings ASCII-case-insensitive
|
||||||
|
///
|
||||||
|
/// \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
|
||||||
|
///
|
||||||
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
|
///
|
||||||
|
template <class T1, class T2>
|
||||||
|
inline int strnicmp(
|
||||||
|
_In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
|
||||||
|
_In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
|
||||||
|
{
|
||||||
|
_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++) {
|
||||||
|
if (a > b) return +1;
|
||||||
|
if (a < b) return -1;
|
||||||
|
}
|
||||||
|
if (i < count1 && str1[i]) return +1;
|
||||||
|
if (i < count2 && str2[i]) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Binary compare two strings case-insensitive
|
/// Binary compare two strings case-insensitive
|
||||||
///
|
///
|
||||||
@ -473,6 +685,7 @@ namespace stdex
|
|||||||
/// \param[in] count1 String 1 code unit count limit
|
/// \param[in] count1 String 1 code unit count limit
|
||||||
/// \param[in] str2 String 2
|
/// \param[in] str2 String 2
|
||||||
/// \param[in] count2 String 2 code unit count limit
|
/// \param[in] count2 String 2 code unit count limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
/// \return Negative if str1<str2; positive if str1>str2; zero if str1==str2
|
||||||
///
|
///
|
||||||
@ -552,11 +765,39 @@ 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 <class T1, class T2>
|
||||||
|
inline size_t stristr(
|
||||||
|
_In_z_ const T1* str,
|
||||||
|
_In_z_ const T2* sample)
|
||||||
|
{
|
||||||
|
_Assume_(str);
|
||||||
|
_Assume_(sample);
|
||||||
|
for (size_t offset = 0;; ++offset) {
|
||||||
|
for (size_t i = offset, j = 0;; ++i, ++j) {
|
||||||
|
if (!sample[j])
|
||||||
|
return offset;
|
||||||
|
if (!str[i])
|
||||||
|
return npos;
|
||||||
|
if (tolower(str[i]) != tolower(sample[j]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Search for a substring case-insensitive
|
/// 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] 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
|
/// \return Offset inside str where sample string is found; stdex::npos if not found
|
||||||
///
|
///
|
||||||
@ -582,12 +823,42 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Search for a substring ASCII-case-insensitive
|
||||||
|
///
|
||||||
|
/// \param[in] str String to search in
|
||||||
|
/// \param[in] count String code unit count limit
|
||||||
|
/// \param[in] sample Substring to search for
|
||||||
|
///
|
||||||
|
/// \return Offset inside str where sample string is found; stdex::npos if not found
|
||||||
|
///
|
||||||
|
template <class T1, class T2>
|
||||||
|
inline size_t strnistr(
|
||||||
|
_In_reads_or_z_opt_(count) const T1* str,
|
||||||
|
_In_ size_t count,
|
||||||
|
_In_z_ const T2* sample)
|
||||||
|
{
|
||||||
|
_Assume_(str || !count);
|
||||||
|
_Assume_(sample);
|
||||||
|
for (size_t offset = 0;; ++offset) {
|
||||||
|
for (size_t i = offset, j = 0;; ++i, ++j) {
|
||||||
|
if (!sample[j])
|
||||||
|
return offset;
|
||||||
|
if (i >= count || !str[i])
|
||||||
|
return npos;
|
||||||
|
if (tolower(str[i]) != tolower(sample[j]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Search for a substring case-insensitive
|
/// Search for a substring case-insensitive
|
||||||
///
|
///
|
||||||
/// \param[in] str String to search in
|
/// \param[in] str String to search in
|
||||||
/// \param[in] count String code unit count limit
|
/// \param[in] count String code unit count limit
|
||||||
/// \param[in] sample Substring to search for
|
/// \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
|
/// \return Offset inside str where sample string is found; stdex::npos if not found
|
||||||
///
|
///
|
||||||
@ -1386,7 +1657,8 @@ namespace stdex
|
|||||||
if (count) {
|
if (count) {
|
||||||
// Copy from stack.
|
// Copy from stack.
|
||||||
str.append(buf, count);
|
str.append(buf, count);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
for (size_t capacity = 2 * 1024 / sizeof(_Elem);; capacity *= 2) {
|
for (size_t capacity = 2 * 1024 / sizeof(_Elem);; capacity *= 2) {
|
||||||
// Allocate on heap and retry.
|
// Allocate on heap and retry.
|
||||||
auto buf_dyn = std::make_unique<_Elem[]>(capacity);
|
auto buf_dyn = std::make_unique<_Elem[]>(capacity);
|
||||||
@ -1433,13 +1705,25 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Convert string to lower-case character-by-character
|
/// Convert string to ASCII-lower-case character-by-character
|
||||||
///
|
|
||||||
/// \note For legacy code support only.
|
|
||||||
///
|
///
|
||||||
/// \param[in,out] str String
|
/// \param[in,out] str String
|
||||||
///
|
///
|
||||||
template<class T>
|
template<class T>
|
||||||
|
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<class T>
|
||||||
inline void strlwr(_Inout_z_ T* str, _In_ const std::locale& locale)
|
inline void strlwr(_Inout_z_ T* str, _In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
_Assume_(str);
|
_Assume_(str);
|
||||||
@ -1449,14 +1733,27 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Convert string to lower-case character-by-character
|
/// Convert string to ASCII-lower-case character-by-character
|
||||||
///
|
|
||||||
/// \note For legacy code support only.
|
|
||||||
///
|
///
|
||||||
/// \param[in,out] str String
|
/// \param[in,out] str String
|
||||||
/// \param[in] count Code unit limit
|
/// \param[in] count Code unit limit
|
||||||
///
|
///
|
||||||
template<class T>
|
template<class T>
|
||||||
|
inline void strlwr(_Inout_updates_z_(count) T* str, _In_ size_t count)
|
||||||
|
{
|
||||||
|
_Assume_(str || !count);
|
||||||
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
|
str[i] = tolower(str[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Convert string to lower-case character-by-character
|
||||||
|
///
|
||||||
|
/// \param[in,out] str String
|
||||||
|
/// \param[in] count Code unit limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
|
///
|
||||||
|
template<class T>
|
||||||
inline void strlwr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
|
inline void strlwr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
_Assume_(str || !count);
|
_Assume_(str || !count);
|
||||||
@ -1466,13 +1763,25 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Convert string to upper-case character-by-character
|
/// Convert string to ASCII-upper-case character-by-character
|
||||||
///
|
|
||||||
/// \note For legacy code support only.
|
|
||||||
///
|
///
|
||||||
/// \param[in,out] str String
|
/// \param[in,out] str String
|
||||||
///
|
///
|
||||||
template<class T>
|
template<class T>
|
||||||
|
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<class T>
|
||||||
inline void strupr(_Inout_z_ T* str, _In_ const std::locale& locale)
|
inline void strupr(_Inout_z_ T* str, _In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
_Assume_(str);
|
_Assume_(str);
|
||||||
@ -1482,14 +1791,27 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Convert string to upper-case character-by-character
|
/// Convert string to ASCII-upper-case character-by-character
|
||||||
///
|
|
||||||
/// \note For legacy code support only.
|
|
||||||
///
|
///
|
||||||
/// \param[in,out] str String
|
/// \param[in,out] str String
|
||||||
/// \param[in] count Code unit limit
|
/// \param[in] count Code unit limit
|
||||||
///
|
///
|
||||||
template<class T>
|
template<class T>
|
||||||
|
inline void strupr(_Inout_updates_z_(count) T* str, _In_ size_t count)
|
||||||
|
{
|
||||||
|
_Assume_(str || !count);
|
||||||
|
for (size_t i = 0; i < count && str[i]; ++i)
|
||||||
|
str[i] = toupper(str[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Convert string to upper-case character-by-character
|
||||||
|
///
|
||||||
|
/// \param[in,out] str String
|
||||||
|
/// \param[in] count Code unit limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
|
///
|
||||||
|
template<class T>
|
||||||
inline void strupr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
|
inline void strupr(_Inout_updates_z_(count) T* str, _In_ size_t count, _In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
_Assume_(str || !count);
|
_Assume_(str || !count);
|
||||||
@ -1499,13 +1821,24 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Convert string to upper-case character-by-character
|
/// Convert string to ASCII-upper-case character-by-character
|
||||||
///
|
|
||||||
/// \note For legacy code support only.
|
|
||||||
///
|
///
|
||||||
/// \param[in,out] str String
|
/// \param[in,out] str String
|
||||||
///
|
///
|
||||||
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
|
inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < str.size(); ++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<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_ const std::locale& locale)
|
inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_ const std::locale& locale)
|
||||||
{
|
{
|
||||||
const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
|
const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
|
||||||
@ -1513,11 +1846,43 @@ namespace stdex
|
|||||||
str[i] = ctype.toupper(str[i]);
|
str[i] = ctype.toupper(str[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Trim ASCII-whitespace from string start
|
||||||
|
///
|
||||||
|
/// \param[in] str String to trim
|
||||||
|
/// \param[in] count Code unit limit
|
||||||
|
///
|
||||||
|
/// \return Number of code units excluding zero terminator in the string after the operation.
|
||||||
|
///
|
||||||
|
template<class T>
|
||||||
|
inline size_t ltrim(
|
||||||
|
_Inout_z_count_(count) T* str, _In_ size_t count)
|
||||||
|
{
|
||||||
|
for (size_t i = 0;; ++i) {
|
||||||
|
if (i >= count) {
|
||||||
|
if (count) str[0] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!str[i]) {
|
||||||
|
str[0] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!isspace(str[i])) {
|
||||||
|
if (!i)
|
||||||
|
return strnlen(str, count);
|
||||||
|
size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
|
||||||
|
str[n] = 0;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trim whitespace from string start
|
/// Trim whitespace from string start
|
||||||
///
|
///
|
||||||
/// \param[in] str String to trim
|
/// \param[in] str String to trim
|
||||||
/// \param[in] count Code unit limit
|
/// \param[in] count Code unit limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Number of code units excluding zero terminator in the string after the operation.
|
/// \return Number of code units excluding zero terminator in the string after the operation.
|
||||||
///
|
///
|
||||||
@ -1546,10 +1911,27 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Trim ASCII-whitespace from string start
|
||||||
|
///
|
||||||
|
/// \param[in,out] s String to trim
|
||||||
|
///
|
||||||
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
|
inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
|
||||||
|
{
|
||||||
|
s.erase(
|
||||||
|
s.begin(),
|
||||||
|
std::find_if(
|
||||||
|
s.begin(),
|
||||||
|
s.end(),
|
||||||
|
[&](_In_ _Elem ch) { return !isspace(ch); }));
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trim whitespace from string start
|
/// Trim whitespace from string start
|
||||||
///
|
///
|
||||||
/// \param[in,out] s String to trim
|
/// \param[in,out] s String to trim
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_ const std::locale& locale)
|
inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_ const std::locale& locale)
|
||||||
@ -1560,7 +1942,31 @@ namespace stdex
|
|||||||
std::find_if(
|
std::find_if(
|
||||||
s.begin(),
|
s.begin(),
|
||||||
s.end(),
|
s.end(),
|
||||||
[&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
|
[&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); }));
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Trim ASCII-whitespace from string end
|
||||||
|
///
|
||||||
|
/// \param[in] str String to trim
|
||||||
|
/// \param[in] count Code unit limit
|
||||||
|
///
|
||||||
|
/// \return Number of code units excluding zero terminator in the string after the operation.
|
||||||
|
///
|
||||||
|
template<class T>
|
||||||
|
inline size_t rtrim(
|
||||||
|
_Inout_z_count_(count) T* str, _In_ size_t count)
|
||||||
|
{
|
||||||
|
for (size_t i = 0, j = 0;;) {
|
||||||
|
if (i >= count || !str[i]) {
|
||||||
|
if (j < count) str[j] = 0;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
if (!isspace(str[i]))
|
||||||
|
j = ++i;
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -1568,6 +1974,7 @@ namespace stdex
|
|||||||
///
|
///
|
||||||
/// \param[in] str String to trim
|
/// \param[in] str String to trim
|
||||||
/// \param[in] count Code unit limit
|
/// \param[in] count Code unit limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Number of code units excluding zero terminator in the string after the operation.
|
/// \return Number of code units excluding zero terminator in the string after the operation.
|
||||||
///
|
///
|
||||||
@ -1589,10 +1996,27 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Trim ASCII-whitespace from string end
|
||||||
|
///
|
||||||
|
/// \param[in,out] s String to trim
|
||||||
|
///
|
||||||
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
|
static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
|
||||||
|
{
|
||||||
|
s.erase(
|
||||||
|
std::find_if(
|
||||||
|
s.rbegin(),
|
||||||
|
s.rend(),
|
||||||
|
[&](_In_ _Elem ch) { return !isspace(ch); }).base(),
|
||||||
|
s.end());
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trim whitespace from string end
|
/// Trim whitespace from string end
|
||||||
///
|
///
|
||||||
/// \param[in,out] s String to trim
|
/// \param[in,out] s String to trim
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_ const std::locale& locale)
|
static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_ const std::locale& locale)
|
||||||
@ -1602,15 +2026,31 @@ namespace stdex
|
|||||||
std::find_if(
|
std::find_if(
|
||||||
s.rbegin(),
|
s.rbegin(),
|
||||||
s.rend(),
|
s.rend(),
|
||||||
[&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
|
[&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
|
||||||
s.end());
|
s.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Trim ASCII-whitespace from string start and end
|
||||||
|
///
|
||||||
|
/// \param[in] str String to trim
|
||||||
|
/// \param[in] count Code unit limit
|
||||||
|
///
|
||||||
|
/// \return Number of code units excluding zero terminator in the string after the operation.
|
||||||
|
///
|
||||||
|
template<class T>
|
||||||
|
inline size_t trim(
|
||||||
|
_Inout_z_count_(count) T* str, _In_ size_t count)
|
||||||
|
{
|
||||||
|
return ltrim(str, rtrim(str, count));
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trim whitespace from string start and end
|
/// Trim whitespace from string start and end
|
||||||
///
|
///
|
||||||
/// \param[in] str String to trim
|
/// \param[in] str String to trim
|
||||||
/// \param[in] count Code unit limit
|
/// \param[in] count Code unit limit
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
///
|
///
|
||||||
/// \return Number of code units excluding zero terminator in the string after the operation.
|
/// \return Number of code units excluding zero terminator in the string after the operation.
|
||||||
///
|
///
|
||||||
@ -1623,25 +2063,50 @@ namespace stdex
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Trim whitespace from string start and end
|
/// Trim ASCII-whitespace from string start and end
|
||||||
///
|
///
|
||||||
/// \param[in,out] s String to trim
|
/// \param[in,out] s String to trim
|
||||||
///
|
///
|
||||||
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_ const std::locale& locale)
|
static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
|
||||||
{
|
{
|
||||||
const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
|
auto nonspace = [&](_In_ _Elem ch) { return !isspace(ch); };
|
||||||
s.erase(
|
s.erase(
|
||||||
s.begin(),
|
s.begin(),
|
||||||
std::find_if(
|
std::find_if(
|
||||||
s.begin(),
|
s.begin(),
|
||||||
s.end(),
|
s.end(),
|
||||||
[&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
|
nonspace));
|
||||||
s.erase(
|
s.erase(
|
||||||
std::find_if(
|
std::find_if(
|
||||||
s.rbegin(),
|
s.rbegin(),
|
||||||
s.rend(),
|
s.rend(),
|
||||||
[&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
|
nonspace).base(),
|
||||||
|
s.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Trim whitespace from string start and end
|
||||||
|
///
|
||||||
|
/// \param[in,out] s String to trim
|
||||||
|
/// \param[in] locale C++ locale to use
|
||||||
|
///
|
||||||
|
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
|
||||||
|
static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_ const std::locale& locale)
|
||||||
|
{
|
||||||
|
const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
|
||||||
|
auto nonspace = [&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); };
|
||||||
|
s.erase(
|
||||||
|
s.begin(),
|
||||||
|
std::find_if(
|
||||||
|
s.begin(),
|
||||||
|
s.end(),
|
||||||
|
nonspace));
|
||||||
|
s.erase(
|
||||||
|
std::find_if(
|
||||||
|
s.rbegin(),
|
||||||
|
s.rend(),
|
||||||
|
nonspace).base(),
|
||||||
s.end());
|
s.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ namespace stdex
|
|||||||
struct charset_less {
|
struct charset_less {
|
||||||
inline bool operator()(_In_z_ const char* a, _In_z_ const char* b) const
|
inline bool operator()(_In_z_ const char* a, _In_z_ const char* b) const
|
||||||
{
|
{
|
||||||
return stdex::stricmp(a, b, stdex::std_locale_C) < 0;
|
return stdex::stricmp(a, b) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static const std::map<const char*, charset_id, charset_less> charsets = {
|
static const std::map<const char*, charset_id, charset_less> charsets = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user