Update upstream source from tag 'upstream/0.2.2'
Update to upstream version '0.2.2'
with Debian dir 158978a390
This commit is contained in:
commit
0fc6e13551
|
|
@ -34,3 +34,13 @@
|
|||
build/
|
||||
.vscode/
|
||||
.cache/
|
||||
|
||||
.cmake/
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
CTestTestfile.cmake
|
||||
DartConfiguration.tcl
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
compile_commands.json
|
||||
hyprutils.pc
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
set(HYPRUTILS_VERSION "0.1.5")
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
string(STRIP ${VER_RAW} HYPRUTILS_VERSION)
|
||||
add_compile_definitions(HYPRUTILS_VERSION="${HYPRUTILS_VERSION}")
|
||||
|
||||
project(hyprutils
|
||||
project(
|
||||
hyprutils
|
||||
VERSION ${HYPRUTILS_VERSION}
|
||||
DESCRIPTION "Small C++ library for utilities used across the Hypr* ecosystem"
|
||||
)
|
||||
DESCRIPTION "Small C++ library for utilities used across the Hypr* ecosystem")
|
||||
|
||||
include(CTest)
|
||||
include(GNUInstallDirs)
|
||||
|
|
@ -34,14 +35,12 @@ find_package(PkgConfig REQUIRED)
|
|||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET pixman-1)
|
||||
|
||||
add_library(hyprutils SHARED ${SRCFILES})
|
||||
target_include_directories( hyprutils
|
||||
target_include_directories(
|
||||
hyprutils
|
||||
PUBLIC "./include"
|
||||
PRIVATE "./src"
|
||||
)
|
||||
set_target_properties(hyprutils PROPERTIES
|
||||
VERSION ${hyprutils_VERSION}
|
||||
SOVERSION 0
|
||||
)
|
||||
PRIVATE "./src")
|
||||
set_target_properties(hyprutils PROPERTIES VERSION ${hyprutils_VERSION}
|
||||
SOVERSION 1)
|
||||
target_link_libraries(hyprutils PkgConfig::deps)
|
||||
|
||||
# tests
|
||||
|
|
@ -49,25 +48,38 @@ add_custom_target(tests)
|
|||
|
||||
add_executable(hyprutils_memory "tests/memory.cpp")
|
||||
target_link_libraries(hyprutils_memory PRIVATE hyprutils PkgConfig::deps)
|
||||
add_test(NAME "Memory" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_memory "memory")
|
||||
add_test(
|
||||
NAME "Memory"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
|
||||
COMMAND hyprutils_memory "memory")
|
||||
add_dependencies(tests hyprutils_memory)
|
||||
|
||||
add_executable(hyprutils_string "tests/string.cpp")
|
||||
target_link_libraries(hyprutils_string PRIVATE hyprutils PkgConfig::deps)
|
||||
add_test(NAME "String" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_string "string")
|
||||
add_test(
|
||||
NAME "String"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
|
||||
COMMAND hyprutils_string "string")
|
||||
add_dependencies(tests hyprutils_string)
|
||||
|
||||
add_executable(hyprutils_signal "tests/signal.cpp")
|
||||
target_link_libraries(hyprutils_signal PRIVATE hyprutils PkgConfig::deps)
|
||||
add_test(NAME "Signal" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_signal "signal")
|
||||
add_test(
|
||||
NAME "Signal"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
|
||||
COMMAND hyprutils_signal "signal")
|
||||
add_dependencies(tests hyprutils_signal)
|
||||
|
||||
add_executable(hyprutils_math "tests/math.cpp")
|
||||
target_link_libraries(hyprutils_math PRIVATE hyprutils PkgConfig::deps)
|
||||
add_test(NAME "Math" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_math "math")
|
||||
add_test(
|
||||
NAME "Math"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
|
||||
COMMAND hyprutils_math "math")
|
||||
add_dependencies(tests hyprutils_math)
|
||||
|
||||
# Installation
|
||||
install(TARGETS hyprutils)
|
||||
install(DIRECTORY "include/hyprutils" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES ${CMAKE_BINARY_DIR}/hyprutils.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/hyprutils.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717602782,
|
||||
"narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=",
|
||||
"lastModified": 1721138476,
|
||||
"narHash": "sha256-+W5eZOhhemLQxelojLxETfbFbc19NWawsXBlapYpqIA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6",
|
||||
"rev": "ad0b5eed1b6031efaed382844806550c3dcb4206",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -23,13 +23,15 @@
|
|||
(builtins.substring 4 2 longDate)
|
||||
(builtins.substring 6 2 longDate)
|
||||
]);
|
||||
|
||||
version = lib.removeSuffix "\n" (builtins.readFile ./VERSION);
|
||||
in {
|
||||
overlays = {
|
||||
default = self.overlays.hyprutils;
|
||||
hyprutils = final: prev: {
|
||||
hyprutils = final.callPackage ./nix/default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
version = "0.pre" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
||||
version = version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
||||
};
|
||||
hyprutils-with-tests = final.hyprutils.override {doCheck = true;};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -135,6 +135,12 @@ namespace Hyprutils::Math {
|
|||
*/
|
||||
Vector2D size() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the size of the box offset by its position.
|
||||
* @return Vector2D representing the bottom right extent of the box.
|
||||
*/
|
||||
Vector2D extent() const;
|
||||
|
||||
/**
|
||||
* @brief Finds the closest point within the box to a given vector.
|
||||
* @param vec Vector from which to find the closest point.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Hyprutils::Math {
|
||||
|
||||
/**
|
||||
* @brief Flag set of box edges
|
||||
*/
|
||||
class CEdges {
|
||||
public:
|
||||
enum eEdges : uint8_t {
|
||||
NONE = 0,
|
||||
TOP = 1,
|
||||
LEFT = 2,
|
||||
BOTTOM = 4,
|
||||
RIGHT = 8,
|
||||
};
|
||||
|
||||
CEdges() = default;
|
||||
CEdges(eEdges edges) : m_edges(edges) {}
|
||||
CEdges(uint8_t edges) : m_edges(static_cast<eEdges>(edges)) {}
|
||||
|
||||
bool operator==(const CEdges& other) {
|
||||
return m_edges == other.m_edges;
|
||||
}
|
||||
|
||||
CEdges operator|(const CEdges& other) {
|
||||
return m_edges | other.m_edges;
|
||||
}
|
||||
|
||||
CEdges operator&(const CEdges& other) {
|
||||
return m_edges & other.m_edges;
|
||||
}
|
||||
|
||||
CEdges operator^(const CEdges& other) {
|
||||
return m_edges ^ other.m_edges;
|
||||
}
|
||||
|
||||
void operator|=(const CEdges& other) {
|
||||
m_edges = (*this | other).m_edges;
|
||||
}
|
||||
|
||||
void operator&=(const CEdges& other) {
|
||||
m_edges = (*this & other).m_edges;
|
||||
}
|
||||
|
||||
void operator^=(const CEdges& other) {
|
||||
m_edges = (*this ^ other).m_edges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the edge set contains the top edge.
|
||||
*/
|
||||
bool top() {
|
||||
return m_edges & TOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the edge set contains the left edge.
|
||||
*/
|
||||
bool left() {
|
||||
return m_edges & LEFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the edge set contains the bottom edge.
|
||||
*/
|
||||
bool bottom() {
|
||||
return m_edges & BOTTOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the edge set contains the right edge.
|
||||
*/
|
||||
bool right() {
|
||||
return m_edges & RIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param top The state the top edge should be set to.
|
||||
*/
|
||||
void setTop(bool top) {
|
||||
m_edges = static_cast<eEdges>((m_edges & ~TOP) | (TOP * top));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param left The state the left edge should be set to.
|
||||
*/
|
||||
void setLeft(bool left) {
|
||||
m_edges = static_cast<eEdges>((m_edges & ~LEFT) | (LEFT * left));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bottom The state the bottom edge should be set to.
|
||||
*/
|
||||
void setBottom(bool bottom) {
|
||||
m_edges = static_cast<eEdges>((m_edges & ~BOTTOM) | (BOTTOM * bottom));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param right The state the right edge should be set to.
|
||||
*/
|
||||
void setRight(bool right) {
|
||||
m_edges = static_cast<eEdges>((m_edges & ~RIGHT) | (RIGHT * right));
|
||||
}
|
||||
|
||||
eEdges m_edges = NONE;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ namespace Hyprutils {
|
|||
CRegion& invert(const CBox& box);
|
||||
CRegion& scale(float scale);
|
||||
CRegion& scale(const Vector2D& scale);
|
||||
CRegion& expand(double units);
|
||||
CRegion& rationalize();
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Hyprutils {
|
|||
namespace CSharedPointer_ {
|
||||
class impl_base {
|
||||
public:
|
||||
virtual ~impl_base(){};
|
||||
virtual ~impl_base() {};
|
||||
|
||||
virtual void inc() noexcept = 0;
|
||||
virtual void dec() noexcept = 0;
|
||||
|
|
@ -31,6 +31,7 @@ namespace Hyprutils {
|
|||
virtual void destroy() noexcept = 0;
|
||||
virtual bool destroying() noexcept = 0;
|
||||
virtual bool dataNonNull() noexcept = 0;
|
||||
virtual void* getData() noexcept = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -107,6 +108,10 @@ namespace Hyprutils {
|
|||
}
|
||||
|
||||
virtual bool dataNonNull() noexcept {
|
||||
return _data != nullptr;
|
||||
}
|
||||
|
||||
virtual void* getData() noexcept {
|
||||
return _data;
|
||||
}
|
||||
|
||||
|
|
@ -213,11 +218,11 @@ namespace Hyprutils {
|
|||
}
|
||||
|
||||
bool operator()(const CSharedPointer& lhs, const CSharedPointer& rhs) const {
|
||||
return (uintptr_t)lhs.impl_ < (uintptr_t)rhs.impl_;
|
||||
return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
|
||||
}
|
||||
|
||||
bool operator<(const CSharedPointer& rhs) const {
|
||||
return (uintptr_t)impl_ < (uintptr_t)rhs.impl_;
|
||||
return reinterpret_cast<uintptr_t>(impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
|
|
@ -234,7 +239,7 @@ namespace Hyprutils {
|
|||
}
|
||||
|
||||
T* get() const {
|
||||
return (T*)(impl_ ? static_cast<CSharedPointer_::impl<T>*>(impl_)->_data : nullptr);
|
||||
return impl_ ? static_cast<T*>(impl_->getData()) : nullptr;
|
||||
}
|
||||
|
||||
unsigned int strongRef() const {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ namespace Hyprutils {
|
|||
/* create a weak ptr from a shared ptr with assignment */
|
||||
template <typename U>
|
||||
validHierarchy<const CWeakPointer<U>&> operator=(const CSharedPointer<U>& rhs) {
|
||||
if ((uintptr_t)impl_ == (uintptr_t)rhs.impl_)
|
||||
if (reinterpret_cast<uintptr_t>(impl_) == reinterpret_cast<uintptr_t>(rhs.impl_))
|
||||
return *this;
|
||||
|
||||
decrementWeak();
|
||||
|
|
@ -139,15 +139,15 @@ namespace Hyprutils {
|
|||
}
|
||||
|
||||
bool operator()(const CWeakPointer& lhs, const CWeakPointer& rhs) const {
|
||||
return (uintptr_t)lhs.impl_ < (uintptr_t)rhs.impl_;
|
||||
return reinterpret_cast<uintptr_t>(lhs.impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
|
||||
}
|
||||
|
||||
bool operator<(const CWeakPointer& rhs) const {
|
||||
return (uintptr_t)impl_ < (uintptr_t)rhs.impl_;
|
||||
return reinterpret_cast<uintptr_t>(impl_) < reinterpret_cast<uintptr_t>(rhs.impl_);
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return (T*)(impl_ ? static_cast<CSharedPointer_::impl<T>*>(impl_)->_data : nullptr);
|
||||
return impl_ ? static_cast<T*>(impl_->getData()) : nullptr;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
#include "../string/VarList.hpp"
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace Hyprutils {
|
||||
namespace Path {
|
||||
/** Check whether a config in the form basePath/hypr/programName.conf exists.
|
||||
@param basePath the path where the config will be searched
|
||||
@param programName name of the program (and config file) to search for
|
||||
*/
|
||||
bool checkConfigExists(const std::string basePath, const std::string programName);
|
||||
|
||||
/** Constructs a full config path given the basePath and programName.
|
||||
@param basePath the path where the config hypr/programName.conf is located
|
||||
@param programName name of the program (and config file)
|
||||
*/
|
||||
std::string fullConfigPath(const std::string basePath, const std::string programName);
|
||||
|
||||
/** Retrieves the absolute path of the $HOME env variable.
|
||||
*/
|
||||
std::optional<std::string> getHome();
|
||||
|
||||
/** Retrieves a CVarList of paths from the $XDG_CONFIG_DIRS env variable.
|
||||
*/
|
||||
std::optional<String::CVarList> getXdgConfigDirs();
|
||||
|
||||
/** Retrieves the absolute path of the $XDG_CONFIG_HOME env variable.
|
||||
*/
|
||||
std::optional<std::string> getXdgConfigHome();
|
||||
|
||||
/** 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 std::nullopt in case of a non-existent value.
|
||||
@param programName name of the program (and config file)
|
||||
*/
|
||||
|
||||
using T = std::optional<std::string>;
|
||||
std::pair<T, T> findConfig(const std::string programName);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ namespace Hyprutils {
|
|||
@param delim if delimiter is 's', use std::isspace
|
||||
@param removeEmpty remove empty args from argv
|
||||
*/
|
||||
CVarList(const std::string& in, const size_t maxSize = 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace Hyprutils {
|
||||
namespace Utils {
|
||||
// calls a function when it goes out of scope
|
||||
class CScopeGuard {
|
||||
public:
|
||||
CScopeGuard(const std::function<void()>& fn_);
|
||||
~CScopeGuard();
|
||||
|
||||
private:
|
||||
std::function<void()> fn;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -199,23 +199,35 @@ Vector2D Hyprutils::Math::CBox::size() const {
|
|||
return {w, h};
|
||||
}
|
||||
|
||||
Vector2D Hyprutils::Math::CBox::extent() const {
|
||||
return pos() + size();
|
||||
}
|
||||
|
||||
Vector2D Hyprutils::Math::CBox::closestPoint(const Vector2D& vec) const {
|
||||
if (containsPoint(vec))
|
||||
return vec;
|
||||
|
||||
Vector2D nv = vec;
|
||||
nv.x = std::clamp(nv.x, x, x + w);
|
||||
nv.y = std::clamp(nv.y, y, y + h);
|
||||
Vector2D maxPoint = {x + w - EPSILON, y + h - EPSILON};
|
||||
|
||||
if (x < maxPoint.x)
|
||||
nv.x = std::clamp(nv.x, x, maxPoint.x);
|
||||
else
|
||||
nv.x = x;
|
||||
if (y < maxPoint.y)
|
||||
nv.y = std::clamp(nv.y, y, maxPoint.y);
|
||||
else
|
||||
nv.y = y;
|
||||
|
||||
if (std::fabs(nv.x - x) < EPSILON)
|
||||
nv.x = x;
|
||||
else if (std::fabs(nv.x - (x + w)) < EPSILON)
|
||||
nv.x = x + w;
|
||||
else if (std::fabs(nv.x - (maxPoint.x)) < EPSILON)
|
||||
nv.x = maxPoint.x;
|
||||
|
||||
if (std::fabs(nv.y - y) < EPSILON)
|
||||
nv.y = y;
|
||||
else if (std::fabs(nv.y - (y + h)) < EPSILON)
|
||||
nv.y = y + h;
|
||||
else if (std::fabs(nv.y - (maxPoint.y)) < EPSILON)
|
||||
nv.y = maxPoint.y;
|
||||
|
||||
return nv;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,19 @@ CRegion& Hyprutils::Math::CRegion::transform(const eTransform t, double w, doubl
|
|||
return *this;
|
||||
}
|
||||
|
||||
CRegion& Hyprutils::Math::CRegion::expand(double units) {
|
||||
auto rects = getRects();
|
||||
|
||||
clear();
|
||||
|
||||
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};
|
||||
add(b);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& Hyprutils::Math::CRegion::rationalize() {
|
||||
intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2});
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
#include <hyprutils/path/Path.hpp>
|
||||
#include <hyprutils/string/VarList.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace Hyprutils;
|
||||
|
||||
namespace Hyprutils::Path {
|
||||
std::string fullConfigPath(std::string basePath, std::string programName) {
|
||||
return basePath + "/hypr/" + programName + ".conf";
|
||||
}
|
||||
|
||||
bool checkConfigExists(std::string basePath, std::string programName) {
|
||||
return std::filesystem::exists(fullConfigPath(basePath, programName));
|
||||
}
|
||||
|
||||
std::optional<std::string> getHome() {
|
||||
static const auto homeDir = getenv("HOME");
|
||||
|
||||
if (!homeDir || !std::filesystem::path(homeDir).is_absolute())
|
||||
return std::nullopt;
|
||||
|
||||
return std::string(homeDir).append("/.config");
|
||||
}
|
||||
|
||||
std::optional<String::CVarList> getXdgConfigDirs() {
|
||||
static const auto xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
|
||||
|
||||
if (!xdgConfigDirs)
|
||||
return std::nullopt;
|
||||
|
||||
static const auto xdgConfigDirsList = String::CVarList(xdgConfigDirs, 0, ':');
|
||||
|
||||
return xdgConfigDirsList;
|
||||
}
|
||||
|
||||
std::optional<std::string> getXdgConfigHome() {
|
||||
static const auto xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
|
||||
if (!xdgConfigHome || !std::filesystem::path(xdgConfigHome).is_absolute())
|
||||
return std::nullopt;
|
||||
|
||||
return xdgConfigHome;
|
||||
}
|
||||
|
||||
using T = std::optional<std::string>;
|
||||
std::pair<T, T> findConfig(std::string programName) {
|
||||
bool xdgConfigHomeExists = false;
|
||||
static const auto xdgConfigHome = getXdgConfigHome();
|
||||
if (xdgConfigHome.has_value()) {
|
||||
xdgConfigHomeExists = true;
|
||||
if (checkConfigExists(xdgConfigHome.value(), programName))
|
||||
return std::make_pair(fullConfigPath(xdgConfigHome.value(), programName), xdgConfigHome);
|
||||
}
|
||||
|
||||
bool homeExists = false;
|
||||
static const auto home = getHome();
|
||||
if (home.has_value()) {
|
||||
homeExists = true;
|
||||
if (checkConfigExists(home.value(), programName))
|
||||
return std::make_pair(fullConfigPath(home.value(), programName), home);
|
||||
}
|
||||
|
||||
static const auto xdgConfigDirs = getXdgConfigDirs();
|
||||
if (xdgConfigDirs.has_value()) {
|
||||
for (auto dir : xdgConfigDirs.value()) {
|
||||
if (checkConfigExists(dir, programName))
|
||||
return std::make_pair(fullConfigPath(dir, programName), std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkConfigExists("/etc/xdg", programName))
|
||||
return std::make_pair(fullConfigPath("/etc/xdg", programName), std::nullopt);
|
||||
|
||||
if (xdgConfigHomeExists)
|
||||
return std::make_pair(std::nullopt, xdgConfigHome);
|
||||
else if (homeExists)
|
||||
return std::make_pair(std::nullopt, home);
|
||||
|
||||
return std::make_pair(std::nullopt, std::nullopt);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,14 +9,10 @@ using namespace Hyprutils::Memory;
|
|||
#define WP CWeakPointer
|
||||
|
||||
void Hyprutils::Signal::CSignal::emit(std::any data) {
|
||||
bool dirty = false;
|
||||
|
||||
std::vector<SP<CSignalListener>> listeners;
|
||||
for (auto& l : m_vListeners) {
|
||||
if (l.expired()) {
|
||||
dirty = true;
|
||||
if (l.expired())
|
||||
continue;
|
||||
}
|
||||
|
||||
listeners.emplace_back(l.lock());
|
||||
}
|
||||
|
|
@ -29,10 +25,9 @@ void Hyprutils::Signal::CSignal::emit(std::any data) {
|
|||
for (auto& l : listeners) {
|
||||
// if there is only one lock, it means the event is only held by the listeners
|
||||
// vector and was removed during our iteration
|
||||
if (l.strongRef() == 1) {
|
||||
dirty = true;
|
||||
if (l.strongRef() == 1)
|
||||
continue;
|
||||
}
|
||||
|
||||
l->emit(data);
|
||||
}
|
||||
|
||||
|
|
@ -43,13 +38,17 @@ void Hyprutils::Signal::CSignal::emit(std::any data) {
|
|||
// release SPs
|
||||
listeners.clear();
|
||||
|
||||
if (dirty)
|
||||
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
|
||||
// we cannot release any expired refs here as one of the listeners could've removed this object and
|
||||
// as such we'd be doing a UAF
|
||||
}
|
||||
|
||||
CHyprSignalListener Hyprutils::Signal::CSignal::registerListener(std::function<void(std::any)> handler) {
|
||||
CHyprSignalListener listener = makeShared<CSignalListener>(handler);
|
||||
m_vListeners.emplace_back(listener);
|
||||
|
||||
// housekeeping: remove any stale listeners
|
||||
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ bool Hyprutils::String::isNumber(const std::string& str, bool allowfloat) {
|
|||
if (str.empty())
|
||||
return false;
|
||||
|
||||
bool decimalParsed = false;
|
||||
|
||||
for (size_t i = 0; i < str.length(); ++i) {
|
||||
const char& c = str.at(i);
|
||||
|
||||
|
|
@ -44,9 +46,11 @@ bool Hyprutils::String::isNumber(const std::string& str, bool allowfloat) {
|
|||
if (i == 0)
|
||||
return false;
|
||||
|
||||
if (str.at(0) == '-')
|
||||
if (decimalParsed)
|
||||
return false;
|
||||
|
||||
decimalParsed = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
using namespace Hyprutils::String;
|
||||
|
||||
Hyprutils::String::CVarList::CVarList(const std::string& in, const size_t lastArgNo, const char delim, const bool removeEmpty) {
|
||||
if (in.empty())
|
||||
if (!removeEmpty && in.empty())
|
||||
m_vArgs.emplace_back("");
|
||||
|
||||
std::string args{in};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
|
||||
using namespace Hyprutils::Utils;
|
||||
|
||||
Hyprutils::Utils::CScopeGuard::CScopeGuard(const std::function<void()>& fn_) : fn(fn_) {
|
||||
;
|
||||
}
|
||||
|
||||
Hyprutils::Utils::CScopeGuard::~CScopeGuard() {
|
||||
if (fn)
|
||||
fn();
|
||||
}
|
||||
|
|
@ -30,6 +30,9 @@ int main(int argc, char** argv, char** envp) {
|
|||
EXPECT(isNumber("vvss", true), false);
|
||||
EXPECT(isNumber("0.9999s", true), false);
|
||||
EXPECT(isNumber("s0.9999", true), false);
|
||||
EXPECT(isNumber("-1.0", true), true);
|
||||
EXPECT(isNumber("-1..0", true), false);
|
||||
EXPECT(isNumber("-10.0000000001", true), true);
|
||||
|
||||
CVarList list("hello world!", 0, 's', true);
|
||||
EXPECT(list[0], "hello");
|
||||
|
|
|
|||
Loading…
Reference in New Issue