- Fixed several memory errors
This commit is contained in:
@@ -16,8 +16,8 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_LANGPROC_wstringS_wstring_H
|
||||
#define FENNEC_LANGPROC_wstringS_wstring_H
|
||||
#ifndef FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||
#define FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||
|
||||
#include <fennec/langproc/strings/detail/_ctype.h>
|
||||
#include <fennec/langproc/strings/wcstring.h>
|
||||
@@ -59,110 +59,126 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with null characters
|
||||
/// \param n the number of characters
|
||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
||||
/// \param n the number of wchar_tacters
|
||||
/// \param c the wchar_tacter to fill with
|
||||
///
|
||||
/// \details adds additional character for null termination.
|
||||
constexpr _wstring(size_t n)
|
||||
: _wstring('\0', n) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` filled with the character `c`
|
||||
/// \param c the characters to fill with
|
||||
/// \param n the number of characters
|
||||
///
|
||||
/// \details adds additional character for null termination.
|
||||
constexpr _wstring(wchar_t c, size_t n)
|
||||
/// \details adds additional wchar_tacter for null termination.
|
||||
constexpr _wstring(size_t n, wchar_t c = '\0')
|
||||
: _str(n + 1) {
|
||||
fennec::wmemset(_str.data(), c, n); _str[n] = '\0';
|
||||
fennec::wmemset(_str, c, n);
|
||||
}
|
||||
|
||||
constexpr _wstring(const alloc_t& alloc)
|
||||
: _str(alloc) {
|
||||
}
|
||||
|
||||
constexpr _wstring(size_t n, wchar_t c, const alloc_t& alloc)
|
||||
: _str(n + 1, alloc) {
|
||||
fennec::wmemset(_str, c, n);
|
||||
}
|
||||
|
||||
constexpr _wstring(const wcstring& cstr)
|
||||
: _str(cstr, cstr.size() + 1) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Copy Constructor
|
||||
/// \param str the buffer to copy
|
||||
/// \param len number of characters in the buffer
|
||||
///
|
||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
||||
constexpr _wstring(const wchar_t* str, size_t n)
|
||||
: _str(str, n + 1) {
|
||||
::wcsncpy(_str.data(), str, n);
|
||||
_str[n] = '\0';
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||
/// \param str the buffer to wrap
|
||||
/// \tparam n the number of wchar_tacters in the buffer including the null-terminator, if present
|
||||
template<size_t n>
|
||||
explicit constexpr _wstring(const wchar_t (&str)[n])
|
||||
: _str(str[n - 1] != '\0' ? n + 1 : n) {
|
||||
fennec::wmemcpy(_str, str, n);
|
||||
if (str[n - 1] != '\0') {
|
||||
_str[n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Copy Constructor
|
||||
/// \param str the buffer to copy
|
||||
/// \param len number of characters in the buffer
|
||||
///
|
||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
||||
constexpr _wstring(const wcstring& str)
|
||||
: _str(str, str.size() + 1) {
|
||||
_str[str.size()] = '\0';
|
||||
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||
/// \param str the buffer to wrap
|
||||
/// \param n the number of wchar_tacters in the buffer including the null-terminator, if present
|
||||
constexpr _wstring(const wchar_t* buf, size_t n)
|
||||
: _str(buf[n - 1] != '\0' ? n + 1 : n) {
|
||||
fennec::wmemcpy(_str, buf, n);
|
||||
if (buf[n - 1] != '\0') {
|
||||
_str[n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Copy Constructor
|
||||
/// \param str the string to copy
|
||||
constexpr _wstring(const wstring& str)
|
||||
: _wstring(str, str.size() - 1) {
|
||||
}
|
||||
|
||||
constexpr _wstring(_wstring&& str) noexcept
|
||||
: _str(fennec::move(str._str)) {
|
||||
}
|
||||
constexpr _wstring(const _wstring& str) = default;
|
||||
|
||||
///
|
||||
/// \brief String Destructor, cleans up the underlying allocation
|
||||
constexpr ~_wstring() = default; // allocation cleans up itself
|
||||
/// \brief String Move Constructor
|
||||
/// \param str the string to take ownership of
|
||||
constexpr _wstring(_wstring&& str) noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief Destructor, cleans up underlying allocation
|
||||
constexpr ~_wstring() = default;
|
||||
|
||||
// Assignment ==========================================================================================================
|
||||
|
||||
constexpr _wstring& operator=(const wcstring& cstr) {
|
||||
_str.callocate(cstr.capacity());
|
||||
fennec::wmemcpy(_str, cstr, cstr.capacity());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr _wstring& operator=(const _wstring& str) = default;
|
||||
constexpr _wstring& operator=(_wstring&& str) noexcept = default;
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \returns The size of the string excluding null terminator
|
||||
constexpr size_t size() const {
|
||||
return _str.capacity() - 1;
|
||||
return _str.capacity() > 0 ? _str.capacity() - 1 : 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The size of the string including null terminator
|
||||
constexpr size_t capacity() const {
|
||||
return _str.capacity();
|
||||
}
|
||||
|
||||
constexpr bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a reference to the character
|
||||
constexpr wchar_t& operator[](int i) {
|
||||
/// \returns a reference to the wchar_tacter
|
||||
constexpr wchar_t& operator[](size_t i) {
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const-Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a copy of the character
|
||||
constexpr wchar_t operator[](int i) const {
|
||||
assertd(i >= 0 && i < size(), "Array Out of Bounds");
|
||||
/// \returns a copy of the wchar_tacter
|
||||
constexpr const wchar_t& operator[](size_t i) const {
|
||||
return _str[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Dereference Operator
|
||||
/// \returns A const qualified pointer to the underlying allocation
|
||||
constexpr const wchar_t* operator*() const {
|
||||
return _str.data();
|
||||
constexpr wchar_t* data() {
|
||||
return _str;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Implicit Dereference Cast
|
||||
constexpr operator const wchar_t*() const {
|
||||
return _str.data();
|
||||
constexpr const wchar_t* data() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
constexpr const wchar_t* cstr() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
// Examination =========================================================================================================
|
||||
|
||||
@@ -183,7 +199,7 @@ public:
|
||||
}
|
||||
n = fennec::min(n, fennec::max(_str, str.size()) + 1);
|
||||
|
||||
return ::wcsncmp(_str.data() + i, str, n);
|
||||
return ::wcsncmp(_str + i, str, n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -191,13 +207,13 @@ public:
|
||||
/// \param ostr the string to compare against
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const wstring& str, size_t i = 0, size_t n = npos) const {
|
||||
constexpr int compare(const _wstring& str, size_t i = 0, size_t n = npos) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return -1;
|
||||
}
|
||||
n = min(n, max(size(), str.size()) + 1);
|
||||
|
||||
return ::wcsncmp(_str.data() + i, str, n);
|
||||
return ::wcsncmp(_str + i, str.data(), n);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const _wstring& str) const {
|
||||
@@ -206,22 +222,22 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||
/// \param c the character to find
|
||||
/// \param c the wchar_tacter to find
|
||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
||||
if (i >= size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
|
||||
const wchar_t* loc = ::wcschr(_str.data() + i, c); // get location using strchr
|
||||
return loc ? loc - _str.data() : size(); // return size if not found
|
||||
const wchar_t* loc = ::wcschr(_str + i, c); // get location using strchr
|
||||
return loc ? loc - _str : size(); // return size if not found
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||
/// \param str the string to find
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t find(const wstring& str, size_t i = 0) const { // bounds check
|
||||
constexpr size_t find(const _wstring& str, size_t i = 0) const { // bounds check
|
||||
if (i >= size()) { // bounds check
|
||||
return size();
|
||||
}
|
||||
@@ -287,7 +303,7 @@ public:
|
||||
/// \param str the string to find
|
||||
/// \param i the index to start at
|
||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
||||
constexpr size_t rfind(const wstring& str, size_t i = npos) const {
|
||||
constexpr size_t rfind(const string& str, size_t i = npos) const {
|
||||
if (size() == 0) {
|
||||
return size();
|
||||
}
|
||||
@@ -303,116 +319,119 @@ public:
|
||||
return size(); // base case
|
||||
}
|
||||
|
||||
// Manipulation ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Resize the string, filling additional bytes with `'\0'`
|
||||
/// \param n the new size of the string
|
||||
constexpr void resize(size_t n) {
|
||||
size_t i = size();
|
||||
_str.reallocate(n + 1);
|
||||
if (n > i) fennec::wmemset(_str.data() + i, L'\0', n - i);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param str the string to copy
|
||||
/// \returns a reference to `this`
|
||||
constexpr wstring& operator=(const wcstring& str) {
|
||||
if (str.empty()) {
|
||||
_str.deallocate();
|
||||
return *this;
|
||||
}
|
||||
if (str.size() > size()) resize(str.size());
|
||||
fennec::wmemcpy(_str.data(), str, str.size());
|
||||
_str[str.size()] = L'\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param str the string to copy
|
||||
/// \returns a reference to `this`
|
||||
constexpr wstring& operator=(const wstring& str) {
|
||||
if (str.size() > size()) resize(str.size());
|
||||
fennec::wmemcpy(_str.data(), str, str.size());
|
||||
_str[str.size()] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Assignment Operator
|
||||
/// \param str the string to move
|
||||
/// \returns a reference to `this`
|
||||
constexpr wstring& operator=(wstring&& str) noexcept {
|
||||
_str = fennec::move(str._str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Retrieve a substring of a string
|
||||
/// \param i the start index
|
||||
/// \param n the number of characters
|
||||
/// \param n the number of wchar_tacters
|
||||
/// \return
|
||||
constexpr wstring substring(size_t i, size_t n = npos) const {
|
||||
constexpr _wstring substring(size_t i, size_t n = npos) const {
|
||||
if (i >= size()) {
|
||||
return wstring("");
|
||||
return _wstring("");
|
||||
}
|
||||
n = min(n, size() - i);
|
||||
return wstring(_str.data() + i, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Returns a string with `c` appended to it
|
||||
/// \param c
|
||||
/// \returns
|
||||
constexpr wstring operator+(wchar_t c) const {
|
||||
// Copy contents with one additional byte.
|
||||
wstring res(_str, _str.size());
|
||||
res[size()] = c; // Set the last character to c
|
||||
n = fennec::min(n, size() - i);
|
||||
_wstring res;
|
||||
res._str.callocate(n + 1);
|
||||
fennec::wmemcpy(res.data(), _str + i, n);
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr wstring operator+(const wcstring& str) const {
|
||||
wstring res(size() + str.size()); // Make a new string with the size of this + str
|
||||
fennec::wmemcpy(&res[0], _str.data(), size()); // Copy the contents of this
|
||||
fennec::wmemcpy(&res[size()], str, str.size()); // Append the contents of str
|
||||
|
||||
|
||||
// Modifiers ===========================================================================================================
|
||||
|
||||
constexpr void resize(size_t n) {
|
||||
_str.creallocate(n + 1);
|
||||
_str[size()] = '\0';
|
||||
}
|
||||
|
||||
constexpr _wstring operator+(wchar_t c) const {
|
||||
if (_str == nullptr) {
|
||||
return _wstring(1, c);
|
||||
}
|
||||
_wstring res;
|
||||
res._str.callocate(capacity() + 1);
|
||||
fennec::wmemcpy(res.data(), _str, size());
|
||||
res[size()] = c;
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr wstring operator+(const wstring& str) const {
|
||||
wstring res(size() + str.size()); // Make a new string with the size of this + str
|
||||
fennec::wmemcpy(&res[0], _str.data(), size()); // Copy the contents of this
|
||||
fennec::wmemcpy(&res[size()], str, str.size()); // Append the contents of str
|
||||
friend constexpr _wstring operator+(wchar_t c, const _wstring& str) {
|
||||
_wstring res(1, c);
|
||||
return res += str;
|
||||
}
|
||||
|
||||
constexpr _wstring operator+(const wcstring& cstr) const {
|
||||
if (_str == nullptr) {
|
||||
return _wstring(cstr);
|
||||
}
|
||||
_wstring res;
|
||||
res._str.callocate(size() + cstr.size() + 1);
|
||||
fennec::wmemcpy(res.data(), _str, size());
|
||||
fennec::wmemcpy(res.data() + size(), cstr, cstr.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr wstring& operator+=(wchar_t c) {
|
||||
size_t x = size();
|
||||
resize(x + 1);
|
||||
_str[x] = c;
|
||||
constexpr _wstring operator+(const _wstring& str) const {
|
||||
if (_str == nullptr) {
|
||||
return _wstring(str);
|
||||
}
|
||||
if (str.data() == nullptr) {
|
||||
return _wstring(*this);
|
||||
}
|
||||
_wstring res;
|
||||
res._str.callocate(size() + str.size() + 1);
|
||||
fennec::wmemcpy(res.data(), _str, size());
|
||||
fennec::wmemcpy(res.data() + size(), str.data(), str.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr _wstring& operator+=(wchar_t c) {
|
||||
if (_str == nullptr) {
|
||||
_str.callocate(2);
|
||||
_str[0] = c;
|
||||
return *this;
|
||||
}
|
||||
_str.creallocate(capacity() + 1);
|
||||
_str[size() - 1] = c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr wstring& operator+=(const wcstring& str) {
|
||||
size_t x = size();
|
||||
resize(x + str.size());
|
||||
fennec::wmemcpy(&_str[x], str, str.size());
|
||||
constexpr _wstring& operator+=(const wcstring& cstr) {
|
||||
if (_str == nullptr) {
|
||||
return *this = cstr;
|
||||
}
|
||||
size_t middle = size();
|
||||
_str.creallocate(middle + cstr.size() + 1);
|
||||
fennec::wmemcpy(_str + middle, cstr, cstr.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr wstring& operator+=(const wstring& str) {
|
||||
size_t x = size();
|
||||
resize(x + str.size());
|
||||
fennec::wmemcpy(&_str[x], str, str.size());
|
||||
constexpr _wstring& operator+=(const _wstring& str) {
|
||||
if (_str == nullptr) {
|
||||
return *this = str;
|
||||
}
|
||||
if (str.data() == nullptr) {
|
||||
return *this;
|
||||
}
|
||||
size_t middle = size();
|
||||
_str.creallocate(middle + str.size() + 1);
|
||||
fennec::wmemcpy(_str + middle, str.data(), str.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
alloc_t _str;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<wstring> : hash<byte_array> {
|
||||
constexpr size_t operator()(const string& str) const {
|
||||
return hash<byte_array>::operator()(byte_array(str.data(), str.size()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // FENNEC_LANGPROC_wstringS_wstring_H
|
||||
#endif // FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||
|
||||
Reference in New Issue
Block a user