In Perl_regfree_internal(), rx is actually not NULL.
[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)) {
b35bc0c6 27 if (SvREADONLY(SvRV(arg)) && mode && *mode != 'r') {
28 if (ckWARN(WARN_LAYER))
29 Perl_warner(aTHX_ packWARN(WARN_LAYER), PL_no_modify);
42bc49da 30 SETERRNO(EINVAL, SS_IVCHAN);
b35bc0c6 31 return -1;
32 }
14d89041 33 s->var = SvREFCNT_inc(SvRV(arg));
03aa69f9 34 if (!SvPOK(s->var) && SvTYPE(SvRV(arg)) > SVt_NULL)
34fcc551 35 (void)SvPV_nolen(s->var);
14d89041 36 }
37 else {
38 s->var =
39 SvREFCNT_inc(perl_get_sv
40 (SvPV_nolen(arg), GV_ADD | GV_ADDMULTI));
41 }
564dc057 42 }
14d89041 43 else {
44 s->var = newSVpvn("", 0);
564dc057 45 }
c5b94a97 46 SvUPGRADE(s->var, SVt_PV);
14d89041 47 code = PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab);
47cc46ee 48 if (!SvOK(s->var) || (PerlIOBase(f)->flags) & PERLIO_F_TRUNCATE)
b162af07 49 SvCUR_set(s->var, 0);
14d89041 50 if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND)
51 s->posn = SvCUR(s->var);
52 else
53 s->posn = 0;
54 return code;
f6c77cf1 55}
56
57IV
14d89041 58PerlIOScalar_popped(pTHX_ PerlIO * f)
f6c77cf1 59{
14d89041 60 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
61 if (s->var) {
62 SvREFCNT_dec(s->var);
63 s->var = Nullsv;
64 }
65 return 0;
f6c77cf1 66}
67
68IV
14d89041 69PerlIOScalar_close(pTHX_ PerlIO * f)
f6c77cf1 70{
14d89041 71 IV code = PerlIOBase_close(aTHX_ f);
72 PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
73 return code;
f6c77cf1 74}
75
76IV
14d89041 77PerlIOScalar_fileno(pTHX_ PerlIO * f)
f6c77cf1 78{
14d89041 79 return -1;
f6c77cf1 80}
81
82IV
14d89041 83PerlIOScalar_seek(pTHX_ PerlIO * f, Off_t offset, int whence)
f6c77cf1 84{
14d89041 85 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
42bc49da 86 STRLEN oldcur = SvCUR(s->var);
87 STRLEN newlen;
14d89041 88 switch (whence) {
42bc49da 89 case SEEK_SET:
14d89041 90 s->posn = offset;
91 break;
42bc49da 92 case SEEK_CUR:
14d89041 93 s->posn = offset + s->posn;
94 break;
42bc49da 95 case SEEK_END:
14d89041 96 s->posn = offset + SvCUR(s->var);
97 break;
98 }
42bc49da 99 if (s->posn < 0) {
100 if (ckWARN(WARN_LAYER))
101 Perl_warner(aTHX_ packWARN(WARN_LAYER), "Offset outside string");
102 SETERRNO(EINVAL, SS_IVCHAN);
103 return -1;
14d89041 104 }
42bc49da 105 newlen = (STRLEN) s->posn;
106 if (newlen > oldcur) {
107 (void) SvGROW(s->var, newlen);
108 Zero(SvPVX(s->var) + oldcur, newlen - oldcur, char);
109 /* No SvCUR_set(), though. This is just a seek, not a write. */
110 }
8b8eea96 111 else if (!SvPVX(s->var)) {
112 /* ensure there's always a character buffer */
113 (void)SvGROW(s->var,1);
114 }
42bc49da 115 SvPOK_on(s->var);
14d89041 116 return 0;
f6c77cf1 117}
118
119Off_t
14d89041 120PerlIOScalar_tell(pTHX_ PerlIO * f)
f6c77cf1 121{
14d89041 122 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
123 return s->posn;
f6c77cf1 124}
125
126SSize_t
14d89041 127PerlIOScalar_unread(pTHX_ PerlIO * f, const void *vbuf, Size_t count)
f6c77cf1 128{
14d89041 129 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
4a9d6100 130 char *dst = SvGROW(s->var, (STRLEN)s->posn + count);
5735c168 131 s->posn -= count;
14d89041 132 Move(vbuf, dst + s->posn, count, char);
14d89041 133 SvPOK_on(s->var);
134 return count;
f6c77cf1 135}
136
137SSize_t
14d89041 138PerlIOScalar_write(pTHX_ PerlIO * f, const void *vbuf, Size_t count)
f6c77cf1 139{
14d89041 140 if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
141 Off_t offset;
142 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
143 SV *sv = s->var;
144 char *dst;
145 if ((PerlIOBase(f)->flags) & PERLIO_F_APPEND) {
146 dst = SvGROW(sv, SvCUR(sv) + count);
147 offset = SvCUR(sv);
148 s->posn = offset + count;
149 }
150 else {
151 if ((s->posn + count) > SvCUR(sv))
4a9d6100 152 dst = SvGROW(sv, (STRLEN)s->posn + count);
14d89041 153 else
154 dst = SvPV_nolen(sv);
155 offset = s->posn;
156 s->posn += count;
157 }
158 Move(vbuf, dst + offset, count, char);
159 if ((STRLEN) s->posn > SvCUR(sv))
4a9d6100 160 SvCUR_set(sv, (STRLEN)s->posn);
14d89041 161 SvPOK_on(s->var);
162 return count;
09bf542c 163 }
14d89041 164 else
165 return 0;
f6c77cf1 166}
167
168IV
14d89041 169PerlIOScalar_fill(pTHX_ PerlIO * f)
f6c77cf1 170{
14d89041 171 return -1;
f6c77cf1 172}
173
174IV
14d89041 175PerlIOScalar_flush(pTHX_ PerlIO * f)
f6c77cf1 176{
14d89041 177 return 0;
f6c77cf1 178}
179
180STDCHAR *
14d89041 181PerlIOScalar_get_base(pTHX_ PerlIO * f)
f6c77cf1 182{
14d89041 183 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
184 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
185 return (STDCHAR *) SvPV_nolen(s->var);
186 }
9849c14c 187 return (STDCHAR *) NULL;
f6c77cf1 188}
189
190STDCHAR *
14d89041 191PerlIOScalar_get_ptr(pTHX_ PerlIO * f)
f6c77cf1 192{
14d89041 193 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
194 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
195 return PerlIOScalar_get_base(aTHX_ f) + s->posn;
196 }
9849c14c 197 return (STDCHAR *) NULL;
f6c77cf1 198}
199
200SSize_t
14d89041 201PerlIOScalar_get_cnt(pTHX_ PerlIO * f)
f6c77cf1 202{
14d89041 203 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
204 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
205 if (SvCUR(s->var) > (STRLEN) s->posn)
4a9d6100 206 return SvCUR(s->var) - (STRLEN)s->posn;
14d89041 207 else
208 return 0;
209 }
75effbe0 210 return 0;
f6c77cf1 211}
212
213Size_t
14d89041 214PerlIOScalar_bufsiz(pTHX_ PerlIO * f)
f6c77cf1 215{
14d89041 216 if (PerlIOBase(f)->flags & PERLIO_F_CANREAD) {
217 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
218 return SvCUR(s->var);
219 }
220 return 0;
f6c77cf1 221}
222
223void
14d89041 224PerlIOScalar_set_ptrcnt(pTHX_ PerlIO * f, STDCHAR * ptr, SSize_t cnt)
f6c77cf1 225{
14d89041 226 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
227 s->posn = SvCUR(s->var) - cnt;
f6c77cf1 228}
229
230PerlIO *
14d89041 231PerlIOScalar_open(pTHX_ PerlIO_funcs * self, PerlIO_list_t * layers, IV n,
232 const char *mode, int fd, int imode, int perm,
233 PerlIO * f, int narg, SV ** args)
f6c77cf1 234{
14d89041 235 SV *arg = (narg > 0) ? *args : PerlIOArg;
236 if (SvROK(arg) || SvPOK(arg)) {
237 if (!f) {
238 f = PerlIO_allocate(aTHX);
239 }
e3feee4e 240 if ( (f = PerlIO_push(aTHX_ f, self, mode, arg)) ) {
14d89041 241 PerlIOBase(f)->flags |= PERLIO_F_OPEN;
242 }
243 return f;
244 }
245 return NULL;
f6c77cf1 246}
247
ecdeb87c 248SV *
14d89041 249PerlIOScalar_arg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
ecdeb87c 250{
14d89041 251 PerlIOScalar *s = PerlIOSelf(f, PerlIOScalar);
252 SV *var = s->var;
253 if (flags & PERLIO_DUP_CLONE)
254 var = PerlIO_sv_dup(aTHX_ var, param);
255 else if (flags & PERLIO_DUP_FD) {
256 /* Equivalent (guesses NI-S) of dup() is to create a new scalar */
257 var = newSVsv(var);
258 }
259 else {
260 var = SvREFCNT_inc(var);
261 }
262 return newRV_noinc(var);
ecdeb87c 263}
264
8cf8f3d1 265PerlIO *
14d89041 266PerlIOScalar_dup(pTHX_ PerlIO * f, PerlIO * o, CLONE_PARAMS * param,
267 int flags)
8cf8f3d1 268{
14d89041 269 if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
270 PerlIOScalar *fs = PerlIOSelf(f, PerlIOScalar);
271 PerlIOScalar *os = PerlIOSelf(o, PerlIOScalar);
272 /* var has been set by implicit push */
273 fs->posn = os->posn;
274 }
275 return f;
8cf8f3d1 276}
f6c77cf1 277
27da23d5 278PERLIO_FUNCS_DECL(PerlIO_scalar) = {
14d89041 279 sizeof(PerlIO_funcs),
280 "scalar",
281 sizeof(PerlIOScalar),
282 PERLIO_K_BUFFERED | PERLIO_K_RAW,
283 PerlIOScalar_pushed,
284 PerlIOScalar_popped,
285 PerlIOScalar_open,
286 PerlIOBase_binmode,
287 PerlIOScalar_arg,
288 PerlIOScalar_fileno,
289 PerlIOScalar_dup,
290 PerlIOBase_read,
291 PerlIOScalar_unread,
292 PerlIOScalar_write,
293 PerlIOScalar_seek,
294 PerlIOScalar_tell,
295 PerlIOScalar_close,
296 PerlIOScalar_flush,
297 PerlIOScalar_fill,
298 PerlIOBase_eof,
299 PerlIOBase_error,
300 PerlIOBase_clearerr,
301 PerlIOBase_setlinebuf,
302 PerlIOScalar_get_base,
303 PerlIOScalar_bufsiz,
304 PerlIOScalar_get_ptr,
305 PerlIOScalar_get_cnt,
306 PerlIOScalar_set_ptrcnt,
f6c77cf1 307};
308
309
310#endif /* Layers available */
311
e934609f 312MODULE = PerlIO::scalar PACKAGE = PerlIO::scalar
f6c77cf1 313
acf4de66 314PROTOTYPES: ENABLE
315
f6c77cf1 316BOOT:
317{
318#ifdef PERLIO_LAYERS
27da23d5 319 PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_scalar));
f6c77cf1 320#endif
321}
322