From c9ea3821b6d5e82a7ab4616b119366ff16415ad4 Mon Sep 17 00:00:00 2001 From: Mars Date: Fri, 25 Apr 2025 01:55:04 -0400 Subject: [PATCH] some docs --- src/config/config.h | 106 +++++++++++--- src/config/weather.h | 43 +++++- src/core/system_data.cpp | 17 +-- src/main.cpp | 3 - src/os/os.h | 65 +++++++-- src/util/macros.h | 44 +++++- src/util/types.h | 308 +++++++++++++++------------------------ 7 files changed, 342 insertions(+), 244 deletions(-) diff --git a/src/config/config.h b/src/config/config.h index 5eb5e15..cc7349e 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -1,10 +1,10 @@ #pragma once #ifdef _WIN32 -#include +#include // GetUserNameA #else -#include -#include +#include // getpwuid +#include // getuid #endif #include @@ -12,46 +12,91 @@ #include "src/util/macros.h" #include "weather.h" +/// Alias for the location type used in Weather config, can be a city name (String) or coordinates (Coords). using Location = std::variant; +/** + * @struct General + * @brief Holds general configuration settings. + */ struct General { - String name = []() -> String { + String name; ///< Default display name, retrieved from the system. + + /** + * @brief Retrieves the default name for the user. + * @return The default name for the user, either from the system or a fallback. + * + * Retrieves the default name for the user based on the operating system. + * On Windows, it uses GetUserNameA to get the username. + * On POSIX systems, it first tries to get the username using getpwuid, + * then checks the USER and LOGNAME environment variables. + */ + static fn getDefaultName() -> String { #ifdef _WIN32 + // Try to get the username using GetUserNameA Array username; DWORD size = sizeof(username); return GetUserNameA(username.data(), &size) ? username.data() : "User"; #else + // Try to get the username using getpwuid if (const passwd* pwd = getpwuid(getuid())) return pwd->pw_name; + // Try to get the username using environment variables if (Result envUser = GetEnv("USER")) return *envUser; + // Finally, try to get the username using LOGNAME + if (Result envLogname = GetEnv("LOGNAME")) + return *envLogname; + + // If all else fails, return a default name return "User"; #endif - }(); + } + /** + * @brief Parses a TOML table to create a General instance. + * @param tbl The TOML table to parse, containing [general]. + * @return A General instance with the parsed values, or defaults otherwise. + */ static fn fromToml(const toml::table& tbl) -> General { - General gen; - return { - .name = tbl["name"].value_or(gen.name), - }; + const toml::node_view nameNode = tbl["name"]; + return { .name = nameNode ? *nameNode.value() : getDefaultName() }; } }; +/** + * @struct NowPlaying + * @brief Holds configuration settings for the Now Playing feature. + */ struct NowPlaying { - bool enabled = false; + bool enabled = false; ///< Flag to enable or disable the Now Playing feature. + /** + * @brief Parses a TOML table to create a NowPlaying instance. + * @param tbl The TOML table to parse, containing [now_playing]. + * @return A NowPlaying instance with the parsed values, or defaults otherwise. + */ static fn fromToml(const toml::table& tbl) -> NowPlaying { return { .enabled = tbl["enabled"].value_or(false) }; } }; +/** + * @struct Weather + * @brief Holds configuration settings for the Weather feature. + */ struct Weather { - bool enabled = false; - bool show_town_name = false; - Location location; - String api_key; - String units; + bool enabled = false; ///< Flag to enable or disable the Weather feature. + bool show_town_name = false; ///< Flag to show the town name in the output. + Location location; ///< Location for weather data, can be a city name or coordinates. + String api_key; ///< API key for the weather service. + String units; ///< Units for temperature, either "metric" or "imperial". + /** + * @brief Parses a TOML table to create a Weather instance. + * @param tbl The TOML table to parse, containing [weather]. + * @return A Weather instance with the parsed values, or defaults otherwise. + */ static fn fromToml(const toml::table& tbl) -> Weather { Weather weather; @@ -81,14 +126,31 @@ struct Weather { return weather; } + /** + * @brief Retrieves the weather information based on the configuration. + * @return The weather information as a WeatherOutput object. + * + * This function fetches the weather data based on the configured location, + * API key, and units. It returns a WeatherOutput object containing the + * retrieved weather data. + */ [[nodiscard]] fn getWeatherInfo() const -> WeatherOutput; }; +/** + * @struct Config + * @brief Holds the application configuration settings. + */ struct Config { - General general; - NowPlaying now_playing; - Weather weather; + General general; ///< General configuration settings. + NowPlaying now_playing; ///< Now Playing configuration settings. + Weather weather; ///< Weather configuration settings.` + /** + * @brief Parses a TOML table to create a Config instance. + * @param tbl The TOML table to parse, containing [general], [now_playing], and [weather]. + * @return A Config instance with the parsed values, or defaults otherwise. + */ static fn fromToml(const toml::table& tbl) -> Config { const toml::node_view genTbl = tbl["general"]; const toml::node_view npTbl = tbl["now_playing"]; @@ -101,5 +163,13 @@ struct Config { }; } + /** + * @brief Retrieves the path to the configuration file. + * @return The path to the configuration file. + * + * This function constructs the path to the configuration file based on + * the operating system and user directory. It returns a std::filesystem::path + * object representing the configuration file path. + */ static fn getInstance() -> Config; }; diff --git a/src/config/weather.h b/src/config/weather.h index df04f9f..0276fe1 100644 --- a/src/config/weather.h +++ b/src/config/weather.h @@ -5,9 +5,16 @@ #include "../util/types.h" // NOLINTBEGIN(readability-identifier-naming) - Needs to specifically use `glaze` +/** + * @struct Condition + * @brief Represents weather conditions. + */ struct Condition { - String description; + String description; ///< Weather condition description (e.g., "clear sky", "light rain"). + /** + * @brief Glaze serialization and deserialization for Condition. + */ struct [[maybe_unused]] glaze { using T = Condition; @@ -15,9 +22,16 @@ struct Condition { }; }; +/** + * @struct Main + * @brief Represents the main weather data. + */ struct Main { - f64 temp; + f64 temp; ///< Temperature in degrees (C/F, depending on config). + /** + * @brief Glaze serialization and deserialization for Main. + */ struct [[maybe_unused]] glaze { using T = Main; @@ -25,17 +39,30 @@ struct Main { }; }; +/** + * @struct Coords + * @brief Represents geographical coordinates. + */ struct Coords { - double lat; - double lon; + double lat; ///< Latitude coordinate. + double lon; ///< Longitude coordinate. }; +/** + * @struct WeatherOutput + * @brief Represents the output of the weather API. + * + * Contains main weather data, location name, and weather conditions. + */ struct WeatherOutput { - Main main; - String name; - Vec weather; - usize dt; + Main main; ///< Main weather data (temperature, etc.). + String name; ///< Location name (e.g., city name). + Vec weather; ///< List of weather conditions (e.g., clear, rain). + usize dt; ///< Timestamp of the weather data (in seconds since epoch). + /** + * @brief Glaze serialization and deserialization for WeatherOutput. + */ struct [[maybe_unused]] glaze { using T = WeatherOutput; diff --git a/src/core/system_data.cpp b/src/core/system_data.cpp index 38c62f7..96a1b8d 100644 --- a/src/core/system_data.cpp +++ b/src/core/system_data.cpp @@ -11,17 +11,12 @@ namespace { const year_month_day ymd = year_month_day { floor(system_clock::now()) }; - String month = std::format("{:%B}", ymd); - - u32 day = static_cast(ymd.day()); - - CStr suffix = day >= 11 && day <= 13 ? "th" - : day % 10 == 1 ? "st" - : day % 10 == 2 ? "nd" - : day % 10 == 3 ? "rd" - : "th"; - - return std::format("{} {}{}", month, day, suffix); + try { + return std::format(std::locale(""), "{:%B %d}", ymd); + } catch (const std::runtime_error& e) { + ERROR_LOG("Warning: Could not retrieve or use system locale ({}). Falling back to default C locale.", e.what()); + return std::format(std::locale::classic(), "{:%B %d}", ymd); + } } } diff --git a/src/main.cpp b/src/main.cpp index 2830cb6..6d60c5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -243,9 +243,6 @@ namespace { } fn main() -> i32 { - std::locale::global(std::locale("")); - DEBUG_LOG("Global locale set to: {}", std::locale().name()); - const Config& config = Config::getInstance(); const SystemData data = SystemData::fetchSystemData(config); diff --git a/src/os/os.h b/src/os/os.h index aa0bc75..8611e97 100644 --- a/src/os/os.h +++ b/src/os/os.h @@ -3,56 +3,95 @@ #include "../util/macros.h" #include "../util/types.h" +/** + * @namespace os + * @brief Provides a platform-abstracted interface for retrieving Operating System information. + * + * This namespace declares functions to get various system details like memory, + * OS version, hardware identifiers, media playback status, etc. + * The actual implementation for each function is platform-specific + * (found in linux.cpp, windows.cpp, macos.cpp). + */ namespace os { /** - * @brief Get the amount of installed RAM in bytes. + * @brief Get the total amount of physical RAM installed in the system. + * @return A Result containing the total RAM in bytes (u64) on success, + * or an error message (String) on failure. */ fn GetMemInfo() -> Result; /** - * @brief Get the currently playing song metadata. + * @brief Gets metadata about the currently playing media. + * @return A Result containing the media information (String) on success, + * or an error code (NowPlayingError) on failure. */ fn GetNowPlaying() -> Result; /** - * @brief Get the OS version. + * @brief Gets the "pretty" name of the operating system. + * @details Examples: "Ubuntu 24.04.2 LTS", "Windows 11 Pro 24H2", "macOS 15 Sequoia". + * @return A Result containing the OS version String on success, + * or an error message (String) on failure. */ fn GetOSVersion() -> Result; /** - * @brief Get the current desktop environment. + * @brief Attempts to retrieve the desktop environment. + * @details This is most relevant on Linux. May check environment variables (XDG_CURRENT_DESKTOP), + * session files, or running processes. On Windows/macOS, it might return a + * UI theme identifier (e.g., "Fluent", "Aqua") or None. + * @return An Option containing the detected DE name String, or None if detection fails or is not applicable. */ fn GetDesktopEnvironment() -> Option; /** - * @brief Get the current window manager. + * @brief Attempts to retrieve the window manager. + * @details On Linux, checks Wayland compositor or X11 WM properties. On Windows, returns "DWM" or similar. + * On macOS, might return "Quartz Compositor" or a specific tiling WM name if active. + * @return A String containing the detected WM name. Might return "Unknown" or a default value if detection fails. */ fn GetWindowManager() -> String; /** - * @brief Get the current shell. + * @brief Attempts to detect the current user shell. + * @details Checks the SHELL environment variable on Linux/macOS. On Windows, inspects the process tree + * to identify known shells like PowerShell, Cmd, or MSYS2 shells (Bash, Zsh). + * @return A String containing the detected shell name (e.g., "Bash", "Zsh", "PowerShell", "Fish"). + * May return the full path or "Unknown" as a fallback. */ fn GetShell() -> String; /** - * @brief Get the product family + * @brief Gets a system identifier, often the hardware model or product family. + * @details Examples: "MacBookPro18,3", "Latitude 5420", "ThinkPad T490". + * Implementation varies: reads DMI info on Linux, registry on Windows, sysctl on macOS. + * @return A String containing the host/product identifier. May be empty if retrieval fails. */ fn GetHost() -> String; /** - * @brief Get the kernel version. + * @brief Gets the operating system's kernel version string. + * @details Examples: "5.15.0-76-generic", "10.0.22621", "23.1.0". + * Uses uname() on Linux/macOS, WinRT/registry on Windows. + * @return A String containing the kernel version. May be empty if retrieval fails. */ fn GetKernelVersion() -> String; /** - * @brief Get the number of installed packages. + * @brief Gets the number of installed packages (Linux-specific). + * @details Sums counts from various package managers (dpkg, rpm, pacman, flatpak, snap, etc.). + * Returns 0 on non-Linux platforms or if no package managers are found. + * @return A u64 representing the total count of detected packages. */ - fn GetPackageCount() -> u64; + fn GetPackageCount() -> u64; // Note: Implementation likely exists only in linux.cpp /** - * @brief Get the current disk usage. - * @return std::pair Used space/total space + * @brief Gets the disk usage for the primary/root filesystem. + * @details Uses statvfs on Linux/macOS, GetDiskFreeSpaceExW on Windows. + * @return A Pair where: + * - first: Used disk space in bytes. + * - second: Total disk space in bytes. + * Returns {0, 0} on failure. */ fn GetDiskUsage() -> Pair; } - diff --git a/src/util/macros.h b/src/util/macros.h index 741cddf..e868601 100644 --- a/src/util/macros.h +++ b/src/util/macros.h @@ -201,7 +201,11 @@ template fn LogImpl(const LogLevel level, const std::source_location& loc, std::format_string fmt, Args&&... args) { using namespace std::chrono; using namespace term; +#ifdef _WIN32 + using enum term::Color; +#else using enum Color; +#endif const auto [color, levelStr] = [&] { switch (level) { @@ -213,32 +217,66 @@ fn LogImpl(const LogLevel level, const std::source_location& loc, std::format_st } }(); - const String filename = std::filesystem::path(loc.file_name()).lexically_normal().string(); - Print(BrightWhite, "[{:%X}] ", zoned_time { current_zone(), std::chrono::floor(system_clock::now()) }); Print(Emphasis::Bold | color, "{} ", levelStr); Print(fmt, std::forward(args)...); #ifndef NDEBUG Print(BrightWhite, "\n{:>14} ", "╰──"); - Print(Emphasis::Italic | BrightWhite, "{}:{}", filename, loc.line()); + Print( + Emphasis::Italic | BrightWhite, + "{}:{}", + std::filesystem::path(loc.file_name()).lexically_normal().string(), + loc.line() + ); #endif Print("\n"); } +// Suppress unused macro warnings in Clang #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-macros" #endif + #ifdef NDEBUG #define DEBUG_LOG(...) static_cast(0) #else +/** + * @def DEBUG_LOG + * @brief Logs a message at the DEBUG level. + * @details Only active in non-release builds (when NDEBUG is not defined). + * Includes timestamp, level, message, and source location. + * @param ... Format string and arguments for the log message. + */ #define DEBUG_LOG(...) LogImpl(LogLevel::DEBUG, std::source_location::current(), __VA_ARGS__) #endif + +/** + * @def INFO_LOG(...) + * @brief Logs a message at the INFO level. + * @details Includes timestamp, level, message, and source location (in debug builds). + * @param ... Format string and arguments for the log message. + */ #define INFO_LOG(...) LogImpl(LogLevel::INFO, std::source_location::current(), __VA_ARGS__) + +/** + * @def WARN_LOG(...) + * @brief Logs a message at the WARN level. + * @details Includes timestamp, level, message, and source location (in debug builds). + * @param ... Format string and arguments for the log message. + */ #define WARN_LOG(...) LogImpl(LogLevel::WARN, std::source_location::current(), __VA_ARGS__) + +/** + * @def ERROR_LOG(...) + * @brief Logs a message at the ERROR level. + * @details Includes timestamp, level, message, and source location (in debug builds). + * @param ... Format string and arguments for the log message. + */ #define ERROR_LOG(...) LogImpl(LogLevel::ERROR, std::source_location::current(), __VA_ARGS__) + #ifdef __clang__ #pragma clang diagnostic pop #endif diff --git a/src/util/types.h b/src/util/types.h index c83fd7d..1e928b8 100644 --- a/src/util/types.h +++ b/src/util/types.h @@ -1,253 +1,170 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include // std::array alias (Array) +#include // std::getenv, std::free +#include // std::expected alias (Result) +#include // std::map alias (Map) +#include // std::shared_ptr and std::unique_ptr aliases (SharedPointer, UniquePointer) +#include // std::optional alias (Option) +#include // std::string and std::string_view aliases (String, StringView) +#include // std::pair alias (Pair) +#include // std::variant alias (NowPlayingError) +#include // std::vector alias (Vec) #ifdef _WIN32 -// ReSharper disable once CppUnusedIncludeDirective -#include -#include -#include -#else -#include +#include // winrt::hresult_error (WindowsError) #endif -/** - * @typedef u8 - * @brief Represents an 8-bit unsigned integer. - * - * This type alias is used for 8-bit unsigned integers, ranging from 0 to 255. - * It is based on the std::uint8_t type. - */ -using u8 = std::uint8_t; +//----------------------------------------------------------------// +// Integer Type Aliases // +// Provides concise names for standard fixed-width integer types. // +//----------------------------------------------------------------// + +using u8 = std::uint8_t; ///< 8-bit unsigned integer. +using u16 = std::uint16_t; ///< 16-bit unsigned integer. +using u32 = std::uint32_t; ///< 32-bit unsigned integer. +using u64 = std::uint64_t; ///< 64-bit unsigned integer. + +using i8 = std::int8_t; ///< 8-bit signed integer. +using i16 = std::int16_t; ///< 16-bit signed integer. +using i32 = std::int32_t; ///< 32-bit signed integer. +using i64 = std::int64_t; ///< 64-bit signed integer. + +//-----------------------------------------------------------// +// Floating-Point Type Aliases // +// Provides concise names for standard floating-point types. // +//-----------------------------------------------------------// + +using f32 = std::float_t; ///< 32-bit floating-point number. +using f64 = std::double_t; ///< 64-bit floating-point number. + +//-------------------------------------------------// +// Size Type Aliases // +// Provides concise names for standard size types. // +//-------------------------------------------------// + +using usize = std::size_t; ///< Unsigned size type (result of sizeof). +using isize = std::ptrdiff_t; ///< Signed size type (result of pointer subtraction). + +//---------------------------------------------------// +// String Type Aliases // +// Provides concise names for standard string types. // +//---------------------------------------------------// + +using String = std::string; ///< Owning, mutable string. +using StringView = std::string_view; ///< Non-owning view of a string. +using CStr = const char*; ///< Pointer to a null-terminated C-style string. + +//----------------------------------------------------// +// Standard Library Type Aliases // +// Provides concise names for standard library types. // +//----------------------------------------------------// + +using Exception = std::exception; ///< Standard exception type. /** - * @typedef u16 - * @brief Represents a 16-bit unsigned integer. - * - * This type alias is used for 16-bit unsigned integers, ranging from 0 to 65,535. - * It is based on the std::uint16_t type. - */ -using u16 = std::uint16_t; - -/** - * @typedef u32 - * @brief Represents a 32-bit unsigned integer. - * - * This type alias is used for 32-bit unsigned integers, ranging from 0 to 4,294,967,295. - * It is based on the std::uint32_t type. - */ -using u32 = std::uint32_t; - -/** - * @typedef u64 - * @brief Represents a 64-bit unsigned integer. - * - * This type alias is used for 64-bit unsigned integers, ranging from 0 to - * 18,446,744,073,709,551,615. It is based on the std::uint64_t type. - */ -using u64 = std::uint64_t; - -// Type Aliases for Signed Integers - -/** - * @typedef i8 - * @brief Represents an 8-bit signed integer. - * - * This type alias is used for 8-bit signed integers, ranging from -128 to 127. - * It is based on the std::int8_t type. - */ -using i8 = std::int8_t; - -/** - * @typedef i16 - * @brief Represents a 16-bit signed integer. - * - * This type alias is used for 16-bit signed integers, ranging from -32,768 to 32,767. - * It is based on the std::int16_t type. - */ -using i16 = std::int16_t; - -/** - * @typedef i32 - * @brief Represents a 32-bit signed integer. - * - * This type alias is used for 32-bit signed integers, ranging from -2,147,483,648 to 2,147,483,647. - * It is based on the std::int32_t type. - */ -using i32 = std::int32_t; - -/** - * @typedef i64 - * @brief Represents a 64-bit signed integer. - * - * This type alias is used for 64-bit signed integers, ranging from -9,223,372,036,854,775,808 to - * 9,223,372,036,854,775,807. It is based on the std::int64_t type. - */ -using i64 = std::int64_t; - -// Type Aliases for Floating-Point Numbers - -/** - * @typedef f32 - * @brief Represents a 32-bit floating-point number. - * - * This type alias is used for 32-bit floating-point numbers, which follow the IEEE 754 standard. - * It is based on the float type. - */ -using f32 = float; - -/** - * @typedef f64 - * @brief Represents a 64-bit floating-point number. - * - * This type alias is used for 64-bit floating-point numbers, which follow the IEEE 754 standard. - * It is based on the double type. - */ -using f64 = double; - -// Type Aliases for Size Types - -/** - * @typedef usize - * @brief Represents an unsigned size type. - * - * This type alias is used for representing the size of objects in bytes. - * It is based on the std::size_t type, which is the result type of the sizeof operator. - */ -using usize = std::size_t; - -/** - * @typedef isize - * @brief Represents a signed size type. - * - * This type alias is used for representing pointer differences. - * It is based on the std::ptrdiff_t type, which is the signed integer type returned when - * subtracting two pointers. - */ -using isize = std::ptrdiff_t; - -/** - * @typedef String - * @brief Represents a string. - */ -using String = std::string; - -/** - * @typedef StringView - * @brief Represents a string view. - * - * This type alias is used for non-owning views of strings, allowing for efficient string manipulation - * without copying the underlying data. - */ -using StringView = std::string_view; - -/** - * @typedef Exception - * @brief Represents a generic exception type. - */ -using Exception = std::exception; - -/** - * @typedef Expected - * @brief Represents an expected value or an error. + * @typedef Result + * @brief Alias for std::expected. Represents a value that can either be + * a success value of type Tp or an error value of type Er. + * @tparam Tp The type of the success value. + * @tparam Er The type of the error value. */ template using Result = std::expected; /** - * @typedef Unexpected - * @brief Represents an unexpected error. + * @typedef Err + * @brief Alias for std::unexpected. Used to construct a Result in an error state. + * @tparam Er The type of the error value. */ template using Err = std::unexpected; /** - * @typedef Optional - * @brief Represents an optional value. + * @typedef Option + * @brief Alias for std::optional. Represents a value that may or may not be present. + * @tparam Tp The type of the potential value. */ template using Option = std::optional; /** * @typedef Array - * @brief Represents a fixed-size array. + * @brief Alias for std::array. Represents a fixed-size array. + * @tparam Tp The element type. + * @tparam sz The size of the array. */ template using Array = std::array; /** * @typedef Vec - * @brief Represents a dynamic array (vector). + * @brief Alias for std::vector. Represents a dynamic-size array (vector). + * @tparam Tp The element type. */ template using Vec = std::vector; /** * @typedef Pair - * @brief Represents a pair of values. + * @brief Alias for std::pair. Represents a pair of values. + * @tparam T1 The type of the first element. + * @tparam T2 The type of the second element. */ template using Pair = std::pair; /** * @typedef Map - * @brief Represents a map (dictionary) of key-value pairs. + * @brief Alias for std::map. Represents an ordered map (dictionary). + * @tparam Key The key type. + * @tparam Val The value type. */ template using Map = std::map; /** * @typedef SharedPointer - * @brief Represents a shared pointer. - * - * This type alias is used for shared ownership of dynamically allocated objects. + * @brief Alias for std::shared_ptr. Manages shared ownership of a dynamically allocated object. + * @tparam Tp The type of the managed object. */ template using SharedPointer = std::shared_ptr; /** * @typedef UniquePointer - * @brief Represents a unique pointer. - * - * This type alias is used for unique ownership of dynamically allocated objects. + * @brief Alias for std::unique_ptr. Manages unique ownership of a dynamically allocated object. + * @tparam Tp The type of the managed object. + * @tparam Dp The deleter type (defaults to std::default_delete). */ -template +template > using UniquePointer = std::unique_ptr; -/** - * @typedef CStr - * @brief Represents a C string (const char*). - * - * This type alias is used for C-style strings, which are null-terminated arrays of characters. - */ -using CStr = const char*; +//--------------------------------------------------------// +// Application-Specific Type Aliases // +// Provides concise names for application-specific types. // +//--------------------------------------------------------// /** * @enum NowPlayingCode - * @brief Represents error codes for Now Playing functionality. + * @brief Error codes specific to the Now Playing feature. */ enum class NowPlayingCode : u8 { - NoPlayers, - NoActivePlayer, + NoPlayers, ///< No media players were found (e.g., no MPRIS services on Linux). + NoActivePlayer, ///< Players were found, but none are currently active or playing. }; #ifdef _WIN32 -/** - * @typedef WindowsError - * @brief Represents a Windows-specific error. - */ -using WindowsError = winrt::hresult_error; +using WindowsError = winrt::hresult_error; ///< Alias for WinRT HRESULT error type. #endif -// Unified error type +/** + * @typedef NowPlayingError + * @brief Represents the possible errors returned by "Now Playing" functions. + * It's a variant that can hold either a generic NowPlayingCode, + * a platform-specific error (WindowsError on Windows, String on others), + * or potentially other error types if extended. + */ using NowPlayingError = std::variant< NowPlayingCode, #ifdef _WIN32 @@ -257,30 +174,45 @@ using NowPlayingError = std::variant< #endif >; -enum class EnvError : u8 { NotFound, AccessError }; +/** + * @enum EnvError + * @brief Error codes for environment variable retrieval. + */ +enum class EnvError : u8 { + NotFound, ///< Environment variable not found. + AccessError, ///< Access error when trying to retrieve the variable. +}; +/** + * @brief Safely retrieves an environment variable. + * @param name The name of the environment variable to retrieve. + * @return A Result containing the value of the environment variable as a String, + * or an EnvError if an error occurred. + */ inline auto GetEnv(CStr name) -> Result { #ifdef _WIN32 char* rawPtr = nullptr; usize bufferSize = 0; + // Use _dupenv_s to safely retrieve environment variables on Windows const i32 err = _dupenv_s(&rawPtr, &bufferSize, name); const UniquePointer ptrManager(rawPtr, free); if (err != 0) - return Err(EnvError::AccessError); + return Err(EnvError::AccessError); // Error retrieving environment variable if (!ptrManager) - return Err(EnvError::NotFound); + return Err(EnvError::NotFound); // Environment variable not found return ptrManager.get(); #else + // Use std::getenv to retrieve environment variables on POSIX systems const CStr value = std::getenv(name); if (!value) - return Err(EnvError::NotFound); + return Err(EnvError::NotFound); // Environment variable not found - return String(value); + return value; #endif }