clang-tidy/clang fixes and format

This commit is contained in:
Honkazel 2025-02-02 18:48:52 +05:00
parent 6a8bc9d2a4
commit 0ccb43f5cd
37 changed files with 1191 additions and 1210 deletions

View file

@ -19,6 +19,14 @@ set(LIBDIR ${CMAKE_INSTALL_FULL_LIBDIR})
configure_file(hyprutils.pc.in hyprutils.pc @ONLY) configure_file(hyprutils.pc.in hyprutils.pc @ONLY)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
add_compile_options(
-Wall
-Wextra
-Wpedantic
-Wno-unused-parameter
-Wno-unused-value
-Wno-missing-field-initializers)
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring hyprutils in Debug") message(STATUS "Configuring hyprutils in Debug")

View file

@ -9,218 +9,216 @@
#include <functional> #include <functional>
#include <chrono> #include <chrono>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Animation { namespace Hyprutils::Animation {
/* A base class for animated variables. */
class CBaseAnimatedVariable {
public:
using CallbackFun = std::function<void(Memory::CWeakPointer<CBaseAnimatedVariable> thisptr)>;
/* A base class for animated variables. */ CBaseAnimatedVariable() {
class CBaseAnimatedVariable { ; // m_bDummy = true;
public: };
using CallbackFun = std::function<void(Memory::CWeakPointer<CBaseAnimatedVariable> thisptr)>;
CBaseAnimatedVariable() { void create(CAnimationManager*, int, Memory::CSharedPointer<CBaseAnimatedVariable>);
; // m_bDummy = true; void connectToActive();
}; void disconnectFromActive();
void create(CAnimationManager*, int, Memory::CSharedPointer<CBaseAnimatedVariable>); /* Needs to call disconnectFromActive to remove `m_pSelf` from the active animation list */
void connectToActive(); virtual ~CBaseAnimatedVariable() {
void disconnectFromActive(); disconnectFromActive();
};
/* Needs to call disconnectFromActive to remove `m_pSelf` from the active animation list */ virtual void warp(bool endCallback = true, bool forceDisconnect = true) = 0;
virtual ~CBaseAnimatedVariable() {
disconnectFromActive();
};
virtual void warp(bool endCallback = true, bool forceDisconnect = true) = 0; CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete;
CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete; //
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete; void setConfig(Memory::CSharedPointer<SAnimationPropertyConfig> pConfig) {
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete; m_pConfig = pConfig;
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete; }
// Memory::CWeakPointer<SAnimationPropertyConfig> getConfig() const {
void setConfig(Memory::CSharedPointer<SAnimationPropertyConfig> pConfig) { return m_pConfig;
m_pConfig = pConfig; }
}
Memory::CWeakPointer<SAnimationPropertyConfig> getConfig() const { bool enabled() const;
return m_pConfig; const std::string& getBezierName() const;
} const std::string& getStyle() const;
bool enabled() const; /* returns the spent (completion) % */
const std::string& getBezierName() const; float getPercent() const;
const std::string& getStyle() const;
/* returns the spent (completion) % */ /* returns the current curve value. */
float getPercent() const; float getCurveValue() const;
/* returns the current curve value. */ /* checks if an animation is in progress */
float getCurveValue() const; bool isBeingAnimated() const {
return m_bIsBeingAnimated;
}
/* checks if an animation is in progress */ /* checks m_bDummy and m_pAnimationManager */
bool isBeingAnimated() const { bool ok() const;
return m_bIsBeingAnimated;
}
/* checks m_bDummy and m_pAnimationManager */ /* calls the update callback */
bool ok() const; void onUpdate();
/* calls the update callback */ /* sets a function to be ran when an animation ended.
void onUpdate();
/* sets a function to be ran when an animation ended.
if "remove" is set to true, it will remove the callback when ran. */ if "remove" is set to true, it will remove the callback when ran. */
void setCallbackOnEnd(CallbackFun func, bool remove = true); void setCallbackOnEnd(CallbackFun func, bool remove = true);
/* sets a function to be ran when an animation is started. /* sets a function to be ran when an animation is started.
if "remove" is set to true, it will remove the callback when ran. */ if "remove" is set to true, it will remove the callback when ran. */
void setCallbackOnBegin(CallbackFun func, bool remove = true); void setCallbackOnBegin(CallbackFun func, bool remove = true);
/* sets the update callback, called every time the value is animated and a step is done /* sets the update callback, called every time the value is animated and a step is done
Warning: calling unregisterVar/registerVar in this handler will cause UB */ Warning: calling unregisterVar/registerVar in this handler will cause UB */
void setUpdateCallback(CallbackFun func); void setUpdateCallback(CallbackFun func);
/* resets all callbacks. Does not call any. */ /* resets all callbacks. Does not call any. */
void resetAllCallbacks(); void resetAllCallbacks();
void onAnimationEnd(); void onAnimationEnd();
void onAnimationBegin(); void onAnimationBegin();
/* returns whether the parent CAnimationManager is dead */ /* returns whether the parent CAnimationManager is dead */
bool isAnimationManagerDead() const; bool isAnimationManagerDead() const;
int m_Type = -1; int m_Type = -1;
protected: protected:
friend class CAnimationManager; friend class CAnimationManager;
CAnimationManager* m_pAnimationManager = nullptr; CAnimationManager* m_pAnimationManager = nullptr;
bool m_bIsConnectedToActive = false; bool m_bIsConnectedToActive = false;
bool m_bIsBeingAnimated = false; bool m_bIsBeingAnimated = false;
Memory::CWeakPointer<CBaseAnimatedVariable> m_pSelf; Memory::CWeakPointer<CBaseAnimatedVariable> m_pSelf;
Memory::CWeakPointer<CAnimationManager::SAnimationManagerSignals> m_pSignals; Memory::CWeakPointer<CAnimationManager::SAnimationManagerSignals> m_pSignals;
private: private:
Memory::CWeakPointer<SAnimationPropertyConfig> m_pConfig; Memory::CWeakPointer<SAnimationPropertyConfig> m_pConfig;
std::chrono::steady_clock::time_point animationBegin; std::chrono::steady_clock::time_point animationBegin;
bool m_bDummy = true; bool m_bDummy = true;
bool m_bRemoveEndAfterRan = true; bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true; bool m_bRemoveBeginAfterRan = true;
CallbackFun m_fEndCallback; CallbackFun m_fEndCallback;
CallbackFun m_fBeginCallback; CallbackFun m_fBeginCallback;
CallbackFun m_fUpdateCallback; CallbackFun m_fUpdateCallback;
}; };
/* This concept represents the minimum requirement for a type to be used with CGenericAnimatedVariable */ /* This concept represents the minimum requirement for a type to be used with CGenericAnimatedVariable */
template <class ValueImpl> template <class ValueImpl>
concept AnimatedType = requires(ValueImpl val) { concept AnimatedType = requires(ValueImpl val) {
requires std::is_copy_constructible_v<ValueImpl>; requires std::is_copy_constructible_v<ValueImpl>;
{ val == val } -> std::same_as<bool>; // requires operator== { val == val } -> std::same_as<bool>; // requires operator==
{ val = val }; // requires operator= { val = val }; // requires operator=
}; };
/* /*
A generic class for variables. A generic class for variables.
VarType is the type of the variable to be animated. VarType is the type of the variable to be animated.
AnimationContext is there to attach additional data to the animation. AnimationContext is there to attach additional data to the animation.
In Hyprland that struct would contain a reference to window, workspace or layer for example. In Hyprland that struct would contain a reference to window, workspace or layer for example.
*/ */
template <AnimatedType VarType, class AnimationContext> template <AnimatedType VarType, class AnimationContext>
class CGenericAnimatedVariable : public CBaseAnimatedVariable { class CGenericAnimatedVariable : public CBaseAnimatedVariable {
public: public:
CGenericAnimatedVariable() = default; CGenericAnimatedVariable() = default;
void create(const int typeInfo, CAnimationManager* pAnimationManager, Memory::CSharedPointer<CGenericAnimatedVariable<VarType, AnimationContext>> pSelf, void create(const int typeInfo, CAnimationManager* pAnimationManager, Memory::CSharedPointer<CGenericAnimatedVariable<VarType, AnimationContext>> pSelf,
const VarType& initialValue) { const VarType& initialValue) {
m_Begun = initialValue; m_Begun = initialValue;
m_Value = initialValue; m_Value = initialValue;
m_Goal = initialValue; m_Goal = initialValue;
CBaseAnimatedVariable::create(pAnimationManager, typeInfo, pSelf); CBaseAnimatedVariable::create(pAnimationManager, typeInfo, pSelf);
} }
CGenericAnimatedVariable(const CGenericAnimatedVariable&) = delete; CGenericAnimatedVariable(const CGenericAnimatedVariable&) = delete;
CGenericAnimatedVariable(CGenericAnimatedVariable&&) = delete; CGenericAnimatedVariable(CGenericAnimatedVariable&&) = delete;
CGenericAnimatedVariable& operator=(const CGenericAnimatedVariable&) = delete; CGenericAnimatedVariable& operator=(const CGenericAnimatedVariable&) = delete;
CGenericAnimatedVariable& operator=(CGenericAnimatedVariable&&) = delete; CGenericAnimatedVariable& operator=(CGenericAnimatedVariable&&) = delete;
virtual void warp(bool endCallback = true, bool forceDisconnect = true) { virtual void warp(bool endCallback = true, bool forceDisconnect = true) {
if (!m_bIsBeingAnimated) if (!m_bIsBeingAnimated)
return; return;
m_Value = m_Goal; m_Value = m_Goal;
onUpdate(); onUpdate();
m_bIsBeingAnimated = false; m_bIsBeingAnimated = false;
if (endCallback) if (endCallback)
onAnimationEnd(); onAnimationEnd();
if (forceDisconnect) if (forceDisconnect)
disconnectFromActive(); disconnectFromActive();
} }
const VarType& value() const { const VarType& value() const {
return m_Value; return m_Value;
} }
/* used to update the value each tick via the AnimationManager */ /* used to update the value each tick via the AnimationManager */
VarType& value() { VarType& value() {
return m_Value; return m_Value;
} }
const VarType& goal() const { const VarType& goal() const {
return m_Goal; return m_Goal;
} }
const VarType& begun() const { const VarType& begun() const {
return m_Begun; return m_Begun;
} }
CGenericAnimatedVariable& operator=(const VarType& v) {
if (v == m_Goal)
return *this;
m_Goal = v;
m_Begun = m_Value;
onAnimationBegin();
CGenericAnimatedVariable& operator=(const VarType& v) {
if (v == m_Goal)
return *this; return *this;
}
/* Sets the actual stored value, without affecting the goal, but resets the timer*/ m_Goal = v;
void setValue(const VarType& v) { m_Begun = m_Value;
if (v == m_Value)
return;
m_Value = v; onAnimationBegin();
m_Begun = m_Value;
onAnimationBegin(); return *this;
} }
/* Sets the actual value and goal*/ /* Sets the actual stored value, without affecting the goal, but resets the timer*/
void setValueAndWarp(const VarType& v) { void setValue(const VarType& v) {
m_Goal = v; if (v == m_Value)
m_bIsBeingAnimated = true; return;
warp(); m_Value = v;
} m_Begun = m_Value;
AnimationContext m_Context; onAnimationBegin();
}
private: /* Sets the actual value and goal*/
VarType m_Value{}; void setValueAndWarp(const VarType& v) {
VarType m_Goal{}; m_Goal = v;
VarType m_Begun{}; m_bIsBeingAnimated = true;
};
} warp();
}
AnimationContext m_Context;
private:
VarType m_Value{};
VarType m_Goal{};
VarType m_Begun{};
};
} }

View file

@ -6,52 +6,51 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Animation { namespace Hyprutils::Animation {
/* /*
Structure for animation properties. Structure for animation properties.
Config properties need to have a static lifetime to allow for config reload. Config properties need to have a static lifetime to allow for config reload.
*/ */
struct SAnimationPropertyConfig { struct SAnimationPropertyConfig {
bool overridden = false; bool overridden = false;
std::string internalBezier = ""; std::string internalBezier = "";
std::string internalStyle = ""; std::string internalStyle = "";
float internalSpeed = 0.f; float internalSpeed = 0.f;
int internalEnabled = -1; int internalEnabled = -1;
Memory::CWeakPointer<SAnimationPropertyConfig> pValues; Memory::CWeakPointer<SAnimationPropertyConfig> pValues;
Memory::CWeakPointer<SAnimationPropertyConfig> pParentAnimation; Memory::CWeakPointer<SAnimationPropertyConfig> pParentAnimation;
}; };
/* A class to manage SAnimationPropertyConfig objects in a tree structure */ /* A class to manage SAnimationPropertyConfig objects in a tree structure */
class CAnimationConfigTree { class CAnimationConfigTree {
public: public:
CAnimationConfigTree() = default; CAnimationConfigTree() = default;
~CAnimationConfigTree() = default; ~CAnimationConfigTree() = default;
/* Add a new animation node inheriting from a parent. /* Add a new animation node inheriting from a parent.
If parent is empty, a root node will be created that references it's own values. If parent is empty, a root node will be created that references it's own values.
Make sure the parent node has already been created through this interface. */ Make sure the parent node has already been created through this interface. */
void createNode(const std::string& nodeName, const std::string& parent = ""); void createNode(const std::string& nodeName, const std::string& parent = "");
/* check if a node name has been created using createNode */ /* check if a node name has been created using createNode */
bool nodeExists(const std::string& nodeName) const; bool nodeExists(const std::string& nodeName) const;
/* Override the values of a node. The root node can also be overriden. */ /* Override the values of a node. The root node can also be overriden. */
void setConfigForNode(const std::string& nodeName, int enabled, float speed, const std::string& bezier, const std::string& style = ""); void setConfigForNode(const std::string& nodeName, int enabled, float speed, const std::string& bezier, const std::string& style = "");
Memory::CSharedPointer<SAnimationPropertyConfig> getConfig(const std::string& name) const; Memory::CSharedPointer<SAnimationPropertyConfig> getConfig(const std::string& name) const;
const std::unordered_map<std::string, Memory::CSharedPointer<SAnimationPropertyConfig>>& getFullConfig() const; const std::unordered_map<std::string, Memory::CSharedPointer<SAnimationPropertyConfig>>& getFullConfig() const;
CAnimationConfigTree(const CAnimationConfigTree&) = delete; CAnimationConfigTree(const CAnimationConfigTree&) = delete;
CAnimationConfigTree(CAnimationConfigTree&&) = delete; CAnimationConfigTree(CAnimationConfigTree&&) = delete;
CAnimationConfigTree& operator=(const CAnimationConfigTree&) = delete; CAnimationConfigTree& operator=(const CAnimationConfigTree&) = delete;
CAnimationConfigTree& operator=(CAnimationConfigTree&&) = delete; CAnimationConfigTree& operator=(CAnimationConfigTree&&) = delete;
private: private:
void setAnimForChildren(Memory::CSharedPointer<SAnimationPropertyConfig> PANIM); void setAnimForChildren(Memory::CSharedPointer<SAnimationPropertyConfig> PANIM);
std::unordered_map<std::string, Memory::CSharedPointer<SAnimationPropertyConfig>> m_mAnimationConfig; std::unordered_map<std::string, Memory::CSharedPointer<SAnimationPropertyConfig>> m_mAnimationConfig;
}; };
}
} }

View file

@ -9,55 +9,54 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Animation { namespace Hyprutils::Animation {
class CBaseAnimatedVariable; class CBaseAnimatedVariable;
/* A class for managing bezier curves and variables that are being animated. */ /* A class for managing bezier curves and variables that are being animated. */
class CAnimationManager { class CAnimationManager {
public: public:
CAnimationManager(); CAnimationManager();
virtual ~CAnimationManager() = default; virtual ~CAnimationManager() = default;
void tickDone(); void tickDone();
void rotateActive(); void rotateActive();
bool shouldTickForNext(); bool shouldTickForNext();
virtual void scheduleTick() = 0; virtual void scheduleTick() = 0;
virtual void onTicked() = 0; virtual void onTicked() = 0;
void addBezierWithName(std::string, const Math::Vector2D&, const Math::Vector2D&); void addBezierWithName(std::string, const Math::Vector2D&, const Math::Vector2D&);
void removeAllBeziers(); void removeAllBeziers();
bool bezierExists(const std::string&); bool bezierExists(const std::string&);
Memory::CSharedPointer<CBezierCurve> getBezier(const std::string&); Memory::CSharedPointer<CBezierCurve> getBezier(const std::string&);
const std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>>& getAllBeziers(); const std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>>& getAllBeziers();
struct SAnimationManagerSignals { struct SAnimationManagerSignals {
Signal::CSignal connect; // WP<CBaseAnimatedVariable> Signal::CSignal connect; // WP<CBaseAnimatedVariable>
Signal::CSignal disconnect; // WP<CBaseAnimatedVariable> Signal::CSignal disconnect; // WP<CBaseAnimatedVariable>
};
Memory::CWeakPointer<SAnimationManagerSignals> getSignals() const;
std::vector<Memory::CWeakPointer<CBaseAnimatedVariable>> m_vActiveAnimatedVariables;
private:
std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>> m_mBezierCurves;
bool m_bTickScheduled = false;
void onConnect(std::any data);
void onDisconnect(std::any data);
struct SAnimVarListeners {
Signal::CHyprSignalListener connect;
Signal::CHyprSignalListener disconnect;
};
Memory::CUniquePointer<SAnimVarListeners> m_listeners;
Memory::CUniquePointer<SAnimationManagerSignals> m_events;
}; };
}
Memory::CWeakPointer<SAnimationManagerSignals> getSignals() const;
std::vector<Memory::CWeakPointer<CBaseAnimatedVariable>> m_vActiveAnimatedVariables;
private:
std::unordered_map<std::string, Memory::CSharedPointer<CBezierCurve>> m_mBezierCurves;
bool m_bTickScheduled = false;
void onConnect(std::any data);
void onDisconnect(std::any data);
struct SAnimVarListeners {
Signal::CHyprSignalListener connect;
Signal::CHyprSignalListener disconnect;
};
Memory::CUniquePointer<SAnimVarListeners> m_listeners;
Memory::CUniquePointer<SAnimationManagerSignals> m_events;
};
} }

View file

@ -5,26 +5,25 @@
#include "../math/Vector2D.hpp" #include "../math/Vector2D.hpp"
namespace Hyprutils { //NOLINTNEXTLINE
namespace Animation { namespace Hyprutils::Animation {
constexpr int BAKEDPOINTS = 255; constexpr int BAKEDPOINTS = 255;
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS; constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
/* An implementation of a cubic bezier curve. */ /* An implementation of a cubic bezier curve. */
class CBezierCurve { class CBezierCurve {
public: public:
/* Calculates a cubic bezier curve based on 2 control points (EXCLUDES the 0,0 and 1,1 points). */ /* Calculates a cubic bezier curve based on 2 control points (EXCLUDES the 0,0 and 1,1 points). */
void setup(const std::array<Hyprutils::Math::Vector2D, 2>& points); void setup(const std::array<Hyprutils::Math::Vector2D, 2>& points);
float getYForT(float const& t) const; float getYForT(float const& t) const;
float getXForT(float const& t) const; float getXForT(float const& t) const;
float getYForPoint(float const& x) const; float getYForPoint(float const& x) const;
private: private:
/* this INCLUDES the 0,0 and 1,1 points. */ /* this INCLUDES the 0,0 and 1,1 points. */
std::vector<Hyprutils::Math::Vector2D> m_vPoints; std::vector<Hyprutils::Math::Vector2D> m_vPoints;
std::array<Hyprutils::Math::Vector2D, BAKEDPOINTS> m_aPointsBaked; std::array<Hyprutils::Math::Vector2D, BAKEDPOINTS> m_aPointsBaked;
}; };
}
} }

View file

@ -18,14 +18,14 @@ namespace Hyprutils::Math {
* @return Scaled SBoxExtents. * @return Scaled SBoxExtents.
*/ */
SBoxExtents operator*(const double& scale) const { SBoxExtents operator*(const double& scale) const {
return SBoxExtents{topLeft * scale, bottomRight * scale}; return SBoxExtents{.topLeft = topLeft * scale, .bottomRight = bottomRight * scale};
} }
/** /**
* @brief Rounds the coordinates of the extents. * @brief Rounds the coordinates of the extents.
* @return Rounded SBoxExtents. * @return Rounded SBoxExtents.
*/ */
SBoxExtents round() { SBoxExtents round() {
return {topLeft.round(), bottomRight.round()}; return {.topLeft = topLeft.round(), .bottomRight = bottomRight.round()};
} }
/** /**
* @brief Checks equality between two SBoxExtents objects. * @brief Checks equality between two SBoxExtents objects.
@ -58,9 +58,7 @@ namespace Hyprutils::Math {
* @param w_ Width of the box. * @param w_ Width of the box.
* @param h_ Height of the box. * @param h_ Height of the box.
*/ */
CBox(double x_, double y_, double w_, double h_) { CBox(double x_, double y_, double w_, double h_) : x(x_), y(y_) {
x = x_;
y = y_;
w = w_; w = w_;
h = h_; h = h_;
} }
@ -75,9 +73,8 @@ namespace Hyprutils::Math {
* @brief Constructs a CBox with uniform dimensions. * @brief Constructs a CBox with uniform dimensions.
* @param d Dimensions to apply uniformly (x, y, width, height). * @param d Dimensions to apply uniformly (x, y, width, height).
*/ */
CBox(const double d) { // XD. This comment will be deleted before MR, but it'll be saved in the history. Sometimes it's nice to be an idiot.
x = d; CBox(const double d) : x(d), y(d) {
y = d;
w = d; w = d;
h = d; h = d;
} }
@ -86,9 +83,7 @@ namespace Hyprutils::Math {
* @param pos Position vector representing the top-left corner. * @param pos Position vector representing the top-left corner.
* @param size Size vector representing width and height. * @param size Size vector representing width and height.
*/ */
CBox(const Vector2D& pos, const Vector2D& size) { CBox(const Vector2D& pos, const Vector2D& size) : x(pos.x), y(pos.y) {
x = pos.x;
y = pos.y;
w = size.x; w = size.x;
h = size.y; h = size.y;
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
//NOLINTNEXTLINE
namespace Hyprutils::Math { namespace Hyprutils::Math {
/** /**

View file

@ -7,53 +7,53 @@
#include "./Misc.hpp" #include "./Misc.hpp"
namespace Hyprutils { //NOLINTNEXTLINE
namespace Math { namespace Hyprutils::Math {
class CBox; class CBox;
class Vector2D; class Vector2D;
class Mat3x3 { //NOLINTNEXTLINE
public: class Mat3x3 {
Mat3x3(); public:
Mat3x3(std::array<float, 9>); Mat3x3();
Mat3x3(std::vector<float>); Mat3x3(std::array<float, 9>);
Mat3x3(std::vector<float>);
/* create an identity 3x3 matrix */ /* create an identity 3x3 matrix */
static Mat3x3 identity(); static Mat3x3 identity();
/* create an output projection matrix */ /* create an output projection matrix */
static Mat3x3 outputProjection(const Vector2D& size, eTransform transform); static Mat3x3 outputProjection(const Vector2D& size, eTransform transform);
/* get the matrix as an array, in a row-major order. */ /* get the matrix as an array, in a row-major order. */
std::array<float, 9> getMatrix() const; std::array<float, 9> getMatrix() const;
/* create a box projection matrix */ /* create a box projection matrix */
Mat3x3 projectBox(const CBox& box, eTransform transform, float rot = 0.F /* rad, CCW */) const; Mat3x3 projectBox(const CBox& box, eTransform transform, float rot = 0.F /* rad, CCW */) const;
/* in-place functions */ /* in-place functions */
Mat3x3& transform(eTransform transform); Mat3x3& transform(eTransform transform);
Mat3x3& rotate(float rot /* rad, CCW */); Mat3x3& rotate(float rot /* rad, CCW */);
Mat3x3& scale(const Vector2D& scale); Mat3x3& scale(const Vector2D& scale);
Mat3x3& scale(const float scale); Mat3x3& scale(const float scale);
Mat3x3& translate(const Vector2D& offset); Mat3x3& translate(const Vector2D& offset);
Mat3x3& transpose(); Mat3x3& transpose();
Mat3x3& multiply(const Mat3x3& other); Mat3x3& multiply(const Mat3x3& other);
/* misc utils */ /* misc utils */
Mat3x3 copy() const; Mat3x3 copy() const;
std::string toString() const; std::string toString() const;
bool operator==(const Mat3x3& other) const { bool operator==(const Mat3x3& other) const {
return other.matrix == matrix; return other.matrix == matrix;
} }
friend std::ostream& operator<<(std::ostream& os, const Mat3x3& mat) { friend std::ostream& operator<<(std::ostream& os, const Mat3x3& mat) {
os << mat.toString(); os << mat.toString();
return os; return os;
} }
private: private:
std::array<float, 9> matrix; std::array<float, 9> matrix;
}; };
} }
}

View file

@ -1,16 +1,16 @@
#pragma once #pragma once
namespace Hyprutils { //NOLINTNEXTLINE
namespace Math { namespace Hyprutils::Math {
enum eTransform { // Welcome nahui
HYPRUTILS_TRANSFORM_NORMAL = 0, enum eTransform : unsigned char {
HYPRUTILS_TRANSFORM_90 = 1, HYPRUTILS_TRANSFORM_NORMAL = 0,
HYPRUTILS_TRANSFORM_180 = 2, HYPRUTILS_TRANSFORM_90 = 1,
HYPRUTILS_TRANSFORM_270 = 3, HYPRUTILS_TRANSFORM_180 = 2,
HYPRUTILS_TRANSFORM_FLIPPED = 4, HYPRUTILS_TRANSFORM_270 = 3,
HYPRUTILS_TRANSFORM_FLIPPED_90 = 5, HYPRUTILS_TRANSFORM_FLIPPED = 4,
HYPRUTILS_TRANSFORM_FLIPPED_180 = 6, HYPRUTILS_TRANSFORM_FLIPPED_90 = 5,
HYPRUTILS_TRANSFORM_FLIPPED_270 = 7, HYPRUTILS_TRANSFORM_FLIPPED_180 = 6,
}; HYPRUTILS_TRANSFORM_FLIPPED_270 = 7,
} };
} }

View file

@ -5,67 +5,67 @@
#include "Vector2D.hpp" #include "Vector2D.hpp"
#include "Box.hpp" #include "Box.hpp"
namespace Hyprutils { //NOLINTNEXTLINE
namespace Math { namespace Hyprutils::Math {
class CRegion { class CRegion {
public: public:
/* Create an empty region */ /* Create an empty region */
CRegion(); CRegion();
/* Create from a reference. Copies, does not own. */ /* Create from a reference. Copies, does not own. */
CRegion(const pixman_region32_t* const ref); CRegion(const pixman_region32_t* const ref);
/* Create from a box */ /* Create from a box */
CRegion(double x, double y, double w, double h); CRegion(double x, double y, double w, double h);
/* Create from a CBox */ /* Create from a CBox */
CRegion(const CBox& box); CRegion(const CBox& box);
/* Create from a pixman_box32_t */ /* Create from a pixman_box32_t */
CRegion(pixman_box32_t* box); CRegion(pixman_box32_t* box);
CRegion(const CRegion&); CRegion(const CRegion&);
CRegion(CRegion&&); CRegion(CRegion&&) noexcept;
~CRegion(); ~CRegion();
CRegion& operator=(CRegion&& other) { CRegion& operator=(CRegion&& other) noexcept {
pixman_region32_copy(&m_rRegion, other.pixman()); pixman_region32_copy(&m_rRegion, other.pixman());
return *this; return *this;
} }
CRegion& operator=(CRegion& other) { // CRegion&& will shit-talkin you about being non-redeclarable and CRegion const&... pixman moment.
pixman_region32_copy(&m_rRegion, other.pixman()); CRegion& operator=(CRegion other) {
return *this; pixman_region32_copy(&m_rRegion, other.pixman());
} return *this;
}
CRegion& clear(); CRegion& clear();
CRegion& set(const CRegion& other); CRegion& set(const CRegion& other);
CRegion& add(const CRegion& other); CRegion& add(const CRegion& other);
CRegion& add(double x, double y, double w, double h); CRegion& add(double x, double y, double w, double h);
CRegion& add(const CBox& other); CRegion& add(const CBox& other);
CRegion& subtract(const CRegion& other); CRegion& subtract(const CRegion& other);
CRegion& intersect(const CRegion& other); CRegion& intersect(const CRegion& other);
CRegion& intersect(double x, double y, double w, double h); CRegion& intersect(double x, double y, double w, double h);
CRegion& translate(const Vector2D& vec); CRegion& translate(const Vector2D& vec);
CRegion& transform(const eTransform t, double w, double h); CRegion& transform(const eTransform t, double w, double h);
CRegion& invert(pixman_box32_t* box); CRegion& invert(pixman_box32_t* box);
CRegion& invert(const CBox& box); CRegion& invert(const CBox& box);
CRegion& scale(float scale); CRegion& scale(float scale);
CRegion& scale(const Vector2D& scale); CRegion& scale(const Vector2D& scale);
CRegion& expand(double units); CRegion& expand(double units);
CRegion& rationalize(); CRegion& rationalize();
CBox getExtents(); CBox getExtents();
bool containsPoint(const Vector2D& vec) const; bool containsPoint(const Vector2D& vec) const;
bool empty() const; bool empty() const;
Vector2D closestPoint(const Vector2D& vec) const; Vector2D closestPoint(const Vector2D& vec) const;
CRegion copy() const; CRegion copy() const;
std::vector<pixman_box32_t> getRects() const; std::vector<pixman_box32_t> getRects() const;
// //
pixman_region32_t* pixman() { pixman_region32_t* pixman() {
return &m_rRegion; return &m_rRegion;
} }
private: private:
pixman_region32_t m_rRegion; pixman_region32_t m_rRegion;
}; };
}
} }

View file

@ -3,102 +3,102 @@
#include <format> #include <format>
#include <string> #include <string>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Math { namespace Hyprutils::Math {
class Vector2D { //NOLINTNEXTLINE
public: class Vector2D {
Vector2D(double, double); public:
Vector2D(int, int); Vector2D(double, double);
Vector2D(); Vector2D(int, int);
~Vector2D(); Vector2D();
~Vector2D();
double x = 0; double x = 0;
double y = 0; double y = 0;
// returns the scale // returns the scale
double normalize(); double normalize();
Vector2D operator+(const Vector2D& a) const { Vector2D operator+(const Vector2D& a) const {
return Vector2D(this->x + a.x, this->y + a.y); return Vector2D(this->x + a.x, this->y + a.y);
} }
Vector2D operator-(const Vector2D& a) const { Vector2D operator-(const Vector2D& a) const {
return Vector2D(this->x - a.x, this->y - a.y); return Vector2D(this->x - a.x, this->y - a.y);
} }
Vector2D operator-() const { Vector2D operator-() const {
return Vector2D(-this->x, -this->y); return Vector2D(-this->x, -this->y);
} }
Vector2D operator*(const double& a) const { Vector2D operator*(const double& a) const {
return Vector2D(this->x * a, this->y * a); return Vector2D(this->x * a, this->y * a);
} }
Vector2D operator/(const double& a) const { Vector2D operator/(const double& a) const {
return Vector2D(this->x / a, this->y / a); return Vector2D(this->x / a, this->y / a);
} }
bool operator==(const Vector2D& a) const { bool operator==(const Vector2D& a) const {
return a.x == x && a.y == y; return a.x == x && a.y == y;
} }
bool operator!=(const Vector2D& a) const { bool operator!=(const Vector2D& a) const {
return a.x != x || a.y != y; return a.x != x || a.y != y;
} }
Vector2D operator*(const Vector2D& a) const { Vector2D operator*(const Vector2D& a) const {
return Vector2D(this->x * a.x, this->y * a.y); return Vector2D(this->x * a.x, this->y * a.y);
} }
Vector2D operator/(const Vector2D& a) const { Vector2D operator/(const Vector2D& a) const {
return Vector2D(this->x / a.x, this->y / a.y); return Vector2D(this->x / a.x, this->y / a.y);
} }
bool operator>(const Vector2D& a) const { bool operator>(const Vector2D& a) const {
return this->x > a.x && this->y > a.y; return this->x > a.x && this->y > a.y;
} }
bool operator<(const Vector2D& a) const { bool operator<(const Vector2D& a) const {
return this->x < a.x && this->y < a.y; return this->x < a.x && this->y < a.y;
} }
Vector2D& operator+=(const Vector2D& a) { Vector2D& operator+=(const Vector2D& a) {
this->x += a.x; this->x += a.x;
this->y += a.y; this->y += a.y;
return *this; return *this;
} }
Vector2D& operator-=(const Vector2D& a) { Vector2D& operator-=(const Vector2D& a) {
this->x -= a.x; this->x -= a.x;
this->y -= a.y; this->y -= a.y;
return *this; return *this;
} }
Vector2D& operator*=(const Vector2D& a) { Vector2D& operator*=(const Vector2D& a) {
this->x *= a.x; this->x *= a.x;
this->y *= a.y; this->y *= a.y;
return *this; return *this;
} }
Vector2D& operator/=(const Vector2D& a) { Vector2D& operator/=(const Vector2D& a) {
this->x /= a.x; this->x /= a.x;
this->y /= a.y; this->y /= a.y;
return *this; return *this;
} }
Vector2D& operator*=(const double& a) { Vector2D& operator*=(const double& a) {
this->x *= a; this->x *= a;
this->y *= a; this->y *= a;
return *this; return *this;
} }
Vector2D& operator/=(const double& a) { Vector2D& operator/=(const double& a) {
this->x /= a; this->x /= a;
this->y /= a; this->y /= a;
return *this; return *this;
} }
double distance(const Vector2D& other) const; double distance(const Vector2D& other) const;
double distanceSq(const Vector2D& other) const; double distanceSq(const Vector2D& other) const;
double size() const; double size() const;
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const; Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const;
Vector2D floor() const; Vector2D floor() const;
Vector2D round() const; Vector2D round() const;
Vector2D getComponentMax(const Vector2D& other) const; Vector2D getComponentMax(const Vector2D& other) const;
}; };
}
} }
// absolutely ridiculous formatter spec parsing // absolutely ridiculous formatter spec parsing

View file

@ -2,118 +2,116 @@
#include <memory> #include <memory>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Memory { namespace Hyprutils::Memory::Impl_ {
namespace Impl_ { //NOLINTNEXTLINE
class impl_base { class impl_base {
public: public:
virtual ~impl_base() {}; virtual ~impl_base() = default;
virtual void inc() noexcept = 0; virtual void inc() noexcept = 0;
virtual void dec() noexcept = 0; virtual void dec() noexcept = 0;
virtual void incWeak() noexcept = 0; virtual void incWeak() noexcept = 0;
virtual void decWeak() noexcept = 0; virtual void decWeak() noexcept = 0;
virtual unsigned int ref() noexcept = 0; virtual unsigned int ref() noexcept = 0;
virtual unsigned int wref() noexcept = 0; virtual unsigned int wref() noexcept = 0;
virtual void destroy() noexcept = 0; virtual void destroy() noexcept = 0;
virtual bool destroying() noexcept = 0; virtual bool destroying() noexcept = 0;
virtual bool dataNonNull() noexcept = 0; virtual bool dataNonNull() noexcept = 0;
virtual bool lockable() noexcept = 0; virtual bool lockable() noexcept = 0;
virtual void* getData() noexcept = 0; virtual void* getData() noexcept = 0;
}; };
template <typename T> template <typename T>
class impl : public impl_base { //NOLINTNEXTLINE
public: class impl : public impl_base {
impl(T* data, bool lock = true) noexcept : _data(data), _lockable(lock) { public:
; impl(T* data, bool lock = true) noexcept : _data(data), _lockable(lock) {
} ;
/* strong refcount */
unsigned int _ref = 0;
/* weak refcount */
unsigned int _weak = 0;
/* if this is lockable (shared) */
bool _lockable = true;
T* _data = nullptr;
friend void swap(impl*& a, impl*& b) {
impl* tmp = a;
a = b;
b = tmp;
}
/* if the destructor was called,
creating shared_ptrs is no longer valid */
bool _destroying = false;
void _destroy() {
if (!_data || _destroying)
return;
// first, we destroy the data, but keep the pointer.
// this way, weak pointers will still be able to
// reference and use, but no longer create shared ones.
_destroying = true;
__deleter(_data);
// now, we can reset the data and call it a day.
_data = nullptr;
_destroying = false;
}
std::default_delete<T> __deleter{};
//
virtual void inc() noexcept {
_ref++;
}
virtual void dec() noexcept {
_ref--;
}
virtual void incWeak() noexcept {
_weak++;
}
virtual void decWeak() noexcept {
_weak--;
}
virtual unsigned int ref() noexcept {
return _ref;
}
virtual unsigned int wref() noexcept {
return _weak;
}
virtual void destroy() noexcept {
_destroy();
}
virtual bool destroying() noexcept {
return _destroying;
}
virtual bool lockable() noexcept {
return _lockable;
}
virtual bool dataNonNull() noexcept {
return _data != nullptr;
}
virtual void* getData() noexcept {
return _data;
}
virtual ~impl() {
destroy();
}
};
} }
}
} /* strong refcount */
unsigned int _ref = 0;
/* weak refcount */
unsigned int _weak = 0;
/* if this is lockable (shared) */
bool _lockable = true;
T* _data = nullptr;
friend void swap(impl*& a, impl*& b) noexcept {
impl* tmp = a;
a = b;
b = tmp;
}
/* if the destructor was called,
creating shared_ptrs is no longer valid */
bool _destroying = false;
void _destroy() {
if (!_data || _destroying)
return;
// first, we destroy the data, but keep the pointer.
// this way, weak pointers will still be able to
// reference and use, but no longer create shared ones.
_destroying = true;
_deleter(_data);
// now, we can reset the data and call it a day.
_data = nullptr;
_destroying = false;
}
std::default_delete<T> _deleter{};
//
virtual void inc() noexcept {
_ref++;
}
virtual void dec() noexcept {
_ref--;
}
virtual void incWeak() noexcept {
_weak++;
}
virtual void decWeak() noexcept {
_weak--;
}
virtual unsigned int ref() noexcept {
return _ref;
}
virtual unsigned int wref() noexcept {
return _weak;
}
virtual void destroy() noexcept {
_destroy();
}
virtual bool destroying() noexcept {
return _destroying;
}
virtual bool lockable() noexcept {
return _lockable;
}
virtual bool dataNonNull() noexcept {
return _data != nullptr;
}
virtual void* getData() noexcept {
return _data;
}
virtual ~impl() {
destroy();
}
};
}

View file

@ -13,178 +13,174 @@
or deref an existing one inside the destructor. or deref an existing one inside the destructor.
*/ */
namespace Hyprutils { namespace Hyprutils::Memory {
namespace Memory { template <typename T>
class CSharedPointer {
public:
template <typename X>
using validHierarchy = std::enable_if_t<std::is_assignable_v<CSharedPointer<T>&, X>, CSharedPointer&>;
template <typename X>
using isConstructible = std::enable_if_t<std::is_constructible_v<T&, X&>>;
template <typename T> /* creates a new shared pointer managing a resource
class CSharedPointer {
public:
template <typename X>
using validHierarchy = typename std::enable_if<std::is_assignable<CSharedPointer<T>&, X>::value, CSharedPointer&>::type;
template <typename X>
using isConstructible = typename std::enable_if<std::is_constructible<T&, X&>::value>::type;
/* creates a new shared pointer managing a resource
avoid calling. Could duplicate ownership. Prefer makeShared */ avoid calling. Could duplicate ownership. Prefer makeShared */
explicit CSharedPointer(T* object) noexcept { explicit CSharedPointer(T* object) noexcept : impl_(new Impl_::impl<T>(object)) {
impl_ = new Impl_::impl<T>(object); increment();
increment(); }
}
/* creates a shared pointer from a reference */ /* creates a shared pointer from a reference */
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CSharedPointer(const CSharedPointer<U>& ref) noexcept { CSharedPointer(const CSharedPointer<U>& ref) noexcept : impl_(ref.impl_) {
impl_ = ref.impl_; increment();
increment(); }
}
CSharedPointer(const CSharedPointer& ref) noexcept { CSharedPointer(const CSharedPointer& ref) noexcept : impl_(ref.impl_) {
impl_ = ref.impl_; increment();
increment(); }
}
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CSharedPointer(CSharedPointer<U>&& ref) noexcept { // reason - ref param not moved. But is that correct?
std::swap(impl_, ref.impl_); CSharedPointer(CSharedPointer<U>& ref) noexcept {
} std::swap(impl_, ref.impl_);
}
CSharedPointer(CSharedPointer&& ref) noexcept { CSharedPointer(CSharedPointer&& ref) noexcept {
std::swap(impl_, ref.impl_); std::swap(impl_, ref.impl_);
} }
/* allows weakPointer to create from an impl */ /* allows weakPointer to create from an impl */
CSharedPointer(Impl_::impl_base* implementation) noexcept { CSharedPointer(Impl_::impl_base* implementation) noexcept : impl_(implementation) {
impl_ = implementation; increment();
increment(); }
}
/* creates an empty shared pointer with no implementation */ /* creates an empty shared pointer with no implementation */
CSharedPointer() noexcept { CSharedPointer() noexcept {
; // empty ; // empty
} }
/* creates an empty shared pointer with no implementation */ /* creates an empty shared pointer with no implementation */
CSharedPointer(std::nullptr_t) noexcept { CSharedPointer(std::nullptr_t) noexcept {
; // empty ; // empty
} }
~CSharedPointer() { ~CSharedPointer() {
decrement(); decrement();
} }
template <typename U> template <typename U>
validHierarchy<const CSharedPointer<U>&> operator=(const CSharedPointer<U>& rhs) { // Same. And also what should i do with the warning of unconventional assign operators?
if (impl_ == rhs.impl_) validHierarchy<const CSharedPointer<U>&> operator=(const CSharedPointer<U>& rhs) {
return *this; if (impl_ == rhs.impl_)
decrement();
impl_ = rhs.impl_;
increment();
return *this; return *this;
}
CSharedPointer& operator=(const CSharedPointer& rhs) { decrement();
if (impl_ == rhs.impl_) impl_ = rhs.impl_;
return *this; increment();
return *this;
decrement(); }
impl_ = rhs.impl_; //Self assignment warning. What to do?
increment(); CSharedPointer& operator=(const CSharedPointer& rhs) {
if (impl_ == rhs.impl_)
return *this; return *this;
}
template <typename U> decrement();
validHierarchy<const CSharedPointer<U>&> operator=(CSharedPointer<U>&& rhs) { impl_ = rhs.impl_;
std::swap(impl_, rhs.impl_); increment();
return *this; return *this;
} }
CSharedPointer& operator=(CSharedPointer&& rhs) { template <typename U>
std::swap(impl_, rhs.impl_); // Same
return *this; validHierarchy<const CSharedPointer<U>&> operator=(CSharedPointer<U>& rhs) {
} std::swap(impl_, rhs.impl_);
return *this;
}
operator bool() const { CSharedPointer& operator=(CSharedPointer&& rhs) noexcept {
return impl_ && impl_->dataNonNull(); std::swap(impl_, rhs.impl_);
} return *this;
}
bool operator==(const CSharedPointer& rhs) const { operator bool() const {
return impl_ == rhs.impl_; return impl_ && impl_->dataNonNull();
} }
bool operator()(const CSharedPointer& lhs, const CSharedPointer& rhs) const { bool operator==(const CSharedPointer& rhs) const {
return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_); return impl_ == rhs.impl_;
} }
bool operator<(const CSharedPointer& rhs) const { bool operator()(const CSharedPointer& lhs, const CSharedPointer& rhs) const {
return reinterpret_cast<uintptr_t>(impl_) < reinterpret_cast<uintptr_t>(rhs.impl_); return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
} }
T* operator->() const { bool operator<(const CSharedPointer& rhs) const {
return get(); return reinterpret_cast<uintptr_t>(impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
} }
T& operator*() const { T* operator->() const {
return *get(); return get();
} }
void reset() { T& operator*() const {
decrement(); return *get();
impl_ = nullptr; }
}
T* get() const { void reset() {
return impl_ ? static_cast<T*>(impl_->getData()) : nullptr; decrement();
} impl_ = nullptr;
}
unsigned int strongRef() const { T* get() const {
return impl_ ? impl_->ref() : 0; return impl_ ? static_cast<T*>(impl_->getData()) : nullptr;
} }
Impl_::impl_base* impl_ = nullptr; unsigned int strongRef() const {
return impl_ ? impl_->ref() : 0;
}
private: Impl_::impl_base* impl_ = nullptr;
/*
private:
/*
no-op if there is no impl_ no-op if there is no impl_
may delete the stored object if ref == 0 may delete the stored object if ref == 0
may delete and reset impl_ if ref == 0 and weak == 0 may delete and reset impl_ if ref == 0 and weak == 0
*/ */
void decrement() { void decrement() {
if (!impl_) if (!impl_)
return; return;
impl_->dec(); impl_->dec();
// if ref == 0, we can destroy impl // if ref == 0, we can destroy impl
if (impl_->ref() == 0) if (impl_->ref() == 0)
destroyImpl(); destroyImpl();
}
/* no-op if there is no impl_ */
void increment() {
if (!impl_)
return;
impl_->inc();
}
/* destroy the pointed-to object
if able, will also destroy impl */
void destroyImpl() {
// destroy the impl contents
impl_->destroy();
// check for weak refs, if zero, we can also delete impl_
if (impl_->wref() == 0) {
delete impl_;
impl_ = nullptr;
}
}
};
template <typename U, typename... Args>
static CSharedPointer<U> makeShared(Args&&... args) {
return CSharedPointer<U>(new U(std::forward<Args>(args)...));
} }
/* no-op if there is no impl_ */
void increment() {
if (!impl_)
return;
impl_->inc();
}
/* destroy the pointed-to object
if able, will also destroy impl */
void destroyImpl() {
// destroy the impl contents
impl_->destroy();
// check for weak refs, if zero, we can also delete impl_
if (impl_->wref() == 0) {
delete impl_;
impl_ = nullptr;
}
}
};
template <typename U, typename... Args>
static CSharedPointer<U> makeShared(Args&&... args) {
return CSharedPointer<U>(new U(std::forward<Args>(args)...));
} }
} }
@ -193,4 +189,4 @@ struct std::hash<Hyprutils::Memory::CSharedPointer<T>> {
std::size_t operator()(const Hyprutils::Memory::CSharedPointer<T>& p) const noexcept { std::size_t operator()(const Hyprutils::Memory::CSharedPointer<T>& p) const noexcept {
return std::hash<void*>{}(p.impl_); return std::hash<void*>{}(p.impl_);
} }
}; };

View file

@ -9,135 +9,134 @@
to be locked. to be locked.
*/ */
namespace Hyprutils { namespace Hyprutils::Memory {
namespace Memory { template <typename T>
template <typename T> class CUniquePointer {
class CUniquePointer { public:
public: template <typename X>
template <typename X> using validHierarchy = std::enable_if_t<std::is_assignable_v<CUniquePointer<T>&, X>, CUniquePointer&>;
using validHierarchy = typename std::enable_if<std::is_assignable<CUniquePointer<T>&, X>::value, CUniquePointer&>::type; template <typename X>
template <typename X> using isConstructible = std::enable_if_t<std::is_constructible_v<T&, X&>>;
using isConstructible = typename std::enable_if<std::is_constructible<T&, X&>::value>::type;
/* creates a new unique pointer managing a resource /* creates a new unique pointer managing a resource
avoid calling. Could duplicate ownership. Prefer makeUnique */ avoid calling. Could duplicate ownership. Prefer makeUnique */
explicit CUniquePointer(T* object) noexcept { explicit CUniquePointer(T* object) noexcept : impl_(new Impl_::impl<T>(object, false)) {
impl_ = new Impl_::impl<T>(object, false); increment();
increment(); }
}
/* creates a shared pointer from a reference */ /* creates a shared pointer from a reference */
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CUniquePointer(const CUniquePointer<U>& ref) = delete; CUniquePointer(const CUniquePointer<U>& ref) = delete;
CUniquePointer(const CUniquePointer& ref) = delete; CUniquePointer(const CUniquePointer& ref) = delete;
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CUniquePointer(CUniquePointer<U>&& ref) noexcept { // Same
std::swap(impl_, ref.impl_); CUniquePointer(CUniquePointer<U>& ref) noexcept {
} std::swap(impl_, ref.impl_);
}
CUniquePointer(CUniquePointer&& ref) noexcept { CUniquePointer(CUniquePointer&& ref) noexcept {
std::swap(impl_, ref.impl_); std::swap(impl_, ref.impl_);
} }
/* creates an empty unique pointer with no implementation */ /* creates an empty unique pointer with no implementation */
CUniquePointer() noexcept { CUniquePointer() noexcept {
; // empty ; // empty
} }
/* creates an empty unique pointer with no implementation */ /* creates an empty unique pointer with no implementation */
CUniquePointer(std::nullptr_t) noexcept { CUniquePointer(std::nullptr_t) noexcept {
; // empty ; // empty
} }
~CUniquePointer() { ~CUniquePointer() {
decrement(); decrement();
} }
template <typename U> template <typename U>
validHierarchy<const CUniquePointer<U>&> operator=(const CUniquePointer<U>& rhs) = delete; validHierarchy<const CUniquePointer<U>&> operator=(const CUniquePointer<U>& rhs) = delete;
CUniquePointer& operator=(const CUniquePointer& rhs) = delete; CUniquePointer& operator=(const CUniquePointer& rhs) = delete;
template <typename U> template <typename U>
validHierarchy<const CUniquePointer<U>&> operator=(CUniquePointer<U>&& rhs) { // Same with both
std::swap(impl_, rhs.impl_); validHierarchy<const CUniquePointer<U>&> operator=(CUniquePointer<U>& rhs) {
return *this; std::swap(impl_, rhs.impl_);
} return *this;
}
CUniquePointer& operator=(CUniquePointer&& rhs) { CUniquePointer& operator=(CUniquePointer&& rhs) noexcept {
std::swap(impl_, rhs.impl_); std::swap(impl_, rhs.impl_);
return *this; return *this;
} }
operator bool() const { operator bool() const {
return impl_; return impl_;
} }
bool operator()(const CUniquePointer& lhs, const CUniquePointer& rhs) const { bool operator()(const CUniquePointer& lhs, const CUniquePointer& rhs) const {
return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_); return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
} }
T* operator->() const { T* operator->() const {
return get(); return get();
} }
T& operator*() const { T& operator*() const {
return *get(); return *get();
} }
void reset() { void reset() {
decrement(); decrement();
impl_ = nullptr; impl_ = nullptr;
} }
T* get() const { T* get() const {
return impl_ ? static_cast<T*>(impl_->getData()) : nullptr; return impl_ ? static_cast<T*>(impl_->getData()) : nullptr;
} }
Impl_::impl_base* impl_ = nullptr; Impl_::impl_base* impl_ = nullptr;
private: private:
/* /*
no-op if there is no impl_ no-op if there is no impl_
may delete the stored object if ref == 0 may delete the stored object if ref == 0
may delete and reset impl_ if ref == 0 and weak == 0 may delete and reset impl_ if ref == 0 and weak == 0
*/ */
void decrement() { void decrement() {
if (!impl_) if (!impl_)
return; return;
impl_->dec(); impl_->dec();
// if ref == 0, we can destroy impl // if ref == 0, we can destroy impl
if (impl_->ref() == 0) if (impl_->ref() == 0)
destroyImpl(); destroyImpl();
}
/* no-op if there is no impl_ */
void increment() {
if (!impl_)
return;
impl_->inc();
}
/* destroy the pointed-to object
if able, will also destroy impl */
void destroyImpl() {
// destroy the impl contents
impl_->destroy();
// check for weak refs, if zero, we can also delete impl_
if (impl_->wref() == 0) {
delete impl_;
impl_ = nullptr;
}
}
};
template <typename U, typename... Args>
static CUniquePointer<U> makeUnique(Args&&... args) {
return CUniquePointer<U>(new U(std::forward<Args>(args)...));
} }
/* no-op if there is no impl_ */
void increment() {
if (!impl_)
return;
impl_->inc();
}
/* destroy the pointed-to object
if able, will also destroy impl */
void destroyImpl() {
// destroy the impl contents
impl_->destroy();
// check for weak refs, if zero, we can also delete impl_
if (impl_->wref() == 0) {
delete impl_;
impl_ = nullptr;
}
}
};
template <typename U, typename... Args>
static CUniquePointer<U> makeUnique(Args&&... args) {
return CUniquePointer<U>(new U(std::forward<Args>(args)...));
} }
} }
@ -146,4 +145,4 @@ struct std::hash<Hyprutils::Memory::CUniquePointer<T>> {
std::size_t operator()(const Hyprutils::Memory::CUniquePointer<T>& p) const noexcept { std::size_t operator()(const Hyprutils::Memory::CUniquePointer<T>& p) const noexcept {
return std::hash<void*>{}(p.impl_); return std::hash<void*>{}(p.impl_);
} }
}; };

View file

@ -9,206 +9,208 @@
See SharedPtr.hpp for more info on how it's different. See SharedPtr.hpp for more info on how it's different.
*/ */
namespace Hyprutils { //NOLINTNEXTLINE
namespace Memory { namespace Hyprutils::Memory {
template <typename T> template <typename T>
class CWeakPointer { class CWeakPointer {
public: public:
template <typename X> template <typename X>
using validHierarchy = typename std::enable_if<std::is_assignable<CWeakPointer<T>&, X>::value, CWeakPointer&>::type; using validHierarchy = std::enable_if_t<std::is_assignable_v<CWeakPointer<T>&, X>, CWeakPointer&>;
template <typename X> template <typename X>
using isConstructible = typename std::enable_if<std::is_constructible<T&, X&>::value>::type; using isConstructible = std::enable_if_t<std::is_constructible_v<T&, X&>>;
/* create a weak ptr from a reference */ /* create a weak ptr from a reference */
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CWeakPointer(const CSharedPointer<U>& ref) noexcept { CWeakPointer(const CSharedPointer<U>& ref) noexcept {
if (!ref.impl_) if (!ref.impl_)
return; return;
impl_ = ref.impl_; impl_ = ref.impl_;
incrementWeak(); incrementWeak();
} }
/* create a weak ptr from a reference */ /* create a weak ptr from a reference */
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CWeakPointer(const CUniquePointer<U>& ref) noexcept { CWeakPointer(const CUniquePointer<U>& ref) noexcept {
if (!ref.impl_) if (!ref.impl_)
return; return;
impl_ = ref.impl_; impl_ = ref.impl_;
incrementWeak(); incrementWeak();
} }
/* create a weak ptr from another weak ptr */ /* create a weak ptr from another weak ptr */
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CWeakPointer(const CWeakPointer<U>& ref) noexcept { CWeakPointer(const CWeakPointer<U>& ref) noexcept {
if (!ref.impl_) if (!ref.impl_)
return; return;
impl_ = ref.impl_; impl_ = ref.impl_;
incrementWeak(); incrementWeak();
} }
CWeakPointer(const CWeakPointer& ref) noexcept { CWeakPointer(const CWeakPointer& ref) noexcept {
if (!ref.impl_) if (!ref.impl_)
return; return;
impl_ = ref.impl_; impl_ = ref.impl_;
incrementWeak(); incrementWeak();
} }
template <typename U, typename = isConstructible<U>> template <typename U, typename = isConstructible<U>>
CWeakPointer(CWeakPointer<U>&& ref) noexcept { // Same
std::swap(impl_, ref.impl_); CWeakPointer(CWeakPointer<U>& ref) noexcept {
} std::swap(impl_, ref.impl_);
}
CWeakPointer(CWeakPointer&& ref) noexcept { CWeakPointer(CWeakPointer&& ref) noexcept {
std::swap(impl_, ref.impl_); std::swap(impl_, ref.impl_);
} }
/* create a weak ptr from another weak ptr with assignment */ /* create a weak ptr from another weak ptr with assignment */
template <typename U> template <typename U>
validHierarchy<const CWeakPointer<U>&> operator=(const CWeakPointer<U>& rhs) { // Same
if (impl_ == rhs.impl_) validHierarchy<const CWeakPointer<U>&> operator=(const CWeakPointer<U>& rhs) {
return *this; if (impl_ == rhs.impl_)
decrementWeak();
impl_ = rhs.impl_;
incrementWeak();
return *this; return *this;
}
CWeakPointer<T>& operator=(const CWeakPointer& rhs) { decrementWeak();
if (impl_ == rhs.impl_) impl_ = rhs.impl_;
return *this; incrementWeak();
return *this;
decrementWeak(); }
impl_ = rhs.impl_; // Same
incrementWeak(); CWeakPointer<T>& operator=(const CWeakPointer& rhs) {
if (impl_ == rhs.impl_)
return *this; return *this;
}
/* create a weak ptr from a shared ptr with assignment */ decrementWeak();
template <typename U> impl_ = rhs.impl_;
validHierarchy<const CWeakPointer<U>&> operator=(const CSharedPointer<U>& rhs) { incrementWeak();
if (reinterpret_cast<uintptr_t>(impl_) == reinterpret_cast<uintptr_t>(rhs.impl_)) return *this;
return *this; }
decrementWeak(); /* create a weak ptr from a shared ptr with assignment */
impl_ = rhs.impl_; template <typename U>
incrementWeak(); // Same...
validHierarchy<const CWeakPointer<U>&> operator=(const CSharedPointer<U>& rhs) {
if (reinterpret_cast<uintptr_t>(impl_) == reinterpret_cast<uintptr_t>(rhs.impl_))
return *this; return *this;
}
/* create an empty weak ptr */ decrementWeak();
CWeakPointer() { impl_ = rhs.impl_;
; incrementWeak();
} return *this;
}
~CWeakPointer() { /* create an empty weak ptr */
decrementWeak(); CWeakPointer() {
} ;
}
/* expired MAY return true even if the pointer is still stored. ~CWeakPointer() {
decrementWeak();
}
/* expired MAY return true even if the pointer is still stored.
the situation would be e.g. self-weak pointer in a destructor. the situation would be e.g. self-weak pointer in a destructor.
for pointer validity, use valid() */ for pointer validity, use valid() */
bool expired() const { bool expired() const {
return !impl_ || !impl_->dataNonNull() || impl_->destroying(); return !impl_ || !impl_->dataNonNull() || impl_->destroying();
} }
/* this means the pointed-to object is not yet deleted and can still be /* this means the pointed-to object is not yet deleted and can still be
referenced, but it might be in the process of being deleted. referenced, but it might be in the process of being deleted.
check !expired() if you want to check whether it's valid and check !expired() if you want to check whether it's valid and
assignable to a SP. */ assignable to a SP. */
bool valid() const { bool valid() const {
return impl_ && impl_->dataNonNull(); return impl_ && impl_->dataNonNull();
} }
void reset() { void reset() {
decrementWeak(); decrementWeak();
impl_ = nullptr;
}
CSharedPointer<T> lock() const {
if (!impl_ || !impl_->dataNonNull() || impl_->destroying() || !impl_->lockable())
return {};
return CSharedPointer<T>(impl_);
}
/* this returns valid() */
operator bool() const {
return valid();
}
bool operator==(const CWeakPointer<T>& rhs) const {
return impl_ == rhs.impl_;
}
bool operator==(const CSharedPointer<T>& rhs) const {
return impl_ == rhs.impl_;
}
bool operator==(const CUniquePointer<T>& rhs) const {
return impl_ == rhs.impl_;
}
bool operator==(std::nullptr_t) const {
return !valid();
}
bool operator!=(std::nullptr_t) const {
return valid();
}
bool operator()(const CWeakPointer& lhs, const CWeakPointer& rhs) const {
return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
}
bool operator<(const CWeakPointer& rhs) const {
return reinterpret_cast<uintptr_t>(impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
}
T* get() const {
return impl_ ? static_cast<T*>(impl_->getData()) : nullptr;
}
T* operator->() const {
return get();
}
T& operator*() const {
return *get();
}
Impl_::impl_base* impl_ = nullptr;
private:
/* no-op if there is no impl_ */
void decrementWeak() {
if (!impl_)
return;
impl_->decWeak();
// we need to check for ->destroying,
// because otherwise we could destroy here
// and have a shared_ptr destroy the same thing
// later (in situations where we have a weak_ptr to self)
if (impl_->wref() == 0 && impl_->ref() == 0 && !impl_->destroying()) {
delete impl_;
impl_ = nullptr; impl_ = nullptr;
} }
}
/* no-op if there is no impl_ */
void incrementWeak() {
if (!impl_)
return;
CSharedPointer<T> lock() const { impl_->incWeak();
if (!impl_ || !impl_->dataNonNull() || impl_->destroying() || !impl_->lockable()) }
return {}; };
return CSharedPointer<T>(impl_);
}
/* this returns valid() */
operator bool() const {
return valid();
}
bool operator==(const CWeakPointer<T>& rhs) const {
return impl_ == rhs.impl_;
}
bool operator==(const CSharedPointer<T>& rhs) const {
return impl_ == rhs.impl_;
}
bool operator==(const CUniquePointer<T>& rhs) const {
return impl_ == rhs.impl_;
}
bool operator==(std::nullptr_t) const {
return !valid();
}
bool operator!=(std::nullptr_t) const {
return valid();
}
bool operator()(const CWeakPointer& lhs, const CWeakPointer& rhs) const {
return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
}
bool operator<(const CWeakPointer& rhs) const {
return reinterpret_cast<uintptr_t>(impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
}
T* get() const {
return impl_ ? static_cast<T*>(impl_->getData()) : nullptr;
}
T* operator->() const {
return get();
}
T& operator*() const {
return *get();
}
Impl_::impl_base* impl_ = nullptr;
private:
/* no-op if there is no impl_ */
void decrementWeak() {
if (!impl_)
return;
impl_->decWeak();
// we need to check for ->destroying,
// because otherwise we could destroy here
// and have a shared_ptr destroy the same thing
// later (in situations where we have a weak_ptr to self)
if (impl_->wref() == 0 && impl_->ref() == 0 && !impl_->destroying()) {
delete impl_;
impl_ = nullptr;
}
}
/* no-op if there is no impl_ */
void incrementWeak() {
if (!impl_)
return;
impl_->incWeak();
}
};
}
} }
template <typename T> template <typename T>

View file

@ -1,39 +1,39 @@
#pragma once #pragma once
#include <fcntl.h> #include <fcntl.h>
namespace Hyprutils {
namespace OS {
class CFileDescriptor {
public:
CFileDescriptor() = default;
explicit CFileDescriptor(int const fd);
CFileDescriptor(CFileDescriptor&&);
CFileDescriptor& operator=(CFileDescriptor&&);
~CFileDescriptor();
CFileDescriptor(const CFileDescriptor&) = delete; //NOLINTNEXTLINE
CFileDescriptor& operator=(const CFileDescriptor&) = delete; namespace Hyprutils::OS {
class CFileDescriptor {
public:
CFileDescriptor() = default;
explicit CFileDescriptor(int const fd);
CFileDescriptor(CFileDescriptor&&) noexcept;
CFileDescriptor& operator=(CFileDescriptor&&) noexcept;
~CFileDescriptor();
bool operator==(const CFileDescriptor& rhs) const { CFileDescriptor(const CFileDescriptor&) = delete;
return m_fd == rhs.m_fd; CFileDescriptor& operator=(const CFileDescriptor&) = delete;
}
bool isValid() const; bool operator==(const CFileDescriptor& rhs) const {
int get() const; return m_fd == rhs.m_fd;
int getFlags() const; }
bool setFlags(int flags);
int take();
void reset();
CFileDescriptor duplicate(int flags = F_DUPFD_CLOEXEC) const;
bool isReadable() const; bool isValid() const;
bool isClosed() const; int get() const;
int getFlags() const;
bool setFlags(int flags);
int take();
void reset();
CFileDescriptor duplicate(int flags = F_DUPFD_CLOEXEC) const;
static bool isReadable(int fd); bool isReadable() const;
static bool isClosed(int fd); bool isClosed() const;
private: static bool isReadable(int fd);
int m_fd = -1; static bool isClosed(int fd);
};
private:
int m_fd = -1;
}; };
}; };

View file

@ -5,33 +5,32 @@
#include <utility> #include <utility>
#include <sys/types.h> #include <sys/types.h>
namespace Hyprutils { //NOLINTNEXTLINE
namespace OS { namespace Hyprutils::OS {
class CProcess { class CProcess {
public: public:
/* Creates a process object, doesn't run yet */ /* Creates a process object, doesn't run yet */
CProcess(const std::string& binary_, const std::vector<std::string>& args_); CProcess(const std::string& binary_, const std::vector<std::string>& args_);
void addEnv(const std::string& name, const std::string& value); void addEnv(const std::string& name, const std::string& value);
/* Run the process, synchronously, get the stdout and stderr. False on fail */ /* Run the process, synchronously, get the stdout and stderr. False on fail */
bool runSync(); bool runSync();
/* Run the process, asynchronously. This will detach the process from this object (and process) and let it live a happy life. False on fail. */ /* Run the process, asynchronously. This will detach the process from this object (and process) and let it live a happy life. False on fail. */
bool runAsync(); bool runAsync();
// only populated when ran sync // only populated when ran sync
const std::string& stdOut(); const std::string& stdOut();
const std::string& stdErr(); const std::string& stdErr();
// only populated when ran async // only populated when ran async
const pid_t pid(); pid_t pid();
private: private:
std::string binary, out, err; std::string binary, out, err;
std::vector<std::string> args; std::vector<std::string> args;
std::vector<std::pair<std::string, std::string>> env; std::vector<std::pair<std::string, std::string>> env;
pid_t grandchildPid = 0; pid_t grandchildPid = 0;
}; };
} }
}

View file

@ -4,39 +4,38 @@
#include <optional> #include <optional>
#include <utility> #include <utility>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Path { namespace Hyprutils::Path {
/** Check whether a config in the form basePath/hypr/programName.conf exists. /** Check whether a config in the form basePath/hypr/programName.conf exists.
@param basePath the path where the config will be searched @param basePath the path where the config will be searched
@param programName name of the program (and config file) to search for @param programName name of the program (and config file) to search for
*/ */
bool checkConfigExists(const std::string basePath, const std::string programName); bool checkConfigExists(const std::string basePath, const std::string programName);
/** Constructs a full config path given the basePath and programName. /** Constructs a full config path given the basePath and programName.
@param basePath the path where the config hypr/programName.conf is located @param basePath the path where the config hypr/programName.conf is located
@param programName name of the program (and config file) @param programName name of the program (and config file)
*/ */
std::string fullConfigPath(const std::string basePath, const std::string programName); std::string fullConfigPath(const std::string basePath, const std::string programName);
/** Retrieves the absolute path of the $HOME env variable. /** Retrieves the absolute path of the $HOME env variable.
*/ */
std::optional<std::string> getHome(); std::optional<std::string> getHome();
/** Retrieves a CVarList of paths from the $XDG_CONFIG_DIRS env variable. /** Retrieves a CVarList of paths from the $XDG_CONFIG_DIRS env variable.
*/ */
std::optional<String::CVarList> getXdgConfigDirs(); std::optional<String::CVarList> getXdgConfigDirs();
/** Retrieves the absolute path of the $XDG_CONFIG_HOME env variable. /** Retrieves the absolute path of the $XDG_CONFIG_HOME env variable.
*/ */
std::optional<std::string> getXdgConfigHome(); std::optional<std::string> getXdgConfigHome();
/** Searches for a config according to the XDG Base Directory specification. /** Searches for a config according to the XDG Base Directory specification.
Returns a pair of the full path to a config and the base path. Returns a pair of the full path to a config and the base path.
Returns std::nullopt in case of a non-existent value. Returns std::nullopt in case of a non-existent value.
@param programName name of the program (and config file) @param programName name of the program (and config file)
*/ */
using T = std::optional<std::string>; using T = std::optional<std::string>;
std::pair<T, T> findConfig(const std::string programName); std::pair<T, T> findConfig(const std::string programName);
}
} }

View file

@ -4,41 +4,40 @@
#include <functional> #include <functional>
#include <hyprutils/memory/SharedPtr.hpp> #include <hyprutils/memory/SharedPtr.hpp>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Signal { namespace Hyprutils::Signal {
class CSignal; class CSignal;
class CSignalListener { class CSignalListener {
public: public:
CSignalListener(std::function<void(std::any)> handler); CSignalListener(std::function<void(std::any)> handler);
CSignalListener(CSignalListener&&) = delete; CSignalListener(CSignalListener&&) = delete;
CSignalListener(CSignalListener&) = delete; CSignalListener(CSignalListener&) = delete;
CSignalListener(const CSignalListener&) = delete; CSignalListener(const CSignalListener&) = delete;
CSignalListener(const CSignalListener&&) = delete; CSignalListener(const CSignalListener&&) = delete;
void emit(std::any data); void emit(std::any data);
private: private:
std::function<void(std::any)> m_fHandler; std::function<void(std::any)> m_fHandler;
}; };
typedef Hyprutils::Memory::CSharedPointer<CSignalListener> CHyprSignalListener; typedef Hyprutils::Memory::CSharedPointer<CSignalListener> CHyprSignalListener;
class CStaticSignalListener { class CStaticSignalListener {
public: public:
CStaticSignalListener(std::function<void(void*, std::any)> handler, void* owner); CStaticSignalListener(std::function<void(void*, std::any)> handler, void* owner);
CStaticSignalListener(CStaticSignalListener&&) = delete; CStaticSignalListener(CStaticSignalListener&&) = delete;
CStaticSignalListener(CStaticSignalListener&) = delete; CStaticSignalListener(CStaticSignalListener&) = delete;
CStaticSignalListener(const CStaticSignalListener&) = delete; CStaticSignalListener(const CStaticSignalListener&) = delete;
CStaticSignalListener(const CStaticSignalListener&&) = delete; CStaticSignalListener(const CStaticSignalListener&&) = delete;
void emit(std::any data); void emit(std::any data);
private: private:
void* m_pOwner = nullptr; void* m_pOwner = nullptr;
std::function<void(void*, std::any)> m_fHandler; std::function<void(void*, std::any)> m_fHandler;
}; };
}
} }

View file

@ -7,22 +7,21 @@
#include <hyprutils/memory/WeakPtr.hpp> #include <hyprutils/memory/WeakPtr.hpp>
#include "./Listener.hpp" #include "./Listener.hpp"
namespace Hyprutils { //NOLINTNEXTLINE
namespace Signal { namespace Hyprutils::Signal {
class CSignal { class CSignal {
public: public:
void emit(std::any data = {}); void emit(std::any data = {});
// //
[[nodiscard("Listener is unregistered when the ptr is lost")]] CHyprSignalListener registerListener(std::function<void(std::any)> handler); [[nodiscard("Listener is unregistered when the ptr is lost")]] CHyprSignalListener registerListener(std::function<void(std::any)> handler);
// this is for static listeners. They die with this signal. // this is for static listeners. They die with this signal.
// TODO: can we somehow rid of the void* data and make it a custom this? // TODO: can we somehow rid of the void* data and make it a custom this?
void registerStaticListener(std::function<void(void*, std::any)> handler, void* owner); void registerStaticListener(std::function<void(void*, std::any)> handler, void* owner);
private: private:
std::vector<Hyprutils::Memory::CWeakPointer<CSignalListener>> m_vListeners; std::vector<Hyprutils::Memory::CWeakPointer<CSignalListener>> m_vListeners;
std::vector<std::unique_ptr<CStaticSignalListener>> m_vStaticListeners; std::vector<std::unique_ptr<CStaticSignalListener>> m_vStaticListeners;
}; };
} }
}

View file

@ -1,11 +1,10 @@
#pragma once #pragma once
#include <string> #include <string>
namespace Hyprutils { //NOLINTNEXTLINE
namespace String { namespace Hyprutils::String {
// trims beginning and end of whitespace characters // trims beginning and end of whitespace characters
std::string trim(const std::string& in); std::string trim(const std::string& in);
bool isNumber(const std::string& str, bool allowfloat = false); bool isNumber(const std::string& str, bool allowfloat = false);
void replaceInString(std::string& string, const std::string& what, const std::string& to); void replaceInString(std::string& string, const std::string& what, const std::string& to);
}; };
};

View file

@ -3,65 +3,64 @@
#include <vector> #include <vector>
#include <string> #include <string>
namespace Hyprutils { //NOLINTNEXTLINE
namespace String { namespace Hyprutils::String {
class CVarList { class CVarList {
public: public:
/** Split string into arg list /** Split string into arg list
@param lastArgNo stop splitting after argv reaches maximum size, last arg will contain rest of unsplit args @param lastArgNo stop splitting after argv reaches maximum size, last arg will contain rest of unsplit args
@param delim if delimiter is 's', use std::isspace @param delim if delimiter is 's', use std::isspace
@param removeEmpty remove empty args from argv @param removeEmpty remove empty args from argv
*/ */
CVarList(const std::string& in, const size_t lastArgNo = 0, const char delim = ',', const bool removeEmpty = false); CVarList(const std::string& in, const size_t lastArgNo = 0, const char delim = ',', const bool removeEmpty = false);
~CVarList() = default; ~CVarList() = default;
size_t size() const { size_t size() const {
return m_vArgs.size(); return m_vArgs.size();
}
std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const;
void map(std::function<void(std::string&)> func) {
for (auto& s : m_vArgs)
func(s);
}
void append(const std::string arg) {
m_vArgs.emplace_back(arg);
}
std::string operator[](const size_t& idx) const {
if (idx >= m_vArgs.size())
return "";
return m_vArgs[idx];
}
// for range-based loops
std::vector<std::string>::iterator begin() {
return m_vArgs.begin();
}
std::vector<std::string>::const_iterator begin() const {
return m_vArgs.begin();
}
std::vector<std::string>::iterator end() {
return m_vArgs.end();
}
std::vector<std::string>::const_iterator end() const {
return m_vArgs.end();
}
bool contains(const std::string& el) {
for (auto& a : m_vArgs) {
if (a == el)
return true;
} }
std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const; return false;
}
void map(std::function<void(std::string&)> func) { private:
for (auto& s : m_vArgs) std::vector<std::string> m_vArgs;
func(s); };
}
void append(const std::string arg) {
m_vArgs.emplace_back(arg);
}
std::string operator[](const size_t& idx) const {
if (idx >= m_vArgs.size())
return "";
return m_vArgs[idx];
}
// for range-based loops
std::vector<std::string>::iterator begin() {
return m_vArgs.begin();
}
std::vector<std::string>::const_iterator begin() const {
return m_vArgs.begin();
}
std::vector<std::string>::iterator end() {
return m_vArgs.end();
}
std::vector<std::string>::const_iterator end() const {
return m_vArgs.end();
}
bool contains(const std::string& el) {
for (auto& a : m_vArgs) {
if (a == el)
return true;
}
return false;
}
private:
std::vector<std::string> m_vArgs;
};
}
} }

View file

@ -2,16 +2,15 @@
#include <functional> #include <functional>
namespace Hyprutils { //NOLINTNEXTLINE
namespace Utils { namespace Hyprutils::Utils {
// calls a function when it goes out of scope // calls a function when it goes out of scope
class CScopeGuard { class CScopeGuard {
public: public:
CScopeGuard(const std::function<void()>& fn_); CScopeGuard(const std::function<void()>& fn_);
~CScopeGuard(); ~CScopeGuard();
private: private:
std::function<void()> fn; std::function<void()> fn;
};
}; };
}; };

View file

@ -13,8 +13,8 @@ void CBaseAnimatedVariable::create(CAnimationManager* pManager, int typeInfo, SP
m_pSelf = pSelf; m_pSelf = pSelf;
m_pAnimationManager = pManager; m_pAnimationManager = pManager;
m_pSignals = pManager->getSignals(); m_pSignals = pManager->getSignals();
m_bDummy = false; m_bDummy = false;
} }
void CBaseAnimatedVariable::connectToActive() { void CBaseAnimatedVariable::connectToActive() {

View file

@ -99,7 +99,7 @@ bool CAnimationManager::bezierExists(const std::string& bezier) {
} }
SP<CBezierCurve> CAnimationManager::getBezier(const std::string& name) { SP<CBezierCurve> CAnimationManager::getBezier(const std::string& name) {
const auto BEZIER = std::find_if(m_mBezierCurves.begin(), m_mBezierCurves.end(), [&](const auto& other) { return other.first == name; }); const auto BEZIER = std::ranges::find_if(m_mBezierCurves, [&](const auto& other) { return other.first == name; });
return BEZIER == m_mBezierCurves.end() ? m_mBezierCurves["default"] : BEZIER->second; return BEZIER == m_mBezierCurves.end() ? m_mBezierCurves["default"] : BEZIER->second;
} }

View file

@ -35,14 +35,14 @@ float CBezierCurve::getXForT(float const& t) const {
float t2 = t * t; float t2 = t * t;
float t3 = t2 * t; float t3 = t2 * t;
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].x + 3 * t2 * (1 - t) * m_vPoints[2].x + t3 * m_vPoints[3].x; return (3 * t * (1 - t) * (1 - t) * m_vPoints[1].x) + (3 * t2 * (1 - t) * m_vPoints[2].x) + (t3 * m_vPoints[3].x);
} }
float CBezierCurve::getYForT(float const& t) const { float CBezierCurve::getYForT(float const& t) const {
float t2 = t * t; float t2 = t * t;
float t3 = t2 * t; float t3 = t2 * t;
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].y + 3 * t2 * (1 - t) * m_vPoints[2].y + t3 * m_vPoints[3].y; return (3 * t * (1 - t) * (1 - t) * m_vPoints[1].y) + (3 * t2 * (1 - t) * m_vPoints[2].y) + (t3 * m_vPoints[3].y);
} }
// Todo: this probably can be done better and faster // Todo: this probably can be done better and faster
@ -74,5 +74,5 @@ float CBezierCurve::getYForPoint(float const& x) const {
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
return 0.f; return 0.f;
return LOWERPOINT->y + (UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA; return LOWERPOINT->y + ((UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA);
} }

View file

@ -37,7 +37,7 @@ CBox& Hyprutils::Math::CBox::translate(const Vector2D& vec) {
} }
Vector2D Hyprutils::Math::CBox::middle() const { Vector2D Hyprutils::Math::CBox::middle() const {
return Vector2D{x + w * HALF, y + h * HALF}; return Vector2D{x + (w * HALF), y + (h * HALF)};
} }
bool Hyprutils::Math::CBox::containsPoint(const Vector2D& vec) const { bool Hyprutils::Math::CBox::containsPoint(const Vector2D& vec) const {
@ -233,5 +233,5 @@ Vector2D Hyprutils::Math::CBox::closestPoint(const Vector2D& vec) const {
} }
SBoxExtents Hyprutils::Math::CBox::extentsFrom(const CBox& small) { SBoxExtents Hyprutils::Math::CBox::extentsFrom(const CBox& small) {
return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}}; return {.topLeft = {small.x - x, small.y - y}, .bottomRight = {w - small.w - (small.x - x), h - small.h - (small.y - y)}};
} }

View file

@ -93,6 +93,7 @@ Mat3x3& Mat3x3::transform(eTransform transform) {
} }
Mat3x3& Mat3x3::rotate(float rot) { Mat3x3& Mat3x3::rotate(float rot) {
//no lint or maybe do something?
multiply(std::array<float, 9>{(float)cos(rot), (float)-sin(rot), 0.0f, (float)sin(rot), (float)cos(rot), 0.0f, 0.0f, 0.0f, 1.0f}); multiply(std::array<float, 9>{(float)cos(rot), (float)-sin(rot), 0.0f, (float)sin(rot), (float)cos(rot), 0.0f, 0.0f, 0.0f, 1.0f});
return *this; return *this;
} }

View file

@ -26,12 +26,13 @@ Hyprutils::Math::CRegion::CRegion(pixman_box32_t* box) {
pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
} }
// What to do with const_cast?
Hyprutils::Math::CRegion::CRegion(const CRegion& other) { Hyprutils::Math::CRegion::CRegion(const CRegion& other) {
pixman_region32_init(&m_rRegion); pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman()); pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
} }
Hyprutils::Math::CRegion::CRegion(CRegion&& other) { Hyprutils::Math::CRegion::CRegion(CRegion&& other) noexcept {
pixman_region32_init(&m_rRegion); pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, other.pixman()); pixman_region32_copy(&m_rRegion, other.pixman());
} }
@ -86,7 +87,7 @@ CRegion& Hyprutils::Math::CRegion::invert(pixman_box32_t* box) {
} }
CRegion& Hyprutils::Math::CRegion::invert(const CBox& box) { CRegion& Hyprutils::Math::CRegion::invert(const CBox& box) {
pixman_box32 pixmanBox = {(int32_t)box.x, (int32_t)box.y, (int32_t)box.w + (int32_t)box.x, (int32_t)box.h + (int32_t)box.y}; pixman_box32 pixmanBox = {.x1 = (int32_t)box.x, .y1 = (int32_t)box.y, .x2 = (int32_t)box.w + (int32_t)box.x, .y2 = (int32_t)box.h + (int32_t)box.y};
return this->invert(&pixmanBox); return this->invert(&pixmanBox);
} }
@ -118,7 +119,7 @@ CRegion& Hyprutils::Math::CRegion::expand(double units) {
clear(); clear();
for (auto& r : rects) { for (auto& r : rects) {
CBox b{(double)r.x1 - units, (double)r.y1 - units, (double)r.x2 - r.x1 + units * 2, (double)r.y2 - r.y1 + units * 2}; CBox b{(double)r.x1 - units, (double)r.y1 - units, (double)r.x2 - r.x1 + (units * 2), (double)r.y2 - r.y1 + (units * 2)};
add(b); add(b);
} }

View file

@ -4,23 +4,18 @@
using namespace Hyprutils::Math; using namespace Hyprutils::Math;
Hyprutils::Math::Vector2D::Vector2D(double xx, double yy) { Hyprutils::Math::Vector2D::Vector2D(double xx, double yy) : x(xx), y(yy) {
x = xx; ;
y = yy;
} }
Hyprutils::Math::Vector2D::Vector2D(int xx, int yy) { Hyprutils::Math::Vector2D::Vector2D(int xx, int yy) : x((double)xx), y((double)yy) {
x = (double)xx; ;
y = (double)yy;
} }
Hyprutils::Math::Vector2D::Vector2D() { Hyprutils::Math::Vector2D::Vector2D() {
x = 0; ;
y = 0;
} }
Hyprutils::Math::Vector2D::~Vector2D() {}
double Hyprutils::Math::Vector2D::normalize() { double Hyprutils::Math::Vector2D::normalize() {
// get max abs // get max abs
const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y); const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y);
@ -48,11 +43,11 @@ double Hyprutils::Math::Vector2D::distance(const Vector2D& other) const {
} }
double Hyprutils::Math::Vector2D::distanceSq(const Vector2D& other) const { double Hyprutils::Math::Vector2D::distanceSq(const Vector2D& other) const {
return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y); return ((x - other.x) * (x - other.x)) + ((y - other.y) * (y - other.y));
} }
double Hyprutils::Math::Vector2D::size() const { double Hyprutils::Math::Vector2D::size() const {
return std::sqrt(x * x + y * y); return std::sqrt((x * x) + (y * y));
} }
Vector2D Hyprutils::Math::Vector2D::getComponentMax(const Vector2D& other) const { Vector2D Hyprutils::Math::Vector2D::getComponentMax(const Vector2D& other) const {

View file

@ -9,9 +9,9 @@ using namespace Hyprutils::OS;
CFileDescriptor::CFileDescriptor(int const fd) : m_fd(fd) {} CFileDescriptor::CFileDescriptor(int const fd) : m_fd(fd) {}
CFileDescriptor::CFileDescriptor(CFileDescriptor&& other) : m_fd(std::exchange(other.m_fd, -1)) {} CFileDescriptor::CFileDescriptor(CFileDescriptor&& other) noexcept : m_fd(std::exchange(other.m_fd, -1)) {}
CFileDescriptor& CFileDescriptor::operator=(CFileDescriptor&& other) { CFileDescriptor& CFileDescriptor::operator=(CFileDescriptor&& other) noexcept {
if (this == &other) // Shit will go haywire if there is duplicate ownership if (this == &other) // Shit will go haywire if there is duplicate ownership
abort(); abort();
@ -37,10 +37,7 @@ int CFileDescriptor::getFlags() const {
} }
bool CFileDescriptor::setFlags(int flags) { bool CFileDescriptor::setFlags(int flags) {
if (fcntl(m_fd, F_SETFD, flags) == -1) return fcntl(m_fd, F_SETFD, flags) != -1;
return false;
return true;
} }
int CFileDescriptor::take() { int CFileDescriptor::take() {

View file

@ -6,7 +6,6 @@ using namespace Hyprutils::OS;
#include <unistd.h> #include <unistd.h>
#include <cstring> #include <cstring>
#include <array> #include <array>
#include <thread>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -89,7 +88,7 @@ bool Hyprutils::OS::CProcess::runSync() {
{.fd = outPipe[0], .events = POLLIN, .revents = 0}, {.fd = outPipe[0], .events = POLLIN, .revents = 0},
{.fd = errPipe[0], .events = POLLIN, .revents = 0}, {.fd = errPipe[0], .events = POLLIN, .revents = 0},
}; };
// Maybe bool or just leave it as it is?
while (1337) { while (1337) {
int ret = poll(pollfds, 2, 5000); int ret = poll(pollfds, 2, 5000);
@ -171,7 +170,7 @@ bool Hyprutils::OS::CProcess::runAsync() {
// run in child // run in child
sigset_t set; sigset_t set;
sigemptyset(&set); sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL); sigprocmask(SIG_SETMASK, &set, nullptr);
grandchild = fork(); grandchild = fork();
if (grandchild == 0) { if (grandchild == 0) {
@ -225,6 +224,6 @@ const std::string& Hyprutils::OS::CProcess::stdErr() {
return err; return err;
} }
const pid_t Hyprutils::OS::CProcess::pid() { pid_t Hyprutils::OS::CProcess::pid() {
return grandchildPid; return grandchildPid;
} }

View file

@ -6,6 +6,7 @@ using namespace Hyprutils;
namespace Hyprutils::Path { namespace Hyprutils::Path {
std::string fullConfigPath(std::string basePath, std::string programName) { std::string fullConfigPath(std::string basePath, std::string programName) {
//no lint or...?
return basePath + "/hypr/" + programName + ".conf"; return basePath + "/hypr/" + programName + ".conf";
} }
@ -62,7 +63,7 @@ namespace Hyprutils::Path {
static const auto xdgConfigDirs = getXdgConfigDirs(); static const auto xdgConfigDirs = getXdgConfigDirs();
if (xdgConfigDirs.has_value()) { if (xdgConfigDirs.has_value()) {
for (auto dir : xdgConfigDirs.value()) { for (auto& dir : xdgConfigDirs.value()) {
if (checkConfigExists(dir, programName)) if (checkConfigExists(dir, programName))
return std::make_pair(fullConfigPath(dir, programName), std::nullopt); return std::make_pair(fullConfigPath(dir, programName), std::nullopt);
} }

View file

@ -1,6 +1,5 @@
#include <hyprutils/signal/Signal.hpp> #include <hyprutils/signal/Signal.hpp>
#include <hyprutils/memory/WeakPtr.hpp> #include <hyprutils/memory/WeakPtr.hpp>
#include <algorithm>
using namespace Hyprutils::Signal; using namespace Hyprutils::Signal;
using namespace Hyprutils::Memory; using namespace Hyprutils::Memory;
@ -18,6 +17,7 @@ void Hyprutils::Signal::CSignal::emit(std::any data) {
} }
std::vector<CStaticSignalListener*> statics; std::vector<CStaticSignalListener*> statics;
statics.reserve(m_vStaticListeners.size());
for (auto& l : m_vStaticListeners) { for (auto& l : m_vStaticListeners) {
statics.emplace_back(l.get()); statics.emplace_back(l.get());
} }
@ -54,4 +54,4 @@ CHyprSignalListener Hyprutils::Signal::CSignal::registerListener(std::function<v
void Hyprutils::Signal::CSignal::registerStaticListener(std::function<void(void*, std::any)> handler, void* owner) { void Hyprutils::Signal::CSignal::registerStaticListener(std::function<void(void*, std::any)> handler, void* owner) {
m_vStaticListeners.emplace_back(std::make_unique<CStaticSignalListener>(handler, owner)); m_vStaticListeners.emplace_back(std::make_unique<CStaticSignalListener>(handler, owner));
} }

View file

@ -6,13 +6,13 @@ using namespace Hyprutils::String;
std::string Hyprutils::String::trim(const std::string& in) { std::string Hyprutils::String::trim(const std::string& in) {
if (in.empty()) if (in.empty())
return in; return in;
//Wsign-compare
int countBefore = 0; size_t countBefore = 0;
while (countBefore < in.length() && std::isspace(in.at(countBefore))) { while (countBefore < in.length() && std::isspace(in.at(countBefore))) {
countBefore++; countBefore++;
} }
//Wsign-compare
int countAfter = 0; size_t countAfter = 0;
while (countAfter < in.length() - countBefore && std::isspace(in.at(in.length() - countAfter - 1))) { while (countAfter < in.length() - countBefore && std::isspace(in.at(in.length() - countAfter - 1))) {
countAfter++; countAfter++;
} }
@ -55,10 +55,7 @@ bool Hyprutils::String::isNumber(const std::string& str, bool allowfloat) {
} }
} }
if (!isdigit(str.back())) return isdigit(str.back()) != 0;
return false;
return true;
} }
void Hyprutils::String::replaceInString(std::string& string, const std::string& what, const std::string& to) { void Hyprutils::String::replaceInString(std::string& string, const std::string& what, const std::string& to) {

View file

@ -22,7 +22,8 @@ Hyprutils::String::CVarList::CVarList(const std::string& in, const size_t lastAr
break; break;
} }
pos += s.size() + 1; pos += s.size() + 1;
m_vArgs.emplace_back(trim(std::string_view{s}.data())); // Is that correct?
m_vArgs.emplace_back(trim(s.data()));
} }
} }
@ -35,4 +36,4 @@ std::string Hyprutils::String::CVarList::join(const std::string& joiner, size_t
} }
return rolling; return rolling;
} }

View file

@ -4,6 +4,7 @@
#include <hyprutils/memory/WeakPtr.hpp> #include <hyprutils/memory/WeakPtr.hpp>
#include <hyprutils/memory/UniquePtr.hpp> #include <hyprutils/memory/UniquePtr.hpp>
#include "shared.hpp" #include "shared.hpp"
#include <cstdint>
#define SP CSharedPointer #define SP CSharedPointer
#define WP CWeakPointer #define WP CWeakPointer
@ -24,7 +25,7 @@ using PANIMVAR = SP<CAnimatedVariable<VarType>>;
template <typename VarType> template <typename VarType>
using PANIMVARREF = WP<CAnimatedVariable<VarType>>; using PANIMVARREF = WP<CAnimatedVariable<VarType>>;
enum eAVTypes { enum eAVTypes : uint8_t {
INT = 1, INT = 1,
TEST, TEST,
}; };
@ -34,12 +35,13 @@ struct SomeTestType {
bool operator==(const SomeTestType& other) const { bool operator==(const SomeTestType& other) const {
return done == other.done; return done == other.done;
} }
// Trivial copy assignment?
SomeTestType& operator=(const SomeTestType& other) { SomeTestType& operator=(const SomeTestType& other) {
done = other.done; done = other.done;
return *this; return *this;
} }
}; };
// Do this static?
CAnimationConfigTree animationTree; CAnimationConfigTree animationTree;
class CMyAnimationManager : public CAnimationManager { class CMyAnimationManager : public CAnimationManager {
@ -106,7 +108,7 @@ class CMyAnimationManager : public CAnimationManager {
; ;
} }
}; };
// Same
UP<CMyAnimationManager> pAnimationManager; UP<CMyAnimationManager> pAnimationManager;
class Subject { class Subject {
@ -120,7 +122,7 @@ class Subject {
PANIMVAR<int> m_iB; PANIMVAR<int> m_iB;
PANIMVAR<SomeTestType> m_iC; PANIMVAR<SomeTestType> m_iC;
}; };
// Same
int config() { int config() {
pAnimationManager = makeUnique<CMyAnimationManager>(); pAnimationManager = makeUnique<CMyAnimationManager>();
@ -299,7 +301,7 @@ int main(int argc, char** argv, char** envp) {
if (v.lock() != vars.back()) if (v.lock() != vars.back())
vars.back()->warp(); vars.back()->warp();
}); });
s.m_iA->setCallbackOnEnd([&s, &vars](auto) { s.m_iA->setCallbackOnEnd([&vars](auto) {
vars.resize(vars.size() + 1); vars.resize(vars.size() + 1);
pAnimationManager->createAnimation(1, vars.back(), "default"); pAnimationManager->createAnimation(1, vars.back(), "default");
*vars.back() = 1337; *vars.back() = 1337;
@ -313,7 +315,7 @@ int main(int argc, char** argv, char** envp) {
EXPECT(s.m_iA->value(), 1000000); EXPECT(s.m_iA->value(), 1000000);
// all vars should be set to 1337 // all vars should be set to 1337
EXPECT(std::find_if(vars.begin(), vars.end(), [](const auto& v) { return v->value() != 1337; }) == vars.end(), true); EXPECT(std::ranges::find_if(vars, [](const auto& v) { return v->value() != 1337; }) == vars.end(), true);
// test one-time callbacks // test one-time callbacks
s.m_iA->resetAllCallbacks(); s.m_iA->resetAllCallbacks();