PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/libFoundation/Foundation/NSString.m

http://sope-appserver.googlecode.com/
Objective C | 2495 lines | 1871 code | 437 blank | 187 comment | 344 complexity | 2a48239224ce3d32fc94baa473eb857e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. NSString.m
  3. Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
  4. All rights reserved.
  5. Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
  6. This file is part of libFoundation.
  7. Permission to use, copy, modify, and distribute this software and its
  8. documentation for any purpose and without fee is hereby granted, provided
  9. that the above copyright notice appear in all copies and that both that
  10. copyright notice and this permission notice appear in supporting
  11. documentation.
  12. We disclaim all warranties with regard to this software, including all
  13. implied warranties of merchantability and fitness, in no event shall
  14. we be liable for any special, indirect or consequential damages or any
  15. damages whatsoever resulting from loss of use, data or profits, whether in
  16. an action of contract, negligence or other tortious action, arising out of
  17. or in connection with the use or performance of this software.
  18. */
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <Foundation/common.h>
  22. #include <Foundation/NSArray.h>
  23. #include <Foundation/NSAutoreleasePool.h>
  24. #include <Foundation/NSData.h>
  25. #include <Foundation/NSDictionary.h>
  26. #include <Foundation/NSCoder.h>
  27. #include <Foundation/NSURL.h>
  28. #include <Foundation/NSURLHandle.h>
  29. #include <Foundation/NSException.h>
  30. #include <Foundation/exceptions/StringExceptions.h>
  31. #include <Foundation/exceptions/GeneralExceptions.h>
  32. #include <Foundation/PropertyListParser.h>
  33. #include <Foundation/NSCharacterSet.h>
  34. #include <Foundation/NSString.h>
  35. #include <Foundation/NSThread.h>
  36. #include <Foundation/NSNotification.h>
  37. #include <Foundation/NSConcreteString.h>
  38. #include <Foundation/NSPathUtilities.h>
  39. #include <Foundation/NSByteOrder.h>
  40. #include "PrivateThreadData.h"
  41. #include "NSObject+PropLists.h"
  42. #include <locale.h>
  43. #include <netinet/in.h>
  44. int NSConvertUTF16toUTF8(unichar **sourceStart,
  45. const unichar *sourceEnd,
  46. unsigned char **targetStart,
  47. const unsigned char *targetEnd);
  48. int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd,
  49. unichar **targetStart, const unichar *targetEnd);
  50. id NSInitStringWithData(NSString *self, NSData *data,
  51. NSStringEncoding encoding);
  52. NSData *dataUsingEncoding(NSString *self,
  53. NSStringEncoding encoding, BOOL flag);
  54. /*
  55. General ideas in NSString class cluster implementation
  56. The NSString class is an abstract class that uses only unicode representation
  57. and handles in an inefficient manner since it operates on abstract strings
  58. accessing characters one by one using characterAtIndex: method.
  59. Currently there is only one abstract subclass of classes designed to implement
  60. ANSI C strings in the default encoding provided by the operating system
  61. (assumed ASCII or ASCII extension like NEXTSTEP). This type of strings are called NS8BitString since they uses characters (usually represented on 8 bits)
  62. for immutable classes and NSMutable8BitString for mutable ones respectively.
  63. This tree of classes is implemented based on `__compact8BitBytes' method
  64. that returns a pointer to the internal representation of the string as char[],
  65. with all characters compact, with no gap.
  66. Unicode and encodings will be supported in the future when I will know
  67. how to handle the following (If you know about these please send me a message)
  68. - convert between different encodings
  69. - convert characters to upper/lower cases
  70. - handle composed character sequences
  71. So for the time being only NS8BitString/NSMutable8BitString are used but their
  72. use in the future will be limited to ...WithCString... methods and the strings
  73. generated by the compiler with @"" construct (which should generate unicode
  74. ones some day in the future).
  75. There is another problem: methods like initWithCharacters... and
  76. initWithCString assume that the underlying support is 16Bit respectively 8Bit
  77. but it is sent to an instance allocated with [NSString alloc]. So we make
  78. NSString alloc method to return a temporary string that will allocate and
  79. initialize the concrete class that will hold the character in initWith...
  80. methods. This class is NSTemporaryString. Thus one must use constructs like
  81. var = [[NSString alloc] initWith...]
  82. var = [NSString stringWith...]
  83. but not
  84. var = [NSString alloc]
  85. [var initWith...]
  86. since the second line will return an instance different from the one in var.
  87. */
  88. #define USE_SINGLE8BITSTRING 1
  89. // #define HAS_UNICODE_STRING 1
  90. /***************************
  91. * NSString abstract class
  92. ***************************/
  93. #if USE_SINGLE8BITSTRING
  94. static id Single8BitStringStore[256];
  95. static Class Single8BitStringClass = Nil;
  96. static inline id _getSingle8BitString(unsigned char _byte) {
  97. register id str;
  98. if (Single8BitStringClass == Nil) {
  99. Single8BitStringClass = [NSCharacter8BitString class];
  100. memset(Single8BitStringStore, 0, sizeof(Single8BitStringStore));
  101. }
  102. if ((str = Single8BitStringStore[(int)_byte]) == nil) {
  103. str = [[Single8BitStringClass allocWithZone:nil]
  104. initWithCString:(char *)&_byte length:1];
  105. Single8BitStringStore[(unsigned int)_byte] = str;
  106. #if DEBUG && 0
  107. printf("%s: add str[%p] for char %c\n", __PRETTY_FUNCTION__,
  108. str, _byte);
  109. #endif
  110. }
  111. return str;
  112. }
  113. #endif
  114. @implementation NSString
  115. static Class NSStringClass = Nil;
  116. + (void)initialize
  117. {
  118. const char *cstr;
  119. if (NSStringClass == Nil)
  120. NSStringClass = [NSString class];
  121. #ifndef __WIN32__
  122. /* required for toupper/tolower to work with umlauts */
  123. if ((cstr = getenv("LC_CTYPE")))
  124. setlocale(LC_CTYPE, cstr);
  125. if ((cstr = getenv("LC_COLLATE")))
  126. setlocale(LC_COLLATE, cstr);
  127. #endif
  128. NSUserName();
  129. }
  130. /* Getting a string's length */
  131. - (unsigned int)length
  132. {
  133. [self subclassResponsibility:_cmd];
  134. return 0;
  135. }
  136. /* Accessing characters */
  137. - (unichar)characterAtIndex:(unsigned int)index
  138. {
  139. [self subclassResponsibility:_cmd];
  140. return 0;
  141. }
  142. - (void)getCharacters:(unichar*)buffer
  143. {
  144. NSRange range = {0, [self length]};
  145. [self getCharacters:buffer range:range];
  146. }
  147. - (void)getCharacters:(unichar *)buffer range:(NSRange)aRange
  148. {
  149. register unsigned int i = 0;
  150. IMP imp = [self methodForSelector:@selector(characterAtIndex:)];
  151. if (aRange.location + aRange.length > [self length]) {
  152. [[[IndexOutOfRangeException alloc]
  153. initWithFormat:@"range (%d,%d) in string %x of length %d",
  154. aRange.location, aRange.length, self, [self length]] raise];
  155. }
  156. for (i = 0; i < aRange.length; i++) {
  157. buffer[i] = (unichar)(long)(*imp)(self, @selector(characterAtIndex:),
  158. aRange.location + i);
  159. }
  160. }
  161. /* Combining strings */
  162. - (NSString *)stringByAppendingString:(NSString *)aString
  163. {
  164. unichar *buf;
  165. unsigned len1, len2;
  166. NSString *s;
  167. len1 = [self length];
  168. len2 = [aString length];
  169. if (len2 == 0)
  170. return [[self copy] autorelease];
  171. buf = calloc(len1 + len2 + 1, sizeof(unichar));
  172. [self getCharacters:buf];
  173. [aString getCharacters:&(buf[len1])];
  174. buf[len1 + len2] = 0;
  175. s = [NSStringClass stringWithCharacters:buf length:(len1 + len2)];
  176. free(buf);
  177. return s;
  178. }
  179. - (NSString*)stringByAppendingFormat:(NSString*)format,...
  180. {
  181. NSMutableString *string = [self mutableCopy];
  182. va_list va;
  183. va_start(va, format);
  184. [string appendFormat:format arguments:va];
  185. va_end(va);
  186. return AUTORELEASE(string);
  187. }
  188. - (NSString*)stringByAppendingFormat:(NSString*)format
  189. arguments:(va_list)argList
  190. {
  191. NSMutableString *string = [self mutableCopy];
  192. [string appendFormat:format arguments:argList];
  193. return AUTORELEASE(string);
  194. }
  195. - (NSString*)stringByPrependingString:(NSString*)aString
  196. {
  197. return [aString stringByAppendingString:self];
  198. }
  199. - (NSString*)stringByPrependingFormat:(NSString*)format,...
  200. {
  201. NSString *string;
  202. va_list va;
  203. va_start(va, format);
  204. string = Avsprintf(format, va);
  205. va_end(va);
  206. return [string stringByAppendingString:self];
  207. }
  208. - (NSString*)stringByPrependingFormat:(NSString*)format
  209. arguments:(va_list)argList
  210. {
  211. NSString *string = Avsprintf(format, argList);
  212. return [string stringByAppendingString:self];
  213. }
  214. /* Dividing strings */
  215. - (NSArray *)componentsSeparatedByString:(NSString *)separator
  216. {
  217. unsigned int first = 0, last = 0;
  218. unsigned int slen;
  219. NSMutableArray *components;
  220. if ((slen = [separator length]) == 0)
  221. return [NSArray arrayWithObject:self];
  222. if ([self length] == 0)
  223. return [NSArray arrayWithObject:self];
  224. components = [NSMutableArray arrayWithCapacity:16];
  225. while ((first = [self indexOfString:separator fromIndex:last]) !=NSNotFound) {
  226. NSRange range;
  227. NSString *substring;
  228. range.location = last;
  229. range.length = (first - last);
  230. substring = [self substringWithRange:range];
  231. [components addObject:substring];
  232. last = first + slen;
  233. }
  234. if ([self length] >= last) {
  235. NSString *lastComponent;
  236. lastComponent = [self substringFromIndex:last];
  237. [components addObject:lastComponent];
  238. }
  239. return components;
  240. }
  241. - (NSString *)substringWithRange:(NSRange)aRange
  242. {
  243. unichar * buf;
  244. id rc;
  245. if (aRange.location + aRange.length > [self length] )
  246. [[[IndexOutOfRangeException alloc]
  247. initWithFormat:@"range (%d,%d) in string %x of length %d",
  248. aRange.location, aRange.length, self, [self length]] raise];
  249. if (aRange.length == 0)
  250. return @"";
  251. buf = MallocAtomic(sizeof(unichar) * (aRange.length + 1));
  252. [self getCharacters:buf range:aRange];
  253. rc = AUTORELEASE([[NSStringClass alloc]
  254. initWithCharactersNoCopy:buf
  255. length:aRange.length
  256. freeWhenDone:YES]);
  257. return rc;
  258. }
  259. - (NSString *)substringFromRange:(NSRange)aRange
  260. {
  261. return [self substringWithRange:aRange];
  262. }
  263. - (NSString *)substringFromIndex:(unsigned int)index
  264. {
  265. NSRange range;
  266. range.location = index;
  267. range.length = [self length]; //- index
  268. if (range.length < index) {
  269. [[[IndexOutOfRangeException alloc]
  270. initWithFormat:@"index %d in string %x of length %d",
  271. index, self, [self length]] raise];
  272. }
  273. range.length -= index;
  274. return [self substringWithRange:range];
  275. }
  276. - (NSString*)substringToIndex:(unsigned int)index
  277. {
  278. NSRange range = {0, index};
  279. return [self substringWithRange:range];
  280. }
  281. - (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)_set
  282. {
  283. unsigned len;
  284. unichar *buf;
  285. unsigned idx;
  286. unsigned ridx;
  287. BOOL (*isMem)(id,SEL,unichar);
  288. if ((len = [self length]) == 0)
  289. return [[self copy] autorelease];
  290. buf = calloc(len + 1, sizeof(unichar));
  291. [self getCharacters:buf];
  292. isMem = (void *)[_set methodForSelector:@selector(characterIsMember:)];
  293. for (idx = 0;
  294. (idx < len) && isMem(_set,@selector(characterIsMember:),buf[idx]);
  295. idx++)
  296. ;
  297. for (ridx = len-1;
  298. (ridx >= idx) && isMem(_set,@selector(characterIsMember:),buf[ridx]);
  299. ridx--)
  300. ;
  301. self = [NSStringClass stringWithCharacters:&(buf[idx])
  302. length:((ridx+1) - idx)];
  303. free(buf);
  304. return self;
  305. }
  306. /* Finding characters and substrings */
  307. - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
  308. {
  309. NSRange range = {0, [self length]};
  310. return [self rangeOfCharacterFromSet:aSet options:0 range:range];
  311. }
  312. - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
  313. options:(unsigned int)mask
  314. {
  315. NSRange range = {0, [self length]};
  316. return [self rangeOfCharacterFromSet:aSet options:mask range:range];
  317. }
  318. - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
  319. options:(unsigned int)mask range:(NSRange)aRange
  320. {
  321. // UNICODE
  322. // ENCODINGS - this code applies to the system's default encoding
  323. SEL characterIsMemberSel = @selector(characterIsMember:);
  324. IMP imp = [aSet methodForSelector:characterIsMemberSel];
  325. if (NSMaxRange(aRange) > [self length])
  326. [[[IndexOutOfRangeException alloc]
  327. initWithFormat:@"range %@ not in string 0x%08x of length %d",
  328. NSStringFromRange(aRange), self, [self length]] raise];
  329. if (mask & NSBackwardsSearch) {
  330. int i;
  331. for (i = aRange.length - 1; i >= aRange.location; i--) {
  332. unichar c = [self characterAtIndex:i];
  333. if ((*imp)(aSet, characterIsMemberSel, c) ||
  334. ((mask & NSCaseInsensitiveSearch)
  335. && ((islower(c)
  336. && (*imp)(aSet, characterIsMemberSel, toupper(c)))
  337. || (isupper(c)
  338. && (*imp)(aSet, characterIsMemberSel, tolower(c)))))) {
  339. return NSMakeRange(i, 1);
  340. }
  341. }
  342. }
  343. else {
  344. unsigned int i, max;
  345. max = NSMaxRange(aRange);
  346. for (i = aRange.location; i < max; i++) {
  347. unichar c = [self characterAtIndex:i];
  348. if ((*imp)(aSet, characterIsMemberSel, c) ||
  349. ((mask & NSCaseInsensitiveSearch) &&
  350. ((islower(c)
  351. && (*imp)(aSet, characterIsMemberSel, toupper(c)))
  352. || (isupper(c)
  353. && (*imp)(aSet, characterIsMemberSel, tolower(c)))))) {
  354. return NSMakeRange(i, 1);
  355. }
  356. }
  357. }
  358. return NSMakeRange(NSNotFound, 0);
  359. }
  360. - (NSRange)rangeOfString:(NSString*)string
  361. {
  362. NSRange range = {0, [self length]};
  363. return [self rangeOfString:string options:0 range:range];
  364. }
  365. - (NSRange)rangeOfString:(NSString*)string options:(unsigned int)mask
  366. {
  367. NSRange range = {0, [self length]};
  368. return [self rangeOfString:string options:mask range:range];
  369. }
  370. - (NSRange)rangeOfString:(NSString*)aString
  371. options:(unsigned int)mask range:(NSRange)aRange
  372. {
  373. // UNICODE
  374. // ENCODINGS - this code applies to the system's default encoding
  375. // islower needs to be replaced with proper NSCharacterSet calls (speed?)
  376. unsigned int i, a;
  377. NSRange range;
  378. if (aRange.location + aRange.length > [self length]) {
  379. [[[IndexOutOfRangeException alloc]
  380. initWithFormat:@"range (%d,%d) in string %x of length %d",
  381. aRange.location, aRange.length, self, [self length]] raise];
  382. }
  383. a = [aString length];
  384. if (a == 0 || aRange.length < a)
  385. return NSMakeRange(0,0);
  386. if (mask & NSAnchoredSearch) {
  387. range.location = aRange.location +
  388. ((mask & NSBackwardsSearch) ? aRange.length - a : 0);
  389. range.length = a;
  390. if ([self compare:aString options:mask range:range] == NSOrderedSame)
  391. return range;
  392. else
  393. return NSMakeRange(NSNotFound, 0);
  394. }
  395. if (mask & NSBackwardsSearch) {
  396. if (mask & NSCaseInsensitiveSearch) {
  397. // Backward case insensitive
  398. unichar cf;
  399. int n;
  400. cf = [aString characterAtIndex: 0 ];
  401. cf = islower(cf) ? toupper(cf) : cf;
  402. for (n = aRange.length - a; n >= 0; n--) {
  403. unichar ca = cf;
  404. unichar cm = [self characterAtIndex:n + aRange.location ];
  405. cm = islower(cm) ? toupper(cm) : cm;
  406. if (cm != ca)
  407. continue;
  408. for (i = 1; i < a; i++) {
  409. cm = [self characterAtIndex:n + i + aRange.location ];
  410. ca = [aString characterAtIndex:i];
  411. cm = islower(cm) ? toupper(cm) : cm;
  412. ca = islower(ca) ? toupper(ca) : ca;
  413. if (cm != ca)
  414. break;
  415. }
  416. if (i == a) {
  417. range.location = aRange.location + n;
  418. range.length = a;
  419. return range;
  420. }
  421. }
  422. }
  423. else {
  424. // Backward case sensitive
  425. int n;
  426. for (n = aRange.length - a; n >= 0; n--) {
  427. if ([self characterAtIndex:n + aRange.location]
  428. != [aString characterAtIndex:0])
  429. continue;
  430. for (i = 1; i < a; i++)
  431. if ([self characterAtIndex:(n + i + aRange.location)]
  432. != [aString characterAtIndex: i] )
  433. break;
  434. if (i == a) {
  435. range.location = aRange.location + n;
  436. range.length = a;
  437. return range;
  438. }
  439. }
  440. }
  441. }
  442. else {
  443. if (mask & NSCaseInsensitiveSearch) {
  444. // Forward case insensitive
  445. unsigned int n;
  446. unichar cf;
  447. cf = [aString characterAtIndex: n];
  448. cf = islower(cf) ? toupper(cf) : cf;
  449. for (n = 0; n + a <= aRange.length; n++) {
  450. unichar ca = cf;
  451. unichar cm = [self characterAtIndex: n + aRange.location ];
  452. cm = islower(cm) ? toupper(cm) : cm;
  453. if (cm != ca)
  454. continue;
  455. for (i = 1; i < a; i++) {
  456. cm = [self characterAtIndex:n + i + aRange.location];
  457. ca = [aString characterAtIndex:i];
  458. cm = islower(cm) ? toupper(cm) : cm;
  459. ca = islower(ca) ? toupper(ca) : ca;
  460. if (cm != ca)
  461. break;
  462. }
  463. if (i == a) {
  464. range.location = aRange.location + n;
  465. range.length = a;
  466. return range;
  467. }
  468. }
  469. }
  470. else {
  471. // Forward case sensitive
  472. unsigned int n;
  473. for (n = 0; n + a <= aRange.length; n++) {
  474. if ([self characterAtIndex:n + aRange.location]
  475. != [aString characterAtIndex: 0] )
  476. continue;
  477. for (i = 1; i < a; i++)
  478. if ([self characterAtIndex:n + i + aRange.location]
  479. != [aString characterAtIndex:i])
  480. break;
  481. if (i == a) {
  482. range.location = aRange.location + n;
  483. range.length = a;
  484. return range;
  485. }
  486. }
  487. }
  488. }
  489. range.location = NSNotFound;
  490. range.length = 0;
  491. return range;
  492. }
  493. - (unsigned int)indexOfString:(NSString *)substring
  494. {
  495. NSRange range = {0, [self length]};
  496. range = [self rangeOfString:substring options:0 range:range];
  497. return range.length ? range.location : NSNotFound;
  498. }
  499. - (unsigned int)indexOfString:(NSString*)substring fromIndex:(unsigned)index
  500. {
  501. NSRange range = {index, [self length]-index};
  502. range = [self rangeOfString:substring options:0 range:range];
  503. return range.length ? range.location : NSNotFound;
  504. }
  505. - (unsigned int)indexOfString:(NSString*)substring range:(NSRange)range
  506. {
  507. range = [self rangeOfString:substring options:0 range:range];
  508. return range.length ? range.location : NSNotFound;
  509. }
  510. /* Determining composed character sequences */
  511. - (NSRange)rangeOfComposedCharacterSequenceAtIndex:(unsigned int)anIndex
  512. {
  513. NSRange range;
  514. unsigned int length = [self length];
  515. if (anIndex >= length) {
  516. [[[IndexOutOfRangeException alloc]
  517. initWithFormat:@"index %d out of range in string %x of length %d",
  518. anIndex, self, length] raise];
  519. }
  520. // UNICODE
  521. range.location = anIndex;
  522. range.length = 1;
  523. return range;
  524. }
  525. /* Converting string contents into a property list */
  526. - (id)propertyList
  527. {
  528. return NSParsePropertyListFromString(self);
  529. }
  530. - (NSMutableDictionary*)propertyListFromStringsFileFormat
  531. {
  532. return NSParseStringsFromString(self);
  533. }
  534. /* Identifying and comparing strings */
  535. - (NSComparisonResult)caseInsensitiveCompare:(NSString*)aString
  536. {
  537. NSRange range = {0, [self length]};
  538. return [self compare:aString options:NSCaseInsensitiveSearch range:range];
  539. }
  540. - (NSComparisonResult)compare:(id)aString
  541. {
  542. NSRange range = {0, [self length]};
  543. return [self compare:aString options:0 range:range];
  544. }
  545. - (NSComparisonResult)compare:(NSString*)aString options:(unsigned int)mask
  546. {
  547. NSRange range = {0, [self length]};
  548. return [self compare:aString options:mask range:range];
  549. }
  550. - (NSComparisonResult)compare:(NSString*)aString
  551. options:(unsigned int)mask range:(NSRange)aRange
  552. {
  553. // UNICODE
  554. // ENCODINGS - this code applies to the system's default encoding
  555. unsigned int i, n, a;
  556. if (NSMaxRange(aRange) > [self length]) {
  557. [[[IndexOutOfRangeException alloc] initWithFormat:@"range %@ in string %x of length %d",
  558. NSStringFromRange(aRange), self, [self length]] raise];
  559. }
  560. a = [aString length];
  561. n = MIN(a, aRange.length);
  562. if (mask & NSCaseInsensitiveSearch) {
  563. for (i = 0; i < n; i++) {
  564. unichar cm = [self characterAtIndex:i + aRange.location];
  565. unichar ca = [aString characterAtIndex:i];
  566. cm = islower(cm) ? toupper(cm) : cm;
  567. ca = islower(ca) ? toupper(ca) : ca;
  568. if (cm < ca)
  569. return NSOrderedAscending;
  570. if (cm > ca)
  571. return NSOrderedDescending;
  572. }
  573. }
  574. else {
  575. for (i = 0; i < n; i++) {
  576. if ([self characterAtIndex:i + aRange.location] <
  577. [aString characterAtIndex:i])
  578. return NSOrderedAscending;
  579. if ([self characterAtIndex:i + aRange.location] >
  580. [aString characterAtIndex:i])
  581. return NSOrderedDescending;
  582. }
  583. }
  584. if (aRange.length < a)
  585. return NSOrderedAscending;
  586. if (aRange.length > a)
  587. return NSOrderedDescending;
  588. return NSOrderedSame;
  589. }
  590. - (BOOL)hasPrefix:(NSString *)aString
  591. {
  592. int mLen = [self length];
  593. int aLen = [aString length];
  594. NSRange range = {0, aLen};
  595. #if DEBUG
  596. if (aString == nil) {
  597. NSLog(@"NOTE: [%@ hasPrefix:nil] does not work on MacOSX !", aString);
  598. #if 0 && DEBUG
  599. # warning ABORT CODE ENABLED - do not deploy!
  600. abort();
  601. #endif
  602. }
  603. #endif
  604. if (aLen == 0)
  605. return NO;
  606. if (aLen > mLen)
  607. return NO;
  608. return [self compare:aString options:0 range:range] == NSOrderedSame;
  609. }
  610. - (BOOL)hasSuffix:(NSString*)aString
  611. {
  612. int mLen = [self length];
  613. int aLen = [aString length];
  614. NSRange range = {mLen-aLen, aLen};
  615. if (aLen == 0)
  616. return NO;
  617. if (aLen > mLen)
  618. return NO;
  619. return [self compare:aString options:0 range:range] == NSOrderedSame;
  620. }
  621. - (BOOL)isEqual:(id)aString
  622. {
  623. register Class clazz;
  624. register BOOL i;
  625. NSRange range;
  626. if (self == aString)
  627. return YES;
  628. else if (aString == nil)
  629. return NO;
  630. if (NSStringClass == Nil)
  631. NSStringClass = [NSString class];
  632. i = NO;
  633. for (clazz = *(id *)aString; clazz; clazz = class_get_super_class(clazz)) {
  634. if (clazz == NSStringClass) {
  635. i = YES;
  636. break;
  637. }
  638. }
  639. if (i == NO)
  640. return NO;
  641. range.location = 0;
  642. range.length = [self length];
  643. return [self compare:aString options:0 range:range] == NSOrderedSame;
  644. }
  645. - (BOOL)isEqualToString:(NSString*)aString
  646. {
  647. NSRange range;
  648. if (self == aString)
  649. return YES;
  650. else if (aString == nil)
  651. return NO;
  652. range.location = 0;
  653. range.length = [self length];
  654. return [self compare:aString options:0 range:range] == NSOrderedSame;
  655. }
  656. - (unsigned)hash
  657. {
  658. unsigned hash = 0, hash2;
  659. int i, n = [self length];
  660. for(i = 0; i < n; i++) {
  661. hash <<= 4;
  662. // UNICODE - must use a for independent of composed characters
  663. hash += [self characterAtIndex:i];
  664. if((hash2 = hash & 0xf0000000))
  665. hash ^= (hash2 >> 24) ^ hash2;
  666. }
  667. return hash;
  668. }
  669. /* Getting a shared prefix */
  670. - (NSString *)commonPrefixWithString:(NSString*)aString
  671. options:(unsigned int)mask
  672. {
  673. NSRange range = {0, 0};
  674. int mLen;
  675. int aLen;
  676. int i;
  677. mLen = [self length];
  678. aLen = [aString length];
  679. if ((mLen == 0) || (aLen == 0)) return @"";
  680. for (i = 0; (i < mLen) && (i < aLen); i++) {
  681. unichar c1, c2;
  682. c1 = [self characterAtIndex:i];
  683. c2 = [self characterAtIndex:i];
  684. if (mask & NSCaseInsensitiveSearch) {
  685. // ENCODINGS - this code applies to the system's default encoding
  686. c1 = tolower(c1);
  687. c2 = tolower(c2);
  688. }
  689. if (c1 != c2)
  690. break;
  691. }
  692. range.length = i;
  693. return [self substringWithRange:range];
  694. }
  695. /* Changing case */
  696. - (NSString *)capitalizedString
  697. {
  698. // UNICODE
  699. // ENCODINGS - this code applies to the system's default encoding
  700. int i;
  701. BOOL f = YES;
  702. int length = [self cStringLength];
  703. unichar* buf = MallocAtomic(sizeof(unichar) * (length + 1));
  704. for (i = 0; i < length; i++) {
  705. unichar c = [self characterAtIndex:i];
  706. if (isspace(c))
  707. f = YES;
  708. if (f) {
  709. buf[i] = islower(c) ? toupper(c) : c;
  710. f = NO;
  711. }
  712. else
  713. buf[i] = isupper(c) ? tolower(c) : c;
  714. }
  715. buf[i] = 0;
  716. return AUTORELEASE([[NSStringClass alloc]
  717. initWithCharactersNoCopy:buf
  718. length:length
  719. freeWhenDone:YES]);
  720. }
  721. - (NSString *)lowercaseString
  722. {
  723. // UNICODE
  724. // ENCODINGS - this code applies to the system's default encoding
  725. int i;
  726. int length = [self cStringLength];
  727. unichar* buf = MallocAtomic(sizeof(unichar) * (length+1));
  728. for (i = 0; i < length; i++) {
  729. unichar c = [self characterAtIndex:i];
  730. buf[i] = isupper(c) ? tolower(c) : c;
  731. }
  732. buf[i] = 0;
  733. return AUTORELEASE([[NSStringClass alloc]
  734. initWithCharactersNoCopy:buf
  735. length:length
  736. freeWhenDone:YES]);
  737. }
  738. - (NSString *)uppercaseString
  739. {
  740. // UNICODE
  741. // ENCODINGS - this code applies to the system's default encoding
  742. int i;
  743. int length = [self cStringLength];
  744. unichar* buf = MallocAtomic(sizeof(unichar) * (length+1));
  745. for (i = 0; i < length; i++) {
  746. unichar c = [self characterAtIndex:i];
  747. buf[i] = islower(c) ? toupper(c) : c;
  748. }
  749. buf[i] = 0;
  750. return AUTORELEASE([[NSStringClass alloc]
  751. initWithCharactersNoCopy:buf
  752. length:length
  753. freeWhenDone:YES]);
  754. }
  755. /* Getting C strings */
  756. - (const char *)cString
  757. {
  758. // UNICODE
  759. // ENCODINGS
  760. [self subclassResponsibility:_cmd];
  761. return NULL;
  762. }
  763. - (unsigned int)cStringLength
  764. {
  765. // UNICODE
  766. // ENCODINGS
  767. [self subclassResponsibility:_cmd];
  768. return 0;
  769. }
  770. - (const char *)UTF8String
  771. {
  772. NSData *d;
  773. unsigned dlen;
  774. unsigned char *cstr;
  775. if ((d = [self dataUsingEncoding:NSUTF8StringEncoding]) == nil)
  776. return NULL;
  777. if ((dlen = [d length]) == 0) {
  778. static unsigned char c = '\0';
  779. return (const char *)&c;
  780. }
  781. cstr = NSZoneMallocAtomic([self zone], sizeof(unsigned char) * (dlen + 1));
  782. [d getBytes:cstr];
  783. cstr[dlen] = '\0';
  784. #if !LIB_FOUNDATION_BOEHM_GC
  785. [NSAutoreleasedPointer autoreleasePointer:cstr];
  786. #endif
  787. return (const char *)cstr;
  788. }
  789. - (void)getCString:(char *)buffer
  790. {
  791. NSRange range = {0, [self length]};
  792. [self getCString:buffer maxLength:NSMaximumStringLength
  793. range:range remainingRange:NULL];
  794. buffer[range.length] = '\0';
  795. }
  796. - (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
  797. {
  798. NSRange range = {0, [self length]};
  799. [self getCString:buffer maxLength:maxLength
  800. range:range remainingRange:NULL];
  801. buffer[range.length] = '\0';
  802. }
  803. - (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
  804. range:(NSRange)aRange remainingRange:(NSRange*)leftoverRange
  805. {
  806. unsigned int toMove, i, cLength;
  807. unichar (*charAtIndex)(id,SEL,int);
  808. charAtIndex = (void*)[self methodForSelector:@selector(characterAtIndex:)];
  809. toMove = MIN(maxLength, aRange.length);
  810. cLength = [self cStringLength];
  811. if (aRange.location + aRange.length > cLength) {
  812. [[[IndexOutOfRangeException alloc]
  813. initWithFormat:@"range (%d,%d) in string %x of length %d",
  814. aRange.location, aRange.length, self, cLength] raise];
  815. }
  816. if (leftoverRange) {
  817. leftoverRange->location = aRange.location + toMove;
  818. leftoverRange->length = cLength - leftoverRange->location;
  819. }
  820. for (i = 0; i < toMove; i++) {
  821. buffer[i] = charAtIndex(self, @selector(characterAtIndex:),
  822. aRange.location + i);
  823. }
  824. if (toMove < maxLength)
  825. buffer[toMove] = '\0';
  826. }
  827. /* Getting numeric values */
  828. - (double)doubleValue
  829. {
  830. // UNICODE
  831. // ENCODINGS
  832. double val = 0.0;
  833. unsigned len;
  834. char *str;
  835. len = [self cStringLength];
  836. if (len == 0)
  837. return 0.0;
  838. if ((str = malloc(len + 1)) == NULL)
  839. return 0.0;
  840. [self getCString:str]; str[len] = '\0';
  841. sscanf(str ? str : "", " %lf ", &val);
  842. free(str);
  843. return val;
  844. }
  845. - (float)floatValue
  846. {
  847. // UNICODE
  848. // ENCODINGS
  849. float val = 0;
  850. unsigned len;
  851. char *str;
  852. if ((len = [self cStringLength]) == 0)
  853. return 0.0;
  854. if ((str = malloc(len + 1)) == NULL)
  855. return 0.0;
  856. [self getCString:str]; str[len] = '\0';
  857. sscanf(str ? str : "", " %f ", &val);
  858. free(str);
  859. return val;
  860. }
  861. - (int)intValue
  862. {
  863. // UNICODE
  864. // ENCODINGS
  865. int val = 0;
  866. unsigned len;
  867. char *str;
  868. if ((len = [self cStringLength]) == 0)
  869. return 0;
  870. if ((str = malloc(len + 1)) == NULL)
  871. return 0;
  872. [self getCString:str]; str[len] = '\0';
  873. sscanf(str ? str : "", " %d ", &val);
  874. free(str);
  875. return val;
  876. }
  877. /* Working with encodings */
  878. + (NSStringEncoding *)availableStringEncodings
  879. {
  880. // UNICODE
  881. // ENCODINGS
  882. static NSStringEncoding availableEncodings[] = {
  883. NSASCIIStringEncoding,
  884. NSISOLatin1StringEncoding,
  885. NSISOLatin9StringEncoding,
  886. NSUTF8StringEncoding,
  887. NSUnicodeStringEncoding,
  888. 0
  889. };
  890. return availableEncodings;
  891. }
  892. + (NSStringEncoding)defaultCStringEncoding
  893. {
  894. // UNICODE
  895. // ENCODINGS
  896. #if USE_LATIN9
  897. return NSISOLatin9StringEncoding;
  898. #else
  899. return NSISOLatin1StringEncoding;
  900. #endif
  901. }
  902. + (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
  903. {
  904. switch(encoding) {
  905. case NSASCIIStringEncoding: return @"NSASCIIStringEncoding";
  906. case NSNEXTSTEPStringEncoding: return @"NSNEXTSTEPStringEncoding";
  907. case NSUTF8StringEncoding: return @"NSUTF8StringEncoding";
  908. case NSISOLatin1StringEncoding: return @"NSISOLatin1StringEncoding";
  909. case NSISOLatin9StringEncoding: return @"NSISOLatin9StringEncoding";
  910. case NSSymbolStringEncoding: return @"NSSymbolStringEncoding";
  911. case NSShiftJISStringEncoding: return @"NSShiftJISStringEncoding";
  912. case NSISOLatin2StringEncoding: return @"NSISOLatin2StringEncoding";
  913. case NSUnicodeStringEncoding: return @"NSUnicodeStringEncoding";
  914. case NSWinLatin1StringEncoding: return @"NSWinLatin1StringEncoding";
  915. case NSISO2022JPStringEncoding: return @"NSISO2022JPStringEncoding";
  916. case NSWindowsCP1251StringEncoding:
  917. return @"NSWindowsCP1251StringEncoding";
  918. case NSWindowsCP1252StringEncoding:
  919. return @"NSWindowsCP1252StringEncoding";
  920. case NSWindowsCP1253StringEncoding:
  921. return @"NSWindowsCP1253StringEncoding";
  922. case NSWindowsCP1254StringEncoding:
  923. return @"NSWindowsCP1254StringEncoding";
  924. case NSWindowsCP1250StringEncoding:
  925. return @"NSWindowsCP1250StringEncoding";
  926. case NSNonLossyASCIIStringEncoding:
  927. return @"NSNonLossyASCIIStringEncoding";
  928. case NSJapaneseEUCStringEncoding:
  929. return @"NSJapaneseEUCStringEncoding";
  930. case NSAdobeStandardCyrillicStringEncoding:
  931. return @"NSAdobeStandardCyrillicStringEncoding";
  932. default:
  933. return @"Invalid encoding";
  934. }
  935. }
  936. - (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
  937. {
  938. id data;
  939. data = [self dataUsingEncoding:encoding allowLossyConversion:NO];
  940. return data ? YES : NO;
  941. }
  942. - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
  943. {
  944. return [self dataUsingEncoding:encoding allowLossyConversion:NO];
  945. }
  946. - (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
  947. allowLossyConversion:(BOOL)flag
  948. {
  949. return dataUsingEncoding(self, encoding, flag);
  950. }
  951. - (NSStringEncoding)fastestEncoding
  952. {
  953. // UNICODE
  954. // ENCODINGS
  955. return NSISOLatin1StringEncoding;
  956. }
  957. - (NSStringEncoding)smallestEncoding
  958. {
  959. // UNICODE
  960. // ENCODINGS
  961. return NSISOLatin1StringEncoding;
  962. }
  963. - (BOOL)getBytes:(void*)bytes maxLength:(unsigned int)maxLength
  964. inEncoding:(NSStringEncoding)encoding
  965. allowLossesInConversion:(BOOL)allowLossesInConversion
  966. fromRange:(NSRange)fromRange
  967. usedRange:(NSRange*)usedRange
  968. remainingRange:(NSRange*)remainingRange
  969. {
  970. // UNICODE
  971. // ENCODINGS
  972. [self notImplemented:_cmd];
  973. return NO;
  974. }
  975. /* Writing to a file */
  976. - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
  977. {
  978. // UNICODE - remove this
  979. NSData *data;
  980. data = [self dataUsingEncoding:[NSStringClass defaultCStringEncoding]];
  981. //data = [NSData dataWithBytes:[self cString] length:[self length]];
  982. return writeToFile(path, data, flag);
  983. }
  984. /* Encoding methods */
  985. - (void)encodeWithCoder:(NSCoder *)aCoder
  986. {
  987. int length;
  988. unichar *buf;
  989. length = [self length];
  990. buf = MallocAtomic(sizeof(unichar) * length);
  991. [self getCharacters:buf];
  992. [aCoder encodeValueOfObjCType:@encode(int) at:&length];
  993. [aCoder encodeArrayOfObjCType:@encode(unichar) count:length at:buf];
  994. lfFree(buf);
  995. }
  996. - (id)initWithCoder:(NSCoder *)aDecoder
  997. {
  998. unichar* buf;
  999. int length;
  1000. [aDecoder decodeValueOfObjCType:@encode(int) at:&length];
  1001. buf = MallocAtomic (sizeof(unichar) * length);
  1002. [aDecoder decodeArrayOfObjCType:@encode(unichar) count:length at:buf];
  1003. self = AUTORELEASE(self);
  1004. return [self initWithCharactersNoCopy:buf
  1005. length:length
  1006. freeWhenDone:YES];
  1007. }
  1008. /* NSCopying methods */
  1009. - (id)copyWithZone:(NSZone *)zone
  1010. {
  1011. if (NSStringClass == Nil)
  1012. NSStringClass = [NSString class];
  1013. return RETAIN(self);
  1014. // return [[NSStringClass allocWithZone:zone] initWithString:self];
  1015. }
  1016. /* NSMutableCopying methods */
  1017. - (id)mutableCopyWithZone:(NSZone*)zone
  1018. {
  1019. return [[NSMutableString allocWithZone:zone] initWithString:self];
  1020. }
  1021. /* NSObject protocol */
  1022. - (NSString *)stringRepresentation
  1023. {
  1024. /*
  1025. an implementation of this method must quote the string for
  1026. use in property lists.
  1027. */
  1028. return [self subclassResponsibility:_cmd];
  1029. }
  1030. - (NSString *)description
  1031. {
  1032. return self;
  1033. }
  1034. @end /* NSString */
  1035. /*********************************
  1036. * NSMutableString abstract class
  1037. *********************************/
  1038. @implementation NSMutableString
  1039. /*
  1040. * Modifying a string
  1041. */
  1042. - (void)appendFormat:(NSString*)format,...
  1043. {
  1044. va_list va;
  1045. va_start(va, format);
  1046. [self appendFormat:format arguments:va];
  1047. va_end(va);
  1048. }
  1049. - (void)appendFormat:(NSString*)format arguments:(va_list)argList;
  1050. {
  1051. // FIX : Vsprinf(self, format, argList)
  1052. [self appendString:Avsprintf(format, argList)];
  1053. }
  1054. - (void)appendString:(NSString*)aString
  1055. {
  1056. NSRange range = {[self length], 0};
  1057. [self replaceCharactersInRange:range withString:aString];
  1058. }
  1059. - (void)prependFormat:(NSString*)format,...
  1060. {
  1061. NSRange range = {0, 0};
  1062. va_list va;
  1063. va_start(va, format);
  1064. [self replaceCharactersInRange:range
  1065. withString:Avsprintf(format, va)];
  1066. va_end(va);
  1067. }
  1068. - (void)prependFormat:(NSString*)format arguments:(va_list)argList
  1069. {
  1070. NSRange range = {0, 0};
  1071. [self replaceCharactersInRange:range
  1072. withString:Avsprintf(format, argList)];
  1073. }
  1074. - (void)prependString:(NSString*)aString
  1075. {
  1076. NSRange range = {0, 0};
  1077. [self replaceCharactersInRange:range withString:aString];
  1078. }
  1079. - (void)deleteCharactersInRange:(NSRange)range
  1080. {
  1081. [self replaceCharactersInRange:range withString:nil];
  1082. }
  1083. - (void)insertString:(NSString*)aString atIndex:(unsigned)index
  1084. {
  1085. NSRange range = {index, 0};
  1086. [self replaceCharactersInRange:range withString:aString];
  1087. }
  1088. - (void)setString:(NSString*)aString
  1089. {
  1090. NSRange range = {0, [self length]};
  1091. [self replaceCharactersInRange:range withString:aString];
  1092. }
  1093. - (void)replaceCharactersInRange:(NSRange)aRange
  1094. withString:(NSString*)aString
  1095. {
  1096. [self subclassResponsibility:_cmd];
  1097. }
  1098. - (id)copyWithZone:(NSZone*)zone
  1099. {
  1100. if (NSStringClass == Nil)
  1101. NSStringClass = [NSString class];
  1102. return [[NSStringClass allocWithZone:zone] initWithString:self];
  1103. }
  1104. @end /* NSMutableString */
  1105. /*********************************
  1106. * NSString creation methods
  1107. *********************************/
  1108. @implementation NSString(NSStringCreation)
  1109. + (id)allocWithZone:(NSZone *)zone
  1110. {
  1111. static Class NSTemporaryStringClass = Nil;
  1112. if (NSStringClass == Nil)
  1113. NSStringClass = [NSString class];
  1114. if (NSTemporaryStringClass == Nil)
  1115. NSTemporaryStringClass = [NSTemporaryString class];
  1116. return (self == NSStringClass)
  1117. ? [NSTemporaryStringClass allocWithZone:zone]
  1118. : (id)NSAllocateObject(self, 0, zone);
  1119. }
  1120. + (id)localizedStringWithFormat:(NSString*)format,...
  1121. {
  1122. va_list va;
  1123. NSString* string;
  1124. va_start(va, format);
  1125. string = AUTORELEASE([[self alloc] initWithFormat:format arguments:va]);
  1126. va_end(va);
  1127. return string;
  1128. }
  1129. + (id)string
  1130. {
  1131. return @"";
  1132. }
  1133. + (id)stringWithCharacters:(const unichar*)chars
  1134. length:(unsigned int)length
  1135. {
  1136. return AUTORELEASE([[self alloc] initWithCharacters:chars length:length]);
  1137. }
  1138. + (id)stringWithCharactersNoCopy:(unichar*)chars
  1139. length:(unsigned int)length freeWhenDone:(BOOL)flag
  1140. {
  1141. return AUTORELEASE([[self alloc] initWithCharactersNoCopy:chars
  1142. length:length freeWhenDone:flag]);
  1143. }
  1144. + (id)stringWithString:(NSString*)aString
  1145. {
  1146. return [self stringWithCString:[aString cString]];
  1147. }
  1148. + (id)stringWithCString:(const char*)byteString
  1149. {
  1150. return AUTORELEASE([[self alloc] initWithCString:byteString]);
  1151. }
  1152. + (id)stringWithUTF8String:(const char *)bytes
  1153. {
  1154. register unsigned char *p;
  1155. for (p = (unsigned char *)bytes; *p; p++) {
  1156. if (*p > 127)
  1157. return AUTORELEASE([[self alloc] initWithUTF8String:bytes]);
  1158. }
  1159. return [self stringWithCString:bytes];
  1160. }
  1161. + (NSString *)stringWithCString:(const char*)byteString
  1162. length:(unsigned int)length
  1163. {
  1164. return AUTORELEASE([[self alloc]
  1165. initWithCString:byteString length:length]);
  1166. }
  1167. + (NSString *)stringWithCStringNoCopy:(char*)byteString
  1168. length:(unsigned int)length freeWhenDone:(BOOL)flag
  1169. {
  1170. return AUTORELEASE([[self alloc] initWithCStringNoCopy:byteString
  1171. length:length freeWhenDone:flag]);
  1172. }
  1173. + (id)stringWithCStringNoCopy:(char*)byteString
  1174. freeWhenDone:(BOOL)flag
  1175. {
  1176. return AUTORELEASE([[self alloc] initWithCStringNoCopy:byteString
  1177. freeWhenDone:flag]);
  1178. }
  1179. + (id)stringWithFormat:(NSString*)format,...
  1180. {
  1181. va_list va;
  1182. NSString* string;
  1183. va_start(va, format);
  1184. string = AUTORELEASE([[self alloc] initWithFormat:format arguments:va]);
  1185. va_end(va);
  1186. return string;
  1187. }
  1188. + (id)stringWithFormat:(NSString *)format arguments:(va_list)argList
  1189. {
  1190. return AUTORELEASE([[self alloc] initWithFormat:format
  1191. arguments:argList]);
  1192. }
  1193. + (id)stringWithContentsOfFile:(NSString *)path
  1194. {
  1195. return AUTORELEASE([[self alloc] initWithContentsOfFile:path]);
  1196. }
  1197. + (id)stringWithContentsOfURL:(NSURL *)_url
  1198. {
  1199. return AUTORELEASE([[self alloc] initWithContentsOfURL:_url]);
  1200. }
  1201. @end /* NSString(NSStringCreation) */
  1202. @implementation NSString(GSAdditions)
  1203. - (NSString *)stringWithoutPrefix:(NSString *)_prefix
  1204. {
  1205. return ([self hasPrefix:_prefix])
  1206. ? [self substringFromIndex:[_prefix length]]
  1207. : (NSString *)[[self copy] autorelease];
  1208. }
  1209. - (NSString *)stringWithoutSuffix:(NSString *)_suffix
  1210. {
  1211. return ([self hasSuffix:_suffix])
  1212. ? [self substringToIndex:([self length] - [_suffix length])]
  1213. : (NSString *)[[self copy] autorelease];
  1214. }
  1215. - (NSString *)stringByReplacingString:(NSString *)_orignal
  1216. withString:(NSString *)_replacement
  1217. {
  1218. /* very slow solution .. */
  1219. if ([self indexOfString:_orignal] == NSNotFound)
  1220. return [[self copy] autorelease];
  1221. return [[self componentsSeparatedByString:_orignal]
  1222. componentsJoinedByString:_replacement];
  1223. }
  1224. static NSCharacterSet *whiteSpaceSet = nil;
  1225. static BOOL (*isWhiteSpaceSetMem)(id, SEL, unichar);
  1226. - (NSString *)stringByTrimmingLeadWhiteSpaces
  1227. {
  1228. /* can't we share the implementation of lead and tail?! It is 98% similiar */
  1229. unsigned len;
  1230. unichar *buf;
  1231. unsigned idx;
  1232. if (whiteSpaceSet == nil) {
  1233. whiteSpaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
  1234. isWhiteSpaceSetMem = (void *)
  1235. [whiteSpaceSet methodForSelector:@selector(characterIsMember:)];
  1236. }
  1237. if ((len = [self length]) == 0)
  1238. return @"";
  1239. buf = calloc(len + 1, sizeof(unichar));
  1240. [self getCharacters:buf];
  1241. for (idx = 0;
  1242. (idx < len) && isWhiteSpaceSetMem(whiteSpaceSet,
  1243. @selector(characterIsMember:),
  1244. buf[idx]);
  1245. idx++)
  1246. ;
  1247. self = [NSStringClass stringWithCharacters:&(buf[idx]) length:(len - idx)];
  1248. free(buf);
  1249. return self;
  1250. }
  1251. - (NSString *)stringByTrimmingTailWhiteSpaces
  1252. {
  1253. unichar *buf;
  1254. unsigned int idx;
  1255. unsigned len;
  1256. if (whiteSpaceSet == nil) {
  1257. whiteSpaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
  1258. isWhiteSpaceSetMem = (void *)
  1259. [whiteSpaceSet methodForSelector:@selector(characterIsMember:)];
  1260. }
  1261. if ((len = [self length]) == 0)
  1262. return @"";
  1263. buf = calloc(len + 2, sizeof(unichar));
  1264. [self getCharacters:buf];
  1265. for (idx = (len - 1);
  1266. (idx >= 0) && isWhiteSpaceSetMem(whiteSpaceSet,
  1267. @selector(characterIsMember:), buf[idx]);
  1268. idx--)
  1269. ;
  1270. self = [NSStringClass stringWithCharacters:buf length:(idx + 1)];
  1271. free(buf);
  1272. return self;
  1273. }
  1274. - (NSString *)stringByTrimmingLeadSpaces
  1275. {
  1276. unsigned int len;
  1277. unsigned int idx;
  1278. unichar *buf;
  1279. if ((len = [self length]) == 0)
  1280. return @"";
  1281. buf = calloc(len + 2, sizeof(unichar));
  1282. [self getCharacters:buf];
  1283. for (idx = 0; (idx < len) && isspace(buf[idx]); idx++)
  1284. ;
  1285. self = [NSStringClass stringWithCharacters:&(buf[idx]) length:(len - idx)];
  1286. if (buf) free(buf);
  1287. return self;
  1288. }
  1289. - (NSString *)stringByTrimmingTailSpaces
  1290. {
  1291. unsigned len;
  1292. unichar *buf;
  1293. int idx;
  1294. if ((len = [self length]) == 0)
  1295. return @"";
  1296. buf = calloc(len + 2, sizeof(unichar));
  1297. [self getCharacters:buf];
  1298. for (idx = (len - 1); (idx >= 0) && isspace(buf[idx]); idx--)
  1299. ;
  1300. self = [NSStringClass stringWithCharacters:buf length:(idx + 1)];
  1301. if (buf) free(buf);
  1302. return self;
  1303. }
  1304. - (NSString *)stringByTrimmingWhiteSpaces
  1305. {
  1306. return [[self stringByTrimmingTailWhiteSpaces]
  1307. stringByTrimmingLeadWhiteSpaces];
  1308. }
  1309. - (NSString *)stringByTrimmingSpaces
  1310. {
  1311. return [[self stringByTrimmingTailSpaces]
  1312. stringByTrimmingLeadSpaces];
  1313. }
  1314. @end /* NSString(GSAdditions) */
  1315. @implementation NSMutableString(GNUstepCompatibility)
  1316. - (void)trimLeadSpaces
  1317. {
  1318. [self setString:[self stringByTrimmingLeadSpaces]];
  1319. }
  1320. - (void)trimTailSpaces
  1321. {
  1322. [self setString:[self stringByTrimmingTailSpaces]];
  1323. }
  1324. - (void)trimSpaces
  1325. {
  1326. [self setString:[self stringByTrimmingSpaces]];
  1327. }
  1328. @end /* NSMutableString(GNUstepCompatibility) */
  1329. @implementation NSMutableString(NSStringCreation)
  1330. + (id)allocWithZone:(NSZone *)zone
  1331. {
  1332. return (self == [NSMutableString class])
  1333. ? [NSMutableTemporaryString allocWithZone:zone]
  1334. : (id)NSAllocateObject(self, 0, zone);
  1335. }
  1336. + (id)stringWithCapacity:(unsigned int)capacity
  1337. {
  1338. return AUTORELEASE([[self alloc] initWithCapacity:capacity]);
  1339. }
  1340. + (id)string
  1341. {
  1342. return [self stringWithCapacity:0];
  1343. }
  1344. @end /* NSMutableString(NSStringCreation) */
  1345. /****************************
  1346. * Initializing strings
  1347. ****************************/
  1348. @implementation NSMutableString(NSStringInitialization)
  1349. - (id)initWithCapacity:(unsigned int)capacity
  1350. {
  1351. [self subclassResponsibility:_cmd];
  1352. return nil;
  1353. }
  1354. - (id)initWithCharacters:(const unichar *)chars length:(unsigned int)length
  1355. {
  1356. unsigned char *buffer;
  1357. unsigned int i, j;
  1358. BOOL isLower8BitEqual = NO;
  1359. BOOL isLower7BitEqual = NO;
  1360. unsigned int convertCount = 0;
  1361. switch ([NSStringClass defaultCStringEncoding]) {
  1362. case NSISOLatin1StringEncoding:
  1363. isLower8BitEqual = YES;
  1364. break;
  1365. case NSASCIIStringEncoding:
  1366. case NSUTF8StringEncoding:
  1367. isLower7BitEqual = YES;
  1368. break;
  1369. }
  1370. /* scan whether this is a non-8-bit- string ... */
  1371. for (i = 0; i < length; i++) {
  1372. //NSMutableString *s;
  1373. #if !HAS_UNICODE_STRING
  1374. /* allow Euro char code (8364) */
  1375. if (chars[i] == 8364) {
  1376. convertCount++;
  1377. continue;
  1378. }
  1379. #endif
  1380. if (isLower8BitEqual && (chars[i] < 256))
  1381. /* valid 8-bit character in default encoding */
  1382. continue;
  1383. if (isLower7BitEqual && (chars[i] < 128))
  1384. /* valid 7-bit character in default encoding */
  1385. continue;
  1386. #if HAS_UNICODE_STRING
  1387. s = [[NSMutableUnicodeString alloc]
  1388. initWithCharacters:chars
  1389. length:length];
  1390. if (flag) {
  1391. lfFree(chars);
  1392. chars = NULL;
  1393. }
  1394. #endif
  1395. return [self notImplemented:_cmd];
  1396. }
  1397. buffer = MallocAtomic(length + (convertCount*3) + 1);
  1398. for (i = 0, j = 0; i < length; i++, j++) {
  1399. #if !HAS_UNICODE_STRING
  1400. if (chars[i] == 8364) {
  1401. buffer[j++] = 'E';
  1402. buffer[j++] = 'U';
  1403. buffer[j] = 'R';
  1404. }
  1405. #endif
  1406. buffer[j] = chars[i];
  1407. }
  1408. buffer[j] = '\0';
  1409. self = [self initWithCString:(char *)buffer length:j];
  1410. if (buffer) lfFree(buffer);
  1411. return self;
  1412. }
  1413. - (id)initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length
  1414. freeWhenDone:(BOOL)flag
  1415. {
  1416. unsigned char *buffer;
  1417. unsigned int i, j;
  1418. BOOL isLower8BitEqual = NO;
  1419. BOOL isLower7BitEqual = NO;
  1420. unsigned int convertCount = 0;
  1421. switch ([NSStringClass defaultCStringEncoding]) {
  1422. case NSISOLatin1StringEncoding:
  1423. isLower8BitEqual = YES;
  1424. break;
  1425. case NSASCIIStringEncoding:
  1426. case NSUTF8StringEncoding:
  1427. case NSISOLatin9StringEncoding:
  1428. isLower7BitEqual = YES;
  1429. break;
  1430. }
  1431. /* scan whether this is a non-8-bit- string ... */
  1432. for (i = 0; i < length; i++) {
  1433. //NSMutableString *s;
  1434. #if !HAS_UNICODE_STRING
  1435. /* allow Euro char code (8364) */
  1436. if (chars[i] == 8364) {
  1437. convertCount++;
  1438. continue;
  1439. }
  1440. #endif
  1441. if (isLower8BitEqual && (chars[i] < 256))
  1442. /* valid 8-bit character in default encoding */
  1443. continue;
  1444. if (isLower7BitEqual && (chars[i] < 128))
  1445. /* valid 7-bit character in default encoding */
  1446. continue;
  1447. #if HAS_UNICODE_STRING
  1448. s = [[NSMutableUTF16String alloc]
  1449. initWithCharacters:chars
  1450. length:length];
  1451. if (flag) {
  1452. lfFree(chars);
  1453. chars = NULL;
  1454. }
  1455. #endif
  1456. return [self notImplemented:_cmd];
  1457. }
  1458. buffer = MallocAtomic(length + (convertCount*3) + 1);
  1459. for (i = 0, j = 0; i < length; i++, j++) {
  1460. #if !HAS_UNICODE_STRING
  1461. if (chars[i] == 8364) {
  1462. buffer[j++] = 'E';
  1463. buffer[j++] = 'U';
  1464. buffer[j] = 'R';
  1465. }
  1466. #endif
  1467. buffer[j] = chars[i];
  1468. }
  1469. buffer[j] = '\0';
  1470. if (flag) {
  1471. lfFree(chars);
  1472. chars = NULL;
  1473. }
  1474. self = [self initWithCString:(char *)buffer length:j];
  1475. if (buffer) lfFree(buffer);
  1476. return self;
  1477. }
  1478. - (id)initWithCString:(const char*)byteString
  1479. {
  1480. if (NSStringClass == Nil)
  1481. NSStringClass = [NSString class];
  1482. return [self initWithString:
  1483. AUTORELEASE([[NSStringClass alloc]
  1484. initWithCStringNoCopy:(char*)byteString
  1485. freeWhenDone:NO])];
  1486. }
  1487. - (id)initWithCString:(const char*)byteString length:(unsigned int)length
  1488. {
  1489. if (NSStringClass == Nil)
  1490. NSStringClass = [NSString class];
  1491. return [self initWithString:
  1492. AUTORELEASE([[NSStringClass alloc]
  1493. initWithCStringNoCopy:(char*)byteString
  1494. length:length freeWhenDone:NO])];
  1495. }
  1496. - (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag
  1497. {
  1498. if (NSStringClass == Nil)
  1499. NSStringClass = [NSString class];
  1500. return [self initWithString:
  1501. AUTORELEASE([[NSStringClass alloc]
  1502. initWithCStringNoCopy:byteString
  1503. freeWhenDone:flag])];
  1504. }
  1505. - (id)initWithCStringNoCopy:(char*)byteString length:(unsigned int)length
  1506. freeWhenDone:(BOOL)flag
  1507. {
  1508. if (NSStringClass == Nil)
  1509. NSStringClass = [NSString class];
  1510. return [self initWithString:
  1511. AUTORELEASE([[NSStringClass alloc]
  1512. initWithCStringNoCopy:byteString
  1513. length:length freeWhenDone:flag])];
  1514. }
  1515. - (id)initWithString:(NSString*)aString
  1516. {
  1517. [self subclassResponsibility:_cmd];
  1518. return nil;
  1519. }
  1520. - (id)initWithFormat:(NSString*)format, ...
  1521. {
  1522. id str;
  1523. va_list va;
  1524. va_start(va, format);
  1525. str = [self initWithFormat:format arguments:va];
  1526. va_end(va);
  1527. return str;
  1528. }
  1529. - (id)initWithFormat:(NSString*)format arguments:(va_list)argList
  1530. {
  1531. return [self initWithString:Avsprintf(format, argList)];
  1532. }
  1533. - (id)initWithFormat:(NSString*)format
  1534. locale:(NSDictionary*)dictionary, ...
  1535. {
  1536. id str;
  1537. va_list va;
  1538. va_start(va, dictionary);
  1539. str = [self initWithFormat:format arguments:va];
  1540. va_end(va);
  1541. return str;
  1542. }
  1543. - (id)initWithFormat:(NSString *)format
  1544. locale:(NSDictionary*)dictionary arguments:(va_list)argList
  1545. {
  1546. return [self initWithFormat:format arguments:argList];
  1547. }
  1548. - (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
  1549. {
  1550. /* NSMutableString */
  1551. return NSInitStringWithData(self, data, encoding);
  1552. }
  1553. - (id)initWithContentsOfFile:(NSString *)path
  1554. {
  1555. // UNICODE
  1556. // ENCODINGS
  1557. [self notImplemented:_cmd];
  1558. return nil;
  1559. }
  1560. @end /* NSMutableString(NSStringInitialization) */
  1561. /****************************
  1562. * Allocate concrete strings
  1563. ****************************/
  1564. /*
  1565. * Classes used for allocation of NSString concrete instances
  1566. */
  1567. @implementation NSTemporaryString
  1568. static BOOL isMultithreaded = NO;
  1569. static NSTemporaryString *temporaryStringsPool = nil;
  1570. static

Large files files are truncated, but you can click here to view the full file