More $VERSION bumps.
[p5sagit/p5-mst-13.2.git] / ext / PerlIO / scalar / scalar.xs
CommitLineData
f6c77cf1 1#define PERL_NO_GET_CONTEXT
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5#ifdef PERLIO_LAYERS
6
7#include "perliol.h"
8
14d89041 9typedef struct {
10 struct _PerlIO base; /* Base "class" info */
11 SV *var;
12 Off_t posn;
f6c77cf1 13} PerlIOScalar;
14
15IV
14d89041 16PerlIOScalar_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg,
17 PerlIO_funcs * tab)
f6c77cf1 18{
14d89041 19 IV code;
20 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
21 /* If called (normally) via open() then arg is ref to scalar we are
22 * using, otherwise arg (from binmode presumably) is either NULL
23 * or the _name_ of the scalar
24 */
25 if (arg) {
cba44c14 26 if (SvROK(arg)) {
14d89041 27 s->var = SvREFCNT_inc(SvRV(arg));
03aa69f9 28 if (!SvPOK(s->var) && SvTYPE(SvRV(arg)) > SVt_NULL)
34fcc551 29 (void)SvPV_nolen(s->var);
14d89041 30 }
31 else {
32 s->var =
33 SvREFCNT_inc(perl_get_sv
34 (SvPV_nolen(arg), GV_ADD | GV_ADDMULTI));
35 }
564dc057 36 }
14d89041 37 else {
38 s->var = newSVpvn("", 0);
564dc057 39 }
c5b94a97 40 SvUPGRADE(s->var, SVt_PV);
14d89041 41 code = PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab);
47cc46ee 42 if (!SvOK(s->var) || (PerlIOBase(f)->flags) & PERLIO_F_TRUNCATE)
b162af07 43 SvCUR_set(s->var, 0);
14d89041 44 if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND)
45 s->posn = SvCUR(s->var);
46 else
47 s->posn = 0;
48 return code;
f6c77cf1 49}
50
51IV
14d89041 52PerlIOScalar_popped(pTHX_ PerlIO * f)
f6c77cf1 53{
14d89041 54 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
55 if (s->var) {
56 SvREFCNT_dec(s->var);
57 s->var = Nullsv;
58 }
59 return 0;
f6c77cf1 60}
61
62IV
14d89041 63PerlIOScalar_close(pTHX_ PerlIO * f)
f6c77cf1 64{
14d89041 65 IV code = PerlIOBase_close(aTHX_ f);
66 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
67 return code;
f6c77cf1 68}
69
70IV
14d89041 71PerlIOScalar_fileno(pTHX_ PerlIO * f)
f6c77cf1 72{
14d89041 73 return -1;
f6c77cf1 74}
75
76IV
14d89041 77PerlIOScalar_seek(pTHX_ PerlIO * f, Off_t offset, int whence)
f6c77cf1 78{
14d89041 79 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
80 switch (whence) {
81 case 0:
82 s->posn = offset;
83 break;
84 case 1:
85 s->posn = offset + s->posn;
86 break;
87 case 2:
88 s->posn = offset + SvCUR(s->var);
89 break;
90 }
91 if ((STRLEN) s->posn > SvCUR(s->var)) {
92 (void) SvGROW(s->var, (STRLEN) s->posn);
93 }
94 return 0;
f6c77cf1 95}
96
97Off_t
14d89041 98PerlIOScalar_tell(pTHX_ PerlIO * f)
f6c77cf1 99{
14d89041 100 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
101 return s->posn;
f6c77cf1 102}
103
104SSize_t
14d89041 105PerlIOScalar_unread(pTHX_ PerlIO * f, const void *vbuf, Size_t count)
f6c77cf1 106{
14d89041 107 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
4a9d6100 108 char *dst = SvGROW(s->var, (STRLEN)s->posn + count);
5735c168 109 s->posn -= count;
14d89041 110 Move(vbuf, dst + s->posn, count, char);
14d89041 111 SvPOK_on(s->var);
112 return count;
f6c77cf1 113}
114
115SSize_t
14d89041 116PerlIOScalar_write(pTHX_ PerlIO * f, const void *vbuf, Size_t count)
f6c77cf1 117{
14d89041 118 if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
119 Off_t offset;
120 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
121 SV *sv = s->var;
122 char *dst;
123 if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND) {
124 dst = SvGROW(sv, SvCUR(sv) + count);
125 offset = SvCUR(sv);
126 s->posn = offset + count;
127 }
128 else {
129 if ((s->posn + count) > SvCUR(sv))
4a9d6100 130 dst = SvGROW(sv, (STRLEN)s->posn + count);
14d89041 131 else
132 dst = SvPV_nolen(sv);
133 offset = s->posn;
134 s->posn += count;
135 }
136 Move(vbuf, dst + offset, count, char);
137 if ((STRLEN) s->posn > SvCUR(sv))
4a9d6100 138 SvCUR_set(sv, (STRLEN)s->posn);
14d89041 139 SvPOK_on(s->var);
140 return count;
09bf542c 141 }
14d89041 142 else
143 return 0;
f6c77cf1 144}
145
146IV
14d89041 147PerlIOScalar_fill(pTHX_ PerlIO * f)
f6c77cf1 148{
14d89041 149 return -1;
f6c77cf1 150}
151
152IV
14d89041 153PerlIOScalar_flush(pTHX_ PerlIO * f)
f6c77cf1 154{
14d89041 155 return 0;
f6c77cf1 156}
157
158STDCHAR *
14d89041 159PerlIOScalar_get_base(pTHX_ PerlIO * f)
f6c77cf1 160{
14d89041 161 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
162 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
163 return (STDCHAR *) SvPV_nolen(s->var);
164 }
165 return (STDCHAR *) Nullch;
f6c77cf1 166}
167
168STDCHAR *
14d89041 169PerlIOScalar_get_ptr(pTHX_ PerlIO * f)
f6c77cf1 170{
14d89041 171 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
172 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
173 return PerlIOScalar_get_base(aTHX_ f) + s->posn;
174 }
175 return (STDCHAR *) Nullch;
f6c77cf1 176}
177
178SSize_t
14d89041 179PerlIOScalar_get_cnt(pTHX_ PerlIO * f)
f6c77cf1 180{
14d89041 181 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
182 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
183 if (SvCUR(s->var) > (STRLEN) s->posn)
4a9d6100 184 return SvCUR(s->var) - (STRLEN)s->posn;
14d89041 185 else
186 return 0;
187 }
75effbe0 188 return 0;
f6c77cf1 189}
190
191Size_t
14d89041 192PerlIOScalar_bufsiz(pTHX_ PerlIO * f)
f6c77cf1 193{
14d89041 194 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
195 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
196 return SvCUR(s->var);
197 }
198 return 0;
f6c77cf1 199}
200
201void
14d89041 202PerlIOScalar_set_ptrcnt(pTHX_ PerlIO * f, STDCHAR * ptr, SSize_t cnt)
f6c77cf1 203{
14d89041 204 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
205 s->posn = SvCUR(s->var) - cnt;
f6c77cf1 206}
207
208PerlIO *
14d89041 209PerlIOScalar_open(pTHX_ PerlIO_funcs * self, PerlIO_list_t * layers, IV n,
210 const char *mode, int fd, int imode, int perm,
211 PerlIO * f, int narg, SV ** args)
f6c77cf1 212{
14d89041 213 SV *arg = (narg > 0) ? *args : PerlIOArg;
214 if (SvROK(arg) || SvPOK(arg)) {
215 if (!f) {
216 f = PerlIO_allocate(aTHX);
217 }
e3feee4e 218 if ( (f = PerlIO_push(aTHX_ f, self, mode, arg)) ) {
14d89041 219 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
220 }
221 return f;
222 }
223 return NULL;
f6c77cf1 224}
225
ecdeb87c 226SV *
14d89041 227PerlIOScalar_arg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
ecdeb87c 228{
14d89041 229 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
230 SV *var = s->var;
231 if (flags & PERLIO_DUP_CLONE)
232 var = PerlIO_sv_dup(aTHX_ var, param);
233 else if (flags & PERLIO_DUP_FD) {
234 /* Equivalent (guesses NI-S) of dup() is to create a new scalar */
235 var = newSVsv(var);
236 }
237 else {
238 var = SvREFCNT_inc(var);
239 }
240 return newRV_noinc(var);
ecdeb87c 241}
242
8cf8f3d1 243PerlIO *
14d89041 244PerlIOScalar_dup(pTHX_ PerlIO * f, PerlIO * o, CLONE_PARAMS * param,
245 int flags)
8cf8f3d1 246{
14d89041 247 if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
248 PerlIOScalar *fs = PerlIOSelf(f, PerlIOScalar);
249 PerlIOScalar *os = PerlIOSelf(o, PerlIOScalar);
250 /* var has been set by implicit push */
251 fs->posn = os->posn;
252 }
253 return f;
8cf8f3d1 254}
f6c77cf1 255
27da23d5 256PERLIO_FUNCS_DECL(PerlIO_scalar) = {
14d89041 257 sizeof(PerlIO_funcs),
258 "scalar",
259 sizeof(PerlIOScalar),
260 PERLIO_K_BUFFERED | PERLIO_K_RAW,
261 PerlIOScalar_pushed,
262 PerlIOScalar_popped,
263 PerlIOScalar_open,
264 PerlIOBase_binmode,
265 PerlIOScalar_arg,
266 PerlIOScalar_fileno,
267 PerlIOScalar_dup,
268 PerlIOBase_read,
269 PerlIOScalar_unread,
270 PerlIOScalar_write,
271 PerlIOScalar_seek,
272 PerlIOScalar_tell,
273 PerlIOScalar_close,
274 PerlIOScalar_flush,
275 PerlIOScalar_fill,
276 PerlIOBase_eof,
277 PerlIOBase_error,
278 PerlIOBase_clearerr,
279 PerlIOBase_setlinebuf,
280 PerlIOScalar_get_base,
281 PerlIOScalar_bufsiz,
282 PerlIOScalar_get_ptr,
283 PerlIOScalar_get_cnt,
284 PerlIOScalar_set_ptrcnt,
f6c77cf1 285};
286
287
288#endif /* Layers available */
289
e934609f 290MODULE = PerlIO::scalar PACKAGE = PerlIO::scalar
f6c77cf1 291
acf4de66 292PROTOTYPES: ENABLE
293
f6c77cf1 294BOOT:
295{
296#ifdef PERLIO_LAYERS
27da23d5 297 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_scalar));
f6c77cf1 298#endif
299}
300