Anonymous avatar Anonymous committed 8f6da5d

AV <-> char** conversion

Comments (0)

Files changed (2)

+/* Modified from API Cookbook A Example 8 */
+
+#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(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 {
+		return( (char**)NULL );
+	}
+
+	/* is it empty? */
+	avlen = av_len(av);
+	if( avlen < 0 ){
+		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, PL_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(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(char **s)
+{
+	char **c;
+	for( c = s; *c != NULL; ++c )
+		safefree( *c );
+	safefree( s );
+}
+
+char ** XS_unpack_charPtrPtr _(( SV *rv ));
+void XS_pack_charPtrPtr _(( SV *st, char **s ));
+void XS_release_charPtrPtr _(( char **s ));
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.