Fetch
view release on metacpan or search on metacpan
xs/headers.xs view on Meta::CPAN
MODULE = Fetch PACKAGE = Fetch::Headers
# Ordered, case-insensitive, multi-valued HTTP headers over a blessed
# [k, v, k, v, ...] arrayref (see include/fetch/ft_headers.h).
# new(%pairs) | new(\@pairs) | new(\%hash) | new($headers): a single arg is
# taken as pairs/arrayref/hashref/Fetch::Headers; any other list is the flat
# name => value list verbatim.
SV *
new(class, ...)
SV *class
CODE:
{
const char *cls = (SvROK(class) && SvOBJECT(SvRV(class)))
? HvNAME(SvSTASH(SvRV(class))) : SvPV_nolen(class);
AV *av = newAV();
if (items == 2) {
ft_hdr_pairs_into(aTHX_ av, ST(1));
} else {
int i;
for (i = 1; i < items; i++) av_push(av, newSVsv(ST(i)));
}
RETVAL = sv_bless(newRV_noinc((SV *)av), gv_stashpv(cls, GV_ADD));
}
OUTPUT:
RETVAL
# first value for $name, or undef
SV *
get(self, name)
SV *self
SV *name
CODE:
{
STRLEN nl;
const char *ns = SvPV_const(name, nl);
AV *av = (AV *)SvRV(self);
SSize_t idx = ft_hdr_find(aTHX_ av, ns, nl);
if (idx < 0) {
RETVAL = newSV(0);
} else {
SV **v = av_fetch(av, idx + 1, 0);
RETVAL = (v && *v) ? newSVsv(*v) : newSV(0);
}
}
OUTPUT:
RETVAL
# every value for $name, in order
void
get_all(self, name)
SV *self
SV *name
PPCODE:
{
STRLEN nl;
const char *ns = SvPV_const(name, nl);
AV *av = (AV *)SvRV(self);
SSize_t n = av_len(av) + 1, i;
for (i = 0; i + 1 < n; i += 2) {
SV **k = av_fetch(av, i, 0);
if (k && *k) {
STRLEN kl;
const char *ks = SvPV_const(*k, kl);
if (ft_ci_eq(ks, kl, ns, nl)) {
SV **v = av_fetch(av, i + 1, 0);
mXPUSHs((v && *v) ? newSVsv(*v) : newSV(0));
}
}
}
}
# is $name present?
int
exists(self, name)
SV *self
SV *name
CODE:
{
STRLEN nl;
const char *ns = SvPV_const(name, nl);
RETVAL = ft_hdr_find(aTHX_ (AV *)SvRV(self), ns, nl) >= 0 ? 1 : 0;
}
OUTPUT:
RETVAL
# append value(s) under $name, keeping any existing
SV *
add(self, name, ...)
SV *self
SV *name
CODE:
{
AV *av = (AV *)SvRV(self);
int i;
for (i = 2; i < items; i++) {
av_push(av, newSVsv(name));
av_push(av, newSVsv(ST(i)));
}
RETVAL = SvREFCNT_inc(self);
}
OUTPUT:
RETVAL
# drop every value for $name
SV *
remove(self, name)
SV *self
SV *name
CODE:
{
STRLEN nl;
const char *ns = SvPV_const(name, nl);
AV *av = (AV *)SvRV(self);
xs/headers.xs view on Meta::CPAN
SV **v = av_fetch(av, i + 1, 0);
av_push(keep, (k && *k) ? newSVsv(*k) : newSV(0));
av_push(keep, (v && *v) ? newSVsv(*v) : newSV(0));
}
}
av_clear(av);
n = av_len(keep) + 1;
for (i = 0; i < n; i++) {
SV **e = av_fetch(keep, i, 0);
av_push(av, (e && *e) ? SvREFCNT_inc(*e) : newSV(0));
}
SvREFCNT_dec((SV *)keep);
RETVAL = SvREFCNT_inc(self);
}
OUTPUT:
RETVAL
# replace all values for $name with the given value(s)
SV *
set(self, name, ...)
SV *self
SV *name
CODE:
{
STRLEN nl;
const char *ns = SvPV_const(name, nl);
AV *av = (AV *)SvRV(self);
AV *keep = newAV();
SSize_t n = av_len(av) + 1, i;
int j;
for (i = 0; i + 1 < n; i += 2) {
SV **k = av_fetch(av, i, 0);
STRLEN kl;
const char *ks = (k && *k) ? SvPV_const(*k, kl) : (kl = 0, "");
if (!(k && *k) || !ft_ci_eq(ks, kl, ns, nl)) {
SV **v = av_fetch(av, i + 1, 0);
av_push(keep, (k && *k) ? newSVsv(*k) : newSV(0));
av_push(keep, (v && *v) ? newSVsv(*v) : newSV(0));
}
}
av_clear(av);
n = av_len(keep) + 1;
for (i = 0; i < n; i++) {
SV **e = av_fetch(keep, i, 0);
av_push(av, (e && *e) ? SvREFCNT_inc(*e) : newSV(0));
}
SvREFCNT_dec((SV *)keep);
for (j = 2; j < items; j++) {
av_push(av, newSVsv(name));
av_push(av, newSVsv(ST(j)));
}
RETVAL = SvREFCNT_inc(self);
}
OUTPUT:
RETVAL
# distinct field names, in order of first appearance
void
names(self)
SV *self
PPCODE:
{
AV *av = (AV *)SvRV(self);
AV *seen = newAV();
SSize_t n = av_len(av) + 1, i;
sv_2mortal((SV *)seen);
for (i = 0; i + 1 < n; i += 2) {
SV **k = av_fetch(av, i, 0);
if (k && *k) {
STRLEN kl;
const char *ks = SvPV_const(*k, kl);
SSize_t m = av_len(seen) + 1, j;
int dup = 0;
for (j = 0; j < m; j++) {
SV **s = av_fetch(seen, j, 0);
STRLEN sl;
const char *ss = (s && *s) ? SvPV_const(*s, sl) : (sl = 0, "");
if (ft_ci_eq(ss, sl, ks, kl)) { dup = 1; break; }
}
if (!dup) {
av_push(seen, newSVsv(*k));
mXPUSHs(newSVsv(*k));
}
}
}
}
# the flat name => value list
void
pairs(self)
SV *self
PPCODE:
{
AV *av = (AV *)SvRV(self);
SSize_t n = av_len(av) + 1, i;
for (i = 0; i < n; i++) {
SV **e = av_fetch(av, i, 0);
mXPUSHs((e && *e) ? newSVsv(*e) : newSV(0));
}
}
# a shallow copy
SV *
clone(self)
SV *self
CODE:
{
AV *av = (AV *)SvRV(self);
AV *cp = newAV();
SSize_t n = av_len(av) + 1, i;
for (i = 0; i < n; i++) {
SV **e = av_fetch(av, i, 0);
av_push(cp, (e && *e) ? newSVsv(*e) : newSV(0));
}
RETVAL = sv_bless(newRV_noinc((SV *)cp),
SvSTASH(SvRV(self)));
SvREFCNT_inc(SvSTASH(SvRV(self)));
}
OUTPUT:
RETVAL
# overlay $other: each field name it carries replaces all of this object's
# values for that name; names present only here are kept, in place.
SV *
merge(self, other)
SV *self
SV *other
CODE:
ft_hdr_merge(aTHX_ (AV *)SvRV(self), other);
RETVAL = SvREFCNT_inc(self);
OUTPUT:
RETVAL
( run in 0.875 second using v1.01-cache-2.11-cpan-4e7a2411597 )