1 /*
2 ClearSilver-CS.xs - Represents the CSPARSE* class
3
4 Copyright(c) 2010 Craftworks. All rights reserved.
5
6 See lib/Text/ClearSilver.pm for details.
7 */
8
9 #include "Text-ClearSilver.h"
10
11 NEOERR*
tcs_output_to_sv(void * vsv,char * s)12 tcs_output_to_sv(void* vsv, char* s) {
13
14 if(*s){
15 dTHX;
16 SV* const sv = (SV*)vsv;
17 STRLEN const len = strlen(s);
18
19 if((SvLEN(sv) - SvCUR(sv)) <= len) {
20 sv_grow(sv, SvLEN(sv) * 2 + len);
21 }
22
23 sv_catpvn(sv, s, len);
24 }
25
26 return STATUS_OK;
27 }
28
29 NEOERR*
tcs_output_to_io(void * io,char * s)30 tcs_output_to_io(void* io, char* s) {
31 bool ok;
32
33 if(*s){
34 dTHX;
35 ENTER;
36 SAVETMPS;
37
38 ok = Perl_do_print(aTHX_ newSVpvn_flags(s, strlen(s), SVs_TEMP), (PerlIO*)io);
39
40 FREETMPS;
41 LEAVE;
42 }
43 else {
44 ok = TRUE;
45 }
46
47 return ok
48 ? STATUS_OK
49 : nerr_raise(NERR_IO, "Unable to output to the filehandle");
50 }
51
52
53
54 #undef cs_parse_string
55 #define cs_parse_string(cs, str) tcs_parse_sv(aTHX_ cs, str)
56
57 /*
58 NOTE: Methods which seem to return NEOERR* throw errors when they fail,
59 otherwise return undef.
60 */
61
62 MODULE = Text::ClearSilver::CS PACKAGE = Text::ClearSilver::CS PREFIX = cs_
63
64 PROTOTYPES: DISABLE
65
66 void
cs_new(SV * klass,SV * hdf_src)67 cs_new(SV* klass, SV* hdf_src)
68 CODE:
69 {
70 SV* self;
71 CSPARSE* cs;
72 HDF* hdf;
73 SV* hdf_sv;
74
75 if(SvROK(klass)){
76 croak("%s->new must be called as a class method", C_CS);
77 }
78
79 self = sv_newmortal();
80 if(sv_derived_from(hdf_src, C_HDF) && SvROK(hdf_src)) {
81 hdf = INT2PTR(HDF*, SvUV(SvRV(hdf_src)) );
82 hdf_sv = hdf_src;
83 }
84 else {
85 hdf = tcs_new_hdf(aTHX_ hdf_src);
86 hdf_sv = sv_newmortal();
87 sv_setref_pv(hdf_sv, C_HDF, hdf);
88 }
89
90 CHECK_ERR( cs_init(&cs, hdf) );
91
92 tcs_register_funcs(aTHX_ cs, NULL);
93
94 sv_setref_pv(self, SvPV_nolen_const(klass), cs);
95
96 /* CS has a hdf */
97 if(hdf_sv){
98 static MGVTBL text_clearsilver_vtbl;
99 sv_magicext(SvRV(self), hdf_sv, PERL_MAGIC_ext,
100 &text_clearsilver_vtbl, NULL, 0);
101 }
102 ST(0) = self;
103 }
104
105 void
cs_DESTROY(Text::ClearSilver::CS cs)106 cs_DESTROY(Text::ClearSilver::CS cs)
107
108 void
109 cs_render(Text::ClearSilver::CS cs, PerlIO* ofp = NULL)
110 CODE:
111 {
112 dXSTARG;
113 NEOERR* err;
114 if(ofp) {
115 sv_setiv(TARG, TRUE);
116 err = cs_render(cs, ofp, tcs_output_to_io);
117 }
118 else {
119 sv_setpvs(TARG, "");
120 err = cs_render(cs, TARG, tcs_output_to_sv);
121 }
122 CHECK_ERR(err);
123 ST(0) = TARG;
124 XSRETURN(1);
125 }
126
127 NEOERR*
cs_parse_file(Text::ClearSilver::CS cs,const char * cs_file)128 cs_parse_file(Text::ClearSilver::CS cs, const char* cs_file)
129
130 NEOERR*
131 cs_parse_string(Text::ClearSilver::CS cs, SV* in_str)
132
133 void
134 cs_dump(Text::ClearSilver::CS cs)
135 CODE:
136 {
137 dXSTARG;
138 sv_setpvs(TARG, "");
139 cs_dump(cs, (void*)TARG, tcs_output_to_sv);
140 ST(0) = TARG;
141 XSRETURN(1);
142 }
143
144