RADLib
RADical C++ application framework
RADCore.h
Go to the documentation of this file.
1 #ifndef RADCORE_H
2 #define RADCORE_H
3 
10 #pragma once
11 #include <RADCore/RADLicenseGate.h>
12 #include <iostream>
13 #include <array>
14 #include <vector>
15 #include <functional>
16 #include <queue>
17 #include <mutex>
18 #include <map>
19 #include <chrono>
20 #include <thread>
21 #include <atomic>
22 #include <memory>
23 #include <algorithm>
24 #include <cstdint>
25 #include <sstream>
26 #include <shared_mutex>
27 #include <future>
28 #include <type_traits>
29 #include <optional>
30 #include <string>
31 #include <filesystem>
32 #include <variant>
33 #include <condition_variable>
34 #include <deque>
35 #include <unordered_map>
36 #include <exception>
37 #include <sys/types.h>
38 
39 #if defined(RADLIB_EMBEDDED) && RADLIB_EMBEDDED && !defined(_GLIBCXX_HAS_GTHREADS)
40 namespace std {
41  class mutex {
42  public:
43  void lock() {
44  while (flag_.test_and_set(std::memory_order_acquire)) {}
45  }
46  void unlock() { flag_.clear(std::memory_order_release); }
47  private:
48  std::atomic_flag flag_ = ATOMIC_FLAG_INIT;
49  };
50 
51  class condition_variable {
52  public:
53  void notify_one() {}
54  void notify_all() {}
55  template<typename Lock, typename Predicate>
56  void wait(Lock&, Predicate predicate) {
57  while (!predicate()) {
58  std::atomic_signal_fence(std::memory_order_seq_cst);
59  }
60  }
61  template<typename Lock, typename Clock, typename Duration, typename Predicate>
62  void wait_until(Lock&, const std::chrono::time_point<Clock, Duration>& deadline, Predicate predicate) {
63  while (!predicate() && Clock::now() < deadline) {
64  std::atomic_signal_fence(std::memory_order_seq_cst);
65  }
66  }
67  };
68 }
69 #endif
70 
71 // ==========================================================
72 // RADICAL COMPUTER TECHNOLOGIES - MACRO SUITE
73 // ==========================================================
75 #define RADEvents public
77 #define RADHandlers public
78 
80 #define RADInfo() RADCore::Internal::LogStream(RADCore::LogLevel::INFO)
82 #define RADDebug() RADCore::Internal::LogStream(RADCore::LogLevel::DEBUG)
83 
84 #ifndef RADCORE_VERSION_MAJOR
85 #define RADCORE_VERSION_MAJOR 1
86 #endif
87 
88 #ifndef RADCORE_VERSION_MINOR
89 #define RADCORE_VERSION_MINOR 0
90 #endif
91 
92 #ifndef RADCORE_VERSION_PATCH
93 #define RADCORE_VERSION_PATCH 0
94 #endif
95 
97 #define RAD_EVENT(Name, Signature) RADCore::Event<void Signature> Name
98 
100 #define RADCONNECT(Sender, RadEvent, Receiver, Class, RadEventHandler) \
101  (Sender).RadEvent.connect(Receiver, &Class::RadEventHandler)
102 
104 #define RADCONNECT_QUEUED(Sender, RadEvent, Loop, Receiver, Class, RadEventHandler) \
105  (Sender).RadEvent.connect_queued(Loop, Receiver, &Class::RadEventHandler)
106 
108 #define radtrig(RadEvent, ...) RadEvent.raise(__VA_ARGS__)
109 
111 #define rtrig RADCore::Internal::TriggerHelper() <<
112 
113 namespace RADCore {
114 
116  constexpr int VersionMajor = RADCORE_VERSION_MAJOR;
118  constexpr int VersionMinor = RADCORE_VERSION_MINOR;
120  const char* runtimeEdition();
124  const char* runtimeAuditStamp();
125 
127  class RADObject;
129  class EventLoop;
131  class EventLoopHandle;
133  class Connection;
134 
136  class RADError {
137  public:
139  RADError() = default;
141  RADError(int code, std::string message)
142  : code_(code), message_(std::move(message)) {}
143 
145  bool hasError() const { return code_ != 0 || !message_.empty(); }
147  int code() const { return code_; }
149  const std::string& message() const { return message_; }
150 
151  private:
152  int code_ = 0;
153  std::string message_;
154  };
155 
157  template<typename T>
158  class RADResult {
159  public:
161  static RADResult success(T value) { return RADResult(std::move(value)); }
163  static RADResult failure(RADError error) { return RADResult(std::move(error)); }
164 
166  bool ok() const { return value_.has_value(); }
168  bool hasError() const { return !ok(); }
170  T& value() { return *value_; }
172  const T& value() const { return *value_; }
174  const RADError& error() const { return error_; }
176  T valueOr(T defaultValue) const { return value_ ? *value_ : std::move(defaultValue); }
177 
178  private:
179  explicit RADResult(T value) : value_(std::move(value)) {}
180  explicit RADResult(RADError error) : error_(std::move(error)) {}
181 
182  std::optional<T> value_;
183  RADError error_;
184  };
185 
187  template<>
188  class RADResult<void> {
189  public:
191  static RADResult success() { return RADResult(); }
193  static RADResult failure(RADError error) { return RADResult(std::move(error)); }
195  bool ok() const { return !error_.hasError(); }
197  bool hasError() const { return error_.hasError(); }
199  const RADError& error() const { return error_; }
200 
201  private:
202  RADResult() = default;
203  explicit RADResult(RADError error) : error_(std::move(error)) {}
204  RADError error_;
205  };
206 
208  template<typename T>
209  class RADSpan {
210  public:
212  RADSpan() = default;
214  RADSpan(T* data, size_t size) : data_(data), size_(size) {}
216  template<typename Container>
217  explicit RADSpan(Container& container) : data_(container.data()), size_(container.size()) {}
218 
220  T* data() const { return data_; }
222  size_t size() const { return size_; }
224  bool empty() const { return size_ == 0; }
226  T& operator[](size_t index) const { return data_[index]; }
228  T* begin() const { return data_; }
230  T* end() const { return data_ + size_; }
231 
232  private:
233  T* data_ = nullptr;
234  size_t size_ = 0;
235  };
236 
241 
244  public:
248  void restart() { start_ = std::chrono::steady_clock::now(); }
250  int64_t elapsedNanoseconds() const {
251  return std::chrono::duration_cast<std::chrono::nanoseconds>(
252  std::chrono::steady_clock::now() - start_).count();
253  }
255  int64_t elapsedMicroseconds() const { return elapsedNanoseconds() / 1000; }
257  int64_t elapsedMilliseconds() const { return elapsedNanoseconds() / 1000000; }
259  double elapsedSeconds() const { return static_cast<double>(elapsedNanoseconds()) / 1000000000.0; }
260 
261  private:
262  std::chrono::steady_clock::time_point start_;
263  };
264 
267  public:
269  RADDeadlineTimer() = default;
271  explicit RADDeadlineTimer(int64_t intervalMs)
272  : deadline_(std::chrono::steady_clock::now() + std::chrono::milliseconds(intervalMs)),
273  valid_(true) {}
275  bool isValid() const { return valid_; }
277  bool hasExpired() const { return valid_ && std::chrono::steady_clock::now() >= deadline_; }
279  int64_t remainingMilliseconds() const {
280  if (!valid_) return 0;
281  const auto now = std::chrono::steady_clock::now();
282  if (now >= deadline_) return 0;
283  return std::chrono::duration_cast<std::chrono::milliseconds>(deadline_ - now).count();
284  }
285 
286  private:
287  std::chrono::steady_clock::time_point deadline_{};
288  bool valid_ = false;
289  };
290 
293  public:
295  RADCancellationToken() : cancelled_(std::make_shared<std::atomic_bool>(false)) {}
297  bool isCancellationRequested() const {
298  return cancelled_ && cancelled_->load(std::memory_order_acquire);
299  }
300 
301  private:
302  friend class RADCancellationSource;
303  explicit RADCancellationToken(std::shared_ptr<std::atomic_bool> cancelled)
304  : cancelled_(std::move(cancelled)) {}
305  std::shared_ptr<std::atomic_bool> cancelled_;
306  };
307 
310  public:
312  RADCancellationSource() : cancelled_(std::make_shared<std::atomic_bool>(false)) {}
314  RADCancellationToken token() const { return RADCancellationToken(cancelled_); }
316  void cancel() { cancelled_->store(true, std::memory_order_release); }
318  bool isCancellationRequested() const { return cancelled_->load(std::memory_order_acquire); }
319 
320  private:
321  std::shared_ptr<std::atomic_bool> cancelled_;
322  };
323 
325  enum class OpenMode : uint32_t {
327  NotOpen = 0,
329  ReadOnly = 1 << 0,
331  WriteOnly = 1 << 1,
333  ReadWrite = (1 << 0) | (1 << 1),
335  Append = 1 << 2,
337  Truncate = 1 << 3,
339  Text = 1 << 4
340  };
341 
343  constexpr OpenMode operator|(OpenMode lhs, OpenMode rhs) {
344  return static_cast<OpenMode>(
345  static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
346  }
347 
349  constexpr OpenMode operator&(OpenMode lhs, OpenMode rhs) {
350  return static_cast<OpenMode>(
351  static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs));
352  }
353 
355  constexpr bool hasOpenMode(OpenMode mode, OpenMode flag) {
356  return (static_cast<uint32_t>(mode) & static_cast<uint32_t>(flag)) != 0;
357  }
358 
360  enum class ByteOrder {
362  LittleEndian,
364  BigEndian
365  };
366 
368  enum class DataStreamStatus {
370  Ok,
372  ReadPastEnd,
374  WriteFailed,
376  ReadFailed
377  };
378 
380  enum class VariantType {
382  Invalid,
384  Bool,
386  Int64,
388  Double,
390  String,
392  ByteArray
393  };
394 
396  class RADVariant {
397  public:
401  RADVariant(bool value);
403  RADVariant(int value);
405  RADVariant(int64_t value);
407  RADVariant(double value);
409  RADVariant(const char* value);
411  RADVariant(std::string value);
413  RADVariant(std::vector<uint8_t> value);
414 
416  VariantType type() const;
418  bool isValid() const;
420  bool toBool(bool defaultValue = false) const;
422  int64_t toInt64(int64_t defaultValue = 0) const;
424  double toDouble(double defaultValue = 0.0) const;
426  std::string toString(const std::string& defaultValue = {}) const;
428  std::vector<uint8_t> toByteArray() const;
429 
430  private:
431  using Storage = std::variant<std::monostate, bool, int64_t, double, std::string, std::vector<uint8_t>>;
432  Storage data_;
433  };
434 
436  class RADDateTime {
437  public:
441  explicit RADDateTime(int64_t unixMilliseconds);
442 
444  static RADDateTime nowUtc();
446  static RADDateTime fromUnixMilliseconds(int64_t unixMilliseconds);
448  static std::optional<RADDateTime> fromIsoString(const std::string& isoString);
449 
451  int64_t toUnixMilliseconds() const;
453  std::string toIsoString() const;
455  bool isValid() const;
456 
457  private:
458  int64_t unixMilliseconds_ = 0;
459  bool valid_ = false;
460  };
461 
463  class RADUuid {
464  public:
468  explicit RADUuid(std::array<uint8_t, 16> bytes);
469 
471  static RADUuid createUuid();
473  static std::optional<RADUuid> fromString(const std::string& text);
474 
476  std::string toString() const;
478  bool isNull() const;
480  const std::array<uint8_t, 16>& bytes() const;
481 
482  private:
483  std::array<uint8_t, 16> bytes_{};
484  };
485 
487  class RADUrl {
488  public:
490  RADUrl() = default;
492  explicit RADUrl(std::string url);
493 
495  static std::optional<RADUrl> parse(const std::string& url);
496 
498  bool isValid() const;
500  const std::string& scheme() const;
502  const std::string& host() const;
504  uint16_t port(uint16_t defaultPort = 0) const;
506  const std::string& path() const;
508  const std::string& query() const;
510  const std::string& fragment() const;
512  std::string toString() const;
513 
514  private:
515  bool valid_ = false;
516  std::string scheme_;
517  std::string host_;
518  uint16_t port_ = 0;
519  std::string path_ = "/";
520  std::string query_;
521  std::string fragment_;
522  };
523 
525  enum class JsonType {
527  Null,
529  Bool,
531  Number,
533  String,
535  Array,
537  Object
538  };
539 
541  class RADJsonValue {
542  public:
546  RADJsonValue(std::nullptr_t);
548  RADJsonValue(bool value);
550  RADJsonValue(int value);
552  RADJsonValue(int64_t value);
554  RADJsonValue(double value);
556  RADJsonValue(const char* value);
558  RADJsonValue(std::string value);
560  RADJsonValue(const RADJsonValue& other);
562  RADJsonValue(RADJsonValue&& other) noexcept = default;
566  RADJsonValue& operator=(RADJsonValue&& other) noexcept = default;
567 
569  static RADJsonValue array();
572 
574  JsonType type() const;
576  bool isNull() const;
578  bool isBool() const;
580  bool isNumber() const;
582  bool isString() const;
584  bool isArray() const;
586  bool isObject() const;
587 
589  bool toBool(bool defaultValue = false) const;
591  double toNumber(double defaultValue = 0.0) const;
593  int toInt(int defaultValue = 0) const;
595  int64_t toInt64(int64_t defaultValue = 0) const;
597  std::string toString(const std::string& defaultValue = {}) const;
598 
600  size_t size() const;
602  bool contains(const std::string& key) const;
604  std::vector<std::string> keys() const;
606  void append(RADJsonValue value);
608  void remove(const std::string& key);
609 
611  RADJsonValue& operator[](const std::string& key);
613  const RADJsonValue& operator[](const std::string& key) const;
615  RADJsonValue& operator[](size_t index);
617  const RADJsonValue& operator[](size_t index) const;
618 
620  std::string toJson(bool pretty = false, int indent = 0) const;
621 
622  private:
623  struct ArrayData;
624  struct ObjectData;
625 
626  using Storage = std::variant<
627  std::nullptr_t,
628  bool,
629  int64_t,
630  double,
631  std::string,
632  std::shared_ptr<ArrayData>,
633  std::shared_ptr<ObjectData>>;
634 
635  void ensureArray();
636  void ensureObject();
637  const ArrayData* arrayData() const;
638  ArrayData* arrayData();
639  const ObjectData* objectData() const;
640  ObjectData* objectData();
641  static Storage cloneStorage(const Storage& storage);
642  static const RADJsonValue& nullValue();
643 
644  Storage data_;
645  };
646 
649  public:
654 
656  static std::optional<RADJsonDocument> fromJson(const std::string& json, std::string* error = nullptr);
658  static std::optional<RADJsonDocument> fromFile(const std::string& path, std::string* error = nullptr);
659 
661  const RADJsonValue& root() const;
665  std::string toJson(bool pretty = false) const;
667  bool toFile(const std::string& path, bool pretty = true, std::string* error = nullptr) const;
668 
669  private:
670  RADJsonValue root_;
671  };
672 
674  class RADSettings {
675  public:
677  explicit RADSettings(std::string fileName);
678 
680  const std::string& fileName() const;
682  bool load(std::string* error = nullptr);
684  bool save(std::string* error = nullptr) const;
686  bool contains(const std::string& key) const;
688  RADJsonValue value(const std::string& key, RADJsonValue defaultValue = {}) const;
690  void setValue(const std::string& key, RADJsonValue value);
692  void remove(const std::string& key);
694  void clear();
695 
696  private:
697  std::string fileName_;
698  RADJsonValue root_;
699  };
700 
702  namespace FileSystem {
704  enum class StandardPath {
706  Home,
708  Desktop,
710  Documents,
712  Downloads,
714  Config,
716  Data,
718  Cache,
720  Temp,
722  Executable,
724  Current
725  };
726 
728  enum class DirectoryEntryType {
730  Unknown,
732  File,
734  Directory,
736  Symlink
737  };
738 
740  struct DirectoryEntry {
742  std::string path;
744  std::string name;
748  uintmax_t size = 0;
750  int64_t modifiedUnixMs = 0;
751  };
752 
754  bool exists(const std::string& path);
756  bool isFile(const std::string& path);
758  bool isDirectory(const std::string& path);
760  bool createDirectories(const std::string& path);
762  bool remove(const std::string& path);
764  bool copyFile(const std::string& source, const std::string& destination, bool overwrite = true);
766  std::string currentPath();
768  std::string tempDirectoryPath();
770  std::string standardPath(StandardPath path);
772  std::string fileName(const std::string& path);
774  std::string extension(const std::string& path);
776  std::string parentPath(const std::string& path);
778  std::vector<DirectoryEntry> listEntries(const std::string& path, bool recursive = false);
780  std::vector<std::string> listDirectory(const std::string& path);
782  std::string mimeTypeForFile(const std::string& path);
784  std::optional<std::string> readTextFile(const std::string& path);
786  bool writeTextFile(const std::string& path, const std::string& text);
787  }
788 
791  public:
793  explicit RADTemporaryDirectory(std::string prefix = "radlib");
796 
805 
807  bool isValid() const;
809  const std::string& path() const;
811  void setAutoRemove(bool enabled);
813  bool autoRemove() const;
815  bool remove();
816 
817  private:
818  std::string path_;
819  bool autoRemove_ = true;
820  };
821 
824  public:
826  explicit RADTemporaryFile(std::string prefix = "radlib");
829 
838 
840  bool isValid() const;
842  const std::string& fileName() const;
844  int fd() const;
846  void setAutoRemove(bool enabled);
848  bool autoRemove() const;
850  bool remove();
851 
852  private:
853  std::string fileName_;
854  int fd_ = -1;
855  bool autoRemove_ = true;
856  };
857 
859  class RADLockFile {
860  public:
862  explicit RADLockFile(std::string fileName);
865 
867  RADLockFile(const RADLockFile&) = delete;
869  RADLockFile& operator=(const RADLockFile&) = delete;
870 
872  bool tryLock();
874  void unlock();
876  bool isLocked() const;
878  const std::string& fileName() const;
879 
880  private:
881  std::string fileName_;
882  int fd_ = -1;
883  };
884 
886  enum class ProcessState {
888  NotRunning,
890  Running,
892  Finished,
895  };
896 
898  struct ThreadAffinity {
900  std::thread::id threadId;
903  };
904 
906  template<typename Signature> class Event;
907 
908  namespace Internal {
909  template<typename T> struct ExtractArgs;
910  template<typename Ret, typename... Args>
911  struct ExtractArgs<Ret(*)(Args...)> { using type = void(Args...); };
912 
913  template<typename... Args> struct EventBinder;
914  struct TriggerHelper;
915  }
916 
924  enum class Priority : int { LOW = 0, NORMAL = 1, HIGH = 2 };
925 
929  size_t connectionId;
931  std::function<void()> disconnectCallback;
932  };
933 
935  class Connection {
936  public:
938  struct State {
940  std::atomic_bool connected{false};
942  std::function<void()> disconnectCallback;
943  };
944 
946  Connection() = default;
947 
949  void disconnect();
951  bool isConnected() const;
952 
953  private:
954  explicit Connection(std::shared_ptr<State> state);
955  static Connection create(std::function<void()> disconnectCallback);
956 
957  std::shared_ptr<State> state_;
958 
959  template<typename Signature> friend class Event;
960  };
961 
963  class RADObject {
964  public:
968  virtual ~RADObject();
970  void registerLink(const ConnectionRecord& record);
971 
973  std::thread::id threadId() const;
979  std::weak_ptr<void> lifetimeToken() const;
981  void moveToThread(std::thread::id tId, EventLoop* loop = nullptr);
982  private:
983  struct Impl;
984  std::unique_ptr<Impl> pImpl;
985  };
986 
988  class EventLoop {
989  public:
991  using Task = std::function<void()>;
996 
998  void post(Priority priority, Task task);
1000  void post(Task task);
1004  void exec();
1006  void quit();
1008  bool isEventThread() const;
1012  bool postDelayed(int delayMs, Task task);
1013 
1015  template<typename F, typename... Args>
1016  void post(Priority priority, F&& f, Args&&... args) {
1017  auto boundTask = [f = std::forward<F>(f), ...args = std::forward<Args>(args)]() mutable {
1018  f(std::forward<Args>(args)...);
1019  };
1020  post(priority, Task(boundTask));
1021  }
1022 
1024  template<typename F, typename... Args>
1025  void post(F&& f, Args&&... args) {
1026  auto boundTask = [f = std::forward<F>(f), ...args = std::forward<Args>(args)]() mutable {
1027  f(std::forward<Args>(args)...);
1028  };
1029  post(Task(boundTask));
1030  }
1031 
1032  private:
1033  struct Impl;
1034  friend class EventLoopHandle;
1035  std::shared_ptr<Impl> pImpl;
1036  };
1037 
1040  public:
1042  EventLoopHandle() = default;
1044  bool isValid() const;
1046  bool post(Priority priority, EventLoop::Task task) const;
1048  bool post(EventLoop::Task task) const;
1050  bool postDelayed(int delayMs, EventLoop::Task task) const;
1051 
1052  private:
1053  friend class EventLoop;
1054  explicit EventLoopHandle(std::weak_ptr<EventLoop::Impl> impl);
1055  std::weak_ptr<EventLoop::Impl> impl_;
1056  };
1057 
1059  void singleShot(int intervalMs, EventLoop& targetLoop, EventLoop::Task task);
1060 
1062  template<typename F>
1063  void invoke(EventLoop& loop, F&& task) {
1064  loop.post(std::forward<F>(task));
1065  }
1066 
1068  template<typename F>
1069  auto invokeBlocking(EventLoop& loop, F&& task) -> std::invoke_result_t<F> {
1070  using ReturnType = std::invoke_result_t<F>;
1071 
1072  if (loop.isEventThread()) {
1073  if constexpr (std::is_void_v<ReturnType>) {
1074  std::forward<F>(task)();
1075  return;
1076  } else {
1077  return std::forward<F>(task)();
1078  }
1079  }
1080 
1081  auto promise = std::make_shared<std::promise<ReturnType>>();
1082  auto future = promise->get_future();
1083  auto taskPtr = std::make_shared<std::decay_t<F>>(std::forward<F>(task));
1084 
1085  loop.post([promise, taskPtr]() mutable {
1086  try {
1087  if constexpr (std::is_void_v<ReturnType>) {
1088  (*taskPtr)();
1089  promise->set_value();
1090  } else {
1091  promise->set_value((*taskPtr)());
1092  }
1093  } catch (...) {
1094  promise->set_exception(std::current_exception());
1095  }
1096  });
1097 
1098  if constexpr (std::is_void_v<ReturnType>) {
1099  future.get();
1100  return;
1101  } else {
1102  return future.get();
1103  }
1104  }
1105 
1108  public:
1110  using RawTask = std::function<void()>;
1111 
1113  void addRawHandler(size_t id, RawTask task);
1115  void removeRawHandler(size_t id);
1117  void invokeAll();
1118  private:
1119  struct BackendSlot { size_t id; RawTask task; };
1120  std::vector<BackendSlot> rawHandlers_;
1121  std::mutex backendMutex_;
1122  };
1123 
1125  template<typename... Args>
1126  class Event<void(Args...)> {
1127  public:
1129  struct LiveHandler {
1131  size_t id;
1133  std::function<void(Args...)> dispatch;
1135  std::shared_ptr<Connection::State> connectionState;
1136  };
1137 
1139  Event() : aliveToken_(std::make_shared<std::atomic_bool>(true)) {}
1140 
1143  // Explicitly invalidate our token to instantly tell all bound receivers that this event is dead!
1144  aliveToken_->store(false, std::memory_order_release);
1145  std::lock_guard<std::mutex> lock(eventMutex_);
1146  for (const auto& handler : handlers_) {
1147  if (handler.connectionState) {
1148  handler.connectionState->connected.store(false, std::memory_order_release);
1149  }
1150  }
1151  }
1152 
1154  template<typename T>
1155  Connection connect(T* receiver, void(T::*memberFunc)(Args...)) {
1156  size_t uniqueId = generateUniqueId();
1157  RADObject* baseReceiver = static_cast<RADObject*>(receiver);
1158 
1159  auto receiverToken = baseReceiver->lifetimeToken();
1160  auto dispatchBridge = [receiverToken, receiver, memberFunc, baseReceiver](Args... args) {
1161  auto receiverLife = receiverToken.lock();
1162  if (!receiverLife) return;
1163 
1164  const ThreadAffinity affinity = baseReceiver->threadAffinity();
1165  if (affinity.threadId == std::this_thread::get_id()) {
1166  (receiver->*memberFunc)(args...);
1167  } else {
1168  EventLoop* targetLoop = affinity.eventLoop;
1169  if (targetLoop) {
1170  targetLoop->post([receiverToken, receiver, memberFunc, ...args = std::forward<Args>(args)]() mutable {
1171  auto queuedReceiverLife = receiverToken.lock();
1172  if (!queuedReceiverLife) return;
1173  (receiver->*memberFunc)(std::forward<Args>(args)...);
1174  });
1175  } else {
1176  (receiver->*memberFunc)(args...);
1177  }
1178  }
1179  };
1180 
1181  backend_.addRawHandler(uniqueId, [this]() {});
1182 
1183  auto token = aliveToken_;
1184  Connection connection = Connection::create([this, uniqueId, token]() {
1185  if (token->load(std::memory_order_acquire)) {
1186  this->disconnect(uniqueId);
1187  }
1188  });
1189 
1190  {
1191  std::lock_guard<std::mutex> lock(eventMutex_);
1192  handlers_.push_back({
1193  uniqueId,
1194  [dispatchBridge](Args... args) { dispatchBridge(args...); },
1195  connection.state_
1196  });
1197  }
1198 
1199  // Capture a copy of our aliveToken inside the registration block!
1200  baseReceiver->registerLink({ uniqueId, [connection]() mutable {
1201  connection.disconnect();
1202  }});
1203 
1204  return connection;
1205  }
1206 
1208  template<typename T>
1209  Connection connect_queued(EventLoop& loop, T* receiver, void(T::*memberFunc)(Args...)) {
1210  size_t uniqueId = generateUniqueId();
1211  RADObject* baseObject = static_cast<RADObject*>(receiver);
1212  auto receiverToken = baseObject->lifetimeToken();
1213 
1214  auto cb = [&loop, receiverToken, receiver, memberFunc](Args... args) {
1215  loop.post([receiverToken, receiver, memberFunc, ...args = std::forward<Args>(args)]() mutable {
1216  auto receiverLife = receiverToken.lock();
1217  if (!receiverLife) return;
1218  (receiver->*memberFunc)(std::forward<Args>(args)...);
1219  });
1220  };
1221 
1222  backend_.addRawHandler(uniqueId, [cb]() {});
1223 
1224  auto token = aliveToken_;
1225  Connection connection = Connection::create([&loop, this, uniqueId, token]() {
1226  if (token->load(std::memory_order_acquire)) {
1227  loop.post(Priority::HIGH, [this, uniqueId]() { this->disconnect(uniqueId); });
1228  }
1229  });
1230 
1231  {
1232  std::lock_guard<std::mutex> lock(eventMutex_);
1233  handlers_.push_back({
1234  uniqueId,
1235  [cb](Args... args) { cb(args...); },
1236  connection.state_
1237  });
1238  }
1239 
1240  baseObject->registerLink({ uniqueId, [connection]() mutable {
1241  connection.disconnect();
1242  }});
1243 
1244  return connection;
1245  }
1246 
1248  void disconnect(size_t targetId) {
1249  std::lock_guard<std::mutex> lock(eventMutex_);
1250  for (const auto& handler : handlers_) {
1251  if (handler.id == targetId && handler.connectionState) {
1252  handler.connectionState->connected.store(false, std::memory_order_release);
1253  }
1254  }
1255  handlers_.erase(std::remove_if(handlers_.begin(), handlers_.end(), [targetId](const LiveHandler& handler) {
1256  return handler.id == targetId;
1257  }), handlers_.end());
1258  backend_.removeRawHandler(targetId);
1259  }
1260 
1262  void raise(Args... args) {
1263  std::vector<std::function<void(Args...)>> localHandlers;
1264  {
1265  std::lock_guard<std::mutex> lock(eventMutex_);
1266  localHandlers.reserve(handlers_.size());
1267  for (const auto& handler : handlers_) {
1268  localHandlers.push_back(handler.dispatch);
1269  }
1270  }
1271  for (const auto& handler : localHandlers) {
1272  if (handler) handler(args...);
1273  }
1274  backend_.invokeAll();
1275  }
1276 
1277  private:
1278  size_t generateUniqueId() { static std::atomic<size_t> s_counter{0}; return s_counter++; }
1279  std::vector<LiveHandler> handlers_;
1280  std::mutex eventMutex_;
1281  EventBackend backend_;
1282  std::shared_ptr<std::atomic_bool> aliveToken_; // Token tracking emitter lifespan state parameters
1283  };
1284 
1286  class RADIODevice : public RADObject {
1287  public:
1288  RADEvents:
1290  RAD_EVENT(readyRead, ());
1292  RAD_EVENT(bytesWritten, (size_t));
1294  RAD_EVENT(errorOccurred, (std::string));
1295 
1297  virtual ~RADIODevice() = default;
1298 
1300  virtual bool open(OpenMode mode) = 0;
1302  virtual void close() = 0;
1304  virtual bool isOpen() const = 0;
1306  virtual ssize_t readData(void* buffer, size_t maxBytes) = 0;
1308  virtual ssize_t writeData(const void* data, size_t size) = 0;
1309 
1311  std::vector<uint8_t> read(size_t maxBytes);
1313  std::vector<uint8_t> readAll(size_t chunkSize = 8192);
1315  ssize_t write(const std::vector<uint8_t>& data);
1317  ssize_t write(const std::string& text);
1318  };
1319 
1321  class RADBuffer : public RADIODevice {
1322  public:
1326  explicit RADBuffer(std::vector<uint8_t> data);
1328  ~RADBuffer() override;
1329 
1331  bool open(OpenMode mode) override;
1333  void close() override;
1335  bool isOpen() const override;
1337  ssize_t readData(void* buffer, size_t maxBytes) override;
1339  ssize_t writeData(const void* data, size_t size) override;
1340 
1342  bool seek(size_t position);
1344  size_t position() const;
1346  size_t size() const;
1348  const std::vector<uint8_t>& data() const;
1350  void clear();
1351 
1352  private:
1353  struct Impl;
1354  std::unique_ptr<Impl> pImpl_;
1355  };
1356 
1358  class RADFile : public RADIODevice {
1359  public:
1363  explicit RADFile(std::string fileName);
1365  ~RADFile() override;
1366 
1368  void setFileName(std::string fileName);
1370  const std::string& fileName() const;
1371 
1373  bool open(OpenMode mode) override;
1375  void close() override;
1377  bool isOpen() const override;
1379  ssize_t readData(void* buffer, size_t maxBytes) override;
1381  ssize_t writeData(const void* data, size_t size) override;
1382 
1384  bool seek(size_t position);
1386  size_t position() const;
1388  size_t size() const;
1389 
1390  private:
1391  struct Impl;
1392  std::unique_ptr<Impl> pImpl_;
1393  };
1394 
1397  public:
1399  explicit RADDataStream(RADIODevice& device);
1400 
1402  void setByteOrder(ByteOrder byteOrder);
1408  bool ok() const;
1410  void resetStatus();
1411 
1413  RADDataStream& operator<<(uint8_t value);
1415  RADDataStream& operator<<(uint16_t value);
1417  RADDataStream& operator<<(uint32_t value);
1419  RADDataStream& operator<<(uint64_t value);
1421  RADDataStream& operator<<(int8_t value);
1423  RADDataStream& operator<<(int16_t value);
1425  RADDataStream& operator<<(int32_t value);
1427  RADDataStream& operator<<(int64_t value);
1429  RADDataStream& operator<<(float value);
1431  RADDataStream& operator<<(double value);
1433  RADDataStream& operator<<(const std::string& value);
1435  RADDataStream& operator<<(const std::vector<uint8_t>& value);
1436 
1438  RADDataStream& operator>>(uint8_t& value);
1440  RADDataStream& operator>>(uint16_t& value);
1442  RADDataStream& operator>>(uint32_t& value);
1444  RADDataStream& operator>>(uint64_t& value);
1446  RADDataStream& operator>>(int8_t& value);
1448  RADDataStream& operator>>(int16_t& value);
1450  RADDataStream& operator>>(int32_t& value);
1452  RADDataStream& operator>>(int64_t& value);
1454  RADDataStream& operator>>(float& value);
1456  RADDataStream& operator>>(double& value);
1458  RADDataStream& operator>>(std::string& value);
1460  RADDataStream& operator>>(std::vector<uint8_t>& value);
1461 
1462  private:
1463  bool writeRaw(const void* data, size_t size);
1464  bool readRaw(void* data, size_t size);
1465  template<typename T>
1466  bool writeIntegral(T value);
1467  template<typename T>
1468  bool readIntegral(T& value);
1469 
1470  RADIODevice& device_;
1471  ByteOrder byteOrder_ = ByteOrder::LittleEndian;
1472  DataStreamStatus status_ = DataStreamStatus::Ok;
1473  };
1474 
1476  enum class FileSystemEvent {
1478  Created,
1480  Modified,
1482  Removed,
1484  Moved,
1486  Overflow,
1488  WatchLost,
1490  Unknown
1491  };
1492 
1495  public:
1496  RADEvents:
1498  RAD_EVENT(changed, (std::string, FileSystemEvent));
1500  RAD_EVENT(errorOccurred, (std::string));
1501 
1506 
1508  bool addPath(const std::string& path);
1510  bool addPath(const std::string& path, bool recursive);
1512  void removePath(const std::string& path);
1514  void clear();
1516  std::vector<std::string> paths() const;
1517 
1518  private:
1519  struct Impl;
1520  std::shared_ptr<Impl> pImpl_;
1521  };
1522 
1523 #if !defined(RADLIB_EMBEDDED) || !RADLIB_EMBEDDED
1525  class RADFuture {
1526  public:
1530  explicit RADFuture(std::shared_ptr<std::shared_future<RADVariant>> future);
1531 
1533  bool isValid() const;
1535  bool isFinished() const;
1537  RADVariant result(RADVariant defaultValue = {}) const;
1539  void wait() const;
1540 
1541  private:
1542  std::shared_ptr<std::shared_future<RADVariant>> future_;
1543  };
1544 
1546  template<typename T>
1547  class RADFutureT {
1548  public:
1550  RADFutureT() = default;
1552  explicit RADFutureT(std::shared_ptr<std::shared_future<T>> future)
1553  : future_(std::move(future)) {}
1554 
1556  bool isValid() const { return future_ && future_->valid(); }
1558  bool isFinished() const {
1559  return isValid() && future_->wait_for(std::chrono::seconds(0)) == std::future_status::ready;
1560  }
1562  void wait() const { if (isValid()) future_->wait(); }
1564  T result() const { return future_->get(); }
1566  T resultOr(T defaultValue) const {
1567  if (!isFinished()) return defaultValue;
1568  try { return future_->get(); } catch (...) { return defaultValue; }
1569  }
1570 
1572  template<typename F>
1573  void then(EventLoop& loop, F&& continuation) const {
1574  auto future = future_;
1575  auto handle = loop.handle();
1576  auto fn = std::make_shared<std::decay_t<F>>(std::forward<F>(continuation));
1577  std::thread([future, handle, fn]() mutable {
1578  if (!future) return;
1579  try {
1580  T value = future->get();
1581  handle.post([fn, value = std::move(value)]() mutable { (*fn)(std::move(value)); });
1582  } catch (...) {
1583  handle.post([fn]() mutable { (*fn)(T{}); });
1584  }
1585  }).detach();
1586  }
1587 
1588  private:
1589  std::shared_ptr<std::shared_future<T>> future_;
1590  };
1591 
1593  template<>
1594  class RADFutureT<void> {
1595  public:
1597  RADFutureT() = default;
1599  explicit RADFutureT(std::shared_ptr<std::shared_future<void>> future)
1600  : future_(std::move(future)) {}
1602  bool isValid() const { return future_ && future_->valid(); }
1604  bool isFinished() const {
1605  return isValid() && future_->wait_for(std::chrono::seconds(0)) == std::future_status::ready;
1606  }
1608  void wait() const { if (isValid()) future_->wait(); }
1610  void result() const { if (future_) future_->get(); }
1612  template<typename F>
1613  void then(EventLoop& loop, F&& continuation) const {
1614  auto future = future_;
1615  auto handle = loop.handle();
1616  auto fn = std::make_shared<std::decay_t<F>>(std::forward<F>(continuation));
1617  std::thread([future, handle, fn]() mutable {
1618  if (future) {
1619  try { future->get(); } catch (...) {}
1620  }
1621  handle.post([fn]() mutable { (*fn)(); });
1622  }).detach();
1623  }
1624 
1625  private:
1626  std::shared_ptr<std::shared_future<void>> future_;
1627  };
1628 
1630  template<typename T>
1631  class RADPromise {
1632  public:
1635  : promise_(std::make_shared<std::promise<T>>()),
1636  future_(std::make_shared<std::shared_future<T>>(promise_->get_future().share())) {}
1638  RADFutureT<T> future() const { return RADFutureT<T>(future_); }
1640  void setValue(T value) { promise_->set_value(std::move(value)); }
1642  void setException(std::exception_ptr error) { promise_->set_exception(error); }
1643 
1644  private:
1645  std::shared_ptr<std::promise<T>> promise_;
1646  std::shared_ptr<std::shared_future<T>> future_;
1647  };
1648 
1650  template<>
1651  class RADPromise<void> {
1652  public:
1655  : promise_(std::make_shared<std::promise<void>>()),
1656  future_(std::make_shared<std::shared_future<void>>(promise_->get_future().share())) {}
1658  RADFutureT<void> future() const { return RADFutureT<void>(future_); }
1660  void setValue() { promise_->set_value(); }
1662  void setException(std::exception_ptr error) { promise_->set_exception(error); }
1663 
1664  private:
1665  std::shared_ptr<std::promise<void>> promise_;
1666  std::shared_ptr<std::shared_future<void>> future_;
1667  };
1668 
1670  class RADThreadPool : public RADObject {
1671  public:
1673  explicit RADThreadPool(size_t threadCount = std::thread::hardware_concurrency());
1675  ~RADThreadPool() override;
1676 
1678  RADFuture submit(EventLoop& completionLoop, std::function<RADVariant()> task);
1680  template<typename F>
1681  auto submitTyped(EventLoop& completionLoop, F&& task) -> RADFutureT<std::invoke_result_t<F>> {
1682  using ReturnType = std::invoke_result_t<F>;
1683  auto promise = std::make_shared<std::promise<ReturnType>>();
1684  auto future = std::make_shared<std::shared_future<ReturnType>>(promise->get_future().share());
1685  auto taskPtr = std::make_shared<std::decay_t<F>>(std::forward<F>(task));
1686  enqueue([promise, taskPtr, &completionLoop]() mutable {
1687  try {
1688  if constexpr (std::is_void_v<ReturnType>) {
1689  (*taskPtr)();
1690  promise->set_value();
1691  } else {
1692  promise->set_value((*taskPtr)());
1693  }
1694  completionLoop.post([] {});
1695  } catch (...) {
1696  promise->set_exception(std::current_exception());
1697  completionLoop.post([] {});
1698  }
1699  });
1700  return RADFutureT<ReturnType>(future);
1701  }
1703  template<typename F>
1704  auto submitCancellable(EventLoop& completionLoop, RADCancellationToken token, F&& task)
1706  using ReturnType = std::invoke_result_t<F, RADCancellationToken>;
1707  auto promise = std::make_shared<std::promise<ReturnType>>();
1708  auto future = std::make_shared<std::shared_future<ReturnType>>(promise->get_future().share());
1709  auto taskPtr = std::make_shared<std::decay_t<F>>(std::forward<F>(task));
1710  enqueue([promise, taskPtr, token, &completionLoop]() mutable {
1711  try {
1712  if constexpr (std::is_void_v<ReturnType>) {
1713  (*taskPtr)(token);
1714  promise->set_value();
1715  } else {
1716  promise->set_value((*taskPtr)(token));
1717  }
1718  completionLoop.post([] {});
1719  } catch (...) {
1720  promise->set_exception(std::current_exception());
1721  completionLoop.post([] {});
1722  }
1723  });
1724  return RADFutureT<ReturnType>(future);
1725  }
1727  void waitForDone();
1729  size_t threadCount() const;
1730 
1731  private:
1732  void enqueue(std::function<void()> task);
1733  struct Impl;
1734  std::shared_ptr<Impl> pImpl_;
1735  };
1736 #endif
1737 
1740  public:
1741  RADEvents:
1743  RAD_EVENT(modelReset, ());
1745  RAD_EVENT(dataChanged, (size_t, size_t));
1747  RAD_EVENT(rowsInserted, (size_t, size_t));
1749  RAD_EVENT(rowsRemoved, (size_t, size_t));
1750 
1752  virtual ~RADAbstractItemModel() = default;
1754  virtual size_t rowCount() const = 0;
1756  virtual size_t columnCount() const = 0;
1758  virtual RADVariant data(size_t row, size_t column = 0) const = 0;
1759  };
1760 
1763  public:
1765  size_t rowCount() const override;
1767  size_t columnCount() const override;
1769  RADVariant data(size_t row, size_t column = 0) const override;
1770 
1772  void append(std::string value);
1774  void set(size_t row, std::string value);
1776  void remove(size_t row);
1778  void clear();
1780  const std::vector<std::string>& values() const;
1781 
1782  private:
1783  std::vector<std::string> values_;
1784  };
1785 
1787  class RADProcess : public RADObject {
1788  public:
1789  RADEvents:
1791  RAD_EVENT(started, ());
1793  RAD_EVENT(finished, (int));
1795  RAD_EVENT(errorOccurred, (std::string));
1796 
1800  ~RADProcess() override;
1801 
1803  bool start(const std::string& program, const std::vector<std::string>& arguments = {});
1805  bool waitForFinished(int timeoutMs = -1);
1807  void kill();
1808 
1812  int exitCode() const;
1814  std::string readAllStandardOutput() const;
1816  std::string readAllStandardError() const;
1817 
1818  private:
1819  struct Impl;
1820  std::unique_ptr<Impl> pImpl_;
1821  };
1822 
1824  class RADPtyProcess : public RADObject {
1825  public:
1826  RADEvents:
1828  RAD_EVENT(started, ());
1830  RAD_EVENT(finished, (int));
1832  RAD_EVENT(errorOccurred, (std::string));
1833 
1837  ~RADPtyProcess() override;
1838 
1840  bool start(const std::string& program = {}, const std::vector<std::string>& arguments = {},
1841  uint16_t rows = 30, uint16_t columns = 120);
1843  bool waitForFinished(int timeoutMs = -1);
1845  void kill();
1847  void close();
1848 
1850  ssize_t readData(void* buffer, size_t maxBytes);
1852  ssize_t writeData(const void* data, size_t size);
1854  ssize_t write(const std::string& text);
1856  bool resizeTerminal(uint16_t rows, uint16_t columns);
1857 
1861  int exitCode() const;
1862 
1863  private:
1864  struct Impl;
1865  std::unique_ptr<Impl> pImpl_;
1866  };
1867 
1869  class Timer : public RADObject {
1870  public:
1871  RADEvents:
1873  RAD_EVENT(timeout, ());
1875  RAD_EVENT(errorOccurred, (std::string));
1876 
1881 
1883  void start(int intervalMs, EventLoop& targetLoop);
1885  void start(EventLoop& targetLoop);
1887  void stop();
1889  void setInterval(int intervalMs);
1891  int interval() const;
1893  bool isActive() const;
1894 
1896  static void singleShot(int intervalMs, EventLoop& targetLoop, EventLoop::Task task);
1897 
1898  private:
1899  std::atomic<bool> active_;
1900  std::thread timerThread_;
1901  std::atomic<int> timerFd_{-1};
1902  std::atomic<int> stopFd_{-1};
1903  std::atomic<int> intervalMs_{0};
1904  };
1905 
1907  class RADThread : public RADObject {
1908  public:
1909  RADEvents:
1911  RAD_EVENT(started, ());
1913  RAD_EVENT(finished, ());
1914 
1915  public:
1919  virtual ~RADThread();
1920 
1924  void quit();
1926  void wait();
1930  bool isRunning() const;
1931  protected:
1933  virtual void run();
1934  private:
1935  struct Impl;
1936  std::unique_ptr<Impl> pImpl;
1937  };
1938 
1939  namespace Internal {
1940  template<typename... Args>
1941  struct EventBinder {Event<void(Args...)>& targetEvent;
1942  EventBinder(Event<void(Args...)>& ev) : targetEvent(ev) {}
1943  void operator()(Args... args) {
1944  targetEvent.raise(std::forward(args)...);
1945  }
1946  };
1947  struct TriggerHelper {
1948  void operator<<(Event<void()>& targetEvent) { targetEvent.raise(); }
1949  template<typename... Args>EventBinder<Args...> operator<<(Event<void(Args...)>& targetEvent) {
1950  return EventBinder<Args...>(targetEvent);
1951  }
1952  };
1953  }
1954 
1956  enum class LogLevel { INFO, DEBUG };
1957 
1959  void initLogger();
1962 
1963  namespace Internal {
1965  class LogStream {
1966  public:
1970  ~LogStream(); // Flushes the accumulated string buffer to the background thread on destruction
1971 
1973  template<typename T>
1974  LogStream& operator<<(const T& value) {
1975  stream_ << value;
1976  return *this;
1977  }
1978 
1980  LogStream& operator<<(std::ostream& (*manip)(std::ostream&)) {
1981  stream_ << manip;
1982  return *this;
1983  }
1984 
1985  private:
1986  LogLevel level_;
1987  std::stringstream stream_;
1988  };
1989  }
1990 } // namespace RADCore
1991 #endif
#define RAD_EVENT(Name, Signature)
Declares a typed RADCore event; example: RAD_EVENT(done, (int)).
Definition: RADCore.h:97
#define RADEvents
Marks a public event declaration block in RADObject-derived classes.
Definition: RADCore.h:75
Explicit event connection handle.
Definition: RADCore.h:935
void disconnect()
Disconnects the associated event handler once.
Connection()=default
Creates a disconnected handle.
bool isConnected() const
Returns true while the connection is still active.
Low-level raw handler collection used internally by typed Event.
Definition: RADCore.h:1107
void addRawHandler(size_t id, RawTask task)
Adds a raw handler by id.
void removeRawHandler(size_t id)
Removes a raw handler by id.
void invokeAll()
Invokes all raw handlers.
std::function< void()> RawTask
Raw no-argument task type.
Definition: RADCore.h:1110
Weak posting handle for EventLoop tasks that may outlive the loop object.
Definition: RADCore.h:1039
bool post(EventLoop::Task task) const
Posts normal-priority task; returns false when the loop is gone.
EventLoopHandle()=default
Creates an invalid handle.
bool isValid() const
Returns true when the referenced loop still accepts work.
bool post(Priority priority, EventLoop::Task task) const
Posts task with explicit priority; returns false when the loop is gone.
bool postDelayed(int delayMs, EventLoop::Task task) const
Posts task after delayMs milliseconds; returns false when the loop is gone.
RADCore task event loop with locked and low-latency scheduling strategies.
Definition: RADCore.h:988
EventLoop(LoopStrategy strategy=RADEVENT_LOCK)
Creates an event loop using strategy.
void post(Priority priority, Task task)
Posts task with explicit priority.
bool processEvents()
Processes currently queued events without entering the main loop.
void post(F &&f, Args &&... args)
Binds f and args into a normal-priority task.
Definition: RADCore.h:1025
bool postDelayed(int delayMs, Task task)
Posts task to this loop after delayMs milliseconds; returns false when stopped.
EventLoopHandle handle() const
Returns a weak posting handle safe to keep beyond this EventLoop object.
void post(Task task)
Posts task at normal priority.
void exec()
Runs the event loop until quit() is called.
~EventLoop()
Stops and destroys the loop implementation.
bool isEventThread() const
Returns true when called from the thread running exec().
void post(Priority priority, F &&f, Args &&... args)
Binds f and args into a task posted with priority.
Definition: RADCore.h:1016
std::function< void()> Task
Task callable type.
Definition: RADCore.h:991
void quit()
Requests the event loop to exit.
void disconnect(size_t targetId)
Disconnects a handler by event-local id.
Definition: RADCore.h:1248
Connection connect_queued(EventLoop &loop, T *receiver, void(T::*memberFunc)(Args...))
Connects this event to a receiver member function through loop.
Definition: RADCore.h:1209
Event()
Creates an empty event.
Definition: RADCore.h:1139
Connection connect(T *receiver, void(T::*memberFunc)(Args...))
Connects this event to a RADObject receiver member function.
Definition: RADCore.h:1155
~Event()
Marks the event dead and disconnects handlers.
Definition: RADCore.h:1142
Typed event template; use RAD_EVENT to declare instances.
Definition: RADCore.h:906
Streaming log proxy used by RADInfo() and RADDebug().
Definition: RADCore.h:1965
LogStream & operator<<(const T &value)
Appends value to the log stream.
Definition: RADCore.h:1974
LogStream(LogLevel level)
Creates a log stream for level.
~LogStream()
Flushes the accumulated string to the logger.
LogStream & operator<<(std::ostream &(*manip)(std::ostream &))
Appends an ostream manipulator such as std::endl.
Definition: RADCore.h:1980
Minimal abstract item model for UI/model integrations.
Definition: RADCore.h:1739
virtual ~RADAbstractItemModel()=default
Destroys model implementations through the base class.
virtual size_t columnCount() const =0
Returns column count.
virtual size_t rowCount() const =0
Returns row count.
virtual RADVariant data(size_t row, size_t column=0) const =0
Returns data at row/column.
In-memory RADIODevice backed by a byte vector.
Definition: RADCore.h:1321
ssize_t readData(void *buffer, size_t maxBytes) override
Reads raw bytes from the current position.
ssize_t writeData(const void *data, size_t size) override
Writes raw bytes at the current position.
void close() override
Closes the memory buffer.
bool seek(size_t position)
Moves the current read/write position.
RADBuffer(std::vector< uint8_t > data)
Creates a buffer initialized with data.
size_t size() const
Returns current buffer size in bytes.
void clear()
Clears buffer contents and resets position.
RADBuffer()
Creates an empty buffer.
bool isOpen() const override
Returns true when open.
size_t position() const
Returns current read/write position.
~RADBuffer() override
Destroys the buffer.
const std::vector< uint8_t > & data() const
Returns the underlying byte vector.
bool open(OpenMode mode) override
Opens the memory buffer.
Owner object used to request cancellation on associated tokens.
Definition: RADCore.h:309
void cancel()
Requests cancellation.
Definition: RADCore.h:316
bool isCancellationRequested() const
Returns true when cancellation was requested.
Definition: RADCore.h:318
RADCancellationSource()
Creates a source with a fresh token.
Definition: RADCore.h:312
RADCancellationToken token() const
Returns the token that observers should poll.
Definition: RADCore.h:314
Shared cancellation token passed to long-running tasks.
Definition: RADCore.h:292
RADCancellationToken()
Creates a non-cancelled standalone token.
Definition: RADCore.h:295
bool isCancellationRequested() const
Returns true when cancellation has been requested.
Definition: RADCore.h:297
Binary serialization stream for RADIODevice.
Definition: RADCore.h:1396
RADDataStream & operator>>(uint16_t &value)
Reads an unsigned 16-bit integer.
RADDataStream(RADIODevice &device)
Creates a stream over device.
void resetStatus()
Resets status to Ok.
RADDataStream & operator<<(const std::string &value)
Writes a length-prefixed string.
RADDataStream & operator<<(uint64_t value)
Writes an unsigned 64-bit integer.
RADDataStream & operator>>(int32_t &value)
Reads a signed 32-bit integer.
DataStreamStatus status() const
Returns current stream status.
RADDataStream & operator<<(int32_t value)
Writes a signed 32-bit integer.
RADDataStream & operator>>(std::vector< uint8_t > &value)
Reads a length-prefixed byte array.
RADDataStream & operator<<(uint16_t value)
Writes an unsigned 16-bit integer.
RADDataStream & operator<<(double value)
Writes a 64-bit double.
RADDataStream & operator<<(uint32_t value)
Writes an unsigned 32-bit integer.
RADDataStream & operator>>(int16_t &value)
Reads a signed 16-bit integer.
void setByteOrder(ByteOrder byteOrder)
Sets byte order for integer and floating point values.
RADDataStream & operator>>(uint8_t &value)
Reads an unsigned 8-bit integer.
RADDataStream & operator<<(int16_t value)
Writes a signed 16-bit integer.
bool ok() const
Returns true when status is Ok.
RADDataStream & operator>>(float &value)
Reads a 32-bit float.
RADDataStream & operator>>(int8_t &value)
Reads a signed 8-bit integer.
RADDataStream & operator<<(const std::vector< uint8_t > &value)
Writes a length-prefixed byte array.
RADDataStream & operator<<(uint8_t value)
Writes an unsigned 8-bit integer.
RADDataStream & operator>>(uint64_t &value)
Reads an unsigned 64-bit integer.
RADDataStream & operator>>(double &value)
Reads a 64-bit double.
RADDataStream & operator<<(int8_t value)
Writes a signed 8-bit integer.
RADDataStream & operator>>(uint32_t &value)
Reads an unsigned 32-bit integer.
RADDataStream & operator<<(float value)
Writes a 32-bit float.
RADDataStream & operator<<(int64_t value)
Writes a signed 64-bit integer.
ByteOrder byteOrder() const
Returns current byte order.
RADDataStream & operator>>(int64_t &value)
Reads a signed 64-bit integer.
RADDataStream & operator>>(std::string &value)
Reads a length-prefixed string.
UTC millisecond timestamp helper.
Definition: RADCore.h:436
static std::optional< RADDateTime > fromIsoString(const std::string &isoString)
Parses an ISO-like UTC string.
int64_t toUnixMilliseconds() const
Returns Unix milliseconds.
bool isValid() const
Returns true when this object contains a valid timestamp.
RADDateTime(int64_t unixMilliseconds)
Creates a valid UTC date-time from Unix milliseconds.
RADDateTime()
Creates an invalid date-time.
static RADDateTime fromUnixMilliseconds(int64_t unixMilliseconds)
Creates a date-time from Unix milliseconds.
static RADDateTime nowUtc()
Returns current UTC time.
std::string toIsoString() const
Formats as an ISO-like UTC string.
Deadline helper for timeout loops and cancellation-aware waits.
Definition: RADCore.h:266
RADDeadlineTimer(int64_t intervalMs)
Creates a deadline intervalMs in the future.
Definition: RADCore.h:271
bool isValid() const
Returns true when this deadline has been configured.
Definition: RADCore.h:275
bool hasExpired() const
Returns true when the deadline has passed.
Definition: RADCore.h:277
int64_t remainingMilliseconds() const
Returns milliseconds remaining, or 0 when expired/invalid.
Definition: RADCore.h:279
RADDeadlineTimer()=default
Creates an expired deadline.
Monotonic elapsed timer based on std::chrono::steady_clock.
Definition: RADCore.h:243
double elapsedSeconds() const
Returns elapsed seconds as a double.
Definition: RADCore.h:259
void restart()
Restarts the timer.
Definition: RADCore.h:248
RADElapsedTimer()
Creates and starts the timer.
Definition: RADCore.h:246
int64_t elapsedMicroseconds() const
Returns elapsed microseconds.
Definition: RADCore.h:255
int64_t elapsedNanoseconds() const
Returns elapsed nanoseconds.
Definition: RADCore.h:250
int64_t elapsedMilliseconds() const
Returns elapsed milliseconds.
Definition: RADCore.h:257
Structured error object returned by RADResult and newer APIs.
Definition: RADCore.h:136
int code() const
Returns numeric error code; 0 means no error.
Definition: RADCore.h:147
RADError(int code, std::string message)
Creates an error with code and message.
Definition: RADCore.h:141
bool hasError() const
Returns true when this object represents an error.
Definition: RADCore.h:145
RADError()=default
Creates a no-error object.
const std::string & message() const
Returns human-readable error message.
Definition: RADCore.h:149
inotify-backed filesystem watcher that emits on a RADCore EventLoop.
Definition: RADCore.h:1494
void removePath(const std::string &path)
Removes a watched path.
~RADFileSystemWatcher() override
Stops the watcher.
std::vector< std::string > paths() const
Returns currently watched paths.
RADFileSystemWatcher(EventLoop &loop)
Creates a watcher that posts events to loop.
bool addPath(const std::string &path)
Adds a non-recursive path watch.
bool addPath(const std::string &path, bool recursive)
Adds a path watch, recursively when requested.
void clear()
Removes all watched paths.
File-backed RADIODevice.
Definition: RADCore.h:1358
void setFileName(std::string fileName)
Sets the file path.
bool isOpen() const override
Returns true when the file is open.
ssize_t readData(void *buffer, size_t maxBytes) override
Reads raw bytes from the file.
size_t position() const
Returns current byte position.
void close() override
Closes the file descriptor.
~RADFile() override
Closes the file if needed.
bool seek(size_t position)
Seeks to an absolute byte position.
const std::string & fileName() const
Returns the file path.
bool open(OpenMode mode) override
Opens the file with mode.
size_t size() const
Returns file size in bytes.
ssize_t writeData(const void *data, size_t size) override
Writes raw bytes to the file.
RADFile(std::string fileName)
Creates a file bound to fileName.
RADFile()
Creates a file with no path.
Void typed future specialization.
Definition: RADCore.h:1594
void wait() const
Blocks until the result is ready.
Definition: RADCore.h:1608
void then(EventLoop &loop, F &&continuation) const
Posts continuation to loop after this future completes.
Definition: RADCore.h:1613
RADFutureT()=default
Creates an invalid future.
void result() const
Waits and rethrows any task exception.
Definition: RADCore.h:1610
bool isFinished() const
Returns true when the result is ready.
Definition: RADCore.h:1604
bool isValid() const
Returns true when a future is present.
Definition: RADCore.h:1602
RADFutureT(std::shared_ptr< std::shared_future< void >> future)
Wraps an existing shared future.
Definition: RADCore.h:1599
Typed shared future with optional continuation support.
Definition: RADCore.h:1547
bool isFinished() const
Returns true when the result is ready.
Definition: RADCore.h:1558
RADFutureT()=default
Creates an invalid future.
T resultOr(T defaultValue) const
Returns result or defaultValue if not ready or failed.
Definition: RADCore.h:1566
void wait() const
Blocks until the result is ready.
Definition: RADCore.h:1562
void then(EventLoop &loop, F &&continuation) const
Posts continuation to loop after this future completes.
Definition: RADCore.h:1573
T result() const
Returns the result, rethrowing any task exception.
Definition: RADCore.h:1564
bool isValid() const
Returns true when a future is present.
Definition: RADCore.h:1556
RADFutureT(std::shared_ptr< std::shared_future< T >> future)
Wraps an existing shared future.
Definition: RADCore.h:1552
Shared future wrapper returning RADVariant results.
Definition: RADCore.h:1525
bool isFinished() const
Returns true when the result is ready.
RADVariant result(RADVariant defaultValue={}) const
Returns result or defaultValue if not ready or failed.
bool isValid() const
Returns true when a future is present.
RADFuture()
Creates an invalid future.
RADFuture(std::shared_ptr< std::shared_future< RADVariant >> future)
Wraps an existing shared future.
void wait() const
Blocks until the future is ready.
Abstract byte-oriented IO device similar to QIODevice.
Definition: RADCore.h:1286
virtual bool open(OpenMode mode)=0
Opens the device with mode.
virtual ~RADIODevice()=default
Destroys the IO device.
ssize_t write(const std::string &text)
Writes string bytes.
virtual void close()=0
Closes the device.
std::vector< uint8_t > read(size_t maxBytes)
Reads up to maxBytes into a byte vector.
std::vector< uint8_t > readAll(size_t chunkSize=8192)
Reads all available data in chunks.
ssize_t write(const std::vector< uint8_t > &data)
Writes a byte vector.
virtual bool isOpen() const =0
Returns true when open.
virtual ssize_t writeData(const void *data, size_t size)=0
Writes raw bytes from data.
virtual ssize_t readData(void *buffer, size_t maxBytes)=0
Reads raw bytes into buffer.
JSON document wrapper around a root RADJsonValue.
Definition: RADCore.h:648
RADJsonValue & root()
Returns mutable root value.
const RADJsonValue & root() const
Returns const root value.
RADJsonDocument()
Creates a document with null root.
RADJsonDocument(RADJsonValue root)
Creates a document from root.
static std::optional< RADJsonDocument > fromFile(const std::string &path, std::string *error=nullptr)
Loads and parses JSON from path.
std::string toJson(bool pretty=false) const
Serializes root to JSON.
static std::optional< RADJsonDocument > fromJson(const std::string &json, std::string *error=nullptr)
Parses JSON text.
bool toFile(const std::string &path, bool pretty=true, std::string *error=nullptr) const
Writes JSON to path.
JSON value supporting null, bool, number, string, array, and object.
Definition: RADCore.h:541
bool isNull() const
Returns true when value is null.
bool isArray() const
Returns true when value is array.
RADJsonValue & operator[](const std::string &key)
Returns object member by key, creating it if needed.
RADJsonValue(RADJsonValue &&other) noexcept=default
Moves the value without deep-copying.
RADJsonValue & operator=(RADJsonValue &&other) noexcept=default
Moves the value without deep-copying.
size_t size() const
Returns array length or object member count.
void append(RADJsonValue value)
Appends value to an array, converting to array if needed.
RADJsonValue(int value)
Creates a JSON number from int.
RADJsonValue(const RADJsonValue &other)
Deep-copies arrays and objects so mutations do not alias the source.
bool toBool(bool defaultValue=false) const
Converts to bool or returns defaultValue.
double toNumber(double defaultValue=0.0) const
Converts to double or returns defaultValue.
void remove(const std::string &key)
Removes key from an object.
RADJsonValue & operator[](size_t index)
Returns array element by index, expanding when needed.
int toInt(int defaultValue=0) const
Converts to int or returns defaultValue.
bool isBool() const
Returns true when value is bool.
bool isObject() const
Returns true when value is object.
std::string toString(const std::string &defaultValue={}) const
Converts to string or returns defaultValue.
RADJsonValue & operator=(const RADJsonValue &other)
Deep-copies arrays and objects so mutations do not alias the source.
std::string toJson(bool pretty=false, int indent=0) const
Serializes this value to JSON.
RADJsonValue(const char *value)
Creates a JSON string from C string.
bool isNumber() const
Returns true when value is number.
JsonType type() const
Returns current JSON type.
RADJsonValue(bool value)
Creates a JSON bool.
RADJsonValue(std::string value)
Creates a JSON string.
const RADJsonValue & operator[](size_t index) const
Returns array element by index or null value when missing.
std::vector< std::string > keys() const
Returns object keys.
RADJsonValue(std::nullptr_t)
Creates JSON null.
const RADJsonValue & operator[](const std::string &key) const
Returns object member by key or null value when missing.
RADJsonValue(int64_t value)
Creates a JSON number from int64.
bool isString() const
Returns true when value is string.
int64_t toInt64(int64_t defaultValue=0) const
Converts to int64 or returns defaultValue.
bool contains(const std::string &key) const
Returns true when object contains key.
static RADJsonValue array()
Creates an empty JSON array.
RADJsonValue()
Creates JSON null.
RADJsonValue(double value)
Creates a JSON number from double.
static RADJsonValue object()
Creates an empty JSON object.
Advisory filesystem lock file.
Definition: RADCore.h:859
void unlock()
Releases the lock if held.
RADLockFile(std::string fileName)
Creates a lock file object for fileName.
bool tryLock()
Attempts to acquire the lock.
const std::string & fileName() const
Returns the lock file path.
bool isLocked() const
Returns true when this object holds the lock.
RADLockFile(const RADLockFile &)=delete
Lock files cannot be copied.
~RADLockFile()
Unlocks on destruction when needed.
RADLockFile & operator=(const RADLockFile &)=delete
Lock files cannot be copied.
Base class for event receivers, senders, and thread-affinity aware objects.
Definition: RADCore.h:963
EventLoop * associatedEventLoop() const
Returns the associated event loop, if any.
void moveToThread(std::thread::id tId, EventLoop *loop=nullptr)
Moves the object's affinity to tId and optional loop.
virtual ~RADObject()
Disconnects tracked event links and releases lifetime token.
ThreadAffinity threadAffinity() const
Returns both thread id and associated loop atomically.
RADObject()
Creates a RADObject bound to the current thread.
std::thread::id threadId() const
Returns the thread id this object is currently associated with.
std::weak_ptr< void > lifetimeToken() const
Returns a weak token used to drop queued callbacks after destruction.
void registerLink(const ConnectionRecord &record)
Registers a connection for cleanup when this object is destroyed.
Child process helper for stdout/stderr capture.
Definition: RADCore.h:1787
bool waitForFinished(int timeoutMs=-1)
Waits for process exit; timeoutMs < 0 waits indefinitely.
void kill()
Sends a kill request to the process.
RADProcess()
Creates a non-running process.
std::string readAllStandardError() const
Returns captured stderr.
ProcessState state() const
Returns process state.
bool start(const std::string &program, const std::vector< std::string > &arguments={})
Starts program with arguments.
int exitCode() const
Returns exit code after finish.
~RADProcess() override
Kills or cleans up the process if needed.
std::string readAllStandardOutput() const
Returns captured stdout.
RADFutureT< void > future() const
Returns the associated typed future.
Definition: RADCore.h:1658
void setException(std::exception_ptr error)
Sets an exception result.
Definition: RADCore.h:1662
RADPromise()
Creates a promise/future pair.
Definition: RADCore.h:1654
void setValue()
Sets successful completion.
Definition: RADCore.h:1660
Typed promise that creates RADFutureT.
Definition: RADCore.h:1631
RADFutureT< T > future() const
Returns the associated typed future.
Definition: RADCore.h:1638
void setValue(T value)
Sets the result value.
Definition: RADCore.h:1640
RADPromise()
Creates a promise/future pair.
Definition: RADCore.h:1634
void setException(std::exception_ptr error)
Sets an exception result.
Definition: RADCore.h:1642
PTY-backed process helper for terminal applications.
Definition: RADCore.h:1824
void close()
Closes the PTY handle.
RADPtyProcess()
Creates a non-running PTY process.
bool waitForFinished(int timeoutMs=-1)
Waits for process exit; timeoutMs < 0 waits indefinitely.
~RADPtyProcess() override
Stops and cleans up the PTY process if needed.
ssize_t write(const std::string &text)
Writes string bytes to the PTY.
ProcessState state() const
Returns process state.
bool resizeTerminal(uint16_t rows, uint16_t columns)
Resizes the PTY terminal dimensions.
void kill()
Sends a kill request to the child.
ssize_t readData(void *buffer, size_t maxBytes)
Reads bytes from the PTY.
int exitCode() const
Returns exit code after finish.
ssize_t writeData(const void *data, size_t size)
Writes bytes to the PTY.
bool start(const std::string &program={}, const std::vector< std::string > &arguments={}, uint16_t rows=30, uint16_t columns=120)
Starts program in a PTY; empty program selects the user's shell.
bool hasError() const
Returns true when this result has an error.
Definition: RADCore.h:197
bool ok() const
Returns true when no error is present.
Definition: RADCore.h:195
static RADResult failure(RADError error)
Creates a failed result.
Definition: RADCore.h:193
const RADError & error() const
Returns the error object.
Definition: RADCore.h:199
static RADResult success()
Creates a successful result.
Definition: RADCore.h:191
Success-or-error return value for APIs that should not throw.
Definition: RADCore.h:158
const T & value() const
Returns the result value; callers should check ok().
Definition: RADCore.h:172
T valueOr(T defaultValue) const
Returns value or defaultValue when failed.
Definition: RADCore.h:176
static RADResult success(T value)
Creates a successful result.
Definition: RADCore.h:161
T & value()
Returns the result value; callers should check ok().
Definition: RADCore.h:170
const RADError & error() const
Returns the error object.
Definition: RADCore.h:174
static RADResult failure(RADError error)
Creates a failed result.
Definition: RADCore.h:163
bool hasError() const
Returns true when this result has an error.
Definition: RADCore.h:168
bool ok() const
Returns true when a value is present.
Definition: RADCore.h:166
void setValue(const std::string &key, RADJsonValue value)
Sets value for key.
RADSettings(std::string fileName)
Creates settings bound to fileName.
void clear()
Removes all settings.
const std::string & fileName() const
Returns backing file path.
bool save(std::string *error=nullptr) const
Saves settings to disk.
void remove(const std::string &key)
Removes key.
bool contains(const std::string &key) const
Returns true when key exists.
RADJsonValue value(const std::string &key, RADJsonValue defaultValue={}) const
Returns value for key or defaultValue.
bool load(std::string *error=nullptr)
Loads settings from disk.
Non-owning contiguous view over T values.
Definition: RADCore.h:209
RADSpan()=default
Creates an empty span.
T * end() const
Returns pointer one past last element.
Definition: RADCore.h:230
T * begin() const
Returns pointer to first element.
Definition: RADCore.h:228
T * data() const
Returns mutable pointer to first element.
Definition: RADCore.h:220
RADSpan(T *data, size_t size)
Creates a span over pointer and element count.
Definition: RADCore.h:214
RADSpan(Container &container)
Creates a span over a std::vector-compatible container.
Definition: RADCore.h:217
bool empty() const
Returns true when the span is empty.
Definition: RADCore.h:224
size_t size() const
Returns element count.
Definition: RADCore.h:222
T & operator[](size_t index) const
Returns element at index without bounds checking.
Definition: RADCore.h:226
One-column string list implementation of RADAbstractItemModel.
Definition: RADCore.h:1762
void append(std::string value)
Appends a value.
void set(size_t row, std::string value)
Sets a row value.
size_t rowCount() const override
Returns number of strings.
const std::vector< std::string > & values() const
Returns underlying values.
void remove(size_t row)
Removes a row.
void clear()
Clears all values.
size_t columnCount() const override
Returns 1.
RADVariant data(size_t row, size_t column=0) const override
Returns row string as RADVariant.
RAII temporary directory with optional auto-remove.
Definition: RADCore.h:790
RADTemporaryDirectory(const RADTemporaryDirectory &)=delete
Temporary directories own a filesystem path and cannot be copied.
RADTemporaryDirectory & operator=(const RADTemporaryDirectory &)=delete
Temporary directories own a filesystem path and cannot be copied.
RADTemporaryDirectory(std::string prefix="radlib")
Creates a temporary directory with prefix.
bool isValid() const
Returns true when directory creation succeeded.
RADTemporaryDirectory & operator=(RADTemporaryDirectory &&other) noexcept
Moves ownership from other.
bool autoRemove() const
Returns true when destruction removes the directory.
void setAutoRemove(bool enabled)
Enables or disables removal on destruction.
const std::string & path() const
Returns the temporary directory path.
RADTemporaryDirectory(RADTemporaryDirectory &&other) noexcept
Moves ownership from other.
bool remove()
Removes the directory immediately.
~RADTemporaryDirectory()
Removes the directory when autoRemove is enabled.
RAII temporary file with optional auto-remove.
Definition: RADCore.h:823
bool remove()
Removes the temporary file immediately.
RADTemporaryFile & operator=(const RADTemporaryFile &)=delete
Temporary files own a file descriptor and cannot be copied.
int fd() const
Returns the native file descriptor.
RADTemporaryFile(const RADTemporaryFile &)=delete
Temporary files own a file descriptor and cannot be copied.
RADTemporaryFile & operator=(RADTemporaryFile &&other) noexcept
Moves ownership from other.
RADTemporaryFile(RADTemporaryFile &&other) noexcept
Moves ownership from other.
bool isValid() const
Returns true when file creation succeeded.
const std::string & fileName() const
Returns the temporary file path.
RADTemporaryFile(std::string prefix="radlib")
Creates a temporary file with prefix.
void setAutoRemove(bool enabled)
Enables or disables removal on destruction.
~RADTemporaryFile()
Closes and removes the file when autoRemove is enabled.
bool autoRemove() const
Returns true when destruction removes the file.
Simple worker thread pool that reports completion through RADFuture.
Definition: RADCore.h:1670
auto submitTyped(EventLoop &completionLoop, F &&task) -> RADFutureT< std::invoke_result_t< F >>
Submits a typed task and posts completion wakeup to completionLoop.
Definition: RADCore.h:1681
RADFuture submit(EventLoop &completionLoop, std::function< RADVariant()> task)
Submits task and posts completion wakeup to completionLoop.
auto submitCancellable(EventLoop &completionLoop, RADCancellationToken token, F &&task) -> RADFutureT< std::invoke_result_t< F, RADCancellationToken >>
Submits a typed task that receives a cancellation token.
Definition: RADCore.h:1704
void waitForDone()
Blocks until queued and active tasks are complete.
size_t threadCount() const
Returns number of worker threads.
~RADThreadPool() override
Stops workers after queued tasks complete.
RADThreadPool(size_t threadCount=std::thread::hardware_concurrency())
Creates a pool with threadCount workers.
Thread object with an owned RADCore EventLoop.
Definition: RADCore.h:1907
void quit()
Requests the event loop to quit.
RADThread()
Creates a stopped thread object.
virtual void run()
Override to run custom work before/around the event loop.
bool isRunning() const
Returns true while the thread is running.
void wait()
Blocks until the thread exits.
void start(LoopStrategy strategy=LoopStrategy::RADEVENT_LOCK)
Starts the thread and its event loop.
virtual ~RADThread()
Quits and joins the thread when needed.
EventLoop & eventLoop()
Returns the thread's event loop after start().
Lightweight URL parser for scheme, host, port, path, query, and fragment.
Definition: RADCore.h:487
std::string toString() const
Rebuilds the URL string.
const std::string & query() const
Returns query without '?'.
RADUrl()=default
Creates an invalid empty URL.
const std::string & host() const
Returns host name or address.
uint16_t port(uint16_t defaultPort=0) const
Returns explicit port or defaultPort.
RADUrl(std::string url)
Parses url into a RADUrl.
bool isValid() const
Returns true when parsing succeeded.
static std::optional< RADUrl > parse(const std::string &url)
Parses url and returns nullopt on failure.
const std::string & fragment() const
Returns fragment without '#'.
const std::string & path() const
Returns URL path.
const std::string & scheme() const
Returns URL scheme without colon.
128-bit UUID helper.
Definition: RADCore.h:463
static std::optional< RADUuid > fromString(const std::string &text)
Parses canonical UUID text.
RADUuid(std::array< uint8_t, 16 > bytes)
Creates a UUID from raw bytes.
static RADUuid createUuid()
Creates a random UUID.
RADUuid()
Creates a null UUID.
const std::array< uint8_t, 16 > & bytes() const
Returns raw UUID bytes.
std::string toString() const
Formats as canonical UUID text.
bool isNull() const
Returns true when all UUID bytes are zero.
Small value container used by models, futures, settings, and database rows.
Definition: RADCore.h:396
VariantType type() const
Returns the current variant type.
double toDouble(double defaultValue=0.0) const
Converts to double or returns defaultValue.
RADVariant(int64_t value)
Stores a signed 64-bit integer.
bool isValid() const
Returns true when the variant stores a non-invalid value.
int64_t toInt64(int64_t defaultValue=0) const
Converts to int64 or returns defaultValue.
bool toBool(bool defaultValue=false) const
Converts to bool or returns defaultValue.
RADVariant()
Creates an invalid variant.
RADVariant(bool value)
Stores a boolean.
RADVariant(const char *value)
Stores a C string as std::string.
RADVariant(double value)
Stores a double.
RADVariant(std::string value)
Stores a string.
std::vector< uint8_t > toByteArray() const
Converts to a byte array where supported.
std::string toString(const std::string &defaultValue={}) const
Converts to string or returns defaultValue.
RADVariant(std::vector< uint8_t > value)
Stores a byte array.
RADVariant(int value)
Stores an integer as Int64.
High-precision timer that emits timeout through a RADCore EventLoop.
Definition: RADCore.h:1869
void start(int intervalMs, EventLoop &targetLoop)
Starts the timer with intervalMs and posts timeout to targetLoop.
void setInterval(int intervalMs)
Sets timer interval in milliseconds.
static void singleShot(int intervalMs, EventLoop &targetLoop, EventLoop::Task task)
Posts task once after intervalMs milliseconds.
bool isActive() const
Returns true while the timer is active.
void stop()
Stops the timer.
int interval() const
Returns timer interval in milliseconds.
~Timer()
Stops the timer if active.
Timer()
Creates an inactive timer.
void start(EventLoop &targetLoop)
Starts the timer using the previously configured interval.
bool isDirectory(const std::string &path)
Returns true when path is a directory.
std::optional< std::string > readTextFile(const std::string &path)
Reads a UTF-8/text file into a string.
std::string extension(const std::string &path)
Returns extension component of path.
StandardPath
Standard platform path categories.
Definition: RADCore.h:704
@ Current
Current working directory.
@ Executable
Running executable path.
@ Home
User home directory.
@ Temp
Temporary directory.
@ Downloads
Downloads directory.
@ Documents
Documents directory.
@ Data
Application data directory.
@ Config
Configuration directory.
DirectoryEntryType
Directory entry type.
Definition: RADCore.h:728
@ Unknown
Type could not be determined.
bool remove(const std::string &path)
Removes file or directory path.
std::string tempDirectoryPath()
Returns system temporary directory.
bool createDirectories(const std::string &path)
Creates path and missing parents.
bool exists(const std::string &path)
Returns true when path exists.
std::vector< DirectoryEntry > listEntries(const std::string &path, bool recursive=false)
Lists directory entries, recursively when requested.
bool copyFile(const std::string &source, const std::string &destination, bool overwrite=true)
Copies a file from source to destination.
std::string mimeTypeForFile(const std::string &path)
Guesses MIME type from file contents or extension.
std::string fileName(const std::string &path)
Returns filename component of path.
std::vector< std::string > listDirectory(const std::string &path)
Lists child paths in a directory.
std::string currentPath()
Returns current working directory.
std::string parentPath(const std::string &path)
Returns parent directory path.
bool writeTextFile(const std::string &path, const std::string &text)
Writes text to a file.
std::string standardPath(StandardPath path)
Returns a standard platform path.
bool isFile(const std::string &path)
Returns true when path is a regular file.
Definition: RADCore.h:113
constexpr LoopStrategy RADEVENT_LOCK
Mutex/condition-variable event loop backend.
Definition: RADCore.h:920
constexpr int VersionMajor
Compile-time RADCore major version.
Definition: RADCore.h:116
VariantType
Runtime type tag for RADVariant.
Definition: RADCore.h:380
@ String
UTF-8 string value.
@ ByteArray
Byte array value.
@ Invalid
No stored value.
@ Bool
Boolean value.
@ Double
Double-precision floating point value.
@ Int64
Signed 64-bit integer value.
ByteOrder
Byte order used by RADDataStream.
Definition: RADCore.h:360
@ BigEndian
Most significant byte first.
@ LittleEndian
Least significant byte first.
void shutdownLogger()
Stops the background logging engine.
constexpr bool hasOpenMode(OpenMode mode, OpenMode flag)
Returns true when mode includes flag.
Definition: RADCore.h:355
auto invokeBlocking(EventLoop &loop, F &&task) -> std::invoke_result_t< F >
Posts task to loop and blocks until the result is available.
Definition: RADCore.h:1069
constexpr OpenMode operator&(OpenMode lhs, OpenMode rhs)
Intersects OpenMode flags.
Definition: RADCore.h:349
Priority
Event loop task priority.
Definition: RADCore.h:924
JsonType
JSON value type tag.
Definition: RADCore.h:525
@ String
JSON string.
@ Array
JSON array.
@ Object
JSON object.
@ Number
JSON number.
@ Null
JSON null.
@ Bool
JSON boolean.
void initLogger()
Starts the background logging engine.
void singleShot(int intervalMs, EventLoop &targetLoop, EventLoop::Task task)
Posts task to targetLoop after intervalMs milliseconds.
constexpr OpenMode operator|(OpenMode lhs, OpenMode rhs)
Combines OpenMode flags.
Definition: RADCore.h:343
const char * runtimeEdition()
Returns the edition used to build the loaded RADCore runtime library.
FileSystemEvent
File watcher event type.
Definition: RADCore.h:1476
@ Created
File or directory was created.
@ Overflow
Watcher event queue overflowed.
@ WatchLost
Watch was lost.
@ Modified
File or directory was modified.
@ Removed
File or directory was removed.
@ Moved
File or directory was moved.
bool runtimeRequiresLicenseKey()
Returns true when the loaded RADCore runtime expects a paid license key.
DataStreamStatus
Read/write status for RADDataStream.
Definition: RADCore.h:368
@ WriteFailed
A write operation failed.
@ ReadFailed
A read operation failed.
@ Ok
No stream error.
@ ReadPastEnd
A read requested more bytes than available.
const char * runtimeAuditStamp()
Returns a stable runtime audit stamp suitable for diagnostics.
void invoke(EventLoop &loop, F &&task)
Posts task to loop.
Definition: RADCore.h:1063
constexpr LoopStrategy RADEVENT_NOLOCK
Low-latency bounded ring event loop backend.
Definition: RADCore.h:922
ProcessState
Process lifecycle state.
Definition: RADCore.h:886
@ FailedToStart
Process failed to start.
@ Running
Process is running.
@ Finished
Process exited.
@ NotRunning
Process has not started.
LogLevel
Logger severity level.
Definition: RADCore.h:1956
OpenMode
Open mode flags shared by RADIODevice, RADFile, and RADBuffer.
Definition: RADCore.h:325
@ ReadOnly
Open for reads.
@ Append
Append writes to the end.
@ WriteOnly
Open for writes.
@ ReadWrite
Open for reads and writes.
@ Text
Text mode hint for platform-specific devices.
@ Truncate
Truncate existing contents on open.
@ NotOpen
Device is not open.
LoopStrategy
Event loop scheduling backend.
Definition: RADCore.h:918
constexpr int VersionMinor
Compile-time RADCore minor version.
Definition: RADCore.h:118
Definition: RADSettings.h:16
Connection record tracked by RADObject for automatic receiver cleanup.
Definition: RADCore.h:927
size_t connectionId
Event-local connection id.
Definition: RADCore.h:929
std::function< void()> disconnectCallback
Callback that disconnects the tracked connection.
Definition: RADCore.h:931
Shared connection state used by Event and Connection.
Definition: RADCore.h:938
std::function< void()> disconnectCallback
Disconnect callback owned by the connection.
Definition: RADCore.h:942
std::atomic_bool connected
True while connected.
Definition: RADCore.h:940
std::shared_ptr< Connection::State > connectionState
Shared connection state.
Definition: RADCore.h:1135
size_t id
Unique handler id.
Definition: RADCore.h:1131
std::function< void(Args...)> dispatch
Dispatch callable.
Definition: RADCore.h:1133
Directory listing entry with basic metadata.
Definition: RADCore.h:740
std::string name
Filename component.
Definition: RADCore.h:744
int64_t modifiedUnixMs
Last modified time in Unix milliseconds when known.
Definition: RADCore.h:750
std::string path
Full path.
Definition: RADCore.h:742
DirectoryEntryType type
Entry type.
Definition: RADCore.h:746
uintmax_t size
File size in bytes when known.
Definition: RADCore.h:748
Definition: RADCore.h:1941
void operator()(Args... args)
Definition: RADCore.h:1943
EventBinder(Event< void(Args...)> &ev)
Definition: RADCore.h:1942
Event< void(Args...)> & targetEvent
Definition: RADCore.h:1941
void(Args...) type
Definition: RADCore.h:911
Definition: RADCore.h:909
Definition: RADCore.h:1947
void operator<<(Event< void()> &targetEvent)
Definition: RADCore.h:1948
Thread affinity snapshot for RADObject event delivery.
Definition: RADCore.h:898
EventLoop * eventLoop
Associated event loop, if any.
Definition: RADCore.h:902
std::thread::id threadId
Target thread id.
Definition: RADCore.h:900