Change the length of strings created from fixed-size buffers.

Use the usual C rule for NUL-terminated strings instead of discarding all the
trailing NUL characters.

This was unexpected (as buffers in C code are not necessarily always padded
with NULs to their full length) and also inconsistent among languages as this
was only done for those of them using typemaps/strings.swg but not for C# or
Java, for example, which terminated the string at the first NUL even before
this change.

Notice that this patch couldn't use strlen() or wcslen() with possibly not
NUL-terminated strings, so we had to add [our own equivalents of] strnlen()
and wcsnlen() and use them instead. This required adding yet another parameter
to string typemap macros, so update the example using them accordingly too.
This commit is contained in:
Vadim Zeitlin 2013-12-18 01:28:32 +01:00 committed by William S Fulton
commit 88a0e228a9
8 changed files with 75 additions and 20 deletions

View file

@ -5,6 +5,14 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 3.0.0 (in progress)
============================
2013-12-23: vadz
[Octave, Perl, Python, R, Ruby, Tcl] Change the length of strings created from fixed-size char
buffers in C code.
This is a potential backwards compatibility break: a "char buf[5]" containing "ho\0la" was
returned as a string of length 5 before, but is returned as a string of length 2 now. Apply
"char FIXSIZE[ANY]" typemaps to explicitly choose the old behaviour.
2013-12-23: talby
[Perl] Add support for directors.

View file

@ -93,6 +93,17 @@ SWIG_FromXMLChPtrAndSize(const XMLCh* input, size_t size)
}
}
%fragment("SWIG_XMLStringNLen","header") {
size_t
SWIG_XMLStringNLen(const XMLCh* s, size_t maxlen)
{
const XMLCh *p;
for (p = s; maxlen-- && *p; p++)
;
return p - s;
}
}
%init {
if (!SWIG_UTF8Transcoder()) {
croak("ERROR: XML::Xerces: INIT: Could not create UTF-8 transcoder");
@ -106,6 +117,7 @@ SWIG_FromXMLChPtrAndSize(const XMLCh* input, size_t size)
SWIG_AsXMLChPtrAndSize,
SWIG_FromXMLChPtrAndSize,
XERCES_CPP_NAMESPACE::XMLString::stringLen,
SWIG_XMLStringNLen,
"<XMLCh.h>", INT_MIN, INT_MAX);

View file

@ -166,7 +166,7 @@ $t->{var_paramd} = $primitive_types::sct_paramd;
$t->{var_paramc} = $primitive_types::sct_paramc;
ok($t->v_check(), 'v_check');
is($primitive_types::def_namet, "ho\0la", "namet");
is($primitive_types::def_namet, "hola", "namet");
$t->{var_namet} = $primitive_types::def_namet;
is($t->{var_namet}, $primitive_types::def_namet, "namet");

View file

@ -185,7 +185,7 @@
char* const def_pchar = (char *const)"hello";
const char* const def_pcharc = "hija";
const namet def_namet = {'h','o',0, 'l','a'};
const namet def_namet = {'h','o','l','a', 0};
extern namet gbl_namet;

View file

@ -165,7 +165,7 @@ t.var_paramc = sct_paramc
t.v_check()
# this value contains a '0' char!
if def_namet != 'ho\0la':
if def_namet != 'hola':
print "bad namet", def_namet
raise RuntimeError

View file

@ -17,8 +17,19 @@ SWIG_pchar_descriptor(void)
}
}
%fragment("SWIG_strnlen","header",fragment="SWIG_FromCharPtrAndSize") {
size_t
SWIG_strnlen(const char* s, size_t maxlen)
{
const char *p;
for (p = s; maxlen-- && *p; p++)
;
return p - s;
}
}
%include <typemaps/strings.swg>
%typemaps_string(%checkcode(STRING), %checkcode(CHAR),
char, Char, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, strlen,
char, Char, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize,
strlen, SWIG_strnlen,
"<limits.h>", CHAR_MIN, CHAR_MAX)

View file

@ -22,6 +22,7 @@
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
SWIG_AsCharPtr,
SWIG_FromCharPtr,
SWIG_AsCharArray,
@ -276,12 +277,13 @@
}
%typemap(freearg) const Char (&)[ANY] "";
%typemap(out,fragment=#SWIG_FromCharPtrAndSize)
%typemap(out,fragment=#SWIG_FromCharPtrAndSize,fragment=#SWIG_CharBufLen)
Char [ANY], const Char[ANY]
{
size_t size = $1_dim0;
%#ifndef SWIG_PRESERVE_CARRAY_SIZE
while (size && ($1[size - 1] == '\0')) --size;
size_t size = SWIG_CharBufLen($1, $1_dim0);
%#else
size_t size = $1_dim0;
%#endif
%set_output(SWIG_FromCharPtrAndSize($1, size));
}
@ -298,23 +300,25 @@
/* varout */
%typemap(varout,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
%typemap(varout,noblock=1,fragment=#SWIG_CharBufLen)
Char [ANY], const Char [ANY] {
size_t size = $1_dim0;
%#ifndef SWIG_PRESERVE_CARRAY_SIZE
while (size && ($1[size - 1] == '\0')) --size;
size_t size = SWIG_CharBufLen($1, $1_dim0);
%#else
size_t size = $1_dim0;
%#endif
%set_varoutput(SWIG_FromCharPtrAndSize($1, size));
}
/* constant */
%typemap(constcode,fragment=#SWIG_FromCharPtrAndSize)
%typemap(constcode,fragment=#SWIG_CharBufLen)
Char [ANY], const Char [ANY]
{
size_t size = $value_dim0;
%#ifndef SWIG_PRESERVE_CARRAY_SIZE
while (size && ($value[size - 1] == '\0')) --size;
size_t size = SWIG_CharBufLen($1, $1_dim0);
%#else
size_t size = $value_dim0;
%#endif
%set_constant("$symname", SWIG_FromCharPtrAndSize($value,size));
}
@ -323,12 +327,13 @@
#if defined(SWIG_DIRECTOR_TYPEMAPS)
/* directorin */
%typemap(directorin,fragment=#SWIG_FromCharPtrAndSize)
%typemap(directorin,fragment=#SWIG_CharBufLen)
Char [ANY], const Char [ANY]
{
size_t size = $1_dim0;
%#ifndef SWIG_PRESERVE_CARRAY_SIZE
while (size && ($1[size - 1] == '\0')) --size;
size_t size = SWIG_CharBufLen($1, $1_dim0);
%#else
size_t size = $1_dim0;
%#endif
$input = SWIG_FromCharPtrAndSize($1, size);
}
@ -360,12 +365,13 @@
/* throws */
%typemap(throws,fragment=#SWIG_FromCharPtrAndSize)
%typemap(throws,fragment=#SWIG_CharBufLen)
Char [ANY], const Char[ANY]
{
size_t size = $1_dim0;
%#ifndef SWIG_PRESERVE_CARRAY_SIZE
while (size && ($1[size - 1] == '\0')) --size;
size_t size = SWIG_CharBufLen($1, $1_dim0);
%#else
size_t size = $1_dim0;
%#endif
%raise(SWIG_FromCharPtrAndSize($1, size), "$type", 0);
}
@ -499,6 +505,7 @@
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
SWIG_NewCopyCharArray,
SWIG_DeleteCharArray,
FragLimits, CHAR_MIN, CHAR_MAX)
@ -586,6 +593,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val)
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
SWIG_As##CharName##Ptr,
SWIG_From##CharName##Ptr,
SWIG_As##CharName##Array,
@ -604,12 +612,14 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val)
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
FragLimits, CHAR_MIN, CHAR_MAX)
%_typemap2_string(StringCode, CharCode,
Char, CharName,
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
%new_copy_array,
%delete_array,
FragLimits, CHAR_MIN, CHAR_MAX)
@ -624,6 +634,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val)
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
SWIG_NewCopyCharArray,
SWIG_DeleteCharArray,
FragLimits, CHAR_MIN, CHAR_MAX)
@ -632,6 +643,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val)
SWIG_AsCharPtrAndSize,
SWIG_FromCharPtrAndSize,
SWIG_CharPtrLen,
SWIG_CharBufLen,
SWIG_NewCopyCharArray,
SWIG_DeleteCharArray,
FragLimits, CHAR_MIN, CHAR_MAX)

View file

@ -18,8 +18,20 @@ SWIG_pwchar_descriptor()
}
}
%fragment("SWIG_wcsnlen","header",fragment="SWIG_FromWCharPtrAndSize") {
size_t
SWIG_wcsnlen(const wchar_t* s, size_t maxlen)
{
const wchar_t *p;
for (p = s; maxlen-- && *p; p++)
;
return p - s;
}
}
%include <typemaps/strings.swg>
%typemaps_string(%checkcode(UNISTRING), %checkcode(UNICHAR),
wchar_t, WChar, SWIG_AsWCharPtrAndSize, SWIG_FromWCharPtrAndSize, wcslen,
wchar_t, WChar, SWIG_AsWCharPtrAndSize, SWIG_FromWCharPtrAndSize,
wcslen, SWIG_wcsnlen,
"<wchar.h>", WCHAR_MIN, WCHAR_MAX)