home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / Classes / String / String.m < prev    next >
Text File  |  1993-01-30  |  7KB  |  332 lines

  1. //
  2. //    String.m -- a generic class to simplify manipulation of (char *)'s
  3. //        Written by Don Yacktman (c) 1993 by Don Yacktman.
  4. //                All rights reserved.
  5. //
  6. //        You may use and copy this class freely as long as you
  7. //        comply with the following terms:
  8. //            (1) If you use this class in an application which you
  9. //                intend to sell commercially, as shareware, or otherwise,
  10. //                you may only do so with express written permission
  11. //                of the author.  Use in applications which will
  12. //                be distributed free of charge is encouraged.
  13. //            (2) You must include the source code to this object and
  14. //                all accompanying documentation with your application,
  15. //                or provide it to users if requested, free of charge.
  16. //            (3) Do not remove the author's name or any of the
  17. //                copyright notices
  18. //
  19.  
  20. #import "String.h"
  21. #import <strings.h>
  22. #import <appkit/appkit.h>
  23.  
  24. @implementation String
  25.  
  26. - init
  27. {
  28.      [super init];
  29.      [self setStringOrderTable:NXDefaultStringOrderTable()];
  30.      buffer = NULL;
  31.      length = 0;
  32.      _length = 0;
  33.      return self;
  34. }
  35.  
  36. - setStringOrderTable:(NXStringOrderTable *)table
  37. {
  38.     orderTable = table;
  39.     return self;
  40. }
  41.  
  42. - (NXStringOrderTable *)stringOrderTable
  43. {
  44.     return orderTable;
  45. }
  46.  
  47. - allocateBuffer:(int)size
  48. {
  49.     return [self allocateBuffer:size fromZone:[self zone]];
  50. }
  51.  
  52. - allocateBuffer:(int)size fromZone:(NXZone *)zone
  53. {
  54.     if(size <= _length) return self;
  55.     [self freeString];
  56.     buffer = (char *)NXZoneMalloc(zone, size);
  57.     buffer[0] = 0;
  58.     _length = size;
  59.  
  60.     return self;
  61. }
  62.  
  63. - setString:(const char *)aString
  64. {
  65.     return [self setString:aString fromZone:[self zone]];
  66. }
  67.  
  68. - setString:(const char *)aString fromZone:(NXZone *)zone
  69. {
  70.     if(!aString) return self;
  71.     [self allocateBuffer:strlen(aString)+1 fromZone:zone];
  72.     strcpy(buffer, aString);
  73.     length = strlen(buffer);
  74.     return self;
  75. }
  76.  
  77. - setStringValue:sender
  78. {
  79.     if (![sender respondsTo:@selector(stringValue)]) return self;
  80.     return [self setString:[sender stringValue] fromZone:[self zone]];
  81. }
  82.  
  83. - setStringValue:sender fromZone:(NXZone *)zone
  84. {
  85.     if (![sender respondsTo:@selector(stringValue)]) return self;
  86.     return [self setString:[sender stringValue] fromZone:zone];
  87. }
  88.  
  89. - (const char *)stringValue
  90. {
  91.     return buffer;
  92. }
  93.  
  94. - read:(NXTypedStream *)stream
  95. {
  96.     char *tmpStr;
  97.     [super read:stream];
  98.     NXReadType(stream, "i", &_length);
  99.     [self allocateBuffer:_length fromZone:[self zone]];
  100.     NXReadType(stream, "*", &tmpStr);
  101.     [self setString:tmpStr fromZone:[self zone]];
  102.     free(tmpStr);
  103.     return self;
  104. }
  105.  
  106. - write:(NXTypedStream *)stream
  107. {
  108.     [super write:stream];
  109.     NXWriteTypes(stream, "i*", &_length, &buffer);
  110.     return self;
  111. }
  112.  
  113. - copyFromZone:(NXZone *)zone
  114. {
  115.     String *myCopy = [super copyFromZone:zone];
  116.     // force child to have it's own copy of the string
  117.     [myCopy _unhookBuffer];
  118.     [myCopy allocateBuffer:_length fromZone:zone];
  119.     [myCopy setString:buffer fromZone:zone];
  120.     return myCopy;
  121. }
  122.  
  123. - _unhookBuffer
  124. { // used by the copy method so that we don't free the buffer from orig. 
  125.     buffer = NULL; _length = 0;
  126.     return self;
  127. }
  128.  
  129. - freeString
  130. {
  131.     if(buffer) free(buffer);
  132.     buffer = NULL;
  133.     length = 0;
  134.     _length = 0;
  135.     return self;
  136. }
  137.  
  138. - free
  139. {
  140.      [self freeString];
  141.      return [super free];
  142. }
  143.  
  144. - cat:(const char *)aString
  145. {
  146.     return [self cat:aString
  147.                  n:strlen(aString)
  148.                  fromZone:[self zone]];
  149. }
  150.  
  151. - cat:(const char *)aString n:(int)n
  152. {
  153.     return [self cat:aString n:n fromZone:[self zone]];
  154. }
  155.  
  156. - cat:(const char *)aString fromZone:(NXZone *)zone
  157. {
  158.     return [self cat:aString n:strlen(aString) fromZone:zone];
  159. }
  160.  
  161. - cat:(const char *)aString n:(int)n fromZone:(NXZone *)zone
  162. {
  163.     char *newBuffer; int newSize;
  164.     newSize = length + n + 1;
  165.     if (newSize > _length) {
  166.         newBuffer = (char *)NXZoneMalloc(zone, newSize);
  167.         _length = newSize;
  168.         newBuffer[0] = '\0';
  169.         strcat(newBuffer, buffer);
  170.         strncat(newBuffer, aString, n);
  171.         free(buffer);
  172.         buffer = newBuffer;
  173.     } else  strncat(buffer, aString, n);
  174.     length = strlen(buffer);
  175.     return self;
  176. }
  177.  
  178. - concatenate:sender
  179. {
  180.     if (![sender respondsTo:@selector(stringValue)]) return self;
  181.     return [self cat:[sender stringValue]
  182.                  n:strlen([sender stringValue])
  183.                  fromZone:[self zone]];
  184. }
  185.  
  186. - concatenate:sender n:(int)n
  187. {
  188.     if (![sender respondsTo:@selector(stringValue)]) return self;
  189.     return [self cat:[sender stringValue] n:n fromZone:[self zone]];
  190. }
  191.  
  192. - concatenate:sender fromZone:(NXZone *)zone
  193. {
  194.     if (![sender respondsTo:@selector(stringValue)]) return self;
  195.     return [self cat:[sender stringValue]
  196.             n:strlen([sender stringValue]) fromZone:zone];
  197. }
  198.  
  199. - concatenate:sender n:(int)n fromZone:(NXZone *)zone
  200. {
  201.     if (![sender respondsTo:@selector(stringValue)]) return self;
  202.     return [self cat:[sender stringValue] n:n fromZone:zone];
  203. }
  204.  
  205. - (const char *)rindex:(char)aChar
  206. {
  207.     return rindex(buffer, aChar);
  208. }
  209.  
  210. - (const char *)index:(char)aChar
  211. {
  212.     return index(buffer, aChar);
  213. }
  214.  
  215. - (int)length
  216. {
  217.     return length;
  218. }
  219.  
  220. - (BOOL)isEqual:anObject
  221. {
  222.     if (anObject == self) return YES;
  223.     // doesn't have to be a String object to be equal...
  224.     if ([anObject respondsTo:@selector(stringValue)]) {
  225.         if (!NXOrderStrings(buffer, [anObject stringValue],
  226.                 YES, -1, orderTable)) return YES;
  227.     }
  228.     return NO;
  229. }
  230.  
  231. - (int)compareTo:sender
  232. {
  233.     return [self compareTo:sender n:(-1) caseSensitive:YES];
  234. }
  235.  
  236. - (int)compareTo:sender n:(int)n
  237. {
  238.     return [self compareTo:sender n:n caseSensitive:YES];
  239. }
  240.  
  241. - (int)cmp:(const char *)aString
  242. {
  243.     return strcmp(buffer, aString);
  244. }
  245.  
  246. - (int)cmp:(const char *)aString n:(int)n
  247. {
  248.     return strncmp(buffer, aString, n);
  249. }
  250.  
  251. - (int)compareTo:sender caseSensitive:(BOOL)sense
  252. {
  253.     return [self compareTo:sender n:(-1) caseSensitive:sense];
  254. }
  255.  
  256. - (int)compareTo:sender n:(int)n caseSensitive:(BOOL)sense
  257. {
  258.     if (![sender respondsTo:@selector(stringValue)]) return 1; // !=
  259.     return NXOrderStrings(buffer, [sender stringValue], sense, n, orderTable);
  260. }
  261.  
  262. - (int)casecmp:(const char *)aString
  263. {
  264.     return strcasecmp(buffer, aString);
  265. }
  266.  
  267. - (int)casecmp:(const char *)aString n:(int)n
  268. {
  269.     return strncasecmp(buffer, aString, n);
  270. }
  271.  
  272. - left:(int)count
  273. {
  274.     return [self left:count fromZone:[self zone]];
  275. }
  276.  
  277. - right:(int)count
  278. {
  279.     return [self right:count fromZone:[self zone]];
  280. }
  281.  
  282. - midFrom:(int)start to:(int)end
  283. {
  284.     return [self midFrom:start to:end fromZone:[self zone]];
  285. }
  286.  
  287. - midFrom:(int)start length:(int)len
  288. {
  289.     return [self midFrom:start length:len fromZone:[self zone]];
  290. }
  291.  
  292. - left:(int)count fromZone:(NXZone *)zone
  293. {
  294.     char smash = buffer[count];
  295.     id newString = [[String allocFromZone:zone] init];
  296.     buffer[count] = '\0';
  297.     [newString setString:buffer fromZone:zone];
  298.     buffer[count] = smash;
  299.     return newString;
  300. }
  301.  
  302. - right:(int)count fromZone:(NXZone *)zone
  303. {
  304.     id newString = [[String allocFromZone:zone] init];
  305.     [newString setString:&buffer[length - count] fromZone:zone];
  306.     return newString;
  307. }
  308.  
  309. - midFrom:(int)start to:(int)end fromZone:(NXZone *)zone
  310. {
  311.     char smash = buffer[end];
  312.     id newString = [[String allocFromZone:zone] init];
  313.     buffer[end] = '\0'; // inclusive; end-1 is not.
  314.     [newString setString:&buffer[start - 1] fromZone:zone];
  315.     buffer[end] = smash;
  316.     return newString;
  317. }
  318.  
  319. - midFrom:(int)start length:(int)len fromZone:(NXZone *)zone
  320. {
  321.     register int spot = start + len - 1;
  322.     char smash = buffer[spot];
  323.     id newString = [[String allocFromZone:zone] init];
  324.     buffer[spot] = '\0';
  325.     [newString setString:&buffer[start - 1] fromZone:zone];
  326.     buffer[spot] = smash;
  327.     return newString;
  328. }
  329.  
  330.  
  331. @end
  332.