SVGKSourceLocalFile.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #import "SVGKSourceLocalFile.h"
  2. @interface SVGKSourceLocalFile()
  3. @property (nonatomic, readwrite) BOOL wasRelative;
  4. @end
  5. @implementation SVGKSourceLocalFile
  6. -(NSString *)keyForAppleDictionaries
  7. {
  8. return self.filePath;
  9. }
  10. +(uint64_t) sizeInBytesOfFilePath:(NSString*) filePath
  11. {
  12. NSError* errorReadingFileAttributes;
  13. NSFileManager* fileManager = [NSFileManager defaultManager];
  14. NSDictionary* atts = [fileManager attributesOfItemAtPath:filePath error:&errorReadingFileAttributes];
  15. if( atts == nil )
  16. return -1;
  17. else
  18. return atts.fileSize;
  19. }
  20. + (SVGKSourceLocalFile*)sourceFromFilename:(NSString*)p {
  21. NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath:p];
  22. //DO NOT DO THIS: let the parser do it at last possible moment (Apple has threading problems otherwise!) [stream open];
  23. SVGKSourceLocalFile* s = [[SVGKSourceLocalFile alloc] initWithInputSteam:stream];
  24. s.filePath = p;
  25. s.approximateLengthInBytesOr0 = [self sizeInBytesOfFilePath:p];
  26. return s;
  27. }
  28. + (SVGKSourceLocalFile *)internalSourceAnywhereInBundle:(NSBundle *)bundle usingName:(NSString *)name
  29. {
  30. NSParameterAssert(name != nil);
  31. /** Apple's File APIs are very very bad and require you to strip the extension HALF the time.
  32. The other HALF the time, they fail unless you KEEP the extension.
  33. It's a mess!
  34. */
  35. NSString *newName = [name stringByDeletingPathExtension];
  36. NSString *extension = [name pathExtension];
  37. if ([@"" isEqualToString:extension]) {
  38. extension = @"svg";
  39. }
  40. /** First, try to find it in the project BUNDLE (this was HARD CODED at compile time; can never be changed!) */
  41. NSString *pathToFileInBundle = nil;
  42. if( bundle != nil )
  43. {
  44. pathToFileInBundle = [bundle pathForResource:newName ofType:extension];
  45. }
  46. /** Second, try to find it in the Documents folder (this is where Apple expects you to store custom files at runtime) */
  47. NSString* pathToFileInDocumentsFolder = nil;
  48. NSString* pathToDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  49. if( pathToDocumentsFolder != nil )
  50. {
  51. pathToFileInDocumentsFolder = [[pathToDocumentsFolder stringByAppendingPathComponent:newName] stringByAppendingPathExtension:extension];
  52. if( [[NSFileManager defaultManager] fileExistsAtPath:pathToFileInDocumentsFolder])
  53. ;
  54. else
  55. pathToFileInDocumentsFolder = nil; // couldn't find a file there
  56. }
  57. if( pathToFileInBundle == nil
  58. && pathToFileInDocumentsFolder == nil )
  59. {
  60. SVGKitLogWarn(@"[%@] MISSING FILE (not found in App-bundle, not found in Documents folder), COULD NOT CREATE DOCUMENT: filename = %@, extension = %@", [self class], newName, extension);
  61. return nil;
  62. }
  63. /** Prefer the Documents-folder version over the Bundle version (allows you to have a default, and override at runtime) */
  64. SVGKSourceLocalFile* source = [SVGKSourceLocalFile sourceFromFilename: pathToFileInDocumentsFolder == nil ? pathToFileInBundle : pathToFileInDocumentsFolder];
  65. return source;
  66. }
  67. + (SVGKSourceLocalFile *)internalSourceAnywhereInBundleUsingName:(NSString *)name
  68. {
  69. return [self internalSourceAnywhereInBundle:[NSBundle mainBundle] usingName:name];
  70. }
  71. -(id)copyWithZone:(NSZone *)zone
  72. {
  73. id copy = [super copyWithZone:zone];
  74. if( copy )
  75. {
  76. /** clone bits */
  77. [copy setFilePath:[self.filePath copy]];
  78. [copy setWasRelative:self.wasRelative];
  79. /** Finally, manually intialize the input stream, as required by super class */
  80. [copy setStream:[NSInputStream inputStreamWithFileAtPath:self.filePath]];
  81. }
  82. return copy;
  83. }
  84. - (SVGKSource *)sourceFromRelativePath:(NSString *)relative {
  85. NSString *absolute = ((NSURL*)[NSURL URLWithString:relative relativeToURL:[NSURL fileURLWithPath:self.filePath]]).path;
  86. if ([[NSFileManager defaultManager] fileExistsAtPath:absolute])
  87. {
  88. SVGKSourceLocalFile* result = [SVGKSourceLocalFile sourceFromFilename:absolute];
  89. result.wasRelative = true;
  90. return result;
  91. }
  92. return nil;
  93. }
  94. -(NSString *)description
  95. {
  96. BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:self.filePath];
  97. return [NSString stringWithFormat:@"File: %@%@\"%@\" (%llu bytes)", self.wasRelative? @"(relative) " : @"", fileExists?@"":@"NOT FOUND! ", self.filePath, self.approximateLengthInBytesOr0 ];
  98. }
  99. @end