mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
common dependencies
This commit is contained in:
@@ -600,7 +600,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "projects-common", "projects
|
||||
src\modules\Projects\projects-common\AppUtils.h = src\modules\Projects\projects-common\AppUtils.h
|
||||
src\modules\Projects\projects-common\Data.h = src\modules\Projects\projects-common\Data.h
|
||||
src\modules\Projects\projects-common\GuidUtils.h = src\modules\Projects\projects-common\GuidUtils.h
|
||||
src\modules\Projects\projects-common\json.h = src\modules\Projects\projects-common\json.h
|
||||
src\modules\Projects\projects-common\MonitorEnumerator.h = src\modules\Projects\projects-common\MonitorEnumerator.h
|
||||
src\modules\Projects\projects-common\VirtualDesktop.h = src\modules\Projects\projects-common\VirtualDesktop.h
|
||||
src\modules\Projects\projects-common\WindowEnumerator.h = src\modules\Projects\projects-common\WindowEnumerator.h
|
||||
|
||||
@@ -6,50 +6,17 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../projects-common/AppUtils.h"
|
||||
#include "../projects-common/MonitorEnumerator.h"
|
||||
#include "../projects-common/WindowEnumerator.h"
|
||||
#include "../projects-common/WindowFilter.h"
|
||||
#include <projects-common/AppUtils.h>
|
||||
#include <projects-common/MonitorEnumerator.h>
|
||||
#include <projects-common/WindowEnumerator.h>
|
||||
#include <projects-common/WindowFilter.h>
|
||||
|
||||
#include <common/Display/dpi_aware.h>
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Management::Deployment;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
namespace Display
|
||||
{
|
||||
namespace DPIAware
|
||||
{
|
||||
enum AwarenessLevel
|
||||
{
|
||||
UNAWARE,
|
||||
SYSTEM_AWARE,
|
||||
PER_MONITOR_AWARE,
|
||||
PER_MONITOR_AWARE_V2,
|
||||
UNAWARE_GDISCALED
|
||||
};
|
||||
|
||||
AwarenessLevel GetAwarenessLevel(DPI_AWARENESS_CONTEXT system_returned_value)
|
||||
{
|
||||
const std::array levels{ DPI_AWARENESS_CONTEXT_UNAWARE,
|
||||
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE,
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE,
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,
|
||||
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED };
|
||||
for (size_t i = 0; i < size(levels); ++i)
|
||||
{
|
||||
if (AreDpiAwarenessContextsEqual(levels[i], system_returned_value))
|
||||
{
|
||||
return static_cast<DPIAware::AwarenessLevel>(i);
|
||||
}
|
||||
}
|
||||
return AwarenessLevel::UNAWARE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace FancyZones
|
||||
{
|
||||
inline bool allMonitorsHaveSameDpiScaling()
|
||||
@@ -114,8 +81,8 @@ namespace FancyZones
|
||||
rect.top -= yOffset;
|
||||
rect.bottom -= yOffset;
|
||||
|
||||
const auto level = Common::Display::DPIAware::GetAwarenessLevel(GetWindowDpiAwarenessContext(window));
|
||||
const bool accountForUnawareness = level < Common::Display::DPIAware::PER_MONITOR_AWARE;
|
||||
const auto level = DPIAware::GetAwarenessLevel(GetWindowDpiAwarenessContext(window));
|
||||
const bool accountForUnawareness = level < DPIAware::PER_MONITOR_AWARE;
|
||||
|
||||
if (accountForUnawareness && !allMonitorsHaveSameDpiScaling())
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../projects-common/Data.h"
|
||||
#include <projects-common/Data.h>
|
||||
|
||||
bool Launch(const Project::Application& app);
|
||||
void Launch(const Project& project);
|
||||
@@ -137,6 +137,9 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\Display\Display.vcxproj">
|
||||
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../projects-common/Data.h"
|
||||
#include <projects-common/Data.h>
|
||||
|
||||
#include "AppLauncher.h"
|
||||
#include <AppLauncher.h>
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow)
|
||||
{
|
||||
|
||||
@@ -3,49 +3,10 @@
|
||||
|
||||
#include <ShellScalingApi.h>
|
||||
|
||||
#include "../projects-common/MonitorEnumerator.h"
|
||||
#include "OnThreadExecutor.h"
|
||||
#include <projects-common/MonitorEnumerator.h>
|
||||
#include <OnThreadExecutor.h>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
namespace Display
|
||||
{
|
||||
namespace DPIAware
|
||||
{
|
||||
constexpr inline int DEFAULT_DPI = 96;
|
||||
|
||||
void Convert(HMONITOR monitor_handle, float& width, float& height)
|
||||
{
|
||||
if (monitor_handle == NULL)
|
||||
{
|
||||
const POINT ptZero = { 0, 0 };
|
||||
monitor_handle = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
UINT dpi_x, dpi_y;
|
||||
if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK)
|
||||
{
|
||||
width = width * dpi_x / DEFAULT_DPI;
|
||||
height = height * dpi_y / DEFAULT_DPI;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT GetScreenDPIForMonitor(HMONITOR targetMonitor, UINT& dpi)
|
||||
{
|
||||
if (targetMonitor != nullptr)
|
||||
{
|
||||
UINT dummy = 0;
|
||||
return GetDpiForMonitor(targetMonitor, MDT_EFFECTIVE_DPI, &dpi, &dummy);
|
||||
}
|
||||
else
|
||||
{
|
||||
dpi = DPIAware::DEFAULT_DPI;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#include <common/Display/dpi_aware.h>
|
||||
|
||||
namespace MonitorUtils
|
||||
{
|
||||
@@ -93,7 +54,7 @@ namespace MonitorUtils
|
||||
float dpiUnawareHeight = static_cast<float>(dpiUnawareMonitorInfo.rcMonitor.bottom - dpiUnawareMonitorInfo.rcMonitor.top);
|
||||
|
||||
UINT dpi = 0;
|
||||
if (Common::Display::DPIAware::GetScreenDPIForMonitor(monitorData.first, dpi) != S_OK)
|
||||
if (DPIAware::GetScreenDPIForMonitor(monitorData.first, dpi) != S_OK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../projects-common/Data.h"
|
||||
#include <projects-common/Data.h>
|
||||
|
||||
// FancyZones: MonitorUtils.h
|
||||
namespace MonitorUtils
|
||||
|
||||
@@ -139,6 +139,9 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\Display\Display.vcxproj">
|
||||
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#include "../projects-common/AppUtils.h"
|
||||
#include "../projects-common/Data.h"
|
||||
#include "../projects-common/GuidUtils.h"
|
||||
#include "../projects-common/WindowEnumerator.h"
|
||||
#include "../projects-common/WindowFilter.h"
|
||||
#include <projects-common/AppUtils.h>
|
||||
#include <projects-common/Data.h>
|
||||
#include <projects-common/GuidUtils.h>
|
||||
#include <projects-common/WindowEnumerator.h>
|
||||
#include <projects-common/WindowFilter.h>
|
||||
|
||||
#include "MonitorUtils.h"
|
||||
#include <MonitorUtils.h>
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow)
|
||||
{
|
||||
@@ -99,7 +99,7 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmd
|
||||
}
|
||||
|
||||
// filter by app path
|
||||
std::wstring processPath = Common::Utils::ProcessPath::get_process_path_waiting_uwp(window);
|
||||
std::wstring processPath = get_process_path_waiting_uwp(window);
|
||||
if (processPath.empty() || WindowUtils::IsExcludedByDefault(window, processPath, title))
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "../projects-common/WindowUtils.h"
|
||||
#include <common/utils/process_path.h>
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
@@ -174,7 +174,7 @@ namespace Utils
|
||||
|
||||
inline std::optional<AppData> GetApp(HWND window, const AppList& apps)
|
||||
{
|
||||
std::wstring processPath = Common::Utils::ProcessPath::get_process_path_waiting_uwp(window);
|
||||
std::wstring processPath = get_process_path_waiting_uwp(window);
|
||||
return Utils::Apps::GetApp(processPath, apps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#include <optional>
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "json.h"
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/utils/json.h>
|
||||
|
||||
struct Project
|
||||
{
|
||||
|
||||
@@ -5,202 +5,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
namespace Display
|
||||
{
|
||||
namespace DPIAware
|
||||
{
|
||||
constexpr inline int DEFAULT_DPI = 96;
|
||||
|
||||
inline void InverseConvert(HMONITOR monitor_handle, float& width, float& height)
|
||||
{
|
||||
if (monitor_handle == NULL)
|
||||
{
|
||||
const POINT ptZero = { 0, 0 };
|
||||
monitor_handle = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
UINT dpi_x, dpi_y;
|
||||
if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK)
|
||||
{
|
||||
width = width * DPIAware::DEFAULT_DPI / dpi_x;
|
||||
height = height * DPIAware::DEFAULT_DPI / dpi_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
namespace ProcessPath
|
||||
{
|
||||
// Get the executable path or module name for modern apps
|
||||
inline std::wstring get_process_path(DWORD pid) noexcept
|
||||
{
|
||||
auto process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, TRUE, pid);
|
||||
std::wstring name;
|
||||
if (process != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
name.resize(MAX_PATH);
|
||||
DWORD name_length = static_cast<DWORD>(name.length());
|
||||
if (QueryFullProcessImageNameW(process, 0, name.data(), &name_length) == 0)
|
||||
{
|
||||
name_length = 0;
|
||||
}
|
||||
name.resize(name_length);
|
||||
CloseHandle(process);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// Get the executable path or module name for modern apps
|
||||
inline std::wstring get_process_path(HWND window) noexcept
|
||||
{
|
||||
const static std::wstring app_frame_host = L"ApplicationFrameHost.exe";
|
||||
|
||||
DWORD pid{};
|
||||
GetWindowThreadProcessId(window, &pid);
|
||||
auto name = get_process_path(pid);
|
||||
|
||||
if (name.length() >= app_frame_host.length() &&
|
||||
name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0)
|
||||
{
|
||||
// It is a UWP app. We will enumerate the windows and look for one created
|
||||
// by something with a different PID
|
||||
DWORD new_pid = pid;
|
||||
|
||||
EnumChildWindows(
|
||||
window, [](HWND hwnd, LPARAM param) -> BOOL {
|
||||
auto new_pid_ptr = reinterpret_cast<DWORD*>(param);
|
||||
DWORD pid;
|
||||
GetWindowThreadProcessId(hwnd, &pid);
|
||||
if (pid != *new_pid_ptr)
|
||||
{
|
||||
*new_pid_ptr = pid;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
},
|
||||
reinterpret_cast<LPARAM>(&new_pid));
|
||||
|
||||
// If we have a new pid, get the new name.
|
||||
if (new_pid != pid)
|
||||
{
|
||||
return get_process_path(new_pid);
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline std::wstring get_process_path_waiting_uwp(HWND window)
|
||||
{
|
||||
const static std::wstring appFrameHost = L"ApplicationFrameHost.exe";
|
||||
|
||||
int attempt = 0;
|
||||
auto processPath = get_process_path(window);
|
||||
|
||||
while (++attempt < 30 && processPath.length() >= appFrameHost.length() &&
|
||||
processPath.compare(processPath.length() - appFrameHost.length(), appFrameHost.length(), appFrameHost) == 0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
processPath = get_process_path(window);
|
||||
}
|
||||
|
||||
return processPath;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ExcludedApps
|
||||
{
|
||||
inline bool find_folder_in_path(const std::wstring& where, const std::vector<std::wstring>& what)
|
||||
{
|
||||
for (const auto& row : what)
|
||||
{
|
||||
const auto pos = where.rfind(row);
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks if a process path is included in a list of strings.
|
||||
inline bool find_app_name_in_path(const std::wstring& where, const std::vector<std::wstring>& what)
|
||||
{
|
||||
for (const auto& row : what)
|
||||
{
|
||||
const auto pos = where.rfind(row);
|
||||
const auto last_slash = where.rfind('\\');
|
||||
//Check that row occurs in where, and its last occurrence contains in itself the first character after the last backslash.
|
||||
if (pos != std::wstring::npos && pos <= last_slash + 1 && pos + row.length() > last_slash)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool check_excluded_app_with_title(const std::vector<std::wstring>& excludedApps, std::wstring title)
|
||||
{
|
||||
CharUpperBuffW(title.data(), static_cast<DWORD>(title.length()));
|
||||
|
||||
for (const auto& app : excludedApps)
|
||||
{
|
||||
if (title.contains(app))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool check_excluded_app(const std::wstring& processPath, const std::wstring& title, const std::vector<std::wstring>& excludedApps)
|
||||
{
|
||||
bool res = find_app_name_in_path(processPath, excludedApps);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
res = check_excluded_app_with_title(excludedApps, title);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Window
|
||||
{
|
||||
// Check if window is part of the shell or the taskbar.
|
||||
inline bool is_system_window(HWND hwnd, const char* class_name)
|
||||
{
|
||||
// We compare the HWND against HWND of the desktop and shell windows,
|
||||
// we also filter out some window class names know to belong to the taskbar.
|
||||
constexpr std::array system_classes = { "SysListView32", "WorkerW", "Shell_TrayWnd", "Shell_SecondaryTrayWnd", "Progman" };
|
||||
const std::array system_hwnds = { GetDesktopWindow(), GetShellWindow() };
|
||||
for (auto system_hwnd : system_hwnds)
|
||||
{
|
||||
if (hwnd == system_hwnd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const auto system_class : system_classes)
|
||||
{
|
||||
if (!strcmp(system_class, class_name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#include <common/Display/dpi_aware.h>
|
||||
#include <common/utils/excluded_apps.h>
|
||||
#include <common/utils/window.h>
|
||||
|
||||
// FancyZones WindowUtils
|
||||
namespace WindowUtils
|
||||
@@ -247,14 +54,14 @@ namespace WindowUtils
|
||||
CharUpperBuffW(processPathUpper.data(), static_cast<DWORD>(processPathUpper.length()));
|
||||
|
||||
static std::vector<std::wstring> defaultExcludedFolders = { NonLocalizable::SystemAppsFolder, NonLocalizable::System, NonLocalizable::System32, NonLocalizable::SystemWOW64 };
|
||||
if (Common::Utils::ExcludedApps::find_folder_in_path(processPathUpper, defaultExcludedFolders))
|
||||
if (find_folder_in_path(processPathUpper, defaultExcludedFolders))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::array<char, 256> className;
|
||||
GetClassNameA(window, className.data(), static_cast<int>(className.size()));
|
||||
if (Common::Utils::Window::is_system_window(window, className.data()))
|
||||
if (is_system_window(window, className.data()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -265,7 +72,7 @@ namespace WindowUtils
|
||||
}
|
||||
|
||||
static std::vector<std::wstring> defaultExcludedApps = { NonLocalizable::CoreWindow, NonLocalizable::SearchUI, NonLocalizable::ProjectsEditor, NonLocalizable::ProjectsLauncher, NonLocalizable::ProjectsSnapshotTool };
|
||||
return (Common::Utils::ExcludedApps::check_excluded_app(processPathUpper, title, defaultExcludedApps));
|
||||
return (check_excluded_app(window, processPathUpper, defaultExcludedApps));
|
||||
}
|
||||
|
||||
inline RECT GetWindowRect(HWND window)
|
||||
@@ -278,8 +85,8 @@ namespace WindowUtils
|
||||
float originX = static_cast<float>(rect.left);
|
||||
float originY = static_cast<float>(rect.top);
|
||||
|
||||
Common::Display::DPIAware::InverseConvert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), width, height);
|
||||
Common::Display::DPIAware::InverseConvert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), originX, originY);
|
||||
DPIAware::InverseConvert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), width, height);
|
||||
DPIAware::InverseConvert(MonitorFromWindow(window, MONITOR_DEFAULTTONULL), originX, originY);
|
||||
|
||||
return RECT(static_cast<LONG>(std::roundf(originX)),
|
||||
static_cast<LONG>(std::roundf(originY)),
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Data.Json.h>
|
||||
|
||||
#include <optional>
|
||||
#include <fstream>
|
||||
|
||||
// common/utils/json.h
|
||||
namespace json
|
||||
{
|
||||
using namespace winrt::Windows::Data::Json;
|
||||
|
||||
inline std::optional<JsonObject> from_file(std::wstring_view file_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ifstream file(file_name.data(), std::ios::binary);
|
||||
if (file.is_open())
|
||||
{
|
||||
using isbi = std::istreambuf_iterator<char>;
|
||||
std::string obj_str{ isbi{ file }, isbi{} };
|
||||
return JsonValue::Parse(winrt::to_hstring(obj_str)).GetObjectW();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_file(std::wstring_view file_name, const JsonObject& obj)
|
||||
{
|
||||
std::wstring obj_str{ obj.Stringify().c_str() };
|
||||
std::ofstream{ file_name.data(), std::ios::binary } << winrt::to_string(obj_str);
|
||||
}
|
||||
|
||||
inline bool has(
|
||||
const json::JsonObject& o,
|
||||
std::wstring_view name,
|
||||
const json::JsonValueType type = JsonValueType::Object)
|
||||
{
|
||||
return o.HasKey(name) && o.GetNamedValue(name).ValueType() == type;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::enable_if_t<std::is_arithmetic_v<T>, JsonValue> value(const T arithmetic)
|
||||
{
|
||||
return json::JsonValue::CreateNumberValue(arithmetic);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::enable_if_t<!std::is_arithmetic_v<T>, JsonValue> value(T s)
|
||||
{
|
||||
return json::JsonValue::CreateStringValue(s);
|
||||
}
|
||||
|
||||
inline JsonValue value(const bool boolean)
|
||||
{
|
||||
return json::JsonValue::CreateBooleanValue(boolean);
|
||||
}
|
||||
|
||||
inline JsonValue value(JsonObject value)
|
||||
{
|
||||
return value.as<JsonValue>();
|
||||
}
|
||||
|
||||
inline JsonValue value(JsonValue value)
|
||||
{
|
||||
return value; // identity function overload for convenience
|
||||
}
|
||||
|
||||
template<typename T, typename D = std::optional<T>>
|
||||
requires std::constructible_from<std::optional<T>, D>
|
||||
void get(const json::JsonObject& o, const wchar_t* name, T& destination, D default_value = std::nullopt)
|
||||
{
|
||||
try
|
||||
{
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
{
|
||||
destination = o.GetNamedBoolean(name);
|
||||
}
|
||||
else if constexpr (std::is_arithmetic_v<T>)
|
||||
{
|
||||
destination = static_cast<T>(o.GetNamedNumber(name));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::wstring>)
|
||||
{
|
||||
destination = o.GetNamedString(name);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, json::JsonObject>)
|
||||
{
|
||||
destination = o.GetNamedObject(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::bool_constant<std::is_same_v<T, T&>>::value, "Unsupported type");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::optional<T> maybe_default{ std::move(default_value) };
|
||||
if (maybe_default.has_value())
|
||||
destination = std::move(*maybe_default);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user