18
18
#include < tuple>
19
19
#include < cstring>
20
20
21
+ #if defined(PYBIND11_CPP17)
22
+ # if defined(__has_include)
23
+ # if __has_include(<string_view>)
24
+ # define PYBIND11_HAS_STRING_VIEW
25
+ # endif
26
+ # elif defined(_MSC_VER)
27
+ # define PYBIND11_HAS_STRING_VIEW
28
+ # endif
29
+ #endif
30
+ #ifdef PYBIND11_HAS_STRING_VIEW
31
+ #include < string_view>
32
+ #endif
33
+
21
34
NAMESPACE_BEGIN (pybind11)
22
35
NAMESPACE_BEGIN(detail)
23
36
// Forward declarations:
@@ -1003,10 +1016,11 @@ template <> class type_caster<bool> {
1003
1016
};
1004
1017
1005
1018
// Helper class for UTF-{8,16,32} C++ stl strings:
1006
- template <typename CharT, class Traits , class Allocator >
1007
- struct type_caster <std::basic_string<CharT, Traits, Allocator>, enable_if_t <is_std_char_type<CharT>::value>> {
1019
+ template <typename StringType, bool IsView = false > struct string_caster {
1020
+ using CharT = typename StringType::value_type;
1021
+
1008
1022
// Simplify life by being able to assume standard char sizes (the standard only guarantees
1009
- // minimums) , but Python requires exact sizes
1023
+ // minimums, but Python requires exact sizes)
1010
1024
static_assert (!std::is_same<CharT, char >::value || sizeof (CharT) == 1 , " Unsupported char size != 1" );
1011
1025
static_assert (!std::is_same<CharT, char16_t >::value || sizeof (CharT) == 2 , " Unsupported char16_t size != 2" );
1012
1026
static_assert (!std::is_same<CharT, char32_t >::value || sizeof (CharT) == 4 , " Unsupported char32_t size != 4" );
@@ -1015,8 +1029,6 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s
1015
1029
" Unsupported wchar_t size != 2/4" );
1016
1030
static constexpr size_t UTF_N = 8 * sizeof (CharT);
1017
1031
1018
- using StringType = std::basic_string<CharT, Traits, Allocator>;
1019
-
1020
1032
bool load (handle src, bool ) {
1021
1033
#if PY_MAJOR_VERSION < 3
1022
1034
object temp;
@@ -1050,11 +1062,16 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s
1050
1062
size_t length = (size_t ) PYBIND11_BYTES_SIZE (utfNbytes.ptr ()) / sizeof (CharT);
1051
1063
if (UTF_N > 8 ) { buffer++; length--; } // Skip BOM for UTF-16/32
1052
1064
value = StringType (buffer, length);
1065
+
1066
+ // If we're loading a string_view we need to keep the encoded Python object alive:
1067
+ if (IsView)
1068
+ view_into = std::move (utfNbytes);
1069
+
1053
1070
return true ;
1054
1071
}
1055
1072
1056
1073
static handle cast (const StringType &src, return_value_policy /* policy */ , handle /* parent */ ) {
1057
- const char *buffer = reinterpret_cast <const char *>(src.c_str ());
1074
+ const char *buffer = reinterpret_cast <const char *>(src.data ());
1058
1075
ssize_t nbytes = ssize_t (src.size () * sizeof (CharT));
1059
1076
handle s = decode_utfN (buffer, nbytes);
1060
1077
if (!s) throw error_already_set ();
@@ -1064,6 +1081,8 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s
1064
1081
PYBIND11_TYPE_CASTER (StringType, _(PYBIND11_STRING_NAME));
1065
1082
1066
1083
private:
1084
+ object view_into;
1085
+
1067
1086
static handle decode_utfN (const char *buffer, ssize_t nbytes) {
1068
1087
#if !defined(PYPY_VERSION)
1069
1088
return
@@ -1101,6 +1120,16 @@ struct type_caster<std::basic_string<CharT, Traits, Allocator>, enable_if_t<is_s
1101
1120
bool load_bytes (enable_if_t <sizeof (C) != 1, handle>) { return false ; }
1102
1121
};
1103
1122
1123
+ template <typename CharT, class Traits , class Allocator >
1124
+ struct type_caster <std::basic_string<CharT, Traits, Allocator>, enable_if_t <is_std_char_type<CharT>::value>>
1125
+ : string_caster<std::basic_string<CharT, Traits, Allocator>> {};
1126
+
1127
+ #ifdef PYBIND11_HAS_STRING_VIEW
1128
+ template <typename CharT, class Traits >
1129
+ struct type_caster <std::basic_string_view<CharT, Traits>, enable_if_t <is_std_char_type<CharT>::value>>
1130
+ : string_caster<std::basic_string_view<CharT, Traits>, true > {};
1131
+ #endif
1132
+
1104
1133
// Type caster for C-style strings. We basically use a std::string type caster, but also add the
1105
1134
// ability to use None as a nullptr char* (which the string caster doesn't allow).
1106
1135
template <typename CharT> struct type_caster <CharT, enable_if_t <is_std_char_type<CharT>::value>> {
0 commit comments