home *** CD-ROM | disk | FTP | other *** search
- // IEMappedFile.m by Monty Zukowski 1/21/93 version 1.0
- //Copyright 1993 Intuitive Edge
- //You are free to use and modify this as long as you acknowledge me in your
- //program somewhere
-
- #import"IEMappedFile.h"
- #import<objc/HashTable.h>
- #import<objc/hashtable.h>
- #import <libc.h>
-
- @implementation IEMappedFile
-
- static HashTable *hash=nil;
-
- +_removeFromHashTable:(IEMappedFile *)obj
- {
- [hash removeKey:[obj name]];
- return self;
- }
-
- +_addName:(NXAtom) theName andObject:obj
- {//returns nil if name is already in the table, otherwise
- // it puts name and obj in the table and returns self.
- if (!hash)
- hash=[[HashTable alloc] initKeyDesc:"%" valueDesc:"@"];
- if (![hash valueForKey:theName])
- {
- [hash insertKey: theName value:obj];
- return self;
- }
- else
- return nil;
- }
-
- +(HashTable *) instances { return hash; }
-
- +newForFilename:(const char *) filename
- {
- NXAtom theAtom=NXUniqueString(filename);
- IEMappedFile *instance;
-
- if (!hash)
- hash=[[HashTable alloc] initKeyDesc:"%" valueDesc:"@"];
- if (instance=[hash valueForKey:theAtom])
- return instance;
- else
- {
- instance=[super new];
- instance->name=theAtom;
- if ([instance _initFromName])
- {
- [hash insertKey:theAtom value:instance];
- return instance;
- }
- else
- {
- [instance free];
- return nil;
- }
- }
- }
-
- -free
- {
- [IEMappedFile _removeFromHashTable:self];
- if (fd>=0)
- close(fd);
- return [super free];
- }
-
- -(const void *) data { return data; }
-
- -(const void *) dataUpdated
- {
- struct stat sbuf;
-
- if (fd>=0)
- {
- if (fstat(fd,&sbuf)!=0) //!=0 means fstat failed
- {
- [self _inactivate];
- }
- else
- if (sbuf.st_mtime!=lastModifyTime)
- {
- [self _initFromName];
- }
- }
- else
- { //fd was invalid, see if it is fixed now
- [self _initFromName];
- }
- return data;
- }
-
- -(int) fd { return fd; }
-
- -(int) size { return size; }
-
- -(NXAtom) name { return name; }
-
- -(time_t) lastModifyTime { return lastModifyTime; }
-
-
- -write:(NXTypedStream *) typedStream
- {
- [super write:typedStream];
- NXWriteType(typedStream,"%",&name);
- return self;
- }
-
- -read:(NXTypedStream *) typedStream
- {
- NXReadType(typedStream,"%",&name);
- [self _initFromName];
- return self;
- }
-
- -finishUnarchiving
- {
- /* This is needed to guarantee that if an IEMappedFile object gets archived
- more than once, on unarchiving there will still only be one object per
- filename.
- */
-
- if ([IEMappedFile _addName:name andObject:self])
- return nil;//returning nil means ok to use self, see Object docs
- else
- {//dont use [self free] because it would remove the name from the hashtable
- NXAtom theName=[self name];
- if (fd>=0)
- close(fd);
- [super free];
- return [IEMappedFile newForFilename:theName];
- }
- }
-
- -_initFromName
- {//returns self if successful, nil otherwise
- struct stat sbuf;
-
- if (stat(name,&sbuf)==0)
- {
- if ((fd=open(name,O_RDONLY,0444))>=0)
- {
- if (map_fd(fd,(vm_offset_t) 0, &(vm_offset_t)data,TRUE,
- (vm_size_t) sbuf.st_size) == KERN_SUCCESS)
- {
- size=sbuf.st_size;
- lastModifyTime=sbuf.st_mtime;
- }
- else
- { //map_fd failed
- [self _inactivate];
- return nil;
- }
- }
- else
- { //couldn't open() name
- [self _inactivate];
- return nil;
- }
- }
- else //couldn't stat name
- {
- [self _inactivate];
- return nil;
- }
- return self;
- }
- -_inactivate
- {
- fd = -1;
- size = 0;
- data = NULL;
- lastModifyTime = 0;
- return self;
- }
- @end