On 25 août 2011, at 07:58, Roberto Colnaghi wrote:
int collationAnyCIAI(void *arg1, int str1Length, const void *str1, int
str2Length, const void *str2) {
NSString *strA = [NSString hexStringWithData:str1 ofLength:1];
NSString *strB = [NSString hexStringWithData:str2 ofLength:1];
int striA;
sscanf([strA cString], "%x", &striA);
int striB;
sscanf([strB cString], "%x", &striB);
I am a lot more experienced with iOS than SQLite, so my 2 cents are biased. In
particular, I have never had to use a custom collation for SQLite. That being
said, the snippet of code I quoted makes me cringe a little, and unless you
have reasons to avoid Cocoa [Touch] entirely, why don't you use it?
In the present case, the NSString class has extensive comparison options,
including the following:
NSDiacriticInsensitiveSearch
Search ignores diacritic marks.
For example, ‘ö’ is equal to ‘o’.
Available in iOS 2.0 and later.
Declared in NSString.h.
This option is passed to:
- (NSComparisonResult)compare:(NSString *)aString
options:(NSStringCompareOptions)mask
Using this option is as simple as calling:
return [strA compare:strB options: NSDiacriticInsensitiveSearch];
You also have variations that take into account the user's current locale:
return [strA localizedCompare:strB];
return [strA localizedCaseInsensitiveCompare:strB];
As those two routines end up calling
- (NSComparisonResult)compare:(NSString *)aString
options:(NSStringCompareOptions)mask range:(NSRange)range locale:(id)locale
They call it passing the current user locale as the locale ([NSLocale
currentLocale]), and the string full range as the range.
You could even use a "smart" comparison using
return [strA localizedStandardCompare: strB]
The methods orders strings in a "natural" order "as in the Finder". For
example, it would order the strings "file 9.txt", "file 20.txt", "file 100.txt"
in that order.
(By the way, the result returned by Cocoa string comparison methods seems
compatible with what SQLite expects:
enum {
NSOrderedAscending<file:///Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS5_0.iOSLibrary.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html#//apple_ref/doc/c_ref/NSOrderedAscending>
= -1,
NSOrderedSame<file:///Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS5_0.iOSLibrary.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html#//apple_ref/doc/c_ref/NSOrderedSame>,
NSOrderedDescending<file:///Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS5_0.iOSLibrary.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html#//apple_ref/doc/c_ref/NSOrderedDescending>
};
typedef NSInteger NSComparisonResult;
if I am mistaken (I haven't looked it put), it looks like converting it should
be straightforward).
But maybe you have good reasons to ignore the Apple-provided collations. In
that case, I still don't get why you don't work directly on the Unicode
strings. You call hexStringWithData:ofLength: (which is not an Apple method and
for which you don't provide the code). Why? What would be wrong with:
NSString *strA = [[NSString alloc] initWithUTF8String:str1]; // release me
before returning
NSString *strB = [[NSString alloc] initWithUTF8String:str2]; // release me
before returning
Or, if the strings from SQLite are not UTF-8 encoded, use
- (id)initWithCString:(const char *)nullTerminatedCString
encoding:(NSStringEncoding)encoding
Then you don't have to do this wasteful charade with hex conversion.
Finally, if hexStringWithData:ofLength: is properly implemented, it returns an
autoreleased string. If the collation routine is called a lot by SQLite, you
will allocate NSStrings like crazy, which is not good citizenship on an iPhone
that could lead your app to be killed by the OS, even if the autoreleased
strings eventually get deallocated the next time in the run loop. Unless you
wrap the whole enchilada in your own autorelease pool (you didn't show that).
In your specific case, it's better to allocate and release your NSStrings right
in your collation routine.
I hope this helps a little.
JD
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users