Add support for "[not]regexmatch" and "regextarget" to %rename.
"regexmatch" and "notregexmatch" can be used with anonymous %renames in the same way as "match" and "notmatch" while "regextarget" specifies that the argument of a non-anonymous %rename should be interpreted as a regular expression. Document the new functions. Also add a new unit test for %regex also testing regexmatch &c and provide test code for C# and Java verifying that it works as intended. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12174 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
48a2e0bdea
commit
70c5bb5a47
7 changed files with 216 additions and 8 deletions
|
|
@ -9,6 +9,24 @@ Version 2.0.1 (in progress)
|
||||||
Fix wrapping of function pointers and member function pointers when the function
|
Fix wrapping of function pointers and member function pointers when the function
|
||||||
returns by reference.
|
returns by reference.
|
||||||
|
|
||||||
|
2010-07-13: vadz
|
||||||
|
Add "regexmatch", "regextarget" and "notregexmatch" which can be
|
||||||
|
used to apply %rename directives to the declarations matching the
|
||||||
|
specified regular expression only. The first two can be used
|
||||||
|
interchangeably, both of the %renames below do the same thing:
|
||||||
|
|
||||||
|
%rename("$ignore", regexmatch$name="Old$") "";
|
||||||
|
%rename("$ignore", regextarget=1) "Old$";
|
||||||
|
|
||||||
|
(namely ignore the declarations having "Old" suffix).
|
||||||
|
|
||||||
|
"notregexmatch" restricts the match to only the declarations which
|
||||||
|
do not match the regular expression, e.g. here is how to rename to
|
||||||
|
lower case versions all declarations except those consisting from
|
||||||
|
capital letters only:
|
||||||
|
|
||||||
|
%rename("$(lower)s", notregexmatch$name="^[A-Z]+$") "";
|
||||||
|
|
||||||
2010-07-13: vadz
|
2010-07-13: vadz
|
||||||
Add the new "regex" encoder that can be used in %rename, e.g.
|
Add the new "regex" encoder that can be used in %rename, e.g.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1949,10 +1949,12 @@ can be used to achieve the same effect as the simpler
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
However <tt>match</tt> can also be applied to the declaration type, for
|
and so is not very interesting on its own. However <tt>match</tt> can also be
|
||||||
example <tt>match="class"</tt> restricts the match to class declarations only
|
applied to the declaration type, for example <tt>match="class"</tt> restricts
|
||||||
(in C++) and <tt>match="enumitem"</tt> restricts it to the enum elements. SWIG
|
the match to class declarations only (in C++) and <tt>match="enumitem"</tt>
|
||||||
also provides convenience macros for such match expressions, for example
|
restricts it to the enum elements. SWIG also provides convenience macros for
|
||||||
|
such match expressions, for example
|
||||||
|
</p>
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
%rename("%(title)s", %$isenumitem) "";
|
%rename("%(title)s", %$isenumitem) "";
|
||||||
|
|
@ -1983,7 +1985,40 @@ to rename all enums nested in the given class to lower case.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Finally, even more powerful variants of <tt>%rename</tt> and <tt>%ignore</tt> directives can be used to help
|
And in addition to literally matching some string with <tt>match</tt> you can
|
||||||
|
also use <tt>regexmatch</tt> or <tt>notregexmatch</tt>to match a string
|
||||||
|
against a regular expression. For example, to ignore all functions having
|
||||||
|
"Old" suffix you could use
|
||||||
|
</p>
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%rename("$ignore", regexmatch$name="Old$") "";
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
For simple cases like this, specifying the regular expression for the
|
||||||
|
declaration name directly can be preferable and can be done using
|
||||||
|
<tt>regextarget</tt>:
|
||||||
|
</p>
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%rename("$ignore", regextarget=1) "Old$";
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As for <tt>notregexmatch</tt>, it restricts the match only to the strings not
|
||||||
|
matching the specified regular expression. So to rename to lower case versions
|
||||||
|
all declarations except those consisting from capital letters only:
|
||||||
|
</p>
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%rename("$(lower)s", notregexmatch$name="^[A-Z]+$") "";
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Finally, variants of <tt>%rename</tt> and <tt>%ignore</tt> directives can be used to help
|
||||||
wrap C++ overloaded functions and methods or C++ methods which use default arguments. This is described in the
|
wrap C++ overloaded functions and methods or C++ methods which use default arguments. This is described in the
|
||||||
<a href="SWIGPlus.html#SWIGPlus_ambiguity_resolution_renaming">Ambiguity resolution and renaming</a> section in the C++ chapter.
|
<a href="SWIGPlus.html#SWIGPlus_ambiguity_resolution_renaming">Ambiguity resolution and renaming</a> section in the C++ chapter.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,7 @@ CPP_TEST_CASES += \
|
||||||
rename_scope \
|
rename_scope \
|
||||||
rename_strip_encoder \
|
rename_strip_encoder \
|
||||||
rename_pcre_encoder \
|
rename_pcre_encoder \
|
||||||
|
rename_pcre_enum \
|
||||||
restrict_cplusplus \
|
restrict_cplusplus \
|
||||||
return_const_value \
|
return_const_value \
|
||||||
return_value_scope \
|
return_value_scope \
|
||||||
|
|
|
||||||
24
Examples/test-suite/csharp/rename_pcre_enum_runme.cs
Normal file
24
Examples/test-suite/csharp/rename_pcre_enum_runme.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using rename_pcre_enumNamespace;
|
||||||
|
|
||||||
|
public class runme {
|
||||||
|
static void Main() {
|
||||||
|
Foo foo = Foo.First;
|
||||||
|
if ( foo == Foo.Second )
|
||||||
|
throw new Exception("Enum values should be different");
|
||||||
|
|
||||||
|
// Check that Foo_Max enum element was ignored.
|
||||||
|
int numFooEnumElements = Enum.GetValues(typeof(Foo)).Length;
|
||||||
|
if ( numFooEnumElements != 2 )
|
||||||
|
throw new Exception(String.Format("Enum should have 2 elements, not {0}",
|
||||||
|
numFooEnumElements));
|
||||||
|
|
||||||
|
BoundaryCondition bc = BoundaryCondition.MaxMax;
|
||||||
|
if ( (int)bc != 2 )
|
||||||
|
throw new Exception("Wrong enum value");
|
||||||
|
|
||||||
|
Colour c = Colour.red;
|
||||||
|
if ( c == Colour.blue )
|
||||||
|
throw new Exception("Enum values should be different");
|
||||||
|
}
|
||||||
|
}
|
||||||
26
Examples/test-suite/java/rename_pcre_enum_runme.java
Normal file
26
Examples/test-suite/java/rename_pcre_enum_runme.java
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import rename_pcre_enum.*;
|
||||||
|
|
||||||
|
public class rename_pcre_enum_runme {
|
||||||
|
static { System.loadLibrary("rename_pcre_enum"); }
|
||||||
|
|
||||||
|
public static void main(String argv[])
|
||||||
|
{
|
||||||
|
Foo foo = Foo.First;
|
||||||
|
if ( foo == Foo.Second )
|
||||||
|
throw new RuntimeException("Enum values should be different");
|
||||||
|
|
||||||
|
// Check that Foo_Max enum element was ignored.
|
||||||
|
int numFooEnumElements = Foo.values().length;
|
||||||
|
if ( numFooEnumElements != 2 )
|
||||||
|
throw new RuntimeException(String.format("Enum should have 2 elements, not %d",
|
||||||
|
numFooEnumElements));
|
||||||
|
|
||||||
|
BoundaryCondition bc = BoundaryCondition.MaxMax;
|
||||||
|
if ( bc.ordinal() != 2 )
|
||||||
|
throw new RuntimeException("Wrong enum value");
|
||||||
|
|
||||||
|
Colour c = Colour.red;
|
||||||
|
if ( c == Colour.blue )
|
||||||
|
throw new RuntimeException("Enum values should be different");
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Examples/test-suite/rename_pcre_enum.i
Normal file
49
Examples/test-suite/rename_pcre_enum.i
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
%module rename_pcre_enum
|
||||||
|
|
||||||
|
// This file is needed for proper enum support in C#/Java backends
|
||||||
|
#if defined(SWIGCSHARP) || defined(SWIGJAVA)
|
||||||
|
%include "enums.swg"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Apply a rule for renaming the enum elements to avoid the common prefixes
|
||||||
|
// redundant in C#/Java
|
||||||
|
%rename("%(regex:/([A-Z][a-z]+)+_(.*)/\\2/)s",%$isenumitem) "";
|
||||||
|
|
||||||
|
// Also don't export special end of enum markers which are often used in C++
|
||||||
|
// code to just have a symbolic name for the number of enum elements but are
|
||||||
|
// not needed in target language.
|
||||||
|
%rename("$ignore", regexmatch$name="([A-Z][a-z]+)+_Max$",%$isenumitem) "";
|
||||||
|
|
||||||
|
// Test another way of doing the same thing with regextarget:
|
||||||
|
%rename("$ignore", %$isenumitem, regextarget=1) "([A-Z][a-z]+)+_Internal$";
|
||||||
|
|
||||||
|
// Apply this renaming rule to all enum elements that don't contain more than
|
||||||
|
// one capital letter.
|
||||||
|
%rename("%(lower)s", notregexmatch$name="[A-Z]\\w*[A-Z]", %$isenumitem) "";
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
|
||||||
|
// Foo_Internal and Foo_Max won't be exported.
|
||||||
|
enum Foo {
|
||||||
|
Foo_Internal = -1,
|
||||||
|
Foo_First,
|
||||||
|
Foo_Second,
|
||||||
|
Foo_Max
|
||||||
|
};
|
||||||
|
|
||||||
|
// All elements of this enum will be exported because they do not match the
|
||||||
|
// excluding regex.
|
||||||
|
enum BoundaryCondition {
|
||||||
|
BoundaryCondition_MinMax,
|
||||||
|
BoundaryCondition_MaxMin,
|
||||||
|
BoundaryCondition_MaxMax
|
||||||
|
};
|
||||||
|
|
||||||
|
// The elements of this enum will have lower-case names.
|
||||||
|
enum Colour {
|
||||||
|
Red,
|
||||||
|
Blue,
|
||||||
|
Green
|
||||||
|
};
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
@ -1062,10 +1062,13 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) {
|
||||||
const char **rkey;
|
const char **rkey;
|
||||||
int isnotmatch = 0;
|
int isnotmatch = 0;
|
||||||
int isrxsmatch = 0;
|
int isrxsmatch = 0;
|
||||||
|
int isregexmatch = 0;
|
||||||
if ((strncmp(ckey, "match", 5) == 0)
|
if ((strncmp(ckey, "match", 5) == 0)
|
||||||
|| (isnotmatch = (strncmp(ckey, "notmatch", 8) == 0))
|
|| (isnotmatch = (strncmp(ckey, "notmatch", 8) == 0))
|
||||||
|| (isrxsmatch = (strncmp(ckey, "rxsmatch", 8) == 0))
|
|| (isrxsmatch = (strncmp(ckey, "rxsmatch", 8) == 0))
|
||||||
|| (isnotmatch = isrxsmatch = (strncmp(ckey, "notrxsmatch", 11) == 0))) {
|
|| (isregexmatch = (strncmp(ckey, "regexmatch", 10) == 0))
|
||||||
|
|| (isnotmatch = isrxsmatch = (strncmp(ckey, "notrxsmatch", 11) == 0))
|
||||||
|
|| (isnotmatch = isregexmatch = (strncmp(ckey, "notregexmatch", 13) == 0))) {
|
||||||
Hash *mi = NewHash();
|
Hash *mi = NewHash();
|
||||||
List *attrlist = Swig_make_attrlist(ckey);
|
List *attrlist = Swig_make_attrlist(ckey);
|
||||||
if (!matchlist)
|
if (!matchlist)
|
||||||
|
|
@ -1080,6 +1083,8 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) {
|
||||||
SetFlag(mi, "notmatch");
|
SetFlag(mi, "notmatch");
|
||||||
if (isrxsmatch)
|
if (isrxsmatch)
|
||||||
SetFlag(mi, "rxsmatch");
|
SetFlag(mi, "rxsmatch");
|
||||||
|
if (isregexmatch)
|
||||||
|
SetFlag(mi, "regexmatch");
|
||||||
Delete(attrlist);
|
Delete(attrlist);
|
||||||
Append(matchlist, mi);
|
Append(matchlist, mi);
|
||||||
Delete(mi);
|
Delete(mi);
|
||||||
|
|
@ -1155,6 +1160,51 @@ static DOH *Swig_get_lattr(Node *n, List *lattr) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PCRE
|
||||||
|
#include <pcre.h>
|
||||||
|
|
||||||
|
int Swig_name_regexmatch_value(Node *n, String *pattern, String *s) {
|
||||||
|
pcre *compiled_pat;
|
||||||
|
const char *err;
|
||||||
|
int errpos;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
compiled_pat = pcre_compile(Char(pattern), 0, &err, &errpos, NULL);
|
||||||
|
if (!compiled_pat) {
|
||||||
|
Swig_error("SWIG", Getline(n),
|
||||||
|
"Invalid regex \"%s\": compilation failed at %d: %s\n",
|
||||||
|
Char(pattern), errpos, err);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = pcre_exec(compiled_pat, NULL, Char(s), Len(s), 0, 0, NULL, 0);
|
||||||
|
pcre_free(compiled_pat);
|
||||||
|
|
||||||
|
if (rc == PCRE_ERROR_NOMATCH)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rc < 0 ) {
|
||||||
|
Swig_error("SWIG", Getline(n),
|
||||||
|
"Matching \"%s\" against regex \"%s\" failed: %d\n",
|
||||||
|
Char(s), Char(pattern), rc);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !HAVE_PCRE */
|
||||||
|
|
||||||
|
int Swig_name_regexmatch_value(Node *n, String *pattern, String *s) {
|
||||||
|
(void)pattern;
|
||||||
|
(void)s;
|
||||||
|
Swig_error("SWIG", Getline(n),
|
||||||
|
"PCRE regex matching is not available in this SWIG build.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_PCRE/!HAVE_PCRE */
|
||||||
|
|
||||||
#if defined(HAVE_RXSPENCER)
|
#if defined(HAVE_RXSPENCER)
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <rxspencer/regex.h>
|
#include <rxspencer/regex.h>
|
||||||
|
|
@ -1228,6 +1278,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
||||||
String *nval = Swig_get_lattr(n, lattr);
|
String *nval = Swig_get_lattr(n, lattr);
|
||||||
int notmatch = GetFlag(mi, "notmatch");
|
int notmatch = GetFlag(mi, "notmatch");
|
||||||
int rxsmatch = GetFlag(mi, "rxsmatch");
|
int rxsmatch = GetFlag(mi, "rxsmatch");
|
||||||
|
int regexmatch = GetFlag(mi, "regexmatch");
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
|
Printf(stdout, "mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
|
||||||
if (rxsmatch) {
|
if (rxsmatch) {
|
||||||
|
|
@ -1238,6 +1289,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
||||||
if (nval) {
|
if (nval) {
|
||||||
String *kwval = Getattr(mi, "value");
|
String *kwval = Getattr(mi, "value");
|
||||||
match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval)
|
match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval)
|
||||||
|
: regexmatch ? Swig_name_regexmatch_value(n, kwval, nval)
|
||||||
: Swig_name_match_value(kwval, nval);
|
: Swig_name_match_value(kwval, nval);
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen);
|
Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen);
|
||||||
|
|
@ -1278,6 +1330,7 @@ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *na
|
||||||
String *sname = 0;
|
String *sname = 0;
|
||||||
int fullname = GetFlag(rn, "fullname");
|
int fullname = GetFlag(rn, "fullname");
|
||||||
int rxstarget = GetFlag(rn, "rxstarget");
|
int rxstarget = GetFlag(rn, "rxstarget");
|
||||||
|
int regextarget = GetFlag(rn, "regextarget");
|
||||||
if (sfmt) {
|
if (sfmt) {
|
||||||
if (fullname && prefix) {
|
if (fullname && prefix) {
|
||||||
String *pname = NewStringf("%s::%s", prefix, name);
|
String *pname = NewStringf("%s::%s", prefix, name);
|
||||||
|
|
@ -1294,7 +1347,9 @@ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *na
|
||||||
DohIncref(name);
|
DohIncref(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match = rxstarget ? Swig_name_rxsmatch_value(tname, sname) : Swig_name_match_value(tname, sname);
|
match = rxstarget ? Swig_name_rxsmatch_value(tname, sname)
|
||||||
|
: regextarget ? Swig_name_regexmatch_value(n, tname, sname)
|
||||||
|
: Swig_name_match_value(tname, sname);
|
||||||
Delete(sname);
|
Delete(sname);
|
||||||
} else {
|
} else {
|
||||||
match = 1;
|
match = 1;
|
||||||
|
|
@ -1393,7 +1448,7 @@ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *ne
|
||||||
|
|
||||||
ParmList *declparms = declaratorparms;
|
ParmList *declparms = declaratorparms;
|
||||||
|
|
||||||
const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "rxstarget", 0 };
|
const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "rxstarget", "regextarget", 0 };
|
||||||
Swig_name_object_attach_keys(rename_keys, newname);
|
Swig_name_object_attach_keys(rename_keys, newname);
|
||||||
|
|
||||||
/* Add the name */
|
/* Add the name */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue