1/* Modified from API Cookbook A Example 8 */
2
3#ifdef __cplusplus
4extern "C" {
5#endif
6#include "EXTERN.h"
7#include "perl.h"
8#include "XSUB.h"
9#include "Av_CharPtrPtr.h"  /* XS_*_charPtrPtr() */
10#ifdef __cplusplus
11}
12#endif
13
14
15/* Used by the INPUT typemap for char**.
16 * Will convert a Perl AV* (containing strings) to a C char**.
17 */
18char ** XS_unpack_charPtrPtr(SV* rv )
19{
20	AV *av;
21	SV **ssv;
22	char **s;
23	int avlen;
24	int x;
25
26	if( SvROK( rv ) && (SvTYPE(SvRV(rv)) == SVt_PVAV) )
27		av = (AV*)SvRV(rv);
28	else {
29		return( (char**)NULL );
30	}
31
32	/* is it empty? */
33	avlen = av_len(av);
34	if( avlen < 0 ){
35		return( (char**)NULL );
36	}
37
38	/* av_len+2 == number of strings, plus 1 for an end-of-array sentinel.
39	 */
40	s = (char **)safemalloc( sizeof(char*) * (avlen + 2) );
41	if( s == NULL ){
42		warn("XS_unpack_charPtrPtr: unable to malloc char**");
43		return( (char**)NULL );
44	}
45	for( x = 0; x <= avlen; ++x ){
46		ssv = av_fetch( av, x, 0 );
47		if( ssv != NULL ){
48			if( SvPOK( *ssv ) ){
49				s[x] = (char *)safemalloc( SvCUR(*ssv) + 1 );
50				if( s[x] == NULL )
51					warn("XS_unpack_charPtrPtr: unable to malloc char*");
52				else
53					strcpy( s[x], SvPV( *ssv, PL_na ) );
54			}
55			else
56				warn("XS_unpack_charPtrPtr: array elem %d was not a string.", x );
57		}
58		else
59			s[x] = (char*)NULL;
60	}
61	s[x] = (char*)NULL; /* sentinel */
62	return( s );
63}
64
65/* Used by the OUTPUT typemap for char**.
66 * Will convert a C char** to a Perl AV*.
67 */
68void XS_pack_charPtrPtr(SV* st, char **s)
69{
70	AV *av = newAV();
71	SV *sv;
72	char **c;
73
74	for( c = s; *c != NULL; ++c ){
75		sv = newSVpv( *c, 0 );
76		av_push( av, sv );
77	}
78	sv = newSVrv( st, NULL );	/* upgrade stack SV to an RV */
79	SvREFCNT_dec( sv );	/* discard */
80	SvRV( st ) = (SV*)av;	/* make stack RV point at our AV */
81}
82
83
84/* cleanup the temporary char** from XS_unpack_charPtrPtr */
85void XS_release_charPtrPtr(char **s)
86{
87	char **c;
88	for( c = s; *c != NULL; ++c )
89		safefree( *c );
90	safefree( s );
91}
92
93