forked from SVGKit/SVGKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSVGKSource.m
More file actions
156 lines (119 loc) · 3.6 KB
/
Copy pathSVGKSource.m
File metadata and controls
156 lines (119 loc) · 3.6 KB
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
148
149
150
151
152
153
154
155
156
#import "SVGKSource.h"
@implementation SVGKSourceFileReader
-(void) setFileHandle:(FILE*) f
{
fileHandle = f;
}
-(FILE*) fileHandle
{
return fileHandle;
}
@end
@implementation SVGKSourceURLReader
@synthesize httpDataFullyDownloaded;
@end
@implementation SVGKSource
@synthesize svgLanguageVersion;
@synthesize hasSourceFile, hasSourceURL;
@synthesize filePath, URL;
+(SVGKSource*) sourceFromFilename:(NSString*) p
{
SVGKSource* d = [[[SVGKSource alloc] init] autorelease];
d.hasSourceFile = TRUE;
d.filePath = p;
return d;
}
+(SVGKSource*) sourceFromURL:(NSURL*) u
{
SVGKSource* d = [[[SVGKSource alloc] init] autorelease];
d.hasSourceURL = TRUE;
d.URL = u;
return d;
}
-(NSObject<SVGKSourceReader>*) newReader:(NSError**) error
{
/**
Is this file being loaded from disk?
Or from network?
*/
if( self.hasSourceURL )
{
/**
NB:
Currently reads the ENTIRE web file synchronously, holding the entire
thing in memory.
Not efficient, might crash for 'huge' files (would need to be large numbers of megabytes, though)
But ... since we want a synchronous parse ...
*/
NSURLResponse* response;
NSData* httpData = nil;
NSURLRequest* request = [NSURLRequest requestWithURL:self.URL];
httpData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error];
if( httpData == nil )
{
NSLog( @"[%@] ERROR: failed to parse SVG from URL, because failed to download file at URL = %@, error = %@", [self class], self.URL, *error );
return nil;
}
SVGKSourceURLReader* urlReader = [[SVGKSourceURLReader alloc] init];
urlReader.httpDataFullyDownloaded = httpData;
return urlReader;
}
else
{
FILE *file; // C is wonderful (ly obscure, with mem management)
const char *cPath = [self.filePath fileSystemRepresentation];
file = fopen(cPath, "r");
if (!file)
{
if( error != nil )
*error = [NSError errorWithDomain:@"SVGKit" code:1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:@"Couldn't open the file %@ for reading", self.filePath], NSLocalizedDescriptionKey,
nil]];
}
SVGKSourceFileReader* fileReader = [[SVGKSourceFileReader alloc] init];
fileReader.fileHandle = file;
return fileReader;
}
}
-(void) closeReader:(NSObject<SVGKSourceReader>*) reader
{
/**
Is this file being loaded from disk?
Or from network?
*/
if( self.hasSourceURL )
{
// nothing needed - the asynch call was already complete
}
else
{
fclose([((SVGKSourceFileReader*)reader) fileHandle]);
}
}
-(int) reader:(NSObject<SVGKSourceReader>*) reader readNextChunk:(char *) chunk maxBytes:(int) READ_CHUNK_SZ
{
/**
Is this file being loaded from disk?
Or from network?
*/
if( self.hasSourceURL )
{
SVGKSourceURLReader* urlReader = (SVGKSourceURLReader*) reader;
const char* dataAsBytes = [urlReader.httpDataFullyDownloaded bytes];
int dataLength = [urlReader.httpDataFullyDownloaded length];
int actualBytesCopied = MIN( dataLength, READ_CHUNK_SZ );
memcpy( chunk, dataAsBytes, actualBytesCopied);
/** trim the copied bytes out of the 'handle' NSData object */
NSRange newRange = { actualBytesCopied, dataLength - actualBytesCopied };
urlReader.httpDataFullyDownloaded = [urlReader.httpDataFullyDownloaded subdataWithRange:newRange];
return actualBytesCopied;
}
else
{
SVGKSourceFileReader* fileReader = (SVGKSourceFileReader*) reader;
size_t bytesRead = 0;
bytesRead = fread(chunk, 1, READ_CHUNK_SZ, [fileReader fileHandle]);
return bytesRead;
}
}
@end