1515
1616#include < version>
1717
18- #if __cpp_lib_ranges < 201911L
19- #error This header requires C++20 mode or above with ranges support
18+ #if !__cpp_concepts
19+ #error This header requires C++20 mode or above with concepts support
2020#endif
2121
22+
2223#include " NSObjectUtil.h"
2324
2425#ifdef __OBJC__
3031#include < ranges>
3132#include < string_view>
3233#include < ostream>
34+ #if __cpp_lib_ranges < 201911L
35+ #include < vector>
36+ #include < span>
37+ #endif
3338
3439#pragma clang diagnostic push
3540#pragma clang diagnostic ignored "-Wnullability-extension"
@@ -446,6 +451,8 @@ inline auto makeStdString(NSStringCharAccess::const_iterator first, NSStringChar
446451 return makeStdString<Char>(first.getCFString (), first.index (), last.index () - first.index ());
447452}
448453
454+ #if __cpp_lib_ranges >= 201911L
455+
449456/* *
450457 Converts NSStringCharAccess or a view derived from it to `std::basic_string<Char>`
451458
@@ -489,6 +496,90 @@ inline auto makeCFString(const CharRange & range) -> CFStringRef __nullable {
489496 }
490497}
491498
499+ #else
500+
501+ /* *
502+ Converts `NSStringCharAccess` to `std::basic_string<Char>`
503+
504+ @tparam Char character type of the resultant std::basic_string
505+
506+ Conversions to char16_t are exact and never fail. Conversions to other character types are transcodings and can fail if source string contains invalid UTF-16
507+ sequences. In such cases an empty string is returned. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
508+ */
509+ template<CharTypeConvertibleWithNSString Char>
510+ inline auto makeStdString (const NSStringCharAccess & access) {
511+ return makeStdString<Char>(access.begin (), access.end ());
512+ }
513+
514+ /* *
515+ Converts `std::basic_string_view` to `CFString`
516+
517+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
518+
519+ @returns nullptr on failure
520+
521+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
522+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
523+ */
524+ template<CharTypeConvertibleWithNSString Char>
525+ inline auto makeCFString (std::basic_string_view<Char> str) -> CFStringRef __nullable {
526+ if (str.empty ())
527+ return CFSTR (" " );
528+ if constexpr (std::is_same_v<Char, char16_t >) {
529+ return CFStringCreateWithCharacters (nullptr , (const UniChar *)str.data (), CFIndex (str.size ()));
530+ } else {
531+ return CFStringCreateWithBytes (nullptr , (const UInt8 *)str.data (), CFIndex (str.size () * sizeof (Char)),
532+ kCFStringEncodingFor <Char>, false );
533+ }
534+ }
535+
536+ /* *
537+ Converts `std::basic_string` to `CFString`
538+
539+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
540+
541+ @returns nullptr on failure
542+
543+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
544+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
545+ */
546+ template<CharTypeConvertibleWithNSString Char>
547+ inline auto makeCFString (std::basic_string<Char> str) -> CFStringRef __nullable {
548+ return makeCFString (std::basic_string_view<Char>(str));
549+ }
550+
551+ /* *
552+ Converts `std::vector<Char>` to `CFString`
553+
554+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
555+
556+ @returns nullptr on failure
557+
558+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
559+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
560+ */
561+ template<CharTypeConvertibleWithNSString Char>
562+ inline auto makeCFString (std::vector<Char> str) -> CFStringRef __nullable {
563+ return makeCFString (std::basic_string_view<Char>(str.data (), str.size ()));
564+ }
565+
566+ /* *
567+ Converts `std::span<Char>` to `CFString`
568+
569+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
570+
571+ @returns nullptr on failure
572+
573+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
574+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
575+ */
576+ template<CharTypeConvertibleWithNSString Char>
577+ inline auto makeCFString (std::span<Char> str) -> CFStringRef __nullable {
578+ return makeCFString (std::basic_string_view<Char>(str.data (), str.size ()));
579+ }
580+
581+ #endif
582+
492583/* *
493584 Converts a null terminated character string to CFString
494585
@@ -524,6 +615,8 @@ inline auto makeCFString(const std::initializer_list<Char> & str) {
524615
525616#ifdef __OBJC__
526617
618+ #if __cpp_lib_ranges >= 201911L
619+
527620/* *
528621 Converts any contiguous range of characters to NSString
529622
@@ -540,6 +633,70 @@ inline auto makeNSString(const CharRange & range) {
540633 return (__bridge_transfer NSString *)makeCFString (range);
541634}
542635
636+ #else
637+
638+ /* *
639+ Converts `std::basic_string_view` to NSString
640+
641+ @returns nil on failure
642+
643+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
644+
645+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
646+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
647+ */
648+ template<CharTypeConvertibleWithNSString Char>
649+ inline auto makeNSString (std::basic_string_view<Char> str) {
650+ return (__bridge_transfer NSString *)makeCFString (str);
651+ }
652+
653+ /* *
654+ Converts `std::basic_string` to NSString
655+
656+ @returns nil on failure
657+
658+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
659+
660+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
661+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
662+ */
663+ template<CharTypeConvertibleWithNSString Char>
664+ inline auto makeNSString (std::basic_string<Char> str) {
665+ return (__bridge_transfer NSString *)makeCFString (str);
666+ }
667+
668+ /* *
669+ Converts `std::vector<Char>` to NSString
670+
671+ @returns nil on failure
672+
673+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
674+
675+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
676+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
677+ */
678+ template<CharTypeConvertibleWithNSString Char>
679+ inline auto makeNSString (std::vector<Char> str) {
680+ return (__bridge_transfer NSString *)makeCFString (str);
681+ }
682+
683+ /* *
684+ Converts `std::span<Char>` to NSString
685+
686+ @returns nil on failure
687+
688+ The type of range's characters can be any of: char, char16_t, char32_t, char8_t, wchar_t.
689+
690+ Conversions from char16_t are exact and can only fail if out of memory. Conversions from other character types are
691+ transcodings and can fail if source string contains invalid UTF sequences. Encodings of char and wchar_t are UTF-8 and UTF-32 respectively.
692+ */
693+ template<CharTypeConvertibleWithNSString Char>
694+ inline auto makeNSString (std::span<Char> str) {
695+ return (__bridge_transfer NSString *)makeCFString (str);
696+ }
697+
698+ #endif
699+
543700/* *
544701 Converts a null terminated character string to NSString
545702
0 commit comments