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