Initial support for std::string_view

So far C#, Java, Lua and PHP are supported.

Closes: #2540
See #1567
This commit is contained in:
Olly Betts 2023-05-08 15:56:37 +12:00
parent 0fa2ab8945
commit 6085a9661e
18 changed files with 994 additions and 11 deletions

View File

@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress)
===========================
2023-05-08: olly
#1567 Add support for std::string_view (new in C++17) for C#, Java,
Lua and PHP.
2023-05-08: olly
[PHP] #2544 Wrap overloaded method with both static and non-static
forms. We now wrap this as a non-static method in PHP, which means

View File

@ -445,6 +445,7 @@
<li><a href="Library.html#Library_stl_cpp_library">STL/C++ library</a>
<ul>
<li><a href="Library.html#Library_std_string">std::string</a>
<li><a href="Library.html#Library_std_string_view">std::string_view</a>
<li><a href="Library.html#Library_std_vector">std::vector</a>
<li><a href="Library.html#Library_stl_exceptions">STL exceptions</a>
<li><a href="Library.html#Library_std_shared_ptr">shared_ptr smart pointer</a>

View File

@ -30,6 +30,7 @@
<li><a href="#Library_stl_cpp_library">STL/C++ library</a>
<ul>
<li><a href="#Library_std_string">std::string</a>
<li><a href="#Library_std_string_view">std::string_view</a>
<li><a href="#Library_std_vector">std::vector</a>
<li><a href="#Library_stl_exceptions">STL exceptions</a>
<li><a href="#Library_std_shared_ptr">shared_ptr smart pointer</a>
@ -1450,14 +1451,15 @@ The following table shows which C++ classes are supported and the equivalent SWI
<tr> <td>std::multiset (C++11)</td> <td>multiset</td> <td>std_multiset.i</td> </tr>
<tr> <td>std::pair</td> <td>utility</td> <td>std_pair.i</td> </tr>
<tr> <td>std::set</td> <td>set</td> <td>std_set.i</td> </tr>
<tr> <td>std::shared_ptr (C++11)</td> <td>shared_ptr</td> <td>std_shared_ptr.i</td> </tr>
<tr> <td>std::string</td> <td>string</td> <td>std_string.i</td> </tr>
<tr> <td>std::string_view (C++17)</td> <td>string_view</td> <td>std_string_view.i</td> </tr>
<tr> <td>std::unordered_map (C++11)</td> <td>unordered_map</td> <td>std_unordered_map.i</td> </tr>
<tr> <td>std::unordered_multimap (C++11)</td> <td>unordered_multimap</td> <td>std_unordered_multimap.i</td> </tr>
<tr> <td>std::unordered_multiset (C++11)</td> <td>unordered_multiset</td> <td>std_unordered_multiset.i</td> </tr>
<tr> <td>std::unordered_set (C++11)</td> <td>unordered_set</td> <td>std_unordered_set.i</td> </tr>
<tr> <td>std::vector</td> <td>vector</td> <td>std_vector.i</td> </tr>
<tr> <td>std::wstring</td> <td>wstring</td> <td>std_wstring.i</td> </tr>
<tr> <td>std::shared_ptr (C++11)</td> <td>shared_ptr</td> <td>std_shared_ptr.i</td> </tr>
</table>
@ -1551,7 +1553,37 @@ void foo(string s, const String &amp;t); // std_string typemaps still applie
</pre>
</div>
<H3><a name="Library_std_vector">12.4.2 std::vector</a></H3>
<H3><a name="Library_std_string_view">12.4.2 std::string_view</a></H3>
<p>
The <tt>std_string_view.i</tt> library provides typemaps for converting C++17 <tt>std::string_view</tt>
objects to and from strings in the target scripting language. For example:
</p>
<div class="code">
<pre>
%module example
%include "std_string_view.i"
std::string_view foo();
void bar(std::string_view x);
</pre>
</div>
<p>
In the target language:
</p>
<div class="targetlang">
<pre>
x = foo(); # Returns a string object
bar("Hello World"); # Pass string as std::string_view
</pre>
</div>
<H3><a name="Library_std_vector">12.4.3 std::vector</a></H3>
<p>
@ -1730,7 +1762,7 @@ if you want to make their head explode.
details and the public API exposed to the interpreter vary.
</p>
<H3><a name="Library_stl_exceptions">12.4.3 STL exceptions</a></H3>
<H3><a name="Library_stl_exceptions">12.4.4 STL exceptions</a></H3>
<p>
@ -1780,10 +1812,10 @@ The <tt>%exception</tt> directive can be used by placing the following code befo
Any thrown STL exceptions will then be gracefully handled instead of causing a crash.
</p>
<H3><a name="Library_std_shared_ptr">12.4.4 shared_ptr smart pointer</a></H3>
<H3><a name="Library_std_shared_ptr">12.4.5 shared_ptr smart pointer</a></H3>
<H4><a name="Library_shared_ptr_basics">12.4.4.1 shared_ptr basics</a></H4>
<H4><a name="Library_shared_ptr_basics">12.4.5.1 shared_ptr basics</a></H4>
<p>
@ -1879,7 +1911,7 @@ System.out.println(val1 + " " + val2);
</pre>
</div>
<H4><a name="Library_shared_ptr_inheritance">12.4.4.2 shared_ptr and inheritance</a></H4>
<H4><a name="Library_shared_ptr_inheritance">12.4.5.2 shared_ptr and inheritance</a></H4>
<p>
@ -1970,7 +2002,7 @@ Adding the missing <tt>%shared_ptr</tt> macros will fix this:
</pre>
</div>
<H4><a name="Library_shared_ptr_overloading">12.4.4.3 shared_ptr and method overloading</a></H4>
<H4><a name="Library_shared_ptr_overloading">12.4.5.3 shared_ptr and method overloading</a></H4>
<p>
@ -1992,7 +2024,7 @@ SWIG will choose to wrap just the first method by default.
For the interested reader, SWIG detects that they are equivalent types via the <a href=Typemaps.html#Typemaps_typecheck_pointer>typecheck typemaps</a> in the shared_ptr library.
</p>
<H4><a name="Library_shared_ptr_templates">12.4.4.4 shared_ptr and templates</a></H4>
<H4><a name="Library_shared_ptr_templates">12.4.5.4 shared_ptr and templates</a></H4>
<p>
@ -2034,14 +2066,14 @@ The SWIG code below shows the required ordering:
</pre>
</div>
<H4><a name="Library_shared_ptr_directors">12.4.4.5 shared_ptr and directors</a></H4>
<H4><a name="Library_shared_ptr_directors">12.4.5.5 shared_ptr and directors</a></H4>
<p>
The languages that support shared_ptr also have support for using shared_ptr with directors.
</p>
<H3><a name="Library_std_unique_ptr">12.4.5 unique_ptr smart pointer</a></H3>
<H3><a name="Library_std_unique_ptr">12.4.6 unique_ptr smart pointer</a></H3>
<p>
@ -2163,7 +2195,7 @@ in a "Cannot release ownership as memory is not owned" exception. For example, i
<b>Compatibility note:</b> Support for <tt>std::unique_ptr</tt> was added in SWIG-4.1.0.
</p>
<H3><a name="Library_std_auto_ptr">12.4.6 auto_ptr smart pointer</a></H3>
<H3><a name="Library_std_auto_ptr">12.4.7 auto_ptr smart pointer</a></H3>
<p>

View File

@ -657,6 +657,7 @@ CPP17_TEST_CASES += \
cpp17_hex_floating_literals \
cpp17_nested_namespaces \
cpp17_nspace_nested_namespaces \
cpp17_string_view \
cpp17_u8_char_literals \
# Broken C++17 test cases.

View File

@ -0,0 +1,112 @@
%module cpp17_string_view
#if defined SWIGCSHARP || defined SWIGJAVA || defined SWIGLUA || defined SWIGPHP
%include <std_string_view.i>
// throw is invalid in C++17 and later, only SWIG to use it
#define TESTCASE_THROW1(T1) throw(T1)
%{
#define TESTCASE_THROW1(T1)
%}
%inline %{
std::string_view test_value(std::string_view x) {
return x;
}
const std::string_view& test_const_reference(const std::string_view &x) {
return x;
}
void test_const_reference_returning_void(const std::string_view &) {
}
void test_const_reference_returning_void(const std::string_view &, int) {
}
void test_pointer(std::string_view *x) {
}
std::string_view *test_pointer_out() {
static std::string_view x = "x";
return &x;
}
void test_const_pointer(const std::string_view *x) {
}
const std::string_view *test_const_pointer_out() {
static std::string_view x = "x";
return &x;
}
void test_reference(std::string_view &x) {
}
std::string_view& test_reference_out() {
static std::string_view x = "test_reference_out message";
return x;
}
std::string_view test_reference_input(std::string_view &input) {
return input;
}
void test_throw() TESTCASE_THROW1(std::string_view){
static std::string_view x = "test_throw message";
throw x;
}
void test_const_reference_throw() TESTCASE_THROW1(const std::string_view &){
static const std::string_view x = "test_const_reference_throw message";
throw x;
}
void test_pointer_throw() TESTCASE_THROW1(std::string_view *) {
throw new std::string_view("foo");
}
void test_const_pointer_throw() TESTCASE_THROW1(const std::string_view *) {
throw static_cast<const std::string_view*>(new std::string_view("foo"));
}
%}
#ifdef SWIGSCILAB
%rename(ConstStr) ConstMemberString;
%rename(ConstStaticStr) ConstStaticMemberString;
#endif
%inline %{
const std::string_view ConstGlobalString = "const global string";
struct Structure {
const std::string_view ConstMemberString;
static const std::string_view ConstStaticMemberString;
Structure() : ConstMemberString("const member string") {}
};
%}
%{
const std::string_view Structure::ConstStaticMemberString = "const static member string";
%}
%inline %{
std::string_view stdstring_empty() {
return std::string_view();
}
char *c_empty() {
return (char *)"";
}
char *c_null() {
return 0;
}
const char *get_null(const char *a) {
return a == 0 ? a : "non-null";
}
%}
#endif

View File

@ -0,0 +1,84 @@
using System;
using cpp17_string_viewNamespace;
public class runme
{
static void Main()
{
// Checking expected use of %typemap(in) std::string {}
cpp17_string_view.test_value("Fee");
// Checking expected result of %typemap(out) std::string {}
if (cpp17_string_view.test_value("Fi") != "Fi")
throw new Exception("Test 1 failed");
// Verify type-checking for %typemap(in) std::string {}
try {
cpp17_string_view.test_value(null);
throw new Exception("Test 2 failed");
} catch (ArgumentNullException) {
}
// Checking expected use of %typemap(in) const std::string & {}
cpp17_string_view.test_const_reference("Fo");
// Checking expected result of %typemap(out) const std::string& {}
if (cpp17_string_view.test_const_reference("Fum") != "Fum")
throw new Exception("Test 3 failed");
// Verify type-checking for %typemap(in) const std::string & {}
try {
cpp17_string_view.test_const_reference(null);
throw new Exception("Test 4 failed");
} catch (ArgumentNullException) {
}
//
// Input and output typemaps for pointers and non-const references to
// std::string are *not* supported; the following tests confirm
// that none of these cases are slipping through.
//
SWIGTYPE_p_std__string_view stringPtr = null;
stringPtr = cpp17_string_view.test_pointer_out();
cpp17_string_view.test_pointer(stringPtr);
stringPtr = cpp17_string_view.test_const_pointer_out();
cpp17_string_view.test_const_pointer(stringPtr);
stringPtr = cpp17_string_view.test_reference_out();
cpp17_string_view.test_reference(stringPtr);
// Check throw exception specification
try {
cpp17_string_view.test_throw();
throw new Exception("Test 5 failed");
} catch (ApplicationException e) {
if (e.Message != "test_throw message")
throw new Exception("Test 5 string check: " + e.Message);
}
try {
cpp17_string_view.test_const_reference_throw();
throw new Exception("Test 6 failed");
} catch (ApplicationException e) {
if (e.Message != "test_const_reference_throw message")
throw new Exception("Test 6 string check: " + e.Message);
}
// Global variables
if (cpp17_string_view.ConstGlobalString != "const global string")
throw new Exception("ConstGlobalString test");
// Member variables
Structure myStructure = new Structure();
if (myStructure.ConstMemberString != "const member string")
throw new Exception("ConstMemberString test");
if (Structure.ConstStaticMemberString != "const static member string")
throw new Exception("ConstStaticMemberString test");
}
}

View File

@ -0,0 +1,52 @@
using System;
using director_string_viewNamespace;
public class runme
{
static void Main()
{
runme r = new runme();
r.run();
}
void run()
{
String s;
director_string_view_A c = new director_string_view_A("hi");
for (int i=0; i<3; i++) {
s = c.call_get(i);
Object ii = i;
if (s != ii.ToString()) throw new Exception("director_string_view_A.get(" + i + ") failed. Got:" + s);
}
director_string_view_B b = new director_string_view_B("hello");
s = b.call_get_first();
if (s != "director_string_view_B.get_first") throw new Exception("call_get_first() failed");
s = b.call_get(0);
if (s != "director_string_view_B.get: hello") throw new Exception("get(0) failed");
}
}
class director_string_view_B : A {
public director_string_view_B(String first) : base(first) {
}
public override String get_first() {
return "director_string_view_B.get_first";
}
public override String get(int n) {
return "director_string_view_B.get: " + base.get(n);
}
}
class director_string_view_A : A {
public director_string_view_A(String first) : base(first) {
}
public override String get(int n) {
Object nn = n;
return nn.ToString();
}
}

View File

@ -0,0 +1,56 @@
%module(directors="1") director_string_view;
#if defined SWIGCSHARP || defined SWIGJAVA || defined SWIGLUA || defined SWIGPHP
%include std_string.i
%include std_string_view.i
// Using thread unsafe wrapping
%warnfilter(SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) A;
%{
#include <vector>
#include <string>
#include <string_view>
%}
%feature("director") A;
%inline %{
struct A
{
A(const std::string& first)
: m_strings(1, first)
{}
virtual ~A() {}
virtual std::string_view get_first() const
{ return get(0); }
virtual std::string_view get(int n) const
{ return m_strings[n]; }
virtual std::string_view call_get_first() const
{ return get_first(); }
virtual std::string_view call_get(int n) const
{ return get(n); }
virtual int string_length(std::string_view s) const
{ return (int)s.size(); }
virtual void process_text(const char *text)
{
}
void call_process_func() { process_text("hello"); }
private:
std::vector<std::string> m_strings;
};
%}
#endif

View File

@ -0,0 +1,92 @@
import cpp17_string_view.*;
public class cpp17_string_view_runme {
static {
try {
System.loadLibrary("cpp17_string_view");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) throws Throwable
{
// Checking expected use of %typemap(in) std::string_view {}
cpp17_string_view.test_value("Fee");
// Checking expected result of %typemap(out) std::string_view {}
if (!cpp17_string_view.test_value("Fi").equals("Fi"))
throw new RuntimeException("Test 1 failed");
// Verify type-checking for %typemap(in) std::string_view {}
try {
cpp17_string_view.test_value(null);
throw new RuntimeException("Test 2 failed");
} catch (NullPointerException e) {
}
// Checking expected use of %typemap(in) const std::string_view & {}
cpp17_string_view.test_const_reference("Fo");
// Checking expected result of %typemap(out) const std::string_view& {}
if (!cpp17_string_view.test_const_reference("Fum").equals("Fum"))
throw new RuntimeException("Test 3 failed");
// Verify type-checking for %typemap(in) const std::string_view & {}
try {
cpp17_string_view.test_const_reference(null);
throw new RuntimeException("Test 4 failed");
} catch (NullPointerException e) {
}
//
// Input and output typemaps for pointers and non-const references to
// std::string_view are *not* supported; the following tests confirm
// that none of these cases are slipping through.
//
SWIGTYPE_p_std__string_view stringPtr = null;
stringPtr = cpp17_string_view.test_pointer_out();
cpp17_string_view.test_pointer(stringPtr);
stringPtr = cpp17_string_view.test_const_pointer_out();
cpp17_string_view.test_const_pointer(stringPtr);
stringPtr = cpp17_string_view.test_reference_out();
cpp17_string_view.test_reference(stringPtr);
// Check throw exception specification
try {
cpp17_string_view.test_throw();
throw new Throwable("Test 5 failed");
} catch (RuntimeException e) {
if (!e.getMessage().equals("test_throw message"))
throw new Exception("Test 5 string check: " + e.getMessage());
}
try {
cpp17_string_view.test_const_reference_throw();
throw new Throwable("Test 6 failed");
} catch (RuntimeException e) {
if (!e.getMessage().equals("test_const_reference_throw message"))
throw new Exception("Test 6 string check: " + e.getMessage());
}
// Global variables
if (!cpp17_string_view.getConstGlobalString().equals("const global string"))
throw new Exception("ConstGlobalString test");
// Member variables
Structure myStructure = new Structure();
if (!myStructure.getConstMemberString().equals("const member string"))
throw new Exception("ConstMemberString test");
if (!Structure.getConstStaticMemberString().equals("const static member string"))
throw new Exception("ConstStaticMemberString test");
}
}

View File

@ -0,0 +1,55 @@
import director_string_view.*;
public class director_string_view_runme {
static {
try {
System.loadLibrary("director_string_view");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
String s;
director_string_view_A c = new director_string_view_A("hi");
for (int i=0; i<3; i++) {
s = c.call_get(i);
if (!s.equals(Integer.valueOf(i).toString())) throw new RuntimeException("director_string_view_A.get(" + i + ") failed. Got:" + s);
}
director_string_view_B b = new director_string_view_B("hello");
s = b.call_get_first();
if (!s.equals("director_string_view_B.get_first")) throw new RuntimeException("call_get_first() failed");
s = b.call_get(0);
if (!s.equals("director_string_view_B.get: hello")) throw new RuntimeException("get(0) failed");
}
}
class director_string_view_B extends A {
public director_string_view_B(String first) {
super(first);
}
public String get_first() {
return "director_string_view_B.get_first";
}
public String get(int n) {
return "director_string_view_B.get: " + super.get(n);
}
}
class director_string_view_A extends A {
public director_string_view_A(String first) {
super(first);
}
public String get(int n) {
return Integer.valueOf(n).toString();
}
}

View File

@ -0,0 +1,50 @@
require("import") -- the import fn
import("cpp17_string_view") -- import lib
for k,v in pairs(cpp17_string_view) do _G[k]=v end -- move to global
-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
-- Checking expected use of %typemap(in) std::string_view {}
test_value("Fee")
-- Checking expected result of %typemap(out) std::string_view {}
s=test_value("Fi")
assert(type(s)=="string" and s =="Fi")
-- Checking expected use of %typemap(in) const std::string_view & {}
test_const_reference("Fo")
-- Checking expected result of %typemap(out) const std::string_view& {}
s=test_const_reference("Fum")
assert(type(s)=="string" and s =="Fum")
-- Input and output typemaps for pointers and non-const references to
-- std::string_view are *not* supported; the following tests confirm
-- that none of these cases are slipping through.
stringPtr = test_pointer_out()
test_pointer(stringPtr)
stringPtr = test_const_pointer_out()
test_const_pointer(stringPtr)
stringPtr = test_reference_out()
test_reference(stringPtr)
-- Global variables
assert(cpp17_string_view.ConstGlobalString=="const global string")
-- Member variables
myStructure = Structure()
assert(myStructure.ConstMemberString=="const member string")
assert(Structure.ConstStaticMemberString=="const static member string")
test_const_reference_returning_void("foo")

View File

@ -0,0 +1,44 @@
<?php
require "tests.php";
# Checking expected use of %typemap(in) std::string_view {}
cpp17_string_view::test_value("Fee");
# Checking expected result of %typemap(out) std::string_view {}
check::equal(cpp17_string_view::test_value("Fi"), "Fi", "Test 1");
# Checking expected use of %typemap(in) const std::string_view & {}
cpp17_string_view::test_const_reference("Fo");
# Checking expected result of %typemap(out) const std::string_view& {}
check::equal(cpp17_string_view::test_const_reference("Fum"), "Fum", "Test 3");
# Input and output typemaps for pointers and non-const references to
# std::string_view are *not* supported; the following tests confirm
# that none of these cases are slipping through.
$stringPtr = cpp17_string_view::test_pointer_out();
cpp17_string_view::test_pointer($stringPtr);
$stringPtr = cpp17_string_view::test_const_pointer_out();
cpp17_string_view::test_const_pointer($stringPtr);
$stringPtr = cpp17_string_view::test_reference_out();
cpp17_string_view::test_reference($stringPtr);
// Global variables
check::equal(ConstGlobalString_get(), "const global string", "ConstGlobalString test");
// Member variables
$myStructure = new Structure();
check::equal($myStructure->ConstMemberString, "const member string", "ConstMemberString test");
check::equal(Structure::ConstStaticMemberString(), "const static member string", "ConstStaticMemberString test");
cpp17_string_view::test_const_reference_returning_void("foo");
check::done();

View File

@ -0,0 +1,34 @@
<?php
require "tests.php";
// No new functions
check::functions(array());
// New classes
check::classes(array('A'));
// No new vars
check::globals(array());
class B extends A {
public $smem;
function get_first() {
return parent::get_first() . " world!";
}
function process_text($string) {
parent::process_text($string);
$this->smem = "hello";
}
}
$b = new B("hello");
$b->get(0);
check::equal($b->get_first(),"hello world!", "get_first failed");
$b->call_process_func();
check::equal($b->smem, "hello", "smem failed");
check::done();

View File

@ -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; %}
}

138
Lib/java/std_string_view.i Normal file
View File

@ -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; %}
}

41
Lib/lua/std_string_view.i Normal file
View File

@ -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;
}

69
Lib/php/std_string_view.i Normal file
View File

@ -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;
%}
}

View File

@ -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