/*********************************************************** Copyright 1995 by Lance Ellinghaus , Cathedral City, California Republic, United States of America All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. LANCE ELLINGHAUS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL LANCE ELLINGHAUS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* This module interfaces with the typhoon (version 1.10.3) database that can be found in the Linux distribution. There are a number of data types: 1) Database 2) Sequence 3) Record 4) Record Buffer To use this module, there are a few things you need to set up from inside the python program. These are done using 'setdbfpath' and 'setdbdpath'. These tell the typhoon library where to find the data files and the DBD description file for the different databases you will be opening. Both of these can be changed during the operation of the python program. Here are the methods and return values for the different data objects defined in this file: Database Object: records() -> listobject containing names of records defined in this database sequences() -> listobject containing names of sequences defined in this database values() -> listobject containing record and sequence objects defined items() -> listobject of tuples containing (name,object) pairs of records and sequences keys() -> listobject containing all names of records and sequences defined kas_key('name') -> [1|0] if name is a sequence or record in this database len() -> number of sequences and records defined object['name'] -> sequence or record object of given name Sequence Object: int(sequence_object) -> intobject containing next incremental number NOTE: you must use the int() function to retrieve this value Record Object: len() -> number of records in datafile keys() -> listobject containing names of all index keys new() -> return blank record buffer object recfirst() -> return record buffer of first record in file reclast() -> return record buffer of last record in file recnext() -> return record buffer of next record in file recprev() -> return record buffer of previous record in file find('index',{}|obj) -> return record buffer of found record in index 'index' the second argument is a dictionary for compound keys or a single object for non-compound keys keyfirst('index') -> return record buffer of first record in index 'index' keylast('index') -> return record buffer of last record in index 'index' keynext('index') -> return record buffer of next record in index 'index' keyprev('index') -> return record buffer of previous record in index 'index' Record Buffer Object: values() -> listobject containing data fields in same order as as defined in the DDL file items() -> listobject containing tuple of ('name',value) pairs keys() -> listobject containing names of fields has_key('name') -> [0|1] is 'name' a valid field name isvalid() -> has this record buffer been commited yet commit() -> commit changes to data file, mark as valid delete() -> delete record from data file, mark as invalid object['name'] -> set or get values for field named 'name' */ /* ChangeLog: Version 1.0beta-1: 11/15/95: released to mailing list */ /* Metaldb objects */ #include "allobjects.h" #include #include "modsupport.h" /* For PyArg_Parse() etc. */ #include "typhoon.h" #include #include "ty_dbd.h" #include "ty_type.h" #include "ty_glob.h" #ifndef TRUE #define TRUE 1 #endif extern char *sys_errlist[]; static PyObject *PyTyphoon_ExcError; /* ------ Info ---------------- */ static PyObject *PyTyphoon_Version; #define PyTyphoon_VERSION "1.0beta-1" /* ------ Error Handling ------ */ static struct _TyphoonErrors { int val; char *str; } PyTyphoonErrors[] = { {S_NOCR, "No Current Record selected"}, {S_NOCD, "No Current Database selected"}, {S_NOTFOUND, "Record not found"}, {S_DUPLICATE, "Duplicate key found"}, {S_DELETED, "Record is deleted"}, {S_RESTRICT, "Restrict rule encountered"}, {S_FOREIGN, "No Foreign key"}, {S_LOCKED, "Record is locked"}, {S_UNLOCKED, "Record is unlocked"}, {S_VERSION, "B-Tree or data file has wrong version"}, {S_INVPARM, "Invalid parameter"}, {S_NOMEM, "Out of Memory"}, {S_NOTAVAIL, "Database not available"}, {S_IOFATAL, "Fatal I/O operation"}, {S_FATAL, "Fatal error - recover"}, {S_MAXCLIENTS,"Too many clients"}, {S_NOSERVER, "No server is installed"}, {S_INVDB, "Invalid database"}, {S_INVREC, "Invalid record"}, {S_INVFLD, "Invalid field name"}, {S_NOTKEY, "Field is not a key"}, {S_RECSIZE, "Variable length record has invalid size"}, {S_BADTYPE, "Bad parameter type"}, {S_INVKEY, "Invalid key"}, {S_INVADDR, "Invalid database address (record number)"}, {S_INVSEQ, "Invalid sequence ID"}, {0, (char *)NULL} }; static PyObject * PyTyphoonErr(i) int i; { struct _TyphoonErrors *te = PyTyphoonErrors; while (te->val) { if (i == te->val) { PyErr_SetString(PyTyphoon_ExcError,te->str); break; } te++; } if (te->val == 0) { char er[80]; sprintf(er,"unknown Error %d", i); PyErr_SetString(PyTyphoon_ExcError,er); } return NULL; } /* ---------------------------------- */ typedef struct { OB_HEAD Dbentry *db; int db_num; } PyTyphoonDbObject; typedef struct { OB_HEAD PyTyphoonDbObject *db_o; Record *recPtr; Field *fldPtr; int recId; } PyTyphoonRecObject; typedef struct { OB_HEAD PyTyphoonRecObject *rec_o; Record *recPtr; Field *fldPtr; char *buf; DB_ADDR recAddr; int valid; } PyTyphoonRecBufObject; typedef struct { OB_HEAD PyTyphoonDbObject *db_o; Sequence *seqPtr; int seqId; } PyTyphoonSeqObject; extern PyTypeObject PyTyphoonDb_Type; /* Really static, forward */ extern PyTypeObject PyTyphoonRec_Type; extern PyTypeObject PyTyphoonRecBuf_Type; extern PyTypeObject PyTyphoonSeq_Type; #define PyTyphoonDb_Check(v) ((v)->ob_type == &PyTyphoonDb_Type) #define PyTyphoonRec_Check(v) ((v)->ob_type == &PyTyphoonRec_Type) #define PyTyphoonRecBuf_Check(v) ((v)->ob_type == &PyTyphoonRecBuf_Type && ((PyTyphoonRecBufObject *)v)->valid == TRUE) #define PyTyphoonSeq_Check(v) ((v)->ob_type == &PyTyphoonSeq_Type) /* --------- Sequence Handling --------- */ static PyObject * PyTyphoonSeq_New(db_o, name) PyTyphoonDbObject *db_o; char *name; { PyTyphoonSeqObject *xp; Sequence *seq = db_o->db->sequence; int ndx = 0; int num = db_o->db->header.sequences; int found = 0; for (; ndx <= num; ndx++, seq++) { if (strcmp(seq->name, name) == 0) { found++; break; } } if (!found) { return PyTyphoonErr(S_INVSEQ); } xp = PyObject_NEW(PyTyphoonSeqObject, &PyTyphoonSeq_Type); if (xp == NULL) return NULL; xp->db_o = db_o; Py_INCREF(xp->db_o); xp->seqPtr = seq; xp->seqId = ndx; return (PyObject *)xp; } static void PyTyphoonSeq_Dealloc(xp) PyTyphoonSeqObject *xp; { if (xp->db_o != NULL) Py_DECREF(xp->db_o); PyMem_DEL(xp); } static PyObject * PyTyphoonSeq_Repr(seq) PyTyphoonSeqObject *seq; { char buf[80]; sprintf(buf,"", seq->seqPtr->name, seq->db_o->db->name); return PyString_FromString(buf); } static PyObject * PyTyphoonSeq_Int(seq) PyTyphoonSeqObject *seq; { unsigned long s; int rtn; switch (rtn = d_dbset(seq->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } switch (rtn = d_getsequence(seq->seqId,&s)) { case S_OKAY: break; default: return PyTyphoonErr(rtn); } return PyInt_FromLong((long)s); } static PyNumberMethods PyTyphoonSeq_As_Number = { (binaryfunc) 0 /* nb_add */, (binaryfunc) 0 /* nb_subtract */, (binaryfunc) 0 /* nb_multiply */, (binaryfunc) 0 /* nb_divide */, (binaryfunc) 0 /* nb_remainder */, (binaryfunc) 0 /* nb_divmod */, (ternaryfunc) 0 /* nb_power */, (unaryfunc) 0 /* nb_negative */, (unaryfunc) 0 /* nb_positive */, (unaryfunc) 0 /* nb_absolute */, (inquiry) 0 /* nb_nonzero */, (unaryfunc) 0 /* nb_invert */, (binaryfunc) 0 /* nb_lshift */, (binaryfunc) 0 /* nb_rshift */, (binaryfunc) 0 /* nb_and */, (binaryfunc) 0 /* nb_xor */, (binaryfunc) 0 /* nb_or */, (coercion) 0 /* nb_coerce */, (unaryfunc) PyTyphoonSeq_Int /* nb_int */, (unaryfunc) 0 /* nb_long */, (unaryfunc) 0 /* nb_float */, (unaryfunc) 0 /* nb_oct */, (unaryfunc) 0 /* nb_hex */ }; static PyTypeObject PyTyphoonSeq_Type = { OB_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "TyphoonSequence", /*tp_name*/ sizeof(PyTyphoonSeqObject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ (destructor)PyTyphoonSeq_Dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ (reprfunc)PyTyphoonSeq_Repr, /*tp_repr*/ &PyTyphoonSeq_As_Number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash (hashfunc) */ }; /* --------- Record Buffer Handling ---- */ static PyObject * PyTyphoonRecBuf_GetFieldValue(recbuf_o,fieldname) PyTyphoonRecBufObject *recbuf_o; char *fieldname; { char *addr; int rtn; int idx; int ndx; PyObject *rtn_o; Field *fld; int found; int ty; int num=0; /* variable length */ Field *fld2; char *addr2; switch (rtn = d_dbset(recbuf_o->rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } fld = recbuf_o->fldPtr; for (idx = 0, found = 0; idx < recbuf_o->rec_o->recPtr->fields; idx++, fld++) { if (strcmp(fld->name,fieldname) == 0) { found++; break; } } if (!found) return PyTyphoonErr(S_INVFLD); addr = recbuf_o->buf + fld->offset; if (fld->type & FT_VARIABLE) { set_recfld(recbuf_o->rec_o->recId+(fld->keyid - recbuf_o->rec_o->recPtr->first_field + 1),NULL,&fld2); addr2 = recbuf_o->buf + fld2->offset; switch (FT_GETBASIC(fld2->type)) { case FT_SHORT: if (fld2->type & FT_UNSIGNED) num = (int)(* (unsigned short *)addr2); else num = (int)(* (short *)addr2); break; case FT_INT: if (fld2->type & FT_UNSIGNED) num = (int)(* (unsigned int *)addr2); else num = (int)(* (int *)addr2); break; case FT_LONG: if (fld2->type & FT_UNSIGNED) num = (int)(* (unsigned long *)addr2); else num = (int)(* (long *)addr2); break; default: num = 1; break; } } switch (FT_GETBASIC(fld->type)) { case FT_CHAR: rtn_o = PyString_FromStringAndSize((char *)addr,1); break; case FT_CHARSTR: if (fld->type & FT_VARIABLE) { #if 0 PyObject *lst = PyList_New(num); if (lst = NULL) num = 0; while (num--) { if (fld->type & FT_UNSIGNED) rtn = PyList_Append(lst, PyString_FromStringAndSize((char *)(unsigned char *)addr,fld->size)); else rtn = PyList_Append(lst, PyString_FromStringAndSize(addr,fld->size)); if (rtn != 0) num = 0; addr = addr + fld->size; } rtn_o = lst; #else if (fld->type & FT_UNSIGNED) rtn_o = PyString_FromStringAndSize((char *)(unsigned char *)addr,num); else rtn_o = PyString_FromStringAndSize(addr,num); #endif } else { if (fld->type & FT_UNSIGNED) rtn_o = PyString_FromStringAndSize((char *)(unsigned char *)addr, strlen(addr) /*fld->size*/); else rtn_o = PyString_FromStringAndSize(addr,strlen(addr) /*fld->size*/); } break; case FT_SHORT: if (num > 0) { PyObject *lst = PyList_New(num); if (lst = NULL) num = 0; while (num--) { if (fld->type & FT_UNSIGNED) rtn = PyList_Append(lst, PyInt_FromLong((long) *(unsigned short *)addr)); else rtn = PyList_Append(lst, PyInt_FromLong((long) *(short *)addr)); if (rtn != 0) num = 0; addr = addr + fld->size; } rtn_o = lst; } else { if (fld->type & FT_UNSIGNED) rtn_o = PyInt_FromLong((long) *(unsigned short *)addr); else rtn_o = PyInt_FromLong((long) *(short *)addr); } break; case FT_INT: if (num > 0) { PyObject *lst = PyList_New(num); if (lst = NULL) num = 0; while (num--) { if (fld->type & FT_UNSIGNED) rtn = PyList_Append(lst, PyInt_FromLong((long) *(unsigned int *)addr)); else rtn = PyList_Append(lst, PyInt_FromLong((long) *(int *)addr)); if (rtn != 0) num = 0; addr = addr + fld->size; } rtn_o = lst; } else { if (fld->type & FT_UNSIGNED) rtn_o = PyInt_FromLong((long) *(unsigned int *)addr); else rtn_o = PyInt_FromLong((long) *(int *)addr); } break; case FT_LONG: if (num > 0) { PyObject *lst = PyList_New(num); if (lst = NULL) num = 0; while (num--) { if (fld->type & FT_UNSIGNED) rtn = PyList_Append(lst, PyInt_FromLong((long) *(unsigned long *)addr)); else rtn = PyList_Append(lst, PyInt_FromLong((long) *(long *)addr)); if (rtn != 0) num = 0; addr = addr + fld->size; } rtn_o = lst; } else { if (fld->type & FT_UNSIGNED) rtn_o = PyInt_FromLong((long) *(unsigned long *)addr); else rtn_o = PyInt_FromLong((long) *(long *)addr); } break; case FT_FLOAT: if (num > 0) { PyObject *lst = PyList_New(num); if (lst = NULL) num = 0; while (num--) { rtn = PyList_Append(lst, PyFloat_FromDouble((double) *(float *)addr)); if (rtn != 0) num = 0; addr = addr + fld->size; } rtn_o = lst; } else { rtn_o = PyFloat_FromDouble((double) *(float *)addr); } break; case FT_DOUBLE: if (num > 0) { PyObject *lst = PyList_New(num); if (lst = NULL) num = 0; while (num--) { rtn = PyList_Append(lst, PyFloat_FromDouble((double) *(double *)addr)); if (rtn != 0) num = 0; addr = addr + fld->size; } rtn_o = lst; } else { rtn_o = PyFloat_FromDouble((double) *(double *)addr); } break; default: { static char er[80]; sprintf(er,"Unsupported type conversion for type %d", FT_GETSIGNEDBASIC(fld->type)); PyErr_SetString(PyTyphoon_ExcError,er); rtn_o = NULL; break; } } return rtn_o; } static int PyTyphoonRecBuf_SetFieldValue(recbuf_o,fieldname,newval) PyTyphoonRecBufObject *recbuf_o; char *fieldname; PyObject *newval; { char *addr; int rtn; int idx; int ndx; PyObject *rtn_o; Field *fld; int found; int ty; int num=0; /* variable length */ switch (rtn = d_dbset(recbuf_o->rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } fld = recbuf_o->fldPtr; for (idx = 0, found = 0; idx < recbuf_o->rec_o->recPtr->fields; idx++, fld++) { if (strcmp(fld->name,fieldname) == 0) { found++; break; } } if (!found) { PyTyphoonErr(S_INVFLD); return -1; } recbuf_o->valid = 0; addr = recbuf_o->buf + fld->offset; if (fld->type & FT_VARIABLE) { Field *fld2; char *addr2; set_recfld(recbuf_o->rec_o->recId+(fld->keyid - recbuf_o->rec_o->recPtr->first_field + 1),NULL,&fld2); addr2 = recbuf_o->buf + fld2->offset; if (FT_GETBASIC(fld->type) == FT_CHAR || FT_GETBASIC(fld->type) == FT_CHARSTR) { if (PyString_Check(newval)) num = PyString_Size(newval); else { static char er[80]; sprintf(er,"field '%s' needs StringObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } } else { if (!PyList_Check(newval)) num = 1; else num = PyList_Size(newval); } switch (FT_GETBASIC(fld2->type)) { case FT_SHORT: if (fld2->type & FT_UNSIGNED) (* (unsigned short *)addr2) = (unsigned short)num; else (* (short *)addr2) = (short)num;; break; case FT_INT: if (fld2->type & FT_UNSIGNED) (* (unsigned int *)addr2) = (unsigned int)num; else (* (int *)addr2) = (int)num; break; case FT_LONG: if (fld2->type & FT_UNSIGNED) (* (unsigned long *)addr2) = (unsigned long)num; else (* (long *)addr2) = (long)num; break; default: num = 1; break; } } switch (FT_GETBASIC(fld->type)) { case FT_CHAR: case FT_CHARSTR: { if (!PyString_Check(newval)) { static char er[80]; sprintf(er,"field '%s' needs StringObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } if (fld->type & FT_VARIABLE) { memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) strncpy((char *)(unsigned char *)addr, (char *)PyString_AsString(newval), num); else strncpy((char *)addr, (char *)PyString_AsString(newval), num); } else { memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) strncpy((char *)(unsigned char *)addr, (char *)PyString_AsString(newval), fld->size); else strncpy((char *)addr, (char *)PyString_AsString(newval), fld->size); } break; } case FT_SHORT: if (num > 0) { int ndx = 0; while (num--) { if (!PyInt_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs IntObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) *(unsigned short *)addr = (unsigned short)PyInt_AsLong(PyList_GetItem(newval,ndx)); else *(short *)addr = (short)PyInt_AsLong(PyList_GetItem(newval,ndx)); addr = addr + fld->size; ndx++; } } else { memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) *(unsigned short *)addr = (unsigned short)PyInt_AsLong(newval); else *(short *)addr = (short)PyInt_AsLong(newval); } break; case FT_INT: if (num > 0) { int ndx = 0; while (num--) { if (!PyInt_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs IntObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) *(unsigned int *)addr = (unsigned int)PyInt_AsLong(PyList_GetItem(newval,ndx)); else *(int *)addr = (int)PyInt_AsLong(PyList_GetItem(newval,ndx)); addr = addr + fld->size; ndx++; } } else { memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) *(unsigned int *)addr = (unsigned int)PyInt_AsLong(newval); else *(int *)addr = (int)PyInt_AsLong(newval); } break; case FT_LONG: if (num > 0) { int ndx = 0; while (num--) { if (!PyInt_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs IntObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) *(unsigned long *)addr = (unsigned long)PyInt_AsLong(PyList_GetItem(newval,ndx)); else *(long *)addr = (long)PyInt_AsLong(PyList_GetItem(newval,ndx)); addr = addr + fld->size; ndx++; } } else { memset(addr,0,fld->size); if (fld->type & FT_UNSIGNED) *(unsigned long *)addr = (unsigned long)PyInt_AsLong(newval); else *(long *)addr = (long)PyInt_AsLong(newval); } break; case FT_FLOAT: if (num > 0) { int ndx = 0; while (num--) { if (!PyFloat_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs FloatObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } memset(addr,0,fld->size); *(float *)addr = (float)PyFloat_AsDouble(PyList_GetItem(newval,ndx)); addr = addr + fld->size; ndx++; } } else { memset(addr,0,fld->size); *(float *)addr = (float)PyFloat_AsDouble(newval); } break; case FT_DOUBLE: if (num > 0) { int ndx = 0; while (num--) { if (!PyFloat_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs FloatObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); return -1; } memset(addr,0,fld->size); *(double *)addr = (double)PyFloat_AsDouble(PyList_GetItem(newval,ndx)); addr = addr + fld->size; ndx++; } } else { memset(addr,0,fld->size); *(double *)addr = (double)PyFloat_AsDouble(newval); } break; default: { static char er[80]; sprintf(er,"Unsupported type conversion for type %d", FT_GETSIGNEDBASIC(fld->type)); PyErr_SetString(PyTyphoon_ExcError,er); return -1; break; } } return 0; } static PyObject * PyTyphoonRecBuf_Values(self,args) PyTyphoonRecBufObject *self; PyObject *args; { PyObject *list; int idx; PyObject *rtn; Field *fld; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (idx = 0, fld = self->fldPtr; idx < self->rec_o->recPtr->fields; idx++, fld++) { if (rtn = PyTyphoonRecBuf_GetFieldValue(self,fld->name)) PyList_Append(list,rtn); else { Py_DECREF(list); return NULL; } } return list; } static PyObject * PyTyphoonRecBuf_Items(self,args) PyTyphoonRecBufObject *self; PyObject *args; { PyObject *list; PyObject *tuple; int idx; PyObject *rtn; Field *fld; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (idx = 0, fld = self->fldPtr; idx < self->rec_o->recPtr->fields; idx++, fld++) { if (rtn = PyTyphoonRecBuf_GetFieldValue(self,fld->name)) { tuple = PyTuple_New(2); PyTuple_SetItem(tuple,0,PyString_FromString(fld->name)); PyTuple_SetItem(tuple,1,rtn); PyList_Append(list,tuple); } else { Py_DECREF(list); return NULL; } } return list; } static PyObject * PyTyphoonRecBuf_Keys(self,args) PyTyphoonRecBufObject *self; PyObject *args; { PyObject *list; int idx; Field *fld; PyObject *rtn; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (idx = 0, fld = self->fldPtr; idx < self->rec_o->recPtr->fields; idx++, fld++) { if (rtn = PyString_FromString(fld->name)) { PyList_Append(list,rtn); } else { Py_DECREF(list); return NULL; } } return list; } static PyObject * PyTyphoonRecBuf_Has_Key(self,args) PyTyphoonRecBufObject *self; PyObject *args; { char *name; int idx; Field *fld; if (!PyArg_Parse(args,"s", &name) ) return NULL; for (idx = 0, fld = self->fldPtr; idx < self->rec_o->recPtr->fields; idx++, fld++) { if (strcmp(name,fld->name) == 0) return PyInt_FromLong((long)1); } return PyInt_FromLong((long)0); } static PyObject * PyTyphoonRecBuf_IsValid(self,args) PyTyphoonRecBufObject *self; PyObject *args; { char *name; int idx; Field *fld; if (!PyArg_NoArgs(args) ) return NULL; return PyInt_FromLong((long)self->valid); } static PyObject * PyTyphoonRecBuf_Commit(recbuf_o,args) PyTyphoonRecBufObject *recbuf_o; PyObject *args; { int rtn; if (!PyArg_NoArgs(args) ) return NULL; if (recbuf_o->valid == 1) return PyInt_FromLong((long)recbuf_o->valid); switch (rtn = d_dbset(recbuf_o->rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return 0; } if (/*recbuf_o->recAddr.recid == 0 && */ recbuf_o->recAddr.recno == 0) { switch (rtn = d_fillnew(recbuf_o->rec_o->recId, recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); recbuf_o->valid = 0; break; } } else { switch (rtn = d_crset(&recbuf_o->recAddr)) { case S_OKAY: break; default: PyTyphoonErr(rtn); recbuf_o->valid = 0; break; } switch (rtn = d_recwrite(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); recbuf_o->valid = 0; break; } } if (recbuf_o->valid == 0) return NULL; return PyInt_FromLong((long)recbuf_o->valid); } static PyObject * PyTyphoonRecBuf_Delete(recbuf_o,args) PyTyphoonRecBufObject *recbuf_o; PyObject *args; { int rtn; if (!PyArg_NoArgs(args) ) return NULL; switch (rtn = d_dbset(recbuf_o->rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return 0; } if (/*recbuf_o->recAddr.recid == 0 && */ recbuf_o->recAddr.recno != 0) { d_crset(&recbuf_o->recAddr); switch (rtn = d_delete()) { case S_OKAY: recbuf_o->valid = 0; recbuf_o->recAddr.recno = 0; break; default: PyTyphoonErr(rtn); break; } } return PyInt_FromLong((long)recbuf_o->recAddr.recno); } static PyMethodDef PyTyphoonRecBuf_Methods[] = { {"values", (PyCFunction)PyTyphoonRecBuf_Values, 0}, {"items", (PyCFunction)PyTyphoonRecBuf_Items, 0}, {"keys", (PyCFunction)PyTyphoonRecBuf_Keys, 0}, {"has_key", (PyCFunction)PyTyphoonRecBuf_Has_Key, 0}, {"isvalid", (PyCFunction)PyTyphoonRecBuf_IsValid, 0}, {"commit", (PyCFunction)PyTyphoonRecBuf_Commit, 0}, {"delete", (PyCFunction)PyTyphoonRecBuf_Delete, 0}, {NULL, NULL} }; static PyObject * PyTyphoonRecBuf_GetAttr(self, name) PyObject *self; char *name; { return Py_FindMethod(PyTyphoonRecBuf_Methods, self, name); } static void PyTyphoonRecBuf_Dealloc(xp) PyTyphoonRecBufObject *xp; { if (xp->rec_o != NULL) Py_DECREF(xp->rec_o); if (xp->buf != NULL) free(xp->buf); /* Scan through each record and flush it if necessary */ PyMem_DEL(xp); } static PyObject * PyTyphoonRecBuf_Repr(rec) PyTyphoonRecBufObject *rec; { char buf[80]; sprintf(buf,"", rec->recAddr.recno, rec->rec_o->recPtr->name, rec->rec_o->db_o->db->name); return PyString_FromString(buf); } static int PyTyphoonRecBuf_Length(recbuf_o) PyTyphoonRecBufObject *recbuf_o; { unsigned long num; int rtn; switch (rtn = d_dbset(recbuf_o->rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return 0; } return (int)recbuf_o->rec_o->recPtr->fields; } static PyObject * PyTyphoonRecBuf_Subscript(self, args) PyTyphoonRecBufObject *self; PyObject *args; { char *name; if (!PyArg_Parse(args, "s", &name)) return NULL; return PyTyphoonRecBuf_GetFieldValue(self, name); } static int PyTyphoonRecBuf_Ass_Subscript(self, arg1, arg2) PyObject *self, *arg1, *arg2; { char *name; if (!PyArg_Parse(arg1, "s", &name)) return NULL; return PyTyphoonRecBuf_SetFieldValue(self, name, arg2); } static mapping_methods PyTyphoonRecBuf_As_Mapping[] = { (inquiry)PyTyphoonRecBuf_Length, /*mp_length*/ (binaryfunc)PyTyphoonRecBuf_Subscript, /*mp_subscript*/ (objobjargproc)PyTyphoonRecBuf_Ass_Subscript /*mp_ass_subscript*/ }; static PyTypeObject PyTyphoonRecBuf_Type = { OB_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "TyphoonRecordBuffer", /*tp_name*/ sizeof(PyTyphoonRecBufObject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ (destructor)PyTyphoonRecBuf_Dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)PyTyphoonRecBuf_GetAttr, /*tp_getattr*/ (setattrfunc)0 /*PyTyphoonRes_SetAttr*/, /*tp_setattr*/ 0, /*tp_compare*/ (reprfunc)PyTyphoonRecBuf_Repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ PyTyphoonRecBuf_As_Mapping, /*tp_as_mapping*/ 0, /*tp_hash (hashfunc) */ }; /* --------- Record Handling ----------- */ static PyObject * PyTyphoonRec_Keys(rec_o, args) PyTyphoonRecObject *rec_o; PyObject *args; { PyObject *list; int idx; Key *key; PyObject *rtn; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (idx = 0, key = &rec_o->db_o->db->key[rec_o->recPtr->first_key]; idx < rec_o->recPtr->keys; idx++, key++) { if (rtn = PyString_FromString(key->name)) { PyList_Append(list,rtn); } else { Py_DECREF(list); return NULL; } } return list; } static PyObject * PyTyphoonRec_NewFill(rec,args) PyTyphoonRecObject *rec; PyObject *args; { int rtn; int sz = rec->recPtr->size; PyTyphoonRecBufObject *xp; if (args != NULL) if (!PyArg_NoArgs(args)) return NULL; xp = PyObject_NEW(PyTyphoonRecBufObject, &PyTyphoonRecBuf_Type); if (xp == NULL) return NULL; xp->rec_o = rec; Py_INCREF(xp->rec_o); xp->recPtr = rec->recPtr; xp->fldPtr = rec->fldPtr; memset((char *)&xp->recAddr,0,sizeof(xp->recAddr)); xp->buf = (char *)malloc(xp->recPtr->size); if (xp->buf == NULL) { Py_DECREF(xp->rec_o); free(xp); return (PyObject *)PyErr_NoMemory(); } memset(xp->buf,0,xp->recPtr->size); xp->valid = 0; return (PyObject *)xp; } static PyObject * PyTyphoonRec_RecFirst(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_NoArgs(args)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } switch ( rtn = d_recfrst(rec_o->recId) ) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_RecLast(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_NoArgs(args)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } switch (rtn = d_reclast(rec_o->recId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_RecNext(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_NoArgs(args)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } switch (rtn = d_recnext(rec_o->recId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_RecPrev(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_NoArgs(args)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } switch (rtn = d_recprev(rec_o->recId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static char * PyTyphoonRec_KeyFill(rec_o, keyName, keyArgs, keyId) PyTyphoonRecObject *rec_o; char *keyName; PyObject *keyArgs; int *keyId; { char *buf; char *addr; int rtn; int idx; int ndx; Key *key; KeyField *keyFld; int found; Field *fld; PyObject *newval; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } key = &rec_o->db_o->db->key[rec_o->recPtr->first_key]; for (idx = 0, found = 0; idx < rec_o->recPtr->keys; idx++, key++) { if (strcmp(key->name,keyName) == 0) { found++; *keyId = idx + rec_o->recPtr->first_key; break; } } if (!found) { PyTyphoonErr(S_INVFLD); return NULL; } keyFld = &rec_o->db_o->db->keyfield[key->first_keyfield]; if (key->fields > 1) { if (!PyDict_Check(keyArgs)) { PyErr_SetString(PyTyphoon_ExcError,"Dictionary required for compound keys"); return NULL; } } else { if (!(PyFloat_Check(keyArgs) || PyInt_Check(keyArgs) || PyString_Check(keyArgs))) { PyErr_SetString(PyTyphoon_ExcError,"Float, Int, or String type required"); return NULL; } } if ((buf = (char *)malloc(key->size)) == NULL) { PyErr_SetNone(PyExc_MemoryError); return NULL; } else { memset(buf, 0, key->size); } for (idx = 0; idx < key->fields; idx++, keyFld++) { fld = &rec_o->db_o->db->field[keyFld->field]; if (key->fields == 1) { newval = keyArgs; } else { if ((newval = PyDict_GetItemString(keyArgs, fld->name)) == NULL) { static char er[80]; sprintf(er, "cannot lookup values for field named '%s'", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } } addr = buf + keyFld->offset; switch (FT_GETBASIC(fld->type)) { case FT_CHAR: case FT_CHARSTR: if (!PyString_Check(newval)) { static char er[80]; sprintf(er,"index field '%s' needs StringObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } if (fld->type & FT_UNSIGNED) strncpy((char *)(unsigned char *)addr, (char *)PyString_AsString(newval), fld->size); else strncpy((char *)addr, (char *)PyString_AsString(newval), fld->size); break; case FT_SHORT: if (!PyInt_Check(newval)) { static char er[80]; sprintf(er,"field '%s' needs IntObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } if (fld->type & FT_UNSIGNED) *(unsigned short *)addr = (unsigned short)PyInt_AsLong(newval); else *(short *)addr = (short)PyInt_AsLong(newval); break; case FT_INT: if (!PyInt_Check(newval)) { static char er[80]; sprintf(er,"field '%s' needs IntObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } if (fld->type & FT_UNSIGNED) *(unsigned int *)addr = (unsigned int)PyInt_AsLong(newval); else *(int *)addr = (int)PyInt_AsLong(newval); break; case FT_LONG: if (!PyInt_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs IntObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } if (fld->type & FT_UNSIGNED) *(unsigned long *)addr = (unsigned long)PyInt_AsLong(newval); else *(long *)addr = (long)PyInt_AsLong(newval); break; case FT_FLOAT: if (!PyFloat_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs FloatObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } *(float *)addr = (float)PyFloat_AsDouble(newval); break; case FT_DOUBLE: if (!PyFloat_Check(PyList_GetItem(newval,ndx))) { static char er[80]; sprintf(er,"field '%s' needs FloatObject", fld->name); PyErr_SetString(PyTyphoon_ExcError, er); free(buf); return NULL; } *(double *)addr = (double)PyFloat_AsDouble(newval); break; default: { static char er[80]; sprintf(er,"Unsupported type conversion for type %d", FT_GETSIGNEDBASIC(fld->type)); PyErr_SetString(PyTyphoon_ExcError,er); free(buf); return NULL; break; } } } return buf; } static PyObject * PyTyphoonRec_KeyFind(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; PyTyphoonRecBufObject *recbuf_o; int keyId; char *keyBuf; char *keyName; PyObject *keyArgs; if (!PyArg_Parse(args, "(sO)", &keyName, &keyArgs)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } if ((keyBuf = PyTyphoonRec_KeyFill(rec_o,keyName,keyArgs,&keyId)) == NULL) return NULL; switch (rtn = d_keyfind(keyId, keyBuf)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); free(keyBuf); return NULL; } break; default: free(keyBuf); PyTyphoonErr(rtn); return NULL; } free(keyBuf); return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_KeyFirst(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; Key *key; int idx; int keyId; int found; char *keyName; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_Parse(args,"s",&keyName)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } key = &rec_o->db_o->db->key[rec_o->recPtr->first_key]; for (idx = 0, found = 0; idx < rec_o->recPtr->keys; idx++, key++) { if (strcmp(key->name,keyName) == 0) { found++; keyId = idx + rec_o->recPtr->first_key; break; } } if (!found) { PyTyphoonErr(S_INVKEY); return NULL; } switch (rtn = d_keyfrst(keyId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_KeyLast(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; Key *key; int idx; int keyId; int found; char *keyName; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_Parse(args,"s",&keyName)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } key = &rec_o->db_o->db->key[rec_o->recPtr->first_key]; for (idx = 0, found = 0; idx < rec_o->recPtr->keys; idx++, key++) { if (strcmp(key->name,keyName) == 0) { found++; keyId = idx + rec_o->recPtr->first_key; break; } } if (!found) { PyTyphoonErr(S_INVKEY); return NULL; } switch (rtn = d_keylast(keyId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_KeyNext(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; Key *key; int idx; int keyId; int found; char *keyName; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_Parse(args,"s",&keyName)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } key = &rec_o->db_o->db->key[rec_o->recPtr->first_key]; for (idx = 0, found = 0; idx < rec_o->recPtr->keys; idx++, key++) { if (strcmp(key->name,keyName) == 0) { found++; keyId = idx + rec_o->recPtr->first_key; break; } } if (!found) { PyTyphoonErr(S_INVKEY); return NULL; } switch (rtn = d_keynext(keyId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyObject * PyTyphoonRec_KeyPrev(rec_o,args) PyTyphoonRecObject *rec_o; PyObject *args; { int rtn; Key *key; int idx; int keyId; int found; char *keyName; PyTyphoonRecBufObject *recbuf_o; if (!PyArg_Parse(args,"s",&keyName)) return NULL; switch (rtn = d_dbset(rec_o->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } key = &rec_o->db_o->db->key[rec_o->recPtr->first_key]; for (idx = 0, found = 0; idx < rec_o->recPtr->keys; idx++, key++) { if (strcmp(key->name,keyName) == 0) { found++; keyId = idx + rec_o->recPtr->first_key; break; } } if (!found) { PyTyphoonErr(S_INVKEY); return NULL; } switch (rtn = d_keyprev(keyId)) { case S_OKAY: recbuf_o = (PyTyphoonRecBufObject *)PyTyphoonRec_NewFill(rec_o,NULL); if (recbuf_o == NULL) return NULL; switch (rtn = d_recread(recbuf_o->buf)) { case S_OKAY: recbuf_o->valid = 1; d_crget(&recbuf_o->recAddr); break; default: PyTyphoonErr(rtn); Py_DECREF(recbuf_o); return NULL; } break; default: PyTyphoonErr(rtn); return NULL; } return (PyObject *)recbuf_o; } static PyMethodDef PyTyphoonRec_Methods[] = { {"keys", (PyCFunction)PyTyphoonRec_Keys, 0}, {"new", (PyCFunction)PyTyphoonRec_NewFill, 0}, {"recfirst", (PyCFunction)PyTyphoonRec_RecFirst, 0}, {"reclast", (PyCFunction)PyTyphoonRec_RecLast, 0}, {"recnext", (PyCFunction)PyTyphoonRec_RecNext, 0}, {"recprev", (PyCFunction)PyTyphoonRec_RecPrev, 0}, {"find", (PyCFunction)PyTyphoonRec_KeyFind, 0}, {"keyfirst", (PyCFunction)PyTyphoonRec_KeyFirst, 0}, {"keylast", (PyCFunction)PyTyphoonRec_KeyLast, 0}, {"keynext", (PyCFunction)PyTyphoonRec_KeyNext, 0}, {"keyprev", (PyCFunction)PyTyphoonRec_KeyPrev, 0}, {NULL, NULL} }; static PyObject * PyTyphoonRec_GetAttr(self, name) PyObject *self; char *name; { return Py_FindMethod(PyTyphoonRec_Methods, self, name); } static PyObject * PyTyphoonRec_New(db_o, name) PyTyphoonDbObject *db_o; char *name; { PyTyphoonRecObject *xp; Record *r = db_o->db->record; int ndx = 0; int num = db_o->db->header.records; int found = 0; int rtn; switch (rtn = d_dbset(db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return NULL; } for (; ndx <= num; ndx++, r++) { if (strcmp(r->name, name) == 0) { found++; break; } } if (!found) { return PyTyphoonErr(S_INVREC); } xp = PyObject_NEW(PyTyphoonRecObject, &PyTyphoonRec_Type); if (xp == NULL) return NULL; xp->db_o = db_o; Py_INCREF(xp->db_o); xp->recPtr = r; xp->recId = INTERN_TO_RECID(ndx); set_recfld(xp->recId,NULL,&xp->fldPtr); return (PyObject *)xp; } static void PyTyphoonRec_Dealloc(xp) PyTyphoonRecObject *xp; { if (xp->db_o != NULL) Py_DECREF(xp->db_o); PyMem_DEL(xp); } static PyObject * PyTyphoonRec_Repr(rec) PyTyphoonRecObject *rec; { char buf[80]; sprintf(buf,"", rec->recPtr->name, rec->db_o->db->name); return PyString_FromString(buf); } static int PyTyphoonRec_Length(rec) PyTyphoonRecObject *rec; { unsigned long num; int rtn; switch (rtn = d_dbset(rec->db_o->db_num)) { case S_OKAY: break; default: PyTyphoonErr(rtn); return 0; } switch (rtn = d_records(rec->recId, &num)) { case S_OKAY: return (int)num; default: PyTyphoonErr(rtn); return 0; } } static PyObject * PyTyphoonRec_Subscript(self, args) PyObject *self; PyObject *args; { PyErr_SetString(PyTyphoon_ExcError,"subscripting not allowed for TyphoonRecord objects"); return NULL; } static int PyTyphoonRec_Ass_Subscript(self, arg1, arg2) PyObject *self, *arg1, *arg2; { PyErr_SetString(PyTyphoon_ExcError,"subscripting not allowed for TyphoonRecord objects"); return -1; } static mapping_methods PyTyphoonRec_As_Mapping[] = { (inquiry)PyTyphoonRec_Length, /*mp_length*/ (binaryfunc)PyTyphoonRec_Subscript, /*mp_subscript*/ (objobjargproc)PyTyphoonRec_Ass_Subscript /*mp_ass_subscript*/ }; static PyTypeObject PyTyphoonRec_Type = { OB_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "TyphoonRecord", /*tp_name*/ sizeof(PyTyphoonRecObject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ (destructor)PyTyphoonRec_Dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)PyTyphoonRec_GetAttr, /*tp_getattr*/ (setattrfunc)0 /*PyTyphoonRes_SetAttr*/, /*tp_setattr*/ 0, /*tp_compare*/ (reprfunc)PyTyphoonRec_Repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ PyTyphoonRec_As_Mapping, /*tp_as_mapping*/ 0, /*tp_hash (hashfunc) */ }; /* ------ Database handling ------ */ static PyObject * PyTyphoonDb_ListRecs(self,args) PyTyphoonDbObject *self; PyObject *args; { PyObject *list; int ndx = 0; int idx = self->db->header.records; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (; ndx < idx; ndx++) PyList_Append(list,PyString_FromString(self->db->record[ndx].name)); return list; } static PyObject * PyTyphoonDb_ListSeqs(self,args) PyTyphoonDbObject *self; PyObject *args; { PyObject *list; int ndx = 0; int idx = self->db->header.sequences; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (; ndx < idx; ndx++) PyList_Append(list,PyString_FromString(self->db->sequence[ndx].name)); return list; } static PyObject * PyTyphoonDb_Values(self,args) PyTyphoonDbObject *self; PyObject *args; { PyObject *list; int ndx; int idx; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (ndx = 0, idx = self->db->header.records; ndx < idx; ndx++) PyList_Append(list,PyTyphoonRec_New(self,self->db->record[ndx].name)); for (ndx = 0, idx = self->db->header.sequences; ndx < idx; ndx++) PyList_Append(list,PyTyphoonSeq_New(self,self->db->sequence[ndx].name)); return list; } static PyObject * PyTyphoonDb_Items(self,args) PyTyphoonDbObject *self; PyObject *args; { PyObject *list; PyObject *tuple; int ndx; int idx; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (ndx = 0, idx = self->db->header.records; ndx < idx; ndx++) { tuple = PyTuple_New(2); PyTuple_SetItem(tuple,0,PyString_FromString(self->db->record[ndx].name)); PyTuple_SetItem(tuple,1,PyTyphoonRec_New(self,self->db->record[ndx].name)); PyList_Append(list,tuple); } for (ndx = 0, idx = self->db->header.sequences; ndx < idx; ndx++) { tuple = PyTuple_New(2); PyTuple_SetItem(tuple,0,PyString_FromString(self->db->sequence[ndx].name)); PyTuple_SetItem(tuple,1,PyTyphoonSeq_New(self,self->db->sequence[ndx].name)); PyList_Append(list,tuple); } return list; } static PyObject * PyTyphoonDb_Keys(self,args) PyTyphoonDbObject *self; PyObject *args; { PyObject *list; int ndx; int idx; if (!PyArg_NoArgs(args)) return NULL; if (!(list = PyList_New(0))) return NULL; for (ndx = 0, idx = self->db->header.records; ndx < idx; ndx++) PyList_Append(list,PyString_FromString(self->db->record[ndx].name)); for (ndx = 0, idx = self->db->header.sequences; ndx < idx; ndx++) PyList_Append(list,PyString_FromString(self->db->sequence[ndx].name)); return list; } static PyObject * PyTyphoonDb_Has_Key(self,args) PyTyphoonDbObject *self; PyObject *args; { char *name; int ndx; int idx; if (!PyArg_Parse(args,"s", &name) ) return NULL; for (ndx = 0, idx = self->db->header.records; ndx < idx; ndx++) if (strcmp(name, self->db->record[ndx].name) == 0) return PyInt_FromLong((long)1); for (ndx = 0, idx = self->db->header.sequences; ndx < idx; ndx++) if (strcmp(name, self->db->sequence[ndx].name) == 0) return PyInt_FromLong((long)1); return PyInt_FromLong((long)0); } static PyMethodDef PyTyphoonDb_Methods[] = { {"records", (PyCFunction)PyTyphoonDb_ListRecs}, {"sequences", (PyCFunction)PyTyphoonDb_ListSeqs}, {"values", (PyCFunction)PyTyphoonDb_Values}, {"items", (PyCFunction)PyTyphoonDb_Items}, {"keys", (PyCFunction)PyTyphoonDb_Keys}, {"has_key", (PyCFunction)PyTyphoonDb_Has_Key}, {NULL, NULL} /* sentinel */ }; static void PyTyphoonDb_Dealloc(xp) PyTyphoonDbObject *xp; { if (d_dbset(xp->db_num) == S_OKAY) d_close(); PyMem_DEL(xp); } static PyObject * PyTyphoonDb_Repr(db_o) PyTyphoonDbObject *db_o; { char buf[80]; sprintf(buf,"", db_o->db->name, (db_o->db->mode == 's' ? "shared" : "exclusive")); return PyString_FromString(buf); } static PyObject * PyTyphoonDb_GetAttr(self, name) PyObject *self; char *name; { return Py_FindMethod(PyTyphoonDb_Methods, self, name); } static int PyTyphoonDb_Length(self) PyTyphoonDbObject *self; { return self->db->header.records + self->db->header.sequences; } static PyObject * PyTyphoonDb_Subscript( self, key ) PyTyphoonDbObject *self; PyObject *key; { char *rec_name; PyObject *rtn; if ( !PyArg_Parse(key,"s", &rec_name) ) return NULL; rtn = PyTyphoonSeq_New(self, rec_name); if (rtn == (PyObject *)NULL) { PyErr_Clear(); rtn = PyTyphoonRec_New(self, rec_name); } return rtn; } static mapping_methods PyTyphoonDb_As_Mapping[] = { (inquiry)PyTyphoonDb_Length, /*mp_length*/ (binaryfunc)PyTyphoonDb_Subscript, /*mp_subscript*/ (objobjargproc)0, /*mp_ass_subscript*/ }; static PyTypeObject PyTyphoonDb_Type = { OB_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "TyphoonDb", /*tp_name*/ sizeof(PyTyphoonDbObject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ (destructor)PyTyphoonDb_Dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)PyTyphoonDb_GetAttr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ (reprfunc)PyTyphoonDb_Repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ PyTyphoonDb_As_Mapping, /*tp_as_mapping*/ 0, /*tp_hash (hashfunc) */ }; static PyObject * PyTyphoon_Open(self, args) PyObject *self; PyObject *args; { char *db_name; char *db_mode; PyTyphoonDbObject *xp; int rtn; if ( !PyArg_Parse(args,"(ss)", &db_name, &db_mode) ) return NULL; switch (rtn = d_open(db_name, db_mode)) { case S_OKAY: break; default: return PyTyphoonErr(rtn); } /* Must be S_OKAY so let's prepare the rest */ xp = PyObject_NEW(PyTyphoonDbObject, &PyTyphoonDb_Type); if (xp == NULL) return NULL; d_dbget(&xp->db_num); xp->db = &typhoon.dbtab[xp->db_num]; return (PyObject *)xp; } static PyObject * PyTyphoon_SetDBFPath(self, args) PyObject *self; PyObject *args; { char *path; if ( !PyArg_Parse(args,"s", &path) ) return NULL; d_dbfpath(path); Py_INCREF(Py_None); return Py_None; } static PyObject * PyTyphoon_SetDBDPath(self, args) PyObject *self; PyObject *args; { char *path; if ( !PyArg_Parse(args,"s", &path) ) return NULL; d_dbdpath(path); Py_INCREF(Py_None); return Py_None; } static PyObject * PyTyphoon_SetFiles(self, args) PyObject *self; PyObject *args; { int maxfiles; int rtn; if ( !PyArg_Parse(args,"i", &maxfiles) ) return NULL; switch(rtn = d_setfiles(maxfiles)) { case S_OKAY: Py_INCREF(Py_None); return Py_None; default: return PyTyphoonErr(rtn); } } /* List of functions defined in the module */ static PyMethodDef PyTyphoon_Methods[] = { {"open", PyTyphoon_Open, 0}, {"setdbfpath", PyTyphoon_SetDBFPath, 0}, {"setdbdpath", PyTyphoon_SetDBDPath, 0}, {"setfiles", PyTyphoon_SetFiles, 0}, NULL, NULL /* sentinel */ }; /* Initialization function for the module (*must* be called initxx) */ static char PyTyphoon_Doc[] = "Python interface to the 1.10.3 version of \n\ the Typhoon Database engine."; void inittyphoon() { PyObject *m, *d; /* Create the module and add the functions */ m = Py_InitModule4("typhoon", PyTyphoon_Methods, PyTyphoon_Doc, (PyObject *)NULL, PYTHON_API_VERSION); /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); PyTyphoon_ExcError = PyString_FromString("typhoon.error"); PyDict_SetItemString(d, "error", PyTyphoon_ExcError); PyTyphoon_Version = PyString_FromString(PyTyphoon_VERSION); PyDict_SetItemString(d, "__version__", PyTyphoon_Version); /* Check for errors */ if (PyErr_Occurred()) Py_FatalError("can't initialize module typhoon"); }