#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "perlio.h"
#include "perliol.h"
#include "eol.h"
#include "fill.h"
#include "write.h"
IV
PerlIOEOL_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab)
{
PerlIOEOL *s = PerlIOSelf(f, PerlIOEOL);
STDCHAR *p, *eol_w = NULL, *eol_r = NULL;
STRLEN len;
if (PerlIOBase(PerlIONext(f))->flags & PERLIO_F_UTF8) {
PerlIOBase(f)->flags |= PERLIO_F_UTF8;
}
else {
PerlIOBase(f)->flags &= ~PERLIO_F_UTF8;
}
s->name = NULL;
s->read.cr = s->write.cr = 0;
s->read.seen = s->write.seen = 0;
p = SvPV(arg, len);
if (len) {
STDCHAR *end = p + len;
Newz('e', eol_r, len + 1, char);
Copy(p, eol_r, len, char);
p = eol_r; end = p + len;
for (; p < end; p++) {
*p = toLOWER(*p);
if ((*p == '-') && (eol_w == NULL)) {
*p = '\0';
eol_w = p+1;
}
}
}
else {
Perl_die(aTHX_ "Must pass CRLF, CR, LF or Native to :eol().");
}
if (eol_w == NULL) { eol_w = eol_r; }
EOL_AssignEOL( eol_r, s->read );
EOL_AssignEOL( eol_w, s->write );
Safefree( eol_r );
return PerlIOBuf_pushed(aTHX_ f, mode, arg, tab);
}
STDCHAR *
PerlIOEOL_get_base(pTHX_ PerlIO *f)
{
PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
if (!b->buf) {
PerlIOEOL *s = PerlIOSelf(f, PerlIOEOL);
if (!b->bufsiz)
b->bufsiz = 4096;
b->buf = Newz( 'B', b->buf, b->bufsiz * ( (s->read.eol == EOL_CRLF) ? 2 : 1 ), STDCHAR );
if (!b->buf) {
b->buf = (STDCHAR *) & b->oneword;
b->bufsiz = sizeof(b->oneword);
}
b->ptr = b->buf;
b->end = b->ptr;
}
return b->buf;
}
void
PerlIOEOL_clearerr(pTHX_ PerlIO *f)
{
PerlIOEOL *s;
if (PerlIOValid(f)) {
s = PerlIOSelf(f, PerlIOEOL);
if (PerlIOBase(f)->flags & PERLIO_F_EOF) {
s->read.cr = s->write.cr = 0;
s->read.seen = s->write.seen = 0;
}
}
PerlIOBase_clearerr(aTHX_ f);
}
SSize_t
PerlIOEOL_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
{
PerlIOEOL *s = PerlIOSelf(f, PerlIOEOL);
const STDCHAR *i, *start = vbuf, *end = vbuf;
end += (unsigned int)count;
EOL_StartUpdate( s->write );
if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) { return 0; }
EOL_Dispatch( s->write, WriteWithCR, WriteWithLF, WriteWithCRLF );
if (start >= end) { return count; }
return ( (start + PerlIOBuf_write(aTHX_ f, start, end - start)) - (STDCHAR*)vbuf );
}
IV
PerlIOEOL_fill(pTHX_ PerlIO * f)
{
IV code = PerlIOBuf_fill(aTHX_ f);
PerlIOEOL *s = PerlIOSelf(f, PerlIOEOL);
PerlIOBuf *b = PerlIOSelf(f, PerlIOBuf);
const STDCHAR *i, *start = b->ptr, *end = b->end;
STDCHAR *buf = NULL, *ptr = NULL;
if (code != 0) { return code; }
EOL_StartUpdate( s->read );
EOL_Dispatch( s->read, FillWithCR, FillWithLF, FillWithCRLF );
if (buf == NULL) { return 0; }
if (i > start) {
Copy(start, ptr, i - start, STDCHAR);
ptr += i - start;
}
b->ptr = b->buf;
b->end = b->buf + (ptr - buf);
if (buf != b->buf) {
Copy(buf, b->buf, ptr - buf, STDCHAR);
Safefree(buf);
}
return 0;
}
PerlIO *
PerlIOEOL_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers,
IV n, const char *mode, int fd, int imode, int perm,
PerlIO *old, int narg, SV **args)
{
SV *arg = (narg > 0) ? *args : PerlIOArg;
PerlIO *f = PerlIOBuf_open( aTHX_ self, layers, n, mode, fd, imode, perm, old, narg, args );
if (f) {
PerlIOEOL *s = PerlIOSelf(f, PerlIOEOL);
s->name = savepv( SvPV_nolen(arg) );
}
return f;
}
PerlIO_funcs PerlIO_eol = {
sizeof(PerlIO_funcs),
"eol",
sizeof(PerlIOEOL),
PERLIO_K_BUFFERED | PERLIO_K_UTF8,
PerlIOEOL_pushed,
PerlIOBuf_popped,
PerlIOEOL_open,
PerlIOBase_binmode,
NULL,
PerlIOBase_fileno,
PerlIOBuf_dup,
PerlIOBuf_read,
PerlIOBuf_unread,
PerlIOEOL_write,
PerlIOBuf_seek,
PerlIOBuf_tell,
PerlIOBuf_close,
PerlIOBuf_flush,
PerlIOEOL_fill,
PerlIOBase_eof,
PerlIOBase_error,
PerlIOEOL_clearerr,
PerlIOBase_setlinebuf,
PerlIOEOL_get_base,
PerlIOBuf_bufsiz,
PerlIOBuf_get_ptr,
PerlIOBuf_get_cnt,
PerlIOBuf_set_ptrcnt
};
MODULE = PerlIO::eol PACKAGE = PerlIO::eol
BOOT:
#ifdef PERLIO_LAYERS
PerlIO_define_layer(aTHX_ &PerlIO_eol);
#endif
unsigned int
eol_is_mixed(arg)
SV *arg
PROTOTYPE: $
CODE:
STRLEN len;
register U8 *i, *end;
register unsigned int seen = 0;
i = (U8*)SvPV(arg, len);
end = i + len;
RETVAL = 0;
for (; i < end; i++) {
EOL_CheckForMixedCRLF( seen, EOL_Break, EOL_Seen( seen, EOL_CR, EOL_Break ), break, ( i++ ) );
}
OUTPUT:
RETVAL
char *
CR()
PROTOTYPE:
CODE:
RETVAL = "\015";
OUTPUT:
RETVAL
char *
LF()
PROTOTYPE:
CODE:
RETVAL = "\012";
OUTPUT:
RETVAL
char *
CRLF()
PROTOTYPE:
CODE:
RETVAL = "\015\012";
OUTPUT:
RETVAL
char *
NATIVE()
PROTOTYPE:
CODE:
RETVAL = (
(EOL_NATIVE == EOL_CR) ? "\015" :
(EOL_NATIVE == EOL_LF) ? "\012" :
(EOL_NATIVE == EOL_CRLF) ? "\015\012" : ""
);
OUTPUT:
RETVAL