1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#import "CSMultiHandle.h"
NSString *CSSizeOfSegmentUnknownException=@"CSSizeOfSegmentUnknownException";
@implementation CSMultiHandle
+(CSMultiHandle *)multiHandleWithHandleArray:(NSArray *)handlearray
{
if(!handlearray) return nil;
int count=[handlearray count];
if(count==0) return nil;
else if(count==1) return [handlearray objectAtIndex:0];
else return [[[self alloc] initWithHandles:handlearray] autorelease];
}
+(CSMultiHandle *)multiHandleWithHandles:(CSHandle *)firsthandle,...
{
if(!firsthandle) return nil;
NSMutableArray *array=[NSMutableArray arrayWithObject:firsthandle];
CSHandle *handle;
va_list va;
va_start(va,firsthandle);
while((handle=va_arg(va,CSHandle *))) [array addObject:handle];
va_end(va);
return [self multiHandleWithHandleArray:array];
}
-(id)initWithHandles:(NSArray *)handlearray
{
if((self=[super initWithName:[NSString stringWithFormat:@"%@, and %d more combined",[[handlearray objectAtIndex:0] name],[handlearray count]-1]]))
{
handles=[handlearray copy];
currhandle=0;
}
return self;
}
-(id)initAsCopyOf:(CSMultiHandle *)other
{
if((self=[super initAsCopyOf:other]))
{
NSMutableArray *handlearray=[NSMutableArray arrayWithCapacity:[other->handles count]];
NSEnumerator *enumerator=[other->handles objectEnumerator];
CSHandle *handle;
while((handle=[enumerator nextObject])) [handlearray addObject:[[handle copy] autorelease]];
handles=[[NSArray arrayWithArray:handlearray] retain];
currhandle=other->currhandle;
}
return self;
}
-(void)dealloc
{
[handles release];
[super dealloc];
}
-(NSArray *)handles { return handles; }
-(CSHandle *)currentHandle { return [handles objectAtIndex:currhandle]; }
-(off_t)fileSize
{
off_t size=0;
int count=[handles count];
for(int i=0;i<count-1;i++)
{
off_t segsize=[(CSHandle *)[handles objectAtIndex:i] fileSize];
if(segsize==CSHandleMaxLength) [self _raiseSizeUnknownForSegment:i];
size+=segsize;
}
off_t segsize=[(CSHandle *)[handles lastObject] fileSize];
if(segsize==CSHandleMaxLength) return CSHandleMaxLength;
else return size+segsize;
}
-(off_t)offsetInFile
{
off_t offs=0;
for(int i=0;i<currhandle;i++)
{
off_t segsize=[(CSHandle *)[handles objectAtIndex:i] fileSize];
if(segsize==CSHandleMaxLength) [self _raiseSizeUnknownForSegment:i];
offs+=segsize;
}
return offs+[[handles objectAtIndex:currhandle] offsetInFile];
}
-(BOOL)atEndOfFile
{
return currhandle==[handles count]-1&&[[handles objectAtIndex:currhandle] atEndOfFile];
}
-(void)seekToFileOffset:(off_t)offs
{
int count=[handles count];
if(offs==0)
{
currhandle=0;
}
else
{
for(currhandle=0;currhandle<count-1;currhandle++)
{
off_t segsize=[(CSHandle *)[handles objectAtIndex:currhandle] fileSize];
if(segsize==CSHandleMaxLength) [self _raiseSizeUnknownForSegment:currhandle];
if(offs<segsize) break;
offs-=segsize;
}
}
[(CSHandle *)[handles objectAtIndex:currhandle] seekToFileOffset:offs];
}
-(void)seekToEndOfFile
{
currhandle=[handles count]-1;
[(CSHandle *)[handles objectAtIndex:currhandle] seekToEndOfFile];
}
-(int)readAtMost:(int)num toBuffer:(void *)buffer
{
off_t total=0;
for(;;)
{
off_t actual=[[handles objectAtIndex:currhandle] readAtMost:num-total toBuffer:((char *)buffer)+total];
total+=actual;
if(total==num||currhandle==[handles count]-1) return total;
currhandle++;
[(CSHandle *)[handles objectAtIndex:currhandle] seekToFileOffset:0];
}
}
-(void)_raiseSizeUnknownForSegment:(int)i
{
[NSException raise:CSSizeOfSegmentUnknownException
format:@"Size of CSMultiHandle segment %d (%@) unknown.",i,[handles objectAtIndex:i]];
}
@end
|