home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula
/
nebula.bin
/
SourceCode
/
Classes
/
IEMappedFile
/
IEMappedFile.m
< prev
next >
Wrap
Text File
|
1993-01-26
|
3KB
|
179 lines
// 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