- Adjusted how asserts work and types of asserts

This commit is contained in:
2025-07-07 01:09:54 -04:00
parent 012052641d
commit 17d8218124
6 changed files with 152 additions and 71 deletions

View File

@@ -55,28 +55,12 @@ struct array
/// \name Element Access
/// @{
///
/// \copydetails array::at(size_t) const
constexpr ValueT& at(size_t i) { static_assert(i < ElemV); assert(i < ElemV, "Array Out of Bounds"); return elements[i]; }
///
/// \brief access specified element, **with bounds checking**
/// \details Returns a reference to the element at \c i
/// \param i index of the element to return
/// \return reference to the requested element
///
/// \par Time-Complexity
/// Constant
///
/// \par Space-Complexity
/// Constant
constexpr const ValueT& at(size_t i) const { static_assert(i < ElemV); assert(i < ElemV, "Array Out of Bounds"); return elements[i]; }
///
/// \copydetails array::operator[](size_t) const
constexpr ValueT& operator[](size_t i) { return elements[i]; }
constexpr ValueT& operator[](size_t i) {
assertd(i < ElemV, "Array Out of Bounds");
return elements[i];
}
///
/// \brief access specified element
@@ -89,7 +73,10 @@ struct array
///
/// \par Space-Complexity
/// Constant
constexpr const ValueT& operator[](size_t i) const { return elements[i]; }
constexpr const ValueT& operator[](size_t i) const {
assertd(i < ElemV, "Array Out of Bounds");
return elements[i];
}
/// @}

View File

@@ -22,6 +22,7 @@
#include <fennec/fproc/strings/cstring.h>
struct FILE;
struct stat;
namespace fennec
{

View File

@@ -60,7 +60,7 @@ public:
///
/// \brief Default Constructor, initializes with nullptr
constexpr cstring()
: _str(nullptr), _len(0), _const(true)
: _str(nullptr), _size(0), _const(true)
{ }
///
@@ -68,7 +68,9 @@ public:
/// \param str the buffer to wrap
/// \param n the number of characters in the buffer plus the null terminator
constexpr cstring(char* str, size_t n)
: _str(str), _len(n - 1), _const(false)
: _str(str)
, _size(n - 1)
, _const(false)
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); }
///
@@ -77,7 +79,9 @@ public:
/// \tparam n the number of characters in the buffer plus the null terminator
template<size_t n>
constexpr cstring(char(&str)[n])
: _str(str), _len(n - 1), _const(false)
: _str(str)
, _size(n - 1)
, _const(false)
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); }
///
@@ -85,7 +89,9 @@ public:
/// \param str the buffer to wrap
/// \param n the number of characters in the buffer plus the null terminator
constexpr cstring(const char* str, size_t n)
: _cstr(str), _len(n - 1), _const(true)
: _cstr(str)
, _size(n - 1)
, _const(true)
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
///
@@ -94,15 +100,23 @@ public:
/// \tparam n the number of characters in the buffer plus the null terminator
template<size_t n>
constexpr cstring(const char(&str)[n])
: _cstr(str), _len(n - 1), _const(true)
: _cstr(str)
, _size(n - 1)
, _const(true)
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
///
/// \brief Move Constructor
/// \param str object to move
constexpr cstring(cstring&& str)
: _cstr(str._cstr), _len(str._len)
{ }
constexpr cstring(cstring&& str) noexcept
: _cstr(str._cstr)
, _size(str._size)
, _const(str._const)
{
str._cstr = nullptr;
str._size = 0;
str._const = true;
}
constexpr cstring(const cstring&) = delete;
constexpr ~cstring() = default;
@@ -110,21 +124,31 @@ public:
template<size_t n>
constexpr cstring& operator=(char(&str)[n]) {
assert(_str[n - 1] == '\0', "Invalid NTBS.");
_str = str; _len = n - 1; _const = false;
_str = str; _size = n - 1; _const = false;
return *this;
}
template<size_t n>
constexpr cstring& operator=(const char(&str)[n]) {
assert(str[n - 1] == '\0', "Invalid NTBS.");
_cstr = str; _len = n - 1; _const = true;
_cstr = str; _size = n - 1; _const = true;
return *this;
}
constexpr cstring& operator=(cstring&& str) noexcept
{
_cstr = str._cstr; str._cstr = nullptr;
_size = str._size; str._size = 0;
_const = str._const; str._const = true;
return *this;
}
// Properties ==========================================================================================================
constexpr size_t size() const { return _len; }
///
/// \returns the size of the string excluding its null terminator, i.e. `(*str)[size()] == '\0'`
constexpr size_t size() const { return _size; }
// Access ==============================================================================================================
@@ -134,8 +158,8 @@ public:
/// \param i the index to access
/// \returns a reference to the character
constexpr char& operator[](size_t i) {
assert(i < size(), "Array Out of Bounds");
assert(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < size(), "Array Out of Bounds");
return _str[i];
}
@@ -144,7 +168,7 @@ public:
/// \param i the index to access
/// \returns a copy of the character
constexpr char operator[](size_t i) const {
assert(i < size(), "Array Out of Bounds");
assertd(i < size(), "Array Out of Bounds");
return _cstr[i];
}
@@ -170,51 +194,77 @@ 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 cstring& str) const
{ return ::strcoll(_cstr, str); }
constexpr int compare(const cstring& str, size_t i = 0) const
{
if (i >= _size) return -1;
return ::strcoll(_cstr + i, str);
}
constexpr bool operator==(const cstring& str) const
{ return compare(str) == 0; }
///
/// \brief Finds the index of the first occurrence of `x` in the string
/// \param x the character to find
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(char x) const
/// \brief Finds the index of the first occurrence of `c` in the string
/// \param c the character to find
/// \param i the index to start at
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(char c, size_t i = 0) const
{
const char* loc = ::strchr(_cstr, x);
return loc ? loc - _cstr : size();
if (i >= _size) return _size; // bounds check
const char* loc = ::strchr(_cstr + i, c); // get location using strchr
return loc ? loc - _cstr : _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
/// \param i the index to start at
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(const cstring& str) const
constexpr size_t find(const cstring& str, size_t i = 0) const
{
const char* loc = ::strstr(_cstr, str);
return loc ? loc - _cstr : size();
if (i + str._size > _size) return _size; // bounds check
const char* loc = ::strstr(_cstr + i, str); // get location using strstr
return loc ? loc - _cstr : _size; // return size if not found
}
///
/// \brief Finds the index of the last occurrence of `x` in the string.
/// \param x the string to find
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(char x) const
/// \brief Finds the index of the last occurrence of `c` in the string.
/// \param c the string to find
/// \param i the index to start at
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(char c, size_t i = 0) const
{
const char* loc = ::strrchr(_cstr, x);
return loc ? loc - _cstr : size();
if (_size == 0) return _size;
i = min(i, _size - 1); // clamp i to bounds
do {
if (_cstr[i] == c) return i; // loop backwards looking for c
} while (i--);
return _size; // base case
}
// TODO: constexpr size_t rfind(const string& str) const;
///
/// \brief Finds the index of the last occurrence of `str` in the string.
/// \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 cstring& str, size_t i = 0) const
{
const char first = str[0];
i = min(i, _size - str._size);
do {
if(_cstr[i] == first)
if (compare(str, i) == 0) return i; // loop backwards looking for str
} while (i--);
return _size; // base case
}
private:
union {
union { // hack to allow both const qualified and non-const strings
char* _str;
const char* _cstr;
};
size_t _len;
bool _const;
size_t _size;
bool _const;
};
}

View File

@@ -107,7 +107,7 @@ public:
/// \param i the index to access
/// \returns a reference to the character
constexpr char& operator[](int i) {
assert(i >= 0 && i < size(), "Array Out of Bounds");
assertd(i >= 0 && i < size(), "Array Out of Bounds");
return _str[i];
}
@@ -115,8 +115,8 @@ public:
/// \brief Const-Array Access Operator
/// \param i the index to access
/// \returns a copy of the character
constexpr char operator[](int i) const {
assert(i >= 0 && i < size(), "Array Out of Bounds");
constexpr char operator[](int i) const {
assertd(i >= 0 && i < size(), "Array Out of Bounds");
return _str[i];
}
@@ -176,16 +176,51 @@ public:
}
///
/// \brief Finds the index of the last occurrence of `x` in the string.
/// \param x the string to find
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(char x) const
/// \brief Finds the index of the last occurrence of `c` in the string.
/// \param c the string to find
/// \param i the index to start at
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(char c, size_t i = 0) const
{
const char* loc = ::strrchr(_str, x);
return loc ? loc - _str : size();
if (size() == 0) return size();
i = min(i, size() - 1); // clamp i to bounds
do {
if (_str[i] == c) return i; // loop backwards looking for c
} while (i--);
return size(); // base case
}
// TODO: constexpr size_t rfind(const string& str) const;
///
/// \brief Finds the index of the last occurrence of `str` in the string.
/// \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 cstring& str, size_t i = 0) const
{
const char first = str[0];
i = min(i, size() - str.size());
do {
if(_str[i] == first)
if (compare(str, i) == 0) return i; // loop backwards looking for str
} while (i--);
return size(); // base case
}
///
/// \brief Finds the index of the last occurrence of `str` in the string.
/// \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 string& str, size_t i = 0) const
{
const char first = str[0];
i = min(i, size() - str.size());
do {
if(_str[i] == first)
if (compare(str, i) == 0) return i; // loop backwards looking for str
} while (i--);
return size(); // base case
}
// Manipulation ========================================================================================================

View File

@@ -27,7 +27,15 @@ using assert_handler = void (*)(const char *, const char *, int , const char *);
extern void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc);
// flagged unlikely to optimize branch prediction
#define assert(expression, description) \
if(not(expression)) { __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); }
if(not(expression)) [[unlikely]] \
{ __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); }
#ifdef NDEBUG
#define assertd(expression, description) (0)
#else
#define assertd(expression, description) assert(expression, description)
#endif
#endif // FENNEC_LANG_ASSERT_H

View File

@@ -324,7 +324,7 @@ struct matrix
///
/// \copydetails matrix::operator[](size_t) const
constexpr column_t& operator[](size_t i)
{ assert(i < columns, "Array Out of Bounds"); return data[i]; }
{ return data[i]; }
///
/// \brief returns the column at index \f$i\f$
@@ -333,12 +333,12 @@ struct matrix
/// \param i the index
/// \returns the column at index \f$i\f$
constexpr const column_t& operator[](size_t i) const
{ assert(i < columns, "Array Out of Bounds"); return data[i]; }
{ return data[i]; }
///
/// \copydetails matrix::operator()(size_t, size_t) const
constexpr scalar_t& operator[](size_t i, size_t j)
{ assert(i < columns && j < rows, "Array Out of Bounds"); return data[i][j]; }
{ return data[i][j]; }
///
/// \brief returns the cell in row \p j column \p i
@@ -346,7 +346,7 @@ struct matrix
/// \param j the row
/// \returns the cell at the specified index.
constexpr scalar_t operator[](size_t i, size_t j) const
{ assert(i < columns && j < rows, "Array Out of Bounds"); return data[i][j]; }
{ return data[i][j]; }
/// @}