home *** CD-ROM | disk | FTP | other *** search
- /* File: HashFile.m - db(3) to HashTable bridge
- *
- * By: Christopher Lane
- * Symbolic Systems Resources Group
- * Knowledge Systems Laboratory
- * Stanford University
- *
- * Date: 10 September 1991
- *
- * Copyright: 1990, 1991 by The Leland Stanford Junior University. This
- * program may be distributed without restriction for non-commercial use.
- */
-
- #import <c.h>
- #import <libc.h>
- #import <string.h>
- #import <assert.h>
-
- #import "HashFile.h"
-
- #define OBJECT @encode(id)
-
- #define NXRewind(stream) NXSeek(stream, 0L, NX_FROMSTART)
-
- @implementation HashFile
-
- + (BOOL) isHashFile:(const char *) name
- {
- return dbExists((char *) name);
- }
-
- - initFromFile:(const char *) name
- {
- return [self initFromFile:name keyDesc:OBJECT valueDesc:OBJECT];
- }
-
- - initFromFile:(const char *) name keyDesc:(const char *) aKeyDesc
- {
- return [self initFromFile:name keyDesc:aKeyDesc valueDesc:OBJECT];
- }
-
- - initFromFile:(const char *) name keyDesc:(const char *) aKeyDesc valueDesc:(const char *) aValueDesc
- {
- NXTypedStream *typedStream;
-
- [self initKeyDesc:aKeyDesc valueDesc:aValueDesc];
-
- if((db = dbOpen(filename = (char *) name)) == NULL) {
- [self free];
- return nil;
- }
-
- readOnly = (BOOL) ((db->flag & (dbFlagReadOnly | dbFlagCompressed)) != 0);
-
- assert(d.k.s = (char *) malloc((size_t) LEAFSIZE));
- assert(d.c.s = (char *) malloc((size_t) LEAFSIZE));
-
- d.k.n = malloc_size(d.k.s);
- d.c.n = malloc_size(d.c.s);
-
- assert(stream = NXOpenMemory(NULL, 0, NX_READWRITE));
- assert(typedStream = NXOpenTypedStream(stream, NX_WRITEONLY));
- offset = NXTell(stream);
- NXCloseTypedStream(typedStream);
-
- return self;
- }
-
- - free
- {
- free(d.k.s);
- free(d.c.s);
- NXCloseMemory(stream, NX_FREEBUFFER);
- assert(dbClose(db));
-
- return [super free];
- }
-
- - empty
- {
- if(!readOnly && dbClose(db) && dbCreate(filename) && (db = dbInit(filename)) != NULL) return [super empty];
-
- return nil;
- }
-
- - (unsigned) count
- {
- unsigned i = 0;
-
- if(dbFirst(db, &d) && d.k.n > 0) do { ++i; } while(dbNext(db, &d));
-
- assert(i >= count);
-
- return i;
- }
-
- - (BOOL) isKey:(const void *) aKey
- {
- if([super isKey:aKey]) return YES;
-
- [self _keyCvtIn:aKey];
-
- return((BOOL) dbFind(db, &d));
- }
-
- - (void *) valueForKey:(const void *) aKey
- {
- void *value = (void *) nil;
-
- if([super isKey:aKey]) return [super valueForKey:aKey];
-
- [self _keyCvtIn:aKey];
-
- if(dbFetch(db, &d)) [super insertKey:[self _keyCvtOut] value:(value = [self _valueCvtOut])];
-
- return value;
- }
-
- - (void *) insertKey:(const void *) aKey value:(void *) aValue
- {
- if(readOnly) return (void *) nil;
-
- [self _keyCvtIn:aKey];
- [self _valueCvtIn:aValue];
-
- if(!dbStore(db, &d)) return (void *) nil;
-
- return [super insertKey:aKey value:aValue];
- }
-
- - (void *) removeKey:(const void *) aKey;
- {
- if(readOnly) return (void *) nil;
-
- [self _keyCvtIn:aKey];
- if(!dbDelete(db, &d)) return (void *) nil;
-
- return([super removeKey:aKey]);
- }
-
- - (NXHashState) initState
- {
- NXHashState state = [super initState];
-
- if(state.i = dbFirst(db, &d)) {
- state.i = d.k.n;
- state.j = d.c.n;
- }
-
- return state;
- }
-
- - (BOOL) nextState:(NXHashState *) aState key:(const void **) aKey value:(void **) aValue
- {
- if(aState->i == FALSE) return NO;
-
- d.k.n = aState->i;
- d.c.n = aState->j;
-
- if(dbGet(db, &d)) {
- *aKey = [self _keyCvtOut];
- *aValue = [self _valueCvtOut];
- }
- else return NO;
-
- if(aState->i = dbNext(db, &d)) {
- aState->i = d.k.n;
- aState->j = d.c.n;
- }
-
- return YES;
- }
-
- - (void) _keyCvtIn:(const void *) aKey
- {
- [self _datumCvtIn:&d.k from:aKey using:keyDesc];
- }
-
- - (void) _valueCvtIn:(const void *) aValue
- {
- [self _datumCvtIn:&d.c from:aValue using:valueDesc];
- }
-
- - (void) _datumCvtIn:(Datum *) aDatum from:(const void *) aBuffer using:(const char *) aDesc
- {
- NXTypedStream *typedStream;
-
- NXRewind(stream);
-
- assert(typedStream = NXOpenTypedStream(stream, NX_WRITEONLY));
-
- offset = NXTell(stream);
-
- NXWriteType(typedStream, aDesc, &aBuffer);
-
- aDatum->n = NXTell(stream) - offset;
-
- NXCloseTypedStream(typedStream);
-
- NXSeek(stream, offset, NX_FROMSTART);
-
- NXRead(stream, (void *) aDatum->s, aDatum->n);
- }
-
- - (void *) _keyCvtOut
- {
- return [self _datumCvtOut:&d.k using:keyDesc];
- }
-
- - (void *) _valueCvtOut
- {
- return [self _datumCvtOut:&d.c using:valueDesc];
- }
-
- - (void *) _datumCvtOut:(Datum *) aDatum using:(const char *) aDesc
- {
- NXTypedStream *typedStream;
- void *buffer;
-
- assert(buffer = (void *) malloc((size_t) aDatum->n));
-
- NXSeek(stream, offset, NX_FROMSTART);
-
- NXWrite(stream, (void *) aDatum->s, aDatum->n);
-
- NXRewind(stream);
-
- assert(typedStream = NXOpenTypedStream(stream, NX_READONLY));
-
- NXReadType(typedStream, aDesc, &buffer);
-
- NXCloseTypedStream(typedStream);
-
- return buffer;
- }
-
- @end
-