diff options
author | Sascha Schumann <sas@php.net> | 1999-07-21 15:12:32 +0000 |
---|---|---|
committer | Sascha Schumann <sas@php.net> | 1999-07-21 15:12:32 +0000 |
commit | b33d0fd7e7365d3247a769a1f046593fd94673ea (patch) | |
tree | cf872545df28aa0bca3719438136360928fab15f /ext/dba/dba.c | |
parent | 3843821d114fc770b1ac36d90bbf049bcc9a28ce (diff) | |
download | php-git-b33d0fd7e7365d3247a769a1f046593fd94673ea.tar.gz |
initial import of DBA
Diffstat (limited to 'ext/dba/dba.c')
-rw-r--r-- | ext/dba/dba.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/ext/dba/dba.c b/ext/dba/dba.c new file mode 100644 index 0000000000..25dc7a56b6 --- /dev/null +++ b/ext/dba/dba.c @@ -0,0 +1,475 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1999 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) the GNU General Public License as published by the Free Software | + | Foundation; either version 2 of the License, or (at your option) | + | any later version. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Authors: Sascha Schumann <sas@schell.de> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +#include "php.h" + +#if HAVE_DBA + +#include "php3_dba.h" + +#include "php3_gdbm.h" +#include "php3_ndbm.h" +#include "php3_dbm.h" +#include "php3_cdb.h" +#include "php3_db2.h" + +function_entry dba_functions[] = { + PHP_FE(dba_open, NULL) + PHP_FE(dba_popen, NULL) + PHP_FE(dba_close, NULL) + PHP_FE(dba_delete, NULL) + PHP_FE(dba_exists, NULL) + PHP_FE(dba_fetch, NULL) + PHP_FE(dba_insert, NULL) + PHP_FE(dba_replace, NULL) + PHP_FE(dba_firstkey, NULL) + PHP_FE(dba_nextkey, NULL) + PHP_FE(dba_optimize, NULL) + PHP_FE(dba_sync, NULL) + {NULL,NULL,NULL} +}; + +static int php3_minit_dba(INIT_FUNC_ARGS); +static int php3_mshutdown_dba(SHUTDOWN_FUNC_ARGS); +static void php3_info_dba(ZEND_MODULES_INFO_FUNC_ARGS); + +php3_module_entry dba_module_entry = { + "DataBase API", dba_functions, + php3_minit_dba, + php3_mshutdown_dba, + NULL, NULL, + php3_info_dba, + STANDARD_MODULE_PROPERTIES +}; + +typedef struct dba_handler { + char *name; + int (*open)(dba_info *); + void (*close)(dba_info *); + char* (*fetch)(dba_info *, char *, int, int *); + int (*update)(dba_info *, char *, int, char *, int, int); + int (*exists)(dba_info *, char *, int); + int (*delete)(dba_info *, char *, int); + char* (*firstkey)(dba_info *, int *); + char* (*nextkey)(dba_info *, int *); + int (*optimize)(dba_info *); + int (*sync)(dba_info *); +} dba_handler; + +/* {{{ macromania */ + +#define DBA_ID_PARS pval *id; dba_info *info = NULL; int type, ac = ARG_COUNT(ht) + +/* these are used to get the standard arguments */ + +#define DBA_GET1 \ + if(ac != 1 || getParameters(ht, ac, &id) != SUCCESS) { \ + WRONG_PARAM_COUNT; \ + } + +#define DBA_GET2 \ + pval *key; \ + if(ac != 2 || getParameters(ht, ac, &key, &id) != SUCCESS) { \ + WRONG_PARAM_COUNT; \ + } \ + convert_to_string(key) + +#define DBA_IF_NOT_CORRECT_TYPE(link_id) \ + info = php3_list_find(link_id, &type); \ + if(!info || (type != GLOBAL(le_db) && type != GLOBAL(le_pdb))) + +#define DBA_ID_GET \ + convert_to_long(id); \ + DBA_IF_NOT_CORRECT_TYPE(id->value.lval) { \ + php3_error(E_WARNING, "Unable to find DBA identifier %d", id->value.lval); \ + RETURN_FALSE; \ + } + +#define DBA_ID_GET1 DBA_ID_PARS; DBA_GET1; DBA_ID_GET +#define DBA_ID_GET2 DBA_ID_PARS; DBA_GET2; DBA_ID_GET + +/* a DBA handler must have specific routines */ + +#define DBA_HND(x) \ +{\ + #x, dba_open_##x, dba_close_##x, dba_fetch_##x, dba_update_##x, \ + dba_exists_##x, dba_delete_##x, dba_firstkey_##x, dba_nextkey_##x, \ + dba_optimize_##x, dba_sync_##x \ +}, + +/* check whether the user has write access */ +#define DBA_WRITE_CHECK \ + if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \ + php3_error(E_WARNING, "you cannot perform a modification to a database without proper access"); \ + RETURN_FALSE; \ + } + +#define GLOBAL(a) a + +/* }}} */ + +/* {{{ globals */ + +static dba_handler handler[] = { +#if DBA_GDBM + DBA_HND(gdbm) +#endif +#if DBA_DBM + DBA_HND(dbm) +#endif +#if DBA_NDBM + DBA_HND(ndbm) +#endif +#if DBA_CDB + DBA_HND(cdb) +#endif +#if DBA_DB2 + DBA_HND(db2) +#endif + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; + +static int le_db; +static int le_pdb; +static HashTable ht_keys; +/* }}} */ + +/* {{{ helper routines */ + /* {{{ dba_close */ + +static void dba_close(dba_info *info) +{ + if(info->hnd) info->hnd->close(info); + if(info->path) free(info->path); + free(info); +} +/* }}} */ + /* {{{ php3_minit_dba */ + +static int php3_minit_dba(INIT_FUNC_ARGS) +{ + _php3_hash_init(&ht_keys, 0, NULL, NULL, 1); + GLOBAL(le_db) = register_list_destructors(dba_close, NULL); + GLOBAL(le_pdb) = register_list_destructors(NULL, dba_close); + return SUCCESS; +} +/* }}} */ + /* {{{ php3_mshutdown_dba */ + +static int php3_mshutdown_dba(SHUTDOWN_FUNC_ARGS) +{ + _php3_hash_destroy(&ht_keys); + return SUCCESS; +} +/* }}} */ + /* {{{ php3_info_dba */ + +static void php3_info_dba(ZEND_MODULE_INFO_FUNC_ARGS) +{ + dba_handler *hptr; + + PUTS("V1 ($Id$)"); + for(hptr = handler; hptr->name; hptr++) { + PUTS(" "); + PUTS(hptr->name); + } +} +/* }}} */ + /* {{{ _php3_dba_update */ + +static void _php3_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode) +{ + DBA_ID_PARS; + pval *val, *key; + + if(ac != 3 || getParameters(ht, ac, &key, &val, &id) != SUCCESS) { + WRONG_PARAM_COUNT; + } + convert_to_string(key); + convert_to_string(val); + DBA_ID_GET; + + DBA_WRITE_CHECK; + + if(info->hnd->update(info, VALLEN(key), VALLEN(val), mode) == SUCCESS) + RETURN_TRUE; + RETURN_FALSE; +} +/* }}} */ + /* {{{ _php3_dba_open */ + +#define FREENOW if(args) efree(args); if(key) efree(key) + +static void _php3_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent) +{ + pval **args = (pval **) NULL; + int ac = ARG_COUNT(ht); + dba_mode_t modenr; + dba_info *info; + dba_handler *hptr; + char *key = NULL; + int keylen = 0; + int listid; + int i; + + if(ac < 3) { + WRONG_PARAM_COUNT; + } + + /* we pass additional args to the respective handler */ + args = emalloc(ac * sizeof(pval *)); + if(getParametersArray(ht, ac, args) != SUCCESS) { + FREENOW; + WRONG_PARAM_COUNT; + } + + /* we only take string arguments */ + for(i = 0; i < ac; i++) { + convert_to_string(args[i]); + keylen += args[i]->value.str.len; + } + + if(persistent) { + /* calculate hash */ + key = emalloc(keylen); + keylen = 0; + + for(i = 0; i < ac; i++) { + memcpy(key+keylen,args[i]->value.str.val,args[i]->value.str.len); + keylen += args[i]->value.str.len; + } + + if(_php3_hash_find(&ht_keys, key, keylen, (void **) &info) == SUCCESS) { + FREENOW; + RETURN_LONG(php3_list_insert(info, GLOBAL(le_pdb))); + } + } + + /* this is O(n) and could be improved */ + for(hptr = handler; hptr->name && + strcasecmp(hptr->name, args[2]->value.str.val); hptr++); + + if(!hptr->name) { + php3_error(E_WARNING, "no such handler: %s", args[2]->value.str.val); + FREENOW; + RETURN_FALSE; + } + + switch(args[1]->value.str.val[0]) { + case 'c': + modenr = DBA_CREAT; + break; + case 'w': + modenr = DBA_WRITER; + break; + case 'r': + modenr = DBA_READER; + break; + case 'n': + modenr = DBA_TRUNC; + break; + default: + php3_error(E_WARNING,"illegal DBA mode: %s",args[1]->value.str.val); + FREENOW; + RETURN_FALSE; + } + + info = malloc(sizeof(*info)); + memset(info, 0, sizeof(info)); + info->path = strdup(args[0]->value.str.val); + info->mode = modenr; + info->argc = ac - 3; + info->argv = args + 3; + + if(hptr->open(info) != SUCCESS) { + dba_close(info); + php3_error(E_WARNING, "driver initialization failed"); + FREENOW; + RETURN_FALSE; + } + info->hnd = hptr; + info->argc = 0; + info->argv = NULL; + + listid = php3_list_insert(info, persistent?GLOBAL(le_pdb):GLOBAL(le_db)); + if(persistent) { + _php3_hash_update(&ht_keys, key, keylen, info, sizeof(*info), NULL); + } + + FREENOW; + RETURN_LONG(listid); +} +#undef FREENOW +/* }}} */ +/* }}} */ + +/* {{{ proto int dba_popen(string path, string mode, string handlername[, ...]) + opens path using the specified handler in mode persistently */ +PHP_FUNCTION(dba_popen) +{ + _php3_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto int dba_open(string path, string mode, string handlername[, ...]) + opens path using the specified handler in mode*/ +PHP_FUNCTION(dba_open) +{ + _php3_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto void dba_close(int handle) + closes database */ +PHP_FUNCTION(dba_close) +{ + DBA_ID_GET1; + + php3_list_delete(id->value.lval); +} +/* }}} */ + +/* {{{ proto bool dba_exists(string key, int handle) + checks, if the specified key exists */ +PHP_FUNCTION(dba_exists) +{ + DBA_ID_GET2; + + if(info->hnd->exists(info, VALLEN(key)) == SUCCESS) { + RETURN_TRUE; + } + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string dba_fetch(string key, int handle) + fetches the data associated with key */ +PHP_FUNCTION(dba_fetch) +{ + char *val; + int len = 0; + DBA_ID_GET2; + + if((val = info->hnd->fetch(info, VALLEN(key), &len)) != NULL) { + RETURN_STRINGL(val, len, 0); + } + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string dba_firstkey(int handle) + resets the internal key pointer and returns the first key */ +PHP_FUNCTION(dba_firstkey) +{ + char *fkey; + int len; + DBA_ID_GET1; + + fkey = info->hnd->firstkey(info, &len); + if(fkey) + RETURN_STRINGL(fkey, len, 0); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string dba_nextkey(int handle) + returns the next key */ +PHP_FUNCTION(dba_nextkey) +{ + char *nkey; + int len; + DBA_ID_GET1; + + nkey = info->hnd->nextkey(info, &len); + if(nkey) + RETURN_STRINGL(nkey, len, 0); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto bool dba_delete(string key, int handle) + deletes the entry associated with key */ +PHP_FUNCTION(dba_delete) +{ + DBA_ID_GET2; + + DBA_WRITE_CHECK; + + if(info->hnd->delete(info, VALLEN(key)) == SUCCESS) + RETURN_TRUE; + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto bool dba_insert(string key, string value, int handle) + inserts value as key, returns false, if key exists already */ +PHP_FUNCTION(dba_insert) +{ + _php3_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto bool dba_replace(string key, string value, int handle) + inserts value as key, replaces key, if key exists already */ +PHP_FUNCTION(dba_replace) +{ + _php3_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto bool dba_optimize(int handle) + optimizes (e.g. clean up, vacuum) database */ +PHP_FUNCTION(dba_optimize) +{ + DBA_ID_GET1; + + DBA_WRITE_CHECK; + if(info->hnd->optimize(info) == SUCCESS) { + RETURN_TRUE; + } + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto bool dba_sync(int handle) + synchronizes database */ +PHP_FUNCTION(dba_sync) +{ + DBA_ID_GET1; + + if(info->hnd->sync(info) == SUCCESS) { + RETURN_TRUE; + } + RETURN_FALSE; +} +/* }}} */ + +#endif |