aboutsummaryrefslogtreecommitdiff
path: root/Source/Swig
diff options
context:
space:
mode:
authorVadim Zeitlin <vz-swig@zeitlins.org>2013-08-30 17:01:01 +0200
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2013-10-15 07:17:56 +0100
commit72afb74f470841d9af504a8f85617c6a70aa837d (patch)
tree7738345ee23ac538eb81deace43782261f2c5ca5 /Source/Swig
parent669a27bb7b9d2da9c1758a5126d1db1f56299f08 (diff)
downloadswig-72afb74f470841d9af504a8f85617c6a70aa837d.tar.gz
Add support for case conversion characters in regex substitutions.
Allow using Perl-like \l, \L, \u, \U and \E escape sequences in the substitution string used with %rename("%(regex:/pattern/subst/)s"). This is useful for e.g. title casing all string after removing some prefix. Closes #82
Diffstat (limited to 'Source/Swig')
-rw-r--r--Source/Swig/misc.c63
1 files changed, 60 insertions, 3 deletions
diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c
index 596f6b424..769882bf8 100644
--- a/Source/Swig/misc.c
+++ b/Source/Swig/misc.c
@@ -1180,8 +1180,38 @@ err_out:
exit(1);
}
+/* This function copies len characters from src to dst, possibly applying case conversions to them: if convertCase is 1, to upper case and if it is -1, to lower
+ * case. If convertNextOnly is 1, only a single character is converted (and convertCase is reset), otherwise all of them are. */
+static void copy_with_maybe_case_conversion(String *dst, const char *src, int len, int *convertCase, int convertNextOnly)
+{
+ /* Deal with the trivial cases first. */
+ if (!len)
+ return;
+
+ if (!*convertCase) {
+ Write(dst, src, len);
+ return;
+ }
+
+ /* If we must convert only the first character, do it and write the rest at once. */
+ if (convertNextOnly) {
+ Putc(*convertCase == 1 ? toupper(*src) : tolower(*src), dst);
+ *convertCase = 0;
+ if (len > 1) {
+ Write(dst, src + 1, len - 1);
+ }
+ } else {
+ /* We need to convert all characters. */
+ int i;
+ for (i = 0; i < len; i++, src++) {
+ Putc(*convertCase == 1 ? toupper(*src) : tolower(*src), dst);
+ }
+ }
+}
+
String *replace_captures(int num_captures, const char *input, String *subst, int captures[], String *pattern, String *s)
{
+ int convertCase = 0, convertNextOnly = 0;
String *result = NewStringEmpty();
const char *p = Char(subst);
@@ -1189,10 +1219,10 @@ String *replace_captures(int num_captures, const char *input, String *subst, int
/* Copy part without substitutions */
const char *q = strchr(p, '\\');
if (!q) {
- Write(result, p, strlen(p));
+ copy_with_maybe_case_conversion(result, p, strlen(p), &convertCase, convertNextOnly);
break;
}
- Write(result, p, q - p);
+ copy_with_maybe_case_conversion(result, p, q - p, &convertCase, convertNextOnly);
p = q + 1;
/* Handle substitution */
@@ -1203,12 +1233,39 @@ String *replace_captures(int num_captures, const char *input, String *subst, int
if (group < num_captures) {
int l = captures[group*2], r = captures[group*2 + 1];
if (l != -1) {
- Write(result, input + l, r - l);
+ copy_with_maybe_case_conversion(result, input + l, r - l, &convertCase, convertNextOnly);
}
} else {
Swig_error("SWIG", Getline(s), "PCRE capture replacement failed while matching \"%s\" using \"%s\" - request for group %d is greater than the number of captures %d.\n",
Char(pattern), input, group, num_captures-1);
}
+ } else {
+ /* Handle Perl-like case conversion escapes. */
+ switch (*p) {
+ case 'u':
+ convertCase = 1;
+ convertNextOnly = 1;
+ break;
+ case 'U':
+ convertCase = 1;
+ convertNextOnly = 0;
+ break;
+ case 'l':
+ convertCase = -1;
+ convertNextOnly = 1;
+ break;
+ case 'L':
+ convertCase = -1;
+ convertNextOnly = 0;
+ break;
+ case 'E':
+ convertCase = 0;
+ break;
+ default:
+ Swig_error("SWIG", Getline(s), "Unrecognized escape character '%c' in the replacement string \"%s\".\n",
+ *p, Char(subst));
+ }
+ p++;
}
}