|
177 | 177 | // file with that name, it is superceded by P1164R1, so only activate if really needed
|
178 | 178 | // #define LWG_2935_BEHAVIOUR
|
179 | 179 | //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 180 | +// LWG #2936 enables new element wise (more expensive) path comparison |
| 181 | +// * if this->root_name().native().compare(p.root_name().native()) != 0 return result |
| 182 | +// * if this->has_root_directory() and !p.has_root_directory() return -1 |
| 183 | +// * if !this->has_root_directory() and p.has_root_directory() return -1 |
| 184 | +// * else result of element wise comparison of path iteration where first comparison is != 0 or 0 |
| 185 | +// if all comparisons are 0 (on Windows this implementation does case insensitive root_name() |
| 186 | +// comparison) |
| 187 | +// #define LWG_2936_BEHAVIOUR |
| 188 | +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
180 | 189 | // LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
|
181 | 190 | #define LWG_2937_BEHAVIOUR
|
182 | 191 | //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
@@ -1754,6 +1763,21 @@ GHC_INLINE bool equals_simple_insensitive(const char* str1, const char* str2)
|
1754 | 1763 | #endif
|
1755 | 1764 | }
|
1756 | 1765 |
|
| 1766 | +GHC_INLINE int compare_simple_insensitive(const char* str1, size_t len1, const char* str2, size_t len2) |
| 1767 | +{ |
| 1768 | + while(len1 > 0 && len2 > 0 && ::tolower((unsigned char)*str1) == ::tolower((unsigned char)*str2)) { |
| 1769 | + --len1; --len2; |
| 1770 | + ++str1; ++str2; |
| 1771 | + } |
| 1772 | + if (len1 && len2) { |
| 1773 | + return *str1 < *str2 ? -1 : 1; |
| 1774 | + } |
| 1775 | + if(len1 == 0 && len2 == 0) { |
| 1776 | + return 0; |
| 1777 | + } |
| 1778 | + return len1 == 0 ? -1 : 1; |
| 1779 | +} |
| 1780 | + |
1757 | 1781 | GHC_INLINE const char* strerror_adapter(char* gnu, char*)
|
1758 | 1782 | {
|
1759 | 1783 | return gnu;
|
@@ -2652,24 +2676,75 @@ GHC_INLINE std::u32string path::generic_u32string() const
|
2652 | 2676 | // 30.10.8.4.8, compare
|
2653 | 2677 | GHC_INLINE int path::compare(const path& p) const noexcept
|
2654 | 2678 | {
|
2655 |
| - return native().compare(p.native()); |
| 2679 | +#ifdef LWG_2936_BEHAVIOUR |
| 2680 | + auto rnl1 = root_name_length(); |
| 2681 | + auto rnl2 = p.root_name_length(); |
| 2682 | +#ifdef GHC_OS_WINDOWS |
| 2683 | + auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2); |
| 2684 | +#else |
| 2685 | + auto rnc = _path.compare(0, rnl1, p._path, 0, (std::min(rnl1, rnl2))); |
| 2686 | +#endif |
| 2687 | + if (rnc) { |
| 2688 | + return rnc; |
| 2689 | + } |
| 2690 | + bool hrd1 = has_root_directory(), hrd2 = p.has_root_directory(); |
| 2691 | + if (hrd1 != hrd2) { |
| 2692 | + return hrd1 ? 1 : -1; |
| 2693 | + } |
| 2694 | + if (hrd1) { |
| 2695 | + ++rnl1; |
| 2696 | + ++rnl2; |
| 2697 | + } |
| 2698 | + auto iter1 = _path.begin() + rnl1; |
| 2699 | + auto iter2 = p._path.begin() + rnl2; |
| 2700 | + while (iter1 != _path.end() && iter2 != p._path.end() && *iter1 == *iter2) { |
| 2701 | + ++iter1; |
| 2702 | + ++iter2; |
| 2703 | + } |
| 2704 | + if (iter1 == _path.end()) { |
| 2705 | + return iter2 == p._path.end() ? 0 : -1; |
| 2706 | + } |
| 2707 | + if (iter2 == p._path.end()) { |
| 2708 | + return 1; |
| 2709 | + } |
| 2710 | + if (*iter1 == '/') { |
| 2711 | + return -1; |
| 2712 | + } |
| 2713 | + if (*iter2 == '/') { |
| 2714 | + return 1; |
| 2715 | + } |
| 2716 | + return *iter1 < *iter2 ? -1 : 1; |
| 2717 | +#else // LWG_2936_BEHAVIOUR |
| 2718 | +#ifdef GHC_OS_WINDOWS |
| 2719 | + auto rnl1 = root_name_length(); |
| 2720 | + auto rnl2 = p.root_name_length(); |
| 2721 | + auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2); |
| 2722 | + auto p1 = _path; |
| 2723 | + std::replace(p1.begin()+rnl1, p1.end(), '/', '\\'); |
| 2724 | + auto p2 = p._path; |
| 2725 | + std::replace(p2.begin()+rnl2, p2.end(), '/', '\\'); |
| 2726 | + return p1.compare(rnl1, std::string::npos, p2, rnl2, std::string::npos); |
| 2727 | +#else |
| 2728 | + return _path.compare(p._path); |
| 2729 | +#endif |
| 2730 | +#endif |
2656 | 2731 | }
|
2657 | 2732 |
|
2658 | 2733 | GHC_INLINE int path::compare(const string_type& s) const
|
2659 | 2734 | {
|
2660 |
| - return native().compare(path(s).native()); |
| 2735 | + return compare(path(s)); |
2661 | 2736 | }
|
2662 | 2737 |
|
2663 | 2738 | #ifdef __cpp_lib_string_view
|
2664 | 2739 | GHC_INLINE int path::compare(std::basic_string_view<value_type> s) const
|
2665 | 2740 | {
|
2666 |
| - return native().compare(path(s).native()); |
| 2741 | + return compare(path(s)); |
2667 | 2742 | }
|
2668 | 2743 | #endif
|
2669 | 2744 |
|
2670 | 2745 | GHC_INLINE int path::compare(const value_type* s) const
|
2671 | 2746 | {
|
2672 |
| - return native().compare(path(s).native()); |
| 2747 | + return compare(path(s)); |
2673 | 2748 | }
|
2674 | 2749 |
|
2675 | 2750 | //-----------------------------------------------------------------------------
|
@@ -3116,32 +3191,52 @@ GHC_INLINE size_t hash_value(const path& p) noexcept
|
3116 | 3191 |
|
3117 | 3192 | GHC_INLINE bool operator==(const path& lhs, const path& rhs) noexcept
|
3118 | 3193 | {
|
| 3194 | +#ifdef LWG_2936_BEHAVIOUR |
| 3195 | + return lhs.compare(rhs) == 0; |
| 3196 | +#else |
3119 | 3197 | return lhs.generic_string() == rhs.generic_string();
|
| 3198 | +#endif |
3120 | 3199 | }
|
3121 | 3200 |
|
3122 | 3201 | GHC_INLINE bool operator!=(const path& lhs, const path& rhs) noexcept
|
3123 | 3202 | {
|
3124 |
| - return lhs.generic_string() != rhs.generic_string(); |
| 3203 | + return !(lhs == rhs); |
3125 | 3204 | }
|
3126 | 3205 |
|
3127 | 3206 | GHC_INLINE bool operator<(const path& lhs, const path& rhs) noexcept
|
3128 | 3207 | {
|
| 3208 | +#ifdef LWG_2936_BEHAVIOUR |
| 3209 | + return lhs.compare(rhs) < 0; |
| 3210 | +#else |
3129 | 3211 | return lhs.generic_string() < rhs.generic_string();
|
| 3212 | +#endif |
3130 | 3213 | }
|
3131 | 3214 |
|
3132 | 3215 | GHC_INLINE bool operator<=(const path& lhs, const path& rhs) noexcept
|
3133 | 3216 | {
|
| 3217 | +#ifdef LWG_2936_BEHAVIOUR |
| 3218 | + return lhs.compare(rhs) <= 0; |
| 3219 | +#else |
3134 | 3220 | return lhs.generic_string() <= rhs.generic_string();
|
| 3221 | +#endif |
3135 | 3222 | }
|
3136 | 3223 |
|
3137 | 3224 | GHC_INLINE bool operator>(const path& lhs, const path& rhs) noexcept
|
3138 | 3225 | {
|
| 3226 | +#ifdef LWG_2936_BEHAVIOUR |
| 3227 | + return lhs.compare(rhs) > 0; |
| 3228 | +#else |
3139 | 3229 | return lhs.generic_string() > rhs.generic_string();
|
| 3230 | +#endif |
3140 | 3231 | }
|
3141 | 3232 |
|
3142 | 3233 | GHC_INLINE bool operator>=(const path& lhs, const path& rhs) noexcept
|
3143 | 3234 | {
|
| 3235 | +#ifdef LWG_2936_BEHAVIOUR |
| 3236 | + return lhs.compare(rhs) >= 0; |
| 3237 | +#else |
3144 | 3238 | return lhs.generic_string() >= rhs.generic_string();
|
| 3239 | +#endif |
3145 | 3240 | }
|
3146 | 3241 |
|
3147 | 3242 | GHC_INLINE path operator/(const path& lhs, const path& rhs)
|
|
0 commit comments