Compare commits
No commits in common. "main" and "windows" have entirely different histories.
|
@ -5,18 +5,14 @@ AlignConsecutiveDeclarations: true
|
|||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
BasedOnStyle: Chromium
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
ColumnLimit: 100
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
Cpp11BracedListStyle: false
|
||||
FixNamespaceComments: false
|
||||
IndentAccessModifiers: false
|
||||
IndentExternBlock: Indent
|
||||
IndentWidth: 2
|
||||
LineEnding: LF
|
||||
NamespaceIndentation: All
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpacesBeforeTrailingComments: 1
|
||||
|
|
46
.clang-tidy
46
.clang-tidy
|
@ -1,29 +1,25 @@
|
|||
# noinspection SpellCheckingInspection
|
||||
Checks: >
|
||||
*,
|
||||
-ctad-maybe-unsupported,
|
||||
-abseil-*,
|
||||
-altera-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-cert-env33-c,
|
||||
-concurrency-mt-unsafe,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-pro-type-member-init,
|
||||
-cppcoreguidelines-pro-type-vararg,
|
||||
-fuchsia-*,
|
||||
-google-*,
|
||||
-hicpp-*,
|
||||
-llvm-include-order,
|
||||
-llvm-include-order,
|
||||
-llvm-namespace-comment,
|
||||
-llvmlibc-*,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
-readability-braces-around-statements,
|
||||
-readability-implicit-bool-conversion,
|
||||
-readability-isolate-declaration,
|
||||
-readability-magic-numbers
|
||||
*,
|
||||
-abseil-*,
|
||||
-altera-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-concurrency-mt-unsafe,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-pro-type-member-init,
|
||||
-fuchsia-*,
|
||||
-google-*,
|
||||
-hicpp-*,
|
||||
-llvm-include-order,
|
||||
-llvm-include-order,
|
||||
-llvmlibc-*,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
-modernize-use-trailing-return-type,
|
||||
-readability-braces-around-statements,
|
||||
-readability-implicit-bool-conversion,
|
||||
-readability-isolate-declaration,
|
||||
-readability-magic-numbers
|
||||
CheckOptions:
|
||||
readability-identifier-naming.ClassCase: CamelCase
|
||||
readability-identifier-naming.EnumCase: CamelCase
|
||||
|
|
4
.clangd
4
.clangd
|
@ -1,4 +0,0 @@
|
|||
Diagnostics:
|
||||
Suppress: >
|
||||
-Wmissing-template-arg-list-after-template-kw,
|
||||
-Wctad-maybe-unsupported
|
25
.gitignore
vendored
25
.gitignore
vendored
|
@ -1,25 +1,2 @@
|
|||
.cache/
|
||||
.cmake/
|
||||
.direnv/
|
||||
.idea/
|
||||
.vs/
|
||||
.vscode/
|
||||
.xmake/
|
||||
|
||||
bin/
|
||||
build/
|
||||
cmake-build-debug/
|
||||
CMakeFiles/
|
||||
out/
|
||||
Testing/
|
||||
|
||||
build.ninja
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
CMakeSettings.json
|
||||
compile_commands.json
|
||||
config.toml
|
||||
draconis++
|
||||
Makefile
|
||||
result
|
||||
/include/
|
||||
cmake-build-*/
|
15
CMakeLists.txt
Normal file
15
CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
cmake_minimum_required(VERSION 3.28)
|
||||
|
||||
project(draconis__)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
set(CMAKE_MAKE_PROGRAM "Ninja")
|
||||
|
||||
add_executable(draconis__ main.cpp
|
||||
util.h)
|
||||
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
find_package(cppwinrt CONFIG REQUIRED)
|
||||
|
||||
target_link_libraries(draconis__ PRIVATE fmt::fmt-header-only)
|
||||
target_link_libraries(draconis__ PRIVATE WindowsApp)
|
|
@ -1,122 +0,0 @@
|
|||
{
|
||||
"curl": {
|
||||
"cargoLocks": null,
|
||||
"date": null,
|
||||
"extract": null,
|
||||
"name": "curl",
|
||||
"passthru": null,
|
||||
"pinned": false,
|
||||
"src": {
|
||||
"deepClone": false,
|
||||
"fetchSubmodules": false,
|
||||
"leaveDotGit": false,
|
||||
"name": null,
|
||||
"owner": "curl",
|
||||
"repo": "curl",
|
||||
"rev": "curl-8_9_1",
|
||||
"sha256": "sha256-b+Giv6n3LCjOIvUeQawR9qrMBTuz8emRRdhbb2XO5ZU=",
|
||||
"type": "github"
|
||||
},
|
||||
"version": "curl-8_9_1"
|
||||
},
|
||||
"fmt": {
|
||||
"cargoLocks": null,
|
||||
"date": null,
|
||||
"extract": null,
|
||||
"name": "fmt",
|
||||
"passthru": null,
|
||||
"pinned": false,
|
||||
"src": {
|
||||
"deepClone": false,
|
||||
"fetchSubmodules": false,
|
||||
"leaveDotGit": false,
|
||||
"name": null,
|
||||
"owner": "fmtlib",
|
||||
"repo": "fmt",
|
||||
"rev": "11.0.2",
|
||||
"sha256": "sha256-IKNt4xUoVi750zBti5iJJcCk3zivTt7nU12RIf8pM+0=",
|
||||
"type": "github"
|
||||
},
|
||||
"version": "11.0.2"
|
||||
},
|
||||
"reflect-cpp": {
|
||||
"cargoLocks": null,
|
||||
"date": null,
|
||||
"extract": null,
|
||||
"name": "reflect-cpp",
|
||||
"passthru": null,
|
||||
"pinned": false,
|
||||
"src": {
|
||||
"deepClone": false,
|
||||
"fetchSubmodules": false,
|
||||
"leaveDotGit": false,
|
||||
"name": null,
|
||||
"owner": "getml",
|
||||
"repo": "reflect-cpp",
|
||||
"rev": "v0.13.0",
|
||||
"sha256": "sha256-dEqdPk5ixnNILxTcdSAOhzP8fzeefMu6pqrL/WgnPlE=",
|
||||
"type": "github"
|
||||
},
|
||||
"version": "v0.13.0"
|
||||
},
|
||||
"sdbus-cpp": {
|
||||
"cargoLocks": null,
|
||||
"date": null,
|
||||
"extract": null,
|
||||
"name": "sdbus-cpp",
|
||||
"passthru": null,
|
||||
"pinned": false,
|
||||
"src": {
|
||||
"deepClone": false,
|
||||
"fetchSubmodules": false,
|
||||
"leaveDotGit": false,
|
||||
"name": null,
|
||||
"owner": "kistler-group",
|
||||
"repo": "sdbus-cpp",
|
||||
"rev": "v2.0.0",
|
||||
"sha256": "sha256-W8V5FRhV3jtERMFrZ4gf30OpIQLYoj2yYGpnYOmH2+g=",
|
||||
"type": "github"
|
||||
},
|
||||
"version": "v2.0.0"
|
||||
},
|
||||
"tomlplusplus": {
|
||||
"cargoLocks": null,
|
||||
"date": null,
|
||||
"extract": null,
|
||||
"name": "tomlplusplus",
|
||||
"passthru": null,
|
||||
"pinned": false,
|
||||
"src": {
|
||||
"deepClone": false,
|
||||
"fetchSubmodules": false,
|
||||
"leaveDotGit": false,
|
||||
"name": null,
|
||||
"owner": "marzer",
|
||||
"repo": "tomlplusplus",
|
||||
"rev": "v3.4.0",
|
||||
"sha256": "sha256-h5tbO0Rv2tZezY58yUbyRVpsfRjY3i+5TPkkxr6La8M=",
|
||||
"type": "github"
|
||||
},
|
||||
"version": "v3.4.0"
|
||||
},
|
||||
"yyjson": {
|
||||
"cargoLocks": null,
|
||||
"date": null,
|
||||
"extract": null,
|
||||
"name": "yyjson",
|
||||
"passthru": null,
|
||||
"pinned": false,
|
||||
"src": {
|
||||
"deepClone": false,
|
||||
"fetchSubmodules": false,
|
||||
"leaveDotGit": false,
|
||||
"name": null,
|
||||
"owner": "ibireme",
|
||||
"repo": "yyjson",
|
||||
"rev": "0.10.0",
|
||||
"sha256": "sha256-mp9Oz08qTyhj3P6F1d81SX96vamUY/JWpD2DTYR+v04=",
|
||||
"type": "github"
|
||||
},
|
||||
"version": "0.10.0"
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
# This file was generated by nvfetcher, please do not modify it manually.
|
||||
{ fetchgit, fetchurl, fetchFromGitHub, dockerTools }:
|
||||
{
|
||||
curl = {
|
||||
pname = "curl";
|
||||
version = "curl-8_9_1";
|
||||
src = fetchFromGitHub {
|
||||
owner = "curl";
|
||||
repo = "curl";
|
||||
rev = "curl-8_9_1";
|
||||
fetchSubmodules = false;
|
||||
sha256 = "sha256-b+Giv6n3LCjOIvUeQawR9qrMBTuz8emRRdhbb2XO5ZU=";
|
||||
};
|
||||
};
|
||||
fmt = {
|
||||
pname = "fmt";
|
||||
version = "11.0.2";
|
||||
src = fetchFromGitHub {
|
||||
owner = "fmtlib";
|
||||
repo = "fmt";
|
||||
rev = "11.0.2";
|
||||
fetchSubmodules = false;
|
||||
sha256 = "sha256-IKNt4xUoVi750zBti5iJJcCk3zivTt7nU12RIf8pM+0=";
|
||||
};
|
||||
};
|
||||
reflect-cpp = {
|
||||
pname = "reflect-cpp";
|
||||
version = "v0.13.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "getml";
|
||||
repo = "reflect-cpp";
|
||||
rev = "v0.13.0";
|
||||
fetchSubmodules = false;
|
||||
sha256 = "sha256-dEqdPk5ixnNILxTcdSAOhzP8fzeefMu6pqrL/WgnPlE=";
|
||||
};
|
||||
};
|
||||
sdbus-cpp = {
|
||||
pname = "sdbus-cpp";
|
||||
version = "v2.0.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "kistler-group";
|
||||
repo = "sdbus-cpp";
|
||||
rev = "v2.0.0";
|
||||
fetchSubmodules = false;
|
||||
sha256 = "sha256-W8V5FRhV3jtERMFrZ4gf30OpIQLYoj2yYGpnYOmH2+g=";
|
||||
};
|
||||
};
|
||||
tomlplusplus = {
|
||||
pname = "tomlplusplus";
|
||||
version = "v3.4.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "marzer";
|
||||
repo = "tomlplusplus";
|
||||
rev = "v3.4.0";
|
||||
fetchSubmodules = false;
|
||||
sha256 = "sha256-h5tbO0Rv2tZezY58yUbyRVpsfRjY3i+5TPkkxr6La8M=";
|
||||
};
|
||||
};
|
||||
yyjson = {
|
||||
pname = "yyjson";
|
||||
version = "0.10.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "ibireme";
|
||||
repo = "yyjson";
|
||||
rev = "0.10.0";
|
||||
fetchSubmodules = false;
|
||||
sha256 = "sha256-mp9Oz08qTyhj3P6F1d81SX96vamUY/JWpD2DTYR+v04=";
|
||||
};
|
||||
};
|
||||
}
|
546
flake.lock
546
flake.lock
|
@ -1,546 +0,0 @@
|
|||
{
|
||||
"nodes": {
|
||||
"codeium": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727497393,
|
||||
"narHash": "sha256-AHL2qezvAAZtOP61cHtnB0RtqPej4LqtGkvXNOAESNw=",
|
||||
"owner": "jcdickinson",
|
||||
"repo": "codeium.nvim",
|
||||
"rev": "17bbefff02be8fd66931f366bd4ed76a76e4a57e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "jcdickinson",
|
||||
"repo": "codeium.nvim",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devshell": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1722113426,
|
||||
"narHash": "sha256-Yo/3loq572A8Su6aY5GP56knpuKYRvM2a1meP9oJZCw=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "67cce7359e4cd3c45296fb4aaf6a19e2a9c757ae",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"revCount": 57,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726153070,
|
||||
"narHash": "sha256-HO4zgY0ekfwO5bX0QH/3kJ/h4KvUDFZg8YpkNwIbg1U=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "bcef6817a8b2aa20a5a6dbb19b43e63c5bf8619a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701680307,
|
||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_3": {
|
||||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"flake-compat"
|
||||
],
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727514110,
|
||||
"narHash": "sha256-0YRcOxJG12VGDFH8iS8pJ0aYQQUAgo/r3ZAL+cSh9nk=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "85f7a7177c678de68224af3402ab8ee1bcee25c8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727383923,
|
||||
"narHash": "sha256-4/vacp3CwdGoPf8U4e/N8OsGYtO09WTcQK5FqYfJbKs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "ffe2d07e771580a005e675108212597e5b367d2d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727507295,
|
||||
"narHash": "sha256-I/FrX1peu4URoj5T5odfuKR2rm4GjYJJpCGF9c0/lDA=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "f2e1c4aa29fc211947c3a7113cba1dd707433b70",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1729311994,
|
||||
"narHash": "sha256-qbXHPupmSGjSJkPmmaOSRd6b2kRgAk+CH/FMRWiYdUM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7e2eb4642f7ca9c4ee2c069d65a48575068b4f57",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1702346276,
|
||||
"narHash": "sha256-eAQgwIWApFQ40ipeOjVSoK4TEHVd6nbSd9fApiHIw5A=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "cf28ee258fd5f9a52de6b9865cdb93a1f96d09b7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1727742380,
|
||||
"narHash": "sha256-5lFzlmiwrl3OHrw7QhZn/ZpZtygzx1UspKOaZqpxXSQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9dc3c339a2aecbd61ab2549248d8b64ba1c28af5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1727348695,
|
||||
"narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1726871744,
|
||||
"narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1726871744,
|
||||
"narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixvim": {
|
||||
"inputs": {
|
||||
"codeium": "codeium",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixvim": "nixvim_2",
|
||||
"treefmt-nix": "treefmt-nix_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1728515236,
|
||||
"narHash": "sha256-gYObAkD39KbYdeSxOxPFaVVgfbRPPgG470E8sFMaQDM=",
|
||||
"owner": "pupbrained",
|
||||
"repo": "nvim-config",
|
||||
"rev": "584a15c6dcf5bea4a9ab3c804b86324b128d3b67",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "pupbrained",
|
||||
"repo": "nvim-config",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixvim_2": {
|
||||
"inputs": {
|
||||
"devshell": "devshell",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts",
|
||||
"git-hooks": "git-hooks",
|
||||
"home-manager": "home-manager",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"nuschtosSearch": "nuschtosSearch",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727645871,
|
||||
"narHash": "sha256-Os3PAThU5XliKkKa+SHsFyV/EsCHogHcYONmpzb6500=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixvim",
|
||||
"rev": "5f4a4b47597d3b9ac26c41ff4e8da28fa662f200",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixvim",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nuschtosSearch": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_3",
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727452028,
|
||||
"narHash": "sha256-ehl/A4HQFRyqj1Fk7cl+dgSf/2Fb1jLwWJtZaMU6RfU=",
|
||||
"owner": "NuschtOS",
|
||||
"repo": "search",
|
||||
"rev": "9f7426e532ef8dfc839c4a3fcc567b13a20a70d3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NuschtOS",
|
||||
"repo": "search",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixvim": "nixvim",
|
||||
"treefmt-nix": "treefmt-nix_3",
|
||||
"utils": "utils"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_3": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_4": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727431250,
|
||||
"narHash": "sha256-uGRlRT47ecicF9iLD1G3g43jn2e+b5KaMptb59LHnvM=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "879b29ae9a0378904fbbefe0dadaed43c8905754",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727431250,
|
||||
"narHash": "sha256-uGRlRT47ecicF9iLD1G3g43jn2e+b5KaMptb59LHnvM=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "879b29ae9a0378904fbbefe0dadaed43c8905754",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix_3": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729242555,
|
||||
"narHash": "sha256-6jWSWxv2crIXmYSEb3LEVsFkCkyVHNllk61X4uhqfCs=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "d986489c1c757f6921a48c1439f19bfb9b8ecab5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
151
flake.nix
151
flake.nix
|
@ -1,151 +0,0 @@
|
|||
{
|
||||
description = "C/C++ environment";
|
||||
|
||||
inputs = {
|
||||
nixvim.url = "github:pupbrained/nvim-config";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs";
|
||||
treefmt-nix.url = "github:numtide/treefmt-nix";
|
||||
utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
treefmt-nix,
|
||||
utils,
|
||||
nixvim,
|
||||
...
|
||||
}:
|
||||
utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
pkgs = import nixpkgs {inherit system;};
|
||||
|
||||
stdenv =
|
||||
if pkgs.hostPlatform.isLinux
|
||||
then pkgs.stdenvAdapters.useMoldLinker pkgs.llvmPackages_18.stdenv
|
||||
else pkgs.llvmPackages_18.stdenv;
|
||||
|
||||
sources = import ./_sources/generated.nix {
|
||||
inherit (pkgs) fetchFromGitHub fetchgit fetchurl dockerTools;
|
||||
};
|
||||
|
||||
mkPkg = name:
|
||||
pkgs.pkgsStatic.${name}.overrideAttrs {
|
||||
inherit (sources.${name}) pname version src;
|
||||
};
|
||||
|
||||
fmt = mkPkg "fmt";
|
||||
tomlplusplus = mkPkg "tomlplusplus";
|
||||
yyjson = mkPkg "yyjson";
|
||||
|
||||
sdbus-cpp = pkgs.sdbus-cpp.overrideAttrs {
|
||||
inherit (sources.sdbus-cpp) pname version src;
|
||||
};
|
||||
|
||||
reflect-cpp = stdenv.mkDerivation {
|
||||
inherit (sources.reflect-cpp) pname version src;
|
||||
|
||||
nativeBuildInputs = with pkgs; [cmake ninja pkg-config];
|
||||
|
||||
cmakeFlags = [
|
||||
"-DCMAKE_TOOLCHAIN_FILE=OFF"
|
||||
"-DCMAKE_BUILD_TYPE=Release"
|
||||
"-DREFLECTCPP_TOML=ON"
|
||||
];
|
||||
};
|
||||
|
||||
deps = with pkgs.pkgsStatic;
|
||||
[
|
||||
curl
|
||||
fmt
|
||||
libiconv
|
||||
tomlplusplus
|
||||
yyjson
|
||||
reflect-cpp
|
||||
]
|
||||
++ linuxPkgs
|
||||
++ darwinPkgs;
|
||||
|
||||
linuxPkgs = nixpkgs.lib.optionals stdenv.isLinux (with pkgs; [
|
||||
pkgsStatic.glib
|
||||
systemdLibs
|
||||
sdbus-cpp
|
||||
valgrind
|
||||
]);
|
||||
|
||||
darwinPkgs = nixpkgs.lib.optionals stdenv.isDarwin (with pkgs.pkgsStatic.darwin.apple_sdk.frameworks; [
|
||||
Foundation
|
||||
MediaPlayer
|
||||
SystemConfiguration
|
||||
]);
|
||||
in
|
||||
with pkgs; {
|
||||
packages = rec {
|
||||
draconisplusplus = stdenv.mkDerivation {
|
||||
name = "draconis++";
|
||||
version = "0.1.0";
|
||||
src = self;
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
buildInputs = deps;
|
||||
|
||||
configurePhase = ''
|
||||
meson setup build
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
meson compile -C build
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
mv build/draconis++ $out/bin/draconis++
|
||||
'';
|
||||
};
|
||||
|
||||
default = draconisplusplus;
|
||||
};
|
||||
|
||||
formatter = treefmt-nix.lib.mkWrapper pkgs {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
alejandra.enable = true;
|
||||
deadnix.enable = true;
|
||||
|
||||
clang-format = {
|
||||
enable = true;
|
||||
package = pkgs.clang-tools_18;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
devShell = mkShell.override {inherit stdenv;} {
|
||||
packages =
|
||||
[
|
||||
alejandra
|
||||
bear
|
||||
clang-tools_18
|
||||
lldb
|
||||
meson
|
||||
ninja
|
||||
nvfetcher
|
||||
pkg-config
|
||||
unzip
|
||||
nixvim.packages.${system}.default
|
||||
|
||||
(writeScriptBin "build" "meson compile -C build")
|
||||
(writeScriptBin "clean" "meson setup build --wipe")
|
||||
(writeScriptBin "run" "meson compile -C build && build/draconis++")
|
||||
]
|
||||
++ deps;
|
||||
|
||||
name = "C++";
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
199
main.cpp
Normal file
199
main.cpp
Normal file
|
@ -0,0 +1,199 @@
|
|||
#include <fmt/chrono.h>
|
||||
#include <fmt/core.h>
|
||||
#include <iostream>
|
||||
#include <windows.h>
|
||||
#include <winrt/Windows.Foundation.h> // ReSharper disable once CppUnusedIncludeDirective
|
||||
#include <winrt/Windows.Media.Control.h>
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/impl/windows.media.control.2.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::Media::Control;
|
||||
|
||||
struct KBToGiB {
|
||||
u64 value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<KBToGiB> : formatter<double> {
|
||||
template <typename FormatContext>
|
||||
typename FormatContext::iterator
|
||||
format(const KBToGiB KTG, FormatContext& ctx) {
|
||||
typename FormatContext::iterator out = formatter<double>::format(
|
||||
static_cast<double>(KTG.value) / pow(1024, 2), ctx
|
||||
);
|
||||
|
||||
*out++ = 'G';
|
||||
*out++ = 'i';
|
||||
*out++ = 'B';
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
enum DateNum : u8 { Ones, Twos, Threes, Default };
|
||||
|
||||
DateNum ParseDate(std::string const& input) {
|
||||
if (input == "1" || input == "21" || input == "31") return Ones;
|
||||
if (input == "2" || input == "22") return Twos;
|
||||
if (input == "3" || input == "23") return Threes;
|
||||
return Default;
|
||||
}
|
||||
|
||||
std::string GetNowPlaying() {
|
||||
using namespace winrt::Windows::Media::Control;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
using MediaProperties =
|
||||
GlobalSystemMediaTransportControlsSessionMediaProperties;
|
||||
using Session = GlobalSystemMediaTransportControlsSession;
|
||||
using SessionManager = GlobalSystemMediaTransportControlsSessionManager;
|
||||
|
||||
try {
|
||||
// Request the session manager asynchronously
|
||||
const IAsyncOperation<SessionManager> sessionManagerOp =
|
||||
SessionManager::RequestAsync();
|
||||
const SessionManager sessionManager = sessionManagerOp.get();
|
||||
|
||||
if (const Session currentSession = sessionManager.GetCurrentSession()) {
|
||||
// Try to get the media properties asynchronously
|
||||
const IAsyncOperation<MediaProperties> mediaPropertiesOp =
|
||||
currentSession.TryGetMediaPropertiesAsync();
|
||||
const MediaProperties mediaProperties = mediaPropertiesOp.get();
|
||||
|
||||
// Convert the hstring title to std::string
|
||||
return to_string(mediaProperties.Title());
|
||||
}
|
||||
|
||||
// If we reach this point, there is no current session
|
||||
return "No current media session.";
|
||||
} catch (...) { return "Failed to get media properties."; }
|
||||
}
|
||||
|
||||
std::string GetRegistryValue(
|
||||
const HKEY& hKey,
|
||||
const std::string& subKey,
|
||||
const std::string& valueName
|
||||
) {
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExA(hKey, subKey.c_str(), 0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return "";
|
||||
|
||||
DWORD dataSize = 0;
|
||||
if (RegQueryValueExA(
|
||||
key, valueName.c_str(), nullptr, nullptr, nullptr, &dataSize
|
||||
) != ERROR_SUCCESS) {
|
||||
RegCloseKey(key);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string value(dataSize, '\0');
|
||||
if (RegQueryValueExA(
|
||||
key,
|
||||
valueName.c_str(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
reinterpret_cast<LPBYTE>(value.data()), // NOLINT(*-reinterpret-cast)
|
||||
&dataSize
|
||||
) != ERROR_SUCCESS) {
|
||||
RegCloseKey(key);
|
||||
return "";
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
// Remove null terminator if present
|
||||
if (!value.empty() && value.back() == '\0') value.pop_back();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string GetPrettyWindowsName() {
|
||||
std::string productName = GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)",
|
||||
"ProductName"
|
||||
);
|
||||
|
||||
const std::string displayVersion = GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)",
|
||||
"DisplayVersion"
|
||||
);
|
||||
|
||||
const std::string releaseId = GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)",
|
||||
"ReleaseId"
|
||||
);
|
||||
|
||||
const int buildNumber = stoi(GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)",
|
||||
"CurrentBuildNumber"
|
||||
));
|
||||
|
||||
fmt::println("Build number: {}", buildNumber);
|
||||
|
||||
// Check if the build number is 22000 or higher
|
||||
if (buildNumber >= 22000 &&
|
||||
productName.find("Windows 10") != std::string::npos)
|
||||
productName.replace(productName.find("Windows 10"), 10, "Windows 11");
|
||||
|
||||
if (!productName.empty()) {
|
||||
std::string result = productName;
|
||||
|
||||
if (!displayVersion.empty())
|
||||
result += " " + displayVersion;
|
||||
else if (!releaseId.empty())
|
||||
result += " " + releaseId;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int main() {
|
||||
init_apartment();
|
||||
|
||||
u64 memInfo = 0;
|
||||
GetPhysicallyInstalledSystemMemory(&memInfo);
|
||||
fmt::println("Installed RAM: {:.2f}", KBToGiB {memInfo});
|
||||
|
||||
fmt::println("Now playing: {}", GetNowPlaying());
|
||||
|
||||
const std::tm localTime = fmt::localtime(time(nullptr));
|
||||
|
||||
std::string date = fmt::format("{:%e}", localTime);
|
||||
|
||||
auto start = date.begin();
|
||||
while (start != date.end() && std::isspace(*start)) ++start;
|
||||
date.erase(date.begin(), start);
|
||||
|
||||
switch (ParseDate(date)) {
|
||||
case Ones:
|
||||
date += "st";
|
||||
break;
|
||||
|
||||
case Twos:
|
||||
date += "nd";
|
||||
break;
|
||||
|
||||
case Threes:
|
||||
date += "rd";
|
||||
break;
|
||||
|
||||
case Default:
|
||||
date += "th";
|
||||
break;
|
||||
}
|
||||
|
||||
fmt::println("{:%B} {}, {:%-I:%0M %p}", localTime, date, localTime);
|
||||
|
||||
fmt::println("Version: {}", GetPrettyWindowsName());
|
||||
|
||||
uninit_apartment();
|
||||
return 0;
|
||||
}
|
117
meson.build
117
meson.build
|
@ -1,117 +0,0 @@
|
|||
project(
|
||||
'draconis++', 'cpp',
|
||||
version: '0.1.0',
|
||||
default_options: [
|
||||
'cpp_std=c++20',
|
||||
'default_library=static',
|
||||
'warning_level=everything',
|
||||
'buildtype=release'
|
||||
]
|
||||
)
|
||||
|
||||
cpp = meson.get_compiler('cpp')
|
||||
|
||||
if host_machine.system() == 'darwin'
|
||||
add_languages('objcpp')
|
||||
objcpp = meson.get_compiler('objcpp')
|
||||
add_project_arguments(
|
||||
objcpp.get_supported_arguments([
|
||||
'-Wno-c++20-compat',
|
||||
'-Wno-c++20-extensions',
|
||||
'-Wno-c++98-compat',
|
||||
'-Wno-c++98-compat-pedantic',
|
||||
'-Wno-disabled-macro-expansion',
|
||||
'-Wno-missing-prototypes',
|
||||
'-Wno-padded',
|
||||
'-Wno-pre-c++20-compat-pedantic',
|
||||
'-Wno-switch-default',
|
||||
'-Wunused-function',
|
||||
'-fvisibility=hidden'
|
||||
]),
|
||||
language: 'objcpp'
|
||||
)
|
||||
endif
|
||||
|
||||
common_cpp_args = [
|
||||
'-Wno-c++20-compat',
|
||||
'-Wno-c++20-extensions',
|
||||
'-Wno-c++98-compat',
|
||||
'-Wno-c++98-compat-pedantic',
|
||||
'-Wno-disabled-macro-expansion',
|
||||
'-Wno-missing-prototypes',
|
||||
'-Wno-padded',
|
||||
'-Wno-pre-c++20-compat-pedantic',
|
||||
'-Wno-switch-default',
|
||||
'-Wunused-function',
|
||||
'-fvisibility=hidden'
|
||||
]
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
common_cpp_args += ['-DCURL_STATICLIB']
|
||||
endif
|
||||
|
||||
add_project_arguments(
|
||||
cpp.get_supported_arguments(common_cpp_args),
|
||||
language: 'cpp'
|
||||
)
|
||||
|
||||
source_file_names = [
|
||||
'src/main.cpp',
|
||||
'src/config/config.cpp',
|
||||
'src/config/weather.cpp'
|
||||
]
|
||||
|
||||
if host_machine.system() == 'linux'
|
||||
source_file_names += ['src/os/linux.cpp']
|
||||
elif host_machine.system() == 'freebsd'
|
||||
source_file_names += ['src/os/freebsd.cpp']
|
||||
elif host_machine.system() == 'darwin'
|
||||
source_file_names += [
|
||||
'src/os/macos.cpp',
|
||||
'src/os/macos/bridge.mm',
|
||||
]
|
||||
elif host_machine.system() == 'windows'
|
||||
source_file_names += ['src/os/windows.cpp']
|
||||
endif
|
||||
|
||||
sources = []
|
||||
|
||||
foreach file : source_file_names
|
||||
sources += files(file)
|
||||
endforeach
|
||||
|
||||
deps = [
|
||||
dependency('fmt'),
|
||||
dependency('libcurl'),
|
||||
dependency('tomlplusplus'),
|
||||
dependency('yyjson')
|
||||
]
|
||||
|
||||
if host_machine.system() == 'darwin'
|
||||
deps += dependency('Foundation')
|
||||
deps += dependency('MediaPlayer')
|
||||
deps += dependency('SystemConfiguration')
|
||||
deps += dependency('iconv')
|
||||
elif host_machine.system() == 'linux' or host_machine.system() == 'freebsd'
|
||||
deps += dependency('sdbus-c++')
|
||||
deps += dependency('x11')
|
||||
endif
|
||||
|
||||
objc_args = []
|
||||
link_args = []
|
||||
|
||||
if host_machine.system() == 'darwin'
|
||||
objc_args += ['-fobjc-arc']
|
||||
elif host_machine.system() == 'windows'
|
||||
windows_sdk_lib_dir = 'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64'
|
||||
link_args += ['-L' + windows_sdk_lib_dir, '-lwindowsapp', '-static']
|
||||
endif
|
||||
|
||||
executable(
|
||||
'draconis++',
|
||||
sources,
|
||||
objc_args: objc_args,
|
||||
link_args: link_args,
|
||||
dependencies: deps
|
||||
)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
[fmt]
|
||||
src.github = "fmtlib/fmt"
|
||||
fetch.github = "fmtlib/fmt"
|
||||
|
||||
[reflect-cpp]
|
||||
src.github = "getml/reflect-cpp"
|
||||
fetch.github = "getml/reflect-cpp"
|
||||
|
||||
[sdbus-cpp]
|
||||
src.github = "kistler-group/sdbus-cpp"
|
||||
fetch.github = "kistler-group/sdbus-cpp"
|
||||
|
||||
[tomlplusplus]
|
||||
src.github = "marzer/tomlplusplus"
|
||||
fetch.github = "marzer/tomlplusplus"
|
||||
|
||||
[yyjson]
|
||||
src.github = "ibireme/yyjson"
|
||||
fetch.github = "ibireme/yyjson"
|
|
@ -1,42 +0,0 @@
|
|||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <fmt/core.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
using rfl::Result;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
inline fn GetConfigPath() -> std::string {
|
||||
#ifdef _WIN32
|
||||
const char* localAppData = std::getenv("LOCALAPPDATA");
|
||||
|
||||
if (!localAppData)
|
||||
throw std::runtime_error("Environment variable LOCALAPPDATA is not set");
|
||||
|
||||
return localAppData;
|
||||
#else
|
||||
const char* home = std::getenv("HOME");
|
||||
|
||||
if (!home)
|
||||
throw std::runtime_error("Environment variable HOME is not set");
|
||||
|
||||
return std::string(home) + "/.config";
|
||||
#endif
|
||||
}
|
||||
|
||||
fn Config::getInstance() -> Config {
|
||||
fs::path configPath = GetConfigPath();
|
||||
configPath /= "draconis++/config.toml";
|
||||
|
||||
const Result<Config> result = rfl::toml::load<Config>(configPath.string());
|
||||
|
||||
if (!result) {
|
||||
fmt::println(stderr, "Failed to load config file: {}", result.error()->what());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return result.value();
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <rfl.hpp>
|
||||
#include <rfl/Field.hpp>
|
||||
|
||||
#include "../util/macros.h"
|
||||
#include "../util/types.h"
|
||||
#include "weather.h"
|
||||
|
||||
using Location = std::variant<string, Coords>;
|
||||
|
||||
struct General {
|
||||
rfl::Field<"name", string> name = "user";
|
||||
};
|
||||
|
||||
struct NowPlaying {
|
||||
bool enabled = false;
|
||||
};
|
||||
|
||||
struct Weather {
|
||||
bool enabled = false;
|
||||
|
||||
Location location;
|
||||
string api_key;
|
||||
string units;
|
||||
|
||||
[[nodiscard]] fn getWeatherInfo() const -> WeatherOutput;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
rfl::Field<"general", General> general = General { .name = "user" };
|
||||
rfl::Field<"now_playing", NowPlaying> now_playing = NowPlaying();
|
||||
rfl::Field<"weather", Weather> weather = Weather();
|
||||
|
||||
static fn getInstance() -> Config;
|
||||
};
|
|
@ -1,154 +0,0 @@
|
|||
#include <chrono>
|
||||
#include <curl/curl.h>
|
||||
#include <fmt/core.h>
|
||||
#include <rfl/json.hpp>
|
||||
#include <rfl/json/load.hpp>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
using rfl::Error;
|
||||
using rfl::Result;
|
||||
|
||||
// Function to read cache from file
|
||||
fn ReadCacheFromFile() -> Result<WeatherOutput> {
|
||||
#ifdef __WIN32__
|
||||
const char* tempPath = getenv("TEMP");
|
||||
const string path = string(tempPath) + "\\weather_cache.json";
|
||||
std::ifstream ifs(path);
|
||||
#else
|
||||
std::ifstream ifs("/tmp/weather_cache.json");
|
||||
#endif
|
||||
|
||||
if (!ifs.is_open())
|
||||
return Error("Cache file not found.");
|
||||
|
||||
fmt::println("Reading from cache file...");
|
||||
|
||||
std::stringstream buf;
|
||||
|
||||
buf << ifs.rdbuf();
|
||||
|
||||
Result<WeatherOutput> val = rfl::json::read<WeatherOutput>(buf.str());
|
||||
|
||||
fmt::println("Successfully read from cache file.");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// Function to write cache to file
|
||||
fn WriteCacheToFile(const WeatherOutput& data) -> Result<u8> {
|
||||
fmt::println("Writing to cache file...");
|
||||
|
||||
#ifdef __WIN32__
|
||||
const char* tempPath = getenv("TEMP");
|
||||
const string path = string(tempPath) + "\\weather_cache.json";
|
||||
std::ofstream ofs(path);
|
||||
#else
|
||||
std::ofstream ofs("/tmp/weather_cache.json");
|
||||
#endif
|
||||
|
||||
if (!ofs.is_open())
|
||||
return Error("Failed to open cache file for writing.");
|
||||
|
||||
ofs << rfl::json::write(data);
|
||||
|
||||
fmt::println("Successfully wrote to cache file.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn WriteCallback(void* contents, const usize size, const usize nmemb, string* str) -> usize {
|
||||
const usize totalSize = size * nmemb;
|
||||
str->append(static_cast<char*>(contents), totalSize);
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
// Function to make API request
|
||||
fn MakeApiRequest(const string& url) -> Result<WeatherOutput> {
|
||||
fmt::println("Making API request to URL: {}", url);
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
string responseBuffer;
|
||||
|
||||
if (curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseBuffer);
|
||||
const CURLcode res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res != CURLE_OK)
|
||||
return Error(fmt::format("Failed to perform cURL request: {}", curl_easy_strerror(res)));
|
||||
|
||||
fmt::println("Received response from API. Response size: {}", responseBuffer.size());
|
||||
fmt::println("Response: {}", responseBuffer);
|
||||
|
||||
WeatherOutput output = rfl::json::read<WeatherOutput>(responseBuffer).value();
|
||||
|
||||
return output; // Return an empty result for now
|
||||
}
|
||||
|
||||
return Error("Failed to initialize cURL.");
|
||||
}
|
||||
|
||||
// Core function to get weather information
|
||||
fn Weather::getWeatherInfo() const -> WeatherOutput {
|
||||
using namespace std::chrono;
|
||||
|
||||
// Check if cache is valid
|
||||
if (Result<WeatherOutput> data = ReadCacheFromFile()) {
|
||||
WeatherOutput dataVal = *data;
|
||||
|
||||
if (system_clock::now() - system_clock::time_point(seconds(dataVal.dt)) < minutes(10)) {
|
||||
fmt::println("Cache is valid. Returning cached data.");
|
||||
|
||||
return dataVal;
|
||||
}
|
||||
|
||||
fmt::println("Cache is expired.");
|
||||
} else {
|
||||
fmt::println("No valid cache found.");
|
||||
}
|
||||
|
||||
WeatherOutput result;
|
||||
|
||||
if (holds_alternative<string>(location)) {
|
||||
const string city = get<string>(location);
|
||||
|
||||
const char* loc = curl_easy_escape(nullptr, city.c_str(), static_cast<int>(city.length()));
|
||||
|
||||
fmt::println("City: {}", loc);
|
||||
|
||||
const string apiUrl = fmt::format(
|
||||
"https://api.openweathermap.org/data/2.5/"
|
||||
"weather?q={}&appid={}&units={}",
|
||||
loc,
|
||||
api_key,
|
||||
units
|
||||
);
|
||||
|
||||
result = MakeApiRequest(apiUrl).value();
|
||||
} else {
|
||||
const auto [lat, lon] = get<Coords>(location);
|
||||
|
||||
fmt::println("Coordinates: lat = {:.3f}, lon = {:.3f}", lat, lon);
|
||||
|
||||
const string apiUrl = fmt::format(
|
||||
"https://api.openweathermap.org/data/2.5/"
|
||||
"weather?lat={:.3f}&lon={:.3f}&appid={}&units={}",
|
||||
lat,
|
||||
lon,
|
||||
api_key,
|
||||
units
|
||||
);
|
||||
|
||||
result = MakeApiRequest(apiUrl).value();
|
||||
}
|
||||
|
||||
// Update the cache with the new data
|
||||
WriteCacheToFile(result);
|
||||
|
||||
fmt::println("Returning new data.");
|
||||
|
||||
return result;
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <rfl.hpp>
|
||||
#include <rfl/toml.hpp>
|
||||
|
||||
#include "../util/types.h"
|
||||
|
||||
using degrees = rfl::Validator<u16, rfl::Minimum<0>, rfl::Maximum<360>>;
|
||||
using percentage = rfl::Validator<i8, rfl::Minimum<0>, rfl::Maximum<100>>;
|
||||
|
||||
struct Condition {
|
||||
string description;
|
||||
string icon;
|
||||
string main;
|
||||
usize id;
|
||||
};
|
||||
|
||||
struct Main {
|
||||
f64 feels_like;
|
||||
f64 temp;
|
||||
f64 temp_max;
|
||||
f64 temp_min;
|
||||
isize pressure;
|
||||
percentage humidity;
|
||||
std::optional<isize> grnd_level;
|
||||
std::optional<isize> sea_level;
|
||||
};
|
||||
|
||||
struct Wind {
|
||||
degrees deg;
|
||||
f64 speed;
|
||||
std::optional<f64> gust;
|
||||
};
|
||||
|
||||
struct Precipitation {
|
||||
rfl::Rename<"1h", f64> one_hour;
|
||||
rfl::Rename<"3h", f64> three_hours;
|
||||
};
|
||||
|
||||
struct Sys {
|
||||
string country;
|
||||
usize id;
|
||||
usize sunrise;
|
||||
usize sunset;
|
||||
usize type;
|
||||
};
|
||||
|
||||
struct Clouds {
|
||||
percentage all;
|
||||
};
|
||||
|
||||
struct Coords {
|
||||
double lat;
|
||||
double lon;
|
||||
};
|
||||
|
||||
struct WeatherOutput {
|
||||
Clouds clouds;
|
||||
isize timezone;
|
||||
isize visibility;
|
||||
Main main;
|
||||
rfl::Rename<"coord", Coords> coords;
|
||||
std::optional<Precipitation> rain;
|
||||
std::optional<Precipitation> snow;
|
||||
string base;
|
||||
string name;
|
||||
std::vector<Condition> weather;
|
||||
Sys sys;
|
||||
usize cod;
|
||||
usize dt;
|
||||
usize id;
|
||||
Wind wind;
|
||||
};
|
92
src/main.cpp
92
src/main.cpp
|
@ -1,92 +0,0 @@
|
|||
#include <ctime>
|
||||
#include <fmt/chrono.h>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <string>
|
||||
|
||||
#include "config/config.h"
|
||||
#include "os/os.h"
|
||||
|
||||
struct BytesToGiB {
|
||||
u64 value;
|
||||
};
|
||||
|
||||
// 1024^3 (size of 1 GiB)
|
||||
constexpr u64 GIB = 1'073'741'824;
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<BytesToGiB> : fmt::formatter<double> {
|
||||
template <typename FmtCtx>
|
||||
constexpr auto format(const BytesToGiB& BTG, FmtCtx& ctx) const -> typename FmtCtx::iterator {
|
||||
auto out = fmt::formatter<double>::format(static_cast<double>(BTG.value) / GIB, ctx);
|
||||
*out++ = 'G';
|
||||
*out++ = 'i';
|
||||
*out++ = 'B';
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
fn GetDate() -> std::string {
|
||||
// Get current local time
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::tm localTime = *std::localtime(&now);
|
||||
|
||||
// Format the date using fmt::format
|
||||
std::string date = fmt::format("{:%e}", localTime);
|
||||
|
||||
// Remove leading whitespace
|
||||
if (!date.empty() && std::isspace(date.front()))
|
||||
date.erase(date.begin());
|
||||
|
||||
// Append appropriate suffix for the date
|
||||
if (date == "1" || date == "21" || date == "31")
|
||||
date += "st";
|
||||
else if (date == "2" || date == "22")
|
||||
date += "nd";
|
||||
else if (date == "3" || date == "23")
|
||||
date += "rd";
|
||||
else
|
||||
date += "th";
|
||||
|
||||
return fmt::format("{:%B} {}", localTime, date);
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
const Config& config = Config::getInstance();
|
||||
|
||||
// Fetching weather information
|
||||
Weather weather = config.weather.get();
|
||||
WeatherOutput weatherInfo = weather.getWeatherInfo();
|
||||
|
||||
// Fetching OS version
|
||||
std::string osVersion = GetOSVersion();
|
||||
|
||||
// Checking if now playing is enabled
|
||||
bool nowPlayingEnabled = config.now_playing.get().enabled;
|
||||
|
||||
// Fetching current date
|
||||
std::string date = GetDate();
|
||||
|
||||
// Fetching memory info
|
||||
u64 memInfo = GetMemInfo();
|
||||
|
||||
const std::string& name = config.general.get().name.get();
|
||||
|
||||
fmt::println("Hello {}!", name);
|
||||
fmt::println("Today is: {}", date);
|
||||
fmt::println("Installed RAM: {:.2f}", BytesToGiB(memInfo));
|
||||
fmt::println("OS: {}", osVersion);
|
||||
|
||||
if (weather.enabled)
|
||||
fmt::println("It is {}°F in {}", std::lround(weatherInfo.main.temp), weatherInfo.name);
|
||||
|
||||
if (nowPlayingEnabled) {
|
||||
const string nowPlaying = GetNowPlaying();
|
||||
if (!nowPlaying.empty())
|
||||
fmt::println("{}", nowPlaying);
|
||||
else
|
||||
fmt::println("No song playing");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
#ifdef __FreeBSD__
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include "os.h"
|
||||
|
||||
fn GetMemInfo() -> u64 {
|
||||
u64 mem = 0;
|
||||
usize size = sizeof(mem);
|
||||
|
||||
sysctlbyname("hw.physmem", &mem, &size, nullptr, 0);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
fn GetOSVersion() -> string {
|
||||
std::ifstream file("/etc/os-release");
|
||||
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Failed to open /etc/os-release" << std::endl;
|
||||
return ""; // Return empty string indicating failure
|
||||
}
|
||||
|
||||
string line;
|
||||
const string prefix = "PRETTY_NAME=";
|
||||
|
||||
while (std::getline(file, line)) {
|
||||
if (line.find(prefix) == 0) {
|
||||
string prettyName = line.substr(prefix.size());
|
||||
|
||||
// Remove surrounding quotes if present
|
||||
if (!prettyName.empty() && prettyName.front() == '"' && prettyName.back() == '"')
|
||||
prettyName = prettyName.substr(1, prettyName.size() - 2);
|
||||
|
||||
return prettyName;
|
||||
}
|
||||
}
|
||||
|
||||
return ""; // Return empty string if PRETTY_NAME= line not found
|
||||
}
|
||||
|
||||
fn GetMprisPlayers(sdbus::IConnection& connection) -> std::vector<string> {
|
||||
const sdbus::ServiceName dbusInterface = sdbus::ServiceName("org.freedesktop.DBus");
|
||||
const sdbus::ObjectPath dbusObjectPath = sdbus::ObjectPath("/org/freedesktop/DBus");
|
||||
const char* dbusMethodListNames = "ListNames";
|
||||
|
||||
const std::unique_ptr<sdbus::IProxy> dbusProxy =
|
||||
createProxy(connection, dbusInterface, dbusObjectPath);
|
||||
|
||||
std::vector<string> names;
|
||||
|
||||
dbusProxy->callMethod(dbusMethodListNames).onInterface(dbusInterface).storeResultsTo(names);
|
||||
|
||||
std::vector<string> mprisPlayers;
|
||||
|
||||
for (const std::basic_string<char>& name : names)
|
||||
if (const char* mprisInterfaceName = "org.mpris.MediaPlayer2";
|
||||
name.find(mprisInterfaceName) != std::string::npos)
|
||||
mprisPlayers.push_back(name);
|
||||
|
||||
return mprisPlayers;
|
||||
}
|
||||
|
||||
fn GetActivePlayer(const std::vector<string>& mprisPlayers) -> string {
|
||||
if (!mprisPlayers.empty())
|
||||
return mprisPlayers.front();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
fn GetNowPlaying() -> string {
|
||||
try {
|
||||
const char *playerObjectPath = "/org/mpris/MediaPlayer2",
|
||||
*playerInterfaceName = "org.mpris.MediaPlayer2.Player";
|
||||
|
||||
std::unique_ptr<sdbus::IConnection> connection = sdbus::createSessionBusConnection();
|
||||
|
||||
std::vector<string> mprisPlayers = GetMprisPlayers(*connection);
|
||||
|
||||
if (mprisPlayers.empty())
|
||||
return "";
|
||||
|
||||
string activePlayer = GetActivePlayer(mprisPlayers);
|
||||
|
||||
if (activePlayer.empty())
|
||||
return "";
|
||||
|
||||
auto playerProxy = sdbus::createProxy(
|
||||
*connection, sdbus::ServiceName(activePlayer), sdbus::ObjectPath(playerObjectPath)
|
||||
);
|
||||
|
||||
sdbus::Variant metadataVariant =
|
||||
playerProxy->getProperty("Metadata").onInterface(playerInterfaceName);
|
||||
|
||||
if (metadataVariant.containsValueOfType<std::map<std::string, sdbus::Variant>>()) {
|
||||
const auto& metadata = metadataVariant.get<std::map<std::string, sdbus::Variant>>();
|
||||
|
||||
auto iter = metadata.find("xesam:title");
|
||||
|
||||
if (iter != metadata.end() && iter->second.containsValueOfType<std::string>())
|
||||
return iter->second.get<std::string>();
|
||||
}
|
||||
} catch (const sdbus::Error& e) {
|
||||
if (e.getName() != "com.github.altdesktop.playerctld.NoActivePlayer")
|
||||
return fmt::format("Error: {}", e.what());
|
||||
|
||||
return "No active player";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
135
src/os/linux.cpp
135
src/os/linux.cpp
|
@ -1,135 +0,0 @@
|
|||
#ifdef __linux__
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <vector>
|
||||
|
||||
#include "os.h"
|
||||
|
||||
enum SessionType { Wayland, X11, TTY, Unknown };
|
||||
|
||||
fn ParseLineAsNumber(const std::string& input) -> u64 {
|
||||
usize start = input.find_first_of("0123456789");
|
||||
|
||||
if (start == std::string::npos)
|
||||
throw std::runtime_error("No number found in input");
|
||||
|
||||
usize end = input.find_first_not_of("0123456789", start);
|
||||
|
||||
return std::stoull(input.substr(start, end - start));
|
||||
}
|
||||
|
||||
fn MeminfoParse(const std::filesystem::path& filepath) -> u64 {
|
||||
std::ifstream input(filepath);
|
||||
|
||||
if (!input.is_open())
|
||||
throw std::runtime_error("Failed to open " + filepath.string());
|
||||
|
||||
std::string line;
|
||||
|
||||
while (std::getline(input, line))
|
||||
if (line.starts_with("MemTotal"))
|
||||
return ParseLineAsNumber(line);
|
||||
|
||||
throw std::runtime_error("MemTotal line not found in " + filepath.string());
|
||||
}
|
||||
|
||||
fn GetMemInfo() -> u64 { return MeminfoParse("/proc/meminfo") * 1024; }
|
||||
|
||||
fn GetOSVersion() -> std::string {
|
||||
std::ifstream file("/etc/os-release");
|
||||
|
||||
if (!file.is_open())
|
||||
throw std::runtime_error("Failed to open /etc/os-release");
|
||||
|
||||
string line;
|
||||
const string prefix = "PRETTY_NAME=";
|
||||
|
||||
while (std::getline(file, line))
|
||||
if (line.starts_with(prefix)) {
|
||||
string prettyName = line.substr(prefix.size());
|
||||
|
||||
if (!prettyName.empty() && prettyName.front() == '"' && prettyName.back() == '"')
|
||||
return prettyName.substr(1, prettyName.size() - 2);
|
||||
|
||||
return prettyName;
|
||||
}
|
||||
|
||||
throw std::runtime_error("PRETTY_NAME line not found in /etc/os-release");
|
||||
}
|
||||
|
||||
fn GetMprisPlayers(sdbus::IConnection& connection) -> std::vector<string> {
|
||||
const sdbus::ServiceName dbusInterface = sdbus::ServiceName("org.freedesktop.DBus");
|
||||
const sdbus::ObjectPath dbusObjectPath = sdbus::ObjectPath("/org/freedesktop/DBus");
|
||||
const char* dbusMethodListNames = "ListNames";
|
||||
|
||||
const std::unique_ptr<sdbus::IProxy> dbusProxy =
|
||||
createProxy(connection, dbusInterface, dbusObjectPath);
|
||||
|
||||
std::vector<string> names;
|
||||
|
||||
dbusProxy->callMethod(dbusMethodListNames).onInterface(dbusInterface).storeResultsTo(names);
|
||||
|
||||
std::vector<string> mprisPlayers;
|
||||
|
||||
for (const std::basic_string<char>& name : names)
|
||||
if (const char* mprisInterfaceName = "org.mpris.MediaPlayer2";
|
||||
name.find(mprisInterfaceName) != std::string::npos)
|
||||
mprisPlayers.push_back(name);
|
||||
|
||||
return mprisPlayers;
|
||||
}
|
||||
|
||||
fn GetActivePlayer(const std::vector<string>& mprisPlayers) -> string {
|
||||
if (!mprisPlayers.empty())
|
||||
return mprisPlayers.front();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
fn GetNowPlaying() -> string {
|
||||
try {
|
||||
const char *playerObjectPath = "/org/mpris/MediaPlayer2",
|
||||
*playerInterfaceName = "org.mpris.MediaPlayer2.Player";
|
||||
|
||||
std::unique_ptr<sdbus::IConnection> connection = sdbus::createSessionBusConnection();
|
||||
|
||||
std::vector<string> mprisPlayers = GetMprisPlayers(*connection);
|
||||
|
||||
if (mprisPlayers.empty())
|
||||
return "";
|
||||
|
||||
string activePlayer = GetActivePlayer(mprisPlayers);
|
||||
|
||||
if (activePlayer.empty())
|
||||
return "";
|
||||
|
||||
auto playerProxy = sdbus::createProxy(
|
||||
*connection, sdbus::ServiceName(activePlayer), sdbus::ObjectPath(playerObjectPath)
|
||||
);
|
||||
|
||||
sdbus::Variant metadataVariant =
|
||||
playerProxy->getProperty("Metadata").onInterface(playerInterfaceName);
|
||||
|
||||
if (metadataVariant.containsValueOfType<std::map<std::string, sdbus::Variant>>()) {
|
||||
const auto& metadata = metadataVariant.get<std::map<std::string, sdbus::Variant>>();
|
||||
|
||||
auto iter = metadata.find("xesam:title");
|
||||
|
||||
if (iter != metadata.end() && iter->second.containsValueOfType<std::string>())
|
||||
return iter->second.get<std::string>();
|
||||
}
|
||||
} catch (const sdbus::Error& e) {
|
||||
if (e.getName() != "com.github.altdesktop.playerctld.NoActivePlayer")
|
||||
return fmt::format("Error: {}", e.what());
|
||||
|
||||
return "No active player";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
#ifdef __APPLE__
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "macos/bridge.h"
|
||||
#include "os.h"
|
||||
|
||||
fn GetMemInfo() -> u64 {
|
||||
u64 mem = 0;
|
||||
usize size = sizeof(mem);
|
||||
|
||||
sysctlbyname("hw.memsize", &mem, &size, nullptr, 0);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
fn GetNowPlaying() -> string {
|
||||
if (const char* title = GetCurrentPlayingTitle(); const char* artist = GetCurrentPlayingArtist())
|
||||
return "Now Playing: " + string(artist) + " - " + string(title);
|
||||
|
||||
return "No song playing";
|
||||
}
|
||||
|
||||
fn GetOSVersion() -> string { return GetMacOSVersion(); }
|
||||
|
||||
fn GetDesktopEnvironment() -> string { return "Aqua"; }
|
||||
|
||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include "../../util/macros.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Bridge : NSObject
|
||||
+ (NSDictionary*)currentPlayingMetadata;
|
||||
+ (NSString*)macOSVersion;
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
extern "C" {
|
||||
fn GetCurrentPlayingTitle() -> const char*;
|
||||
fn GetCurrentPlayingArtist() -> const char*;
|
||||
fn GetMacOSVersion() -> const char*;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1,132 +0,0 @@
|
|||
#ifdef __APPLE__
|
||||
|
||||
#import <dispatch/dispatch.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import "bridge.h"
|
||||
|
||||
using MRMediaRemoteGetNowPlayingInfoFunction =
|
||||
void (*)(dispatch_queue_t queue, void (^handler)(NSDictionary* information));
|
||||
|
||||
@implementation Bridge
|
||||
+ (NSDictionary*)currentPlayingMetadata {
|
||||
CFURLRef ref = CFURLCreateWithFileSystemPath(
|
||||
kCFAllocatorDefault,
|
||||
CFSTR("/System/Library/PrivateFrameworks/MediaRemote.framework"),
|
||||
kCFURLPOSIXPathStyle,
|
||||
false
|
||||
);
|
||||
|
||||
if (!ref) {
|
||||
NSLog(@"Failed to load MediaRemote framework");
|
||||
return nil;
|
||||
}
|
||||
|
||||
CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, ref);
|
||||
CFRelease(ref);
|
||||
|
||||
if (!bundle) {
|
||||
NSLog(@"Failed to load MediaRemote framework");
|
||||
return nil;
|
||||
}
|
||||
|
||||
MRMediaRemoteGetNowPlayingInfoFunction mrMediaRemoteGetNowPlayingInfo =
|
||||
reinterpret_cast<MRMediaRemoteGetNowPlayingInfoFunction>(
|
||||
CFBundleGetFunctionPointerForName(bundle, CFSTR("MRMediaRemoteGetNowPlayingInfo"))
|
||||
);
|
||||
|
||||
if (!mrMediaRemoteGetNowPlayingInfo) {
|
||||
NSLog(@"Failed to get function pointer for MRMediaRemoteGetNowPlayingInfo");
|
||||
CFRelease(bundle);
|
||||
return nil;
|
||||
}
|
||||
|
||||
__block NSDictionary* nowPlayingInfo = nil;
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
mrMediaRemoteGetNowPlayingInfo(
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
^(NSDictionary* information) {
|
||||
nowPlayingInfo = [information copy];
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}
|
||||
);
|
||||
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
CFRelease(bundle);
|
||||
return nowPlayingInfo;
|
||||
}
|
||||
|
||||
+ (NSString*)macOSVersion {
|
||||
NSProcessInfo* processInfo = [NSProcessInfo processInfo];
|
||||
|
||||
NSOperatingSystemVersion osVersion = [processInfo operatingSystemVersion];
|
||||
|
||||
NSString* version;
|
||||
if (osVersion.patchVersion == 0) {
|
||||
version =
|
||||
[NSString stringWithFormat:@"%ld.%ld", osVersion.majorVersion, osVersion.minorVersion];
|
||||
} else {
|
||||
version = [NSString stringWithFormat:@"%ld.%ld.%ld",
|
||||
osVersion.majorVersion,
|
||||
osVersion.minorVersion,
|
||||
osVersion.patchVersion];
|
||||
}
|
||||
|
||||
// Dictionary to map macOS versions to their respective names
|
||||
NSDictionary<NSNumber*, NSString*>* versionNames =
|
||||
@{ @11 : @"Big Sur", @12 : @"Monterey", @13 : @"Ventura", @14 : @"Sonoma", @15 : @"Sequoia" };
|
||||
|
||||
NSNumber* majorVersionNumber = @(osVersion.majorVersion);
|
||||
NSString* versionName = versionNames[majorVersionNumber];
|
||||
|
||||
if (versionName == nil)
|
||||
versionName = @"Unknown";
|
||||
|
||||
NSString* fullVersion = [NSString stringWithFormat:@"macOS %@ %@", version, versionName];
|
||||
|
||||
return fullVersion;
|
||||
}
|
||||
@end
|
||||
|
||||
extern "C" {
|
||||
fn GetCurrentPlayingTitle() -> const char* {
|
||||
NSDictionary* metadata = [Bridge currentPlayingMetadata];
|
||||
|
||||
if (metadata == nil)
|
||||
return nullptr;
|
||||
|
||||
NSString* title = [metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoTitle"];
|
||||
|
||||
if (title)
|
||||
return strdup([title UTF8String]);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fn GetCurrentPlayingArtist() -> const char* {
|
||||
NSDictionary* metadata = [Bridge currentPlayingMetadata];
|
||||
|
||||
if (metadata == nil)
|
||||
return nullptr;
|
||||
|
||||
NSString* artist = [metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoArtist"];
|
||||
|
||||
if (artist)
|
||||
return strdup([artist UTF8String]);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fn GetMacOSVersion() -> const char* {
|
||||
NSString* version = [Bridge macOSVersion];
|
||||
|
||||
if (version)
|
||||
return strdup([version UTF8String]);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
29
src/os/os.h
29
src/os/os.h
|
@ -1,29 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../util/macros.h"
|
||||
#include "../util/types.h"
|
||||
|
||||
/**
|
||||
* @brief Get the amount of installed RAM in bytes.
|
||||
*/
|
||||
fn GetMemInfo() -> u64;
|
||||
|
||||
/**
|
||||
* @brief Get the currently playing song metadata.
|
||||
*/
|
||||
fn GetNowPlaying() -> string;
|
||||
|
||||
/**
|
||||
* @brief Get the OS version.
|
||||
*/
|
||||
fn GetOSVersion() -> string;
|
||||
|
||||
/**
|
||||
* @brief Get the current desktop environment.
|
||||
*/
|
||||
fn GetDesktopEnvironment() -> string;
|
||||
|
||||
/**
|
||||
* @brief Get the current window manager.
|
||||
*/
|
||||
fn GetWindowManager() -> string;
|
|
@ -1,111 +0,0 @@
|
|||
#ifdef __WIN32__
|
||||
|
||||
#include <exception>
|
||||
#include <windows.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Media.Control.h>
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/impl/Windows.Media.Control.2.h>
|
||||
|
||||
#include "os.h"
|
||||
|
||||
fn GetMemInfo() -> u64 {
|
||||
u64 mem = 0;
|
||||
GetPhysicallyInstalledSystemMemory(&mem);
|
||||
return mem * 1024;
|
||||
}
|
||||
|
||||
fn GetNowPlaying() -> string {
|
||||
using namespace winrt::Windows::Media::Control;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
using MediaProperties = GlobalSystemMediaTransportControlsSessionMediaProperties;
|
||||
using Session = GlobalSystemMediaTransportControlsSession;
|
||||
using SessionManager = GlobalSystemMediaTransportControlsSessionManager;
|
||||
|
||||
try {
|
||||
// Request the session manager asynchronously
|
||||
const IAsyncOperation<SessionManager> sessionManagerOp = SessionManager::RequestAsync();
|
||||
const SessionManager sessionManager = sessionManagerOp.get();
|
||||
|
||||
if (const Session currentSession = sessionManager.GetCurrentSession()) {
|
||||
// Try to get the media properties asynchronously
|
||||
const MediaProperties mediaProperties = currentSession.TryGetMediaPropertiesAsync().get();
|
||||
|
||||
// Convert the hstring title to string
|
||||
return to_string(mediaProperties.Title());
|
||||
}
|
||||
|
||||
// If we reach this point, there is no current session
|
||||
return "No current media session.";
|
||||
} catch (...) { return "Failed to get media properties."; }
|
||||
}
|
||||
|
||||
fn GetRegistryValue(const HKEY& hKey, const string& subKey, const string& valueName) -> string {
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExA(hKey, subKey.c_str(), 0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return "";
|
||||
|
||||
DWORD dataSize = 0;
|
||||
if (RegQueryValueExA(key, valueName.c_str(), nullptr, nullptr, nullptr, &dataSize) !=
|
||||
ERROR_SUCCESS) {
|
||||
RegCloseKey(key);
|
||||
return "";
|
||||
}
|
||||
|
||||
string value(dataSize, '\0');
|
||||
if (RegQueryValueExA(
|
||||
key,
|
||||
valueName.c_str(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
reinterpret_cast<LPBYTE>(value.data()), // NOLINT(*-reinterpret-cast)
|
||||
&dataSize
|
||||
) != ERROR_SUCCESS) {
|
||||
RegCloseKey(key);
|
||||
return "";
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
// Remove null terminator if present
|
||||
if (!value.empty() && value.back() == '\0')
|
||||
value.pop_back();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
fn GetOSVersion() -> string {
|
||||
string productName = GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", "ProductName"
|
||||
);
|
||||
|
||||
const string displayVersion = GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", "DisplayVersion"
|
||||
);
|
||||
|
||||
const string releaseId = GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", "ReleaseId"
|
||||
);
|
||||
|
||||
// Check for Windows 11
|
||||
if (const i32 buildNumber = stoi(GetRegistryValue(
|
||||
HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", "CurrentBuildNumber"
|
||||
));
|
||||
buildNumber >= 22000 && productName.find("Windows 10") != string::npos)
|
||||
productName.replace(productName.find("Windows 10"), 10, "Windows 11");
|
||||
|
||||
if (!productName.empty()) {
|
||||
string result = productName;
|
||||
|
||||
if (!displayVersion.empty())
|
||||
result += " " + displayVersion;
|
||||
else if (!releaseId.empty())
|
||||
result += " " + releaseId;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Allows for rust-style function definitions
|
||||
*/
|
||||
#define fn auto
|
||||
|
||||
/**
|
||||
* @brief Allows for easy getter creation
|
||||
*
|
||||
* @param class_name The class to use
|
||||
* @param type Type of the getter
|
||||
* @param name Name of the getter
|
||||
*/
|
||||
#define DEFINE_GETTER(class_name, type, name) \
|
||||
fn class_name::get##name() const->type { return m_##name; }
|
||||
|
||||
/**
|
||||
* @brief Helper for making reflect-cpp impls
|
||||
*
|
||||
* @param struct_name The struct name
|
||||
* @param lower_name The arg name
|
||||
* @param ... Values of the class to convert
|
||||
*/
|
||||
#define DEF_IMPL(struct_name, ...) \
|
||||
struct struct_name##Impl { \
|
||||
__VA_ARGS__; \
|
||||
\
|
||||
static fn from_class(const struct_name& instance) noexcept -> struct_name##Impl; \
|
||||
\
|
||||
[[nodiscard]] fn to_class() const -> struct_name; \
|
||||
};
|
|
@ -1,218 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
#include "macros.h"
|
||||
#include "types.h"
|
||||
|
||||
/**
|
||||
* @class Error
|
||||
* @brief Represents an error with a message.
|
||||
*
|
||||
* This class is used to encapsulate error messages that can be returned from functions.
|
||||
*/
|
||||
class Error {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an Error with a message.
|
||||
* @param message The error message.
|
||||
*/
|
||||
explicit Error(string message) : m_Message(std::move(message)) {}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the error message.
|
||||
* @return A constant reference to the error message string.
|
||||
*/
|
||||
[[nodiscard]] fn message() const -> const string& { return m_Message; }
|
||||
|
||||
private:
|
||||
string m_Message; ///< The error message.
|
||||
};
|
||||
|
||||
// Primary template for Result with a default type of void
|
||||
|
||||
/**
|
||||
* @class Result
|
||||
* @brief Represents a result that can either be a value or an error.
|
||||
*
|
||||
* This is the primary template for Result, which defaults to handling void results.
|
||||
*/
|
||||
template <typename T = void>
|
||||
class Result;
|
||||
|
||||
// Specialization for Result<void>
|
||||
|
||||
/**
|
||||
* @class Result<void>
|
||||
* @brief Specialization of Result for handling void results.
|
||||
*
|
||||
* This class is used when a function either succeeds with no value or fails with an error.
|
||||
*/
|
||||
template <>
|
||||
class Result<void> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a successful Result.
|
||||
*/
|
||||
Result() : m_Result(std::monostate {}) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs an error Result.
|
||||
* @param error The error object.
|
||||
*/
|
||||
Result(const Error& error) : m_Result(error) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs an error Result.
|
||||
* @param error An rvalue reference to the error object.
|
||||
*/
|
||||
Result(Error&& error) : m_Result(std::move(error)) {}
|
||||
|
||||
/**
|
||||
* @brief Checks if the Result is successful.
|
||||
* @return True if the Result is successful, otherwise false.
|
||||
*/
|
||||
[[nodiscard]] fn isOk() const -> bool { return std::holds_alternative<std::monostate>(m_Result); }
|
||||
|
||||
/**
|
||||
* @brief Checks if the Result contains an error.
|
||||
* @return True if the Result contains an error, otherwise false.
|
||||
*/
|
||||
[[nodiscard]] fn isErr() const -> bool { return std::holds_alternative<Error>(m_Result); }
|
||||
|
||||
/**
|
||||
* @brief Throws an exception if the Result contains an error.
|
||||
*
|
||||
* This function should be called only if the Result is successful.
|
||||
*/
|
||||
void value() const {
|
||||
if (isErr()) {
|
||||
throw std::logic_error("Attempted to access value of an error Result");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the error object.
|
||||
* @return A constant reference to the Error object.
|
||||
* @throws std::logic_error if the Result is successful.
|
||||
*/
|
||||
[[nodiscard]] fn error() const -> const Error& {
|
||||
if (isOk()) {
|
||||
throw std::logic_error("Attempted to access error of an ok Result");
|
||||
}
|
||||
return std::get<Error>(m_Result);
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<std::monostate, Error>
|
||||
m_Result; ///< The underlying result, which can be either void or an Error.
|
||||
};
|
||||
|
||||
// Primary template for Result
|
||||
|
||||
/**
|
||||
* @class Result
|
||||
* @brief Represents a result that can either be a value of type T or an error.
|
||||
*
|
||||
* This template class is used to handle results that can either be a successful value or an error.
|
||||
* @tparam T The type of the successful value.
|
||||
*/
|
||||
template <typename T>
|
||||
class Result {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a successful Result with a value.
|
||||
* @param value The value of the Result.
|
||||
*/
|
||||
Result(const T& value) : m_Result(value) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs a successful Result with a value.
|
||||
* @param value An rvalue reference to the value.
|
||||
*/
|
||||
Result(T&& value) : m_Result(std::move(value)) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs an error Result.
|
||||
* @param error The error object.
|
||||
*/
|
||||
Result(const Error& error) : m_Result(error) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs an error Result.
|
||||
* @param error An rvalue reference to the error object.
|
||||
*/
|
||||
Result(Error&& error) : m_Result(std::move(error)) {}
|
||||
|
||||
/**
|
||||
* @brief Checks if the Result is successful.
|
||||
* @return True if the Result is successful, otherwise false.
|
||||
*/
|
||||
[[nodiscard]] fn isOk() const -> bool { return std::holds_alternative<T>(m_Result); }
|
||||
|
||||
/**
|
||||
* @brief Checks if the Result contains an error.
|
||||
* @return True if the Result contains an error, otherwise false.
|
||||
*/
|
||||
[[nodiscard]] fn isErr() const -> bool { return std::holds_alternative<Error>(m_Result); }
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value.
|
||||
* @return A constant reference to the value.
|
||||
* @throws std::logic_error if the Result contains an error.
|
||||
*/
|
||||
fn value() const -> const T& {
|
||||
if (isErr()) {
|
||||
throw std::logic_error("Attempted to access value of an error Result");
|
||||
}
|
||||
return std::get<T>(m_Result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the error object.
|
||||
* @return A constant reference to the Error object.
|
||||
* @throws std::logic_error if the Result is successful.
|
||||
*/
|
||||
[[nodiscard]] fn error() const -> const Error& {
|
||||
if (isOk()) {
|
||||
throw std::logic_error("Attempted to access error of an ok Result");
|
||||
}
|
||||
return std::get<Error>(m_Result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the value or returns a default value.
|
||||
* @param defaultValue The default value to return if the Result contains an error.
|
||||
* @return The value if the Result is successful, otherwise the default value.
|
||||
*/
|
||||
fn valueOr(const T& defaultValue) const -> T {
|
||||
return isOk() ? std::get<T>(m_Result) : defaultValue;
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<T, Error>
|
||||
m_Result; ///< The underlying result, which can be either a value of type T or an Error.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper function to create a successful Result.
|
||||
*
|
||||
* This function deduces the type of the value and creates a successful Result.
|
||||
* @tparam T The type of the value.
|
||||
* @param value The value to be stored in the Result.
|
||||
* @return A Result object containing the value.
|
||||
*/
|
||||
template <typename T>
|
||||
fn Ok(T&& value) {
|
||||
return Result<std::decay_t<T>>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to create a successful Result<void>.
|
||||
*
|
||||
* This function creates a successful Result that does not contain a value.
|
||||
* @return A Result<void> object indicating success.
|
||||
*/
|
||||
inline fn Ok() -> Result<void> { return {}; }
|
126
src/util/types.h
126
src/util/types.h
|
@ -1,126 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @typedef u8
|
||||
* @brief Represents an 8-bit unsigned integer.
|
||||
*
|
||||
* This type alias is used for 8-bit unsigned integers, ranging from 0 to 255.
|
||||
* It is based on the std::uint8_t type.
|
||||
*/
|
||||
using u8 = std::uint8_t;
|
||||
|
||||
/**
|
||||
* @typedef u16
|
||||
* @brief Represents a 16-bit unsigned integer.
|
||||
*
|
||||
* This type alias is used for 16-bit unsigned integers, ranging from 0 to 65,535.
|
||||
* It is based on the std::uint16_t type.
|
||||
*/
|
||||
using u16 = std::uint16_t;
|
||||
|
||||
/**
|
||||
* @typedef u32
|
||||
* @brief Represents a 32-bit unsigned integer.
|
||||
*
|
||||
* This type alias is used for 32-bit unsigned integers, ranging from 0 to 4,294,967,295.
|
||||
* It is based on the std::uint32_t type.
|
||||
*/
|
||||
using u32 = std::uint32_t;
|
||||
|
||||
/**
|
||||
* @typedef u64
|
||||
* @brief Represents a 64-bit unsigned integer.
|
||||
*
|
||||
* This type alias is used for 64-bit unsigned integers, ranging from 0 to
|
||||
* 18,446,744,073,709,551,615. It is based on the std::uint64_t type.
|
||||
*/
|
||||
using u64 = std::uint64_t;
|
||||
|
||||
// Type Aliases for Signed Integers
|
||||
|
||||
/**
|
||||
* @typedef i8
|
||||
* @brief Represents an 8-bit signed integer.
|
||||
*
|
||||
* This type alias is used for 8-bit signed integers, ranging from -128 to 127.
|
||||
* It is based on the std::int8_t type.
|
||||
*/
|
||||
using i8 = std::int8_t;
|
||||
|
||||
/**
|
||||
* @typedef i16
|
||||
* @brief Represents a 16-bit signed integer.
|
||||
*
|
||||
* This type alias is used for 16-bit signed integers, ranging from -32,768 to 32,767.
|
||||
* It is based on the std::int16_t type.
|
||||
*/
|
||||
using i16 = std::int16_t;
|
||||
|
||||
/**
|
||||
* @typedef i32
|
||||
* @brief Represents a 32-bit signed integer.
|
||||
*
|
||||
* This type alias is used for 32-bit signed integers, ranging from -2,147,483,648 to 2,147,483,647.
|
||||
* It is based on the std::int32_t type.
|
||||
*/
|
||||
using i32 = std::int32_t;
|
||||
|
||||
/**
|
||||
* @typedef i64
|
||||
* @brief Represents a 64-bit signed integer.
|
||||
*
|
||||
* This type alias is used for 64-bit signed integers, ranging from -9,223,372,036,854,775,808 to
|
||||
* 9,223,372,036,854,775,807. It is based on the std::int64_t type.
|
||||
*/
|
||||
using i64 = std::int64_t;
|
||||
|
||||
// Type Aliases for Floating-Point Numbers
|
||||
|
||||
/**
|
||||
* @typedef f32
|
||||
* @brief Represents a 32-bit floating-point number.
|
||||
*
|
||||
* This type alias is used for 32-bit floating-point numbers, which follow the IEEE 754 standard.
|
||||
* It is based on the float type.
|
||||
*/
|
||||
using f32 = float;
|
||||
|
||||
/**
|
||||
* @typedef f64
|
||||
* @brief Represents a 64-bit floating-point number.
|
||||
*
|
||||
* This type alias is used for 64-bit floating-point numbers, which follow the IEEE 754 standard.
|
||||
* It is based on the double type.
|
||||
*/
|
||||
using f64 = double;
|
||||
|
||||
// Type Aliases for Size Types
|
||||
|
||||
/**
|
||||
* @typedef usize
|
||||
* @brief Represents an unsigned size type.
|
||||
*
|
||||
* This type alias is used for representing the size of objects in bytes.
|
||||
* It is based on the std::size_t type, which is the result type of the sizeof operator.
|
||||
*/
|
||||
using usize = std::size_t;
|
||||
|
||||
/**
|
||||
* @typedef isize
|
||||
* @brief Represents a signed size type.
|
||||
*
|
||||
* This type alias is used for representing pointer differences.
|
||||
* It is based on the std::ptrdiff_t type, which is the signed integer type returned when
|
||||
* subtracting two pointers.
|
||||
*/
|
||||
using isize = std::ptrdiff_t;
|
||||
|
||||
/**
|
||||
* @typedef string
|
||||
* @brief Represents a string.
|
||||
*/
|
||||
using string = std::string;
|
23
util.h
Normal file
23
util.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Unsigned integers
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
|
||||
// Signed integers
|
||||
using i8 = std::int8_t;
|
||||
using i16 = std::int16_t;
|
||||
using i32 = std::int32_t;
|
||||
using i64 = std::int64_t;
|
||||
|
||||
// Floating-points
|
||||
using f32 = float;
|
||||
using f64 = double;
|
||||
|
||||
// Size types
|
||||
using usize = std::size_t;
|
||||
using isize = std::ptrdiff_t;
|
12
vcpkg.json
Normal file
12
vcpkg.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name" : "draconispp",
|
||||
"version-string" : "1.0.0",
|
||||
"builtin-baseline" : "14b91796a68c87bc8d5cb35911b39287ccb7bd95",
|
||||
"dependencies" : [ {
|
||||
"name" : "fmt",
|
||||
"version>=" : "10.2.1#2"
|
||||
}, {
|
||||
"name" : "cppwinrt",
|
||||
"version>=" : "2.0.240111.5"
|
||||
} ]
|
||||
}
|
Loading…
Reference in a new issue