#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
/* for 5.6.1 */
/* #define NEED_sv_2pvbyte */
#define NEED_sv_2pv_flags
#include "ppport.h"
#include "depot.h"
#include "curia.h"
#include "cabin.h"
#include "villa.h"
#include "vista_xs.h"
#include "odeum.h"
/*
The DBM_setFilter & DBM_ckFilter macros are only used by
the *DB*_File modules
Imported from XSUB.h for older XS
*/
#ifndef DBM_setFilter
#define DBM_setFilter(db_type, code) \
STMT_START { \
if (db_type) \
RETVAL = sv_mortalcopy(db_type); \
ST(0) = RETVAL; \
if ( db_type && (code == &PL_sv_undef) ) { \
SvREFCNT_dec(db_type); \
db_type = NULL; \
} \
else if (code) { \
if (db_type) { \
sv_setsv(db_type, code); \
} \
else { \
db_type = newSVsv(code); \
} \
} \
} STMT_END
#endif
#ifndef DBM_ckFilter
#define DBM_ckFilter(arg, type, name) \
STMT_START { \
if (db->type) { \
if (db->filtering) { \
croak("recursion detected in %s", name); \
} \
ENTER; \
SAVETMPS; \
SAVEINT(db->filtering); \
db->filtering = TRUE; \
SAVESPTR(DEFSV); \
if (name[7] == 's') { \
arg = newSVsv(arg); \
} \
DEFSV = arg; \
SvTEMP_off(arg); \
PUSHMARK(SP); \
PUTBACK; \
(void)call_sv(db->type, G_DISCARD); \
SPAGAIN; \
PUTBACK; \
FREETMPS; \
LEAVE; \
if (name[7] == 's') { \
arg = sv_2mortal(arg); \
} \
} \
} STMT_END
#endif
typedef struct {
void* dbp;
SV* comparer; /* subroutine reference */
SV* filter_fetch_key;
SV* filter_store_key;
SV* filter_fetch_value;
SV* filter_store_value;
int filtering;
} QDBM_File_type;
typedef QDBM_File_type* QDBM_File;
typedef SV* datum_key;
typedef SV* datum_value;
#define dpptr(db) ( (DEPOT*)db->dbp )
#define crptr(db) ( (CURIA*)db->dbp )
#define vlptr(db) ( (VILLA*)db->dbp )
#define vstptr(db) ( (VISTA*)db->dbp )
/* define static data for btree comparer */
#define MY_CXT_KEY "QDBM_File::_guts" XS_VERSION
typedef struct {
SV* comparer;
} my_cxt_t;
START_MY_CXT
#define DEF_QDBM_STORE(FUNCNAME, PUTFUNC, DBPTR) \
static int FUNCNAME(QDBM_File db, datum_key key, datum_value value, int dmode); \
static int FUNCNAME(QDBM_File db, datum_key key, datum_value value, int dmode) { \
STRLEN ksize; \
STRLEN vsize; \
const char* kbyte; \
const char* vbyte; \
kbyte = SvPV_const(key, ksize); \
vbyte = SvPV_const(value, vsize); \
return PUTFUNC( DBPTR(db), kbyte, (int)ksize, vbyte, (int)vsize, dmode ); \
}
DEF_QDBM_STORE(store_dp, dpput, dpptr)
DEF_QDBM_STORE(store_cr, crput, crptr)
DEF_QDBM_STORE(store_crlob, crputlob, crptr)
DEF_QDBM_STORE(store_vl, vlput, vlptr)
DEF_QDBM_STORE(store_vst, vstput, vstptr)
#undef DEF_QDBM_STORE_FUNC
static int btree_compare(const char* key_a, int ksize_a, const char* key_b, int ksize_b);
static int btree_compare(const char* key_a, int ksize_a, const char* key_b, int ksize_b) {
int count;
int retval;
dSP;
dMY_CXT;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal( newSVpvn(key_a, (STRLEN)ksize_a) ) );
XPUSHs( sv_2mortal( newSVpvn(key_b, (STRLEN)ksize_b) ) );
PUTBACK;
count = call_sv(MY_CXT.comparer, G_SCALAR);
SPAGAIN;
if (1 != count) {
croak("qdbm compare error: subroutine returned %d values, expected 1\n", count);
}
retval = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return retval;
}
MODULE = QDBM_File PACKAGE = QDBM_File
BOOT:
{
MY_CXT_INIT;
MY_CXT.comparer = &PL_sv_undef;
}
INCLUDE: dbm_filter.xsh
QDBM_File
TIEHASH(char* dbtype, char* filename, int flags = O_CREAT|O_RDWR, int mode = 0644, int buckets = -1)
ALIAS:
new = 1
PREINIT:
DEPOT* dbp;
int o_flags;
CODE:
RETVAL = NULL;
o_flags = ( (flags & O_WRONLY) || (flags & O_RDWR) ) ? DP_OWRITER : DP_OREADER;
if (flags & O_CREAT) o_flags |= DP_OCREAT;
if (flags & O_TRUNC) o_flags |= DP_OTRUNC;
dbp = dpopen(filename, o_flags, buckets);
if (NULL != dbp) {
Newxz(RETVAL, 1, QDBM_File_type);
RETVAL->dbp = (void*)dbp;
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
void
DESTROY(QDBM_File db)
CODE:
if (db) {
if ( dpclose( dpptr(db) ) ) {
if (db->comparer) SvREFCNT_dec(db->comparer);
if (db->filter_fetch_key) SvREFCNT_dec(db->filter_fetch_key);
if (db->filter_store_key) SvREFCNT_dec(db->filter_store_key);
if (db->filter_fetch_value) SvREFCNT_dec(db->filter_fetch_value);
if (db->filter_store_value) SvREFCNT_dec(db->filter_store_value);
Safefree(db);
}
else {
croak( "qdbm close error: %s\n", dperrmsg(dpecode) );
}
}
datum_value
FETCH(QDBM_File db, datum_key key, int start = 0, int offset = -1)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
char* value;
CODE:
kbyte = SvPV_const(key, ksize);
value = dpget( dpptr(db), kbyte, (int)ksize, start, offset, &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
STORE(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_dp(db, key, value, DP_DOVER);
OUTPUT:
RETVAL
bool
store_keep(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_dp(db, key, value, DP_DKEEP);
OUTPUT:
RETVAL
bool
store_cat(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_dp(db, key, value, DP_DCAT);
OUTPUT:
RETVAL
bool
DELETE(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
CODE:
kbyte = SvPV_const(key, ksize);
RETVAL = dpout( dpptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
EXISTS(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
CODE:
kbyte = SvPV_const(key, ksize);
vsize = dpvsiz( dpptr(db), kbyte, (int)ksize );
RETVAL = (-1 != vsize);
OUTPUT:
RETVAL
datum_key
FIRSTKEY(QDBM_File db)
PREINIT:
int ksize;
char* key;
CODE:
if ( dpiterinit( dpptr(db) ) ) {
key = dpiternext( dpptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
datum_key
NEXTKEY(QDBM_File db, datum_key prev_key)
PREINIT:
int ksize;
char* key;
CODE:
key = dpiternext( dpptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
set_align(QDBM_File db, int align)
CODE:
RETVAL = dpsetalign( dpptr(db), align );
OUTPUT:
RETVAL
bool
set_fbp_size(QDBM_File db, int size)
CODE:
RETVAL = dpsetfbpsiz( dpptr(db), size );
OUTPUT:
RETVAL
bool
sync(QDBM_File db)
CODE:
RETVAL = dpsync( dpptr(db) );
OUTPUT:
RETVAL
bool
optimize(QDBM_File db, int buckets = -1)
CODE:
RETVAL = dpoptimize( dpptr(db), buckets );
OUTPUT:
RETVAL
int
get_record_size(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
CODE:
kbyte = SvPV_const(key, ksize);
RETVAL = dpvsiz( dpptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
init_iterator(QDBM_File db)
CODE:
RETVAL = dpiterinit( dpptr(db) );
OUTPUT:
RETVAL
SV*
get_name(QDBM_File db)
PREINIT:
char* name;
CODE:
name = dpname( dpptr(db) );
if (NULL != name) {
RETVAL = newSVpv(name, 0);
cbfree(name);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_size(QDBM_File db)
CODE:
RETVAL = dpfsiz( dpptr(db) );
OUTPUT:
RETVAL
int
count_buckets(QDBM_File db)
CODE:
RETVAL = dpbnum( dpptr(db) );
OUTPUT:
RETVAL
int
count_used_buckets(QDBM_File db)
CODE:
RETVAL = dpbusenum( dpptr(db) );
OUTPUT:
RETVAL
int
count_records(QDBM_File db)
ALIAS:
SCALAR = 1
CODE:
RETVAL = dprnum( dpptr(db) );
OUTPUT:
RETVAL
bool
is_writable(QDBM_File db)
CODE:
RETVAL = dpwritable( dpptr(db) );
OUTPUT:
RETVAL
bool
is_fatal_error(QDBM_File db)
CODE:
RETVAL = dpfatalerror( dpptr(db) );
OUTPUT:
RETVAL
const char*
get_error(SV* package)
CODE:
RETVAL = dperrmsg(dpecode);
OUTPUT:
RETVAL
time_t
get_mtime(QDBM_File db)
CODE:
RETVAL = dpmtime( dpptr(db) );
OUTPUT:
RETVAL
bool
repair(SV* package, char* filename)
CODE:
if ( sv_isobject(package) ) {
warn("qdbm repair warning: called via instance method\n");
}
RETVAL = dprepair(filename);
OUTPUT:
RETVAL
bool
export_db(QDBM_File db, char* filename)
CODE:
RETVAL = dpexportdb( dpptr(db), filename );
OUTPUT:
RETVAL
bool
import_db(QDBM_File db, char* filename)
CODE:
RETVAL = dpimportdb( dpptr(db), filename );
OUTPUT:
RETVAL
MODULE = QDBM_File PACKAGE = QDBM_File::Multiple
INCLUDE: dbm_filter.xsh
QDBM_File
TIEHASH(char* dbtype, char* filename, int flags = O_CREAT|O_RDWR, int mode = 0644, int buckets = -1, int directories = -1)
ALIAS:
new = 1
PREINIT:
CURIA* dbp;
int o_flags;
CODE:
RETVAL = NULL;
o_flags = ( (flags & O_WRONLY) || (flags & O_RDWR) ) ? CR_OWRITER : CR_OREADER;
if (flags & O_CREAT) o_flags |= CR_OCREAT;
if (flags & O_TRUNC) o_flags |= CR_OTRUNC;
dbp = cropen(filename, o_flags, buckets, directories);
if (NULL != dbp) {
Newxz(RETVAL, 1, QDBM_File_type);
RETVAL->dbp = (void*)dbp;
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
void
DESTROY(QDBM_File db)
CODE:
if (db) {
if ( crclose( crptr(db) ) ) {
if (db->comparer) SvREFCNT_dec(db->comparer);
if (db->filter_fetch_key) SvREFCNT_dec(db->filter_fetch_key);
if (db->filter_store_key) SvREFCNT_dec(db->filter_store_key);
if (db->filter_fetch_value) SvREFCNT_dec(db->filter_fetch_value);
if (db->filter_store_value) SvREFCNT_dec(db->filter_store_value);
Safefree(db);
}
else {
croak( "qdbm close error: %s\n", dperrmsg(dpecode) );
}
}
datum_value
FETCH(QDBM_File db, datum_key key, int start = 0, int offset = -1)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
char* value;
CODE:
kbyte = SvPV_const(key, ksize);
value = crget( crptr(db), kbyte, (int)ksize, start, offset, &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
STORE(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_cr(db, key, value, CR_DOVER);
OUTPUT:
RETVAL
bool
store_keep(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_cr(db, key, value, CR_DKEEP);
OUTPUT:
RETVAL
bool
store_cat(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_cr(db, key, value, CR_DCAT);
OUTPUT:
RETVAL
bool
DELETE(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
CODE:
kbyte = SvPV_const(key, ksize);
RETVAL = crout( crptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
EXISTS(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
CODE:
kbyte = SvPV_const(key, ksize);
vsize = crvsiz( crptr(db), kbyte, (int)ksize );
RETVAL = (-1 != vsize);
OUTPUT:
RETVAL
datum_key
FIRSTKEY(QDBM_File db)
PREINIT:
int ksize;
char* key;
CODE:
if ( criterinit( crptr(db) ) ) {
key = criternext( crptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
datum_key
NEXTKEY(QDBM_File db, datum_key prev_key)
PREINIT:
int ksize;
char* key;
CODE:
key = criternext( crptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
set_align(QDBM_File db, int align)
CODE:
RETVAL = crsetalign( crptr(db), align );
OUTPUT:
RETVAL
bool
set_fbp_size(QDBM_File db, int size)
CODE:
RETVAL = crsetfbpsiz( crptr(db), size);
OUTPUT:
RETVAL
bool
sync(QDBM_File db)
CODE:
RETVAL = crsync( crptr(db) );
OUTPUT:
RETVAL
bool
optimize(QDBM_File db, int buckets = -1)
CODE:
RETVAL = croptimize( crptr(db), buckets );
OUTPUT:
RETVAL
int
get_record_size(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
CODE:
kbyte = SvPV_const(key, ksize);
RETVAL = crvsiz( crptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
init_iterator(QDBM_File db)
CODE:
RETVAL = criterinit( crptr(db) );
OUTPUT:
RETVAL
SV*
get_name(QDBM_File db)
PREINIT:
char* name;
CODE:
name = crname( crptr(db) );
if (NULL != name) {
RETVAL = newSVpv(name, 0);
cbfree(name);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_size(QDBM_File db)
CODE:
RETVAL = crfsiz( crptr(db) );
OUTPUT:
RETVAL
int
count_buckets(QDBM_File db)
CODE:
RETVAL = crbnum( crptr(db) );
OUTPUT:
RETVAL
int
count_used_buckets(QDBM_File db)
CODE:
RETVAL = crbusenum( crptr(db) );
OUTPUT:
RETVAL
int
count_records(QDBM_File db)
ALIAS:
SCALAR = 1
CODE:
RETVAL = crrnum( crptr(db) );
OUTPUT:
RETVAL
bool
is_writable(QDBM_File db)
CODE:
RETVAL = crwritable( crptr(db) );
OUTPUT:
RETVAL
bool
is_fatal_error(QDBM_File db)
CODE:
RETVAL = crfatalerror( crptr(db) );
OUTPUT:
RETVAL
const char*
get_error(SV* package)
CODE:
RETVAL = dperrmsg(dpecode);
OUTPUT:
RETVAL
time_t
get_mtime(QDBM_File db)
CODE:
RETVAL = crmtime( crptr(db) );
OUTPUT:
RETVAL
bool
repair(SV* package, char* filename)
CODE:
if ( sv_isobject(package) ) {
warn("qdbm repair warning: called via instance method\n");
}
RETVAL = crrepair(filename);
OUTPUT:
RETVAL
bool
export_db(QDBM_File db, char* filename)
CODE:
RETVAL = crexportdb( crptr(db), filename );
OUTPUT:
RETVAL
bool
import_db(QDBM_File db, char* filename)
CODE:
RETVAL = crimportdb( crptr(db), filename );
OUTPUT:
RETVAL
datum_value
fetch_lob(QDBM_File db, datum_key key, int start = 0, int offset = -1)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
char* value;
CODE:
kbyte = SvPV_const(key, ksize);
value = crgetlob( crptr(db), kbyte, (int)ksize, start, offset, &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
store_lob(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_crlob(db, key, value, CR_DOVER);
OUTPUT:
RETVAL
bool
store_keep_lob(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_crlob(db, key, value, CR_DKEEP);
OUTPUT:
RETVAL
bool
store_cat_lob(QDBM_File db, datum_key key, datum_value value)
CODE:
RETVAL = store_crlob(db, key, value, CR_DCAT);
OUTPUT:
RETVAL
bool
delete_lob(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
CODE:
kbyte = SvPV_const(key, ksize);
RETVAL = croutlob( crptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
exists_lob(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
CODE:
kbyte = SvPV_const(key, ksize);
vsize = crvsizlob( crptr(db), kbyte, (int)ksize );
RETVAL = (-1 != vsize);
OUTPUT:
RETVAL
int
count_lob_records(QDBM_File db)
CODE:
RETVAL = crrnumlob( crptr(db) );
OUTPUT:
RETVAL
MODULE = QDBM_File PACKAGE = QDBM_File::BTree
INCLUDE: dbm_filter.xsh
QDBM_File
TIEHASH(char* dbtype, char* filename, int flags = O_CREAT|O_RDWR, int mode = 0644, SV* comparer = &PL_sv_undef)
ALIAS:
new = 1
PREINIT:
VILLA* dbp;
int o_flags;
VLCFUNC cmpptr;
CODE:
RETVAL = NULL;
cmpptr = SvOK(comparer) ? btree_compare : VL_CMPLEX;
o_flags = ( (flags & O_WRONLY) || (flags & O_RDWR) ) ? VL_OWRITER : VL_OREADER;
if (flags & O_CREAT) o_flags |= VL_OCREAT;
if (flags & O_TRUNC) o_flags |= VL_OTRUNC;
dbp = vlopen(filename, o_flags, cmpptr);
if (NULL != dbp) {
Newxz(RETVAL, 1, QDBM_File_type);
RETVAL->dbp = (void*)dbp;
RETVAL->comparer = newSVsv(comparer);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
void
DESTROY(QDBM_File db)
CODE:
if (db) {
if ( vlclose( vlptr(db) ) ) {
if (db->comparer) SvREFCNT_dec(db->comparer);
if (db->filter_fetch_key) SvREFCNT_dec(db->filter_fetch_key);
if (db->filter_store_key) SvREFCNT_dec(db->filter_store_key);
if (db->filter_fetch_value) SvREFCNT_dec(db->filter_fetch_value);
if (db->filter_store_value) SvREFCNT_dec(db->filter_store_value);
Safefree(db);
}
else {
croak( "qdbm close error: %s\n", dperrmsg(dpecode) );
}
}
datum_value
FETCH(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
char* value;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
value = vlget( vlptr(db), kbyte, (int)ksize, &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
STORE(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vl(db, key, value, VL_DOVER);
OUTPUT:
RETVAL
bool
store_keep(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vl(db, key, value, VL_DKEEP);
OUTPUT:
RETVAL
bool
store_cat(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vl(db, key, value, VL_DCAT);
OUTPUT:
RETVAL
bool
store_dup(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vl(db, key, value, VL_DDUP);
OUTPUT:
RETVAL
bool
store_dupr(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vl(db, key, value, VL_DDUPR);
OUTPUT:
RETVAL
bool
DELETE(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vlout( vlptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
EXISTS(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
vsize = vlvsiz( vlptr(db), kbyte, (int)ksize );
RETVAL = (-1 != vsize);
OUTPUT:
RETVAL
datum_key
FIRSTKEY(QDBM_File db)
PREINIT:
int ksize;
char* key;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
if ( vlcurfirst( vlptr(db) ) ) {
key = vlcurkey( vlptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
datum_key
NEXTKEY(QDBM_File db, datum_key prev_key)
PREINIT:
int ksize;
char* key;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
if ( vlcurnext( vlptr(db) ) ) {
key = vlcurkey( vlptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_record_size(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vlvsiz( vlptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
int
count_match_records(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vlvnum( vlptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
delete_list(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vloutlist( vlptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
void
fetch_list(QDBM_File db, datum_key key)
PREINIT:
int i;
STRLEN ksize;
const char* kbyte;
int vsize;
const char* value;
CBLIST* list;
SV* value_sv;
dMY_CXT;
PPCODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
list = vlgetlist( vlptr(db), kbyte, (int)ksize );
if (NULL != list) {
for (i = 0; i < cblistnum(list); i++) {
value = cblistval(list, i, &vsize);
value_sv = newSVpvn(value, (STRLEN)vsize);
DBM_ckFilter(value_sv, filter_fetch_value, "filter_fetch_value");
XPUSHs( sv_2mortal(value_sv) );
}
cblistclose(list);
}
else {
XSRETURN_EMPTY;
}
bool
store_list(QDBM_File db, datum_key key, ...)
PREINIT:
int i;
STRLEN ksize;
const char* kbyte;
STRLEN vsize;
const char* vbyte;
CBLIST* list;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
list = cblistopen();
for (i = 2; i < items; i++) {
DBM_ckFilter( ST(i), filter_store_value, "filter_store_value" );
SvGETMAGIC( ST(i) );
sv_utf8_downgrade( ST(i), 0 );
vbyte = SvPV_const( ST(i), vsize );
cblistpush(list, vbyte, (int)vsize);
}
kbyte = SvPV_const(key, ksize);
RETVAL = vlputlist( vlptr(db), kbyte, (int)ksize, list );
OUTPUT:
RETVAL
CLEANUP:
cblistclose(list);
bool
init_iterator(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlcurfirst( vlptr(db) );
OUTPUT:
RETVAL
bool
move_first(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlcurfirst( vlptr(db) );
OUTPUT:
RETVAL
bool
move_last(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlcurlast( vlptr(db) );
OUTPUT:
RETVAL
bool
move_next(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlcurnext( vlptr(db) );
OUTPUT:
RETVAL
bool
move_prev(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlcurprev( vlptr(db) );
OUTPUT:
RETVAL
bool
move_forward(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vlcurjump( vlptr(db), kbyte, (int)ksize, VL_JFORWARD );
OUTPUT:
RETVAL
bool
move_backword(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vlcurjump( vlptr(db), kbyte, (int)ksize, VL_JBACKWARD );
OUTPUT:
RETVAL
datum_key
get_current_key(QDBM_File db)
PREINIT:
int ksize;
char* key;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
key = vlcurkey( vlptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
datum_key
get_current_value(QDBM_File db)
PREINIT:
int vsize;
char* value;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
value = vlcurval( vlptr(db), &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
store_current(QDBM_File db, datum_value value)
PREINIT:
STRLEN vsize;
const char* vbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
vbyte = SvPV_const(value, vsize);
RETVAL = vlcurput(
vlptr(db),
vbyte,
(int)vsize,
VL_CPCURRENT
);
OUTPUT:
RETVAL
bool
store_after(QDBM_File db, datum_value value)
PREINIT:
STRLEN vsize;
const char* vbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
vbyte = SvPV_const(value, vsize);
RETVAL = vlcurput(
vlptr(db),
vbyte,
(int)vsize,
VL_CPAFTER
);
OUTPUT:
RETVAL
bool
store_before(QDBM_File db, datum_value value)
PREINIT:
STRLEN vsize;
const char* vbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
vbyte = SvPV_const(value, vsize);
RETVAL = vlcurput(
vlptr(db),
vbyte,
(int)vsize,
VL_CPBEFORE
);
OUTPUT:
RETVAL
bool
delete_current(QDBM_File db, datum_key key)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlcurout( vlptr(db) );
OUTPUT:
RETVAL
void
set_tuning(QDBM_File db, int max_leaf_record, int max_non_leaf_index, int max_cache_leaf, int max_cache_non_leaf)
CODE:
vlsettuning( vlptr(db), max_leaf_record, max_non_leaf_index, max_cache_leaf, max_cache_non_leaf );
bool
set_fbp_size(QDBM_File db, int size)
CODE:
RETVAL = vlsetfbpsiz( vlptr(db), size );
OUTPUT:
RETVAL
bool
sync(QDBM_File db)
CODE:
RETVAL = vlsync( vlptr(db) );
OUTPUT:
RETVAL
bool
optimize(QDBM_File db)
CODE:
RETVAL = vloptimize( vlptr(db) );
OUTPUT:
RETVAL
SV*
get_name(QDBM_File db)
PREINIT:
char* name;
CODE:
name = vlname( vlptr(db) );
if (NULL != name) {
RETVAL = newSVpv(name, 0);
cbfree(name);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_size(QDBM_File db)
CODE:
RETVAL = vlfsiz( vlptr(db) );
OUTPUT:
RETVAL
int
count_leafs(QDBM_File db)
CODE:
RETVAL = vllnum( vlptr(db) );
OUTPUT:
RETVAL
int
count_non_leafs(QDBM_File db)
CODE:
RETVAL = vlnnum( vlptr(db) );
OUTPUT:
RETVAL
int
count_records(QDBM_File db)
ALIAS:
SCALAR = 1
CODE:
RETVAL = vlrnum( vlptr(db) );
OUTPUT:
RETVAL
bool
is_writable(QDBM_File db)
CODE:
RETVAL = vlwritable( vlptr(db) );
OUTPUT:
RETVAL
bool
is_fatal_error(QDBM_File db)
CODE:
RETVAL = vlfatalerror( vlptr(db) );
OUTPUT:
RETVAL
const char*
get_error(SV* package)
CODE:
RETVAL = dperrmsg(dpecode);
OUTPUT:
RETVAL
time_t
get_mtime(QDBM_File db)
CODE:
RETVAL = vlmtime( vlptr(db) );
OUTPUT:
RETVAL
bool
begin_transaction(QDBM_File db)
CODE:
RETVAL = vltranbegin( vlptr(db) );
OUTPUT:
RETVAL
bool
commit(QDBM_File db)
CODE:
RETVAL = vltrancommit( vlptr(db) );
OUTPUT:
RETVAL
bool
rollback(QDBM_File db)
CODE:
RETVAL = vltranabort( vlptr(db) );
OUTPUT:
RETVAL
bool
repair(SV* package, char* filename, SV* comparer = &PL_sv_undef)
PREINIT:
VLCFUNC cmpptr;
dMY_CXT;
CODE:
cmpptr = SvOK(comparer) ? btree_compare : VL_CMPLEX;
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = comparer;
if ( sv_isobject(package) ) {
warn("qdbm repair warning: called via instance method\n");
}
RETVAL = vlrepair(filename, cmpptr);
OUTPUT:
RETVAL
bool
export_db(QDBM_File db, char* filename)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlexportdb( vlptr(db), filename );
OUTPUT:
RETVAL
bool
import_db(QDBM_File db, char* filename)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vlimportdb( vlptr(db), filename );
OUTPUT:
RETVAL
MODULE = QDBM_File PACKAGE = QDBM_File::BTree::Multiple
INCLUDE: dbm_filter.xsh
QDBM_File
TIEHASH(char* dbtype, char* filename, int flags = O_CREAT|O_RDWR, int mode = 0644, SV* comparer = &PL_sv_undef)
ALIAS:
new = 1
PREINIT:
VISTA* dbp;
int o_flags;
VSTCFUNC cmpptr;
CODE:
RETVAL = NULL;
cmpptr = SvOK(comparer) ? btree_compare : VST_CMPLEX;
o_flags = ( (flags & O_WRONLY) || (flags & O_RDWR) ) ? VST_OWRITER : VST_OREADER;
if (flags & O_CREAT) o_flags |= VST_OCREAT;
if (flags & O_TRUNC) o_flags |= VST_OTRUNC;
dbp = vstopen(filename, o_flags, cmpptr);
if (NULL != dbp) {
Newxz(RETVAL, 1, QDBM_File_type);
RETVAL->dbp = (void*)dbp;
RETVAL->comparer = newSVsv(comparer);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
void
DESTROY(QDBM_File db)
CODE:
if (db) {
if ( vstclose( vstptr(db) ) ) {
if (db->comparer) SvREFCNT_dec(db->comparer);
if (db->filter_fetch_key) SvREFCNT_dec(db->filter_fetch_key);
if (db->filter_store_key) SvREFCNT_dec(db->filter_store_key);
if (db->filter_fetch_value) SvREFCNT_dec(db->filter_fetch_value);
if (db->filter_store_value) SvREFCNT_dec(db->filter_store_value);
Safefree(db);
}
else {
croak( "qdbm close error: %s\n", dperrmsg(dpecode) );
}
}
datum_value
FETCH(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
char* value;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
value = vstget( vstptr(db), kbyte, (int)ksize, &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
STORE(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vst(db, key, value, VST_DOVER);
OUTPUT:
RETVAL
bool
store_keep(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vst(db, key, value, VST_DKEEP);
OUTPUT:
RETVAL
bool
store_cat(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vst(db, key, value, VST_DCAT);
OUTPUT:
RETVAL
bool
store_dup(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vst(db, key, value, VST_DDUP);
OUTPUT:
RETVAL
bool
store_dupr(QDBM_File db, datum_key key, datum_value value)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = store_vst(db, key, value, VST_DDUPR);
OUTPUT:
RETVAL
bool
DELETE(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vstout( vstptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
EXISTS(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
int vsize;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
vsize = vstvsiz( vstptr(db), kbyte, (int)ksize );
RETVAL = (-1 != vsize);
OUTPUT:
RETVAL
datum_key
FIRSTKEY(QDBM_File db)
PREINIT:
int ksize;
char* key;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
if ( vstcurfirst( vstptr(db) ) ) {
key = vstcurkey( vstptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
datum_key
NEXTKEY(QDBM_File db, datum_key prev_key)
PREINIT:
int ksize;
char* key;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
if ( vstcurnext( vstptr(db) ) ) {
key = vstcurkey( vstptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_record_size(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vstvsiz( vstptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
int
count_match_records(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vstvnum( vstptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
bool
delete_list(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vstoutlist( vstptr(db), kbyte, (int)ksize );
OUTPUT:
RETVAL
void
fetch_list(QDBM_File db, datum_key key)
PREINIT:
int i;
STRLEN ksize;
const char* kbyte;
int vsize;
const char* value;
CBLIST* list;
SV* value_sv;
dMY_CXT;
PPCODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
list = vstgetlist( vstptr(db), kbyte, (int)ksize );
if (NULL != list) {
for (i = 0; i < cblistnum(list); i++) {
value = cblistval(list, i, &vsize);
value_sv = newSVpvn(value, (STRLEN)vsize);
DBM_ckFilter(value_sv, filter_fetch_value, "filter_fetch_value");
XPUSHs( sv_2mortal(value_sv) );
}
cblistclose(list);
}
else {
XSRETURN_EMPTY;
}
bool
store_list(QDBM_File db, datum_key key, ...)
PREINIT:
int i;
STRLEN ksize;
const char* kbyte;
STRLEN vsize;
const char* vbyte;
CBLIST* list;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
list = cblistopen();
for (i = 2; i < items; i++) {
DBM_ckFilter( ST(i), filter_store_value, "filter_store_value" );
SvGETMAGIC( ST(i) );
sv_utf8_downgrade( ST(i), 0 );
vbyte = SvPV_const( ST(i), vsize );
cblistpush(list, vbyte, (int)vsize);
}
kbyte = SvPV_const(key, ksize);
RETVAL = vstputlist( vstptr(db), kbyte, (int)ksize, list );
OUTPUT:
RETVAL
CLEANUP:
cblistclose(list);
bool
init_iterator(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstcurfirst( vstptr(db) );
OUTPUT:
RETVAL
bool
move_first(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstcurfirst( vstptr(db) );
OUTPUT:
RETVAL
bool
move_last(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstcurlast( vstptr(db) );
OUTPUT:
RETVAL
bool
move_next(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstcurnext( vstptr(db) );
OUTPUT:
RETVAL
bool
move_prev(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstcurprev( vstptr(db) );
OUTPUT:
RETVAL
bool
move_forward(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vstcurjump( vstptr(db), kbyte, (int)ksize, VST_JFORWARD );
OUTPUT:
RETVAL
bool
move_backword(QDBM_File db, datum_key key)
PREINIT:
STRLEN ksize;
const char* kbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
kbyte = SvPV_const(key, ksize);
RETVAL = vstcurjump( vstptr(db), kbyte, (int)ksize, VST_JBACKWARD );
OUTPUT:
RETVAL
datum_key
get_current_key(QDBM_File db)
PREINIT:
int ksize;
char* key;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
key = vstcurkey( vstptr(db), &ksize );
if (NULL != key) {
RETVAL = newSVpvn(key, (STRLEN)ksize);
cbfree(key);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
datum_key
get_current_value(QDBM_File db)
PREINIT:
int vsize;
char* value;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
value = vstcurval( vstptr(db), &vsize );
if (NULL != value) {
RETVAL = newSVpvn(value, (STRLEN)vsize);
cbfree(value);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
store_current(QDBM_File db, datum_value value)
PREINIT:
STRLEN vsize;
const char* vbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
vbyte = SvPV_const(value, vsize);
RETVAL = vstcurput(
vstptr(db),
vbyte,
(int)vsize,
VL_CPCURRENT
);
OUTPUT:
RETVAL
bool
store_after(QDBM_File db, datum_value value)
PREINIT:
STRLEN vsize;
const char* vbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
vbyte = SvPV_const(value, vsize);
RETVAL = vstcurput(
vstptr(db),
vbyte,
(int)vsize,
VL_CPAFTER
);
OUTPUT:
RETVAL
bool
store_before(QDBM_File db, datum_value value)
PREINIT:
STRLEN vsize;
const char* vbyte;
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
vbyte = SvPV_const(value, vsize);
RETVAL = vstcurput(
vstptr(db),
vbyte,
(int)vsize,
VL_CPBEFORE
);
OUTPUT:
RETVAL
bool
delete_current(QDBM_File db)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstcurout( vstptr(db) );
OUTPUT:
RETVAL
void
set_tuning(QDBM_File db, int max_leaf_record, int max_non_leaf_index, int max_cache_leaf, int max_cache_non_leaf)
CODE:
vstsettuning( vstptr(db), max_leaf_record, max_non_leaf_index, max_cache_leaf, max_cache_non_leaf );
bool
set_fbp_size(QDBM_File db, int size)
CODE:
RETVAL = vstsetfbpsiz( vstptr(db), size );
OUTPUT:
RETVAL
bool
sync(QDBM_File db)
CODE:
RETVAL = vstsync( vstptr(db) );
OUTPUT:
RETVAL
bool
optimize(QDBM_File db)
CODE:
RETVAL = vstoptimize( vstptr(db) );
OUTPUT:
RETVAL
SV*
get_name(QDBM_File db)
PREINIT:
char* name;
CODE:
name = vstname( vstptr(db) );
if (NULL != name) {
RETVAL = newSVpv(name, 0);
cbfree(name);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_size(QDBM_File db)
CODE:
RETVAL = vstfsiz( vstptr(db) );
OUTPUT:
RETVAL
int
count_leafs(QDBM_File db)
CODE:
RETVAL = vstlnum( vstptr(db) );
OUTPUT:
RETVAL
int
count_non_leafs(QDBM_File db)
CODE:
RETVAL = vstnnum( vstptr(db) );
OUTPUT:
RETVAL
int
count_records(QDBM_File db)
ALIAS:
SCALAR = 1
CODE:
RETVAL = vstrnum( vstptr(db) );
OUTPUT:
RETVAL
bool
is_writable(QDBM_File db)
CODE:
RETVAL = vstwritable( vstptr(db) );
OUTPUT:
RETVAL
const char*
get_error(SV* package)
CODE:
RETVAL = dperrmsg(dpecode);
OUTPUT:
RETVAL
bool
is_fatal_error(QDBM_File db)
CODE:
RETVAL = vstfatalerror( vstptr(db) );
OUTPUT:
RETVAL
time_t
get_mtime(QDBM_File db)
CODE:
RETVAL = vstmtime( vstptr(db) );
OUTPUT:
RETVAL
bool
begin_transaction(QDBM_File db)
CODE:
RETVAL = vsttranbegin( vstptr(db) );
OUTPUT:
RETVAL
bool
commit(QDBM_File db)
CODE:
RETVAL = vsttrancommit( vstptr(db) );
OUTPUT:
RETVAL
bool
rollback(QDBM_File db)
CODE:
RETVAL = vsttranabort( vstptr(db) );
OUTPUT:
RETVAL
bool
repair(SV* package, char* filename, SV* comparer = &PL_sv_undef)
PREINIT:
VSTCFUNC cmpptr;
dMY_CXT;
CODE:
cmpptr = SvOK(comparer) ? btree_compare : VST_CMPLEX;
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = comparer;
if ( sv_isobject(package) ) {
warn("qdbm repair warning: called via instance method\n");
}
RETVAL = vstrepair(filename, cmpptr);
OUTPUT:
RETVAL
bool
export_db(QDBM_File db, char* filename)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstexportdb( vstptr(db), filename );
OUTPUT:
RETVAL
bool
import_db(QDBM_File db, char* filename)
PREINIT:
dMY_CXT;
CODE:
SAVESPTR(MY_CXT.comparer);
MY_CXT.comparer = db->comparer;
RETVAL = vstimportdb( vstptr(db), filename );
OUTPUT:
RETVAL
MODULE = QDBM_File PACKAGE = QDBM_File::InvertedIndex
ODEUM*
new(char* dbtype, char* filename, int flags = O_CREAT|O_RDWR)
PREINIT:
int o_flags;
CODE:
o_flags = ( (flags & O_WRONLY) || (flags & O_RDWR) ) ? OD_OWRITER : OD_OREADER;
if (flags & O_CREAT) o_flags |= OD_OCREAT;
if (flags & O_TRUNC) o_flags |= OD_OTRUNC;
RETVAL = odopen(filename, o_flags);
if (NULL == RETVAL) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
void
DESTROY(ODEUM* db)
CODE:
if (db) {
if ( !odclose(db) ) {
croak( "qdbm close error: %s\n", dperrmsg(dpecode) );
}
}
bool
store_document(ODEUM* db, ODDOC* doc, int max_words = -1, bool over = (bool)TRUE)
CODE:
RETVAL = odput(db, doc, max_words, over);
OUTPUT:
RETVAL
bool
delete_document_by_uri(ODEUM* db, const char* uri)
CODE:
RETVAL = odout(db, uri);
OUTPUT:
RETVAL
bool
delete_document_by_id(ODEUM* db, int id)
CODE:
RETVAL = odoutbyid(db, id);
OUTPUT:
RETVAL
ODDOC*
get_document_by_uri(ODEUM* db, const char* uri)
CODE:
RETVAL = odget(db, uri);
if (NULL == RETVAL) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
ODDOC*
get_document_by_id(ODEUM* db, int id)
CODE:
RETVAL = odgetbyid(db, id);
if (NULL == RETVAL) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int
get_document_id(ODEUM* db, const char* uri)
CODE:
RETVAL = odgetidbyuri(db, uri);
OUTPUT:
RETVAL
bool
exists_document_by_uri(ODEUM* db, const char* uri)
CODE:
RETVAL = ( -1 != odgetidbyuri(db, uri) );
OUTPUT:
RETVAL
bool
exists_document_by_id(ODEUM* db, int id)
CODE:
RETVAL = odcheck(db, id);
OUTPUT:
RETVAL
void
search_document(ODEUM* db, const char* word, int max = -1)
PREINIT:
int i;
int length;
ODPAIR* pair;
PPCODE:
pair = odsearch(db, word, max, &length);
if (NULL != pair) {
for (i = 0; i < length; i++) {
mXPUSHi(pair[i].id);
}
cbfree(pair);
}
else {
XSRETURN_EMPTY;
}
int
search_document_count(ODEUM* db, const char* word)
CODE:
RETVAL = odsearchdnum(db, word);
OUTPUT:
RETVAL
bool
init_iterator(ODEUM* db)
CODE:
RETVAL = oditerinit(db);
OUTPUT:
RETVAL
ODDOC*
get_next_document(ODEUM* db)
CODE:
RETVAL = oditernext(db);
if (NULL == RETVAL) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
bool
sync(ODEUM* db)
CODE:
RETVAL = odsync(db);
OUTPUT:
RETVAL
bool
optimize(ODEUM* db)
CODE:
RETVAL = odoptimize(db);
OUTPUT:
RETVAL
SV*
get_name(ODEUM* db)
PREINIT:
char* name;
CODE:
name = odname(db);
if (NULL != name) {
RETVAL = newSVpv(name, 0);
cbfree(name);
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
double
get_size(ODEUM* db)
CODE:
RETVAL = odfsiz(db);
OUTPUT:
RETVAL
int
count_buckets(ODEUM* db)
CODE:
RETVAL = odbnum(db);
OUTPUT:
RETVAL
int
count_used_buckets(ODEUM* db)
CODE:
RETVAL = odbusenum(db);
OUTPUT:
RETVAL
int
count_documents(ODEUM* db)
CODE:
RETVAL = oddnum(db);
OUTPUT:
RETVAL
int
count_words(ODEUM* db)
CODE:
RETVAL = odwnum(db);
OUTPUT:
RETVAL
bool
is_writable(ODEUM* db)
CODE:
RETVAL = odwritable(db);
OUTPUT:
RETVAL
bool
is_fatal_error(ODEUM* db)
CODE:
RETVAL = odfatalerror(db);
OUTPUT:
RETVAL
const char*
get_error(SV* package)
CODE:
RETVAL = dperrmsg(dpecode);
OUTPUT:
RETVAL
time_t
get_mtime(ODEUM* db)
CODE:
RETVAL = odmtime(db);
OUTPUT:
RETVAL
bool
merge(SV* package, const char* name, ...)
PREINIT:
int i;
STRLEN elemsize;
const char* elembyte;
CBLIST* elemnames;
CODE:
if ( sv_isobject(package) ) {
warn("qdbm merge warning: called via instance method\n");
}
else {
elemnames = cblistopen();
for (i = 2; i < items; i++) {
SvGETMAGIC( ST(i) );
sv_utf8_downgrade( ST(i), 0 );
elembyte = SvPV_const( ST(i), elemsize );
cblistpush(elemnames, elembyte, (int)elemsize);
}
RETVAL = odmerge(name, elemnames);
}
OUTPUT:
RETVAL
void
_get_scores(ODEUM* db, ODDOC* doc, int max)
PREINIT:
const char* key;
const char* value;
int ksize;
int vsize;
CBMAP* scores;
PPCODE:
scores = oddocscores(doc, max, db);
if ( 0 == cbmaprnum(scores) ) {
cbmapclose(scores);
XSRETURN_EMPTY;
}
else {
cbmapiterinit(scores);
while ( NULL != ( key = cbmapiternext(scores, &ksize) ) ) {
value = cbmapiterval(key, &vsize);
XPUSHs( sv_2mortal( newSVpvn(key, (STRLEN)ksize) ) );
XPUSHs( sv_2mortal( newSVpvn(value, (STRLEN)vsize) ) );
}
cbmapclose(scores);
}
void
set_tuning(SV* package, int index_buckets, int inverted_index_division_num, int dirty_buffer_buckets, int dirty_buffer_size)
CODE:
if ( sv_isobject(package) ) {
warn("qdbm set_tuning warning: called via instance method\n");
}
else {
odsettuning(
index_buckets,
inverted_index_division_num,
dirty_buffer_buckets,
dirty_buffer_size
);
}
void
set_char_class(ODEUM* db, const char* space, const char* delimiter, const char* glue)
CODE:
odsetcharclass(db, space, delimiter, glue);
void
analyze_text(SV* self, const char* text)
PREINIT:
ODEUM* db;
int i;
const char* value;
int vsize;
CBLIST* appearance_words;
PPCODE:
if ( sv_isobject(self) && sv_derived_from(self, "QDBM_File::InvertedIndex") ) {
db = (ODEUM*)SvIV( (SV*)SvRV(self) );
appearance_words = cblistopen();
odanalyzetext(db, text, appearance_words, NULL);
}
else {
appearance_words = odbreaktext(text);
}
if ( 0 == cblistnum(appearance_words) ) {
cblistclose(appearance_words);
XSRETURN_EMPTY;
}
else {
for (i = 0; i < cblistnum(appearance_words); i++) {
value = cblistval(appearance_words, i, &vsize);
XPUSHs( sv_2mortal( newSVpvn(value, (STRLEN)vsize) ) );
}
cblistclose(appearance_words);
}
char*
normalize_word(SV* package, const char* asis)
PREINIT:
char* normalized_word;
CODE:
if ( sv_isobject(package) ) {
warn("qdbm normalize_word warning: called via instance method\n");
}
else {
normalized_word = odnormalizeword(asis);
RETVAL = normalized_word;
}
OUTPUT:
RETVAL
CLEANUP:
cbfree(normalized_word);
void
query(ODEUM *db, const char* query)
PREINIT:
int i;
int length;
int vsize;
const char* value;
ODPAIR* pair;
SV* errsv;
CBLIST* errors;
PPCODE:
errors = cblistopen();
pair = odquery(db, query, &length, errors);
if (NULL == pair) {
errsv = newSVpvn("", (STRLEN)0);
SAVEMORTALIZESV(errsv);
for (i = 0; i < cblistnum(errors); i++) {
value = cblistval(errors, i, &vsize);
sv_catpv(errsv, "qdbm query warning: ");
sv_catpv(errsv, value);
sv_catpv(errsv, "\n");
}
cblistclose(errors);
warn( SvPV_nolen(errsv) );
XSRETURN_EMPTY;
}
else {
for (i = 0; i < length; i++) {
mXPUSHi(pair[i].id);
}
cblistclose(errors);
cbfree(pair);
}
MODULE = QDBM_File PACKAGE = QDBM_File::InvertedIndex::Document
ODDOC*
new(char* package, char* uri)
CODE:
RETVAL = oddocopen(uri);
OUTPUT:
RETVAL
void
set_attribute(ODDOC* doc, const char* name, const char* value)
CODE:
oddocaddattr(doc, name, value);
const char*
get_attribute(ODDOC* doc, const char* name)
CODE:
RETVAL = oddocgetattr(doc, name);
if (NULL == RETVAL) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
void
add_word(ODDOC* doc, const char* normal, const char* asis)
CODE:
oddocaddword(doc, normal, asis);
int
get_id(ODDOC* doc)
CODE:
RETVAL = oddocid(doc);
OUTPUT:
RETVAL
const char*
get_uri(ODDOC* doc)
CODE:
RETVAL = oddocuri(doc);
OUTPUT:
RETVAL
void
get_normalized_words(ODDOC* doc)
PREINIT:
int i;
const char* value;
int vsize;
const CBLIST* words;
PPCODE:
words = oddocnwords(doc);
if ( 0 < cblistnum(words) ) {
for (i = 0; i < cblistnum(words); i++) {
value = cblistval(words, i, &vsize);
XPUSHs( sv_2mortal( newSVpvn(value, (STRLEN)vsize) ) );
}
}
else {
XSRETURN_EMPTY;
}
void
get_appearance_words(ODDOC* doc)
PREINIT:
int i;
const char* value;
int vsize;
const CBLIST* words;
PPCODE:
words = oddocawords(doc);
if ( 0 < cblistnum(words) ) {
for (i = 0; i < cblistnum(words); i++) {
value = cblistval(words, i, &vsize);
XPUSHs( sv_2mortal( newSVpvn(value, (STRLEN)vsize) ) );
}
}
else {
XSRETURN_EMPTY;
}
void
_get_scores(ODDOC* doc, int max, ODEUM* db = NULL)
PREINIT:
const char* key;
const char* value;
int ksize;
int vsize;
CBMAP* scores;
PPCODE:
scores = oddocscores(doc, max, db);
if ( 0 == cbmaprnum(scores) ) {
cbmapclose(scores);
XSRETURN_EMPTY;
}
else {
cbmapiterinit(scores);
while ( NULL != ( key = cbmapiternext(scores, &ksize) ) ) {
value = cbmapiterval(key, &vsize);
XPUSHs( sv_2mortal( newSVpvn(key, (STRLEN)ksize) ) );
XPUSHs( sv_2mortal( newSVpvn(value, (STRLEN)vsize) ) );
}
cbmapclose(scores);
}
void
DESTROY(ODDOC* doc)
CODE:
if (doc) {
oddocclose(doc);
}