blob: f28fa6315bf360a02b1f153b26dd91213e665ff6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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, 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( 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 );
}
|