Heap-Simple-XS
view release on metacpan or search on metacpan
key_insert(aTHX_ h, *key_ref, *val_ref);
}
XSRETURN_EMPTY;
void
extract_top(heap h)
ALIAS:
Heap::Simple::XS::extract_min = 1
Heap::Simple::XS::extract_first = 2
PPCODE:
if (h->used <= 2) {
if (h->used < 2) {
if (ix != 2) croak("Empty heap");
XSRETURN_EMPTY;
}
if (h->locked) croak("recursive heap change");
SAVEINT(h->locked);
h->locked = 1;
--h->used;
if (h->wrapped && !h->fast) SvREFCNT_dec(h->keys[h->used]);
} else {
PUTBACK;
if (h->locked) croak("recursive heap change");
SAVEINT(h->locked);
h->locked = 1;
PUSHs(sv_2mortal(extract_top(aTHX_ h)));
}
void
extract_upto(heap h, SV *border)
PPCODE:
/* special case, avoid uneeded access to border */
if (h->used < 2) return;
if (h->locked) croak("recursive heap change");
SAVEINT(h->locked);
h->locked = 1;
if (h->fast) {
NV b;
if (h->order == LESS) b = SvNV(border);
else if (h->order == MORE) b = -SvNV(border);
else croak("No fast %s order", order_name(h));
top = extract_top(aTHX_ h);
SPAGAIN;
XPUSHs(sv_2mortal(top));
if (h->used < 2) break;
}
}
if ((h->used+4)*4 < h->allocated) extend(h, 0); /* shrink really */
void
extract_all(heap h)
PPCODE:
if (h->locked) croak("recursive heap change");
SAVEINT(h->locked);
h->locked = 1;
/* Extends one too much. Who cares... */
EXTEND(SP, h->used);
EXTEND_MORTAL(h->used);
if (h->fast) {
/* No PUTBACK/SPAGAIN needed since fast extract top
won't change the stack */
while (h->used > 1) XPUSHs(sv_2mortal(extract_top(aTHX_ h)));
top = extract_top(aTHX_ h);
SPAGAIN;
XPUSHs(sv_2mortal(top));
}
if ((1+4)*4 < h->allocated) extend(h, 0); /* shrink really */
void
top(heap h)
ALIAS:
Heap::Simple::XS::first = 1
PPCODE:
if (h->used < 2) {
if (ix != 1) croak("Empty heap");
XSRETURN_EMPTY;
}
if (h->has_values) PUSHs(sv_2mortal(SvREFCNT_inc(h->values[1])));
else if (h->order == LESS) XSRETURN_NV( FKEY(NV, h, 1));
else if (h->order == MORE) XSRETURN_NV(-FKEY(NV, h, 1));
else croak("No fast %s order", order_name(h));
void
top_key(heap h)
ALIAS:
Heap::Simple::XS::min_key = 1
Heap::Simple::XS::first_key = 2
PPCODE:
if (h->used < 2) {
if (ix == 2) XSRETURN_EMPTY;
if (!h->infinity || !SvOK(h->infinity)) croak("Empty heap");
PUSHs(sv_2mortal(SvREFCNT_inc(h->infinity)));
} else if (h->fast) {
if (h->order== LESS) XSRETURN_NV( FKEY(NV, h, 1));
else if (h->order== MORE) XSRETURN_NV(-FKEY(NV, h, 1));
else croak("No fast %s order", order_name(h));
} else PUSHs(sv_2mortal(SvREFCNT_inc(KEY(h, 1))));
void
keys(heap h)
PREINIT:
/* you can actally modify the values through the return */
size_t i;
SV *key;
PPCODE:
/* Extends one too much. Who cares... */
EXTEND(SP, h->used);
EXTEND_MORTAL(h->used);
if (h->fast) {
if (h->order == LESS) for (i=1; i<h->used; i++)
PUSHs(sv_2mortal(newSVnv( FKEY(NV, h, i))));
else if (h->order == MORE) for (i=1; i<h->used; i++)
PUSHs(sv_2mortal(newSVnv(-FKEY(NV, h, i))));
else croak("No fast %s order", order_name(h));
} else {
SPAGAIN;
PUSHs(sv_2mortal(SvREFCNT_inc(key)));
}
}
void
values(heap h)
PREINIT:
/* you can actally modify the values through the return */
size_t i;
PPCODE:
/* Extends one too much. Who cares... */
EXTEND(SP, h->used);
EXTEND_MORTAL(h->used);
if (h->has_values) for (i=1; i<h->used; i++)
PUSHs(sv_2mortal(SvREFCNT_inc(h->values[i])));
else if (h->order == LESS) for (i=1; i<h->used; i++)
PUSHs(sv_2mortal(newSVnv( FKEY(NV, h, i))));
else if (h->order == MORE) for (i=1; i<h->used; i++)
PUSHs(sv_2mortal(newSVnv(-FKEY(NV, h, i))));
else croak("No fast %s order", order_name(h));
void
clear(heap h)
PREINIT:
SV *key, *value;
PPCODE:
if (h->locked) croak("recursive heap change");
SAVEINT(h->locked);
h->locked = 1;
if (h->fast || !h->wrapped) {
if (h->has_values)
while (h->used > 1) SvREFCNT_dec(h->values[--h->used]);
else h->used = 1;
} else {
while (h->used > 1) {
--h->used;
OUTPUT:
RETVAL
void
_absorb(SV * heap1, SV *heap2)
PREINIT:
int copied2, one_by_one;
SV *heap1_ref, *value;
heap h1, h2;
PPCODE:
/* Helper for absorb, puts h1 into h2 */
h1 = C_HEAP(heap1, "heap1");
/* Keep argument alive for the duration */
heap1_ref = SvRV(heap1);
sv_2mortal(SvREFCNT_inc(heap1_ref));
if (h1->locked) croak("recursive heap change");
SAVEINT(h1->locked);
h1->locked = 1;
if (h1->used < 2) XSRETURN_EMPTY;
}
}
void
_key_absorb(SV * heap1, SV *heap2)
PREINIT:
int copied2;
SV *heap1_ref, *key, *value;
heap h1, h2;
int one_by_one;
PPCODE:
/* Helper for absorb, puts h1 into h2 */
h1 = C_HEAP(heap1, "heap1");
/* Keep arguments alive for the duration */
heap1_ref = SvRV(heap1);
sv_2mortal(SvREFCNT_inc(heap1_ref));
if (h1->locked) croak("recursive heap change");
SAVEINT(h1->locked);
h1->locked = 1;
if (h1->used < 2) XSRETURN_EMPTY;
/* Needed or the stack will remember and return the stuff we pushed */
SPAGAIN;
if (count) {
if (count < 0) croak("Forced void context call '_key_absorb' succeeded in returning %d values. This is impossible", (int) count);
SP -= count;
}
}
void
infinity(heap h, SV *new_infinity=0)
PPCODE:
if (GIMME_V != G_VOID)
XPUSHs(h->infinity ?
sv_2mortal(SvREFCNT_inc(h->infinity)) : &PL_sv_undef);
if (new_infinity) {
if (h->infinity) sv_2mortal(h->infinity);
h->infinity = newSVsv(new_infinity);
}
IV
key_index(heap h)
key_function(heap h)
CODE:
if (h->elements != FUNCTION && h->elements != ANY_ELEM)
croak("Heap elements are not of type 'Function' or 'Any'");
RETVAL = SvREFCNT_inc(h->hkey);
OUTPUT:
RETVAL
void
user_data(heap h, SV *new_user_data=0)
PPCODE:
if (GIMME_V != G_VOID)
PUSHs(h->user_data ? h->user_data : &PL_sv_undef);
if (new_user_data) {
if (h->user_data) sv_2mortal(h->user_data);
h->user_data = newSVsv(new_user_data);
}
void
order(heap h)
PPCODE:
PUSHs(h->order == CODE_ORDER ?
h->order_sv : sv_2mortal(newSVpv(order_name(h), 0)));
void
elements(heap h)
PPCODE:
XPUSHs(sv_2mortal(newSVpv(elements_name(h), 0)));
if (GIMME_V == G_ARRAY) switch(h->elements) {
case SCALAR:
break;
case ARRAY:
XPUSHs(sv_2mortal(newSViv(h->aindex)));
break;
case HASH:
case METHOD:
case OBJECT:
case FUNCTION:
case ANY_ELEM:
if (h->hkey) XPUSHs(sv_2mortal(newSVsv(h->hkey)));
break;
default:
croak("Assertion: unhandled element type %s", elements_name(h));
}
void
wrapped(heap h)
PPCODE:
if (h->key_ops) XSRETURN_YES;
if (GIMME_V == G_SCALAR) XSRETURN_NO;
XSRETURN_EMPTY;
void
dirty(heap h)
PPCODE:
if (h->dirty) XSRETURN_YES;
if (GIMME_V == G_SCALAR) XSRETURN_NO;
XSRETURN_EMPTY;
void
can_die(heap h)
PPCODE:
/* ->fast types are wrapped too really */
if (h->can_die) XSRETURN_YES;
if (GIMME_V == G_SCALAR) XSRETURN_NO;
XSRETURN_EMPTY;
void
max_count(heap h)
PPCODE:
if (h->max_count == MAX_SIZE) XSRETURN_NV(INFINITY);
XSRETURN_UV(h->max_count);
void
merge_arrays(heap h, ...)
PREINIT:
I32 i, j;
size_t l, filled, left, k0, k1, k2;
SV *value, **ptr, *key;
AV *av, *work_av;
}
}
break;
}
XSRETURN(1);
void
DESTROY(heap h)
PREINIT:
SV *key, *value;
PPCODE:
/* Let's assume the module isn't buggy and it always increases the refcount
on the heap during modification.
That means that the user is explicitely calling DESTROY */
if (h->locked)
croak("Refusing explicit DESTROY call during heap modification");
h->locked = 1;
if (h->fast || !h->wrapped) {
if (h->has_values)
while (h->used > 1) SvREFCNT_dec(h->values[--h->used]);
} else {
( run in 0.503 second using v1.01-cache-2.11-cpan-71847e10f99 )