DB_File.xs -- Perl 5 interface to Berkeley DB
written by Paul Marquess <Paul.Marquess@btinternet.com>
- last modified 6th March 1999
- version 1.65
+ last modified 6th June 1999
+ version 1.67
All comments/suggestions/problems are welcome
to fix a flag mapping problem with O_RDONLY on the Hurd
1.65 - Fixed a bug in the PUSH logic.
Added BOOT check that using 2.3.4 or greater
+ 1.66 - Added DBM filter code
+ 1.67 - Backed off the use of newSVpvn.
+ Fixed DBM Filter code for Perl 5.004.
+ Fixed a small memory leak in the filter code.
#endif
+/* DEFSV appears first in 5.004_56 */
+#ifndef DEFSV
+#define DEFSV GvSV(defgv)
+#endif
+
/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
* shortly #included by the <db.h>) __attribute__ to the possibly
* already defined __attribute__, for example by GNUC or by Perl. */
#include <fcntl.h>
/* #define TRACE */
+#define DBM_FILTERING
#ifdef DB_VERSION_MAJOR
DBC * cursor ;
#endif
+#ifdef DBM_FILTERING
+ SV * filter_fetch_key ;
+ SV * filter_store_key ;
+ SV * filter_fetch_value ;
+ SV * filter_store_value ;
+ int filtering ;
+#endif /* DBM_FILTERING */
+
} DB_File_type;
typedef DB_File_type * DB_File ;
typedef DBT DBTKEY ;
+#ifdef DBM_FILTERING
+
+#define ckFilter(arg,type,name) \
+ if (db->type) { \
+ SV * save_defsv ; \
+ /* printf("filtering %s\n", name) ;*/ \
+ if (db->filtering) \
+ croak("recursion detected in %s", name) ; \
+ db->filtering = TRUE ; \
+ save_defsv = newSVsv(DEFSV) ; \
+ sv_setsv(DEFSV, arg) ; \
+ PUSHMARK(sp) ; \
+ (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
+ sv_setsv(arg, DEFSV) ; \
+ sv_setsv(DEFSV, save_defsv) ; \
+ SvREFCNT_dec(save_defsv) ; \
+ db->filtering = FALSE ; \
+ /*printf("end of filtering %s\n", name) ;*/ \
+ }
+
+#else
+
+#define ckFilter(arg,type, name)
+
+#endif /* DBM_FILTERING */
+
#define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
-#define OutputValue(arg, name) \
- { if (RETVAL == 0) { \
- my_sv_setpvn(arg, name.data, name.size) ; \
- } \
+#define OutputValue(arg, name) \
+ { if (RETVAL == 0) { \
+ my_sv_setpvn(arg, name.data, name.size) ; \
+ ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
+ } \
}
-#define OutputKey(arg, name) \
- { if (RETVAL == 0) \
- { \
- if (db->type != DB_RECNO) { \
- my_sv_setpvn(arg, name.data, name.size); \
- } \
- else \
- sv_setiv(arg, (I32)*(I32*)name.data - 1); \
- } \
+#define OutputKey(arg, name) \
+ { if (RETVAL == 0) \
+ { \
+ if (db->type != DB_RECNO) { \
+ my_sv_setpvn(arg, name.data, name.size); \
+ } \
+ else \
+ sv_setiv(arg, (I32)*(I32*)name.data - 1); \
+ ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
+ } \
}
#ifdef DB_VERSION_MAJOR
static int
-db_put(db, key, value, flags)
-DB_File db ;
-DBTKEY key ;
-DBT value ;
-u_int flags ;
-
+db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
{
int status ;
#endif /* DB_VERSION_MAJOR */
static void
-GetVersionInfo()
+GetVersionInfo(pTHX)
{
SV * ver_sv = perl_get_sv("DB_File::db_version", TRUE) ;
#ifdef DB_VERSION_MAJOR
static int
-btree_compare(key1, key2)
-const DBT * key1 ;
-const DBT * key2 ;
+btree_compare(const DBT *key1, const DBT *key2)
{
+ dTHX;
dSP ;
void * data1, * data2 ;
int retval ;
}
static DB_Prefix_t
-btree_prefix(key1, key2)
-const DBT * key1 ;
-const DBT * key2 ;
+btree_prefix(const DBT *key1, const DBT *key2)
{
+ dTHX;
dSP ;
void * data1, * data2 ;
int retval ;
}
static DB_Hash_t
-hash_cb(data, size)
-const void * data ;
-size_t size ;
+hash_cb(const void *data, size_t size)
{
+ dTHX;
dSP ;
int retval ;
int count ;
#ifdef TRACE
static void
-PrintHash(hash)
-INFO * hash ;
+PrintHash(INFO *hash)
{
printf ("HASH Info\n") ;
printf (" hash = %s\n",
}
static void
-PrintRecno(recno)
-INFO * recno ;
+PrintRecno(INFO *recno)
{
printf ("RECNO Info\n") ;
printf (" flags = %d\n", recno->db_RE_flags) ;
}
static void
-PrintBtree(btree)
-INFO * btree ;
+PrintBtree(INFO *btree)
{
printf ("BTREE Info\n") ;
printf (" compare = %s\n",
static I32
-GetArrayLength(db)
-DB_File db ;
+GetArrayLength(pTHX_ DB_File db)
{
DBT key ;
DBT value ;
}
static recno_t
-GetRecnoKey(db, value)
-DB_File db ;
-I32 value ;
+GetRecnoKey(pTHX_ DB_File db, I32 value)
{
if (value < 0) {
/* Get the length of the array */
- I32 length = GetArrayLength(db) ;
+ I32 length = GetArrayLength(aTHX_ db) ;
/* check for attempt to write before start of array */
if (length + value + 1 <= 0)
}
static DB_File
-ParseOpenInfo(isHASH, name, flags, mode, sv)
-int isHASH ;
-char * name ;
-int flags ;
-int mode ;
-SV * sv ;
+ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
{
SV ** svp;
HV * action ;
Zero(RETVAL, 1, DB_File_type) ;
/* Default to HASH */
+#ifdef DBM_FILTERING
+ RETVAL->filtering = 0 ;
+ RETVAL->filter_fetch_key = RETVAL->filter_store_key =
+ RETVAL->filter_fetch_value = RETVAL->filter_store_value =
+#endif /* DBM_FILTERING */
RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
RETVAL->type = DB_HASH ;
}
-static int
-not_here(s)
-char *s;
-{
- croak("DB_File::%s not implemented on this architecture", s);
- return -1;
-}
-
static double
-constant(name, arg)
-char *name;
-int arg;
+constant(char *name, int arg)
{
errno = 0;
switch (*name) {
BOOT:
{
- GetVersionInfo() ;
+ GetVersionInfo(aTHX) ;
empty.data = &zero ;
empty.size = sizeof(recno_t) ;
if (items == 6)
sv = ST(5) ;
- RETVAL = ParseOpenInfo(isHASH, name, flags, mode, sv) ;
+ RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
if (RETVAL->dbp == NULL)
RETVAL = NULL ;
}
SvREFCNT_dec(db->compare) ;
if (db->prefix)
SvREFCNT_dec(db->prefix) ;
+#ifdef DBM_FILTERING
+ 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) ;
+#endif /* DBM_FILTERING */
Safefree(db) ;
#ifdef DB_VERSION_MAJOR
if (RETVAL > 0)
if (RETVAL != 0)
break;
}
-#else
+#else
+
/* Set the Cursor to the Last element */
RETVAL = do_SEQ(db, key, value, R_LAST) ;
if (RETVAL >= 0)
ALIAS: FETCHSIZE = 1
CODE:
CurrentDB = db ;
- RETVAL = GetArrayLength(db) ;
+ RETVAL = GetArrayLength(aTHX_ db) ;
OUTPUT:
RETVAL
key
value
+#ifdef DBM_FILTERING
+
+#define setFilter(type) \
+ { \
+ 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) ; \
+ } \
+ }
+
+
+SV *
+filter_fetch_key(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ setFilter(filter_fetch_key) ;
+
+SV *
+filter_store_key(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ setFilter(filter_store_key) ;
+
+SV *
+filter_fetch_value(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ setFilter(filter_fetch_value) ;
+
+SV *
+filter_store_value(db, code)
+ DB_File db
+ SV * code
+ SV * RETVAL = &PL_sv_undef ;
+ CODE:
+ setFilter(filter_store_value) ;
+
+#endif /* DBM_FILTERING */