Heap-Simple-XS

 view release on metacpan or  search on metacpan

XS.xs  view on Meta::CPAN


        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]);

XS.xs  view on Meta::CPAN

    } 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));

XS.xs  view on Meta::CPAN

            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)));

XS.xs  view on Meta::CPAN

        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 {

XS.xs  view on Meta::CPAN

            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;

XS.xs  view on Meta::CPAN


  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;

XS.xs  view on Meta::CPAN

        }
    }

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;

XS.xs  view on Meta::CPAN

        /* 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)

XS.xs  view on Meta::CPAN

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;

XS.xs  view on Meta::CPAN

            }
        }
        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 2.045 seconds using v1.01-cache-2.11-cpan-71847e10f99 )