summaryrefslogtreecommitdiffstats
path: root/perl-install/Newt/Av_CharPtrPtr.c
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/Newt/Av_CharPtrPtr.c')
-rw-r--r--perl-install/Newt/Av_CharPtrPtr.c99
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 );
+}
+