From 0351199b235c4d9bc55eeb5f9f1aa045b4afc341 Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Sun, 11 May 2025 10:32:27 -0700 Subject: [PATCH 01/10] Decimal spec --- specs/decimal/decimal.md | 467 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 467 insertions(+) create mode 100644 specs/decimal/decimal.md diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md new file mode 100644 index 0000000000..d0f05b378f --- /dev/null +++ b/specs/decimal/decimal.md @@ -0,0 +1,467 @@ +# 1. Decimal + +THIS FEATURE IS CURRENTLY EXPERIMENTAL. + +This feature provides a common decimal representation and aids for use within and across programming languages. + +Some languages have a native decimal data type, e.g. [Decimal struct in C#](https://learn.microsoft.com/dotnet/api/system.decimal) +and [decimal in Python](https://docs.python.org/3/library/decimal.html). These are recommended for +use in their languages. Windows App SDK provides supplemental aids for interoperability with the +common data type. + +Other languages have no native decimal data type e.g. C++, Rust and Javascript. Windows App SDK +provides language native support for some languages including interoperability with the common data +type: + +* C++ -- `Microsoft::Windows::Foundation::decimal` + +Windows App SDK provides a decimal WinRT runtimeclass `Microsoft.Windows.Foundation.Decimal` as a +fallback for languages without a native decimal data type (whether provided by the language or +Windows App SDK). This is fully functional but has performance overhead relative to language native +data types which are commonly stack allocated and offer better language integration. The WinRT type +is recommended when your language has no native type or other comparable solution. + +# 2. Common Decimal Representation + +The Win32 [DECIMAL](https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1) +structure is the common decimal format, stored as a 96-bit (12-byte) unsigned integer scaled by a +variable power of 10. The power of 10 scaling factor specifies the number of digits to the right of +the decimal point, and ranges from 0 to 28. This is expressed in WinRT as the following structure: + +```c# (but really midl3) + struct DecimalValue + { + UInt16 Reserved; + Byte Scale; // Allowed values: 0-28 + Byte Sign; // Allowed values: 0x80 = negative, 0x00 = zero or positive + UInt32 Hi32; + UInt64 Lo64; + } +``` + +This matches the memory layout and use of the Win32 [DECIMAL](https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1) +structure and the [C# Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal). This +data structure may be re-expressed in each language using language-specific constructs e.g. WinRT +defines the `DecimalValue` structure as the Win32 `DECIMAL` definition syntax is incompatible with +WinRT IDL. + +# 3. WinRT API + +Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure. + +```c# (but really MIDL3) +namespace Microsoft.Windows.Foundation +{ + [contractversion(1)] + apicontract DecimalContract{}; + + /// WinRT representation of the Win32 DECIMAL structure. + /// @note This is the identical memory layout and encoding of the Win32 DECIMAL structure. + /// The latter's definition is valid for COM but not WinRT making this equivalent structure necessary. + /// @see https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1 + [feature(Feature_Decimal)] + [contract(DecimalContract, 1)] + struct DecimalValue + { + UInt16 Reserved; + UInt8 Scale; // Allowed values: 0-28 + UInt8 Sign; // Allowed values: 0x80 = negative, 0x00 = zero or positive + UInt32 Hi32; + UInt64 Lo64; + }; + + [feature(Feature_Decimal)] + [contract(DecimalContract, 1)] + runtimeclass DecimalHelper + { + static DecimalValue FromBoolean(Boolean value); + static DecimalValue FromInt16(Int16 value); + static DecimalValue FromInt32(Int32 value); + static DecimalValue FromInt64(Int64 value); + static DecimalValue FromUInt8(UInt8 value); + static DecimalValue FromUInt16(UInt16 value); + static DecimalValue FromUInt32(UInt32 value); + static DecimalValue FromUInt64(UInt64 value); + static DecimalValue FromSingle(Single value); + static DecimalValue FromDouble(Double value); + static DecimalValue FromString(String value); // LCID=LOCALE_INVARIANT + static DecimalValue FromStringWithSystemDefaultLocale(String value); // LCID=GetSystemDefaultLCID() + static DecimalValue FromStringWithUserDefaultLocale(String value); // LCID=GetUserDefaultLCID() + static DecimalValue FromStringWithThreadLocale(String value); // LCID=GetThreadLocale() + + static Boolean ToBoolean(DecimalValue value); + static Int16 ToInt16(DecimalValue value); + static Int32 ToInt32(DecimalValue value); + static Int64 ToInt64(DecimalValue value); + static UInt8 ToUInt8(DecimalValue value); + static UInt16 ToUInt16(DecimalValue value); + static UInt32 ToUInt32(DecimalValue value); + static UInt64 ToUInt64(DecimalValue value); + static Single ToSingle(DecimalValue value); + static Double ToDouble(DecimalValue value); + static String ToString(DecimalValue value); // LCID=LOCALE_INVARIANT + static String ToStringWithSystemDefaultLocale(DecimalValue value); // LCID=GetSystemDefaultLCID() + static String ToStringWithUserDefaultLocale(DecimalValue value); // LCID=GetUserDefaultLCID() + static String ToStringWithThreadLocale(DecimalValue value); // LCID=GetThreadLocale() + + /// Return true if (left == right). + static Boolean Equals(DecimalValue left, DecimalValue right); + + /// Compare decimal values. + /// @return 0 if left and right are equal, <0 if left is less than right or >0 if left is greater than right. + static Int32 Compare(DecimalValue left, DecimalValue right); + + /// Return true if the value is valid. + static Boolean IsValid(DecimalValue value); + + /// Return the scaling factor of the value (the number of decimal digits). + /// @return the scaling factor, ranging from 0 to max_scale(). + static UInt32 Scale(DecimalValue value); + + /// Return the sign of the value. + /// @return 0 if value is zero, <0 if value is less than zero or >0 if value is greater than zero. + static Int32 Sign(DecimalValue value); + + /// Return the maximum scaling factor + static UInt32 MaxScale(); + + /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). + static DecimalValue MaxValue(); + + /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335). + static DecimalValue MinValue(); + + /// Return a decimal whose value is (-value). + static DecimalValue Negate(DecimalValue value); + + /// Return the absolute value. + static DecimalValue Abs(DecimalValue value); + + /// Return the integral digits; any fractional digits are discarded. + static DecimalValue Truncate(DecimalValue value); + + /// Return the integral digits rounded down to -infinity; any fractional digits are discarded. + static DecimalValue Floor(DecimalValue value); + + /// Return the integral digits rounded up to +infinity; any fractional digits are discarded. + static DecimalValue Ceiling(DecimalValue value); + + /// Return the value rounded to the specific number of decimal places. + static DecimalValue Round(DecimalValue value, Int32 decimalPlaces); + + /// Return value clamped to the inclusive range of min and max. + /// @return value if min <= value <= max, or min if value < min, or max if max < value. + static DecimalValue Clamp(DecimalValue value, DecimalValue min, DecimalValue max); + + /// Returns a DecimalValue whose value is (left + right). + static DecimalValue Add(DecimalValue left, DecimalValue right); + + /// Returns a DecimalValue whose value is (left - right). + static DecimalValue Subtract(DecimalValue left, DecimalValue right); + + /// Returns a DecimalValue whose value is (left * right). + static DecimalValue Multiply(DecimalValue left, DecimalValue right); + + /// Returns a DecimalValue whose value is (left / right). + static DecimalValue Divide(DecimalValue left, DecimalValue right); + + /// Returns a DecimalValue whose value is (left % right). + static DecimalValue Modulo(DecimalValue left, DecimalValue right); + } +} +``` + +# 4. C++ API + +Windows App SDK provides a native language decimal data type for C++ as the +`Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: + +* Constructor and assignment (operator=) overloads to define a decimal object from various data types +* to_xxx() methods converting a decimal object's value to various data types +* Relational operations: `compare()` `==` `!=` `<` `<=` `>` `>=` +* Unary operations: + - ++ -- +* Binary operations: + += - -= * *= / /= % %= +* Properties: `sign()` `scale()` +* Mathematical operations: `abs()` `truncate()` `floor()` `ceil()` `round()` `clamp()` +* Constants: `max_scale()` `max_value()` `min_value()` + +Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception + +## 4.1. decimal.h + +```c++ +#if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) +#define __WindowsAppSDK_Microsoft_Windows_Foundation_decimal_ + +#include <oleauto.h> + +#if !defined(_VC_NODEFAULTLIB) +#pragma comment(linker, "/defaultlib:oleaut32.lib") +#endif + +inline int compare(const DECIMAL& left, const DECIMAL& right); + +inline bool operator==(const DECIMAL& left, const DECIMAL& right); + +inline bool operator!=(const DECIMAL& left, const DECIMAL& right); + +inline bool operator< (const DECIMAL& left, const DECIMAL& right); + +inline bool operator<=(const DECIMAL& left, const DECIMAL& right); + +inline bool operator> (const DECIMAL& left, const DECIMAL& right); + +inline bool operator>=(const DECIMAL& left, const DECIMAL& right); + +namespace Microsoft::Windows::Foundation +{ +class decimal +{ +public: + decimal() = default; + ~decimal() = default; + + decimal(const decimal& value); + decimal(decimal&& value); + constexpr decimal(const DECIMAL& value); + decimal(bool value)l + decimal(char value); + decimal(std::int16_t value); + decimal(std::int32_t value); + decimal(std::int64_t value); + decimal(std::uint8_t value); + decimal(std::uint16_t value); + decimal(std::uint32_t value); + decimal(std::uint64_t value); + decimal(float value); + decimal(double value); + decimal(long value); + decimal(unsigned long value); + decimal(PCWSTR value); + decimal(PCWSTR value, const LCID locale); + decimal(const std::wstring& value); + decimal(const std::wstring& value, const LCID locale); +#if defined(__WINSTRING_H_) + decimal(const HSTRING& value); + decimal(const HSTRING& value, const LCID locale); +#endif // defined(__WINSTRING_H_) +#if defined(WINRT_BASE_H) + decimal(const winrt::hstring& value); + decimal(const winrt::hstring& value, const LCID locale); +#endif // defined(WINRT_BASE_H) + + decimal& operator=(const decimal& value); + decimal& operator=(decimal&& value); + decimal& operator=(const DECIMAL& value); + decimal& operator=(bool value); + decimal& operator=(char value); + decimal& operator=(std::int16_t value); + decimal& operator=(std::int32_t value); + decimal& operator=(std::int64_t value); + decimal& operator=(std::uint8_t value); + decimal& operator=(std::uint16_t value); + decimal& operator=(std::uint32_t value); + decimal& operator=(std::uint64_t value); + decimal& operator=(float value); + decimal& operator=(double value); + decimal& operator=(long value); + decimal& operator=(unsigned long value); + decimal& operator=(PCWSTR value); + decimal& operator=(const std::wstring& value); +#if defined(__WINSTRING_H_) + decimal& operator=(const HSTRING& value); +#endif // defined(__WINSTRING_H_) +#if defined(WINRT_BASE_H) + decimal& operator=(const winrt::hstring& value); +#endif // defined(WINRT_BASE_H) + + const DECIMAL& to_decimal() const; + bool to_bool() const; + char to_char() const; + std::int16_t to_int16() const; + std::int32_t to_int32() const; + std::int64_t to_int64() const; + std::uint8_t to_uint8() const; + std::uint16_t to_uint16() const; + std::uint32_t to_uint32() const; + std::uint64_t to_uint64() const; + float to_float() const; + double to_double() const; + long to_long() const; + unsigned long to_ulong() const; + std::wstring to_string() const; + std::wstring to_string(const LCID locale) const; +#if defined(__WINSTRING_H_) + HSTRING to_HSTRING() const; + HSTRING to_HSTRING(const LCID locale) const; +#endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) + winrt::hstring to_hstring() const; + winrt::hstring to_hstring(const LCID locale) const; +#endif // defined(WINRT_BASE_H) + + bool operator==(const decimal& value) const; + bool operator!=(const decimal& value) const; + bool operator< (const decimal& value) const; + bool operator<=(const decimal& value) const; + bool operator> (const decimal& value) const; + bool operator>=(const decimal& value) const; + int compare(const decimal& value) const; + + bool operator==(const DECIMAL& value) const; + bool operator!=(const DECIMAL& value) const; + bool operator< (const DECIMAL& value) const; + bool operator<=(const DECIMAL& value) const; + bool operator> (const DECIMAL& value) const; + bool operator>=(const DECIMAL& value) const; + int compare(const DECIMAL& value) const; + + /// Return true if this is valid. + bool is_valid(); + + /// Return true if value is valid. + static constexpr bool is_valid(const DECIMAL& value); + + /// Return the scaling factor of the value (the number of decimal digits). + /// @return the scaling factor, ranging from 0 to max_scale(). + std::uint32_t scale() const; + + /// Return the sign of the value. + /// @return 0 if this os zero, <0 if this is less than zero or >0 if this is greater than zero. + std::int32_t sign() const; + + /// Return the maximum scaling factor + static constexpr std::uint32_t max_scale(); + + /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). + static constexpr decimal max_value(); + + /// Return the minimum value (-79,228,162,514,264,337,593,543,950,335). + static constexpr decimal min_value(); + + decimal operator+() const; + + decimal operator-() const; + + decimal abs() const; + + /// Return the integral digits; any fractional digits are discarded. + decimal truncate() const; + + /// Return the integral digits rounded down to -infinity; any fractional digits are discarded. + decimal floor() const; + + /// Return the integral digits rounded up to +infinity; any fractional digits are discarded. + decimal ceil() const; + + /// Return this clamped to the inclusive range of min and max. + /// @return this if min <= this <= max, or min if this < min, or max if max < this. + decimal clamp(decimal min, decimal max) const; + + decimal operator++(); + decimal operator++(int); + + decimal operator--(); + decimal operator--(int); + + decimal operator+(const decimal& value) const; + decimal operator-(const decimal& value) const; + decimal operator*(const decimal& value) const; + decimal operator/(const decimal& value) const; + + /// Modulo operation using the Truncated method. + /// @note The % operator in C, C#, Rust and other languages use this method. + /// @note The result's sign will match the current value's sign. + /// @see https://en.wikipedia.org/wiki/Modulo + decimal operator%(const decimal& value) const; + + decimal& operator+=(const decimal& value); + decimal& operator-=(const decimal& value); + decimal& operator*=(const decimal& value); + decimal& operator/=(const decimal& value); + decimal& operator%=(const decimal& value); + + decimal round(const std::int32_t decimalPlaces) const; + +private: + DECIMAL m_decimal{}; +}; +} + +#endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) +``` + +## 4.2. decimalcppwinmrt.h + +```c++ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#include <oleauto.h> + +//---------------------------------------------------------------------- +// WinRT DecimalValue support + +#if defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_) +#define __WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_ + +//---------------------------------------------------------- +// WinRT DecimalValue <-> Win32 DECIMAL conversions + +namespace winrt::Microsoft::Windows::Foundation +{ +/// Return value as a Win32 DECIMAL structure. +inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); + +/// Return value as a WinRT DecimalValue structure. +inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value); +} + +//---------------------------------------------------------- +// WinRT DecimalValue operators + +// C++/WinRT generates bool operator==(DecimalValue const& left, DecimalValue const& right) + +// C++/WinRT generates bool operator!=(DecimalValue const& left, DecimalValue const& right) + +inline bool operator<( + winrt::Microsoft::Windows::Foundation::DecimalValue const& left, + winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + +inline bool operator<=( + winrt::Microsoft::Windows::Foundation::DecimalValue const& left, + winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + +inline bool operator>( + winrt::Microsoft::Windows::Foundation::DecimalValue const& left, + winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + +inline bool operator>=( + winrt::Microsoft::Windows::Foundation::DecimalValue const& left, + winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + +#endif // defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_) + +//---------------------------------------------------------------------- +// C++ decimal support + +#if defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_) +#define __WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_ + +//---------------------------------------------------------- +// WinRT DecimalValue <-> C++ decimal conversions + +namespace winrt::Microsoft::Windows::Foundation +{ +/// Return true if value is valid. +constexpr bool is_valid(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); + +/// Return value as a C++ decimal object. +inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); + +/// Return value as a WinRT DecimalValue structure. +inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value); +} + +#endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_) +``` From 23387a19d4cb0c719e088db9c7093a24326001db Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 12 May 2025 19:11:42 -0700 Subject: [PATCH 02/10] Added examples --- specs/decimal/decimal.md | 149 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index d0f05b378f..0cff83f2fd 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -45,7 +45,152 @@ data structure may be re-expressed in each language using language-specific cons defines the `DecimalValue` structure as the Win32 `DECIMAL` definition syntax is incompatible with WinRT IDL. -# 3. WinRT API +# 3. Examples + +The examples are a program displaying the results of the the mathematical formula: + +``` +x = (((a - b) + (c % d)) * e).round(5) / f; +y = x++.round(3).clamp(f, g); +z = --y.floor() * ++x.ceil() * -y.truncate(); +``` + +Given the values + +``` +a = 1 +b = 0.5 +c = -6.66 +d = 1.23 +e = 4567.089 +f = -4 +g = 1967 +h = 1001.0 +``` + +the output is + +``` +x == 12.4177225 +y == 11.418 +z == -1540 +``` + +and the process exit code is -1540. + +# 3.1. C# + +NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal) +providing the canonical reference for examples in other languages. + +```c++ +Using System; +Using System.IO; + +class Program +{ + static void Main() + { + var a = new Decimal(1); + var b = new Decimal(0.5); + var c = Decimal.Parse("-6.66"); + var d = Decimal.Parse("1.23"); + var e = Decimal.Parse("4567.089"); + var f = new Decimal((long)-4); + var g = new Decimal((uint)1967); + var h = new Decimal(1001.0); + + var x = Decimal.Round(((a - b) + (c % d)) * e, 5) / f; + var y = Math.Clamp(Decimal.Round(x++, 3), f, g); + var yfloor = Decimal.Floor(y); + var xceil = Decimal.Ceiling(x); + var z = --yfloor * ++xceil * -Decimal.Truncate(y); + + Console.WriteLine($"x = {x}"); + Console.WriteLine($"y = {y}"); + Console.WriteLine($"z = {z}"); + + Environment.Exit((int)z); + } +} +``` + +# 3.2. C++ + +This program illustrates the reference example using Windows App SDK's C++ decimal class. + +```c++ +#include <windows.h> +#include <stdio.h> +#include <decimal.h> + +int main() +{ + const Microsoft::Windows::Foundation::decimal a{ 1 }; + const Microsoft::Windows::Foundation::decimal b{ 0.5 }; + const Microsoft::Windows::Foundation::decimal c{ L"-6.66" }; + const Microsoft::Windows::Foundation::decimal d{ L"1.23" }; + const Microsoft::Windows::Foundation::decimal e{ L"4567.089" }; + const Microsoft::Windows::Foundation::decimal f{ -4ll }; + const Microsoft::Windows::Foundation::decimal g{ 1967u }; + const Microsoft::Windows::Foundation::decimal h{ 1001.0f }; + + auto x = (((a - b) + (c % d)) * e).round(5) / f; + auto y = x++.round(3).clamp(f, g); + auto z = --y.floor() * ++x.ceil() * -y.truncate(); + + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"x = %ls", x.to_string().c_str())); + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"y = %ls", y.to_string().c_str())); + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"z = %ls", z.to_string().c_str())); + + printf(L"x = %ls\n", x.to_string().c_str()); + printf(L"y = %ls\n", y.to_string().c_str()); + printf(L"z = %ls\n", z.to_string().c_str()); + return z.to_int32(); +} +``` + +# 3.3. WinRT + +This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass. + +```c++ +#include <windows.h> +#include <stdio.h> +#include <winrt/Microsoft.Windows.Foundation.h> + +int main() +{ + using DH = winrt::Microsoft::Windows::Foundation::DecimalHelper; + const auto a{ DH::FromInt32(1) }; + const auto b{ DH::FromDouble(0.5) }; + const auto c{ DH::FromString(L"-6.66") }; + const auto d{ DH::FromString(L"1.23") }; + const auto e{ DH::FromString(L"4567.089") }; + const auto f{ DH::FromInt64(-4ll) }; + const auto g{ DH::FromUInt16(1967u) }; + const auto h{ DH::FromSingle(1001.0f) }; + + // WinRT equivalent to C++ formula + // + // x = (((a - b) + (c % d)) * e).round(5) / f + // y = x++.round(3).clamp(f, g) + // z = --y.floor() * ++x.ceil() * -y.truncate() + + auto x = DH::Divide(DH::Round(DH::Multiply(DH::Add(DH::Subtract(a, b), (DH::Modulo(c, d))), e), 5), f); + auto one = DH::FromInt32(1); + auto y = DH::Clamp(DH::Round(x, 3), f, g); + x = DH::Add(x, one); + auto z = DH::Multiply(DH::Multiply(DH::Subtract(DH::Floor(y), one), DH::Add(DH::Ceiling(x), one)), DH::Negate(DH::Truncate(y))); + + printf(L"x = %ls\n", DH::ToString(x).c_str()); + printf(L"y = %ls\n", DH::ToString(y).c_str()); + printf(L"z = %ls\n", DH::ToString(z).c_str()); + return DH::ToInt32(z); +} +``` + +# 4. WinRT API Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure. @@ -171,7 +316,7 @@ namespace Microsoft.Windows.Foundation } ``` -# 4. C++ API +# 5. C++ API Windows App SDK provides a native language decimal data type for C++ as the `Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: From 1e32d6d07b1bb5640e0c4abb4c1b442ad59dd48c Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Tue, 13 May 2025 11:59:54 -0700 Subject: [PATCH 03/10] Added TOC. Added C# API. Fixed some numbering --- specs/decimal/decimal.md | 47 ++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index 0cff83f2fd..2906a928d6 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -1,3 +1,15 @@ +- [1. Decimal](#1-decimal) +- [2. Common Decimal Representation](#2-common-decimal-representation) +- [3. Examples](#3-examples) +- [4. C#](#4-c) +- [5. C++](#5-c) +- [6. WinRT](#6-winrt) +- [7. WinRT API](#7-winrt-api) +- [8. C++ API](#8-c-api) + - [8.1. decimal.h](#81-decimalh) + - [8.2. decimalcppwinmrt.h](#82-decimalcppwinmrth) +- [9. C# API](#9-c-api) + # 1. Decimal THIS FEATURE IS CURRENTLY EXPERIMENTAL. @@ -78,7 +90,7 @@ z == -1540 and the process exit code is -1540. -# 3.1. C# +# 4. C# NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal) providing the canonical reference for examples in other languages. @@ -115,7 +127,7 @@ class Program } ``` -# 3.2. C++ +# 5. C++ This program illustrates the reference example using Windows App SDK's C++ decimal class. @@ -150,7 +162,7 @@ int main() } ``` -# 3.3. WinRT +# 6. WinRT This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass. @@ -190,7 +202,7 @@ int main() } ``` -# 4. WinRT API +# 7. WinRT API Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure. @@ -316,7 +328,7 @@ namespace Microsoft.Windows.Foundation } ``` -# 5. C++ API +# 8. C++ API Windows App SDK provides a native language decimal data type for C++ as the `Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: @@ -332,7 +344,7 @@ Windows App SDK provides a native language decimal data type for C++ as the Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception -## 4.1. decimal.h +## 8.1. decimal.h ```c++ #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) @@ -536,7 +548,9 @@ private: #endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) ``` -## 4.2. decimalcppwinmrt.h +## 8.2. decimalcppwinmrt.h + +This header provides C++/WinRT and Windows App SDK's DecimalValue integration. ```c++ // Copyright (c) Microsoft Corporation and Contributors. @@ -610,3 +624,22 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Mic #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_) ``` + +# 9. C# API + +C# provides rich support via its [Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal). +Windows App SDK adds a small C# API in an assembly for interop with `DecimalValue`. + +```c# +namespace Microsoft.Windows.Foundation +{ + public static class DecimalExtensions + { + /// Return a WinRT DecimalValue structure. + public static Microsoft.Windows.Foundation.DecimalValue ToDecimalValue(this decimal d); + + /// Return a C# Decimal object. + public static decimal FromDecimalValue(this decimal d, Microsoft.Windows.Foundation.DecimalValue value); + } +} +``` From 96444b098141afa55f26b9242883268bda226326 Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 26 May 2025 11:49:22 -0700 Subject: [PATCH 04/10] Incorporate feedback --- specs/decimal/decimal.md | 251 +++++++++++++++++++++++++++++---------- 1 file changed, 189 insertions(+), 62 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index 2906a928d6..994524e530 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -7,7 +7,7 @@ - [7. WinRT API](#7-winrt-api) - [8. C++ API](#8-c-api) - [8.1. decimal.h](#81-decimalh) - - [8.2. decimalcppwinmrt.h](#82-decimalcppwinmrth) + - [8.2. decimalcppwinmrt.h](#82-decimalcppwinrth) - [9. C# API](#9-c-api) # 1. Decimal @@ -57,6 +57,13 @@ data structure may be re-expressed in each language using language-specific cons defines the `DecimalValue` structure as the Win32 `DECIMAL` definition syntax is incompatible with WinRT IDL. +2.1. OLE Automation APIs + +The [OLE Automation APIs](https://learn.microsoft.com/windows/win32/api/oleauto/) operating on +[DECIMAL](https://learn.microsoft.com/windows/win32/api/wtypes/ns-wtypes-decimal-r1) provide the +core functionality used by the APIs in this spec e.g. [VarDecFromStr](https://learn.microsoft.com/windows/win32/api/oleauto/nf-oleauto-vardecfromstr) +to convert a string to `DECIMAL`. + # 3. Examples The examples are a program displaying the results of the the mathematical formula: @@ -90,7 +97,7 @@ z == -1540 and the process exit code is -1540. -# 4. C# +# 3.1. C# Example NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal) providing the canonical reference for examples in other languages. @@ -114,9 +121,7 @@ class Program var x = Decimal.Round(((a - b) + (c % d)) * e, 5) / f; var y = Math.Clamp(Decimal.Round(x++, 3), f, g); - var yfloor = Decimal.Floor(y); - var xceil = Decimal.Ceiling(x); - var z = --yfloor * ++xceil * -Decimal.Truncate(y); + var z = (Decimal.Floor(y) - 1) * (Decimal.Ceiling(x) + 1) * -Decimal.Truncate(y); Console.WriteLine($"x = {x}"); Console.WriteLine($"y = {y}"); @@ -127,7 +132,7 @@ class Program } ``` -# 5. C++ +# 3.2. C++ Example This program illustrates the reference example using Windows App SDK's C++ decimal class. @@ -151,18 +156,14 @@ int main() auto y = x++.round(3).clamp(f, g); auto z = --y.floor() * ++x.ceil() * -y.truncate(); - WEX::Logging::Log::Comment(WEX::Common::String().Format(L"x = %ls", x.to_string().c_str())); - WEX::Logging::Log::Comment(WEX::Common::String().Format(L"y = %ls", y.to_string().c_str())); - WEX::Logging::Log::Comment(WEX::Common::String().Format(L"z = %ls", z.to_string().c_str())); - - printf(L"x = %ls\n", x.to_string().c_str()); - printf(L"y = %ls\n", y.to_string().c_str()); - printf(L"z = %ls\n", z.to_string().c_str()); + printf("x = %ls\n", x.to_wstring_invariant().c_str()); + printf("y = %ls\n", y.to_wstring_invariant().c_str()); + printf("z = %ls\n", z.to_wstring_invariant().c_str()); return z.to_int32(); } ``` -# 6. WinRT +# 3.3. WinRT Example This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass. @@ -176,9 +177,9 @@ int main() using DH = winrt::Microsoft::Windows::Foundation::DecimalHelper; const auto a{ DH::FromInt32(1) }; const auto b{ DH::FromDouble(0.5) }; - const auto c{ DH::FromString(L"-6.66") }; - const auto d{ DH::FromString(L"1.23") }; - const auto e{ DH::FromString(L"4567.089") }; + const auto c{ DH::FromStringInvariant(L"-6.66") }; + const auto d{ DH::FromStringInvariant(L"1.23") }; + const auto e{ DH::FromStringInvariant(L"4567.089") }; const auto f{ DH::FromInt64(-4ll) }; const auto g{ DH::FromUInt16(1967u) }; const auto h{ DH::FromSingle(1001.0f) }; @@ -195,16 +196,16 @@ int main() x = DH::Add(x, one); auto z = DH::Multiply(DH::Multiply(DH::Subtract(DH::Floor(y), one), DH::Add(DH::Ceiling(x), one)), DH::Negate(DH::Truncate(y))); - printf(L"x = %ls\n", DH::ToString(x).c_str()); - printf(L"y = %ls\n", DH::ToString(y).c_str()); - printf(L"z = %ls\n", DH::ToString(z).c_str()); + printf(L"x = %ls\n", DH::ToStringInvariant(x).c_str()); + printf(L"y = %ls\n", DH::ToStringInvariant(y).c_str()); + printf(L"z = %ls\n", DH::ToStringInvariant(z).c_str()); return DH::ToInt32(z); } ``` -# 7. WinRT API +# 4. WinRT API -Windows App SDK provides a `Decimal` WinRT runtimeclass in addition to the `DecimalValue` structure. +Windows App SDK provides a `DecimalHelper` WinRT runtimeclass in addition to the `DecimalValue` structure. ```c# (but really MIDL3) namespace Microsoft.Windows.Foundation @@ -241,10 +242,24 @@ namespace Microsoft.Windows.Foundation static DecimalValue FromUInt64(UInt64 value); static DecimalValue FromSingle(Single value); static DecimalValue FromDouble(Double value); - static DecimalValue FromString(String value); // LCID=LOCALE_INVARIANT - static DecimalValue FromStringWithSystemDefaultLocale(String value); // LCID=GetSystemDefaultLCID() - static DecimalValue FromStringWithUserDefaultLocale(String value); // LCID=GetUserDefaultLCID() - static DecimalValue FromStringWithThreadLocale(String value); // LCID=GetThreadLocale() + + /// Parse the string using the user's default locale. + static DecimalValue FromString(String value); + + /// Parse the string using the invariant locale. + static DecimalValue FromStringInvariant(String value); + + /// Parse the string using the specified locale. + static DecimalValue FromString(String value, String localeName); + + /// Parse the string using the user's default locale. + static Boolean TryParseString(String value, DecimalValue* value); + + /// Parse the string using the invariant locale. + static Boolean TryParseStringInvariant(String value, DecimalValue* value); + + /// Parse the string using the specified locale. + static Boolean TryParseString(String value, String localeName, DecimalValue* value); static Boolean ToBoolean(DecimalValue value); static Int16 ToInt16(DecimalValue value); @@ -256,10 +271,15 @@ namespace Microsoft.Windows.Foundation static UInt64 ToUInt64(DecimalValue value); static Single ToSingle(DecimalValue value); static Double ToDouble(DecimalValue value); - static String ToString(DecimalValue value); // LCID=LOCALE_INVARIANT - static String ToStringWithSystemDefaultLocale(DecimalValue value); // LCID=GetSystemDefaultLCID() - static String ToStringWithUserDefaultLocale(DecimalValue value); // LCID=GetUserDefaultLCID() - static String ToStringWithThreadLocale(DecimalValue value); // LCID=GetThreadLocale() + + /// Format the string using the user's default locale. + static String ToString(DecimalValue value); + + /// Format the string using the invariant locale. + static String ToStringInvariant(DecimalValue value); + + /// Format the string using the specified locale. + static String ToString(DecimalValue value, String localeName); /// Return true if (left == right). static Boolean Equals(DecimalValue left, DecimalValue right); @@ -273,7 +293,7 @@ namespace Microsoft.Windows.Foundation /// Return the scaling factor of the value (the number of decimal digits). /// @return the scaling factor, ranging from 0 to max_scale(). - static UInt32 Scale(DecimalValue value); + static UInt8 Scale(DecimalValue value); /// Return the sign of the value. /// @return 0 if value is zero, <0 if value is less than zero or >0 if value is greater than zero. @@ -328,7 +348,7 @@ namespace Microsoft.Windows.Foundation } ``` -# 8. C++ API +# 5. C++ API Windows App SDK provides a native language decimal data type for C++ as the `Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: @@ -344,7 +364,7 @@ Windows App SDK provides a native language decimal data type for C++ as the Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception -## 8.1. decimal.h +## 5.1. decimal.h ```c++ #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) @@ -381,7 +401,7 @@ public: decimal(const decimal& value); decimal(decimal&& value); constexpr decimal(const DECIMAL& value); - decimal(bool value)l + decimal(bool value); decimal(char value); decimal(std::int16_t value); decimal(std::int32_t value); @@ -394,17 +414,102 @@ public: decimal(double value); decimal(long value); decimal(unsigned long value); - decimal(PCWSTR value); - decimal(PCWSTR value, const LCID locale); - decimal(const std::wstring& value); - decimal(const std::wstring& value, const LCID locale); -#if defined(__WINSTRING_H_) - decimal(const HSTRING& value); - decimal(const HSTRING& value, const LCID locale); -#endif // defined(__WINSTRING_H_) + + /// Parse the string using the user's default locale. + static decimal from_string(PCWSTR source); + + /// Parse the string using the invariant locale. + static decimal from_string_invariant(PCWSTR source); + + /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_string(PCWSTR source, PCWSTR localeName); + + /// Parse the string using the user's default locale. + static bool try_from_string(PCWSTR source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_string_invariant(PCWSTR source, decimal& value); + + /// Parse the string using the specified locale. + static bool try_from_string(PCWSTR source, PCWSTR localeName, decimal& value); + + /// Parse the string using the user's default locale. + static decimal from_string(const std::string& source); + + /// Parse the string using the invariant locale. + static decimal from_string_invariant(const std::string& source); + + /// Parse the string using the specified locale. + static decimal from_string(const std::string& source, const std::string& localeName); + + /// Parse the string using the user's default locale. + static bool try_from_string(const std::string& source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_string_invariant(const std::string& source, decimal& value); + + /// Parse bool try_string using the specified local, decimal& valuee. + static decimal from_string(const std::string& source, const std::string& localeName); + + /// Parse the string using the user's default locale. + static decimal from_wstring(const std::wstring& source); + + /// Parse the string using the invariant locale. + static decimal from_wstring_invariant(const std::wstring& source); + + /// Parse the string using the specified locale. + static decimal from_wstring(const std::wstring& source, const std::wstring& localeName); + + /// Parse the string using the user's default locale. + static bool try_from_wstring(const std::wstring& source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_wstring_invariant(const std::wstring& source, decimal& value); + + /// Parse bool try_string using the specified local, decimal& valuee. + static decimal from_wstring(const std::wstring& source, const std::wstring& localeNAme); + +#if defined(__hstring_h__) + /// Parse the string using the user's default locale. + static decimal from_hstring(const HSTRING& source); + + /// Parse the string using the invariant locale. + static decimal from_hstring_invariant(const HSTRING& source); + + /// Parse the string using the specified locale. + static decimal from_hstring(const HSTRING& source, const HSTRING& localeName); + + /// Parse the string using the user's default locale. + static bool try_from_hstring(const HSTRING& source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_hstring_invariant(const HSTRING& source, decimal& value); + + /// Parse the string using the specified locale. + static bool try_from_hstring(const HSTRING& source, const HSTRING& localeName, decimal& value); +#endif // defined(__hstring_h__) + #if defined(WINRT_BASE_H) - decimal(const winrt::hstring& value); - decimal(const winrt::hstring& value, const LCID locale); + /// Parse the string using the user's default locale. + static decimal from_hstring(const winrt::hstring& source); + + /// Parse the string using the invariant locale. + static decimal from_hstring_invariant(const winrt::hstring& source); + + /// Parse the string using the specified locale. + static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeNAme); + + /// Parse the string using the user's default locale. + static bool try_from_hstring(const winrt::hstring& source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_hstring_invariant(const winrt::hstring& source, decimal& value); + + /// Parse the string using the specified locale. + static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value); #endif // defined(WINRT_BASE_H) decimal& operator=(const decimal& value); @@ -423,14 +528,6 @@ public: decimal& operator=(double value); decimal& operator=(long value); decimal& operator=(unsigned long value); - decimal& operator=(PCWSTR value); - decimal& operator=(const std::wstring& value); -#if defined(__WINSTRING_H_) - decimal& operator=(const HSTRING& value); -#endif // defined(__WINSTRING_H_) -#if defined(WINRT_BASE_H) - decimal& operator=(const winrt::hstring& value); -#endif // defined(WINRT_BASE_H) const DECIMAL& to_decimal() const; bool to_bool() const; @@ -446,15 +543,45 @@ public: double to_double() const; long to_long() const; unsigned long to_ulong() const; - std::wstring to_string() const; - std::wstring to_string(const LCID locale) const; -#if defined(__WINSTRING_H_) + + // Format the string using the user's default locale. + std::string to_string() const; + + // Format the string using the invariant locale. + std::string to_string_invariant() const; + + // Format the string using the specified locale. + std::string to_string(const std::string& localeName) const; + + // Format the string using the user's default locale. + std::wstring to_wstring() const; + + // Format the string using the invariant locale. + std::wstring to_wstring_invariant() const; + + // Format the string using the invariant locale. + std::wstring to_wstring(const std::wstring& localeName) const; + +#if defined(__hstring_h__) + // Format the string using the user's default locale. HSTRING to_HSTRING() const; - HSTRING to_HSTRING(const LCID locale) const; -#endif // defined(WINRT_BASE_H) + + // Format the string using the specified locale. + HSTRING to_HSTRING_invariant() const; + + // Format the string using the specified locale. + HSTRING to_HSTRING(const HSTRING& localeName) const; +#endif // defined(__hstring_h__) + #if defined(WINRT_BASE_H) + // Format the string using the user's default locale. winrt::hstring to_hstring() const; - winrt::hstring to_hstring(const LCID locale) const; + + // Format the string using the specified locale. + winrt::hstring to_hstring_invariant() const; + + // Format the string using the specified locale. + winrt::hstring to_hstring(const winrt::hstring& localeName) const; #endif // defined(WINRT_BASE_H) bool operator==(const decimal& value) const; @@ -481,7 +608,7 @@ public: /// Return the scaling factor of the value (the number of decimal digits). /// @return the scaling factor, ranging from 0 to max_scale(). - std::uint32_t scale() const; + std::uint8_t scale() const; /// Return the sign of the value. /// @return 0 if this os zero, <0 if this is less than zero or >0 if this is greater than zero. @@ -548,7 +675,7 @@ private: #endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) ``` -## 8.2. decimalcppwinmrt.h +## 5.2. decimalcppwinrt.h This header provides C++/WinRT and Windows App SDK's DecimalValue integration. @@ -625,7 +752,7 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Mic #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_) ``` -# 9. C# API +# 6. C# API C# provides rich support via its [Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal). Windows App SDK adds a small C# API in an assembly for interop with `DecimalValue`. @@ -639,7 +766,7 @@ namespace Microsoft.Windows.Foundation public static Microsoft.Windows.Foundation.DecimalValue ToDecimalValue(this decimal d); /// Return a C# Decimal object. - public static decimal FromDecimalValue(this decimal d, Microsoft.Windows.Foundation.DecimalValue value); + public static decimal ToDecimal(this decimal d, Microsoft.Windows.Foundation.DecimalValue value); } } ``` From 40e6407e7f03b2aef4cf1fba912b73022025874e Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 26 May 2025 12:07:27 -0700 Subject: [PATCH 05/10] Incorporated feedback --- specs/decimal/decimal.md | 84 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index 994524e530..7599ccc1aa 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -402,7 +402,6 @@ public: decimal(decimal&& value); constexpr decimal(const DECIMAL& value); decimal(bool value); - decimal(char value); decimal(std::int16_t value); decimal(std::int32_t value); decimal(std::int64_t value); @@ -415,6 +414,31 @@ public: decimal(long value); decimal(unsigned long value); + //---- Parse String: PCSTR + + /// Parse the string using the user's default locale. + static decimal from_string(PCSTR source); + + /// Parse the string using the invariant locale. + static decimal from_string_invariant(PCSTR source); + + /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT ("!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT ("") for the user default locale. + static decimal from_string(PCSTR source, PCSTR localeName); + + /// Parse the string using the user's default locale. + static bool try_from_string(PCSTR source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_string_invariant(PCSTR source, decimal& value); + + /// Parse the string using the specified locale. + static bool try_from_string(PCSTR source, PCSTR localeName, decimal& value); + + //---- Parse String: PCWSTR + /// Parse the string using the user's default locale. static decimal from_string(PCWSTR source); @@ -436,6 +460,8 @@ public: /// Parse the string using the specified locale. static bool try_from_string(PCWSTR source, PCWSTR localeName, decimal& value); + //---- Parse String: std::string + /// Parse the string using the user's default locale. static decimal from_string(const std::string& source); @@ -454,6 +480,28 @@ public: /// Parse bool try_string using the specified local, decimal& valuee. static decimal from_string(const std::string& source, const std::string& localeName); + //---- Parse String: std::string_value + + /// Parse the string_value using the user's default locale. + static decimal from_string_value(const std::string_value& source); + + /// Parse the string_value using the invariant locale. + static decimal from_string_value_invariant(const std::string_value& source); + + /// Parse the string_value using the specified locale. + static decimal from_string_value(const std::string_value& source, const std::string_value& localeName); + + /// Parse the string_value using the user's default locale. + static bool try_from_string_value(const std::string_value& source, decimal& value); + + /// Parse the string_value using the invariant locale. + static bool try_from_string_value_invariant(const std::string_value& source, decimal& value); + + /// Parse bool try_string_value using the specified local, decimal& valuee. + static decimal from_string_value(const std::string_value& source, const std::string_value& localeName); + + //---- Parse String: std::wstring + /// Parse the string using the user's default locale. static decimal from_wstring(const std::wstring& source); @@ -472,7 +520,29 @@ public: /// Parse bool try_string using the specified local, decimal& valuee. static decimal from_wstring(const std::wstring& source, const std::wstring& localeNAme); + //---- Parse String: std::wstring_value + + /// Parse the string using the user's default locale. + static decimal from_wstring_value(const std::wstring_value& source); + + /// Parse the string using the invariant locale. + static decimal from_wstring_value_invariant(const std::wstring_value& source); + + /// Parse the string using the specified locale. + static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeName); + + /// Parse the string using the user's default locale. + static bool try_from_wstring_value(const std::wstring_value& source, decimal& value); + + /// Parse the string using the invariant locale. + static bool try_from_wstring_value_invariant(const std::wstring_value& source, decimal& value); + + /// Parse bool try_string using the specified local, decimal& valuee. + static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeNAme); + #if defined(__hstring_h__) + //---- Parse String: HSTRING + /// Parse the string using the user's default locale. static decimal from_hstring(const HSTRING& source); @@ -493,6 +563,8 @@ public: #endif // defined(__hstring_h__) #if defined(WINRT_BASE_H) + //---- Parse String: winrt::hstring + /// Parse the string using the user's default locale. static decimal from_hstring(const winrt::hstring& source); @@ -516,7 +588,6 @@ public: decimal& operator=(decimal&& value); decimal& operator=(const DECIMAL& value); decimal& operator=(bool value); - decimal& operator=(char value); decimal& operator=(std::int16_t value); decimal& operator=(std::int32_t value); decimal& operator=(std::int64_t value); @@ -531,7 +602,6 @@ public: const DECIMAL& to_decimal() const; bool to_bool() const; - char to_char() const; std::int16_t to_int16() const; std::int32_t to_int32() const; std::int64_t to_int64() const; @@ -544,6 +614,8 @@ public: long to_long() const; unsigned long to_ulong() const; + //---- Parse String: std::string + // Format the string using the user's default locale. std::string to_string() const; @@ -553,6 +625,8 @@ public: // Format the string using the specified locale. std::string to_string(const std::string& localeName) const; + //---- Parse String: std::wstring + // Format the string using the user's default locale. std::wstring to_wstring() const; @@ -563,6 +637,8 @@ public: std::wstring to_wstring(const std::wstring& localeName) const; #if defined(__hstring_h__) + //---- Parse String: HSTRING + // Format the string using the user's default locale. HSTRING to_HSTRING() const; @@ -574,6 +650,8 @@ public: #endif // defined(__hstring_h__) #if defined(WINRT_BASE_H) + //---- Parse String: winrt::hstring + // Format the string using the user's default locale. winrt::hstring to_hstring() const; From 8f0ce08a14864a025dd2d8d20b0bc11aa4644d48 Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 9 Jun 2025 10:38:20 -0700 Subject: [PATCH 06/10] Incorporated feedback --- specs/decimal/decimal.md | 337 ++++++++++++++++++++++++++++----------- 1 file changed, 241 insertions(+), 96 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index 7599ccc1aa..8278217f40 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -145,9 +145,9 @@ int main() { const Microsoft::Windows::Foundation::decimal a{ 1 }; const Microsoft::Windows::Foundation::decimal b{ 0.5 }; - const Microsoft::Windows::Foundation::decimal c{ L"-6.66" }; - const Microsoft::Windows::Foundation::decimal d{ L"1.23" }; - const Microsoft::Windows::Foundation::decimal e{ L"4567.089" }; + const auto c{ Microsoft::Windows::Foundation::decimal::from_string("-6.66") }; + const auto d{ Microsoft::Windows::Foundation::decimal::from_string("1.23") }; + const auto e{ Microsoft::Windows::Foundation::decimal::from_string("4567.089" }; const Microsoft::Windows::Foundation::decimal f{ -4ll }; const Microsoft::Windows::Foundation::decimal g{ 1967u }; const Microsoft::Windows::Foundation::decimal h{ 1001.0f }; @@ -244,22 +244,24 @@ namespace Microsoft.Windows.Foundation static DecimalValue FromDouble(Double value); /// Parse the string using the user's default locale. - static DecimalValue FromString(String value); + static DecimalValue FromString(String source); /// Parse the string using the invariant locale. - static DecimalValue FromStringInvariant(String value); + static DecimalValue FromStringInvariant(String source); /// Parse the string using the specified locale. - static DecimalValue FromString(String value, String localeName); + [method_name("FromStringWithLocale")] + static DecimalValue FromString(String source, String localeName); /// Parse the string using the user's default locale. - static Boolean TryParseString(String value, DecimalValue* value); + static Boolean TryFromString(String source, out DecimalValue value); /// Parse the string using the invariant locale. - static Boolean TryParseStringInvariant(String value, DecimalValue* value); + static Boolean TryFromStringInvariant(String source, out DecimalValue value); /// Parse the string using the specified locale. - static Boolean TryParseString(String value, String localeName, DecimalValue* value); + [method_name("TryFromStringWithLocale")] + static Boolean TryFromString(String source, String localeName, out DecimalValue value); static Boolean ToBoolean(DecimalValue value); static Int16 ToInt16(DecimalValue value); @@ -279,6 +281,7 @@ namespace Microsoft.Windows.Foundation static String ToStringInvariant(DecimalValue value); /// Format the string using the specified locale. + [method_name("ToStringWithLocale")] static String ToString(DecimalValue value, String localeName); /// Return true if (left == right). @@ -291,6 +294,9 @@ namespace Microsoft.Windows.Foundation /// Return true if the value is valid. static Boolean IsValid(DecimalValue value); + /// Return true if value is an integral number. + static Boolean IsInteger(DecimalValue value); + /// Return the scaling factor of the value (the number of decimal digits). /// @return the scaling factor, ranging from 0 to max_scale(). static UInt8 Scale(DecimalValue value); @@ -300,7 +306,7 @@ namespace Microsoft.Windows.Foundation static Int32 Sign(DecimalValue value); /// Return the maximum scaling factor - static UInt32 MaxScale(); + static UInt8 MaxScale(); /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). static DecimalValue MaxValue(); @@ -354,13 +360,15 @@ Windows App SDK provides a native language decimal data type for C++ as the `Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: * Constructor and assignment (operator=) overloads to define a decimal object from various data types -* to_xxx() methods converting a decimal object's value to various data types +* to_xxx() methods converting a decimal object's value to various string data types +* [try]_from_xxx() methods converting a decimal object's value from various string data types * Relational operations: `compare()` `==` `!=` `<` `<=` `>` `>=` -* Unary operations: + - ++ -- -* Binary operations: + += - -= * *= / /= % %= +* Unary operations: `+` `-` `++` `--` +* Binary operations: `+` `+=` `-` `-=` `*` `*=` `/` `/=` `%` `%=` * Properties: `sign()` `scale()` * Mathematical operations: `abs()` `truncate()` `floor()` `ceil()` `round()` `clamp()` * Constants: `max_scale()` `max_value()` `min_value()` +* Validation: `is_integer()` `is_valid()` Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception @@ -399,23 +407,36 @@ public: ~decimal() = default; decimal(const decimal& value); + decimal(decimal&& value); + constexpr decimal(const DECIMAL& value); + decimal(bool value); + decimal(std::int16_t value); + decimal(std::int32_t value); + decimal(std::int64_t value); + decimal(std::uint8_t value); + decimal(std::uint16_t value); + decimal(std::uint32_t value); + decimal(std::uint64_t value); + decimal(float value); + decimal(double value); + decimal(long value); - decimal(unsigned long value); - //---- Parse String: PCSTR + decimal(unsigned long value); +public: /// Parse the string using the user's default locale. static decimal from_string(PCSTR source); @@ -424,7 +445,7 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT ("!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. /// @note localeName=LOCALE_NAME_USER_DEFAULT ("") for the user default locale. static decimal from_string(PCSTR source, PCSTR localeName); @@ -437,8 +458,7 @@ public: /// Parse the string using the specified locale. static bool try_from_string(PCSTR source, PCSTR localeName, decimal& value); - //---- Parse String: PCWSTR - +public: /// Parse the string using the user's default locale. static decimal from_string(PCWSTR source); @@ -447,7 +467,7 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_NAME_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. static decimal from_string(PCWSTR source, PCWSTR localeName); @@ -460,8 +480,7 @@ public: /// Parse the string using the specified locale. static bool try_from_string(PCWSTR source, PCWSTR localeName, decimal& value); - //---- Parse String: std::string - +public: /// Parse the string using the user's default locale. static decimal from_string(const std::string& source); @@ -469,6 +488,9 @@ public: static decimal from_string_invariant(const std::string& source); /// Parse the string using the specified locale. + /// @note localeName="!x-sys-default-locale" for the system default locale. + /// @note localeName=NULL for the invariant locale. + /// @note localeName="" for the user default locale. static decimal from_string(const std::string& source, const std::string& localeName); /// Parse the string using the user's default locale. @@ -477,31 +499,32 @@ public: /// Parse the string using the invariant locale. static bool try_from_string_invariant(const std::string& source, decimal& value); - /// Parse bool try_string using the specified local, decimal& valuee. - static decimal from_string(const std::string& source, const std::string& localeName); - - //---- Parse String: std::string_value - - /// Parse the string_value using the user's default locale. - static decimal from_string_value(const std::string_value& source); + /// Parse the string using the specified locale. + static bool try_from_string(const std::string& source, const std::string& localeName, decimal& value); - /// Parse the string_value using the invariant locale. - static decimal from_string_value_invariant(const std::string_value& source); +public: + /// Parse the string using the user's default locale. + static decimal from_string_view(const std::string_view& source); - /// Parse the string_value using the specified locale. - static decimal from_string_value(const std::string_value& source, const std::string_value& localeName); + /// Parse the string using the invariant locale. + static decimal from_string_view_invariant(const std::string_view& source); - /// Parse the string_value using the user's default locale. - static bool try_from_string_value(const std::string_value& source, decimal& value); + /// Parse the string using the specified locale. + /// @note localeName="!x-sys-default-locale" for the system default locale. + /// @note localeName=NULL for the invariant locale. + /// @note localeName="" for the user default locale. + static decimal from_string_view(const std::string_view& source, const std::string_view& localeName); - /// Parse the string_value using the invariant locale. - static bool try_from_string_value_invariant(const std::string_value& source, decimal& value); + /// Parse the string using the user's default locale. + static bool try_from_string_view(const std::string_view& source, decimal& value); - /// Parse bool try_string_value using the specified local, decimal& valuee. - static decimal from_string_value(const std::string_value& source, const std::string_value& localeName); + /// Parse the string using the invariant locale. + static bool try_from_string_view_invariant(const std::string_view& source, decimal& value); - //---- Parse String: std::wstring + /// Parse the string using the specified locale. + static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value); +public: /// Parse the string using the user's default locale. static decimal from_wstring(const std::wstring& source); @@ -509,6 +532,9 @@ public: static decimal from_wstring_invariant(const std::wstring& source); /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. static decimal from_wstring(const std::wstring& source, const std::wstring& localeName); /// Parse the string using the user's default locale. @@ -517,105 +543,156 @@ public: /// Parse the string using the invariant locale. static bool try_from_wstring_invariant(const std::wstring& source, decimal& value); - /// Parse bool try_string using the specified local, decimal& valuee. - static decimal from_wstring(const std::wstring& source, const std::wstring& localeNAme); - - //---- Parse String: std::wstring_value + /// Parse the string using the specified locale. + static bool try_from_wstring(const std::wstring& source, const std::wstring& localeName, decimal& value); +public: /// Parse the string using the user's default locale. - static decimal from_wstring_value(const std::wstring_value& source); + static decimal from_wstring_view(const std::wstring_view& source); /// Parse the string using the invariant locale. - static decimal from_wstring_value_invariant(const std::wstring_value& source); + static decimal from_wstring_view_invariant(const std::wstring_view& source); /// Parse the string using the specified locale. - static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeName); + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName); /// Parse the string using the user's default locale. - static bool try_from_wstring_value(const std::wstring_value& source, decimal& value); + static bool try_from_wstring_view(const std::wstring_view& source, decimal& value); /// Parse the string using the invariant locale. - static bool try_from_wstring_value_invariant(const std::wstring_value& source, decimal& value); + static bool try_from_wstring_view_invariant(const std::wstring_view& source, decimal& value); - /// Parse bool try_string using the specified local, decimal& valuee. - static decimal from_wstring_value(const std::wstring_value& source, const std::wstring_value& localeNAme); + /// Parse the string using the specified locale. + static bool try_from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName, decimal& value); +public: #if defined(__hstring_h__) - //---- Parse String: HSTRING - /// Parse the string using the user's default locale. - static decimal from_hstring(const HSTRING& source); + static decimal from_HSTRING(const HSTRING& source); +#endif // defined(__hstring_h__) +#if defined(__hstring_h__) /// Parse the string using the invariant locale. - static decimal from_hstring_invariant(const HSTRING& source); + static decimal from_HSTRING_invariant(const HSTRING& source); +#endif // defined(__hstring_h__) +#if defined(__hstring_h__) /// Parse the string using the specified locale. - static decimal from_hstring(const HSTRING& source, const HSTRING& localeName); + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName); +#endif // defined(__hstring_h__) +#if defined(__hstring_h__) /// Parse the string using the user's default locale. - static bool try_from_hstring(const HSTRING& source, decimal& value); + static bool try_from_HSTRING(const HSTRING& source, decimal& value); +#endif // defined(__hstring_h__) +#if defined(__hstring_h__) /// Parse the string using the invariant locale. - static bool try_from_hstring_invariant(const HSTRING& source, decimal& value); + static bool try_from_HSTRING_invariant(const HSTRING& source, decimal& value); +#endif // defined(__hstring_h__) +#if defined(__hstring_h__) /// Parse the string using the specified locale. - static bool try_from_hstring(const HSTRING& source, const HSTRING& localeName, decimal& value); + static bool try_from_HSTRING(const HSTRING& source, const HSTRING& localeName, decimal& value); #endif // defined(__hstring_h__) +public: #if defined(WINRT_BASE_H) - //---- Parse String: winrt::hstring - /// Parse the string using the user's default locale. static decimal from_hstring(const winrt::hstring& source); +#endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) /// Parse the string using the invariant locale. static decimal from_hstring_invariant(const winrt::hstring& source); +#endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) /// Parse the string using the specified locale. - static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeNAme); + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeName); +#endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) /// Parse the string using the user's default locale. static bool try_from_hstring(const winrt::hstring& source, decimal& value); +#endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) /// Parse the string using the invariant locale. static bool try_from_hstring_invariant(const winrt::hstring& source, decimal& value); +#endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) /// Parse the string using the specified locale. static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value); #endif // defined(WINRT_BASE_H) decimal& operator=(const decimal& value); + decimal& operator=(decimal&& value); + decimal& operator=(const DECIMAL& value); + decimal& operator=(bool value); + decimal& operator=(std::int16_t value); + decimal& operator=(std::int32_t value); + decimal& operator=(std::int64_t value); + decimal& operator=(std::uint8_t value); + decimal& operator=(std::uint16_t value); + decimal& operator=(std::uint32_t value); + decimal& operator=(std::uint64_t value); + decimal& operator=(float value); + decimal& operator=(double value); + decimal& operator=(long value); + decimal& operator=(unsigned long value); const DECIMAL& to_decimal() const; + bool to_bool() const; + std::int16_t to_int16() const; + std::int32_t to_int32() const; + std::int64_t to_int64() const; + std::uint8_t to_uint8() const; + std::uint16_t to_uint16() const; + std::uint32_t to_uint32() const; + std::uint64_t to_uint64() const; + float to_float() const; + double to_double() const; + long to_long() const; - unsigned long to_ulong() const; - //---- Parse String: std::string + unsigned long to_ulong() const; +public: // Format the string using the user's default locale. std::string to_string() const; @@ -623,67 +700,96 @@ public: std::string to_string_invariant() const; // Format the string using the specified locale. - std::string to_string(const std::string& localeName) const; + std::string to_string(PCWSTR localeName) const; - //---- Parse String: std::wstring + // Format the string using the specified locale. + std::string to_string(const std::string& localeName) const; +public: // Format the string using the user's default locale. std::wstring to_wstring() const; // Format the string using the invariant locale. std::wstring to_wstring_invariant() const; - // Format the string using the invariant locale. + // Format the string using the specified locale. std::wstring to_wstring(const std::wstring& localeName) const; -#if defined(__hstring_h__) - //---- Parse String: HSTRING + // Format the string using the specified locale. + std::wstring to_wstring(PCWSTR localeName) const; - // Format the string using the user's default locale. +public: +#if defined(__hstring_h__) HSTRING to_HSTRING() const; +#endif // defined(__hstring_h__) - // Format the string using the specified locale. +#if defined(__hstring_h__) HSTRING to_HSTRING_invariant() const; +#endif // defined(__hstring_h__) - // Format the string using the specified locale. +#if defined(__hstring_h__) HSTRING to_HSTRING(const HSTRING& localeName) const; #endif // defined(__hstring_h__) -#if defined(WINRT_BASE_H) - //---- Parse String: winrt::hstring +#if defined(__hstring_h__) + HSTRING to_HSTRING(PCWSTR localeName) const; +#endif // defined(__hstring_h__) - // Format the string using the user's default locale. +public: +#if defined(WINRT_BASE_H) winrt::hstring to_hstring() const; +#endif // defined(WINRT_BASE_H) - // Format the string using the specified locale. +#if defined(WINRT_BASE_H) winrt::hstring to_hstring_invariant() const; +#endif // defined(WINRT_BASE_H) - // Format the string using the specified locale. +#if defined(WINRT_BASE_H) winrt::hstring to_hstring(const winrt::hstring& localeName) const; #endif // defined(WINRT_BASE_H) +#if defined(WINRT_BASE_H) + winrt::hstring to_hstring(PCWSTR localeName) const; +#endif // defined(WINRT_BASE_H) + +public: bool operator==(const decimal& value) const; + bool operator!=(const decimal& value) const; + bool operator< (const decimal& value) const; + bool operator<=(const decimal& value) const; + bool operator> (const decimal& value) const; + bool operator>=(const decimal& value) const; + int compare(const decimal& value) const; bool operator==(const DECIMAL& value) const; + bool operator!=(const DECIMAL& value) const; + bool operator< (const DECIMAL& value) const; + bool operator<=(const DECIMAL& value) const; + bool operator> (const DECIMAL& value) const; + bool operator>=(const DECIMAL& value) const; - int compare(const DECIMAL& value) const; - /// Return true if this is valid. - bool is_valid(); + int compare(const DECIMAL& value) const; /// Return true if value is valid. static constexpr bool is_valid(const DECIMAL& value); + /// Return true if this is an integral number. + bool is_integer() const; + + /// Return true if value is an integral number. + static constexpr bool is_integer(const DECIMAL& value); + /// Return the scaling factor of the value (the number of decimal digits). /// @return the scaling factor, ranging from 0 to max_scale(). std::uint8_t scale() const; @@ -693,7 +799,7 @@ public: std::int32_t sign() const; /// Return the maximum scaling factor - static constexpr std::uint32_t max_scale(); + static constexpr std::uint8_t max_scale(); /// Return the maximum value (79,228,162,514,264,337,593,543,950,335). static constexpr decimal max_value(); @@ -721,32 +827,38 @@ public: decimal clamp(decimal min, decimal max) const; decimal operator++(); + decimal operator++(int); decimal operator--(); + decimal operator--(int); decimal operator+(const decimal& value) const; + + decimal& operator+=(const decimal& value); + decimal operator-(const decimal& value) const; + + decimal& operator-=(const decimal& value); + decimal operator*(const decimal& value) const; + + decimal& operator*=(const decimal& value); + decimal operator/(const decimal& value) const; + decimal& operator/=(const decimal& value); + /// Modulo operation using the Truncated method. /// @note The % operator in C, C#, Rust and other languages use this method. /// @note The result's sign will match the current value's sign. /// @see https://en.wikipedia.org/wiki/Modulo decimal operator%(const decimal& value) const; - decimal& operator+=(const decimal& value); - decimal& operator-=(const decimal& value); - decimal& operator*=(const decimal& value); - decimal& operator/=(const decimal& value); decimal& operator%=(const decimal& value); decimal round(const std::int32_t decimalPlaces) const; - -private: - DECIMAL m_decimal{}; }; } @@ -775,10 +887,16 @@ This header provides C++/WinRT and Windows App SDK's DecimalValue integration. namespace winrt::Microsoft::Windows::Foundation { /// Return value as a Win32 DECIMAL structure. -inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); +inline DECIMAL to_DECIMAL(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) +{ + return std::bit_cast<DECIMAL>(value); +} /// Return value as a WinRT DecimalValue structure. -inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value); +inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIMAL const& value) +{ + return std::bit_cast<winrt::Microsoft::Windows::Foundation::DecimalValue>(value); +} } //---------------------------------------------------------- @@ -790,19 +908,31 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(DECIM inline bool operator<( winrt::Microsoft::Windows::Foundation::DecimalValue const& left, - winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + winrt::Microsoft::Windows::Foundation::DecimalValue const& right) +{ + return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) < 0; +} inline bool operator<=( winrt::Microsoft::Windows::Foundation::DecimalValue const& left, - winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + winrt::Microsoft::Windows::Foundation::DecimalValue const& right) +{ + return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) <= 0; +} inline bool operator>( winrt::Microsoft::Windows::Foundation::DecimalValue const& left, - winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + winrt::Microsoft::Windows::Foundation::DecimalValue const& right) +{ + return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) > 0; +} inline bool operator>=( winrt::Microsoft::Windows::Foundation::DecimalValue const& left, - winrt::Microsoft::Windows::Foundation::DecimalValue const& right); + winrt::Microsoft::Windows::Foundation::DecimalValue const& right) +{ + return winrt::Microsoft::Windows::Foundation::DecimalHelper::Compare(left, right) >= 0; +} #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && !defined(__WINDOWSAPPSDK_WINRT_M_W_F_DECIMAL_) @@ -818,13 +948,28 @@ inline bool operator>=( namespace winrt::Microsoft::Windows::Foundation { /// Return true if value is valid. -constexpr bool is_valid(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); +constexpr bool is_valid(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) +{ + return ::Microsoft::Windows::Foundation::decimal::is_valid(to_DECIMAL(value)); +} + +/// Return true if value is an integral number. +constexpr bool is_integer(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) +{ + return ::Microsoft::Windows::Foundation::decimal::is_integer(to_DECIMAL(value)); +} /// Return value as a C++ decimal object. -inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value); +inline ::Microsoft::Windows::Foundation::decimal to_decimal(winrt::Microsoft::Windows::Foundation::DecimalValue const& value) +{ + return ::Microsoft::Windows::Foundation::decimal{ to_DECIMAL(value) }; +} /// Return value as a WinRT DecimalValue structure. -inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value); +inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Microsoft::Windows::Foundation::decimal const& value) +{ + return to_DecimalValue(value.to_decimal()); +} } #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_) From a3c74f98ad895c89f3640f4e864590adf8b6f2d3 Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 9 Jun 2025 10:46:43 -0700 Subject: [PATCH 07/10] Incorporated feedback --- specs/decimal/decimal.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index 8278217f40..98f6524626 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -1,19 +1,17 @@ - [1. Decimal](#1-decimal) - [2. Common Decimal Representation](#2-common-decimal-representation) - [3. Examples](#3-examples) -- [4. C#](#4-c) -- [5. C++](#5-c) -- [6. WinRT](#6-winrt) +- [4. C# Example](#4-c-example) +- [5. C++ Example](#5-c-example) +- [6. WinRT Example](#6-winrt-example) - [7. WinRT API](#7-winrt-api) - [8. C++ API](#8-c-api) - [8.1. decimal.h](#81-decimalh) - - [8.2. decimalcppwinmrt.h](#82-decimalcppwinrth) + - [8.2. decimalcppwinrt.h](#82-decimalcppwinrth) - [9. C# API](#9-c-api) # 1. Decimal -THIS FEATURE IS CURRENTLY EXPERIMENTAL. - This feature provides a common decimal representation and aids for use within and across programming languages. Some languages have a native decimal data type, e.g. [Decimal struct in C#](https://learn.microsoft.com/dotnet/api/system.decimal) @@ -97,7 +95,7 @@ z == -1540 and the process exit code is -1540. -# 3.1. C# Example +# 4. C# Example NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal) providing the canonical reference for examples in other languages. @@ -132,7 +130,7 @@ class Program } ``` -# 3.2. C++ Example +# 5. C++ Example This program illustrates the reference example using Windows App SDK's C++ decimal class. @@ -163,7 +161,7 @@ int main() } ``` -# 3.3. WinRT Example +# 6. WinRT Example This program illustrates the reference example using Windows App SDK's WinRT `DecimalValue` struct and `DecimalHelper` runtimeclass. @@ -203,7 +201,7 @@ int main() } ``` -# 4. WinRT API +# 7. WinRT API Windows App SDK provides a `DecimalHelper` WinRT runtimeclass in addition to the `DecimalValue` structure. @@ -354,7 +352,7 @@ namespace Microsoft.Windows.Foundation } ``` -# 5. C++ API +# 8. C++ API Windows App SDK provides a native language decimal data type for C++ as the `Microsoft::Windows::Foundation::decimal` class in `decimal.h`. This class has the following features: @@ -372,7 +370,7 @@ Windows App SDK provides a native language decimal data type for C++ as the Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will throw a divide-by-zero exception -## 5.1. decimal.h +## 8.1. decimal.h ```c++ #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) @@ -865,7 +863,7 @@ public: #endif // !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) ``` -## 5.2. decimalcppwinrt.h +## 8.2. decimalcppwinrt.h This header provides C++/WinRT and Windows App SDK's DecimalValue integration. @@ -975,7 +973,7 @@ inline winrt::Microsoft::Windows::Foundation::DecimalValue to_DecimalValue(::Mic #endif // defined(WINRT_Microsoft_Windows_Foundation_H) && defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) && !defined(__WINDOWSAPPSDK_CPP_M_W_F_DECIMAL_) ``` -# 6. C# API +# 9. C# API C# provides rich support via its [Decimal struct](https://learn.microsoft.com/dotnet/api/system.decimal). Windows App SDK adds a small C# API in an assembly for interop with `DecimalValue`. From 2289225a2bf560c53048eea457308f4bbd18d7db Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 9 Jun 2025 22:22:41 -0700 Subject: [PATCH 08/10] Corrected syntax errors --- specs/decimal/decimal.md | 106 +++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 37 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index 98f6524626..c0c9100501 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -100,7 +100,7 @@ and the process exit code is -1540. NOTE: This example uses [C#'s Decimal support](https://learn.microsoft.com/dotnet/api/system.decimal) providing the canonical reference for examples in other languages. -```c++ +```c# Using System; Using System.IO; @@ -373,11 +373,21 @@ Errors are expressed via thrown exceptions e.g. `decimal{1} / decimal{0}` will t ## 8.1. decimal.h ```c++ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + #if !defined(__WindowsAppSDK_Microsoft_Windows_Foundation_decimal_) #define __WindowsAppSDK_Microsoft_Windows_Foundation_decimal_ +#include <winnls.h> #include <oleauto.h> +#include <string> + +#include <wil/cppwinrt.h> +#include <wil/resource.h> +#include <wil/result_macros.h> + #if !defined(_VC_NODEFAULTLIB) #pragma comment(linker, "/defaultlib:oleaut32.lib") #endif @@ -491,6 +501,12 @@ public: /// @note localeName="" for the user default locale. static decimal from_string(const std::string& source, const std::string& localeName); + /// Parse the string using the specified locale. + /// @note localeName="!x-sys-default-locale" for the system default locale. + /// @note localeName=NULL for the invariant locale. + /// @note localeName="" for the user default locale. + static decimal from_string(const std::string& source, const PCSTR localeName); + /// Parse the string using the user's default locale. static bool try_from_string(const std::string& source, decimal& value); @@ -500,6 +516,9 @@ public: /// Parse the string using the specified locale. static bool try_from_string(const std::string& source, const std::string& localeName, decimal& value); + /// Parse the string using the specified locale. + static bool try_from_string(const std::string& source, PCSTR localeName, decimal& value); + public: /// Parse the string using the user's default locale. static decimal from_string_view(const std::string_view& source); @@ -513,12 +532,21 @@ public: /// @note localeName="" for the user default locale. static decimal from_string_view(const std::string_view& source, const std::string_view& localeName); + /// Parse the string using the specified locale. + /// @note localeName="!x-sys-default-locale" for the system default locale. + /// @note localeName=NULL for the invariant locale. + /// @note localeName="" for the user default locale. + static decimal from_string_view(const std::string_view& source, PCSTR localeName); + /// Parse the string using the user's default locale. static bool try_from_string_view(const std::string_view& source, decimal& value); /// Parse the string using the invariant locale. static bool try_from_string_view_invariant(const std::string_view& source, decimal& value); + /// Parse the string using the specified locale. + static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value) + /// Parse the string using the specified locale. static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value); @@ -535,6 +563,12 @@ public: /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. static decimal from_wstring(const std::wstring& source, const std::wstring& localeName); + /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_wstring(const std::wstring& source, const std::wstring& localeName); + /// Parse the string using the user's default locale. static bool try_from_wstring(const std::wstring& source, decimal& value); @@ -544,6 +578,9 @@ public: /// Parse the string using the specified locale. static bool try_from_wstring(const std::wstring& source, const std::wstring& localeName, decimal& value); + /// Parse the string using the specified locale. + static bool try_from_wstring(const std::wstring& source, PCWSTR localeName, decimal& value); + public: /// Parse the string using the user's default locale. static decimal from_wstring_view(const std::wstring_view& source); @@ -557,6 +594,12 @@ public: /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName); + /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_wstring_view(const std::wstring_view& source, PCWSTR localeName); + /// Parse the string using the user's default locale. static bool try_from_wstring_view(const std::wstring_view& source, decimal& value); @@ -566,70 +609,71 @@ public: /// Parse the string using the specified locale. static bool try_from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName, decimal& value); + /// Parse the string using the specified locale. + static bool try_from_wstring_view(const std::wstring_view& source, PCWSTR localeName, decimal& value); + public: -#if defined(__hstring_h__) +#if defined(__hstring_h__) && defined(__WINSTRING_H_) /// Parse the string using the user's default locale. static decimal from_HSTRING(const HSTRING& source); -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) /// Parse the string using the invariant locale. static decimal from_HSTRING_invariant(const HSTRING& source); -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName); -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) + /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName); + /// Parse the string using the user's default locale. static bool try_from_HSTRING(const HSTRING& source, decimal& value); -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) /// Parse the string using the invariant locale. static bool try_from_HSTRING_invariant(const HSTRING& source, decimal& value); -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) /// Parse the string using the specified locale. static bool try_from_HSTRING(const HSTRING& source, const HSTRING& localeName, decimal& value); -#endif // defined(__hstring_h__) + + /// Parse the string using the specified locale. + static bool try_from_HSTRING(const HSTRING& source, PCWSTR localeName, decimal& value); +#endif // defined(__hstring_h__) && defined(__WINSTRING_H_) public: #if defined(WINRT_BASE_H) /// Parse the string using the user's default locale. static decimal from_hstring(const winrt::hstring& source); -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) /// Parse the string using the invariant locale. static decimal from_hstring_invariant(const winrt::hstring& source); -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeName); -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) + /// Parse the string using the specified locale. + /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. + /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + static decimal from_hstring(const winrt::hstring& source, PCWSTR localeName); + /// Parse the string using the user's default locale. static bool try_from_hstring(const winrt::hstring& source, decimal& value); -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) /// Parse the string using the invariant locale. static bool try_from_hstring_invariant(const winrt::hstring& source, decimal& value); -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) + /// Parse the string using the specified locale. + static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value) + /// Parse the string using the specified locale. static bool try_from_hstring(const winrt::hstring& source, const winrt::hstring& localeName, decimal& value); #endif // defined(WINRT_BASE_H) @@ -717,36 +761,24 @@ public: std::wstring to_wstring(PCWSTR localeName) const; public: -#if defined(__hstring_h__) +#if defined(__hstring_h__) && defined(__WINSTRING_H_) HSTRING to_HSTRING() const; -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) HSTRING to_HSTRING_invariant() const; -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) HSTRING to_HSTRING(const HSTRING& localeName) const; -#endif // defined(__hstring_h__) -#if defined(__hstring_h__) HSTRING to_HSTRING(PCWSTR localeName) const; -#endif // defined(__hstring_h__) +#endif // defined(__hstring_h__) && defined(__WINSTRING_H_) public: #if defined(WINRT_BASE_H) winrt::hstring to_hstring() const; -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) winrt::hstring to_hstring_invariant() const; -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) winrt::hstring to_hstring(const winrt::hstring& localeName) const; -#endif // defined(WINRT_BASE_H) -#if defined(WINRT_BASE_H) winrt::hstring to_hstring(PCWSTR localeName) const; #endif // defined(WINRT_BASE_H) From 30427b59979e0a5da113ab3561991f075bb6bea5 Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Mon, 16 Jun 2025 02:02:07 -0700 Subject: [PATCH 09/10] Fixed some comments --- specs/decimal/decimal.md | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index c0c9100501..de60bf4371 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -453,8 +453,8 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT ("!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT ("") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT ("") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_string(PCSTR source, PCSTR localeName); /// Parse the string using the user's default locale. @@ -475,8 +475,8 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_string(PCWSTR source, PCWSTR localeName); /// Parse the string using the user's default locale. @@ -497,14 +497,14 @@ public: /// Parse the string using the specified locale. /// @note localeName="!x-sys-default-locale" for the system default locale. - /// @note localeName=NULL for the invariant locale. - /// @note localeName="" for the user default locale. + /// @note localeName="" for the invariant locale. + /// @note localeName=NULL for the user default locale. static decimal from_string(const std::string& source, const std::string& localeName); /// Parse the string using the specified locale. /// @note localeName="!x-sys-default-locale" for the system default locale. - /// @note localeName=NULL for the invariant locale. - /// @note localeName="" for the user default locale. + /// @note localeName="" for the invariant locale. + /// @note localeName=NULL for the user default locale. static decimal from_string(const std::string& source, const PCSTR localeName); /// Parse the string using the user's default locale. @@ -528,14 +528,14 @@ public: /// Parse the string using the specified locale. /// @note localeName="!x-sys-default-locale" for the system default locale. - /// @note localeName=NULL for the invariant locale. - /// @note localeName="" for the user default locale. + /// @note localeName="" for the invariant locale. + /// @note localeName=NULL for the user default locale. static decimal from_string_view(const std::string_view& source, const std::string_view& localeName); /// Parse the string using the specified locale. /// @note localeName="!x-sys-default-locale" for the system default locale. - /// @note localeName=NULL for the invariant locale. - /// @note localeName="" for the user default locale. + /// @note localeName="" for the invariant locale. + /// @note localeName=NULL for the user default locale. static decimal from_string_view(const std::string_view& source, PCSTR localeName); /// Parse the string using the user's default locale. @@ -559,14 +559,14 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_wstring(const std::wstring& source, const std::wstring& localeName); /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_wstring(const std::wstring& source, const std::wstring& localeName); /// Parse the string using the user's default locale. @@ -590,14 +590,14 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName); /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_wstring_view(const std::wstring_view& source, PCWSTR localeName); /// Parse the string using the user's default locale. @@ -622,14 +622,14 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName); /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_HSTRING(const HSTRING& source, const HSTRING& localeName); /// Parse the string using the user's default locale. @@ -655,14 +655,14 @@ public: /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_hstring(const winrt::hstring& source, const winrt::hstring& localeName); /// Parse the string using the specified locale. /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_INVARIANT (NULL) for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (L"") for the user default locale. + /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. + /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. static decimal from_hstring(const winrt::hstring& source, PCWSTR localeName); /// Parse the string using the user's default locale. From 24018a33efbadc4c9daf6e8f2ec1fdb3ede86971 Mon Sep 17 00:00:00 2001 From: Howard Kapustein <howardk@microsoft.com> Date: Sat, 28 Jun 2025 19:35:00 -0700 Subject: [PATCH 10/10] Removed *string_view overloads as there's no good way for us to handle if not null-terminated (callers can handle it best) --- specs/decimal/decimal.md | 62 ---------------------------------------- 1 file changed, 62 deletions(-) diff --git a/specs/decimal/decimal.md b/specs/decimal/decimal.md index de60bf4371..01b628a0be 100644 --- a/specs/decimal/decimal.md +++ b/specs/decimal/decimal.md @@ -519,37 +519,6 @@ public: /// Parse the string using the specified locale. static bool try_from_string(const std::string& source, PCSTR localeName, decimal& value); -public: - /// Parse the string using the user's default locale. - static decimal from_string_view(const std::string_view& source); - - /// Parse the string using the invariant locale. - static decimal from_string_view_invariant(const std::string_view& source); - - /// Parse the string using the specified locale. - /// @note localeName="!x-sys-default-locale" for the system default locale. - /// @note localeName="" for the invariant locale. - /// @note localeName=NULL for the user default locale. - static decimal from_string_view(const std::string_view& source, const std::string_view& localeName); - - /// Parse the string using the specified locale. - /// @note localeName="!x-sys-default-locale" for the system default locale. - /// @note localeName="" for the invariant locale. - /// @note localeName=NULL for the user default locale. - static decimal from_string_view(const std::string_view& source, PCSTR localeName); - - /// Parse the string using the user's default locale. - static bool try_from_string_view(const std::string_view& source, decimal& value); - - /// Parse the string using the invariant locale. - static bool try_from_string_view_invariant(const std::string_view& source, decimal& value); - - /// Parse the string using the specified locale. - static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value) - - /// Parse the string using the specified locale. - static bool try_from_string_view(const std::string_view& source, const std::string_view& localeName, decimal& value); - public: /// Parse the string using the user's default locale. static decimal from_wstring(const std::wstring& source); @@ -581,37 +550,6 @@ public: /// Parse the string using the specified locale. static bool try_from_wstring(const std::wstring& source, PCWSTR localeName, decimal& value); -public: - /// Parse the string using the user's default locale. - static decimal from_wstring_view(const std::wstring_view& source); - - /// Parse the string using the invariant locale. - static decimal from_wstring_view_invariant(const std::wstring_view& source); - - /// Parse the string using the specified locale. - /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. - static decimal from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName); - - /// Parse the string using the specified locale. - /// @note localeName=LOCALE_NAME_SYSTEM_DEFAULT (L"!x-sys-default-locale") for the system default locale. - /// @note localeName=LOCALE_NAME_INVARIANT (L"") for the invariant locale. - /// @note localeName=LOCALE_NAME_USER_DEFAULT (NULL) for the user default locale. - static decimal from_wstring_view(const std::wstring_view& source, PCWSTR localeName); - - /// Parse the string using the user's default locale. - static bool try_from_wstring_view(const std::wstring_view& source, decimal& value); - - /// Parse the string using the invariant locale. - static bool try_from_wstring_view_invariant(const std::wstring_view& source, decimal& value); - - /// Parse the string using the specified locale. - static bool try_from_wstring_view(const std::wstring_view& source, const std::wstring_view& localeName, decimal& value); - - /// Parse the string using the specified locale. - static bool try_from_wstring_view(const std::wstring_view& source, PCWSTR localeName, decimal& value); - public: #if defined(__hstring_h__) && defined(__WINSTRING_H_) /// Parse the string using the user's default locale.