This is IEMappedFile.m in view mode; [Download] [Up]
// 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.