/ NSString.m
NSString.m
1 // 2 // NSString.m 3 // CoreFoundation 4 // 5 // Copyright (c) 2014 Apportable. All rights reserved. 6 // 7 8 #import <Foundation/NSData.h> 9 #import <unicode/uchar.h> 10 #import <objc/runtime.h> 11 #import "NSStringInternal.h" 12 #import "NSObjectInternal.h" 13 #import "CFPriv.h" 14 #import "ForFoundationOnly.h" 15 16 static inline CFStringRef __CFExceptionProem(id self, SEL _cmd) { 17 const char *className = class_getName([self class]); 18 if (!className) { 19 className = "NULL CLASS"; 20 } 21 const char *selName = sel_getName(_cmd); 22 if (!selName) { 23 selName = "NULL SEL"; 24 } 25 26 CFStringRef proem = nil; 27 char *allocBuf = NULL; 28 asprintf(&allocBuf, "(%s/%s)", className, selName); 29 if (allocBuf) { 30 proem = CFStringCreateWithCString(NULL, allocBuf, kCFStringEncodingUTF8); 31 proem = CFMakeCollectable(proem); 32 free(allocBuf); 33 } 34 return proem; 35 } 36 37 static inline void mutateError(id self, SEL _cmd, int err) { 38 switch (err) { 39 case _CFStringErrNone: 40 break; 41 case _CFStringErrNotMutable: 42 NSSTRING_INVALIDMUTATIONERROR; 43 break; 44 case _CFStringErrNilArg: 45 NSSTRING_NILSTRINGERROR; 46 break; 47 case _CFStringErrBounds: 48 NSSTRING_BOUNDSERROR; 49 break; 50 default: 51 NSSTRING_ILLEGALREQUESTERROR; 52 break; 53 } 54 } 55 56 @implementation __NSCFString 57 58 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key 59 { 60 return NO; 61 } 62 63 - (NSUInteger)replaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSStringCompareOptions)options range:(NSRange)searchRange 64 { 65 if (!_CFStringIsMutable((CFStringRef)self)) 66 { 67 NSInvalidMutation(); 68 return NSNotFound; 69 } 70 71 if ((options & NSRegularExpressionSearch) != 0) 72 { 73 return [super replaceOccurrencesOfString:target withString:replacement options:options range:searchRange]; 74 } 75 else 76 { 77 CFStringCompareFlags flags = (CFStringCompareFlags)options; 78 if ((options & NSLiteralSearch) == 0) 79 { 80 flags |= kCFCompareNonliteral; 81 } 82 return CFStringFindAndReplace((CFMutableStringRef)self, (CFStringRef)target, (CFStringRef)replacement, CFRangeMake(searchRange.location, searchRange.length), flags); 83 } 84 } 85 86 - (void)appendCharacters:(unichar *)characters length:(NSUInteger)length 87 { 88 if (_CFStringIsMutable((CFStringRef)self)) 89 { 90 CFStringAppendCharacters((CFMutableStringRef)self, characters, length); 91 } 92 else 93 { 94 NSInvalidMutation(); 95 } 96 } 97 98 - (void)setString:(NSString *)str 99 { 100 if (_CFStringIsMutable((CFStringRef)self)) 101 { 102 CFStringReplaceAll((CFMutableStringRef)self, (CFStringRef)str); 103 } 104 else 105 { 106 NSInvalidMutation(); 107 } 108 } 109 110 - (void)appendFormat:(NSString *)format, ... 111 { 112 if (_CFStringIsMutable((CFStringRef)self)) 113 { 114 va_list args; 115 va_start(args, format); 116 _CFStringAppendFormatAndArgumentsAux((CFMutableStringRef)self, &_NSCFCopyDescription2, NULL, (CFStringRef)format, args); 117 va_end(args); 118 } 119 else 120 { 121 NSInvalidMutation(); 122 } 123 } 124 125 - (void)deleteCharactersInRange:(NSRange)range 126 { 127 if (_CFStringIsMutable((CFStringRef)self)) 128 { 129 CFStringDelete((CFMutableStringRef)self, CFRangeMake(range.location, range.length)); 130 } 131 else 132 { 133 NSInvalidMutation(); 134 } 135 } 136 137 - (void)appendString:(NSString *)str 138 { 139 CFIndex len = _CFStringGetLength2((CFStringRef)self); 140 int ret = __CFStringCheckAndReplace((CFMutableStringRef)self, CFRangeMake(len, 0), (CFStringRef)str); 141 mutateError(self, _cmd, ret); 142 } 143 144 - (void)insertString:(NSString *)str atIndex:(NSUInteger)index 145 { 146 if (_CFStringIsMutable((CFStringRef)self)) 147 { 148 CFStringInsert((CFMutableStringRef)self, index, (CFStringRef)str); 149 } 150 else 151 { 152 NSInvalidMutation(); 153 } 154 } 155 156 - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)replacement 157 { 158 if (_CFStringIsMutable((CFStringRef)self)) 159 { 160 CFStringReplace((CFMutableStringRef)self, CFRangeMake(range.location, range.length), (CFStringRef)replacement); 161 } 162 else 163 { 164 NSInvalidMutation(); 165 } 166 } 167 168 - (BOOL)_isCString 169 { 170 return __CFStringIsEightBit((CFStringRef)self); 171 } 172 173 - (Class)classForCoder 174 { 175 if (_CFStringIsMutable((CFStringRef)self)) 176 { 177 return objc_lookUpClass("NSMutableString"); 178 } 179 else 180 { 181 return objc_lookUpClass("NSString"); 182 } 183 } 184 185 - (NSStringEncoding)smallestEncoding 186 { 187 return CFStringConvertEncodingToNSStringEncoding(CFStringGetSmallestEncoding((CFStringRef)self)); 188 } 189 190 - (NSStringEncoding)fastestEncoding 191 { 192 return CFStringConvertEncodingToNSStringEncoding(CFStringGetFastestEncoding((CFStringRef)self)); 193 } 194 195 - (id)mutableCopyWithZone:(NSZone *)zone 196 { 197 return (id)CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef)self); 198 } 199 200 - (id)copyWithZone:(NSZone *)zone 201 { 202 return (id)CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef)self); 203 } 204 205 - (void)getLineStart:(NSUInteger *)startPtr end:(NSUInteger *)lineEndPtr contentsEnd:(NSUInteger *)contentsEndPtr forRange:(NSRange)range 206 { 207 CFStringGetLineBounds((CFStringRef)self, CFRangeMake(range.location, range.length), (CFIndex *)startPtr, (CFIndex *)lineEndPtr, (CFIndex *)contentsEndPtr); 208 } 209 210 - (BOOL)hasSuffix:(NSString *)prefix 211 { 212 return CFStringHasSuffix((CFStringRef)self, (CFStringRef)prefix); 213 } 214 215 - (BOOL)hasPrefix:(NSString *)suffix 216 { 217 return CFStringHasPrefix((CFStringRef)self, (CFStringRef)suffix); 218 } 219 220 - (BOOL)isEqualToString:(NSString *)other 221 { 222 if (other == nil) 223 { 224 return NO; 225 } 226 227 return CFEqual((CFTypeRef)self, (CFTypeRef)other); 228 } 229 230 - (BOOL)isEqual:(id)other 231 { 232 if (other == nil) 233 { 234 return NO; 235 } 236 237 return CFEqual((CFTypeRef)self, (CFTypeRef)other); 238 } 239 240 - (id)substringWithRange:(NSRange)range 241 { 242 return [(__NSCFString *)CFStringCreateWithSubstring(kCFAllocatorDefault, (CFStringRef)self, CFRangeMake(range.location, range.length)) autorelease]; 243 } 244 245 - (BOOL)getCString:(char *)bytes maxLength:(NSUInteger)maxLength encoding:(NSStringEncoding)encoding 246 { 247 return CFStringGetCString((CFStringRef)self, bytes, maxLength, CFStringConvertNSStringEncodingToEncoding(encoding)); 248 } 249 250 - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding 251 { 252 CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding); 253 254 if (cfEncoding == kCFStringEncodingInvalidId) 255 { 256 return NULL; 257 } 258 const char *str = CFStringGetCStringPtr((CFStringRef)self, cfEncoding); 259 260 if (str != NULL) 261 { 262 return str; 263 } 264 else 265 { 266 #pragma clang diagnostic push 267 #pragma clang diagnostic ignored "-Wobjc-method-access" 268 return [super cStringUsingEncoding:encoding]; 269 #pragma clang diagnostic pop 270 } 271 } 272 273 - (NSUInteger)cStringLength 274 { 275 return [(NSString *)self lengthOfBytesUsingEncoding:CFStringConvertEncodingToNSStringEncoding(CFStringGetSystemEncoding())]; 276 } 277 278 static inline const char *cStringForEncoding(__NSCFString *self, CFStringEncoding encoding, BOOL allowLossyConversion) 279 { 280 const char *str = CFStringGetCStringPtr((CFStringRef)self, encoding); 281 282 if (str == NULL) 283 { 284 NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(encoding); 285 NSUInteger length = [(NSString *)self lengthOfBytesUsingEncoding:enc]; 286 NSMutableData *data = [[NSMutableData alloc] initWithCapacity:length + 1]; 287 [data setLength:length + 1]; 288 NSStringEncodingConversionOptions opts = 0; 289 if (allowLossyConversion) 290 { 291 opts = NSStringEncodingConversionAllowLossy|NSStringEncodingConversionExternalRepresentation; 292 } 293 [self getBytes:[data mutableBytes] maxLength:length usedLength:NULL encoding:enc options:opts range:NSMakeRange(0, [self length]) remainingRange:NULL]; 294 str = [data bytes]; 295 [data autorelease]; 296 } 297 298 return str; 299 } 300 301 - (const char *)UTF8String 302 { 303 return cStringForEncoding(self, kCFStringEncodingUTF8, NO); 304 } 305 306 - (const char *)cString 307 { 308 return cStringForEncoding(self, CFStringGetSystemEncoding(), NO); 309 } 310 311 - (const char *)lossyCString 312 { 313 return cStringForEncoding(self, CFStringGetSystemEncoding(), YES); 314 } 315 316 - (const char *)_fastCStringContents:(BOOL)unused 317 { 318 CFStringEncoding encoding = CFStringGetSystemEncoding(); 319 return CFStringGetCStringPtr((CFStringRef)self, encoding); 320 } 321 322 - (const unichar*)_fastCharacterContents 323 { 324 return CFStringGetCharactersPtr((CFStringRef)self); 325 } 326 327 - (void)getCharacters:(unichar *)buffer range:(NSRange)range 328 { 329 CFStringGetCharacters((CFStringRef)self, CFRangeMake(range.location, range.length), buffer); 330 } 331 332 - (unichar)characterAtIndex:(NSUInteger)index 333 { 334 return CFStringGetCharacterAtIndex((CFStringRef)self, index); 335 } 336 337 - (NSUInteger)length 338 { 339 return _CFStringGetLength2((CFStringRef)self); 340 } 341 342 - (NSUInteger)hash 343 { 344 return __CFStringHash((CFTypeRef)self); 345 } 346 347 - (NSUInteger)retainCount 348 { 349 return CFGetRetainCount((CFTypeRef)self); 350 } 351 352 - (BOOL)_isDeallocating 353 { 354 return _CFIsDeallocating((CFTypeRef)self); 355 } 356 357 - (BOOL)_tryRetain 358 { 359 return _CFTryRetain((CFTypeRef)self) != NULL; 360 } 361 362 - (oneway void)release 363 { 364 CFRelease((CFTypeRef)self); 365 } 366 367 - (id)retain 368 { 369 return (id)CFRetain((CFTypeRef)self); 370 } 371 372 - (BOOL)isNSString__ 373 { 374 return YES; 375 } 376 377 - (CFTypeID)_cfTypeID 378 { 379 return CFStringGetTypeID(); 380 } 381 382 @end