Use WinRT JSON parser instead of custom cpprestsdk solution (#822)

This commit is contained in:
yuyoyuppe 2019-12-06 11:40:23 +03:00 committed by GitHub
parent e714cb9e8b
commit 7357e40d3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 488 additions and 15702 deletions

View File

@ -40,10 +40,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fancyzones", "src\modules\f
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests-FancyZones", "src\modules\fancyzones\tests\UnitTests\UnitTests.vcxproj", "{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk", "deps\cpprestsdk\cpprestsdk.vcxproj", "{4E577735-DFAB-41AF-8A6E-B6E8872A2928}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deps", "deps", "{1FAF749F-0D6F-4BF5-A563-31A4B5279D27}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{1AFB6476-670D-4E80-A464-657E01DFF482}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests-CommonLib", "src\common\UnitTests-CommonLib\UnitTests-CommonLib.vcxproj", "{1A066C63-64B3-45F8-92FE-664E1CCE8077}"
@ -114,10 +110,6 @@ Global
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.Build.0 = Debug|x64
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.ActiveCfg = Release|x64
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.Build.0 = Release|x64
{4E577735-DFAB-41AF-8A6E-B6E8872A2928}.Debug|x64.ActiveCfg = Debug|x64
{4E577735-DFAB-41AF-8A6E-B6E8872A2928}.Debug|x64.Build.0 = Debug|x64
{4E577735-DFAB-41AF-8A6E-B6E8872A2928}.Release|x64.ActiveCfg = Release|x64
{4E577735-DFAB-41AF-8A6E-B6E8872A2928}.Release|x64.Build.0 = Release|x64
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.ActiveCfg = Debug|x64
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.Build.0 = Debug|x64
{1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.ActiveCfg = Release|x64
@ -159,7 +151,6 @@ Global
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{48804216-2A0E-4168-A6D8-9CD068D14227} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{4E577735-DFAB-41AF-8A6E-B6E8872A2928} = {1FAF749F-0D6F-4BF5-A563-31A4B5279D27}
{1A066C63-64B3-45F8-92FE-664E1CCE8077} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}

View File

@ -1,12 +0,0 @@
# C++ Rest SDK - JSON library
This JSON library is taken from the C++ REST SDK in https://github.com/microsoft/cpprestsdk
Based in the [v2.10.13 release](https://github.com/microsoft/cpprestsdk/tree/v2.10.13/Release), it consists of the needed files to build and use the JSON classes described in `include/cpprest/json.h`.
Changes made to the files in order to build in the PowerToys project:
- Removal of `#include` references to files that are not needed.
- `#include "pch.h"` instead of `#include "stdafx.h"` to use the PowerToys pre-compiled header.
- `#define _NO_ASYNCRTIMP` in [`include/cpprest/details/cpprest_compat.h`](./include/cpprest/details/cpprest_compat.h) since this class will be statically linked.
The contents of the C++ Rest SDK license are included in [license.txt](./license.txt).

View File

@ -1,121 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{4E577735-DFAB-41AF-8A6E-B6E8872A2928}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>common</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>cpprestsdk</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="include\cpprest\asyncrt_utils.h" />
<ClInclude Include="include\cpprest\base_uri.h" />
<ClInclude Include="include\cpprest\details\basic_types.h" />
<ClInclude Include="include\cpprest\details\cpprest_compat.h" />
<ClInclude Include="include\cpprest\details\SafeInt3.hpp" />
<ClInclude Include="include\cpprest\details\web_utilities.h" />
<ClInclude Include="include\cpprest\json.h" />
<ClInclude Include="include\cpprest\uri.h" />
<ClInclude Include="include\cpprest\uri_builder.h" />
<ClInclude Include="include\cpprest\version.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\json\json.cpp" />
<ClCompile Include="src\json\json_parsing.cpp" />
<ClCompile Include="src\json\json_serialization.cpp" />
<ClCompile Include="src\utilities\asyncrt_utils.cpp" />
<ClCompile Include="src\utilities\base64.cpp" />
<ClCompile Include="src\utilities\web_utilities.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,697 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Various common utilities.
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include "cpprest/details/basic_types.h"
//#include "pplx/pplxtasks.h"
#include <chrono>
#include <cstdint>
#include <limits.h>
#include <locale.h>
#include <random>
#include <string>
#include <system_error>
#include <vector>
#ifndef _WIN32
#include <sys/time.h>
#if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269
/* Systems using glibc: xlocale.h has been removed from glibc 2.26
The above include of locale.h is sufficient
Further details: https://sourceware.org/git/?p=glibc.git;a=commit;h=f0be25b6336db7492e47d2e8e72eb8af53b5506d */
#include <xlocale.h>
#endif
#endif
/// Various utilities for string conversions and date and time manipulation.
namespace utility
{
// Left over from VS2010 support, remains to avoid breaking.
typedef std::chrono::seconds seconds;
/// Functions for converting to/from std::chrono::seconds to xml string.
namespace timespan
{
/// <summary>
/// Converts a timespan/interval in seconds to xml duration string as specified by
/// http://www.w3.org/TR/xmlschema-2/#duration
/// </summary>
_ASYNCRTIMP utility::string_t __cdecl seconds_to_xml_duration(utility::seconds numSecs);
/// <summary>
/// Converts an xml duration to timespan/interval in seconds
/// http://www.w3.org/TR/xmlschema-2/#duration
/// </summary>
_ASYNCRTIMP utility::seconds __cdecl xml_duration_to_seconds(const utility::string_t& timespanString);
} // namespace timespan
/// Functions for Unicode string conversions.
namespace conversions
{
/// <summary>
/// Converts a UTF-16 string to a UTF-8 string.
/// </summary>
/// <param name="w">A two byte character UTF-16 string.</param>
/// <returns>A single byte character UTF-8 string.</returns>
_ASYNCRTIMP std::string __cdecl utf16_to_utf8(const utf16string& w);
/// <summary>
/// Converts a UTF-8 string to a UTF-16
/// </summary>
/// <param name="s">A single byte character UTF-8 string.</param>
/// <returns>A two byte character UTF-16 string.</returns>
_ASYNCRTIMP utf16string __cdecl utf8_to_utf16(const std::string& s);
/// <summary>
/// Converts a ASCII (us-ascii) string to a UTF-16 string.
/// </summary>
/// <param name="s">A single byte character us-ascii string.</param>
/// <returns>A two byte character UTF-16 string.</returns>
_ASYNCRTIMP utf16string __cdecl usascii_to_utf16(const std::string& s);
/// <summary>
/// Converts a Latin1 (iso-8859-1) string to a UTF-16 string.
/// </summary>
/// <param name="s">A single byte character UTF-8 string.</param>
/// <returns>A two byte character UTF-16 string.</returns>
_ASYNCRTIMP utf16string __cdecl latin1_to_utf16(const std::string& s);
/// <summary>
/// Converts a Latin1 (iso-8859-1) string to a UTF-8 string.
/// </summary>
/// <param name="s">A single byte character UTF-8 string.</param>
/// <returns>A single byte character UTF-8 string.</returns>
_ASYNCRTIMP utf8string __cdecl latin1_to_utf8(const std::string& s);
/// <summary>
/// Converts to a platform dependent Unicode string type.
/// </summary>
/// <param name="s">A single byte character UTF-8 string.</param>
/// <returns>A platform dependent string type.</returns>
#ifdef _UTF16_STRINGS
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string&& s);
#else
inline utility::string_t&& to_string_t(std::string&& s) { return std::move(s); }
#endif
/// <summary>
/// Converts to a platform dependent Unicode string type.
/// </summary>
/// <param name="s">A two byte character UTF-16 string.</param>
/// <returns>A platform dependent string type.</returns>
#ifdef _UTF16_STRINGS
inline utility::string_t&& to_string_t(utf16string&& s) { return std::move(s); }
#else
_ASYNCRTIMP utility::string_t __cdecl to_string_t(utf16string&& s);
#endif
/// <summary>
/// Converts to a platform dependent Unicode string type.
/// </summary>
/// <param name="s">A single byte character UTF-8 string.</param>
/// <returns>A platform dependent string type.</returns>
#ifdef _UTF16_STRINGS
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const std::string& s);
#else
inline const utility::string_t& to_string_t(const std::string& s) { return s; }
#endif
/// <summary>
/// Converts to a platform dependent Unicode string type.
/// </summary>
/// <param name="s">A two byte character UTF-16 string.</param>
/// <returns>A platform dependent string type.</returns>
#ifdef _UTF16_STRINGS
inline const utility::string_t& to_string_t(const utf16string& s) { return s; }
#else
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const utf16string& s);
#endif
/// <summary>
/// Converts to a UTF-16 from string.
/// </summary>
/// <param name="value">A single byte character UTF-8 string.</param>
/// <returns>A two byte character UTF-16 string.</returns>
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string& value);
/// <summary>
/// Converts to a UTF-16 from string.
/// </summary>
/// <param name="value">A two byte character UTF-16 string.</param>
/// <returns>A two byte character UTF-16 string.</returns>
inline const utf16string& to_utf16string(const utf16string& value) { return value; }
/// <summary>
/// Converts to a UTF-16 from string.
/// </summary>
/// <param name="value">A two byte character UTF-16 string.</param>
/// <returns>A two byte character UTF-16 string.</returns>
inline utf16string&& to_utf16string(utf16string&& value) { return std::move(value); }
/// <summary>
/// Converts to a UTF-8 string.
/// </summary>
/// <param name="value">A single byte character UTF-8 string.</param>
/// <returns>A single byte character UTF-8 string.</returns>
inline std::string&& to_utf8string(std::string&& value) { return std::move(value); }
/// <summary>
/// Converts to a UTF-8 string.
/// </summary>
/// <param name="value">A single byte character UTF-8 string.</param>
/// <returns>A single byte character UTF-8 string.</returns>
inline const std::string& to_utf8string(const std::string& value) { return value; }
/// <summary>
/// Converts to a UTF-8 string.
/// </summary>
/// <param name="value">A two byte character UTF-16 string.</param>
/// <returns>A single byte character UTF-8 string.</returns>
_ASYNCRTIMP std::string __cdecl to_utf8string(const utf16string& value);
/// <summary>
/// Encode the given byte array into a base64 string
/// </summary>
_ASYNCRTIMP utility::string_t __cdecl to_base64(const std::vector<unsigned char>& data);
/// <summary>
/// Encode the given 8-byte integer into a base64 string
/// </summary>
_ASYNCRTIMP utility::string_t __cdecl to_base64(uint64_t data);
/// <summary>
/// Decode the given base64 string to a byte array
/// </summary>
_ASYNCRTIMP std::vector<unsigned char> __cdecl from_base64(const utility::string_t& str);
template<typename Source>
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
"locale support is required.")
utility::string_t print_string(const Source& val, const std::locale& loc = std::locale())
{
utility::ostringstream_t oss;
oss.imbue(loc);
oss << val;
if (oss.bad())
{
throw std::bad_cast();
}
return oss.str();
}
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
"locale support is required.")
inline utility::string_t print_string(const utility::string_t& val) { return val; }
namespace details
{
#if defined(__ANDROID__)
template<class T>
inline std::string to_string(const T t)
{
std::ostringstream os;
os.imbue(std::locale::classic());
os << t;
return os.str();
}
#endif
template<class T>
inline utility::string_t to_string_t(const T t)
{
#ifdef _UTF16_STRINGS
using std::to_wstring;
return to_wstring(t);
#else
#if !defined(__ANDROID__)
using std::to_string;
#endif
return to_string(t);
#endif
}
template<typename Source>
utility::string_t print_string(const Source& val)
{
utility::ostringstream_t oss;
oss.imbue(std::locale::classic());
oss << val;
if (oss.bad())
{
throw std::bad_cast();
}
return oss.str();
}
inline const utility::string_t& print_string(const utility::string_t& val) { return val; }
template<typename Source>
utf8string print_utf8string(const Source& val)
{
return conversions::to_utf8string(print_string(val));
}
inline const utf8string& print_utf8string(const utf8string& val) { return val; }
template<typename Target>
Target scan_string(const utility::string_t& str)
{
Target t;
utility::istringstream_t iss(str);
iss.imbue(std::locale::classic());
iss >> t;
if (iss.bad())
{
throw std::bad_cast();
}
return t;
}
inline const utility::string_t& scan_string(const utility::string_t& str) { return str; }
} // namespace details
template<typename Target>
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
"locale support is required.")
Target scan_string(const utility::string_t& str, const std::locale& loc = std::locale())
{
Target t;
utility::istringstream_t iss(str);
iss.imbue(loc);
iss >> t;
if (iss.bad())
{
throw std::bad_cast();
}
return t;
}
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
"locale support is required.")
inline utility::string_t scan_string(const utility::string_t& str) { return str; }
} // namespace conversions
namespace details
{
/// <summary>
/// Cross platform RAII container for setting thread local locale.
/// </summary>
class scoped_c_thread_locale
{
public:
_ASYNCRTIMP scoped_c_thread_locale();
_ASYNCRTIMP ~scoped_c_thread_locale();
#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
#ifdef _WIN32
typedef _locale_t xplat_locale;
#else
typedef locale_t xplat_locale;
#endif
static _ASYNCRTIMP xplat_locale __cdecl c_locale();
#endif
private:
#ifdef _WIN32
std::string m_prevLocale;
int m_prevThreadSetting;
#elif !(defined(ANDROID) || defined(__ANDROID__))
locale_t m_prevLocale;
#endif
scoped_c_thread_locale(const scoped_c_thread_locale&);
scoped_c_thread_locale& operator=(const scoped_c_thread_locale&);
};
/// <summary>
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
/// taking global lock for performance reasons.
/// </summary>
inline bool __cdecl is_alnum(const unsigned char uch) CPPREST_NOEXCEPT
{ // test if uch is an alnum character
// special casing char to avoid branches
// clang-format off
static CPPREST_CONSTEXPR bool is_alnum_table[UCHAR_MAX + 1] = {
/* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */
/* 0X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 1X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 2X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0-9 */
/* 4X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A-Z */
/* 5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
/* 6X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a-z */
/* 7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
/* non-ASCII values initialized to 0 */
};
// clang-format on
return (is_alnum_table[uch]);
}
/// <summary>
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
/// taking global lock for performance reasons.
/// </summary>
inline bool __cdecl is_alnum(const char ch) CPPREST_NOEXCEPT { return (is_alnum(static_cast<unsigned char>(ch))); }
/// <summary>
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
/// taking global lock for performance reasons.
/// </summary>
template<class Elem>
inline bool __cdecl is_alnum(Elem ch) CPPREST_NOEXCEPT
{
// assumes 'x' == L'x' for the ASCII range
typedef typename std::make_unsigned<Elem>::type UElem;
const auto uch = static_cast<UElem>(ch);
return (uch <= static_cast<UElem>('z') && is_alnum(static_cast<unsigned char>(uch)));
}
/// <summary>
/// Simplistic implementation of make_unique. A better implementation would be based on variadic templates
/// and therefore not be compatible with Dev10.
/// </summary>
template<typename _Type>
std::unique_ptr<_Type> make_unique()
{
return std::unique_ptr<_Type>(new _Type());
}
template<typename _Type, typename _Arg1>
std::unique_ptr<_Type> make_unique(_Arg1&& arg1)
{
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1)));
}
template<typename _Type, typename _Arg1, typename _Arg2>
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2)
{
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2)));
}
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3>
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3)
{
return std::unique_ptr<_Type>(
new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3)));
}
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4>
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4)
{
return std::unique_ptr<_Type>(new _Type(
std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3), std::forward<_Arg4>(arg4)));
}
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4, typename _Arg5>
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4, _Arg5&& arg5)
{
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1),
std::forward<_Arg2>(arg2),
std::forward<_Arg3>(arg3),
std::forward<_Arg4>(arg4),
std::forward<_Arg5>(arg5)));
}
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4, typename _Arg5, typename _Arg6>
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4, _Arg5&& arg5, _Arg6&& arg6)
{
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1),
std::forward<_Arg2>(arg2),
std::forward<_Arg3>(arg3),
std::forward<_Arg4>(arg4),
std::forward<_Arg5>(arg5),
std::forward<_Arg6>(arg6)));
}
/// <summary>
/// Cross platform utility function for performing case insensitive string equality comparison.
/// </summary>
/// <param name="left">First string to compare.</param>
/// <param name="right">Second strong to compare.</param>
/// <returns>true if the strings are equivalent, false otherwise</returns>
_ASYNCRTIMP bool __cdecl str_iequal(const std::string& left, const std::string& right) CPPREST_NOEXCEPT;
/// <summary>
/// Cross platform utility function for performing case insensitive string equality comparison.
/// </summary>
/// <param name="left">First string to compare.</param>
/// <param name="right">Second strong to compare.</param>
/// <returns>true if the strings are equivalent, false otherwise</returns>
_ASYNCRTIMP bool __cdecl str_iequal(const std::wstring& left, const std::wstring& right) CPPREST_NOEXCEPT;
/// <summary>
/// Cross platform utility function for performing case insensitive string less-than comparison.
/// </summary>
/// <param name="left">First string to compare.</param>
/// <param name="right">Second strong to compare.</param>
/// <returns>true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise,
/// false.</returns>
_ASYNCRTIMP bool __cdecl str_iless(const std::string& left, const std::string& right) CPPREST_NOEXCEPT;
/// <summary>
/// Cross platform utility function for performing case insensitive string less-than comparison.
/// </summary>
/// <param name="left">First string to compare.</param>
/// <param name="right">Second strong to compare.</param>
/// <returns>true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise,
/// false.</returns>
_ASYNCRTIMP bool __cdecl str_iless(const std::wstring& left, const std::wstring& right) CPPREST_NOEXCEPT;
/// <summary>
/// Convert a string to lowercase in place.
/// </summary>
/// <param name="target">The string to convert to lowercase.</param>
_ASYNCRTIMP void __cdecl inplace_tolower(std::string& target) CPPREST_NOEXCEPT;
/// <summary>
/// Convert a string to lowercase in place.
/// </summary>
/// <param name="target">The string to convert to lowercase.</param>
_ASYNCRTIMP void __cdecl inplace_tolower(std::wstring& target) CPPREST_NOEXCEPT;
#ifdef _WIN32
/// <summary>
/// Category error type for Windows OS errors.
/// </summary>
class windows_category_impl : public std::error_category
{
public:
virtual const char* name() const CPPREST_NOEXCEPT { return "windows"; }
virtual std::string message(int errorCode) const CPPREST_NOEXCEPT;
virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT;
};
/// <summary>
/// Gets the one global instance of the windows error category.
/// </summary>
/// </returns>An error category instance.</returns>
_ASYNCRTIMP const std::error_category& __cdecl windows_category();
#else
/// <summary>
/// Gets the one global instance of the linux error category.
/// </summary>
/// </returns>An error category instance.</returns>
_ASYNCRTIMP const std::error_category& __cdecl linux_category();
#endif
/// <summary>
/// Gets the one global instance of the current platform's error category.
/// </summary>
_ASYNCRTIMP const std::error_category& __cdecl platform_category();
/// <summary>
/// Creates an instance of std::system_error from a OS error code.
/// </summary>
inline std::system_error __cdecl create_system_error(unsigned long errorCode)
{
std::error_code code((int)errorCode, platform_category());
return std::system_error(code, code.message());
}
/// <summary>
/// Creates a std::error_code from a OS error code.
/// </summary>
inline std::error_code __cdecl create_error_code(unsigned long errorCode)
{
return std::error_code((int)errorCode, platform_category());
}
/// <summary>
/// Creates the corresponding error message from a OS error code.
/// </summary>
inline utility::string_t __cdecl create_error_message(unsigned long errorCode)
{
return utility::conversions::to_string_t(create_error_code(errorCode).message());
}
} // namespace details
class datetime
{
public:
typedef uint64_t interval_type;
/// <summary>
/// Defines the supported date and time string formats.
/// </summary>
enum date_format
{
RFC_1123,
ISO_8601
};
/// <summary>
/// Returns the current UTC time.
/// </summary>
static _ASYNCRTIMP datetime __cdecl utc_now();
/// <summary>
/// An invalid UTC timestamp value.
/// </summary>
enum : interval_type
{
utc_timestamp_invalid = static_cast<interval_type>(-1)
};
/// <summary>
/// Returns seconds since Unix/POSIX time epoch at 01-01-1970 00:00:00.
/// If time is before epoch, utc_timestamp_invalid is returned.
/// </summary>
static interval_type utc_timestamp()
{
const auto seconds = utc_now().to_interval() / _secondTicks;
if (seconds >= 11644473600LL)
{
return seconds - 11644473600LL;
}
else
{
return utc_timestamp_invalid;
}
}
datetime() : m_interval(0) {}
/// <summary>
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 format.
/// </summary>
/// <returns>Returns a <c>datetime</c> of zero if not successful.</returns>
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123);
/// <summary>
/// Returns a string representation of the <c>datetime</c>.
/// </summary>
_ASYNCRTIMP utility::string_t to_string(date_format format = RFC_1123) const;
/// <summary>
/// Returns the integral time value.
/// </summary>
interval_type to_interval() const { return m_interval; }
datetime operator-(interval_type value) const { return datetime(m_interval - value); }
datetime operator+(interval_type value) const { return datetime(m_interval + value); }
bool operator==(datetime dt) const { return m_interval == dt.m_interval; }
bool operator!=(const datetime& dt) const { return !(*this == dt); }
static interval_type from_milliseconds(unsigned int milliseconds) { return milliseconds * _msTicks; }
static interval_type from_seconds(unsigned int seconds) { return seconds * _secondTicks; }
static interval_type from_minutes(unsigned int minutes) { return minutes * _minuteTicks; }
static interval_type from_hours(unsigned int hours) { return hours * _hourTicks; }
static interval_type from_days(unsigned int days) { return days * _dayTicks; }
bool is_initialized() const { return m_interval != 0; }
private:
friend int operator-(datetime t1, datetime t2);
static const interval_type _msTicks = static_cast<interval_type>(10000);
static const interval_type _secondTicks = 1000 * _msTicks;
static const interval_type _minuteTicks = 60 * _secondTicks;
static const interval_type _hourTicks = 60 * 60 * _secondTicks;
static const interval_type _dayTicks = 24 * 60 * 60 * _secondTicks;
// Private constructor. Use static methods to create an instance.
datetime(interval_type interval) : m_interval(interval) {}
// Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
interval_type m_interval;
};
inline int operator-(datetime t1, datetime t2)
{
auto diff = (t1.m_interval - t2.m_interval);
// Round it down to seconds
diff /= 10 * 1000 * 1000;
return static_cast<int>(diff);
}
/// <summary>
/// Nonce string generator class.
/// </summary>
class nonce_generator
{
public:
/// <summary>
/// Define default nonce length.
/// </summary>
enum
{
default_length = 32
};
/// <summary>
/// Nonce generator constructor.
/// </summary>
/// <param name="length">Length of the generated nonce string.</param>
nonce_generator(int length = default_length)
: m_random(static_cast<unsigned int>(utility::datetime::utc_timestamp())), m_length(length)
{
}
/// <summary>
/// Generate a nonce string containing random alphanumeric characters (A-Za-z0-9).
/// Length of the generated string is set by length().
/// </summary>
/// <returns>The generated nonce string.</returns>
_ASYNCRTIMP utility::string_t generate();
/// <summary>
/// Get length of generated nonce string.
/// </summary>
/// <returns>Nonce string length.</returns>
int length() const { return m_length; }
/// <summary>
/// Set length of the generated nonce string.
/// </summary>
/// <param name="length">Lenght of nonce string.</param>
void set_length(int length) { m_length = length; }
private:
std::mt19937 m_random;
int m_length;
};
} // namespace utility

View File

@ -1,391 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Protocol independent support for URIs.
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include "cpprest/asyncrt_utils.h"
#include "cpprest/details/basic_types.h"
#include <map>
#include <string>
#include <utility>
#include <vector>
namespace web
{
namespace details
{
struct uri_components
{
uri_components() : m_path(_XPLATSTR("/")), m_port(-1) {}
uri_components(const uri_components&) = default;
uri_components& operator=(const uri_components&) = default;
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
uri_components(uri_components&& other) CPPREST_NOEXCEPT : m_scheme(std::move(other.m_scheme)),
m_host(std::move(other.m_host)),
m_user_info(std::move(other.m_user_info)),
m_path(std::move(other.m_path)),
m_query(std::move(other.m_query)),
m_fragment(std::move(other.m_fragment)),
m_port(other.m_port)
{
}
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
uri_components& operator=(uri_components&& other) CPPREST_NOEXCEPT
{
if (this != &other)
{
m_scheme = std::move(other.m_scheme);
m_host = std::move(other.m_host);
m_user_info = std::move(other.m_user_info);
m_path = std::move(other.m_path);
m_query = std::move(other.m_query);
m_fragment = std::move(other.m_fragment);
m_port = other.m_port;
}
return *this;
}
_ASYNCRTIMP utility::string_t join();
utility::string_t m_scheme;
utility::string_t m_host;
utility::string_t m_user_info;
utility::string_t m_path;
utility::string_t m_query;
utility::string_t m_fragment;
int m_port;
};
} // namespace details
/// <summary>
/// A single exception type to represent errors in parsing, encoding, and decoding URIs.
/// </summary>
class uri_exception : public std::exception
{
public:
uri_exception(std::string msg) : m_msg(std::move(msg)) {}
~uri_exception() CPPREST_NOEXCEPT {}
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
private:
std::string m_msg;
};
/// <summary>
/// A flexible, protocol independent URI implementation.
///
/// URI instances are immutable. Querying the various fields on an empty URI will return empty strings. Querying
/// various diagnostic members on an empty URI will return false.
/// </summary>
/// <remarks>
/// This implementation accepts both URIs ('http://msn.com/path') and URI relative-references
/// ('/path?query#frag').
///
/// This implementation does not provide any scheme-specific handling -- an example of this
/// would be the following: 'http://path1/path'. This is a valid URI, but it's not a valid
/// http-uri -- that is, it's syntactically correct but does not conform to the requirements
/// of the http scheme (http requires a host).
/// We could provide this by allowing a pluggable 'scheme' policy-class, which would provide
/// extra capability for validating and canonicalizing a URI according to scheme, and would
/// introduce a layer of type-safety for URIs of differing schemes, and thus differing semantics.
///
/// One issue with implementing a scheme-independent URI facility is that of comparing for equality.
/// For instance, these URIs are considered equal 'http://msn.com', 'http://msn.com:80'. That is --
/// the 'default' port can be either omitted or explicit. Since we don't have a way to map a scheme
/// to it's default port, we don't have a way to know these are equal. This is just one of a class of
/// issues with regard to scheme-specific behavior.
/// </remarks>
class uri
{
public:
/// <summary>
/// The various components of a URI. This enum is used to indicate which
/// URI component is being encoded to the encode_uri_component. This allows
/// specific encoding to be performed.
///
/// Scheme and port don't allow '%' so they don't need to be encoded.
/// </summary>
class components
{
public:
enum component
{
user_info,
host,
path,
query,
fragment,
full_uri
};
};
/// <summary>
/// Encodes a URI component according to RFC 3986.
/// Note if a full URI is specified instead of an individual URI component all
/// characters not in the unreserved set are escaped.
/// </summary>
/// <param name="raw">The URI as a string.</param>
/// <returns>The encoded string.</returns>
_ASYNCRTIMP static utility::string_t __cdecl encode_uri(const utility::string_t& raw,
uri::components::component = components::full_uri);
/// <summary>
/// Encodes a string by converting all characters except for RFC 3986 unreserved characters to their
/// hexadecimal representation.
/// </summary>
/// <returns>The encoded string.</returns>
_ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t& data);
/// <summary>
/// Decodes an encoded string.
/// </summary>
/// <param name="encoded">The URI as a string.</param>
/// <returns>The decoded string.</returns>
_ASYNCRTIMP static utility::string_t __cdecl decode(const utility::string_t& encoded);
/// <summary>
/// Splits a path into its hierarchical components.
/// </summary>
/// <param name="path">The path as a string</param>
/// <returns>A <c>std::vector&lt;utility::string_t&gt;</c> containing the segments in the path.</returns>
_ASYNCRTIMP static std::vector<utility::string_t> __cdecl split_path(const utility::string_t& path);
/// <summary>
/// Splits a query into its key-value components.
/// </summary>
/// <param name="query">The query string</param>
/// <returns>A <c>std::map&lt;utility::string_t, utility::string_t&gt;</c> containing the key-value components of
/// the query.</returns>
_ASYNCRTIMP static std::map<utility::string_t, utility::string_t> __cdecl split_query(
const utility::string_t& query);
/// <summary>
/// Validates a string as a URI.
/// </summary>
/// <remarks>
/// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query').
/// </remarks>
/// <param name="uri_string">The URI string to be validated.</param>
/// <returns><c>true</c> if the given string represents a valid URI, <c>false</c> otherwise.</returns>
_ASYNCRTIMP static bool __cdecl validate(const utility::string_t& uri_string);
/// <summary>
/// Creates an empty uri
/// </summary>
uri() : m_uri(_XPLATSTR("/")) {}
/// <summary>
/// Creates a URI from the given encoded string. This will throw an exception if the string
/// does not contain a valid URI. Use uri::validate if processing user-input.
/// </summary>
/// <param name="uri_string">A pointer to an encoded string to create the URI instance.</param>
_ASYNCRTIMP uri(const utility::char_t* uri_string);
/// <summary>
/// Creates a URI from the given encoded string. This will throw an exception if the string
/// does not contain a valid URI. Use uri::validate if processing user-input.
/// </summary>
/// <param name="uri_string">An encoded URI string to create the URI instance.</param>
_ASYNCRTIMP uri(const utility::string_t& uri_string);
/// <summary>
/// Copy constructor.
/// </summary>
uri(const uri&) = default;
/// <summary>
/// Copy assignment operator.
/// </summary>
uri& operator=(const uri&) = default;
/// <summary>
/// Move constructor.
/// </summary>
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
uri(uri&& other) CPPREST_NOEXCEPT : m_uri(std::move(other.m_uri)), m_components(std::move(other.m_components)) {}
/// <summary>
/// Move assignment operator
/// </summary>
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
uri& operator=(uri&& other) CPPREST_NOEXCEPT
{
if (this != &other)
{
m_uri = std::move(other.m_uri);
m_components = std::move(other.m_components);
}
return *this;
}
/// <summary>
/// Get the scheme component of the URI as an encoded string.
/// </summary>
/// <returns>The URI scheme as a string.</returns>
const utility::string_t& scheme() const { return m_components.m_scheme; }
/// <summary>
/// Get the user information component of the URI as an encoded string.
/// </summary>
/// <returns>The URI user information as a string.</returns>
const utility::string_t& user_info() const { return m_components.m_user_info; }
/// <summary>
/// Get the host component of the URI as an encoded string.
/// </summary>
/// <returns>The URI host as a string.</returns>
const utility::string_t& host() const { return m_components.m_host; }
/// <summary>
/// Get the port component of the URI. Returns -1 if no port is specified.
/// </summary>
/// <returns>The URI port as an integer.</returns>
int port() const { return m_components.m_port; }
/// <summary>
/// Get the path component of the URI as an encoded string.
/// </summary>
/// <returns>The URI path as a string.</returns>
const utility::string_t& path() const { return m_components.m_path; }
/// <summary>
/// Get the query component of the URI as an encoded string.
/// </summary>
/// <returns>The URI query as a string.</returns>
const utility::string_t& query() const { return m_components.m_query; }
/// <summary>
/// Get the fragment component of the URI as an encoded string.
/// </summary>
/// <returns>The URI fragment as a string.</returns>
const utility::string_t& fragment() const { return m_components.m_fragment; }
/// <summary>
/// Creates a new uri object with the same authority portion as this one, omitting the resource and query portions.
/// </summary>
/// <returns>The new uri object with the same authority.</returns>
_ASYNCRTIMP uri authority() const;
/// <summary>
/// Gets the path, query, and fragment portion of this uri, which may be empty.
/// </summary>
/// <returns>The new URI object with the path, query and fragment portion of this URI.</returns>
_ASYNCRTIMP uri resource() const;
/// <summary>
/// An empty URI specifies no components, and serves as a default value
/// </summary>
bool is_empty() const { return this->m_uri.empty() || this->m_uri == _XPLATSTR("/"); }
/// <summary>
/// A loopback URI is one which refers to a hostname or ip address with meaning only on the local machine.
/// </summary>
/// <remarks>
/// Examples include "localhost", or ip addresses in the loopback range (127.0.0.0/24).
/// </remarks>
/// <returns><c>true</c> if this URI references the local host, <c>false</c> otherwise.</returns>
bool is_host_loopback() const
{
return !is_empty() &&
((host() == _XPLATSTR("localhost")) || (host().size() > 4 && host().substr(0, 4) == _XPLATSTR("127.")));
}
/// <summary>
/// A wildcard URI is one which refers to all hostnames that resolve to the local machine (using the * or +)
/// </summary>
/// <example>
/// http://*:80
/// </example>
bool is_host_wildcard() const
{
return !is_empty() && (this->host() == _XPLATSTR("*") || this->host() == _XPLATSTR("+"));
}
/// <summary>
/// A portable URI is one with a hostname that can be resolved globally (used from another machine).
/// </summary>
/// <returns><c>true</c> if this URI can be resolved globally (used from another machine), <c>false</c>
/// otherwise.</returns> <remarks> The hostname "localhost" is a reserved name that is guaranteed to resolve to the
/// local machine, and cannot be used for inter-machine communication. Likewise the hostnames "*" and "+" on Windows
/// represent wildcards, and do not map to a resolvable address.
/// </remarks>
bool is_host_portable() const { return !(is_empty() || is_host_loopback() || is_host_wildcard()); }
/// <summary>
/// A default port is one where the port is unspecified, and will be determined by the operating system.
/// The choice of default port may be dictated by the scheme (http -> 80) or not.
/// </summary>
/// <returns><c>true</c> if this URI instance has a default port, <c>false</c> otherwise.</returns>
bool is_port_default() const { return !is_empty() && this->port() == 0; }
/// <summary>
/// An "authority" URI is one with only a scheme, optional userinfo, hostname, and (optional) port.
/// </summary>
/// <returns><c>true</c> if this is an "authority" URI, <c>false</c> otherwise.</returns>
bool is_authority() const { return !is_empty() && is_path_empty() && query().empty() && fragment().empty(); }
/// <summary>
/// Returns whether the other URI has the same authority as this one
/// </summary>
/// <param name="other">The URI to compare the authority with.</param>
/// <returns><c>true</c> if both the URI's have the same authority, <c>false</c> otherwise.</returns>
bool has_same_authority(const uri& other) const { return !is_empty() && this->authority() == other.authority(); }
/// <summary>
/// Returns whether the path portion of this URI is empty
/// </summary>
/// <returns><c>true</c> if the path portion of this URI is empty, <c>false</c> otherwise.</returns>
bool is_path_empty() const { return path().empty() || path() == _XPLATSTR("/"); }
/// <summary>
/// Returns the full (encoded) URI as a string.
/// </summary>
/// <returns>The full encoded URI string.</returns>
utility::string_t to_string() const { return m_uri; }
/// <summary>
/// Returns an URI resolved against <c>this</c> as the base URI
/// according to RFC3986, Section 5 (https://tools.ietf.org/html/rfc3986#section-5).
/// </summary>
/// <param name="relativeUri">The relative URI to be resolved against <c>this</c> as base.</param>
/// <returns>The new resolved URI string.</returns>
_ASYNCRTIMP utility::string_t resolve_uri(const utility::string_t& relativeUri) const;
_ASYNCRTIMP bool operator==(const uri& other) const;
bool operator<(const uri& other) const { return m_uri < other.m_uri; }
bool operator!=(const uri& other) const { return !(this->operator==(other)); }
private:
friend class uri_builder;
/// <summary>
/// Creates a URI from the given URI components.
/// </summary>
/// <param name="components">A URI components object to create the URI instance.</param>
_ASYNCRTIMP uri(const details::uri_components& components);
// Used by uri_builder
static utility::string_t __cdecl encode_query_impl(const utf8string& raw);
utility::string_t m_uri;
details::uri_components m_components;
};
} // namespace web

File diff suppressed because it is too large Load Diff

View File

@ -1,131 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Platform-dependent type definitions
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include "cpprest/details/cpprest_compat.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#ifndef _WIN32
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>
#else
#include <cstdint>
#endif
#include "cpprest/details/SafeInt3.hpp"
namespace utility
{
#ifdef _WIN32
#define _UTF16_STRINGS
#endif
// We should be using a 64-bit size type for most situations that do
// not involve specifying the size of a memory allocation or buffer.
typedef uint64_t size64_t;
#ifndef _WIN32
typedef uint32_t HRESULT; // Needed for PPLX
#endif
#ifdef _UTF16_STRINGS
//
// On Windows, all strings are wide
//
typedef wchar_t char_t;
typedef std::wstring string_t;
#define _XPLATSTR(x) L##x
typedef std::wostringstream ostringstream_t;
typedef std::wofstream ofstream_t;
typedef std::wostream ostream_t;
typedef std::wistream istream_t;
typedef std::wifstream ifstream_t;
typedef std::wistringstream istringstream_t;
typedef std::wstringstream stringstream_t;
#define ucout std::wcout
#define ucin std::wcin
#define ucerr std::wcerr
#else
//
// On POSIX platforms, all strings are narrow
//
typedef char char_t;
typedef std::string string_t;
#define _XPLATSTR(x) x
typedef std::ostringstream ostringstream_t;
typedef std::ofstream ofstream_t;
typedef std::ostream ostream_t;
typedef std::istream istream_t;
typedef std::ifstream ifstream_t;
typedef std::istringstream istringstream_t;
typedef std::stringstream stringstream_t;
#define ucout std::cout
#define ucin std::cin
#define ucerr std::cerr
#endif // endif _UTF16_STRINGS
#ifndef _TURN_OFF_PLATFORM_STRING
// The 'U' macro can be used to create a string or character literal of the platform type, i.e. utility::char_t.
// If you are using a library causing conflicts with 'U' macro, it can be turned off by defining the macro
// '_TURN_OFF_PLATFORM_STRING' before including the C++ REST SDK header files, and e.g. use '_XPLATSTR' instead.
#define U(x) _XPLATSTR(x)
#endif // !_TURN_OFF_PLATFORM_STRING
} // namespace utility
typedef char utf8char;
typedef std::string utf8string;
typedef std::stringstream utf8stringstream;
typedef std::ostringstream utf8ostringstream;
typedef std::ostream utf8ostream;
typedef std::istream utf8istream;
typedef std::istringstream utf8istringstream;
#ifdef _UTF16_STRINGS
typedef wchar_t utf16char;
typedef std::wstring utf16string;
typedef std::wstringstream utf16stringstream;
typedef std::wostringstream utf16ostringstream;
typedef std::wostream utf16ostream;
typedef std::wistream utf16istream;
typedef std::wistringstream utf16istringstream;
#else
typedef char16_t utf16char;
typedef std::u16string utf16string;
typedef std::basic_stringstream<utf16char> utf16stringstream;
typedef std::basic_ostringstream<utf16char> utf16ostringstream;
typedef std::basic_ostream<utf16char> utf16ostream;
typedef std::basic_istream<utf16char> utf16istream;
typedef std::basic_istringstream<utf16char> utf16istringstream;
#endif
#if defined(_WIN32)
// Include on everything except Windows Desktop ARM, unless explicitly excluded.
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
#if defined(WINAPI_FAMILY)
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && defined(_M_ARM)
#define CPPREST_EXCLUDE_WEBSOCKETS
#endif
#else
#if defined(_M_ARM)
#define CPPREST_EXCLUDE_WEBSOCKETS
#endif
#endif
#endif
#endif

View File

@ -1,91 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Standard macros and definitions.
* This header has minimal dependency on windows headers and is safe for use in the public API
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#if defined(_WIN32)
#if _MSC_VER >= 1900
#define CPPREST_NOEXCEPT noexcept
#define CPPREST_CONSTEXPR constexpr
#else
#define CPPREST_NOEXCEPT
#define CPPREST_CONSTEXPR const
#endif // _MSC_VER >= 1900
#define CASABLANCA_UNREFERENCED_PARAMETER(x) (x)
#include <sal.h>
#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv
#define __declspec(x) __attribute__((x))
#define dllimport
#define novtable /* no novtable equivalent */
#define __assume(x) \
do \
{ \
if (!(x)) __builtin_unreachable(); \
} while (false)
#define CASABLANCA_UNREFERENCED_PARAMETER(x) (void)x
#define CPPREST_NOEXCEPT noexcept
#define CPPREST_CONSTEXPR constexpr
#include <assert.h>
#define _ASSERTE(x) assert(x)
// No SAL on non Windows platforms
#include "cpprest/details/nosal.h"
#if !defined(__cdecl)
#if defined(cdecl)
#define __cdecl __attribute__((cdecl))
#else // ^^^ defined cdecl ^^^ // vvv !defined cdecl vvv
#define __cdecl
#endif // defined cdecl
#endif // not defined __cdecl
#if defined(__ANDROID__)
// This is needed to disable the use of __thread inside the boost library.
// Android does not support thread local storage -- if boost is included
// without this macro defined, it will create references to __tls_get_addr
// which (while able to link) will not be available at runtime and prevent
// the .so from loading.
#if not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
#define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
#endif // not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
#endif // defined(__ANDROID__)
#ifdef __clang__
#include <cstdio>
#endif // __clang__
#endif // _WIN32
#define _NO_ASYNCRTIMP
#ifdef _NO_ASYNCRTIMP
#define _ASYNCRTIMP
#else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv
#ifdef _ASYNCRT_EXPORT
#define _ASYNCRTIMP __declspec(dllexport)
#else // ^^^ _ASYNCRT_EXPORT ^^^ // vvv !_ASYNCRT_EXPORT vvv
#define _ASYNCRTIMP __declspec(dllimport)
#endif // _ASYNCRT_EXPORT
#endif // _NO_ASYNCRTIMP
#ifdef CASABLANCA_DEPRECATION_NO_WARNINGS
#define CASABLANCA_DEPRECATED(x)
#else
#define CASABLANCA_DEPRECATED(x) __declspec(deprecated(x))
#endif // CASABLANCA_DEPRECATION_NO_WARNINGS

View File

@ -1,223 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* utility classes used by the different web:: clients
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include "cpprest/asyncrt_utils.h"
#include "cpprest/uri.h"
namespace web
{
namespace details
{
class zero_memory_deleter
{
public:
_ASYNCRTIMP void operator()(::utility::string_t* data) const;
};
typedef std::unique_ptr<::utility::string_t, zero_memory_deleter> plaintext_string;
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
#if defined(__cplusplus_winrt)
class winrt_encryption
{
public:
winrt_encryption() {}
_ASYNCRTIMP winrt_encryption(const std::wstring& data);
_ASYNCRTIMP plaintext_string decrypt() const;
private:
::pplx::task<Windows::Storage::Streams::IBuffer ^> m_buffer;
};
#else
class win32_encryption
{
public:
win32_encryption() {}
_ASYNCRTIMP win32_encryption(const std::wstring& data);
_ASYNCRTIMP ~win32_encryption();
_ASYNCRTIMP plaintext_string decrypt() const;
private:
std::vector<char> m_buffer;
size_t m_numCharacters;
};
#endif
#endif
} // namespace details
/// <summary>
/// Represents a set of user credentials (user name and password) to be used
/// for authentication.
/// </summary>
class credentials
{
public:
/// <summary>
/// Constructs an empty set of credentials without a user name or password.
/// </summary>
credentials() {}
/// <summary>
/// Constructs credentials from given user name and password.
/// </summary>
/// <param name="username">User name as a string.</param>
/// <param name="password">Password as a string.</param>
credentials(utility::string_t username, const utility::string_t& password)
: m_username(std::move(username)), m_password(password)
{
}
/// <summary>
/// The user name associated with the credentials.
/// </summary>
/// <returns>A string containing the user name.</returns>
const utility::string_t& username() const { return m_username; }
/// <summary>
/// The password for the user name associated with the credentials.
/// </summary>
/// <returns>A string containing the password.</returns>
CASABLANCA_DEPRECATED(
"This API is deprecated for security reasons to avoid unnecessary password copies stored in plaintext.")
utility::string_t password() const
{
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
return utility::string_t(*m_password.decrypt());
#else
return m_password;
#endif
}
/// <summary>
/// Checks if credentials have been set
/// </summary>
/// <returns><c>true</c> if user name and password is set, <c>false</c> otherwise.</returns>
bool is_set() const { return !m_username.empty(); }
details::plaintext_string _internal_decrypt() const
{
// Encryption APIs not supported on XP
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
return m_password.decrypt();
#else
return details::plaintext_string(new ::utility::string_t(m_password));
#endif
}
private:
::utility::string_t m_username;
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
#if defined(__cplusplus_winrt)
details::winrt_encryption m_password;
#else
details::win32_encryption m_password;
#endif
#else
::utility::string_t m_password;
#endif
};
/// <summary>
/// web_proxy represents the concept of the web proxy, which can be auto-discovered,
/// disabled, or specified explicitly by the user.
/// </summary>
class web_proxy
{
enum web_proxy_mode_internal
{
use_default_,
use_auto_discovery_,
disabled_,
user_provided_
};
public:
enum web_proxy_mode
{
use_default = use_default_,
use_auto_discovery = use_auto_discovery_,
disabled = disabled_
};
/// <summary>
/// Constructs a proxy with the default settings.
/// </summary>
web_proxy() : m_address(_XPLATSTR("")), m_mode(use_default_) {}
/// <summary>
/// Creates a proxy with specified mode.
/// </summary>
/// <param name="mode">Mode to use.</param>
web_proxy(web_proxy_mode mode) : m_address(_XPLATSTR("")), m_mode(static_cast<web_proxy_mode_internal>(mode)) {}
/// <summary>
/// Creates a proxy explicitly with provided address.
/// </summary>
/// <param name="address">Proxy URI to use.</param>
web_proxy(uri address) : m_address(address), m_mode(user_provided_) {}
/// <summary>
/// Gets this proxy's URI address. Returns an empty URI if not explicitly set by user.
/// </summary>
/// <returns>A reference to this proxy's URI.</returns>
const uri& address() const { return m_address; }
/// <summary>
/// Gets the credentials used for authentication with this proxy.
/// </summary>
/// <returns>Credentials to for this proxy.</returns>
const web::credentials& credentials() const { return m_credentials; }
/// <summary>
/// Sets the credentials to use for authentication with this proxy.
/// </summary>
/// <param name="cred">Credentials to use for this proxy.</param>
void set_credentials(web::credentials cred)
{
if (m_mode == disabled_)
{
throw std::invalid_argument("Cannot attach credentials to a disabled proxy");
}
m_credentials = std::move(cred);
}
/// <summary>
/// Checks if this proxy was constructed with default settings.
/// </summary>
/// <returns>True if default, false otherwise.</param>
bool is_default() const { return m_mode == use_default_; }
/// <summary>
/// Checks if using a proxy is disabled.
/// </summary>
/// <returns>True if disabled, false otherwise.</returns>
bool is_disabled() const { return m_mode == disabled_; }
/// <summary>
/// Checks if the auto discovery protocol, WPAD, is to be used.
/// </summary>
/// <returns>True if auto discovery enabled, false otherwise.</returns>
bool is_auto_discovery() const { return m_mode == use_auto_discovery_; }
/// <summary>
/// Checks if a proxy address is explicitly specified by the user.
/// </summary>
/// <returns>True if a proxy address was explicitly specified, false otherwise.</returns>
bool is_specified() const { return m_mode == user_provided_; }
private:
web::uri m_address;
web_proxy_mode_internal m_mode;
web::credentials m_credentials;
};
} // namespace web

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Protocol independent support for URIs.
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#ifndef CASA_URI_H
#define CASA_URI_H
#include "cpprest/base_uri.h"
#include "cpprest/uri_builder.h"
#endif

View File

@ -1,295 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Builder style class for creating URIs.
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#include "cpprest/base_uri.h"
#include <string>
namespace web
{
/// <summary>
/// Builder for constructing URIs incrementally.
/// </summary>
class uri_builder
{
public:
/// <summary>
/// Creates a builder with an initially empty URI.
/// </summary>
uri_builder() = default;
/// <summary>
/// Creates a builder with a existing URI object.
/// </summary>
/// <param name="uri_str">Encoded string containing the URI.</param>
uri_builder(const uri& uri_str) : m_uri(uri_str.m_components) {}
/// <summary>
/// Get the scheme component of the URI as an encoded string.
/// </summary>
/// <returns>The URI scheme as a string.</returns>
const utility::string_t& scheme() const { return m_uri.m_scheme; }
/// <summary>
/// Get the user information component of the URI as an encoded string.
/// </summary>
/// <returns>The URI user information as a string.</returns>
const utility::string_t& user_info() const { return m_uri.m_user_info; }
/// <summary>
/// Get the host component of the URI as an encoded string.
/// </summary>
/// <returns>The URI host as a string.</returns>
const utility::string_t& host() const { return m_uri.m_host; }
/// <summary>
/// Get the port component of the URI. Returns -1 if no port is specified.
/// </summary>
/// <returns>The URI port as an integer.</returns>
int port() const { return m_uri.m_port; }
/// <summary>
/// Get the path component of the URI as an encoded string.
/// </summary>
/// <returns>The URI path as a string.</returns>
const utility::string_t& path() const { return m_uri.m_path; }
/// <summary>
/// Get the query component of the URI as an encoded string.
/// </summary>
/// <returns>The URI query as a string.</returns>
const utility::string_t& query() const { return m_uri.m_query; }
/// <summary>
/// Get the fragment component of the URI as an encoded string.
/// </summary>
/// <returns>The URI fragment as a string.</returns>
const utility::string_t& fragment() const { return m_uri.m_fragment; }
/// <summary>
/// Set the scheme of the URI.
/// </summary>
/// <param name="scheme">Uri scheme.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_scheme(const utility::string_t& scheme)
{
m_uri.m_scheme = scheme;
return *this;
}
/// <summary>
/// Set the user info component of the URI.
/// </summary>
/// <param name="user_info">User info as a decoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_user_info(const utility::string_t& user_info, bool do_encoding = false)
{
if (do_encoding)
{
m_uri.m_user_info = uri::encode_uri(user_info, uri::components::user_info);
}
else
{
m_uri.m_user_info = user_info;
}
return *this;
}
/// <summary>
/// Set the host component of the URI.
/// </summary>
/// <param name="host">Host as a decoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_host(const utility::string_t& host, bool do_encoding = false)
{
if (do_encoding)
{
m_uri.m_host = uri::encode_uri(host, uri::components::host);
}
else
{
m_uri.m_host = host;
}
return *this;
}
/// <summary>
/// Set the port component of the URI.
/// </summary>
/// <param name="port">Port as an integer.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_port(int port)
{
m_uri.m_port = port;
return *this;
}
/// <summary>
/// Set the port component of the URI.
/// </summary>
/// <param name="port">Port as a string.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
/// <remarks>When string can't be converted to an integer the port is left unchanged.</remarks>
_ASYNCRTIMP uri_builder& set_port(const utility::string_t& port);
/// <summary>
/// Set the path component of the URI.
/// </summary>
/// <param name="path">Path as a decoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_path(const utility::string_t& path, bool do_encoding = false)
{
if (do_encoding)
{
m_uri.m_path = uri::encode_uri(path, uri::components::path);
}
else
{
m_uri.m_path = path;
}
return *this;
}
/// <summary>
/// Set the query component of the URI.
/// </summary>
/// <param name="query">Query as a decoded string.</param>
/// <param name="do_encoding">Specify whether apply URI encoding to the given string.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_query(const utility::string_t& query, bool do_encoding = false)
{
if (do_encoding)
{
m_uri.m_query = uri::encode_uri(query, uri::components::query);
}
else
{
m_uri.m_query = query;
}
return *this;
}
/// <summary>
/// Set the fragment component of the URI.
/// </summary>
/// <param name="fragment">Fragment as a decoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
uri_builder& set_fragment(const utility::string_t& fragment, bool do_encoding = false)
{
if (do_encoding)
{
m_uri.m_fragment = uri::encode_uri(fragment, uri::components::fragment);
}
else
{
m_uri.m_fragment = fragment;
}
return *this;
}
/// <summary>
/// Clears all components of the underlying URI in this uri_builder.
/// </summary>
void clear() { m_uri = details::uri_components(); }
/// <summary>
/// Appends another path to the path of this uri_builder.
/// </summary>
/// <param name="path">Path to append as a already encoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this uri_builder to support chaining.</returns>
_ASYNCRTIMP uri_builder& append_path(const utility::string_t& path, bool do_encoding = false);
/// <summary>
/// Appends the raw contents of the path argument to the path of this uri_builder with no separator de-duplication.
/// </summary>
/// <remarks>
/// The path argument is appended after adding a '/' separator without regards to the contents of path. If an empty
/// string is provided, this function will immediately return without changes to the stored path value. For example:
/// if the current contents are "/abc" and path="/xyz", the result will be "/abc//xyz".
/// </remarks>
/// <param name="path">Path to append as a already encoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this uri_builder to support chaining.</returns>
_ASYNCRTIMP uri_builder& append_path_raw(const utility::string_t& path, bool do_encoding = false);
/// <summary>
/// Appends another query to the query of this uri_builder.
/// </summary>
/// <param name="query">Query to append as a decoded string.</param>
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
/// <returns>A reference to this uri_builder to support chaining.</returns>
_ASYNCRTIMP uri_builder& append_query(const utility::string_t& query, bool do_encoding = false);
/// <summary>
/// Appends an relative uri (Path, Query and fragment) at the end of the current uri.
/// </summary>
/// <param name="relative_uri">The relative uri to append.</param>
/// <returns>A reference to this uri_builder to support chaining.</returns>
_ASYNCRTIMP uri_builder& append(const uri& relative_uri);
/// <summary>
/// Appends another query to the query of this uri_builder, encoding it first. This overload is useful when building
/// a query segment of the form "element=10", where the right hand side of the query is stored as a type other than
/// a string, for instance, an integral type.
/// </summary>
/// <param name="name">The name portion of the query string</param>
/// <param name="value">The value portion of the query string</param>
/// <returns>A reference to this uri_builder to support chaining.</returns>
template<typename T>
uri_builder& append_query(const utility::string_t& name, const T& value, bool do_encoding = true)
{
if (do_encoding)
append_query_encode_impl(name, utility::conversions::details::print_utf8string(value));
else
append_query_no_encode_impl(name, utility::conversions::details::print_string(value));
return *this;
}
/// <summary>
/// Combine and validate the URI components into a encoded string. An exception will be thrown if the URI is
/// invalid.
/// </summary>
/// <returns>The created URI as a string.</returns>
_ASYNCRTIMP utility::string_t to_string() const;
/// <summary>
/// Combine and validate the URI components into a URI class instance. An exception will be thrown if the URI is
/// invalid.
/// </summary>
/// <returns>The create URI as a URI class instance.</returns>
_ASYNCRTIMP uri to_uri() const;
/// <summary>
/// Validate the generated URI from all existing components of this uri_builder.
/// </summary>
/// <returns>Whether the URI is valid.</returns>
_ASYNCRTIMP bool is_valid();
private:
_ASYNCRTIMP void append_query_encode_impl(const utility::string_t& name, const utf8string& value);
_ASYNCRTIMP void append_query_no_encode_impl(const utility::string_t& name, const utility::string_t& value);
details::uri_components m_uri;
};
} // namespace web

View File

@ -1,10 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
*/
#define CPPREST_VERSION_MINOR 10
#define CPPREST_VERSION_MAJOR 2
#define CPPREST_VERSION_REVISION 13
#define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION)

View File

@ -1,25 +0,0 @@
C++ REST SDK
The MIT License (MIT)
Copyright (c) Microsoft Corporation
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1 +0,0 @@
#include "pch.h"

34
deps/cpprestsdk/pch.h vendored
View File

@ -1,34 +0,0 @@
#include <winrt/base.h>
#include <Windows.h>
#include <dxgi1_3.h>
#include <d3d11_2.h>
#include <d2d1_3.h>
#include <d2d1_3helper.h>
#include <d2d1helper.h>
#include <dwrite.h>
#include <dcomp.h>
#include <dwmapi.h>
#include <Shobjidl.h>
#include <Shlwapi.h>
#include <string>
#include <algorithm>
#include <chrono>
#include <mutex>
#include <thread>
#include <functional>
#include <condition_variable>
#include <stdexcept>
#include <tuple>
#include <unordered_set>
#include <string>
#include <vector>
// cpprestsdk headers
#include "cpprest/details/basic_types.h"
#include "cpprest/details/cpprest_compat.h"
#include "cpprest/version.h"
// json
#include "cpprest/json.h"
// utilities
#include "cpprest/asyncrt_utils.h"
#include "cpprest/details/web_utilities.h"

View File

@ -1,475 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* HTTP Library: JSON parser and writer
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#include "pch.h"
using namespace web;
bool json::details::g_keep_json_object_unsorted = false;
void json::keep_object_element_order(bool keep_order) { json::details::g_keep_json_object_unsorted = keep_order; }
utility::ostream_t& web::json::operator<<(utility::ostream_t& os, const web::json::value& val)
{
val.serialize(os);
return os;
}
utility::istream_t& web::json::operator>>(utility::istream_t& is, json::value& val)
{
val = json::value::parse(is);
return is;
}
web::json::value::value()
: m_value(utility::details::make_unique<web::json::details::_Null>())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Null)
#endif
{
}
web::json::value::value(int32_t value)
: m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Number)
#endif
{
}
web::json::value::value(uint32_t value)
: m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Number)
#endif
{
}
web::json::value::value(int64_t value)
: m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Number)
#endif
{
}
web::json::value::value(uint64_t value)
: m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Number)
#endif
{
}
web::json::value::value(double value)
: m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Number)
#endif
{
}
web::json::value::value(bool value)
: m_value(utility::details::make_unique<web::json::details::_Boolean>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::Boolean)
#endif
{
}
web::json::value::value(utility::string_t value)
: m_value(utility::details::make_unique<web::json::details::_String>(std::move(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::String)
#endif
{
}
web::json::value::value(utility::string_t value, bool has_escape_chars)
: m_value(utility::details::make_unique<web::json::details::_String>(std::move(value), has_escape_chars))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::String)
#endif
{
}
web::json::value::value(const utility::char_t* value)
: m_value(utility::details::make_unique<web::json::details::_String>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::String)
#endif
{
}
web::json::value::value(const utility::char_t* value, bool has_escape_chars)
: m_value(utility::details::make_unique<web::json::details::_String>(utility::string_t(value), has_escape_chars))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(value::String)
#endif
{
}
web::json::value::value(const value& other)
: m_value(other.m_value->_copy_value())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
, m_kind(other.m_kind)
#endif
{
}
web::json::value& web::json::value::operator=(const value& other)
{
if (this != &other)
{
m_value = std::unique_ptr<details::_Value>(other.m_value->_copy_value());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
m_kind = other.m_kind;
#endif
}
return *this;
}
web::json::value::value(value&& other) CPPREST_NOEXCEPT : m_value(std::move(other.m_value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
m_kind(other.m_kind)
#endif
{
}
web::json::value& web::json::value::operator=(web::json::value&& other) CPPREST_NOEXCEPT
{
if (this != &other)
{
m_value.swap(other.m_value);
#ifdef ENABLE_JSON_VALUE_VISUALIZER
m_kind = other.m_kind;
#endif
}
return *this;
}
web::json::value web::json::value::null() { return web::json::value(); }
web::json::value web::json::value::number(double value) { return web::json::value(value); }
web::json::value web::json::value::number(int32_t value) { return web::json::value(value); }
web::json::value web::json::value::number(uint32_t value) { return web::json::value(value); }
web::json::value web::json::value::number(int64_t value) { return web::json::value(value); }
web::json::value web::json::value::number(uint64_t value) { return web::json::value(value); }
web::json::value web::json::value::boolean(bool value) { return web::json::value(value); }
web::json::value web::json::value::string(utility::string_t value)
{
std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(std::move(value));
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::String
#endif
);
}
web::json::value web::json::value::string(utility::string_t value, bool has_escape_chars)
{
std::unique_ptr<details::_Value> ptr =
utility::details::make_unique<details::_String>(std::move(value), has_escape_chars);
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::String
#endif
);
}
#ifdef _WIN32
web::json::value web::json::value::string(const std::string& value)
{
std::unique_ptr<details::_Value> ptr =
utility::details::make_unique<details::_String>(utility::conversions::to_utf16string(value));
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::String
#endif
);
}
#endif
web::json::value web::json::value::object(bool keep_order)
{
std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(keep_order);
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::Object
#endif
);
}
web::json::value web::json::value::object(std::vector<std::pair<::utility::string_t, value>> fields, bool keep_order)
{
std::unique_ptr<details::_Value> ptr =
utility::details::make_unique<details::_Object>(std::move(fields), keep_order);
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::Object
#endif
);
}
web::json::value web::json::value::array()
{
std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>();
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::Array
#endif
);
}
web::json::value web::json::value::array(size_t size)
{
std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(size);
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::Array
#endif
);
}
web::json::value web::json::value::array(std::vector<value> elements)
{
std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(std::move(elements));
return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
,
value::Array
#endif
);
}
const web::json::number& web::json::value::as_number() const { return m_value->as_number(); }
double web::json::value::as_double() const { return m_value->as_double(); }
int web::json::value::as_integer() const { return m_value->as_integer(); }
bool web::json::value::as_bool() const { return m_value->as_bool(); }
json::array& web::json::value::as_array() { return m_value->as_array(); }
const json::array& web::json::value::as_array() const { return m_value->as_array(); }
json::object& web::json::value::as_object() { return m_value->as_object(); }
const json::object& web::json::value::as_object() const { return m_value->as_object(); }
bool web::json::number::is_int32() const
{
switch (m_type)
{
case signed_type:
return m_intval >= (std::numeric_limits<int32_t>::min)() && m_intval <= (std::numeric_limits<int32_t>::max)();
case unsigned_type: return m_uintval <= (std::numeric_limits<int32_t>::max)();
case double_type:
default: return false;
}
}
bool web::json::number::is_uint32() const
{
switch (m_type)
{
case signed_type: return m_intval >= 0 && m_intval <= (std::numeric_limits<uint32_t>::max)();
case unsigned_type: return m_uintval <= (std::numeric_limits<uint32_t>::max)();
case double_type:
default: return false;
}
}
bool web::json::number::is_int64() const
{
switch (m_type)
{
case signed_type: return true;
case unsigned_type: return m_uintval <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)());
case double_type:
default: return false;
}
}
bool web::json::details::_String::has_escape_chars(const _String& str)
{
return std::any_of(std::begin(str.m_string), std::end(str.m_string), [](utility::string_t::value_type const x) {
if (x <= 31)
{
return true;
}
if (x == '"')
{
return true;
}
if (x == '\\')
{
return true;
}
return false;
});
}
web::json::value::value_type json::value::type() const { return m_value->type(); }
bool json::value::is_integer() const
{
if (!is_number())
{
return false;
}
return m_value->is_integer();
}
bool json::value::is_double() const
{
if (!is_number())
{
return false;
}
return m_value->is_double();
}
json::value& web::json::details::_Object::index(const utility::string_t& key) { return m_object[key]; }
bool web::json::details::_Object::has_field(const utility::string_t& key) const
{
return m_object.find(key) != m_object.end();
}
bool web::json::value::has_number_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_number();
}
bool web::json::value::has_integer_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_integer();
}
bool web::json::value::has_double_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_double();
}
bool web::json::value::has_boolean_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_boolean();
}
bool web::json::value::has_string_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_string();
}
bool web::json::value::has_array_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_array();
}
bool web::json::value::has_object_field(const utility::string_t& key) const
{
return has_field(key) && at(key).is_object();
}
utility::string_t json::value::to_string() const
{
#ifndef _WIN32
utility::details::scoped_c_thread_locale locale;
#endif
return m_value->to_string();
}
bool json::value::operator==(const json::value& other) const
{
if (this->m_value.get() == other.m_value.get()) return true;
if (this->type() != other.type()) return false;
switch (this->type())
{
case Null: return true;
case Number: return this->as_number() == other.as_number();
case Boolean: return this->as_bool() == other.as_bool();
case String: return this->as_string() == other.as_string();
case Object:
return static_cast<const json::details::_Object*>(this->m_value.get())
->is_equal(static_cast<const json::details::_Object*>(other.m_value.get()));
case Array:
return static_cast<const json::details::_Array*>(this->m_value.get())
->is_equal(static_cast<const json::details::_Array*>(other.m_value.get()));
}
__assume(0);
}
void web::json::value::erase(size_t index) { return this->as_array().erase(index); }
void web::json::value::erase(const utility::string_t& key) { return this->as_object().erase(key); }
// at() overloads
web::json::value& web::json::value::at(size_t index) { return this->as_array().at(index); }
const web::json::value& web::json::value::at(size_t index) const { return this->as_array().at(index); }
web::json::value& web::json::value::at(const utility::string_t& key) { return this->as_object().at(key); }
const web::json::value& web::json::value::at(const utility::string_t& key) const { return this->as_object().at(key); }
web::json::value& web::json::value::operator[](const utility::string_t& key)
{
if (this->is_null())
{
m_value.reset(new web::json::details::_Object(details::g_keep_json_object_unsorted));
#ifdef ENABLE_JSON_VALUE_VISUALIZER
m_kind = value::Object;
#endif
}
return m_value->index(key);
}
web::json::value& web::json::value::operator[](size_t index)
{
if (this->is_null())
{
m_value.reset(new web::json::details::_Array());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
m_kind = value::Array;
#endif
}
return m_value->index(index);
}
// Remove once VS 2013 is no longer supported.
#if defined(_WIN32) && _MSC_VER < 1900
static web::json::details::json_error_category_impl instance;
#endif
const web::json::details::json_error_category_impl& web::json::details::json_error_category()
{
#if !defined(_WIN32) || _MSC_VER >= 1900
static web::json::details::json_error_category_impl instance;
#endif
return instance;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,254 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* HTTP Library: JSON parser and writer
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#include "pch.h"
#include <stdio.h>
#ifndef _WIN32
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
using namespace web;
using namespace web::json;
using namespace utility;
using namespace utility::conversions;
//
// JSON Serialization
//
#ifdef _WIN32
void web::json::value::serialize(std::ostream& stream) const
{
// This has better performance than writing directly to stream.
std::string str;
m_value->serialize_impl(str);
stream << str;
}
void web::json::value::format(std::basic_string<wchar_t>& string) const { m_value->format(string); }
#endif
void web::json::value::serialize(utility::ostream_t& stream) const
{
#ifndef _WIN32
utility::details::scoped_c_thread_locale locale;
#endif
// This has better performance than writing directly to stream.
utility::string_t str;
m_value->serialize_impl(str);
stream << str;
}
void web::json::value::format(std::basic_string<char>& string) const { m_value->format(string); }
template<typename CharType>
void web::json::details::append_escape_string(std::basic_string<CharType>& str,
const std::basic_string<CharType>& escaped)
{
for (const auto& ch : escaped)
{
switch (ch)
{
case '\"':
str += '\\';
str += '\"';
break;
case '\\':
str += '\\';
str += '\\';
break;
case '\b':
str += '\\';
str += 'b';
break;
case '\f':
str += '\\';
str += 'f';
break;
case '\r':
str += '\\';
str += 'r';
break;
case '\n':
str += '\\';
str += 'n';
break;
case '\t':
str += '\\';
str += 't';
break;
default:
// If a control character then must unicode escaped.
if (ch >= 0 && ch <= 0x1F)
{
static const std::array<CharType, 16> intToHex = {
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}};
str += '\\';
str += 'u';
str += '0';
str += '0';
str += intToHex[(ch & 0xF0) >> 4];
str += intToHex[ch & 0x0F];
}
else
{
str += ch;
}
}
}
}
void web::json::details::format_string(const utility::string_t& key, utility::string_t& str)
{
str.push_back('"');
append_escape_string(str, key);
str.push_back('"');
}
#ifdef _WIN32
void web::json::details::format_string(const utility::string_t& key, std::string& str)
{
str.push_back('"');
append_escape_string(str, utility::conversions::to_utf8string(key));
str.push_back('"');
}
#endif
void web::json::details::_String::format(std::basic_string<char>& str) const
{
str.push_back('"');
if (m_has_escape_char)
{
append_escape_string(str, utility::conversions::to_utf8string(m_string));
}
else
{
str.append(utility::conversions::to_utf8string(m_string));
}
str.push_back('"');
}
void web::json::details::_Number::format(std::basic_string<char>& stream) const
{
if (m_number.m_type != number::type::double_type)
{
// #digits + 1 to avoid loss + 1 for the sign + 1 for null terminator.
const size_t tempSize = std::numeric_limits<uint64_t>::digits10 + 3;
char tempBuffer[tempSize];
#ifdef _WIN32
// This can be improved performance-wise if we implement our own routine
if (m_number.m_type == number::type::signed_type)
_i64toa_s(m_number.m_intval, tempBuffer, tempSize, 10);
else
_ui64toa_s(m_number.m_uintval, tempBuffer, tempSize, 10);
const auto numChars = strnlen_s(tempBuffer, tempSize);
#else
int numChars;
if (m_number.m_type == number::type::signed_type)
numChars = snprintf(tempBuffer, tempSize, "%" PRId64, m_number.m_intval);
else
numChars = snprintf(tempBuffer, tempSize, "%" PRIu64, m_number.m_uintval);
#endif
stream.append(tempBuffer, numChars);
}
else
{
// #digits + 2 to avoid loss + 1 for the sign + 1 for decimal point + 5 for exponent (e+xxx) + 1 for null
// terminator
const size_t tempSize = std::numeric_limits<double>::digits10 + 10;
char tempBuffer[tempSize];
#ifdef _WIN32
const auto numChars = _sprintf_s_l(tempBuffer,
tempSize,
"%.*g",
utility::details::scoped_c_thread_locale::c_locale(),
std::numeric_limits<double>::digits10 + 2,
m_number.m_value);
#else
const auto numChars =
snprintf(tempBuffer, tempSize, "%.*g", std::numeric_limits<double>::digits10 + 2, m_number.m_value);
#endif
stream.append(tempBuffer, numChars);
}
}
#ifdef _WIN32
void web::json::details::_String::format(std::basic_string<wchar_t>& str) const
{
str.push_back(L'"');
if (m_has_escape_char)
{
append_escape_string(str, m_string);
}
else
{
str.append(m_string);
}
str.push_back(L'"');
}
void web::json::details::_Number::format(std::basic_string<wchar_t>& stream) const
{
if (m_number.m_type != number::type::double_type)
{
// #digits + 1 to avoid loss + 1 for the sign + 1 for null terminator.
const size_t tempSize = std::numeric_limits<uint64_t>::digits10 + 3;
wchar_t tempBuffer[tempSize];
if (m_number.m_type == number::type::signed_type)
_i64tow_s(m_number.m_intval, tempBuffer, tempSize, 10);
else
_ui64tow_s(m_number.m_uintval, tempBuffer, tempSize, 10);
stream.append(tempBuffer, wcsnlen_s(tempBuffer, tempSize));
}
else
{
// #digits + 2 to avoid loss + 1 for the sign + 1 for decimal point + 5 for exponent (e+xxx) + 1 for null
// terminator
const size_t tempSize = std::numeric_limits<double>::digits10 + 10;
wchar_t tempBuffer[tempSize];
const int numChars = _swprintf_s_l(tempBuffer,
tempSize,
L"%.*g",
utility::details::scoped_c_thread_locale::c_locale(),
std::numeric_limits<double>::digits10 + 2,
m_number.m_value);
stream.append(tempBuffer, numChars);
}
}
#endif
const utility::string_t& web::json::details::_String::as_string() const { return m_string; }
const utility::string_t& web::json::value::as_string() const { return m_value->as_string(); }
utility::string_t json::value::serialize() const
{
#ifndef _WIN32
utility::details::scoped_c_thread_locale locale;
#endif
return m_value->to_string();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,260 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#include "pch.h"
using namespace web;
using namespace utility;
std::vector<unsigned char> _from_base64(const utility::string_t& str);
utility::string_t _to_base64(const unsigned char* ptr, size_t size);
std::vector<unsigned char> __cdecl conversions::from_base64(const utility::string_t& str) { return _from_base64(str); }
utility::string_t __cdecl conversions::to_base64(const std::vector<unsigned char>& input)
{
if (input.size() == 0)
{
// return empty string
return utility::string_t();
}
return _to_base64(&input[0], input.size());
}
utility::string_t __cdecl conversions::to_base64(uint64_t input)
{
return _to_base64(reinterpret_cast<const unsigned char*>(&input), sizeof(input));
}
static const char* _base64_enctbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const std::array<unsigned char, 128> _base64_dectbl = {
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62,
255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, 255, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255}};
struct _triple_byte
{
unsigned char _1_1 : 2;
unsigned char _0 : 6;
unsigned char _2_1 : 4;
unsigned char _1_2 : 4;
unsigned char _3 : 6;
unsigned char _2_2 : 2;
};
struct _double_byte
{
unsigned char _1_1 : 2;
unsigned char _0 : 6;
unsigned char _2_1 : 4;
unsigned char _1_2 : 4;
};
struct _single_byte
{
unsigned char _1_1 : 2;
unsigned char _0 : 6;
};
//
// A note on the implementation of BASE64 encoding and decoding:
//
// This is a fairly basic and naive implementation; there is probably a lot of room for
// performance improvement, as well as for adding options such as support for URI-safe base64,
// ignoring CRLF, relaxed validation rules, etc. The decoder is currently pretty strict.
//
#ifdef __GNUC__
// gcc is concerned about the bitfield uses in the code, something we simply need to ignore.
#pragma GCC diagnostic ignored "-Wconversion"
#endif
std::vector<unsigned char> _from_base64(const utility::string_t& input)
{
std::vector<unsigned char> result;
if (input.empty()) return result;
size_t padding = 0;
// Validation
{
auto size = input.size();
if ((size % 4) != 0)
{
throw std::runtime_error("length of base64 string is not an even multiple of 4");
}
for (auto iter = input.begin(); iter != input.end(); ++iter, --size)
{
const size_t ch_sz = static_cast<size_t>(*iter);
if (ch_sz >= _base64_dectbl.size() || _base64_dectbl[ch_sz] == 255)
{
throw std::runtime_error("invalid character found in base64 string");
}
if (_base64_dectbl[ch_sz] == 254)
{
padding++;
// padding only at the end
if (size > 2)
{
throw std::runtime_error("invalid padding character found in base64 string");
}
if (size == 2)
{
const size_t ch2_sz = static_cast<size_t>(*(iter + 1));
if (ch2_sz >= _base64_dectbl.size() || _base64_dectbl[ch2_sz] != 254)
{
throw std::runtime_error("invalid padding character found in base64 string");
}
}
}
}
}
auto size = input.size();
const char_t* ptr = &input[0];
auto outsz = (size / 4) * 3;
outsz -= padding;
result.resize(outsz);
size_t idx = 0;
for (; size > 4; ++idx)
{
unsigned char target[3];
memset(target, 0, sizeof(target));
_triple_byte* record = reinterpret_cast<_triple_byte*>(target);
unsigned char val0 = _base64_dectbl[ptr[0]];
unsigned char val1 = _base64_dectbl[ptr[1]];
unsigned char val2 = _base64_dectbl[ptr[2]];
unsigned char val3 = _base64_dectbl[ptr[3]];
record->_0 = val0;
record->_1_1 = val1 >> 4;
result[idx] = target[0];
record->_1_2 = val1 & 0xF;
record->_2_1 = val2 >> 2;
result[++idx] = target[1];
record->_2_2 = val2 & 0x3;
record->_3 = val3 & 0x3F;
result[++idx] = target[2];
ptr += 4;
size -= 4;
}
// Handle the last four bytes separately, to avoid having the conditional statements
// in all the iterations (a performance issue).
{
unsigned char target[3];
memset(target, 0, sizeof(target));
_triple_byte* record = reinterpret_cast<_triple_byte*>(target);
unsigned char val0 = _base64_dectbl[ptr[0]];
unsigned char val1 = _base64_dectbl[ptr[1]];
unsigned char val2 = _base64_dectbl[ptr[2]];
unsigned char val3 = _base64_dectbl[ptr[3]];
record->_0 = val0;
record->_1_1 = val1 >> 4;
result[idx] = target[0];
record->_1_2 = val1 & 0xF;
if (val2 != 254)
{
record->_2_1 = val2 >> 2;
result[++idx] = target[1];
}
else
{
// There shouldn't be any information (ones) in the unused bits,
if (record->_1_2 != 0)
{
throw std::runtime_error("Invalid end of base64 string");
}
return result;
}
record->_2_2 = val2 & 0x3;
if (val3 != 254)
{
record->_3 = val3 & 0x3F;
result[++idx] = target[2];
}
else
{
// There shouldn't be any information (ones) in the unused bits.
if (record->_2_2 != 0)
{
throw std::runtime_error("Invalid end of base64 string");
}
return result;
}
}
return result;
}
utility::string_t _to_base64(const unsigned char* ptr, size_t size)
{
utility::string_t result;
for (; size >= 3;)
{
const _triple_byte* record = reinterpret_cast<const _triple_byte*>(ptr);
unsigned char idx0 = record->_0;
unsigned char idx1 = (record->_1_1 << 4) | record->_1_2;
unsigned char idx2 = (record->_2_1 << 2) | record->_2_2;
unsigned char idx3 = record->_3;
result.push_back(char_t(_base64_enctbl[idx0]));
result.push_back(char_t(_base64_enctbl[idx1]));
result.push_back(char_t(_base64_enctbl[idx2]));
result.push_back(char_t(_base64_enctbl[idx3]));
size -= 3;
ptr += 3;
}
switch (size)
{
case 1:
{
const _single_byte* record = reinterpret_cast<const _single_byte*>(ptr);
unsigned char idx0 = record->_0;
unsigned char idx1 = (record->_1_1 << 4);
result.push_back(char_t(_base64_enctbl[idx0]));
result.push_back(char_t(_base64_enctbl[idx1]));
result.push_back('=');
result.push_back('=');
break;
}
case 2:
{
const _double_byte* record = reinterpret_cast<const _double_byte*>(ptr);
unsigned char idx0 = record->_0;
unsigned char idx1 = (record->_1_1 << 4) | record->_1_2;
unsigned char idx2 = (record->_2_1 << 2);
result.push_back(char_t(_base64_enctbl[idx0]));
result.push_back(char_t(_base64_enctbl[idx1]));
result.push_back(char_t(_base64_enctbl[idx2]));
result.push_back('=');
break;
}
}
return result;
}

View File

@ -1,157 +0,0 @@
/***
* Copyright (C) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
*
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* Credential and proxy utilities.
*
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#include "pch.h"
#include <assert.h>
#if defined(_WIN32) && !defined(__cplusplus_winrt)
#include <Wincrypt.h>
#endif
#if defined(__cplusplus_winrt)
#include <robuffer.h>
#endif
namespace web
{
namespace details
{
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
#if defined(__cplusplus_winrt)
// Helper function to zero out memory of an IBuffer.
void winrt_secure_zero_buffer(Windows::Storage::Streams::IBuffer ^ buffer)
{
Microsoft::WRL::ComPtr<IInspectable> bufferInspectable(reinterpret_cast<IInspectable*>(buffer));
Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
bufferInspectable.As(&bufferByteAccess);
// This shouldn't happen but if can't get access to the raw bytes for some reason
// then we can't zero out.
byte* rawBytes;
if (bufferByteAccess->Buffer(&rawBytes) == S_OK)
{
SecureZeroMemory(rawBytes, buffer->Length);
}
}
winrt_encryption::winrt_encryption(const std::wstring& data)
{
auto provider = ref new Windows::Security::Cryptography::DataProtection::DataProtectionProvider(
ref new Platform::String(L"Local=user"));
// Create buffer containing plain text password.
Platform::ArrayReference<unsigned char> arrayref(
reinterpret_cast<unsigned char*>(const_cast<std::wstring::value_type*>(data.c_str())),
static_cast<unsigned int>(data.size()) * sizeof(std::wstring::value_type));
Windows::Storage::Streams::IBuffer ^ plaintext =
Windows::Security::Cryptography::CryptographicBuffer::CreateFromByteArray(arrayref);
m_buffer = pplx::create_task(provider->ProtectAsync(plaintext));
m_buffer.then(
[plaintext](pplx::task<Windows::Storage::Streams::IBuffer ^>) { winrt_secure_zero_buffer(plaintext); });
}
plaintext_string winrt_encryption::decrypt() const
{
// To fully guarantee asynchrony would require significant impact on existing code. This code path
// is never run on a user's thread and is only done once when setting up a connection.
auto encrypted = m_buffer.get();
auto provider = ref new Windows::Security::Cryptography::DataProtection::DataProtectionProvider();
auto plaintext = pplx::create_task(provider->UnprotectAsync(encrypted)).get();
// Get access to raw bytes in plain text buffer.
Microsoft::WRL::ComPtr<IInspectable> bufferInspectable(reinterpret_cast<IInspectable*>(plaintext));
Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
bufferInspectable.As(&bufferByteAccess);
byte* rawPlaintext;
const auto& result = bufferByteAccess->Buffer(&rawPlaintext);
if (result != S_OK)
{
throw ::utility::details::create_system_error(result);
}
// Construct string and zero out memory from plain text buffer.
auto data = plaintext_string(
new std::wstring(reinterpret_cast<const std::wstring::value_type*>(rawPlaintext), plaintext->Length / 2));
SecureZeroMemory(rawPlaintext, plaintext->Length);
return std::move(data);
}
#else
win32_encryption::win32_encryption(const std::wstring& data) : m_numCharacters(data.size())
{
// Early return because CryptProtectMemory crashes with empty string
if (m_numCharacters == 0)
{
return;
}
if (data.size() > (std::numeric_limits<DWORD>::max)() / sizeof(wchar_t))
{
throw std::length_error("Encryption string too long");
}
const auto dataSizeDword = static_cast<DWORD>(data.size() * sizeof(wchar_t));
// Round up dataSizeDword to be a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE
static_assert(CRYPTPROTECTMEMORY_BLOCK_SIZE == 16, "Power of 2 assumptions in this bit masking violated");
const auto mask = static_cast<DWORD>(CRYPTPROTECTMEMORY_BLOCK_SIZE - 1u);
const auto dataNumBytes = (dataSizeDword & ~mask) + ((dataSizeDword & mask) != 0) * CRYPTPROTECTMEMORY_BLOCK_SIZE;
assert((dataNumBytes % CRYPTPROTECTMEMORY_BLOCK_SIZE) == 0);
assert(dataNumBytes >= dataSizeDword);
m_buffer.resize(dataNumBytes);
memcpy_s(m_buffer.data(), m_buffer.size(), data.c_str(), dataNumBytes);
if (!CryptProtectMemory(m_buffer.data(), dataNumBytes, CRYPTPROTECTMEMORY_SAME_PROCESS))
{
throw ::utility::details::create_system_error(GetLastError());
}
}
win32_encryption::~win32_encryption() { SecureZeroMemory(m_buffer.data(), m_buffer.size()); }
plaintext_string win32_encryption::decrypt() const
{
// Copy the buffer and decrypt to avoid having to re-encrypt.
auto result = plaintext_string(new std::wstring(reinterpret_cast<const std::wstring::value_type*>(m_buffer.data()),
m_buffer.size() / sizeof(wchar_t)));
auto& data = *result;
if (!m_buffer.empty())
{
if (!CryptUnprotectMemory(&data[0], static_cast<DWORD>(m_buffer.size()), CRYPTPROTECTMEMORY_SAME_PROCESS))
{
throw ::utility::details::create_system_error(GetLastError());
}
assert(m_numCharacters <= m_buffer.size());
SecureZeroMemory(&data[m_numCharacters], data.size() - m_numCharacters);
data.erase(m_numCharacters);
}
return result;
}
#endif
#endif
void zero_memory_deleter::operator()(::utility::string_t* data) const
{
CASABLANCA_UNREFERENCED_PARAMETER(data);
#if defined(_WIN32)
SecureZeroMemory(&(*data)[0], data->size() * sizeof(::utility::string_t::value_type));
delete data;
#endif
}
} // namespace details
} // namespace web

View File

@ -10,9 +10,6 @@
General project organization:
#### The [`deps`](/deps) folder
Contains other projects that PowerToys uses as dependencies.
#### The [`doc`](/doc) folder
Documentation for the project, including a [coding guide](/doc/coding) and [design docs](/doc/specs).

View File

@ -15,48 +15,45 @@ namespace UnitTestsCommonLib
TEST_METHOD(LoadFromJsonBoolTrue)
{
PowerToyValues values = PowerToyValues::from_json_string(m_json);
Assert::IsTrue(values.is_bool_value(L"bool_toggle_true"));
bool value = values.get_bool_value(L"bool_toggle_true");
Assert::AreEqual(true, value);
auto value = values.get_bool_value(L"bool_toggle_true");
Assert::IsTrue(value.has_value());
Assert::AreEqual(true, *value);
}
TEST_METHOD(LoadFromJsonBoolFalse)
{
PowerToyValues values = PowerToyValues::from_json_string(m_json);
Assert::IsTrue(values.is_bool_value(L"bool_toggle_false"));
bool value = values.get_bool_value(L"bool_toggle_false");
Assert::AreEqual(false, value);
auto value = values.get_bool_value(L"bool_toggle_false");
Assert::IsTrue(value.has_value());
Assert::AreEqual(false, *value);
}
TEST_METHOD(LoadFromJsonInt)
{
PowerToyValues values = PowerToyValues::from_json_string(m_json);
Assert::IsTrue(values.is_int_value(L"int_spinner"));
int value = values.get_int_value(L"int_spinner");
Assert::AreEqual(10, value);
auto value = values.get_int_value(L"int_spinner");
Assert::IsTrue(value.has_value());
Assert::AreEqual(10, *value);
}
TEST_METHOD(LoadFromJsonString)
{
PowerToyValues values = PowerToyValues::from_json_string(m_json);
Assert::IsTrue(values.is_string_value(L"string_text"));
auto value = values.get_string_value(L"string_text");
std::wstring value = values.get_string_value(L"string_text");
Assert::IsTrue(value.has_value());
std::wstring expected = L"a quick fox";
Assert::AreEqual(expected, value);
Assert::AreEqual(expected, *value);
}
TEST_METHOD(LoadFromJsonColorPicker)
{
PowerToyValues values = PowerToyValues::from_json_string(m_json);
Assert::IsTrue(values.is_string_value(L"color_picker"));
auto value = values.get_string_value(L"color_picker");
std::wstring value = values.get_string_value(L"color_picker");
Assert::IsTrue(value.has_value());
std::wstring expected = L"#ff8d12";
Assert::AreEqual(expected, value);
Assert::AreEqual(expected, *value);
}
};
}

View File

@ -98,6 +98,7 @@
<ClInclude Include="d2d_window.h" />
<ClInclude Include="dpi_aware.h" />
<ClInclude Include="hwnd_data_cache.h" />
<ClInclude Include="json.h" />
<ClInclude Include="monitors.h" />
<ClInclude Include="on_thread_executor.h" />
<ClInclude Include="pch.h" />
@ -119,6 +120,7 @@
<ClCompile Include="d2d_window.cpp" />
<ClCompile Include="dpi_aware.cpp" />
<ClCompile Include="hwnd_data_cache.cpp" />
<ClCompile Include="json.cpp" />
<ClCompile Include="monitors.cpp" />
<ClCompile Include="on_thread_executor.cpp" />
<ClCompile Include="pch.cpp">
@ -132,11 +134,6 @@
<ClCompile Include="common.cpp" />
<ClCompile Include="windows_colors.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\deps\cpprestsdk\cpprestsdk.vcxproj">
<Project>{4e577735-dfab-41af-8a6e-b6e8872a2928}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -75,6 +75,9 @@
<ClInclude Include="hwnd_data_cache.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="json.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="d2d_svg.cpp">
@ -120,5 +123,8 @@
<ClCompile Include="hwnd_data_cache.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="json.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

26
src/common/json.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "pch.h"
#include "json.h"
#include <fstream>
namespace json
{
std::optional<JsonObject> from_file(std::wstring_view file_name)
{
try
{
std::wifstream file(file_name.data(), std::ios::binary);
using isbi = std::istreambuf_iterator<wchar_t>;
return JsonValue::Parse(std::wstring{isbi{file}, isbi{}}).GetObjectW();
}
catch(...)
{
return std::nullopt;
}
}
void to_file(std::wstring_view file_name, const JsonObject & obj)
{
std::wofstream{file_name.data(), std::ios::binary} << obj.Stringify().c_str();
}
}

50
src/common/json.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Data.Json.h>
#include <optional>
namespace json
{
using namespace winrt::Windows::Data::Json;
std::optional<JsonObject> from_file(std::wstring_view file_name);
void to_file(std::wstring_view file_name, const JsonObject& obj);
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
}
}

View File

@ -4,12 +4,13 @@
#include <fstream>
namespace PTSettingsHelper {
constexpr inline const wchar_t * settings_filename = L"\\settings.json";
std::wstring get_root_save_folder_location() {
PWSTR local_app_path;
std::wstring result(L"");
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
result = std::wstring(local_app_path);
std::wstring result{local_app_path};
CoTaskMemFree(local_app_path);
result += L"\\Microsoft\\PowerToys";
@ -20,7 +21,7 @@ namespace PTSettingsHelper {
return result;
}
std::wstring get_module_save_folder_location(const std::wstring& powertoy_name) {
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name) {
std::wstring result = get_root_save_folder_location();
result += L"\\";
result += powertoy_name;
@ -31,45 +32,33 @@ namespace PTSettingsHelper {
return result;
}
std::wstring get_module_save_file_location(const std::wstring& powertoy_name) {
std::wstring result = get_module_save_folder_location(powertoy_name);
result += L"\\settings.json";
return result;
std::wstring get_module_save_file_location(std::wstring_view powertoy_name) {
return get_module_save_folder_location(powertoy_name) + settings_filename;
}
std::wstring get_powertoys_general_save_file_location() {
std::wstring result = get_root_save_folder_location();
result += L"\\settings.json";
return result;
return get_root_save_folder_location() + settings_filename;
}
void save_module_settings(const std::wstring& powertoy_name, web::json::value& settings) {
std::wstring save_file_location = get_module_save_file_location(powertoy_name);
std::ofstream save_file(save_file_location, std::ios::binary);
settings.serialize(save_file);
save_file.close();
void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings) {
const std::wstring save_file_location = get_module_save_file_location(powertoy_name);
json::to_file(save_file_location, settings);
}
web::json::value load_module_settings(const std::wstring& powertoy_name) {
std::wstring save_file_location = get_module_save_file_location(powertoy_name);
std::ifstream save_file(save_file_location, std::ios::binary);
web::json::value result = web::json::value::parse(save_file);
save_file.close();
return result;
json::JsonObject load_module_settings(std::wstring_view powertoy_name) {
const std::wstring save_file_location = get_module_save_file_location(powertoy_name);
auto saved_settings = json::from_file(save_file_location);
return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{};
}
void save_general_settings(web::json::value& settings) {
std::wstring save_file_location = get_powertoys_general_save_file_location();
std::ofstream save_file(save_file_location, std::ios::binary);
settings.serialize(save_file);
save_file.close();
void save_general_settings(const json::JsonObject& settings) {
const std::wstring save_file_location = get_powertoys_general_save_file_location();
json::to_file(save_file_location, settings);
}
web::json::value load_general_settings() {
std::wstring save_file_location = get_powertoys_general_save_file_location();
std::ifstream save_file(save_file_location, std::ios::binary);
web::json::value result = web::json::value::parse(save_file);
save_file.close();
return result;
json::JsonObject load_general_settings() {
const std::wstring save_file_location = get_powertoys_general_save_file_location();
auto saved_settings = json::from_file(save_file_location);
return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{};
}
}

View File

@ -1,13 +1,14 @@
#pragma once
#include <string>
#include <Shlobj.h>
#include <cpprest/json.h>
#include "json.h"
namespace PTSettingsHelper {
void save_module_settings(const std::wstring& powertoy_name, web::json::value& settings);
web::json::value load_module_settings(const std::wstring& powertoy_name);
void save_general_settings(web::json::value& settings);
web::json::value load_general_settings();
void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings);
json::JsonObject load_module_settings(std::wstring_view powertoy_name);
void save_general_settings(const json::JsonObject& settings);
json::JsonObject load_general_settings();
}

View File

@ -4,128 +4,127 @@
namespace PowerToysSettings {
Settings::Settings(const HINSTANCE hinstance, const std::wstring& powertoy_name) {
Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name) {
m_instance = hinstance;
m_json = web::json::value::object();
m_json.as_object()[L"version"] = web::json::value::string(L"1.0");
m_json.as_object()[L"name"] = web::json::value::string(powertoy_name);
m_json.as_object()[L"properties"] = web::json::value::object();
m_json.SetNamedValue(L"version", json::value(L"1.0"));
m_json.SetNamedValue(L"name", json::value(powertoy_name));
m_json.SetNamedValue(L"properties", json::JsonObject{});
}
void Settings::set_description(UINT resource_id) {
m_json.as_object()[L"description"] = web::json::value::string(get_resource(resource_id));
m_json.SetNamedValue(L"description", json::value(get_resource(resource_id)));
}
void Settings::set_description(const std::wstring& description) {
m_json.as_object()[L"description"] = web::json::value::string(description);
void Settings::set_description(std::wstring_view description) {
m_json.SetNamedValue(L"description", json::value(description));
}
void Settings::set_icon_key(const std::wstring& icon_key) {
m_json.as_object()[L"icon_key"] = web::json::value::string(icon_key);
void Settings::set_icon_key(std::wstring_view icon_key) {
m_json.SetNamedValue(L"icon_key", json::value(icon_key));
}
void Settings::set_overview_link(const std::wstring& overview_link) {
m_json.as_object()[L"overview_link"] = web::json::value::string(overview_link);
void Settings::set_overview_link(std::wstring_view overview_link) {
m_json.SetNamedValue(L"overview_link", json::value(overview_link));
}
void Settings::set_video_link(const std::wstring& video_link) {
m_json.as_object()[L"video_link"] = web::json::value::string(video_link);
void Settings::set_video_link(std::wstring_view video_link) {
m_json.SetNamedValue(L"video_link", json::value(video_link));
}
// add_bool_toogle overloads.
void Settings::add_bool_toogle(const std::wstring& name, UINT description_resource_id, bool value) {
void Settings::add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value) {
add_bool_toogle(name, get_resource(description_resource_id), value);
}
void Settings::add_bool_toogle(const std::wstring& name, const std::wstring& description, bool value) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"bool_toggle");
item.as_object()[L"value"] = web::json::value::boolean(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
void Settings::add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value) {
json::JsonObject toggle;
toggle.SetNamedValue(L"display_name", json::value(description));
toggle.SetNamedValue(L"editor_type", json::value(L"bool_toggle"));
toggle.SetNamedValue(L"value", json::value(value));
toggle.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, toggle);
}
// add_int_spinner overloads.
void Settings::add_int_spinner(const std::wstring& name, UINT description_resource_id, int value, int min, int max, int step) {
void Settings::add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step) {
add_int_spinner(name, get_resource(description_resource_id), value, min, max, step);
}
void Settings::add_int_spinner(const std::wstring& name, const std::wstring& description, int value, int min, int max, int step) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"int_spinner");
item.as_object()[L"value"] = web::json::value::number(value);
item.as_object()[L"min"] = web::json::value::number(min);
item.as_object()[L"max"] = web::json::value::number(max);
item.as_object()[L"step"] = web::json::value::number(step);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
void Settings::add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step) {
json::JsonObject spinner;
spinner.SetNamedValue(L"display_name", json::value(description));
spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner"));
spinner.SetNamedValue(L"value", json::value(value));
spinner.SetNamedValue(L"min", json::value(min));
spinner.SetNamedValue(L"max", json::value(max));
spinner.SetNamedValue(L"step", json::value(step));
spinner.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, spinner);
}
// add_string overloads.
void Settings::add_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value) {
void Settings::add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) {
add_string(name, get_resource(description_resource_id), value);
}
void Settings::add_string(const std::wstring& name, const std::wstring& description, const std::wstring& value) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"string_text");
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) {
json::JsonObject string;
string.SetNamedValue(L"display_name", json::value(description));
string.SetNamedValue(L"editor_type", json::value(L"string_text"));
string.SetNamedValue(L"value", json::value(value));
string.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, string);
}
// add_multiline_string overloads.
void Settings::add_multiline_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value) {
void Settings::add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) {
add_multiline_string(name, get_resource(description_resource_id), value);
}
void Settings::add_multiline_string(const std::wstring& name, const std::wstring& description, const std::wstring& value) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"string_text");
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
item.as_object()[L"multiline"] = web::json::value::boolean(true);
void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) {
json::JsonObject ml_string;
ml_string.SetNamedValue(L"display_name", json::value(description));
ml_string.SetNamedValue(L"editor_type", json::value(L"string_text"));
ml_string.SetNamedValue(L"value", json::value(value));
ml_string.SetNamedValue(L"order", json::value(++m_curr_priority));
ml_string.SetNamedValue(L"multiline", json::value(true));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, ml_string);
}
// add_color_picker overloads.
void Settings::add_color_picker(const std::wstring& name, UINT description_resource_id, const std::wstring& value) {
void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value) {
add_color_picker(name, get_resource(description_resource_id), value);
}
void Settings::add_color_picker(const std::wstring& name, const std::wstring& description, const std::wstring& value) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"color_picker");
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value) {
json::JsonObject picker;
picker.SetNamedValue(L"display_name", json::value(description));
picker.SetNamedValue(L"editor_type", json::value(L"color_picker"));
picker.SetNamedValue(L"value", json::value(value));
picker.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, picker);
}
void Settings::add_hotkey(const std::wstring& name, UINT description_resource_id, const HotkeyObject& hotkey) {
void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey) {
add_hotkey(name, get_resource(description_resource_id), hotkey);
}
void Settings::add_hotkey(const std::wstring& name, const std::wstring& description, const HotkeyObject& hotkey) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"hotkey");
item.as_object()[L"value"] = hotkey.get_json();
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
void Settings::add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey_obj) {
json::JsonObject hotkey;
hotkey.SetNamedValue(L"display_name", json::value(description));
hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey"));
hotkey.SetNamedValue(L"value", hotkey_obj.get_json());
hotkey.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, hotkey);
}
void Settings::add_choice_group(const std::wstring& name, UINT description_resource_id, const std::wstring& value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) {
void Settings::add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) {
std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts;
keys_and_texts.reserve(keys_and_text_ids.size());
for (const auto& kv : keys_and_text_ids) {
@ -134,25 +133,25 @@ namespace PowerToysSettings {
add_choice_group(name, get_resource(description_resource_id), value, keys_and_texts);
}
void Settings::add_choice_group(const std::wstring& name, const std::wstring& description, const std::wstring& value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"choice_group");
auto options = web::json::value::array(keys_and_texts.size());
for (std::size_t i = 0; i < keys_and_texts.size(); ++i) {
auto entry = web::json::value::object();
entry.as_object()[L"key"] = web::json::value::string(keys_and_texts[i].first);
entry.as_object()[L"text"] = web::json::value::string(keys_and_texts[i].second);
options.as_array()[i] = entry;
void Settings::add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) {
json::JsonObject choice_group;
choice_group.SetNamedValue(L"display_name", json::value(description));
choice_group.SetNamedValue(L"editor_type", json::value(L"choice_group"));
json::JsonArray options;
for(const auto & [key, text] : keys_and_texts) {
json::JsonObject entry;
entry.SetNamedValue(L"key", json::value(key));
entry.SetNamedValue(L"text", json::value(text));
options.Append(std::move(entry));
}
item.as_object()[L"options"] = options;
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
choice_group.SetNamedValue(L"options", std::move(options));
choice_group.SetNamedValue(L"value", json::value(value));
choice_group.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, choice_group);
}
void Settings::add_dropdown(const std::wstring& name, UINT description_resource_id, const std::wstring& value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) {
void Settings::add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids) {
std::vector<std::pair<std::wstring, std::wstring>> keys_and_texts;
keys_and_texts.reserve(keys_and_text_ids.size());
for (const auto& kv : keys_and_text_ids) {
@ -161,55 +160,55 @@ namespace PowerToysSettings {
add_dropdown(name, get_resource(description_resource_id), value, keys_and_texts);
}
void Settings::add_dropdown(const std::wstring& name, const std::wstring& description, const std::wstring& value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"editor_type"] = web::json::value::string(L"dropdown");
auto options = web::json::value::array(keys_and_texts.size());
for (std::size_t i = 0; i < keys_and_texts.size(); ++i) {
auto entry = web::json::value::object();
entry.as_object()[L"key"] = web::json::value::string(keys_and_texts[i].first);
entry.as_object()[L"text"] = web::json::value::string(keys_and_texts[i].second);
options.as_array()[i] = entry;
void Settings::add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts) {
json::JsonObject dropdown;
dropdown.SetNamedValue(L"display_name", json::value(description));
dropdown.SetNamedValue(L"editor_type", json::value(L"dropdown"));
json::JsonArray options;
for(const auto & [key, text] : keys_and_texts) {
json::JsonObject entry;
entry.SetNamedValue(L"key", json::value(key));
entry.SetNamedValue(L"text", json::value(text));
options.Append(std::move(entry));
}
item.as_object()[L"options"] = options;
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
dropdown.SetNamedValue(L"options", std::move(options));
dropdown.SetNamedValue(L"value", json::value(value));
dropdown.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, dropdown);
}
// add_custom_action overloads.
void Settings::add_custom_action(const std::wstring& name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id) {
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id) {
add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), get_resource(ext_description_resource_id));
}
void Settings::add_custom_action(const std::wstring& name, UINT description_resource_id, UINT button_text_resource_id, const std::wstring& value) {
void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value) {
add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), value);
}
void Settings::add_custom_action(const std::wstring& name, const std::wstring& description, const std::wstring& button_text, const std::wstring& value) {
web::json::value item = web::json::value::object();
item.as_object()[L"display_name"] = web::json::value::string(description);
item.as_object()[L"button_text"] = web::json::value::string(button_text);
item.as_object()[L"editor_type"] = web::json::value::string(L"custom_action");
item.as_object()[L"value"] = web::json::value::string(value);
item.as_object()[L"order"] = web::json::value::number(++m_curr_priority);
void Settings::add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value) {
json::JsonObject custom_action;
custom_action.SetNamedValue(L"display_name", json::value(description));
custom_action.SetNamedValue(L"button_text", json::value(button_text));
custom_action.SetNamedValue(L"editor_type", json::value(L"custom_action"));
custom_action.SetNamedValue(L"value", json::value(value));
custom_action.SetNamedValue(L"order", json::value(++m_curr_priority));
m_json.as_object()[L"properties"].as_object()[name] = item;
m_json.GetNamedObject(L"properties").SetNamedValue(name, custom_action);
}
// Serialization methods.
std::wstring Settings::serialize() {
return m_json.serialize();
return m_json.Stringify().c_str();
}
bool Settings::serialize_to_buffer(wchar_t* buffer, int *buffer_size) {
std::wstring result = m_json.serialize();
int result_len = (int)result.length();
auto result = m_json.Stringify();
const int result_len = (int)result.size() + 1;
if (buffer == nullptr || *buffer_size < result_len) {
*buffer_size = result_len + 1;
*buffer_size = result_len;
return false;
} else {
wcscpy_s(buffer, *buffer_size, result.c_str());
@ -220,110 +219,73 @@ namespace PowerToysSettings {
// Resource helper.
std::wstring Settings::get_resource(UINT resource_id) {
if (resource_id != 0) {
wchar_t buffer[512];
if (LoadString(m_instance, resource_id, buffer, ARRAYSIZE(buffer)) > 0) {
return std::wstring(buffer);
wchar_t* res_ptr;
const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast<wchar_t *>(&res_ptr), 0);
if (resource_length != 0) {
return {*reinterpret_cast<wchar_t **>(&res_ptr), resource_length};
}
}
return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id);
}
PowerToyValues::PowerToyValues(const std::wstring& powertoy_name) {
PowerToyValues::PowerToyValues(std::wstring_view powertoy_name) {
_name = powertoy_name;
m_json = web::json::value::object();
set_version();
m_json.as_object()[L"name"] = web::json::value::string(powertoy_name);
m_json.as_object()[L"properties"] = web::json::value::object();
m_json.SetNamedValue(L"name", json::value(powertoy_name));
m_json.SetNamedValue(L"properties", json::JsonObject{});
}
PowerToyValues PowerToyValues::from_json_string(const std::wstring& json) {
PowerToyValues PowerToyValues::from_json_string(std::wstring_view json) {
PowerToyValues result = PowerToyValues();
result.m_json = web::json::value::parse(json);
result._name = result.m_json.as_object()[L"name"].as_string();
result.m_json = json::JsonValue::Parse(json).GetObjectW();
result._name = result.m_json.GetNamedString(L"name");
return result;
}
PowerToyValues PowerToyValues::load_from_settings_file(const std::wstring & powertoy_name) {
PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_name) {
PowerToyValues result = PowerToyValues();
result.m_json = PTSettingsHelper::load_module_settings(powertoy_name);
result._name = powertoy_name;
return result;
}
template <typename T>
web::json::value add_property_generic(const std::wstring& name, T value) {
std::vector<std::pair<std::wstring, web::json::value>> vector = { std::make_pair(L"value", web::json::value(value)) };
return web::json::value::object(vector);
inline bool has_property(const json::JsonObject& o, std::wstring_view name, const json::JsonValueType type) {
const json::JsonObject props = o.GetNamedObject(L"properties", json::JsonObject{});
return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type);
}
template <>
void PowerToyValues::add_property(const std::wstring& name, bool value) {
m_json.as_object()[L"properties"].as_object()[name] = add_property_generic(name, value);
};
template <>
void PowerToyValues::add_property(const std::wstring& name, int value) {
m_json.as_object()[L"properties"].as_object()[name] = add_property_generic(name, value);
};
template <>
void PowerToyValues::add_property(const std::wstring& name, std::wstring value) {
m_json.as_object()[L"properties"].as_object()[name] = add_property_generic(name, value);
};
template <>
void PowerToyValues::add_property(const std::wstring& name, HotkeyObject value) {
m_json.as_object()[L"properties"].as_object()[name] = add_property_generic(name, value.get_json());
};
bool PowerToyValues::is_bool_value(const std::wstring& property_name) {
return m_json.is_object() &&
m_json.has_object_field(L"properties") &&
m_json[L"properties"].has_object_field(property_name) &&
m_json[L"properties"][property_name].has_boolean_field(L"value");
std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::Boolean)) {
return std::nullopt;
}
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value");
}
bool PowerToyValues::is_int_value(const std::wstring& property_name) {
return m_json.is_object() &&
m_json.has_object_field(L"properties") &&
m_json[L"properties"].has_object_field(property_name) &&
m_json[L"properties"][property_name].has_integer_field(L"value");
std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::Number)) {
return std::nullopt;
}
return static_cast<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value"));
}
bool PowerToyValues::is_string_value(const std::wstring& property_name) {
return m_json.is_object() &&
m_json.has_object_field(L"properties") &&
m_json[L"properties"].has_object_field(property_name) &&
m_json[L"properties"][property_name].has_string_field(L"value");
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::String)) {
return std::nullopt;
}
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str();
}
bool PowerToyValues::is_object_value(const std::wstring& property_name) {
return m_json.is_object() &&
m_json.has_object_field(L"properties") &&
m_json[L"properties"].has_object_field(property_name) &&
m_json[L"properties"][property_name].has_object_field(L"value");
}
bool PowerToyValues::get_bool_value(const std::wstring& property_name) {
return m_json[L"properties"][property_name][L"value"].as_bool();
}
int PowerToyValues::get_int_value(const std::wstring& property_name) {
return m_json[L"properties"][property_name][L"value"].as_integer();
}
std::wstring PowerToyValues::get_string_value(const std::wstring& property_name) {
return m_json[L"properties"][property_name][L"value"].as_string();
}
web::json::value PowerToyValues::get_json(const std::wstring& property_name) {
return m_json[L"properties"][property_name][L"value"];
std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name) {
if (!has_property(m_json, property_name, json::JsonValueType::Object)) {
return std::nullopt;
}
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value");
}
std::wstring PowerToyValues::serialize() {
set_version();
return m_json.serialize();
return m_json.Stringify().c_str();
}
void PowerToyValues::save_to_settings_file() {
@ -332,6 +294,6 @@ namespace PowerToysSettings {
}
void PowerToyValues::set_version() {
m_json.as_object()[L"version"] = web::json::value::string(m_version);
m_json.SetNamedValue(L"version", json::value(m_version));
}
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <string>
#include <cpprest/json.h>
#include "json.h"
namespace PowerToysSettings {
@ -10,45 +10,45 @@ namespace PowerToysSettings {
public:
Settings(
const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase'
const std::wstring& powertoy_name
std::wstring_view powertoy_name
);
// Add additional general information to the PowerToy settings.
void set_description(UINT resource_id);
void set_description(const std::wstring& description);
void set_description(std::wstring_view description);
void set_icon_key(const std::wstring& icon_key);
void set_overview_link(const std::wstring& overview_link);
void set_video_link(const std::wstring& video_link);
void set_icon_key(std::wstring_view icon_key);
void set_overview_link(std::wstring_view overview_link);
void set_video_link(std::wstring_view video_link);
// Add properties to the PowerToy settings.
void add_bool_toogle(const std::wstring& name, UINT description_resource_id, bool value);
void add_bool_toogle(const std::wstring& name, const std::wstring& description, bool value);
void add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value);
void add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value);
void add_int_spinner(const std::wstring& name, UINT description_resource_id, int value, int min, int max, int step);
void add_int_spinner(const std::wstring& name, const std::wstring& description, int value, int min, int max, int step);
void add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step);
void add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step);
void add_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value);
void add_string(const std::wstring& name, const std::wstring& description, const std::wstring& value);
void add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value);
void add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value);
void add_multiline_string(const std::wstring& name, UINT description_resource_id, const std::wstring& value);
void add_multiline_string(const std::wstring& name, const std::wstring& description, const std::wstring& value);
void add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value);
void add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value);
void add_color_picker(const std::wstring& name, UINT description_resource_id, const std::wstring& value);
void add_color_picker(const std::wstring& name, const std::wstring& description, const std::wstring& value);
void add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value);
void add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value);
void add_hotkey(const std::wstring& name, UINT description_resource_id, const HotkeyObject& hotkey);
void add_hotkey(const std::wstring& name, const std::wstring& description, const HotkeyObject& hotkey);
void add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey);
void add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey);
void add_choice_group(const std::wstring& name, UINT description_resource_id, const std::wstring& value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids);
void add_choice_group(const std::wstring& name, const std::wstring& description, const std::wstring& value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts);
void add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids);
void add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts);
void add_dropdown(const std::wstring& name, UINT description_resource_id, const std::wstring& value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids);
void add_dropdown(const std::wstring& name, const std::wstring& description, const std::wstring& value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts);
void add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids);
void add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts);
void add_custom_action(const std::wstring& name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id);
void add_custom_action(const std::wstring& name, UINT description_resource_id, UINT button_text_resource_id, const std::wstring& value);
void add_custom_action(const std::wstring& name, const std::wstring& description, const std::wstring& button_text, const std::wstring& value);
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id);
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value);
void add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value);
// Serialize the internal json to a string.
@ -57,7 +57,7 @@ namespace PowerToysSettings {
bool serialize_to_buffer(wchar_t* buffer, int* buffer_size);
private:
web::json::value m_json;
json::JsonObject m_json;
int m_curr_priority = 0; // For keeping order when adding elements.
HINSTANCE m_instance;
@ -66,24 +66,22 @@ namespace PowerToysSettings {
class PowerToyValues {
public:
PowerToyValues(const std::wstring& powertoy_name);
static PowerToyValues from_json_string(const std::wstring& json);
static PowerToyValues load_from_settings_file(const std::wstring& powertoy_name);
PowerToyValues(std::wstring_view powertoy_name);
static PowerToyValues from_json_string(std::wstring_view json);
static PowerToyValues load_from_settings_file(std::wstring_view powertoy_name);
template <typename T>
void add_property(const std::wstring& name, T value);
inline void add_property(std::wstring_view name, T value)
{
json::JsonObject prop_value;
prop_value.SetNamedValue(L"value", json::value(value));
m_json.GetNamedObject(L"properties").SetNamedValue(name, prop_value);
}
// Check property value type
bool is_bool_value(const std::wstring& property_name);
bool is_int_value(const std::wstring& property_name);
bool is_string_value(const std::wstring& property_name);
bool is_object_value(const std::wstring& property_name);
// Get property value
bool get_bool_value(const std::wstring& property_name);
int get_int_value(const std::wstring& property_name);
std::wstring get_string_value(const std::wstring& property_name);
web::json::value get_json(const std::wstring& property_name);
std::optional<bool> get_bool_value(std::wstring_view property_name);
std::optional<int> get_int_value(std::wstring_view property_name);
std::optional<std::wstring> get_string_value(std::wstring_view property_name);
std::optional<json::JsonObject> get_json(std::wstring_view property_name);
std::wstring serialize();
void save_to_settings_file();
@ -91,60 +89,58 @@ namespace PowerToysSettings {
private:
const std::wstring m_version = L"1.0";
void set_version();
web::json::value m_json;
json::JsonObject m_json;
std::wstring _name;
PowerToyValues() {}
};
class CustomActionObject {
public:
static CustomActionObject from_json_string(const std::wstring& json) {
web::json::value parsed_json = web::json::value::parse(json);
return CustomActionObject(parsed_json);
static CustomActionObject from_json_string(std::wstring_view json) {
return CustomActionObject(json::JsonValue::Parse(json).GetObjectW());
}
std::wstring get_name() { return m_json[L"action_name"].as_string(); }
std::wstring get_value() { return m_json[L"value"].as_string(); }
std::wstring get_name() { return m_json.GetNamedString(L"action_name").c_str(); }
std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); }
protected:
CustomActionObject(web::json::value action_json) : m_json(action_json) {};
web::json::value m_json;
CustomActionObject(json::JsonObject action_json) : m_json(std::move(action_json)) {};
json::JsonObject m_json;
};
class HotkeyObject {
public:
static HotkeyObject from_json(web::json::value json) {
return HotkeyObject(json);
static HotkeyObject from_json(json::JsonObject json) {
return HotkeyObject(std::move(json));
}
static HotkeyObject from_json_string(const std::wstring& json) {
web::json::value parsed_json = web::json::value::parse(json);
return HotkeyObject(parsed_json);
static HotkeyObject from_json_string(std::wstring_view json) {
return HotkeyObject(json::JsonValue::Parse(json).GetObjectW());
}
static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code) {
web::json::value json = web::json::value::object();
json.as_object()[L"win"] = web::json::value::boolean(win_pressed);
json.as_object()[L"ctrl"] = web::json::value::boolean(ctrl_pressed);
json.as_object()[L"alt"] = web::json::value::boolean(alt_pressed);
json.as_object()[L"shift"] = web::json::value::boolean(shift_pressed);
json.as_object()[L"code"] = web::json::value::number(vk_code);
json.as_object()[L"key"] = web::json::value::string(key_from_code(vk_code));
return HotkeyObject(json);
json::JsonObject json;
json.SetNamedValue(L"win", json::value(win_pressed));
json.SetNamedValue(L"ctrl", json::value(ctrl_pressed));
json.SetNamedValue(L"alt", json::value(alt_pressed));
json.SetNamedValue(L"shift", json::value(shift_pressed));
json.SetNamedValue(L"code", json::value(vk_code));
json.SetNamedValue(L"key", json::value(key_from_code(vk_code)));
return std::move(json);
}
const web::json::value& get_json() const { return m_json; }
const json::JsonObject& get_json() const { return m_json; }
std::wstring get_key() { return m_json[L"key"].as_string(); }
UINT get_code() { return m_json[L"code"].as_integer(); }
bool win_pressed() { return m_json[L"win"].as_bool(); }
bool ctrl_pressed() { return m_json[L"ctrl"].as_bool(); }
bool alt_pressed() { return m_json[L"alt"].as_bool(); }
bool shift_pressed() { return m_json[L"shift"].as_bool(); }
UINT get_modifiers_repeat() {
std::wstring get_key() const { return m_json.GetNamedString(L"key").c_str(); }
UINT get_code() const { return static_cast<UINT>(m_json.GetNamedNumber(L"code")); }
bool win_pressed() const { return m_json.GetNamedBoolean(L"win"); }
bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); }
bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); }
bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); }
UINT get_modifiers_repeat() const {
return (win_pressed() ? MOD_WIN : 0) |
(ctrl_pressed() ? MOD_CONTROL : 0) |
(alt_pressed() ? MOD_ALT : 0) |
(shift_pressed() ? MOD_SHIFT : 0);
}
UINT get_modifiers() {
UINT get_modifiers() const {
return get_modifiers_repeat() | MOD_NOREPEAT;
}
protected:
@ -178,12 +174,12 @@ namespace PowerToysSettings {
}
return L"(Key " + std::to_wstring(key_code) + L")";
}
HotkeyObject(web::json::value hotkey_json) : m_json(hotkey_json) {
HotkeyObject(json::JsonObject hotkey_json) : m_json(std::move(hotkey_json)) {
if (get_key() == L"~" && get_modifiers_repeat() == MOD_WIN) {
m_json.as_object()[L"key"] = web::json::value::string(key_from_code(get_code()));
m_json.SetNamedValue(L"key", json::value(key_from_code(get_code())));
}
};
web::json::value m_json;
json::JsonObject m_json;
};
}

View File

@ -112,25 +112,25 @@ void FancyZonesSettings::LoadSettings(PCWSTR config, bool fromFile) noexcept try
for (auto const& setting : m_configBools)
{
if (values.is_bool_value(setting.name))
if (const auto val = values.get_bool_value(setting.name))
{
*setting.value = values.get_bool_value(setting.name);
*setting.value = *val;
}
}
if (values.is_string_value(m_zoneHiglightName))
if (auto val = values.get_string_value(m_zoneHiglightName))
{
m_settings.zoneHightlightColor = values.get_string_value(m_zoneHiglightName);
m_settings.zoneHightlightColor = std::move(*val);
}
if (values.is_object_value(m_editorHotkeyName))
if (const auto val = values.get_json(m_editorHotkeyName))
{
m_settings.editorHotkey = PowerToysSettings::HotkeyObject::from_json(values.get_json(m_editorHotkeyName));
m_settings.editorHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
}
if (values.is_string_value(m_excludedAppsName))
if (auto val = values.get_string_value(m_excludedAppsName))
{
m_settings.excludedApps = values.get_string_value(m_excludedAppsName);
m_settings.excludedApps = std::move(*val);
m_settings.excludedAppsArray.clear();
auto excludedUppercase = m_settings.excludedApps;
CharUpperBuffW(excludedUppercase.data(), (DWORD)excludedUppercase.length());
@ -163,7 +163,7 @@ void FancyZonesSettings::SaveSettings() noexcept try
}
values.add_property(m_zoneHiglightName, m_settings.zoneHightlightColor);
values.add_property(m_editorHotkeyName, m_settings.editorHotkey);
values.add_property(m_editorHotkeyName, m_settings.editorHotkey.get_json());
values.add_property(m_excludedAppsName, m_settings.excludedApps);
values.save_to_settings_file();

View File

@ -252,11 +252,11 @@ public:
PowerToysSettings::PowerToyValues values =
PowerToysSettings::PowerToyValues::from_json_string(config);
CSettings::SetPersistState(values.get_bool_value(L"bool_persist_input"));
CSettings::SetMRUEnabled(values.get_bool_value(L"bool_mru_enabled"));
CSettings::SetMaxMRUSize(values.get_int_value(L"int_max_mru_size"));
CSettings::SetShowIconOnMenu(values.get_bool_value(L"bool_show_icon_on_menu"));
CSettings::SetExtendedContextMenuOnly(values.get_bool_value(L"bool_show_extended_menu"));
CSettings::SetPersistState(values.get_bool_value(L"bool_persist_input").value());
CSettings::SetMRUEnabled(values.get_bool_value(L"bool_mru_enabled").value());
CSettings::SetMaxMRUSize(values.get_int_value(L"int_max_mru_size").value());
CSettings::SetShowIconOnMenu(values.get_bool_value(L"bool_show_icon_on_menu").value());
CSettings::SetExtendedContextMenuOnly(values.get_bool_value(L"bool_show_extended_menu").value());
}
catch (std::exception) {
// Improper JSON.

View File

@ -61,39 +61,37 @@ void OverlayWindow::set_config(const wchar_t * config) {
try {
PowerToysSettings::PowerToyValues _values =
PowerToysSettings::PowerToyValues::from_json_string(config);
if (_values.is_int_value(pressTime.name)) {
int press_delay_time = _values.get_int_value(pressTime.name);
pressTime.value = press_delay_time;
if (const auto press_delay_time = _values.get_int_value(pressTime.name)) {
pressTime.value = *press_delay_time;
if (target_state) {
target_state->set_delay(press_delay_time);
target_state->set_delay(*press_delay_time);
}
}
if (_values.is_int_value(overlayOpacity.name)) {
int overlay_opacity = _values.get_int_value(overlayOpacity.name);
overlayOpacity.value = overlay_opacity;
if (const auto overlay_opacity = _values.get_int_value(overlayOpacity.name)) {
overlayOpacity.value = *overlay_opacity;
if (winkey_popup) {
winkey_popup->apply_overlay_opacity(((float)overlayOpacity.value) / 100.0f);
}
}
if (_values.is_string_value(theme.name)) {
theme.value = _values.get_string_value(theme.name);
if (auto val = _values.get_string_value(theme.name)) {
theme.value = std::move(*val);
winkey_popup->set_theme(theme.value);
}
_values.save_to_settings_file();
Trace::SettingsChanged(pressTime.value, overlayOpacity.value, theme.value);
}
catch (std::exception&) {
// Improper JSON.
catch (...) {
// Improper JSON. TODO: handle the error.
}
}
void OverlayWindow::enable() {
if (!_enabled) {
Trace::EnableShortcutGuide(true);
winkey_popup = new D2DOverlayWindow();
winkey_popup = std::make_unique<D2DOverlayWindow>();
winkey_popup->apply_overlay_opacity(((float)overlayOpacity.value)/100.0f);
winkey_popup->set_theme(theme.value);
target_state = new TargetState(pressTime.value);
target_state = std::make_unique<TargetState>(pressTime.value);
winkey_popup->initialize();
}
_enabled = true;
@ -107,10 +105,8 @@ void OverlayWindow::disable(bool trace_event) {
}
winkey_popup->hide();
target_state->exit();
delete target_state;
delete winkey_popup;
target_state = nullptr;
winkey_popup = nullptr;
target_state.reset();
winkey_popup.reset();
}
}
@ -164,14 +160,14 @@ void OverlayWindow::init_settings() {
try {
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(OverlayWindow::get_name());
if (settings.is_int_value(pressTime.name)) {
pressTime.value = settings.get_int_value(pressTime.name);
if (const auto val = settings.get_int_value(pressTime.name)) {
pressTime.value = *val;
}
if (settings.is_int_value(overlayOpacity.name)) {
overlayOpacity.value = settings.get_int_value(overlayOpacity.name);
if (const auto val = settings.get_int_value(overlayOpacity.name)) {
overlayOpacity.value = *val;
}
if (settings.is_string_value(theme.name)) {
theme.value = settings.get_string_value(theme.name);
if (auto val = settings.get_string_value(theme.name)) {
theme.value = std::move(*val);
}
}
catch (std::exception&) {

View File

@ -32,8 +32,8 @@ public:
virtual void destroy() override;
private:
TargetState* target_state;
D2DOverlayWindow *winkey_popup;
std::unique_ptr<TargetState> target_state;
std::unique_ptr<D2DOverlayWindow> winkey_popup;
bool _enabled = false;
void init_settings();

View File

@ -5,45 +5,38 @@
#include "powertoy_module.h"
#include <common/windows_colors.h>
using namespace web;
static std::wstring settings_theme = L"system";
web::json::value load_general_settings() {
json::JsonObject load_general_settings() {
auto loaded = PTSettingsHelper::load_general_settings();
if (loaded.has_string_field(L"theme")) {
settings_theme = loaded.as_object()[L"theme"].as_string();
if (settings_theme != L"dark" && settings_theme != L"light") {
settings_theme = L"system";
}
} else {
settings_theme = loaded.GetNamedString(L"theme", L"system");
if (settings_theme != L"dark" && settings_theme != L"light") {
settings_theme = L"system";
}
return loaded;
}
web::json::value get_general_settings() {
json::value result = json::value::object();
bool startup = is_auto_start_task_active_for_this_user();
result.as_object()[L"startup"] = json::value::boolean(startup);
json::JsonObject get_general_settings() {
json::JsonObject result;
const bool startup = is_auto_start_task_active_for_this_user();
result.SetNamedValue(L"startup", json::value(startup));
json::value enabled = json::value::object();
json::JsonObject enabled;
for (auto&[name, powertoy] : modules()) {
enabled.as_object()[name] = json::value::boolean(powertoy.is_enabled());
enabled.SetNamedValue(name, json::value(powertoy.is_enabled()));
}
result.as_object()[L"enabled"] = enabled;
result.SetNamedValue(L"enabled", std::move(enabled));
result.as_object()[L"theme"] = json::value::string(settings_theme);
result.as_object()[L"system_theme"] = json::value::string(WindowsColors::is_dark_mode() ? L"dark" : L"light");
result.as_object()[L"powertoys_version"] = json::value::string(get_product_version());
result.SetNamedValue(L"theme", json::value(settings_theme));
result.SetNamedValue(L"system_theme", json::value(WindowsColors::is_dark_mode() ? L"dark" : L"light"));
result.SetNamedValue(L"powertoys_version", json::value(get_product_version()));
return result;
}
void apply_general_settings(const json::value& general_configs) {
bool contains_startup = general_configs.has_boolean_field(L"startup");
if (contains_startup) {
bool startup = general_configs.at(L"startup").as_bool();
bool current_startup = is_auto_start_task_active_for_this_user();
void apply_general_settings(const json::JsonObject& general_configs) {
if (json::has(general_configs, L"startup", json::JsonValueType::Boolean)) {
const bool startup = general_configs.GetNamedBoolean(L"startup");
const bool current_startup = is_auto_start_task_active_for_this_user();
if (current_startup != startup) {
if (startup) {
enable_auto_start_task_for_this_user();
@ -52,26 +45,33 @@ void apply_general_settings(const json::value& general_configs) {
}
}
}
bool contains_enabled = general_configs.has_object_field(L"enabled");
if (contains_enabled) {
for (auto enabled_element : general_configs.at(L"enabled").as_object()) {
if (enabled_element.second.is_boolean() && modules().find(enabled_element.first) != modules().end()) {
bool module_inst_enabled = modules().at(enabled_element.first).is_enabled();
bool target_enabled = enabled_element.second.as_bool();
if (module_inst_enabled != target_enabled) {
if (target_enabled) {
modules().at(enabled_element.first).enable();
} else {
modules().at(enabled_element.first).disable();
}
}
if (json::has(general_configs, L"enabled")) {
for (const auto& enabled_element : general_configs.GetNamedObject(L"enabled")) {
const auto value = enabled_element.Value();
if (value.ValueType() != json::JsonValueType::Boolean) {
continue;
}
const std::wstring name{enabled_element.Key().c_str()};
const bool found = modules().find(name) != modules().end();
if (!found) {
continue;
}
const bool module_inst_enabled = modules().at(name).is_enabled();
const bool target_enabled = value.GetBoolean();
if (module_inst_enabled == target_enabled) {
continue;
}
if (target_enabled) {
modules().at(name).enable();
} else {
modules().at(name).disable();
}
}
}
if (general_configs.has_string_field(L"theme")) {
settings_theme = general_configs.at(L"theme").as_string();
if (json::has(general_configs, L"theme", json::JsonValueType::String)) {
settings_theme = general_configs.GetNamedString(L"theme");
}
json::value save_settings = get_general_settings();
json::JsonObject save_settings = get_general_settings();
PTSettingsHelper::save_general_settings(save_settings);
}
@ -80,21 +80,22 @@ void start_initial_powertoys() {
std::unordered_set<std::wstring> powertoys_to_enable;
json::value general_settings;
json::JsonObject general_settings;
try {
general_settings = load_general_settings();
json::value enabled = general_settings[L"enabled"];
for (auto enabled_element : enabled.as_object()) {
if (enabled_element.second.as_bool()) {
json::JsonObject enabled = general_settings.GetNamedObject(L"enabled");
for (const auto & enabled_element : enabled) {
if (enabled_element.Value().GetBoolean()) {
// Enable this powertoy.
powertoys_to_enable.emplace(enabled_element.first);
powertoys_to_enable.emplace(enabled_element.Key());
}
}
only_enable_some_powertoys = true;
}
catch (std::exception&) {
catch (...) {
// Couldn't read the general settings correctly.
// Load all powertoys.
// TODO: notify user about invalid json config
only_enable_some_powertoys = false;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <cpprest/json.h>
web::json::value get_general_settings();
void apply_general_settings(const web::json::value& general_configs);
#include <common/json.h>
json::JsonObject get_general_settings();
void apply_general_settings(const json::JsonObject & general_configs);
void start_initial_powertoys();

View File

@ -23,3 +23,12 @@ PowertoyModule load_powertoy(const std::wstring& filename) {
module->register_system_menu_helper(&SystemMenuHelperInstace());
return PowertoyModule(module, handle);
}
json::JsonObject PowertoyModule::json_config() const {
int size = 0;
module->get_config(nullptr, &size);
std::wstring result;
result.resize(size - 1);
module->get_config(result.data(), &size);
return json::JsonObject::Parse(result);
}

View File

@ -9,6 +9,7 @@
#include <functional>
class PowertoyModule;
#include <common/json.h>
struct PowertoyModuleDeleter {
void operator()(PowertoyModuleIface* module) const {
@ -48,6 +49,8 @@ public:
const std::wstring& get_name() const {
return name;
}
json::JsonObject json_config() const;
const std::wstring get_config() const {
std::wstring result;

View File

@ -4,89 +4,88 @@
#include <sstream>
#include <accctrl.h>
#include <aclapi.h>
#include <cpprest/json.h>
#include "powertoy_module.h"
#include <common/two_way_pipe_message_ipc.h>
#include "tray_icon.h"
#include "general_settings.h"
#include "common/windows_colors.h"
#define BUFSIZE 1024
#include <common/json.h>
using namespace web;
#define BUFSIZE 1024
TwoWayPipeMessageIPC* current_settings_ipc = NULL;
json::value get_power_toys_settings() {
json::value result = json::value::object();
for (auto&[name, powertoy] : modules()) {
json::JsonObject get_power_toys_settings() {
json::JsonObject result;
for (const auto&[name, powertoy] : modules()) {
try {
json::value powertoys_config = json::value::parse(powertoy.get_config());
result.as_object()[name] = powertoys_config;
result.SetNamedValue(name, powertoy.json_config());
}
catch (json::json_exception&) {
//Malformed JSON.
catch (...) {
// TODO: handle malformed JSON.
}
}
return result;
}
json::value get_all_settings() {
json::value result = json::value::object();
result.as_object()[L"general"] = get_general_settings();
result.as_object()[L"powertoys"] = get_power_toys_settings();
json::JsonObject get_all_settings() {
json::JsonObject result;
result.SetNamedValue(L"general", get_general_settings());
result.SetNamedValue(L"powertoys", get_power_toys_settings());
return result;
}
void dispatch_json_action_to_module(const json::value& powertoys_configs) {
for (auto powertoy_element : powertoys_configs.as_object()) {
std::wstringstream ws;
ws << powertoy_element.second;
if (modules().find(powertoy_element.first) != modules().end()) {
modules().at(powertoy_element.first).call_custom_action(ws.str());
void dispatch_json_action_to_module(const json::JsonObject& powertoys_configs) {
for (const auto& powertoy_element : powertoys_configs) {
const std::wstring name{powertoy_element.Key().c_str()};
if (modules().find(name) != modules().end()) {
const auto element = powertoy_element.Value().Stringify();
modules().at(name).call_custom_action(element.c_str());
}
}
}
void send_json_config_to_module(const std::wstring& module_key, const std::wstring& settings) {
if (modules().find(module_key) != modules().end()) {
modules().at(module_key).set_config(settings);
modules().at(module_key).set_config(settings.c_str());
}
}
void dispatch_json_config_to_modules(const json::value& powertoys_configs) {
for (auto powertoy_element : powertoys_configs.as_object()) {
std::wstringstream ws;
ws << powertoy_element.second;
send_json_config_to_module(powertoy_element.first, ws.str());
void dispatch_json_config_to_modules(const json::JsonObject& powertoys_configs) {
for (const auto& powertoy_element : powertoys_configs) {
const auto element = powertoy_element.Value().Stringify();
send_json_config_to_module(powertoy_element.Key().c_str(), element.c_str());
}
};
void dispatch_received_json(const std::wstring &json_to_parse) {
json::value j = json::value::parse(json_to_parse);
for(auto base_element : j.as_object()) {
if (base_element.first == L"general") {
apply_general_settings(base_element.second);
std::wstringstream ws;
ws << get_all_settings();
if (current_settings_ipc != NULL) {
current_settings_ipc->send(ws.str());
const json::JsonObject j = json::JsonObject::Parse(json_to_parse);
for(const auto & base_element : j) {
const auto name = base_element.Key();
const auto value = base_element.Value();
if (name == L"general") {
apply_general_settings(value.GetObjectW());
if (current_settings_ipc != nullptr) {
const std::wstring settings_string{get_all_settings().Stringify().c_str()};
current_settings_ipc->send(settings_string);
}
} else if (base_element.first == L"powertoys") {
dispatch_json_config_to_modules(base_element.second);
std::wstringstream ws;
ws << get_all_settings();
if (current_settings_ipc != NULL) {
current_settings_ipc->send(ws.str());
} else if (name == L"powertoys") {
dispatch_json_config_to_modules(value.GetObjectW());
if (current_settings_ipc != nullptr) {
const std::wstring settings_string{get_all_settings().Stringify().c_str()};
current_settings_ipc->send(settings_string);
}
} else if (base_element.first == L"refresh") {
std::wstringstream ws;
ws << get_all_settings();
if (current_settings_ipc != NULL) {
current_settings_ipc->send(ws.str());
} else if (name == L"refresh") {
if (current_settings_ipc != nullptr) {
const std::wstring settings_string{get_all_settings().Stringify().c_str()};
current_settings_ipc->send(settings_string);
}
} else if (base_element.first == L"action") {
dispatch_json_action_to_module(base_element.second);
} else if (name == L"action") {
dispatch_json_action_to_module(value.GetObjectW());
}
}
return;
@ -118,7 +117,7 @@ void run_settings_window() {
wcscat_s(executable_path, L"\\PowerToysSettings.exe");
WCHAR executable_args[MAX_PATH * 3];
std::wstring settings_theme_setting = get_general_settings().at(L"theme").as_string();
const std::wstring settings_theme_setting{get_general_settings().GetNamedString(L"theme").c_str()};
std::wstring settings_theme;
if (settings_theme_setting == L"dark" || (settings_theme_setting == L"system" && WindowsColors::is_dark_mode())) {
settings_theme = L" dark"; // Include arg separating space