X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FODBM_File%2FODBM_File.xs;h=3504ff64fdb7a40d580d7fe968153d117d58d3d5;hb=eb5402b2a7d45862a5feaae8ddab00f7e505298a;hp=2272474dcc62677a516c8b1ccc67a57f30edb461;hpb=748a93069b3d16374a9859d1456065dd3ae11394;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/ODBM_File/ODBM_File.xs b/ext/ODBM_File/ODBM_File.xs index 2272474..3504ff6 100644 --- a/ext/ODBM_File/ODBM_File.xs +++ b/ext/ODBM_File/ODBM_File.xs @@ -2,22 +2,78 @@ #include "perl.h" #include "XSUB.h" -#ifdef NULL -#undef NULL +#ifdef I_DBM +# include +#else +# ifdef I_RPCSVC_DBM +# include +# endif +#endif + +#ifndef HAS_DBMINIT_PROTO +int dbminit(char* filename); +int dbmclose(void); +datum fetch(datum key); +int store(datum key, datum dat); +# ifdef __cplusplus +int odelete(datum key); /* Cannot be delete() for C++. */ +# else +int delete(datum key); +# endif +datum firstkey(void); +datum nextkey(datum key); +#endif + +#ifdef DBM_BUG_DUPLICATE_FREE +/* + * DBM on at least Ultrix and HPUX call dbmclose() from dbminit(), + * resulting in duplicate free() because dbmclose() does *not* + * check if it has already been called for this DBM. + * If some malloc/free calls have been done between dbmclose() and + * the next dbminit(), the memory might be used for something else when + * it is freed. + * Verified to work on ultrix4.3. Probably will work on HP/UX. + * Set DBM_BUG_DUPLICATE_FREE in the extension hint file. + */ +/* Close the previous dbm, and fail to open a new dbm */ +#define dbmclose() ((void) dbminit("/non/exist/ent")) #endif -#include #include -typedef void* ODBM_File; +typedef struct { + void * dbp ; + SV * filter_fetch_key ; + SV * filter_store_key ; + SV * filter_fetch_value ; + SV * filter_store_value ; + int filtering ; + } ODBM_File_type; + +typedef ODBM_File_type * ODBM_File ; +typedef datum datum_key ; +typedef datum datum_key_copy ; +typedef datum datum_value ; #define odbm_FETCH(db,key) fetch(key) #define odbm_STORE(db,key,value,flags) store(key,value) -#define odbm_DELETE(db,key) delete(key) +#ifdef __cplusplus +# define odbm_DELETE(db,key) odelete(key) +#else +# define odbm_DELETE(db,key) delete(key) +#endif #define odbm_FIRSTKEY(db) firstkey() #define odbm_NEXTKEY(db,key) nextkey(key) -static int dbmrefcnt; +#define MY_CXT_KEY "ODBM_File::_guts" XS_VERSION + +typedef struct { + int x_dbmrefcnt; +} my_cxt_t; + +START_MY_CXT + +#define dbmrefcnt (MY_CXT.x_dbmrefcnt) #ifndef DBM_REPLACE #define DBM_REPLACE 0 @@ -25,6 +81,11 @@ static int dbmrefcnt; MODULE = ODBM_File PACKAGE = ODBM_File PREFIX = odbm_ +BOOT: +{ + MY_CXT_INIT; +} + ODBM_File odbm_TIEHASH(dbtype, filename, flags, mode) char * dbtype @@ -33,11 +94,16 @@ odbm_TIEHASH(dbtype, filename, flags, mode) int mode CODE: { - char tmpbuf[1025]; + char *tmpbuf; + void * dbp ; + dMY_CXT; + if (dbmrefcnt++) croak("Old dbm can only open one database"); + Newx(tmpbuf, strlen(filename) + 5, char); + SAVEFREEPV(tmpbuf); sprintf(tmpbuf,"%s.dir",filename); - if (stat(tmpbuf, &statbuf) < 0) { + if (stat(tmpbuf, &PL_statbuf) < 0) { if (flags & O_CREAT) { if (mode < 0 || close(creat(tmpbuf,mode)) < 0) croak("ODBM_File: Can't create %s", filename); @@ -48,28 +114,34 @@ odbm_TIEHASH(dbtype, filename, flags, mode) else croak("ODBM_FILE: Can't open %s", filename); } - RETVAL = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0); - ST(0) = sv_mortalcopy(&sv_undef); - sv_setptrobj(ST(0), RETVAL, "ODBM_File"); + dbp = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0); + RETVAL = (ODBM_File)safemalloc(sizeof(ODBM_File_type)) ; + Zero(RETVAL, 1, ODBM_File_type) ; + RETVAL->dbp = dbp ; + ST(0) = sv_mortalcopy(&PL_sv_undef); + sv_setptrobj(ST(0), RETVAL, dbtype); } void DESTROY(db) ODBM_File db + PREINIT: + dMY_CXT; CODE: dbmrefcnt--; dbmclose(); + safefree(db); -datum +datum_value odbm_FETCH(db, key) ODBM_File db - datum key + datum_key_copy key int odbm_STORE(db, key, value, flags = DBM_REPLACE) ODBM_File db - datum key - datum value + datum_key key + datum_value value int flags CLEANUP: if (RETVAL) { @@ -82,14 +154,66 @@ odbm_STORE(db, key, value, flags = DBM_REPLACE) int odbm_DELETE(db, key) ODBM_File db - datum key + datum_key key -datum +datum_key odbm_FIRSTKEY(db) ODBM_File db -datum +datum_key odbm_NEXTKEY(db, key) ODBM_File db - datum key + datum_key key + + +#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 = Nullsv ; \ + } \ + else if (code) { \ + if (db->type) \ + sv_setsv(db->type, code) ; \ + else \ + db->type = newSVsv(code) ; \ + } \ + } + + + +SV * +filter_fetch_key(db, code) + ODBM_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + DBM_setFilter(db->filter_fetch_key, code) ; + +SV * +filter_store_key(db, code) + ODBM_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + DBM_setFilter(db->filter_store_key, code) ; + +SV * +filter_fetch_value(db, code) + ODBM_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + DBM_setFilter(db->filter_fetch_value, code) ; + +SV * +filter_store_value(db, code) + ODBM_File db + SV * code + SV * RETVAL = &PL_sv_undef ; + CODE: + DBM_setFilter(db->filter_store_value, code) ;