Senna

 view release on metacpan or  search on metacpan

lib/Senna.xs  view on Meta::CPAN

        char *path;
        int  key_size;
        int  flags;
        int  initial_n_segments;
        sen_encoding encoding;
    PREINIT:
        sen_index *index;
        SV *sv;
    CODE:
        index = sen_index_create(path, key_size, flags, initial_n_segments, encoding);
        if (index == NULL)
            croak ("Failed to create senna index");

        XS_STRUCT2OBJ(sv, class, index);
        RETVAL = sv;
    OUTPUT:
        RETVAL
    
SV *
SIndex_xs_open(class, path)
        char *class;
        char *path;
    PREINIT:
        sen_index *index;
        int key_size;
        SV *sv;
    CODE:
        index = sen_index_open(path);
        if (index == NULL)
            croak ("Failed to open senna index");

        /* Make sure that index does not have some unsupported key_size
         */
        sen_index_info(index, &key_size, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        if (key_size != SEN_VARCHAR_KEY && key_size != SEN_INT_KEY)
            croak("Senna::Index does not support key_size other than 0 or 4");

        XS_STRUCT2OBJ(sv, class, index);
        SvREADONLY_on(sv);

        RETVAL = sv;
    OUTPUT:
        RETVAL

void
SIndex_info(self)
        SV *self;
    PREINIT:
        sen_index *index;
        int key_size;
        int flags;
        int initial_n_segments;
        sen_encoding encoding;
        unsigned int nrecords_keys;
        unsigned int file_size_keys;
        unsigned int nrecords_lexicon;
        unsigned int file_size_lexicon;
        unsigned int inv_seg_size;
        unsigned int inv_chunk_size;
        sen_rc rc;
    PPCODE:
        index = XS_STATE(sen_index *, self);
        rc = sen_index_info(index,
            &key_size, &flags, &initial_n_segments, &encoding,
            &nrecords_keys, &file_size_keys, &nrecords_lexicon,
            &file_size_lexicon, &inv_seg_size, &inv_chunk_size
        );

        if (rc != sen_success)
            croak("Failed to call sen_index_info: %d", rc);

        EXTEND(SP, 10);
        mPUSHi(key_size);
        mPUSHi(flags);
        mPUSHi(initial_n_segments);
        mPUSHi(encoding);
        mPUSHi(nrecords_keys);
        mPUSHi(file_size_keys);
        mPUSHi(nrecords_lexicon);
        mPUSHi(file_size_lexicon);
        mPUSHi(inv_seg_size);
        mPUSHi(inv_chunk_size);

SV *
SIndex_path(self)
        SV *self;
    PREINIT:
        sen_index *index;
        char path[SEN_MAX_PATH_SIZE];
    CODE:
        index = XS_STATE(sen_index *, self);
        sen_index_path(index, path, SEN_MAX_PATH_SIZE);
        RETVAL = newSVpv(path, 0);
    OUTPUT:
        RETVAL

SV *
SIndex_close(obj)
        SV *obj;
    PREINIT:
        sen_index *index;
    CODE:
        index = XS_STATE(sen_index *, obj);
        RETVAL = sen_rc2obj(sen_index_close(index));
    OUTPUT:
        RETVAL

SV *
SIndex_remove(self)
        SV *self;
    PREINIT:
        sen_index *index;
        char path[SEN_MAX_PATH_SIZE];
    CODE:
        index = XS_STATE(sen_index *, self);
        if (! sen_index_path(index, path, SEN_MAX_PATH_SIZE))
            croak("sen_index_path did not return a proper path");
        RETVAL = sen_rc2obj(sen_index_remove(path));
    OUTPUT:
        RETVAL

SV *
SIndex_xs_rename(self, new)
        SV *self;
        char *new;
    PREINIT:
        sen_index *index;
        char path[SEN_MAX_PATH_SIZE];
    CODE:
        index = XS_STATE(sen_index *, self);
        if (! sen_index_path(index, path, SEN_MAX_PATH_SIZE))
            croak("sen_index_path did not return a proper path");
        RETVAL = sen_rc2obj(sen_index_rename(path, new));
    OUTPUT:
        RETVAL

void
SIndex_xs_select(self, query_sv, records, op_sv, optarg_sv)
        SV *self;
        SV *query_sv;
        SV *records;
        SV *op_sv;
        SV *optarg_sv;
    PREINIT:
        SV *sv;
        STRLEN query_len = 0;
        sen_index   *index;
        sen_rc       rc;
        sen_records *r;
        sen_select_optarg *optarg = NULL;
        sen_sel_operator op = SvOK(op_sv) ? SvIV(op_sv) : 0;
        char *query = NULL;
        int need_optarg_free = 0;
        int need_records_free = 0;
    PPCODE:
        index = XS_STATE(sen_index *, self);

        if ( SvOK(query_sv) ) {
            query = SvPV(query_sv, query_len);
        }

        if (! SvOK(records)) {
            r = sen_records_open(sen_rec_document, sen_rec_none, 0);
            need_records_free = 1;
        } else {
            r = XS_STATE(sen_records *, records);
        }

        if (SvOK(optarg_sv)) {
            optarg = XS_STATE(sen_select_optarg *, optarg_sv);
            if (optarg != NULL) {
                Newz(1234, optarg, 1, sen_select_optarg);
                optarg->mode = sen_sel_exact;
                need_optarg_free = 1;
            }
        }

        rc = sen_index_select(
            index,
            query,
#if (SENNA_MAJOR_VERSION >= 1)
            query_len,
#endif
            r,
            op,
            optarg
        );

        if (need_optarg_free) {
            Safefree(optarg);
        }

        if (rc != sen_success) {
            Safefree(r);
            croak ("Failed to execute sen_index_select: rc = %d", rc);
        }

        if (GIMME_V == G_VOID) {
            if (need_records_free) sen_records_close(r);
            /* no op */;
        } else if (GIMME_V == G_SCALAR) {
            XS_STRUCT2OBJ(sv, "Senna::Records", r);
            XPUSHs(sv);
        } else {
            char keybuf[SEN_MAX_KEY_SIZE];
            int  score;
            int  hits;

            hits = sen_records_nhits(r);
            if (hits <= 0)
                return;

            EXTEND(SP, hits);
            while (sen_records_next(r, &keybuf, SEN_MAX_KEY_SIZE, &score)) {
                /* Construct Senna::Record object */

lib/Senna.xs  view on Meta::CPAN

        new_values = SvOK(new) ? XS_STATE(sen_values *, new) : NULL;

        sv2senna_key(index, key, &void_key);
        RETVAL = sen_rc2obj(sen_index_update(index, key, section, old_values, new_values));
    OUTPUT:
        RETVAL

SV *
SIndex_xs_query_exec(self, query, op = sen_sel_or)
        SV *self;
        SV *query;
        sen_sel_operator op;
    PREINIT:
        sen_index *i;
        sen_query *q;
        sen_records *r;
        sen_rc rc;
        SV *sv;
    CODE:
        i = XS_STATE(sen_index *, self);
        q = XS_STATE(sen_query *, query);

        Newz(1234, r, 1, sen_records);

        rc = sen_query_exec(i, q, r, op);
        if (rc != sen_success)
            croak("sen_query_exec failed: rc = %d", rc);

        XS_STRUCT2OBJ(sv, "Senna::Records", r);
        RETVAL = sv;
    OUTPUT:
        RETVAL

MODULE = Senna      PACKAGE = Senna::Records   PREFIX=SRecords_

SV *
SRecords_xs_open(class, record_unit, subrec_unit, max_n_subrecs)
        char *class;
        sen_rec_unit record_unit;
        sen_rec_unit subrec_unit;
        unsigned int max_n_subrecs;
    PREINIT:
        sen_records *r;
        SV *sv;
    CODE:
        r = sen_records_open(record_unit, subrec_unit, max_n_subrecs);
        if (r == NULL)
            croak("Failed to open sen_records");

        XS_STRUCT2OBJ(sv, class, r);
        RETVAL = sv;
    OUTPUT:
        RETVAL

void
SRecords_xs_next(self)
        SV *self;
    PREINIT:
        sen_records *r;
        sen_rc rc;
    PPCODE:
        r = XS_STATE(sen_records *, self);

        if (GIMME_V == G_SCALAR) {
            /* If we're being called in scalar context, then just return if
             * we have a next record or not
             */
            rc = sen_records_next(r, NULL, 0, NULL);
            XPUSHs(rc == 0 ? &PL_sv_no : &PL_sv_yes);
        } else {
            /* Otherwise, grab the next entry along with other metadata */
            SV *key_sv;
            int score = 0;
            int key_size = 0;
            int section = 0;
            int pos = 0;
            int n_subrecs = 0;

            sen_sym_info(r->keys, &key_size, NULL, NULL, NULL, NULL);

            if (key_size == SEN_INT_KEY) {
                long key;

                rc = sen_records_next(r, &key, 0, &score);
                sen_record_info(r, sen_records_curr_rec(r),
                    NULL, 0, NULL,
                    &section, &pos, NULL, &n_subrecs);
                key_sv = newSViv(key);
            } else {
                char key[SEN_MAX_KEY_SIZE];

                rc = sen_records_next(r, &key, SEN_MAX_KEY_SIZE, &score);
                sen_record_info(r, sen_records_curr_rec(r),
                    NULL, 0, NULL,
                    &section, &pos, NULL, &n_subrecs);
                key_sv = newSVpv(key, 0);
            }

            if (rc != 0) {
                XPUSHs(key_sv);
                XPUSHs(sv_2mortal(newSViv(score)));
                XPUSHs(sv_2mortal(newSViv(section)));
                XPUSHs(sv_2mortal(newSViv(pos)));
                XPUSHs(sv_2mortal(newSViv(n_subrecs)));
            }
        }

SV *
SRecords_rewind(self)
        SV *self;
    PREINIT:
        sen_records *r;
    CODE:
        r = XS_STATE(sen_records *, self);
        RETVAL = sen_rc2obj(sen_records_rewind(r));
    OUTPUT:
        RETVAL

int
SRecords_nhits(self)
        SV *self;

lib/Senna.xs  view on Meta::CPAN

        sen_id id;
        unsigned int value;
    PREINIT:
        sen_sym *sym;
    CODE:
        sym = XS_STATE(sen_sym *, self);
        RETVAL = sen_rc2obj(sen_sym_pocket_set(sym, id, value));
    OUTPUT:
        RETVAL

sen_id
SSymbol_xs_next(self, id)
        SV *self;
        sen_id id;
    PREINIT:
        sen_sym *sym;
    CODE:
        sym = XS_STATE(sen_sym *, self);
        RETVAL = sen_sym_next(sym, id);
    OUTPUT:
        RETVAL

MODULE = Senna      PACKAGE = Senna::Set   PREFIX=SSet_

SV *
SSet_xs_open(class, key_size = SEN_VARCHAR_KEY, value_size = 0, n_entries = 0)
        char *class;
        unsigned int key_size;
        unsigned int value_size;
        unsigned int n_entries;
    PREINIT:
        SV *sv;
        sen_set *set;
    CODE:
        set = sen_set_open(key_size, value_size, n_entries);
        XS_STRUCT2OBJ(sv, class, set);
        RETVAL = sv;
    OUTPUT:
        RETVAL

SV *
SSet_close(self)
        SV *self;
    PREINIT:
        sen_set *set;
    CODE:
        set = XS_STATE(sen_set *, self);
        RETVAL = sen_rc2obj(sen_set_close(set));
    OUTPUT:
        RETVAL

void
SSet_info(self)
        SV *self;
    PREINIT:
        sen_rc rc;
        sen_set *set;
        unsigned int key_size;
        unsigned int value_size;
        unsigned int n_entries;
    PPCODE:
        set = XS_STATE(sen_set *, self);
        rc = sen_set_info(set, &key_size, &value_size, &n_entries);
        if (rc != sen_success)
            croak ("Failed to call sen_set_info: %d", rc);

        EXTEND(SP, 3);
        PUSHs(sv_2mortal(newSViv(key_size)));
        PUSHs(sv_2mortal(newSViv(value_size)));
        PUSHs(sv_2mortal(newSViv(n_entries)));

MODULE = Senna      PACKAGE = Senna::Snippet   PREFIX=SSnip_

SV *
SSnip_xs_open(class, encoding, flags, width, max_results, default_open_tag_sv, default_close_tag_sv, mapping_sv)
        char*        class;
        sen_encoding encoding;
        int          flags;
        size_t       width;
        unsigned int max_results;
        SV*          default_open_tag_sv;
        SV*          default_close_tag_sv;
        SV*          mapping_sv;
    PREINIT:
        int mapping;
        sen_snip *snip;
        sen_perl_snip *perl_snip;
        char *default_open_tag = NULL;
        char *default_close_tag = NULL;
        STRLEN default_open_tag_len = 0;
        STRLEN default_close_tag_len = 0;
        SV *sv;
    CODE:
        if (max_results > MAX_SNIP_RESULT_COUNT) 
            croak("Senna::Snippet::new(): max_results exceeds MAX_SNIP_RESULT_COUNT (%d)", MAX_SNIP_RESULT_COUNT);

        if (SvPOK(default_open_tag_sv) && sv_len(default_open_tag_sv))
            default_open_tag = SvPV(default_open_tag_sv, default_open_tag_len);

        if (SvPOK(default_close_tag_sv) && sv_len(default_close_tag_sv))
            default_close_tag = SvPV(default_close_tag_sv, default_close_tag_len);

        mapping = SvTRUE(mapping_sv) ? -1 : 0;

        Newz(1234, perl_snip, 1, sen_perl_snip);

        if (default_open_tag == NULL)
            croak("Senna::Snippet::new(): default_open_tag must be specified");

        if (default_close_tag == NULL)
            croak("Senna::Snippet::new(): default_close_tag must be specified");


        perl_snip->open_tags_size = 1;
        Newz(1234, perl_snip->open_tags, 1, char *);
        Newz(1234, perl_snip->open_tags[perl_snip->open_tags_size - 1], default_open_tag_len + 1, char);
        Copy(default_open_tag, perl_snip->open_tags[perl_snip->open_tags_size - 1], default_open_tag_len, char);
        default_open_tag = perl_snip->open_tags[perl_snip->open_tags_size - 1];

        perl_snip->close_tags_size = 1;
        Newz(1234, perl_snip->close_tags, 1, char *);

lib/Senna.xs  view on Meta::CPAN

        sen_perl_snip *snip;
        STRLEN opentag_len = 0;
        STRLEN closetag_len = 0;
    CODE:
        snip = XS_STATE(sen_perl_snip *, self);

        if (SvPOK(opentag_sv) && sv_len(opentag_sv) > 0) {
            opentag = SvPV(opentag_sv, opentag_len);
            snip->open_tags_size++;
            Renew(snip->open_tags, snip->open_tags_size, char *);
            Newz(1234, snip->open_tags[snip->open_tags_size - 1], opentag_len + 1, char);
            Copy(opentag, snip->open_tags[snip->open_tags_size - 1], opentag_len, char);
            opentag = snip->open_tags[snip->open_tags_size - 1];
        }
            
        if (SvPOK(closetag_sv) && sv_len(closetag_sv) > 0) {
            closetag = SvPV(closetag_sv, closetag_len);
            snip->close_tags_size++;
            Renew(snip->close_tags, snip->close_tags_size, char *);
            Newz(1234, snip->close_tags[snip->close_tags_size - 1], closetag_len + 1, char);
            Copy(closetag, snip->close_tags[snip->close_tags_size - 1], closetag_len, char);
            closetag = snip->close_tags[snip->close_tags_size - 1];
        }
            
        RETVAL = sen_rc2obj(
            sen_snip_add_cond(
                snip->snip,
                keyword,
#if (SENNA_MAJOR_VERSION >= 1)
                strlen(keyword),
#endif
                opentag,
#if (SENNA_MAJOR_VERSION >= 1)
                opentag_len,
#endif
                closetag
#if (SENNA_MAJOR_VERSION >= 1)
                ,
                closetag_len
#endif
            )
        );
    OUTPUT:
        RETVAL

void
SSnip_xs_exec(self, string)
        SV *self;
        char *string;
    PREINIT:
        sen_perl_snip    *snip;
        unsigned int nresults;
        char        *result;
#if (SENNA_MAJOR_VERSION >= 1)
        unsigned int max_tagged_len;
#else
        size_t       max_tagged_len;
#endif
        int          i;
        sen_rc rc;
    PPCODE:
        snip = XS_STATE(sen_perl_snip *, self);
        sen_snip_exec(
            snip->snip,
            string,
#if (SENNA_MAJOR_VERSION >= 1)
            strlen(string),
#endif
            &nresults,
            &max_tagged_len
        );

        EXTEND(SP, nresults);
        Newz(1234, result, max_tagged_len, char);
        for(i = 0; i < nresults; i++) {
            rc = sen_snip_get_result(
                snip->snip,
                i,
                result
#if (SENNA_MAJOR_VERSION >= 1)
                ,
                &max_tagged_len
#endif
            );
            if (rc != sen_success) 
                croak("Call to sen_snip_get_result returned %d", rc);
            PUSHs(sv_2mortal(newSVpv(result, 0)));
        }
        Safefree(result);

void
DESTROY(self)
        SV *self;
    PREINIT:
        sen_perl_snip *snip;
        int i;
    PPCODE:
        snip = XS_STATE(sen_perl_snip *, self);
        sen_snip_close(snip->snip);

        for(i = 0; i < snip->open_tags_size; i++) {
            Safefree(snip->open_tags[i]);
        }
        Safefree(snip->open_tags);

        for(i = 0; i < snip->close_tags_size; i++) {
            Safefree(snip->close_tags[i]);
        }
        Safefree(snip->close_tags);

        


MODULE = Senna      PACKAGE = Senna::OptArg::Sort  PREFIX=SOSort_

SV *
SOSort_xs_new(class, mode, compar = NULL, compar_arg = NULL)
        char *class;
        sen_sort_mode mode;
        CV *compar;
        AV *compar_arg;
    PREINIT:
        sen_sort_optarg *optarg;
        SV *sv;
    CODE:
        Newz(1234, optarg, 1, sen_sort_optarg);
        optarg->mode = mode;

        if (SvOK(compar)) {
            optarg->compar = &sen_sort_optarg_cb;
        
            /* The callback arguments are always the CV of the callback,
             * the AV of the argument list, and key_size of the index.
             */
            Newz(1234, optarg->compar_arg, 2, void *);
            ((void **)optarg->compar_arg)[0] = compar;
            if (SvOK(compar_arg) && SvTYPE(compar_arg) == SVt_PVCV)
                ((void **)optarg->compar_arg)[1] = SvREFCNT_inc(compar_arg);
        }

        XS_STRUCT2OBJ(sv, class, optarg);
        RETVAL = sv;
    OUTPUT:
        RETVAL

sen_sort_mode
SOSort_mode(self)
        SV *self;
    PREINIT:
        sen_sort_optarg *optarg;
    CODE:
        optarg = XS_STATE(sen_sort_optarg *, self);
        RETVAL = optarg->mode;
    OUTPUT:
        RETVAL

CV *
SOSort_compar(self)
        SV *self;
    PREINIT:
        sen_sort_optarg *optarg;
        void **args;
    CODE:
        optarg = XS_STATE(sen_sort_optarg *, self);
        /* The CV is always placed in the first element of ->compar_arg */
        args = (void **) optarg->compar_arg;
        if (args[0] == NULL)
            XSRETURN_UNDEF;

        RETVAL = (CV *) args[0];
    OUTPUT:
        RETVAL

void
SOSort_compar_arg(self)
        SV *self;
    PREINIT:
        sen_sort_optarg *optarg;
        void **args;
    PPCODE:
        optarg = XS_STATE(sen_sort_optarg *, self);
        /* The CV is always placed in the second element of ->func_arg */
        args = (void **) optarg->compar_arg;
        if (GIMME_V == G_SCALAR) {
            AV *av;
            if (args[1] == NULL)
                return;

            av = (AV *) args[1];
            EXTEND(SP, 1);
            PUSHs(newRV_noinc((SV *) av));
        } else {
            AV *av;
            int i;
            int len;
            SV **svr;

            av = (AV *) args[1];
            len = av_len(av) + 1;
            if (len <= 0)
                return;

            EXTEND(SP, len);
            for (i = 0; i < len; i++) {
                svr = av_fetch(av, i - 1, 0);
                if (*svr != NULL && SvOK(*svr)) {
                    PUSHs(*svr);
                }
            }
        }

void
SOSort_DESTROY(self)
        SV *self;
    PREINIT:
        sen_sort_optarg *optarg;
    CODE:
        optarg = XS_STATE(sen_sort_optarg *, self);
        if (optarg->compar_arg != NULL) {
            void **args = (void **) optarg->compar_arg;

            if (args[0] != NULL)
                SvREFCNT_dec((CV *) args[0]);

            if (args[1] != NULL)
                SvREFCNT_dec((AV *) args[1]);

            Safefree(args);
        }

        Safefree(optarg);

MODULE = Senna      PACKAGE = Senna::OptArg::Select  PREFIX=SOSelect_

SV *
SOSelect_xs_new(class, mode, similarity_threshold, max_interval, weight_vector, func = NULL, func_args = NULL)
        char *class;
        sen_sel_mode mode;
        int          similarity_threshold;
        int          max_interval;

lib/Senna.xs  view on Meta::CPAN

        if (SvOK(func)) {
            int key_size;
            void **args;

            optarg->func = &sen_select_optarg_cb;

            /* The callback arguments are always the CV of the callback,
             * the AV of the argument list, and key_size of the index.
             */
            Newz(1234, args, 2, void *);
            args[0] = (void *) func;
            if (SvOK(func_args))
                args[1] = (void *) func_args;
            optarg->func_arg = (void *) args;
        }

        XS_STRUCT2OBJ(sv, class, optarg);
        RETVAL = sv;

    OUTPUT:
        RETVAL

sen_sel_mode
SOSelect_mode(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
    CODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        RETVAL = optarg->mode;
    OUTPUT:
        RETVAL

int
SOSelect_similarity_threshold(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
    CODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        RETVAL = optarg->similarity_threshold;
    OUTPUT:
        RETVAL

int
SOSelect_max_interval(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
    CODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        RETVAL = optarg->max_interval;
    OUTPUT:
        RETVAL

void
SOSelect_weight_vector(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
    PPCODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        if (optarg->vector_size <= 0)
            return;

        if (GIMME_V == G_SCALAR) {
            AV *av = newAV();
            int i;

            EXTEND(SP, 1);
            av_extend(av, optarg->vector_size - 1);
            for (i = 0; i < optarg->vector_size; i++) {
                av_push(av, newSViv(optarg->weight_vector[i]));
            }
            PUSHs(newRV_inc((SV *) av));
        } else {
            int i;

            EXTEND(SP, optarg->vector_size);
            for (i = 0; i < optarg->vector_size; i++) {
                PUSHs(newSViv(optarg->weight_vector[i]));
            }
        }

CV *
SOSelect_func(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
        void **args;
    CODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        /* The CV is always placed in the first element of ->func_arg */
        args = (void **) optarg->func_arg;
        if (args[0] == NULL)
            XSRETURN_UNDEF;

        RETVAL = (CV *) args[0];
    OUTPUT:
        RETVAL

void
SOSelect_func_arg(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
        void **args;
    PPCODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        /* The CV is always placed in the second element of ->func_arg */
        args = (void **) optarg->func_arg;
        if (GIMME_V == G_SCALAR) {
            AV *av;
            if (args[1] == NULL)
                return;

            av = (AV *) args[1];
            EXTEND(SP, 1);
            PUSHs(newRV_noinc((SV *) av));
        } else {
            AV *av;
            int i;
            int len;
            SV **svr;

            av = (AV *) args[1];
            len = av_len(av) + 1;
            if (len <= 0)
                return;

            EXTEND(SP, len);
            for (i = 0; i < len; i++) {
                svr = av_fetch(av, i - 1, 0);
                if (*svr != NULL && SvOK(*svr)) {
                    PUSHs(*svr);
                }
            }
        }

SV *
SOSelect_DESTROY(self)
        SV *self;
    PREINIT:
        sen_select_optarg *optarg;
    CODE:
        optarg = XS_STATE(sen_select_optarg *, self);
        if (optarg->weight_vector != NULL)
            Safefree(optarg->weight_vector);

        if (optarg->func_arg != NULL) {
            void **args = (void **) optarg->func_arg;
            if (args[0] != NULL)
                SvREFCNT_dec((CV *) args[0]);

            if (args[1] != NULL)
                SvREFCNT_dec((AV *) args[1]);

            Safefree(optarg->func_arg);
        }

        Safefree(optarg);

MODULE = Senna    PACKAGE = Senna::Values    PREFIX=SValues_

SV *
SValues_open(class)
        char *class;
    PREINIT:



( run in 1.410 second using v1.01-cache-2.11-cpan-5511b514fd6 )