Revision: 28510
          http://sourceforge.net/p/bibdesk/svn/28510
Author:   hofman
Date:     2024-01-02 00:29:30 +0000 (Tue, 02 Jan 2024)
Log Message:
-----------
use NSHashTable with custom pointer functions for BibItem equality and 
equivalence rather than bridges CFSet

Modified Paths:
--------------
    trunk/bibdesk/BDSKSharingServer.m
    trunk/bibdesk/BibDocument_Actions.m
    trunk/bibdesk/BibDocument_Groups.m
    trunk/bibdesk/NSPointerFunctions_BDSKExtensions.h
    trunk/bibdesk/NSPointerFunctions_BDSKExtensions.m

Modified: trunk/bibdesk/BDSKSharingServer.m
===================================================================
--- trunk/bibdesk/BDSKSharingServer.m   2024-01-01 23:50:39 UTC (rev 28509)
+++ trunk/bibdesk/BDSKSharingServer.m   2024-01-02 00:29:30 UTC (rev 28510)
@@ -50,6 +50,7 @@
 #import "BDSKPublicationsArray.h"
 #import "BDSKMacroResolver.h"
 #import "NSObject_BDSKExtensions.h"
+#import "NSPointerFunctions_BDSKExtensions.h"
 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -840,10 +841,11 @@
     __block NSDictionary *pubsAndMacros = nil;
     
     dispatch_sync(dispatch_get_main_queue(), ^{
-        NSMutableSet *allPubs = (NSMutableSet 
*)CFSetCreateMutable(CFAllocatorGetDefault(), 0, 
&kBDSKBibItemEqualitySetCallBacks);
+        NSHashTable *allPubs = [[NSHashTable alloc] 
initWithPointerFunctions:[NSPointerFunctions itemEqualityPointerFunctions] 
capacity:0];
         NSMutableDictionary *allMacros = [[NSMutableDictionary alloc] init];
         for (BibDocument *doc in [NSApp orderedDocuments]) {
-            [allPubs addObjectsFromArray:[doc publications]];
+            for (BibItem *pub in [doc publications])
+                [allPubs addObject:pub];
             NSMapTable *macroDefs = [[doc macroResolver] macroDefinitions];
             for (NSString *key in macroDefs)
                 [allMacros setObject:[macroDefs objectForKey:key] forKey:key];

Modified: trunk/bibdesk/BibDocument_Actions.m
===================================================================
--- trunk/bibdesk/BibDocument_Actions.m 2024-01-01 23:50:39 UTC (rev 28509)
+++ trunk/bibdesk/BibDocument_Actions.m 2024-01-02 00:29:30 UTC (rev 28510)
@@ -95,6 +95,7 @@
 #import "BDSKColorLabelWell.h"
 #import "BDSKMergeController.h"
 #import "BDSKFindController.h"
+#import "NSPointerFunctions_BDSKExtensions.h"
 
 #define BDSKLyXPipePathKey @"BDSKLyXPipePath"
 
@@ -1712,20 +1713,22 @@
     NSMutableArray *duplicatePubs = nil;
     NSZone *zone = NSDefaultMallocZone();
     CFIndex countOfItems = [publications count];
-    BibItem **pubs = (BibItem **)NSZoneMalloc(zone, sizeof(BibItem *) * 
countOfItems);
-    CFSetCallBacks callBacks = kBDSKBibItemEqualitySetCallBacks;
-    
-    [publications getObjects:pubs range:NSMakeRange(0, countOfItems)];
+    NSPointerFunctions *pointerFunctions = nil;
+    NSArray *pubs = nil;
 
     if ([self hasGroupTypeSelected:BDSKExternalGroupType]) {
         duplicatePubs = [[NSMutableArray alloc] 
initWithArray:groupedPublications];
-        callBacks = kBDSKBibItemEquivalenceSetCallBacks;
+        pointerFunctions = [NSPointerFunctions 
itemEquivalencePointerFunctions];
+        pubs = [publications copy];
     } else {
         duplicatePubs = [[NSMutableArray alloc] initWithArray:publications];
+        pointerFunctions = [NSPointerFunctions itemEqualityPointerFunctions];
         
         // Tests equality based on standard fields (high probability that 
these will be duplicates)
         countOfItems = [duplicatePubs count];
-        NSSet *uniquePubs = (NSSet *)CFSetCreate(CFAllocatorGetDefault(), 
(const void **)pubs, countOfItems, &callBacks);
+        NSHashTable *uniquePubs = [[NSHashTable alloc] 
initWithPointerFunctions:pointerFunctions capacity:countOfItems];
+        for (BibItem *pub in publications)
+            [uniquePubs addObject:pub];
         // remove all unique ones based on pointer equality
         for (BibItem *pub in uniquePubs)
             [duplicatePubs removeObjectIdenticalTo:pub];
@@ -1732,14 +1735,15 @@
         [uniquePubs release];
         
         // original buffer should be large enough, since we've only removed 
items from pubsToRemove
-        countOfItems = [duplicatePubs count];
-        [duplicatePubs getObjects:pubs range:NSMakeRange(0, countOfItems)];
+        pubs = [duplicatePubs copy];
         [duplicatePubs setArray:publications];
     }
     
     if (allCandidates) {
-        NSSet *removeSet = (NSSet *)CFSetCreate(CFAllocatorGetDefault(), 
(const void **)pubs, countOfItems, &callBacks);
-        
+        NSHashTable *removeSet = [[NSHashTable alloc] 
initWithPointerFunctions:pointerFunctions capacity:countOfItems];
+        for (BibItem *pub in pubs)
+            [removeSet addObject:pub];
+
         CFIndex idx = [duplicatePubs count];
         
         while(idx--){
@@ -1748,13 +1752,12 @@
         }
         
         [removeSet release];
-            [self selectPublications:duplicatePubs];
+        [self selectPublications:duplicatePubs];
     } else {
-        [duplicatePubs release];
-        duplicatePubs = [[NSMutableArray alloc] initWithObjects:pubs 
count:countOfItems];
+        [duplicatePubs setArray:pubs];
         [self selectPublications:duplicatePubs];
     }
-    NSZoneFree(zone, pubs);
+    [pubs release];
     [duplicatePubs release];
     
     if(countOfItems)

Modified: trunk/bibdesk/BibDocument_Groups.m
===================================================================
--- trunk/bibdesk/BibDocument_Groups.m  2024-01-01 23:50:39 UTC (rev 28509)
+++ trunk/bibdesk/BibDocument_Groups.m  2024-01-02 00:29:30 UTC (rev 28510)
@@ -1353,11 +1353,9 @@
 
 - (NSArray *)mergeInPublications:(NSArray *)items{
     // first construct a set of current items to compare based on BibItem 
equality callbacks
-    CFIndex countOfItems = [publications count];
-    BibItem **pubs = (BibItem **)NSZoneMalloc(NULL, sizeof(BibItem *) * 
countOfItems);
-    [publications getObjects:pubs range:NSMakeRange(0, countOfItems)];
-    NSSet *currentPubs = [(NSSet *)CFSetCreate(CFAllocatorGetDefault(), (const 
void **)pubs, countOfItems, &kBDSKBibItemEquivalenceSetCallBacks) autorelease];
-    NSZoneFree(NULL, pubs);
+    NSHashTable *currentPubs = [[NSHashTable alloc] 
initWithPointerFunctions:[NSPointerFunctions itemEquivalencePointerFunctions] 
capacity:[publications count]];
+    for (BibItem *pub in publications)
+        [currentPubs addObject:pub];
     
     NSMutableArray *newPubs = [NSMutableArray arrayWithCapacity:[items count]];
     
@@ -1370,6 +1368,8 @@
         }
     }
     
+    [currentPubs release];
+    
     if ([newPubs count] == 0)
         return @[];
     
@@ -1620,11 +1620,9 @@
 #pragma mark Importing
 
 - (void)setImported:(BOOL)flag forPublications:(NSArray *)pubs 
inGroup:(BDSKExternalGroup *)aGroup{
-    CFIndex countOfItems = [pubs count];
-    BibItem **items = (BibItem **)NSZoneMalloc(NULL, sizeof(BibItem *) * 
countOfItems);
-    [pubs getObjects:items range:NSMakeRange(0, countOfItems)];
-    NSSet *pubSet = (NSSet *)CFSetCreate(CFAllocatorGetDefault(), (const void 
**)items, countOfItems, &kBDSKBibItemEquivalenceSetCallBacks);
-    NSZoneFree(NULL, items);
+    NSHashTable *pubSet = [[NSHashTable alloc] 
initWithPointerFunctions:[NSPointerFunctions itemEquivalencePointerFunctions] 
capacity:[pubs count]];
+    for (BibItem *pub in pubs)
+        [pubSet addObject:pub];
     
     NSArray *groupsToTest = aGroup ? @[aGroup] : [[groups externalParent] 
children];
     

Modified: trunk/bibdesk/NSPointerFunctions_BDSKExtensions.h
===================================================================
--- trunk/bibdesk/NSPointerFunctions_BDSKExtensions.h   2024-01-01 23:50:39 UTC 
(rev 28509)
+++ trunk/bibdesk/NSPointerFunctions_BDSKExtensions.h   2024-01-02 00:29:30 UTC 
(rev 28510)
@@ -43,5 +43,7 @@
 
 + (NSPointerFunctions *)caseInsensitiveStringPointerFunctions;
 + (NSPointerFunctions *)fuzzyAuthorPointerFunctions;
++ (NSPointerFunctions *)itemEqualityPointerFunctions;
++ (NSPointerFunctions *)itemEquivalencePointerFunctions;
 
 @end

Modified: trunk/bibdesk/NSPointerFunctions_BDSKExtensions.m
===================================================================
--- trunk/bibdesk/NSPointerFunctions_BDSKExtensions.m   2024-01-01 23:50:39 UTC 
(rev 28509)
+++ trunk/bibdesk/NSPointerFunctions_BDSKExtensions.m   2024-01-02 00:29:30 UTC 
(rev 28510)
@@ -38,6 +38,9 @@
 
 #import "NSPointerFunctions_BDSKExtensions.h"
 #import "BibAuthor.h"
+#import "BibItem.h"
+#import "BDSKTypeManager.h"
+#import "CFString_BDSKExtensions.h"
 
 static BOOL caseInsensitiveStringEqual(const void *item1, const void *item2, 
NSUInteger (*size)(const void *item)) {
     return CFStringCompare(item1, item2, kCFCompareCaseInsensitive | 
kCFCompareNonliteral) == kCFCompareEqualTo;
@@ -81,6 +84,48 @@
     return [(BibAuthor *)value1 fuzzyEqual:(BibAuthor *)value2];
 }
 
+static NSUInteger BibItemEqualityHash(const void *item, NSUInteger 
(*size)(const void *item))
+{
+    BDSKASSERT([(id)item isKindOfClass:[BibItem class]]);
+    return BDCaseInsensitiveStringHash([(BibItem *)item citeKey]);
+}
+
+static BOOL BibItemEqual(const void *value1, const void *value2, NSUInteger 
(*size)(const void *item))
+{
+    BDSKASSERT([(id)value1 isKindOfClass:[BibItem class]] && [(id)value2 
isKindOfClass:[BibItem class]]);
+    return ([(BibItem *)value1 isEqualToItem:(BibItem *)value2]);
+}
+
+static NSUInteger BibItemEquivalenceHash(const void *item, NSUInteger 
(*size)(const void *item))
+{
+    BDSKASSERT([(id)item isKindOfClass:[BibItem class]]);
+    
+    NSString *type = [(BibItem *)item pubType] ?: @"";
+    CFHashCode hash = BDCaseInsensitiveStringHash(type);
+    NSUInteger prime = 31;
+    NSUInteger factor = 1;
+
+    // hash only the standard fields; are these all we should compare?
+    BDSKTypeManager *btm = [BDSKTypeManager sharedManager];
+    NSMutableArray *keys = [[NSMutableArray alloc] initWithCapacity:20];
+    [keys addObjectsFromArray:[btm requiredFieldsForType:type]];
+    [keys addObjectsFromArray:[btm optionalFieldsForType:type]];
+    [keys removeObject:BDSKLocalUrlString];
+    for (NSString *key in keys) {
+        factor *= prime;
+        hash += factor * [[(BibItem *)item stringValueOfField:key inherit:NO] 
?: @"" hash];
+    }
+    [keys release];
+    
+    return hash;
+}
+
+static BOOL BibItemEquivalent(const void *value1, const void *value2, 
NSUInteger (*size)(const void *item))
+{
+    BDSKASSERT([(id)value1 isKindOfClass:[BibItem class]] && [(id)value2 
isKindOfClass:[BibItem class]]);
+    return ([(BibItem *)value1 isEquivalentToItem:(BibItem *)value2]);
+}
+
 @implementation NSPointerFunctions (BDSKExtensions)
 
 + (NSPointerFunctions *)caseInsensitiveStringPointerFunctions {
@@ -97,4 +142,18 @@
     return pointerFunctions;
 }
 
++ (NSPointerFunctions *)itemEqualityPointerFunctions {
+    NSPointerFunctions *pointerFunctions = [self 
pointerFunctionsWithOptions:NSPointerFunctionsWeakMemory | 
NSPointerFunctionsObjectPersonality];;
+    [pointerFunctions setIsEqualFunction:&BibItemEqual];
+    [pointerFunctions setHashFunction:&BibItemEqualityHash];
+    return pointerFunctions;
+}
+
++ (NSPointerFunctions *)itemEquivalencePointerFunctions {
+    NSPointerFunctions *pointerFunctions = [self 
pointerFunctionsWithOptions:NSPointerFunctionsWeakMemory | 
NSPointerFunctionsObjectPersonality];;
+    [pointerFunctions setIsEqualFunction:&BibItemEquivalent];
+    [pointerFunctions setHashFunction:&BibItemEquivalenceHash];
+    return pointerFunctions;
+}
+
 @end

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to