- Adjusted how asserts work and types of asserts
This commit is contained in:
@@ -55,28 +55,12 @@ struct array
|
|||||||
/// \name Element Access
|
/// \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
|
/// \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
|
/// \brief access specified element
|
||||||
@@ -89,7 +73,10 @@ struct array
|
|||||||
///
|
///
|
||||||
/// \par Space-Complexity
|
/// \par Space-Complexity
|
||||||
/// Constant
|
/// 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];
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <fennec/fproc/strings/cstring.h>
|
#include <fennec/fproc/strings/cstring.h>
|
||||||
|
|
||||||
struct FILE;
|
struct FILE;
|
||||||
|
struct stat;
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Default Constructor, initializes with nullptr
|
/// \brief Default Constructor, initializes with nullptr
|
||||||
constexpr cstring()
|
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 str the buffer to wrap
|
||||||
/// \param n the number of characters in the buffer plus the null terminator
|
/// \param n the number of characters in the buffer plus the null terminator
|
||||||
constexpr cstring(char* str, size_t n)
|
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."); }
|
{ 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
|
/// \tparam n the number of characters in the buffer plus the null terminator
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
constexpr cstring(char(&str)[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."); }
|
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); }
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -85,7 +89,9 @@ public:
|
|||||||
/// \param str the buffer to wrap
|
/// \param str the buffer to wrap
|
||||||
/// \param n the number of characters in the buffer plus the null terminator
|
/// \param n the number of characters in the buffer plus the null terminator
|
||||||
constexpr cstring(const char* str, size_t n)
|
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."); }
|
{ 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
|
/// \tparam n the number of characters in the buffer plus the null terminator
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
constexpr cstring(const char(&str)[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."); }
|
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Constructor
|
/// \brief Move Constructor
|
||||||
/// \param str object to move
|
/// \param str object to move
|
||||||
constexpr cstring(cstring&& str)
|
constexpr cstring(cstring&& str) noexcept
|
||||||
: _cstr(str._cstr), _len(str._len)
|
: _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(const cstring&) = delete;
|
||||||
constexpr ~cstring() = default;
|
constexpr ~cstring() = default;
|
||||||
@@ -110,21 +124,31 @@ public:
|
|||||||
template<size_t n>
|
template<size_t n>
|
||||||
constexpr cstring& operator=(char(&str)[n]) {
|
constexpr cstring& operator=(char(&str)[n]) {
|
||||||
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
assert(_str[n - 1] == '\0', "Invalid NTBS.");
|
||||||
_str = str; _len = n - 1; _const = false;
|
_str = str; _size = n - 1; _const = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t n>
|
template<size_t n>
|
||||||
constexpr cstring& operator=(const char(&str)[n]) {
|
constexpr cstring& operator=(const char(&str)[n]) {
|
||||||
assert(str[n - 1] == '\0', "Invalid NTBS.");
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
// 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 ==============================================================================================================
|
// Access ==============================================================================================================
|
||||||
@@ -134,8 +158,8 @@ public:
|
|||||||
/// \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[](size_t i) {
|
constexpr char& operator[](size_t i) {
|
||||||
assert(i < size(), "Array Out of Bounds");
|
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||||
assert(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
assertd(i < size(), "Array Out of Bounds");
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +168,7 @@ public:
|
|||||||
/// \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[](size_t i) const {
|
constexpr char operator[](size_t i) const {
|
||||||
assert(i < size(), "Array Out of Bounds");
|
assertd(i < size(), "Array Out of Bounds");
|
||||||
return _cstr[i];
|
return _cstr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,51 +194,77 @@ 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 cstring& str) const
|
constexpr int compare(const cstring& str, size_t i = 0) const
|
||||||
{ return ::strcoll(_cstr, str); }
|
{
|
||||||
|
if (i >= _size) return -1;
|
||||||
|
return ::strcoll(_cstr + i, str);
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool operator==(const cstring& str) const
|
constexpr bool operator==(const cstring& str) const
|
||||||
{ return compare(str) == 0; }
|
{ return compare(str) == 0; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the first occurrence of `x` in the string
|
/// \brief Finds the index of the first occurrence of `c` in the string
|
||||||
/// \param x the character to find
|
/// \param c the character to find
|
||||||
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
|
/// \param i the index to start at
|
||||||
constexpr size_t find(char x) const
|
/// \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);
|
if (i >= _size) return _size; // bounds check
|
||||||
return loc ? loc - _cstr : size();
|
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.
|
/// \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
|
||||||
|
/// \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 find(const cstring& str) const
|
constexpr size_t find(const cstring& str, size_t i = 0) const
|
||||||
{
|
{
|
||||||
const char* loc = ::strstr(_cstr, str);
|
if (i + str._size > _size) return _size; // bounds check
|
||||||
return loc ? loc - _cstr : size();
|
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.
|
/// \brief Finds the index of the last occurrence of `c` in the string.
|
||||||
/// \param x the string to find
|
/// \param c the string to find
|
||||||
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
|
/// \param i the index to start at
|
||||||
constexpr size_t rfind(char x) const
|
/// \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);
|
if (_size == 0) return _size;
|
||||||
return loc ? loc - _cstr : 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:
|
private:
|
||||||
union {
|
union { // hack to allow both const qualified and non-const strings
|
||||||
char* _str;
|
char* _str;
|
||||||
const char* _cstr;
|
const char* _cstr;
|
||||||
};
|
};
|
||||||
size_t _len;
|
size_t _size;
|
||||||
bool _const;
|
bool _const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public:
|
|||||||
/// \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[](int i) {
|
||||||
assert(i >= 0 && i < size(), "Array Out of Bounds");
|
assertd(i >= 0 && i < size(), "Array Out of Bounds");
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +115,8 @@ 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 char operator[](int i) const {
|
||||||
assert(i >= 0 && i < size(), "Array Out of Bounds");
|
assertd(i >= 0 && i < size(), "Array Out of Bounds");
|
||||||
return _str[i];
|
return _str[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,16 +176,51 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Finds the index of the last occurrence of `x` in the string.
|
/// \brief Finds the index of the last occurrence of `c` in the string.
|
||||||
/// \param x the string to find
|
/// \param c the string to find
|
||||||
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
|
/// \param i the index to start at
|
||||||
constexpr size_t rfind(char x) const
|
/// \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);
|
if (size() == 0) return size();
|
||||||
return loc ? loc - _str : 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 ========================================================================================================
|
// Manipulation ========================================================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
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) \
|
#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
|
#endif // FENNEC_LANG_ASSERT_H
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ struct matrix
|
|||||||
///
|
///
|
||||||
/// \copydetails matrix::operator[](size_t) const
|
/// \copydetails matrix::operator[](size_t) const
|
||||||
constexpr column_t& operator[](size_t i)
|
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$
|
/// \brief returns the column at index \f$i\f$
|
||||||
@@ -333,12 +333,12 @@ struct matrix
|
|||||||
/// \param i the index
|
/// \param i the index
|
||||||
/// \returns the column at index \f$i\f$
|
/// \returns the column at index \f$i\f$
|
||||||
constexpr const column_t& operator[](size_t i) const
|
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
|
/// \copydetails matrix::operator()(size_t, size_t) const
|
||||||
constexpr scalar_t& operator[](size_t i, size_t j)
|
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
|
/// \brief returns the cell in row \p j column \p i
|
||||||
@@ -346,7 +346,7 @@ struct matrix
|
|||||||
/// \param j the row
|
/// \param j the row
|
||||||
/// \returns the cell at the specified index.
|
/// \returns the cell at the specified index.
|
||||||
constexpr scalar_t operator[](size_t i, size_t j) const
|
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]; }
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user