Revision: 4746
http://skim-app.svn.sourceforge.net/skim-app/?rev=4746&view=rev
Author: amaxwell
Date: 2008-10-06 22:58:24 +0000 (Mon, 06 Oct 2008)
Log Message:
-----------
Remove private use or partial surrogate pairs, as well as other private use
characters.
Modified Paths:
--------------
trunk/NSString_SKExtensions.m
Modified: trunk/NSString_SKExtensions.m
===================================================================
--- trunk/NSString_SKExtensions.m 2008-10-06 17:26:46 UTC (rev 4745)
+++ trunk/NSString_SKExtensions.m 2008-10-06 22:58:24 UTC (rev 4746)
@@ -143,18 +143,83 @@
return
[(id)SKStringCreateByCollapsingAndTrimmingWhitespaceAndNewlines(CFAllocatorGetDefault(),
(CFStringRef)self) autorelease];
}
+// NS and CF character sets won't find these, due to the way CFString handles
surrogate pairs. These inlines were borrowed from CFCharacterSetPriv.h in
CF-lite-476.13.
+static inline bool __SKIsSurrogateHighCharacter(UniChar character) {
+ return ((character >= 0xD800UL) && (character <= 0xDBFFUL) ? true : false);
+}
+
+static inline bool __SKIsSurrogateLowCharacter(UniChar character) {
+ return ((character >= 0xDC00UL) && (character <= 0xDFFFUL) ? true : false);
+}
+
+static inline UTF32Char __SKGetLongCharacterForSurrogatePair(UniChar
surrogateHigh, UniChar surrogateLow) {
+ return ((surrogateHigh - 0xD800UL) << 10) + (surrogateLow - 0xDC00UL) +
0x0010000UL;
+}
+
+#define SURROGATE_START 0xD800
+#define SURROGATE_END 0xDFFF
+
+// remove anything in the private use planes, and/or malformed surrogate pair
sequences
- (NSString *)stringByRemovingAliens {
- NSCharacterSet *charSet = [NSCharacterSet privateUseCharacterSet];
- if ([self rangeOfCharacterFromSet:charSet].length) {
- NSMutableString *ms = [[self mutableCopy] autorelease];
- NSRange r = [ms rangeOfCharacterFromSet:charSet];
- while (r.length) {
- [ms deleteCharactersInRange:r];
- r = [ms rangeOfCharacterFromSet:charSet];
+
+ // make a mutable copy only if needed
+ CFMutableStringRef theString = NULL;
+
+ CFStringInlineBuffer inlineBuffer;
+ CFIndex length = CFStringGetLength((void *)self);
+
+ // use the current mutable string with the inline buffer, but make a new
mutable copy if needed
+ CFStringInitInlineBuffer((void *)self, &inlineBuffer, CFRangeMake(0,
length));
+ UniChar ch;
+ NSCharacterSet *privateUse = [NSCharacterSet privateUseCharacterSet];
+
+#define LAZY_COPY do{if(NULL==theString){theString=(void*)[[self mutableCopy]
autorelease];}} while(0)
+
+ // idx is current index into the inline buffer, and delIdx is current
index in the mutable string
+ CFIndex idx = 0, delIdx = 0;
+ while(idx < length){
+ ch = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, idx);
+ if ([privateUse characterIsMember:ch]) {
+ LAZY_COPY;
+ CFStringDelete(theString, CFRangeMake(delIdx, 1));
+ } else if ((ch >= SURROGATE_START) && (ch <= SURROGATE_END)) {
+
+ if ((idx + 1) < length) {
+
+ UniChar highChar = ch;
+ UniChar lowChar =
CFStringGetCharacterFromInlineBuffer(&inlineBuffer, idx + 1);
+ UTF32Char longChar =
__SKGetLongCharacterForSurrogatePair(highChar, lowChar);
+ // if we only have half of a surrogate pair, delete the
offending character
+ if (__SKIsSurrogateLowCharacter(lowChar) == false ||
__SKIsSurrogateHighCharacter(highChar) == false) {
+ LAZY_COPY;
+ CFStringDelete(theString, CFRangeMake(delIdx, 1));
+ // only deleted a single char, so don't need to adjust idx
+ } else if
(CFCharacterSetIsLongCharacterMember((CFCharacterSetRef)privateUse, longChar)) {
+ LAZY_COPY;
+ // remove the pair; can't display private use characters
+ CFStringDelete(theString, CFRangeMake(delIdx, 2));
+ // adjust since we removed two characters...
+ idx++;
+ } else {
+ // valid surrogate pair, so we'll leave it alone
+ delIdx += 2;
+ idx++;
+ }
+
+ } else {
+ // insufficient length for this to be a valid sequence, so
it's only half of a surrogate pair
+ LAZY_COPY;
+ CFStringDelete(theString, CFRangeMake(delIdx, 1));
+ }
+
+ } else {
+ // keep track of our index in the copy and the original
+ delIdx++;
}
- return ms;
+ idx++;
}
- return self;
+
+ return (NULL == theString ? self : (id)theString);
}
- (NSString *)stringByAppendingEllipsis;
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit