Mercurial > hg > xemacs-beta
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 |