comparison pkg-src/tree-nx/String.m @ 163:0132846995bd r20-3b8

Import from CVS: tag r20-3b8
author cvs
date Mon, 13 Aug 2007 09:43:35 +0200
parents
children
comparison
equal deleted inserted replaced
162:4de2936b4e77 163:0132846995bd
1 //
2 // String.m -- a generic class to simplify manipulation of (char *)'s
3 // Written by Don Yacktman (c) 1993 by Don Yacktman.
4 // Version 1.1. 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 - initString:(const char *)aString
37 {
38 [self init];
39 return [self setString:aString];
40 }
41
42 - setStringOrderTable:(NXStringOrderTable *)table
43 {
44 orderTable = table;
45 return self;
46 }
47
48 - (NXStringOrderTable *)stringOrderTable
49 {
50 return orderTable;
51 }
52
53 - allocateBuffer:(int)size
54 {
55 return [self allocateBuffer:size fromZone:[self zone]];
56 }
57
58 - allocateBuffer:(int)size fromZone:(NXZone *)zone
59 {
60 if (size <= _length) return self;
61 [self freeString];
62 buffer = (char *)NXZoneMalloc(zone, size);
63 buffer[0] = 0;
64 _length = size;
65
66 return self;
67 }
68
69 - setString:(const char *)aString
70 {
71 return [self setString:aString fromZone:[self zone]];
72 }
73
74 - setString:(const char *)aString fromZone:(NXZone *)zone
75 {
76 if (!aString) return self;
77 // Note that I could have used NXCopyStringBufferFromZone() here
78 // instead. This works just as well, but it may be slower...
79 // I haven't checked that out, though. It might be worth doing.
80 [self allocateBuffer:strlen(aString)+1 fromZone:zone];
81 strcpy(buffer, aString);
82 length = strlen(buffer);
83 return self;
84 }
85
86 - setStringValue:sender
87 {
88 if (![sender respondsTo:@selector(stringValue)]) return self;
89 return [self setString:[sender stringValue] fromZone:[self zone]];
90 }
91
92 - setStringValue:sender fromZone:(NXZone *)zone
93 {
94 if (![sender respondsTo:@selector(stringValue)]) return self;
95 return [self setString:[sender stringValue] fromZone:zone];
96 }
97
98 - (const char *)stringValue
99 {
100 return buffer;
101 }
102
103 - read:(NXTypedStream *)stream
104 {
105 char *tmpStr;
106 [super read:stream];
107 NXReadType(stream, "i", &_length);
108 tmpStr = (char *)malloc(_length + 1);
109 NXReadType(stream, "*", &tmpStr);
110 [self setString:tmpStr fromZone:[self zone]];
111 free(tmpStr);
112 return self;
113 }
114
115 - write:(NXTypedStream *)stream
116 {
117 [super write:stream];
118 NXWriteTypes(stream, "i*", &_length, &buffer);
119 return self;
120 }
121
122 - copyFromZone:(NXZone *)zone
123 {
124 String *myCopy = [super copyFromZone:zone];
125 // force child to have it's own copy of the string buffer
126 [myCopy _unhookBuffer];
127 [myCopy allocateBuffer:_length fromZone:zone];
128 [myCopy setString:buffer fromZone:zone];
129 return myCopy;
130 }
131
132 - _unhookBuffer
133 { // used by the copy method so that we don't free the buffer from orig.
134 buffer = NULL; _length = 0;
135 return self;
136 }
137
138 - freeString
139 {
140 if(buffer) free(buffer);
141 buffer = NULL;
142 length = 0;
143 _length = 0;
144 return self;
145 }
146
147 - free
148 {
149 [self freeString];
150 return [super free];
151 }
152
153 - cat:(const char *)aString
154 {
155 return [self cat:aString
156 n:strlen(aString)
157 fromZone:[self zone]];
158 }
159
160 - cat:(const char *)aString n:(int)n
161 {
162 return [self cat:aString n:n fromZone:[self zone]];
163 }
164
165 - cat:(const char *)aString fromZone:(NXZone *)zone
166 {
167 return [self cat:aString n:strlen(aString) fromZone:zone];
168 }
169
170 - cat:(const char *)aString n:(int)n fromZone:(NXZone *)zone
171 {
172 char *newBuffer; int newSize;
173 newSize = length + n + 1;
174 if (newSize > _length) {
175 newBuffer = (char *)NXZoneMalloc(zone, newSize);
176 _length = newSize;
177 newBuffer[0] = '\0';
178 strcat(newBuffer, buffer);
179 strncat(newBuffer, aString, n);
180 free(buffer);
181 buffer = newBuffer;
182 } else strncat(buffer, aString, n);
183 length = strlen(buffer);
184 return self;
185 }
186
187 - concatenate:sender
188 {
189 if (![sender respondsTo:@selector(stringValue)]) return self;
190 return [self cat:[sender stringValue]
191 n:strlen([sender stringValue])
192 fromZone:[self zone]];
193 }
194
195 - concatenate:sender n:(int)n
196 {
197 if (![sender respondsTo:@selector(stringValue)]) return self;
198 return [self cat:[sender stringValue] n:n fromZone:[self zone]];
199 }
200
201 - concatenate:sender fromZone:(NXZone *)zone
202 {
203 if (![sender respondsTo:@selector(stringValue)]) return self;
204 return [self cat:[sender stringValue]
205 n:strlen([sender stringValue]) fromZone:zone];
206 }
207
208 - concatenate:sender n:(int)n fromZone:(NXZone *)zone
209 {
210 if (![sender respondsTo:@selector(stringValue)]) return self;
211 return [self cat:[sender stringValue] n:n fromZone:zone];
212 }
213
214 - (const char *)rindex:(char)aChar
215 {
216 return rindex(buffer, aChar);
217 }
218
219 - (const char *)index:(char)aChar
220 {
221 return index(buffer, aChar);
222 }
223
224 - (const char *)strstr:(const char *)subString
225 {
226 return strstr(buffer, subString);
227 }
228
229 - subStringRight:subString
230 {
231 const char *sub;
232 if ([subString respondsTo:@selector(stringValue)])
233 sub = [subString stringValue];
234 else return nil; // error if can't get string value
235 return [[String allocFromZone:[self zone]]
236 initString:strstr(buffer, sub)];
237 }
238
239 - subStringLeft:subString
240 {
241 const char *sub;
242 char *tempString = NXCopyStringBufferFromZone(buffer, [self zone]);
243 char *temp2;
244 id retVal = [String alloc];
245
246 if ([subString respondsTo:@selector(stringValue)])
247 sub = [subString stringValue];
248 else return nil; // error if can't get string value
249 temp2 = strstr(tempString, sub);
250 if (temp2) {
251 temp2[0] = '\0'; // terminate it early
252 [retVal initString:tempString];
253 } else { // substring not found
254 return [self copy];
255 }
256 free(tempString);
257 return retVal;
258 }
259
260 - (int)length
261 {
262 return length;
263 }
264
265 - (BOOL)isEqual:anObject
266 {
267 if (anObject == self) return YES;
268 // doesn't have to be a String object to be equal...
269 if ([anObject respondsTo:@selector(stringValue)]) {
270 if (!NXOrderStrings(buffer, [anObject stringValue],
271 YES, -1, orderTable)) return YES;
272 }
273 return NO;
274 }
275
276 - (int)compareTo:sender
277 {
278 return [self compareTo:sender n:(-1) caseSensitive:YES];
279 }
280
281 - (int)compareTo:sender n:(int)n
282 {
283 return [self compareTo:sender n:n caseSensitive:YES];
284 }
285
286 - (int)cmp:(const char *)aString
287 {
288 return strcmp(buffer, aString);
289 }
290
291 - (int)cmp:(const char *)aString n:(int)n
292 {
293 return strncmp(buffer, aString, n);
294 }
295
296 - (int)compareTo:sender caseSensitive:(BOOL)sense
297 {
298 return [self compareTo:sender n:(-1) caseSensitive:sense];
299 }
300
301 - (int)compareTo:sender n:(int)n caseSensitive:(BOOL)sense
302 {
303 if (![sender respondsTo:@selector(stringValue)]) return 1; // !=
304 return NXOrderStrings(buffer, [sender stringValue], sense, n, orderTable);
305 }
306
307 - (int)casecmp:(const char *)aString
308 {
309 return strcasecmp(buffer, aString);
310 }
311
312 - (int)casecmp:(const char *)aString n:(int)n
313 {
314 return strncasecmp(buffer, aString, n);
315 }
316
317 - left:(int)count
318 {
319 return [self left:count fromZone:[self zone]];
320 }
321
322 - right:(int)count
323 {
324 return [self right:count fromZone:[self zone]];
325 }
326
327 - midFrom:(int)start to:(int)end
328 {
329 return [self midFrom:start to:end fromZone:[self zone]];
330 }
331
332 - midFrom:(int)start length:(int)len
333 {
334 return [self midFrom:start length:len fromZone:[self zone]];
335 }
336
337 - left:(int)count fromZone:(NXZone *)zone
338 {
339 char smash = buffer[count];
340 id newString = [[String allocFromZone:zone] init];
341 buffer[count] = '\0';
342 [newString setString:buffer fromZone:zone];
343 buffer[count] = smash;
344 return newString;
345 }
346
347 - right:(int)count fromZone:(NXZone *)zone
348 {
349 id newString = [[String allocFromZone:zone] init];
350 [newString setString:&buffer[length - count] fromZone:zone];
351 return newString;
352 }
353
354 - midFrom:(int)start to:(int)end fromZone:(NXZone *)zone
355 {
356 char smash = buffer[end];
357 id newString = [[String allocFromZone:zone] init];
358 buffer[end] = '\0'; // inclusive; end-1 is not.
359 [newString setString:&buffer[start - 1] fromZone:zone];
360 buffer[end] = smash;
361 return newString;
362 }
363
364 - midFrom:(int)start length:(int)len fromZone:(NXZone *)zone
365 {
366 register int spot = start + len - 1;
367 char smash = buffer[spot];
368 id newString = [[String allocFromZone:zone] init];
369 buffer[spot] = '\0';
370 [newString setString:&buffer[start - 1] fromZone:zone];
371 buffer[spot] = smash;
372 return newString;
373 }
374
375
376 @end