File-Raw
view release on metacpan or search on metacpan
HV *hash;
SV **idx_sv;
IV idx;
PERL_UNUSED_VAR(items);
if (PL_dirty) XSRETURN_EMPTY;
if (!SvROK(ST(0)) || SvTYPE(SvRV(ST(0))) != SVt_PVHV) {
XSRETURN_EMPTY;
}
hash = (HV*)SvRV(ST(0));
idx_sv = hv_fetch(hash, "_idx", 4, 0);
idx = idx_sv ? SvIV(*idx_sv) : -1;
if (idx >= 0) {
file_mmap_close(idx);
}
XSRETURN_EMPTY;
}
XS_INTERNAL(xs_lines_iter) {
dXSARGS;
const char *path;
IV idx;
SV *idx_sv;
if (items < 1)
croak("Usage: file::lines_iter(path [, plugin => ..., key => value ...])");
path = SvPV_nolen(ST(0));
/* Plugin path: slurp + dispatch READ, wrap the resulting AoA in an
* iterator that walks records in order. This is eager (whole AoA
* held in memory) - for true streaming use each_line($p, $cb,
* plugin => ...). The iterator interface itself is preserved so
* code that stores the iterator handle still composes. */
if (items > 1) {
HV *opts;
SV *bytes;
SV *out;
AV *records;
LineIterEntry *entry;
opts = file_plugin_build_opts(aTHX_ &ST(0), 1, items, "lines_iter");
bytes = file_slurp_internal(aTHX_ path);
out = file_plugin_dispatch_read(aTHX_ opts, path, bytes);
SvREFCNT_dec((SV *)opts);
if (!out) {
SvREFCNT_dec(bytes);
ST(0) = &PL_sv_undef;
XSRETURN(1);
}
if (out != bytes) SvREFCNT_dec(bytes);
if (!SvROK(out) || SvTYPE(SvRV(out)) != SVt_PVAV) {
SvREFCNT_dec(out);
croak("File::Raw::lines_iter: plugin must return an arrayref of records");
}
records = (AV *)SvRV(out);
SvREFCNT_inc(records); /* keep the AV alive on its own */
SvREFCNT_dec(out); /* drop the RV wrapper */
idx = alloc_iter_slot();
entry = &g_iters[idx];
entry->fd = -1; /* sentinel: no file behind us */
entry->buffer = NULL;
entry->buf_size = 0;
entry->buf_pos = 0;
entry->buf_len = 0;
entry->eof = 0;
entry->refcount = 1;
entry->path = NULL;
entry->records = records;
entry->records_idx = 0;
idx_sv = newSViv(idx);
ST(0) = sv_2mortal(sv_bless(newRV_noinc(idx_sv),
gv_stashpv("File::Raw::lines", GV_ADD)));
XSRETURN(1);
}
idx = file_lines_open(aTHX_ path);
if (idx < 0) {
ST(0) = &PL_sv_undef;
XSRETURN(1);
}
/* Use simple IV reference - much faster than hash */
idx_sv = newSViv(idx);
ST(0) = sv_2mortal(sv_bless(newRV_noinc(idx_sv), gv_stashpv("File::Raw::lines", GV_ADD)));
XSRETURN(1);
}
XS_INTERNAL(xs_lines_iter_next) {
dXSARGS;
SV *rv;
IV idx;
LineIterEntry *entry;
char *line_start;
char *newline;
size_t line_len;
SV *result;
ssize_t n;
if (items != 1) croak("Usage: $iter->next");
rv = ST(0);
if (UNLIKELY(!SvROK(rv))) {
croak("Invalid lines iterator object");
}
/* Direct IV access - no hash lookup */
idx = SvIV(SvRV(rv));
if (UNLIKELY(idx < 0 || idx >= g_iters_count)) {
ST(0) = &PL_sv_undef;
XSRETURN(1);
}
( run in 1.479 second using v1.01-cache-2.11-cpan-14f38c9f855 )