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
-* 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