- Fixed several memory errors
This commit is contained in:
@@ -208,6 +208,7 @@ add_library(fennec STATIC
|
|||||||
# EXTRA SOURCES ========================================================================================================
|
# EXTRA SOURCES ========================================================================================================
|
||||||
|
|
||||||
${FENNEC_EXTRA_SOURCES}
|
${FENNEC_EXTRA_SOURCES}
|
||||||
|
include/fennec/containers/variant.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(fennec metaprogramming)
|
add_dependencies(fennec metaprogramming)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class CStringPrinter:
|
|||||||
return 'string'
|
return 'string'
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
value = "\"" + self.val['_str'].string('', 'replace', self.val['_size'] - 1) + "\""
|
value = "\"" + self.val['_str'].string('', 'replace', self.val['_size']) + "\""
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def display_hint(self):
|
def display_hint(self):
|
||||||
|
|||||||
@@ -528,7 +528,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
allocation<elem_t, alloc_t> _table;
|
allocation<node, alloc_t> _table;
|
||||||
dynarray<size_t> _freed;
|
dynarray<size_t> _freed;
|
||||||
size_t _root, _last, _size;
|
size_t _root, _last, _size;
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Implicit Boolean Check, returns `true` when there is a value contained
|
/// \brief Implicit Boolean Check, returns `true` when there is a value contained
|
||||||
constexpr explicit operator bool() const {
|
constexpr operator bool() const {
|
||||||
return _set;
|
return _set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The next node id were `insert` or `emplace` to be called
|
/// \returns The next node id were `insert` or `emplace` to be called
|
||||||
constexpr size_t next_free() const {
|
constexpr size_t next_id() const {
|
||||||
size_t i = _size;
|
size_t i = _size;
|
||||||
if (not _freed.empty()) {
|
if (not _freed.empty()) {
|
||||||
i = _freed.front();
|
i = _freed.front();
|
||||||
@@ -418,7 +418,10 @@ public:
|
|||||||
OrderT order;
|
OrderT order;
|
||||||
i = order(*this, i);
|
i = order(*this, i);
|
||||||
while (i != npos) {
|
while (i != npos) {
|
||||||
uint8_t mode = visit(*_table[i].value, i);
|
uint8_t mode = traversal_control_continue;
|
||||||
|
if (_table[i].value) {
|
||||||
|
mode = visit(*_table[i].value, i);
|
||||||
|
}
|
||||||
if (mode == traversal_control_break) {
|
if (mode == traversal_control_break) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ public:
|
|||||||
|
|
||||||
// Check the first element;
|
// Check the first element;
|
||||||
if (_alloc[i].psl >= psl && _alloc[i].value) {
|
if (_alloc[i].psl >= psl && _alloc[i].value) {
|
||||||
if (*_alloc[i].value == val) {
|
if (_equal(*_alloc[i].value, val)) {
|
||||||
return iterator(this, i);
|
return iterator(this, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,13 +230,13 @@ public:
|
|||||||
bool c0 = p0 >= 0 && _alloc[i0].psl >= p0, c1 = _alloc[i1].psl >= p1; // Check that we are in range
|
bool c0 = p0 >= 0 && _alloc[i0].psl >= p0, c1 = _alloc[i1].psl >= p1; // Check that we are in range
|
||||||
|
|
||||||
if (c0 && _alloc[i0].value) {
|
if (c0 && _alloc[i0].value) {
|
||||||
if (*_alloc[i0].value == val) {
|
if (_equal(*_alloc[i0].value, val)) {
|
||||||
return iterator(this, i0);
|
return iterator(this, i0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c1 && _alloc[i1].value) {
|
if (c1 && _alloc[i1].value) {
|
||||||
if (*_alloc[i1].value == val) {
|
if (_equal(*_alloc[i1].value, val)) {
|
||||||
return iterator(this, i1);
|
return iterator(this, i1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
include/fennec/containers/variant.h
Normal file
34
include/fennec/containers/variant.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// fennec, a free and open source game engine
|
||||||
|
// Copyright © 2025 Medusa Slockbower
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file variant.h
|
||||||
|
/// \brief Contains the definition for a structure that holds a single value from multiple types
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_CONTAINERS_VARIANT_H
|
||||||
|
#define FENNEC_CONTAINERS_VARIANT_H
|
||||||
|
|
||||||
|
#endif // FENNEC_CONTAINERS_VARIANT_H
|
||||||
@@ -248,7 +248,7 @@ public:
|
|||||||
bool eof() const;
|
bool eof() const;
|
||||||
|
|
||||||
|
|
||||||
// Read Operations =====================================================================================================
|
// Binary Read Operations ==============================================================================================
|
||||||
|
|
||||||
char getc();
|
char getc();
|
||||||
wchar_t getwc();
|
wchar_t getwc();
|
||||||
@@ -269,7 +269,7 @@ public:
|
|||||||
wstring getwline();
|
wstring getwline();
|
||||||
|
|
||||||
|
|
||||||
// Write Operations ====================================================================================================
|
// Binary Write Operations =============================================================================================
|
||||||
|
|
||||||
bool putc(char c);
|
bool putc(char c);
|
||||||
bool putwc(wchar_t c);
|
bool putwc(wchar_t c);
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const string& str() const { return _str; }
|
const string& str() const { return _str; }
|
||||||
|
const char* cstr() const { return _str.cstr(); }
|
||||||
|
|
||||||
bool empty() {
|
bool empty() {
|
||||||
size_t size = _str.size();
|
size_t size = _str.size();
|
||||||
@@ -195,7 +196,7 @@ public:
|
|||||||
|
|
||||||
while (not parse.empty()) {
|
while (not parse.empty()) {
|
||||||
// Handle dots
|
// Handle dots
|
||||||
while (parse._str[0] == '.') {
|
while (not parse.empty() && parse._str[0] == '.') {
|
||||||
// Check for ".."
|
// Check for ".."
|
||||||
if (parse._str[1] == '.') {
|
if (parse._str[1] == '.') {
|
||||||
// ".."
|
// ".."
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ public:
|
|||||||
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
|
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
|
||||||
constexpr size_t size() const { return _size; }
|
constexpr size_t size() const { return _size; }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the size of the string including its null terminator, i.e. `(*str)[capacity() - 1] == '\0'`
|
||||||
|
constexpr size_t capacity() const { return _size + 1; }
|
||||||
|
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _cstr == nullptr || _size == 0;
|
return _cstr == nullptr || _size == 0;
|
||||||
}
|
}
|
||||||
@@ -198,9 +202,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Dereference Operator
|
/// \brief Data Access
|
||||||
/// \returns A const qualified pointer to the underlying allocation
|
/// \returns A const qualified pointer to the underlying allocation
|
||||||
constexpr const char* operator*() const {
|
constexpr char* data() {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Data Access
|
||||||
|
/// \returns A const qualified pointer to the underlying allocation
|
||||||
|
constexpr const char* data() const {
|
||||||
return _cstr;
|
return _cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,8 +341,8 @@ private:
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct hash<cstring> : hash<byte_array> {
|
struct hash<cstring> : hash<byte_array> {
|
||||||
constexpr size_t operator()(const cstring& str) {
|
constexpr size_t operator()(const cstring& str) const {
|
||||||
return hash<byte_array>::operator()(byte_array(*str, str.size()));
|
return hash<byte_array>::operator()(byte_array(str, str.size()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -59,114 +59,104 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with null characters
|
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
||||||
/// \param n the number of characters
|
/// \param n the number of characters
|
||||||
///
|
|
||||||
/// \details adds additional character for null termination.
|
|
||||||
constexpr _string(size_t n)
|
|
||||||
: _string('\0', n) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Sized Constructor, initializes a null-terminated string of size `n` filled with the character `c`
|
|
||||||
/// \param c the character to fill with
|
/// \param c the character to fill with
|
||||||
/// \param n the number of characters
|
|
||||||
///
|
///
|
||||||
/// \details adds additional character for null termination.
|
/// \details adds additional character for null termination.
|
||||||
constexpr _string(char c, size_t n)
|
constexpr _string(size_t n, char c = '\0')
|
||||||
: _str(n + 1) {
|
: _str(n + 1) {
|
||||||
fennec::memset(_str.data(), c, n);
|
fennec::memset(_str, c, n);
|
||||||
_str[n] = '\0';
|
}
|
||||||
|
|
||||||
|
constexpr _string(const alloc_t& alloc)
|
||||||
|
: _str(alloc) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr _string(size_t n, char c, const alloc_t& alloc)
|
||||||
|
: _str(n + 1, alloc) {
|
||||||
|
fennec::memset(_str, c, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr _string(const cstring& cstr)
|
||||||
|
: _str(cstr, cstr.size() + 1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Buffer Copy Constructor
|
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||||
/// \param str the buffer to copy
|
|
||||||
/// \param n 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 `n` is the intended number of characters.
|
|
||||||
constexpr _string(char* str, size_t n)
|
|
||||||
: _str(str[n - 1] == '\0' ? n : n + 1) {
|
|
||||||
fennec::memcpy(_str.data(), str, n);
|
|
||||||
if (str[n - 1] != '\0') _str[n] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
|
||||||
/// \param str the buffer to wrap
|
/// \param str the buffer to wrap
|
||||||
/// \tparam n the number of characters in the buffer plus the null terminator
|
/// \tparam n the number of characters in the buffer including the null-terminator, if present
|
||||||
template<size_t n>
|
|
||||||
explicit constexpr _string(char(&str)[n])
|
|
||||||
: _str(str, n) {
|
|
||||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Buffer Copy Constructor
|
|
||||||
/// \param str the buffer to copy
|
|
||||||
/// \param n 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 `n` is the intended number of characters.
|
|
||||||
constexpr _string(const char* str, size_t n)
|
|
||||||
: _str(str[n - 1] == '\0' ? n : n + 1) {
|
|
||||||
fennec::memcpy(_str.data(), str, n);
|
|
||||||
if (str[n - 1] != '\0') _str[n] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Buffer Constructor, wraps the provided C-Style string
|
|
||||||
/// \param str the buffer to wrap
|
|
||||||
/// \tparam n the number of characters in the buffer plus the null terminator
|
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
explicit constexpr _string(const char (&str)[n])
|
explicit constexpr _string(const char (&str)[n])
|
||||||
: _str(str, n) {
|
: _str(str[n - 1] != '\0' ? n + 1 : n) {
|
||||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
fennec::memcpy(_str, str, n);
|
||||||
|
if (str[n - 1] != '\0') {
|
||||||
|
_str[n] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Buffer Copy Constructor
|
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||||
/// \param str the buffer to copy
|
/// \param str the buffer to wrap
|
||||||
constexpr _string(const cstring& str)
|
/// \param n the number of characters in the buffer including the null-terminator, if present
|
||||||
: _str(str, str.size() + 1) {
|
constexpr _string(const char* buf, size_t n)
|
||||||
|
: _str(buf[n - 1] != '\0' ? n + 1 : n) {
|
||||||
|
fennec::memcpy(_str, buf, n);
|
||||||
|
if (buf[n - 1] != '\0') {
|
||||||
|
_str[n] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Copy Constructor
|
/// \brief String Copy Constructor
|
||||||
/// \param str the string to copy
|
/// \param str the string to copy
|
||||||
constexpr _string(const _string& str)
|
constexpr _string(const _string& str) = default;
|
||||||
: _str(str._str) {
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr _string(_string&& str) noexcept
|
|
||||||
: _str(fennec::move(str._str)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Destructor, cleans up the underlying allocation
|
/// \brief String Move Constructor
|
||||||
constexpr ~_string() = default; // allocation cleans up itself
|
/// \param str the string to take ownership of
|
||||||
|
constexpr _string(_string&& str) noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Destructor, cleans up underlying allocation
|
||||||
|
constexpr ~_string() = default;
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
constexpr _string& operator=(const cstring& cstr) {
|
||||||
|
_str.callocate(cstr.capacity());
|
||||||
|
fennec::memcpy(_str, cstr, cstr.capacity());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr _string& operator=(const _string& str) = default;
|
||||||
|
constexpr _string& operator=(_string&& str) noexcept = default;
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The size of the string excluding null terminator
|
/// \returns The size of the string excluding null terminator
|
||||||
constexpr size_t size() const {
|
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 {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Access ==============================================================================================================
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a reference to the character
|
/// \returns a reference to the character
|
||||||
constexpr char& operator[](int i) {
|
constexpr char& operator[](size_t i) {
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,24 +164,21 @@ public:
|
|||||||
/// \brief Const-Array Access Operator
|
/// \brief Const-Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a copy of the character
|
/// \returns a copy of the character
|
||||||
constexpr char operator[](int i) const {
|
constexpr const char& operator[](size_t i) const {
|
||||||
assertd(i >= 0 && (size_t)i < size(), "Array Out of Bounds");
|
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
constexpr char* data() {
|
||||||
/// \brief Dereference Operator
|
return _str;
|
||||||
/// \returns A const qualified pointer to the underlying allocation
|
|
||||||
constexpr const char* operator*() const {
|
|
||||||
return _str.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
constexpr const char* data() const {
|
||||||
/// \brief Implicit Dereference Cast
|
return _str;
|
||||||
constexpr operator const char*() const {
|
|
||||||
return _str.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr const char* cstr() const {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
// Examination =========================================================================================================
|
// Examination =========================================================================================================
|
||||||
|
|
||||||
@@ -212,7 +199,7 @@ public:
|
|||||||
}
|
}
|
||||||
n = fennec::min(n, fennec::max(_str, str.size()) + 1);
|
n = fennec::min(n, fennec::max(_str, str.size()) + 1);
|
||||||
|
|
||||||
return ::strncmp(_str.data() + i, str, n);
|
return ::strncmp(_str + i, str, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -226,7 +213,7 @@ public:
|
|||||||
}
|
}
|
||||||
n = min(n, max(size(), str.size()) + 1);
|
n = min(n, max(size(), str.size()) + 1);
|
||||||
|
|
||||||
return ::strncmp(_str.data() + i, str, n);
|
return ::strncmp(_str + i, str.data(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool operator==(const _string& str) const {
|
constexpr bool operator==(const _string& str) const {
|
||||||
@@ -242,8 +229,8 @@ public:
|
|||||||
return size();
|
return size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* loc = ::strchr(_str.data() + i, c); // get location using strchr
|
const char* loc = ::strchr(_str + i, c); // get location using strchr
|
||||||
return loc ? loc - _str.data() : size(); // return size if not found
|
return loc ? loc - _str : size(); // return size if not found
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -332,63 +319,6 @@ public:
|
|||||||
return size(); // base case
|
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::memset(_str.data() + i, '\0', n + 1 - i);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Copy Assignment Operator
|
|
||||||
/// \param str the string to copy
|
|
||||||
/// \returns a reference to `this`
|
|
||||||
constexpr _string& operator=(const cstring& str) {
|
|
||||||
if (str.empty()) {
|
|
||||||
_str.deallocate();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
resize(str.size());
|
|
||||||
fennec::memcpy(_str.data(), str, str.size());
|
|
||||||
_str[str.size()] = '\0';
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Copy Assignment Operator
|
|
||||||
/// \param str the string to copy
|
|
||||||
/// \returns a reference to `this`
|
|
||||||
constexpr _string& operator=(const string& str) {
|
|
||||||
resize(str.size());
|
|
||||||
fennec::memcpy(_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 _string& operator=(string&& str) noexcept {
|
|
||||||
_str = move(str._str);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Replace all instances of `x` with `y`
|
|
||||||
/// \param x the character to search for
|
|
||||||
/// \param y the character to replace with
|
|
||||||
void replace(char x, char y) {
|
|
||||||
size_t i = 0;
|
|
||||||
while ((i = find(x, 0)) != size()) {
|
|
||||||
_str[i] = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Retrieve a substring of a string
|
/// \brief Retrieve a substring of a string
|
||||||
/// \param i the start index
|
/// \param i the start index
|
||||||
@@ -398,59 +328,97 @@ public:
|
|||||||
if (i >= size()) {
|
if (i >= size()) {
|
||||||
return _string("");
|
return _string("");
|
||||||
}
|
}
|
||||||
n = min(n, size() - i);
|
n = fennec::min(n, size() - i);
|
||||||
return _string(_str.data() + i, n);
|
_string res;
|
||||||
}
|
res._str.callocate(n + 1);
|
||||||
|
fennec::memcpy(res.data(), _str + i, n);
|
||||||
///
|
|
||||||
/// \brief Returns a string with `c` appended to it
|
|
||||||
/// \param c
|
|
||||||
/// \returns
|
|
||||||
constexpr _string operator+(char c) const {
|
|
||||||
// Copy contents with one additional byte.
|
|
||||||
_string res(_str.data(), _str.size() + 1);
|
|
||||||
res[size()] = c; // Set the last character to c
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr _string operator+(char c, _string& str) {
|
|
||||||
return _string(c, 1) + str;
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
constexpr void resize(size_t n) {
|
||||||
|
_str.creallocate(n + 1);
|
||||||
|
_str[size()] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr _string operator+(const cstring& str) const {
|
constexpr _string operator+(char c) const {
|
||||||
_string res(size() + str.size()); // Make a new string with the size of this + str
|
if (_str == nullptr) {
|
||||||
fennec::memcpy(&res[0], _str.data(), size()); // Copy the contents of this
|
return _string(1, c);
|
||||||
fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
|
}
|
||||||
|
_string res;
|
||||||
|
res._str.callocate(capacity() + 1);
|
||||||
|
fennec::memcpy(res.data(), _str, size());
|
||||||
|
res[size()] = c;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr _string operator+(char c, const _string& str) {
|
||||||
|
_string res(1, c);
|
||||||
|
return res += str;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr _string operator+(const cstring& cstr) const {
|
||||||
|
if (_str == nullptr) {
|
||||||
|
return _string(cstr);
|
||||||
|
}
|
||||||
|
_string res;
|
||||||
|
res._str.callocate(size() + cstr.size() + 1);
|
||||||
|
fennec::memcpy(res.data(), _str, size());
|
||||||
|
fennec::memcpy(res.data() + size(), cstr, cstr.size());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr _string operator+(const _string& str) const {
|
constexpr _string operator+(const _string& str) const {
|
||||||
_string res(size() + str.size()); // Make a new string with the size of this + str
|
if (_str == nullptr) {
|
||||||
fennec::memcpy(&res[0], _str.data(), size()); // Copy the contents of this
|
return _string(str);
|
||||||
fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
|
}
|
||||||
|
if (str.data() == nullptr) {
|
||||||
|
return _string(*this);
|
||||||
|
}
|
||||||
|
_string res;
|
||||||
|
res._str.callocate(size() + str.size() + 1);
|
||||||
|
fennec::memcpy(res.data(), _str, size());
|
||||||
|
fennec::memcpy(res.data() + size(), str.data(), str.size());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr _string& operator+=(char c) {
|
constexpr _string& operator+=(char c) {
|
||||||
size_t x = size();
|
if (_str == nullptr) {
|
||||||
resize(x + 1);
|
_str.callocate(2);
|
||||||
_str[x] = c;
|
_str[0] = c;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
_str.creallocate(capacity() + 1);
|
||||||
|
_str[size() - 1] = c;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr _string& operator+=(const cstring& str) {
|
constexpr _string& operator+=(const cstring& cstr) {
|
||||||
size_t x = size();
|
if (_str == nullptr) {
|
||||||
resize(x + str.size());
|
return *this = cstr;
|
||||||
fennec::memcpy(&_str[x], str, str.size());
|
}
|
||||||
|
size_t middle = size();
|
||||||
|
_str.creallocate(middle + cstr.size() + 1);
|
||||||
|
fennec::memcpy(_str + middle, cstr, cstr.size());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr _string& operator+=(const _string& str) {
|
constexpr _string& operator+=(const _string& str) {
|
||||||
size_t x = size();
|
if (_str == nullptr) {
|
||||||
resize(x + str.size());
|
return *this = str;
|
||||||
fennec::memcpy(&_str[x], str, str.size());
|
}
|
||||||
|
if (str.data() == nullptr) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
size_t middle = size();
|
||||||
|
_str.creallocate(middle + str.size() + 1);
|
||||||
|
fennec::memcpy(_str + middle, str.data(), str.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
alloc_t _str;
|
alloc_t _str;
|
||||||
@@ -459,7 +427,7 @@ private:
|
|||||||
template<>
|
template<>
|
||||||
struct hash<string> : hash<byte_array> {
|
struct hash<string> : hash<byte_array> {
|
||||||
constexpr size_t operator()(const string& str) const {
|
constexpr size_t operator()(const string& str) const {
|
||||||
return hash<byte_array>::operator()(byte_array(*str, str.size()));
|
return hash<byte_array>::operator()(byte_array(str.data(), str.size()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Default Constructor, initializes with nullptr
|
/// \brief Default Constructor, initializes with nullptr
|
||||||
constexpr wcstring()
|
constexpr wcstring()
|
||||||
: _str(nullptr)
|
: _str(nullptr), _size(0), _const(true) {
|
||||||
, _size(0)
|
|
||||||
, _const(true) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -148,7 +146,7 @@ public:
|
|||||||
template<size_t n>
|
template<size_t n>
|
||||||
constexpr wcstring& operator=(wchar_t(&str)[n]) {
|
constexpr wcstring& operator=(wchar_t(&str)[n]) {
|
||||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||||
_str = str; _size = n - 1; _const = false;
|
_str = str, _size = n - 1, _const = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +173,10 @@ public:
|
|||||||
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
|
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
|
||||||
constexpr size_t size() const { return _size; }
|
constexpr size_t size() const { return _size; }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns the size of the string including its null terminator, i.e. `(*str)[capacity() - 1] == '\0'`
|
||||||
|
constexpr size_t capacity() const { return _size + 1; }
|
||||||
|
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _cstr == nullptr || _size == 0;
|
return _cstr == nullptr || _size == 0;
|
||||||
}
|
}
|
||||||
@@ -196,15 +198,22 @@ public:
|
|||||||
/// \brief Const-Array Access Operator
|
/// \brief Const-Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a copy of the character
|
/// \returns a copy of the character
|
||||||
constexpr wchar_t operator[](size_t i) const {
|
constexpr const wchar_t& operator[](size_t i) const {
|
||||||
assertd(i < size(), "Array Out of Bounds");
|
assertd(i < size(), "Array Out of Bounds");
|
||||||
return _cstr[i];
|
return _cstr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Dereference Operator
|
/// \brief Data Access
|
||||||
/// \returns A const qualified pointer to the underlying allocation
|
/// \returns A const qualified pointer to the underlying allocation
|
||||||
constexpr const wchar_t* operator*() const {
|
constexpr wchar_t* data() {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Data Access
|
||||||
|
/// \returns A const qualified pointer to the underlying allocation
|
||||||
|
constexpr const wchar_t* data() const {
|
||||||
return _cstr;
|
return _cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,12 +229,14 @@ public:
|
|||||||
///
|
///
|
||||||
/// \returns The length of the string to the first null-terminator
|
/// \returns The length of the string to the first null-terminator
|
||||||
constexpr size_t length() const {
|
constexpr size_t length() const {
|
||||||
return find(L'\0');
|
return find('\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Comparison
|
/// \brief String Comparison
|
||||||
/// \param str the string to compare against
|
/// \param str the string to compare against
|
||||||
|
/// \param i the index to start at
|
||||||
|
/// \param n the number of characters to compare
|
||||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
/// \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.
|
/// current locale, otherwise a positive value.
|
||||||
constexpr int compare(const wcstring& str, size_t i = 0, size_t n = npos) const {
|
constexpr int compare(const wcstring& str, size_t i = 0, size_t n = npos) const {
|
||||||
@@ -237,6 +248,15 @@ public:
|
|||||||
return ::wcsncmp(_cstr + i, str, n);
|
return ::wcsncmp(_cstr + i, str, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief String Equality
|
||||||
|
/// \param str the string to compare against
|
||||||
|
/// \returns True if all characters are equal, false otherwise
|
||||||
|
template<size_t n>
|
||||||
|
constexpr bool operator==(const wchar_t (&str)[n]) const {
|
||||||
|
return compare(wcstring(str)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Equality
|
/// \brief String Equality
|
||||||
/// \param str the string to compare against
|
/// \param str the string to compare against
|
||||||
@@ -278,7 +298,7 @@ public:
|
|||||||
/// \param c the string to find
|
/// \param c the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
|
||||||
constexpr size_t rfind(wchar_t c, size_t i = npos) const {
|
constexpr size_t rfind(char c, size_t i = npos) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
@@ -300,7 +320,7 @@ public:
|
|||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t first = str[0];
|
const char first = str[0];
|
||||||
i = min(i, _size - str._size);
|
i = min(i, _size - str._size);
|
||||||
do {
|
do {
|
||||||
if(_cstr[i] == first) {
|
if(_cstr[i] == first) {
|
||||||
@@ -321,6 +341,13 @@ private:
|
|||||||
bool _const;
|
bool _const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct hash<wcstring> : hash<byte_array> {
|
||||||
|
constexpr size_t operator()(const wcstring& str) const {
|
||||||
|
return hash<byte_array>::operator()(byte_array(str, str.size()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FENNEC_LANGPROC_STRINGS_wcstring_H
|
#endif // FENNEC_LANGPROC_STRINGS_wcstring_H
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
#ifndef FENNEC_LANGPROC_wstringS_wstring_H
|
#ifndef FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||||
#define FENNEC_LANGPROC_wstringS_wstring_H
|
#define FENNEC_LANGPROC_wstringS_WSTRING_H
|
||||||
|
|
||||||
#include <fennec/langproc/strings/detail/_ctype.h>
|
#include <fennec/langproc/strings/detail/_ctype.h>
|
||||||
#include <fennec/langproc/strings/wcstring.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
|
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with `'c'...`
|
||||||
/// \param n the number of characters
|
/// \param n the number of wchar_tacters
|
||||||
|
/// \param c the wchar_tacter to fill with
|
||||||
///
|
///
|
||||||
/// \details adds additional character for null termination.
|
/// \details adds additional wchar_tacter for null termination.
|
||||||
constexpr _wstring(size_t n)
|
constexpr _wstring(size_t n, wchar_t c = '\0')
|
||||||
: _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)
|
|
||||||
: _str(n + 1) {
|
: _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
|
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||||
/// \param str the buffer to copy
|
/// \param str the buffer to wrap
|
||||||
/// \param len number of characters in the buffer
|
/// \tparam n the number of wchar_tacters in the buffer including the null-terminator, if present
|
||||||
///
|
template<size_t n>
|
||||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
explicit constexpr _wstring(const wchar_t (&str)[n])
|
||||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
: _str(str[n - 1] != '\0' ? n + 1 : n) {
|
||||||
constexpr _wstring(const wchar_t* str, size_t n)
|
fennec::wmemcpy(_str, str, n);
|
||||||
: _str(str, n + 1) {
|
if (str[n - 1] != '\0') {
|
||||||
::wcsncpy(_str.data(), str, n);
|
|
||||||
_str[n] = '\0';
|
_str[n] = '\0';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Buffer Copy Constructor
|
/// \brief Buffer Constructor, wraps the provided C-Style string, appending a null-terminator if not present
|
||||||
/// \param str the buffer to copy
|
/// \param str the buffer to wrap
|
||||||
/// \param len number of characters in the buffer
|
/// \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)
|
||||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
: _str(buf[n - 1] != '\0' ? n + 1 : n) {
|
||||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
fennec::wmemcpy(_str, buf, n);
|
||||||
constexpr _wstring(const wcstring& str)
|
if (buf[n - 1] != '\0') {
|
||||||
: _str(str, str.size() + 1) {
|
_str[n] = '\0';
|
||||||
_str[str.size()] = '\0';
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Copy Constructor
|
/// \brief String Copy Constructor
|
||||||
/// \param str the string to copy
|
/// \param str the string to copy
|
||||||
constexpr _wstring(const wstring& str)
|
constexpr _wstring(const _wstring& str) = default;
|
||||||
: _wstring(str, str.size() - 1) {
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr _wstring(_wstring&& str) noexcept
|
|
||||||
: _str(fennec::move(str._str)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief String Destructor, cleans up the underlying allocation
|
/// \brief String Move Constructor
|
||||||
constexpr ~_wstring() = default; // allocation cleans up itself
|
/// \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 ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The size of the string excluding null terminator
|
/// \returns The size of the string excluding null terminator
|
||||||
constexpr size_t size() const {
|
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 {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Access ==============================================================================================================
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Array Access Operator
|
/// \brief Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a reference to the character
|
/// \returns a reference to the wchar_tacter
|
||||||
constexpr wchar_t& operator[](int i) {
|
constexpr wchar_t& operator[](size_t i) {
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Const-Array Access Operator
|
/// \brief Const-Array Access Operator
|
||||||
/// \param i the index to access
|
/// \param i the index to access
|
||||||
/// \returns a copy of the character
|
/// \returns a copy of the wchar_tacter
|
||||||
constexpr wchar_t operator[](int i) const {
|
constexpr const wchar_t& operator[](size_t i) const {
|
||||||
assertd(i >= 0 && i < size(), "Array Out of Bounds");
|
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
constexpr wchar_t* data() {
|
||||||
/// \brief Dereference Operator
|
return _str;
|
||||||
/// \returns A const qualified pointer to the underlying allocation
|
|
||||||
constexpr const wchar_t* operator*() const {
|
|
||||||
return _str.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
constexpr const wchar_t* data() const {
|
||||||
/// \brief Implicit Dereference Cast
|
return _str;
|
||||||
constexpr operator const wchar_t*() const {
|
|
||||||
return _str.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr const wchar_t* cstr() const {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
// Examination =========================================================================================================
|
// Examination =========================================================================================================
|
||||||
|
|
||||||
@@ -183,7 +199,7 @@ public:
|
|||||||
}
|
}
|
||||||
n = fennec::min(n, fennec::max(_str, str.size()) + 1);
|
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
|
/// \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
|
/// \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.
|
/// 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
|
if (i >= size()) { // bounds check
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
n = min(n, max(size(), str.size()) + 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 {
|
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
|
/// \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()`
|
/// \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 {
|
constexpr size_t find(wchar_t c, size_t i = 0) const {
|
||||||
if (i >= size()) { // bounds check
|
if (i >= size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t* loc = ::wcschr(_str.data() + i, c); // get location using strchr
|
const wchar_t* loc = ::wcschr(_str + i, c); // get location using strchr
|
||||||
return loc ? loc - _str.data() : size(); // return size if not found
|
return loc ? loc - _str : size(); // return size if not found
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `str` in the string.
|
/// \brief Finds the index of the first occurrence of `str` in the string.
|
||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \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
|
if (i >= size()) { // bounds check
|
||||||
return size();
|
return size();
|
||||||
}
|
}
|
||||||
@@ -287,7 +303,7 @@ public:
|
|||||||
/// \param str the string to find
|
/// \param str the string to find
|
||||||
/// \param i the index to start at
|
/// \param i the index to start at
|
||||||
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
|
/// \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) {
|
if (size() == 0) {
|
||||||
return size();
|
return size();
|
||||||
}
|
}
|
||||||
@@ -303,116 +319,119 @@ public:
|
|||||||
return size(); // base case
|
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
|
/// \brief Retrieve a substring of a string
|
||||||
/// \param i the start index
|
/// \param i the start index
|
||||||
/// \param n the number of characters
|
/// \param n the number of wchar_tacters
|
||||||
/// \return
|
/// \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()) {
|
if (i >= size()) {
|
||||||
return wstring("");
|
return _wstring("");
|
||||||
}
|
}
|
||||||
n = min(n, size() - i);
|
n = fennec::min(n, size() - i);
|
||||||
return wstring(_str.data() + i, n);
|
_wstring res;
|
||||||
}
|
res._str.callocate(n + 1);
|
||||||
|
fennec::wmemcpy(res.data(), _str + 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
|
|
||||||
return res;
|
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
|
// Modifiers ===========================================================================================================
|
||||||
fennec::wmemcpy(&res[size()], str, str.size()); // Append the contents of str
|
|
||||||
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr wstring operator+(const wstring& str) const {
|
friend constexpr _wstring operator+(wchar_t c, const _wstring& str) {
|
||||||
wstring res(size() + str.size()); // Make a new string with the size of this + str
|
_wstring res(1, c);
|
||||||
fennec::wmemcpy(&res[0], _str.data(), size()); // Copy the contents of this
|
return res += str;
|
||||||
fennec::wmemcpy(&res[size()], str, str.size()); // Append the contents of 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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr wstring& operator+=(wchar_t c) {
|
constexpr _wstring operator+(const _wstring& str) const {
|
||||||
size_t x = size();
|
if (_str == nullptr) {
|
||||||
resize(x + 1);
|
return _wstring(str);
|
||||||
_str[x] = c;
|
}
|
||||||
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr wstring& operator+=(const wcstring& str) {
|
constexpr _wstring& operator+=(const wcstring& cstr) {
|
||||||
size_t x = size();
|
if (_str == nullptr) {
|
||||||
resize(x + str.size());
|
return *this = cstr;
|
||||||
fennec::wmemcpy(&_str[x], str, str.size());
|
}
|
||||||
|
size_t middle = size();
|
||||||
|
_str.creallocate(middle + cstr.size() + 1);
|
||||||
|
fennec::wmemcpy(_str + middle, cstr, cstr.size());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr wstring& operator+=(const wstring& str) {
|
constexpr _wstring& operator+=(const _wstring& str) {
|
||||||
size_t x = size();
|
if (_str == nullptr) {
|
||||||
resize(x + str.size());
|
return *this = str;
|
||||||
fennec::wmemcpy(&_str[x], str, str.size());
|
}
|
||||||
|
if (str.data() == nullptr) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
size_t middle = size();
|
||||||
|
_str.creallocate(middle + str.size() + 1);
|
||||||
|
fennec::wmemcpy(_str + middle, str.data(), str.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
alloc_t _str;
|
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
|
||||||
|
|||||||
@@ -491,13 +491,7 @@ public:
|
|||||||
/// If there is already an allocated block of memory, the previous allocation is released.
|
/// If there is already an allocated block of memory, the previous allocation is released.
|
||||||
/// \param n The number of elements of type `T` to allocate for
|
/// \param n The number of elements of type `T` to allocate for
|
||||||
constexpr void callocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void callocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
deallocate();
|
allocate(n, align);
|
||||||
|
|
||||||
if (align != zero<align_t>()) {
|
|
||||||
_data = _alloc.allocate(_capacity = n, _alignment = align);
|
|
||||||
} else {
|
|
||||||
_data = _alloc.allocate(_capacity = n);
|
|
||||||
}
|
|
||||||
fennec::memset(static_cast<void*>(_data), 0, _capacity * sizeof(T));
|
fennec::memset(static_cast<void*>(_data), 0, _capacity * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,12 +517,15 @@ public:
|
|||||||
constexpr void reallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void reallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
if (_data == nullptr) {
|
if (_data == nullptr) {
|
||||||
allocate(n, align);
|
allocate(n, align);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t* old = _data;
|
value_t* old = _data; size_t old_cap = _capacity;
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
allocate(n, align);
|
allocate(n, align);
|
||||||
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
|
|
||||||
|
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, old_cap) * sizeof(T));
|
||||||
|
|
||||||
_alloc.deallocate(old);
|
_alloc.deallocate(old);
|
||||||
_capacity = n;
|
_capacity = n;
|
||||||
}
|
}
|
||||||
@@ -539,12 +536,19 @@ public:
|
|||||||
constexpr void creallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
constexpr void creallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||||
if (_data == nullptr) {
|
if (_data == nullptr) {
|
||||||
callocate(n, align);
|
callocate(n, align);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t* old = _data;
|
value_t* old = _data; size_t old_cap = _capacity;
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
callocate(n, align);
|
allocate(n, align);
|
||||||
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
|
|
||||||
|
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, old_cap) * sizeof(T));
|
||||||
|
|
||||||
|
if (_capacity > old_cap) {
|
||||||
|
fennec::memset(static_cast<void*>(_data + old_cap), 0, _capacity - old_cap);
|
||||||
|
}
|
||||||
|
|
||||||
_alloc.deallocate(old);
|
_alloc.deallocate(old);
|
||||||
_capacity = n;
|
_capacity = n;
|
||||||
}
|
}
|
||||||
@@ -557,14 +561,17 @@ public:
|
|||||||
return _data[i];
|
return _data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr value_t operator[](size_t i) const requires is_fundamental_v<value_t> {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
assertd(i < capacity(), "Array Out of Bounds");
|
assertd(i < capacity(), "Array Out of Bounds");
|
||||||
return _data[i];
|
return _data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const value_t& operator[](size_t i) const {
|
constexpr operator value_t*() {
|
||||||
assertd(i < capacity(), "Array Out of Bounds");
|
return _data;
|
||||||
return _data[i];
|
}
|
||||||
|
|
||||||
|
constexpr operator const value_t*() const {
|
||||||
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t* begin() {
|
value_t* begin() {
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ bool file::open(const string& p, uint8_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the file
|
// Attempt to open the file
|
||||||
_handle = fopen(p, fmode_translate(mode));
|
_handle = fopen(p.cstr(), fmode_translate(mode));
|
||||||
|
|
||||||
// Validate the file
|
// Validate the file
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -233,7 +233,7 @@ bool file::open(const path& p, uint8_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the file
|
// Attempt to open the file
|
||||||
_handle = fopen(p.str(), fmode_translate(mode));
|
_handle = fopen(p.cstr(), fmode_translate(mode));
|
||||||
|
|
||||||
// Validate the file
|
// Validate the file
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -313,7 +313,7 @@ bool file::erase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Erase the file
|
// Erase the file
|
||||||
remove(path.str());
|
remove(path.cstr());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ bool file::rename(const cstring& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the new file
|
// Attempt to open the new file
|
||||||
FILE* fnew = fopen(fpath.str(), "wx");
|
FILE* fnew = fopen(fpath.cstr(), "wx");
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (fnew == nullptr) {
|
if (fnew == nullptr) {
|
||||||
@@ -395,7 +395,7 @@ bool file::rename(const cstring& str) {
|
|||||||
fclose(_handle);
|
fclose(_handle);
|
||||||
|
|
||||||
// Reopen the new file
|
// Reopen the new file
|
||||||
_handle = freopen(fpath.str(), fmode_translate(_mode), fnew);
|
_handle = freopen(fpath.cstr(), fmode_translate(_mode), fnew);
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -404,7 +404,7 @@ bool file::rename(const cstring& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Erase the old file
|
// Erase the old file
|
||||||
remove(_path.str());
|
remove(_path.cstr());
|
||||||
|
|
||||||
// Set the new path
|
// Set the new path
|
||||||
_path = fpath;
|
_path = fpath;
|
||||||
@@ -429,7 +429,7 @@ bool file::rename(const string& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the new file
|
// Attempt to open the new file
|
||||||
FILE* fnew = fopen(fpath.str(), "wx");
|
FILE* fnew = fopen(fpath.cstr(), "wx");
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (fnew == nullptr) {
|
if (fnew == nullptr) {
|
||||||
@@ -488,7 +488,7 @@ bool file::rename(const string& str) {
|
|||||||
fclose(_handle);
|
fclose(_handle);
|
||||||
|
|
||||||
// Reopen the new file
|
// Reopen the new file
|
||||||
_handle = freopen(_path.str(), fmode_translate(_mode), fnew);
|
_handle = freopen(_path.cstr(), fmode_translate(_mode), fnew);
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -518,7 +518,7 @@ bool file::rename(const path& p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the new file
|
// Attempt to open the new file
|
||||||
FILE* fnew = fopen(fpath.str(), "wx");
|
FILE* fnew = fopen(fpath.cstr(), "wx");
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (fnew == nullptr) {
|
if (fnew == nullptr) {
|
||||||
@@ -577,7 +577,7 @@ bool file::rename(const path& p) {
|
|||||||
fclose(_handle);
|
fclose(_handle);
|
||||||
|
|
||||||
// Reopen the new file
|
// Reopen the new file
|
||||||
_handle = freopen(_path.str(), fmode_translate(_mode), fnew);
|
_handle = freopen(_path.cstr(), fmode_translate(_mode), fnew);
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
@@ -608,7 +608,7 @@ file file::copy(const cstring& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the new file
|
// Attempt to open the new file
|
||||||
FILE* fnew = fopen(fpath.str(), "wx");
|
FILE* fnew = fopen(fpath.cstr(), "wx");
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (fnew == nullptr) {
|
if (fnew == nullptr) {
|
||||||
@@ -698,7 +698,7 @@ file file::copy(const string& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the new file
|
// Attempt to open the new file
|
||||||
FILE* fnew = fopen(fpath.str(), "wx");
|
FILE* fnew = fopen(fpath.cstr(), "wx");
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (fnew == nullptr) {
|
if (fnew == nullptr) {
|
||||||
@@ -789,7 +789,7 @@ file file::copy(const path& p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to open the new file
|
// Attempt to open the new file
|
||||||
FILE* fnew = fopen(fpath.str(), "wx");
|
FILE* fnew = fopen(fpath.cstr(), "wx");
|
||||||
|
|
||||||
// Check for open failure
|
// Check for open failure
|
||||||
if (fnew == nullptr) {
|
if (fnew == nullptr) {
|
||||||
@@ -989,7 +989,7 @@ wstring file::getwline() {
|
|||||||
|
|
||||||
// Check if there is a file
|
// Check if there is a file
|
||||||
if (_handle == nullptr) {
|
if (_handle == nullptr) {
|
||||||
return 0;
|
return _wstring{ L"" };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the next line;
|
// Read the next line;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ path path::current() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
path path::current(const path& path) {
|
path path::current(const path& path) {
|
||||||
if (chdir(path._str)) {
|
if (chdir(path._str.cstr())) {
|
||||||
return fennec::path("");
|
return fennec::path("");
|
||||||
}
|
}
|
||||||
return current();
|
return current();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ static constexpr void insert_driver(list<platform::driver<CtorT>>& drvrs, CtorT
|
|||||||
|
|
||||||
iter_t it = drvrs.begin();
|
iter_t it = drvrs.begin();
|
||||||
while (it != drvrs.end()) {
|
while (it != drvrs.end()) {
|
||||||
if (priority > it->priority) {
|
if (priority >= it->priority) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ void unix_platform::unload_object(shared_object* obj) {
|
|||||||
|
|
||||||
platform::symbol unix_platform::find_symbol(shared_object* obj, const cstring& name) {
|
platform::symbol unix_platform::find_symbol(shared_object* obj, const cstring& name) {
|
||||||
string _name = name;
|
string _name = name;
|
||||||
void* symbol = dlsym(obj, _name);
|
void* symbol = dlsym(obj, _name.cstr());
|
||||||
if (symbol == nullptr) {
|
if (symbol == nullptr) {
|
||||||
_name = '_' + _name;
|
_name = '_' + _name;
|
||||||
symbol = dlsym(obj, _name);
|
symbol = dlsym(obj, _name.cstr());
|
||||||
}
|
}
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ inline std::ostream& operator<<(std::ostream& os, const quaternion<ScalarT>& q)
|
|||||||
|
|
||||||
// Helper for printing strings
|
// Helper for printing strings
|
||||||
inline std::ostream& operator<<(std::ostream& os, const cstring& str) {
|
inline std::ostream& operator<<(std::ostream& os, const cstring& str) {
|
||||||
return os << *str;
|
return os << str.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for printing strings
|
// Helper for printing strings
|
||||||
inline std::ostream& operator<<(std::ostream& os, const string& str) {
|
inline std::ostream& operator<<(std::ostream& os, const string& str) {
|
||||||
return os << *str;
|
return os << str.cstr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for printing strings
|
// Helper for printing strings
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ inline void fennec_test_containers_rdtree() {
|
|||||||
|
|
||||||
fennec_test_spacer(1);
|
fennec_test_spacer(1);
|
||||||
|
|
||||||
|
test.traverse<tree_t::pre_order>([](size_t i, size_t n) -> uint8_t {
|
||||||
|
assertf(i + 1 == n, "Tree Traverse Test Failed");
|
||||||
|
return traversal_control_continue;
|
||||||
|
});
|
||||||
|
|
||||||
test.erase(0);
|
test.erase(0);
|
||||||
|
|
||||||
fennec_test_run(test.empty(), true);
|
fennec_test_run(test.empty(), true);
|
||||||
|
|||||||
Reference in New Issue
Block a user