Initial string_view for set_name, set_value

This commit is contained in:
halx99 2021-09-29 10:37:52 +08:00
parent 9e382f9807
commit 15697a7b86
2 changed files with 163 additions and 12 deletions

View File

@ -5320,18 +5320,18 @@ namespace pugi
} }
#endif #endif
PUGI__FN bool xml_attribute::set_name(const char_t* rhs) PUGI__FN bool xml_attribute::set_name(string_view rhs)
{ {
if (!_attr) return false; if (!_attr) return false;
return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs.data(), rhs.length());
} }
PUGI__FN bool xml_attribute::set_value(const char_t* rhs) PUGI__FN bool xml_attribute::set_value(string_view rhs)
{ {
if (!_attr) return false; if (!_attr) return false;
return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs.data(), rhs.length());
} }
PUGI__FN bool xml_attribute::set_value(int rhs) PUGI__FN bool xml_attribute::set_value(int rhs)
@ -5674,24 +5674,24 @@ namespace pugi
return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node();
} }
PUGI__FN bool xml_node::set_name(const char_t* rhs) PUGI__FN bool xml_node::set_name(string_view rhs)
{ {
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
if (type_ != node_element && type_ != node_pi && type_ != node_declaration) if (type_ != node_element && type_ != node_pi && type_ != node_declaration)
return false; return false;
return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs.data(), rhs.length());
} }
PUGI__FN bool xml_node::set_value(const char_t* rhs) PUGI__FN bool xml_node::set_value(string_view rhs)
{ {
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype)
return false; return false;
return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs.data(), rhs.length());
} }
PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_)

View File

@ -38,6 +38,16 @@
# include <string> # include <string>
#endif #endif
#if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && ((defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (defined(_MSVC_LANG) && (_MSVC_LANG > 201402L))))
#ifndef PUGI_CXX17_FEATURES
#define PUGI_CXX17_FEATURES 1
#endif // C++17 features macro
#endif // C++17 features check
#if defined(PUGI_CXX17_FEATURES) && PUGI_CXX17_FEATURES
#include <string_view>
#endif // C++17 features
// Macro for deprecated features // Macro for deprecated features
#ifndef PUGIXML_DEPRECATED #ifndef PUGIXML_DEPRECATED
# if defined(__GNUC__) # if defined(__GNUC__)
@ -140,6 +150,147 @@ namespace pugi
#endif #endif
} }
// string_view
namespace pugi {
#if defined(PUGI_CXX17_FEATURES) && PUGI_CXX17_FEATURES
template <typename C, typename T = std::char_traits<C>>
using basic_string_view = std::basic_string_view<C, T>;
typedef std::string_view string_view;
typedef std::wstring_view wstring_view;
typedef std::u16string_view u16string_view;
typedef std::u32string_view u32string_view;
typedef std::hash<std::string_view> string_view_hash;
#else
template <typename Char, typename Traits = std::char_traits<Char>>
struct basic_string_view {
std::size_t s;
const Char* p;
basic_string_view(const std::string& r)
: basic_string_view(r.data(), r.size()) {
}
basic_string_view(const Char* ptr)
: basic_string_view(ptr, Traits::length(ptr)) {
}
basic_string_view(const Char* ptr, std::size_t sz)
: s(sz), p(ptr) {
}
static int compare(const Char* lhs_p, std::size_t lhs_sz, const Char* rhs_p, std::size_t rhs_sz) {
int result = Traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz);
if (result != 0)
return result;
if (lhs_sz < rhs_sz)
return -1;
if (lhs_sz > rhs_sz)
return 1;
return 0;
}
const Char* begin() const {
return p;
}
const Char* end() const {
return p + s;
}
const Char* cbegin() const {
return p;
}
const Char* cend() const {
return p + s;
}
const Char* data() const {
return p;
}
std::size_t size() const {
return s;
}
std::size_t length() const {
return size();
}
operator std::basic_string<Char, Traits>() const {
return std::basic_string<Char, Traits>(data(), size());
}
bool operator==(const basic_string_view& r) const {
return compare(p, s, r.data(), r.size()) == 0;
}
bool operator==(const Char* r) const {
return compare(r, Traits::length(r), p, s) == 0;
}
bool operator==(const std::basic_string<Char, Traits>& r) const {
return compare(r.data(), r.size(), p, s) == 0;
}
bool operator!=(const basic_string_view& r) const {
return !(*this == r);
}
bool operator!=(const char* r) const {
return !(*this == r);
}
bool operator!=(const std::basic_string<Char, Traits>& r) const {
return !(*this == r);
}
};
template <typename Ch, typename Tr = std::char_traits<Ch>>
struct basic_string_view_hash {
typedef basic_string_view<Ch, Tr> argument_type;
typedef std::size_t result_type;
template <typename Al>
result_type operator()(const std::basic_string<Ch, Tr, Al>& r) const {
return (*this)(argument_type(r.c_str(), r.size()));
}
result_type operator()(const argument_type& r) const {
#if defined(SOL_USE_BOOST) && SOL_USE_BOOST
return boost::hash_range(r.begin(), r.end());
#else
// Modified, from libstdc++
// An implementation attempt at Fowler No Voll, 1a.
// Supposedly, used in MSVC,
// GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...?
// But, well. Can't win them all, right?
// This should normally only apply when NOT using boost,
// so this should almost never be tapped into...
std::size_t hash = 0;
const unsigned char* cptr = reinterpret_cast<const unsigned char*>(r.data());
for (std::size_t sz = r.size(); sz != 0; --sz) {
hash ^= static_cast<size_t>(*cptr++);
hash *= static_cast<size_t>(1099511628211ULL);
}
return hash;
#endif
}
};
} // namespace pugi
namespace std {
template <typename Ch, typename Tr>
struct hash< ::pugi::basic_string_view<Ch, Tr> > : ::pugi::basic_string_view_hash<Ch, Tr> {};
} // namespace std
namespace pugi {
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
using string_view_hash = std::hash<string_view>;
#endif
} // namespace pugi
// The PugiXML namespace // The PugiXML namespace
namespace pugi namespace pugi
{ {
@ -415,8 +566,8 @@ namespace pugi
bool as_bool(bool def = false) const; bool as_bool(bool def = false) const;
// Set attribute name/value (returns false if attribute is empty or there is not enough memory) // Set attribute name/value (returns false if attribute is empty or there is not enough memory)
bool set_name(const char_t* rhs); bool set_name(string_view rhs);
bool set_value(const char_t* rhs); bool set_value(string_view rhs);
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
bool set_value(int rhs); bool set_value(int rhs);
@ -549,8 +700,8 @@ namespace pugi
const char_t* child_value(const char_t* name) const; const char_t* child_value(const char_t* name) const;
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
bool set_name(const char_t* rhs); bool set_name(string_view rhs);
bool set_value(const char_t* rhs); bool set_value(string_view rhs);
// Add attribute with specified name. Returns added attribute, or empty attribute on errors. // Add attribute with specified name. Returns added attribute, or empty attribute on errors.
xml_attribute append_attribute(const char_t* name); xml_attribute append_attribute(const char_t* name);