/* * $Id: sdbm.c,v 1.10 1997/05/21 20:47:59 laughton Exp laughton $ * *--------------------------------------------------------------------------- * * Peter J. Laughton * AECL * Chalk River Laboratories * Chalk River, Ontario * CANADA K0J 1J0 * * Phone: (613) 584-8811, extension 4267 * FAX: (613) 584-1108 * * Internet: laughtonp@crl.aecl.ca * *--------------------------------------------------------------------------- * * Revision history (as of 1995 October 25): * * $Log: sdbm.c,v $ * Revision 1.11 99/03/11 17:03:56 17:03:56 laughton * proper type-dependent calloc calls now used * * Revision 1.10 1997/05/21 20:47:59 laughton * maximum number of records in one file doubled * * Revision 1.9 1996/12/19 19:34:56 laughton * Intel-x86/Windows95 support added (the list sep is a ';', not a ':') * * Revision 1.8 1996/06/28 13:04:34 laughton * support for NDAS file conversion started * * Revision 1.7 1995/12/12 22:21:27 laughton * more GDBM updates * * Revision 1.6 1995/12/07 20:10:45 laughton * minor SGI compiler warnings rectified * * Revision 1.5 1995/12/05 21:08:47 laughton * emitTitle bug fixed. * * Revision 1.4 1995/12/04 14:46:12 laughton * continuing development * * Revision 1.3 1995/12/01 21:27:19 laughton * more error handling and identification of library titles * * Revision 1.2 1995/11/30 20:22:37 laughton * continuing development * * Revision 1.1 1995/11/07 16:32:06 laughton * Initial revision * */ #include #include #include #include "sdbm.h" #define MAXKEYLENGTH 64 #define StringTypeC 8 #define MAKE_ARRAY(thing,number) \ ((thing *) calloc((unsigned) (number),sizeof(thing))) static int magicNumber=0x198802ab; /* file-type marker */ typedef struct { char key[MAXKEYLENGTH+1]; /* string of printable characters */ int dataType; /* numeric flag indicating real, integer, etc */ int size; /* in bytes */ int dataOffset; /* from the beginning of the file */ } HeaderElement; typedef struct { char *filename; FILE *filePointer; int nValidRecords; /* > 0 means active */ HeaderElement *header; } SDBFile; #define size_HE (sizeof(HeaderElement)) #define MAXDBFILES 10 #define MAXFNLENGTH 100 static SDBFile dbFile[MAXDBFILES]; static int dbfCount=0; static int initReadF=0; /* =============================================== */ /* Prototypes of static functions appearing below: */ /* =============================================== */ static int installDBF(char *filename); static int compareHeaderElements(const void *h1, const void *h2); static int searchHeader(HeaderElement *header, char *searchKey, int n); /* =============================================== */ int initRead(char *flist) { int i; char nbuf[MAXFNLENGTH+1]; int fc, lc; int retval; char flistSep; #ifdef PC_TargetCPU flistSep=';'; #else flistSep=':'; #endif initReadF=1; for (i=0; i MAXFNLENGTH) return FixedLimitExceeded; strncpy(nbuf, flist+fc, lc-fc); nbuf[lc-fc]='\0'; retval=installDBF(nbuf); if (retval) return retval; /* non-zero is an error code */ fc=lc; } emitTitles(); return 0; /* success */ } int countRecs(int *nRecs, int dbFileIndex) { *nRecs=0; if (dbFileIndex < 0 || dbFileIndex > MAXDBFILES-1) return BadFile; *nRecs=dbFile[dbFileIndex].nValidRecords; return 0; /* success */ } static int installDBF(char *filename) { int mn=0; int i; /* Later, add a check to make sure this is not a new file. */ if (dbfCount >= MAXDBFILES) return FixedLimitExceeded; dbFile[dbfCount].filename=strdup(filename); if (!dbFile[dbfCount].filename) return MemoryAllocFailure; dbFile[dbfCount].filePointer=fopen(filename,"rb"); if (!dbFile[dbfCount].filePointer) return OpenFailure; /* Check that the magic number is present. */ if(fread(&mn,sizeof(int),1,dbFile[dbfCount].filePointer) < 1) goto L10; if (mn!=magicNumber) return BadFile; if(fread(&dbFile[dbfCount].nValidRecords, sizeof(int), 1, dbFile[dbfCount].filePointer) < 1) goto L10; dbFile[dbfCount].header=MAKE_ARRAY(HeaderElement, dbFile[dbfCount].nValidRecords); if (!dbFile[dbfCount].header) return MemoryAllocFailure; /* Load the header into memory (for now) */ for (i=0; i < dbFile[dbfCount].nValidRecords; i++) if(fread(&dbFile[dbfCount].header[i], size_HE, 1, dbFile[dbfCount].filePointer) < 1) goto L10; dbfCount++; return 0; /* success */ L10: printf("\n XSDB error 1: fread failure -- %s\n",filename); fflush(stdout); exit(1); } static int compareHeaderElements(const void *h1, const void *h2) { return strcmp(((HeaderElement *)h1)->key, ((HeaderElement *)h2)->key); } void closeSDBRead() { int i,irc; for (i=0; i= l) { midPoint=(l+u)/2; /* floor results automatically */ sign=strcmp(searchKey,header[midPoint].key); if (sign < 0) u=midPoint-1; else if (sign > 0) l=midPoint+1; else return midPoint; } return FAIL; } datum readRecord(char *recordName) { int keyIndex; datum record; int nbytes; int i; int found=0; /* Failure is indicated if these values remain intact on exit. */ record.dptr=0; record.dsize=0; if (!initReadF) return record; for (i=0; i> 2, 4); if (!record.dptr) return record; record.dsize=nbytes; /* Jump to the location in the file and read the record into memory. */ fseek(dbFile[i].filePointer, dbFile[i].header[keyIndex].dataOffset, SEEK_SET); if(fread((char*)record.dptr, 1, nbytes, dbFile[i].filePointer) < 1) goto L10; return record; L10: printf("\n XSDB error: fread failure 2 -- %s\n",recordName); fflush(stdout); exit(1); } datum readIndexedRecord(int keyIndex, int dbFileIndex, char *recordKey, int *dataType) { datum record; int nbytes; /* Failure is indicated if these values remain intact on exit. */ record.dptr=0; record.dsize=0; if (dbFileIndex < 0 || dbFileIndex > MAXDBFILES-1) return record; if (!initReadF) return record; if (keyIndex >= dbFile[dbFileIndex].nValidRecords) return record; strcpy(recordKey, dbFile[dbFileIndex].header[keyIndex].key); *dataType=dbFile[dbFileIndex].header[keyIndex].dataType; nbytes=dbFile[dbFileIndex].header[keyIndex].size; if (*dataType == StringTypeC) record.dptr=calloc(nbytes, 1); else record.dptr=calloc(nbytes >> 2, 4); if (!record.dptr) return record; record.dsize=nbytes; /* Jump to the location in the file and read the record into memory. */ fseek(dbFile[dbFileIndex].filePointer, dbFile[dbFileIndex].header[keyIndex].dataOffset, SEEK_SET); if(fread((char*)record.dptr, 1, nbytes, dbFile[dbFileIndex].filePointer) < 1) goto L10; return record; L10: printf("\n XSDB error: fread failure 3 -- %s\n",recordKey); fflush(stdout); exit(1); } void emitTitles() { int keyIndex; datum record; int i; for (i=0; i MAXKEYLENGTH) return InvalidKey; strcat(header[writeRecordIndex].key,recordName); header[writeRecordIndex].dataType=dataType; header[writeRecordIndex].size=nbytes; header[writeRecordIndex].dataOffset=nextDataOffset; offset=nbytes; fseek(sdbFile,offset,SEEK_END); /* extend the file */ fseek(sdbFile,nextDataOffset,SEEK_SET); /* position for write */ fwrite((char*)data, 1, nbytes, sdbFile); writeRecordIndex++; nextDataOffset+=offset; return 0; }