diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71629f5fc6..f22e9d3735 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install codespell shell: bash @@ -29,7 +29,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: uname -a run: uname -a @@ -68,7 +68,7 @@ jobs: ffversion: ${{ steps.ffversion.outputs.ffversion }} steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: uname -a run: uname -a @@ -137,7 +137,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: uname -a run: uname -a @@ -198,7 +198,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: uraimo/run-on-arch-action@v3 @@ -237,7 +237,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: uraimo/run-on-arch-action@v3 @@ -273,7 +273,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: uraimo/run-on-arch-action@v3 @@ -308,7 +308,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: uraimo/run-on-arch-action@v3 @@ -343,7 +343,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: uraimo/run-on-arch-action@v3 @@ -374,7 +374,7 @@ jobs: name: Musl-amd64 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: setup alpine linux uses: jirutka/setup-alpine@master @@ -416,7 +416,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: uname -a run: uname -a @@ -463,7 +463,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: uname -a run: uname -a @@ -507,7 +507,7 @@ jobs: name: SunOS-amd64 steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: vmactions/omnios-vm@v1 @@ -543,7 +543,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: cross-platform-actions/action@master @@ -580,7 +580,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: cross-platform-actions/action@master @@ -616,7 +616,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: cross-platform-actions/action@master @@ -653,7 +653,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: vmactions/dragonflybsd-vm@v1 @@ -688,7 +688,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: run VM uses: cross-platform-actions/action@master @@ -700,7 +700,7 @@ jobs: shell: bash run: | uname -a - pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 + pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features @@ -726,7 +726,7 @@ jobs: shell: msys2 {0} steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: setup-msys2 uses: msys2/setup-msys2@v2 @@ -788,7 +788,7 @@ jobs: shell: msys2 {0} steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: setup-msys2 uses: msys2/setup-msys2@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c9cd1bd1c..1fcb195631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,48 @@ +# 2.50.0 + +Changes: +* Keys in JSON configuration files are now case-sensitive, as stated in v2.49.0. + * This is a breaking change, but it should not affect most users as long as your config file passes JSON schema validation. +* All module config flags have been removed, as stated in v2.49.0. + * To configure modules via the command line, use: `echo '{"modules": [{"type":"custom","format":"Hello Fastfetch!"}]}' | fastfetch -c -`. +* The percent bar config `display.bar.*` options have been replaced with a more organized, nested object structure. + * `display.bar.charElapsed` has been renamed to `display.bar.char.elapsed`. + * `display.bar.charTotal` has been renamed to `display.bar.char.total`. + * `display.bar.borderLeft` has been renamed to `display.bar.border.left`. + * `display.bar.borderRight` has been renamed to `display.bar.border.right`. +* The undocumented flag `--load-config` has been removed. + * Use `--config` or `-c` instead. +* Flashfetch, a simplified fastfetch variant that used a hardcoded module list with direct function calls to reduce startup overhead, has been changed to a version that aims to match neofetch's behavior as closely as possible, for demonstration purposes. + * Flashfetch is intended to be built from source (like [st](https://st.suckless.org/)). We do not provide prebuilt binaries in distributions. + +Features: +* Added support for reading JSON config from stdin using `--config -` or `-c -`. +* Added `display.bar.border.{leftElapsed,rightElapsed}` for using the border as part of the bar content. (#1875) + * `display.bar.border: null` has been added as a shorthand to disable bar borders. +* Added `display.bar.color.{elapsed,total,border}` to customize the color of the elapsed, total, and border sections of the percent bar. + * `display.bar.color: null` has been added as a shorthand to disable bar colors. +* Improved Bedrock Linux detection (#1881, OS / Disk, Linux) +* Added the command flag `--gen-config-full`, which generates a JSON config file containing all optional module options. +* Improved the default IP address display when `localip.showAllIPs` is not set (LocalIP) + * For IPv4, the preferred source address (if detected) is shown. + * For IPv6, the first GUA or ULA that is not deprecated or temporary is shown. +* Added support for interface speed detection on SunOS (LocalIP, SunOS) +* Added detection support for Xlibre (#1888, WM, Linux) +* Improved the accuracy of color detection (Cursor, macOS) +* Improved the proformance of `Nix` package manager detection on macOS by porting optimizations form Linux port (#1893, Packages, macOS) + +Bugfixes: +* Fixed custom object inheriting a key from the previous custom object if the key is blank (#1477) +* Fixed a possible segfault when parsing color strings in the JSON config (#1878) +* Fixed GPU driver detection when DRM is used (GPU, FreeBSD) +* Fixed default route detection on DragonFly BSD (LocalIP, DFBSD) +* Fixed lliurex detection (#1882, OS, Linux) +* Fixed compatibility with `-ffast-math` (#1894) +* Fixed physical GPU sometimes being ignored (#1896, GPU, Windows) + +Logos: +* Added ObsidianOS (#1890) + # 2.49.0 Deprecation Notice: @@ -26,8 +71,8 @@ Features: * Add `--{duration,percent,size,freq,temp}-space-before-unit [always|never]` options to add a space before the unit when printing duration, percent, size, frequency and temperature values * Add `--duration-abbreviation` to abbreviate duration values in custom format * For example: `1 day, 2 hours, 3 mins` will be displayed as `1d 2h 3m` -* Add `--percent-with` to pad the percent value with spaces to a fixed width - * For example: `--percent-with 3` will display ` 50%` instead of `50%`; useful for aligning percent values in custom format +* Add `--percent-width` to pad the percent value with spaces to a fixed width + * For example: `--percent-width 3` will display ` 50%` instead of `50%`; useful for aligning percent values in custom format Bugfixes: * Improve accuracy of Flatpak count detection (#1856, Packages, Linux) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22917aec6c..4c1fb94b50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.49.0 + VERSION 2.50.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -474,7 +474,6 @@ set(LIBFASTFETCH_SRC src/modules/wmtheme/wmtheme.c src/modules/zpool/zpool.c src/options/display.c - src/options/modules.c src/options/logo.c src/options/general.c src/util/edidHelper.c @@ -548,6 +547,7 @@ if(LINUX) src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c src/detection/packages/packages_linux.c + src/detection/packages/packages_nix.c src/detection/poweradapter/poweradapter_linux.c src/detection/processes/processes_linux.c src/detection/gtk_qt/qt.c @@ -896,7 +896,7 @@ elseif(OpenBSD) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c - src/common/netif/netif_bsd.c + src/common/netif/netif_apple.c src/common/networking/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -940,6 +940,7 @@ elseif(APPLE) src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m src/detection/packages/packages_apple.c + src/detection/packages/packages_nix.c src/detection/poweradapter/poweradapter_apple.c src/detection/processes/processes_bsd.c src/detection/sound/sound_apple.c @@ -1042,7 +1043,7 @@ elseif(SunOS) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c src/common/io/io_unix.c - src/common/netif/netif_bsd.c + src/common/netif/netif_apple.c src/common/networking/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_nosupport.c diff --git a/README.md b/README.md index f31b8b5116..11832f6ba7 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,6 @@ Some distributions package outdated versions of fastfetch. Older versions receiv Packaging status -* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer) * Debian: `apt install fastfetch` (for Debian 13 or newer) * Debian / Ubuntu: Download `fastfetch-linux-.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer). * Arch Linux: `pacman -S fastfetch` @@ -58,7 +57,7 @@ If fastfetch is not packaged for your distribution or an outdated version is pac ### macOS -* [HomeBrew](https://formulae.brew.sh/formula/fastfetch#default): `brew install fastfetch` +* [Homebrew](https://formulae.brew.sh/formula/fastfetch#default): `brew install fastfetch` * [MacPorts](https://ports.macports.org/port/fastfetch/): `sudo port install fastfetch` ### Windows @@ -95,7 +94,8 @@ See the Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building * Run with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) to find what interests you: `fastfetch -c all.jsonc` * View all data that fastfetch detects: `fastfetch -s [:][:] --format json` * Display help messages: `fastfetch --help` -* Generate a config file based on command line arguments: `fastfetch --arg1 --arg2 --gen-config` +* Generate a minimal config file: `fastfetch [-s [:]] --gen-config []` + * Use: `--gen-config-full` to generate a full config file with all optional options ## Customization diff --git a/debian/changelog b/debian/changelog index 331be609b5..0d9c31f5a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.49.0) jammy; urgency=medium + + * Update to 2.49.0 + + -- Carter Li Thu, 31 Jul 2025 14:32:59 +0800 + fastfetch (2.48.0) jammy; urgency=medium * Update to 2.48.0 diff --git a/debian/files b/debian/files index 9c35d4bb28..0f3b308001 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.48.0_source.buildinfo universe/utils optional +fastfetch_2.49.0_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index 3805a71fe1..a1e66b3f9d 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -10,25 +10,25 @@ ] }, "key": { - "description": "Key of the module", - "type": "string" + "description": "Key of the module\nOne whitespace character (` `) can be used to hide the key", + "type": "string", + "minLength": 1 }, "keyColor": { - "description": "Color of the module key. Left empty to use `display.color.keys`", + "description": "Color of the module key to override the global setting `display.color.key`", "$ref": "#/$defs/colors" }, "keyWidth": { - "description": "Width of the module key. Use 0 to use `display.keyWidth`", + "description": "Width of the module key to override the global setting `display.keyWidth`", "type": "integer", - "minimum": 0, - "default": 0 + "minimum": 1 }, "keyIcon": { "description": "Set the icon to be displayed by `display.keyType: \"icon\"`", "type": "string" }, "outputColor": { - "description": "Output color of the module. Left empty to use `display.color.output`", + "description": "Output color of the module to override the global setting `display.color.output`", "$ref": "#/$defs/colors" }, "percentType": { @@ -549,7 +549,7 @@ "const": null }, { - "description": "Set the source file of the logo", + "description": "Set the source file of the logo or built-in ASCII art name", "type": "string" }, { @@ -559,23 +559,67 @@ "properties": { "type": { "description": "Set the type of the logo", - "enum": [ - "auto", - "builtin", - "small", - "file", - "file-raw", - "data", - "data-raw", - "command-raw", - "sixel", - "kitty", - "kitty-direct", - "kitty-icat", - "iterm", - "chafa", - "raw", - "none" + "oneOf": [ + { + "const": "auto", + "description": "If something is given, first try built-in, then file. Otherwise detect logo" + }, + { + "const": "builtin", + "description": "Built-in ASCII art" + }, + { + "const": "small", + "description": "Built-in ASCII art, small version (not all logos support this option)" + }, + { + "const": "file", + "description": "Text file, printed with color code replacement" + }, + { + "const": "file-raw", + "description": "Text file, printed as is" + }, + { + "const": "data", + "description": "Text data, printed with color code replacement" + }, + { + "const": "data-raw", + "description": "Text data, printed as is" + }, + { + "const": "sixel", + "description": "Image file, printed as sixel codes" + }, + { + "const": "kitty", + "description": "Image file, printed using kitty graphics protocol" + }, + { + "const": "kitty-direct", + "description": "Image file, tells the terminal emulator to read image data from the specified file" + }, + { + "const": "kitty-icat", + "description": "Image file, uses `kitten icat` to display the image. Requires binary `kitten` to be installed" + }, + { + "const": "iterm", + "description": "Image file, uses `iTerm` image protocol" + }, + { + "const": "chafa", + "description": "Image file, prints `ASCII` art image generated by `libchafa`" + }, + { + "const": "raw", + "description": "Image file, printed as `raw` binary string image" + }, + { + "const": "none", + "description": "Disable logo printing" + } ], "default": "auto" }, @@ -627,14 +671,30 @@ } }, "width": { - "type": "integer", - "description": "Set the width of the logo (in characters). Required for iTerm image protocol", - "minimum": 1 + "oneOf": [ + { + "type": "null", + "description": "Auto detect width (default)" + }, + { + "type": "integer", + "description": "Set the width of the logo (in characters). Required for some image protocols", + "minimum": 1 + } + ] }, "height": { - "type": "integer", - "description": "Set the height of the logo (in characters). Required for iTerm image protocol", - "minimum": 1 + "oneOf": [ + { + "type": "null", + "description": "Auto detect width (default)" + }, + { + "type": "integer", + "description": "Set the height of the logo (in characters). Required for some image protocols", + "minimum": 1 + } + ] }, "padding": { "type": "object", @@ -700,32 +760,71 @@ "canvasMode": { "type": "string", "description": "Determine how colors are used in the output. This value maps to enum ChafaCanvasMode.", - "enum": [ - "TRUECOLOR", - "INDEXED_256", - "INDEXED_240", - "INDEXED_16", - "FGBG_BGFG", - "FGBG", - "INDEXED_8", - "INDEXED_16_8" + "oneOf": [ + { + "const": "TRUECOLOR", + "description": "Use 24-bit true colors" + }, + { + "const": "INDEXED_256", + "description": "Use 256 colors" + }, + { + "const": "INDEXED_240", + "description": "Use 240 colors, but avoid using the lower 16 whose values vary between terminal environments" + }, + { + "const": "INDEXED_16", + "description": "Use 16 colors using the aixterm ANSI extension" + }, + { + "const": "FGBG_BGFG", + "description": "Use default foreground and background colors, plus inversion" + }, + { + "const": "FGBG", + "description": "Use default foreground and background colors. No ANSI codes will be used" + }, + { + "const": "INDEXED_8", + "description": "Use 8 colors, compatible with original ANSI X3.64" + }, + { + "const": "INDEXED_16_8", + "description": "Use 16 FG colors (8 of which enabled with bold/bright) and 8 BG colors" + } ] }, "colorSpace": { "type": "string", "description": "Set color space used for quantization. This value maps to enum ChafaColorSpace.", - "enum": [ - "RGB", - "DIN99D" + "oneOf": [ + { + "const": "RGB", + "description": "RGB color space. Fast but imprecise" + }, + { + "const": "DIN99D", + "description": "DIN99d color space. Slower, but good perceptual color precision" + } ] }, "ditherMode": { "type": "string", "description": "Set output dither mode (No effect with 24-bit color). This value maps to enum ChafaDitherMode.", - "enum": [ - "NONE", - "ORDERED", - "DIFFUSION" + "oneOf": [ + { + "const": "NONE", + "description": "No dithering" + }, + { + "const": "ORDERED", + "description": "Ordered dithering (Bayer or similar)" + }, + { + "const": "DIFFUSION", + "description": "Error diffusion dithering (Floyd-Steinberg or similar)" + } ] } } @@ -889,11 +988,23 @@ "type": { "type": "string", "description": "Set whether to show icon before string keys", - "enum": [ - "none", - "string", - "icon", - "both" + "oneOf": [ + { + "const": "none", + "description": "Disable keys" + }, + { + "const": "string", + "description": "Show string keys" + }, + { + "const": "icon", + "description": "Show icon keys (requires newest nerd font)" + }, + { + "const": "both", + "description": "Show both icon and string keys" + } ], "default": "string" }, @@ -955,7 +1066,24 @@ "unit": { "type": "string", "description": "Set the unit of temperature", - "enum": ["D", "Default", "Celsius", "C", "Fahrenheit", "F", "Kelvin", "K"], + "oneOf": [ + { + "const": "C", + "description": "Celsius" + }, + { + "const": "F", + "description": "Fahrenheit" + }, + { + "const": "K", + "description": "Kelvin" + }, + { + "const": "D", + "description": "Default (alias for Celsius)" + } + ], "default": "D" }, "ndigits": { @@ -997,25 +1125,87 @@ "additionalProperties": false, "description": "Set the bar configuration", "properties": { - "charElapsed": { - "type": "string", - "description": "Set the character to use in elapsed part", - "default": "■" - }, - "charTotal": { - "type": "string", - "description": "Set the character to use in total part", - "default": "-" + "char": { + "type": "object", + "additionalProperties": false, + "description": "Set the characters used in the bar", + "properties": { + "elapsed": { + "type": "string", + "description": "Set the character to use in elapsed part", + "default": "■" + }, + "total": { + "type": "string", + "description": "Set the character to use in total part", + "default": "-" + } + } }, - "borderLeft": { - "type": "string", - "description": "Set the string to use at left border", - "default": "[ " + "border": { + "oneOf": [ + { + "type": "null", + "description": "Disable bar borders" + }, + { + "type": "object", + "additionalProperties": false, + "description": "Set the string to use of borders of percentage bars", + "properties": { + "left": { + "type": "string", + "description": "Set the string to use at left border", + "default": "[ " + }, + "right": { + "type": "string", + "description": "Set the string to use at right border", + "default": " ]" + }, + "leftElapsed": { + "type": "string", + "description": "If both leftElapsed and rightElapsed are set, the border will be used as parts of bar content", + "default": "" + }, + "rightElapsed": { + "type": "string", + "description": "If both leftElapsed and rightElapsed are set, the border will be used as parts of bar content", + "default": "" + } + } + } + ] }, - "borderRight": { - "type": "string", - "description": "Set the string to use at right border", - "default": " ]" + "color": { + "oneOf": [ + { + "type": "null", + "description": "Disable color in percentage bars" + }, + { + "type": "object", + "additionalProperties": false, + "description": "Set the color to use of percentage bars", + "properties": { + "elapsed": { + "description": "Color to use in the elapsed part of percentage bars\nBy default, auto selected by percent.color.{green,yellow,red}", + "$ref": "#/$defs/colors", + "default": "auto" + }, + "total": { + "description": "Color to use in the total part of percentage bars", + "$ref": "#/$defs/colors", + "default": "light_white" + }, + "border": { + "description": "Color to use in the borders of percentage bars", + "$ref": "#/$defs/colors", + "default": "light_white" + } + } + } + ] }, "width": { "type": "integer", @@ -1739,14 +1929,35 @@ "symbol": { "description": "Set the symbol to use", "type": "string", - "enum": [ - "block", - "background", - "circle", - "diamond", - "triangle", - "square", - "star" + "oneOf": [ + { + "const": "block", + "description": "\u2588\u2588\u2588" + }, + { + "const": "background", + "description": "(whitespaces with background)" + }, + { + "const": "circle", + "description": "\u25cf" + }, + { + "const": "diamond", + "description": "\u25c6" + }, + { + "const": "triangle", + "description": "\u25b2" + }, + { + "const": "square", + "description": "\u25a0" + }, + { + "const": "star", + "description": "\u2605" + } ], "default": "background" }, @@ -1783,9 +1994,15 @@ "key": { "$ref": "#/$defs/key" }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, "keyIcon": { "$ref": "#/$defs/keyIcon" }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, "condition": { "$ref": "#/$defs/conditions" } @@ -1805,7 +2022,7 @@ "type": "string" }, "param": { - "description": "Set the parameter used when starting the shell\nDefault: /c for Windows, -c for *nix", + "description": "Set the parameter used when starting the shell\nIf set to an empty string, it will be ignored\nDefault: /c for Windows, -c for *nix", "type": "string" }, "text": { @@ -1949,15 +2166,34 @@ "const": "display" }, "compactType": { - "enum": [ - "none", - "original", - "scaled", - "original-with-refresh-rate", - "scaled-with-refresh-rate" - ], "description": "Set if all displays should be printed in one line", - "default": "none" + "oneOf": [ + { + "const": null, + "description": "Disable compact mode" + }, + { + "const": "none", + "description": "Disable compact mode (kept for compatibility)" + }, + { + "const": "original", + "description": "Print original resolutions" + }, + { + "const": "scaled", + "description": "Print scaled resolutions" + }, + { + "const": "original-with-refresh-rate", + "description": "Print original resolutions with refresh rates" + }, + { + "const": "scaled-with-refresh-rate", + "description": "Print scaled resolutions with refresh rates" + } + ], + "default": null }, "preciseRefreshRate": { "description": "Set if decimal refresh rates should not be rounded into integers when printing", @@ -1966,12 +2202,25 @@ }, "order": { "description": "Set the order should be used when printing", - "enum": [ - "none", - "asc", - "desc" + "oneOf": [ + { + "const": null, + "description": "Use the default order" + }, + { + "const": "none", + "description": "Use the detected order (kept for compatibility)" + }, + { + "const": "asc", + "description": "Sort by display name in ascending order" + }, + { + "const": "desc", + "description": "Sort by display name in descending order" + } ], - "default": "none" + "default": null }, "key": { "$ref": "#/$defs/key" @@ -2018,6 +2267,11 @@ "type": "string", "description": "A colon separated file systems to hide from the disk output" }, + "showRegular": { + "type": "boolean", + "description": "Set if regular volume should be printed", + "default": true + }, "showExternal": { "type": "boolean", "description": "Set if external volume should be printed", @@ -2045,7 +2299,7 @@ }, "useAvailable": { "type": "boolean", - "description": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes", + "description": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes\nMay be required for macOS to display correct results", "default": false }, "percent": { @@ -2132,8 +2386,8 @@ }, "slowVersionDetection": { "type": "boolean", - "description": "Set if DE version should be detected with slow operations.\nShould be unnecessary for most cases.", - "default": "false" + "description": "Set if DE version should be detected with slow operations.\nShould be unnecessary for most cases.\nThis is only used as a fallback method. Please file a bug report if you encounter any issues.", + "default": false }, "key": { "$ref": "#/$defs/key" @@ -2168,10 +2422,19 @@ "description": "Print DNS servers" }, "showType": { - "enum": [ - "ipv4", - "ipv6", - "both" + "oneOf": [ + { + "const": "ipv4", + "description": "Show IPv4 addresses only" + }, + { + "const": "ipv6", + "description": "Show IPv6 addresses only" + }, + { + "const": "both", + "description": "Show both IPv4 and IPv6 addresses" + } ], "default": "both", "description": "Specify the type of DNS servers should be detected" @@ -2317,31 +2580,65 @@ "$ref": "#/$defs/temperature" }, "driverSpecific": { - "description": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)", + "description": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)\nRequires the latest GPU drivers to be installed.", "type": "boolean", "default": false }, "detectionMethod": { "description": "Force using a specified method to detect GPUs", "type": "string", - "enum": [ - "auto", - "pci", - "vulkan", - "opencl", - "opengl" + "oneOf": [ + { + "const": "auto", + "description": "Query platform-specific graphics APIs.\nRequires proper GPU drivers to be installed.\nSupported on Linux, FreeBSD, Windows and macOS" + }, + { + "const": "pci", + "description": "Search PCI devices, which does not require GPU drivers to be installed.\nNot supported on Windows and macOS" + }, + { + "const": "vulkan", + "description": "Use Vulkan API.\nSlow and requires proper Vulkan drivers to be installed.\nUsed for Android" + }, + { + "const": "opencl", + "description": "Use OpenCL API.\nSlow and requires proper OpenCL drivers to be installed" + }, + { + "const": "opengl", + "description": "Use OpenGL API.\nSlow and only detects one GPU.\nUsed for OpenBSD" + } ], - "default": "auto" + "default": "" }, "hideType": { "description": "Specify the type of GPUs should not be printed", - "enum": [ - "integrated", - "discrete", - "unknown", - "none" + "oneOf": [ + { + "const": null, + "description": "Do not hide any GPUs" + }, + { + "const": "none", + "description": "Do not hide any GPUs (kept for compatibility)" + }, + { + "const": "integrated", + "description": "Hide integrated GPUs" + }, + { + "const": "discrete", + "description": "Hide discrete GPUs" + }, + { + "const": "unknown", + "description": "Hide unknown (unrecognized) GPUs" + } ], - "default": "none" + "default": null + }, + "percent": { + "$ref": "#/$defs/percent" }, "key": { "$ref": "#/$defs/key" @@ -2600,7 +2897,7 @@ "default": true }, "showAllIps": { - "description": "Show all IPs bound to the same interface.\nBy default only the first IP is shown", + "description": "Show all IPs bound to the same interface.\nBy default only the firstly detected IP is shown", "type": "boolean", "default": false }, @@ -2619,7 +2916,7 @@ "type": "string" }, "defaultRouteOnly": { - "description": "Show ips that are used for default routing only", + "description": "Show ips that are used for default routing only\nDoesn't work on Android", "type": "boolean", "default": true }, @@ -2867,7 +3164,7 @@ "type": "string" }, "defaultRouteOnly": { - "description": "Show ips that are used for default routing only", + "description": "Show ips that are used for default routing only\nDoesn't work on Android", "type": "boolean", "default": true }, @@ -2878,7 +3175,7 @@ }, "waitTime": { "type": "integer", - "description": "Wait time (in ms). Disk I/O = (totalBytesEnd - totalBytesStart) / waitTime", + "description": "Wait time (in ms). Net I/O = (totalBytesEnd - totalBytesStart) / waitTime", "default": 200, "minimum": 1 }, @@ -2948,10 +3245,19 @@ }, "library": { "description": "Set the OpenGL context creation library to use", - "enum": [ - "auto", - "egl", - "glx" + "oneOf": [ + { + "const": "auto", + "description": "Prefer EGL on *nix; prefer platform-specific implementation on others" + }, + { + "const": "egl", + "description": "Use EGL, which works on TTY" + }, + { + "const": "glx", + "description": "Use GLX, requires X session (*nix only)" + } ], "default": "auto" }, @@ -3020,44 +3326,51 @@ "description": "List installed package managers and count of installed packages" }, "disabled": { - "description": "List of package managers to be disabled when detecting", - "type": "array", - "items": { - "type": "string", - "enum": [ - "am", - "apk", - "brew", - "choco", - "dpkg", - "emerge", - "eopkg", - "flatpak", - "guix", - "hpkg", - "linglong", - "lpkg", - "lpkgbuild", - "macports", - "mport", - "nix", - "opkg", - "pacman", - "pacstall", - "paludis", - "pisi", - "pkg", - "pkgtool", - "qi", - "rpm", - "scoop", - "snap", - "sorcery", - "winget", - "xbps" - ], - "uniqueItems": true - }, + "oneOf": [ + { + "description": "List of package managers to be disabled when detecting\nWarning: Some detection methods can be very slow.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "am", + "apk", + "brew", + "choco", + "dpkg", + "emerge", + "eopkg", + "flatpak", + "guix", + "hpkg", + "linglong", + "lpkg", + "lpkgbuild", + "macports", + "mport", + "nix", + "opkg", + "pacman", + "pacstall", + "paludis", + "pisi", + "pkg", + "pkgtool", + "rpm", + "scoop", + "snap", + "sorcery", + "winget", + "xbps" + ], + "uniqueItems": true + } + }, + { + "description": "Enable all package managers", + "type": "null" + } + ], "default": ["winget"] }, "combined": { @@ -3271,10 +3584,10 @@ "default": "http://ipinfo.io/ip" }, "timeout": { - "description": "Time in milliseconds to wait for the public ip server to respond", + "description": "Time in milliseconds to wait for the public ip server to respond.\n0 to disable timeout", "type": "integer", "minimum": 0, - "default": "disabled (0)" + "default": 0 }, "ipv6": { "description": "Whether to use IPv6 for public IP detection server", @@ -3377,10 +3690,19 @@ "soundType": { "description": "Set what type of sound devices should be printed", "type": "string", - "enum": [ - "main", - "active", - "all" + "oneOf": [ + { + "const": "main", + "description": "Print only main sound devices" + }, + { + "const": "active", + "description": "Print only active sound devices" + }, + { + "const": "all", + "description": "Print all sound devices" + } ], "default": "main" }, @@ -3878,14 +4200,14 @@ "const": "weather" }, "location": { - "description": "The location to display", + "description": "The location to display\nMust be URI encoded (e.g., a whitespace must be encoded as \"+\")", "type": "string" }, "timeout": { - "description": "Time in milliseconds to wait for the weather server to respond", + "description": "Time in milliseconds to wait for the weather server to respond.\n0 to disable timeout", "type": "integer", "minimum": 0, - "default": "disabled (0)" + "default": 0 }, "outputFormat": { "description": "The output weather format to be used (must be URI encoded)", diff --git a/presets/examples/20.jsonc b/presets/examples/20.jsonc index 4bdbe5faf3..7f16be91fc 100644 --- a/presets/examples/20.jsonc +++ b/presets/examples/20.jsonc @@ -12,10 +12,11 @@ "type": ["bar", "hide-others"] }, "bar": { - "borderLeft": "", - "borderRight": "", - "charElapsed": "█", - "charTotal": "░", + "border": null, + "char": { + "elapsed": "█", + "total": "░" + }, "width": 40 }, "constants": [ diff --git a/presets/examples/28.jsonc b/presets/examples/28.jsonc new file mode 100644 index 0000000000..f49c2ca95c --- /dev/null +++ b/presets/examples/28.jsonc @@ -0,0 +1,63 @@ +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "type": "small" + }, + "display": { + "separator": " ", + "key": { + "type": "both" + }, + "bar": { + "border": { + "left": "\uee00", + "leftElapsed": "\uee03", + "right": "\uee02", + "rightElapsed": "\uee05" + }, + "char": { + "total": "\uee01", + "elapsed": "\uee04" + }, + "color": { + "total": null + } + }, + "percent": { + "type": [ + "bar", + "bar-monochrome" + ] + } + }, + "modules": [ + "title", + "separator", + { + "type": "memory", + "key": "MEM" + }, + { + "type": "swap", + "key": "SWP" + }, + { + "type": "disk", + "folders": "/", + "key": "DSK" + }, + { + "type": "battery", + "key": "BAT" + }, + { + "type": "brightness", + "key": "BGT" + }, + { + "type": "colors", + "paddingLeft": 6, + "symbol": "circle" + } + ] +} diff --git a/presets/examples/29.jsonc b/presets/examples/29.jsonc new file mode 100644 index 0000000000..493350a439 --- /dev/null +++ b/presets/examples/29.jsonc @@ -0,0 +1,136 @@ +// #1887 +{ + "$schema": "file:///Users/carter/fastfetch/doc/json_schema.json", + "logo": null, + "display": { + "constants": [ + "\u001b[s\u001b[33C│\u001b[u", + " » " + ], + "separator": "", + "percent": { + "type": ["num", "bar"] + }, + "brightColor": false, + "bar": { + "border": { + "left": "[", + "leftElapsed": "[─", + "right": "]", + "rightElapsed": "─]" + }, + "char": { + "elapsed": "─", + "total": "─" + }, + "color": { + "elapsed": "default", + "total": "light_black" + }, + "width": 14 + }, + "color": { + "separator": "default", + "keys": "default", + "output": "default" + } + }, + "modules": [ + "title", + { + "type": "custom", + "format": "┌────「 {#1}OS{#} 」────────────────────────────┐" + }, + { + "type": "os", + "key": "│ {icon}{$2}{$1}" + }, + { + "type": "disk", + "folders": "/", + "key": "│ {$1}", + "format": "{size-percentage-bar} {size-percentage}" + }, + { + "type": "disk", + "folders": "/", + "key": "│ {$1}", + "format": "{size-used} / {size-total}" + }, + { + "type": "custom", + "format": "└────────────────────────────────────────┘" + }, + "break", + { + "type": "custom", + "format": "┌────「 {#1}UI{#} 」────────────────────────────┐" + }, + { + "type": "wm", + "key": "│ {icon}{$2}{$1}" + }, + { + "type": "wmtheme", + "key": "│ {icon}{$2}{$1}" + }, + { + "type": "custom", + "key": "│ {$1}" + }, + { + "type": "display", + "key": "│ {icon}{$2}{$1}", + "format": "{width}x{height} @ {refresh-rate} Hz" + }, + { + "type": "custom", + "key": "│ {$1}" + }, + { + "type": "terminal", + "key": "│ {icon}{$2}{$1}" + }, + { + "type": "terminalfont", + "key": "│ {icon}{$2}{$1}" + }, + { + "type": "custom", + "format": "└────────────────────────────────────────┘" + }, + "break", + { + "type": "custom", + "format": "┌────「 {#1}HW{#} 」────────────────────────────┐" + }, + { + "type": "cpu", + "key": "│ {icon}{$2}{$1}", + "format": "{name}" + }, + { + "type": "gpu", + "key": "│ {icon}{$2}{$1}", + "format": "{name}" + }, + { + "type": "custom", + "key": "│ {$1}" + }, + { + "type": "memory", + "key": "│ {icon}{$2}{$1}", + "format": "{percentage-bar} {percentage}" + }, + { + "type": "memory", + "key": "│ {$1}", + "format": "{used} / {total}" + }, + { + "type": "custom", + "format": "└────────────────────────────────────────┘" + } + ] +} diff --git a/presets/examples/9.jsonc b/presets/examples/9.jsonc index eda3d0eff7..2fc1da3c87 100644 --- a/presets/examples/9.jsonc +++ b/presets/examples/9.jsonc @@ -8,8 +8,10 @@ "width": 11 }, "bar": { - "charElapsed": "=", - "charTotal": "-", + "char": { + "elapsed": "=", + "total": "-" + }, "width": 13 }, "percent": { diff --git a/presets/neofetch.jsonc b/presets/neofetch.jsonc index 66f9b9de69..0f38ed5f2e 100644 --- a/presets/neofetch.jsonc +++ b/presets/neofetch.jsonc @@ -3,7 +3,12 @@ "display": { "size": { "maxPrefix": "MB", - "ndigits": 0 + "ndigits": 0, + "spaceBeforeUnit": "never" + }, + "freq": { + "ndigits": 3, + "spaceBeforeUnit": "never" } }, "modules": [ @@ -39,11 +44,12 @@ "cpu", { "type": "gpu", - "key": "GPU" + "key": "GPU", + "format": "{name}" }, { "type": "memory", - "format": "{} / {}" + "format": "{used} / {total}" }, "break", "colors" diff --git a/src/common/commandoption.c b/src/common/commandoption.c index d91072928e..a0e2493834 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -10,21 +10,8 @@ #include #include -bool ffParseModuleOptions(const char* key, const char* value) -{ - if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false; - - for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules) - { - FFModuleBaseInfo* baseInfo = *modules; - if (baseInfo->parseCommandOptions(baseInfo, key, value)) return true; - } - return false; -} - void ffPrepareCommandOption(FFdata* data) { - FFOptionsModules* const options = &instance.config.modules; //If we don't have a custom structure, use the default one if(data->structure.length == 0) ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string @@ -33,54 +20,78 @@ void ffPrepareCommandOption(FFdata* data) ffPrepareCPUUsage(); if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME)) - ffPrepareDiskIO(&options->diskIo); + { + __attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options; + ffInitDiskIOOptions(&options); + ffPrepareDiskIO(&options); + } if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME)) - ffPrepareNetIO(&options->netIo); + { + __attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options; + ffInitNetIOOptions(&options); + ffPrepareNetIO(&options); + } if(instance.config.general.multithreading) { if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME)) - ffPreparePublicIp(&options->publicIP); + { + __attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options; + ffInitPublicIpOptions(&options); + ffPreparePublicIp(&options); + } if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME)) - ffPrepareWeather(&options->weather); + { + __attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options; + ffInitWeatherOptions(&options); + ffPrepareWeather(&options); + } } } -static void genJsonConfig(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc) +static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc) { yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules"); if (!modules) modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules"); - yyjson_mut_val* module = yyjson_mut_obj(doc); FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name); ffStrbufLowerCase(&type); - yyjson_mut_obj_add_strbuf(doc, module, "type", &type); - if (baseInfo->generateJsonConfig) - baseInfo->generateJsonConfig(baseInfo, doc, module); + if (instance.state.fullConfig) + { + yyjson_mut_val* module = yyjson_mut_obj(doc); + yyjson_mut_obj_add_strbuf(doc, module, "type", &type); - if (yyjson_mut_obj_size(module) > 1) - yyjson_mut_arr_add_val(modules, module); + if (baseInfo->generateJsonConfig) + baseInfo->generateJsonConfig(options, doc, module); + + if (yyjson_mut_obj_size(module) > 1) + yyjson_mut_arr_add_val(modules, module); + else + yyjson_mut_arr_add_strbuf(doc, modules, &type); + } else + { yyjson_mut_arr_add_strbuf(doc, modules, &type); + } } -static void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc) +static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc) { yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root); yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name); if (baseInfo->generateJsonResult) - baseInfo->generateJsonResult(baseInfo, doc, module); + baseInfo->generateJsonResult(options, doc, module); else yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format"); } static void parseStructureCommand( const char* line, - void (*fn)(FFModuleBaseInfo *baseInfo, yyjson_mut_doc* jsonDoc), + void (*fn)(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* jsonDoc), yyjson_mut_doc* jsonDoc ) { @@ -91,10 +102,13 @@ static void parseStructureCommand( FFModuleBaseInfo* baseInfo = *modules; if (ffStrEqualsIgnCase(line, baseInfo->name)) { + uint8_t optionBuf[FF_OPTION_MAX_SIZE]; + baseInfo->initOptions(optionBuf); if (__builtin_expect(jsonDoc != NULL, false)) - fn(baseInfo, jsonDoc); + fn(baseInfo, optionBuf, jsonDoc); else - baseInfo->printModule(baseInfo); + baseInfo->printModule(optionBuf); + baseInfo->destroyOptions(optionBuf); return; } } diff --git a/src/common/commandoption.h b/src/common/commandoption.h index f8cf120447..98472a13af 100644 --- a/src/common/commandoption.h +++ b/src/common/commandoption.h @@ -9,7 +9,6 @@ typedef struct FFdata bool configLoaded; } FFdata; -bool ffParseModuleOptions(const char* key, const char* value); void ffPrepareCommandOption(FFdata* data); void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc); void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc); diff --git a/src/common/format.c b/src/common/format.c index fa91992048..d2ec98178f 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -113,8 +113,8 @@ static inline void appendInvalidPlaceholder(FFstrbuf* buffer, const char* start, static inline bool formatArgSet(const FFformatarg* arg) { return arg->value != NULL && ( - (arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN - (arg->type == FF_FORMAT_ARG_TYPE_FLOAT && *(float*)arg->value > 0.0) || //Also is false for NaN + (arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || + (arg->type == FF_FORMAT_ARG_TYPE_FLOAT && *(float*)arg->value > 0.0) || (arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) || (arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) || (arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet((char*)arg->value)) || diff --git a/src/common/init.c b/src/common/init.c index 8b6032c03e..220dbae053 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -25,6 +25,7 @@ static void initState(FFstate* state) state->logoHeight = 0; state->keysHeight = 0; state->terminalLightTheme = false; + state->titleFqdn = false; ffPlatformInit(&state->platform); state->configDoc = NULL; @@ -42,14 +43,13 @@ static void defaultConfig(void) { ffOptionsInitLogo(&instance.config.logo); ffOptionsInitGeneral(&instance.config.general); - ffOptionsInitModules(&instance.config.modules); ffOptionsInitDisplay(&instance.config.display); } void ffInitInstance(void) { #ifdef WIN32 - //https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support + // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendat> setlocale(LC_ALL, ".UTF8"); #else // Never use `setlocale(LC_ALL, "")` @@ -96,11 +96,6 @@ static void chldSignalHandler(FF_MAYBE_UNUSED int signal) void ffStart(void) { - #ifdef FF_START_DETECTION_THREADS - if(instance.config.general.multithreading) - startDetectionThreads(); - #endif - ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc; ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc; @@ -150,7 +145,6 @@ static void destroyConfig(void) { ffOptionsDestroyLogo(&instance.config.logo); ffOptionsDestroyGeneral(&instance.config.general); - ffOptionsDestroyModules(&instance.config.modules); ffOptionsDestroyDisplay(&instance.config.display); } diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 4170d6c66b..838b307acf 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -12,52 +12,57 @@ #include #include -bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs) +bool ffJsonConfigParseModuleArgs(yyjson_val* key, yyjson_val* val, FFModuleArgs* moduleArgs) { - if(ffStrEqualsIgnCase(key, "key")) + if (unsafe_yyjson_equals_str(key, "type") || unsafe_yyjson_equals_str(key, "condition")) + return true; + + if (unsafe_yyjson_equals_str(key, "key")) { - ffStrbufSetNS(&moduleArgs->key, (uint32_t) yyjson_get_len(val), yyjson_get_str(val)); + ffStrbufSetJsonVal(&moduleArgs->key, val); return true; } - else if(ffStrEqualsIgnCase(key, "format")) + else if (unsafe_yyjson_equals_str(key, "format")) { - ffStrbufSetNS(&moduleArgs->outputFormat, (uint32_t) yyjson_get_len(val), yyjson_get_str(val)); + ffStrbufSetJsonVal(&moduleArgs->outputFormat, val); return true; } - else if(ffStrEqualsIgnCase(key, "outputColor")) + else if (unsafe_yyjson_equals_str(key, "outputColor")) { ffOptionParseColor(yyjson_get_str(val), &moduleArgs->outputColor); return true; } - else if(ffStrEqualsIgnCase(key, "keyColor")) + else if (unsafe_yyjson_equals_str(key, "keyColor")) { ffOptionParseColor(yyjson_get_str(val), &moduleArgs->keyColor); return true; } - else if(ffStrEqualsIgnCase(key, "keyWidth")) + else if (unsafe_yyjson_equals_str(key, "keyWidth")) { moduleArgs->keyWidth = (uint32_t) yyjson_get_uint(val); return true; } - else if(ffStrEqualsIgnCase(key, "keyIcon")) + else if (unsafe_yyjson_equals_str(key, "keyIcon")) { - ffStrbufSetS(&moduleArgs->keyIcon, yyjson_get_str(val)); + ffStrbufSetJsonVal(&moduleArgs->keyIcon, val); return true; } return false; } -void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs) +void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* moduleArgs) { - if (!ffStrbufEqual(&defaultModuleArgs->key, &moduleArgs->key)) + if (moduleArgs->key.length > 0) yyjson_mut_obj_add_strbuf(doc, module, "key", &moduleArgs->key); - if (!ffStrbufEqual(&defaultModuleArgs->outputFormat, &moduleArgs->outputFormat)) + if (moduleArgs->outputFormat.length > 0) yyjson_mut_obj_add_strbuf(doc, module, "format", &moduleArgs->outputFormat); - if (!ffStrbufEqual(&defaultModuleArgs->keyColor, &moduleArgs->keyColor)) + if (moduleArgs->outputColor.length > 0) + yyjson_mut_obj_add_strbuf(doc, module, "outputColor", &moduleArgs->outputColor); + if (moduleArgs->keyColor.length > 0) yyjson_mut_obj_add_strbuf(doc, module, "keyColor", &moduleArgs->keyColor); - if (moduleArgs->keyWidth != defaultModuleArgs->keyWidth) + if (moduleArgs->keyWidth > 0) yyjson_mut_obj_add_uint(doc, module, "keyWidth", moduleArgs->keyWidth); - if (!ffStrbufEqual(&defaultModuleArgs->keyIcon, &moduleArgs->keyIcon)) + if (moduleArgs->keyIcon.length > 0) yyjson_mut_obj_add_strbuf(doc, module, "keyIcon", &moduleArgs->keyIcon); } @@ -96,12 +101,12 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p return "Invalid enum value type; must be a string or integer"; } -static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc) +static inline void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc) { yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root); yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name); if (baseInfo->generateJsonResult) - baseInfo->generateJsonResult(baseInfo, doc, module); + baseInfo->generateJsonResult(options, doc, module); else yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format"); } @@ -115,11 +120,14 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_ FFModuleBaseInfo* baseInfo = *modules; if (ffStrEqualsIgnCase(type, baseInfo->name)) { - if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal); + uint8_t optionBuf[FF_OPTION_MAX_SIZE]; + baseInfo->initOptions(optionBuf); + if (jsonVal) baseInfo->parseJsonObject(optionBuf, jsonVal); if (__builtin_expect(jsonDoc != NULL, false)) - genJsonResult(baseInfo, jsonDoc); + genJsonResult(baseInfo, optionBuf, jsonDoc); else - baseInfo->printModule(baseInfo); + baseInfo->printModule(optionBuf); + baseInfo->destroyOptions(optionBuf); return true; } } @@ -128,7 +136,6 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { - FFconfig* cfg = &instance.config; switch (type[0]) { case 'b': case 'B': { @@ -139,32 +146,40 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) case 'd': case 'D': { if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME)) { - if (module) cfg->modules.diskIo.moduleInfo.parseJsonObject(&cfg->modules.diskIo, module); - ffPrepareDiskIO(&cfg->modules.diskIo); + __attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options; + ffInitDiskIOOptions(&options); + if (module) ffDiskIOModuleInfo.parseJsonObject(&options, module); + ffPrepareDiskIO(&options); } break; } case 'n': case 'N': { if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) { - if (module) cfg->modules.netIo.moduleInfo.parseJsonObject(&cfg->modules.netIo, module); - ffPrepareNetIO(&cfg->modules.netIo); + __attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options; + ffInitNetIOOptions(&options); + if (module) ffNetIOModuleInfo.parseJsonObject(&options, module); + ffPrepareNetIO(&options); } break; } case 'p': case 'P': { if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME)) { - if (module) cfg->modules.publicIP.moduleInfo.parseJsonObject(&cfg->modules.publicIP, module); - ffPreparePublicIp(&cfg->modules.publicIP); + __attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options; + ffInitPublicIpOptions(&options); + if (module) ffPublicIPModuleInfo.parseJsonObject(&options, module); + ffPreparePublicIp(&options); } break; } case 'w': case 'W': { if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME)) { - if (module) cfg->modules.weather.moduleInfo.parseJsonObject(&cfg->modules.weather, module); - ffPrepareWeather(&cfg->modules.weather); + __attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options; + ffInitWeatherOptions(&options); + if (module) ffWeatherModuleInfo.parseJsonObject(&options, module); + ffPrepareWeather(&options); } break; } diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index 12182855a3..08a297f752 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -2,10 +2,10 @@ #include "fastfetch.h" -bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs); +bool ffJsonConfigParseModuleArgs(yyjson_val* key, yyjson_val* val, FFModuleArgs* moduleArgs); const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]); void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc); -void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs); +void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* moduleArgs); yyjson_api_inline yyjson_mut_val* yyjson_mut_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) { return yyjson_mut_strncpy(doc, buf->chars, buf->length); diff --git a/src/common/modules.c b/src/common/modules.c index 724c1aa493..7ad2210058 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -1,69 +1,69 @@ -#include "fastfetch.h" +#include "modules/modules.h" static FFModuleBaseInfo* A[] = { NULL, }; static FFModuleBaseInfo* B[] = { - (FFModuleBaseInfo*) &instance.config.modules.battery, - (FFModuleBaseInfo*) &instance.config.modules.bios, - (FFModuleBaseInfo*) &instance.config.modules.bluetooth, - (FFModuleBaseInfo*) &instance.config.modules.bluetoothRadio, - (FFModuleBaseInfo*) &instance.config.modules.board, - (FFModuleBaseInfo*) &instance.config.modules.bootmgr, - (FFModuleBaseInfo*) &instance.config.modules.break_, - (FFModuleBaseInfo*) &instance.config.modules.brightness, - (FFModuleBaseInfo*) &instance.config.modules.btrfs, + &ffBatteryModuleInfo, + &ffBiosModuleInfo, + &ffBluetoothModuleInfo, + &ffBluetoothRadioModuleInfo, + &ffBoardModuleInfo, + &ffBootmgrModuleInfo, + &ffBreakModuleInfo, + &ffBrightnessModuleInfo, + &ffBtrfsModuleInfo, NULL, }; static FFModuleBaseInfo* C[] = { - (FFModuleBaseInfo*) &instance.config.modules.camera, - (FFModuleBaseInfo*) &instance.config.modules.chassis, - (FFModuleBaseInfo*) &instance.config.modules.command, - (FFModuleBaseInfo*) &instance.config.modules.colors, - (FFModuleBaseInfo*) &instance.config.modules.cpu, - (FFModuleBaseInfo*) &instance.config.modules.cpuCache, - (FFModuleBaseInfo*) &instance.config.modules.cpuUsage, - (FFModuleBaseInfo*) &instance.config.modules.cursor, - (FFModuleBaseInfo*) &instance.config.modules.custom, + &ffCameraModuleInfo, + &ffChassisModuleInfo, + &ffCommandModuleInfo, + &ffColorsModuleInfo, + &ffCPUModuleInfo, + &ffCPUCacheModuleInfo, + &ffCPUUsageModuleInfo, + &ffCursorModuleInfo, + &ffCustomModuleInfo, NULL, }; static FFModuleBaseInfo* D[] = { - (FFModuleBaseInfo*) &instance.config.modules.dateTime, - (FFModuleBaseInfo*) &instance.config.modules.de, - (FFModuleBaseInfo*) &instance.config.modules.display, - (FFModuleBaseInfo*) &instance.config.modules.disk, - (FFModuleBaseInfo*) &instance.config.modules.diskIo, - (FFModuleBaseInfo*) &instance.config.modules.dns, + &ffDateTimeModuleInfo, + &ffDEModuleInfo, + &ffDisplayModuleInfo, + &ffDiskModuleInfo, + &ffDiskIOModuleInfo, + &ffDNSModuleInfo, NULL, }; static FFModuleBaseInfo* E[] = { - (FFModuleBaseInfo*) &instance.config.modules.editor, + &ffEditorModuleInfo, NULL, }; static FFModuleBaseInfo* F[] = { - (FFModuleBaseInfo*) &instance.config.modules.font, + &ffFontModuleInfo, NULL, }; static FFModuleBaseInfo* G[] = { - (FFModuleBaseInfo*) &instance.config.modules.gamepad, - (FFModuleBaseInfo*) &instance.config.modules.gpu, + &ffGamepadModuleInfo, + &ffGPUModuleInfo, NULL, }; static FFModuleBaseInfo* H[] = { - (FFModuleBaseInfo*) &instance.config.modules.host, + &ffHostModuleInfo, NULL, }; static FFModuleBaseInfo* I[] = { - (FFModuleBaseInfo*) &instance.config.modules.icons, - (FFModuleBaseInfo*) &instance.config.modules.initSystem, + &ffIconsModuleInfo, + &ffInitSystemModuleInfo, NULL, }; @@ -72,47 +72,47 @@ static FFModuleBaseInfo* J[] = { }; static FFModuleBaseInfo* K[] = { - (FFModuleBaseInfo*) &instance.config.modules.kernel, - (FFModuleBaseInfo*) &instance.config.modules.keyboard, + &ffKernelModuleInfo, + &ffKeyboardModuleInfo, NULL, }; static FFModuleBaseInfo* L[] = { - (FFModuleBaseInfo*) &instance.config.modules.lm, - (FFModuleBaseInfo*) &instance.config.modules.loadavg, - (FFModuleBaseInfo*) &instance.config.modules.locale, - (FFModuleBaseInfo*) &instance.config.modules.localIP, + &ffLMModuleInfo, + &ffLoadavgModuleInfo, + &ffLocaleModuleInfo, + &ffLocalIPModuleInfo, NULL, }; static FFModuleBaseInfo* M[] = { - (FFModuleBaseInfo*) &instance.config.modules.media, - (FFModuleBaseInfo*) &instance.config.modules.memory, - (FFModuleBaseInfo*) &instance.config.modules.monitor, - (FFModuleBaseInfo*) &instance.config.modules.mouse, + &ffMediaModuleInfo, + &ffMemoryModuleInfo, + &ffMonitorModuleInfo, + &ffMouseModuleInfo, NULL, }; static FFModuleBaseInfo* N[] = { - (FFModuleBaseInfo*) &instance.config.modules.netIo, + &ffNetIOModuleInfo, NULL, }; static FFModuleBaseInfo* O[] = { - (FFModuleBaseInfo*) &instance.config.modules.openCL, - (FFModuleBaseInfo*) &instance.config.modules.openGL, - (FFModuleBaseInfo*) &instance.config.modules.os, + &ffOpenCLModuleInfo, + &ffOpenGLModuleInfo, + &ffOSModuleInfo, NULL, }; static FFModuleBaseInfo* P[] = { - (FFModuleBaseInfo*) &instance.config.modules.packages, - (FFModuleBaseInfo*) &instance.config.modules.physicalDisk, - (FFModuleBaseInfo*) &instance.config.modules.physicalMemory, - (FFModuleBaseInfo*) &instance.config.modules.player, - (FFModuleBaseInfo*) &instance.config.modules.powerAdapter, - (FFModuleBaseInfo*) &instance.config.modules.processes, - (FFModuleBaseInfo*) &instance.config.modules.publicIP, + &ffPackagesModuleInfo, + &ffPhysicalDiskModuleInfo, + &ffPhysicalMemoryModuleInfo, + &ffPlayerModuleInfo, + &ffPowerAdapterModuleInfo, + &ffProcessesModuleInfo, + &ffPublicIPModuleInfo, NULL, }; @@ -125,42 +125,42 @@ static FFModuleBaseInfo* R[] = { }; static FFModuleBaseInfo* S[] = { - (FFModuleBaseInfo*) &instance.config.modules.separator, - (FFModuleBaseInfo*) &instance.config.modules.shell, - (FFModuleBaseInfo*) &instance.config.modules.sound, - (FFModuleBaseInfo*) &instance.config.modules.swap, + &ffSeparatorModuleInfo, + &ffShellModuleInfo, + &ffSoundModuleInfo, + &ffSwapModuleInfo, NULL, }; static FFModuleBaseInfo* T[] = { - (FFModuleBaseInfo*) &instance.config.modules.terminal, - (FFModuleBaseInfo*) &instance.config.modules.terminalFont, - (FFModuleBaseInfo*) &instance.config.modules.terminalSize, - (FFModuleBaseInfo*) &instance.config.modules.terminalTheme, - (FFModuleBaseInfo*) &instance.config.modules.title, - (FFModuleBaseInfo*) &instance.config.modules.theme, - (FFModuleBaseInfo*) &instance.config.modules.tpm, + &ffTerminalModuleInfo, + &ffTerminalFontModuleInfo, + &ffTerminalSizeModuleInfo, + &ffTerminalThemeModuleInfo, + &ffTitleModuleInfo, + &ffThemeModuleInfo, + &ffTPMModuleInfo, NULL, }; static FFModuleBaseInfo* U[] = { - (FFModuleBaseInfo*) &instance.config.modules.uptime, - (FFModuleBaseInfo*) &instance.config.modules.users, + &ffUptimeModuleInfo, + &ffUsersModuleInfo, NULL, }; static FFModuleBaseInfo* V[] = { - (FFModuleBaseInfo*) &instance.config.modules.version, - (FFModuleBaseInfo*) &instance.config.modules.vulkan, + &ffVersionModuleInfo, + &ffVulkanModuleInfo, NULL, }; static FFModuleBaseInfo* W[] = { - (FFModuleBaseInfo*) &instance.config.modules.wallpaper, - (FFModuleBaseInfo*) &instance.config.modules.weather, - (FFModuleBaseInfo*) &instance.config.modules.wm, - (FFModuleBaseInfo*) &instance.config.modules.wifi, - (FFModuleBaseInfo*) &instance.config.modules.wmTheme, + &ffWallpaperModuleInfo, + &ffWeatherModuleInfo, + &ffWMModuleInfo, + &ffWifiModuleInfo, + &ffWMThemeModuleInfo, NULL, }; @@ -173,7 +173,7 @@ static FFModuleBaseInfo* Y[] = { }; static FFModuleBaseInfo* Z[] = { - (FFModuleBaseInfo*) &instance.config.modules.zpool, + &ffZpoolModuleInfo, NULL, }; diff --git a/src/common/netif/netif.c b/src/common/netif/netif.c index 8d02b1a542..52792a9f91 100644 --- a/src/common/netif/netif.c +++ b/src/common/netif/netif.c @@ -2,30 +2,23 @@ #ifndef _WIN32 #include -#else - #include - #include + #include #endif -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex); -enum { IF_INDEX_UNINITIALIZED = (uint32_t) -1, IF_INDEX_INVALID = (uint32_t) -2 }; -static uint32_t ifIndex = IF_INDEX_UNINITIALIZED; -static char ifName[IF_NAMESIZE + 1]; - -static inline void init() -{ - if (ifIndex == (uint32_t) IF_INDEX_UNINITIALIZED && !ffNetifGetDefaultRouteImpl(ifName, &ifIndex)) - ifIndex = (uint32_t) IF_INDEX_INVALID; -} - -const char* ffNetifGetDefaultRouteIfName() +const FFNetifDefaultRouteResult* ffNetifGetDefaultRouteV4(void) { - init(); - return ifName; + static FFNetifDefaultRouteResult result; + if (result.status == FF_NETIF_UNINITIALIZED) { + result.status = ffNetifGetDefaultRouteImplV4(&result) ? FF_NETIF_OK : FF_NETIF_INVALID; + } + return &result; } -uint32_t ffNetifGetDefaultRouteIfIndex() +const FFNetifDefaultRouteResult* ffNetifGetDefaultRouteV6(void) { - init(); - return ifIndex; + static FFNetifDefaultRouteResult result; + if (result.status == FF_NETIF_UNINITIALIZED) { + result.status = ffNetifGetDefaultRouteImplV6(&result) ? FF_NETIF_OK : FF_NETIF_INVALID; + } + return &result; } diff --git a/src/common/netif/netif.h b/src/common/netif/netif.h index 40c97948d2..99a1a69a02 100644 --- a/src/common/netif/netif.h +++ b/src/common/netif/netif.h @@ -2,5 +2,29 @@ #include "fastfetch.h" -const char* ffNetifGetDefaultRouteIfName(); -uint32_t ffNetifGetDefaultRouteIfIndex(); +#ifndef _WIN32 + #include + #include +#endif + +typedef enum __attribute__((__packed__)) FFNetifDefaultRouteResultStatus { + FF_NETIF_UNINITIALIZED, + FF_NETIF_INVALID, + FF_NETIF_OK +} FFNetifDefaultRouteResultStatus; + +typedef struct FFNetifDefaultRouteResult { + uint32_t ifIndex; + + #ifndef _WIN32 + char ifName[IF_NAMESIZE + 1]; + uint32_t preferredSourceAddrV4; + #endif + enum FFNetifDefaultRouteResultStatus status; +} FFNetifDefaultRouteResult; + +bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result); +bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result); + +const FFNetifDefaultRouteResult* ffNetifGetDefaultRouteV4(void); +const FFNetifDefaultRouteResult* ffNetifGetDefaultRouteV6(void); diff --git a/src/common/netif/netif_apple.c b/src/common/netif/netif_apple.c new file mode 100644 index 0000000000..c565330620 --- /dev/null +++ b/src/common/netif/netif_apple.c @@ -0,0 +1,201 @@ +#include "netif.h" + +#include "common/io/io.h" +#include "util/mallocHelper.h" + +#include +#include +#include +#include +#include + +#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) + +#if __APPLE__ + // https://github.com/apple-oss-distributions/network_cmds/blob/8f38231438e6a4d16ef8015e97e12c2c05105644/rtsol.tproj/if.c#L243 + #define ROUNDUP(a) ROUNDUP2((a), sizeof(uint32_t)) +#elif __sun + // https://github.com/illumos/illumos-gate/blob/95b8c88950fa7b19af46bc63230137cf96b0bff7/usr/src/cmd/cmd-inet/usr.sbin/route.c#L339 + #define ROUNDUP(a) ROUNDUP2((a), sizeof(long)) +#else + #error unknown platform +#endif + +static struct sockaddr * +get_rt_address(struct rt_msghdr *rtm, int desired) +{ + struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + + for (int i = 0; i < RTAX_MAX; i++) + { + if (rtm->rtm_addrs & (1 << i)) + { + if ((1 << i) == desired) + return sa; + + #ifndef __sun + uint32_t salen = sa->sa_len; + #else + uint32_t salen; + // https://github.com/illumos/illumos-gate/blob/95b8c88950fa7b19af46bc63230137cf96b0bff7/usr/src/cmd/cmd-inet/usr.sbin/route.c#L2941 + switch (sa->sa_family) { + case AF_INET: + salen = sizeof (struct sockaddr_in); + break; + case AF_LINK: + salen = sizeof (struct sockaddr_dl); + break; + case AF_INET6: + salen = sizeof (struct sockaddr_in6); + break; + default: + salen = sizeof (struct sockaddr); + break; + } + #endif + sa = (struct sockaddr *)(ROUNDUP(salen) + (char *)sa); + } + } + return NULL; +} + +bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) +{ + //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 + + FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); + if (pfRoute < 0) + return false; + + { + struct timeval timeout = {1, 0}; + setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); + setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); + } + + int pid = getpid(); + + struct { + struct rt_msghdr hdr; + struct sockaddr_in dst; + uint8_t data[512]; + } rtmsg = { + .hdr = { + .rtm_type = RTM_GET, + .rtm_flags = RTF_UP | RTF_GATEWAY, + .rtm_version = RTM_VERSION, + .rtm_addrs = RTA_DST | RTA_IFP | RTA_IFA, + .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), + .rtm_pid = pid, + .rtm_seq = 1, + }, + .dst = { + .sin_family = AF_INET, + #ifndef __sun + .sin_len = sizeof(rtmsg.dst), + #endif + }, + }; + + if (send(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen, 0) != rtmsg.hdr.rtm_msglen) + return false; + + while (recv(pfRoute, &rtmsg, sizeof(rtmsg), 0) > 0 && !(rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)) + ; + + #ifndef __sun // On Solaris, the RTF_GATEWAY flag is not set for default routes for some reason + if ((rtmsg.hdr.rtm_flags & (RTF_UP | RTF_GATEWAY)) == (RTF_UP | RTF_GATEWAY)) + #endif + { + struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); + if (sdl + #ifndef __sun + && sdl->sdl_len + #endif + ) + { + assert(sdl->sdl_nlen <= IF_NAMESIZE); + memcpy(result->ifName, sdl->sdl_data, sdl->sdl_nlen); + result->ifName[sdl->sdl_nlen] = '\0'; + result->ifIndex = sdl->sdl_index; + + // Get the preferred source address + struct sockaddr_in* src = (struct sockaddr_in*)get_rt_address(&rtmsg.hdr, RTA_IFA); + if (src && src->sin_family == AF_INET) + result->preferredSourceAddrV4 = src->sin_addr.s_addr; + + return true; + } + return false; + } + + return false; +} + +bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result) +{ + //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 + + FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET6); + if (pfRoute < 0) + return false; + + { + struct timeval timeout = {1, 0}; + setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); + setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); + } + + int pid = getpid(); + + struct { + struct rt_msghdr hdr; + struct sockaddr_in6 dst; + uint8_t data[512]; + } rtmsg = { + .hdr = { + .rtm_type = RTM_GET, + .rtm_flags = RTF_UP | RTF_GATEWAY, + .rtm_version = RTM_VERSION, + .rtm_addrs = RTA_DST | RTA_IFP, + .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), + .rtm_pid = pid, + .rtm_seq = 2, + }, + .dst = { + .sin6_family = AF_INET6, + #ifndef __sun + .sin6_len = sizeof(rtmsg.dst), + #endif + }, + }; + + if (send(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen, 0) != rtmsg.hdr.rtm_msglen) + return false; + + while (recv(pfRoute, &rtmsg, sizeof(rtmsg), 0) > 0 && !(rtmsg.hdr.rtm_seq == 2 && rtmsg.hdr.rtm_pid == pid)) + ; + + #ifndef __sun // On Solaris, the RTF_GATEWAY flag is not set for default routes for some reason + if ((rtmsg.hdr.rtm_flags & (RTF_UP | RTF_GATEWAY)) == (RTF_UP | RTF_GATEWAY)) + #endif + { + struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); + if (sdl + #ifndef __sun + && sdl->sdl_len + #endif + ) + { + assert(sdl->sdl_nlen <= IF_NAMESIZE); + memcpy(result->ifName, sdl->sdl_data, sdl->sdl_nlen); + result->ifName[sdl->sdl_nlen] = '\0'; + result->ifIndex = sdl->sdl_index; + + return true; + } + return false; + } + + return false; +} diff --git a/src/common/netif/netif_bsd.c b/src/common/netif/netif_bsd.c index f85c39a629..90c7889088 100644 --- a/src/common/netif/netif_bsd.c +++ b/src/common/netif/netif_bsd.c @@ -8,25 +8,24 @@ #include #include #include - -#if defined(__OpenBSD__) || defined(__DragonFly__) - #include -#endif +#include #define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) -#if defined(__APPLE__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__NetBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) -#elif defined(__FreeBSD__) || defined(__DragonFly__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__OpenBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__sun) -# define ROUNDUP(a) ROUNDUP2((a), _SS_ALIGNSIZE) +#if __DragonFly__ + // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/cf0aa2f1e47a3f0a6055fe427563cb3f3e627064/sys/net/route.h#L315C9-L315C19 + #define ROUNDUP(a) ROUNDUP2((a), sizeof(long)) +#elif __FreeBSD__ + // https://github.com/freebsd/freebsd-src/blob/e4c0ecba44b20ebb2e4d80978c2cb6d16b730cb9/sys/net/route.h#L368C9-L368C16 + #define ROUNDUP(a) ROUNDUP2((a), sizeof(long)) +#elif __NetBSD__ + // https://github.com/NetBSD/src/blob/29beb637d057520c0ed37ac2cde966f7cc0cadf4/sys/net/route.h#L330 + #define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) +#elif __OpenBSD__ + // https://github.com/openbsd/src/blob/ca647cfa4ec3ccb8360714bc0ebc32a394f7fb6a/regress/sys/netinet/bindconnect/bindconnect.c#L250 + #define ROUNDUP(a) ROUNDUP2((a), sizeof(long)) #else -# error unknown platform + #error unknown platform #endif static struct sockaddr * @@ -40,23 +39,18 @@ get_rt_address(struct rt_msghdr *rtm, int desired) { if ((1 << i) == desired) return sa; -#ifdef __sun - sa = (struct sockaddr *)(ROUNDUP(sizeof(struct sockaddr)) + (char *)sa); -#else sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa); -#endif } } return NULL; } -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) { - #if defined(__OpenBSD__) || defined(__DragonFly__) int mib[6] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY}; size_t needed; - if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0 || needed == 0) return false; FF_AUTO_FREE char* buf = malloc(needed); @@ -71,80 +65,62 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) rtm = (struct rt_msghdr *)next; struct sockaddr* sa = (struct sockaddr *)(rtm + 1); - if ((rtm->rtm_flags & RTF_GATEWAY) && (sa->sa_family == AF_INET)) + if ((rtm->rtm_flags & RTF_GATEWAY) && !(rtm->rtm_flags & RTF_REJECT) && (sa->sa_family == AF_INET)) { struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP); - if (sdl->sdl_family == AF_LINK) + if (sdl && sdl->sdl_family == AF_LINK) { assert(sdl->sdl_nlen <= IF_NAMESIZE); - memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); - iface[sdl->sdl_nlen] = '\0'; - *ifIndex = sdl->sdl_index; + memcpy(result->ifName, sdl->sdl_data, sdl->sdl_nlen); + result->ifName[sdl->sdl_nlen] = '\0'; + result->ifIndex = sdl->sdl_index; + + // Get the preferred source address + struct sockaddr_in* src = (struct sockaddr_in*)get_rt_address(rtm, RTA_IFA); + if (src && src->sin_family == AF_INET) + result->preferredSourceAddrV4 = src->sin_addr.s_addr; + return true; } } } - #else - //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 + return false; +} + +bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result) +{ + int mib[6] = {CTL_NET, PF_ROUTE, 0, AF_INET6, NET_RT_FLAGS, RTF_GATEWAY}; + size_t needed; - FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); - if (pfRoute < 0) + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0 || needed == 0) return false; - { - struct timeval timeout = {1, 0}; - setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); - setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); - } + FF_AUTO_FREE char* buf = malloc(needed); - int pid = getpid(); - - struct { - struct rt_msghdr hdr; - struct sockaddr_in dst; - uint8_t data[512]; - } rtmsg = { - .hdr = { - .rtm_type = RTM_GET, - .rtm_flags = RTF_UP | RTF_GATEWAY, - .rtm_version = RTM_VERSION, - .rtm_addrs = RTA_DST | RTA_IFP, - .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), - .rtm_pid = pid, - .rtm_seq = 1, - }, - .dst = { - .sin_family = AF_INET, - #ifndef __sun - .sin_len = sizeof(rtmsg.dst), - #endif - }, - }; - - if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen) + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) return false; - while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0) + char* lim = buf + needed; + struct rt_msghdr* rtm; + for (char* next = buf; next < lim; next += rtm->rtm_msglen) { - if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid) + rtm = (struct rt_msghdr *)next; + struct sockaddr* sa = (struct sockaddr *)(rtm + 1); + + if ((rtm->rtm_flags & RTF_GATEWAY) && !(rtm->rtm_flags & RTF_REJECT) && (sa->sa_family == AF_INET6)) { - struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); - if (sdl - #ifndef __sun - && sdl->sdl_len - #endif - ) + struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP); + if (sdl && sdl->sdl_family == AF_LINK) { assert(sdl->sdl_nlen <= IF_NAMESIZE); - memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); - iface[sdl->sdl_nlen] = '\0'; - *ifIndex = sdl->sdl_index; + memcpy(result->ifName, sdl->sdl_data, sdl->sdl_nlen); + result->ifName[sdl->sdl_nlen] = '\0'; + result->ifIndex = sdl->sdl_index; + return true; } - return false; } } - #endif return false; } diff --git a/src/common/netif/netif_haiku.c b/src/common/netif/netif_haiku.c index daa0cd7a1c..06f8e90b68 100644 --- a/src/common/netif/netif_haiku.c +++ b/src/common/netif/netif_haiku.c @@ -11,9 +11,8 @@ // loosely based on Haiku's src/bin/network/route/route.cpp -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) { - // TODO: AF_INET6 FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET, SOCK_RAW, AF_INET); if (pfRoute < 0) return false; @@ -42,8 +41,11 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) while (interface < end) { if (interface->ifr_route.flags & RTF_DEFAULT) { - strlcpy(iface, interface->ifr_name, IF_NAMESIZE); - *ifIndex = if_nametoindex(interface->ifr_name); + // interface->ifr_metric? + strlcpy(result->ifName, interface->ifr_name, IF_NAMESIZE); + result->ifIndex = if_nametoindex(interface->ifr_name); + if (interface->ifr_route.source) + result->preferredSourceAddrV4 = ((struct sockaddr_in*)interface->ifr_route.source)->sin_addr.s_addr; return true; } @@ -55,9 +57,56 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) if (interface->ifr_route.gateway != NULL) addressSize += interface->ifr_route.gateway->sa_len; - interface = (struct ifreq*)((addr_t)interface + IF_NAMESIZE - + sizeof(struct route_entry) + addressSize); + interface = (struct ifreq*)((addr_t)interface + IF_NAMESIZE + sizeof(struct route_entry) + addressSize); } return false; } + +bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result) +{ + FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET, SOCK_RAW, AF_INET6); + if (pfRoute < 0) + return false; + + struct ifconf config; + config.ifc_len = sizeof(config.ifc_value); + if (ioctl(pfRoute, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0) + return false; + + int size = config.ifc_value; + if (size <= 0) + return false; + + FF_AUTO_FREE void *buffer = malloc((size_t) size); + if (buffer == NULL) { + return false; + } + + config.ifc_len = size; + config.ifc_buf = buffer; + if (ioctl(pfRoute, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0) + return false; + + struct ifreq *interface = (struct ifreq*)buffer; + struct ifreq *end = (struct ifreq*)((uint8_t*)buffer + size); + + while (interface < end) { + if (interface->ifr_route.flags & RTF_DEFAULT) { + strlcpy(result->ifName, interface->ifr_name, IF_NAMESIZE); + result->ifIndex = if_nametoindex(interface->ifr_name); + return true; + } + + size_t addressSize = 0; + if (interface->ifr_route.destination != NULL) + addressSize += interface->ifr_route.destination->sa_len; + if (interface->ifr_route.mask != NULL) + addressSize += interface->ifr_route.mask->sa_len; + if (interface->ifr_route.gateway != NULL) + addressSize += interface->ifr_route.gateway->sa_len; + + interface = (struct ifreq*)((addr_t)interface + IF_NAMESIZE + sizeof(struct route_entry) + addressSize); + } + return false; +} diff --git a/src/common/netif/netif_linux.c b/src/common/netif/netif_linux.c index 6c0dbd1e60..cef654d6b5 100644 --- a/src/common/netif/netif_linux.c +++ b/src/common/netif/netif_linux.c @@ -1,52 +1,342 @@ #include "netif.h" #include "common/io/io.h" +#include "util/mallocHelper.h" +#include +#include #include -#include #define FF_STR_INDIR(x) #x #define FF_STR(x) FF_STR_INDIR(x) -static bool getDefaultRouteIPv4(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) { - FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); - if (!netRoute) return false; + FF_AUTO_CLOSE_FD int sock_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); + if (sock_fd < 0) + return false; - // skip first line - FF_UNUSED(fscanf(netRoute, "%*[^\n]\n")); + unsigned pid = (unsigned) getpid(); - unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, ... - while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2) + // Bind socket + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + .nl_pid = pid, + .nl_groups = 0, // No multicast groups + }; + + if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + return false; + } + + struct { + struct nlmsghdr nlh; + struct rtmsg rtm; + struct rtattr rta; + uint32_t table; + } req = { + // Netlink message header + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = RTM_GETROUTE, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, + .nlmsg_seq = 1, + .nlmsg_pid = pid, + }, + // Route message + .rtm = { + .rtm_family = AF_INET, + .rtm_dst_len = 0, // Match all destinations + .rtm_src_len = 0, // Match all sources + .rtm_tos = 0, + .rtm_table = RT_TABLE_UNSPEC, + .rtm_protocol = RTPROT_UNSPEC, + .rtm_scope = RT_SCOPE_UNIVERSE, + .rtm_type = RTN_UNSPEC, + .rtm_flags = 0, + }, + // Route attribute for main table + .rta = { + .rta_len = RTA_LENGTH(sizeof(uint32_t)), + .rta_type = RTA_TABLE, + }, + .table = RT_TABLE_MAIN, + }; + + struct sockaddr_nl dest_addr = { + .nl_family = AF_NETLINK, + .nl_pid = 0, // Kernel + .nl_groups = 0, // No multicast groups + }; + + ssize_t sent = sendto(sock_fd, &req, sizeof(req), 0, + (struct sockaddr*)&dest_addr, sizeof(dest_addr)); + + if (sent != sizeof(req)) { + return false; + } + + struct sockaddr_nl src_addr = {}; + socklen_t src_addr_len = sizeof(src_addr); + + struct iovec iov = {}; + struct msghdr msg = { + .msg_name = &src_addr, + .msg_namelen = sizeof(src_addr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + + ssize_t peek_size = recvmsg(sock_fd, &msg, MSG_PEEK | MSG_TRUNC); + if (peek_size < 0) { + return false; + } + + FF_AUTO_FREE uint8_t* buffer = malloc((size_t)peek_size); + + ssize_t received = recvfrom(sock_fd, buffer, (size_t)peek_size, 0, + (struct sockaddr*)&src_addr, &src_addr_len); + if (received != peek_size) { + return false; + } + + struct { + uint32_t metric; + uint32_t ifindex; + uint32_t prefsrc; + } entry; + uint32_t minMetric = UINT32_MAX; + + for (const struct nlmsghdr* nlh = (struct nlmsghdr*)buffer; + NLMSG_OK(nlh, received); + nlh = NLMSG_NEXT(nlh, received)) { + if (nlh->nlmsg_seq != 1 || nlh->nlmsg_pid != pid) + continue; + if (nlh->nlmsg_type == NLMSG_DONE) + break; + + if (nlh->nlmsg_type != RTM_NEWROUTE) + continue; + + struct rtmsg* rtm = (struct rtmsg*)NLMSG_DATA(nlh); + if (rtm->rtm_family != AF_INET) + continue; + + if (rtm->rtm_dst_len != 0) + continue; + + entry = (__typeof__(entry)) { .metric = UINT32_MAX }; + + // Parse route attributes + size_t rtm_len = RTM_PAYLOAD(nlh); + for (struct rtattr* rta = RTM_RTA(rtm); + RTA_OK(rta, rtm_len); + rta = RTA_NEXT(rta, rtm_len)) + { + if (RTA_PAYLOAD(rta) < sizeof(uint32_t)) + continue; // Skip invalid attributes + + uint32_t rta_data = *(uint32_t*) RTA_DATA(rta); + switch (rta->rta_type) { + case RTA_DST: + if (rta_data != 0) goto next; + break; + case RTA_OIF: + entry.ifindex = rta_data; + break; + case RTA_GATEWAY: + if (rta_data == 0) goto next; + break; + case RTA_PRIORITY: + if (rta_data >= minMetric) goto next; + entry.metric = rta_data; + break; + case RTA_PREFSRC: + entry.prefsrc = rta_data; + break; + } + } + + if (entry.metric >= minMetric) + { + next: + continue; + } + minMetric = entry.metric; + result->ifIndex = entry.ifindex; + result->preferredSourceAddrV4 = entry.prefsrc; + } + + if (minMetric < UINT32_MAX) { - if (destination != 0) continue; - *ifIndex = if_nametoindex(iface); + if_indextoname(result->ifIndex, result->ifName); return true; } - iface[0] = '\0'; return false; } -static bool getDefaultRouteIPv6(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result) { - FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/ipv6_route", "r"); - if (!netRoute) return false; + FF_AUTO_CLOSE_FD int sock_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); + if (sock_fd < 0) + return false; - uint32_t prefixLen; - //destination, dest_prefix_len, source, src_prefix_len, next hop, metric, ref counter, use counter, flags, iface - while (fscanf(netRoute, "%*s %x %*s %*s %*s %*s %*s %*s %*s %" FF_STR(IF_NAMESIZE) "s", &prefixLen, iface) == 2) + unsigned pid = (unsigned) getpid(); + + // Bind socket + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + .nl_pid = pid, + .nl_groups = 0, // No multicast groups + }; + + if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + return false; + } + + struct { + struct nlmsghdr nlh; + struct rtmsg rtm; + struct rtattr rta; + uint32_t table; + } req = { + // Netlink message header + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = RTM_GETROUTE, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, + .nlmsg_seq = 1, + .nlmsg_pid = pid, + }, + // Route message + .rtm = { + .rtm_family = AF_INET6, // IPv6 instead of IPv4 + .rtm_dst_len = 0, // Match all destinations + .rtm_src_len = 0, // Match all sources + .rtm_tos = 0, + .rtm_table = RT_TABLE_UNSPEC, + .rtm_protocol = RTPROT_UNSPEC, + .rtm_scope = RT_SCOPE_UNIVERSE, + .rtm_type = RTN_UNSPEC, + .rtm_flags = 0, + }, + // Route attribute for main table + .rta = { + .rta_len = RTA_LENGTH(sizeof(uint32_t)), + .rta_type = RTA_TABLE, + }, + .table = RT_TABLE_MAIN, + }; + + struct sockaddr_nl dest_addr = { + .nl_family = AF_NETLINK, + .nl_pid = 0, // Kernel + .nl_groups = 0, // No multicast groups + }; + + ssize_t sent = sendto(sock_fd, &req, sizeof(req), 0, + (struct sockaddr*)&dest_addr, sizeof(dest_addr)); + + if (sent != sizeof(req)) { + return false; + } + + struct sockaddr_nl src_addr = {}; + socklen_t src_addr_len = sizeof(src_addr); + + struct iovec iov = {}; + struct msghdr msg = { + .msg_name = &src_addr, + .msg_namelen = sizeof(src_addr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + + ssize_t peek_size = recvmsg(sock_fd, &msg, MSG_PEEK | MSG_TRUNC); + if (peek_size < 0) { + return false; + } + + FF_AUTO_FREE uint8_t* buffer = malloc((size_t)peek_size); + + ssize_t received = recvfrom(sock_fd, buffer, (size_t)peek_size, 0, + (struct sockaddr*)&src_addr, &src_addr_len); + if (received != peek_size) { + return false; + } + + struct { + uint32_t metric; + uint32_t ifindex; + } entry; + uint32_t minMetric = UINT32_MAX; + + for (const struct nlmsghdr* nlh = (struct nlmsghdr*)buffer; + NLMSG_OK(nlh, received); + nlh = NLMSG_NEXT(nlh, received)) { + if (nlh->nlmsg_seq != 1 || nlh->nlmsg_pid != pid) + continue; + if (nlh->nlmsg_type == NLMSG_DONE) + break; + + if (nlh->nlmsg_type != RTM_NEWROUTE) + continue; + + struct rtmsg* rtm = (struct rtmsg*)NLMSG_DATA(nlh); + if (rtm->rtm_family != AF_INET6) + continue; + + if (rtm->rtm_dst_len != 0) + continue; + + entry = (__typeof__(entry)) { .metric = UINT32_MAX }; + + // Parse route attributes + size_t rtm_len = RTM_PAYLOAD(nlh); + for (struct rtattr* rta = RTM_RTA(rtm); + RTA_OK(rta, rtm_len); + rta = RTA_NEXT(rta, rtm_len)) + { + switch (rta->rta_type) { + case RTA_DST: + if (RTA_PAYLOAD(rta) >= sizeof(struct in6_addr)) { + struct in6_addr* dst = (struct in6_addr*) RTA_DATA(rta); + if (!IN6_IS_ADDR_UNSPECIFIED(dst)) goto next; + } + break; + case RTA_OIF: + if (RTA_PAYLOAD(rta) >= sizeof(uint32_t)) { + entry.ifindex = *(uint32_t*) RTA_DATA(rta); + } + break; + case RTA_GATEWAY: + if (RTA_PAYLOAD(rta) >= sizeof(struct in6_addr)) { + struct in6_addr* gw = (struct in6_addr*) RTA_DATA(rta); + if (IN6_IS_ADDR_UNSPECIFIED(gw)) goto next; + } + break; + case RTA_PRIORITY: + if (RTA_PAYLOAD(rta) >= sizeof(uint32_t)) { + uint32_t metric = *(uint32_t*) RTA_DATA(rta); + if (metric >= minMetric) goto next; + entry.metric = metric; + } + break; + } + } + + if (entry.metric >= minMetric) + { + next: + continue; + } + minMetric = entry.metric; + result->ifIndex = entry.ifindex; + } + + if (minMetric < UINT32_MAX) { - if (prefixLen != 0) continue; - *ifIndex = if_nametoindex(iface); + if_indextoname(result->ifIndex, result->ifName); return true; } - iface[0] = '\0'; return false; } - -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) -{ - if (getDefaultRouteIPv4(iface, ifIndex)) - return true; - - return getDefaultRouteIPv6(iface, ifIndex); -} diff --git a/src/common/netif/netif_windows.c b/src/common/netif/netif_windows.c index 0dfd2bd077..4fa7144b3d 100644 --- a/src/common/netif/netif_windows.c +++ b/src/common/netif/netif_windows.c @@ -4,7 +4,7 @@ #include // AF_INET6, IN6_IS_ADDR_UNSPECIFIED #include -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result) { PMIB_IPFORWARD_TABLE2 pIpForwardTable = NULL; @@ -18,20 +18,17 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) { MIB_IPFORWARD_ROW2* row = &pIpForwardTable->Table[i]; - if ((row->DestinationPrefix.PrefixLength == 0) && - ((row->DestinationPrefix.Prefix.Ipv4.sin_family == AF_INET && - row->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr == 0) || - (row->DestinationPrefix.Prefix.Ipv6.sin6_family == AF_INET6 && - IN6_IS_ADDR_UNSPECIFIED(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr)))) + if (row->DestinationPrefix.PrefixLength == 0 && + row->DestinationPrefix.Prefix.Ipv4.sin_family == AF_INET && + row->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr == 0) { MIB_IF_ROW2 ifRow = { .InterfaceIndex = row->InterfaceIndex, }; - if (NETIO_SUCCESS(GetIfEntry2(&ifRow)) && - ifRow.OperStatus == IfOperStatusUp) + if (NETIO_SUCCESS(GetIfEntry2(&ifRow)) && ifRow.OperStatus == IfOperStatusUp) { MIB_IPINTERFACE_ROW ipInterfaceRow = { - .Family = (row->DestinationPrefix.Prefix.Ipv4.sin_family == AF_INET) ? AF_INET : AF_INET6, + .Family = AF_INET, .InterfaceIndex = row->InterfaceIndex, }; @@ -43,9 +40,57 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) if (realMetric < smallestMetric) { smallestMetric = realMetric; - *ifIndex = row->InterfaceIndex; - if (WideCharToMultiByte(CP_UTF8, 0, ifRow.Alias, -1, iface, IF_NAMESIZE, NULL, NULL) > 0) - iface[IF_NAMESIZE] = '\0'; + result->ifIndex = row->InterfaceIndex; + foundDefault = true; + break; + } + } + } + } + + FreeMibTable(pIpForwardTable); + + return foundDefault; +} + + +bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result) +{ + PMIB_IPFORWARD_TABLE2 pIpForwardTable = NULL; + + if (!NETIO_SUCCESS(GetIpForwardTable2(AF_UNSPEC, &pIpForwardTable))) + return false; + + bool foundDefault = false; + uint32_t smallestMetric = UINT32_MAX; + + for (ULONG i = 0; i < pIpForwardTable->NumEntries; ++i) + { + MIB_IPFORWARD_ROW2* row = &pIpForwardTable->Table[i]; + + if (row->DestinationPrefix.PrefixLength == 0 && + row->DestinationPrefix.Prefix.Ipv6.sin6_family == AF_INET6 && + IN6_IS_ADDR_UNSPECIFIED(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr)) + { + MIB_IF_ROW2 ifRow = { + .InterfaceIndex = row->InterfaceIndex, + }; + if (NETIO_SUCCESS(GetIfEntry2(&ifRow)) && ifRow.OperStatus == IfOperStatusUp) + { + MIB_IPINTERFACE_ROW ipInterfaceRow = { + .Family = AF_INET6, + .InterfaceIndex = row->InterfaceIndex, + }; + + uint32_t realMetric = row->Metric /* Metric offset */; + + if (NETIO_SUCCESS(GetIpInterfaceEntry(&ipInterfaceRow))) + realMetric += ipInterfaceRow.Metric /* Interface metric */; + + if (realMetric < smallestMetric) + { + smallestMetric = realMetric; + result->ifIndex = row->InterfaceIndex; foundDefault = true; } } diff --git a/src/common/networking/networking_linux.c b/src/common/networking/networking_linux.c index 80576d5871..074d4f528d 100644 --- a/src/common/networking/networking_linux.c +++ b/src/common/networking/networking_linux.c @@ -346,7 +346,7 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho FF_DEBUG("Multithreading mode enabled, creating connection thread"); state->thread = ffThreadCreate(connectAndSendThreadMain, state); if (state->thread) { - FF_DEBUG("Thread creation successful: thread=%p", (void*)state->thread); + FF_DEBUG("Thread creation successful: thread=%p", (void*)(uintptr_t)state->thread); return NULL; } FF_DEBUG("Thread creation failed"); diff --git a/src/common/option.c b/src/common/option.c index f1af4b48b9..71a9a1d196 100644 --- a/src/common/option.c +++ b/src/common/option.c @@ -28,55 +28,6 @@ const char* ffOptionTestPrefix(const char* argumentKey, const char* moduleName) return subKey; } -bool ffOptionParseModuleArgs(const char* argumentKey, const char* subKey, const char* value, FFModuleArgs* result) -{ - if(ffStrEqualsIgnCase(subKey, "key")) - { - ffOptionParseString(argumentKey, value, &result->key); - return true; - } - else if(ffStrEqualsIgnCase(subKey, "format")) - { - ffOptionParseString(argumentKey, value, &result->outputFormat); - return true; - } - else if(ffStrEqualsIgnCase(subKey, "output-color")) - { - if(value == NULL) - { - fprintf(stderr, "Error: usage: %s \n", argumentKey); - exit(477); - } - ffOptionParseColor(value, &result->outputColor); - return true; - } - else if(ffStrStartsWithIgnCase(subKey, "key-")) - { - const char* subKey2 = subKey + strlen("key-"); - if(ffStrEqualsIgnCase(subKey2, "color")) - { - if(value == NULL) - { - fprintf(stderr, "Error: usage: %s \n", argumentKey); - exit(477); - } - ffOptionParseColor(value, &result->keyColor); - return true; - } - else if(ffStrEqualsIgnCase(subKey2, "width")) - { - result->keyWidth = ffOptionParseUInt32(argumentKey, value); - return true; - } - else if(ffStrEqualsIgnCase(subKey2, "icon")) - { - ffOptionParseString(argumentKey, value, &result->keyIcon); - return true; - } - } - return false; -} - void ffOptionParseString(const char* argumentKey, const char* value, FFstrbuf* buffer) { if(value == NULL) @@ -157,6 +108,8 @@ bool ffOptionParseBoolean(const char* str) void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer) { + if (!value || value[0] == '\0') return; + // If value is already an ANSI escape code, use it if (value[0] == '\e' && value[1] == '[') { diff --git a/src/common/option.h b/src/common/option.h index 689881a0a9..a47b9b5041 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -29,7 +29,8 @@ typedef struct FFModuleBaseInfo // This is UB, because `void*` is not compatible with `FF*Options*`. // However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer // https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type - bool (*parseCommandOptions)(void* options, const char* key, const char* value); + void (*initOptions)(void* options); + void (*destroyOptions)(void* options); void (*parseJsonObject)(void* options, struct yyjson_val *module); void (*printModule)(void* options); void (*generateJsonResult)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module); @@ -63,7 +64,6 @@ typedef struct FFKeyValuePair } FFKeyValuePair; const char* ffOptionTestPrefix(const char* argumentKey, const char* moduleName); -bool ffOptionParseModuleArgs(const char* argumentKey, const char* pkey, const char* value, FFModuleArgs* result); void ffOptionParseString(const char* argumentKey, const char* value, FFstrbuf* buffer); FF_C_NODISCARD uint32_t ffOptionParseUInt32(const char* argumentKey, const char* value); FF_C_NODISCARD int32_t ffOptionParseInt32(const char* argumentKey, const char* value); @@ -94,3 +94,5 @@ static inline void ffOptionDestroyModuleArg(FFModuleArgs* args) ffStrbufDestroy(&args->outputFormat); ffStrbufDestroy(&args->outputColor); } + +enum { FF_OPTION_MAX_SIZE = 1 << 8 }; // Maximum size of a single option value, used for static allocation diff --git a/src/common/percent.c b/src/common/percent.c index 7465561837..e14c62a8d6 100644 --- a/src/common/percent.c +++ b/src/common/percent.c @@ -60,23 +60,32 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf const FFOptionsDisplay* options = &instance.config.display; - uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5); + const bool borderAsValue = options->barBorderLeftElapsed.length && options->barBorderRightElapsed.length; + + uint8_t blocksPercent = (uint8_t) (percent / 100.0 * options->barWidth + 0.5); assert(blocksPercent <= options->barWidth); - if(options->barBorderLeft.length) + if(!borderAsValue && options->barBorderLeft.length) { - if(!options->pipe) - ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m"); + if(!options->pipe && options->barColorBorder.length > 0) + ffStrbufAppendF(buffer, "\e[%sm", options->barColorBorder.chars); ffStrbufAppend(buffer, &options->barBorderLeft); } - if (percent != percent) + if (percent == -DBL_MAX) { - if(!options->pipe) + // Use total color for simplification + if(!options->pipe && options->barColorTotal.length > 0) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m"); - for (uint32_t i = 0; i < options->barWidth; ++i) - ffStrbufAppend(buffer, &options->barCharElapsed); + for (uint8_t i = 0; i < options->barWidth; ++i) + { + ffStrbufAppend(buffer, borderAsValue && i == 0 + ? &options->barBorderLeft + : borderAsValue && i == options->barWidth - 1 + ? &options->barBorderRight + : &options->barCharTotal); + } } else { @@ -85,16 +94,19 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf const char* colorRed = options->percentColorRed.chars; FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type; - bool monochrome = !!(percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT); - for (uint32_t i = 0; i < blocksPercent; ++i) + bool autoColorElapsed = ffStrbufIgnCaseEqualS(&options->barColorElapsed, "auto"); + + for (uint8_t i = 0; i < blocksPercent; ++i) { - if(!options->pipe) + if(!options->pipe && options->barColorElapsed.length > 0) { - if (monochrome) + if ((percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT) || !autoColorElapsed) { const char* color = NULL; - if (green <= yellow) + if (!autoColorElapsed) + color = options->barColorElapsed.chars; + else if (green <= yellow) { if (percent < green) color = colorGreen; else if (percent < yellow) color = colorYellow; @@ -120,26 +132,36 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConf ffStrbufAppendF(buffer, "\e[%sm", (green <= yellow ? colorGreen : colorRed)); } } - ffStrbufAppend(buffer, &options->barCharElapsed); + ffStrbufAppend(buffer, borderAsValue && i == 0 + ? &options->barBorderLeftElapsed + : borderAsValue && i == options->barWidth - 1 + ? &options->barBorderRightElapsed + : &options->barCharElapsed); } if (blocksPercent < options->barWidth) { - if(!options->pipe) - ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m"); - for (uint32_t i = blocksPercent; i < options->barWidth; ++i) - ffStrbufAppend(buffer, &options->barCharTotal); + if(!options->pipe && options->barColorTotal.length > 0) + ffStrbufAppendF(buffer, "\e[%sm", options->barColorTotal.chars); + for (uint8_t i = blocksPercent; i < options->barWidth; ++i) + { + ffStrbufAppend(buffer, borderAsValue && i == 0 + ? &options->barBorderLeftElapsed + : borderAsValue && i == options->barWidth - 1 + ? &options->barBorderRightElapsed + : &options->barCharTotal); + } } } - if(options->barBorderRight.length) + if(!borderAsValue && options->barBorderRight.length) { - if(!options->pipe) - ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m"); + if(!options->pipe && options->barColorBorder.length > 0) + ffStrbufAppendF(buffer, "\e[%sm", options->barColorBorder.chars); ffStrbufAppend(buffer, &options->barBorderRight); } - if(!options->pipe) + if(!options->pipe && (options->barColorElapsed.length > 0 || options->barColorTotal.length > 0 || options->barColorBorder.length > 0)) { ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); appendOutputColor(buffer, module); @@ -165,7 +187,7 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConf const char* colorYellow = options->percentColorYellow.chars; const char* colorRed = options->percentColorRed.chars; - if(percent != percent) + if(percent == -DBL_MAX) ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m"); else if(green <= yellow) { @@ -239,14 +261,14 @@ bool ffPercentParseCommandOptions(const char* key, const char* subkey, const cha return false; } -bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config) +bool ffPercentParseJsonObject(yyjson_val* key, yyjson_val* value, FFPercentageModuleConfig* config) { - if (!ffStrEqualsIgnCase(key, "percent")) + if (!unsafe_yyjson_equals_str(key, "percent")) return false; if (!yyjson_is_obj(value)) { - fprintf(stderr, "Error: usage: %s must be an object\n", key); + fprintf(stderr, "Error: usage: %s must be an object\n", unsafe_yyjson_get_str(key)); exit(480); } @@ -288,16 +310,10 @@ bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageMo return true; } -void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config) +void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig config) { - if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow) - return; - yyjson_mut_val* percent = yyjson_mut_obj_add_obj(doc, module, "percent"); - if (config.green != defaultConfig.green) - yyjson_mut_obj_add_uint(doc, percent, "green", config.green); - if (config.yellow != defaultConfig.yellow) - yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow); - if (config.type != defaultConfig.type) - yyjson_mut_obj_add_uint(doc, percent, "type", config.type); + yyjson_mut_obj_add_uint(doc, percent, "green", config.green); + yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow); + yyjson_mut_obj_add_uint(doc, percent, "type", config.type); } diff --git a/src/common/percent.h b/src/common/percent.h index 7341b7ba05..a8bb18e33d 100644 --- a/src/common/percent.h +++ b/src/common/percent.h @@ -11,7 +11,7 @@ typedef enum __attribute__((__packed__)) FFPercentageTypeFlags FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1, FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2, FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3, - FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT = FF_PERCENTAGE_TYPE_NUM_COLOR_BIT, + FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT = 1 << 4, FF_PERCENTAGE_TYPE_FORCE_UNSIGNED_ = UINT8_MAX, } FFPercentageTypeFlags; static_assert(sizeof(FFPercentageTypeFlags) == 1, ""); @@ -40,6 +40,6 @@ typedef struct yyjson_val yyjson_val; typedef struct yyjson_mut_doc yyjson_mut_doc; typedef struct yyjson_mut_val yyjson_mut_val; bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config); -bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config); -void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config); +bool ffPercentParseJsonObject(yyjson_val* key, yyjson_val* value, FFPercentageModuleConfig* config); +void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig config); const char* ffPercentParseTypeJsonConfig(yyjson_val* value, FFPercentageTypeFlags* result); diff --git a/src/common/temps.c b/src/common/temps.c index 3e1e59c543..d524a79a14 100644 --- a/src/common/temps.c +++ b/src/common/temps.c @@ -5,7 +5,7 @@ void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config, const FFModuleArgs* module) { - if (celsius != celsius) // ignores NaN + if (celsius == -DBL_MAX) // ignores invalid value return; const FFOptionsDisplay* options = &instance.config.display; @@ -107,9 +107,9 @@ bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* return false; } -bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config) +bool ffTempsParseJsonObject(yyjson_val* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config) { - if (!ffStrEqualsIgnCase(key, "temp")) + if (!unsafe_yyjson_equals_str(key, "temp")) return false; if (yyjson_is_bool(value)) @@ -126,7 +126,7 @@ bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, F if (!yyjson_is_obj(value)) { - fprintf(stderr, "Error: usage: %s must be an object or a boolean\n", key); + fprintf(stderr, "Error: usage: %s must be an object or a boolean\n", unsafe_yyjson_get_str(key)); exit(480); } @@ -159,23 +159,14 @@ bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, F return true; } -void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF_MAYBE_UNUSED bool defaultTemp, FFColorRangeConfig defaultConfig, bool temp, FFColorRangeConfig config) +void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, bool temp, FFColorRangeConfig config) { - assert(defaultTemp == false); // assume defaultTemp is always false - if (!temp) - return; - - if (config.green != defaultConfig.green || config.yellow != defaultConfig.yellow) - { - yyjson_mut_val* temp = yyjson_mut_obj_add_obj(doc, module, "temp"); - if (config.green != defaultConfig.green) - yyjson_mut_obj_add_uint(doc, temp, "green", config.green); - if (config.yellow != defaultConfig.yellow) - yyjson_mut_obj_add_uint(doc, temp, "yellow", config.yellow); - } + yyjson_mut_obj_add_bool(doc, module, "temp", false); else { - yyjson_mut_obj_add_bool(doc, module, "temp", true); + yyjson_mut_val* temp = yyjson_mut_obj_add_obj(doc, module, "temp"); + yyjson_mut_obj_add_uint(doc, temp, "green", config.green); + yyjson_mut_obj_add_uint(doc, temp, "yellow", config.yellow); } } diff --git a/src/common/temps.h b/src/common/temps.h index 2236713d26..f2f8eda89e 100644 --- a/src/common/temps.h +++ b/src/common/temps.h @@ -5,5 +5,5 @@ void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config, const FFModuleArgs* module); bool ffTempsParseCommandOptions(const char* key, const char* subkey, const char* value, bool* useTemp, FFColorRangeConfig* config); -bool ffTempsParseJsonObject(const char* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config); -void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF_MAYBE_UNUSED bool defaultTemp, FFColorRangeConfig defaultConfig, bool temp, FFColorRangeConfig config); +bool ffTempsParseJsonObject(yyjson_val* key, yyjson_val* value, bool* useTemp, FFColorRangeConfig* config); +void ffTempsGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, bool temp, FFColorRangeConfig config); diff --git a/src/data/help.json b/src/data/help.json index 59f16be662..e99c6867f8 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -77,7 +77,16 @@ }, { "long": "gen-config", - "desc": "Generate a config file at the specified path with options from the command line (if any)", + "desc": "Generate a minimal config file at the specified path", + "remark": "Defaults to \"~/.config/fastfetch/config.jsonc\". Will print the generated config if is \"-\"", + "arg": { + "type": "path", + "optional": true + } + }, + { + "long": "gen-config-full", + "desc": "Generate a full config file with all optional options at the specified path", "remark": "Defaults to \"~/.config/fastfetch/config.jsonc\". Will print the generated config if is \"-\"", "arg": { "type": "path", @@ -699,6 +708,47 @@ "default": " ]" } }, + { + "long": "bar-border-left-elapsed", + "desc": "If both bar-border-left-elapsed and bar-border-right-elapsed are set, the border will be used as parts of bar content", + "arg": { + "type": "string", + "default": "" + } + }, + { + "long": "bar-border-right-elapsed", + "desc": "If both bar-border-left-elapsed and bar-border-right-elapsed are set, the border will be used as parts of bar content", + "arg": { + "type": "string", + "default": "" + } + }, + { + "long": "bar-color-elapsed", + "desc": "Set the color to use in the elapsed part of percentage bars", + "remark": "By default, auto selected by percent-color-{green,yellow,red}", + "arg": { + "type": "color", + "default": "" + } + }, + { + "long": "bar-color-total", + "desc": "Set the color to use in the total part of percentage bars", + "arg": { + "type": "color", + "default": "light_white" + } + }, + { + "long": "bar-color-border", + "desc": "Set the color to use in the borders of percentage bars", + "arg": { + "type": "color", + "default": "light_white" + } + }, { "long": "bar-width", "desc": "Set the width of percentage bars in characters", @@ -857,906 +907,5 @@ } } } - ], - "Module specific": [ - { - "long": "title-fqdn", - "desc": "Specify whether the title should use fully qualified domain name", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "title-color-user", - "desc": "Set the color of the user name (left part)", - "remark": "See `-h color` for the list of available colors", - "arg": { - "type": "color", - "default": "Use color of \"--color-title\"" - } - }, - { - "long": "title-color-at", - "desc": "Set the color of the @ symbol (middle part)", - "remark": "See `-h color` for the list of available colors", - "arg": { - "type": "color", - "default": "Use color of \"--color-title\"" - } - }, - { - "long": "title-color-host", - "desc": "Set the color of the host name (right part)", - "remark": "See `-h color` for the list of available colors", - "arg": { - "type": "color", - "default": "default" - } - }, - { - "long": "separator-string", - "desc": "Set the string to be printed by the separator line", - "arg": { - "type": "str", - "default": "-" - } - }, - { - "long": "separator-output-color", - "desc": "Set the color of the separator line", - "arg": { - "type": "color", - "default": "default" - } - }, - { - "long": "separator-length", - "desc": "Set the length of the separator line", - "remark": "Set to 0 to automatically calculate it based on the title length", - "arg": { - "type": "num", - "default": "0" - } - }, - { - "long": "disk-folders", - "desc": "A colon (semicolon on Windows) separated list of folder paths to detect", - "remark": "On Windows, a drive letter must be upper-cased and end with \"\\\". \"/\" is used as an alias of the system drive. This option overrides other disk-show-* options", - "arg": { - "type": "path", - "default": "Auto detection using mount-points" - } - }, - { - "long": "disk-hide-folders", - "desc": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output", - "arg": { - "type": "path", - "default": "/efi:/boot:/boot/efi:/boot/firmware" - } - }, - { - "long": "disk-hide-fs", - "desc": "A colon separated list of file systems to hide from the disk output", - "arg": { - "type": "string", - "default": "" - } - }, - { - "long": "disk-show-regular", - "desc": "Specify whether regular volumes should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "disk-show-external", - "desc": "Specify whether external volumes should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "disk-show-hidden", - "desc": "Specify whether hidden volumes should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "disk-show-subvolumes", - "desc": "Specify whether subvolumes should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "disk-show-readonly", - "desc": "Specify whether read-only volumes should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "disk-show-unknown", - "desc": "Specify whether unknown volumes (unable to detect sizes) should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "disk-use-available", - "desc": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes", - "remark": "May be required for macOS to display correct results", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "diskio-detect-total", - "desc": "Detect total bytes instead of current rate", - "arg": { - "type": "bool", - "default": false - } - }, - { - "long": "diskio-name-prefix", - "desc": "Show only disks with the given name prefix", - "arg": { - "type": "str" - } - }, - { - "long": "diskio-wait-time", - "desc": "Set the wait time (in ms) when detecting disk usage", - "arg": { - "type": "num", - "default": 1000 - } - }, - { - "long": "physicaldisk-name-prefix", - "desc": "Show only disks with the given name prefix", - "arg": { - "type": "str" - } - }, - { - "long": "physicaldisk-temp", - "desc": "Detect and display SSD temperature if supported", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "bluetooth-show-disconnected", - "desc": "Specify whether disconnected Bluetooth devices should be displayed", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "packages-disabled", - "desc": "A colon-separated list of package managers to disable when detecting", - "remark": [ - "Some detection methods can be very slow.", - "You may need to increase the value of '--processing-timeout' to make it work properly.", - "Use `--packages-disabled none` to enable all." - ], - "arg": { - "type": "string", - "default": "winget" - } - }, - { - "long": "packages-combined", - "desc": "Whether to combine related package managers into single counts", - "remark": "e.g., nix-system + nix-user = nix", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "display-compact-type", - "desc": "Specify whether all displays should be printed in one line", - "arg": { - "type": "enum", - "enum": { - "none": "Disable this compact mode", - "original": "Print original resolutions", - "scaled": "Print scaled resolutions", - "original-with-refresh-rate": "Print original resolutions with refresh rate", - "scaled-with-refresh-rate": "Print scaled resolutions with refresh rate" - }, - "default": "none" - } - }, - { - "long": "display-precise-refresh-rate", - "desc": "Specify whether decimal refresh rates should not be rounded to integers when printing", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "display-order", - "desc": "Set the order to use when printing displays", - "arg": { - "type": "enum", - "enum": { - "none": "Use the detected order", - "asc": "Sort by display name in ascending order", - "desc": "Sort by display name in descending order" - }, - "default": "none" - } - }, - { - "long": "brightness-ddcci-sleep", - "desc": "Set the sleep time (in ms) when sending DDC/CI requests", - "remark": "See for details", - "arg": { - "type": "num", - "default": 10 - } - }, - { - "long": "brightness-compact", - "desc": "Specify whether multiple results should be printed in one line", - "arg": { - "type": "bool", - "default": false - } - }, - { - "long": "sound-type", - "desc": "Set which types of sound devices should be displayed", - "arg": { - "type": "enum", - "enum": { - "main": "Print only main sound devices", - "active": "Print only active sound devices", - "all": "Print all sound devices" - }, - "default": "main" - } - }, - { - "long": "battery-use-setup-api", - "desc": "Specify whether \"SetupAPI\" should be used on Windows to detect battery info", - "remark": [ - "SetupAPI supports multiple batteries, but is slower.", - "Windows only" - ], - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "cpu-temp", - "desc": "Detect and display CPU temperature if supported", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "cpu-show-pe-core-count", - "desc": "Detect and display CPU frequency of different core types (e.g., P-cores and E-cores) if supported", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "cpucache-compact", - "desc": "Show all CPU caches in one line", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "cpuusage-separate", - "desc": "Display CPU usage per logical core, instead of an average result", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "cpuusage-wait-time", - "desc": "Set the wait time (in ms) when detecting CPU usage", - "arg": { - "type": "num", - "default": 200 - } - }, - { - "long": "de-slow-version-detection", - "desc": "Specify whether DE version should be detected with slower operations", - "remark": [ - "This is only used as a fallback method. Please file a bug report if you encounter any issues.", - "Linux only" - ], - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "gpu-temp", - "desc": "Detect and display GPU temperature if supported", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "gpu-driver-specific", - "desc": "Use driver-specific methods to detect more detailed GPU information (memory usage, core count, etc.)", - "remark": "Requires the latest GPU drivers to be installed.", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "gpu-detection-method", - "desc": "Force using a specified method to detect GPUs", - "remark": "Will fall back to other methods if the specified method fails", - "arg": { - "type": "enum", - "enum": { - "auto": "Query platform-specific graphics APIs. Requires proper GPU drivers to be installed. Supported on Linux, FreeBSD, Windows and macOS", - "pci": "Search PCI devices, which does not require GPU drivers to be installed. Not supported on Windows and macOS", - "vulkan": "Use Vulkan API. Slow and requires proper Vulkan drivers to be installed. Used for Android", - "opencl": "Use OpenCL API. Slow and requires proper OpenCL drivers to be installed", - "opengl": "Use OpenGL API. Slow and only detects one GPU. Used for OpenBSD" - }, - "default": "auto" - } - }, - { - "long": "gpu-hide-type", - "desc": "Specify which types of GPUs should not be displayed (default: all GPUs are shown, regardless of recognition)", - "arg": { - "type": "enum", - "enum": { - "integrated": "Hide integrated GPUs", - "discrete": "Hide discrete GPUs", - "unknown": "Hide unknown (unrecognized) GPUs", - "none": "Do not hide any GPUs" - }, - "default": "none" - } - }, - { - "long": "battery-temp", - "desc": "Detect and display battery temperature if supported", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "loadavg-ndigits", - "desc": "Set the number of digits to keep after the decimal point when printing load average", - "arg": { - "type": "num", - "default": 2 - } - }, - { - "long": "loadavg-compact", - "desc": "Show load average values in one line", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "localip-show-ipv4", - "desc": "Show IPv4 addresses in the local IP module", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "localip-show-ipv6", - "desc": "Show IPv6 addresses in the local IP module", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-show-mac", - "desc": "Show MAC addresses in the local IP module", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-show-loop", - "desc": "Show loopback addresses (127.0.0.1) in the local IP module", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-show-mtu", - "desc": "Show network interface MTU (Maximum Transmission Unit) size in bytes", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-show-speed", - "desc": "Show network interface link speed in human-readable format (or as a 1Mb units integer in JSON format)", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-show-prefix-len", - "desc": "Show network prefix length (/N) in the local IP module", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "localip-name-prefix", - "desc": "Show only interfaces with the given interface name prefix", - "arg": { - "type": "str" - } - }, - { - "long": "localip-default-route-only", - "desc": "Show only the interface that is used for default routing", - "remark": "Doesn't work on Android", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "localip-show-all-ips", - "desc": "Show all IPs bound to the same interface. By default, only the first IP is shown", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-show-flags", - "desc": "Show network interface flags in the local IP module", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "localip-compact", - "desc": "Show all IPs in one line", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "dns-show-type", - "desc": "Specify which types of DNS servers should be detected", - "arg": { - "type": "enum", - "enum": { - "ipv4": "Show IPv4 addresses only", - "ipv6": "Show IPv6 addresses only", - "both": "Show both IPv4 and IPv6 addresses" - }, - "default": "both" - } - }, - { - "long": "netio-name-prefix", - "desc": "Show only interfaces with the given name prefix", - "arg": { - "type": "str" - } - }, - { - "long": "netio-default-route-only", - "desc": "Show only the interface that is used for default routing", - "remark": "Doesn't work on Android", - "arg": { - "type": "bool", - "optional": true, - "default": true - } - }, - { - "long": "netio-detect-total", - "desc": "Detect total bytes instead of current rate", - "arg": { - "type": "bool", - "default": false - } - }, - { - "long": "netio-wait-time", - "desc": "Set the wait time (in ms) when detecting network usage", - "arg": { - "type": "num", - "default": 1000 - } - }, - { - "long": "publicip-timeout", - "desc": "Time in milliseconds to wait for the public IP server to respond", - "remark": "0 to disable timeout", - "arg": { - "type": "num", - "default": 0 - } - }, - { - "long": "publicip-url", - "desc": "The URL of the public IP detection server to use", - "arg": { - "type": "str" - } - }, - { - "long": "publicip-ipv6", - "desc": "Specify whether to use IPv6 for the public IP detection server", - "arg": { - "type": "bool", - "default": false - } - }, - { - "long": "weather-location", - "desc": "Set the location to use", - "remark": "Must be URI encoded (e.g., a whitespace must be encoded as \"+\")", - "arg": { - "type": "str" - } - }, - { - "long": "weather-timeout", - "desc": "Time in milliseconds to wait for the weather server to respond", - "remark": "0 to disable timeout", - "arg": { - "type": "num", - "default": 0 - } - }, - { - "long": "weather-output-format", - "desc": "The output weather format to use", - "remark": "Must be URI encoded", - "arg": { - "type": "str" - } - }, - { - "long": "wm-detect-plugin", - "desc": "Specify whether window manager plugins should be detected on supported platforms", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "users-compact", - "desc": "Show all active users in one line", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "users-myself-only", - "desc": "Show only the current user", - "arg": { - "type": "bool", - "optional": true, - "default": false - } - }, - { - "long": "player-name", - "desc": "The name of the player to use for the Media and Player modules", - "remark": "Linux only", - "arg": { - "type": "str" - } - }, - { - "long": "opengl-library", - "desc": "Set the OpenGL context creation library to use", - "arg": { - "type": "enum", - "enum": { - "auto": "Prefer EGL on *nix; prefer platform-specific implementation on others", - "egl": "EGL", - "glx": "GLX (*nix only)" - }, - "default": "auto" - } - }, - { - "long": "command-shell", - "desc": "Set the shell program to execute the command text", - "arg": { - "type": "str", - "default": "\"cmd\" for Windows; \"/bin/sh\" for *nix" - } - }, - { - "long": "command-param", - "desc": "Set the parameter to use when starting the shell", - "remark": "If set to an empty string, it will be ignored", - "arg": { - "type": "str", - "default": "\"/c\" for Windows; \"-c\" for *nix" - } - }, - { - "long": "command-key", - "desc": "Set the module key to display", - "arg": { - "type": "str" - } - }, - { - "long": "command-text", - "desc": "Set the command text to execute", - "arg": { - "type": "str" - } - }, - { - "long": "colors-symbol", - "desc": "Set the symbol to be printed by the Colors module", - "arg": { - "type": "enum", - "enum": { - "block": "\u2588\u2588\u2588", - "background": "(whitespaces with background)", - "circle": "\u25cf", - "diamond": "\u25c6", - "triangle": "\u25b2", - "square": "\u25a0", - "star": "\u2605" - }, - "default": "background" - } - }, - { - "long": "colors-padding-left", - "desc": "Set the number of white spaces to print before the symbol", - "arg": { - "type": "num", - "default": 0 - } - }, - { - "long": "colors-block-width", - "desc": "Set the block width in spaces", - "arg": { - "type": "num", - "default": 3 - } - }, - { - "long": "colors-block-range-start", - "desc": "Set the start range of colors in the blocks to print", - "remark": [ - "Display colors 0-15 in the blocks. (16 colors)", - "Display colors 0-7 in the blocks. (8 colors)", - "Only works for `--colors-symbol block`.", - "Must be in range 0-15", - "See also `--colors-range-end`" - ], - "arg": { - "type": "num", - "default": 0 - } - }, - { - "long": "colors-block-range-end", - "desc": "Set the end range of colors in the blocks to print", - "remark": [ - "Display colors 0-15 in the blocks. (16 colors)", - "Display colors 0-7 in the blocks. (8 colors)", - "Only works for `--colors-symbol block`.", - "Must be in range 0-15", - "See also `--colors-range-start`" - ], - "arg": { - "type": "num", - "default": 15 - } - } - ], - "General module": [ - { - "long": "-format", - "desc": [ - "Set the format string to use for a specific module", - "See ", - "For help about a specific format string, use \"fastfetch -h -format\"" - ], - "arg": { - "type": "format" - }, - "pseudo": true - }, - { - "long": "-key", - "desc": [ - "Set the key to use for a specific module.", - "For modules that print multiple lines, the string is parsed", - "as a format string with the index as the first character" - ], - "arg": { - "type": "key" - }, - "pseudo": true - }, - { - "long": "-key-color", - "desc": "Override the global \"--color-keys\" option for a specific module", - "arg": { - "type": "color" - }, - "pseudo": true - }, - { - "long": "-key-icon", - "desc": "Set the icon to be displayed by \"--key-type icon\"", - "arg": { - "type": "string" - }, - "pseudo": true - }, - { - "long": "-output-color", - "desc": "Override the global \"--color-output\" option for a specific module", - "arg": { - "type": "color" - }, - "pseudo": true - }, - { - "long": "-key-width", - "desc": "Override the global \"--key-width\" option for a specific module", - "arg": { - "type": "num" - }, - "pseudo": true - }, - { - "long": "-percent-green", - "desc": [ - "Threshold for percentage color ranges", - "Values less than percent-green will be shown in green" - ], - "arg": { - "type": "num" - }, - "pseudo": true - }, - { - "long": "-percent-yellow", - "desc": [ - "Threshold for percentage color ranges", - "Values greater than percent-green and less than percent-yellow will be shown in yellow", - "Values greater than percent-yellow will be shown in red" - ], - "arg": { - "type": "num" - }, - "pseudo": true - }, - { - "long": "-percent-type", - "desc": "Set the percentage output type", - "remark": [ - "0 to use global `--percent-type` value", - "1 for percentage number", - "2 for multi-color bar", - "3 for both", - "6 for bar only", - "9 for colored number", - "10 for monochrome bar" - ], - "arg": { - "type": "num", - "default": 0 - }, - "pseudo": true - }, - { - "long": "-temp-green", - "desc": [ - "Threshold for temperature color ranges", - "Values less than temp-green will be shown in green" - ], - "arg": { - "type": "num" - }, - "pseudo": true - }, - { - "long": "-temp-yellow", - "desc": [ - "Threshold for temperature color ranges", - "Values greater than temp-green and less than temp-yellow will be shown in yellow", - "Values greater than temp-yellow will be shown in red" - ], - "arg": { - "type": "num" - }, - "pseudo": true - } ] } diff --git a/src/detection/battery/battery.h b/src/detection/battery/battery.h index 94aa65e324..ddeb7c6e7b 100644 --- a/src/detection/battery/battery.h +++ b/src/detection/battery/battery.h @@ -1,8 +1,9 @@ #pragma once #include "fastfetch.h" +#include "modules/battery/option.h" -#define FF_BATTERY_TEMP_UNSET (0/0.0) +#define FF_BATTERY_TEMP_UNSET (-DBL_MAX) typedef struct FFBatteryResult { diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index da2cb8f211..26b8e571d7 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -96,6 +96,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) battery->temperature = FF_BATTERY_TEMP_UNSET; battery->cycleCount = 0; battery->timeRemaining = -1; + battery->capacity = 0; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); ffStrbufInit(&battery->status); @@ -124,11 +125,11 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) { double level = 0, scale = 0; if (ffParsePropLines(start, "level: ", &temp)) - level = ffStrbufToDouble(&temp); + level = ffStrbufToDouble(&temp, -DBL_MAX); ffStrbufClear(&temp); if (ffParsePropLines(start, "scale: ", &temp)) - scale = ffStrbufToDouble(&temp); + scale = ffStrbufToDouble(&temp, -DBL_MAX); ffStrbufClear(&temp); if (level > 0 && scale > 0) @@ -138,7 +139,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) if(options->temp) { if (ffParsePropLines(start, "temperature: ", &temp)) - battery->temperature = ffStrbufToDouble(&temp); + battery->temperature = ffStrbufToDouble(&temp, FF_BATTERY_TEMP_UNSET); ffStrbufClear(&temp); } diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 8a9b2c6411..d6987bc354 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -45,7 +45,7 @@ static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl return; FFBatteryResult* result = ffListAdd(results); - result->capacity = ffStrbufToDouble(&tmpBuffer); + result->capacity = ffStrbufToDouble(&tmpBuffer, 0); //At this point, we have a battery. Try to get as much values as possible. @@ -154,7 +154,11 @@ static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl if (options->temp) { if (ffReadFileBufferRelative(dfd, "temp", &tmpBuffer)) - result->temperature = ffStrbufToDouble(&tmpBuffer) / 10; + { + result->temperature = ffStrbufToDouble(&tmpBuffer, FF_BATTERY_TEMP_UNSET); + if (result->temperature != FF_BATTERY_TEMP_UNSET) + result->temperature /= 10; + } } } diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index dde78d2177..9730664a09 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -103,7 +103,7 @@ static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results) battery->cycleCount = bi.CycleCount; - battery->temperature = 0.0/0.0; + battery->temperature = FF_BATTERY_TEMP_UNSET; if(options->temp) { bqi.InformationLevel = BatteryTemperature; diff --git a/src/detection/bios/bios.h b/src/detection/bios/bios.h index 5272c5ca15..4a0969d266 100644 --- a/src/detection/bios/bios.h +++ b/src/detection/bios/bios.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/bios/option.h" typedef struct FFBiosResult { diff --git a/src/detection/bluetooth/bluetooth.h b/src/detection/bluetooth/bluetooth.h index 57bf9ef3ac..0a4153ce5a 100644 --- a/src/detection/bluetooth/bluetooth.h +++ b/src/detection/bluetooth/bluetooth.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/bluetooth/option.h" typedef struct FFBluetoothResult { diff --git a/src/detection/bluetoothradio/bluetoothradio.h b/src/detection/bluetoothradio/bluetoothradio.h index 46ea60f580..8999b84a4b 100644 --- a/src/detection/bluetoothradio/bluetoothradio.h +++ b/src/detection/bluetoothradio/bluetoothradio.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/bluetoothradio/option.h" typedef struct FFBluetoothRadioResult { diff --git a/src/detection/board/board.h b/src/detection/board/board.h index 64a8dd3a74..f41e60e132 100644 --- a/src/detection/board/board.h +++ b/src/detection/board/board.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/board/option.h" typedef struct FFBoardResult { diff --git a/src/detection/bootmgr/bootmgr.h b/src/detection/bootmgr/bootmgr.h index c2d1ac2a3f..e0fbcddcc9 100644 --- a/src/detection/bootmgr/bootmgr.h +++ b/src/detection/bootmgr/bootmgr.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/bootmgr/option.h" typedef struct FFBootmgrResult { diff --git a/src/detection/brightness/brightness.h b/src/detection/brightness/brightness.h index 3db260a666..5f2f1405a7 100644 --- a/src/detection/brightness/brightness.h +++ b/src/detection/brightness/brightness.h @@ -1,7 +1,7 @@ #pragma once #include "fastfetch.h" -#include "util/FFlist.h" +#include "modules/brightness/option.h" typedef struct FFBrightnessResult { diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index 602649c3c8..678c89a6ad 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -32,7 +32,7 @@ static const char* detectWithBacklight(FFlist* result) ffStrbufAppendS(&backlightDir, "/brightness"); if(ffReadFileBuffer(backlightDir.chars, &buffer)) { - double actualBrightness = ffStrbufToDouble(&buffer); + double actualBrightness = ffStrbufToDouble(&buffer, 0); ffStrbufSubstrBefore(&backlightDir, backlightDirLength); ffStrbufAppendS(&backlightDir, entry->d_name); ffStrbufAppendS(&backlightDir, "/max_brightness"); @@ -71,7 +71,7 @@ static const char* detectWithBacklight(FFlist* result) } else ffStrbufInitS(&brightness->name, entry->d_name); - brightness->max = ffStrbufToDouble(&buffer); + brightness->max = ffStrbufToDouble(&buffer, 0); brightness->min = 0; brightness->current = actualBrightness; brightness->builtin = true; diff --git a/src/detection/btrfs/btrfs.h b/src/detection/btrfs/btrfs.h index a82157d091..8940ebc8ab 100644 --- a/src/detection/btrfs/btrfs.h +++ b/src/detection/btrfs/btrfs.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/btrfs/option.h" typedef struct FFBtrfsDiskUsage { diff --git a/src/detection/camera/camera.h b/src/detection/camera/camera.h index 83d07f3126..ee0c32d0cf 100644 --- a/src/detection/camera/camera.h +++ b/src/detection/camera/camera.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/camera/option.h" typedef struct FFCameraResult { diff --git a/src/detection/camera/camera_android.c b/src/detection/camera/camera_android.c index 623bb93ae8..7f5f24447a 100644 --- a/src/detection/camera/camera_android.c +++ b/src/detection/camera/camera_android.c @@ -45,7 +45,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) ffStrbufInitStatic(&camera->name, "Unknown"); } ffStrbufInit(&camera->vendor); - ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id"))); + ffStrbufInitJsonVal(&camera->id, yyjson_obj_get(device, "id")); yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes")); if (yyjson_is_obj(sizes)) { diff --git a/src/detection/chassis/chassis.h b/src/detection/chassis/chassis.h index 0c9c0380de..8f57232ecb 100644 --- a/src/detection/chassis/chassis.h +++ b/src/detection/chassis/chassis.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/chassis/option.h" typedef struct FFChassisResult { diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 5af7a8275b..4f07b97799 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -1,8 +1,9 @@ #pragma once #include "fastfetch.h" +#include "modules/cpu/option.h" -#define FF_CPU_TEMP_UNSET (0/0.0) +#define FF_CPU_TEMP_UNSET (-DBL_MAX) typedef struct FFCPUCore { diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 46ab37b788..411c1f0d56 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -28,19 +28,19 @@ static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) ffStrbufAppendS(dir, "temp1_input"); if(!ffReadFileBuffer(dir->chars, buffer)) - return 0.0/0.0; + return FF_CPU_TEMP_UNSET; } ffStrbufSubstrBefore(dir, dirLength); - double value = ffStrbufToDouble(buffer);// millidegree Celsius + double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius - if(value != value) - return 0.0/0.0; + if(value == FF_CPU_TEMP_UNSET) + return FF_CPU_TEMP_UNSET; ffStrbufAppendS(dir, "name"); if (!ffReadFileBuffer(dir->chars, buffer)) - return 0.0/0.0; + return FF_CPU_TEMP_UNSET; ffStrbufTrimRightSpace(buffer); @@ -51,14 +51,17 @@ static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) ffStrbufEqualS(buffer, "coretemp") // Intel ) return value / 1000.; - return 0.0/0.0; + return FF_CPU_TEMP_UNSET; } static double detectTZTemp(FFstrbuf* buffer) { if (ffReadFileBuffer("/sys/class/thermal/thermal_zone0/temp", buffer)) - return ffStrbufToDouble(buffer) / 1000.; - return 0.0/0.0; + { + double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius + return value != FF_CPU_TEMP_UNSET ? value / 1000. : FF_CPU_TEMP_UNSET; + } + return FF_CPU_TEMP_UNSET; } static double detectCPUTemp(void) @@ -72,7 +75,7 @@ static double detectCPUTemp(void) FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); if(dirp == NULL) - return 0.0/0.0; + return FF_CPU_TEMP_UNSET; struct dirent* entry; while((entry = readdir(dirp)) != NULL) @@ -84,7 +87,7 @@ static double detectCPUTemp(void) ffStrbufAppendC(&baseDir, '/'); double result = parseHwmonDir(&baseDir, &buffer); - if (result == result) + if (result != FF_CPU_TEMP_UNSET) return result; ffStrbufSubstrBefore(&baseDir, baseDirLength); diff --git a/src/detection/cpucache/cpucache.h b/src/detection/cpucache/cpucache.h index f639642404..2e6e060e4a 100644 --- a/src/detection/cpucache/cpucache.h +++ b/src/detection/cpucache/cpucache.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/cpucache/option.h" typedef enum __attribute__((__packed__)) FFCPUCacheType { diff --git a/src/detection/cpuusage/cpuusage.h b/src/detection/cpuusage/cpuusage.h index 7950d452b8..353b7297c3 100644 --- a/src/detection/cpuusage/cpuusage.h +++ b/src/detection/cpuusage/cpuusage.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/cpuusage/option.h" typedef struct FFCpuUsageInfo { uint64_t inUseAll; diff --git a/src/detection/cursor/cursor.h b/src/detection/cursor/cursor.h index 3e3ff6d403..6a6f68b275 100644 --- a/src/detection/cursor/cursor.h +++ b/src/detection/cursor/cursor.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/cursor/option.h" typedef struct FFCursorResult { diff --git a/src/detection/cursor/cursor_apple.m b/src/detection/cursor/cursor_apple.m index 29187e11de..610bd1ed8a 100644 --- a/src/detection/cursor/cursor_apple.m +++ b/src/detection/cursor/cursor_apple.m @@ -2,19 +2,30 @@ #import -static void appendColor(FFstrbuf* str, NSDictionary* color) +static void appendColor(FFstrbuf* str, NSDictionary* dict) { - int r = (int) (((NSNumber*) color[@"red"]).doubleValue * 255); - int g = (int) (((NSNumber*) color[@"green"]).doubleValue * 255); - int b = (int) (((NSNumber*) color[@"blue"]).doubleValue * 255); - int a = (int) (((NSNumber*) color[@"alpha"]).doubleValue * 255); - - if (r == 255 && g == 255 && b == 255 && a == 255) - ffStrbufAppendS(str, "White"); - else if (r == 0 && g == 0 && b == 0 && a == 255) - ffStrbufAppendS(str, "Black"); - else - ffStrbufAppendF(str, "#%02X%02X%02X%02X", r, g, b, a); + uint32_t r = (uint32_t) (((NSNumber*) dict[@"red"]).doubleValue * 255 + .5); + uint32_t g = (uint32_t) (((NSNumber*) dict[@"green"]).doubleValue * 255 + .5); + uint32_t b = (uint32_t) (((NSNumber*) dict[@"blue"]).doubleValue * 255 + .5); + uint32_t a = (uint32_t) (((NSNumber*) dict[@"alpha"]).doubleValue * 255 + .5); + uint32_t color = (r << 24) | (g << 16) | (b << 8) | a; + + switch (color) + { + case 0x000000FF: ffStrbufAppendS(str, "Black"); return; + case 0x0433FFFF: ffStrbufAppendS(str, "Blue"); return; + case 0xAA7942FF: ffStrbufAppendS(str, "Brown"); return; + case 0x00FDFFFF: ffStrbufAppendS(str, "Cyan"); return; + case 0x00F900FF: ffStrbufAppendS(str, "Green"); return; + case 0xFF40FFFF: ffStrbufAppendS(str, "Magenta"); return; + case 0xFF9300FF: ffStrbufAppendS(str, "Orange"); return; + case 0x942192FF: ffStrbufAppendS(str, "Purple"); return; + case 0xFF2600FF: ffStrbufAppendS(str, "Red"); return; + case 0xFFFB00FF: ffStrbufAppendS(str, "Yellow"); return; + case 0xFFFFFFFF: ffStrbufAppendS(str, "White"); return; + case 0x00000000: ffStrbufAppendS(str, "Transparent"); return; + default: ffStrbufAppendF(str, "#%08X", color); return; + } } void ffDetectCursor(FFCursorResult* result) @@ -46,7 +57,7 @@ void ffDetectCursor(FFCursorResult* result) NSNumber* mouseDriverCursorSize = dict[@"mouseDriverCursorSize"]; if (mouseDriverCursorSize) - ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32)); + ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32 + 0.5)); else ffStrbufAppendS(&result->size, "32"); } diff --git a/src/detection/de/de.h b/src/detection/de/de.h index 9d8b2201f1..67e8c1c41b 100644 --- a/src/detection/de/de.h +++ b/src/detection/de/de.h @@ -1,5 +1,6 @@ #pragma once #include "fastfetch.h" +#include "modules/de/option.h" const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options); diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index 4a24f9de05..526de81282 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/disk/option.h" typedef struct FFDisk { diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 0076c21f62..fe13c8599d 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -55,6 +55,9 @@ static bool isPhysicalDevice(const struct mntent* device) ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices ) return false; + if (ffStrStartsWith(device->mnt_dir, "/bedrock/")) // Ignore Bedrock Linux subvolumes + return false; + struct stat deviceStat; if(stat(device->mnt_fsname, &deviceStat) != 0) return false; diff --git a/src/detection/diskio/diskio.h b/src/detection/diskio/diskio.h index 0082b18b75..fdaae3b18a 100644 --- a/src/detection/diskio/diskio.h +++ b/src/detection/diskio/diskio.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/diskio/option.h" typedef struct FFDiskIOResult { diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 7949f61ec2..f502f175a3 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/display/option.h" #define FF_DE_PRETTY_PLASMA "KDE Plasma" #define FF_DE_PRETTY_GNOME "GNOME" diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index beb6aac0ad..c27672bec8 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -6,6 +6,7 @@ #include "common/time.h" #include "util/edidHelper.h" #include "util/mallocHelper.h" +#include "util/stringUtils.h" #include #include @@ -24,6 +25,9 @@ typedef struct XcbPropertyData FF_LIBRARY_SYMBOL(xcb_get_atom_name_name) FF_LIBRARY_SYMBOL(xcb_get_atom_name_name_length) FF_LIBRARY_SYMBOL(xcb_get_atom_name_reply) + FF_LIBRARY_SYMBOL(xcb_get_setup) + FF_LIBRARY_SYMBOL(xcb_setup_vendor) + FF_LIBRARY_SYMBOL(xcb_setup_vendor_length) } XcbPropertyData; static bool xcbInitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, XcbPropertyData* propertyData) @@ -38,6 +42,9 @@ static bool xcbInitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, XcbProperty FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name_name, false) FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name_name_length, false) FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name_reply, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_setup, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_setup_vendor, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_setup_vendor_length, false) return true; } @@ -86,6 +93,23 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect ffStrbufSetS(&result->wmProcessName, wmName); } +static void xcbFetchServerVendor(XcbPropertyData* data, xcb_connection_t* connection, FFDisplayServerResult* result) +{ + const xcb_setup_t* setup = data->ffxcb_get_setup(connection); + + int length = data->ffxcb_setup_vendor_length(setup); + if(length <= 0) + return; + + FF_STRBUF_AUTO_DESTROY serverVendor = ffStrbufCreateNS((uint32_t) length, data->ffxcb_setup_vendor(setup)); + + if (!ffStrbufEqualS(&serverVendor, "The X.Org Foundation")) // Original + { + ffStrbufDestroy(&result->wmProtocolName); + ffStrbufInitMove(&result->wmProtocolName, &serverVendor); + } +} + typedef struct XcbRandrData { FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_current) @@ -381,8 +405,10 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result) xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(data.connection)); - if(iterator.rem > 0 && propertyDataInitialized) + if(iterator.rem > 0 && propertyDataInitialized) { xcbDetectWMfromEWMH(&data.propData, data.connection, iterator.data->root, result); + xcbFetchServerVendor(&data.propData, data.connection, result); + } while(iterator.rem > 0) diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index ab16102be4..324290b32b 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -14,6 +14,7 @@ typedef struct X11PropertyData { FF_LIBRARY_SYMBOL(XInternAtom) FF_LIBRARY_SYMBOL(XGetWindowProperty) + FF_LIBRARY_SYMBOL(XServerVendor) FF_LIBRARY_SYMBOL(XFree) } X11PropertyData; @@ -21,6 +22,7 @@ static bool x11InitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, X11Property { FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XInternAtom, false) FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XGetWindowProperty, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XServerVendor, false) FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XFree, false) return true; @@ -62,6 +64,16 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl data->ffXFree(wmWindow); } +static void x11FetchServerVendor(X11PropertyData* data, Display* display, FFDisplayServerResult* result) +{ + const char* serverVendor = data->ffXServerVendor(display); + if (serverVendor && !ffStrEquals(serverVendor, "The X.Org Foundation")) { + ffStrbufSetS(&result->wmProtocolName, serverVendor); + } + + +} + typedef struct XrandrData { FF_LIBRARY_SYMBOL(XInternAtom) @@ -305,8 +317,10 @@ const char* ffdsConnectXrandr(FFDisplayServerResult* result) if(data.display == NULL) return "XOpenDisplay() failed"; - if(propertyDataInitialized && ScreenCount(data.display) > 0) + if(propertyDataInitialized && ScreenCount(data.display) > 0) { x11DetectWMFromEWMH(&propertyData, data.display, result); + x11FetchServerVendor(&propertyData, data.display, result); + } data.result = result; diff --git a/src/detection/dns/dns.h b/src/detection/dns/dns.h index ec25005c3d..3653f62d31 100644 --- a/src/detection/dns/dns.h +++ b/src/detection/dns/dns.h @@ -1,5 +1,6 @@ #pragma once #include "fastfetch.h" +#include "modules/dns/option.h" const char* ffDetectDNS(FFDNSOptions* options, FFlist* results /* list of FFstrbuf */); diff --git a/src/detection/dns/dns_windows.c b/src/detection/dns/dns_windows.c index 55cda9e4fd..48615117fb 100644 --- a/src/detection/dns/dns_windows.c +++ b/src/detection/dns/dns_windows.c @@ -37,7 +37,7 @@ const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) return "GetAdaptersAddresses() failed"; } - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteV4()->ifIndex; // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) { diff --git a/src/detection/editor/editor.h b/src/detection/editor/editor.h index 38d63aebe2..d130c43bdd 100644 --- a/src/detection/editor/editor.h +++ b/src/detection/editor/editor.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/editor/option.h" typedef struct FFEditorResult { diff --git a/src/detection/font/font.h b/src/detection/font/font.h index 0f0e28d1f8..ed05d1d8cb 100644 --- a/src/detection/font/font.h +++ b/src/detection/font/font.h @@ -1,8 +1,9 @@ #pragma once #include "fastfetch.h" +#include "modules/font/option.h" -#define FF_DETECT_FONT_NUM_FONTS 4 +enum { FF_DETECT_FONT_NUM_FONTS = 4 }; typedef struct FFFontResult { diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index a27ab01c76..5bd667ff22 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -2,6 +2,7 @@ #include "detection/vulkan/vulkan.h" #include "detection/opencl/opencl.h" #include "detection/opengl/opengl.h" +#include "modules/opengl/opengl.h" const char* FF_GPU_VENDOR_NAME_APPLE = "Apple"; const char* FF_GPU_VENDOR_NAME_AMD = "AMD"; @@ -56,7 +57,10 @@ const char* detectByOpenGL(FFlist* gpus) ffStrbufInit(&result.slv); ffStrbufInit(&result.library); - const char* error = ffDetectOpenGL(&instance.config.modules.openGL, &result); + __attribute__((__cleanup__(ffDestroyOpenGLOptions))) FFOpenGLOptions options; + ffInitOpenGLOptions(&options); + const char* error = ffDetectOpenGL(&options, &result); + if (!error) { FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus); diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index e4db0f8588..bad28d9280 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -1,12 +1,13 @@ #pragma once #include "fastfetch.h" +#include "modules/gpu/option.h" -#define FF_GPU_TEMP_UNSET (0/0.0) +#define FF_GPU_TEMP_UNSET (-DBL_MAX) #define FF_GPU_CORE_COUNT_UNSET -1 #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) #define FF_GPU_FREQUENCY_UNSET 0 -#define FF_GPU_CORE_USAGE_UNSET (0/0.0) +#define FF_GPU_CORE_USAGE_UNSET (-DBL_MAX) #define FF_GPU_INDEX_UNSET ((uint32_t)-1) extern const char* FF_GPU_VENDOR_NAME_APPLE; diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 026f9acad2..bad4f92930 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -1,6 +1,4 @@ #include "gpu.h" -#include "common/library.h" -#include "detection/cpu/cpu.h" #include "util/apple/cf_helpers.h" #include "util/apple/smc_temps.h" @@ -109,7 +107,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->frequency = FF_GPU_FREQUENCY_UNSET; IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId); - ffStrbufInitStatic(&gpu->platformApi, "Metal"); + ffStrbufInitStatic(&gpu->platformApi, "IOKit"); ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver); diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index b4c2636998..d7d9606be1 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -106,7 +106,10 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus) .name_len = ARRAY_SIZE(driverName), }; if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0) - ffStrbufSetF(&gpu->driver, "%*s %d.%d.%d", (int) ver.name_len, ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel); + { + driverName[ver.name_len] = '\0'; + ffStrbufSetF(&gpu->driver, "%s %d.%d.%d", ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel); + } if (ffStrStartsWith(driverName, "i915")) ffDrmDetectI915(gpu, fd); diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 21dae1dc84..d32b60004a 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -4,12 +4,10 @@ #include "util/windows/unicode.h" #include "util/windows/registry.h" #include "util/mallocHelper.h" +#include "util/debug.h" +#include "util/windows/nt.h" -#define INITGUID #include -#include -#include -#include "util/windows/nt.h" #define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}" enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 }; @@ -19,35 +17,55 @@ const uint32_t regDirectxKeyPrefixLength = (uint32_t) __builtin_strlen("SOFTWARE wchar_t regDriverKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\" FF_EMPTY_GUID_STR L"\\0000"; const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\CurrentControlSet\\Control\\Class\\"); +#define GUID_DEVCLASS_DISPLAY_STRING L"{4d36e968-e325-11ce-bfc1-08002be10318}" // Found in + const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { - ULONG devInfListSize = 0; - if (CM_Get_Device_Interface_List_SizeW(&devInfListSize, (LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || devInfListSize <= 1) + FF_DEBUG("Starting GPU detection"); + + ULONG devIdListSize = 0; + if (CM_Get_Device_ID_List_SizeW(&devIdListSize, GUID_DEVCLASS_DISPLAY_STRING, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS || devIdListSize <= 1) + { + FF_DEBUG("No display devices found, list size: %lu", devIdListSize); return "No display devices found"; + } - FF_AUTO_FREE DEVINSTID_W devInfList = malloc(devInfListSize * sizeof(*devInfList)); + FF_DEBUG("Found device ID list size: %lu", devIdListSize); - if (CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, devInfList, devInfListSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS) - return "CM_Get_Device_Interface_ListW failed"; + FF_AUTO_FREE DEVINSTID_W devIdList = malloc(devIdListSize * sizeof(*devIdList)); - for (wchar_t* devInf = devInfList; *devInf; devInf += wcslen(devInf) + 1) + if (CM_Get_Device_ID_ListW(GUID_DEVCLASS_DISPLAY_STRING, devIdList, devIdListSize, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT) != CR_SUCCESS) { - if (wcsncmp(devInf, L"\\\\?\\ROOT#BasicDisplay#", 22) == 0) - continue; // Skip Microsoft Basic Display Adapter + FF_DEBUG("CM_Get_Device_ID_ListW failed"); + return "CM_Get_Device_ID_ListW failed"; + } + + int deviceCount = 0; + for (wchar_t* devId = devIdList; *devId; devId += wcslen(devId) + 1) + { + FF_DEBUG("Processing device ID: %ls", devId); + + if (wcsncmp(devId, L"SWD\\", 4) == 0) + { + FF_DEBUG("Skipping SWD device interface to avoid duplicates"); + continue; + } DEVINST devInst = 0; - wchar_t buffer[256]; - ULONG bufferLen = 0; { - DEVPROPTYPE propertyType; - bufferLen = sizeof(buffer); - if (CM_Get_Device_Interface_PropertyW(devInf, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &bufferLen, 0) != CR_SUCCESS || - CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) + if (CM_Locate_DevNodeW(&devInst, devId, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) + { + FF_DEBUG("Failed to get device instance ID or locate device node"); continue; + } + FF_DEBUG("Device instance ID: %lu", devInst); } FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + deviceCount++; + FF_DEBUG("Added GPU #%d to list", deviceCount); + ffStrbufInit(&gpu->vendor); ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); @@ -63,8 +81,15 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->frequency = FF_GPU_FREQUENCY_UNSET; unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0; - if (swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) + if (swscanf(devId, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) + { + FF_DEBUG("Parsed PCI IDs - Vendor: 0x%x, Device: 0x%x, SubSystem: 0x%x, Rev: 0x%x", vendorId, deviceId, subSystemId, revId); ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); + } + else + { + FF_DEBUG("Failed to parse PCI device information from instance ID"); + } uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0; @@ -78,53 +103,87 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* pciFunc = pciAddr & 0xFFFF; gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc; pciAddr = 1; // Set to 1 to indicate that the device is a PCI device + FF_DEBUG("PCI location - Bus: %u, Device: %u, Function: %u, DeviceID: %llu", pciBus, pciDev, pciFunc, gpu->deviceId); } + else + { + FF_DEBUG("Failed to get PCI address"); + } + } + else + { + FF_DEBUG("Failed to get PCI bus number"); } uint64_t adapterLuid = 0; FF_HKEY_AUTO_DESTROY hVideoIdKey = NULL; + + wchar_t buffer[256]; + ULONG bufferLen = 0; if (CM_Open_DevNode_Key(devInst, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hVideoIdKey, CM_REGISTRY_HARDWARE) == CR_SUCCESS) { + FF_DEBUG("Opened device node registry key"); bufferLen = sizeof(buffer); if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS && bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) { + FF_DEBUG("Found VideoID: %ls", buffer); wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN); FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) { + FF_DEBUG("Opened DirectX registry key"); + if (gpu->vendor.length == 0) { uint32_t vendorId = 0; if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) + { + FF_DEBUG("Found vendor ID from DirectX registry: 0x%x", vendorId); ffStrbufSetStatic(&gpu->vendor, ffGPUGetVendorString(vendorId)); + } } - ffRegReadStrbuf(hDirectxKey, L"Description", &gpu->name, NULL); + if (ffRegReadStrbuf(hDirectxKey, L"Description", &gpu->name, NULL)) + FF_DEBUG("Found GPU description: %s", gpu->name.chars); + + if (ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &gpu->dedicated.total, NULL)) + FF_DEBUG("Found dedicated video memory: %llu bytes", gpu->dedicated.total); - ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &gpu->dedicated.total, NULL); if (ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &gpu->shared.total, NULL)) { + FF_DEBUG("Found dedicated system memory: %llu bytes", gpu->shared.total); uint64_t sharedSystemMemory = 0; if (ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) + { gpu->shared.total += sharedSystemMemory; + FF_DEBUG("Added shared system memory: %llu bytes, total shared: %llu bytes", sharedSystemMemory, gpu->shared.total); + } } if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL)) { + FF_DEBUG("Found adapter LUID: %llu", adapterLuid); if (!gpu->deviceId) gpu->deviceId = adapterLuid; } uint32_t featureLevel = 0; if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) + { + FF_DEBUG("Found D3D12 feature level: 0x%x", featureLevel); ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); + } else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) + { + FF_DEBUG("Found D3D11 feature level: 0x%x", featureLevel); ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); + } uint64_t driverVersion = 0; if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion) { + FF_DEBUG("Found driver version: %llu", driverVersion); ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u", (unsigned) (driverVersion >> 48) & 0xFFFF, (unsigned) (driverVersion >> 32) & 0xFFFF, @@ -133,21 +192,38 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ); } } + else + { + FF_DEBUG("Failed to open DirectX registry key"); + } + } + else + { + FF_DEBUG("Failed to get VideoID or invalid buffer length"); } } + else + { + FF_DEBUG("Failed to open device node registry key"); + } if (gpu->vendor.length == 0 || gpu->name.length == 0) { + FF_DEBUG("Trying fallback registry method for vendor/name"); bufferLen = sizeof(buffer); if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DRIVER, NULL, buffer, &bufferLen, 0) == CR_SUCCESS && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2) { + FF_DEBUG("Found driver GUID: %ls", buffer); wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000")); FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL; if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDriverKey, &hRegDriverKey, NULL)) { + FF_DEBUG("Opened driver registry key"); + if (gpu->vendor.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL)) { + FF_DEBUG("Found provider name: %s", gpu->vendor.chars); if (ffStrbufContainS(&gpu->vendor, "Intel")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) @@ -155,20 +231,35 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); } - if (gpu->name.length == 0) - ffRegReadStrbuf(hRegDriverKey, L"DriverDesc", &gpu->name, NULL); - if (gpu->driver.length == 0) - ffRegReadStrbuf(hRegDriverKey, L"DriverVersion", &gpu->driver, NULL); + if (gpu->name.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"DriverDesc", &gpu->name, NULL)) + FF_DEBUG("Found driver description: %s", gpu->name.chars); + if (gpu->driver.length == 0 && ffRegReadStrbuf(hRegDriverKey, L"DriverVersion", &gpu->driver, NULL)) + FF_DEBUG("Found driver version: %s", gpu->driver.chars); if (gpu->dedicated.total == FF_GPU_VMEM_SIZE_UNSET) { if (!ffRegReadUint64(hRegDriverKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) { uint32_t memorySize = 0; if (ffRegReadUint(hRegDriverKey, L"HardwareInformation.MemorySize", &memorySize, NULL)) + { gpu->dedicated.total = memorySize; + FF_DEBUG("Found memory size from hardware info: %u bytes", memorySize); + } + } + else + { + FF_DEBUG("Found qwMemorySize from hardware info: %llu bytes", gpu->dedicated.total); } } } + else + { + FF_DEBUG("Failed to open driver registry key"); + } + } + else + { + FF_DEBUG("Failed to get driver GUID or invalid buffer length"); } } @@ -177,6 +268,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (options->driverSpecific && getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName)) { + FF_DEBUG("Calling driver-specific detection function for vendor: %s, DLL: %s", gpu->vendor.chars, dllName); detectFn( &(FFGpuDriverCondition) { .type = (deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID : 0) @@ -210,17 +302,31 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }, dllName ); + FF_DEBUG("Driver-specific detection completed"); + } + else if (options->driverSpecific) + { + FF_DEBUG("No driver-specific detection function found for vendor: %s", gpu->vendor.chars); } if (!gpu->name.length) { + FF_DEBUG("Trying to get device description as fallback"); bufferLen = sizeof(buffer); if (CM_Get_DevNode_Registry_PropertyW(devInst, CM_DRP_DEVICEDESC, NULL, buffer, &bufferLen, 0) == CR_SUCCESS) + { ffStrbufSetWS(&gpu->name, buffer); + FF_DEBUG("Found device description: %s", gpu->name.chars); + } + else + { + FF_DEBUG("Failed to get device description"); + } } if (gpu->type == FF_GPU_TYPE_UNKNOWN && adapterLuid > 0) { + FF_DEBUG("Trying to determine GPU type using D3DKMT APIs"); HMODULE hgdi32 = GetModuleHandleW(L"gdi32.dll"); if (hgdi32) { @@ -230,6 +336,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* D3DKMT_OPENADAPTERFROMLUID openAdapterFromLuid = { .AdapterLuid = *(LUID*)&adapterLuid }; if (NT_SUCCESS(ffD3DKMTOpenAdapterFromLuid(&openAdapterFromLuid))) { + FF_DEBUG("Successfully opened adapter from LUID"); + D3DKMT_ADAPTERTYPE adapterType = {}; D3DKMT_QUERYADAPTERINFO queryAdapterInfo = { .hAdapter = openAdapterFromLuid.hAdapter, @@ -239,14 +347,20 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }; if (NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) // Vista and later { + FF_DEBUG("Queried adapter type - HybridDiscrete: %d, HybridIntegrated: %d", adapterType.HybridDiscrete, adapterType.HybridIntegrated); if (adapterType.HybridDiscrete) gpu->type = FF_GPU_TYPE_DISCRETE; else if (adapterType.HybridIntegrated) gpu->type = FF_GPU_TYPE_INTEGRATED; } + else + { + FF_DEBUG("Failed to query adapter type"); + } if (gpu->frequency == FF_GPU_FREQUENCY_UNSET) { + FF_DEBUG("Trying to get GPU frequency information"); for (ULONG nodeIdx = 0; ; nodeIdx++) { D3DKMT_NODEMETADATA nodeMetadata = { @@ -258,8 +372,16 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* .pPrivateDriverData = &nodeMetadata, .PrivateDriverDataSize = sizeof(nodeMetadata), }; - if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) break; // Windows 10 and later - if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) continue; + if (!NT_SUCCESS(D3DKMTQueryAdapterInfo(&queryAdapterInfo))) + { + FF_DEBUG("No more nodes to query (index %lu)", nodeIdx); + break; // Windows 10 and later + } + if (nodeMetadata.NodeData.EngineType != DXGK_ENGINE_TYPE_3D) + { + FF_DEBUG("Skipping node %lu (not 3D engine)", nodeIdx); + continue; + } D3DKMT_QUERYSTATISTICS queryStatistics = { .Type = D3DKMT_QUERYSTATISTICS_NODE2, @@ -269,18 +391,29 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics))) // Windows 11 (22H2) and later { gpu->frequency = (uint32_t) (queryStatistics.QueryResult.NodeInformation.NodePerfData.MaxFrequency / 1000 / 1000); + FF_DEBUG("Found GPU frequency: %u MHz", gpu->frequency); break; } + else + { + FF_DEBUG("Failed to query node statistics for node %lu", nodeIdx); + } } } D3DKMT_CLOSEADAPTER closeAdapter = { .hAdapter = openAdapterFromLuid.hAdapter }; (void) D3DKMTCloseAdapter(&closeAdapter); openAdapterFromLuid.hAdapter = 0; + FF_DEBUG("Closed adapter handle"); + } + else + { + FF_DEBUG("Failed to open adapter from LUID"); } - if (options->temp && gpu->temperature != gpu->temperature) + if (options->temp && gpu->temperature == FF_GPU_TEMP_UNSET) { + FF_DEBUG("Trying to get GPU temperature"); D3DKMT_QUERYSTATISTICS queryStatistics = { .Type = D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER, .AdapterLuid = *(LUID*)&adapterLuid, @@ -288,20 +421,49 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }; if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)) && queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature != 0) + { gpu->temperature = queryStatistics.QueryResult.PhysAdapterInformation.AdapterPerfData.Temperature / 10.0; + FF_DEBUG("Found GPU temperature: %.1f°C", gpu->temperature); + } + else + { + FF_DEBUG("Failed to get GPU temperature or temperature is 0"); + } } } + else + { + FF_DEBUG("D3DKMTOpenAdapterFromLuid not available"); + } + } + else + { + FF_DEBUG("Failed to get gdi32.dll module handle"); } } if (gpu->type == FF_GPU_TYPE_UNKNOWN) { + FF_DEBUG("Using fallback GPU type detection"); if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) + { gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + FF_DEBUG("Intel GPU type determined: %s", gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete"); + } else if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) + { gpu->type = gpu->dedicated.total >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + FF_DEBUG("GPU type determined by memory size (%llu bytes): %s", gpu->dedicated.total, gpu->type == FF_GPU_TYPE_DISCRETE ? "Discrete" : "Integrated"); + } + else + { + FF_DEBUG("Unable to determine GPU type"); + } } + + FF_DEBUG("Completed processing GPU #%d - Vendor: %s, Name: %s, Type: %d", deviceCount, gpu->vendor.chars, gpu->name.chars, gpu->type); } + FF_DEBUG("GPU detection completed, found %d devices", deviceCount); return NULL; } diff --git a/src/detection/host/host.h b/src/detection/host/host.h index a8aa16b74f..bd76e434e8 100644 --- a/src/detection/host/host.h +++ b/src/detection/host/host.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/host/option.h" typedef struct FFHostResult { diff --git a/src/detection/icons/icons.h b/src/detection/icons/icons.h index f921270c66..4c96304aa1 100644 --- a/src/detection/icons/icons.h +++ b/src/detection/icons/icons.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/icons/option.h" typedef struct FFIconsResult { diff --git a/src/detection/initsystem/initsystem.h b/src/detection/initsystem/initsystem.h index 07f79ff742..7103616bf4 100644 --- a/src/detection/initsystem/initsystem.h +++ b/src/detection/initsystem/initsystem.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/initsystem/option.h" typedef struct FFInitSystemResult { diff --git a/src/detection/lm/lm.h b/src/detection/lm/lm.h index 4cbaf7c13e..1cd8bb3ba0 100644 --- a/src/detection/lm/lm.h +++ b/src/detection/lm/lm.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/lm/option.h" typedef struct FFLMResult { diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index a3fde0f1cc..78609f6908 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/localip/option.h" typedef struct FFLocalIpResult { @@ -20,7 +21,7 @@ typedef struct FFLocalIpNIFlag const char *name; } FFLocalIpNIFlag; -static inline void ffLocalIpFillNIFlags(FFstrbuf *buf, uint32_t flag, const FFLocalIpNIFlag names[]) +static inline void ffLocalIpFillNIFlags(FFstrbuf *buf, uint64_t flag, const FFLocalIpNIFlag names[]) { for (const FFLocalIpNIFlag *nf = names; flag && nf->name; ++nf) { diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index f9cc343d6f..298631927f 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -11,11 +11,18 @@ #include #include #include +#include +#include #ifdef __linux__ #include #include #include +#include +#endif + +#if __has_include() + #include #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__HAIKU__) @@ -27,60 +34,81 @@ #if defined(__sun) || defined(__HAIKU__) #include #endif +#if defined(__sun) +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) +{ + assert(pkc); + if (*pkc) + kstat_close(*pkc); +} +#endif + +#define FF_LOCALIP_NIFLAG(name) { IFF_##name, #name } static const FFLocalIpNIFlag niFlagOptions[] = { - { IFF_UP, "UP" }, - { IFF_BROADCAST, "BROADCAST" }, + FF_LOCALIP_NIFLAG(UP), + FF_LOCALIP_NIFLAG(BROADCAST), #ifdef IFF_DEBUG - { IFF_DEBUG, "DEBUG" }, + FF_LOCALIP_NIFLAG(DEBUG), #endif - { IFF_LOOPBACK, "LOOPBACK" }, - { IFF_POINTOPOINT, "POINTOPOINT" }, + FF_LOCALIP_NIFLAG(LOOPBACK), + FF_LOCALIP_NIFLAG(POINTOPOINT), #ifdef IFF_RUNNING - { IFF_RUNNING, "RUNNING" }, + FF_LOCALIP_NIFLAG(RUNNING), #endif - { IFF_NOARP, "NOARP" }, - { IFF_PROMISC, "PROMISC" }, - { IFF_ALLMULTI, "ALLMULTI" }, - { IFF_MULTICAST, "MULTICAST" }, + FF_LOCALIP_NIFLAG(NOARP), + FF_LOCALIP_NIFLAG(PROMISC), + FF_LOCALIP_NIFLAG(ALLMULTI), +#ifdef IFF_INTELLIGENT + FF_LOCALIP_NIFLAG(INTELLIGENT), +#endif + FF_LOCALIP_NIFLAG(MULTICAST), #ifdef IFF_NOTRAILERS - { IFF_NOTRAILERS, "NOTRAILERS" }, + FF_LOCALIP_NIFLAG(NOTRAILERS), #endif #ifdef __linux__ - { IFF_MASTER, "MASTER" }, - { IFF_SLAVE, "SLAVE" }, - { IFF_PORTSEL, "PORTSEL" }, - { IFF_AUTOMEDIA, "AUTOMEDIA" }, - { IFF_DYNAMIC, "DYNAMIC" }, - { IFF_LOWER_UP, "LOWER_UP" }, - { IFF_DORMANT, "DORMANT" }, - { IFF_ECHO, "ECHO" }, + FF_LOCALIP_NIFLAG(MASTER), + FF_LOCALIP_NIFLAG(SLAVE), + FF_LOCALIP_NIFLAG(PORTSEL), + FF_LOCALIP_NIFLAG(AUTOMEDIA), + FF_LOCALIP_NIFLAG(DYNAMIC), + FF_LOCALIP_NIFLAG(LOWER_UP), + FF_LOCALIP_NIFLAG(DORMANT), + FF_LOCALIP_NIFLAG(ECHO), #endif #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) - { IFF_OACTIVE, "OACTIVE" }, - { IFF_SIMPLEX, "SIMPLEX" }, - { IFF_LINK0, "LINK0" }, - { IFF_LINK1, "LINK1" }, - { IFF_LINK2, "LINK2" }, + FF_LOCALIP_NIFLAG(OACTIVE), + FF_LOCALIP_NIFLAG(SIMPLEX), + FF_LOCALIP_NIFLAG(LINK0), + FF_LOCALIP_NIFLAG(LINK1), + FF_LOCALIP_NIFLAG(LINK2), #endif #ifdef IFF_ALTPHYS - { IFF_ALTPHYS, "ALTPHYS" }, + FF_LOCALIP_NIFLAG(ALTPHYS), #endif #ifdef IFF_CANTCONFIG - { IFF_CANTCONFIG, "CANTCONFIG" }, + FF_LOCALIP_NIFLAG(CANTCONFIG), #endif #ifdef __HAIKU__ - { IFF_AUTOUP, "IAUTOUP" }, - { IFF_SIMPLEX, "SIMPLEX" }, - { IFF_LINK, "LINK" }, - { IFF_AUTO_CONFIGURED, "AUTO_CONFIGURED" }, - { IFF_CONFIGURING, "CONFIGURING" }, + FF_LOCALIP_NIFLAG(AUTOUP), + FF_LOCALIP_NIFLAG(SIMPLEX), + FF_LOCALIP_NIFLAG(LINK), + FF_LOCALIP_NIFLAG(AUTO_CONFIGURED), + FF_LOCALIP_NIFLAG(CONFIGURING), +#endif +#ifdef __sun + FF_LOCALIP_NIFLAG(MULTI_BCAST), + FF_LOCALIP_NIFLAG(UNNUMBERED), + FF_LOCALIP_NIFLAG(DHCPRUNNING), + FF_LOCALIP_NIFLAG(PRIVATE), #endif // sentinel {}, }; -static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, uint32_t flags, bool firstOnly) +static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, uint64_t flags, bool firstOnly) { FFLocalIpResult* ip = NULL; @@ -88,6 +116,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, { if (!ffStrbufEqualS(&temp->name, name)) continue; ip = temp; + if (defaultRoute) ip->defaultRoute = true; break; } if (!ip) @@ -129,34 +158,118 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, } } +static bool isIPv6AddressPreferred(struct ifaddrs* ifa, struct sockaddr_in6* addr) +{ +#ifndef IN6_IS_ADDR_GLOBAL +#define IN6_IS_ADDR_GLOBAL(a) \ + ((((const uint32_t *) (a))[0] & htonl(0x70000000)) == htonl(0x20000000)) +#endif +#ifndef IN6_IS_ADDR_UNIQUE_LOCAL +#define IN6_IS_ADDR_UNIQUE_LOCAL(a) \ + ((((const uint32_t *) (a))[0] & htonl(0xfe000000)) == htonl(0xfc000000)) +#endif + if (!IN6_IS_ADDR_GLOBAL(&addr->sin6_addr) && !IN6_IS_ADDR_UNIQUE_LOCAL(&addr->sin6_addr)) + return false; + +#ifdef SIOCGIFAFLAG_IN6 + static int sockfd = 0; + if (sockfd == 0) + { + sockfd = socket(AF_INET6, SOCK_DGRAM + #ifdef SOCK_CLOEXEC + | SOCK_CLOEXEC + #endif + , 0); + #ifndef SOCK_CLOEXEC + if (sockfd > 0) fcntl(sockfd, F_SETFD, FD_CLOEXEC); + #endif + } + if (sockfd < 0) return true; // Give up + + struct in6_ifreq ifr6 = {}; + ffStrCopy(ifr6.ifr_name, ifa->ifa_name, IFNAMSIZ); + ifr6.ifr_addr = *addr; + + if (ioctl(sockfd, SIOCGIFAFLAG_IN6, &ifr6) != 0) + return true; + #ifdef IN6_IFF_PREFER_SOURCE + if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_PREFER_SOURCE) + return true; + #endif + return !(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY | IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED + #ifdef IN6_IFF_OPTIMISTIC + | IN6_IFF_OPTIMISTIC + #endif + )); +#elif __linux__ + FF_UNUSED(ifa); + + static FFlist addresses = {}; + if (addresses.elementSize == 0) + { + ffListInit(&addresses, sizeof(struct in6_addr)); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (!ffReadFileBuffer("/proc/net/if_inet6", &buffer)) + return true; + + char* line = NULL; + size_t len = 0; + while (ffStrbufGetline(&line, &len, &buffer)) + { + struct in6_addr* entry = (struct in6_addr*) ffListAdd(&addresses); + uint8_t flags; + if (sscanf(line, "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 " %*s %*s %*s %" SCNx8 " %*s", + &entry->s6_addr[0], &entry->s6_addr[1], &entry->s6_addr[2], &entry->s6_addr[3], + &entry->s6_addr[4], &entry->s6_addr[5], &entry->s6_addr[6], &entry->s6_addr[7], + &entry->s6_addr[8], &entry->s6_addr[9], &entry->s6_addr[10], &entry->s6_addr[11], + &entry->s6_addr[12], &entry->s6_addr[13], &entry->s6_addr[14], &entry->s6_addr[15], + &flags) != 17 || + (!IN6_IS_ADDR_GLOBAL(entry) && !IN6_IS_ADDR_UNIQUE_LOCAL(entry)) || + (flags & (IFA_F_DEPRECATED | IFA_F_TEMPORARY | IFA_F_TENTATIVE | IFA_F_DADFAILED | IFA_F_OPTIMISTIC)) + ) + --addresses.length; + } + } + if (addresses.capacity == 0) return true; // Give up + + FF_LIST_FOR_EACH(struct in6_addr, entry, addresses) + { + if (memcmp(&addr->sin6_addr, entry, sizeof(struct in6_addr)) == 0) + return true; + } + return false; +#elif __sun + if (ifa->ifa_flags & IFF_PREFERRED) + return true; + return !(ifa->ifa_flags & (IFF_DEPRECATED | IFF_TEMPORARY | IFF_DUPLICATE)); +#else + return true; +#endif +} + const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) { struct ifaddrs* ifAddrStruct = NULL; if(getifaddrs(&ifAddrStruct) < 0) return "getifaddrs(&ifAddrStruct) failed"; - const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName(); - for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) continue; + #ifdef IFF_RUNNING if (!(ifa->ifa_flags & IFF_RUNNING)) continue; #endif - bool isDefaultRoute = ffStrEquals(defaultRouteIfName, ifa->ifa_name); - if ((options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) && !isDefaultRoute) - continue; - if ((ifa->ifa_flags & IFF_LOOPBACK) && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT)) continue; if (options->namePrefix.length && strncmp(ifa->ifa_name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; - uint32_t flags = options->showType & FF_LOCALIP_TYPE_FLAGS_BIT ? ifa->ifa_flags : 0; + uint64_t flags = options->showType & FF_LOCALIP_TYPE_FLAGS_BIT ? ifa->ifa_flags : 0; if (ifa->ifa_addr->sa_family == AF_INET) { @@ -164,6 +277,22 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) continue; struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr; + + const FFNetifDefaultRouteResult* defaultRoute = ffNetifGetDefaultRouteV4(); + bool isDefaultRouteIf = ffStrEquals(defaultRoute->ifName, ifa->ifa_name); + if (options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) + { + if (!isDefaultRouteIf) + continue; + + if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)) + { + bool isPreferredSourceAddr = defaultRoute->preferredSourceAddrV4 == 0 || ipv4->sin_addr.s_addr == defaultRoute->preferredSourceAddrV4; + if (!isPreferredSourceAddr) + continue; + } + } + char addressBuffer[INET_ADDRSTRLEN + 16]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); @@ -178,14 +307,22 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRouteIf, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } else if (ifa->ifa_addr->sa_family == AF_INET6) { if (!(options->showType & FF_LOCALIP_TYPE_IPV6_BIT)) continue; + const FFNetifDefaultRouteResult* defaultRoute = ffNetifGetDefaultRouteV6(); + bool isDefaultRouteIf = ffStrEquals(defaultRoute->ifName, ifa->ifa_name); + if ((options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) && !isDefaultRouteIf) + continue; + struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr; + if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT) && !isIPv6AddressPreferred(ifa, ipv6)) + continue; + char addressBuffer[INET6_ADDRSTRLEN + 16]; inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN); @@ -203,7 +340,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRouteIf, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } #if __FreeBSD__ || __OpenBSD__ || __APPLE__ || __NetBSD__ || __HAIKU__ else if (ifa->ifa_addr->sa_family == AF_LINK) @@ -215,7 +352,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr); snprintf(addressBuffer, ARRAY_SIZE(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, false, flags, false); } #else else if (ifa->ifa_addr->sa_family == AF_PACKET) @@ -227,7 +364,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr; snprintf(addressBuffer, ARRAY_SIZE(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, false, flags, false); } #endif } @@ -642,6 +779,24 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) ffStrbufSetF(&iface->mac, "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); } + if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT) + { + __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); + for (kstat_t* ks = kc->kc_chain; ks; ks = ks->ks_next) + { + if (!ffStrEquals(ks->ks_class, "net") || !ffStrEquals(ks->ks_module, "link")) continue; + if (ffStrbufEqualS(&iface->name, ks->ks_name)) + { + if (kstat_read(kc, ks, NULL) >= 0) + { + kstat_named_t* ifspeed = (kstat_named_t*) kstat_data_lookup(ks, "ifspeed"); + if (ifspeed) + iface->speed = (int32_t) (ifspeed->value.ui64 / 1000 / 1000); + } + break; + } + } + } #endif } } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 1b067885df..e983330790 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -6,17 +6,19 @@ #include "util/windows/unicode.h" #include "localip.h" +#define FF_LOCALIP_NIFLAG(name) { IP_ADAPTER_##name, #name } + static const FFLocalIpNIFlag niFlagOptions[] = { - { IP_ADAPTER_DDNS_ENABLED, "DDNS_ENABLED" }, - { IP_ADAPTER_REGISTER_ADAPTER_SUFFIX, "REGISTER_ADAPTER_SUFFIX" }, - { IP_ADAPTER_DHCP_ENABLED, "DHCP_ENABLED" }, - { IP_ADAPTER_RECEIVE_ONLY, "RECEIVE_ONLY" }, - { IP_ADAPTER_NO_MULTICAST, "NO_MULTICAST" }, - { IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG, "IPV6_OTHER_STATEFUL_CONFIG" }, - { IP_ADAPTER_NETBIOS_OVER_TCPIP_ENABLED, "NETBIOS_OVER_TCPIP_ENABLED" }, - { IP_ADAPTER_IPV4_ENABLED, "IPV4_ENABLED" }, - { IP_ADAPTER_IPV6_ENABLED, "IPV6_ENABLED" }, - { IP_ADAPTER_IPV6_MANAGE_ADDRESS_CONFIG, "IPV6_MANAGE_ADDRESS_CONFIG" }, + FF_LOCALIP_NIFLAG(DDNS_ENABLED), + FF_LOCALIP_NIFLAG(REGISTER_ADAPTER_SUFFIX), + FF_LOCALIP_NIFLAG(DHCP_ENABLED), + FF_LOCALIP_NIFLAG(RECEIVE_ONLY), + FF_LOCALIP_NIFLAG(NO_MULTICAST), + FF_LOCALIP_NIFLAG(IPV6_OTHER_STATEFUL_CONFIG), + FF_LOCALIP_NIFLAG(NETBIOS_OVER_TCPIP_ENABLED), + FF_LOCALIP_NIFLAG(IPV4_ENABLED), + FF_LOCALIP_NIFLAG(IPV6_ENABLED), + FF_LOCALIP_NIFLAG(IPV6_MANAGE_ADDRESS_CONFIG), // sentinel {}, }; @@ -90,7 +92,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) return "GetAdaptersAddresses() failed"; } - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteV4()->ifIndex; // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) @@ -127,6 +129,9 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) for (IP_ADAPTER_UNICAST_ADDRESS* ifa = adapter->FirstUnicastAddress; ifa; ifa = ifa->Next) { + if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT) && ifa->DadState != IpDadStatePreferred) + continue; + if (ifa->Address.lpSockaddr->sa_family == AF_INET) { if (!(typesToAdd & (FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_ALL_IPS_BIT))) continue; diff --git a/src/detection/media/media.h b/src/detection/media/media.h index 5c97da471d..598bbf55a5 100644 --- a/src/detection/media/media.h +++ b/src/detection/media/media.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/media/option.h" typedef struct FFMediaResult { diff --git a/src/detection/memory/memory.h b/src/detection/memory/memory.h index 8929883e81..71a9ea9a44 100644 --- a/src/detection/memory/memory.h +++ b/src/detection/memory/memory.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/memory/option.h" typedef struct FFMemoryResult { diff --git a/src/detection/netio/netio.h b/src/detection/netio/netio.h index de633a1072..47328b4326 100644 --- a/src/detection/netio/netio.h +++ b/src/detection/netio/netio.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/netio/option.h" typedef struct FFNetIOResult { diff --git a/src/detection/netio/netio_apple.c b/src/detection/netio/netio_apple.c index cd51060263..69f2667c96 100644 --- a/src/detection/netio/netio_apple.c +++ b/src/detection/netio/netio_apple.c @@ -11,7 +11,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { int mib[] = {CTL_NET, PF_LINK, NETLINK_GENERIC, options->defaultRouteOnly ? IFMIB_IFDATA : IFMIB_IFALLDATA, - options->defaultRouteOnly ? (int) ffNetifGetDefaultRouteIfIndex() : 0, + options->defaultRouteOnly ? (int) ffNetifGetDefaultRouteV4()->ifIndex : 0, IFDATA_GENERAL}; size_t bufSize = 0; @@ -26,7 +26,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) size_t ifCount = bufSize / sizeof(struct ifmibdata); - const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName(); + const char* defaultRouteIfName = ffNetifGetDefaultRouteV4()->ifName; for (size_t i = 0; i < ifCount; i++) { diff --git a/src/detection/netio/netio_bsd.c b/src/detection/netio/netio_bsd.c index 9044600e58..dcf9b709d9 100644 --- a/src/detection/netio/netio_bsd.c +++ b/src/detection/netio/netio_bsd.c @@ -12,7 +12,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteV4()->ifIndex; size_t bufSize = 0; if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, NULL, &bufSize, 0, 0) < 0) diff --git a/src/detection/netio/netio_haiku.cpp b/src/detection/netio/netio_haiku.cpp index e0c62ebf21..812d926f41 100644 --- a/src/detection/netio/netio_haiku.cpp +++ b/src/detection/netio/netio_haiku.cpp @@ -13,7 +13,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) BNetworkInterface interface; uint32 cookie = 0; - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteV4()->ifIndex; while (roster.GetNextInterface(&cookie, interface) == B_OK) { diff --git a/src/detection/netio/netio_linux.c b/src/detection/netio/netio_linux.c index 2a28c10eb4..651a612fa1 100644 --- a/src/detection/netio/netio_linux.c +++ b/src/detection/netio/netio_linux.c @@ -53,7 +53,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName(); + const char* defaultRouteIfName = ffNetifGetDefaultRouteV4()->ifName; if (options->defaultRouteOnly) { diff --git a/src/detection/netio/netio_sunos.c b/src/detection/netio/netio_sunos.c index e87222e830..e946d6d7e3 100644 --- a/src/detection/netio/netio_sunos.c +++ b/src/detection/netio/netio_sunos.c @@ -16,7 +16,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) if (!kc) return "kstat_open() failed"; - const char* defaultRoute = ffNetifGetDefaultRouteIfName(); + const char* defaultRouteIfName = ffNetifGetDefaultRouteV4()->ifName; for (kstat_t* ks = kc->kc_chain; ks; ks = ks->ks_next) { @@ -25,7 +25,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) if (options->namePrefix.length && strncmp(ks->ks_name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; - bool isDefaultRoute = ffStrEquals(ks->ks_name, defaultRoute); + bool isDefaultRoute = ffStrEquals(ks->ks_name, defaultRouteIfName); if (options->defaultRouteOnly && !isDefaultRoute) continue; diff --git a/src/detection/netio/netio_windows.c b/src/detection/netio/netio_windows.c index 1d3ab8fbe7..56e5fc06d4 100644 --- a/src/detection/netio/netio_windows.c +++ b/src/detection/netio/netio_windows.c @@ -37,7 +37,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) return "GetAdaptersAddresses() failed"; } - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteV4()->ifIndex; // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) diff --git a/src/detection/opencl/opencl.h b/src/detection/opencl/opencl.h index a8b0063e4d..c7d6ddb961 100644 --- a/src/detection/opencl/opencl.h +++ b/src/detection/opencl/opencl.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/opencl/option.h" typedef struct FFOpenCLResult { diff --git a/src/detection/opengl/opengl.h b/src/detection/opengl/opengl.h index 466dcf2565..5dbf2e3925 100644 --- a/src/detection/opengl/opengl.h +++ b/src/detection/opengl/opengl.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/opengl/option.h" typedef struct FFOpenGLResult { diff --git a/src/detection/os/os.h b/src/detection/os/os.h index e1b7828fec..09226b9c24 100644 --- a/src/detection/os/os.h +++ b/src/detection/os/os.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/os/option.h" typedef struct FFOSResult { diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 0774b9816b..9b5ef3690f 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -89,6 +89,21 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result) ffStrbufSetStatic(&result->idLike, "ubuntu"); } + if (ffPathExists("/usr/bin/lliurex-version", FF_PATHTYPE_FILE)) + { + ffStrbufSetStatic(&result->name, "LliureX"); + ffStrbufSetStatic(&result->id, "lliurex"); + ffStrbufClear(&result->version); + if (ffProcessAppendStdOut(&result->version, (char* const[]) { + "/usr/bin/lliurex-version", + NULL, + }) == NULL) // 8.2.2 + ffStrbufTrimRightSpace(&result->version); + ffStrbufSetF(&result->prettyName, "LliureX %s", result->version.chars); + ffStrbufSetStatic(&result->idLike, "ubuntu"); + return; + } + if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu")) { ffStrbufSetStatic(&result->name, "Kubuntu"); @@ -169,15 +184,6 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result) ffStrbufSetStatic(&result->idLike, "ubuntu"); return; } - - if(ffStrContains(xdgConfigDirs, "lliurex")) - { - ffStrbufSetStatic(&result->name, "LliureX"); - ffStrbufSetF(&result->prettyName, "LliureX %s", result->version.chars); - ffStrbufSetStatic(&result->id, "lliurex"); - ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; - } } FF_MAYBE_UNUSED static void getDebianVersion(FFOSResult* result) @@ -306,16 +312,10 @@ FF_MAYBE_UNUSED static bool detectFedoraVariant(FFOSResult* result) return false; } -static void detectOS(FFOSResult* os) +static bool detectBedrock(FFOSResult* os) { - #ifdef FF_CUSTOM_OS_RELEASE_PATH - parseOsRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os); - #ifdef FF_CUSTOM_LSB_RELEASE_PATH - parseLsbRelease(FF_STR(FF_CUSTOM_LSB_RELEASE_PATH), os); - #endif - return; - #endif - + const char* bedrockRestrict = getenv("BEDROCK_RESTRICT"); + if(bedrockRestrict && bedrockRestrict[0] == '1') return false; if(parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os)) { if(os->id.length == 0) @@ -328,8 +328,23 @@ static void detectOS(FFOSResult* os) ffStrbufAppendS(&os->prettyName, "Bedrock Linux"); parseOsRelease("/bedrock" FASTFETCH_TARGET_DIR_ETC "/os-release", os); - return; + return true; } + return false; +} + +static void detectOS(FFOSResult* os) +{ + #ifdef FF_CUSTOM_OS_RELEASE_PATH + parseOsRelease(FF_STR(FF_CUSTOM_OS_RELEASE_PATH), os); + #ifdef FF_CUSTOM_LSB_RELEASE_PATH + parseLsbRelease(FF_STR(FF_CUSTOM_LSB_RELEASE_PATH), os); + #endif + return; + #endif + + if (detectBedrock(os)) + return; // Refer: https://gist.github.com/natefoo/814c5bf936922dad97ff diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index e96b0762c5..c71711dcc3 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/packages/option.h" typedef struct FFPackagesResult { @@ -54,6 +55,9 @@ const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* option bool ffPackagesReadCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, const char* filePath, const char* packageId, uint32_t* result); bool ffPackagesWriteCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, uint32_t num_elements); +#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__APPLE__) +uint32_t ffPackagesGetNix(FFstrbuf* baseDir, const char* dirname); +#endif #ifndef _WIN32 uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir); #endif diff --git a/src/detection/packages/packages_apple.c b/src/detection/packages/packages_apple.c index 8391a0f56e..5a176c834d 100644 --- a/src/detection/packages/packages_apple.c +++ b/src/detection/packages/packages_apple.c @@ -4,91 +4,66 @@ #include "common/processing.h" #include "util/stringUtils.h" -static void countBrewPackages(const char* dirname, FFPackagesResult* result) +static void countBrewPackages(FFstrbuf* baseDir, FFPackagesResult* result) { - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname); - uint32_t baseDirLength = baseDir.length; - - ffStrbufAppendS(&baseDir, "/Caskroom"); - result->brewCask += ffPackagesGetNumElements(baseDir.chars, true); - ffStrbufSubstrBefore(&baseDir, baseDirLength); - - ffStrbufAppendS(&baseDir, "/Cellar"); - result->brew += ffPackagesGetNumElements(baseDir.chars, true); - ffStrbufSubstrBefore(&baseDir, baseDirLength); -} - -static void getBrewPackages(FFPackagesResult* result) -{ - const char* prefix = getenv("HOMEBREW_PREFIX"); - if(ffStrSet(prefix)) - return countBrewPackages(prefix, result); - - countBrewPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/homebrew", result); - countBrewPackages(FASTFETCH_TARGET_DIR_USR "/local", result); -} - -static uint32_t countMacPortsPackages(const char* dirname) -{ - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(dirname); - ffStrbufAppendS(&baseDir, "/var/macports/software"); - - return ffPackagesGetNumElements(baseDir.chars, true); -} - -static uint32_t getMacPortsPackages() -{ - const char* prefix = getenv("MACPORTS_PREFIX"); - if(ffStrSet(prefix)) - return countMacPortsPackages(prefix); - - return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/local"); -} - -static uint32_t getNixPackagesImpl(const char* path) -{ - //Nix detection is kinda slow, so we only do it if the dir exists - if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY)) - return 0; - - FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(128); - - //https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222 - FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(255); - ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites "); - ffStrbufAppendS(&command, path); - ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq | wc -l"); + uint32_t baseDirLength = baseDir->length; - ffProcessAppendStdOut(&output, (char* const[]) { - FASTFETCH_TARGET_DIR_ROOT "/bin/sh", - "-c", - command.chars, - NULL - }); + ffStrbufAppendS(baseDir, "/Caskroom"); + result->brewCask += ffPackagesGetNumElements(baseDir->chars, true); + ffStrbufSubstrBefore(baseDir, baseDirLength); - return (uint32_t) strtoul(output.chars, NULL, 10); + ffStrbufAppendS(baseDir, "/Cellar"); + result->brew += ffPackagesGetNumElements(baseDir->chars, true); + ffStrbufSubstrBefore(baseDir, baseDirLength); } -static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname) +static uint32_t getMacPortsPackages(FFstrbuf* baseDir) { - uint32_t baseDirLength = baseDir->length; - ffStrbufAppendS(baseDir, dirname); - uint32_t num_elements = getNixPackagesImpl(baseDir->chars); - ffStrbufSubstrBefore(baseDir, baseDirLength); - return num_elements; + ffStrbufAppendS(baseDir, "/var/macports/software"); + return ffPackagesGetNumElements(baseDir->chars, true); } void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) { - if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT)) getBrewPackages(result); - if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT)) result->macports = getMacPortsPackages(); + FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreate(); + if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT)) + { + const char* prefix = getenv("HOMEBREW_PREFIX"); + if (ffStrSet(prefix)) + { + ffStrbufSetS(&baseDir, prefix); + } + else + { + #ifdef __aarch64__ + ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/opt/homebrew"); + #else + ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_USR "/local"); + #endif + } + countBrewPackages(&baseDir, result); + } + if (!(options->disabled & FF_PACKAGES_FLAG_MACPORTS_BIT)) + { + const char* prefix = getenv("MACPORTS_PREFIX"); + if (ffStrSet(prefix)) + { + ffStrbufSetS(&baseDir, prefix); + } + else + { + ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT "/opt/local"); + } + + result->macports = getMacPortsPackages(&baseDir); + } if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT); - result->nixDefault += getNixPackages(&baseDir, "/nix/var/nix/profiles/default"); - result->nixSystem += getNixPackages(&baseDir, "/run/current-system"); + ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT); + result->nixDefault += ffPackagesGetNix(&baseDir, "/nix/var/nix/profiles/default"); + result->nixSystem += ffPackagesGetNix(&baseDir, "/run/current-system"); ffStrbufSet(&baseDir, &instance.state.platform.homeDir); - result->nixUser = getNixPackages(&baseDir, "/.nix-profile"); + result->nixUser = ffPackagesGetNix(&baseDir, "/.nix-profile"); } } diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 9fdb294850..2fb000300b 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -1,7 +1,6 @@ #include "packages.h" #include "common/io/io.h" #include "common/parsing.h" -#include "common/processing.h" #include "common/properties.h" #include "common/settings.h" #include "detection/os/os.h" @@ -124,157 +123,6 @@ static uint32_t countFilesRecursive(FFstrbuf* baseDir, const char* dirname, cons return sum; } -static bool isValidNixPkg(FFstrbuf* pkg) -{ - if (!ffPathExists(pkg->chars, FF_PATHTYPE_DIRECTORY)) - return false; - - ffStrbufSubstrAfterLastC(pkg, '/'); - if ( - ffStrbufStartsWithS(pkg, "nixos-system-nixos-") || - ffStrbufEndsWithS(pkg, "-doc") || - ffStrbufEndsWithS(pkg, "-man") || - ffStrbufEndsWithS(pkg, "-info") || - ffStrbufEndsWithS(pkg, "-dev") || - ffStrbufEndsWithS(pkg, "-bin") - ) return false; - - enum { START, DIGIT, DOT, MATCH } state = START; - - for (uint32_t i = 0; i < pkg->length; i++) - { - char c = pkg->chars[i]; - switch (state) - { - case START: - if (ffCharIsDigit(c)) - state = DIGIT; - break; - case DIGIT: - if (ffCharIsDigit(c)) - continue; - if (c == '.') - state = DOT; - else - state = START; - break; - case DOT: - if (ffCharIsDigit(c)) - state = MATCH; - else - state = START; - break; - case MATCH: - break; - } - } - - return state == MATCH; -} - -static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count) -{ - if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE)) - return false; - - FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreate(); - if (!ffReadFileBuffer(cacheDir->chars, &cacheContent)) - return false; - - // Format: \n - uint32_t split = ffStrbufFirstIndexC(&cacheContent, '\n'); - if (split == cacheContent.length) - return false; - - ffStrbufSetNS(hash, split, cacheContent.chars); - *count = (uint32_t)atoi(cacheContent.chars + split + 1); - - return true; -} - -static bool writeNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t count) -{ - FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreateCopy(hash); - ffStrbufAppendF(&cacheContent, "\n%u", count); - return ffWriteFileBuffer(cacheDir->chars, &cacheContent); -} - -static uint32_t getNixPackagesImpl(char* path) -{ - //Nix detection is kinda slow, so we only do it if the dir exists - if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY)) - return 0; - - FF_STRBUF_AUTO_DESTROY cacheDir = ffStrbufCreateCopy(&instance.state.platform.cacheDir); - ffStrbufEnsureEndsWithC(&cacheDir, '/'); - ffStrbufAppendS(&cacheDir, "fastfetch/packages/nix"); - ffStrbufAppendS(&cacheDir, path); - - //Check the hash first to determine if we need to recompute the count - FF_STRBUF_AUTO_DESTROY hash = ffStrbufCreateA(64); - FF_STRBUF_AUTO_DESTROY cacheHash = ffStrbufCreateA(64); - uint32_t count = 0; - - ffProcessAppendStdOut(&hash, (char* const[]) { - "nix-store", - "--query", - "--hash", - path, - NULL - }); - - if (checkNixCache(&cacheDir, &cacheHash, &count) && ffStrbufEqual(&hash, &cacheHash)) - return count; - - //Cache is invalid, recompute the count - count = 0; - - //Implementation based on bash script from here: - //https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222 - - FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024); - - ffProcessAppendStdOut(&output, (char* const[]) { - "nix-store", - "--query", - "--requisites", - path, - NULL - }); - - uint32_t lineLength = 0; - for (uint32_t i = 0; i < output.length; i++) - { - if (output.chars[i] != '\n') - { - lineLength++; - continue; - } - - output.chars[i] = '\0'; - FFstrbuf line = { - .allocated = 0, - .length = lineLength, - .chars = output.chars + i - lineLength - }; - if (isValidNixPkg(&line)) - count++; - lineLength = 0; - } - - writeNixCache(&cacheDir, &hash, count); - return count; -} - -static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname) -{ - uint32_t baseDirLength = baseDir->length; - ffStrbufAppendS(baseDir, dirname); - uint32_t num_elements = getNixPackagesImpl(baseDir->chars); - ffStrbufSubstrBefore(baseDir, baseDirLength); - return num_elements; -} - static uint32_t getXBPSImpl(FFstrbuf* baseDir) { DIR* dir = opendir(baseDir->chars); @@ -572,8 +420,8 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpakPackages(baseDir, "/var/lib"); if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { - packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default"); - packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system"); + packageCounts->nixDefault += ffPackagesGetNix(baseDir, "/nix/var/nix/profiles/default"); + packageCounts->nixSystem += ffPackagesGetNix(baseDir, "/run/current-system"); } if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", true); if (!(options->disabled & FF_PACKAGES_FLAG_LPKGBUILD_BIT)) packageCounts->lpkgbuild += getNumElements(baseDir, "/opt/Loc-OS-LPKG/lpkgbuild/remove", false); @@ -673,7 +521,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { // Count packages from $HOME/.nix-profile - result->nixUser += getNixPackages(&baseDir, ".nix-profile"); + result->nixUser += ffPackagesGetNix(&baseDir, ".nix-profile"); // Check in $XDG_STATE_HOME/nix/profile FF_STRBUF_AUTO_DESTROY stateHome = ffStrbufCreate(); @@ -688,11 +536,11 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) ffStrbufSet(&stateHome, &instance.state.platform.homeDir); ffStrbufAppendS(&stateHome, ".local/state/"); } - result->nixUser += getNixPackages(&stateHome, "nix/profile"); + result->nixUser += ffPackagesGetNix(&stateHome, "nix/profile"); // Check in /etc/profiles/per-user/$USER FF_STRBUF_AUTO_DESTROY userPkgsDir = ffStrbufCreateStatic("/etc/profiles/per-user/"); - result->nixUser += getNixPackages(&userPkgsDir, instance.state.platform.userName.chars); + result->nixUser += ffPackagesGetNix(&userPkgsDir, instance.state.platform.userName.chars); } if (!(options->disabled & FF_PACKAGES_FLAG_GUIX_BIT)) diff --git a/src/detection/packages/packages_nix.c b/src/detection/packages/packages_nix.c new file mode 100644 index 0000000000..08a5479a6b --- /dev/null +++ b/src/detection/packages/packages_nix.c @@ -0,0 +1,155 @@ +#include "packages.h" +#include "common/io/io.h" +#include "common/processing.h" +#include "util/stringUtils.h" + +static bool isValidNixPkg(FFstrbuf* pkg) +{ + if (!ffPathExists(pkg->chars, FF_PATHTYPE_DIRECTORY)) + return false; + + ffStrbufSubstrAfterLastC(pkg, '/'); + if ( + ffStrbufStartsWithS(pkg, "nixos-system-nixos-") || + ffStrbufEndsWithS(pkg, "-doc") || + ffStrbufEndsWithS(pkg, "-man") || + ffStrbufEndsWithS(pkg, "-info") || + ffStrbufEndsWithS(pkg, "-dev") || + ffStrbufEndsWithS(pkg, "-bin") + ) return false; + + enum { START, DIGIT, DOT, MATCH } state = START; + + for (uint32_t i = 0; i < pkg->length; i++) + { + char c = pkg->chars[i]; + switch (state) + { + case START: + if (ffCharIsDigit(c)) + state = DIGIT; + break; + case DIGIT: + if (ffCharIsDigit(c)) + continue; + if (c == '.') + state = DOT; + else + state = START; + break; + case DOT: + if (ffCharIsDigit(c)) + state = MATCH; + else + state = START; + break; + case MATCH: + break; + } + } + + return state == MATCH; +} + +static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count) +{ + if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE)) + return false; + + FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreate(); + if (!ffReadFileBuffer(cacheDir->chars, &cacheContent)) + return false; + + // Format: \n + uint32_t split = ffStrbufFirstIndexC(&cacheContent, '\n'); + if (split == cacheContent.length) + return false; + + ffStrbufSetNS(hash, split, cacheContent.chars); + *count = (uint32_t)atoi(cacheContent.chars + split + 1); + + return true; +} + +static bool writeNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t count) +{ + FF_STRBUF_AUTO_DESTROY cacheContent = ffStrbufCreateCopy(hash); + ffStrbufAppendF(&cacheContent, "\n%u", count); + return ffWriteFileBuffer(cacheDir->chars, &cacheContent); +} + +static uint32_t getNixPackagesImpl(char* path) +{ + //Nix detection is kinda slow, so we only do it if the dir exists + if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY)) + return 0; + + FF_STRBUF_AUTO_DESTROY cacheDir = ffStrbufCreateCopy(&instance.state.platform.cacheDir); + ffStrbufEnsureEndsWithC(&cacheDir, '/'); + ffStrbufAppendS(&cacheDir, "fastfetch/packages/nix"); + ffStrbufAppendS(&cacheDir, path); + + //Check the hash first to determine if we need to recompute the count + FF_STRBUF_AUTO_DESTROY hash = ffStrbufCreateA(64); + FF_STRBUF_AUTO_DESTROY cacheHash = ffStrbufCreateA(64); + uint32_t count = 0; + + ffProcessAppendStdOut(&hash, (char* const[]) { + "nix-store", + "--query", + "--hash", + path, + NULL + }); + + if (checkNixCache(&cacheDir, &cacheHash, &count) && ffStrbufEqual(&hash, &cacheHash)) + return count; + + //Cache is invalid, recompute the count + count = 0; + + //Implementation based on bash script from here: + //https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222 + + FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024); + + ffProcessAppendStdOut(&output, (char* const[]) { + "nix-store", + "--query", + "--requisites", + path, + NULL + }); + + uint32_t lineLength = 0; + for (uint32_t i = 0; i < output.length; i++) + { + if (output.chars[i] != '\n') + { + lineLength++; + continue; + } + + output.chars[i] = '\0'; + FFstrbuf line = { + .allocated = 0, + .length = lineLength, + .chars = output.chars + i - lineLength + }; + if (isValidNixPkg(&line)) + count++; + lineLength = 0; + } + + writeNixCache(&cacheDir, &hash, count); + return count; +} + +uint32_t ffPackagesGetNix(FFstrbuf* baseDir, const char* dirname) +{ + uint32_t baseDirLength = baseDir->length; + ffStrbufAppendS(baseDir, dirname); + uint32_t num_elements = getNixPackagesImpl(baseDir->chars); + ffStrbufSubstrBefore(baseDir, baseDirLength); + return num_elements; +} diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index f4a497dd45..019b7629d1 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -59,7 +59,7 @@ static void detectScoop(FFPackagesResult* result) { ffStrbufClear(&scoopPath); if (root) - ffStrbufSetS(&scoopPath, yyjson_get_str(yyjson_obj_get(root, "root_path"))); + ffStrbufSetJsonVal(&scoopPath, yyjson_obj_get(root, "root_path")); if (scoopPath.length == 0) { ffStrbufSet(&scoopPath, &instance.state.platform.homeDir); @@ -72,7 +72,7 @@ static void detectScoop(FFPackagesResult* result) { ffStrbufClear(&scoopPath); if (root) - ffStrbufSetS(&scoopPath, yyjson_get_str(yyjson_obj_get(root, "global_path"))); + ffStrbufSetJsonVal(&scoopPath, yyjson_obj_get(root, "global_path")); if (scoopPath.length == 0) { ffStrbufSetS(&scoopPath, getenv("ProgramData")); diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index fbed2f52c3..d0b84d37e4 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -1,6 +1,7 @@ #include "fastfetch.h" +#include "modules/physicaldisk/option.h" -#define FF_PHYSICALDISK_TEMP_UNSET (0/0.0) +#define FF_PHYSICALDISK_TEMP_UNSET (-DBL_MAX) typedef enum __attribute__((__packed__)) FFPhysicalDiskType { diff --git a/src/detection/physicalmemory/physicalmemory.h b/src/detection/physicalmemory/physicalmemory.h index 2580295caa..74ca377679 100644 --- a/src/detection/physicalmemory/physicalmemory.h +++ b/src/detection/physicalmemory/physicalmemory.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/physicalmemory/option.h" typedef struct FFPhysicalMemoryResult { diff --git a/src/detection/poweradapter/poweradapter.h b/src/detection/poweradapter/poweradapter.h index 43c3a48e92..64c0eb5ec8 100644 --- a/src/detection/poweradapter/poweradapter.h +++ b/src/detection/poweradapter/poweradapter.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/poweradapter/option.h" typedef struct FFPowerAdapterResult { diff --git a/src/detection/poweradapter/poweradapter_linux.c b/src/detection/poweradapter/poweradapter_linux.c index 2dd03e73c4..0aba7e4dd9 100644 --- a/src/detection/poweradapter/poweradapter_linux.c +++ b/src/detection/poweradapter/poweradapter_linux.c @@ -31,13 +31,13 @@ static void parsePowerAdapter(int dfd, FF_MAYBE_UNUSED const char* id, FFlist* r return; //input_power_limit must exist and be not empty - if (!ffReadFileBufferRelative(dfd, "input_power_limit", &tmpBuffer)) + if (!ffReadFileBufferRelative(dfd, "input_power_limit", &tmpBuffer) || tmpBuffer.length == 0) return; FFPowerAdapterResult* result = ffListAdd(results); ffStrbufInit(&result->name); ffStrbufInit(&result->description); - result->watts = (int) (ffStrbufToDouble(&tmpBuffer) / 1e6 + 0.5); + result->watts = (int) (ffStrbufToDouble(&tmpBuffer, 0) / 1e6 + 0.5); ffStrbufInit(&result->manufacturer); ffStrbufInit(&result->modelName); ffStrbufInit(&result->serial); diff --git a/src/detection/publicip/publicip.c b/src/detection/publicip/publicip.c index a568f5d707..7fed00cc29 100644 --- a/src/detection/publicip/publicip.c +++ b/src/detection/publicip/publicip.c @@ -5,7 +5,7 @@ static FFNetworkingState states[2]; static const char* statuses[2] = { FF_UNITIALIZED, FF_UNITIALIZED }; -void ffPreparePublicIp(FFPublicIpOptions* options) +void ffPreparePublicIp(FFPublicIPOptions* options) { FFNetworkingState* state = &states[options->ipv6]; const char** status = &statuses[options->ipv6]; @@ -58,7 +58,7 @@ static inline void wrapYyjsonFree(yyjson_doc** doc) yyjson_doc_free(*doc); } -const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result) +const char* ffDetectPublicIp(FFPublicIPOptions* options, FFPublicIpResult* result) { FFNetworkingState* state = &states[options->ipv6]; const char** status = &statuses[options->ipv6]; @@ -84,7 +84,7 @@ const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* resul if (doc) { yyjson_val* root = yyjson_doc_get_root(doc); - ffStrbufAppendS(&result->ip, yyjson_get_str(yyjson_obj_get(root, "ip"))); + ffStrbufAppendJsonVal(&result->ip, yyjson_obj_get(root, "ip")); ffStrbufDestroy(&result->location); ffStrbufInitF(&result->location, "%s, %s", yyjson_get_str(yyjson_obj_get(root, "city")), yyjson_get_str(yyjson_obj_get(root, "country"))); return NULL; diff --git a/src/detection/publicip/publicip.h b/src/detection/publicip/publicip.h index 4635147627..917e787ab3 100644 --- a/src/detection/publicip/publicip.h +++ b/src/detection/publicip/publicip.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/publicip/option.h" typedef struct FFPublicIpResult { @@ -8,5 +9,5 @@ typedef struct FFPublicIpResult FFstrbuf location; } FFPublicIpResult; -void ffPreparePublicIp(FFPublicIpOptions* options); -const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result); +void ffPreparePublicIp(FFPublicIPOptions* options); +const char* ffDetectPublicIp(FFPublicIPOptions* options, FFPublicIpResult* result); diff --git a/src/detection/swap/swap.h b/src/detection/swap/swap.h index 227b4968e4..c89940c122 100644 --- a/src/detection/swap/swap.h +++ b/src/detection/swap/swap.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/swap/option.h" typedef struct FFSwapResult { diff --git a/src/detection/terminalfont/terminalfont.h b/src/detection/terminalfont/terminalfont.h index 0cb33b71d1..03ddad99ef 100644 --- a/src/detection/terminalfont/terminalfont.h +++ b/src/detection/terminalfont/terminalfont.h @@ -2,6 +2,7 @@ #include "fastfetch.h" #include "common/font.h" +#include "modules/font/option.h" typedef struct FFTerminalFontResult { diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index 3aebf79dcf..8c541603e3 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -23,16 +23,14 @@ static const char* detectWTProfile(yyjson_val* profile, FFstrbuf* name, double* if (name->length == 0) { - yyjson_val* pface = yyjson_obj_get(font, "face"); - if(yyjson_is_str(pface)) - ffStrbufAppendS(name, unsafe_yyjson_get_str(pface)); + ffStrbufAppendJsonVal(name, yyjson_obj_get(font, "face")); } if (*size < 0) { yyjson_val* psize = yyjson_obj_get(font, "size"); if (yyjson_is_num(psize)) - *size = yyjson_get_num(psize); + *size = unsafe_yyjson_get_num(psize); } return NULL; } @@ -46,7 +44,7 @@ static inline void wrapYyjsonFree(yyjson_doc** doc) static const char* detectFromWTImpl(FFstrbuf* content, FFstrbuf* name, double* size) { - yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(content->chars, content->length, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, NULL); + yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(content->chars, content->length, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS, NULL, NULL); if (!doc) return "Failed to parse WT JSON config file"; diff --git a/src/detection/terminalshell/terminalshell.h b/src/detection/terminalshell/terminalshell.h index cebc4647d7..a2a6f23f87 100644 --- a/src/detection/terminalshell/terminalshell.h +++ b/src/detection/terminalshell/terminalshell.h @@ -1,6 +1,8 @@ #pragma once #include "fastfetch.h" +#include "modules/terminal/option.h" +#include "modules/shell/option.h" typedef struct FFShellResult { diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 3414d148f5..adda26c038 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -53,7 +53,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) ffStrbufContainS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend ffStrbufEqualS(&result->processName, "clifm") || //https://github.com/leo-arch/clifm/issues/289 ffStrbufEqualS(&result->processName, "valgrind") || - ffStrbufEqualS(&result->processName, "fastfetch") || //994 + ffStrbufEqualS(&result->processName, "fastfetch") || //#994 ffStrbufEqualS(&result->processName, "flashfetch") || ffStrbufEqualS(&result->processName, "proot") || ffStrbufEqualS(&result->processName, "script") || diff --git a/src/detection/terminalsize/terminalsize.h b/src/detection/terminalsize/terminalsize.h index f8b116d73e..e178f34b90 100644 --- a/src/detection/terminalsize/terminalsize.h +++ b/src/detection/terminalsize/terminalsize.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/terminalsize/option.h" typedef struct FFTerminalSizeResult { diff --git a/src/detection/terminaltheme/terminaltheme.h b/src/detection/terminaltheme/terminaltheme.h index 9f54c7f227..a3077823bd 100644 --- a/src/detection/terminaltheme/terminaltheme.h +++ b/src/detection/terminaltheme/terminaltheme.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/terminaltheme/option.h" typedef struct FFTerminalThemeColor { diff --git a/src/detection/theme/theme.h b/src/detection/theme/theme.h index aa70f05ba2..afd3400c60 100644 --- a/src/detection/theme/theme.h +++ b/src/detection/theme/theme.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/theme/option.h" typedef struct FFThemeResult { diff --git a/src/detection/tpm/tpm.h b/src/detection/tpm/tpm.h index 2310a23bfe..5b5aa4e43a 100644 --- a/src/detection/tpm/tpm.h +++ b/src/detection/tpm/tpm.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/tpm/option.h" typedef struct FFTPMResult { diff --git a/src/detection/uptime/uptime.h b/src/detection/uptime/uptime.h index 6f0696d39a..f6426bc596 100644 --- a/src/detection/uptime/uptime.h +++ b/src/detection/uptime/uptime.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/uptime/option.h" typedef struct FFUptimeResult { diff --git a/src/detection/users/users.h b/src/detection/users/users.h index e29a1858d7..baa3775c69 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/users/option.h" typedef struct FFUserResult { diff --git a/src/detection/version/version.h b/src/detection/version/version.h index 272e87bc3e..e97099aac2 100644 --- a/src/detection/version/version.h +++ b/src/detection/version/version.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/version/option.h" typedef struct FFVersionResult { diff --git a/src/detection/vulkan/vulkan.h b/src/detection/vulkan/vulkan.h index 5b6d7832e1..75a5b8de75 100644 --- a/src/detection/vulkan/vulkan.h +++ b/src/detection/vulkan/vulkan.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/vulkan/option.h" typedef struct FFVulkanResult { diff --git a/src/detection/weather/weather.h b/src/detection/weather/weather.h index 24dde33bba..bd3d1bc088 100644 --- a/src/detection/weather/weather.h +++ b/src/detection/weather/weather.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/weather/option.h" void ffPrepareWeather(FFWeatherOptions* options); const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result); diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index f941869a05..a7a99f4e4a 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/wifi/option.h" struct FFWifiInterface { diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index 2c0360cbae..e74a96b370 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -40,13 +40,13 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; - ffStrbufAppendS(&item->inf.status, yyjson_get_str(yyjson_obj_get(root, "supplicant_state"))); + ffStrbufAppendJsonVal(&item->inf.status, yyjson_obj_get(root, "supplicant_state")); if(!item->inf.status.length) { ffStrbufAppendS(&item->inf.status, "Unknown"); @@ -59,9 +59,9 @@ const char* ffDetectWifi(FFlist* result) double rssi = yyjson_get_num(yyjson_obj_get(root, "rssi")); item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2; - ffStrbufAppendS(&item->inf.description, yyjson_get_str(yyjson_obj_get(root, "ip"))); - ffStrbufAppendS(&item->conn.bssid, yyjson_get_str(yyjson_obj_get(root, "bssid"))); - ffStrbufAppendS(&item->conn.ssid, yyjson_get_str(yyjson_obj_get(root, "ssid"))); + ffStrbufAppendJsonVal(&item->inf.description, yyjson_obj_get(root, "ip")); + ffStrbufAppendJsonVal(&item->conn.bssid, yyjson_obj_get(root, "bssid")); + ffStrbufAppendJsonVal(&item->conn.ssid, yyjson_obj_get(root, "ssid")); item->conn.frequency = (uint16_t) yyjson_get_int(yyjson_obj_get(root, "frequency_mhz")); item->conn.txRate = yyjson_get_num(yyjson_obj_get(root, "link_speed_mbps")); item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 1792bb8517..02521294f9 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -11,9 +11,9 @@ static inline double rssiToSignalQuality(int rssi) static bool queryIpconfig(const char* ifName, FFstrbuf* result) { - if (@available(macOS 26.0, *)) + if (@available(macOS 15.6, *)) { - // ipconfig no longer work in Tahoe + // ipconfig reports too return false; } @@ -66,8 +66,6 @@ static bool getWifiInfoByIpconfig(FFstrbuf* ipconfig, const char* prefix, FFstrb }) == NULL; if (!ok) return "Failed to run wdutil info command"; - // ffStrbufSetS(&wdutil, "————————————————————————————————————————————————————————————————————\nNETWORK\n————————————————————————————————————————————————————————————————————\n Primary IPv4 : en0 (Wi-Fi / 37C2D473-40B7-4AFB-93D2-49C588580986)\n : 192.168.48.96\n Primary IPv6 : en0 (Wi-Fi / 37C2D473-40B7-4AFB-93D2-49C588580986)\n : 240a:42a3:5200:1092:18c7:87a2:c8df:ad5a\n : 240a:42a3:5200:1092:5837:b618:deb0:b60c\n DNS Addresses : 240a:42a3:5200:1092::1b\n : 192.168.48.210\n Apple : Reachable\n————————————————————————————————————————————————————————————————————\nWIFI\n————————————————————————————————————————————————————————————————————\n MAC Address : 9e:c4:0a:4b:fe:ab (hw=f4:d4:88:70:f3:39)\n Interface Name : en0\n Power : On [On]\n Op Mode : STA\n SSID : iQOO 13\n BSSID : 92:ad:bb:24:51:bb\n RSSI : -24 dBm\n CCA : 36 %\n Noise : -83 dBm\n Tx Rate : 229.0 Mbps\n Security : WPA2 Personal\n PHY Mode : 11ax\n MCS Index : 9\n Guard Interval : 800\n NSS : 2\n Channel : 2g6/20\n Country Code : CN\n Scan Cache Count : 37\n NetworkServiceID : 37C2D473-40B7-4AFB-93D2-49C588580986\n IPv4 Config Method : DHCP\n IPv4 Address : 192.168.48.96\n IPv4 Router : 192.168.48.210\n IPv6 Config Method : Automatic\n IPv6 Address : 240a:42a3:5200:1092:18c7:87a2:c8df:ad5a\n : 240a:42a3:5200:1092:5837:b618:deb0:b60c\n IPv6 Router : fe80::90ad:bbff:fe24:51bb\n DNS : 192.168.48.210\n : 240a:42a3:5200:1092::1b\n BTC Mode : Off\n Desense :\n Chain Ack : []\n BTC Profile 2.4GHz : Disabled\n BTC Profile 5GHz : Disabled\n Sniffer Supported : YES\n Supports 6e : No\n Supported Channels : 2g1/20,2g2/20,2g3/20,2g4/20,2g5/20,2g6/20,2g7/20,2g8/20,2g9/20,2g10/20,2g11/20,2g12/20,2g13/20,5g36/20,5g40/20,5g44/20,5g48/20,5g52/20,5g56/20,5g60/20,5g64/20,5g149/20,5g153/20,5g157/20,5g161/20,5g165/20,5g36/40,5g40/40,5g44/40,5g48/40,5g52/40,5g56/40,5g60/40,5g64/40,5g149/40,5g153/40,5g157/40,5g161/40,5g36/80,5g40/80,5g44/80,5g48/80,5g52/80,5g56/80,5g60/80,5g64/80,5g149/80,5g153/80,5g157/80,5g161/80\n————————————————————————————————————————————————————————————————————\nBLUETOOTH\n————————————————————————————————————————————————————————————————————\n Power : On\n Address : f4:d4:88:78:91:4a\n Discoverable : No\n Connectable : Yes\n Scanning : No\n Devices : 12 (paired=5 cloud=1 connected=0)\n\n iQOO Wireless Active\n Address : 20:18:5b:3a:fe:93\n Paired : Yes\n CloudPaired : No\n Connected : No\n\n ERAZER N500\n Address : c1:35:45:fb:16:ac\n Paired : No\n CloudPaired : No\n Connected : No\n\n M585/M590\n Address : c9:7a:ff:82:3b:fe\n Paired : No\n CloudPaired : No\n Connected : No\n\n Xiaomi Earphones Explore\n Address : e0:08:71:78:75:0d\n Paired : Yes\n CloudPaired : No\n Connected : No\n\n WH-1000XM5\n Address : 88:c9:e8:61:fa:76\n Paired : Yes\n CloudPaired : No\n Connected : No\n\n ERAZER G501\n Address : d1:00:0f:08:ae:42\n Paired : No\n CloudPaired : No\n Connected : No\n\n MSI BluetoothMouse\n Address : e0:10:9c:40:73:c5\n Paired : No\n CloudPaired : No\n Connected : No\n\n Bluetooth Mouse M336/M337/M535\n Address : 34:88:5d:8f:c0:fe\n Paired : Yes\n CloudPaired : No\n Connected : No\n\n MacBook Pro\n Address : 3c:15:c2:e5:00:b7\n Paired : No\n CloudPaired : Yes\n Connected : No\n\n\n Address : e4:57:68:8e:bb:28\n Paired : No\n CloudPaired : No\n Connected : No\n\n ERAZER N500\n Address : c1:35:45:fb:16:aa\n Paired : No\n CloudPaired : No\n Connected : No\n\n Pro Controller\n Address : 5c:52:1e:88:7e:70\n Paired : Yes\n CloudPaired : No\n Connected : No\n\n————————————————————————————————————————————————————————————————————\nAWDL\n————————————————————————————————————————————————————————————————————\n MAC Address : 46:3a:d9:c1:b0:2e (hw=46:3a:d9:c1:b0:2e)\n AirDrop Disc Mode : Everyone\n AWDL Enabled : No\n Interface Name : awdl0\n Power : On\n IPv6 Address : fe80::443a:d9ff:fec1:b02e\n Schedule State : n/a\n Channel Sequence : n/a\n Op Mode : n/a\n Real Time Mode : No\n Sync State : n/a\n Sync Params : n/a\n Master Channel : n/a\n Election Params : n/a\n————————————————————————————————————————————————————————————————————\nPOWER\n————————————————————————————————————————————————————————————————————\n Power Source : AC\n Battery Warning Level: None\n System Caps : FullWake:cpu disk net aud vid\n————————————————————————————————————————————————————————————————————\nWIFI FAULTS LAST HOUR\n————————————————————————————————————————————————————————————————————\n None\n————————————————————————————————————————————————————————————————————\nWIFI RECOVERIES LAST HOUR\n————————————————————————————————————————————————————————————————————\n None\n————————————————————————————————————————————————————————————————————\nWIFI LINK TESTS LAST HOUR\n————————————————————————————————————————————————————————————————————\n None"); - // ... // ———————————————————————————————————————————————————————————————————— // WIFI @@ -141,9 +139,9 @@ static bool getWifiInfoByIpconfig(FFstrbuf* ipconfig, const char* prefix, FFstrb ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; @@ -247,9 +245,9 @@ static bool getWifiInfoByIpconfig(FFstrbuf* ipconfig, const char* prefix, FFstrb ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; @@ -387,7 +385,7 @@ static bool getWifiInfoByIpconfig(FFstrbuf* ipconfig, const char* prefix, FFstrb const char* ffDetectWifi(FFlist* result) { - if (@available(macOS 26.0, *)) + if (@available(macOS 15.6, *)) { if (detectByWdutil(result) == NULL) return NULL; diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index 458957b6d6..860b66bc2a 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -35,9 +35,9 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 34c3d9f084..b76ebc82a7 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -76,7 +76,7 @@ static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer) dbus.lib->ffdbus_message_unref(device); } - if (item->conn.txRate != item->conn.txRate) + if (item->conn.txRate == -DBL_MAX) { FF_DEBUG("Getting bitrate from NetworkManager"); uint32_t bitrate; @@ -162,7 +162,7 @@ static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer) } else if (ffStrEquals(key, "Strength")) { - if (item->conn.signalQuality != item->conn.signalQuality) + if (item->conn.signalQuality == -DBL_MAX) { FF_DEBUG("Found Strength property"); uint32_t strengthPercent; @@ -314,14 +314,14 @@ static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) ffStrbufClear(buffer); if(ffParsePropLines(output.chars, "rx bitrate: ", buffer)) { - item->conn.rxRate = ffStrbufToDouble(buffer); + item->conn.rxRate = ffStrbufToDouble(buffer, -DBL_MAX); FF_DEBUG("RX bitrate: %.2f Mbps", item->conn.rxRate); } ffStrbufClear(buffer); if(ffParsePropLines(output.chars, "tx bitrate: ", buffer)) { - item->conn.txRate = ffStrbufToDouble(buffer); + item->conn.txRate = ffStrbufToDouble(buffer, -DBL_MAX); FF_DEBUG("TX bitrate: %.2f Mbps (raw: %s)", item->conn.txRate, buffer->chars); if(ffStrbufContainS(buffer, " EHT-MCS ")) @@ -548,9 +548,9 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; diff --git a/src/detection/wifi/wifi_nbsd.c b/src/detection/wifi/wifi_nbsd.c index 6bb9df8ac8..2f0db6523e 100644 --- a/src/detection/wifi/wifi_nbsd.c +++ b/src/detection/wifi/wifi_nbsd.c @@ -45,9 +45,9 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index 969df87806..f811b585ca 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -35,9 +35,9 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index f3128a9d10..e93b56d790 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -80,9 +80,9 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; item->conn.channel = 0; item->conn.frequency = 0; diff --git a/src/detection/wm/wm.h b/src/detection/wm/wm.h index 5f5fa4adfe..115a8cdd82 100644 --- a/src/detection/wm/wm.h +++ b/src/detection/wm/wm.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/wm/wm.h" const char* ffDetectWMPlugin(FFstrbuf* pluginName); const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FFWMOptions* options); diff --git a/src/detection/zpool/zpool.h b/src/detection/zpool/zpool.h index aa8bee03eb..e8a5191ae5 100644 --- a/src/detection/zpool/zpool.h +++ b/src/detection/zpool/zpool.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/zpool/option.h" typedef struct FFZpoolResult { diff --git a/src/detection/zpool/zpool_linux.c b/src/detection/zpool/zpool_linux.c index 6c28def6db..d03082bd24 100644 --- a/src/detection/zpool/zpool_linux.c +++ b/src/detection/zpool/zpool_linux.c @@ -74,7 +74,7 @@ static int enumZpoolCallback(zpool_handle_t* zpool, void* param) item->total = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_SIZE, &source); item->used = item->total - data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FREE, &source); uint64_t fragmentation = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FRAGMENTATION, &source); - item->fragmentation = fragmentation == UINT64_MAX ? 0.0/0.0 : (double) fragmentation; + item->fragmentation = fragmentation == UINT64_MAX ? -DBL_MAX : (double) fragmentation; return 0; } diff --git a/src/fastfetch.c b/src/fastfetch.c index 9a278619c6..56818ca87c 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -3,7 +3,6 @@ #include "common/init.h" #include "common/io/io.h" #include "common/jsonconfig.h" -#include "common/printing.h" #include "detection/version/version.h" #include "logo/logo.h" #include "util/stringUtils.h" @@ -183,10 +182,11 @@ static void printFullHelp() yyjson_doc_free(doc); puts("\n\ -Parsing is not case sensitive. E.g. `--print-logos` is equal to `--Print-Logos`\n\ +Command flags are not case sensitive. E.g. `--print-logos` is equal to `--Print-Logos`\n\ If a value starts with a ?, it is optional. An optional boolean value defaults to true if not specified.\n\ More detailed help messages for each options can be printed with `-h `\n\ -All options can be made permanent with command `fastfetch --gen-config`"); +For detailed information on logo options, module configuration, and formatting, visit:\n\ + https://github.com/fastfetch-cli/fastfetch/wiki/Configuration"); } static bool printSpecificCommandHelp(const char* command) @@ -382,16 +382,25 @@ static bool parseJsoncFile(const char* path, bool strictJson) { yyjson_read_err error; - instance.state.configDoc = yyjson_read_file(path, strictJson ? 0 : YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS, NULL, &error); + yyjson_read_flag flg = strictJson ? 0 : YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS; + instance.state.configDoc = path + ? yyjson_read_file(path, flg, NULL, &error) + : yyjson_read_fp(stdin, flg, NULL, &error); if (!instance.state.configDoc) { if (error.code != YYJSON_READ_ERROR_FILE_OPEN) { - size_t row = 0, col = error.pos; - FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate(); - if (ffAppendFileBuffer(path, &content)) - yyjson_locate_pos(content.chars, content.length, error.pos, &row, &col, NULL); - fprintf(stderr, "Error: failed to parse JSON config file `%s` at (%zu, %zu): %s\n", path, row, col, error.msg); + if (path) + { + size_t row = 0, col = error.pos; + FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate(); + if (ffAppendFileBuffer(path, &content)) + yyjson_locate_pos(content.chars, content.length, error.pos, &row, &col, NULL); + fprintf(stderr, "Error: failed to parse JSON config file `%s` at (%zu, %zu): %s\n", path, row, col, error.msg); + } + else + fprintf(stderr, "Error: failed to parse JSON from stdin at %zu: %s\n", error.pos, error.msg); + exit(477); } return false; @@ -420,7 +429,8 @@ static bool parseJsoncFile(const char* path, bool strictJson) return true; } -static void generateConfigFile(bool force, const char* filePath) + +static void generateConfigFile(bool force, const char* filePath, bool fullConfig) { if (!filePath) { @@ -434,9 +444,11 @@ static void generateConfigFile(bool force, const char* filePath) if (!force && ffPathExists(instance.state.genConfigPath.chars, FF_PATHTYPE_ANY)) { - fprintf(stderr, "Error: file `%s` exists. Use `--gen-config-force` to overwrite\n", instance.state.genConfigPath.chars); + fprintf(stderr, "Error: file `%s` exists. Use `--gen-config%s-force` to overwrite\n", instance.state.genConfigPath.chars, fullConfig ? "-full" : ""); exit(477); } + + instance.state.fullConfig = fullConfig; } static void optionParseConfigFile(FFdata* data, const char* key, const char* value) @@ -458,6 +470,12 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val if (value[0] == '\0' || ffStrEqualsIgnCase(value, "none")) return; + if (value[0] == '-' && value[1] == '\0') + { + parseJsoncFile(NULL, false); + return; + } + //Try to load as an absolute path FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateS(value); @@ -598,10 +616,14 @@ static void parseCommand(FFdata* data, char* key, char* value) exit(0); } else if(ffStrEqualsIgnCase(key, "--gen-config")) - generateConfigFile(false, value); + generateConfigFile(false, value, false); else if(ffStrEqualsIgnCase(key, "--gen-config-force")) - generateConfigFile(true, value); - else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--load-config") || ffStrEqualsIgnCase(key, "--config")) + generateConfigFile(true, value, false); + else if(ffStrEqualsIgnCase(key, "--gen-config-full")) + generateConfigFile(false, value, true); + else if(ffStrEqualsIgnCase(key, "--gen-config-full-force")) + generateConfigFile(true, value, true); + else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--config")) optionParseConfigFile(data, key, value); else if(ffStrEqualsIgnCase(key, "--format")) { @@ -644,8 +666,7 @@ static void parseOption(FFdata* data, const char* key, const char* value) else if( ffOptionsParseGeneralCommandLine(&instance.config.general, key, value) || ffOptionsParseLogoCommandLine(&instance.config.logo, key, value) || - ffOptionsParseDisplayCommandLine(&instance.config.display, key, value) || - ffParseModuleOptions(key, value) + ffOptionsParseDisplayCommandLine(&instance.config.display, key, value) ) {} else @@ -726,16 +747,21 @@ static void run(FFdata* data) ffFinish(); } -static void writeConfigFile(FFdata* data, const FFstrbuf* filename) +static void writeConfigFile(FFdata* data) { + const FFstrbuf* filename = &instance.state.genConfigPath; + yyjson_mut_doc* doc = yyjson_mut_doc_new(NULL); yyjson_mut_val* root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); - yyjson_mut_obj_add_str(doc, root, "$schema", "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json"); + yyjson_mut_obj_add_str(doc, root, "$schema", "https://github.com/fastfetch-cli/fastfetch/raw/master/doc/json_schema.json"); - ffOptionsGenerateLogoJsonConfig(&instance.config.logo, doc); - ffOptionsGenerateDisplayJsonConfig(&instance.config.display, doc); - ffOptionsGenerateGeneralJsonConfig(&instance.config.general, doc); + if (instance.state.fullConfig) + { + ffOptionsGenerateLogoJsonConfig(&instance.config.logo, doc); + ffOptionsGenerateDisplayJsonConfig(&instance.config.display, doc); + ffOptionsGenerateGeneralJsonConfig(&instance.config.general, doc); + } ffMigrateCommandOptionToJsonc(data, doc); if (ffStrbufEqualS(filename, "-")) @@ -780,7 +806,7 @@ int main(int argc, char** argv) if (__builtin_expect(instance.state.genConfigPath.length == 0, true)) run(&data); else - writeConfigFile(&data, &instance.state.genConfigPath); + writeConfigFile(&data); ffStrbufDestroy(&data.structure); } diff --git a/src/fastfetch.h b/src/fastfetch.h index d20248e936..ea4d14621c 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -20,7 +20,6 @@ #include "util/platform/FFPlatform.h" #include "util/unused.h" -#include "options/modules.h" #include "options/logo.h" #include "options/display.h" #include "options/general.h" @@ -42,7 +41,6 @@ typedef struct FFconfig FFOptionsLogo logo; FFOptionsDisplay display; FFOptionsGeneral general; - FFOptionsModules modules; } FFconfig; typedef struct FFstate @@ -51,11 +49,13 @@ typedef struct FFstate uint32_t logoHeight; uint32_t keysHeight; bool terminalLightTheme; + bool titleFqdn; FFPlatform platform; yyjson_doc* configDoc; yyjson_mut_doc* resultDoc; FFstrbuf genConfigPath; + bool fullConfig; } FFstate; typedef struct FFinstance diff --git a/src/flashfetch.c b/src/flashfetch.c index 371a0ca98b..f4256cff63 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -3,55 +3,138 @@ #include "common/init.h" #include "modules/modules.h" +// A dirty replicate of neofetch int main(void) { - ffInitInstance(); //This also applies default configuration to instance.config + ffInitInstance(); // Init everything - //Modify instance.config here - FFOptionsModules* const options = &instance.config.modules; + // Modify global config here if needed + instance.config.display.sizeMaxPrefix = 2; // MB + instance.config.display.sizeNdigits = 0; + instance.config.display.freqNdigits = 3; + instance.config.display.freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER; + instance.config.display.sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_NEVER; - // ffPrepareCPUUsage(); - // ffPreparePublicIp(&options->publicIP); - // ffPrepareWeather(&options->weather); - - //Does things like starting detection threads, disabling line wrap, etc + // Logo printing and other preparation stuff ffStart(); - //Printing - void* const modules[] = { - &options->title, - &options->separator, - &options->os, - &options->host, - &options->kernel, - &options->uptime, - &options->packages, - &options->shell, - &options->display, - &options->de, - &options->wm, - &options->wmTheme, - &options->theme, - &options->icons, - &options->font, - &options->cursor, - &options->terminal, - &options->terminalFont, - &options->cpu, - &options->gpu, - &options->memory, - &options->swap, - &options->disk, - &options->localIP, - &options->battery, - &options->powerAdapter, - &options->locale, - &options->break_, - &options->colors, - }; - - for (size_t i = 0; i < ARRAY_SIZE(modules); i++) - ((const FFModuleBaseInfo*) modules[i])->printModule(modules[i]); + // Print all modules + { + __attribute__((cleanup(ffDestroyTitleOptions))) FFTitleOptions options; + ffInitTitleOptions(&options); + ffPrintTitle(&options); + } + { + __attribute__((cleanup(ffDestroySeparatorOptions))) FFSeparatorOptions options; + ffInitSeparatorOptions(&options); + ffPrintSeparator(&options); + } + { + __attribute__((cleanup(ffDestroyOSOptions))) FFOSOptions options; + ffInitOSOptions(&options); + ffPrintOS(&options); + } + { + __attribute__((cleanup(ffDestroyHostOptions))) FFHostOptions options; + ffInitHostOptions(&options); + ffPrintHost(&options); + } + { + __attribute__((cleanup(ffDestroyKernelOptions))) FFKernelOptions options; + ffInitKernelOptions(&options); + ffStrbufSetStatic(&options.moduleArgs.outputFormat, "{release}"); + ffPrintKernel(&options); + } + { + __attribute__((cleanup(ffDestroyUptimeOptions))) FFUptimeOptions options; + ffInitUptimeOptions(&options); + ffPrintUptime(&options); + } + { + __attribute__((cleanup(ffDestroyPackagesOptions))) FFPackagesOptions options; + ffInitPackagesOptions(&options); + options.combined = true; + ffPrintPackages(&options); + } + { + __attribute__((cleanup(ffDestroyShellOptions))) FFShellOptions options; + ffInitShellOptions(&options); + ffPrintShell(&options); + } + { + __attribute__((cleanup(ffDestroyDisplayOptions))) FFDisplayOptions options; + ffInitDisplayOptions(&options); + options.compactType = FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT; + ffStrbufSetStatic(&options.moduleArgs.key, "Resolution"); + ffPrintDisplay(&options); + } + { + __attribute__((cleanup(ffDestroyDEOptions))) FFDEOptions options; + ffInitDEOptions(&options); + ffPrintDE(&options); + } + { + instance.config.general.detectVersion = false; + __attribute__((cleanup(ffDestroyWMOptions))) FFWMOptions options; + ffInitWMOptions(&options); + options.detectPlugin = true; + ffPrintWM(&options); + instance.config.general.detectVersion = true; + } + { + __attribute__((cleanup(ffDestroyWMThemeOptions))) FFWMThemeOptions options; + ffInitWMThemeOptions(&options); + ffPrintWMTheme(&options); + } + { + __attribute__((cleanup(ffDestroyThemeOptions))) FFThemeOptions options; + ffInitThemeOptions(&options); + ffPrintTheme(&options); + } + { + __attribute__((cleanup(ffDestroyIconsOptions))) FFIconsOptions options; + ffInitIconsOptions(&options); + ffPrintIcons(&options); + } + { + __attribute__((cleanup(ffDestroyTerminalOptions))) FFTerminalOptions options; + ffInitTerminalOptions(&options); + ffPrintTerminal(&options); + } + { + __attribute__((cleanup(ffDestroyTerminalFontOptions))) FFTerminalFontOptions options; + ffInitTerminalFontOptions(&options); + ffStrbufSetStatic(&options.moduleArgs.outputFormat, "{/name}{-}{/}{name}{?size} {size}{?}"); + ffPrintTerminalFont(&options); + } + { + __attribute__((cleanup(ffDestroyCPUOptions))) FFCPUOptions options; + ffInitCPUOptions(&options); + ffPrintCPU(&options); + } + { + __attribute__((cleanup(ffDestroyGPUOptions))) FFGPUOptions options; + ffInitGPUOptions(&options); + ffStrbufSetStatic(&options.moduleArgs.key, "GPU"); + ffStrbufSetStatic(&options.moduleArgs.outputFormat, "{name}"); + ffPrintGPU(&options); + } + { + __attribute__((cleanup(ffDestroyMemoryOptions))) FFMemoryOptions options; + ffInitMemoryOptions(&options); + ffStrbufSetStatic(&options.moduleArgs.outputFormat, "{} / {}"); + ffPrintMemory(&options); + } + { + __attribute__((cleanup(ffDestroyBreakOptions))) FFBreakOptions options; + ffInitBreakOptions(&options); + ffPrintBreak(&options); + } + { + __attribute__((cleanup(ffDestroyColorsOptions))) FFColorsOptions options; + ffInitColorsOptions(&options); + ffPrintColors(&options); + } ffFinish(); ffDestroyInstance(); diff --git a/src/logo/ascii/obsidianos.txt b/src/logo/ascii/obsidianos.txt new file mode 100644 index 0000000000..8042b3e920 --- /dev/null +++ b/src/logo/ascii/obsidianos.txt @@ -0,0 +1,19 @@ + $1-`$2 + .$1o+`$2 + `o$1oo/$2 + `+o$1ooo:$2 + `+oo$1oooo:$2 + -+oo$1oooo+:$2 + `/:-:+$1+oooo+:$2 + `/++++/$1+++++++:$2 + `/++++++$1++++++++:$2 + `/+++oooo$1ooooooooo/`$2 + ./ooosssso$1++osssssso+`$2 + .oossssso-`$1```/ossssss+`$2 + -osssssso. $1 :ssssssso.$2 + :osssssss/ $1 osssso+++.$2 + /ossssssss/ $1 +ssssooo/-$2 + `/ossssso+/:- $1 -:/+osssso+-$2 + `+sso+:-` $1 `.-/+oso:$2 +`++:. $1 `-/+/$2 +.` $1 `/$2 \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 35eabdb65e..c7608fbfbe 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3392,6 +3392,15 @@ static const FFlogo O[] = { FF_COLOR_FG_WHITE, }, }, + // ObsidianOS + { + .names = {"ObsidianOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_OBSIDIANOS, + .colors = { + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_CYAN, + }, + }, // OmniOS { .names = {"OmniOS"}, diff --git a/src/logo/logo.c b/src/logo/logo.c index 0052ac7f8f..c2c4acbbf1 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -568,14 +568,12 @@ static bool logoTryKnownType(void) { FF_STRBUF_AUTO_DESTROY source = ffStrbufCreate(); - FFCommandOptions* commandOptions = &instance.config.modules.command; - const char* error = ffProcessAppendStdOut(&source, commandOptions->param.length ? (char* const[]){ - commandOptions->shell.chars, - commandOptions->param.chars, - options->source.chars, - NULL - } : (char* const[]){ - commandOptions->shell.chars, + const char* error = ffProcessAppendStdOut(&source, (char* const[]){ + #ifdef _WIN32 + "cmd.exe", "/c", + #else + "/bin/sh", "-c", + #endif options->source.chars, NULL }); diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index f1afddbb15..99bf868731 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -72,7 +72,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin ffStrbufAppend(&str, &result->status); } - if(result->temperature == result->temperature) //FF_BATTERY_TEMP_UNSET + if(result->temperature != FF_BATTERY_TEMP_UNSET) { if(str.length > 0) ffStrbufAppendS(&str, " - "); @@ -159,45 +159,17 @@ void ffPrintBattery(FFBatteryOptions* options) } } -bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BATTERY_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffTempsParseCommandOptions(key, subKey, value, &options->temp, &options->tempConfig)) - return true; - - #ifdef _WIN32 - if (ffStrEqualsIgnCase(subKey, "use-setup-api")) - { - options->useSetupApi = ffOptionParseBoolean(value); - return true; - } - #endif - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; #ifdef _WIN32 - if (ffStrEqualsIgnCase(key, "useSetupApi")) + if (unsafe_yyjson_equals_str(key, "useSetupApi")) { options->useSetupApi = yyjson_get_bool(val); continue; @@ -210,25 +182,20 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBatteryJsonConfig(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBatteryOptions))) FFBatteryOptions defaultOptions; - ffInitBatteryOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); #ifdef _WIN32 - if (defaultOptions.useSetupApi != options->useSetupApi) yyjson_mut_obj_add_bool(doc, module, "useSetupApi", options->useSetupApi); #endif - ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig); - - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffTempsGenerateJsonConfig(doc, module, options->temp, options->tempConfig); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -254,7 +221,10 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "status", &battery->status); yyjson_mut_obj_add_strbuf(doc, obj, "technology", &battery->technology); yyjson_mut_obj_add_strbuf(doc, obj, "serial", &battery->serial); - yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); + if (battery->temperature != FF_BATTERY_TEMP_UNSET) + yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); + else + yyjson_mut_obj_add_null(doc, obj, "temperature"); yyjson_mut_obj_add_uint(doc, obj, "cycleCount", battery->cycleCount); if (battery->timeRemaining > 0) yyjson_mut_obj_add_int(doc, obj, "timeRemaining", battery->timeRemaining); @@ -273,10 +243,28 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBatteryOptions(FFBatteryOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + options->temp = false; + options->tempConfig = (FFColorRangeConfig) { 60, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; + + #ifdef _WIN32 + options->useSetupApi = false; + #endif +} + +void ffDestroyBatteryOptions(FFBatteryOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBatteryModuleInfo = { .name = FF_BATTERY_MODULE_NAME, .description = "Print battery capacity, status, etc", - .parseCommandOptions = (void*) ffParseBatteryCommandOptions, + .initOptions = (void*) ffInitBatteryOptions, + .destroyOptions = (void*) ffDestroyBatteryOptions, .parseJsonObject = (void*) ffParseBatteryJsonObject, .printModule = (void*) ffPrintBattery, .generateJsonResult = (void*) ffGenerateBatteryJsonResult, @@ -299,21 +287,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Battery time remaining (formatted)", "time-formatted"}, })) }; - -void ffInitBatteryOptions(FFBatteryOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - options->temp = false; - options->tempConfig = (FFColorRangeConfig) { 60, 80 }; - options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; - - #ifdef _WIN32 - options->useSetupApi = false; - #endif -} - -void ffDestroyBatteryOptions(FFBatteryOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/battery/battery.h b/src/modules/battery/battery.h index 60d0f1c893..820a7bc7cf 100644 --- a/src/modules/battery/battery.h +++ b/src/modules/battery/battery.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BATTERY_MODULE_NAME "Battery" void ffPrintBattery(FFBatteryOptions* options); void ffInitBatteryOptions(FFBatteryOptions* options); void ffDestroyBatteryOptions(FFBatteryOptions* options); + +extern FFModuleBaseInfo ffBatteryModuleInfo; diff --git a/src/modules/battery/option.h b/src/modules/battery/option.h index 8b04ef1b4b..1ac5b97bec 100644 --- a/src/modules/battery/option.h +++ b/src/modules/battery/option.h @@ -1,13 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFBatteryOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool temp; @@ -18,3 +15,5 @@ typedef struct FFBatteryOptions bool useSetupApi; #endif } FFBatteryOptions; + +static_assert(sizeof(FFBatteryOptions) <= FF_OPTION_MAX_SIZE, "FFBatteryOptions size exceeds maximum allowed size"); diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index b8a3b0cc3a..d2f59629e0 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -75,39 +75,22 @@ void ffPrintBios(FFBiosOptions* options) ffStrbufDestroy(&bios.type); } -bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BIOS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBiosJsonConfig(FFBiosOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBiosOptions))) FFBiosOptions defaultOptions; - ffInitBiosOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -142,10 +125,21 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut ffStrbufDestroy(&bios.type); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBiosOptions(FFBiosOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyBiosOptions(FFBiosOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBiosModuleInfo = { .name = FF_BIOS_MODULE_NAME, .description = "Print information of 1st-stage bootloader (name, version, release date, etc)", - .parseCommandOptions = (void*) ffParseBiosCommandOptions, + .initOptions = (void*) ffInitBiosOptions, + .destroyOptions = (void*) ffDestroyBiosOptions, .parseJsonObject = (void*) ffParseBiosJsonObject, .printModule = (void*) ffPrintBios, .generateJsonResult = (void*) ffGenerateBiosJsonResult, @@ -158,14 +152,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Firmware type", "type"}, })) }; - -void ffInitBiosOptions(FFBiosOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyBiosOptions(FFBiosOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/bios/bios.h b/src/modules/bios/bios.h index 14444c4354..22b35edda4 100644 --- a/src/modules/bios/bios.h +++ b/src/modules/bios/bios.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BIOS_MODULE_NAME "BIOS" void ffPrintBios(FFBiosOptions* options); void ffInitBiosOptions(FFBiosOptions* options); void ffDestroyBiosOptions(FFBiosOptions* options); + +extern FFModuleBaseInfo ffBiosModuleInfo; diff --git a/src/modules/bios/option.h b/src/modules/bios/option.h index 483e7b664f..0008035692 100644 --- a/src/modules/bios/option.h +++ b/src/modules/bios/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFBiosOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFBiosOptions; + +static_assert(sizeof(FFBiosOptions) <= FF_OPTION_MAX_SIZE, "FFBiosOptions size exceeds maximum allowed size"); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index b931785569..b5e05f21bc 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -97,39 +97,16 @@ void ffPrintBluetooth(FFBluetoothOptions* options) } } -bool ffParseBluetoothCommandOptions(FFBluetoothOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BLUETOOTH_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "show-disconnected")) - { - options->showDisconnected = ffOptionParseBoolean(value); - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "showDisconnected")) + if (unsafe_yyjson_equals_str(key, "showDisconnected")) { options->showDisconnected = yyjson_get_bool(val); continue; @@ -138,21 +115,17 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBluetoothJsonConfig(FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBluetoothOptions))) FFBluetoothOptions defaultOptions; - ffInitBluetoothOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - if (options->showDisconnected != defaultOptions.showDisconnected) - yyjson_mut_obj_add_bool(doc, module, "showDisconnected", options->showDisconnected); + yyjson_mut_obj_add_bool(doc, module, "showDisconnected", options->showDisconnected); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateBluetoothJsonResult(FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -186,10 +159,23 @@ void ffGenerateBluetoothJsonResult(FFBluetoothOptions* options, yyjson_mut_doc* } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBluetoothOptions(FFBluetoothOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + options->showDisconnected = false; + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; +} + +void ffDestroyBluetoothOptions(FFBluetoothOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBluetoothModuleInfo = { .name = FF_BLUETOOTH_MODULE_NAME, .description = "List (connected) bluetooth devices", - .parseCommandOptions = (void*) ffParseBluetoothCommandOptions, + .initOptions = (void*) ffInitBluetoothOptions, + .destroyOptions = (void*) ffDestroyBluetoothOptions, .parseJsonObject = (void*) ffParseBluetoothJsonObject, .printModule = (void*) ffPrintBluetooth, .generateJsonResult = (void*) ffGenerateBluetoothJsonResult, @@ -203,16 +189,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Battery percentage bar", "battery-percentage-bar"}, })) }; - -void ffInitBluetoothOptions(FFBluetoothOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - options->showDisconnected = false; - options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; -} - -void ffDestroyBluetoothOptions(FFBluetoothOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/bluetooth/bluetooth.h b/src/modules/bluetooth/bluetooth.h index 20c3b6d81d..889be9690d 100644 --- a/src/modules/bluetooth/bluetooth.h +++ b/src/modules/bluetooth/bluetooth.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BLUETOOTH_MODULE_NAME "Bluetooth" void ffPrintBluetooth(FFBluetoothOptions* options); void ffInitBluetoothOptions(FFBluetoothOptions* options); void ffDestroyBluetoothOptions(FFBluetoothOptions* options); + +extern FFModuleBaseInfo ffBluetoothModuleInfo; diff --git a/src/modules/bluetooth/option.h b/src/modules/bluetooth/option.h index 4de6fff725..516c0d8b4b 100644 --- a/src/modules/bluetooth/option.h +++ b/src/modules/bluetooth/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFBluetoothOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool showDisconnected; FFPercentageModuleConfig percent; } FFBluetoothOptions; + +static_assert(sizeof(FFBluetoothOptions) <= FF_OPTION_MAX_SIZE, "FFBluetoothOptions size exceeds maximum allowed size"); diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 771296bded..810b5f438e 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -105,39 +105,22 @@ void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) } } -bool ffParseBluetoothRadioCommandOptions(FFBluetoothRadioOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BLUETOOTHRADIO_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBluetoothRadioJsonConfig(FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBluetoothRadioOptions))) FFBluetoothRadioOptions defaultOptions; - ffInitBluetoothRadioOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -180,10 +163,21 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰐻"); +} + +void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .name = FF_BLUETOOTHRADIO_MODULE_NAME, .description = "List bluetooth radios width supported version and vendor", - .parseCommandOptions = (void*) ffParseBluetoothRadioCommandOptions, + .initOptions = (void*) ffInitBluetoothRadioOptions, + .destroyOptions = (void*) ffDestroyBluetoothRadioOptions, .parseJsonObject = (void*) ffParseBluetoothRadioJsonObject, .printModule = (void*) ffPrintBluetoothRadio, .generateJsonResult = (void*) ffGenerateBluetoothRadioJsonResult, @@ -199,14 +193,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Connectable / Pairable", "connectable"}, })) }; - -void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰐻"); -} - -void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/bluetoothradio/bluetoothradio.h b/src/modules/bluetoothradio/bluetoothradio.h index ee9ef11959..9d63525fe9 100644 --- a/src/modules/bluetoothradio/bluetoothradio.h +++ b/src/modules/bluetoothradio/bluetoothradio.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio" void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options); void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options); void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options); + +extern FFModuleBaseInfo ffBluetoothRadioModuleInfo; diff --git a/src/modules/bluetoothradio/option.h b/src/modules/bluetoothradio/option.h index 714200d3e8..1b718b834c 100644 --- a/src/modules/bluetoothradio/option.h +++ b/src/modules/bluetoothradio/option.h @@ -1,12 +1,11 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFBluetoothRadioOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFBluetoothRadioOptions; + +static_assert(sizeof(FFBluetoothRadioOptions) <= FF_OPTION_MAX_SIZE, "FFBluetoothRadioOptions size exceeds maximum allowed size"); diff --git a/src/modules/board/board.c b/src/modules/board/board.c index a539aa9bfe..a9cf573f67 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -50,39 +50,22 @@ void ffPrintBoard(FFBoardOptions* options) ffStrbufDestroy(&result.serial); } -bool ffParseBoardCommandOptions(FFBoardOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BOARD_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBoardJsonConfig(FFBoardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBoardOptions))) FFBoardOptions defaultOptions; - ffInitBoardOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateBoardJsonResult(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -120,10 +103,21 @@ void ffGenerateBoardJsonResult(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_m ffStrbufDestroy(&board.serial); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBoardOptions(FFBoardOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyBoardOptions(FFBoardOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBoardModuleInfo = { .name = FF_BOARD_MODULE_NAME, .description = "Print motherboard name and other info", - .parseCommandOptions = (void*) ffParseBoardCommandOptions, + .initOptions = (void*) ffInitBoardOptions, + .destroyOptions = (void*) ffDestroyBoardOptions, .parseJsonObject = (void*) ffParseBoardJsonObject, .printModule = (void*) ffPrintBoard, .generateJsonResult = (void*) ffGenerateBoardJsonResult, @@ -135,14 +129,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Board serial number", "serial"}, })) }; - -void ffInitBoardOptions(FFBoardOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyBoardOptions(FFBoardOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/board/board.h b/src/modules/board/board.h index 7fdbffe953..3fdea021de 100644 --- a/src/modules/board/board.h +++ b/src/modules/board/board.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BOARD_MODULE_NAME "Board" void ffPrintBoard(FFBoardOptions* options); void ffInitBoardOptions(FFBoardOptions* options); void ffDestroyBoardOptions(FFBoardOptions* options); + +extern FFModuleBaseInfo ffBoardModuleInfo; diff --git a/src/modules/board/option.h b/src/modules/board/option.h index 1640ff3d37..bcc69adf36 100644 --- a/src/modules/board/option.h +++ b/src/modules/board/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFBoardOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFBoardOptions; + +static_assert(sizeof(FFBoardOptions) <= FF_OPTION_MAX_SIZE, "FFBoardOptions size exceeds maximum allowed size"); diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 601420bc53..350499530e 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -50,39 +50,22 @@ void ffPrintBootmgr(FFBootmgrOptions* options) ffStrbufDestroy(&bootmgr.firmware); } -bool ffParseBootmgrCommandOptions(FFBootmgrOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BOOTMGR_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseBootmgrJsonObject(FFBootmgrOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBootmgrJsonConfig(FFBootmgrOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBootmgrOptions))) FFBootmgrOptions defaultOptions; - ffInitBootmgrOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateBootmgrJsonResult(FF_MAYBE_UNUSED FFBootmgrOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -111,10 +94,21 @@ void ffGenerateBootmgrJsonResult(FF_MAYBE_UNUSED FFBootmgrOptions* options, yyjs ffStrbufDestroy(&bootmgr.firmware); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBootmgrOptions(FFBootmgrOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyBootmgrOptions(FFBootmgrOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBootmgrModuleInfo = { .name = FF_BOOTMGR_MODULE_NAME, .description = "Print information of 2nd-stage bootloader (name, firmware, etc)", - .parseCommandOptions = (void*) ffParseBootmgrCommandOptions, + .initOptions = (void*) ffInitBootmgrOptions, + .destroyOptions = (void*) ffDestroyBootmgrOptions, .parseJsonObject = (void*) ffParseBootmgrJsonObject, .printModule = (void*) ffPrintBootmgr, .generateJsonResult = (void*) ffGenerateBootmgrJsonResult, @@ -127,14 +121,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Boot order", "order"}, })) }; - -void ffInitBootmgrOptions(FFBootmgrOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyBootmgrOptions(FFBootmgrOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/bootmgr/bootmgr.h b/src/modules/bootmgr/bootmgr.h index 31a3b7946b..9150f5218d 100644 --- a/src/modules/bootmgr/bootmgr.h +++ b/src/modules/bootmgr/bootmgr.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BOOTMGR_MODULE_NAME "Bootmgr" void ffPrintBootmgr(FFBootmgrOptions* options); void ffInitBootmgrOptions(FFBootmgrOptions* options); void ffDestroyBootmgrOptions(FFBootmgrOptions* options); + +extern FFModuleBaseInfo ffBootmgrModuleInfo; diff --git a/src/modules/bootmgr/option.h b/src/modules/bootmgr/option.h index 04a7d3cc56..e27e71efd4 100644 --- a/src/modules/bootmgr/option.h +++ b/src/modules/bootmgr/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFBootmgrOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFBootmgrOptions; + +static_assert(sizeof(FFBootmgrOptions) <= FF_OPTION_MAX_SIZE, "FFBootmgrOptions size exceeds maximum allowed size"); diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 6e3379ee05..34fb4c2add 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -8,28 +8,32 @@ void ffPrintBreak(FF_MAYBE_UNUSED FFBreakOptions* options) putchar('\n'); } -bool ffParseBreakCommandOptions(FF_MAYBE_UNUSED FFBreakOptions* options, FF_MAYBE_UNUSED const char* key, FF_MAYBE_UNUSED const char* value) -{ - return false; -} - void ffParseBreakJsonObject(FF_MAYBE_UNUSED FFBreakOptions* options, FF_MAYBE_UNUSED yyjson_val* module) { -} + yyjson_val *key, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key, val) + { + if (unsafe_yyjson_equals_str(key, "type") || unsafe_yyjson_equals_str(key, "condition")) + continue; -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_BREAK_MODULE_NAME, - .description = "Print a empty line", - .parseCommandOptions = (void*) ffParseBreakCommandOptions, - .parseJsonObject = (void*) ffParseBreakJsonObject, - .printModule = (void*) ffPrintBreak, -}; + ffPrintError(FF_BREAK_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + } +} void ffInitBreakOptions(FF_MAYBE_UNUSED FFBreakOptions* options) { - options->moduleInfo = ffModuleInfo; } void ffDestroyBreakOptions(FF_MAYBE_UNUSED FFBreakOptions* options) { } + +FFModuleBaseInfo ffBreakModuleInfo = { + .name = FF_BREAK_MODULE_NAME, + .description = "Print a empty line", + .initOptions = (void*) ffInitBreakOptions, + .destroyOptions = (void*) ffDestroyBreakOptions, + .parseJsonObject = (void*) ffParseBreakJsonObject, + .printModule = (void*) ffPrintBreak, +}; diff --git a/src/modules/break/break.h b/src/modules/break/break.h index b651a503e4..772d19744b 100644 --- a/src/modules/break/break.h +++ b/src/modules/break/break.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BREAK_MODULE_NAME "Break" void ffPrintBreak(FFBreakOptions* options); void ffInitBreakOptions(FFBreakOptions* options); void ffDestroyBreakOptions(FFBreakOptions* options); + +extern FFModuleBaseInfo ffBreakModuleInfo; diff --git a/src/modules/break/option.h b/src/modules/break/option.h index 4d2870c268..e5acbf20dd 100644 --- a/src/modules/break/option.h +++ b/src/modules/break/option.h @@ -1,10 +1,9 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFBreakOptions { - FFModuleBaseInfo moduleInfo; } FFBreakOptions; + +static_assert(sizeof(FFBreakOptions) <= FF_OPTION_MAX_SIZE, "FFBreakOptions size exceeds maximum allowed size"); diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index bcbd81364d..c3855b07d1 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -112,51 +112,22 @@ void ffPrintBrightness(FFBrightnessOptions* options) } } -bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BRIGHTNESS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "ddcci-sleep")) - { - options->ddcciSleep = ffOptionParseUInt32(key, value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "compact")) - { - options->compact = ffOptionParseBoolean(value); - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "ddcciSleep")) + if (unsafe_yyjson_equals_str(key, "ddcciSleep")) { options->ddcciSleep = (uint32_t) yyjson_get_uint(val); continue; } - if (ffStrEqualsIgnCase(key, "compact")) + if (unsafe_yyjson_equals_str(key, "compact")) { options->compact = (uint32_t) yyjson_get_bool(val); continue; @@ -165,24 +136,19 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBrightnessJsonConfig(FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBrightnessOptions))) FFBrightnessOptions defaultOptions; - ffInitBrightnessOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - if (defaultOptions.ddcciSleep != options->ddcciSleep) - yyjson_mut_obj_add_uint(doc, module, "ddcciSleep", options->ddcciSleep); + yyjson_mut_obj_add_uint(doc, module, "ddcciSleep", options->ddcciSleep); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); - if (defaultOptions.compact != options->compact) - yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); } void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -216,10 +182,25 @@ void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBrightnessOptions(FFBrightnessOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰯪"); + + options->ddcciSleep = 10; + options->percent = (FFPercentageModuleConfig) { 100, 100, 0 }; + options->compact = false; +} + +void ffDestroyBrightnessOptions(FFBrightnessOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBrightnessModuleInfo = { .name = FF_BRIGHTNESS_MODULE_NAME, .description = "Print current brightness level of your monitors", - .parseCommandOptions = (void*) ffParseBrightnessCommandOptions, + .initOptions = (void*) ffInitBrightnessOptions, + .destroyOptions = (void*) ffDestroyBrightnessOptions, .parseJsonObject = (void*) ffParseBrightnessJsonObject, .printModule = (void*) ffPrintBrightness, .generateJsonResult = (void*) ffGenerateBrightnessJsonResult, @@ -234,18 +215,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Is built-in screen", "is-builtin"}, })) }; - -void ffInitBrightnessOptions(FFBrightnessOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰯪"); - - options->ddcciSleep = 10; - options->percent = (FFPercentageModuleConfig) { 100, 100, 0 }; - options->compact = false; -} - -void ffDestroyBrightnessOptions(FFBrightnessOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/brightness/brightness.h b/src/modules/brightness/brightness.h index 36faaf304b..3b443425f4 100644 --- a/src/modules/brightness/brightness.h +++ b/src/modules/brightness/brightness.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BRIGHTNESS_MODULE_NAME "Brightness" void ffPrintBrightness(FFBrightnessOptions* options); void ffInitBrightnessOptions(FFBrightnessOptions* options); void ffDestroyBrightnessOptions(FFBrightnessOptions* options); + +extern FFModuleBaseInfo ffBrightnessModuleInfo; diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index 70337f59ee..4ff3843e7e 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -1,16 +1,15 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFBrightnessOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; uint32_t ddcciSleep; // ms FFPercentageModuleConfig percent; bool compact; } FFBrightnessOptions; + +static_assert(sizeof(FFBrightnessOptions) <= FF_OPTION_MAX_SIZE, "FFBrightnessOptions size exceeds maximum allowed size"); diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 31b58e1f30..e337d4c72b 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -130,47 +130,27 @@ void ffPrintBtrfs(FFBtrfsOptions* options) } } -bool ffParseBtrfsCommandOptions(FFBtrfsOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_BTRFS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseBtrfsJsonObject(FFBtrfsOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateBtrfsJsonConfig(FFBtrfsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyBtrfsOptions))) FFBtrfsOptions defaultOptions; - ffInitBtrfsOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateBtrfsJsonResult(FF_MAYBE_UNUSED FFBtrfsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -217,10 +197,22 @@ void ffGenerateBtrfsJsonResult(FF_MAYBE_UNUSED FFBtrfsOptions* options, yyjson_m } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitBtrfsOptions(FFBtrfsOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󱑛"); + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; +} + +void ffDestroyBtrfsOptions(FFBtrfsOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffBtrfsModuleInfo = { .name = FF_BTRFS_MODULE_NAME, .description = "Print Linux BTRFS volumes", - .parseCommandOptions = (void*) ffParseBtrfsCommandOptions, + .initOptions = (void*) ffInitBtrfsOptions, + .destroyOptions = (void*) ffDestroyBtrfsOptions, .parseJsonObject = (void*) ffParseBtrfsJsonObject, .printModule = (void*) ffPrintBtrfs, .generateJsonResult = (void*) ffGenerateBtrfsJsonResult, @@ -241,15 +233,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Sector size", "sector-size"}, })) }; - -void ffInitBtrfsOptions(FFBtrfsOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󱑛"); - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; -} - -void ffDestroyBtrfsOptions(FFBtrfsOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/btrfs/btrfs.h b/src/modules/btrfs/btrfs.h index 25df250847..3cd77df322 100644 --- a/src/modules/btrfs/btrfs.h +++ b/src/modules/btrfs/btrfs.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_BTRFS_MODULE_NAME "Btrfs" void ffPrintBtrfs(FFBtrfsOptions* options); void ffInitBtrfsOptions(FFBtrfsOptions* options); void ffDestroyBtrfsOptions(FFBtrfsOptions* options); + +extern FFModuleBaseInfo ffBtrfsModuleInfo; diff --git a/src/modules/btrfs/option.h b/src/modules/btrfs/option.h index 2e4b069b4d..019eacb19d 100644 --- a/src/modules/btrfs/option.h +++ b/src/modules/btrfs/option.h @@ -1,14 +1,13 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFBtrfsOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; } FFBtrfsOptions; + +static_assert(sizeof(FFBtrfsOptions) <= FF_OPTION_MAX_SIZE, "FFBtrfsOptions size exceeds maximum allowed size"); diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 48d450f497..d12d7a6622 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -67,39 +67,22 @@ void ffPrintCamera(FFCameraOptions* options) } } -bool ffParseCameraCommandOptions(FFCameraOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CAMERA_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateCameraJsonConfig(FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCameraOptions))) FFCameraOptions defaultOptions; - ffInitCameraOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateCameraJsonResult(FF_MAYBE_UNUSED FFCameraOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -134,10 +117,21 @@ void ffGenerateCameraJsonResult(FF_MAYBE_UNUSED FFCameraOptions* options, yyjson } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitCameraOptions(FFCameraOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰄀"); +} + +void ffDestroyCameraOptions(FFCameraOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffCameraModuleInfo = { .name = FF_CAMERA_MODULE_NAME, .description = "Print available cameras", - .parseCommandOptions = (void*) ffParseCameraCommandOptions, + .initOptions = (void*) ffInitCameraOptions, + .destroyOptions = (void*) ffDestroyCameraOptions, .parseJsonObject = (void*) ffParseCameraJsonObject, .printModule = (void*) ffPrintCamera, .generateJsonResult = (void*) ffGenerateCameraJsonResult, @@ -151,14 +145,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Height (in px)", "height"}, })) }; - -void ffInitCameraOptions(FFCameraOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰄀"); -} - -void ffDestroyCameraOptions(FFCameraOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/camera/camera.h b/src/modules/camera/camera.h index 47d2e1cc73..1de49bdcaf 100644 --- a/src/modules/camera/camera.h +++ b/src/modules/camera/camera.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CAMERA_MODULE_NAME "Camera" void ffPrintCamera(FFCameraOptions* options); void ffInitCameraOptions(FFCameraOptions* options); void ffDestroyCameraOptions(FFCameraOptions* options); + +extern FFModuleBaseInfo ffCameraModuleInfo; diff --git a/src/modules/camera/option.h b/src/modules/camera/option.h index 7c7ac05b63..6a2481fe8e 100644 --- a/src/modules/camera/option.h +++ b/src/modules/camera/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFCameraOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFCameraOptions; + +static_assert(sizeof(FFCameraOptions) <= FF_OPTION_MAX_SIZE, "FFCameraOptions size exceeds maximum allowed size"); diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 5d7ef92393..e1344ab2bd 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -51,39 +51,22 @@ void ffPrintChassis(FFChassisOptions* options) ffStrbufDestroy(&result.serial); } -bool ffParseChassisCommandOptions(FFChassisOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CHASSIS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateChassisJsonConfig(FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyChassisOptions))) FFChassisOptions defaultOptions; - ffInitChassisOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateChassisJsonResult(FF_MAYBE_UNUSED FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -121,10 +104,21 @@ void ffGenerateChassisJsonResult(FF_MAYBE_UNUSED FFChassisOptions* options, yyjs ffStrbufDestroy(&result.serial); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitChassisOptions(FFChassisOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyChassisOptions(FFChassisOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffChassisModuleInfo = { .name = FF_CHASSIS_MODULE_NAME, .description = "Print chassis type (desktop, laptop, etc)", - .parseCommandOptions = (void*) ffParseChassisCommandOptions, + .initOptions = (void*) ffInitChassisOptions, + .destroyOptions = (void*) ffDestroyChassisOptions, .parseJsonObject = (void*) ffParseChassisJsonObject, .printModule = (void*) ffPrintChassis, .generateJsonResult = (void*) ffGenerateChassisJsonResult, @@ -136,14 +130,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Chassis serial number", "serial"}, })), }; - -void ffInitChassisOptions(FFChassisOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyChassisOptions(FFChassisOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/chassis/chassis.h b/src/modules/chassis/chassis.h index f37358c94c..47a80d6fff 100644 --- a/src/modules/chassis/chassis.h +++ b/src/modules/chassis/chassis.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CHASSIS_MODULE_NAME "Chassis" void ffPrintChassis(FFChassisOptions* options); void ffInitChassisOptions(FFChassisOptions* options); void ffDestroyChassisOptions(FFChassisOptions* options); + +extern FFModuleBaseInfo ffChassisModuleInfo; diff --git a/src/modules/chassis/option.h b/src/modules/chassis/option.h index de6338cd50..b3100653fd 100644 --- a/src/modules/chassis/option.h +++ b/src/modules/chassis/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFChassisOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFChassisOptions; + +static_assert(sizeof(FFChassisOptions) <= FF_OPTION_MAX_SIZE, "FFChassisOptions size exceeds maximum allowed size"); diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 7d4367b391..27dae0f40f 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -125,69 +125,16 @@ void ffPrintColors(FFColorsOptions* options) } } -bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_COLORS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "symbol")) - { - options->symbol = (FFColorsSymbol) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "block", FF_COLORS_SYMBOL_BLOCK }, - { "background", FF_COLORS_SYMBOL_BACKGROUND }, - { "circle", FF_COLORS_SYMBOL_CIRCLE }, - { "diamond", FF_COLORS_SYMBOL_DIAMOND }, - { "triangle", FF_COLORS_SYMBOL_TRIANGLE }, - { "square", FF_COLORS_SYMBOL_SQUARE }, - { "star", FF_COLORS_SYMBOL_STAR }, - {}, - }); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "padding-left")) - { - options->paddingLeft = ffOptionParseUInt32(key, value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "block-width")) - { - options->block.width = (uint8_t) ffOptionParseUInt32(key, value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "block-range-start")) - { - options->block.range[0] = min((uint8_t) ffOptionParseUInt32(key, value), 15); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "block-range-end")) - { - options->block.range[1] = min((uint8_t) ffOptionParseUInt32(key, value), 15); - return true; - } - - return false; -} - void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "symbol")) + if (unsafe_yyjson_equals_str(key, "symbol")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -201,22 +148,22 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) {}, }); if (error) - ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", key, error); + ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); else options->symbol = (FFColorsSymbol) value; continue; } - if (ffStrEqualsIgnCase(key, "paddingLeft")) + if (unsafe_yyjson_equals_str(key, "paddingLeft")) { options->paddingLeft = (uint32_t) yyjson_get_uint(val); continue; } - if (ffStrEqualsIgnCase(key, "block")) + if (unsafe_yyjson_equals_str(key, "block")) { if (!yyjson_is_obj(val)) - ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", key); + ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key)); else { yyjson_val* width = yyjson_obj_get(val, "width"); @@ -227,15 +174,15 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) if (range) { if (!yyjson_is_arr(range) || yyjson_arr_size(range) != 2) - ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", key); + ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key)); else { uint8_t start = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 0)); uint8_t end = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 1)); if (start > end) - ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", key); + ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key)); else if (end > 15) - ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", key); + ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key)); else { options->block.range[0] = start; @@ -247,63 +194,41 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key); + ffPrintError(FF_COLORS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateColorsJsonConfig(FFColorsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyColorsOptions))) FFColorsOptions defaultOptions; - ffInitColorsOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_remove_key(module, "format"); // Not supported - if (defaultOptions.symbol != options->symbol) + switch (options->symbol) { - switch (options->symbol) - { - case FF_COLORS_SYMBOL_CIRCLE: yyjson_mut_obj_add_str(doc, module, "symbol", "circle"); break; - case FF_COLORS_SYMBOL_DIAMOND: yyjson_mut_obj_add_str(doc, module, "symbol", "diamond"); break; - case FF_COLORS_SYMBOL_TRIANGLE: yyjson_mut_obj_add_str(doc, module, "symbol", "triangle"); break; - case FF_COLORS_SYMBOL_SQUARE: yyjson_mut_obj_add_str(doc, module, "symbol", "square"); break; - case FF_COLORS_SYMBOL_STAR: yyjson_mut_obj_add_str(doc, module, "symbol", "star"); break; - default: yyjson_mut_obj_add_str(doc, module, "symbol", "block"); break; - } + case FF_COLORS_SYMBOL_CIRCLE: yyjson_mut_obj_add_str(doc, module, "symbol", "circle"); break; + case FF_COLORS_SYMBOL_DIAMOND: yyjson_mut_obj_add_str(doc, module, "symbol", "diamond"); break; + case FF_COLORS_SYMBOL_TRIANGLE: yyjson_mut_obj_add_str(doc, module, "symbol", "triangle"); break; + case FF_COLORS_SYMBOL_SQUARE: yyjson_mut_obj_add_str(doc, module, "symbol", "square"); break; + case FF_COLORS_SYMBOL_STAR: yyjson_mut_obj_add_str(doc, module, "symbol", "star"); break; + default: yyjson_mut_obj_add_str(doc, module, "symbol", "block"); break; } - if (defaultOptions.paddingLeft != options->paddingLeft) - yyjson_mut_obj_add_uint(doc, module, "paddingLeft", options->paddingLeft); + yyjson_mut_obj_add_uint(doc, module, "paddingLeft", options->paddingLeft); { - yyjson_mut_val* block = yyjson_mut_obj(doc); + yyjson_mut_val* block = yyjson_mut_obj_add_obj(doc, module, "block"); - if (defaultOptions.block.width != options->block.width) - yyjson_mut_obj_add_uint(doc, block, "width", options->block.width); - - if (memcmp(defaultOptions.block.range, options->block.range, sizeof(options->block.range)) != 0) - { - yyjson_mut_val* range = yyjson_mut_obj_add_arr(doc, block, "range"); - for (uint8_t i = 0; i < 2; i++) - yyjson_mut_arr_add_uint(doc, range, options->block.range[i]); - } + yyjson_mut_obj_add_uint(doc, block, "width", options->block.width); - if (yyjson_mut_obj_size(block) > 0) - yyjson_mut_obj_add_val(doc, module, "block", block); + yyjson_mut_val* range = yyjson_mut_obj_add_arr(doc, block, "range"); + for (uint8_t i = 0; i < 2; i++) + yyjson_mut_arr_add_uint(doc, range, options->block.range[i]); } } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_COLORS_MODULE_NAME, - .description = "Print some colored blocks", - .parseCommandOptions = (void*) ffParseColorsCommandOptions, - .parseJsonObject = (void*) ffParseColorsJsonObject, - .printModule = (void*) ffPrintColors, - .generateJsonConfig = (void*) ffGenerateColorsJsonConfig, -}; - void ffInitColorsOptions(FFColorsOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, ""); ffStrbufSetStatic(&options->moduleArgs.key, " "); options->symbol = FF_COLORS_SYMBOL_BACKGROUND; @@ -314,7 +239,17 @@ void ffInitColorsOptions(FFColorsOptions* options) }; } -void ffDestroyColorsOptions(FF_MAYBE_UNUSED FFColorsOptions* options) +void ffDestroyColorsOptions(FFColorsOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); } + +FFModuleBaseInfo ffColorsModuleInfo = { + .name = FF_COLORS_MODULE_NAME, + .description = "Print some colored blocks", + .initOptions = (void*) ffInitColorsOptions, + .destroyOptions = (void*) ffDestroyColorsOptions, + .parseJsonObject = (void*) ffParseColorsJsonObject, + .printModule = (void*) ffPrintColors, + .generateJsonConfig = (void*) ffGenerateColorsJsonConfig, +}; diff --git a/src/modules/colors/colors.h b/src/modules/colors/colors.h index 8520f54b67..3581dabd9d 100644 --- a/src/modules/colors/colors.h +++ b/src/modules/colors/colors.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_COLORS_MODULE_NAME "Colors" void ffPrintColors(FFColorsOptions* options); void ffInitColorsOptions(FFColorsOptions* options); void ffDestroyColorsOptions(FFColorsOptions* options); + +extern FFModuleBaseInfo ffColorsModuleInfo; diff --git a/src/modules/colors/option.h b/src/modules/colors/option.h index 1a948a9b1b..6a0bbb0d47 100644 --- a/src/modules/colors/option.h +++ b/src/modules/colors/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef enum __attribute__((__packed__)) FFColorsSymbol @@ -23,10 +21,11 @@ typedef struct FFBlockConfig typedef struct FFColorsOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFColorsSymbol symbol; uint32_t paddingLeft; FFBlockConfig block; } FFColorsOptions; + +static_assert(sizeof(FFColorsOptions) <= FF_OPTION_MAX_SIZE, "FFColorsOptions size exceeds maximum allowed size"); diff --git a/src/modules/command/command.c b/src/modules/command/command.c index a6d38ab159..5a92d3ceaf 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -43,84 +43,46 @@ void ffPrintCommand(FFCommandOptions* options) } } -bool ffParseCommandCommandOptions(FFCommandOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_COMMAND_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if(ffStrEqualsIgnCase(subKey, "shell")) - { - ffOptionParseString(key, value, &options->shell); - return true; - } - - if(ffStrEqualsIgnCase(subKey, "param")) - { - ffOptionParseString(key, value, &options->param); - return true; - } - - if(ffStrEqualsIgnCase(subKey, "text")) - { - ffOptionParseString(key, value, &options->text); - return true; - } - - return false; -} - void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "shell")) + if (unsafe_yyjson_equals_str(key, "shell")) { - ffStrbufSetS(&options->shell, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->shell, val); continue; } - if (ffStrEqualsIgnCase(key, "param")) + if (unsafe_yyjson_equals_str(key, "param")) { - ffStrbufSetS(&options->param, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->param, val); continue; } - if (ffStrEqualsIgnCase(key, "text")) + if (unsafe_yyjson_equals_str(key, "text")) { - ffStrbufSetS(&options->text, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->text, val); continue; } - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateCommandJsonConfig(FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCommandOptions))) FFCommandOptions defaultOptions; - ffInitCommandOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_strbuf(doc, module, "shell", &options->shell); - if (!ffStrbufEqual(&defaultOptions.shell, &options->shell)) - yyjson_mut_obj_add_strbuf(doc, module, "shell", &options->shell); + yyjson_mut_obj_add_strbuf(doc, module, "param", &options->param); - if (!ffStrbufEqual(&defaultOptions.param, &options->param)) - yyjson_mut_obj_add_strbuf(doc, module, "param", &options->param); - - if (!ffStrbufEqual(&defaultOptions.text, &options->text)) - yyjson_mut_obj_add_strbuf(doc, module, "text", &options->text); + yyjson_mut_obj_add_strbuf(doc, module, "text", &options->text); } void ffGenerateCommandJsonResult(FF_MAYBE_UNUSED FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -152,22 +114,8 @@ void ffGenerateCommandJsonResult(FF_MAYBE_UNUSED FFCommandOptions* options, yyjs yyjson_mut_obj_add_strbuf(doc, module, "result", &result); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_COMMAND_MODULE_NAME, - .description = "Run custom shell scripts", - .parseCommandOptions = (void*) ffParseCommandCommandOptions, - .parseJsonObject = (void*) ffParseCommandJsonObject, - .printModule = (void*) ffPrintCommand, - .generateJsonResult = (void*) ffGenerateCommandJsonResult, - .generateJsonConfig = (void*) ffGenerateCommandJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Command result", "result"}, - })) -}; - void ffInitCommandOptions(FFCommandOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, ""); ffStrbufInitStatic(&options->shell, @@ -194,3 +142,17 @@ void ffDestroyCommandOptions(FFCommandOptions* options) ffStrbufDestroy(&options->param); ffStrbufDestroy(&options->text); } + +FFModuleBaseInfo ffCommandModuleInfo = { + .name = FF_COMMAND_MODULE_NAME, + .description = "Run custom shell scripts", + .initOptions = (void*) ffInitCommandOptions, + .destroyOptions = (void*) ffDestroyCommandOptions, + .parseJsonObject = (void*) ffParseCommandJsonObject, + .printModule = (void*) ffPrintCommand, + .generateJsonResult = (void*) ffGenerateCommandJsonResult, + .generateJsonConfig = (void*) ffGenerateCommandJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"Command result", "result"}, + })) +}; diff --git a/src/modules/command/command.h b/src/modules/command/command.h index 2464128019..dd28a8056f 100644 --- a/src/modules/command/command.h +++ b/src/modules/command/command.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_COMMAND_MODULE_NAME "Command" void ffPrintCommand(FFCommandOptions* options); void ffInitCommandOptions(FFCommandOptions* options); void ffDestroyCommandOptions(FFCommandOptions* options); + +extern FFModuleBaseInfo ffCommandModuleInfo; diff --git a/src/modules/command/option.h b/src/modules/command/option.h index d30c51ea87..62fbeb9818 100644 --- a/src/modules/command/option.h +++ b/src/modules/command/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFCommandOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf shell; FFstrbuf param; FFstrbuf text; } FFCommandOptions; + +static_assert(sizeof(FFCommandOptions) <= FF_OPTION_MAX_SIZE, "FFCommandOptions size exceeds maximum allowed size"); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 2511a6b04d..857cdd2ab9 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -81,7 +81,7 @@ void ffPrintCPU(FFCPUOptions* options) ffFreqAppendNum(freq, &str); } - if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET + if(cpu.temperature != FF_CPU_TEMP_UNSET) { ffStrbufAppendS(&str, " - "); ffTempsAppendNum(cpu.temperature, &str, options->tempConfig, &options->moduleArgs); @@ -117,68 +117,41 @@ void ffPrintCPU(FFCPUOptions* options) ffStrbufDestroy(&cpu.vendor); } -bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CPU_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffTempsParseCommandOptions(key, subKey, value, &options->temp, &options->tempConfig)) - return true; - - if (ffStrEqualsIgnCase(subKey, "show-pe-core-count")) - { - options->showPeCoreCount = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffTempsParseJsonObject(key, val, &options->temp, &options->tempConfig)) continue; - if (ffStrEqualsIgnCase(key, "freqNdigits")) + if (unsafe_yyjson_equals_str(key, "freqNdigits")) { ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits"); continue; } - if (ffStrEqualsIgnCase(key, "showPeCoreCount")) + if (unsafe_yyjson_equals_str(key, "showPeCoreCount")) { options->showPeCoreCount = yyjson_get_bool(val); continue; } - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCPUOptions))) FFCPUOptions defaultOptions; - ffInitCPUOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffTempsGenerateJsonConfig(doc, module, options->temp, options->tempConfig); - ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig); - - if (defaultOptions.showPeCoreCount != options->showPeCoreCount) - yyjson_mut_obj_add_bool(doc, module, "showPeCoreCount", options->showPeCoreCount); + yyjson_mut_obj_add_bool(doc, module, "showPeCoreCount", options->showPeCoreCount); } void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -228,17 +201,34 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, core, "freq", cpu.coreTypes[i].freq); } - yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); + if (cpu.temperature != FF_CPU_TEMP_UNSET) + yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); + else + yyjson_mut_obj_add_null(doc, obj, "temperature"); } ffStrbufDestroy(&cpu.name); ffStrbufDestroy(&cpu.vendor); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitCPUOptions(FFCPUOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + options->temp = false; + options->tempConfig = (FFColorRangeConfig) { 60, 80 }; + options->showPeCoreCount = false; +} + +void ffDestroyCPUOptions(FFCPUOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffCPUModuleInfo = { .name = FF_CPU_MODULE_NAME, .description = "Print CPU name, frequency, etc", - .parseCommandOptions = (void*) ffParseCPUCommandOptions, + .initOptions = (void*) ffInitCPUOptions, + .destroyOptions = (void*) ffDestroyCPUOptions, .parseJsonObject = (void*) ffParseCPUJsonObject, .printModule = (void*) ffPrintCPU, .generateJsonResult = (void*) ffGenerateCPUJsonResult, @@ -256,17 +246,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Processor package count", "packages"}, })) }; - -void ffInitCPUOptions(FFCPUOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - options->temp = false; - options->tempConfig = (FFColorRangeConfig) { 60, 80 }; - options->showPeCoreCount = false; -} - -void ffDestroyCPUOptions(FFCPUOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/cpu/cpu.h b/src/modules/cpu/cpu.h index 1db4efbf72..c6be135006 100644 --- a/src/modules/cpu/cpu.h +++ b/src/modules/cpu/cpu.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CPU_MODULE_NAME "CPU" void ffPrintCPU(FFCPUOptions* options); void ffInitCPUOptions(FFCPUOptions* options); void ffDestroyCPUOptions(FFCPUOptions* options); + +extern FFModuleBaseInfo ffCPUModuleInfo; diff --git a/src/modules/cpu/option.h b/src/modules/cpu/option.h index af2c87a3f7..e0948af2eb 100644 --- a/src/modules/cpu/option.h +++ b/src/modules/cpu/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFCPUOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool temp; FFColorRangeConfig tempConfig; bool showPeCoreCount; } FFCPUOptions; + +static_assert(sizeof(FFCPUOptions) <= FF_OPTION_MAX_SIZE, "FFCPUOptions size exceeds maximum allowed size"); diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 64eaa06124..aeb9422b4e 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -132,51 +132,30 @@ void ffPrintCPUCache(FFCPUCacheOptions* options) ffListDestroy(&result.caches[3]); } -bool ffParseCPUCacheCommandOptions(FFCPUCacheOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CPUCACHE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "compact")) - { - options->compact = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParseCPUCacheJsonObject(FFCPUCacheOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "compact")) + if (unsafe_yyjson_equals_str(key, "compact")) { options->compact = yyjson_get_bool(val); continue; } - ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateCPUCacheJsonConfig(FFCPUCacheOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCPUCacheOptions))) FFCPUCacheOptions defaultOptions; - ffInitCPUCacheOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); } void ffGenerateCPUCacheJsonResult(FF_MAYBE_UNUSED FFCPUCacheOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -228,23 +207,8 @@ void ffGenerateCPUCacheJsonResult(FF_MAYBE_UNUSED FFCPUCacheOptions* options, yy ffListDestroy(&result.caches[3]); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_CPUCACHE_MODULE_NAME, - .description = "Print CPU cache sizes", - .parseCommandOptions = (void*) ffParseCPUCacheCommandOptions, - .parseJsonObject = (void*) ffParseCPUCacheJsonObject, - .printModule = (void*) ffPrintCPUCache, - .generateJsonResult = (void*) ffGenerateCPUCacheJsonResult, - .generateJsonConfig = (void*) ffGenerateCPUCacheJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Separate result", "result"}, - {"Sum result", "sum"}, - })) -}; - void ffInitCPUCacheOptions(FFCPUCacheOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, ""); options->compact = false; @@ -254,3 +218,18 @@ void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); } + +FFModuleBaseInfo ffCPUCacheModuleInfo = { + .name = FF_CPUCACHE_MODULE_NAME, + .description = "Print CPU cache sizes", + .initOptions = (void*) ffInitCPUCacheOptions, + .destroyOptions = (void*) ffDestroyCPUCacheOptions, + .parseJsonObject = (void*) ffParseCPUCacheJsonObject, + .printModule = (void*) ffPrintCPUCache, + .generateJsonResult = (void*) ffGenerateCPUCacheJsonResult, + .generateJsonConfig = (void*) ffGenerateCPUCacheJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"Separate result", "result"}, + {"Sum result", "sum"}, + })) +}; diff --git a/src/modules/cpucache/cpucache.h b/src/modules/cpucache/cpucache.h index c6d5d8ef64..22987a8571 100644 --- a/src/modules/cpucache/cpucache.h +++ b/src/modules/cpucache/cpucache.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CPUCACHE_MODULE_NAME "CPUCache" void ffPrintCPUCache(FFCPUCacheOptions* options); void ffInitCPUCacheOptions(FFCPUCacheOptions* options); void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options); + +extern FFModuleBaseInfo ffCPUCacheModuleInfo; diff --git a/src/modules/cpucache/option.h b/src/modules/cpucache/option.h index f3e65eef7a..f53acf6913 100644 --- a/src/modules/cpucache/option.h +++ b/src/modules/cpucache/option.h @@ -1,13 +1,12 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFCPUCacheOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool compact; } FFCPUCacheOptions; + +static_assert(sizeof(FFCPUCacheOptions) <= FF_OPTION_MAX_SIZE, "FFCPUCacheOptions size exceeds maximum allowed size"); diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 6d15261eb1..a86f78e209 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -116,51 +116,22 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) } } -bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CPUUSAGE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "separate")) - { - options->separate = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "wait-time")) - { - options->waitTime = ffOptionParseUInt32(key, value); - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "separate")) + if (unsafe_yyjson_equals_str(key, "separate")) { options->separate = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "waitTime")) + if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); continue; @@ -169,21 +140,19 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateCPUUsageJsonConfig(FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCPUUsageOptions))) FFCPUUsageOptions defaultOptions; - ffInitCPUUsageOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "separate", options->separate); - if (options->separate != defaultOptions.separate) - yyjson_mut_obj_add_bool(doc, module, "separate", options->separate); + ffPercentGenerateJsonConfig(doc, module, options->percent); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); } void ffGenerateCPUUsageJsonResult(FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -203,10 +172,24 @@ void ffGenerateCPUUsageJsonResult(FFCPUUsageOptions* options, yyjson_mut_doc* do } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitCPUUsageOptions(FFCPUUsageOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰓅"); + options->separate = false; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; + options->waitTime = 200; +} + +void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffCPUUsageModuleInfo = { .name = FF_CPUUSAGE_MODULE_NAME, .description = "Print CPU usage. Costs some time to collect data", - .parseCommandOptions = (void*) ffParseCPUUsageCommandOptions, + .initOptions = (void*) ffInitCPUUsageOptions, + .destroyOptions = (void*) ffDestroyCPUUsageOptions, .parseJsonObject = (void*) ffParseCPUUsageJsonObject, .printModule = (void*) ffPrintCPUUsage, .generateJsonResult = (void*) ffGenerateCPUUsageJsonResult, @@ -222,17 +205,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"CPU usage (percentage bar, minimum)", "min-bar"}, })) }; - -void ffInitCPUUsageOptions(FFCPUUsageOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰓅"); - options->separate = false; - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; - options->waitTime = 200; -} - -void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/cpuusage/cpuusage.h b/src/modules/cpuusage/cpuusage.h index bbd74f085c..221e747784 100644 --- a/src/modules/cpuusage/cpuusage.h +++ b/src/modules/cpuusage/cpuusage.h @@ -1,6 +1,6 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CPUUSAGE_MODULE_NAME "CPUUsage" @@ -9,3 +9,5 @@ void ffPrepareCPUUsage(); void ffPrintCPUUsage(FFCPUUsageOptions* options); void ffInitCPUUsageOptions(FFCPUUsageOptions* options); void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options); + +extern FFModuleBaseInfo ffCPUUsageModuleInfo; diff --git a/src/modules/cpuusage/option.h b/src/modules/cpuusage/option.h index 9f65f701d1..dc19fbe76e 100644 --- a/src/modules/cpuusage/option.h +++ b/src/modules/cpuusage/option.h @@ -1,16 +1,15 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFCPUUsageOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool separate; FFPercentageModuleConfig percent; uint32_t waitTime; // in ms } FFCPUUsageOptions; + +static_assert(sizeof(FFCPUUsageOptions) <= FF_OPTION_MAX_SIZE, "FFCPUUsageOptions size exceeds maximum allowed size"); diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 9652398b50..d8ce2c26e7 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -48,39 +48,22 @@ void ffPrintCursor(FFCursorOptions* options) ffStrbufDestroy(&result.size); } -bool ffParseCursorCommandOptions(FFCursorOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CURSOR_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateCursorJsonConfig(FFCursorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCursorOptions))) FFCursorOptions defaultOptions; - ffInitCursorOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateCursorJsonResult(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -108,10 +91,21 @@ void ffGenerateCursorJsonResult(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson ffStrbufDestroy(&result.size); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitCursorOptions(FFCursorOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰆿"); +} + +void ffDestroyCursorOptions(FFCursorOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffCursorModuleInfo = { .name = FF_CURSOR_MODULE_NAME, .description = "Print cursor style name", - .parseCommandOptions = (void*) ffParseCursorCommandOptions, + .initOptions = (void*) ffInitCursorOptions, + .destroyOptions = (void*) ffDestroyCursorOptions, .parseJsonObject = (void*) ffParseCursorJsonObject, .printModule = (void*) ffPrintCursor, .generateJsonResult = (void*) ffGenerateCursorJsonResult, @@ -121,14 +115,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Cursor size", "size"}, })), }; - -void ffInitCursorOptions(FFCursorOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰆿"); -} - -void ffDestroyCursorOptions(FFCursorOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/cursor/cursor.h b/src/modules/cursor/cursor.h index 939033682d..c74031cfab 100644 --- a/src/modules/cursor/cursor.h +++ b/src/modules/cursor/cursor.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CURSOR_MODULE_NAME "Cursor" void ffPrintCursor(FFCursorOptions* options); void ffInitCursorOptions(FFCursorOptions* options); void ffDestroyCursorOptions(FFCursorOptions* options); + +extern FFModuleBaseInfo ffCursorModuleInfo; diff --git a/src/modules/cursor/option.h b/src/modules/cursor/option.h index 26c2bb9f4e..3f02c567cc 100644 --- a/src/modules/cursor/option.h +++ b/src/modules/cursor/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFCursorOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFCursorOptions; + +static_assert(sizeof(FFCursorOptions) <= FF_OPTION_MAX_SIZE, "FFCursorOptions size exceeds maximum allowed size"); diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index b0f3175746..4c2b8137d3 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -9,53 +9,26 @@ void ffPrintCustom(FFCustomOptions* options) ffPrintFormat(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {})); } -bool ffParseCustomCommandOptions(FFCustomOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_CUSTOM_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffGenerateCustomJsonConfig(FFCustomOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyCustomOptions))) FFCustomOptions defaultOptions; - ffInitCustomOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffParseCustomJsonObject(FFCustomOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_CUSTOM_MODULE_NAME, - .description = "Print a custom string, with or without key", - .parseCommandOptions = (void*) ffParseCustomCommandOptions, - .parseJsonObject = (void*) ffParseCustomJsonObject, - .printModule = (void*) ffPrintCustom, - .generateJsonConfig = (void*) ffGenerateCustomJsonConfig, -}; - void ffInitCustomOptions(FFCustomOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, ""); ffStrbufSetStatic(&options->moduleArgs.key, " "); } @@ -64,3 +37,13 @@ void ffDestroyCustomOptions(FFCustomOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); } + +FFModuleBaseInfo ffCustomModuleInfo = { + .name = FF_CUSTOM_MODULE_NAME, + .description = "Print a custom string, with or without key", + .initOptions = (void*) ffInitCustomOptions, + .destroyOptions = (void*) ffDestroyCustomOptions, + .parseJsonObject = (void*) ffParseCustomJsonObject, + .printModule = (void*) ffPrintCustom, + .generateJsonConfig = (void*) ffGenerateCustomJsonConfig, +}; diff --git a/src/modules/custom/custom.h b/src/modules/custom/custom.h index 172fe9ea36..f4dfefab0c 100644 --- a/src/modules/custom/custom.h +++ b/src/modules/custom/custom.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_CUSTOM_MODULE_NAME "Custom" void ffPrintCustom(FFCustomOptions* options); void ffInitCustomOptions(FFCustomOptions* options); void ffDestroyCustomOptions(FFCustomOptions* options); + +extern FFModuleBaseInfo ffCustomModuleInfo; diff --git a/src/modules/custom/option.h b/src/modules/custom/option.h index b0776a833a..c66ccee7d8 100644 --- a/src/modules/custom/option.h +++ b/src/modules/custom/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFCustomOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFCustomOptions; + +static_assert(sizeof(FFCustomOptions) <= FF_OPTION_MAX_SIZE, "FFCustomOptions size exceeds maximum allowed size"); diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 06bca8d605..213b3bfdcc 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -117,39 +117,22 @@ void ffPrintDateTime(FFDateTimeOptions* options) puts(buffer); } -bool ffParseDateTimeCommandOptions(FFDateTimeOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_DATETIME_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateDateTimeJsonConfig(FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyDateTimeOptions))) FFDateTimeOptions defaultOptions; - ffInitDateTimeOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateDateTimeJsonResult(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -157,10 +140,21 @@ void ffGenerateDateTimeJsonResult(FF_MAYBE_UNUSED FFDateTimeOptions* options, yy yyjson_mut_obj_add_strcpy(doc, module, "result", ffTimeToFullStr(ffTimeGetNow())); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitDateTimeOptions(FFDateTimeOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyDateTimeOptions(FFDateTimeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffDateTimeModuleInfo = { .name = FF_DATETIME_MODULE_NAME, .description = "Print current date and time", - .parseCommandOptions = (void*) ffParseDateTimeCommandOptions, + .initOptions = (void*) ffInitDateTimeOptions, + .destroyOptions = (void*) ffDestroyDateTimeOptions, .parseJsonObject = (void*) ffParseDateTimeJsonObject, .printModule = (void*) ffPrintDateTime, .generateJsonResult = (void*) ffGenerateDateTimeJsonResult, @@ -191,14 +185,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Day in month with leading zero", "day-pretty"}, })) }; - -void ffInitDateTimeOptions(FFDateTimeOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyDateTimeOptions(FFDateTimeOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/datetime/datetime.h b/src/modules/datetime/datetime.h index b169e73d1f..bdf8f732d6 100644 --- a/src/modules/datetime/datetime.h +++ b/src/modules/datetime/datetime.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_DATETIME_MODULE_NAME "DateTime" void ffPrintDateTime(FFDateTimeOptions* options); void ffInitDateTimeOptions(FFDateTimeOptions* options); void ffDestroyDateTimeOptions(FFDateTimeOptions* options); + +extern FFModuleBaseInfo ffDateTimeModuleInfo; diff --git a/src/modules/datetime/option.h b/src/modules/datetime/option.h index f9d25cfe39..fffd5dc51d 100644 --- a/src/modules/datetime/option.h +++ b/src/modules/datetime/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFDateTimeOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFDateTimeOptions; + +static_assert(sizeof(FFDateTimeOptions) <= FF_OPTION_MAX_SIZE, "FFDateTimeOptions size exceeds maximum allowed size"); diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 341e03e2c0..ac901566db 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -42,54 +42,30 @@ void ffPrintDE(FFDEOptions* options) } } -bool ffParseDECommandOptions(FFDEOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_DE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "slow-version-detection")) - { - options->slowVersionDetection = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "slowVersionDetection")) + if (unsafe_yyjson_equals_str(key, "slowVersionDetection")) { options->slowVersionDetection = yyjson_get_bool(val); continue; } - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateDEJsonConfig(FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyDEOptions))) FFDEOptions defaultOptions; - ffInitDEOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (defaultOptions.slowVersionDetection != options->slowVersionDetection) - yyjson_mut_obj_add_bool(doc, module, "slowVersionDetection", options->slowVersionDetection); + yyjson_mut_obj_add_bool(doc, module, "slowVersionDetection", options->slowVersionDetection); } void ffGenerateDEJsonResult(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -111,10 +87,23 @@ void ffGenerateDEJsonResult(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "version", &version); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitDEOptions(FFDEOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->slowVersionDetection = false; +} + +void ffDestroyDEOptions(FFDEOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffDEModuleInfo = { .name = FF_DE_MODULE_NAME, .description = "Print desktop environment name", - .parseCommandOptions = (void*) ffParseDECommandOptions, + .initOptions = (void*) ffInitDEOptions, + .destroyOptions = (void*) ffDestroyDEOptions, .parseJsonObject = (void*) ffParseDEJsonObject, .printModule = (void*) ffPrintDE, .generateJsonResult = (void*) ffGenerateDEJsonResult, @@ -125,16 +114,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"DE version", "version"}, })) }; - -void ffInitDEOptions(FFDEOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - - options->slowVersionDetection = false; -} - -void ffDestroyDEOptions(FFDEOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/de/de.h b/src/modules/de/de.h index 01cc458aae..ca945380bd 100644 --- a/src/modules/de/de.h +++ b/src/modules/de/de.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_DE_MODULE_NAME "DE" void ffPrintDE(FFDEOptions* options); void ffInitDEOptions(FFDEOptions* options); void ffDestroyDEOptions(FFDEOptions* options); + +extern FFModuleBaseInfo ffDEModuleInfo; diff --git a/src/modules/de/option.h b/src/modules/de/option.h index f94797666b..c587a0c96b 100644 --- a/src/modules/de/option.h +++ b/src/modules/de/option.h @@ -1,13 +1,12 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFDEOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool slowVersionDetection; } FFDEOptions; + +static_assert(sizeof(FFDEOptions) <= FF_OPTION_MAX_SIZE, "FFDEOptions size exceeds maximum allowed size"); diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 1596b3861a..ea74e4ef3b 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -203,132 +203,43 @@ void ffPrintDisk(FFDiskOptions* options) } } -bool ffParseDiskCommandOptions(FFDiskOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_DISK_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "folders")) - { - ffOptionParseString(key, value, &options->folders); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "hide-folders")) - { - ffOptionParseString(key, value, &options->hideFolders); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "hide-fs")) - { - ffOptionParseString(key, value, &options->hideFS); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-regular")) - { - if (ffOptionParseBoolean(value)) - options->showTypes |= FF_DISK_VOLUME_TYPE_REGULAR_BIT; - else - options->showTypes &= ~FF_DISK_VOLUME_TYPE_REGULAR_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-external")) - { - if (ffOptionParseBoolean(value)) - options->showTypes |= FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; - else - options->showTypes &= ~FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-hidden")) - { - if (ffOptionParseBoolean(value)) - options->showTypes |= FF_DISK_VOLUME_TYPE_HIDDEN_BIT; - else - options->showTypes &= ~FF_DISK_VOLUME_TYPE_HIDDEN_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-subvolumes")) - { - if (ffOptionParseBoolean(value)) - options->showTypes |= FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; - else - options->showTypes &= ~FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-readonly")) - { - if (ffOptionParseBoolean(value)) - options->showTypes |= FF_DISK_VOLUME_TYPE_READONLY_BIT; - else - options->showTypes &= ~FF_DISK_VOLUME_TYPE_READONLY_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-unknown")) - { - if (ffOptionParseBoolean(value)) - options->showTypes |= FF_DISK_VOLUME_TYPE_UNKNOWN_BIT; - else - options->showTypes &= ~FF_DISK_VOLUME_TYPE_UNKNOWN_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "use-available")) - { - if (ffOptionParseBoolean(value)) - options->calcType = FF_DISK_CALC_TYPE_AVAILABLE; - else - options->calcType = FF_DISK_CALC_TYPE_FREE; - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + if (unsafe_yyjson_equals_str(key, "folders")) + { + ffStrbufSetJsonVal(&options->folders, val); continue; + } - if (ffStrEqualsIgnCase(key, "folders")) + if (unsafe_yyjson_equals_str(key, "hideFolders")) { - ffStrbufSetS(&options->folders, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->hideFolders, val); continue; } - if (ffStrEqualsIgnCase(key, "hideFolders")) + if (unsafe_yyjson_equals_str(key, "hideFS")) { - ffStrbufSetS(&options->hideFolders, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->hideFS, val); continue; } - if (ffStrEqualsIgnCase(key, "hideFS")) + if (unsafe_yyjson_equals_str(key, "showRegular")) { - ffStrbufSetS(&options->hideFS, yyjson_get_str(val)); + if (yyjson_get_bool(val)) + options->showTypes |= FF_DISK_VOLUME_TYPE_REGULAR_BIT; + else + options->showTypes &= ~FF_DISK_VOLUME_TYPE_REGULAR_BIT; continue; } - if (ffStrEqualsIgnCase(key, "showExternal")) + if (unsafe_yyjson_equals_str(key, "showExternal")) { if (yyjson_get_bool(val)) options->showTypes |= FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; @@ -337,7 +248,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showHidden")) + if (unsafe_yyjson_equals_str(key, "showHidden")) { if (yyjson_get_bool(val)) options->showTypes |= FF_DISK_VOLUME_TYPE_HIDDEN_BIT; @@ -346,7 +257,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showSubvolumes")) + if (unsafe_yyjson_equals_str(key, "showSubvolumes")) { if (yyjson_get_bool(val)) options->showTypes |= FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; @@ -355,7 +266,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showReadOnly")) + if (unsafe_yyjson_equals_str(key, "showReadOnly")) { if (yyjson_get_bool(val)) options->showTypes |= FF_DISK_VOLUME_TYPE_READONLY_BIT; @@ -364,7 +275,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showUnknown")) + if (unsafe_yyjson_equals_str(key, "showUnknown")) { if (yyjson_get_bool(val)) options->showTypes |= FF_DISK_VOLUME_TYPE_UNKNOWN_BIT; @@ -373,7 +284,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "useAvailable")) + if (unsafe_yyjson_equals_str(key, "useAvailable")) { if (yyjson_get_bool(val)) options->calcType = FF_DISK_CALC_TYPE_AVAILABLE; @@ -385,48 +296,35 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateDiskJsonConfig(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyDiskOptions))) FFDiskOptions defaultOptions; - ffInitDiskOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "showRegular", !!(options->showTypes & FF_DISK_VOLUME_TYPE_REGULAR_BIT)); - if (defaultOptions.showTypes != options->showTypes) - { - if (options->showTypes & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT) - yyjson_mut_obj_add_bool(doc, module, "showExternal", true); + yyjson_mut_obj_add_bool(doc, module, "showExternal", !!(options->showTypes & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT)); - if (options->showTypes & FF_DISK_VOLUME_TYPE_HIDDEN_BIT) - yyjson_mut_obj_add_bool(doc, module, "showHidden", true); + yyjson_mut_obj_add_bool(doc, module, "showHidden", !!(options->showTypes & FF_DISK_VOLUME_TYPE_HIDDEN_BIT)); - if (options->showTypes & FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT) - yyjson_mut_obj_add_bool(doc, module, "showSubvolumes", true); + yyjson_mut_obj_add_bool(doc, module, "showSubvolumes", !!(options->showTypes & FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT)); - if (options->showTypes & FF_DISK_VOLUME_TYPE_READONLY_BIT) - yyjson_mut_obj_add_bool(doc, module, "showReadOnly", true); + yyjson_mut_obj_add_bool(doc, module, "showReadOnly", !!(options->showTypes & FF_DISK_VOLUME_TYPE_READONLY_BIT)); - if (options->showTypes & FF_DISK_VOLUME_TYPE_UNKNOWN_BIT) - yyjson_mut_obj_add_bool(doc, module, "showUnknown", true); - } + yyjson_mut_obj_add_bool(doc, module, "showUnknown", !!(options->showTypes & FF_DISK_VOLUME_TYPE_UNKNOWN_BIT)); - if (!ffStrbufEqual(&options->folders, &defaultOptions.folders)) - yyjson_mut_obj_add_strbuf(doc, module, "folders", &options->folders); + yyjson_mut_obj_add_strbuf(doc, module, "folders", &options->folders); - if (!ffStrbufEqual(&options->hideFolders, &defaultOptions.hideFolders)) - yyjson_mut_obj_add_strbuf(doc, module, "hideFolders", &options->hideFolders); + yyjson_mut_obj_add_strbuf(doc, module, "hideFolders", &options->hideFolders); - if (!ffStrbufEqual(&options->hideFS, &defaultOptions.hideFS)) - yyjson_mut_obj_add_strbuf(doc, module, "hideFS", &options->hideFS); + yyjson_mut_obj_add_strbuf(doc, module, "hideFS", &options->hideFS); - if (defaultOptions.calcType != options->calcType) - yyjson_mut_obj_add_bool(doc, module, "useAvailable", options->calcType == FF_DISK_CALC_TYPE_AVAILABLE); + yyjson_mut_obj_add_bool(doc, module, "useAvailable", options->calcType == FF_DISK_CALC_TYPE_AVAILABLE); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -498,10 +396,35 @@ void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitDiskOptions(FFDiskOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + + ffStrbufInit(&options->folders); + #if _WIN32 || __APPLE__ || __ANDROID__ + ffStrbufInit(&options->hideFolders); + #else + ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware"); + #endif + ffStrbufInit(&options->hideFS); + options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT; + options->calcType = FF_DISK_CALC_TYPE_FREE; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; +} + +void ffDestroyDiskOptions(FFDiskOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->folders); + ffStrbufDestroy(&options->hideFolders); + ffStrbufDestroy(&options->hideFS); +} + +FFModuleBaseInfo ffDiskModuleInfo = { .name = FF_DISK_MODULE_NAME, .description = "Print partitions, space usage, file system, etc", - .parseCommandOptions = (void*) ffParseDiskCommandOptions, + .initOptions = (void*) ffInitDiskOptions, + .destroyOptions = (void*) ffDestroyDiskOptions, .parseJsonObject = (void*) ffParseDiskJsonObject, .printModule = (void*) ffPrintDisk, .generateJsonResult = (void*) ffGenerateDiskJsonResult, @@ -533,28 +456,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Years fraction after creation", "years-fraction"}, })) }; - -void ffInitDiskOptions(FFDiskOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - - ffStrbufInit(&options->folders); - #if _WIN32 || __APPLE__ || __ANDROID__ - ffStrbufInit(&options->hideFolders); - #else - ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware"); - #endif - ffStrbufInit(&options->hideFS); - options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT; - options->calcType = FF_DISK_CALC_TYPE_FREE; - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; -} - -void ffDestroyDiskOptions(FFDiskOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); - ffStrbufDestroy(&options->folders); - ffStrbufDestroy(&options->hideFolders); - ffStrbufDestroy(&options->hideFS); -} diff --git a/src/modules/disk/disk.h b/src/modules/disk/disk.h index e21531eaed..c96155fe13 100644 --- a/src/modules/disk/disk.h +++ b/src/modules/disk/disk.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_DISK_MODULE_NAME "Disk" void ffPrintDisk(FFDiskOptions* options); void ffInitDiskOptions(FFDiskOptions* options); void ffDestroyDiskOptions(FFDiskOptions* options); + +extern FFModuleBaseInfo ffDiskModuleInfo; diff --git a/src/modules/disk/option.h b/src/modules/disk/option.h index 427e159f9f..f4ec16f935 100644 --- a/src/modules/disk/option.h +++ b/src/modules/disk/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" @@ -25,7 +23,6 @@ typedef enum __attribute__((__packed__)) FFDiskCalcType typedef struct FFDiskOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf folders; @@ -35,3 +32,5 @@ typedef struct FFDiskOptions FFDiskCalcType calcType; FFPercentageModuleConfig percent; } FFDiskOptions; + +static_assert(sizeof(FFDiskOptions) <= FF_OPTION_MAX_SIZE, "FFDiskOptions size exceeds maximum allowed size"); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 19af8eb3c9..5fa60982e6 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -95,81 +95,46 @@ void ffPrintDiskIO(FFDiskIOOptions* options) } } -bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_DISKIO_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "name-prefix")) - { - ffOptionParseString(key, value, &options->namePrefix); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "detect-total")) - { - options->detectTotal = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "wait-time")) - { - options->waitTime = ffOptionParseUInt32(key, value); - return true; - } - - return false; -} - void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "namePrefix")) + if (unsafe_yyjson_equals_str(key, "namePrefix")) { - ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->namePrefix, val); continue; } - if (ffStrEqualsIgnCase(key, "detectTotal")) + if (unsafe_yyjson_equals_str(key, "detectTotal")) { options->detectTotal = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "waitTime")) + if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); continue; } - ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateDiskIOJsonConfig(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions defaultOptions; - ffInitDiskIOOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); - if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix)) - yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); + yyjson_mut_obj_add_bool(doc, module, "detectTotal", options->detectTotal); - if (defaultOptions.detectTotal != options->detectTotal) - yyjson_mut_obj_add_bool(doc, module, "detectTotal", options->detectTotal); + yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); } void ffGenerateDiskIOJsonResult(FFDiskIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -202,10 +167,26 @@ void ffGenerateDiskIOJsonResult(FFDiskIOOptions* options, yyjson_mut_doc* doc, y } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitDiskIOOptions(FFDiskIOOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰓅"); + + ffStrbufInit(&options->namePrefix); + options->detectTotal = false; + options->waitTime = 1000; +} + +void ffDestroyDiskIOOptions(FFDiskIOOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); +} + +FFModuleBaseInfo ffDiskIOModuleInfo = { .name = FF_DISKIO_MODULE_NAME, .description = "Print physical disk I/O throughput", - .parseCommandOptions = (void*) ffParseDiskIOCommandOptions, + .initOptions = (void*) ffInitDiskIOOptions, + .destroyOptions = (void*) ffDestroyDiskIOOptions, .parseJsonObject = (void*) ffParseDiskIOJsonObject, .printModule = (void*) ffPrintDiskIO, .generateJsonResult = (void*) ffGenerateDiskIOJsonResult, @@ -221,19 +202,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Number of writes", "write-count"}, })) }; - -void ffInitDiskIOOptions(FFDiskIOOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰓅"); - - ffStrbufInit(&options->namePrefix); - options->detectTotal = false; - options->waitTime = 1000; -} - -void ffDestroyDiskIOOptions(FFDiskIOOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); - ffStrbufDestroy(&options->namePrefix); -} diff --git a/src/modules/diskio/diskio.h b/src/modules/diskio/diskio.h index b3fa27bde8..ba3977bae2 100644 --- a/src/modules/diskio/diskio.h +++ b/src/modules/diskio/diskio.h @@ -1,6 +1,6 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_DISKIO_MODULE_NAME "DiskIO" @@ -9,3 +9,5 @@ void ffPrepareDiskIO(FFDiskIOOptions* options); void ffPrintDiskIO(FFDiskIOOptions* options); void ffInitDiskIOOptions(FFDiskIOOptions* options); void ffDestroyDiskIOOptions(FFDiskIOOptions* options); + +extern FFModuleBaseInfo ffDiskIOModuleInfo; diff --git a/src/modules/diskio/option.h b/src/modules/diskio/option.h index c41e0428b5..5de458fa33 100644 --- a/src/modules/diskio/option.h +++ b/src/modules/diskio/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFDiskIOOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf namePrefix; uint32_t waitTime; bool detectTotal; } FFDiskIOOptions; + +static_assert(sizeof(FFDiskIOOptions) <= FF_OPTION_MAX_SIZE, "FFDiskIOOptions size exceeds maximum allowed size"); diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 437bc79f6f..33b48e9117 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -217,134 +217,106 @@ void ffPrintDisplay(FFDisplayOptions* options) } } -bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_DISPLAY_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "compact-type")) - { - options->compactType = (FFDisplayCompactType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "none", FF_DISPLAY_COMPACT_TYPE_NONE }, - { "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT }, - { "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT }, - { "original-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT }, - { "scaled-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT }, - {}, - }); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "precise-refresh-rate")) - { - options->preciseRefreshRate = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "order")) - { - options->order = (FFDisplayOrder) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "asc", FF_DISPLAY_ORDER_ASC }, - { "desc", FF_DISPLAY_ORDER_DESC }, - { "none", FF_DISPLAY_ORDER_NONE }, - {}, - }); - return true; - } - - return false; -} - void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "compactType")) + if (unsafe_yyjson_equals_str(key, "compactType")) { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "none", FF_DISPLAY_COMPACT_TYPE_NONE }, - { "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT }, - { "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT }, - { "original-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT }, - { "scaled-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT }, - {}, - }); - if (error) - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error); + if (yyjson_is_null(val)) + options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; else - options->compactType = (FFDisplayCompactType) value; + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "none", FF_DISPLAY_COMPACT_TYPE_NONE }, + { "original", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT }, + { "scaled", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT }, + { "original-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT }, + { "scaled-with-refresh-rate", FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT }, + {}, + }); + if (error) + ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + else + options->compactType = (FFDisplayCompactType) value; + } continue; } - if (ffStrEqualsIgnCase(key, "preciseRefreshRate")) + if (unsafe_yyjson_equals_str(key, "preciseRefreshRate")) { options->preciseRefreshRate = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "order")) + if (unsafe_yyjson_equals_str(key, "order")) { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "asc", FF_DISPLAY_ORDER_ASC }, - { "desc", FF_DISPLAY_ORDER_DESC }, - { "none", FF_DISPLAY_ORDER_NONE }, - {}, - }); - if (error) - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error); + if (yyjson_is_null(val)) + options->order = FF_DISPLAY_ORDER_NONE; else - options->order = (FFDisplayOrder) value; + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "asc", FF_DISPLAY_ORDER_ASC }, + { "desc", FF_DISPLAY_ORDER_DESC }, + { "none", FF_DISPLAY_ORDER_NONE }, + {}, + }); + if (error) + ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + else + options->order = (FFDisplayOrder) value; + } continue; } - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateDisplayJsonConfig(FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyDisplayOptions))) FFDisplayOptions defaultOptions; - ffInitDisplayOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (options->compactType != defaultOptions.compactType) + switch ((int) options->compactType) { - switch ((int) options->compactType) - { - case FF_DISPLAY_COMPACT_TYPE_NONE: - yyjson_mut_obj_add_str(doc, module, "compactType", "none"); - break; - case FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT: - yyjson_mut_obj_add_str(doc, module, "compactType", "original"); - break; - case FF_DISPLAY_COMPACT_TYPE_SCALED_BIT: - yyjson_mut_obj_add_str(doc, module, "compactType", "scaled"); - break; - case FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT: - yyjson_mut_obj_add_str(doc, module, "compactType", "original-with-refresh-rate"); - break; - case FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT: - yyjson_mut_obj_add_str(doc, module, "compactType", "scaled-with-refresh-rate"); - break; - } + case FF_DISPLAY_COMPACT_TYPE_NONE: + yyjson_mut_obj_add_str(doc, module, "compactType", "none"); + break; + case FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT: + yyjson_mut_obj_add_str(doc, module, "compactType", "original"); + break; + case FF_DISPLAY_COMPACT_TYPE_SCALED_BIT: + yyjson_mut_obj_add_str(doc, module, "compactType", "scaled"); + break; + case FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT: + yyjson_mut_obj_add_str(doc, module, "compactType", "original-with-refresh-rate"); + break; + case FF_DISPLAY_COMPACT_TYPE_SCALED_BIT | FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT: + yyjson_mut_obj_add_str(doc, module, "compactType", "scaled-with-refresh-rate"); + break; } - if (options->preciseRefreshRate != defaultOptions.preciseRefreshRate) - yyjson_mut_obj_add_bool(doc, module, "preciseRefreshRate", options->preciseRefreshRate); + yyjson_mut_obj_add_bool(doc, module, "preciseRefreshRate", options->preciseRefreshRate); + + switch (options->order) + { + case FF_DISPLAY_ORDER_NONE: + yyjson_mut_obj_add_null(doc, module, "order"); + break; + case FF_DISPLAY_ORDER_ASC: + yyjson_mut_obj_add_str(doc, module, "order", "asc"); + break; + case FF_DISPLAY_ORDER_DESC: + yyjson_mut_obj_add_str(doc, module, "order", "desc"); + break; + } } void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -436,10 +408,23 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitDisplayOptions(FFDisplayOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰍹"); + options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; + options->preciseRefreshRate = false; +} + +void ffDestroyDisplayOptions(FFDisplayOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffDisplayModuleInfo = { .name = FF_DISPLAY_MODULE_NAME, .description = "Print resolutions, refresh rates, etc", - .parseCommandOptions = (void*) ffParseDisplayCommandOptions, + .initOptions = (void*) ffInitDisplayOptions, + .destroyOptions = (void*) ffDestroyDisplayOptions, .parseJsonObject = (void*) ffParseDisplayJsonObject, .printModule = (void*) ffPrintDisplay, .generateJsonResult = (void*) ffGenerateDisplayJsonResult, @@ -471,16 +456,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Screen preferred refresh rate (in Hz)", "preferred-refresh-rate"}, })) }; - -void ffInitDisplayOptions(FFDisplayOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰍹"); - options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; - options->preciseRefreshRate = false; -} - -void ffDestroyDisplayOptions(FFDisplayOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/display/display.h b/src/modules/display/display.h index 7479295cf4..8b9f419418 100644 --- a/src/modules/display/display.h +++ b/src/modules/display/display.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_DISPLAY_MODULE_NAME "Display" void ffPrintDisplay(FFDisplayOptions* options); void ffInitDisplayOptions(FFDisplayOptions* options); void ffDestroyDisplayOptions(FFDisplayOptions* options); + +extern FFModuleBaseInfo ffDisplayModuleInfo; diff --git a/src/modules/display/option.h b/src/modules/display/option.h index 7233b2dd3f..12ad3c5ec2 100644 --- a/src/modules/display/option.h +++ b/src/modules/display/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef enum __attribute__((__packed__)) FFDisplayCompactType @@ -22,10 +20,11 @@ typedef enum __attribute__((__packed__)) FFDisplayOrder typedef struct FFDisplayOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFDisplayCompactType compactType; bool preciseRefreshRate; FFDisplayOrder order; } FFDisplayOptions; + +static_assert(sizeof(FFDisplayOptions) <= FF_OPTION_MAX_SIZE, "FFDisplayOptions size exceeds maximum allowed size"); diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index fc330a2f36..aa36ceacbe 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -57,41 +57,16 @@ void ffPrintDNS(FFDNSOptions* options) } } -bool ffParseDNSCommandOptions(FFDNSOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_DNS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "show-type")) - { - options->showType = (FFDNSShowType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "both", FF_DNS_TYPE_BOTH }, - { "ipv4", FF_DNS_TYPE_IPV4_BIT }, - { "ipv6", FF_DNS_TYPE_IPV6_BIT }, - {}, - }); - return true; - } - - return false; -} - void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "showType")) + if (unsafe_yyjson_equals_str(key, "showType")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -101,44 +76,35 @@ void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module) {}, }); if (error) - ffPrintError(FF_DNS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", key, error); + ffPrintError(FF_DNS_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); else options->showType = (FFDNSShowType) value; continue; } - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateDNSJsonConfig(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyDNSOptions))) FFDNSOptions defaultOptions; - ffInitDNSOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (defaultOptions.showType != options->showType) + switch ((uint8_t) options->showType) { - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch" // FF_DNS_TYPE_FORCE_UNSIGNED - switch (options->showType) - { - case FF_DNS_TYPE_IPV4_BIT: - yyjson_mut_obj_add_str(doc, module, "showType", "ipv4"); - break; - case FF_DNS_TYPE_IPV6_BIT: - yyjson_mut_obj_add_str(doc, module, "showType", "ipv6"); - break; - case FF_DNS_TYPE_BOTH: - yyjson_mut_obj_add_str(doc, module, "showType", "both"); - break; - } - #pragma GCC diagnostic pop + case FF_DNS_TYPE_IPV4_BIT: + yyjson_mut_obj_add_str(doc, module, "showType", "ipv4"); + break; + case FF_DNS_TYPE_IPV6_BIT: + yyjson_mut_obj_add_str(doc, module, "showType", "ipv6"); + break; + case FF_DNS_TYPE_BOTH: + yyjson_mut_obj_add_str(doc, module, "showType", "both"); + break; } } -void ffGenerateDNSJsonResult(FF_MAYBE_UNUSED FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateDNSJsonResult(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFstrbuf)); @@ -164,22 +130,8 @@ void ffGenerateDNSJsonResult(FF_MAYBE_UNUSED FFDNSOptions* options, yyjson_mut_d } } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_DNS_MODULE_NAME, - .description = "Print configured DNS servers", - .parseCommandOptions = (void*) ffParseDNSCommandOptions, - .parseJsonObject = (void*) ffParseDNSJsonObject, - .printModule = (void*) ffPrintDNS, - .generateJsonResult = (void*) ffGenerateDNSJsonResult, - .generateJsonConfig = (void*) ffGenerateDNSJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"DNS result", "result"}, - })) -}; - void ffInitDNSOptions(FFDNSOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, "󰇖"); options->showType = FF_DNS_TYPE_BOTH; @@ -189,3 +141,17 @@ void ffDestroyDNSOptions(FFDNSOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); } + +FFModuleBaseInfo ffDNSModuleInfo = { + .name = FF_DNS_MODULE_NAME, + .description = "Print configured DNS servers", + .initOptions = (void*) ffInitDNSOptions, + .destroyOptions = (void*) ffDestroyDNSOptions, + .parseJsonObject = (void*) ffParseDNSJsonObject, + .printModule = (void*) ffPrintDNS, + .generateJsonResult = (void*) ffGenerateDNSJsonResult, + .generateJsonConfig = (void*) ffGenerateDNSJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"DNS result", "result"}, + })) +}; diff --git a/src/modules/dns/dns.h b/src/modules/dns/dns.h index a26504d599..e337637751 100644 --- a/src/modules/dns/dns.h +++ b/src/modules/dns/dns.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_DNS_MODULE_NAME "DNS" void ffPrintDNS(FFDNSOptions* options); void ffInitDNSOptions(FFDNSOptions* options); void ffDestroyDNSOptions(FFDNSOptions* options); + +extern FFModuleBaseInfo ffDNSModuleInfo; diff --git a/src/modules/dns/option.h b/src/modules/dns/option.h index 18dbb147b1..bc3bd56903 100644 --- a/src/modules/dns/option.h +++ b/src/modules/dns/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef enum __attribute__((__packed__)) FFDNSShowType { @@ -13,8 +11,9 @@ typedef enum __attribute__((__packed__)) FFDNSShowType { typedef struct FFDNSOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFDNSShowType showType; } FFDNSOptions; + +static_assert(sizeof(FFDNSOptions) <= FF_OPTION_MAX_SIZE, "FFDNSOptions size exceeds maximum allowed size"); diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 42ff06a5ee..e001d22e88 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -54,39 +54,22 @@ void ffPrintEditor(FFEditorOptions* options) ffStrbufDestroy(&result.version); } -bool ffParseEditorCommandOptions(FFEditorOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_EDITOR_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseEditorJsonObject(FFEditorOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateEditorJsonConfig(FFEditorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyEditorOptions))) FFEditorOptions defaultOptions; - ffInitEditorOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateEditorJsonResult(FF_MAYBE_UNUSED FFEditorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -118,10 +101,21 @@ void ffGenerateEditorJsonResult(FF_MAYBE_UNUSED FFEditorOptions* options, yyjson ffStrbufDestroy(&result.version); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitEditorOptions(FFEditorOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󱞎"); +} + +void ffDestroyEditorOptions(FFEditorOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffEditorModuleInfo = { .name = FF_EDITOR_MODULE_NAME, .description = "Print information of the default editor ($VISUAL or $EDITOR)", - .parseCommandOptions = (void*) ffParseEditorCommandOptions, + .initOptions = (void*) ffInitEditorOptions, + .destroyOptions = (void*) ffDestroyEditorOptions, .parseJsonObject = (void*) ffParseEditorJsonObject, .printModule = (void*) ffPrintEditor, .generateJsonResult = (void*) ffGenerateEditorJsonResult, @@ -134,14 +128,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Version", "version"}, })) }; - -void ffInitEditorOptions(FFEditorOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󱞎"); -} - -void ffDestroyEditorOptions(FFEditorOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/editor/editor.h b/src/modules/editor/editor.h index c18c8f67db..0e5be29e1f 100644 --- a/src/modules/editor/editor.h +++ b/src/modules/editor/editor.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_EDITOR_MODULE_NAME "Editor" void ffPrintEditor(FFEditorOptions* options); void ffInitEditorOptions(FFEditorOptions* options); void ffDestroyEditorOptions(FFEditorOptions* options); + +extern FFModuleBaseInfo ffEditorModuleInfo; diff --git a/src/modules/editor/option.h b/src/modules/editor/option.h index 92503d6590..f7c545f84e 100644 --- a/src/modules/editor/option.h +++ b/src/modules/editor/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFEditorOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFEditorOptions; + +static_assert(sizeof(FFEditorOptions) <= FF_OPTION_MAX_SIZE, "FFEditorOptions size exceeds maximum allowed size"); diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 8efd244ca3..eedf32c4ea 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -41,39 +41,22 @@ void ffPrintFont(FFFontOptions* options) ffStrbufDestroy(&font.fonts[i]); } -bool ffParseFontCommandOptions(FFFontOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_FONT_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateFontJsonConfig(FFFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyFontOptions))) FFFontOptions defaultOptions; - ffInitFontOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateFontJsonResult(FF_MAYBE_UNUSED FFFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -102,10 +85,21 @@ void ffGenerateFontJsonResult(FF_MAYBE_UNUSED FFFontOptions* options, yyjson_mut ffStrbufDestroy(&font.fonts[i]); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitFontOptions(FFFontOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyFontOptions(FFFontOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffFontModuleInfo = { .name = FF_FONT_MODULE_NAME, .description = "Print system font names", - .parseCommandOptions = (void*) ffParseFontCommandOptions, + .initOptions = (void*) ffInitFontOptions, + .destroyOptions = (void*) ffDestroyFontOptions, .parseJsonObject = (void*) ffParseFontJsonObject, .printModule = (void*) ffPrintFont, .generateJsonResult = (void*) ffGenerateFontJsonResult, @@ -118,14 +112,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Combined fonts for display", "combined"}, })) }; - -void ffInitFontOptions(FFFontOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyFontOptions(FFFontOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/font/font.h b/src/modules/font/font.h index 01d78f0ec6..9d3630bd22 100644 --- a/src/modules/font/font.h +++ b/src/modules/font/font.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_FONT_MODULE_NAME "Font" void ffPrintFont(FFFontOptions* options); void ffInitFontOptions(FFFontOptions* options); void ffDestroyFontOptions(FFFontOptions* options); + +extern FFModuleBaseInfo ffFontModuleInfo; diff --git a/src/modules/font/option.h b/src/modules/font/option.h index 12552bcceb..6c942e7dd2 100644 --- a/src/modules/font/option.h +++ b/src/modules/font/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFFontOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFFontOptions; + +static_assert(sizeof(FFFontOptions) <= FF_OPTION_MAX_SIZE, "FFFontOptions size exceeds maximum allowed size"); diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 3bcc4f6f9a..5b1b6f7d5d 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -77,47 +77,27 @@ void ffPrintGamepad(FFGamepadOptions* options) } } -bool ffParseGamepadCommandOptions(FFGamepadOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_GAMEPAD_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateGamepadJsonConfig(FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyGamepadOptions))) FFGamepadOptions defaultOptions; - ffInitGamepadOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -147,10 +127,22 @@ void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitGamepadOptions(FFGamepadOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰺵"); + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; +} + +void ffDestroyGamepadOptions(FFGamepadOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffGamepadModuleInfo = { .name = FF_GAMEPAD_MODULE_NAME, .description = "List (connected) gamepads", - .parseCommandOptions = (void*) ffParseGamepadCommandOptions, + .initOptions = (void*) ffInitGamepadOptions, + .destroyOptions = (void*) ffDestroyGamepadOptions, .parseJsonObject = (void*) ffParseGamepadJsonObject, .printModule = (void*) ffPrintGamepad, .generateJsonResult = (void*) ffGenerateGamepadJsonResult, @@ -162,15 +154,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Battery percentage bar", "battery-percentage-bar"}, })) }; - -void ffInitGamepadOptions(FFGamepadOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰺵"); - options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; -} - -void ffDestroyGamepadOptions(FFGamepadOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/gamepad/gamepad.h b/src/modules/gamepad/gamepad.h index 309edd0a76..7d252d8c07 100644 --- a/src/modules/gamepad/gamepad.h +++ b/src/modules/gamepad/gamepad.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_GAMEPAD_MODULE_NAME "Gamepad" void ffPrintGamepad(FFGamepadOptions* options); void ffInitGamepadOptions(FFGamepadOptions* options); void ffDestroyGamepadOptions(FFGamepadOptions* options); + +extern FFModuleBaseInfo ffGamepadModuleInfo; diff --git a/src/modules/gamepad/option.h b/src/modules/gamepad/option.h index d1b570bf81..8640a0d7c8 100644 --- a/src/modules/gamepad/option.h +++ b/src/modules/gamepad/option.h @@ -1,13 +1,12 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFGamepadOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; } FFGamepadOptions; + +static_assert(sizeof(FFGamepadOptions) <= FF_OPTION_MAX_SIZE, "FFGamepadOptions size exceeds maximum allowed size"); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index f2f5806c78..d128ac6fbc 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -46,7 +46,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu ffFreqAppendNum(gpu->frequency, &output); } - if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET + if(gpu->temperature != FF_GPU_TEMP_UNSET) { ffStrbufAppendS(&output, " - "); ffTempsAppendNum(gpu->temperature, &output, options->tempConfig, &options->moduleArgs); @@ -126,7 +126,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FF_STRBUF_AUTO_DESTROY coreUsageNum = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY coreUsageBar = ffStrbufCreate(); - if (gpu->coreUsage == gpu->coreUsage) //FF_GPU_CORE_USAGE_UNSET + if (gpu->coreUsage != FF_GPU_CORE_USAGE_UNSET) { if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffPercentAppendNum(&coreUsageNum, gpu->coreUsage, options->percent, false, &options->moduleArgs); @@ -202,76 +202,25 @@ void ffPrintGPU(FFGPUOptions* options) } } -bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_GPU_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "driver-specific")) - { - options->driverSpecific = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "detection-method")) - { - options->detectionMethod = (FFGPUDetectionMethod) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "auto", FF_GPU_DETECTION_METHOD_AUTO }, - { "pci", FF_GPU_DETECTION_METHOD_PCI }, - { "vulkan", FF_GPU_DETECTION_METHOD_VULKAN }, - { "opencl", FF_GPU_DETECTION_METHOD_OPENCL }, - { "opengl", FF_GPU_DETECTION_METHOD_OPENGL }, - {}, - }); - return true; - } - - if (ffTempsParseCommandOptions(key, subKey, value, &options->temp, &options->tempConfig)) - return true; - - if (ffStrEqualsIgnCase(subKey, "hide-type")) - { - options->hideType = (FFGPUType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "none", FF_GPU_TYPE_NONE }, - { "unknown", FF_GPU_TYPE_UNKNOWN }, - { "integrated", FF_GPU_TYPE_INTEGRATED }, - { "discrete", FF_GPU_TYPE_DISCRETE }, - {}, - }); - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffTempsParseJsonObject(key, val, &options->temp, &options->tempConfig)) continue; - if (ffStrEqualsIgnCase(key, "driverSpecific")) + if (unsafe_yyjson_equals_str(key, "driverSpecific")) { options->driverSpecific = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "detectionMethod")) + if (unsafe_yyjson_equals_str(key, "detectionMethod")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -283,90 +232,85 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) {}, }); if (error) - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error); + ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); else options->detectionMethod = (FFGPUDetectionMethod) value; continue; } - if (ffStrEqualsIgnCase(key, "hideType")) + if (unsafe_yyjson_equals_str(key, "hideType")) { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "none", FF_GPU_TYPE_NONE }, - { "unknown", FF_GPU_TYPE_UNKNOWN }, - { "integrated", FF_GPU_TYPE_INTEGRATED }, - { "discrete", FF_GPU_TYPE_DISCRETE }, - {}, - }); - if (error) - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error); + if (yyjson_is_null(val)) + options->hideType = FF_GPU_TYPE_NONE; else - options->hideType = (FFGPUType) value; + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "none", FF_GPU_TYPE_NONE }, + { "unknown", FF_GPU_TYPE_UNKNOWN }, + { "integrated", FF_GPU_TYPE_INTEGRATED }, + { "discrete", FF_GPU_TYPE_DISCRETE }, + {}, + }); + if (error) + ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + else + options->hideType = (FFGPUType) value; + } continue; } if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyGPUOptions))) FFGPUOptions defaultOptions; - ffInitGPUOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - if (options->driverSpecific != defaultOptions.driverSpecific) - yyjson_mut_obj_add_bool(doc, module, "driverSpecific", options->driverSpecific); + yyjson_mut_obj_add_bool(doc, module, "driverSpecific", options->driverSpecific); - if (options->detectionMethod != defaultOptions.detectionMethod) + switch (options->detectionMethod) { - switch (options->detectionMethod) - { - case FF_GPU_DETECTION_METHOD_AUTO: - yyjson_mut_obj_add_str(doc, module, "detectionMethod", "auto"); - break; - case FF_GPU_DETECTION_METHOD_PCI: - yyjson_mut_obj_add_str(doc, module, "detectionMethod", "pci"); - break; - case FF_GPU_DETECTION_METHOD_VULKAN: - yyjson_mut_obj_add_str(doc, module, "detectionMethod", "vulkan"); - break; - case FF_GPU_DETECTION_METHOD_OPENCL: - yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opencl"); - break; - case FF_GPU_DETECTION_METHOD_OPENGL: - yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opengl"); - break; - } + case FF_GPU_DETECTION_METHOD_AUTO: + yyjson_mut_obj_add_str(doc, module, "detectionMethod", "auto"); + break; + case FF_GPU_DETECTION_METHOD_PCI: + yyjson_mut_obj_add_str(doc, module, "detectionMethod", "pci"); + break; + case FF_GPU_DETECTION_METHOD_VULKAN: + yyjson_mut_obj_add_str(doc, module, "detectionMethod", "vulkan"); + break; + case FF_GPU_DETECTION_METHOD_OPENCL: + yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opencl"); + break; + case FF_GPU_DETECTION_METHOD_OPENGL: + yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opengl"); + break; } - ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig); + ffTempsGenerateJsonConfig(doc, module, options->temp, options->tempConfig); - if (options->hideType != defaultOptions.hideType) + switch (options->hideType) { - switch (options->hideType) - { - case FF_GPU_TYPE_NONE: - yyjson_mut_obj_add_str(doc, module, "hideType", "none"); - break; - case FF_GPU_TYPE_UNKNOWN: - yyjson_mut_obj_add_str(doc, module, "hideType", "unknown"); - break; - case FF_GPU_TYPE_INTEGRATED: - yyjson_mut_obj_add_str(doc, module, "hideType", "integrated"); - break; - case FF_GPU_TYPE_DISCRETE: - yyjson_mut_obj_add_str(doc, module, "hideType", "discrete"); - break; - } + case FF_GPU_TYPE_NONE: + yyjson_mut_obj_add_str(doc, module, "hideType", "none"); + break; + case FF_GPU_TYPE_UNKNOWN: + yyjson_mut_obj_add_str(doc, module, "hideType", "unknown"); + break; + case FF_GPU_TYPE_INTEGRATED: + yyjson_mut_obj_add_str(doc, module, "hideType", "integrated"); + break; + case FF_GPU_TYPE_DISCRETE: + yyjson_mut_obj_add_str(doc, module, "hideType", "discrete"); + break; } - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -394,7 +338,10 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ else yyjson_mut_obj_add_null(doc, obj, "coreCount"); - yyjson_mut_obj_add_real(doc, obj, "coreUsage", gpu->coreUsage); + if (gpu->coreUsage != FF_GPU_CORE_USAGE_UNSET) + yyjson_mut_obj_add_real(doc, obj, "coreUsage", gpu->coreUsage); + else + yyjson_mut_obj_add_null(doc, obj, "coreUsage"); yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, obj, "memory"); @@ -427,7 +374,7 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_strbuf(doc, obj, "driver", &gpu->driver); yyjson_mut_obj_add_strbuf(doc, obj, "name", &gpu->name); - if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET + if(gpu->temperature != FF_GPU_TEMP_UNSET) yyjson_mut_obj_add_real(doc, obj, "temperature", gpu->temperature); else yyjson_mut_obj_add_null(doc, obj, "temperature"); @@ -445,7 +392,10 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi); - yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency); + if (gpu->frequency != FF_GPU_FREQUENCY_UNSET) + yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency); + else + yyjson_mut_obj_add_null(doc, obj, "frequency"); yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId); } @@ -460,10 +410,34 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitGPUOptions(FFGPUOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰾲"); + + options->driverSpecific = false; + options->detectionMethod = + #if defined(__x86_64__) || defined(__i386__) + FF_GPU_DETECTION_METHOD_PCI + #else + FF_GPU_DETECTION_METHOD_AUTO + #endif + ; + options->temp = false; + options->hideType = FF_GPU_TYPE_NONE; + options->tempConfig = (FFColorRangeConfig) { 60, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; +} + +void ffDestroyGPUOptions(FFGPUOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffGPUModuleInfo = { .name = FF_GPU_MODULE_NAME, .description = "Print GPU names, graphic memory size, type, etc", - .parseCommandOptions = (void*) ffParseGPUCommandOptions, + .initOptions = (void*) ffInitGPUOptions, + .destroyOptions = (void*) ffDestroyGPUOptions, .parseJsonObject = (void*) ffParseGPUJsonObject, .printModule = (void*) ffPrintGPU, .generateJsonResult = (void*) ffGenerateGPUJsonResult, @@ -491,27 +465,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Memory type (Windows only)", "memory-type"}, })), }; - -void ffInitGPUOptions(FFGPUOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰾲"); - - options->driverSpecific = false; - options->detectionMethod = - #if defined(__x86_64__) || defined(__i386__) - FF_GPU_DETECTION_METHOD_PCI - #else - FF_GPU_DETECTION_METHOD_AUTO - #endif - ; - options->temp = false; - options->hideType = FF_GPU_TYPE_NONE; - options->tempConfig = (FFColorRangeConfig) { 60, 80 }; - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; -} - -void ffDestroyGPUOptions(FFGPUOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/gpu/gpu.h b/src/modules/gpu/gpu.h index 36dbd441d7..afc952d6ce 100644 --- a/src/modules/gpu/gpu.h +++ b/src/modules/gpu/gpu.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_GPU_MODULE_NAME "GPU" void ffPrintGPU(FFGPUOptions* options); void ffInitGPUOptions(FFGPUOptions* options); void ffDestroyGPUOptions(FFGPUOptions* options); + +extern FFModuleBaseInfo ffGPUModuleInfo; diff --git a/src/modules/gpu/option.h b/src/modules/gpu/option.h index f88343770a..0d1d0fac8e 100644 --- a/src/modules/gpu/option.h +++ b/src/modules/gpu/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" @@ -24,14 +22,14 @@ typedef enum __attribute__((__packed__)) FFGPUDetectionMethod typedef struct FFGPUOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFGPUType hideType; FFGPUDetectionMethod detectionMethod; bool temp; bool driverSpecific; - bool forceMethod; FFColorRangeConfig tempConfig; FFPercentageModuleConfig percent; } FFGPUOptions; + +static_assert(sizeof(FFGPUOptions) <= FF_OPTION_MAX_SIZE, "FFGPUOptions size exceeds maximum allowed size"); diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 609521f77e..9a265c058a 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,39 +67,22 @@ void ffPrintHost(FFHostOptions* options) ffStrbufDestroy(&host.vendor); } -bool ffParseHostCommandOptions(FFHostOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_HOST_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateHostJsonConfig(FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyHostOptions))) FFHostOptions defaultOptions; - ffInitHostOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateHostJsonResult(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -145,10 +128,21 @@ void ffGenerateHostJsonResult(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut ffStrbufDestroy(&host.vendor); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitHostOptions(FFHostOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰌢"); +} + +void ffDestroyHostOptions(FFHostOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffHostModuleInfo = { .name = FF_HOST_MODULE_NAME, .description = "Print product name of your computer", - .parseCommandOptions = (void*) ffParseHostCommandOptions, + .initOptions = (void*) ffInitHostOptions, + .destroyOptions = (void*) ffDestroyHostOptions, .parseJsonObject = (void*) ffParseHostJsonObject, .printModule = (void*) ffPrintHost, .generateJsonResult = (void*) ffGenerateHostJsonResult, @@ -163,14 +157,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Product uuid", "uuid"}, })) }; - -void ffInitHostOptions(FFHostOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰌢"); -} - -void ffDestroyHostOptions(FFHostOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/host/host.h b/src/modules/host/host.h index 780849bf28..79f22e5272 100644 --- a/src/modules/host/host.h +++ b/src/modules/host/host.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_HOST_MODULE_NAME "Host" void ffPrintHost(FFHostOptions* options); void ffInitHostOptions(FFHostOptions* options); void ffDestroyHostOptions(FFHostOptions* options); + +extern FFModuleBaseInfo ffHostModuleInfo; diff --git a/src/modules/host/option.h b/src/modules/host/option.h index 1c6bf26f34..2516f864c7 100644 --- a/src/modules/host/option.h +++ b/src/modules/host/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFHostOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFHostOptions; + +static_assert(sizeof(FFHostOptions) <= FF_OPTION_MAX_SIZE, "FFHostOptions size exceeds maximum allowed size"); diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 3c0dd98db2..c1347790e3 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -43,39 +43,22 @@ void ffPrintIcons(FFIconsOptions* options) ffStrbufDestroy(&result.icons2); } -bool ffParseIconsCommandOptions(FFIconsOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_ICONS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateIconsJsonConfig(FFIconsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyIconsOptions))) FFIconsOptions defaultOptions; - ffInitIconsOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateIconsJsonResult(FF_MAYBE_UNUSED FFIconsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -100,10 +83,21 @@ void ffGenerateIconsJsonResult(FF_MAYBE_UNUSED FFIconsOptions* options, yyjson_m ffStrbufDestroy(&result.icons2); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitIconsOptions(FFIconsOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyIconsOptions(FFIconsOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffIconsModuleInfo = { .name = FF_ICONS_MODULE_NAME, .description = "Print icon style name", - .parseCommandOptions = (void*) ffParseIconsCommandOptions, + .initOptions = (void*) ffInitIconsOptions, + .destroyOptions = (void*) ffDestroyIconsOptions, .parseJsonObject = (void*) ffParseIconsJsonObject, .printModule = (void*) ffPrintIcons, .generateJsonResult = (void*) ffGenerateIconsJsonResult, @@ -113,14 +107,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Icons part 2", "icons2"}, })) }; - -void ffInitIconsOptions(FFIconsOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyIconsOptions(FFIconsOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/icons/icons.h b/src/modules/icons/icons.h index d31a83a9aa..6f2bb877cc 100644 --- a/src/modules/icons/icons.h +++ b/src/modules/icons/icons.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_ICONS_MODULE_NAME "Icons" void ffPrintIcons(FFIconsOptions* options); void ffInitIconsOptions(FFIconsOptions* options); void ffDestroyIconsOptions(FFIconsOptions* options); + +extern FFModuleBaseInfo ffIconsModuleInfo; diff --git a/src/modules/icons/option.h b/src/modules/icons/option.h index 456668796f..966bba5f5f 100644 --- a/src/modules/icons/option.h +++ b/src/modules/icons/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFIconsOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFIconsOptions; + +static_assert(sizeof(FFIconsOptions) <= FF_OPTION_MAX_SIZE, "FFIconsOptions size exceeds maximum allowed size"); diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index 38b8ece011..28ad9ba80b 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -48,39 +48,22 @@ void ffPrintInitSystem(FFInitSystemOptions* options) ffStrbufDestroy(&result.version); } -bool ffParseInitSystemCommandOptions(FFInitSystemOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_INITSYSTEM_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseInitSystemJsonObject(FFInitSystemOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateInitSystemJsonConfig(FFInitSystemOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyInitSystemOptions))) FFInitSystemOptions defaultOptions; - ffInitInitSystemOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateInitSystemJsonResult(FF_MAYBE_UNUSED FFInitSystemOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -112,10 +95,21 @@ void ffGenerateInitSystemJsonResult(FF_MAYBE_UNUSED FFInitSystemOptions* options ffStrbufDestroy(&result.version); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitInitSystemOptions(FFInitSystemOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰿄"); +} + +void ffDestroyInitSystemOptions(FFInitSystemOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffInitSystemModuleInfo = { .name = FF_INITSYSTEM_MODULE_NAME, .description = "Print init system (pid 1) name and version", - .parseCommandOptions = (void*) ffParseInitSystemCommandOptions, + .initOptions = (void*) ffInitInitSystemOptions, + .destroyOptions = (void*) ffDestroyInitSystemOptions, .parseJsonObject = (void*) ffParseInitSystemJsonObject, .printModule = (void*) ffPrintInitSystem, .generateJsonResult = (void*) ffGenerateInitSystemJsonResult, @@ -127,14 +121,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Init system pid", "pid"}, })) }; - -void ffInitInitSystemOptions(FFInitSystemOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰿄"); -} - -void ffDestroyInitSystemOptions(FFInitSystemOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/initsystem/initsystem.h b/src/modules/initsystem/initsystem.h index 718f6691b6..37b601481b 100644 --- a/src/modules/initsystem/initsystem.h +++ b/src/modules/initsystem/initsystem.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_INITSYSTEM_MODULE_NAME "InitSystem" void ffPrintInitSystem(FFInitSystemOptions* options); void ffInitInitSystemOptions(FFInitSystemOptions* options); void ffDestroyInitSystemOptions(FFInitSystemOptions* options); + +extern FFModuleBaseInfo ffInitSystemModuleInfo; diff --git a/src/modules/initsystem/option.h b/src/modules/initsystem/option.h index aa46206709..54c10158ed 100644 --- a/src/modules/initsystem/option.h +++ b/src/modules/initsystem/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFInitSystemOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFInitSystemOptions; + +static_assert(sizeof(FFInitSystemOptions) <= FF_OPTION_MAX_SIZE, "FFInitSystemOptions size exceeds maximum allowed size"); diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index d747e67528..042ef3735a 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -32,39 +32,22 @@ void ffPrintKernel(FFKernelOptions* options) } } -bool ffParseKernelCommandOptions(FFKernelOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_KERNEL_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateKernelJsonConfig(FFKernelOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyKernelOptions))) FFKernelOptions defaultOptions; - ffInitKernelOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateKernelJsonResult(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -80,10 +63,21 @@ void ffGenerateKernelJsonResult(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson yyjson_mut_obj_add_uint(doc, obj, "pageSize", info->pageSize); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitKernelOptions(FFKernelOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyKernelOptions(FFKernelOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffKernelModuleInfo = { .name = FF_KERNEL_MODULE_NAME, .description = "Print system kernel version", - .parseCommandOptions = (void*) ffParseKernelCommandOptions, + .initOptions = (void*) ffInitKernelOptions, + .destroyOptions = (void*) ffDestroyKernelOptions, .parseJsonObject = (void*) ffParseKernelJsonObject, .printModule = (void*) ffPrintKernel, .generateJsonResult = (void*) ffGenerateKernelJsonResult, @@ -97,14 +91,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Page size", "page-size"}, })) }; - -void ffInitKernelOptions(FFKernelOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyKernelOptions(FFKernelOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/kernel/kernel.h b/src/modules/kernel/kernel.h index c1a6be8568..743ac21487 100644 --- a/src/modules/kernel/kernel.h +++ b/src/modules/kernel/kernel.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_KERNEL_MODULE_NAME "Kernel" void ffPrintKernel(FFKernelOptions* options); void ffInitKernelOptions(FFKernelOptions* options); void ffDestroyKernelOptions(FFKernelOptions* options); + +extern FFModuleBaseInfo ffKernelModuleInfo; diff --git a/src/modules/kernel/option.h b/src/modules/kernel/option.h index fd3cb17a3c..2b2b27d7e3 100644 --- a/src/modules/kernel/option.h +++ b/src/modules/kernel/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFKernelOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFKernelOptions; + +static_assert(sizeof(FFKernelOptions) <= FF_OPTION_MAX_SIZE, "FFKernelOptions size exceeds maximum allowed size"); diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index e48e533dfb..ed67bf5696 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -48,39 +48,22 @@ void ffPrintKeyboard(FFKeyboardOptions* options) } } -bool ffParseKeyboardCommandOptions(FFKeyboardOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_KEYBOARD_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateKeyboardJsonConfig(FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyKeyboardOptions))) FFKeyboardOptions defaultOptions; - ffInitKeyboardOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -110,10 +93,21 @@ void ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitKeyboardOptions(FFKeyboardOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyKeyboardOptions(FFKeyboardOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffKeyboardModuleInfo = { .name = FF_KEYBOARD_MODULE_NAME, .description = "List (connected) keyboards", - .parseCommandOptions = (void*) ffParseKeyboardCommandOptions, + .initOptions = (void*) ffInitKeyboardOptions, + .destroyOptions = (void*) ffDestroyKeyboardOptions, .parseJsonObject = (void*) ffParseKeyboardJsonObject, .printModule = (void*) ffPrintKeyboard, .generateJsonResult = (void*) ffGenerateKeyboardJsonResult, @@ -123,14 +117,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Serial number", "serial"}, })) }; - -void ffInitKeyboardOptions(FFKeyboardOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyKeyboardOptions(FFKeyboardOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/keyboard/keyboard.h b/src/modules/keyboard/keyboard.h index b54a3ccba9..fee46ccb1e 100644 --- a/src/modules/keyboard/keyboard.h +++ b/src/modules/keyboard/keyboard.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_KEYBOARD_MODULE_NAME "Keyboard" void ffPrintKeyboard(FFKeyboardOptions* options); void ffInitKeyboardOptions(FFKeyboardOptions* options); void ffDestroyKeyboardOptions(FFKeyboardOptions* options); + +extern FFModuleBaseInfo ffKeyboardModuleInfo; diff --git a/src/modules/keyboard/option.h b/src/modules/keyboard/option.h index 4f39eee19e..b65de5ceb1 100644 --- a/src/modules/keyboard/option.h +++ b/src/modules/keyboard/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFKeyboardOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFKeyboardOptions; + +static_assert(sizeof(FFKeyboardOptions) <= FF_OPTION_MAX_SIZE, "FFKeyboardOptions size exceeds maximum allowed size"); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 5dc29dd3b9..df67aa076f 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -47,39 +47,22 @@ void ffPrintLM(FFLMOptions* options) ffStrbufDestroy(&result.version); } -bool ffParseLMCommandOptions(FFLMOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_LM_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateLMJsonConfig(FFLMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyLMOptions))) FFLMOptions defaultOptions; - ffInitLMOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateLMJsonResult(FF_MAYBE_UNUSED FFLMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -113,10 +96,21 @@ void ffGenerateLMJsonResult(FF_MAYBE_UNUSED FFLMOptions* options, yyjson_mut_doc ffStrbufDestroy(&result.version); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitLMOptions(FFLMOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰧨"); +} + +void ffDestroyLMOptions(FFLMOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffLMModuleInfo = { .name = FF_LM_MODULE_NAME, .description = "Print login manager (desktop manager) name and version", - .parseCommandOptions = (void*) ffParseLMCommandOptions, + .initOptions = (void*) ffInitLMOptions, + .destroyOptions = (void*) ffDestroyLMOptions, .parseJsonObject = (void*) ffParseLMJsonObject, .printModule = (void*) ffPrintLM, .generateJsonResult = (void*) ffGenerateLMJsonResult, @@ -127,14 +121,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"LM version", "version"}, })) }; - -void ffInitLMOptions(FFLMOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰧨"); -} - -void ffDestroyLMOptions(FFLMOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/lm/lm.h b/src/modules/lm/lm.h index f6e1569e11..950ca6ad1d 100644 --- a/src/modules/lm/lm.h +++ b/src/modules/lm/lm.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_LM_MODULE_NAME "LM" void ffPrintLM(FFLMOptions* options); void ffInitLMOptions(FFLMOptions* options); void ffDestroyLMOptions(FFLMOptions* options); + +extern FFModuleBaseInfo ffLMModuleInfo; diff --git a/src/modules/lm/option.h b/src/modules/lm/option.h index 4255382ff0..21a4ad8b72 100644 --- a/src/modules/lm/option.h +++ b/src/modules/lm/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFLMOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFLMOptions; + +static_assert(sizeof(FFLMOptions) <= FF_OPTION_MAX_SIZE, "FFLMOptions size exceeds maximum allowed size"); diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 2a02f935af..8d1d76ead9 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -90,51 +90,22 @@ void ffPrintLoadavg(FFLoadavgOptions* options) } } -bool ffParseLoadavgCommandOptions(FFLoadavgOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_LOADAVG_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "ndigits")) - { - options->ndigits = (uint8_t) ffOptionParseUInt32(key, value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "compact")) - { - options->compact = ffOptionParseBoolean(value); - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "ndigits")) + if (unsafe_yyjson_equals_str(key, "ndigits")) { options->ndigits = (uint8_t) yyjson_get_uint(val); continue; } - if (ffStrEqualsIgnCase(key, "compact")) + if (unsafe_yyjson_equals_str(key, "compact")) { options->compact = yyjson_get_bool(val); continue; @@ -143,24 +114,19 @@ void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module) if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateLoadavgJsonConfig(FFLoadavgOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyLoadavgOptions))) FFLoadavgOptions defaultOptions; - ffInitLoadavgOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_uint(doc, module, "ndigits", options->ndigits); - if (defaultOptions.ndigits != options->ndigits) - yyjson_mut_obj_add_uint(doc, module, "ndigits", options->ndigits); + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); - if (defaultOptions.compact != options->compact) - yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); - - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateLoadavgJsonResult(FF_MAYBE_UNUSED FFLoadavgOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -179,24 +145,8 @@ void ffGenerateLoadavgJsonResult(FF_MAYBE_UNUSED FFLoadavgOptions* options, yyjs yyjson_mut_arr_add_real(doc, arr, result[i]); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_LOADAVG_MODULE_NAME, - .description = "Print system load averages", - .parseCommandOptions = (void*) ffParseLoadavgCommandOptions, - .parseJsonObject = (void*) ffParseLoadavgJsonObject, - .printModule = (void*) ffPrintLoadavg, - .generateJsonResult = (void*) ffGenerateLoadavgJsonResult, - .generateJsonConfig = (void*) ffGenerateLoadavgJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Load average over 1min", "loadavg1"}, - {"Load average over 5min", "loadavg2"}, - {"Load average over 15min", "loadavg3"}, - })) -}; - void ffInitLoadavgOptions(FFLoadavgOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, ""); options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; @@ -208,3 +158,19 @@ void ffDestroyLoadavgOptions(FFLoadavgOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); } + +FFModuleBaseInfo ffLoadavgModuleInfo = { + .name = FF_LOADAVG_MODULE_NAME, + .description = "Print system load averages", + .initOptions = (void*) ffInitLoadavgOptions, + .destroyOptions = (void*) ffDestroyLoadavgOptions, + .parseJsonObject = (void*) ffParseLoadavgJsonObject, + .printModule = (void*) ffPrintLoadavg, + .generateJsonResult = (void*) ffGenerateLoadavgJsonResult, + .generateJsonConfig = (void*) ffGenerateLoadavgJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"Load average over 1min", "loadavg1"}, + {"Load average over 5min", "loadavg2"}, + {"Load average over 15min", "loadavg3"}, + })) +}; diff --git a/src/modules/loadavg/loadavg.h b/src/modules/loadavg/loadavg.h index 1d546f57be..8ee495bf83 100644 --- a/src/modules/loadavg/loadavg.h +++ b/src/modules/loadavg/loadavg.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_LOADAVG_MODULE_NAME "Loadavg" void ffPrintLoadavg(FFLoadavgOptions* options); void ffInitLoadavgOptions(FFLoadavgOptions* options); void ffDestroyLoadavgOptions(FFLoadavgOptions* options); + +extern FFModuleBaseInfo ffLoadavgModuleInfo; diff --git a/src/modules/loadavg/option.h b/src/modules/loadavg/option.h index aee5f435cf..947b310db1 100644 --- a/src/modules/loadavg/option.h +++ b/src/modules/loadavg/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFLoadavgOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; uint8_t ndigits; bool compact; } FFLoadavgOptions; + +static_assert(sizeof(FFLoadavgOptions) <= FF_OPTION_MAX_SIZE, "FFLoadavgOptions size exceeds maximum allowed size"); diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index ba82b32350..1dc81d3424 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -28,39 +28,22 @@ void ffPrintLocale(FFLocaleOptions* options) } } -bool ffParseLocaleCommandOptions(FFLocaleOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_LOCALE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateLocaleJsonConfig(FFLocaleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyLocaleOptions))) FFLocaleOptions defaultOptions; - ffInitLocaleOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateLocaleJsonResult(FF_MAYBE_UNUSED FFLocaleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -77,10 +60,21 @@ void ffGenerateLocaleJsonResult(FF_MAYBE_UNUSED FFLocaleOptions* options, yyjson yyjson_mut_obj_add_strbuf(doc, module, "result", &locale); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitLocaleOptions(FFLocaleOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyLocaleOptions(FFLocaleOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffLocaleModuleInfo = { .name = FF_LOCALE_MODULE_NAME, .description = "Print system locale name", - .parseCommandOptions = (void*) ffParseLocaleCommandOptions, + .initOptions = (void*) ffInitLocaleOptions, + .destroyOptions = (void*) ffDestroyLocaleOptions, .parseJsonObject = (void*) ffParseLocaleJsonObject, .printModule = (void*) ffPrintLocale, .generateJsonResult = (void*) ffGenerateLocaleJsonResult, @@ -89,14 +83,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Locale code", "result"}, })) }; - -void ffInitLocaleOptions(FFLocaleOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyLocaleOptions(FFLocaleOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/locale/locale.h b/src/modules/locale/locale.h index c1fe3f8f70..a56a612ae1 100644 --- a/src/modules/locale/locale.h +++ b/src/modules/locale/locale.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_LOCALE_MODULE_NAME "Locale" void ffPrintLocale(FFLocaleOptions* options); void ffInitLocaleOptions(FFLocaleOptions* options); void ffDestroyLocaleOptions(FFLocaleOptions* options); + +extern FFModuleBaseInfo ffLocaleModuleInfo; diff --git a/src/modules/locale/option.h b/src/modules/locale/option.h index c6ba96720c..236d61ee3a 100644 --- a/src/modules/locale/option.h +++ b/src/modules/locale/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFLocaleOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFLocaleOptions; + +static_assert(sizeof(FFLocaleOptions) <= FF_OPTION_MAX_SIZE, "FFLocaleOptions size exceeds maximum allowed size"); diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 4c98b1d6f6..b6edad8794 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -178,135 +178,16 @@ void ffPrintLocalIp(FFLocalIpOptions* options) } } -bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_LOCALIP_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "show-ipv4")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_IPV4_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_IPV4_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-ipv6")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_IPV6_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_IPV6_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-mac")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_MAC_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_MAC_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-loop")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_LOOP_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_LOOP_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-prefix-len")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_PREFIX_LEN_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_PREFIX_LEN_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-mtu")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_MTU_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_MTU_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-speed")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_SPEED_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_SPEED_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-flags")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_FLAGS_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_FLAGS_BIT; - return true; - } - - if(ffStrEqualsIgnCase(subKey, "compact")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_COMPACT_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_COMPACT_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "default-route-only")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "show-all-ips")) - { - if (ffOptionParseBoolean(value)) - options->showType |= FF_LOCALIP_TYPE_ALL_IPS_BIT; - else - options->showType &= ~FF_LOCALIP_TYPE_ALL_IPS_BIT; - return true; - } - - if (ffStrEqualsIgnCase(subKey, "name-prefix")) - { - ffOptionParseString(key, value, &options->namePrefix); - return true; - } - - return false; -} - void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "showIpv4")) + if (unsafe_yyjson_equals_str(key, "showIpv4")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_IPV4_BIT; @@ -315,7 +196,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showIpv6")) + if (unsafe_yyjson_equals_str(key, "showIpv6")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_IPV6_BIT; @@ -324,7 +205,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showMac")) + if (unsafe_yyjson_equals_str(key, "showMac")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_MAC_BIT; @@ -333,7 +214,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showLoop")) + if (unsafe_yyjson_equals_str(key, "showLoop")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_LOOP_BIT; @@ -342,7 +223,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showPrefixLen")) + if (unsafe_yyjson_equals_str(key, "showPrefixLen")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_PREFIX_LEN_BIT; @@ -351,7 +232,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showMtu")) + if (unsafe_yyjson_equals_str(key, "showMtu")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_MTU_BIT; @@ -360,7 +241,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showSpeed")) + if (unsafe_yyjson_equals_str(key, "showSpeed")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_SPEED_BIT; @@ -369,7 +250,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showFlags")) + if (unsafe_yyjson_equals_str(key, "showFlags")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_FLAGS_BIT; @@ -378,7 +259,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "compact")) + if (unsafe_yyjson_equals_str(key, "compact")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_COMPACT_BIT; @@ -387,7 +268,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "defaultRouteOnly")) + if (unsafe_yyjson_equals_str(key, "defaultRouteOnly")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT; @@ -396,7 +277,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "showAllIps")) + if (unsafe_yyjson_equals_str(key, "showAllIps")) { if (yyjson_get_bool(val)) options->showType |= FF_LOCALIP_TYPE_ALL_IPS_BIT; @@ -405,61 +286,43 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "namePrefix")) + if (unsafe_yyjson_equals_str(key, "namePrefix")) { - ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->namePrefix, val); continue; } - ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateLocalIpJsonConfig(FFLocalIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyLocalIpOptions))) FFLocalIpOptions defaultOptions; - ffInitLocalIpOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - if (defaultOptions.showType != options->showType) - { - if (!(options->showType & FF_LOCALIP_TYPE_IPV4_BIT)) - yyjson_mut_obj_add_bool(doc, module, "showIpv4", false); + yyjson_mut_obj_add_bool(doc, module, "showIpv4", !!(options->showType & FF_LOCALIP_TYPE_IPV4_BIT)); - if (options->showType & FF_LOCALIP_TYPE_IPV6_BIT) - yyjson_mut_obj_add_bool(doc, module, "showIpv6", true); + yyjson_mut_obj_add_bool(doc, module, "showIpv6", !!(options->showType & FF_LOCALIP_TYPE_IPV6_BIT)); - if (options->showType & FF_LOCALIP_TYPE_MAC_BIT) - yyjson_mut_obj_add_bool(doc, module, "showMac", true); + yyjson_mut_obj_add_bool(doc, module, "showMac", !!(options->showType & FF_LOCALIP_TYPE_MAC_BIT)); - if (options->showType & FF_LOCALIP_TYPE_LOOP_BIT) - yyjson_mut_obj_add_bool(doc, module, "showLoop", true); + yyjson_mut_obj_add_bool(doc, module, "showLoop", !!(options->showType & FF_LOCALIP_TYPE_LOOP_BIT)); - if (options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) - yyjson_mut_obj_add_bool(doc, module, "showPrefixLen", true); + yyjson_mut_obj_add_bool(doc, module, "showPrefixLen", !!(options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT)); - if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) - yyjson_mut_obj_add_bool(doc, module, "showMtu", true); + yyjson_mut_obj_add_bool(doc, module, "showMtu", !!(options->showType & FF_LOCALIP_TYPE_MTU_BIT)); - if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT) - yyjson_mut_obj_add_bool(doc, module, "showSpeed", true); + yyjson_mut_obj_add_bool(doc, module, "showSpeed", !!(options->showType & FF_LOCALIP_TYPE_SPEED_BIT)); - if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) - yyjson_mut_obj_add_bool(doc, module, "showFlags", true); + yyjson_mut_obj_add_bool(doc, module, "showFlags", !!(options->showType & FF_LOCALIP_TYPE_FLAGS_BIT)); - if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT) - yyjson_mut_obj_add_bool(doc, module, "compact", true); + yyjson_mut_obj_add_bool(doc, module, "compact", !!(options->showType & FF_LOCALIP_TYPE_COMPACT_BIT)); - if (!(options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT)) - yyjson_mut_obj_add_bool(doc, module, "defaultRouteOnly", false); + yyjson_mut_obj_add_bool(doc, module, "defaultRouteOnly", !!(options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT)); - if (options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT) - yyjson_mut_obj_add_bool(doc, module, "showAllIps", true); - } + yyjson_mut_obj_add_bool(doc, module, "showAllIps", !!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); - if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix)) - yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); + yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); } void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -504,29 +367,8 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs } } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_LOCALIP_MODULE_NAME, - .description = "List local IP addresses (v4 or v6), MAC addresses, etc", - .parseCommandOptions = (void*) ffParseLocalIpCommandOptions, - .parseJsonObject = (void*) ffParseLocalIpJsonObject, - .printModule = (void*) ffPrintLocalIp, - .generateJsonResult = (void*) ffGenerateLocalIpJsonResult, - .generateJsonConfig = (void*) ffGenerateLocalIpJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"IPv4 address", "ipv4"}, - {"IPv6 address", "ipv6"}, - {"MAC address", "mac"}, - {"Interface name", "ifname"}, - {"Is default route", "is-default-route"}, - {"MTU size in bytes", "mtu"}, - {"Link speed (formatted)", "speed"}, - {"Interface flags", "flags"}, - })) -}; - void ffInitLocalIpOptions(FFLocalIpOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, "󰩟"); options->showType = FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_PREFIX_LEN_BIT @@ -542,3 +384,24 @@ void ffDestroyLocalIpOptions(FFLocalIpOptions* options) ffOptionDestroyModuleArg(&options->moduleArgs); ffStrbufDestroy(&options->namePrefix); } + +FFModuleBaseInfo ffLocalIPModuleInfo = { + .name = FF_LOCALIP_MODULE_NAME, + .description = "List local IP addresses (v4 or v6), MAC addresses, etc", + .initOptions = (void*) ffInitLocalIpOptions, + .destroyOptions = (void*) ffDestroyLocalIpOptions, + .parseJsonObject = (void*) ffParseLocalIpJsonObject, + .printModule = (void*) ffPrintLocalIp, + .generateJsonResult = (void*) ffGenerateLocalIpJsonResult, + .generateJsonConfig = (void*) ffGenerateLocalIpJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"IPv4 address", "ipv4"}, + {"IPv6 address", "ipv6"}, + {"MAC address", "mac"}, + {"Interface name", "ifname"}, + {"Is default route", "is-default-route"}, + {"MTU size in bytes", "mtu"}, + {"Link speed (formatted)", "speed"}, + {"Interface flags", "flags"}, + })) +}; diff --git a/src/modules/localip/localip.h b/src/modules/localip/localip.h index 1ac2559793..6164699752 100644 --- a/src/modules/localip/localip.h +++ b/src/modules/localip/localip.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_LOCALIP_MODULE_NAME "LocalIp" void ffPrintLocalIp(FFLocalIpOptions* options); void ffInitLocalIpOptions(FFLocalIpOptions* options); void ffDestroyLocalIpOptions(FFLocalIpOptions* options); + +extern FFModuleBaseInfo ffLocalIPModuleInfo; diff --git a/src/modules/localip/option.h b/src/modules/localip/option.h index c95b77d8b3..b809fe2fab 100644 --- a/src/modules/localip/option.h +++ b/src/modules/localip/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef enum __attribute__((__packed__)) FFLocalIpType @@ -25,9 +23,10 @@ static_assert(sizeof(FFLocalIpType) == sizeof(uint16_t), ""); typedef struct FFLocalIpOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFLocalIpType showType; FFstrbuf namePrefix; } FFLocalIpOptions; + +static_assert(sizeof(FFLocalIpOptions) <= FF_OPTION_MAX_SIZE, "FFLocalIpOptions size exceeds maximum allowed size"); diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 08e446e544..1a175008ff 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -106,39 +106,22 @@ void ffPrintMedia(FFMediaOptions* options) } } -bool ffParseMediaCommandOptions(FFMediaOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_MEDIA_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateMediaJsonConfig(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyMediaOptions))) FFMediaOptions defaultOptions; - ffInitMediaOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateMediaJsonResult(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -165,10 +148,21 @@ void ffGenerateMediaJsonResult(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_m yyjson_mut_obj_add_strbuf(doc, player, "url", &media->url); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitMediaOptions(FFMediaOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyMediaOptions(FFMediaOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffMediaModuleInfo = { .name = FF_MEDIA_MODULE_NAME, .description = "Print playing song name", - .parseCommandOptions = (void*) ffParseMediaCommandOptions, + .initOptions = (void*) ffInitMediaOptions, + .destroyOptions = (void*) ffDestroyMediaOptions, .parseJsonObject = (void*) ffParseMediaJsonObject, .printModule = (void*) ffPrintMedia, .generateJsonResult = (void*) ffGenerateMediaJsonResult, @@ -181,14 +175,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Status", "status"}, })) }; - -void ffInitMediaOptions(FFMediaOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyMediaOptions(FFMediaOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/media/media.h b/src/modules/media/media.h index 7c010b1fef..af18735b9b 100644 --- a/src/modules/media/media.h +++ b/src/modules/media/media.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_MEDIA_MODULE_NAME "Media" void ffPrintMedia(FFMediaOptions* options); void ffInitMediaOptions(FFMediaOptions* options); void ffDestroyMediaOptions(FFMediaOptions* options); + +extern FFModuleBaseInfo ffMediaModuleInfo; diff --git a/src/modules/media/option.h b/src/modules/media/option.h index cb57b8b6e8..e90ee854f7 100644 --- a/src/modules/media/option.h +++ b/src/modules/media/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFMediaOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFMediaOptions; + +static_assert(sizeof(FFMediaOptions) <= FF_OPTION_MAX_SIZE, "FFMediaOptions size exceeds maximum allowed size"); diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index deac7ef91d..659c440134 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -71,47 +71,27 @@ void ffPrintMemory(FFMemoryOptions* options) } } -bool ffParseMemoryCommandOptions(FFMemoryOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_MEMORY_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateMemoryJsonConfig(FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyMemoryOptions))) FFMemoryOptions defaultOptions; - ffInitMemoryOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateMemoryJsonResult(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -130,10 +110,22 @@ void ffGenerateMemoryJsonResult(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitMemoryOptions(FFMemoryOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; +} + +void ffDestroyMemoryOptions(FFMemoryOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffMemoryModuleInfo = { .name = FF_MEMORY_MODULE_NAME, .description = "Print system memory usage info", - .parseCommandOptions = (void*) ffParseMemoryCommandOptions, + .initOptions = (void*) ffInitMemoryOptions, + .destroyOptions = (void*) ffDestroyMemoryOptions, .parseJsonObject = (void*) ffParseMemoryJsonObject, .printModule = (void*) ffPrintMemory, .generateJsonResult = (void*) ffGenerateMemoryJsonResult, @@ -145,15 +137,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Percentage used (bar)", "percentage-bar"}, })) }; - -void ffInitMemoryOptions(FFMemoryOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; -} - -void ffDestroyMemoryOptions(FFMemoryOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/memory/memory.h b/src/modules/memory/memory.h index dcef5e50d9..5c43b4f759 100644 --- a/src/modules/memory/memory.h +++ b/src/modules/memory/memory.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_MEMORY_MODULE_NAME "Memory" void ffPrintMemory(FFMemoryOptions* options); void ffInitMemoryOptions(FFMemoryOptions* options); void ffDestroyMemoryOptions(FFMemoryOptions* options); + +extern FFModuleBaseInfo ffMemoryModuleInfo; diff --git a/src/modules/memory/option.h b/src/modules/memory/option.h index 76fc9fd06d..243847f5ff 100644 --- a/src/modules/memory/option.h +++ b/src/modules/memory/option.h @@ -1,14 +1,13 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFMemoryOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; } FFMemoryOptions; + +static_assert(sizeof(FFMemoryOptions) <= FF_OPTION_MAX_SIZE, "FFMemoryOptions size exceeds maximum allowed size"); diff --git a/src/modules/modules.h b/src/modules/modules.h index e6594f0309..adc128f94f 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -1,7 +1,5 @@ #pragma once -// For "fastfetch.c" and "flashfetch.c" - #include "modules/battery/battery.h" #include "modules/bios/bios.h" #include "modules/bluetooth/bluetooth.h" diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index afaab6a27f..65af67a12b 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -86,39 +86,22 @@ void ffPrintMonitor(FFMonitorOptions* options) } } -bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_MONITOR_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateMonitorJsonConfig(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyMonitorOptions))) FFMonitorOptions defaultOptions; - ffInitMonitorOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -126,10 +109,21 @@ void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjs yyjson_mut_obj_add_str(doc, module, "error", "Monitor module is an alias of Display module"); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitMonitorOptions(FFMonitorOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰹑"); +} + +void ffDestroyMonitorOptions(FFMonitorOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffMonitorModuleInfo = { .name = FF_MONITOR_MODULE_NAME, .description = "Alias of Display module", - .parseCommandOptions = (void*) ffParseMonitorCommandOptions, + .initOptions = (void*) ffInitMonitorOptions, + .destroyOptions = (void*) ffDestroyMonitorOptions, .parseJsonObject = (void*) ffParseMonitorJsonObject, .printModule = (void*) ffPrintMonitor, .generateJsonResult = (void*) ffGenerateMonitorJsonResult, @@ -149,14 +143,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"True if the display is HDR compatible", "hdr-compatible"}, })) }; - -void ffInitMonitorOptions(FFMonitorOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰹑"); -} - -void ffDestroyMonitorOptions(FFMonitorOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h index d928c2ffef..17320b22ea 100644 --- a/src/modules/monitor/monitor.h +++ b/src/modules/monitor/monitor.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_MONITOR_MODULE_NAME "Monitor" void ffPrintMonitor(FFMonitorOptions* options); void ffInitMonitorOptions(FFMonitorOptions* options); void ffDestroyMonitorOptions(FFMonitorOptions* options); + +extern FFModuleBaseInfo ffMonitorModuleInfo; diff --git a/src/modules/monitor/option.h b/src/modules/monitor/option.h index b474ae7b25..07905ecba7 100644 --- a/src/modules/monitor/option.h +++ b/src/modules/monitor/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFMonitorOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFMonitorOptions; + +static_assert(sizeof(FFMonitorOptions) <= FF_OPTION_MAX_SIZE, "FFMonitorOptions size exceeds maximum allowed size"); diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index 58a7cfcf0b..00ce7d4bac 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -48,39 +48,22 @@ void ffPrintMouse(FFMouseOptions* options) } } -bool ffParseMouseCommandOptions(FFMouseOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_MOUSE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateMouseJsonConfig(FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyMouseOptions))) FFMouseOptions defaultOptions; - ffInitMouseOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -110,10 +93,21 @@ void ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_m } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitMouseOptions(FFMouseOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰍽"); +} + +void ffDestroyMouseOptions(FFMouseOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffMouseModuleInfo = { .name = FF_MOUSE_MODULE_NAME, .description = "List connected mouses", - .parseCommandOptions = (void*) ffParseMouseCommandOptions, + .initOptions = (void*) ffInitMouseOptions, + .destroyOptions = (void*) ffDestroyMouseOptions, .parseJsonObject = (void*) ffParseMouseJsonObject, .printModule = (void*) ffPrintMouse, .generateJsonResult = (void*) ffGenerateMouseJsonResult, @@ -123,14 +117,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Mouse serial number", "serial"}, })) }; - -void ffInitMouseOptions(FFMouseOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰍽"); -} - -void ffDestroyMouseOptions(FFMouseOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/mouse/mouse.h b/src/modules/mouse/mouse.h index d78a375ae0..796c998e9e 100644 --- a/src/modules/mouse/mouse.h +++ b/src/modules/mouse/mouse.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_MOUSE_MODULE_NAME "Mouse" void ffPrintMouse(FFMouseOptions* options); void ffInitMouseOptions(FFMouseOptions* options); void ffDestroyMouseOptions(FFMouseOptions* options); + +extern FFModuleBaseInfo ffMouseModuleInfo; diff --git a/src/modules/mouse/option.h b/src/modules/mouse/option.h index db9ea18662..470104d3fc 100644 --- a/src/modules/mouse/option.h +++ b/src/modules/mouse/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFMouseOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFMouseOptions; + +static_assert(sizeof(FFMouseOptions) <= FF_OPTION_MAX_SIZE, "FFMouseOptions size exceeds maximum allowed size"); diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 5b0fb4bbb4..8e932d4057 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -103,96 +103,54 @@ void ffPrintNetIO(FFNetIOOptions* options) } } -bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_NETIO_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "name-prefix")) - { - ffOptionParseString(key, value, &options->namePrefix); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "default-route-only")) - { - options->defaultRouteOnly = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "detect-total")) - { - options->detectTotal = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "wait-time")) - { - options->waitTime = ffOptionParseUInt32(key, value); - return true; - } - - return false; -} - void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "namePrefix")) + if (unsafe_yyjson_equals_str(key, "namePrefix")) { - ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->namePrefix, val); continue; } - if (ffStrEqualsIgnCase(key, "defaultRouteOnly")) + if (unsafe_yyjson_equals_str(key, "defaultRouteOnly")) { options->defaultRouteOnly = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "detectTotal")) + if (unsafe_yyjson_equals_str(key, "detectTotal")) { options->detectTotal = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "waitTime")) + if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); continue; } - ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateNetIOJsonConfig(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions defaultOptions; - ffInitNetIOOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); - if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix)) - yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); + yyjson_mut_obj_add_bool(doc, module, "defaultRouteOnly", options->defaultRouteOnly); - if (options->defaultRouteOnly != defaultOptions.defaultRouteOnly) - yyjson_mut_obj_add_bool(doc, module, "defaultRouteOnly", options->defaultRouteOnly); + yyjson_mut_obj_add_bool(doc, module, "detectTotal", options->detectTotal); - if (options->detectTotal != defaultOptions.detectTotal) - yyjson_mut_obj_add_bool(doc, module, "detectTotal", options->detectTotal); + yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); } void ffGenerateNetIOJsonResult(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -228,10 +186,33 @@ void ffGenerateNetIOJsonResult(FFNetIOOptions* options, yyjson_mut_doc* doc, yyj } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitNetIOOptions(FFNetIOOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰾆"); + + ffStrbufInit(&options->namePrefix); + options->defaultRouteOnly = + #if __ANDROID__ + false + #else + true + #endif + ; + options->detectTotal = false; + options->waitTime = 1000; +} + +void ffDestroyNetIOOptions(FFNetIOOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); +} + +FFModuleBaseInfo ffNetIOModuleInfo = { .name = FF_NETIO_MODULE_NAME, .description = "Print network I/O throughput", - .parseCommandOptions = (void*) ffParseNetIOCommandOptions, + .initOptions = (void*) ffInitNetIOOptions, + .destroyOptions = (void*) ffDestroyNetIOOptions, .parseJsonObject = (void*) ffParseNetIOJsonObject, .printModule = (void*) ffPrintNetIO, .generateJsonResult = (void*) ffGenerateNetIOJsonResult, @@ -251,26 +232,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Number of packets dropped when sending [per second]", "tx-drops"}, })) }; - -void ffInitNetIOOptions(FFNetIOOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰾆"); - - ffStrbufInit(&options->namePrefix); - options->defaultRouteOnly = - #if __ANDROID__ || __OpenBSD__ - false - #else - true - #endif - ; - options->detectTotal = false; - options->waitTime = 1000; -} - -void ffDestroyNetIOOptions(FFNetIOOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); - ffStrbufDestroy(&options->namePrefix); -} diff --git a/src/modules/netio/netio.h b/src/modules/netio/netio.h index 5b94e4bf27..b5468347ee 100644 --- a/src/modules/netio/netio.h +++ b/src/modules/netio/netio.h @@ -1,6 +1,6 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_NETIO_MODULE_NAME "NetIO" @@ -9,3 +9,5 @@ void ffPrepareNetIO(FFNetIOOptions* options); void ffPrintNetIO(FFNetIOOptions* options); void ffInitNetIOOptions(FFNetIOOptions* options); void ffDestroyNetIOOptions(FFNetIOOptions* options); + +extern FFModuleBaseInfo ffNetIOModuleInfo; diff --git a/src/modules/netio/option.h b/src/modules/netio/option.h index 7709b21e15..61ffa37d5a 100644 --- a/src/modules/netio/option.h +++ b/src/modules/netio/option.h @@ -1,12 +1,9 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFNetIOOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf namePrefix; @@ -14,3 +11,5 @@ typedef struct FFNetIOOptions bool defaultRouteOnly; bool detectTotal; } FFNetIOOptions; + +static_assert(sizeof(FFNetIOOptions) <= FF_OPTION_MAX_SIZE, "FFNetIOOptions size exceeds maximum allowed size"); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index dd32e9c4af..64f0ba63e6 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -30,39 +30,22 @@ void ffPrintOpenCL(FFOpenCLOptions* options) } } -bool ffParseOpenCLCommandOptions(FFOpenCLOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_OPENCL_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateOpenCLJsonConfig(FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyOpenCLOptions))) FFOpenCLOptions defaultOptions; - ffInitOpenCLOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -128,10 +111,21 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitOpenCLOptions(FFOpenCLOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyOpenCLOptions(FFOpenCLOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffOpenCLModuleInfo = { .name = FF_OPENCL_MODULE_NAME, .description = "Print highest OpenCL version supported by the GPU", - .parseCommandOptions = (void*) ffParseOpenCLCommandOptions, + .initOptions = (void*) ffInitOpenCLOptions, + .destroyOptions = (void*) ffDestroyOpenCLOptions, .parseJsonObject = (void*) ffParseOpenCLJsonObject, .printModule = (void*) ffPrintOpenCL, .generateJsonResult = (void*) ffGenerateOpenCLJsonResult, @@ -142,14 +136,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Platform vendor", "vendor"}, })) }; - -void ffInitOpenCLOptions(FFOpenCLOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyOpenCLOptions(FFOpenCLOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/opencl/opencl.h b/src/modules/opencl/opencl.h index f378e3f0bb..bf47c6fbe9 100644 --- a/src/modules/opencl/opencl.h +++ b/src/modules/opencl/opencl.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_OPENCL_MODULE_NAME "OpenCL" void ffPrintOpenCL(FFOpenCLOptions* options); void ffInitOpenCLOptions(FFOpenCLOptions* options); void ffDestroyOpenCLOptions(FFOpenCLOptions* options); + +extern FFModuleBaseInfo ffOpenCLModuleInfo; diff --git a/src/modules/opencl/option.h b/src/modules/opencl/option.h index 048c9b2668..2fd7dff26a 100644 --- a/src/modules/opencl/option.h +++ b/src/modules/opencl/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFOpenCLOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFOpenCLOptions; + +static_assert(sizeof(FFOpenCLOptions) <= FF_OPTION_MAX_SIZE, "FFOpenCLOptions size exceeds maximum allowed size"); diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 4dcebcdbac..9dc99887ef 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -43,41 +43,16 @@ void ffPrintOpenGL(FFOpenGLOptions* options) ffStrbufDestroy(&result.library); } -bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_OPENGL_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "library")) - { - options->library = (FFOpenGLLibrary) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "auto", FF_OPENGL_LIBRARY_AUTO }, - { "egl", FF_OPENGL_LIBRARY_EGL }, - { "glx", FF_OPENGL_LIBRARY_GLX }, - {} - }); - return true; - } - - return false; -} - void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "library")) + if (unsafe_yyjson_equals_str(key, "library")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -87,37 +62,31 @@ void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module) {}, }); if (error) - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error); + ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); else options->library = (FFOpenGLLibrary) value; continue; } - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateOpenGLJsonConfig(FFOpenGLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyOpenGLOptions))) FFOpenGLOptions defaultOptions; - ffInitOpenGLOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (options->library != defaultOptions.library) + switch (options->library) { - switch (options->library) - { - case FF_OPENGL_LIBRARY_AUTO: - yyjson_mut_obj_add_str(doc, module, "library", "auto"); - break; - case FF_OPENGL_LIBRARY_EGL: - yyjson_mut_obj_add_str(doc, module, "library", "egl"); - break; - case FF_OPENGL_LIBRARY_GLX: - yyjson_mut_obj_add_str(doc, module, "library", "glx"); - break; - } + case FF_OPENGL_LIBRARY_AUTO: + yyjson_mut_obj_add_str(doc, module, "library", "auto"); + break; + case FF_OPENGL_LIBRARY_EGL: + yyjson_mut_obj_add_str(doc, module, "library", "egl"); + break; + case FF_OPENGL_LIBRARY_GLX: + yyjson_mut_obj_add_str(doc, module, "library", "glx"); + break; } } @@ -152,10 +121,23 @@ void ffGenerateOpenGLJsonResult(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson ffStrbufDestroy(&result.library); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitOpenGLOptions(FFOpenGLOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->library = FF_OPENGL_LIBRARY_AUTO; +} + +void ffDestroyOpenGLOptions(FFOpenGLOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffOpenGLModuleInfo = { .name = FF_OPENGL_MODULE_NAME, .description = "Print highest OpenGL version supported by the GPU", - .parseCommandOptions = (void*) ffParseOpenGLCommandOptions, + .initOptions = (void*) ffInitOpenGLOptions, + .destroyOptions = (void*) ffDestroyOpenGLOptions, .parseJsonObject = (void*) ffParseOpenGLJsonObject, .printModule = (void*) ffPrintOpenGL, .generateJsonResult = (void*) ffGenerateOpenGLJsonResult, @@ -168,16 +150,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"OpenGL library used", "library"}, })) }; - -void ffInitOpenGLOptions(FFOpenGLOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - - options->library = FF_OPENGL_LIBRARY_AUTO; -} - -void ffDestroyOpenGLOptions(FFOpenGLOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/opengl/opengl.h b/src/modules/opengl/opengl.h index 0f9d347359..f60938d1e6 100644 --- a/src/modules/opengl/opengl.h +++ b/src/modules/opengl/opengl.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_OPENGL_MODULE_NAME "OpenGL" void ffPrintOpenGL(FFOpenGLOptions* options); void ffInitOpenGLOptions(FFOpenGLOptions* options); void ffDestroyOpenGLOptions(FFOpenGLOptions* options); + +extern FFModuleBaseInfo ffOpenGLModuleInfo; diff --git a/src/modules/opengl/option.h b/src/modules/opengl/option.h index bdd4e446a8..cc4b6ef461 100644 --- a/src/modules/opengl/option.h +++ b/src/modules/opengl/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef enum __attribute__((__packed__)) FFOpenGLLibrary @@ -13,8 +11,9 @@ typedef enum __attribute__((__packed__)) FFOpenGLLibrary typedef struct FFOpenGLOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFOpenGLLibrary library; } FFOpenGLOptions; + +static_assert(sizeof(FFOpenGLOptions) <= FF_OPTION_MAX_SIZE, "FFOpenGLOptions size exceeds maximum allowed size"); diff --git a/src/modules/os/option.h b/src/modules/os/option.h index ae098a53a3..c7142b237a 100644 --- a/src/modules/os/option.h +++ b/src/modules/os/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFOSOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFOSOptions; + +static_assert(sizeof(FFOSOptions) <= FF_OPTION_MAX_SIZE, "FFOSOptions size exceeds maximum allowed size"); diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 566af94145..c3b3efd661 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -115,39 +115,22 @@ void ffPrintOS(FFOSOptions* options) } } -bool ffParseOSCommandOptions(FFOSOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_OS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateOSJsonConfig(FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyOSOptions))) FFOSOptions defaultOptions; - ffInitOSOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateOSJsonResult(FF_MAYBE_UNUSED FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -173,33 +156,8 @@ void ffGenerateOSJsonResult(FF_MAYBE_UNUSED FFOSOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "versionID", &os->versionID); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_OS_MODULE_NAME, - .description = "Print operating system name and version", - .parseCommandOptions = (void*) ffParseOSCommandOptions, - .parseJsonObject = (void*) ffParseOSJsonObject, - .printModule = (void*) ffPrintOS, - .generateJsonResult = (void*) ffGenerateOSJsonResult, - .generateJsonConfig = (void*) ffGenerateOSJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Name of the kernel", "sysname"}, - {"Name of the OS", "name"}, - {"Pretty name of the OS, if available", "pretty-name"}, - {"ID of the OS", "id"}, - {"ID like of the OS", "id-like"}, - {"Variant of the OS", "variant"}, - {"Variant ID of the OS", "variant-id"}, - {"Version of the OS", "version"}, - {"Version ID of the OS", "version-id"}, - {"Version codename of the OS", "codename"}, - {"Build ID of the OS", "build-id"}, - {"Architecture of the OS", "arch"}, - })) -}; - void ffInitOSOptions(FFOSOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, #ifdef _WIN32 "" @@ -215,6 +173,8 @@ void ffInitOSOptions(FFOSOptions* options) "" #elif __OpenBSD__ "" + #elif __Haiku__ + "" #else "?" #endif @@ -225,3 +185,28 @@ void ffDestroyOSOptions(FFOSOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); } + +FFModuleBaseInfo ffOSModuleInfo = { + .name = FF_OS_MODULE_NAME, + .description = "Print operating system name and version", + .initOptions = (void*) ffInitOSOptions, + .destroyOptions = (void*) ffDestroyOSOptions, + .parseJsonObject = (void*) ffParseOSJsonObject, + .printModule = (void*) ffPrintOS, + .generateJsonResult = (void*) ffGenerateOSJsonResult, + .generateJsonConfig = (void*) ffGenerateOSJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"Name of the kernel", "sysname"}, + {"Name of the OS", "name"}, + {"Pretty name of the OS, if available", "pretty-name"}, + {"ID of the OS", "id"}, + {"ID like of the OS", "id-like"}, + {"Variant of the OS", "variant"}, + {"Variant ID of the OS", "variant-id"}, + {"Version of the OS", "version"}, + {"Version ID of the OS", "version-id"}, + {"Version codename of the OS", "codename"}, + {"Build ID of the OS", "build-id"}, + {"Architecture of the OS", "arch"}, + })) +}; diff --git a/src/modules/os/os.h b/src/modules/os/os.h index ff2aa787da..bf6ebf9d60 100644 --- a/src/modules/os/os.h +++ b/src/modules/os/os.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_OS_MODULE_NAME "OS" void ffPrintOS(FFOSOptions* options); void ffInitOSOptions(FFOSOptions* options); void ffDestroyOSOptions(FFOSOptions* options); + +extern FFModuleBaseInfo ffOSModuleInfo; diff --git a/src/modules/packages/option.h b/src/modules/packages/option.h index 5709578d44..240ca66664 100644 --- a/src/modules/packages/option.h +++ b/src/modules/packages/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef enum __attribute__((__packed__)) FFPackagesFlags @@ -44,9 +42,10 @@ static_assert(sizeof(FFPackagesFlags) == sizeof(uint64_t), ""); typedef struct FFPackagesOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPackagesFlags disabled; bool combined; } FFPackagesOptions; + +static_assert(sizeof(FFPackagesOptions) <= FF_OPTION_MAX_SIZE, "FFPackagesOptions size exceeds maximum allowed size"); diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 06c1817a33..d17911de01 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -205,135 +205,20 @@ void ffPrintPackages(FFPackagesOptions* options) ffStrbufDestroy(&counts.pacmanBranch); } -bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_PACKAGES_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "disabled")) - { - options->disabled = FF_PACKAGES_FLAG_NONE; - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - ffOptionParseString(key, value, &buffer); - - char *start = buffer.chars, *end = strchr(start, ':'); - while (true) - { - if (end) - *end = '\0'; - - #define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(start, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; } - switch (toupper(start[0])) - { - case 'A': if (false); - FF_TEST_PACKAGE_NAME(APK) - FF_TEST_PACKAGE_NAME(AM) - break; - case 'B': if (false); - FF_TEST_PACKAGE_NAME(BREW) - break; - case 'C': if (false); - FF_TEST_PACKAGE_NAME(CHOCO) - break; - case 'D': if (false); - FF_TEST_PACKAGE_NAME(DPKG) - break; - case 'E': if (false); - FF_TEST_PACKAGE_NAME(EMERGE) - FF_TEST_PACKAGE_NAME(EOPKG) - break; - case 'F': if (false); - FF_TEST_PACKAGE_NAME(FLATPAK) - break; - case 'G': if (false); - FF_TEST_PACKAGE_NAME(GUIX) - break; - case 'H': if (false); - FF_TEST_PACKAGE_NAME(HPKG) - break; - case 'L': if (false); - FF_TEST_PACKAGE_NAME(LPKG) - FF_TEST_PACKAGE_NAME(LPKGBUILD) - FF_TEST_PACKAGE_NAME(LINGLONG) - break; - case 'M': if (false); - FF_TEST_PACKAGE_NAME(MACPORTS) - FF_TEST_PACKAGE_NAME(MPORT) - break; - case 'N': if (false); - FF_TEST_PACKAGE_NAME(NIX) - break; - case 'O': if (false); - FF_TEST_PACKAGE_NAME(OPKG) - break; - case 'P': if (false); - FF_TEST_PACKAGE_NAME(PACMAN) - FF_TEST_PACKAGE_NAME(PACSTALL) - FF_TEST_PACKAGE_NAME(PALUDIS) - FF_TEST_PACKAGE_NAME(PISI) - FF_TEST_PACKAGE_NAME(PKG) - FF_TEST_PACKAGE_NAME(PKGTOOL) - FF_TEST_PACKAGE_NAME(PKGSRC) - break; - case 'R': if (false); - FF_TEST_PACKAGE_NAME(RPM) - break; - case 'S': if (false); - FF_TEST_PACKAGE_NAME(SCOOP) - FF_TEST_PACKAGE_NAME(SNAP) - FF_TEST_PACKAGE_NAME(SOAR) - FF_TEST_PACKAGE_NAME(SORCERY) - break; - case 'W': if (false); - FF_TEST_PACKAGE_NAME(WINGET) - break; - case 'X': if (false); - FF_TEST_PACKAGE_NAME(XBPS) - break; - } - #undef FF_TEST_PACKAGE_NAME - - if (end) - { - start = end + 1; - end = strchr(start, ':'); - } - else - break; - } - - return true; - } - - if (ffStrEqualsIgnCase(subKey, "combined")) - { - options->combined = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if (ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "disabled")) + if (unsafe_yyjson_equals_str(key, "disabled")) { if (!yyjson_is_null(val) && !yyjson_is_arr(val)) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", key); + ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); continue; } @@ -345,7 +230,12 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) size_t flagIdx, flagMax; yyjson_arr_foreach(val, flagIdx, flagMax, flagObj) { - const char* flag = yyjson_get_str(flagObj); + if (!yyjson_is_str(flagObj)) + { + ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); + continue; + } + const char* flag = unsafe_yyjson_get_str(flagObj); #define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(flag, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; } switch (toupper(flag[0])) @@ -422,64 +312,62 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) } } - if (ffStrEqualsIgnCase(key, "combined")) + if (unsafe_yyjson_equals_str(key, "combined")) { options->combined = yyjson_get_bool(val); continue; } - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyPackagesOptions))) FFPackagesOptions defaultOptions; - ffInitPackagesOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (options->disabled != defaultOptions.disabled) - { - yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "disabled"); - #define FF_TEST_PACKAGE_NAME(name) else if ((options->disabled & FF_PACKAGES_FLAG_ ## name ## _BIT) != (defaultOptions.disabled & FF_PACKAGES_FLAG_ ## name ## _BIT)) { yyjson_mut_arr_add_str(doc, arr, #name); } - if (false); - FF_TEST_PACKAGE_NAME(AM) - FF_TEST_PACKAGE_NAME(APK) - FF_TEST_PACKAGE_NAME(BREW) - FF_TEST_PACKAGE_NAME(CHOCO) - FF_TEST_PACKAGE_NAME(DPKG) - FF_TEST_PACKAGE_NAME(EMERGE) - FF_TEST_PACKAGE_NAME(EOPKG) - FF_TEST_PACKAGE_NAME(FLATPAK) - FF_TEST_PACKAGE_NAME(GUIX) - FF_TEST_PACKAGE_NAME(HPKG) - FF_TEST_PACKAGE_NAME(LINGLONG) - FF_TEST_PACKAGE_NAME(LPKG) - FF_TEST_PACKAGE_NAME(LPKGBUILD) - FF_TEST_PACKAGE_NAME(MACPORTS) - FF_TEST_PACKAGE_NAME(MPORT) - FF_TEST_PACKAGE_NAME(NIX) - FF_TEST_PACKAGE_NAME(OPKG) - FF_TEST_PACKAGE_NAME(PACMAN) - FF_TEST_PACKAGE_NAME(PACSTALL) - FF_TEST_PACKAGE_NAME(PALUDIS) - FF_TEST_PACKAGE_NAME(PISI) - FF_TEST_PACKAGE_NAME(PKG) - FF_TEST_PACKAGE_NAME(PKGTOOL) - FF_TEST_PACKAGE_NAME(PKGSRC) - FF_TEST_PACKAGE_NAME(RPM) - FF_TEST_PACKAGE_NAME(SCOOP) - FF_TEST_PACKAGE_NAME(SNAP) - FF_TEST_PACKAGE_NAME(SOAR) - FF_TEST_PACKAGE_NAME(SORCERY) - FF_TEST_PACKAGE_NAME(WINGET) - FF_TEST_PACKAGE_NAME(XBPS) - #undef FF_TEST_PACKAGE_NAME + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "disabled"); + #define FF_TEST_PACKAGE_NAME(name) else if ((options->disabled & FF_PACKAGES_FLAG_ ## name ## _BIT)) { \ + ffStrbufSetS(&buf, #name); \ + ffStrbufLowerCase(&buf); \ + yyjson_mut_arr_add_strbuf(doc, arr, &buf); \ } - - if (options->combined != defaultOptions.combined) - yyjson_mut_obj_add_bool(doc, module, "combined", options->combined); + if (false); + FF_TEST_PACKAGE_NAME(AM) + FF_TEST_PACKAGE_NAME(APK) + FF_TEST_PACKAGE_NAME(BREW) + FF_TEST_PACKAGE_NAME(CHOCO) + FF_TEST_PACKAGE_NAME(DPKG) + FF_TEST_PACKAGE_NAME(EMERGE) + FF_TEST_PACKAGE_NAME(EOPKG) + FF_TEST_PACKAGE_NAME(FLATPAK) + FF_TEST_PACKAGE_NAME(GUIX) + FF_TEST_PACKAGE_NAME(HPKG) + FF_TEST_PACKAGE_NAME(LINGLONG) + FF_TEST_PACKAGE_NAME(LPKG) + FF_TEST_PACKAGE_NAME(LPKGBUILD) + FF_TEST_PACKAGE_NAME(MACPORTS) + FF_TEST_PACKAGE_NAME(MPORT) + FF_TEST_PACKAGE_NAME(NIX) + FF_TEST_PACKAGE_NAME(OPKG) + FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) + FF_TEST_PACKAGE_NAME(PALUDIS) + FF_TEST_PACKAGE_NAME(PISI) + FF_TEST_PACKAGE_NAME(PKG) + FF_TEST_PACKAGE_NAME(PKGTOOL) + FF_TEST_PACKAGE_NAME(PKGSRC) + FF_TEST_PACKAGE_NAME(RPM) + FF_TEST_PACKAGE_NAME(SCOOP) + FF_TEST_PACKAGE_NAME(SNAP) + FF_TEST_PACKAGE_NAME(SOAR) + FF_TEST_PACKAGE_NAME(SORCERY) + FF_TEST_PACKAGE_NAME(WINGET) + FF_TEST_PACKAGE_NAME(XBPS) + #undef FF_TEST_PACKAGE_NAME + + yyjson_mut_obj_add_bool(doc, module, "combined", options->combined); } void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -541,10 +429,24 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitPackagesOptions(FFPackagesOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰏖"); + + options->disabled = FF_PACKAGES_DISABLE_LIST; + options->combined = false; +} + +void ffDestroyPackagesOptions(FFPackagesOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffPackagesModuleInfo = { .name = FF_PACKAGES_MODULE_NAME, .description = "List installed package managers and count of installed packages", - .parseCommandOptions = (void*) ffParsePackagesCommandOptions, + .initOptions = (void*) ffInitPackagesOptions, + .destroyOptions = (void*) ffDestroyPackagesOptions, .parseJsonObject = (void*) ffParsePackagesJsonObject, .printModule = (void*) ffPrintPackages, .generateJsonResult = (void*) ffGeneratePackagesJsonResult, @@ -599,17 +501,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Total number of all hpkg packages", "hpkg-all"}, })) }; - -void ffInitPackagesOptions(FFPackagesOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰏖"); - - options->disabled = FF_PACKAGES_DISABLE_LIST; - options->combined = false; -} - -void ffDestroyPackagesOptions(FFPackagesOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/packages/packages.h b/src/modules/packages/packages.h index 97b8b4c910..8b904d48db 100644 --- a/src/modules/packages/packages.h +++ b/src/modules/packages/packages.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_PACKAGES_MODULE_NAME "Packages" void ffPrintPackages(FFPackagesOptions* options); void ffInitPackagesOptions(FFPackagesOptions* options); void ffDestroyPackagesOptions(FFPackagesOptions* options); + +extern FFModuleBaseInfo ffPackagesModuleInfo; diff --git a/src/modules/physicaldisk/option.h b/src/modules/physicaldisk/option.h index fbd2dc6855..3951f06109 100644 --- a/src/modules/physicaldisk/option.h +++ b/src/modules/physicaldisk/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFPhysicalDiskOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf namePrefix; bool temp; FFColorRangeConfig tempConfig; } FFPhysicalDiskOptions; + +static_assert(sizeof(FFPhysicalDiskOptions) <= FF_OPTION_MAX_SIZE, "FFPhysicalDiskOptions size exceeds maximum allowed size"); diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index f687706977..72ffe85f08 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -92,7 +92,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) ffStrbufAppendC(&buffer, ']'); } - if (dev->temperature == dev->temperature) //FF_PHYSICALDISK_TEMP_UNSET + if (dev->temperature != FF_PHYSICALDISK_TEMP_UNSET) { if(buffer.length > 0) ffStrbufAppendS(&buffer, " - "); @@ -133,62 +133,35 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) } } -bool ffParsePhysicalDiskCommandOptions(FFPhysicalDiskOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_PHYSICALDISK_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "name-prefix")) - { - ffOptionParseString(key, value, &options->namePrefix); - return true; - } - - if (ffTempsParseCommandOptions(key, subKey, value, &options->temp, &options->tempConfig)) - return true; - - return false; -} - void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "namePrefix")) + if (unsafe_yyjson_equals_str(key, "namePrefix")) { - ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->namePrefix, val); continue; } if (ffTempsParseJsonObject(key, val, &options->temp, &options->tempConfig)) continue; - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGeneratePhysicalDiskJsonConfig(FFPhysicalDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyPhysicalDiskOptions))) FFPhysicalDiskOptions defaultOptions; - ffInitPhysicalDiskOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix)) - yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); + yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); - ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig); + ffTempsGenerateJsonConfig(doc, module, options->temp, options->tempConfig); } void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -236,7 +209,10 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, obj, "revision", &dev->revision); - yyjson_mut_obj_add_real(doc, obj, "temperature", dev->temperature); + if (dev->temperature != FF_PHYSICALDISK_TEMP_UNSET) + yyjson_mut_obj_add_real(doc, obj, "temperature", dev->temperature); + else + yyjson_mut_obj_add_null(doc, obj, "temperature"); } FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) @@ -249,10 +225,26 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰋊"); + + ffStrbufInit(&options->namePrefix); + options->temp = false; + options->tempConfig = (FFColorRangeConfig) { 50, 70 }; +} + +void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); +} + +FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .name = FF_PHYSICALDISK_MODULE_NAME, .description = "Print physical disk information", - .parseCommandOptions = (void*) ffParsePhysicalDiskCommandOptions, + .initOptions = (void*) ffInitPhysicalDiskOptions, + .destroyOptions = (void*) ffDestroyPhysicalDiskOptions, .parseJsonObject = (void*) ffParsePhysicalDiskJsonObject, .printModule = (void*) ffPrintPhysicalDisk, .generateJsonResult = (void*) ffGeneratePhysicalDiskJsonResult, @@ -270,19 +262,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Device temperature (formatted)", "temperature"}, })) }; - -void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰋊"); - - ffStrbufInit(&options->namePrefix); - options->temp = false; - options->tempConfig = (FFColorRangeConfig) { 50, 70 }; -} - -void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); - ffStrbufDestroy(&options->namePrefix); -} diff --git a/src/modules/physicaldisk/physicaldisk.h b/src/modules/physicaldisk/physicaldisk.h index d8216c1409..e73b3f358d 100644 --- a/src/modules/physicaldisk/physicaldisk.h +++ b/src/modules/physicaldisk/physicaldisk.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_PHYSICALDISK_MODULE_NAME "PhysicalDisk" void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options); void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options); void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options); + +extern FFModuleBaseInfo ffPhysicalDiskModuleInfo; diff --git a/src/modules/physicalmemory/option.h b/src/modules/physicalmemory/option.h index 96ebccc57e..154354b4a5 100644 --- a/src/modules/physicalmemory/option.h +++ b/src/modules/physicalmemory/option.h @@ -1,12 +1,11 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFPhysicalMemoryOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFPhysicalMemoryOptions; + +static_assert(sizeof(FFPhysicalMemoryOptions) <= FF_OPTION_MAX_SIZE, "FFPhysicalMemoryOptions size exceeds maximum allowed size"); diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 4bfe28ef46..09534595d6 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -80,39 +80,22 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) } } -bool ffParsePhysicalMemoryCommandOptions(FFPhysicalMemoryOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_PHYSICALMEMORY_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParsePhysicalMemoryJsonObject(FFPhysicalMemoryOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_PHYSICALMEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_PHYSICALMEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGeneratePhysicalMemoryJsonConfig(FFPhysicalMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyPhysicalMemoryOptions))) FFPhysicalMemoryOptions defaultOptions; - ffInitPhysicalMemoryOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGeneratePhysicalMemoryJsonResult(FF_MAYBE_UNUSED FFPhysicalMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -153,10 +136,21 @@ void ffGeneratePhysicalMemoryJsonResult(FF_MAYBE_UNUSED FFPhysicalMemoryOptions* } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰑭"); +} + +void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .name = FF_PHYSICALMEMORY_MODULE_NAME, .description = "Print system physical memory devices", - .parseCommandOptions = (void*) ffParsePhysicalMemoryCommandOptions, + .initOptions = (void*) ffInitPhysicalMemoryOptions, + .destroyOptions = (void*) ffDestroyPhysicalMemoryOptions, .parseJsonObject = (void*) ffParsePhysicalMemoryJsonObject, .printModule = (void*) ffPrintPhysicalMemory, .generateJsonConfig = (void*) ffGeneratePhysicalMemoryJsonConfig, @@ -175,14 +169,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"True if ECC enabled", "is-ecc-enabled"}, })) }; - -void ffInitPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰑭"); -} - -void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/physicalmemory/physicalmemory.h b/src/modules/physicalmemory/physicalmemory.h index c9e0048d12..7df2b6c94b 100644 --- a/src/modules/physicalmemory/physicalmemory.h +++ b/src/modules/physicalmemory/physicalmemory.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_PHYSICALMEMORY_MODULE_NAME "PhysicalMemory" void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options); void ffInitPhysicalMemoryOptions(FFPhysicalMemoryOptions* options); void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options); + +extern FFModuleBaseInfo ffPhysicalMemoryModuleInfo; diff --git a/src/modules/player/option.h b/src/modules/player/option.h index 1d34797fb3..9d55821fdc 100644 --- a/src/modules/player/option.h +++ b/src/modules/player/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFPlayerOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFPlayerOptions; + +static_assert(sizeof(FFPlayerOptions) <= FF_OPTION_MAX_SIZE, "FFPlayerOptions size exceeds maximum allowed size"); diff --git a/src/modules/player/player.c b/src/modules/player/player.c index cf9a1b314c..347a2977ea 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -81,39 +81,22 @@ void ffPrintPlayer(FFPlayerOptions* options) } } -bool ffParsePlayerCommandOptions(FFPlayerOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_PLAYER_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_PLAYER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_PLAYER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGeneratePlayerJsonConfig(FFPlayerOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyPlayerOptions))) FFPlayerOptions defaultOptions; - ffInitPlayerOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGeneratePlayerJsonResult(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -121,10 +104,21 @@ void ffGeneratePlayerJsonResult(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_ yyjson_mut_obj_add_str(doc, module, "error", "Player module is an alias of Media module"); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitPlayerOptions(FFPlayerOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰥠"); +} + +void ffDestroyPlayerOptions(FFPlayerOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffPlayerModuleInfo = { .name = FF_PLAYER_MODULE_NAME, .description = "Print music player name", - .parseCommandOptions = (void*) ffParsePlayerCommandOptions, + .initOptions = (void*) ffInitPlayerOptions, + .destroyOptions = (void*) ffDestroyPlayerOptions, .parseJsonObject = (void*) ffParsePlayerJsonObject, .printModule = (void*) ffPrintPlayer, .generateJsonResult = (void*) ffGeneratePlayerJsonResult, @@ -136,14 +130,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"URL name", "url"}, })) }; - -void ffInitPlayerOptions(FFPlayerOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰥠"); -} - -void ffDestroyPlayerOptions(FFPlayerOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/player/player.h b/src/modules/player/player.h index 3912a3fe37..b99a6da6b5 100644 --- a/src/modules/player/player.h +++ b/src/modules/player/player.h @@ -1,10 +1,12 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_PLAYER_MODULE_NAME "Player" void ffPrintPlayer(FFPlayerOptions* options); void ffInitPlayerOptions(FFPlayerOptions* options); void ffDestroyPlayerOptions(FFPlayerOptions* options); + +extern FFModuleBaseInfo ffPlayerModuleInfo; diff --git a/src/modules/poweradapter/option.h b/src/modules/poweradapter/option.h index 02a72eaf77..303bbba733 100644 --- a/src/modules/poweradapter/option.h +++ b/src/modules/poweradapter/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFPowerAdapterOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFPowerAdapterOptions; + +static_assert(sizeof(FFPowerAdapterOptions) <= FF_OPTION_MAX_SIZE, "FFPowerAdapterOptions size exceeds maximum allowed size"); diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index ee8a613426..00c96ab0e4 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -56,38 +56,21 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) } } -bool ffParsePowerAdapterCommandOptions(FFPowerAdapterOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_POWERADAPTER_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffGeneratePowerAdapterJsonConfig(FFPowerAdapterOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyPowerAdapterOptions))) FFPowerAdapterOptions defaultOptions; - ffInitPowerAdapterOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_POWERADAPTER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_POWERADAPTER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -125,10 +108,21 @@ void ffGeneratePowerAdapterJsonResult(FF_MAYBE_UNUSED FFPowerAdapterOptions* opt } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰚥"); +} + +void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffPowerAdapterModuleInfo = { .name = FF_POWERADAPTER_MODULE_NAME, .description = "Print power adapter name and charging watts", - .parseCommandOptions = (void*) ffParsePowerAdapterCommandOptions, + .initOptions = (void*) ffInitPowerAdapterOptions, + .destroyOptions = (void*) ffDestroyPowerAdapterOptions, .parseJsonObject = (void*) ffParsePowerAdapterJsonObject, .printModule = (void*) ffPrintPowerAdapter, .generateJsonResult = (void*) ffGeneratePowerAdapterJsonResult, @@ -142,14 +136,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Power adapter serial number", "serial"}, })) }; - -void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰚥"); -} - -void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/poweradapter/poweradapter.h b/src/modules/poweradapter/poweradapter.h index 315c6e749b..165060a5e4 100644 --- a/src/modules/poweradapter/poweradapter.h +++ b/src/modules/poweradapter/poweradapter.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_POWERADAPTER_MODULE_NAME "PowerAdapter" void ffPrintPowerAdapter(FFPowerAdapterOptions* options); void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options); void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options); + +extern FFModuleBaseInfo ffPowerAdapterModuleInfo; diff --git a/src/modules/processes/option.h b/src/modules/processes/option.h index 6946ecad49..0b59f9df34 100644 --- a/src/modules/processes/option.h +++ b/src/modules/processes/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFProcessesOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFProcessesOptions; + +static_assert(sizeof(FFProcessesOptions) <= FF_OPTION_MAX_SIZE, "FFProcessesOptions size exceeds maximum allowed size"); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 6839642ee7..e7740a448a 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -29,39 +29,22 @@ void ffPrintProcesses(FFProcessesOptions* options) } } -bool ffParseProcessesCommandOptions(FFProcessesOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_PROCESSES_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateProcessesJsonConfig(FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyProcessesOptions))) FFProcessesOptions defaultOptions; - ffInitProcessesOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateProcessesJsonResult(FF_MAYBE_UNUSED FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -78,10 +61,21 @@ void ffGenerateProcessesJsonResult(FF_MAYBE_UNUSED FFProcessesOptions* options, yyjson_mut_obj_add_uint(doc, module, "result", result); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitProcessesOptions(FFProcessesOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyProcessesOptions(FFProcessesOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffProcessesModuleInfo = { .name = FF_PROCESSES_MODULE_NAME, .description = "Print number of running processes", - .parseCommandOptions = (void*) ffParseProcessesCommandOptions, + .initOptions = (void*) ffInitProcessesOptions, + .destroyOptions = (void*) ffDestroyProcessesOptions, .parseJsonObject = (void*) ffParseProcessesJsonObject, .printModule = (void*) ffPrintProcesses, .generateJsonResult = (void*) ffGenerateProcessesJsonResult, @@ -90,14 +84,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Process count", "result"} })) }; - -void ffInitProcessesOptions(FFProcessesOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyProcessesOptions(FFProcessesOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/processes/processes.h b/src/modules/processes/processes.h index d2159ca0e9..d9f0ae3d82 100644 --- a/src/modules/processes/processes.h +++ b/src/modules/processes/processes.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_PROCESSES_MODULE_NAME "Processes" void ffPrintProcesses(FFProcessesOptions* options); void ffInitProcessesOptions(FFProcessesOptions* options); void ffDestroyProcessesOptions(FFProcessesOptions* options); + +extern FFModuleBaseInfo ffProcessesModuleInfo; diff --git a/src/modules/publicip/option.h b/src/modules/publicip/option.h index 427bab31a9..e3118cb28f 100644 --- a/src/modules/publicip/option.h +++ b/src/modules/publicip/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" -typedef struct FFPublicIpOptions +typedef struct FFPublicIPOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf url; uint32_t timeout; bool ipv6; -} FFPublicIpOptions; +} FFPublicIPOptions; + +static_assert(sizeof(FFPublicIPOptions) <= FF_OPTION_MAX_SIZE, "FFPublicIPOptions size exceeds maximum allowed size"); diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index d712ba1bed..e52696dd65 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -6,7 +6,7 @@ #define FF_PUBLICIP_DISPLAY_NAME "Public IP" -void ffPrintPublicIp(FFPublicIpOptions* options) +void ffPrintPublicIp(FFPublicIPOptions* options) { FFPublicIpResult result; ffStrbufInit(&result.ip); @@ -39,87 +39,49 @@ void ffPrintPublicIp(FFPublicIpOptions* options) ffStrbufDestroy(&result.location); } -bool ffParsePublicIpCommandOptions(FFPublicIpOptions* options, const char* key, const char* value) +void ffParsePublicIpJsonObject(FFPublicIPOptions* options, yyjson_val* module) { - const char* subKey = ffOptionTestPrefix(key, FF_PUBLICIP_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "url")) - { - ffOptionParseString(key, value, &options->url); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "timeout")) - { - options->timeout = ffOptionParseUInt32(key, value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "ipv6")) - { - options->ipv6 = ffOptionParseBoolean(value); - return true; - } - - return false; -} - -void ffParsePublicIpJsonObject(FFPublicIpOptions* options, yyjson_val* module) -{ - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "url")) + if (unsafe_yyjson_equals_str(key, "url")) { - ffStrbufSetS(&options->url, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->url, val); continue; } - if (ffStrEqualsIgnCase(key, "timeout")) + if (unsafe_yyjson_equals_str(key, "timeout")) { options->timeout = (uint32_t) yyjson_get_uint(val); continue; } - if (ffStrEqualsIgnCase(key, "ipv6")) + if (unsafe_yyjson_equals_str(key, "ipv6")) { options->ipv6 = yyjson_get_bool(val); continue; } - ffPrintError(FF_PUBLICIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_PUBLICIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } -void ffGeneratePublicIpJsonConfig(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGeneratePublicIpJsonConfig(FFPublicIPOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIpOptions defaultOptions; - ffInitPublicIpOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_strbuf(doc, module, "url", &options->url); - if (!ffStrbufEqual(&options->url, &defaultOptions.url)) - yyjson_mut_obj_add_strbuf(doc, module, "url", &options->url); + yyjson_mut_obj_add_uint(doc, module, "timeout", options->timeout); - if (defaultOptions.timeout != options->timeout) - yyjson_mut_obj_add_uint(doc, module, "timeout", options->timeout); - - if (defaultOptions.ipv6 != options->ipv6) - yyjson_mut_obj_add_bool(doc, module, "ipv6", options->ipv6); + yyjson_mut_obj_add_bool(doc, module, "ipv6", options->ipv6); } -void ffGeneratePublicIpJsonResult(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGeneratePublicIpJsonResult(FFPublicIPOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFPublicIpResult result; ffStrbufInit(&result.ip); @@ -140,23 +102,8 @@ void ffGeneratePublicIpJsonResult(FFPublicIpOptions* options, yyjson_mut_doc* do ffStrbufDestroy(&result.location); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_PUBLICIP_MODULE_NAME, - .description = "Print your public IP address, etc", - .parseCommandOptions = (void*) ffParsePublicIpCommandOptions, - .parseJsonObject = (void*) ffParsePublicIpJsonObject, - .printModule = (void*) ffPrintPublicIp, - .generateJsonResult = (void*) ffGeneratePublicIpJsonResult, - .generateJsonConfig = (void*) ffGeneratePublicIpJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Public IP address", "ip"}, - {"Location", "location"}, - })) -}; - -void ffInitPublicIpOptions(FFPublicIpOptions* options) +void ffInitPublicIpOptions(FFPublicIPOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, "󰩠"); ffStrbufInit(&options->url); @@ -164,9 +111,24 @@ void ffInitPublicIpOptions(FFPublicIpOptions* options) options->ipv6 = false; } -void ffDestroyPublicIpOptions(FFPublicIpOptions* options) +void ffDestroyPublicIpOptions(FFPublicIPOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); ffStrbufDestroy(&options->url); } + +FFModuleBaseInfo ffPublicIPModuleInfo = { + .name = FF_PUBLICIP_MODULE_NAME, + .description = "Print your public IP address, etc", + .initOptions = (void*) ffInitPublicIpOptions, + .destroyOptions = (void*) ffDestroyPublicIpOptions, + .parseJsonObject = (void*) ffParsePublicIpJsonObject, + .printModule = (void*) ffPrintPublicIp, + .generateJsonResult = (void*) ffGeneratePublicIpJsonResult, + .generateJsonConfig = (void*) ffGeneratePublicIpJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"Public IP address", "ip"}, + {"Location", "location"}, + })) +}; diff --git a/src/modules/publicip/publicip.h b/src/modules/publicip/publicip.h index e54bab8093..5fd70ab4f3 100644 --- a/src/modules/publicip/publicip.h +++ b/src/modules/publicip/publicip.h @@ -1,11 +1,13 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_PUBLICIP_MODULE_NAME "PublicIp" -void ffPreparePublicIp(FFPublicIpOptions* options); +void ffPreparePublicIp(FFPublicIPOptions* options); -void ffPrintPublicIp(FFPublicIpOptions* options); -void ffInitPublicIpOptions(FFPublicIpOptions* options); -void ffDestroyPublicIpOptions(FFPublicIpOptions* options); +void ffPrintPublicIp(FFPublicIPOptions* options); +void ffInitPublicIpOptions(FFPublicIPOptions* options); +void ffDestroyPublicIpOptions(FFPublicIPOptions* options); + +extern FFModuleBaseInfo ffPublicIPModuleInfo; diff --git a/src/modules/separator/option.h b/src/modules/separator/option.h index 5f435e7f09..92274c806b 100644 --- a/src/modules/separator/option.h +++ b/src/modules/separator/option.h @@ -1,14 +1,12 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFSeparatorOptions { - FFModuleBaseInfo moduleInfo; - FFstrbuf string; FFstrbuf outputColor; uint32_t length; } FFSeparatorOptions; + +static_assert(sizeof(FFSeparatorOptions) <= FF_OPTION_MAX_SIZE, "FFSeparatorOptions size exceeds maximum allowed size"); diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index aa3e3d58a2..4e31590c75 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -56,7 +56,6 @@ void ffPrintSeparator(FFSeparatorOptions* options) { setlocale(LC_CTYPE, ""); mbstate_t state = {}; - bool fqdn = instance.config.modules.title.fqdn; const FFPlatform* platform = &instance.state.platform; FF_AUTO_FREE wchar_t* wstr = malloc((max( @@ -64,7 +63,7 @@ void ffPrintSeparator(FFSeparatorOptions* options) uint32_t titleLength = 1 // @ + getWcsWidth(&platform->userName, wstr, &state) // user name - + (fqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name + + (instance.state.titleFqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name if(__builtin_expect(options->string.length == 1, 1)) { @@ -114,85 +113,46 @@ void ffPrintSeparator(FFSeparatorOptions* options) putchar('\n'); } -bool ffParseSeparatorCommandOptions(FFSeparatorOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_SEPARATOR_MODULE_NAME); - if (!subKey) return false; - - if (ffStrEqualsIgnCase(subKey, "string")) - { - ffOptionParseString(key, value, &options->string); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "output-color")) - { - ffOptionParseColor(value, &options->outputColor); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "length")) - { - options->length = ffOptionParseUInt32(key, value); - return true; - } - - return false; -} - void ffParseSeparatorJsonObject(FFSeparatorOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) + if (unsafe_yyjson_equals_str(key, "type") || unsafe_yyjson_equals_str(key, "condition")) continue; - if (ffStrEqualsIgnCase(key, "string")) + if (unsafe_yyjson_equals_str(key, "string")) { - ffStrbufSetS(&options->string, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->string, val); continue; } - if (ffStrEndsWithIgnCase(key, "outputColor")) + if (unsafe_yyjson_equals_str(key, "outputColor")) { ffOptionParseColor(yyjson_get_str(val), &options->outputColor); continue; } - if (ffStrEndsWithIgnCase(key, "length")) + if (unsafe_yyjson_equals_str(key, "length")) { options->length = (uint32_t) yyjson_get_uint(val); continue; } - ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key); + ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateSeparatorJsonConfig(FFSeparatorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroySeparatorOptions))) FFSeparatorOptions defaultOptions; - ffInitSeparatorOptions(&defaultOptions); - - if (!ffStrbufEqual(&options->string, &defaultOptions.string)) - yyjson_mut_obj_add_strbuf(doc, module, "string", &options->string); + yyjson_mut_obj_add_strbuf(doc, module, "string", &options->string); + yyjson_mut_obj_add_strbuf(doc, module, "outputColor", &options->outputColor); + yyjson_mut_obj_add_uint(doc, module, "length", options->length); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_SEPARATOR_MODULE_NAME, - .description = "Print a separator line", - .parseCommandOptions = (void*) ffParseSeparatorCommandOptions, - .parseJsonObject = (void*) ffParseSeparatorJsonObject, - .printModule = (void*) ffPrintSeparator, - .generateJsonConfig = (void*) ffGenerateSeparatorJsonConfig, -}; - void ffInitSeparatorOptions(FFSeparatorOptions* options) { - options->moduleInfo = ffModuleInfo; ffStrbufInitStatic(&options->string, "-"); ffStrbufInit(&options->outputColor); options->length = 0; @@ -202,3 +162,13 @@ void ffDestroySeparatorOptions(FFSeparatorOptions* options) { ffStrbufDestroy(&options->string); } + +FFModuleBaseInfo ffSeparatorModuleInfo = { + .name = FF_SEPARATOR_MODULE_NAME, + .description = "Print a separator line", + .initOptions = (void*) ffInitSeparatorOptions, + .destroyOptions = (void*) ffDestroySeparatorOptions, + .parseJsonObject = (void*) ffParseSeparatorJsonObject, + .printModule = (void*) ffPrintSeparator, + .generateJsonConfig = (void*) ffGenerateSeparatorJsonConfig, +}; diff --git a/src/modules/separator/separator.h b/src/modules/separator/separator.h index bca9355215..d23fc6c943 100644 --- a/src/modules/separator/separator.h +++ b/src/modules/separator/separator.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_SEPARATOR_MODULE_NAME "Separator" void ffPrintSeparator(FFSeparatorOptions* options); void ffInitSeparatorOptions(FFSeparatorOptions* options); void ffDestroySeparatorOptions(FFSeparatorOptions* options); + +extern FFModuleBaseInfo ffSeparatorModuleInfo; diff --git a/src/modules/shell/option.h b/src/modules/shell/option.h index b356cbac93..49ec83f516 100644 --- a/src/modules/shell/option.h +++ b/src/modules/shell/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFShellOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFShellOptions; + +static_assert(sizeof(FFShellOptions) <= FF_OPTION_MAX_SIZE, "FFShellOptions size exceeds maximum allowed size"); diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index f68cb399d2..42bb9149d8 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -42,39 +42,22 @@ void ffPrintShell(FFShellOptions* options) } } -bool ffParseShellCommandOptions(FFShellOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_SHELL_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateShellJsonConfig(FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyShellOptions))) FFShellOptions defaultOptions; - ffInitShellOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateShellJsonResult(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -102,10 +85,21 @@ void ffGenerateShellJsonResult(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_m yyjson_mut_obj_add_null(doc, obj, "tty"); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitShellOptions(FFShellOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyShellOptions(FFShellOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffShellModuleInfo = { .name = FF_SHELL_MODULE_NAME, .description = "Print current shell name and version", - .parseCommandOptions = (void*) ffParseShellCommandOptions, + .initOptions = (void*) ffInitShellOptions, + .destroyOptions = (void*) ffDestroyShellOptions, .parseJsonObject = (void*) ffParseShellJsonObject, .printModule = (void*) ffPrintShell, .generateJsonResult = (void*) ffGenerateShellJsonResult, @@ -121,14 +115,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Shell tty used", "tty"}, })) }; - -void ffInitShellOptions(FFShellOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyShellOptions(FFShellOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/shell/shell.h b/src/modules/shell/shell.h index 01f9f17def..db39aa9643 100644 --- a/src/modules/shell/shell.h +++ b/src/modules/shell/shell.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_SHELL_MODULE_NAME "Shell" void ffPrintShell(FFShellOptions* options); void ffInitShellOptions(FFShellOptions* options); void ffDestroyShellOptions(FFShellOptions* options); + +extern FFModuleBaseInfo ffShellModuleInfo; diff --git a/src/modules/sound/option.h b/src/modules/sound/option.h index 7ec2c16147..0c9f0fd4f6 100644 --- a/src/modules/sound/option.h +++ b/src/modules/sound/option.h @@ -1,7 +1,5 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" @@ -14,9 +12,10 @@ typedef enum __attribute__((__packed__)) FFSoundType typedef struct FFSoundOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFSoundType soundType; FFPercentageModuleConfig percent; } FFSoundOptions; + +static_assert(sizeof(FFSoundOptions) <= FF_OPTION_MAX_SIZE, "FFSoundOptions size exceeds maximum allowed size"); diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index f57ebb0916..1b4d0285cd 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -112,44 +112,16 @@ void ffPrintSound(FFSoundOptions* options) } } -bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_SOUND_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "sound-type")) - { - options->soundType = (FFSoundType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "main", FF_SOUND_TYPE_MAIN }, - { "active", FF_SOUND_TYPE_ACTIVE }, - { "all", FF_SOUND_TYPE_ALL }, - {}, - }); - return true; - } - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "soundType")) + if (unsafe_yyjson_equals_str(key, "soundType")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -159,7 +131,7 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) {}, }); if (error) - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error); + ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); else options->soundType = (FFSoundType) value; continue; @@ -168,34 +140,28 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateSoundJsonConfig(FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroySoundOptions))) FFSoundOptions defaultOptions; - ffInitSoundOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (defaultOptions.soundType != options->soundType) + switch (options->soundType) { - switch (options->soundType) - { - case FF_SOUND_TYPE_MAIN: - yyjson_mut_obj_add_str(doc, module, "soundType", "main"); - break; - case FF_SOUND_TYPE_ACTIVE: - yyjson_mut_obj_add_str(doc, module, "soundType", "active"); - break; - case FF_SOUND_TYPE_ALL: - yyjson_mut_obj_add_str(doc, module, "soundType", "all"); - break; - } + case FF_SOUND_TYPE_MAIN: + yyjson_mut_obj_add_str(doc, module, "soundType", "main"); + break; + case FF_SOUND_TYPE_ACTIVE: + yyjson_mut_obj_add_str(doc, module, "soundType", "active"); + break; + case FF_SOUND_TYPE_ALL: + yyjson_mut_obj_add_str(doc, module, "soundType", "all"); + break; } - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -234,10 +200,24 @@ void ffGenerateSoundJsonResult(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_m } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitSoundOptions(FFSoundOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->soundType = FF_SOUND_TYPE_MAIN; + options->percent = (FFPercentageModuleConfig) { 80, 90, 0 }; +} + +void ffDestroySoundOptions(FFSoundOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffSoundModuleInfo = { .name = FF_SOUND_MODULE_NAME, .description = "Print sound devices, volume, etc", - .parseCommandOptions = (void*) ffParseSoundCommandOptions, + .initOptions = (void*) ffInitSoundOptions, + .destroyOptions = (void*) ffDestroySoundOptions, .parseJsonObject = (void*) ffParseSoundJsonObject, .printModule = (void*) ffPrintSound, .generateJsonResult = (void*) ffGenerateSoundJsonResult, @@ -251,17 +231,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Platform API used", "platform-api"}, })) }; - -void ffInitSoundOptions(FFSoundOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - - options->soundType = FF_SOUND_TYPE_MAIN; - options->percent = (FFPercentageModuleConfig) { 80, 90, 0 }; -} - -void ffDestroySoundOptions(FFSoundOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h index 35c3f2a7bf..80766b5ae4 100644 --- a/src/modules/sound/sound.h +++ b/src/modules/sound/sound.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_SOUND_MODULE_NAME "Sound" void ffPrintSound(FFSoundOptions* options); void ffInitSoundOptions(FFSoundOptions* options); void ffDestroySoundOptions(FFSoundOptions* options); + +extern FFModuleBaseInfo ffSoundModuleInfo; diff --git a/src/modules/swap/option.h b/src/modules/swap/option.h index e0f44e02a0..2d96911002 100644 --- a/src/modules/swap/option.h +++ b/src/modules/swap/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFSwapOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; bool separate; } FFSwapOptions; + +static_assert(sizeof(FFSwapOptions) <= FF_OPTION_MAX_SIZE, "FFSwapOptions size exceeds maximum allowed size"); diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index fb3072f44e..45e01c77bb 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -131,59 +131,34 @@ void ffPrintSwap(FFSwapOptions* options) } } -bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_SWAP_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - if (ffStrEqualsIgnCase(subKey, "separate")) - { - options->separate = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - if (ffStrEqualsIgnCase(key, "separate")) + if (unsafe_yyjson_equals_str(key, "separate")) { options->separate = yyjson_get_bool(val); continue; } - ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateSwapJsonConfig(FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroySwapOptions))) FFSwapOptions defaultOptions; - ffInitSwapOptions(&defaultOptions); - - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "separate", options->separate); } void ffGenerateSwapJsonResult(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -212,10 +187,23 @@ void ffGenerateSwapJsonResult(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitSwapOptions(FFSwapOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰓡"); + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; + options->separate = false; +} + +void ffDestroySwapOptions(FFSwapOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffSwapModuleInfo = { .name = FF_SWAP_MODULE_NAME, .description = "Print swap (paging file) space usage", - .parseCommandOptions = (void*) ffParseSwapCommandOptions, + .initOptions = (void*) ffInitSwapOptions, + .destroyOptions = (void*) ffDestroySwapOptions, .parseJsonObject = (void*) ffParseSwapJsonObject, .printModule = (void*) ffPrintSwap, .generateJsonResult = (void*) ffGenerateSwapJsonResult, @@ -228,16 +216,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Name", "name"}, })) }; - -void ffInitSwapOptions(FFSwapOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰓡"); - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; - options->separate = false; -} - -void ffDestroySwapOptions(FFSwapOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/swap/swap.h b/src/modules/swap/swap.h index b44ae4df39..7f31ecd01a 100644 --- a/src/modules/swap/swap.h +++ b/src/modules/swap/swap.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_SWAP_MODULE_NAME "Swap" void ffPrintSwap(FFSwapOptions* options); void ffInitSwapOptions(FFSwapOptions* options); void ffDestroySwapOptions(FFSwapOptions* options); + +extern FFModuleBaseInfo ffSwapModuleInfo; diff --git a/src/modules/terminal/option.h b/src/modules/terminal/option.h index e974c9979b..49b005e034 100644 --- a/src/modules/terminal/option.h +++ b/src/modules/terminal/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFTerminalOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFTerminalOptions; + +static_assert(sizeof(FFTerminalOptions) <= FF_OPTION_MAX_SIZE, "FFTerminalOptions size exceeds maximum allowed size"); diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index dc01af2db2..f5085421dd 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -38,39 +38,22 @@ void ffPrintTerminal(FFTerminalOptions* options) } } -bool ffParseTerminalCommandOptions(FFTerminalOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_TERMINAL_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateTerminalJsonConfig(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyTerminalOptions))) FFTerminalOptions defaultOptions; - ffInitTerminalOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateTerminalJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -95,10 +78,21 @@ void ffGenerateTerminalJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yy yyjson_mut_obj_add_strbuf(doc, obj, "tty", &result->tty); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitTerminalOptions(FFTerminalOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyTerminalOptions(FFTerminalOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTerminalModuleInfo = { .name = FF_TERMINAL_MODULE_NAME, .description = "Print current terminal name and version", - .parseCommandOptions = (void*) ffParseTerminalCommandOptions, + .initOptions = (void*) ffInitTerminalOptions, + .destroyOptions = (void*) ffDestroyTerminalOptions, .parseJsonObject = (void*) ffParseTerminalJsonObject, .printModule = (void*) ffPrintTerminal, .generateJsonResult = (void*) ffGenerateTerminalJsonResult, @@ -114,14 +108,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Terminal tty / pts used", "tty"}, })) }; - -void ffInitTerminalOptions(FFTerminalOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyTerminalOptions(FFTerminalOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/terminal/terminal.h b/src/modules/terminal/terminal.h index 9e1bbf75e2..df30bfadf7 100644 --- a/src/modules/terminal/terminal.h +++ b/src/modules/terminal/terminal.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_TERMINAL_MODULE_NAME "Terminal" void ffPrintTerminal(FFTerminalOptions* options); void ffInitTerminalOptions(FFTerminalOptions* options); void ffDestroyTerminalOptions(FFTerminalOptions* options); + +extern FFModuleBaseInfo ffTerminalModuleInfo; diff --git a/src/modules/terminalfont/option.h b/src/modules/terminalfont/option.h index 64417bf0aa..db652adcee 100644 --- a/src/modules/terminalfont/option.h +++ b/src/modules/terminalfont/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFTerminalFontOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFTerminalFontOptions; + +static_assert(sizeof(FFTerminalFontOptions) <= FF_OPTION_MAX_SIZE, "FFTerminalFontOptions size exceeds maximum allowed size"); diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 219b8fa72c..7ba2fc6730 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -46,42 +46,25 @@ void ffPrintTerminalFont(FFTerminalFontOptions* options) ffFontDestroy(&terminalFont.fallback); } -bool ffParseTerminalFontCommandOptions(FFTerminalFontOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_TERMINALFONT_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_TERMINALFONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_TERMINALFONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateTerminalFontJsonConfig(FFTerminalFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyTerminalFontOptions))) FFTerminalFontOptions defaultOptions; - ffInitTerminalFontOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } -void ffGenerateTerminalFontJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateTerminalFontJsonResult(FF_MAYBE_UNUSED FFTerminalFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFTerminalFontResult result; ffFontInit(&result.font); @@ -120,10 +103,21 @@ void ffGenerateTerminalFontJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options ffFontDestroy(&result.fallback); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitTerminalFontOptions(FFTerminalFontOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTerminalFontModuleInfo = { .name = FF_TERMINALFONT_MODULE_NAME, .description = "Print font name and size used by current terminal", - .parseCommandOptions = (void*) ffParseTerminalFontCommandOptions, + .initOptions = (void*) ffInitTerminalFontOptions, + .destroyOptions = (void*) ffDestroyTerminalFontOptions, .parseJsonObject = (void*) ffParseTerminalFontJsonObject, .printModule = (void*) ffPrintTerminalFont, .generateJsonResult = (void*) ffGenerateTerminalFontJsonResult, @@ -135,14 +129,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Terminal font styles", "styles"}, })), }; - -void ffInitTerminalFontOptions(FFTerminalFontOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/terminalfont/terminalfont.h b/src/modules/terminalfont/terminalfont.h index 01eee08022..c1716912ab 100644 --- a/src/modules/terminalfont/terminalfont.h +++ b/src/modules/terminalfont/terminalfont.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_TERMINALFONT_MODULE_NAME "TerminalFont" void ffPrintTerminalFont(FFTerminalFontOptions* options); void ffInitTerminalFontOptions(FFTerminalFontOptions* options); void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options); + +extern FFModuleBaseInfo ffTerminalFontModuleInfo; diff --git a/src/modules/terminalsize/option.h b/src/modules/terminalsize/option.h index 7d584837f5..518856a8c0 100644 --- a/src/modules/terminalsize/option.h +++ b/src/modules/terminalsize/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFTerminalSizeOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFTerminalSizeOptions; + +static_assert(sizeof(FFTerminalSizeOptions) <= FF_OPTION_MAX_SIZE, "FFTerminalSizeOptions size exceeds maximum allowed size"); diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 389f4d6f03..bc220107e2 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -38,42 +38,25 @@ void ffPrintTerminalSize(FFTerminalSizeOptions* options) } } -bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_TERMINALSIZE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateTerminalSizeJsonConfig(FFTerminalSizeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyTerminalSizeOptions))) FFTerminalSizeOptions defaultOptions; - ffInitTerminalSizeOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } -void ffGenerateTerminalSizeJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateTerminalSizeJsonResult(FF_MAYBE_UNUSED FFTerminalSizeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFTerminalSizeResult result; @@ -90,10 +73,21 @@ void ffGenerateTerminalSizeJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options yyjson_mut_obj_add_uint(doc, obj, "height", result.height); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰲎"); +} + +void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTerminalSizeModuleInfo = { .name = FF_TERMINALSIZE_MODULE_NAME, .description = "Print current terminal size", - .parseCommandOptions = (void*) ffParseTerminalSizeCommandOptions, + .initOptions = (void*) ffInitTerminalSizeOptions, + .destroyOptions = (void*) ffDestroyTerminalSizeOptions, .parseJsonObject = (void*) ffParseTerminalSizeJsonObject, .printModule = (void*) ffPrintTerminalSize, .generateJsonResult = (void*) ffGenerateTerminalSizeJsonResult, @@ -105,14 +99,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Terminal height (in pixels)", "height"}, })), }; - -void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰲎"); -} - -void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h index e88f8b6c7a..859d09b0c1 100644 --- a/src/modules/terminalsize/terminalsize.h +++ b/src/modules/terminalsize/terminalsize.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_TERMINALSIZE_MODULE_NAME "TerminalSize" void ffPrintTerminalSize(FFTerminalSizeOptions* options); void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options); void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); + +extern FFModuleBaseInfo ffTerminalSizeModuleInfo; diff --git a/src/modules/terminaltheme/option.h b/src/modules/terminaltheme/option.h index aecbe18d7c..3d8cdc252d 100644 --- a/src/modules/terminaltheme/option.h +++ b/src/modules/terminaltheme/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFTerminalThemeOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFTerminalThemeOptions; + +static_assert(sizeof(FFTerminalThemeOptions) <= FF_OPTION_MAX_SIZE, "FFTerminalThemeOptions size exceeds maximum allowed size"); diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 25834d66e1..e6286dd6a3 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -43,42 +43,25 @@ void ffPrintTerminalTheme(FFTerminalThemeOptions* options) } } -bool ffParseTerminalThemeCommandOptions(FFTerminalThemeOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_TERMINALTHEME_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseTerminalThemeJsonObject(FFTerminalThemeOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateTerminalThemeJsonConfig(FFTerminalThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyTerminalThemeOptions))) FFTerminalThemeOptions defaultOptions; - ffInitTerminalThemeOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } -void ffGenerateTerminalThemeJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateTerminalThemeJsonResult(FF_MAYBE_UNUSED FFTerminalThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFTerminalThemeResult result = {}; @@ -103,10 +86,21 @@ void ffGenerateTerminalThemeJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* option yyjson_mut_obj_add_bool(doc, bg, "dark", result.bg.dark); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰔎"); +} + +void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTerminalThemeModuleInfo = { .name = FF_TERMINALTHEME_MODULE_NAME, .description = "Print current terminal theme (foreground and background colors)", - .parseCommandOptions = (void*) ffParseTerminalThemeCommandOptions, + .initOptions = (void*) ffInitTerminalThemeOptions, + .destroyOptions = (void*) ffDestroyTerminalThemeOptions, .parseJsonObject = (void*) ffParseTerminalThemeJsonObject, .printModule = (void*) ffPrintTerminalTheme, .generateJsonResult = (void*) ffGenerateTerminalThemeJsonResult, @@ -118,14 +112,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Terminal background type (Dark / Light)", "bg-type"}, })) }; - -void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰔎"); -} - -void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/terminaltheme/terminaltheme.h b/src/modules/terminaltheme/terminaltheme.h index fb5cbb58ac..dbe6ac192f 100644 --- a/src/modules/terminaltheme/terminaltheme.h +++ b/src/modules/terminaltheme/terminaltheme.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_TERMINALTHEME_MODULE_NAME "TerminalTheme" void ffPrintTerminalTheme(FFTerminalThemeOptions* options); void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options); void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options); + +extern FFModuleBaseInfo ffTerminalThemeModuleInfo; diff --git a/src/modules/theme/option.h b/src/modules/theme/option.h index 9c3b32a888..ca232bfb9c 100644 --- a/src/modules/theme/option.h +++ b/src/modules/theme/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFThemeOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFThemeOptions; + +static_assert(sizeof(FFThemeOptions) <= FF_OPTION_MAX_SIZE, "FFThemeOptions size exceeds maximum allowed size"); diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index e99a217796..d0945fb0d6 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -43,39 +43,22 @@ void ffPrintTheme(FFThemeOptions* options) ffStrbufDestroy(&result.theme2); } -bool ffParseThemeCommandOptions(FFThemeOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_THEME_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateThemeJsonConfig(FFThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyThemeOptions))) FFThemeOptions defaultOptions; - ffInitThemeOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateThemeJsonResult(FF_MAYBE_UNUSED FFThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -100,10 +83,21 @@ void ffGenerateThemeJsonResult(FF_MAYBE_UNUSED FFThemeOptions* options, yyjson_m ffStrbufDestroy(&result.theme2); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitThemeOptions(FFThemeOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰉼"); +} + +void ffDestroyThemeOptions(FFThemeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffThemeModuleInfo = { .name = FF_THEME_MODULE_NAME, .description = "Print current theme of desktop environment", - .parseCommandOptions = (void*) ffParseThemeCommandOptions, + .initOptions = (void*) ffInitThemeOptions, + .destroyOptions = (void*) ffDestroyThemeOptions, .parseJsonObject = (void*) ffParseThemeJsonObject, .printModule = (void*) ffPrintTheme, .generateJsonResult = (void*) ffGenerateThemeJsonResult, @@ -113,14 +107,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Theme part 2", "theme2"}, })) }; - -void ffInitThemeOptions(FFThemeOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰉼"); -} - -void ffDestroyThemeOptions(FFThemeOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/theme/theme.h b/src/modules/theme/theme.h index 6ead202bff..6d677a2d05 100644 --- a/src/modules/theme/theme.h +++ b/src/modules/theme/theme.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_THEME_MODULE_NAME "Theme" void ffPrintTheme(FFThemeOptions* options); void ffInitThemeOptions(FFThemeOptions* options); void ffDestroyThemeOptions(FFThemeOptions* options); + +extern FFModuleBaseInfo ffThemeModuleInfo; diff --git a/src/modules/title/option.h b/src/modules/title/option.h index 9c3ea074bb..16505d39b4 100644 --- a/src/modules/title/option.h +++ b/src/modules/title/option.h @@ -1,16 +1,15 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFTitleOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - bool fqdn; FFstrbuf colorUser; FFstrbuf colorAt; FFstrbuf colorHost; + bool fqdn; } FFTitleOptions; + +static_assert(sizeof(FFTitleOptions) <= FF_OPTION_MAX_SIZE, "FFTitleOptions size exceeds maximum allowed size"); diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 02afec2ce9..d05a86b62f 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -2,7 +2,6 @@ #include "common/jsonconfig.h" #include "modules/title/title.h" #include "util/textModifier.h" -#include "util/stringUtils.h" static void appendText(FFstrbuf* output, const FFstrbuf* text, const FFstrbuf* color) { @@ -30,6 +29,7 @@ void ffPrintTitle(FFTitleOptions* options) FF_STRBUF_AUTO_DESTROY hostName = ffStrbufCreateCopy(&instance.state.platform.hostName); if (!options->fqdn) ffStrbufSubstrBeforeFirstC(&hostName, '.'); + instance.state.titleFqdn = options->fqdn; FF_STRBUF_AUTO_DESTROY hostNameColored = ffStrbufCreate(); appendText(&hostNameColored, &hostName, &options->colorHost); @@ -68,60 +68,22 @@ void ffPrintTitle(FFTitleOptions* options) } } -bool ffParseTitleCommandOptions(FFTitleOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_TITLE_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "fqdn")) - { - options->fqdn = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "color-user")) - { - ffOptionParseColor(value, &options->colorUser); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "color-at")) - { - ffOptionParseColor(value, &options->colorAt); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "color-host")) - { - ffOptionParseColor(value, &options->colorHost); - return true; - } - - return false; -} - void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "fqdn")) + if (unsafe_yyjson_equals_str(key, "fqdn")) { options->fqdn = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "color")) + if (unsafe_yyjson_equals_str(key, "color")) { if (!yyjson_is_obj(val)) continue; @@ -138,33 +100,20 @@ void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_TITLE_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key); + ffPrintError(FF_TITLE_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateTitleJsonConfig(FFTitleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyTitleOptions))) FFTitleOptions defaultOptions; - ffInitTitleOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - if (defaultOptions.fqdn != options->fqdn) - yyjson_mut_obj_add_bool(doc, module, "fqdn", options->fqdn); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - yyjson_mut_val* color = yyjson_mut_obj(doc); + yyjson_mut_obj_add_bool(doc, module, "fqdn", options->fqdn); - if (!ffStrbufEqual(&options->colorUser, &defaultOptions.colorUser)) - yyjson_mut_obj_add_strbuf(doc, color, "user", &options->colorUser); - - if (!ffStrbufEqual(&options->colorAt, &defaultOptions.colorAt)) - yyjson_mut_obj_add_strbuf(doc, color, "at", &options->colorAt); - - if (!ffStrbufEqual(&options->colorHost, &defaultOptions.colorHost)) - yyjson_mut_obj_add_strbuf(doc, color, "host", &options->colorHost); - - if (yyjson_mut_obj_size(color)) - yyjson_mut_obj_add_val(doc, module, "color", color); + yyjson_mut_val* color = yyjson_mut_obj_add_obj(doc, module, "color"); + yyjson_mut_obj_add_strbuf(doc, color, "user", &options->colorUser); + yyjson_mut_obj_add_strbuf(doc, color, "at", &options->colorAt); + yyjson_mut_obj_add_strbuf(doc, color, "host", &options->colorHost); } void ffGenerateTitleJsonResult(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -178,30 +127,8 @@ void ffGenerateTitleJsonResult(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_m yyjson_mut_obj_add_strbuf(doc, obj, "userShell", &instance.state.platform.userShell); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_TITLE_MODULE_NAME, - .description = "Print title, which contains your user name, hostname", - .parseCommandOptions = (void*) ffParseTitleCommandOptions, - .parseJsonObject = (void*) ffParseTitleJsonObject, - .printModule = (void*) ffPrintTitle, - .generateJsonResult = (void*) ffGenerateTitleJsonResult, - .generateJsonConfig = (void*) ffGenerateTitleJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"User name", "user-name"}, - {"Host name", "host-name"}, - {"Home directory", "home-dir"}, - {"Executable path of current process", "exe-path"}, - {"User's default shell", "user-shell"}, - {"User name (colored)", "user-name-colored"}, - {"@ symbol (colored)", "at-symbol-colored"}, - {"Host name (colored)", "host-name-colored"}, - {"Full user name", "full-user-name"}, - })) -}; - void ffInitTitleOptions(FFTitleOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, ""); ffStrbufSetStatic(&options->moduleArgs.key, " "); @@ -218,3 +145,25 @@ void ffDestroyTitleOptions(FFTitleOptions* options) ffStrbufDestroy(&options->colorAt); ffStrbufDestroy(&options->colorHost); } + +FFModuleBaseInfo ffTitleModuleInfo = { + .name = FF_TITLE_MODULE_NAME, + .description = "Print title, which contains your user name, hostname", + .initOptions = (void*) ffInitTitleOptions, + .destroyOptions = (void*) ffDestroyTitleOptions, + .parseJsonObject = (void*) ffParseTitleJsonObject, + .printModule = (void*) ffPrintTitle, + .generateJsonResult = (void*) ffGenerateTitleJsonResult, + .generateJsonConfig = (void*) ffGenerateTitleJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"User name", "user-name"}, + {"Host name", "host-name"}, + {"Home directory", "home-dir"}, + {"Executable path of current process", "exe-path"}, + {"User's default shell", "user-shell"}, + {"User name (colored)", "user-name-colored"}, + {"@ symbol (colored)", "at-symbol-colored"}, + {"Host name (colored)", "host-name-colored"}, + {"Full user name", "full-user-name"}, + })) +}; diff --git a/src/modules/title/title.h b/src/modules/title/title.h index 83ddfa9b53..4a41bcfe66 100644 --- a/src/modules/title/title.h +++ b/src/modules/title/title.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_TITLE_MODULE_NAME "Title" void ffPrintTitle(FFTitleOptions* options); void ffInitTitleOptions(FFTitleOptions* options); void ffDestroyTitleOptions(FFTitleOptions* options); + +extern FFModuleBaseInfo ffTitleModuleInfo; diff --git a/src/modules/tpm/option.h b/src/modules/tpm/option.h index d98c21df27..19fb790299 100644 --- a/src/modules/tpm/option.h +++ b/src/modules/tpm/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFTPMOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFTPMOptions; + +static_assert(sizeof(FFTPMOptions) <= FF_OPTION_MAX_SIZE, "FFTPMOptions size exceeds maximum allowed size"); diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 9d849671a1..ad540bf121 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -38,42 +38,25 @@ void ffPrintTPM(FFTPMOptions* options) ffStrbufDestroy(&result.description); } -bool ffParseTPMCommandOptions(FFTPMOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_TPM_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseTPMJsonObject(FFTPMOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateTPMJsonConfig(FFTPMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyTPMOptions))) FFTPMOptions defaultOptions; - ffInitTPMOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } -void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTPMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFTPMResult result = { .version = ffStrbufCreate(), @@ -95,10 +78,21 @@ void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_ ffStrbufDestroy(&result.description); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitTPMOptions(FFTPMOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyTPMOptions(FFTPMOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTPMModuleInfo = { .name = FF_TPM_MODULE_NAME, .description = "Print info of Trusted Platform Module (TPM) Security Device", - .parseCommandOptions = (void*) ffParseTPMCommandOptions, + .initOptions = (void*) ffInitTPMOptions, + .destroyOptions = (void*) ffDestroyTPMOptions, .parseJsonObject = (void*) ffParseTPMJsonObject, .printModule = (void*) ffPrintTPM, .generateJsonResult = (void*) ffGenerateTPMJsonResult, @@ -108,14 +102,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"TPM general description", "description"}, })) }; - -void ffInitTPMOptions(FFTPMOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyTPMOptions(FFTPMOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/tpm/tpm.h b/src/modules/tpm/tpm.h index 3356a46dc0..c5ef666df9 100644 --- a/src/modules/tpm/tpm.h +++ b/src/modules/tpm/tpm.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_TPM_MODULE_NAME "TPM" void ffPrintTPM(FFTPMOptions* options); void ffInitTPMOptions(FFTPMOptions* options); void ffDestroyTPMOptions(FFTPMOptions* options); + +extern FFModuleBaseInfo ffTPMModuleInfo; diff --git a/src/modules/uptime/option.h b/src/modules/uptime/option.h index f047db76c8..4235995c59 100644 --- a/src/modules/uptime/option.h +++ b/src/modules/uptime/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFUptimeOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFUptimeOptions; + +static_assert(sizeof(FFUptimeOptions) <= FF_OPTION_MAX_SIZE, "FFUptimeOptions size exceeds maximum allowed size"); diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 74d985f85d..ca64ec572a 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -56,39 +56,22 @@ void ffPrintUptime(FFUptimeOptions* options) } } -bool ffParseUptimeCommandOptions(FFUptimeOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_UPTIME_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateUptimeJsonConfig(FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyUptimeOptions))) FFUptimeOptions defaultOptions; - ffInitUptimeOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateUptimeJsonResult(FF_MAYBE_UNUSED FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -107,10 +90,21 @@ void ffGenerateUptimeJsonResult(FF_MAYBE_UNUSED FFUptimeOptions* options, yyjson yyjson_mut_obj_add_strcpy(doc, obj, "bootTime", ffTimeToFullStr(result.bootTime)); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitUptimeOptions(FFUptimeOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyUptimeOptions(FFUptimeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffUptimeModuleInfo = { .name = FF_UPTIME_MODULE_NAME, .description = "Print how long system has been running", - .parseCommandOptions = (void*) ffParseUptimeCommandOptions, + .initOptions = (void*) ffInitUptimeOptions, + .destroyOptions = (void*) ffDestroyUptimeOptions, .parseJsonObject = (void*) ffParseUptimeJsonObject, .printModule = (void*) ffPrintUptime, .generateJsonResult = (void*) ffGenerateUptimeJsonResult, @@ -128,14 +122,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Formatted uptime", "formatted"}, })) }; - -void ffInitUptimeOptions(FFUptimeOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyUptimeOptions(FFUptimeOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h index 17b6c1bc6f..a12fcd549f 100644 --- a/src/modules/uptime/uptime.h +++ b/src/modules/uptime/uptime.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_UPTIME_MODULE_NAME "Uptime" void ffPrintUptime(FFUptimeOptions* options); void ffInitUptimeOptions(FFUptimeOptions* options); void ffDestroyUptimeOptions(FFUptimeOptions* options); + +extern FFModuleBaseInfo ffUptimeModuleInfo; diff --git a/src/modules/users/option.h b/src/modules/users/option.h index af194fea2d..16ea5e88f7 100644 --- a/src/modules/users/option.h +++ b/src/modules/users/option.h @@ -1,14 +1,13 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFUsersOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool compact; bool myselfOnly; } FFUsersOptions; + +static_assert(sizeof(FFUsersOptions) <= FF_OPTION_MAX_SIZE, "FFUsersOptions size exceeds maximum allowed size"); diff --git a/src/modules/users/users.c b/src/modules/users/users.c index 9ba72977b8..fce2dc7efa 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -107,69 +107,41 @@ void ffPrintUsers(FFUsersOptions* options) } } -bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_USERS_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "compact")) - { - options->compact = ffOptionParseBoolean(value); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "myself-only")) - { - options->myselfOnly = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if (ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) + if (unsafe_yyjson_equals_str(key, "type") || unsafe_yyjson_equals_str(key, "condition")) continue; if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "compact")) + if (unsafe_yyjson_equals_str(key, "compact")) { options->compact = yyjson_get_bool(val); continue; } - if (ffStrEqualsIgnCase(key, "myselfOnly")) + if (unsafe_yyjson_equals_str(key, "myselfOnly")) { options->myselfOnly = yyjson_get_bool(val); continue; } - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateUsersJsonConfig(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyUsersOptions))) FFUsersOptions defaultOptions; - ffInitUsersOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); - if (options->compact != defaultOptions.compact) - yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); - - if (options->myselfOnly != defaultOptions.myselfOnly) - yyjson_mut_obj_add_bool(doc, module, "myselfOnly", options->myselfOnly); + yyjson_mut_obj_add_bool(doc, module, "myselfOnly", options->myselfOnly); } void ffGenerateUsersJsonResult(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -208,10 +180,24 @@ void ffGenerateUsersJsonResult(FFUsersOptions* options, yyjson_mut_doc* doc, yyj } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitUsersOptions(FFUsersOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->compact = false; + options->myselfOnly = false; +} + +void ffDestroyUsersOptions(FFUsersOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffUsersModuleInfo = { .name = FF_USERS_MODULE_NAME, .description = "Print users currently logged in", - .parseCommandOptions = (void*) ffParseUsersCommandOptions, + .initOptions = (void*) ffInitUsersOptions, + .destroyOptions = (void*) ffDestroyUsersOptions, .parseJsonObject = (void*) ffParseUsersJsonObject, .printModule = (void*) ffPrintUsers, .generateJsonResult = (void*) ffGenerateUsersJsonResult, @@ -232,17 +218,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Years fraction after login", "years-fraction"}, })) }; - -void ffInitUsersOptions(FFUsersOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - - options->compact = false; - options->myselfOnly = false; -} - -void ffDestroyUsersOptions(FFUsersOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/users/users.h b/src/modules/users/users.h index 81d3dd3f50..bc249bda1e 100644 --- a/src/modules/users/users.h +++ b/src/modules/users/users.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_USERS_MODULE_NAME "Users" void ffPrintUsers(FFUsersOptions* options); void ffInitUsersOptions(FFUsersOptions* options); void ffDestroyUsersOptions(FFUsersOptions* options); + +extern FFModuleBaseInfo ffUsersModuleInfo; diff --git a/src/modules/version/option.h b/src/modules/version/option.h index 12c151be0f..f3b68b4f2f 100644 --- a/src/modules/version/option.h +++ b/src/modules/version/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFVersionOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFVersionOptions; + +static_assert(sizeof(FFVersionOptions) <= FF_OPTION_MAX_SIZE, "FFVersionOptions size exceeds maximum allowed size"); diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 426cbc3d26..15f519c123 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -44,39 +44,22 @@ void ffPrintVersion(FFVersionOptions* options) } } -bool ffParseVersionCommandOptions(FFVersionOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_VERSION_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateVersionJsonConfig(FFVersionOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyVersionOptions))) FFVersionOptions defaultOptions; - ffInitVersionOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateVersionJsonResult(FF_MAYBE_UNUSED FFVersionOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -111,10 +94,21 @@ void ffGenerateVersionJsonResult(FF_MAYBE_UNUSED FFVersionOptions* options, yyjs } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitVersionOptions(FFVersionOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyVersionOptions(FFVersionOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffVersionModuleInfo = { .name = FF_VERSION_MODULE_NAME, .description = "Print Fastfetch version", - .parseCommandOptions = (void*) ffParseVersionCommandOptions, + .initOptions = (void*) ffInitVersionOptions, + .destroyOptions = (void*) ffDestroyVersionOptions, .parseJsonObject = (void*) ffParseVersionJsonObject, .printModule = (void*) ffPrintVersion, .generateJsonResult = (void*) ffGenerateVersionJsonResult, @@ -132,14 +126,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Libc used when compiling", "libc"}, })) }; - -void ffInitVersionOptions(FFVersionOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyVersionOptions(FFVersionOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/version/version.h b/src/modules/version/version.h index 1cab28d94d..1135e53943 100644 --- a/src/modules/version/version.h +++ b/src/modules/version/version.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_VERSION_MODULE_NAME "Version" void ffPrintVersion(FFVersionOptions* options); void ffInitVersionOptions(FFVersionOptions* options); void ffDestroyVersionOptions(FFVersionOptions* options); + +extern FFModuleBaseInfo ffVersionModuleInfo; diff --git a/src/modules/vulkan/option.h b/src/modules/vulkan/option.h index 132af5bbe8..38ec20c995 100644 --- a/src/modules/vulkan/option.h +++ b/src/modules/vulkan/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFVulkanOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFVulkanOptions; + +static_assert(sizeof(FFVulkanOptions) <= FF_OPTION_MAX_SIZE, "FFVulkanOptions size exceeds maximum allowed size"); diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index d67ca9e703..429df582c0 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -50,39 +50,22 @@ void ffPrintVulkan(FFVulkanOptions* options) } } -bool ffParseVulkanCommandOptions(FFVulkanOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_VULKAN_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateVulkanJsonConfig(FFVulkanOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyVulkanOptions))) FFVulkanOptions defaultOptions; - ffInitVulkanOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateVulkanJsonResult(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -142,10 +125,21 @@ void ffGenerateVulkanJsonResult(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitVulkanOptions(FFVulkanOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyVulkanOptions(FFVulkanOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffVulkanModuleInfo = { .name = FF_VULKAN_MODULE_NAME, .description = "Print highest Vulkan version supported by the GPU", - .parseCommandOptions = (void*) ffParseVulkanCommandOptions, + .initOptions = (void*) ffInitVulkanOptions, + .destroyOptions = (void*) ffDestroyVulkanOptions, .parseJsonObject = (void*) ffParseVulkanJsonObject, .printModule = (void*) ffPrintVulkan, .generateJsonResult = (void*) ffGenerateVulkanJsonResult, @@ -157,14 +151,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Instance version", "instance-version"}, })) }; - -void ffInitVulkanOptions(FFVulkanOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); -} - -void ffDestroyVulkanOptions(FFVulkanOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/vulkan/vulkan.h b/src/modules/vulkan/vulkan.h index 397c420930..7a5d0f29d4 100644 --- a/src/modules/vulkan/vulkan.h +++ b/src/modules/vulkan/vulkan.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_VULKAN_MODULE_NAME "Vulkan" void ffPrintVulkan(FFVulkanOptions* options); void ffInitVulkanOptions(FFVulkanOptions* options); void ffDestroyVulkanOptions(FFVulkanOptions* options); + +extern FFModuleBaseInfo ffVulkanModuleInfo; diff --git a/src/modules/wallpaper/option.h b/src/modules/wallpaper/option.h index 539a57f9b7..621699fa33 100644 --- a/src/modules/wallpaper/option.h +++ b/src/modules/wallpaper/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFWallpaperOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFWallpaperOptions; + +static_assert(sizeof(FFWallpaperOptions) <= FF_OPTION_MAX_SIZE, "FFWallpaperOptions size exceeds maximum allowed size"); diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index bd95a4d0e5..6c6466b385 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -40,39 +40,22 @@ void ffPrintWallpaper(FFWallpaperOptions* options) } } -bool ffParseWallpaperCommandOptions(FFWallpaperOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_WALLPAPER_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateWallpaperJsonConfig(FFWallpaperOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyWallpaperOptions))) FFWallpaperOptions defaultOptions; - ffInitWallpaperOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateWallpaperJsonResult(FF_MAYBE_UNUSED FFWallpaperOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -87,10 +70,21 @@ void ffGenerateWallpaperJsonResult(FF_MAYBE_UNUSED FFWallpaperOptions* options, yyjson_mut_obj_add_strbuf(doc, module, "result", &fullpath); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitWallpaperOptions(FFWallpaperOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰸉"); +} + +void ffDestroyWallpaperOptions(FFWallpaperOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffWallpaperModuleInfo = { .name = FF_WALLPAPER_MODULE_NAME, .description = "Print image file path of current wallpaper", - .parseCommandOptions = (void*) ffParseWallpaperCommandOptions, + .initOptions = (void*) ffInitWallpaperOptions, + .destroyOptions = (void*) ffDestroyWallpaperOptions, .parseJsonObject = (void*) ffParseWallpaperJsonObject, .printModule = (void*) ffPrintWallpaper, .generateJsonResult = (void*) ffGenerateWallpaperJsonResult, @@ -100,14 +94,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Full path", "full-path"}, })) }; - -void ffInitWallpaperOptions(FFWallpaperOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰸉"); -} - -void ffDestroyWallpaperOptions(FFWallpaperOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/wallpaper/wallpaper.h b/src/modules/wallpaper/wallpaper.h index a2c804ae3d..3ca28bfcdb 100644 --- a/src/modules/wallpaper/wallpaper.h +++ b/src/modules/wallpaper/wallpaper.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_WALLPAPER_MODULE_NAME "Wallpaper" void ffPrintWallpaper(FFWallpaperOptions* options); void ffInitWallpaperOptions(FFWallpaperOptions* options); void ffDestroyWallpaperOptions(FFWallpaperOptions* options); + +extern FFModuleBaseInfo ffWallpaperModuleInfo; diff --git a/src/modules/weather/option.h b/src/modules/weather/option.h index b8c7e7cade..76c3df11b3 100644 --- a/src/modules/weather/option.h +++ b/src/modules/weather/option.h @@ -1,15 +1,14 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFWeatherOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf location; FFstrbuf outputFormat; uint32_t timeout; } FFWeatherOptions; + +static_assert(sizeof(FFWeatherOptions) <= FF_OPTION_MAX_SIZE, "FFWeatherOptions size exceeds maximum allowed size"); diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 78570d0efa..fec43ff5da 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -29,84 +29,46 @@ void ffPrintWeather(FFWeatherOptions* options) } } -bool ffParseWeatherCommandOptions(FFWeatherOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_WEATHER_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "location")) - { - ffOptionParseString(key, value, &options->location); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "output-format")) - { - ffOptionParseString(key, value, &options->outputFormat); - return true; - } - - if (ffStrEqualsIgnCase(subKey, "timeout")) - { - options->timeout = ffOptionParseUInt32(key, value); - return true; - } - - return false; -} - void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "location")) + if (unsafe_yyjson_equals_str(key, "location")) { - ffStrbufSetS(&options->location, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->location, val); continue; } - if (ffStrEqualsIgnCase(key, "outputFormat")) + if (unsafe_yyjson_equals_str(key, "outputFormat")) { - ffStrbufSetS(&options->outputFormat, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->outputFormat, val); continue; } - if (ffStrEqualsIgnCase(key, "timeout")) + if (unsafe_yyjson_equals_str(key, "timeout")) { options->timeout = (uint32_t) yyjson_get_uint(val); continue; } - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateWeatherJsonConfig(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions defaultOptions; - ffInitWeatherOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + yyjson_mut_obj_add_strbuf(doc, module, "location", &options->location); - if (!ffStrbufEqual(&options->location, &defaultOptions.location)) - yyjson_mut_obj_add_strbuf(doc, module, "location", &options->location); + yyjson_mut_obj_add_strbuf(doc, module, "outputFormat", &options->outputFormat); - if (!ffStrbufEqual(&options->outputFormat, &defaultOptions.outputFormat)) - yyjson_mut_obj_add_strbuf(doc, module, "outputFormat", &options->outputFormat); - - if (options->timeout != defaultOptions.timeout) - yyjson_mut_obj_add_uint(doc, module, "timeout", options->timeout); + yyjson_mut_obj_add_uint(doc, module, "timeout", options->timeout); } void ffGenerateWeatherJsonResult(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -123,22 +85,8 @@ void ffGenerateWeatherJsonResult(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, module, "result", &result); } -static FFModuleBaseInfo ffModuleInfo = { - .name = FF_WEATHER_MODULE_NAME, - .description = "Print weather information", - .parseCommandOptions = (void*) ffParseWeatherCommandOptions, - .parseJsonObject = (void*) ffParseWeatherJsonObject, - .printModule = (void*) ffPrintWeather, - .generateJsonResult = (void*) ffGenerateWeatherJsonResult, - .generateJsonConfig = (void*) ffGenerateWeatherJsonConfig, - .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Weather result", "result"}, - })) -}; - void ffInitWeatherOptions(FFWeatherOptions* options) { - options->moduleInfo = ffModuleInfo; ffOptionInitModuleArg(&options->moduleArgs, "󰖙"); ffStrbufInit(&options->location); @@ -152,3 +100,17 @@ void ffDestroyWeatherOptions(FFWeatherOptions* options) ffStrbufDestroy(&options->outputFormat); } + +FFModuleBaseInfo ffWeatherModuleInfo = { + .name = FF_WEATHER_MODULE_NAME, + .description = "Print weather information", + .initOptions = (void*) ffInitWeatherOptions, + .destroyOptions = (void*) ffDestroyWeatherOptions, + .parseJsonObject = (void*) ffParseWeatherJsonObject, + .printModule = (void*) ffPrintWeather, + .generateJsonResult = (void*) ffGenerateWeatherJsonResult, + .generateJsonConfig = (void*) ffGenerateWeatherJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + {"Weather result", "result"}, + })) +}; diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h index 1ec2f02a2a..5b3c9739bf 100644 --- a/src/modules/weather/weather.h +++ b/src/modules/weather/weather.h @@ -1,6 +1,6 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_WEATHER_MODULE_NAME "Weather" @@ -9,3 +9,5 @@ void ffPrepareWeather(FFWeatherOptions* options); void ffPrintWeather(FFWeatherOptions* options); void ffInitWeatherOptions(FFWeatherOptions* options); void ffDestroyWeatherOptions(FFWeatherOptions* options); + +extern FFModuleBaseInfo ffWeatherModuleInfo; diff --git a/src/modules/wifi/option.h b/src/modules/wifi/option.h index 3628df69dc..f745792673 100644 --- a/src/modules/wifi/option.h +++ b/src/modules/wifi/option.h @@ -1,13 +1,12 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFWifiOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; } FFWifiOptions; + +static_assert(sizeof(FFWifiOptions) <= FF_OPTION_MAX_SIZE, "FFWifiOptions size exceeds maximum allowed size"); diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index c7038a0fc0..69df42cf58 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -55,7 +55,7 @@ void ffPrintWifi(FFWifiOptions* options) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if(item->conn.ssid.length) { - if(item->conn.signalQuality == item->conn.signalQuality) + if(item->conn.signalQuality != -DBL_MAX) { if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { @@ -86,7 +86,7 @@ void ffPrintWifi(FFWifiOptions* options) ffStrbufAppendC(&buffer, ' '); } - if(item->conn.signalQuality == item->conn.signalQuality) + if(item->conn.signalQuality != -DBL_MAX) { if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffPercentAppendNum(&buffer, item->conn.signalQuality, options->percent, buffer.length > 0, &options->moduleArgs); @@ -136,47 +136,27 @@ void ffPrintWifi(FFWifiOptions* options) } } -bool ffParseWifiCommandOptions(FFWifiOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_WIFI_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateWifiJsonConfig(FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyWifiOptions))) FFWifiOptions defaultOptions; - ffInitWifiOptions(&defaultOptions); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -204,9 +184,18 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, conn, "bssid", &wifi->conn.bssid); yyjson_mut_obj_add_strbuf(doc, conn, "protocol", &wifi->conn.protocol); yyjson_mut_obj_add_strbuf(doc, conn, "security", &wifi->conn.security); - yyjson_mut_obj_add_real(doc, conn, "signalQuality", wifi->conn.signalQuality); - yyjson_mut_obj_add_real(doc, conn, "rxRate", wifi->conn.rxRate); - yyjson_mut_obj_add_real(doc, conn, "txRate", wifi->conn.txRate); + if (wifi->conn.signalQuality != -DBL_MAX) + yyjson_mut_obj_add_real(doc, conn, "signalQuality", wifi->conn.signalQuality); + else + yyjson_mut_obj_add_null(doc, conn, "signalQuality"); + if (wifi->conn.rxRate != -DBL_MAX) + yyjson_mut_obj_add_real(doc, conn, "rxRate", wifi->conn.rxRate); + else + yyjson_mut_obj_add_null(doc, conn, "rxRate"); + if (wifi->conn.txRate != -DBL_MAX) + yyjson_mut_obj_add_real(doc, conn, "txRate", wifi->conn.txRate); + else + yyjson_mut_obj_add_null(doc, conn, "txRate"); yyjson_mut_obj_add_uint(doc, conn, "channel", wifi->conn.channel); yyjson_mut_obj_add_uint(doc, conn, "frequency", wifi->conn.frequency); } @@ -223,10 +212,23 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitWifiOptions(FFWifiOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->percent = (FFPercentageModuleConfig) { 75, 50, 0 }; +} + +void ffDestroyWifiOptions(FFWifiOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffWifiModuleInfo = { .name = FF_WIFI_MODULE_NAME, .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", - .parseCommandOptions = (void*) ffParseWifiCommandOptions, + .initOptions = (void*) ffInitWifiOptions, + .destroyOptions = (void*) ffDestroyWifiOptions, .parseJsonObject = (void*) ffParseWifiJsonObject, .printModule = (void*) ffPrintWifi, .generateJsonResult = (void*) ffGenerateWifiJsonResult, @@ -247,16 +249,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Connection channel band in GHz", "band"}, })) }; - -void ffInitWifiOptions(FFWifiOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - - options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; -} - -void ffDestroyWifiOptions(FFWifiOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/wifi/wifi.h b/src/modules/wifi/wifi.h index bd23565d38..0fcef5f1c8 100644 --- a/src/modules/wifi/wifi.h +++ b/src/modules/wifi/wifi.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_WIFI_MODULE_NAME "Wifi" void ffPrintWifi(FFWifiOptions* options); void ffInitWifiOptions(FFWifiOptions* options); void ffDestroyWifiOptions(FFWifiOptions* options); + +extern FFModuleBaseInfo ffWifiModuleInfo; diff --git a/src/modules/wm/option.h b/src/modules/wm/option.h index b38ab7c3a3..d213c9c3ad 100644 --- a/src/modules/wm/option.h +++ b/src/modules/wm/option.h @@ -1,13 +1,12 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFWMOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; bool detectPlugin; } FFWMOptions; + +static_assert(sizeof(FFWMOptions) <= FF_OPTION_MAX_SIZE, "FFWMOptions size exceeds maximum allowed size"); diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 5dc4135638..6753ce2da8 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -63,54 +63,30 @@ void ffPrintWM(FFWMOptions* options) } } -bool ffParseWMCommandOptions(FFWMOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_WM_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffStrEqualsIgnCase(subKey, "detect-plugin")) - { - options->detectPlugin = ffOptionParseBoolean(value); - return true; - } - - return false; -} - void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - if (ffStrEqualsIgnCase(key, "detectPlugin")) + if (unsafe_yyjson_equals_str(key, "detectPlugin")) { options->detectPlugin = yyjson_get_bool(val); continue; } - ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateWMJsonConfig(FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyWMOptions))) FFWMOptions defaultOptions; - ffInitWMOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - if (options->detectPlugin != defaultOptions.detectPlugin) - yyjson_mut_obj_add_bool(doc, module, "detectPlugin", options->detectPlugin); + yyjson_mut_obj_add_bool(doc, module, "detectPlugin", options->detectPlugin); } void ffGenerateWMJsonResult(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -139,10 +115,22 @@ void ffGenerateWMJsonResult(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "version", &version); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitWMOptions(FFWMOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, ""); + options->detectPlugin = false; +} + +void ffDestroyWMOptions(FFWMOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffWMModuleInfo = { .name = FF_WM_MODULE_NAME, .description = "Print window manager name and version", - .parseCommandOptions = (void*) ffParseWMCommandOptions, + .initOptions = (void*) ffInitWMOptions, + .destroyOptions = (void*) ffDestroyWMOptions, .parseJsonObject = (void*) ffParseWMJsonObject, .printModule = (void*) ffPrintWM, .generateJsonResult = (void*) ffGenerateWMJsonResult, @@ -155,15 +143,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"WM version", "version"}, })) }; - -void ffInitWMOptions(FFWMOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, ""); - options->detectPlugin = false; -} - -void ffDestroyWMOptions(FFWMOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/wm/wm.h b/src/modules/wm/wm.h index 93edec8b45..5b6556806b 100644 --- a/src/modules/wm/wm.h +++ b/src/modules/wm/wm.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_WM_MODULE_NAME "WM" void ffPrintWM(FFWMOptions* options); void ffInitWMOptions(FFWMOptions* options); void ffDestroyWMOptions(FFWMOptions* options); + +extern FFModuleBaseInfo ffWMModuleInfo; diff --git a/src/modules/wmtheme/option.h b/src/modules/wmtheme/option.h index b2b9fc5a8c..b12f9f8b30 100644 --- a/src/modules/wmtheme/option.h +++ b/src/modules/wmtheme/option.h @@ -1,11 +1,10 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" typedef struct FFWMThemeOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; } FFWMThemeOptions; + +static_assert(sizeof(FFWMThemeOptions) <= FF_OPTION_MAX_SIZE, "FFWMThemeOptions size exceeds maximum allowed size"); diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 6659d88e1b..d40ab821e9 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -29,39 +29,22 @@ void ffPrintWMTheme(FFWMThemeOptions* options) } } -bool ffParseWMThemeCommandOptions(FFWMThemeOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_WMTHEME_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; - ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateWMThemeJsonConfig(FFWMThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyWMThemeOptions))) FFWMThemeOptions defaultOptions; - ffInitWMThemeOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); } void ffGenerateWMThemeJsonResult(FF_MAYBE_UNUSED FFWMThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -76,10 +59,21 @@ void ffGenerateWMThemeJsonResult(FF_MAYBE_UNUSED FFWMThemeOptions* options, yyjs yyjson_mut_obj_add_strbuf(doc, module, "result", &themeOrError); } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitWMThemeOptions(FFWMThemeOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󰓸"); +} + +void ffDestroyWMThemeOptions(FFWMThemeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffWMThemeModuleInfo = { .name = FF_WMTHEME_MODULE_NAME, .description = "Print current theme of window manager", - .parseCommandOptions = (void*) ffParseWMThemeCommandOptions, + .initOptions = (void*) ffInitWMThemeOptions, + .destroyOptions = (void*) ffDestroyWMThemeOptions, .parseJsonObject = (void*) ffParseWMThemeJsonObject, .printModule = (void*) ffPrintWMTheme, .generateJsonResult = (void*) ffGenerateWMThemeJsonResult, @@ -88,14 +82,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"WM theme", "result"}, })) }; - -void ffInitWMThemeOptions(FFWMThemeOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󰓸"); -} - -void ffDestroyWMThemeOptions(FFWMThemeOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/wmtheme/wmtheme.h b/src/modules/wmtheme/wmtheme.h index 9a2a24982f..e3bad8ee06 100644 --- a/src/modules/wmtheme/wmtheme.h +++ b/src/modules/wmtheme/wmtheme.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_WMTHEME_MODULE_NAME "WMTheme" void ffPrintWMTheme(FFWMThemeOptions* options); void ffInitWMThemeOptions(FFWMThemeOptions* options); void ffDestroyWMThemeOptions(FFWMThemeOptions* options); + +extern FFModuleBaseInfo ffWMThemeModuleInfo; diff --git a/src/modules/zpool/option.h b/src/modules/zpool/option.h index ac4f8ff3ff..49522b3be5 100644 --- a/src/modules/zpool/option.h +++ b/src/modules/zpool/option.h @@ -1,14 +1,13 @@ #pragma once -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - #include "common/option.h" #include "common/percent.h" typedef struct FFZpoolOptions { - FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFPercentageModuleConfig percent; } FFZpoolOptions; + +static_assert(sizeof(FFZpoolOptions) <= FF_OPTION_MAX_SIZE, "FFZpoolOptions size exceeds maximum allowed size"); diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 151836f0b5..9efddacdb8 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -107,47 +107,27 @@ void ffPrintZpool(FFZpoolOptions* options) } } -bool ffParseZpoolCommandOptions(FFZpoolOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_ZPOOL_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) - return true; - - return false; -} - void ffParseZpoolJsonObject(FFZpoolOptions* options, yyjson_val* module) { - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(module, idx, max, key_, val) + yyjson_obj_foreach(module, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - if(ffStrEqualsIgnCase(key, "type") || ffStrEqualsIgnCase(key, "condition")) - continue; - if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; if (ffPercentParseJsonObject(key, val, &options->percent)) continue; - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateZpoolJsonConfig(FFZpoolOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - __attribute__((__cleanup__(ffDestroyZpoolOptions))) FFZpoolOptions defaultOptions; - ffInitZpoolOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); - ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + ffPercentGenerateJsonConfig(doc, module, options->percent); } void ffGenerateZpoolJsonResult(FF_MAYBE_UNUSED FFZpoolOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -171,7 +151,10 @@ void ffGenerateZpoolJsonResult(FF_MAYBE_UNUSED FFZpoolOptions* options, yyjson_m yyjson_mut_obj_add_uint(doc, obj, "used", zpool->used); yyjson_mut_obj_add_uint(doc, obj, "total", zpool->total); yyjson_mut_obj_add_uint(doc, obj, "version", zpool->version); - yyjson_mut_obj_add_real(doc, obj, "fragmentation", zpool->fragmentation); + if (zpool->fragmentation != -DBL_MAX) + yyjson_mut_obj_add_real(doc, obj, "fragmentation", zpool->fragmentation); + else + yyjson_mut_obj_add_null(doc, obj, "fragmentation"); } FF_LIST_FOR_EACH(FFZpoolResult, zpool, results) @@ -181,10 +164,22 @@ void ffGenerateZpoolJsonResult(FF_MAYBE_UNUSED FFZpoolOptions* options, yyjson_m } } -static FFModuleBaseInfo ffModuleInfo = { +void ffInitZpoolOptions(FFZpoolOptions* options) +{ + ffOptionInitModuleArg(&options->moduleArgs, "󱑛"); + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; +} + +void ffDestroyZpoolOptions(FFZpoolOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffZpoolModuleInfo = { .name = FF_ZPOOL_MODULE_NAME, .description = "Print ZFS storage pools", - .parseCommandOptions = (void*) ffParseZpoolCommandOptions, + .initOptions = (void*) ffInitZpoolOptions, + .destroyOptions = (void*) ffDestroyZpoolOptions, .parseJsonObject = (void*) ffParseZpoolJsonObject, .printModule = (void*) ffPrintZpool, .generateJsonResult = (void*) ffGenerateZpoolJsonResult, @@ -200,15 +195,3 @@ static FFModuleBaseInfo ffModuleInfo = { {"Fragmentation percentage bar", "fragmentation-percentage-bar"}, })) }; - -void ffInitZpoolOptions(FFZpoolOptions* options) -{ - options->moduleInfo = ffModuleInfo; - ffOptionInitModuleArg(&options->moduleArgs, "󱑛"); - options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; -} - -void ffDestroyZpoolOptions(FFZpoolOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/zpool/zpool.h b/src/modules/zpool/zpool.h index 03623e063e..7f282f2538 100644 --- a/src/modules/zpool/zpool.h +++ b/src/modules/zpool/zpool.h @@ -1,9 +1,11 @@ #pragma once -#include "fastfetch.h" +#include "option.h" #define FF_ZPOOL_MODULE_NAME "Zpool" void ffPrintZpool(FFZpoolOptions* options); void ffInitZpoolOptions(FFZpoolOptions* options); void ffDestroyZpoolOptions(FFZpoolOptions* options); + +extern FFModuleBaseInfo ffZpoolModuleInfo; diff --git a/src/options/display.c b/src/options/display.c index eae73b1c9b..95cff25e87 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -13,13 +13,11 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va if (!object) return NULL; if (!yyjson_is_obj(object)) return "Property 'display' must be an object"; - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(object, idx, max, key_, val) + yyjson_obj_foreach(object, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - - if (ffStrEqualsIgnCase(key, "stat")) + if (unsafe_yyjson_equals_str(key, "stat")) { if (yyjson_is_bool(val)) { @@ -39,46 +37,44 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va else return "display.stat must be a boolean or a positive integer"; } - else if (ffStrEqualsIgnCase(key, "pipe")) + else if (unsafe_yyjson_equals_str(key, "pipe")) options->pipe = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "showErrors")) + else if (unsafe_yyjson_equals_str(key, "showErrors")) options->showErrors = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "disableLinewrap")) + else if (unsafe_yyjson_equals_str(key, "disableLinewrap")) options->disableLinewrap = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "hideCursor")) + else if (unsafe_yyjson_equals_str(key, "hideCursor")) options->hideCursor = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "separator")) - ffStrbufSetS(&options->keyValueSeparator, yyjson_get_str(val)); - else if (ffStrEqualsIgnCase(key, "color")) + else if (unsafe_yyjson_equals_str(key, "separator")) + ffStrbufSetJsonVal(&options->keyValueSeparator, val); + else if (unsafe_yyjson_equals_str(key, "color")) { if (yyjson_is_str(val)) { - ffOptionParseColor(yyjson_get_str(val), &options->colorKeys); + ffOptionParseColor(unsafe_yyjson_get_str(val), &options->colorKeys); ffStrbufSet(&options->colorTitle, &options->colorKeys); } else if (yyjson_is_obj(val)) { - const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys")); + yyjson_val* colorKeys = yyjson_obj_get(val, "keys"); if (colorKeys) - ffOptionParseColor(colorKeys, &options->colorKeys); - const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title")); + ffOptionParseColor(yyjson_get_str(colorKeys), &options->colorKeys); + yyjson_val* colorTitle = yyjson_obj_get(val, "title"); if (colorTitle) - ffOptionParseColor(colorTitle, &options->colorTitle); - const char* colorOutput = yyjson_get_str(yyjson_obj_get(val, "output")); + ffOptionParseColor(yyjson_get_str(colorTitle), &options->colorTitle); + yyjson_val* colorOutput = yyjson_obj_get(val, "output"); if (colorOutput) - ffOptionParseColor(colorOutput, &options->colorOutput); - const char* colorSeparator = yyjson_get_str(yyjson_obj_get(val, "separator")); + ffOptionParseColor(yyjson_get_str(colorOutput), &options->colorOutput); + yyjson_val* colorSeparator = yyjson_obj_get(val, "separator"); if (colorSeparator) - ffOptionParseColor(colorSeparator, &options->colorSeparator); + ffOptionParseColor(yyjson_get_str(colorSeparator), &options->colorSeparator); } else return "display.color must be either a string or an object"; } - else if (ffStrEqualsIgnCase(key, "brightColor")) + else if (unsafe_yyjson_equals_str(key, "brightColor")) options->brightColor = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "binaryPrefix")) - return "`display.binaryPrefix` has been renamed to `display.size.binaryPrefix`. Sorry for another break change."; - else if (ffStrEqualsIgnCase(key, "duration")) + else if (unsafe_yyjson_equals_str(key, "duration")) { if (!yyjson_is_obj(val)) return "display.duration must be an object"; @@ -100,7 +96,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va options->durationSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; } } - else if (ffStrEqualsIgnCase(key, "size")) + else if (unsafe_yyjson_equals_str(key, "size")) { if (!yyjson_is_obj(val)) return "display.size must be an object"; @@ -156,7 +152,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va options->sizeSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; } } - else if (ffStrEqualsIgnCase(key, "temp")) + else if (unsafe_yyjson_equals_str(key, "temp")) { if (!yyjson_is_obj(val)) return "display.temp must be an object"; @@ -213,7 +209,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va options->tempSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; } } - else if (ffStrEqualsIgnCase(key, "percent")) + else if (unsafe_yyjson_equals_str(key, "percent")) { if (!yyjson_is_obj(val)) return "display.percent must be an object"; @@ -261,25 +257,108 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_val* width = yyjson_obj_get(val, "width"); if (width) options->percentWidth = (uint8_t) yyjson_get_uint(width); } - else if (ffStrEqualsIgnCase(key, "bar")) + else if (unsafe_yyjson_equals_str(key, "bar")) { if (yyjson_is_obj(val)) { - const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed")); - if (charElapsed) - ffStrbufSetS(&options->barCharElapsed, charElapsed); + yyjson_val* char_ = yyjson_obj_get(val, "char"); + if (char_) + { + if (!yyjson_is_obj(char_)) return "display.bar.char must be an object"; + + yyjson_val* charElapsed = yyjson_obj_get(char_, "elapsed"); + if (charElapsed) + ffStrbufSetJsonVal(&options->barCharElapsed, charElapsed); + + yyjson_val* charTotal = yyjson_obj_get(char_, "total"); + if (charTotal) + ffStrbufSetJsonVal(&options->barCharTotal, charTotal); + } + else + { + yyjson_val* charElapsed = yyjson_obj_get(val, "charElapsed"); + if (charElapsed) + return "display.bar.charElapsed has been renamed to display.bar.char.elapsed."; + + yyjson_val* charTotal = yyjson_obj_get(val, "charTotal"); + if (charTotal) + return "display.bar.charTotal has been renamed to display.bar.char.total."; + } - const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal")); - if (charTotal) - ffStrbufSetS(&options->barCharTotal, charTotal); + yyjson_val* border = yyjson_obj_get(val, "border"); + if (border) + { + if (yyjson_is_null(border)) + { + ffStrbufClear(&options->barBorderLeft); + ffStrbufClear(&options->barBorderRight); + ffStrbufClear(&options->barBorderLeftElapsed); + ffStrbufClear(&options->barBorderRightElapsed); + } + else + { + if (!yyjson_is_obj(border)) return "display.bar.border must be an object"; + + yyjson_val* borderLeft = yyjson_obj_get(border, "left"); + if (borderLeft) + ffStrbufSetJsonVal(&options->barBorderLeft, borderLeft); + + yyjson_val* borderRight = yyjson_obj_get(border, "right"); + if (borderRight) + ffStrbufSetJsonVal(&options->barBorderRight, borderRight); + + yyjson_val* borderLeftElapsed = yyjson_obj_get(border, "leftElapsed"); + if (borderLeftElapsed) + ffStrbufSetJsonVal(&options->barBorderLeftElapsed, borderLeftElapsed); + + yyjson_val* borderRightElapsed = yyjson_obj_get(border, "rightElapsed"); + if (borderRightElapsed) + ffStrbufSetJsonVal(&options->barBorderRightElapsed, borderRightElapsed); + } + } + else + { + yyjson_val* borderLeft = yyjson_obj_get(val, "borderLeft"); + if (borderLeft) + return "display.bar.borderLeft has been renamed to display.bar.border.left."; - yyjson_val* borderLeft = yyjson_obj_get(val, "borderLeft"); - if (borderLeft) - ffStrbufSetS(&options->barBorderLeft, yyjson_get_str(borderLeft)); + yyjson_val* borderRight = yyjson_obj_get(val, "borderRight"); + if (borderRight) + return "display.bar.borderRight has been renamed to display.bar.border.right."; + } - yyjson_val* borderRight = yyjson_obj_get(val, "borderRight"); - if (borderRight) - ffStrbufSetS(&options->barBorderRight, yyjson_get_str(borderRight)); + yyjson_val* color = yyjson_obj_get(val, "color"); + if (color) + { + if (yyjson_is_null(color)) + { + ffStrbufClear(&options->barColorElapsed); + ffStrbufClear(&options->barColorTotal); + ffStrbufClear(&options->barColorBorder); + } + else + { + if (!yyjson_is_obj(color)) return "display.bar.color must be an object"; + + yyjson_val* colorElapsed = yyjson_obj_get(color, "elapsed"); + if (colorElapsed) + { + const char* value = yyjson_get_str(colorElapsed); + if (!value) + ffStrbufClear(&options->barColorElapsed); + else if (ffStrEqualsIgnCase(value, "auto")) + ffStrbufSetStatic(&options->barColorElapsed, "auto"); + else + ffOptionParseColor(value, &options->barColorElapsed); + } + + yyjson_val* colorTotal = yyjson_obj_get(color, "total"); + if (colorTotal) ffOptionParseColor(yyjson_get_str(colorTotal), &options->barColorTotal); + + yyjson_val* colorBorder = yyjson_obj_get(color, "border"); + if (colorBorder) ffOptionParseColor(yyjson_get_str(colorBorder), &options->barColorBorder); + } + } yyjson_val* width = yyjson_obj_get(val, "width"); if (width) @@ -288,7 +367,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va else return "display.bar must be an object"; } - else if (ffStrEqualsIgnCase(key, "fraction")) + else if (unsafe_yyjson_equals_str(key, "fraction")) { if (yyjson_is_obj(val)) { @@ -305,11 +384,9 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va else return "display.fraction must be an object"; } - else if (ffStrEqualsIgnCase(key, "noBuffer")) + else if (unsafe_yyjson_equals_str(key, "noBuffer")) options->noBuffer = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "keyWidth")) - return "display.keyWidth has been renamed to display.key.width"; - else if (ffStrEqualsIgnCase(key, "key")) + else if (unsafe_yyjson_equals_str(key, "key")) { if (yyjson_is_obj(val)) { @@ -339,16 +416,16 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va else return "display.key must be an object"; } - else if (ffStrEqualsIgnCase(key, "constants")) + else if (unsafe_yyjson_equals_str(key, "constants")) { if (!yyjson_is_arr(val)) return "display.constants must be an array"; yyjson_val* item; size_t idx, max; yyjson_arr_foreach(val, idx, max, item) - ffStrbufInitS(ffListAdd(&options->constants), yyjson_get_str(item)); + ffStrbufInitJsonVal(ffListAdd(&options->constants), item); } - else if (ffStrEqualsIgnCase(key, "freq")) + else if (unsafe_yyjson_equals_str(key, "freq")) { if (!yyjson_is_obj(val)) return "display.freq must be an object"; @@ -623,6 +700,23 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key ffOptionParseString(key, value, &options->barBorderLeft); else if(ffStrEqualsIgnCase(subkey, "border-right")) ffOptionParseString(key, value, &options->barBorderRight); + else if(ffStrEqualsIgnCase(subkey, "border-left-elapsed")) + ffOptionParseString(key, value, &options->barBorderLeftElapsed); + else if(ffStrEqualsIgnCase(subkey, "border-right-elapsed")) + ffOptionParseString(key, value, &options->barBorderRightElapsed); + else if(ffStrEqualsIgnCase(subkey, "color-elapsed")) + { + if (!value) + ffStrbufClear(&options->barColorElapsed); + else if (ffStrEqualsIgnCase(value, "auto")) + ffStrbufSetStatic(&options->barColorElapsed, "auto"); + else + ffOptionParseColor(value, &options->barColorElapsed); + } + else if(ffStrEqualsIgnCase(subkey, "color-total")) + ffOptionParseColor(value, &options->barColorTotal); + else if(ffStrEqualsIgnCase(subkey, "color-border")) + ffOptionParseColor(value, &options->barColorBorder); else return false; } @@ -671,7 +765,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) options->hideCursor = false; options->sizeBinaryPrefix = FF_SIZE_BINARY_PREFIX_TYPE_IEC; options->sizeNdigits = 2; - options->sizeMaxPrefix = UINT8_MAX; + options->sizeMaxPrefix = 8; // YB options->sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; options->stat = -1; @@ -691,7 +785,13 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->barCharTotal, "-"); ffStrbufInitStatic(&options->barBorderLeft, "[ "); ffStrbufInitStatic(&options->barBorderRight, " ]"); + ffStrbufInit(&options->barBorderLeftElapsed); + ffStrbufInit(&options->barBorderRightElapsed); + ffStrbufInitStatic(&options->barColorElapsed, "auto"); + ffStrbufInitStatic(&options->barColorTotal, instance.state.terminalLightTheme ? FF_COLOR_FG_WHITE : FF_COLOR_FG_LIGHT_WHITE); + ffStrbufInitStatic(&options->barColorBorder, instance.state.terminalLightTheme ? FF_COLOR_FG_WHITE : FF_COLOR_FG_LIGHT_WHITE); options->barWidth = 10; + options->durationAbbreviation = false; options->durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; options->percentType = 9; @@ -725,188 +825,239 @@ void ffOptionsDestroyDisplay(FFOptionsDisplay* options) void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_doc* doc) { - __attribute__((__cleanup__(ffOptionsDestroyDisplay))) FFOptionsDisplay defaultOptions; - ffOptionsInitDisplay(&defaultOptions); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, doc->root, "display"); - yyjson_mut_val* obj = yyjson_mut_obj(doc); + if (options->stat <= 0) + yyjson_mut_obj_add_bool(doc, obj, "stat", options->stat == 0); + else + yyjson_mut_obj_add_int(doc, obj, "stat", options->stat); - if (options->stat != defaultOptions.stat) - { - if (options->stat <= 0) - yyjson_mut_obj_add_bool(doc, obj, "stat", options->stat == 0); - else - yyjson_mut_obj_add_int(doc, obj, "stat", options->stat); - } + yyjson_mut_obj_add_bool(doc, obj, "pipe", options->pipe); - if (options->pipe != defaultOptions.pipe) - yyjson_mut_obj_add_bool(doc, obj, "pipe", options->pipe); + yyjson_mut_obj_add_bool(doc, obj, "showErrors", options->showErrors); - if (options->showErrors != defaultOptions.showErrors) - yyjson_mut_obj_add_bool(doc, obj, "showErrors", options->showErrors); + yyjson_mut_obj_add_bool(doc, obj, "disableLinewrap", options->disableLinewrap); - if (options->disableLinewrap != defaultOptions.disableLinewrap) - yyjson_mut_obj_add_bool(doc, obj, "disableLinewrap", options->disableLinewrap); + yyjson_mut_obj_add_bool(doc, obj, "hideCursor", options->hideCursor); - if (options->hideCursor != defaultOptions.hideCursor) - yyjson_mut_obj_add_bool(doc, obj, "hideCursor", options->hideCursor); + yyjson_mut_obj_add_strbuf(doc, obj, "separator", &options->keyValueSeparator); - if (!ffStrbufEqual(&options->keyValueSeparator, &defaultOptions.keyValueSeparator)) - yyjson_mut_obj_add_strbuf(doc, obj, "separator", &options->keyValueSeparator); + { + yyjson_mut_val* color = yyjson_mut_obj_add_obj(doc, obj, "color"); + yyjson_mut_obj_add_strbuf(doc, color, "keys", &options->colorKeys); + yyjson_mut_obj_add_strbuf(doc, color, "title", &options->colorTitle); + yyjson_mut_obj_add_strbuf(doc, color, "output", &options->colorOutput); + yyjson_mut_obj_add_strbuf(doc, color, "separator", &options->colorSeparator); + } + + yyjson_mut_obj_add_bool(doc, obj, "brightColor", options->brightColor); { - yyjson_mut_val* color = yyjson_mut_obj(doc); - if (!ffStrbufEqual(&options->colorKeys, &defaultOptions.colorKeys)) - yyjson_mut_obj_add_strbuf(doc, color, "keys", &options->colorKeys); - if (!ffStrbufEqual(&options->colorTitle, &defaultOptions.colorTitle)) - yyjson_mut_obj_add_strbuf(doc, color, "title", &options->colorTitle); - if (!ffStrbufEqual(&options->colorOutput, &defaultOptions.colorOutput)) - yyjson_mut_obj_add_strbuf(doc, color, "output", &options->colorOutput); - if (!ffStrbufEqual(&options->colorSeparator, &defaultOptions.colorSeparator)) - yyjson_mut_obj_add_strbuf(doc, color, "separator", &options->colorSeparator); - if (yyjson_mut_obj_size(color) > 0) - { - if (yyjson_mut_obj_size(color) == 2 && ffStrbufEqual(&options->colorKeys, &options->colorTitle)) - yyjson_mut_obj_add_strbuf(doc, obj, "color", &options->colorKeys); - else - yyjson_mut_obj_add_val(doc, obj, "color", color); + yyjson_mut_val* duration = yyjson_mut_obj_add_obj(doc, obj, "duration"); + yyjson_mut_obj_add_bool(doc, duration, "abbreviation", options->durationAbbreviation); + switch (options->durationSpaceBeforeUnit) + { + case FF_SPACE_BEFORE_UNIT_DEFAULT: + yyjson_mut_obj_add_str(doc, duration, "spaceBeforeUnit", "default"); + break; + case FF_SPACE_BEFORE_UNIT_ALWAYS: + yyjson_mut_obj_add_str(doc, duration, "spaceBeforeUnit", "always"); + break; + case FF_SPACE_BEFORE_UNIT_NEVER: + yyjson_mut_obj_add_str(doc, duration, "spaceBeforeUnit", "never"); + break; } } - if (options->brightColor != defaultOptions.brightColor) - yyjson_mut_obj_add_bool(doc, obj, "brightColor", options->brightColor); - { - yyjson_mut_val* size = yyjson_mut_obj(doc); - if (options->sizeNdigits != defaultOptions.sizeNdigits) - yyjson_mut_obj_add_uint(doc, size, "ndigits", options->sizeNdigits); - if (options->sizeMaxPrefix != defaultOptions.sizeMaxPrefix && options->sizeMaxPrefix <= 8) - { - yyjson_mut_obj_add_str(doc, size, "maxPrefix", ((const char* []) { - "B", - "kB", - "MB", - "GB", - "TB", - "PB", - "EB", - "ZB", - "YB", - })[options->sizeMaxPrefix]); - } - if (options->sizeBinaryPrefix != defaultOptions.sizeBinaryPrefix) - { - switch (options->sizeBinaryPrefix) - { - case FF_SIZE_BINARY_PREFIX_TYPE_IEC: - yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "iec"); - break; - case FF_SIZE_BINARY_PREFIX_TYPE_SI: - yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "si"); - break; - case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC: - yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "jedec"); - break; - } + yyjson_mut_val* size = yyjson_mut_obj_add_obj(doc, obj, "size"); + yyjson_mut_obj_add_str(doc, size, "maxPrefix", ((const char* []) { + "B", + "kB", + "MB", + "GB", + "TB", + "PB", + "EB", + "ZB", + "YB", + })[options->sizeMaxPrefix]); + switch (options->sizeBinaryPrefix) + { + case FF_SIZE_BINARY_PREFIX_TYPE_IEC: + yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "iec"); + break; + case FF_SIZE_BINARY_PREFIX_TYPE_SI: + yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "si"); + break; + case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC: + yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "jedec"); + break; + } + yyjson_mut_obj_add_uint(doc, size, "ndigits", options->sizeNdigits); + switch (options->sizeSpaceBeforeUnit) + { + case FF_SPACE_BEFORE_UNIT_DEFAULT: + yyjson_mut_obj_add_str(doc, size, "spaceBeforeUnit", "default"); + break; + case FF_SPACE_BEFORE_UNIT_ALWAYS: + yyjson_mut_obj_add_str(doc, size, "spaceBeforeUnit", "always"); + break; + case FF_SPACE_BEFORE_UNIT_NEVER: + yyjson_mut_obj_add_str(doc, size, "spaceBeforeUnit", "never"); + break; } - if (yyjson_mut_obj_size(size) > 0) - yyjson_mut_obj_add_val(doc, obj, "size", size); } { - yyjson_mut_val* temperature = yyjson_mut_obj(doc); - if (options->tempUnit != defaultOptions.tempUnit) + yyjson_mut_val* temperature = yyjson_mut_obj_add_obj(doc, obj, "temp"); + switch (options->tempUnit) { - switch (options->tempUnit) - { - case FF_TEMPERATURE_UNIT_DEFAULT: - yyjson_mut_obj_add_str(doc, temperature, "unit", "DEFAULT"); - break; - case FF_TEMPERATURE_UNIT_CELSIUS: - yyjson_mut_obj_add_str(doc, obj, "unit", "C"); - break; - case FF_TEMPERATURE_UNIT_FAHRENHEIT: - yyjson_mut_obj_add_str(doc, obj, "unit", "F"); - break; - case FF_TEMPERATURE_UNIT_KELVIN: - yyjson_mut_obj_add_str(doc, obj, "unit", "K"); - break; - } + case FF_TEMPERATURE_UNIT_DEFAULT: + yyjson_mut_obj_add_str(doc, temperature, "unit", "D"); + break; + case FF_TEMPERATURE_UNIT_CELSIUS: + yyjson_mut_obj_add_str(doc, obj, "unit", "C"); + break; + case FF_TEMPERATURE_UNIT_FAHRENHEIT: + yyjson_mut_obj_add_str(doc, obj, "unit", "F"); + break; + case FF_TEMPERATURE_UNIT_KELVIN: + yyjson_mut_obj_add_str(doc, obj, "unit", "K"); + break; + } + yyjson_mut_obj_add_uint(doc, temperature, "ndigits", options->tempNdigits); + { + yyjson_mut_val* color = yyjson_mut_obj_add_obj(doc, temperature, "color"); + yyjson_mut_obj_add_strbuf(doc, color, "green", &options->tempColorGreen); + yyjson_mut_obj_add_strbuf(doc, color, "yellow", &options->tempColorYellow); + yyjson_mut_obj_add_strbuf(doc, color, "red", &options->tempColorRed); + } + switch (options->tempSpaceBeforeUnit) + { + case FF_SPACE_BEFORE_UNIT_DEFAULT: + yyjson_mut_obj_add_str(doc, temperature, "spaceBeforeUnit", "default"); + break; + case FF_SPACE_BEFORE_UNIT_ALWAYS: + yyjson_mut_obj_add_str(doc, temperature, "spaceBeforeUnit", "always"); + break; + case FF_SPACE_BEFORE_UNIT_NEVER: + yyjson_mut_obj_add_str(doc, temperature, "spaceBeforeUnit", "never"); + break; } - if (options->tempNdigits != defaultOptions.tempNdigits) - yyjson_mut_obj_add_uint(doc, temperature, "ndigits", options->tempNdigits); - { - yyjson_mut_val* color = yyjson_mut_obj(doc); - if (!ffStrbufEqual(&options->tempColorGreen, &defaultOptions.tempColorGreen)) - yyjson_mut_obj_add_strbuf(doc, color, "green", &options->tempColorGreen); - if (!ffStrbufEqual(&options->tempColorYellow, &defaultOptions.tempColorYellow)) - yyjson_mut_obj_add_strbuf(doc, color, "yellow", &options->tempColorYellow); - if (!ffStrbufEqual(&options->tempColorRed, &defaultOptions.tempColorRed)) - yyjson_mut_obj_add_strbuf(doc, color, "red", &options->tempColorRed); - if (yyjson_mut_obj_size(color) > 0) - yyjson_mut_obj_add_val(doc, temperature, "color", color); - } - if (yyjson_mut_obj_size(temperature) > 0) - yyjson_mut_obj_add_val(doc, obj, "temp", temperature); } { - yyjson_mut_val* percent = yyjson_mut_obj(doc); - if (options->percentType != defaultOptions.percentType) - yyjson_mut_obj_add_uint(doc, percent, "type", options->percentType); - if (options->percentNdigits != defaultOptions.percentNdigits) - yyjson_mut_obj_add_uint(doc, percent, "ndigits", options->percentNdigits); - { - yyjson_mut_val* color = yyjson_mut_obj(doc); - if (!ffStrbufEqual(&options->percentColorGreen, &defaultOptions.percentColorGreen)) - yyjson_mut_obj_add_strbuf(doc, color, "green", &options->percentColorGreen); - if (!ffStrbufEqual(&options->percentColorYellow, &defaultOptions.percentColorYellow)) - yyjson_mut_obj_add_strbuf(doc, color, "yellow", &options->percentColorYellow); - if (!ffStrbufEqual(&options->percentColorRed, &defaultOptions.percentColorRed)) - yyjson_mut_obj_add_strbuf(doc, color, "red", &options->percentColorRed); - if (yyjson_mut_obj_size(color) > 0) - yyjson_mut_obj_add_val(doc, percent, "color", color); - } - if (yyjson_mut_obj_size(percent) > 0) - yyjson_mut_obj_add_val(doc, obj, "percent", percent); + yyjson_mut_val* percent = yyjson_mut_obj_add_obj(doc, obj, "percent"); + { + yyjson_mut_val* type = yyjson_mut_obj_add_arr(doc, percent, "type"); + if (options->percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + yyjson_mut_arr_add_str(doc, type, "num"); + if (options->percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + yyjson_mut_arr_add_str(doc, type, "var"); + if (options->percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) + yyjson_mut_arr_add_str(doc, type, "hide-others"); + if (options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT) + yyjson_mut_arr_add_str(doc, type, "num-color"); + if (options->percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT) + yyjson_mut_arr_add_str(doc, type, "bar-monochrome"); + } + yyjson_mut_obj_add_uint(doc, percent, "ndigits", options->percentNdigits); + { + yyjson_mut_val* color = yyjson_mut_obj_add_obj(doc, percent, "color"); + yyjson_mut_obj_add_strbuf(doc, color, "green", &options->percentColorGreen); + yyjson_mut_obj_add_strbuf(doc, color, "yellow", &options->percentColorYellow); + yyjson_mut_obj_add_strbuf(doc, color, "red", &options->percentColorRed); + } + switch (options->percentSpaceBeforeUnit) + { + case FF_SPACE_BEFORE_UNIT_DEFAULT: + yyjson_mut_obj_add_str(doc, percent, "spaceBeforeUnit", "default"); + break; + case FF_SPACE_BEFORE_UNIT_ALWAYS: + yyjson_mut_obj_add_str(doc, percent, "spaceBeforeUnit", "always"); + break; + case FF_SPACE_BEFORE_UNIT_NEVER: + yyjson_mut_obj_add_str(doc, percent, "spaceBeforeUnit", "never"); + break; + } + yyjson_mut_obj_add_uint(doc, percent, "width", options->percentWidth); } { - yyjson_mut_val* bar = yyjson_mut_obj(doc); - if (!ffStrbufEqual(&options->barCharElapsed, &defaultOptions.barCharElapsed)) - yyjson_mut_obj_add_strbuf(doc, bar, "charElapsed", &options->barCharElapsed); - if (!ffStrbufEqual(&options->barCharTotal, &defaultOptions.barCharTotal)) - yyjson_mut_obj_add_strbuf(doc, bar, "charTotal", &options->barCharTotal); - if (!ffStrbufEqual(&options->barBorderLeft, &defaultOptions.barBorderLeft)) - yyjson_mut_obj_add_strbuf(doc, bar, "borderLeft", &options->barBorderLeft); - if (!ffStrbufEqual(&options->barBorderRight, &defaultOptions.barBorderRight)) - yyjson_mut_obj_add_strbuf(doc, bar, "borderRight", &options->barBorderRight); - if (options->barWidth != defaultOptions.barWidth) - yyjson_mut_obj_add_uint(doc, bar, "width", options->barWidth); - - if (yyjson_mut_obj_size(bar) > 0) - yyjson_mut_obj_add_val(doc, obj, "bar", bar); + yyjson_mut_val* bar = yyjson_mut_obj_add_obj(doc, obj, "bar"); + + yyjson_mut_val* char_ = yyjson_mut_obj_add_obj(doc, bar, "char"); + yyjson_mut_obj_add_strbuf(doc, char_, "elapsed", &options->barCharElapsed); + yyjson_mut_obj_add_strbuf(doc, char_, "total", &options->barCharTotal); + + yyjson_mut_val* border = yyjson_mut_obj_add_obj(doc, bar, "border"); + yyjson_mut_obj_add_strbuf(doc, border, "left", &options->barBorderLeft); + yyjson_mut_obj_add_strbuf(doc, border, "right", &options->barBorderRight); + yyjson_mut_obj_add_strbuf(doc, border, "leftElapsed", &options->barBorderLeftElapsed); + yyjson_mut_obj_add_strbuf(doc, border, "rightElapsed", &options->barBorderRightElapsed); + + yyjson_mut_val* color = yyjson_mut_obj_add_obj(doc, bar, "color"); + yyjson_mut_obj_add_strbuf(doc, color, "elapsed", &options->barColorElapsed); + yyjson_mut_obj_add_strbuf(doc, color, "total", &options->barColorTotal); + yyjson_mut_obj_add_strbuf(doc, color, "border", &options->barColorBorder); + + yyjson_mut_obj_add_uint(doc, bar, "width", options->barWidth); } - if (options->noBuffer != defaultOptions.noBuffer) - yyjson_mut_obj_add_bool(doc, obj, "noBuffer", options->noBuffer); + { + yyjson_mut_val* fraction = yyjson_mut_obj_add_obj(doc, obj, "fraction"); - if (options->keyWidth != defaultOptions.keyWidth) - yyjson_mut_obj_add_uint(doc, obj, "keyWidth", options->keyWidth); + if (options->fractionNdigits < 0) + yyjson_mut_obj_add_null(doc, fraction, "ndigits"); + else + yyjson_mut_obj_add_uint(doc, fraction, "ndigits", (uint8_t) options->fractionNdigits); + } - if (options->keyType != defaultOptions.keyType) - yyjson_mut_obj_add_uint(doc, obj, "keyType", options->keyType); + yyjson_mut_obj_add_bool(doc, obj, "noBuffer", options->noBuffer); - if (options->keyPaddingLeft != defaultOptions.keyPaddingLeft) - yyjson_mut_obj_add_uint(doc, obj, "keyPaddingLeft", options->keyPaddingLeft); + { + yyjson_mut_val* key = yyjson_mut_obj_add_obj(doc, obj, "key"); + yyjson_mut_obj_add_uint(doc, key, "width", options->keyWidth); + switch ((uint8_t) options->keyType) + { + case FF_MODULE_KEY_TYPE_NONE: + yyjson_mut_obj_add_str(doc, key, "type", "none"); + break; + case FF_MODULE_KEY_TYPE_STRING: + yyjson_mut_obj_add_str(doc, key, "type", "string"); + break; + case FF_MODULE_KEY_TYPE_ICON: + yyjson_mut_obj_add_str(doc, key, "type", "icon"); + break; + case FF_MODULE_KEY_TYPE_BOTH: + yyjson_mut_obj_add_str(doc, key, "type", "both"); + break; + } + + yyjson_mut_obj_add_uint(doc, key, "paddingLeft", options->keyPaddingLeft); + } { - yyjson_mut_val* freq = yyjson_mut_obj(doc); - if (options->freqNdigits != defaultOptions.freqNdigits) - yyjson_mut_obj_add_int(doc, freq, "ndigits", options->freqNdigits); - if (yyjson_mut_obj_size(freq) > 0) - yyjson_mut_obj_add_val(doc, obj, "freq", freq); + yyjson_mut_val* freq = yyjson_mut_obj_add_obj(doc, obj, "freq"); + yyjson_mut_obj_add_int(doc, freq, "ndigits", options->freqNdigits); + switch (options->percentSpaceBeforeUnit) + { + case FF_SPACE_BEFORE_UNIT_DEFAULT: + yyjson_mut_obj_add_str(doc, freq, "spaceBeforeUnit", "default"); + break; + case FF_SPACE_BEFORE_UNIT_ALWAYS: + yyjson_mut_obj_add_str(doc, freq, "spaceBeforeUnit", "always"); + break; + case FF_SPACE_BEFORE_UNIT_NEVER: + yyjson_mut_obj_add_str(doc, freq, "spaceBeforeUnit", "never"); + break; + } } - if (yyjson_mut_obj_size(obj) > 0) - yyjson_mut_obj_add_val(doc, doc->root, "display", obj); + { + yyjson_mut_val* constants = yyjson_mut_obj_add_arr(doc, obj, "constants"); + FF_LIST_FOR_EACH(FFstrbuf, item, options->constants) + yyjson_mut_arr_add_strbuf(doc, constants, item); + } } diff --git a/src/options/display.h b/src/options/display.h index 6a50b848cf..4193cd2c6e 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -1,5 +1,6 @@ #pragma once +#include "common/percent.h" #include "util/FFstrbuf.h" typedef enum __attribute__((__packed__)) FFSizeBinaryPrefixType @@ -60,6 +61,11 @@ typedef struct FFOptionsDisplay FFstrbuf barCharTotal; FFstrbuf barBorderLeft; FFstrbuf barBorderRight; + FFstrbuf barBorderLeftElapsed; + FFstrbuf barBorderRightElapsed; + FFstrbuf barColorElapsed; // "auto" for auto selection from percent config; empty for no custom color (inherits) + FFstrbuf barColorTotal; // empty for no custom color (inherits) + FFstrbuf barColorBorder; // empty for no custom color (inherits) uint8_t barWidth; FFPercentageTypeFlags percentType; uint8_t percentNdigits; diff --git a/src/options/general.c b/src/options/general.c index eb09b127ee..72f79798bb 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -12,28 +12,28 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va if (!object) return NULL; if (!yyjson_is_obj(object)) return "Property 'general' must be an object"; - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(object, idx, max, key_, val) + yyjson_obj_foreach(object, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - - if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading")) + if (unsafe_yyjson_equals_str(key, "thread")) options->multithreading = yyjson_get_bool(val); - else if (ffStrEqualsIgnCase(key, "processingTimeout")) + else if (unsafe_yyjson_equals_str(key, "processingTimeout")) options->processingTimeout = (int32_t) yyjson_get_int(val); - else if (ffStrEqualsIgnCase(key, "preRun")) + else if (unsafe_yyjson_equals_str(key, "preRun")) { - if (system(yyjson_get_str(val)) < 0) + if (!yyjson_is_str(val)) + return "general.preRun must be a string"; + if (system(unsafe_yyjson_get_str(val)) < 0) return "Failed to execute preRun command"; } - else if (ffStrEqualsIgnCase(key, "detectVersion")) + else if (unsafe_yyjson_equals_str(key, "detectVersion")) options->detectVersion = yyjson_get_bool(val); #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) - else if (ffStrEqualsIgnCase(key, "playerName")) - ffStrbufSetS(&options->playerName, yyjson_get_str(val)); - else if (ffStrEqualsIgnCase(key, "dsForceDrm")) + else if (unsafe_yyjson_equals_str(key, "playerName")) + ffStrbufSetJsonVal(&options->playerName, val); + else if (unsafe_yyjson_equals_str(key, "dsForceDrm")) { if (yyjson_is_str(val)) { @@ -53,7 +53,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va options->dsForceDrm = yyjson_get_bool(val) ? FF_DS_FORCE_DRM_TYPE_TRUE : FF_DS_FORCE_DRM_TYPE_FALSE; } #elif defined(_WIN32) - else if (ffStrEqualsIgnCase(key, "wmiTimeout")) + else if (unsafe_yyjson_equals_str(key, "wmiTimeout")) options->wmiTimeout = (int32_t) yyjson_get_int(val); #endif @@ -119,45 +119,34 @@ void ffOptionsDestroyGeneral(FF_MAYBE_UNUSED FFOptionsGeneral* options) void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_doc* doc) { - __attribute__((__cleanup__(ffOptionsDestroyGeneral))) FFOptionsGeneral defaultOptions; - ffOptionsInitGeneral(&defaultOptions); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, doc->root, "general"); - yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_bool(doc, obj, "thread", options->multithreading); - if (options->multithreading != defaultOptions.multithreading) - yyjson_mut_obj_add_bool(doc, obj, "thread", options->multithreading); + yyjson_mut_obj_add_int(doc, obj, "processingTimeout", options->processingTimeout); - if (options->processingTimeout != defaultOptions.processingTimeout) - yyjson_mut_obj_add_int(doc, obj, "processingTimeout", options->processingTimeout); + yyjson_mut_obj_add_bool(doc, obj, "detectVersion", options->detectVersion); #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) - if (!ffStrbufEqual(&options->playerName, &defaultOptions.playerName)) - yyjson_mut_obj_add_strbuf(doc, obj, "playerName", &options->playerName); + yyjson_mut_obj_add_strbuf(doc, obj, "playerName", &options->playerName); - if (options->dsForceDrm != defaultOptions.dsForceDrm) + switch (options->dsForceDrm) { - switch (options->dsForceDrm) - { - case FF_DS_FORCE_DRM_TYPE_FALSE: - yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", false); - break; - case FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY: - yyjson_mut_obj_add_str(doc, obj, "dsForceDrm", "sysfs-only"); - break; - case FF_DS_FORCE_DRM_TYPE_TRUE: - yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", true); - break; - } + case FF_DS_FORCE_DRM_TYPE_FALSE: + yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", false); + break; + case FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY: + yyjson_mut_obj_add_str(doc, obj, "dsForceDrm", "sysfs-only"); + break; + case FF_DS_FORCE_DRM_TYPE_TRUE: + yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", true); + break; } #elif defined(_WIN32) - if (options->wmiTimeout != defaultOptions.wmiTimeout) - yyjson_mut_obj_add_int(doc, obj, "wmiTimeout", options->wmiTimeout); + yyjson_mut_obj_add_int(doc, obj, "wmiTimeout", options->wmiTimeout); #endif - - if (yyjson_mut_obj_size(obj) > 0) - yyjson_mut_obj_add_val(doc, doc->root, "general", obj); } diff --git a/src/options/logo.c b/src/options/logo.c index 5b3aed829b..2e93dd5187 100644 --- a/src/options/logo.c +++ b/src/options/logo.c @@ -263,20 +263,17 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo if (yyjson_is_str(object)) { - const char* value = yyjson_get_str(object); - ffStrbufSetS(&options->source, value); + ffStrbufSetJsonVal(&options->source, object); return NULL; } if (!yyjson_is_obj(object)) return "Property 'logo' must be an object"; - yyjson_val *key_, *val; + yyjson_val *key, *val; size_t idx, max; - yyjson_obj_foreach(object, idx, max, key_, val) + yyjson_obj_foreach(object, idx, max, key, val) { - const char* key = yyjson_get_str(key_); - - if (ffStrEqualsIgnCase(key, "type")) + if (unsafe_yyjson_equals_str(key, "type")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -303,22 +300,21 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo options->type = (FFLogoType) value; continue; } - else if (ffStrEqualsIgnCase(key, "source")) + else if (unsafe_yyjson_equals_str(key, "source")) { - ffStrbufSetS(&options->source, yyjson_get_str(val)); + ffStrbufSetJsonVal(&options->source, val); continue; } - else if (ffStrEqualsIgnCase(key, "color")) + else if (unsafe_yyjson_equals_str(key, "color")) { if (!yyjson_is_obj(val)) return "Property 'color' must be an object"; - yyjson_val *key_c, *valc; + yyjson_val *keyc, *valc; size_t idxc, maxc; - yyjson_obj_foreach(val, idxc, maxc, key_c, valc) + yyjson_obj_foreach(val, idxc, maxc, keyc, valc) { - const char* keyc = yyjson_get_str(key_c); - uint32_t index = (uint32_t) strtoul(keyc, NULL, 10); + uint32_t index = (uint32_t) strtoul(unsafe_yyjson_get_str(keyc), NULL, 10); if (index < 1 || index > FASTFETCH_LOGO_MAX_COLORS) return "Keys of property 'color' must be a number between 1 to 9"; @@ -326,23 +322,33 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo } continue; } - else if (ffStrEqualsIgnCase(key, "width")) + else if (unsafe_yyjson_equals_str(key, "width")) { - uint32_t value = (uint32_t) yyjson_get_uint(val); - if (value == 0) - return "Logo width must be a positive integer"; - options->width = value; + if (yyjson_is_null(val)) + options->width = 0; + else + { + uint32_t value = (uint32_t) yyjson_get_uint(val); + if (value == 0) + return "Logo width must be a positive integer"; + options->width = value; + } continue; } - else if (ffStrEqualsIgnCase(key, "height")) + else if (unsafe_yyjson_equals_str(key, "height")) { - uint32_t value = (uint32_t) yyjson_get_uint(val); - if (value == 0) - return "Logo height must be a positive integer"; - options->height = value; + if (yyjson_is_null(val)) + options->height = 0; + else + { + uint32_t value = (uint32_t) yyjson_get_uint(val); + if (value == 0) + return "Logo height must be a positive integer"; + options->height = value; + } continue; } - else if (ffStrEqualsIgnCase(key, "padding")) + else if (unsafe_yyjson_equals_str(key, "padding")) { if (!yyjson_is_obj(val)) return "Logo padding must be an object"; @@ -361,24 +367,22 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo #undef FF_PARSE_PADDING_POSITON continue; } - else if (ffStrEqualsIgnCase(key, "printRemaining")) + else if (unsafe_yyjson_equals_str(key, "printRemaining")) { options->printRemaining = yyjson_get_bool(val); continue; } - else if (ffStrEqualsIgnCase(key, "preserveAspectRatio")) + else if (unsafe_yyjson_equals_str(key, "preserveAspectRatio")) { options->preserveAspectRatio = yyjson_get_bool(val); continue; } - else if (ffStrEqualsIgnCase(key, "recache")) + else if (unsafe_yyjson_equals_str(key, "recache")) { options->recache = yyjson_get_bool(val); continue; } - else if(ffStrEqualsIgnCase(key, "separate")) - return "logo.separate has been renamed to logo.position\n"; - else if (ffStrEqualsIgnCase(key, "position")) + else if (unsafe_yyjson_equals_str(key, "position")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { @@ -392,7 +396,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo options->position = (FFLogoPosition) value; continue; } - else if (ffStrEqualsIgnCase(key, "chafa")) + else if (unsafe_yyjson_equals_str(key, "chafa")) { if (!yyjson_is_obj(val)) return "Chafa config must be an object"; @@ -403,7 +407,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo yyjson_val* symbols = yyjson_obj_get(val, "symbols"); if (symbols) - ffStrbufSetS(&options->chafaSymbols, yyjson_get_str(symbols)); + ffStrbufSetJsonVal(&options->chafaSymbols, symbols); yyjson_val* canvasMode = yyjson_obj_get(val, "canvasMode"); if (canvasMode) @@ -464,121 +468,106 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc) { - __attribute__((__cleanup__(ffOptionsDestroyLogo))) FFOptionsLogo defaultOptions; - ffOptionsInitLogo(&defaultOptions); - yyjson_mut_val* obj = yyjson_mut_obj(doc); - if (options->type != defaultOptions.type) + switch (options->type) { - switch (options->type) - { - case FF_LOGO_TYPE_NONE: - yyjson_mut_obj_add_null(doc, doc->root, "logo"); - return; - case FF_LOGO_TYPE_BUILTIN: - yyjson_mut_obj_add_str(doc, obj, "type", "builtin"); - break; - case FF_LOGO_TYPE_SMALL: - yyjson_mut_obj_add_str(doc, obj, "type", "small"); - break; - case FF_LOGO_TYPE_FILE: - yyjson_mut_obj_add_str(doc, obj, "type", "file"); - break; - case FF_LOGO_TYPE_FILE_RAW: - yyjson_mut_obj_add_str(doc, obj, "type", "file-raw"); - break; - case FF_LOGO_TYPE_DATA: - yyjson_mut_obj_add_str(doc, obj, "type", "data"); - break; - case FF_LOGO_TYPE_DATA_RAW: - yyjson_mut_obj_add_str(doc, obj, "type", "data-raw"); - break; - case FF_LOGO_TYPE_COMMAND_RAW: - yyjson_mut_obj_add_str(doc, obj, "type", "command-raw"); - break; - case FF_LOGO_TYPE_IMAGE_SIXEL: - yyjson_mut_obj_add_str(doc, obj, "type", "sixel"); - break; - case FF_LOGO_TYPE_IMAGE_KITTY: - yyjson_mut_obj_add_str(doc, obj, "type", "kitty"); - break; - case FF_LOGO_TYPE_IMAGE_ITERM: - yyjson_mut_obj_add_str(doc, obj, "type", "iterm"); - break; - case FF_LOGO_TYPE_IMAGE_CHAFA: - yyjson_mut_obj_add_str(doc, obj, "type", "chafa"); - break; - case FF_LOGO_TYPE_IMAGE_RAW: - yyjson_mut_obj_add_str(doc, obj, "type", "raw"); - break; - default: - yyjson_mut_obj_add_str(doc, obj, "type", "auto"); - break; - } + case FF_LOGO_TYPE_NONE: + yyjson_mut_obj_add_null(doc, doc->root, "logo"); + return; + case FF_LOGO_TYPE_BUILTIN: + yyjson_mut_obj_add_str(doc, obj, "type", "builtin"); + break; + case FF_LOGO_TYPE_SMALL: + yyjson_mut_obj_add_str(doc, obj, "type", "small"); + break; + case FF_LOGO_TYPE_FILE: + yyjson_mut_obj_add_str(doc, obj, "type", "file"); + break; + case FF_LOGO_TYPE_FILE_RAW: + yyjson_mut_obj_add_str(doc, obj, "type", "file-raw"); + break; + case FF_LOGO_TYPE_DATA: + yyjson_mut_obj_add_str(doc, obj, "type", "data"); + break; + case FF_LOGO_TYPE_DATA_RAW: + yyjson_mut_obj_add_str(doc, obj, "type", "data-raw"); + break; + case FF_LOGO_TYPE_COMMAND_RAW: + yyjson_mut_obj_add_str(doc, obj, "type", "command-raw"); + break; + case FF_LOGO_TYPE_IMAGE_SIXEL: + yyjson_mut_obj_add_str(doc, obj, "type", "sixel"); + break; + case FF_LOGO_TYPE_IMAGE_KITTY: + yyjson_mut_obj_add_str(doc, obj, "type", "kitty"); + break; + case FF_LOGO_TYPE_IMAGE_KITTY_DIRECT: + yyjson_mut_obj_add_str(doc, obj, "type", "kitty-direct"); + break; + case FF_LOGO_TYPE_IMAGE_KITTY_ICAT: + yyjson_mut_obj_add_str(doc, obj, "type", "kitty-icat"); + break; + case FF_LOGO_TYPE_IMAGE_ITERM: + yyjson_mut_obj_add_str(doc, obj, "type", "iterm"); + break; + case FF_LOGO_TYPE_IMAGE_CHAFA: + yyjson_mut_obj_add_str(doc, obj, "type", "chafa"); + break; + case FF_LOGO_TYPE_IMAGE_RAW: + yyjson_mut_obj_add_str(doc, obj, "type", "raw"); + break; + default: + yyjson_mut_obj_add_str(doc, obj, "type", "auto"); + break; } - if (!ffStrbufEqual(&options->source, &defaultOptions.source)) - yyjson_mut_obj_add_str(doc, obj, "source", options->source.chars); + yyjson_mut_obj_add_str(doc, obj, "source", options->source.chars); { yyjson_mut_val* color = yyjson_mut_obj(doc); for (int i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++) { - if (!ffStrbufEqual(&options->colors[i], &defaultOptions.colors[i])) - { - char c = (char)('1' + i); - yyjson_mut_obj_add(color, yyjson_mut_strncpy(doc, &c, 1), yyjson_mut_strbuf(doc, &options->colors[i])); - } + char c = (char)('1' + i); + yyjson_mut_obj_add(color, yyjson_mut_strncpy(doc, &c, 1), yyjson_mut_strbuf(doc, &options->colors[i])); } - if (yyjson_mut_obj_size(color) > 0) - yyjson_mut_obj_add_val(doc, obj, "color", color); + yyjson_mut_obj_add_val(doc, obj, "color", color); } - if (options->width != defaultOptions.width) + if (options->width == 0) + yyjson_mut_obj_add_null(doc, obj, "width"); + else yyjson_mut_obj_add_uint(doc, obj, "width", options->width); - if (options->height != defaultOptions.height) + if (options->height == 0) + yyjson_mut_obj_add_null(doc, obj, "height"); + else yyjson_mut_obj_add_uint(doc, obj, "height", options->height); { - yyjson_mut_val* padding = yyjson_mut_obj(doc); - if (options->paddingTop != defaultOptions.paddingTop) - yyjson_mut_obj_add_uint(doc, padding, "top", options->paddingTop); - if (options->paddingLeft != defaultOptions.paddingLeft) - yyjson_mut_obj_add_uint(doc, padding, "left", options->paddingLeft); - if (options->paddingRight != defaultOptions.paddingRight) - yyjson_mut_obj_add_uint(doc, padding, "right", options->paddingRight); - - if (yyjson_mut_obj_size(padding) > 0) - yyjson_mut_obj_add_val(doc, obj, "padding", padding); + yyjson_mut_val* padding = yyjson_mut_obj_add_obj(doc, obj, "padding"); + yyjson_mut_obj_add_uint(doc, padding, "top", options->paddingTop); + yyjson_mut_obj_add_uint(doc, padding, "left", options->paddingLeft); + yyjson_mut_obj_add_uint(doc, padding, "right", options->paddingRight); } - if (options->printRemaining != defaultOptions.printRemaining) - yyjson_mut_obj_add_bool(doc, obj, "printRemaining", options->printRemaining); + yyjson_mut_obj_add_bool(doc, obj, "printRemaining", options->printRemaining); - if (options->preserveAspectRatio != defaultOptions.preserveAspectRatio) - yyjson_mut_obj_add_bool(doc, obj, "preserveAspectRatio", options->preserveAspectRatio); + yyjson_mut_obj_add_bool(doc, obj, "preserveAspectRatio", options->preserveAspectRatio); - if (options->recache != defaultOptions.recache) - yyjson_mut_obj_add_bool(doc, obj, "recache", options->recache); + yyjson_mut_obj_add_bool(doc, obj, "recache", options->recache); - if (options->position != defaultOptions.position) - { - yyjson_mut_obj_add_str(doc, obj, "position", ((const char* []) { - "left", - "top", - "right", - })[options->position]); - } + yyjson_mut_obj_add_str(doc, obj, "position", ((const char* []) { + "left", + "top", + "right", + })[options->position]); { yyjson_mut_val* chafa = yyjson_mut_obj(doc); - if (options->chafaFgOnly != defaultOptions.chafaFgOnly) - yyjson_mut_obj_add_bool(doc, chafa, "fgOnly", options->chafaFgOnly); - if (!ffStrbufEqual(&options->chafaSymbols, &defaultOptions.chafaSymbols)) - yyjson_mut_obj_add_strbuf(doc, chafa, "symbols", &options->chafaSymbols); - if (options->chafaCanvasMode != defaultOptions.chafaCanvasMode && options->chafaCanvasMode <= 7) + yyjson_mut_obj_add_bool(doc, chafa, "fgOnly", options->chafaFgOnly); + yyjson_mut_obj_add_strbuf(doc, chafa, "symbols", &options->chafaSymbols); + if (options->chafaCanvasMode <= 7) { yyjson_mut_obj_add_str(doc, chafa, "canvasMode", ((const char* []) { "TRUECOLOR", @@ -591,14 +580,14 @@ void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc "INDEXED_16_8", })[options->chafaCanvasMode]); } - if (options->chafaColorSpace != defaultOptions.chafaColorSpace && options->chafaColorSpace <= 1) + if (options->chafaColorSpace <= 1) { yyjson_mut_obj_add_str(doc, chafa, "colorSpace", ((const char* []) { "RGB", "DIN99D", })[options->chafaColorSpace]); } - if (options->chafaDitherMode != defaultOptions.chafaDitherMode && options->chafaDitherMode <= 2) + if (options->chafaDitherMode <= 2) { yyjson_mut_obj_add_str(doc, chafa, "ditherMode", ((const char* []) { "NONE", @@ -607,10 +596,8 @@ void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc })[options->chafaDitherMode]); } - if (yyjson_mut_obj_size(chafa) > 0) - yyjson_mut_obj_add_val(doc, obj, "chafa", chafa); + yyjson_mut_obj_add_val(doc, obj, "chafa", chafa); } - if (yyjson_mut_obj_size(obj) > 0) - yyjson_mut_obj_add_val(doc, doc->root, "logo", obj); + yyjson_mut_obj_add_val(doc, doc->root, "logo", obj); } diff --git a/src/options/modules.c b/src/options/modules.c deleted file mode 100644 index 755f65a87a..0000000000 --- a/src/options/modules.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "fastfetch.h" -#include "modules/modules.h" - -void ffOptionsInitModules(FFOptionsModules* options) -{ - ffInitBatteryOptions(&options->battery); - ffInitBiosOptions(&options->bios); - ffInitBluetoothOptions(&options->bluetooth); - ffInitBluetoothRadioOptions(&options->bluetoothRadio); - ffInitBoardOptions(&options->board); - ffInitBootmgrOptions(&options->bootmgr); - ffInitBreakOptions(&options->break_); - ffInitBrightnessOptions(&options->brightness); - ffInitBtrfsOptions(&options->btrfs); - ffInitCameraOptions(&options->camera); - ffInitCPUOptions(&options->cpu); - ffInitCPUUsageOptions(&options->cpuUsage); - ffInitCPUCacheOptions(&options->cpuCache); - ffInitChassisOptions(&options->chassis); - ffInitColorsOptions(&options->colors); - ffInitCommandOptions(&options->command); - ffInitCursorOptions(&options->cursor); - ffInitCustomOptions(&options->custom); - ffInitDEOptions(&options->de); - ffInitDateTimeOptions(&options->dateTime); - ffInitDiskOptions(&options->disk); - ffInitDiskIOOptions(&options->diskIo); - ffInitDisplayOptions(&options->display); - ffInitDNSOptions(&options->dns); - ffInitEditorOptions(&options->editor); - ffInitFontOptions(&options->font); - ffInitGPUOptions(&options->gpu); - ffInitGamepadOptions(&options->gamepad); - ffInitHostOptions(&options->host); - ffInitIconsOptions(&options->icons); - ffInitInitSystemOptions(&options->initSystem); - ffInitKernelOptions(&options->kernel); - ffInitKeyboardOptions(&options->keyboard); - ffInitLMOptions(&options->lm); - ffInitLoadavgOptions(&options->loadavg); - ffInitLocalIpOptions(&options->localIP); - ffInitLocaleOptions(&options->locale); - ffInitMediaOptions(&options->media); - ffInitMemoryOptions(&options->memory); - ffInitMonitorOptions(&options->monitor); - ffInitMouseOptions(&options->mouse); - ffInitNetIOOptions(&options->netIo); - ffInitOSOptions(&options->os); - ffInitOpenCLOptions(&options->openCL); - ffInitOpenGLOptions(&options->openGL); - ffInitPackagesOptions(&options->packages); - ffInitPhysicalDiskOptions(&options->physicalDisk); - ffInitPhysicalMemoryOptions(&options->physicalMemory); - ffInitPlayerOptions(&options->player); - ffInitPowerAdapterOptions(&options->powerAdapter); - ffInitProcessesOptions(&options->processes); - ffInitPublicIpOptions(&options->publicIP); - ffInitSeparatorOptions(&options->separator); - ffInitShellOptions(&options->shell); - ffInitSoundOptions(&options->sound); - ffInitSwapOptions(&options->swap); - ffInitTerminalOptions(&options->terminal); - ffInitTerminalFontOptions(&options->terminalFont); - ffInitTerminalSizeOptions(&options->terminalSize); - ffInitTerminalThemeOptions(&options->terminalTheme); - ffInitThemeOptions(&options->theme); - ffInitTitleOptions(&options->title); - ffInitTPMOptions(&options->tpm); - ffInitUptimeOptions(&options->uptime); - ffInitUsersOptions(&options->users); - ffInitVersionOptions(&options->version); - ffInitVulkanOptions(&options->vulkan); - ffInitWMOptions(&options->wm); - ffInitWMThemeOptions(&options->wmTheme); - ffInitWallpaperOptions(&options->wallpaper); - ffInitWeatherOptions(&options->weather); - ffInitWifiOptions(&options->wifi); - ffInitZpoolOptions(&options->zpool); -} - -void ffOptionsDestroyModules(FFOptionsModules* options) -{ - ffDestroyBatteryOptions(&options->battery); - ffDestroyBiosOptions(&options->bios); - ffDestroyBluetoothOptions(&options->bluetooth); - ffDestroyBluetoothRadioOptions(&options->bluetoothRadio); - ffDestroyBoardOptions(&options->board); - ffDestroyBootmgrOptions(&options->bootmgr); - ffDestroyBreakOptions(&options->break_); - ffDestroyBrightnessOptions(&options->brightness); - ffDestroyBtrfsOptions(&options->btrfs); - ffDestroyCameraOptions(&options->camera); - ffDestroyCPUOptions(&options->cpu); - ffDestroyCPUCacheOptions(&options->cpuCache); - ffDestroyCPUUsageOptions(&options->cpuUsage); - ffDestroyChassisOptions(&options->chassis); - ffDestroyColorsOptions(&options->colors); - ffDestroyCommandOptions(&options->command); - ffDestroyCursorOptions(&options->cursor); - ffDestroyCustomOptions(&options->custom); - ffDestroyDEOptions(&options->de); - ffDestroyDateTimeOptions(&options->dateTime); - ffDestroyDiskOptions(&options->disk); - ffDestroyDiskIOOptions(&options->diskIo); - ffDestroyDisplayOptions(&options->display); - ffDestroyDNSOptions(&options->dns); - ffDestroyEditorOptions(&options->editor); - ffDestroyFontOptions(&options->font); - ffDestroyGPUOptions(&options->gpu); - ffDestroyGamepadOptions(&options->gamepad); - ffDestroyHostOptions(&options->host); - ffDestroyIconsOptions(&options->icons); - ffDestroyInitSystemOptions(&options->initSystem); - ffDestroyKernelOptions(&options->kernel); - ffDestroyKeyboardOptions(&options->keyboard); - ffDestroyLMOptions(&options->lm); - ffDestroyLoadavgOptions(&options->loadavg); - ffDestroyLocalIpOptions(&options->localIP); - ffDestroyLocaleOptions(&options->locale); - ffDestroyMediaOptions(&options->media); - ffDestroyMemoryOptions(&options->memory); - ffDestroyMonitorOptions(&options->monitor); - ffDestroyMouseOptions(&options->mouse); - ffDestroyNetIOOptions(&options->netIo); - ffDestroyOSOptions(&options->os); - ffDestroyOpenCLOptions(&options->openCL); - ffDestroyOpenGLOptions(&options->openGL); - ffDestroyPhysicalDiskOptions(&options->physicalDisk); - ffDestroyPhysicalMemoryOptions(&options->physicalMemory); - ffDestroyPackagesOptions(&options->packages); - ffDestroyPlayerOptions(&options->player); - ffDestroyPowerAdapterOptions(&options->powerAdapter); - ffDestroyProcessesOptions(&options->processes); - ffDestroyPublicIpOptions(&options->publicIP); - ffDestroySeparatorOptions(&options->separator); - ffDestroyShellOptions(&options->shell); - ffDestroySoundOptions(&options->sound); - ffDestroySwapOptions(&options->swap); - ffDestroyTerminalOptions(&options->terminal); - ffDestroyTerminalFontOptions(&options->terminalFont); - ffDestroyTerminalSizeOptions(&options->terminalSize); - ffDestroyTerminalThemeOptions(&options->terminalTheme); - ffDestroyThemeOptions(&options->theme); - ffDestroyTitleOptions(&options->title); - ffDestroyTPMOptions(&options->tpm); - ffDestroyUptimeOptions(&options->uptime); - ffDestroyUsersOptions(&options->users); - ffDestroyVersionOptions(&options->version); - ffDestroyVulkanOptions(&options->vulkan); - ffDestroyWMOptions(&options->wm); - ffDestroyWMThemeOptions(&options->wmTheme); - ffDestroyWallpaperOptions(&options->wallpaper); - ffDestroyWeatherOptions(&options->weather); - ffDestroyWifiOptions(&options->wifi); - ffDestroyZpoolOptions(&options->zpool); -} diff --git a/src/options/modules.h b/src/options/modules.h deleted file mode 100644 index 4ff82f972f..0000000000 --- a/src/options/modules.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include "modules/options.h" - -typedef struct FFOptionsModules -{ - FFBatteryOptions battery; - FFBiosOptions bios; - FFBluetoothOptions bluetooth; - FFBluetoothRadioOptions bluetoothRadio; - FFBoardOptions board; - FFBootmgrOptions bootmgr; - FFBreakOptions break_; - FFBrightnessOptions brightness; - FFBtrfsOptions btrfs; - FFCPUOptions cpu; - FFCPUCacheOptions cpuCache; - FFCPUUsageOptions cpuUsage; - FFCameraOptions camera; - FFChassisOptions chassis; - FFColorsOptions colors; - FFCommandOptions command; - FFCursorOptions cursor; - FFCustomOptions custom; - FFDEOptions de; - FFDateTimeOptions dateTime; - FFDiskOptions disk; - FFDiskIOOptions diskIo; - FFDisplayOptions display; - FFDNSOptions dns; - FFEditorOptions editor; - FFFontOptions font; - FFGPUOptions gpu; - FFGamepadOptions gamepad; - FFHostOptions host; - FFIconsOptions icons; - FFInitSystemOptions initSystem; - FFKernelOptions kernel; - FFKeyboardOptions keyboard; - FFLMOptions lm; - FFLoadavgOptions loadavg; - FFLocalIpOptions localIP; - FFLocaleOptions locale; - FFMediaOptions media; - FFMemoryOptions memory; - FFMonitorOptions monitor; - FFMouseOptions mouse; - FFNetIOOptions netIo; - FFOSOptions os; - FFOpenCLOptions openCL; - FFOpenGLOptions openGL; - FFPackagesOptions packages; - FFPhysicalDiskOptions physicalDisk; - FFPhysicalMemoryOptions physicalMemory; - FFPlayerOptions player; - FFPowerAdapterOptions powerAdapter; - FFProcessesOptions processes; - FFPublicIpOptions publicIP; - FFSeparatorOptions separator; - FFShellOptions shell; - FFSoundOptions sound; - FFSwapOptions swap; - FFTerminalOptions terminal; - FFTerminalFontOptions terminalFont; - FFTerminalSizeOptions terminalSize; - FFTerminalThemeOptions terminalTheme; - FFThemeOptions theme; - FFTitleOptions title; - FFTPMOptions tpm; - FFUptimeOptions uptime; - FFUsersOptions users; - FFVersionOptions version; - FFVulkanOptions vulkan; - FFWMOptions wm; - FFWMThemeOptions wmTheme; - FFWallpaperOptions wallpaper; - FFWeatherOptions weather; - FFWifiOptions wifi; - FFZpoolOptions zpool; -} FFOptionsModules; - -void ffOptionsInitModules(FFOptionsModules* options); -void ffOptionsDestroyModules(FFOptionsModules* options); diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 6fe0b151c8..6e0db579b4 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -219,12 +219,6 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c) strbuf->length += 1; } -void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value) -{ - ffStrbufClear(strbuf); - ffStrbufAppendNS(strbuf, length, value); -} - void ffStrbufTrimLeft(FFstrbuf* strbuf, char c) { if(strbuf->length == 0) @@ -527,11 +521,11 @@ void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) fputc('\n', file); } -double ffStrbufToDouble(const FFstrbuf* strbuf) +double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) { char* str_end; double result = strtod(strbuf->chars, &str_end); - return str_end == strbuf->chars ? 0.0/0.0 : result; + return str_end == strbuf->chars ? defaultValue : result; } uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 7e96927225..44498d3e91 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -9,6 +9,7 @@ #include #include #include +#include "3rdparty/yyjson/yyjson.h" #ifdef _WIN32 // #include @@ -48,7 +49,6 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c); void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c); -void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value); FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufTrimLeft(FFstrbuf* strbuf, char c); @@ -84,7 +84,7 @@ bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c); void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file); void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file); -FF_C_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf); +FF_C_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue); FF_C_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue); FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue); @@ -211,6 +211,16 @@ static inline void ffStrbufAppendS(FFstrbuf* strbuf, const char* value) ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value); } +static inline bool ffStrbufAppendJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) +{ + if (yyjson_is_str(jsonVal)) + { + ffStrbufAppendNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal)); + return true; + } + return false; +} + static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value) { ffStrbufClear(strbuf); @@ -219,6 +229,12 @@ static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value) ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value); } +static inline void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value) +{ + ffStrbufClear(strbuf); + ffStrbufAppendNS(strbuf, length, value); +} + static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value) { assert(value && value != strbuf); @@ -230,6 +246,12 @@ static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value) ffStrbufSetNS(strbuf, value->length, value->chars); } +static inline bool ffStrbufSetJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) +{ + ffStrbufClear(strbuf); + return ffStrbufAppendJsonVal(strbuf, jsonVal); +} + static inline void ffStrbufInit(FFstrbuf* strbuf) { extern char* CHAR_NULL_PTR; @@ -284,6 +306,12 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateNS(uint32_t length, const ch return strbuf; } +static inline bool ffStrbufInitJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) +{ + ffStrbufInit(strbuf); + return ffStrbufAppendJsonVal(strbuf, jsonVal); +} + static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str) { ffStrbufInit(strbuf); diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 9f9a4384f9..68d560013f 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -230,7 +230,7 @@ bool FFWmiRecord::getReal(const wchar_t* key, double* real) case VT_R4: *real = vtProp.fltVal; break; case VT_R8: *real = vtProp.dblVal; break; case VT_BOOL: *real = vtProp.boolVal != VARIANT_FALSE; break; - default: *real = NAN; result = false; + default: *real = -DBL_MAX; result = false; } } return result; diff --git a/tests/strbuf.c b/tests/strbuf.c index 94addc4668..456b9c3300 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -136,7 +136,7 @@ int main(void) //toNumber - VERIFY(ffStrbufToDouble(&strbuf) == 123456789.0); + VERIFY(ffStrbufToDouble(&strbuf, -DBL_MAX) == 123456789.0); VERIFY(ffStrbufToUInt(&strbuf, 999) == 123456789); //countC