diff options
Diffstat (limited to 'perl-install/Newt/Av_CharPtrPtr.c')
-rw-r--r-- | perl-install/Newt/Av_CharPtrPtr.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/perl-install/Newt/Av_CharPtrPtr.c b/perl-install/Newt/Av_CharPtrPtr.c new file mode 100644 index 000000000..d108ef5d0 --- /dev/null +++ b/perl-install/Newt/Av_CharPtrPtr.c @@ -0,0 +1,99 @@ +#ifdef __cplusplus +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include "Av_CharPtrPtr.h" /* XS_*_charPtrPtr() */ +#ifdef __cplusplus +} +#endif + + +/* Used by the INPUT typemap for char**. + * Will convert a Perl AV* (containing strings) to a C char**. + */ +char ** +XS_unpack_charPtrPtr( rv ) +SV *rv; +{ + AV *av; + SV **ssv; + char **s; + int avlen; + int x; + + if( SvROK( rv ) && (SvTYPE(SvRV(rv)) == SVt_PVAV) ) + av = (AV*)SvRV(rv); + else { + warn("XS_unpack_charPtrPtr: rv was not an AV ref"); + return( (char**)NULL ); + } + + /* is it empty? */ + avlen = av_len(av); + if( avlen < 0 ){ + warn("XS_unpack_charPtrPtr: array was empty"); + return( (char**)NULL ); + } + + /* av_len+2 == number of strings, plus 1 for an end-of-array sentinel. + */ + s = (char **)safemalloc( sizeof(char*) * (avlen + 2) ); + if( s == NULL ){ + warn("XS_unpack_charPtrPtr: unable to malloc char**"); + return( (char**)NULL ); + } + for( x = 0; x <= avlen; ++x ){ + ssv = av_fetch( av, x, 0 ); + if( ssv != NULL ){ + if( SvPOK( *ssv ) ){ + s[x] = (char *)safemalloc( SvCUR(*ssv) + 1 ); + if( s[x] == NULL ) + warn("XS_unpack_charPtrPtr: unable to malloc char*"); + else + strcpy( s[x], SvPV( *ssv, na ) ); + } + else + warn("XS_unpack_charPtrPtr: array elem %d was not a string.", x ); + } + else + s[x] = (char*)NULL; + } + s[x] = (char*)NULL; /* sentinel */ + return( s ); +} + +/* Used by the OUTPUT typemap for char**. + * Will convert a C char** to a Perl AV*. + */ +void +XS_pack_charPtrPtr( st, s ) +SV *st; +char **s; +{ + AV *av = newAV(); + SV *sv; + char **c; + + for( c = s; *c != NULL; ++c ){ + sv = newSVpv( *c, 0 ); + av_push( av, sv ); + } + sv = newSVrv( st, NULL ); /* upgrade stack SV to an RV */ + SvREFCNT_dec( sv ); /* discard */ + SvRV( st ) = (SV*)av; /* make stack RV point at our AV */ +} + + +/* cleanup the temporary char** from XS_unpack_charPtrPtr */ +void +XS_release_charPtrPtr(s) +char **s; +{ + char **c; + for( c = s; *c != NULL; ++c ) + safefree( *c ); + safefree( s ); +} + |