Revision: 26797 http://sourceforge.net/p/bibdesk/svn/26797 Author: hofman Date: 2021-09-04 12:12:44 +0000 (Sat, 04 Sep 2021) Log Message: ----------- Wrap AliasHandle for linked file in an object
Modified Paths: -------------- trunk/bibdesk/BDSKLinkedFile.m Modified: trunk/bibdesk/BDSKLinkedFile.m =================================================================== --- trunk/bibdesk/BDSKLinkedFile.m 2021-09-04 06:30:28 UTC (rev 26796) +++ trunk/bibdesk/BDSKLinkedFile.m 2021-09-04 12:12:44 UTC (rev 26797) @@ -53,21 +53,20 @@ #define RELATIVEPATH_KEY @"relativePath" static NSURL *BDSKCreateURLFromFSRef(const FSRef *inRef); -static void BDSKDisposeAliasHandle(AliasHandle inAlias); -static AliasHandle BDSKDataToAliasHandle(NSData *inData); -static NSData *BDSKAliasHandleToData(AliasHandle inAlias); -static BOOL BDSKAliasHandleToFSRef(const AliasHandle inAlias, const FSRef *inBaseRef, FSRef *outRef, BOOL *shouldUpdate); -static AliasHandle BDSKFSRefToAliasHandle(const FSRef *inRef, const FSRef *inBaseRef); -static void BDSKUpdateAliasWithFSRef(AliasHandle alias, const FSRef *inRef, const FSRef *inBaseRef); static BOOL BDSKPathToFSRef(NSString *inPath, FSRef *outRef); -static AliasHandle BDSKPathToAliasHandle(NSString *inPath, NSString *inBasePath); static NSDictionary *BDSKDictionaryFromPlistData(NSData *data); static NSDictionary *BDSKDictionaryFromArchivedData(NSData *data); -typedef union _BDSKLocator { +@interface BDSKAlias : NSObject { AliasHandle alias; - NSData *bookmark; -} BDSKLocator; +} ++ (id)newWithData:(NSData *)data; ++ (id)newWithFSRef:(const FSRef *)aRef baseRef:(const FSRef *)baseRef; ++ (id)newWithPath:(NSString *)path basePath:(NSString *)basePath; +- (BOOL)getFSRef:(FSRef *)outRef baseRef:(const FSRef *)baseRef shouldUpdate:(BOOL *)shouldUpdate; +- (void)updateWithFSRef:(const FSRef *)outRef baseRef:(const FSRef *)baseRef; +@property (nonatomic, readonly) NSData *data; +@end // Private placeholder subclass @@ -77,7 +76,7 @@ // Private concrete subclasses @interface BDSKLinkedAliasFile : BDSKLinkedFile { - BDSKLocator locator; + id alias; // can be a BDSKAlias or bookmark NSData const FSRef *fileRef; NSString *relativePath; NSURL *fileURL; @@ -277,12 +276,12 @@ @implementation BDSKLinkedAliasFile -- (id)initWithLocator:(BDSKLocator)aLocator isBookmark:(BOOL)isBookmarkData relativePath:(NSString *)relPath delegate:(id<BDSKLinkedFileDelegate>)aDelegate; +- (id)initWithAlias:(id)anAlias isBookmark:(BOOL)isBookmarkData relativePath:(NSString *)relPath delegate:(id<BDSKLinkedFileDelegate>)aDelegate; { - BDSKASSERT((isBookmarkData ? nil != aLocator.bookmark : NULL != aLocator.alias) || nil != relPath); + BDSKASSERT(nil != anAlias || nil != relPath); BDSKASSERT(nil == aDelegate || [aDelegate respondsToSelector:@selector(basePathForLinkedFile:)]); - if ((isBookmarkData ? aLocator.bookmark == nil : aLocator.alias == NULL) && relPath == nil) { + if (anAlias == nil && relPath == nil) { [self release]; self = nil; } else { @@ -289,7 +288,7 @@ self = [super init]; if (self) { fileRef = NULL; // this is updated lazily, as we don't know the base path at this point - locator = aLocator; + alias = [anAlias retain]; isBookmark = isBookmarkData; relativePath = [relPath copy]; delegate = aDelegate; @@ -312,10 +311,11 @@ NSString *basePath = [aDelegate basePathForLinkedFile:self]; NSString *relPath = basePath ? [aPath relativePathFromPath:basePath] : nil; - BDSKLocator aLocator; - aLocator.alias = BDSKPathToAliasHandle(aPath, basePath); + id anAlias; + anAlias = [BDSKAlias newWithPath:aPath basePath:basePath]; - self = [self initWithLocator:aLocator isBookmark:NO relativePath:relPath delegate:aDelegate]; + self = [self initWithAlias:anAlias isBookmark:NO relativePath:relPath delegate:aDelegate]; + [anAlias release]; if (self && basePath) // this initalizes the FSRef and update the alias [self updateFileRef]; @@ -324,13 +324,15 @@ - (id)initWithData:(NSData *)data isBookmark:(BOOL)isBookmarkData relativePath:(NSString *)relPath delegate:(id<BDSKLinkedFileDelegate>)aDelegate; { - BDSKLocator aLocator; + id anAlias; if (isBookmarkData) - aLocator.bookmark = [data copy]; + anAlias = [data copy]; else - aLocator.alias = BDSKDataToAliasHandle(data); + anAlias = [BDSKAlias newWithData:data]; - return [self initWithLocator:aLocator isBookmark:isBookmarkData relativePath:relPath delegate:aDelegate]; + self = [self initWithAlias:anAlias isBookmark:isBookmarkData relativePath:relPath delegate:aDelegate]; + [anAlias release]; + return self; } - (id)initWithBase64String:(NSString *)base64String delegate:(id<BDSKLinkedFileDelegate>)aDelegate; @@ -425,8 +427,8 @@ NSData *data = [self aliasDataRelativeToPath:[delegate basePathForLinkedFile:self]]; if ([coder allowsKeyedCoding]) { [coder encodeObject:data forKey:ALIASDATA_KEY]; - if (data == nil && isBookmark && locator.bookmark) - [coder encodeObject:locator.bookmark forKey:BOOKMARK_KEY]; + if (data == nil && isBookmark && alias) + [coder encodeObject:alias forKey:BOOKMARK_KEY]; [coder encodeObject:relativePath forKey:RELATIVEPATH_KEY]; } else { [coder encodeObject:data]; @@ -437,11 +439,7 @@ - (void)dealloc { BDSKZONEDESTROY(fileRef); - if (isBookmark) { - BDSKDESTROY(locator.bookmark); - } else { - BDSKDisposeAliasHandle(locator.alias); locator.alias = NULL; - } + BDSKDESTROY(alias); BDSKDESTROY(relativePath); BDSKDESTROY(fileURL); [super dealloc]; @@ -453,8 +451,8 @@ [self updateFileURL]; NSData *data = [self aliasDataRelativeToPath:[delegate basePathForLinkedFile:self]]; BOOL isBookmarkData = NO; - if (data == nil && isBookmark && locator.bookmark){ - data = locator.bookmark; + if (data == nil && isBookmark && alias){ + data = alias; isBookmarkData = YES; } return [[[self class] allocWithZone:aZone] initWithData:data isBookmark:isBookmarkData relativePath:relativePath delegate:delegate]; @@ -516,16 +514,16 @@ BDSKASSERT(baseRef != NULL); // update the alias - if (isBookmark == NO && locator.alias != NULL) { - BDSKUpdateAliasWithFSRef(locator.alias, fileRef, baseRef); + if (isBookmark == NO && alias != nil) { + [alias updateWithFSRef:fileRef baseRef:baseRef]; } else { - AliasHandle anAlias = BDSKFSRefToAliasHandle(fileRef, baseRef); + BDSKAlias *anAlias = [BDSKAlias newWithFSRef:fileRef baseRef:baseRef]; if (anAlias) { if (isBookmark) { - BDSKDESTROY(locator.bookmark); + BDSKDESTROY(alias); isBookmark = NO; } - locator.alias = anAlias; + alias = anAlias; } } } @@ -552,11 +550,11 @@ } if (hasRef == NO) { - if (isBookmark == NO && locator.alias != NULL) { - hasRef = BDSKAliasHandleToFSRef(locator.alias, hasBaseRef ? &baseRef : NULL, &aRef, &shouldUpdate); + if (isBookmark == NO && alias != nil) { + hasRef = [alias getFSRef:&aRef baseRef:hasBaseRef ? &baseRef : NULL shouldUpdate:&shouldUpdate]; shouldUpdate = (shouldUpdate || relativePath == nil) && hasBaseRef && hasRef; - } else if (isBookmark && locator.bookmark != nil) { - NSURL *aURL = [NSURL URLByResolvingBookmarkData:locator.bookmark options:NSURLBookmarkResolutionWithoutUI relativeToURL:(basePath ? [NSURL fileURLWithPath:basePath] : nil) bookmarkDataIsStale:NULL error:NULL]; + } else if (isBookmark && alias != nil) { + NSURL *aURL = [NSURL URLByResolvingBookmarkData:alias options:NSURLBookmarkResolutionWithoutUI relativeToURL:(basePath ? [NSURL fileURLWithPath:basePath] : nil) bookmarkDataIsStale:NULL error:NULL]; hasRef = BDSKPathToFSRef([aURL path], &aRef); shouldUpdate = hasBaseRef && hasRef; } @@ -647,20 +645,20 @@ - (NSData *)aliasDataRelativeToPath:(NSString *)basePath; { FSRef baseRef; - AliasHandle anAlias = NULL; + BDSKAlias *anAlias = NULL; NSData *data = nil; if (fileRef) { BOOL hasBaseRef = BDSKPathToFSRef(basePath, &baseRef); - anAlias = BDSKFSRefToAliasHandle(fileRef, hasBaseRef ? &baseRef : NULL); + anAlias = [BDSKAlias newWithFSRef:fileRef baseRef:&baseRef]; } else if (relativePath && basePath) { - anAlias = BDSKPathToAliasHandle(([relativePath isAbsolutePath] ? relativePath : [basePath stringByAppendingPathComponent:relativePath]), basePath); + anAlias = [BDSKAlias newWithPath:([relativePath isAbsolutePath] ? relativePath : [basePath stringByAppendingPathComponent:relativePath]) basePath:basePath]; } if (anAlias != NULL) { - data = BDSKAliasHandleToData(anAlias); - BDSKDisposeAliasHandle(anAlias); - } else if (isBookmark == NO && locator.alias != NULL) { - data = BDSKAliasHandleToData(locator.alias); + data = [anAlias data]; + [anAlias release]; + } else if (isBookmark == NO && alias != nil) { + data = [alias data]; } return data; @@ -679,7 +677,7 @@ if (noAlias == NO || path == nil) { data = [self aliasDataRelativeToPath:newBasePath]; if (data == nil && isBookmark) { - data = locator.bookmark; + data = alias; dataKey = BOOKMARK_KEY; } } @@ -691,22 +689,22 @@ } - (void)setAliasWithPath:(NSString *)aPath basePath:(NSString *)basePath { - AliasHandle anAlias = BDSKPathToAliasHandle(aPath, basePath); - if (anAlias != NULL) { + BDSKAlias *anAlias = [BDSKAlias newWithPath:aPath basePath:basePath]; + if (anAlias != nil) { BOOL saveIsBookmark = isBookmark; - BDSKLocator saveLocator = locator; - locator.alias = anAlias; + id saveAlias = alias; + alias = anAlias; isBookmark = NO; [self updateFileRef]; if (fileRef == NULL) { - BDSKDisposeAliasHandle(anAlias); - locator = saveLocator; + [anAlias release]; + alias = saveAlias; isBookmark = saveIsBookmark; [self updateFileRef]; } else if (saveIsBookmark) { - [saveLocator.bookmark release]; + [saveAlias release]; } else { - BDSKDisposeAliasHandle(saveLocator.alias); + [saveAlias release]; } } } @@ -868,50 +866,6 @@ return inRef == NULL ? NULL : (NSURL *)CFURLCreateFromFSRef(NULL, inRef); } -static void BDSKDisposeAliasHandle(AliasHandle inAlias) -{ - if (inAlias != NULL) - DisposeHandle((Handle)inAlias); -} - -static AliasHandle BDSKDataToAliasHandle(NSData *inData) -{ - CFIndex len; - Handle handle = NULL; - - if (inData != nil) { - len = CFDataGetLength((CFDataRef)inData); - handle = NewHandle(len); - - if ((handle != NULL) && (len > 0)) { - HLock(handle); - memmove((void *)*handle, (const void *)CFDataGetBytePtr((CFDataRef)inData), len); - HUnlock(handle); - } - } - return (AliasHandle)handle; -} - -static NSData *BDSKAliasHandleToData(AliasHandle inAlias) -{ - Handle inHandle = (Handle)inAlias; - CFDataRef data = NULL; - CFIndex len; - SInt8 handleState; - - if (inHandle != NULL) { - len = GetHandleSize(inHandle); - handleState = HGetState(inHandle); - - HLock(inHandle); - - data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *) *inHandle, len); - - HSetState(inHandle, handleState); - } - return [(NSData *)data autorelease]; -} - static const FSRef *BDSKBaseRefIfOnSameVolume(const FSRef *inBaseRef, const FSRef *inRef) { FSCatalogInfo baseCatalogInfo, catalogInfo; @@ -923,38 +877,6 @@ return sameVolume ? inBaseRef : NULL; } -static BOOL BDSKAliasHandleToFSRef(const AliasHandle inAlias, const FSRef *inBaseRef, FSRef *outRef, BOOL *shouldUpdate) -{ - OSStatus err = noErr; - short aliasCount = 1; - - // it would be preferable to search the (relative) path before the fileID, but than links to symlinks will always be resolved to the target - err = FSMatchAliasBulk(inBaseRef, kARMNoUI | kARMSearch | kARMSearchRelFirst | kARMTryFileIDFirst, inAlias, &aliasCount, outRef, (Boolean *)shouldUpdate, NULL, NULL); - - return noErr == err; -} - -static AliasHandle BDSKFSRefToAliasHandle(const FSRef *inRef, const FSRef *inBaseRef) -{ - OSStatus err = noErr; - AliasHandle alias = NULL; - - err = FSNewAlias(BDSKBaseRefIfOnSameVolume(inBaseRef, inRef), inRef, &alias); - - if (err != noErr && alias != NULL) { - DisposeHandle((Handle)alias); - alias = NULL; - } - - return alias; -} - -static void BDSKUpdateAliasWithFSRef(AliasHandle alias, const FSRef *inRef, const FSRef *inBaseRef) -{ - Boolean didUpdate; - FSUpdateAlias(BDSKBaseRefIfOnSameVolume(inBaseRef, inRef), inRef, alias, &didUpdate); -} - static BOOL BDSKPathToFSRef(NSString *inPath, FSRef *outRef) { OSStatus err = fnfErr; @@ -964,20 +886,9 @@ return noErr == err; } + #pragma clang diagnostic pop -static AliasHandle BDSKPathToAliasHandle(NSString *inPath, NSString *inBasePath) -{ - FSRef ref, baseRef; - AliasHandle alias = NULL; - - if (BDSKPathToFSRef(inPath, &ref) && - (inBasePath == nil || BDSKPathToFSRef(inBasePath, &baseRef))) - alias = BDSKFSRefToAliasHandle(&ref, inBasePath ? &baseRef : NULL); - - return alias; -} - static NSDictionary *BDSKDictionaryFromPlistData(NSData *data) { NSDictionary *dictionary = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:NULL]; if ([dictionary isKindOfClass:[NSDictionary class]] == NO) @@ -999,3 +910,105 @@ return nil; return dictionary; } + +@implementation BDSKAlias + +@dynamic data; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +- (id)initWithAliasHandle:(AliasHandle)handle { + self = [super init]; + if (self) { + alias = (AliasHandle)handle; + } + return self; +} + ++ (id)newWithData:(NSData *)data { + CFIndex len; + Handle handle = NULL; + + if (data != nil) { + len = CFDataGetLength((CFDataRef)data); + handle = NewHandle(len); + + if ((handle != NULL) && (len > 0)) { + HLock(handle); + memmove((void *)*handle, (const void *)CFDataGetBytePtr((CFDataRef)data), len); + HUnlock(handle); + } + } + + return handle == NULL ? nil : [[self alloc] initWithAliasHandle:(AliasHandle)handle]; +} + ++ (id)newWithFSRef:(const FSRef *)aRef baseRef:(const FSRef *)baseRef { + OSStatus err = noErr; + AliasHandle handle = NULL; + + err = FSNewAlias(BDSKBaseRefIfOnSameVolume(baseRef, aRef), aRef, &handle); + + if (err != noErr && handle != NULL) { + DisposeHandle((Handle)handle); + handle = NULL; + } + + return handle == NULL ? nil : [[self alloc] initWithAliasHandle:(AliasHandle)handle]; +} + ++ (id)newWithPath:(NSString *)path basePath:(NSString *)basePath { + FSRef ref, baseRef; + + if (BDSKPathToFSRef(path, &ref) && + (basePath == nil || BDSKPathToFSRef(basePath, &baseRef))) + return [self newWithFSRef:&ref baseRef:&baseRef]; + return nil; +} + +- (void)dealloc { + if (alias != NULL) { + DisposeHandle((Handle)alias); + alias = NULL; + } + [super dealloc]; +} + +- (BOOL)getFSRef:(FSRef *)outRef baseRef:(const FSRef *)baseRef shouldUpdate:(BOOL *)shouldUpdate { + OSStatus err = noErr; + short aliasCount = 1; + + // it would be preferable to search the (relative) path before the fileID, but than links to symlinks will always be resolved to the target + err = FSMatchAliasBulk(baseRef, kARMNoUI | kARMSearch | kARMSearchRelFirst | kARMTryFileIDFirst, alias, &aliasCount, outRef, (Boolean *)shouldUpdate, NULL, NULL); + + return noErr == err; +} + +- (NSData *)data { + Handle handle = (Handle)alias; + CFDataRef data = NULL; + CFIndex len; + SInt8 handleState; + + if (handle != NULL) { + len = GetHandleSize(handle); + handleState = HGetState(handle); + + HLock(handle); + + data = CFDataCreate(kCFAllocatorDefault, (const UInt8 *) *handle, len); + + HSetState(handle, handleState); + } + return [(NSData *)data autorelease]; +} + +- (void)updateWithFSRef:(const FSRef *)aRef baseRef:(const FSRef *)baseRef { + Boolean didUpdate; + FSUpdateAlias(BDSKBaseRefIfOnSameVolume(baseRef, aRef), aRef, alias, &didUpdate); +} + +#pragma clang diagnostic pop + +@end This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ Bibdesk-commit mailing list Bibdesk-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bibdesk-commit