Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
539 changes: 510 additions & 29 deletions stl/inc/algorithm

Large diffs are not rendered by default.

98 changes: 26 additions & 72 deletions stl/inc/compare
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ using _Compare_t = signed char;
// These "pretty" enumerator names are safe since they reuse names of user-facing entities.
enum class _Compare_eq : _Compare_t { equal = 0, equivalent = equal };
enum class _Compare_ord : _Compare_t { less = -1, greater = 1 };
enum class _Compare_ncmp : _Compare_t { unordered = -127 };
enum class _Compare_ncmp : _Compare_t { unordered = -128 };

// CLASS partial_ordering
class partial_ordering {
Expand All @@ -53,21 +53,7 @@ public:
return _Val._Value == 0;
}

#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(const partial_ordering&, const partial_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
}

_NODISCARD friend constexpr bool operator==(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 == _Val._Value;
}

_NODISCARD friend constexpr bool operator!=(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 != _Val._Value;
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;

_NODISCARD friend constexpr bool operator<(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value == static_cast<_Compare_t>(_Compare_ord::less);
Expand All @@ -78,44 +64,44 @@ public:
}

_NODISCARD friend constexpr bool operator<=(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value <= 0 && _Val._Is_ordered();
// The stored value is either less (0xff), equivalent (0x00), greater (0x01), or unordered (0x80).
// Subtracting from 0 produces either 0x01, 0x00, 0xff, or 0x80. The result is greater than or equal to 0
// if and only if the initial value was less or equivalent, for which we want to return true.
return static_cast<signed char>(0 - static_cast<unsigned int>(_Val._Value)) >= 0;
}

_NODISCARD friend constexpr bool operator>=(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value >= 0;
}

_NODISCARD friend constexpr bool operator<(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 < _Val._Value;
return _Val > 0;
}

_NODISCARD friend constexpr bool operator>(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 > _Val._Value && _Val._Is_ordered();
return _Val < 0;
}

_NODISCARD friend constexpr bool operator<=(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 <= _Val._Value;
return _Val >= 0;
}

_NODISCARD friend constexpr bool operator>=(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 >= _Val._Value && _Val._Is_ordered();
return _Val <= 0;
}

#ifdef __cpp_impl_three_way_comparison
_NODISCARD friend constexpr partial_ordering operator<=>(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val;
}

_NODISCARD friend constexpr partial_ordering operator<=>(_Literal_zero, const partial_ordering _Val) noexcept {
return partial_ordering{static_cast<_Compare_ord>(-_Val._Value)};
// The stored value is either less (0xff), equivalent (0x00), greater (0x01), or unordered (0x80).
// Subtracting from 0 produces either 0x01, 0x00, 0xff, or 0x80. Note that the effect is to
// exchange less for greater (and vice versa), while leaving equivalent and unordered unchanged.
return partial_ordering{static_cast<_Compare_ord>(0 - static_cast<unsigned int>(_Val._Value))};
}
#endif // __cpp_impl_three_way_comparison

private:
_NODISCARD constexpr bool _Is_ordered() const noexcept {
return _Value != static_cast<_Compare_t>(_Compare_ncmp::unordered);
}

_Compare_t _Value;
};

Expand Down Expand Up @@ -144,21 +130,7 @@ public:
return _Val._Value == 0;
}

#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(const weak_ordering&, const weak_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
}

_NODISCARD friend constexpr bool operator==(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 == _Val._Value;
}

_NODISCARD friend constexpr bool operator!=(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 != _Val._Value;
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;

_NODISCARD friend constexpr bool operator<(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value < 0;
Expand All @@ -177,30 +149,28 @@ public:
}

_NODISCARD friend constexpr bool operator<(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 < _Val._Value;
return _Val > 0;
}

_NODISCARD friend constexpr bool operator>(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 > _Val._Value;
return _Val < 0;
}

_NODISCARD friend constexpr bool operator<=(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 <= _Val._Value;
return _Val >= 0;
}

_NODISCARD friend constexpr bool operator>=(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 >= _Val._Value;
return _Val <= 0;
}

#ifdef __cpp_impl_three_way_comparison
_NODISCARD friend constexpr weak_ordering operator<=>(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val;
}

_NODISCARD friend constexpr weak_ordering operator<=>(_Literal_zero, const weak_ordering _Val) noexcept {
return weak_ordering{static_cast<_Compare_ord>(-_Val._Value)};
}
#endif // __cpp_impl_three_way_comparison

private:
_Compare_t _Value;
Expand Down Expand Up @@ -235,21 +205,7 @@ public:
return _Val._Value == 0;
}

#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(const strong_ordering&, const strong_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
}

_NODISCARD friend constexpr bool operator==(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 == _Val._Value;
}

_NODISCARD friend constexpr bool operator!=(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 != _Val._Value;
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;

_NODISCARD friend constexpr bool operator<(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value < 0;
Expand All @@ -268,30 +224,28 @@ public:
}

_NODISCARD friend constexpr bool operator<(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 < _Val._Value;
return _Val > 0;
}

_NODISCARD friend constexpr bool operator>(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 > _Val._Value;
return _Val < 0;
}

_NODISCARD friend constexpr bool operator<=(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 <= _Val._Value;
return _Val >= 0;
}

_NODISCARD friend constexpr bool operator>=(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 >= _Val._Value;
return _Val <= 0;
}

#ifdef __cpp_impl_three_way_comparison
_NODISCARD friend constexpr strong_ordering operator<=>(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val;
}

_NODISCARD friend constexpr strong_ordering operator<=>(_Literal_zero, const strong_ordering _Val) noexcept {
return strong_ordering{static_cast<_Compare_ord>(-_Val._Value)};
}
#endif // __cpp_impl_three_way_comparison

private:
_Compare_t _Value;
Expand Down Expand Up @@ -364,7 +318,7 @@ struct common_comparison_category {
using type = common_comparison_category_t<_Types...>;
};

#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
#ifdef __cpp_lib_concepts
// clang-format off
template <class _Ty, class _Cat>
concept _Compares_as = same_as<common_comparison_category_t<_Ty, _Cat>, _Cat>;
Expand Down Expand Up @@ -409,7 +363,7 @@ struct compare_three_way {
using is_transparent = int;
};
// clang-format on
#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
#endif // __cpp_lib_concepts

// Other components not yet implemented
_STD_END
Expand Down
34 changes: 32 additions & 2 deletions stl/inc/filesystem
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,32 @@ namespace filesystem {
return _Output;
}

// More lenient version of _Convert_wide_to_narrow: Instead of failing on non-representable characters,
// replace them with a replacement character.
template <class _Traits, class _Alloc>
_NODISCARD basic_string<typename _Traits::char_type, _Traits, _Alloc> _Convert_wide_to_narrow_replace_chars(
const __std_code_page _Code_page, const wstring_view _Input, const _Alloc& _Al) {
basic_string<typename _Traits::char_type, _Traits, _Alloc> _Output(_Al);

if (!_Input.empty()) {
if (_Input.size() > static_cast<size_t>(INT_MAX)) {
_Throw_system_error(errc::invalid_argument);
}

const int _Len = _Check_convert_result(__std_fs_convert_wide_to_narrow_replace_chars(
_Code_page, _Input.data(), static_cast<int>(_Input.size()), nullptr, 0));

_Output.resize(static_cast<size_t>(_Len));

const auto _Data_as_char = reinterpret_cast<char*>(_Output.data());

(void) _Check_convert_result(__std_fs_convert_wide_to_narrow_replace_chars(
_Code_page, _Input.data(), static_cast<int>(_Input.size()), _Data_as_char, _Len));
}

return _Output;
}

_NODISCARD inline wstring _Convert_utf32_to_wide(const u32string_view _Input) {
wstring _Output;

Expand Down Expand Up @@ -1786,8 +1812,12 @@ namespace filesystem {
static string _Pretty_message(const string_view _Op, const path& _Path1, const path& _Path2 = {}) {
using namespace _STD string_view_literals; // TRANSITION, VSO-571749
string _Result;
const string _Path1_str = _Path1.string();
const string _Path2_str = _Path2.string();
// Convert the paths to narrow encoding in a way that gracefully handles non-encodable characters
const auto _Code_page = __std_fs_code_page();
const string _Path1_str = _Convert_wide_to_narrow_replace_chars<char_traits<char>>(
_Code_page, _Path1.native(), allocator<char>{});
const string _Path2_str = _Convert_wide_to_narrow_replace_chars<char_traits<char>>(
_Code_page, _Path2.native(), allocator<char>{});
_Result.reserve(_Op.size() + (_Path2_str.empty() ? 4 : 8) + _Path1_str.size() + _Path2_str.size());
_Result += _Op;
_Result += R"(: ")"sv; // 3 chars
Expand Down
30 changes: 1 addition & 29 deletions stl/inc/span
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@
#if !_HAS_CXX20
#pragma message("The contents of <span> are available only with C++20 or later.")
#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv
#include <compare>
#include <cstddef>
#include <type_traits>
#include <xutility>

#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
#include <compare>
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
Expand Down Expand Up @@ -153,39 +151,13 @@ struct _Span_iterator {
return _Myptr == _Right._Myptr;
}

#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD constexpr strong_ordering operator<=>(const _Span_iterator& _Right) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(
_Mybegin == _Right._Mybegin && _Myend == _Right._Myend, "cannot compare incompatible span iterators");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr <=> _Right._Myptr;
}
#else // ^^^ use spaceship / no spaceship vvv
_NODISCARD constexpr bool operator!=(const _Span_iterator& _Right) const noexcept {
return !(*this == _Right);
}

_NODISCARD constexpr bool operator<(const _Span_iterator& _Right) const noexcept {
#if _ITERATOR_DEBUG_LEVEL >= 1
_STL_VERIFY(
_Mybegin == _Right._Mybegin && _Myend == _Right._Myend, "cannot compare incompatible span iterators");
#endif // _ITERATOR_DEBUG_LEVEL >= 1
return _Myptr < _Right._Myptr;
}

_NODISCARD constexpr bool operator>(const _Span_iterator& _Right) const noexcept {
return _Right < *this;
}

_NODISCARD constexpr bool operator<=(const _Span_iterator& _Right) const noexcept {
return !(_Right < *this);
}

_NODISCARD constexpr bool operator>=(const _Span_iterator& _Right) const noexcept {
return !(*this < _Right);
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L

#if _ITERATOR_DEBUG_LEVEL >= 1
friend constexpr void _Verify_range(const _Span_iterator& _First, const _Span_iterator& _Last) noexcept {
Expand Down
4 changes: 4 additions & 0 deletions stl/inc/xfilesystem_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ _NODISCARD __std_fs_convert_result __stdcall __std_fs_convert_wide_to_narrow(_In
_In_reads_(_Input_len) const wchar_t* _Input_str, _In_ int _Input_len,
_Out_writes_opt_(_Output_len) char* _Output_str, _In_ int _Output_len) noexcept;

_NODISCARD __std_fs_convert_result __stdcall __std_fs_convert_wide_to_narrow_replace_chars(
_In_ __std_code_page _Code_page, _In_reads_(_Input_len) const wchar_t* _Input_str, _In_ int _Input_len,
_Out_writes_opt_(_Output_len) char* _Output_str, _In_ int _Output_len) noexcept;

_NODISCARD __std_win_error __stdcall __std_fs_get_file_id(
_Out_ __std_fs_file_id* _Id, _In_z_ const wchar_t* _Path) noexcept;

Expand Down
Loading