Skip to content

Instantly share code, notes, and snippets.

@fwextensions
Created July 24, 2018 06:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fwextensions/2bbdd453bc941dcfa36b06065c760980 to your computer and use it in GitHub Desktop.
Save fwextensions/2bbdd453bc941dcfa36b06065c760980 to your computer and use it in GitHub Desktop.
Bodged together test of QSSense.m
#import <Cocoa/Cocoa.h>
//
// QSense.m
// QSqSense
//
// Created by Alcor on 11/22/04.
// Copyright 2004 Blacktree. All rights reserved.
//
#import "QSSense.h"
#define MIN_ABBR_OPTIMIZE 0
#define IGNORED_SCORE 0.9
#define SKIPPED_SCORE 0.15
CGFloat QSScoreForAbbreviationWithRanges(CFStringRef str, CFStringRef abbr, id mask, CFRange strRange, CFRange abbrRange);
CGFloat QSScoreForAbbreviation(CFStringRef str, CFStringRef abbr, id mask) {
return QSScoreForAbbreviationOrTransliteration(str, abbr, mask);
}
CGFloat QSScoreForAbbreviationOrTransliteration(CFStringRef str, CFStringRef abbr, id mask) {
CGFloat score = QSScoreForAbbreviationWithRanges(str, abbr, mask, CFRangeMake(0, CFStringGetLength(str)), CFRangeMake(0, CFStringGetLength(abbr)));
if (score == 0) {
CFMutableStringRef mutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, str);
CFStringTransform(mutableString, nil, kCFStringTransformToLatin, false);
if (CFStringCompare(str, mutableString, 0) != kCFCompareEqualTo) {
// only do this if the two strings are not equal (otherwise it's a wasted compute)
score = QSScoreForAbbreviationWithRanges(mutableString, abbr, nil, CFRangeMake(0, CFStringGetLength(mutableString)), CFRangeMake(0, CFStringGetLength(abbr)));
}
if (mutableString) {
CFRelease(mutableString);
}
return score;
}
return score;
}
CGFloat QSScoreForAbbreviationWithRanges(CFStringRef str, CFStringRef abbr, id mask, CFRange strRange, CFRange abbrRange) {
printf("call: %s\n", CFStringGetCStringPtr(abbr, kCFStringEncodingMacRoman));
if (!abbrRange.length)
return IGNORED_SCORE; //deduct some points for all remaining letters
if (abbrRange.length > strRange.length)
return 0.0;
static CFCharacterSetRef wordSeparator = NULL;
static CFCharacterSetRef uppercase = NULL;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
wordSeparator = CFCharacterSetCreateMutableCopy(NULL, CFCharacterSetGetPredefined(kCFCharacterSetWhitespace));
CFCharacterSetAddCharactersInString((CFMutableCharacterSetRef)wordSeparator, (CFStringRef)@".");
uppercase = CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter);
});
// Create an inline buffer version of str. Will be used in loop below
// for faster lookups.
CFStringInlineBuffer inlineBuffer;
CFStringInitInlineBuffer(str, &inlineBuffer, strRange);
// this will correctly fill the buffer with the entire string
// CFStringInitInlineBuffer(str, &inlineBuffer, CFRangeMake(0, CFStringGetLength(str)));
CFLocaleRef userLoc = CFLocaleCopyCurrent();
CGFloat score = 0.0, remainingScore = 0.0;
CFIndex i, j;
CFRange matchedRange, remainingStrRange, adjustedStrRange = strRange;
// Search for steadily smaller portions of the abbreviation
for (i = abbrRange.length; i > 0; i--) {
CFStringRef curAbbr = CFStringCreateWithSubstring (NULL, abbr, CFRangeMake(abbrRange.location, i) );
// terminality
// axeen
BOOL found = CFStringFindWithOptionsAndLocale(str, curAbbr,
CFRangeMake(adjustedStrRange.location, adjustedStrRange.length - abbrRange.length + i),
kCFCompareCaseInsensitive | kCFCompareDiacriticInsensitive | kCFCompareLocalized,
userLoc, &matchedRange);
printf("%i found: %i\n", (int) i, found);
// this prints null when the string gets down to 1 or 2 chars. ffs.
// printf("%i %s\n", (int) i, CFStringGetCStringPtr(curAbbr, kCFStringEncodingUTF8));
CFShow(curAbbr);
CFRelease(curAbbr);
if (!found) {
continue;
}
if (mask) {
[mask addIndexesInRange:NSMakeRange(matchedRange.location, matchedRange.length)];
}
remainingStrRange.location = matchedRange.location + matchedRange.length;
remainingStrRange.length = strRange.location + strRange.length - remainingStrRange.location;
// Search what is left of the string with the rest of the abbreviation
remainingScore = QSScoreForAbbreviationWithRanges(str, abbr, mask, remainingStrRange, CFRangeMake(abbrRange.location + i, abbrRange.length - i));
if (remainingScore) {
score = remainingStrRange.location-strRange.location;
// ignore skipped characters if is first letter of a word
if (matchedRange.location > strRange.location) {
// if some letters were skipped
UniChar previousChar = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, matchedRange.location - 1);
UniChar character = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, matchedRange.location);
printf("prev and current: %c %c (%i %i)\n", previousChar, character, (int) matchedRange.location - 1, (int) matchedRange.location);
if (CFCharacterSetIsCharacterMember(wordSeparator, previousChar)) {
// We're on the first letter of a word
for (j = matchedRange.location - 2; j >= strRange.location; j--) {
if (CFCharacterSetIsCharacterMember(wordSeparator, CFStringGetCharacterFromInlineBuffer(&inlineBuffer, j)))
score--;
else
score -= SKIPPED_SCORE;
}
} else if (CFCharacterSetIsCharacterMember(uppercase, character)) {
for (j = matchedRange.location - 1; j >= strRange.location; j--) {
if (CFCharacterSetIsCharacterMember(uppercase, CFStringGetCharacterFromInlineBuffer(&inlineBuffer, j)))
score--;
else
score -= SKIPPED_SCORE;
}
} else {
printf("before: %.20f minus %i %f\n", score, (matchedRange.location-strRange.location)/2, (float) (matchedRange.location-strRange.location)/2);
score -= (matchedRange.location-strRange.location)/2;
printf("after: %.20f\n", score);
}
}
score += remainingScore * remainingStrRange.length;
score /= strRange.length;
CFRelease(userLoc);
printf("score: %.20f\n", score);
return score;
}
}
CFRelease(userLoc);
return 0;
}
int main(int argc, const char * argv[]) {
CFStringRef str = CFSTR("Test string");
// printf("%.20f\n", QSScoreForAbbreviation(str, CFSTR("t"), nil));
// printf("%.20f\n", QSScoreForAbbreviation(str, CFSTR("ts"), nil));
printf("%.20f\n", QSScoreForAbbreviation(str, CFSTR("tet"), nil));
// printf("%.20f\n", QSScoreForAbbreviation(str, CFSTR("str"), nil));
// printf("%.20f\n", QSScoreForAbbreviation(str, CFSTR("ng"), nil));
printf("%.20f\n", QSScoreForAbbreviation(CFSTR("react hot loader"), CFSTR("rhl"), nil));
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment