summaryrefslogtreecommitdiff
path: root/hyprctl
diff options
context:
space:
mode:
authorsam <haminoooin@gmail.com>2025-06-07 03:23:33 +0800
committerGitHub <noreply@github.com>2025-06-06 20:23:33 +0100
commit2794f485cb5d52b3ff572953ddcfaf7fd3c25182 (patch)
tree6dcfa69e39fc5a5f28d809a03d840e56e14f77e9 /hyprctl
parent0ac3bef72473c619194514d01ca55f2ed8c617c3 (diff)
hyprctl: Remove exceptions, use modern error handling (#10664)
Diffstat (limited to 'hyprctl')
-rw-r--r--hyprctl/main.cpp98
1 files changed, 62 insertions, 36 deletions
diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp
index 4a8b9819..e3d39e0b 100644
--- a/hyprctl/main.cpp
+++ b/hyprctl/main.cpp
@@ -14,6 +14,9 @@
#include <unistd.h>
#include <algorithm>
#include <csignal>
+#include <ranges>
+#include <optional>
+#include <charconv>
#include <iostream>
#include <string>
@@ -37,7 +40,6 @@ struct SInstanceData {
uint64_t time;
uint64_t pid;
std::string wlSocket;
- bool valid = true;
};
void log(const std::string& str) {
@@ -64,50 +66,74 @@ std::string getRuntimeDir() {
return std::string{XDG} + "/hypr";
}
+static std::optional<uint64_t> toUInt64(const std::string& str) {
+ uint64_t value = 0;
+ const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
+ if (ec != std::errc() || ptr != str.data() + str.size())
+ return std::nullopt;
+ return value;
+}
+
+static std::optional<SInstanceData> parseInstance(const std::filesystem::directory_entry& entry) {
+ if (!entry.is_directory())
+ return std::nullopt;
+
+ const auto lockPath = entry.path() / "hyprland.lock";
+ std::ifstream ifs(lockPath);
+ if (!ifs.is_open())
+ return std::nullopt;
+
+ SInstanceData data;
+ data.id = entry.path().filename().string();
+
+ const auto first = data.id.find_first_of('_');
+ const auto last = data.id.find_last_of('_');
+ if (first == std::string::npos || last == std::string::npos || last <= first)
+ return std::nullopt;
+
+ auto time = toUInt64(data.id.substr(first + 1, last - first - 1));
+ if (!time)
+ return std::nullopt;
+ data.time = *time;
+
+ std::string line;
+ if (!std::getline(ifs, line))
+ return std::nullopt;
+
+ auto pid = toUInt64(line);
+ if (!pid)
+ return std::nullopt;
+ data.pid = *pid;
+
+ if (!std::getline(ifs, data.wlSocket))
+ return std::nullopt;
+
+ if (std::getline(ifs, line) && !line.empty())
+ return std::nullopt; // more lines than expected
+
+ return data;
+}
+
std::vector<SInstanceData> instances() {
std::vector<SInstanceData> result;
- try {
- if (!std::filesystem::exists(getRuntimeDir()))
- return {};
- } catch (std::exception& e) { return {}; }
+ std::error_code ec;
+ const auto runtimeDir = getRuntimeDir();
+ if (!std::filesystem::exists(runtimeDir, ec) || ec)
+ return result;
- std::error_code ec;
- std::filesystem::directory_iterator it = std::filesystem::directory_iterator(getRuntimeDir(), std::filesystem::directory_options::skip_permission_denied, ec);
+ std::filesystem::directory_iterator it(runtimeDir, std::filesystem::directory_options::skip_permission_denied, ec);
if (ec)
- return {};
- for (const auto& el : it) {
- if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock"))
- continue;
- // read lock
- SInstanceData* data = &result.emplace_back();
- data->id = el.path().filename().string();
-
- try {
- data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1, data->id.find_last_of('_') - (data->id.find_first_of('_') + 1)));
- } catch (std::exception& e) { continue; }
-
- // read file
- std::ifstream ifs(el.path().string() + "/hyprland.lock");
-
- int i = 0;
- for (std::string line; std::getline(ifs, line); ++i) {
- if (i == 0) {
- try {
- data->pid = std::stoull(line);
- } catch (std::exception& e) { continue; }
- } else if (i == 1) {
- data->wlSocket = line;
- } else
- break;
- }
+ return result;
- ifs.close();
+ for (const auto& el : it) {
+ if (auto instance = parseInstance(el))
+ result.emplace_back(std::move(*instance));
}
- std::erase_if(result, [&](const auto& el) { return kill(el.pid, 0) != 0 && errno == ESRCH; });
+ std::erase_if(result, [](const auto& el) { return kill(el.pid, 0) != 0 && errno == ESRCH; });
- std::sort(result.begin(), result.end(), [&](const auto& a, const auto& b) { return a.time < b.time; });
+ std::ranges::sort(result, {}, &SInstanceData::time);
return result;
}