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
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to