Revision: 27771
          http://sourceforge.net/p/bibdesk/svn/27771
Author:   hofman
Date:     2022-07-27 18:18:38 +0000 (Wed, 27 Jul 2022)
Log Message:
-----------
Pass valicator block and hash to unique string method to avoid passing 
additional information only locally available

Modified Paths:
--------------
    trunk/bibdesk/BDSKFormatParser.m

Modified: trunk/bibdesk/BDSKFormatParser.m
===================================================================
--- trunk/bibdesk/BDSKFormatParser.m    2022-07-27 08:52:03 UTC (rev 27770)
+++ trunk/bibdesk/BDSKFormatParser.m    2022-07-27 18:18:38 UTC (rev 27771)
@@ -64,12 +64,10 @@
                 endingWith:(NSString *)endString
           addingCharacters:(NSUInteger)number
                  fromRange:(NSRange)charRange
-                    prefix:(NSString *)prefixOrField
-                    suffix:(NSString *)suffixOrField
-                  forField:(NSString *)fieldName
-                    ofItem:(id <BDSKParseableItem>)pub
-                  inFolder:(NSURL *)papersFolderURL
-                    format:(NSString *)format;
+                    prefix:(NSString *)prefix
+                    suffix:(NSString *)suffix
+                      hash:(NSUInteger)hash
+                 validator:(NSString *(^)(NSString *))validator;
 
 + (BOOL)currentString:(NSString *)suggestion
         matchesString:(NSString *)baseStr
@@ -106,8 +104,7 @@
 
 static NSString *validCiteKey(NSString *key, id<BDSKParseableItem> pub);
 
-static NSUInteger hashedField(id<BDSKParseableItem> pub, NSString *field);
-static BOOL isUniversal(NSString *format);
+static NSUInteger hashedField(id<BDSKParseableItem> pub, NSString *field, BOOL 
isUniversal);
 
 static BOOL scanOptArg(NSScanner *scanner, NSString **result, BOOL 
*lastCharEscaped);
 static BOOL scanSignedDigit(NSScanner *scanner, NSUInteger *resultDigit, BOOL 
*resultSign);
@@ -160,7 +157,8 @@
     NSString *uniquePrefix = nil;
     NSString *uniqueSuffix = nil;
        NSCharacterSet *slashCharSet = [NSCharacterSet 
characterSetWithCharactersInString:@"/"];
-       BOOL isLocalFile = [fieldName isGeneralLocalFileField];
+    BOOL isCiteKey = [fieldName isEqualToString:BDSKCiteKeyString];
+    BOOL isLocalFile = [fieldName isGeneralLocalFileField];
     NSURL *papersFolderURL = nil;
     
     [scanner setCharactersToBeSkipped:nil];
@@ -519,8 +517,7 @@
                                                scanOptArg(scanner, &slash, 
NULL);
                         
                                                if (NO == [scanner 
scanUnsignedInteger:&numChars]) numChars = 0;
-                        if (NO == [fieldName 
isEqualToString:BDSKCiteKeyString] &&
-                            [key isEqualToString:BDSKCiteKeyString]) {
+                        if (NO == isCiteKey && [key 
isEqualToString:BDSKCiteKeyString]) {
                             value = [pub citeKey];
                         } else if ([fieldName 
isEqualToString:BDSKContainerString]) {
                             value = [pub container];
@@ -752,7 +749,7 @@
                }
        }
        
-    if (([fieldName isEqualToString:BDSKCiteKeyString] && [[NSUserDefaults 
standardUserDefaults] boolForKey:BDSKCiteKeyLowercaseKey]) ||
+    if ((isCiteKey && [[NSUserDefaults standardUserDefaults] 
boolForKey:BDSKCiteKeyLowercaseKey]) ||
         (isLocalFile && [[NSUserDefaults standardUserDefaults] 
boolForKey:BDSKLocalFileLowercaseKey])) {
         [parsedStr setString:[parsedStr lowercaseString]];
         baseParsedStr = [baseParsedStr lowercaseString];
@@ -795,7 +792,7 @@
                 currentStr = [currentStr 
substringFromIndex:[[resolvedPapersFolderURL path] length] + 1];
             else
                 currentStr = nil;
-        } else if ([fieldName isEqualToString:BDSKCiteKeyString]) {
+        } else if (isCiteKey) {
             currentStr = validCiteKey([pub citeKey], pub);
         } else {
             currentStr = [pub stringValueOfField:fieldName];
@@ -806,10 +803,27 @@
                      endingWith:parsedStr
                addingCharacters:uniqueNumber
                       fromRange:charRange
-                         prefix:uniqueNumber ? nil : uniquePrefix
-                         suffix:uniqueNumber ? nil : uniqueSuffix]) {
+                         prefix:uniqueNumber > 0 ? nil : uniquePrefix
+                         suffix:uniqueNumber > 0 ? nil : uniqueSuffix]) {
             [parsedStr setString:currentStr];
         } else {
+            NSString *(^validator)(NSString *) = nil;
+            if (isCiteKey)
+                validator = ^(NSString *str){ return validCiteKey(str, pub); };
+            else if (isLocalFile)
+                validator = ^(NSString *str){ return [NSString 
isEmptyString:str] || [[papersFolderURL URLByAppendingPathComponent:str 
isDirectory:NO] checkResourceIsReachableAndReturnError:NULL] ? nil : str; };
+            else
+                validator = ^(NSString *str){ return [NSString 
isEmptyString:str] ? nil : str; };
+            
+            NSUInteger hash = NSNotFound;
+            if (uniqueNumber > 0 && (uniquePrefix || uniqueSuffix)) {
+                BOOL isUniversal = uniqueNumber == 2 && [format 
hasPrefix:@"%a1:%Y%u["] && [format hasSuffix:@"]2"] && [format 
rangeOfCharacterFromSet:[[BDSKTypeManager sharedManager] 
invalidCharactersForField:BDSKCiteKeyString] options:0 range:NSMakeRange(9, 
[format length] - 11)].location == NSNotFound;
+                hash = hashedField(pub, uniquePrefix ?: uniqueSuffix, 
isUniversal);
+                if (hash == NSNotFound && uniquePrefix && uniqueSuffix)
+                    hash = hashedField(pub, uniqueSuffix, isUniversal);
+                uniquePrefix = uniqueSuffix = nil;
+            }
+            
             [parsedStr setString:[self uniqueString:baseParsedStr
                                          endingWith:parsedStr
                                    addingCharacters:uniqueNumber
@@ -816,10 +830,8 @@
                                           fromRange:charRange
                                              prefix:uniquePrefix
                                              suffix:uniqueSuffix
-                                           forField:fieldName
-                                             ofItem:pub
-                                           inFolder:resolvedPapersFolderURL
-                                             format:format]];
+                                               hash:hash
+                                          validator:(NSString *(^)(NSString 
*))validator]];
         }
        }
        
@@ -831,13 +843,29 @@
                 endingWith:(NSString *)endStr
           addingCharacters:(NSUInteger)number
                  fromRange:(NSRange)charRange
-                    prefix:(NSString *)prefixOrField
-                    suffix:(NSString *)suffixOrField
-                  forField:(NSString *)fieldName
-                    ofItem:(id <BDSKParseableItem>)pub
-                  inFolder:(NSURL *)papersFolderURL
-                    format:(NSString *)format {
+                    prefix:(NSString *)prefix
+                    suffix:(NSString *)suffix
+                      hash:(NSUInteger)hash
+                 validator:(NSString *(^)(NSString *))validator {
+    NSUInteger n;
+    NSString *uniqueStr;
+    char fallback[number + 1];
+    memset(fallback, '\0', number + 1);
+    NSString *fallbackStr = nil;
     
+    if (number > 0) {
+        if (hash != NSNotFound) {
+            // first try unique characters based on the hashed field, to get a 
deterministic value
+            // consistent with the universal cite key of Papers 2 and 3
+            for (n = number; n > 0; n--, hash /= charRange.length)
+                fallback[n - 1] = charRange.location + (hash % 
charRange.length);
+            if ((uniqueStr = validator([NSString stringWithFormat:@"%@%s%@", 
baseStr, fallback, endStr])))
+                return uniqueStr;
+        } else {
+            memset(fallback, NSMaxRange(charRange) - 1, number);
+        }
+    }
+    
     __block NSString *(^uniqueString)(char *, NSUInteger, NSUInteger) = 
^NSString *(char *chars, NSUInteger count, NSUInteger i) {
         if (i < count) {
             char c;
@@ -851,59 +879,16 @@
         } else {
             NSMutableString *str = [NSMutableString stringWithString:baseStr];
             if (count) {
-                if (number == 0 && prefixOrField) [str 
appendString:prefixOrField];
+                if (prefix) [str appendString:prefix];
                 [str appendFormat:@"%s", chars];
-                if (number == 0 && suffixOrField) [str 
appendString:suffixOrField];
+                if (suffix) [str appendString:suffix];
             }
             [str appendString:endStr];
-            // validate te result
-            if ([NSString isEmptyString:str])
-                return nil;
-            else if ([fieldName isEqualToString:BDSKCiteKeyString])
-                return validCiteKey(str, pub);
-            else if ([fieldName isGeneralLocalFileField])
-                return [[papersFolderURL URLByAppendingPathComponent:str 
isDirectory:NO] checkResourceIsReachableAndReturnError:NULL] ? nil : str;
-            else
-                return str;
+            // validate the result
+            return validator(str);
         }
     };
     
-    NSUInteger n = number;
-    NSString *uniqueStr = nil;
-    char fallback[number + 1];
-    memset(fallback, '\0', number + 1);
-    
-    if (number > 0) {
-        if (prefixOrField) {
-            // first try unique characters based on the hashed field, to get a 
deterministic value
-            // consistent with the universal cite key of Papers 2 and 3
-            for (NSString *hashField in [NSArray 
arrayWithObjects:prefixOrField, suffixOrField, nil]) {
-                NSUInteger hash = hashedField(pub, hashField);
-                if (hash == NSNotFound) continue;
-                char chars[number + 1];
-                memset(chars, '\0', number + 1);
-                n = number;
-                while (n-- > 0) {
-                    chars[n] = charRange.location + (hash % charRange.length);
-                    if (n > 0) hash /= charRange.length;
-                }
-                if (isUniversal(format)) {
-                    // try to reproduce Paper's universal cite key for doi or 
title
-                    if ([hashField isEqualToString:BDSKDoiString])
-                        chars[0] = 'b' + (hash % 10);
-                    else if ([hashField isEqualToString:BDSKTitleString])
-                        chars[0] = 't' + (hash % 4);
-                }
-                if (fallback[0] == '\0')
-                    strcpy(fallback, chars);
-                if ((uniqueStr = uniqueString(chars, number, number)))
-                    return uniqueStr;
-            }
-        }
-        if (fallback[0] == '\0')
-            memset(fallback, NSMaxRange(charRange) - 1, number);
-    }
-    
     // run along characters to find one that is unique
     n = number;
     do {
@@ -1320,11 +1305,7 @@
     return nil;
 }
 
-static BOOL isUniversal(NSString *format) {
-    return [format hasPrefix:@"%a1:%Y%u["] && [format hasSuffix:@"]2"] && 
[format rangeOfCharacterFromSet:[[BDSKTypeManager sharedManager] 
invalidCharactersForField:BDSKCiteKeyString] options:0 range:NSMakeRange(9, 
[format length] - 11)].location == NSNotFound;
-}
-
-static NSUInteger hashedField(id<BDSKParseableItem> pub, NSString *field) {
+static NSUInteger hashedField(id<BDSKParseableItem> pub, NSString *field, BOOL 
isUniversal) {
     NSString *string = nil;
     
     if ([field isEqualToString:BDSKDoiString]) {
@@ -1367,7 +1348,13 @@
         return NSNotFound;
     
     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
-    return crc32(0, [data bytes], [data length]);
+    NSUInteger hash = crc32(0, [data bytes], [data length]);
+    
+    // try to reproduce Paper's universal cite key for doi or title
+    if (isUniversal && ([field isEqualToString:BDSKTitleString] || [field 
isEqualToString:BDSKDoiString]))
+        hash = (hash % 26) + 26 * ([field isEqualToString:BDSKDoiString] ? 1 + 
((hash / 26) % 10) : 19 + ((hash / 26) % 4));
+    
+    return hash;
 }
 
 static BOOL scanOptArg(NSScanner *scanner, NSString **result, BOOL 
*lastCharEscaped) {

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