diff options
author | Olly Betts <olly@survex.com> | 2023-05-08 15:56:37 +1200 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2023-05-08 15:56:37 +1200 |
commit | 6085a9661edd6bbfbe0dbffd187afda8be8aefd0 (patch) | |
tree | 747308c4a6a0008fe1ba2b5ab7b74b425b063f73 /Lib | |
parent | 0fa2ab8945ff40e770045dd86ed0380c006643fc (diff) | |
download | swig-6085a9661edd6bbfbe0dbffd187afda8be8aefd0.tar.gz |
Initial support for std::string_view
So far C#, Java, Lua and PHP are supported.
Closes: #2540
See #1567
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/csharp/std_string_view.i | 113 | ||||
-rw-r--r-- | Lib/java/std_string_view.i | 138 | ||||
-rw-r--r-- | Lib/lua/std_string_view.i | 41 | ||||
-rw-r--r-- | Lib/php/std_string_view.i | 69 | ||||
-rw-r--r-- | Lib/swig.swg | 5 |
5 files changed, 366 insertions, 0 deletions
diff --git a/Lib/csharp/std_string_view.i b/Lib/csharp/std_string_view.i new file mode 100644 index 000000000..b03c8461a --- /dev/null +++ b/Lib/csharp/std_string_view.i @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- + * std_string_view.i + * + * Typemaps for std::string_view and const std::string_view& + * These are mapped to a C# String and are passed around by value. + * + * To use non-const std::string_view references use the following %apply. Note + * that they are passed by value. + * %apply const std::string_view & {std::string_view &}; + * ----------------------------------------------------------------------------- */ + +%{ +#include <string_view> +#include <string> +%} + +namespace std { + +%naturalvar string_view; + +class string_view; + +// string_view +%typemap(ctype) string_view "const char *" +%typemap(imtype) string_view "string" +%typemap(cstype) string_view "string" + +%typemap(csdirectorin) string_view "$iminput" +%typemap(csdirectorout) string_view "$cscall" + +%typemap(in, canthrow=1) string_view +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + $1 = std::string_view($input); %} +%typemap(out) string_view %{ $result = SWIG_csharp_string_callback(std::string($1).c_str()); %} + +%typemap(directorout, canthrow=1) string_view +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + $result = std::string_view($input); %} + +%typemap(directorin) string_view %{ $input = std::string($1).c_str(); %} + +%typemap(csin) string_view "$csinput" +%typemap(csout, excode=SWIGEXCODE) string_view { + string ret = $imcall;$excode + return ret; + } + +%typemap(typecheck) string_view = char *; + +%typemap(throws, canthrow=1) string_view +%{ SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, std::string($1).c_str()); + return $null; %} + +// const string_view & +%typemap(ctype) const string_view & "const char *" +%typemap(imtype) const string_view & "string" +%typemap(cstype) const string_view & "string" + +%typemap(csdirectorin) const string_view & "$iminput" +%typemap(csdirectorout) const string_view & "$cscall" + +%typemap(in, canthrow=1) const string_view & +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + $*1_ltype $1_str($input); + $1 = &$1_str; %} +%typemap(out) const string_view & %{ $result = SWIG_csharp_string_callback(std::string(*$1).c_str()); %} + +%typemap(csin) const string_view & "$csinput" +%typemap(csout, excode=SWIGEXCODE) const string_view & { + string ret = $imcall;$excode + return ret; + } + +%typemap(directorout, canthrow=1, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string_view & +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + /* possible thread/reentrant code problem */ + static std::string $1_str; + $1_str = $input; + static $*1_ltype $1_strview; + $1_strview = $1_str; + $result = &$1_strview; %} + +%typemap(directorin) const string_view & %{ $input = std::string($1).c_str(); %} + +%typemap(csvarin, excode=SWIGEXCODE2) const string_view & %{ + set { + $imcall;$excode + } %} +%typemap(csvarout, excode=SWIGEXCODE2) const string_view & %{ + get { + string ret = $imcall;$excode + return ret; + } %} + +%typemap(typecheck) const string_view & = char *; + +%typemap(throws, canthrow=1) const string_view & +%{ SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, std::string($1).c_str()); + return $null; %} + +} diff --git a/Lib/java/std_string_view.i b/Lib/java/std_string_view.i new file mode 100644 index 000000000..005b9c0f8 --- /dev/null +++ b/Lib/java/std_string_view.i @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------- + * std_string_view.i + * + * Typemaps for std::string_view and const std::string_view& + * These are mapped to a Java String and are passed around by value. + * + * To use non-const std::string_view references use the following %apply. Note + * that they are passed by value. + * %apply const std::string_view & {std::string_view &}; + * ----------------------------------------------------------------------------- */ + +%{ +#include <string_view> +#include <string> +%} + +namespace std { + +%naturalvar string_view; + +class string_view; + +// string_view +%typemap(jni) string_view "jstring" +%typemap(jtype) string_view "String" +%typemap(jstype) string_view "String" +%typemap(javadirectorin) string_view "$jniinput" +%typemap(javadirectorout) string_view "$javacall" + +%typemap(in) string_view +%{ if(!$input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + $1 = std::string_view($1_pstr); %} + +/* std::string_view requires the string data to remain valid while the + * string_view is in use. */ +%typemap(freearg) string_view +%{ jenv->ReleaseStringUTFChars($input, $1_pstr); %} + +%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) string_view +%{ if(!$input) { + if (!jenv->ExceptionCheck()) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + } + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + /* possible thread/reentrant code problem */ + static std::string $1_str; + $1_str = $1_pstr; + $result = std::string_view($1_str); + jenv->ReleaseStringUTFChars($input, $1_pstr); %} + +/* std::string_view::data() isn't zero-byte terminated, but NewStringUTF() + * requires a zero byte so it seems we have to make a copy (ick). The + * cleanest way to do that seems to be via a temporary std::string. + */ +%typemap(directorin,descriptor="Ljava/lang/String;") string_view +%{ $input = jenv->NewStringUTF(std::string($1).c_str()); + Swig::LocalRefGuard $1_refguard(jenv, $input); %} + +%typemap(out) string_view +%{ $result = jenv->NewStringUTF(std::string($1).c_str()); %} + +%typemap(javain) string_view "$javainput" + +%typemap(javaout) string_view { + return $jnicall; + } + +%typemap(typecheck) string_view = char *; + +%typemap(throws) string_view +%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, std::string($1).c_str()); + return $null; %} + +// const string_view & +%typemap(jni) const string_view & "jstring" +%typemap(jtype) const string_view & "String" +%typemap(jstype) const string_view & "String" +%typemap(javadirectorin) const string_view & "$jniinput" +%typemap(javadirectorout) const string_view & "$javacall" + +%typemap(in) const string_view & +%{ if(!$input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + $*1_ltype $1_str($1_pstr); + $1 = &$1_str; %} + +/* std::string_view requires the string data to remain valid while the + * string_view is in use. */ +%typemap(freearg) const string_view & +%{ jenv->ReleaseStringUTFChars($input, $1_pstr); %} + +%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string_view & +%{ if(!$input) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return $null; + } + const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0); + if (!$1_pstr) return $null; + /* possible thread/reentrant code problem */ + static std::string $1_str; + $1_str = $1_pstr; + static $*1_ltype $1_strview; + $1_strview = $1_str; + $result = &$1_str; + jenv->ReleaseStringUTFChars($input, $1_pstr); %} + +%typemap(directorin,descriptor="Ljava/lang/String;") const string_view & +%{ $input = jenv->NewStringUTF(std::string($1).c_str()); + Swig::LocalRefGuard $1_refguard(jenv, $input); %} + +%typemap(out) const string_view & +%{ $result = jenv->NewStringUTF(std::string(*$1).c_str()); %} + +%typemap(javain) const string_view & "$javainput" + +%typemap(javaout) const string_view & { + return $jnicall; + } + +%typemap(typecheck) const string_view & = char *; + +%typemap(throws) const string_view & +%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, std::string($1).c_str()); + return $null; %} + +} diff --git a/Lib/lua/std_string_view.i b/Lib/lua/std_string_view.i new file mode 100644 index 000000000..f2a439eaa --- /dev/null +++ b/Lib/lua/std_string_view.i @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + * std_string_view.i + * + * std::string_view typemaps for LUA + * ----------------------------------------------------------------------------- */ + +%{ +#include <string_view> +%} + +namespace std { + +%naturalvar string_view; + +%typemap(in,checkfn="lua_isstring") string_view +%{$1 = std::string_view(lua_tostring(L,$input),lua_rawlen(L,$input));%} + +%typemap(out) string_view +%{ lua_pushlstring(L,$1.data(),$1.size()); SWIG_arg++;%} + +%typemap(in,checkfn="lua_isstring") const string_view& ($*1_ltype temp) +%{temp = std::string_view(lua_tostring(L,$input),lua_rawlen(L,$input)); $1=&temp;%} + +%typemap(out) const string_view& +%{ lua_pushlstring(L,$1->data(),$1->size()); SWIG_arg++;%} + +// for throwing of any kind of string_view, string_view ref's and string_view pointers +// we convert all to lua strings +%typemap(throws) string_view, string_view&, const string_view& +%{ lua_pushlstring(L,$1.data(),$1.size()); SWIG_fail;%} + +%typemap(throws) string_view*, const string_view* +%{ lua_pushlstring(L,$1->data(),$1->size()); SWIG_fail;%} + +%typecheck(SWIG_TYPECHECK_STRINGVIEW) string_view, const string_view& { + $1 = lua_isstring(L,$input); +} + +class string_view; + +} diff --git a/Lib/php/std_string_view.i b/Lib/php/std_string_view.i new file mode 100644 index 000000000..7f53f9e22 --- /dev/null +++ b/Lib/php/std_string_view.i @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + * std_string_view.i + * + * SWIG typemaps for std::string_view types + * ----------------------------------------------------------------------------- */ + +%include <exception.i> + +%{ +#include <string_view> +%} + +namespace std { + + %naturalvar string_view; + + class string_view; + + %typemap(typecheck,precedence=SWIG_TYPECHECK_STRINGVIEW) string_view, const string_view& %{ + $1 = (Z_TYPE($input) == IS_STRING) ? 1 : 0; + %} + + %typemap(in, phptype="string") string_view %{ + convert_to_string(&$input); + $1 = std::string_view(Z_STRVAL($input), Z_STRLEN($input)); + %} + + %typemap(directorout) string_view %{ + convert_to_string($input); + $result = std::string_view(Z_STRVAL_P($input), Z_STRLEN_P($input)); + %} + + %typemap(out, phptype="string") string_view %{ + ZVAL_STRINGL($result, $1.data(), $1.size()); + %} + + %typemap(directorin) string_view, const string_view& %{ + ZVAL_STRINGL($input, $1.data(), $1.size()); + %} + + %typemap(out, phptype="string") const string_view& %{ + ZVAL_STRINGL($result, $1->data(), $1->size()); + %} + + %typemap(throws) string_view, const string_view& %{ + { + zval swig_exception; + ZVAL_STRINGL(&swig_exception, $1.data(), $1.size()); + zend_throw_exception_object(&swig_exception); + goto fail; + } + %} + + %typemap(throws) string_view*, const string_view* %{ + { + zval swig_exception; + ZVAL_STRINGL(&swig_exception, $1->data(), $1->size()); + zend_throw_exception_object(&swig_exception); + goto fail; + } + %} + + %typemap(in, phptype="string") const string_view& ($*1_ltype temp) %{ + convert_to_string(&$input); + temp = std::string_view(Z_STRVAL($input), Z_STRLEN($input)); + $1 = &temp; + %} + +} diff --git a/Lib/swig.swg b/Lib/swig.swg index f904f53c6..696dc8145 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -361,6 +361,11 @@ static int NAME(TYPE x) { %define SWIG_TYPECHECK_STDUNISTRING 115 %enddef %define SWIG_TYPECHECK_UNISTRING 120 %enddef %define SWIG_TYPECHECK_CHAR 130 %enddef +/* Give std::string_view a slightly higher precedence because if there are + * overloaded forms then it may be more efficient to pass as std::string_view + * (e.g. to pass as std::string requires copying the data into a std::string). + */ +%define SWIG_TYPECHECK_STRINGVIEW 134 %enddef %define SWIG_TYPECHECK_STDSTRING 135 %enddef %define SWIG_TYPECHECK_STRING 140 %enddef %define SWIG_TYPECHECK_PAIR 150 %enddef |