diff options
author | Vadim Zeitlin <vz-swig@zeitlins.org> | 2013-08-30 17:01:01 +0200 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2013-10-15 07:17:56 +0100 |
commit | 72afb74f470841d9af504a8f85617c6a70aa837d (patch) | |
tree | 7738345ee23ac538eb81deace43782261f2c5ca5 /Source/Swig | |
parent | 669a27bb7b9d2da9c1758a5126d1db1f56299f08 (diff) | |
download | swig-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.c | 63 |
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++; } } |