blob: fe67ca09c32c7a0a049dabd7ef9393b4adfb5bbe [file] [log] [blame]
Guido van Rossume270b431992-09-03 20:21:07 +00001/***********************************************************
Guido van Rossum9bfef441993-03-29 10:43:31 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossume270b431992-09-03 20:21:07 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* strop module */
26
27#include "allobjects.h"
28#include "modsupport.h"
29
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000030#include <ctype.h>
Guido van Rossume22e6441993-07-09 10:51:31 +000031/* XXX This file assumes that the <ctype.h> is*() functions
32 XXX are defined for all 8-bit characters! */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000033
Guido van Rossume270b431992-09-03 20:21:07 +000034
35static object *
36strop_split(self, args)
37 object *self; /* Not used */
38 object *args;
39{
Guido van Rossum572d2d91993-11-05 10:14:49 +000040 int len, i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000041 char *s;
42 char c;
43 object *list, *item;
44
45 if (!getargs(args, "s#", &s, &len))
46 return NULL;
47 list = newlistobject(0);
48 if (list == NULL)
49 return NULL;
50
51 i = 0;
52 while (i < len) {
53 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000054 ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000055 i = i+1;
56 }
57 j = i;
58 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000059 !((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000060 i = i+1;
61 }
62 if (j < i) {
63 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +000064 if (item == NULL) {
65 DECREF(list);
66 return NULL;
67 }
68 err = addlistitem(list, item);
69 DECREF(item);
70 if (err < 0) {
Guido van Rossume270b431992-09-03 20:21:07 +000071 DECREF(list);
72 return NULL;
73 }
74 }
75 }
76
77 return list;
78}
79
80
81static object *
82strop_splitfields(self, args)
83 object *self; /* Not used */
84 object *args;
85{
Guido van Rossum572d2d91993-11-05 10:14:49 +000086 int len, n, i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000087 char *s, *sub;
Guido van Rossume270b431992-09-03 20:21:07 +000088 object *list, *item;
89
90 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
91 return NULL;
92 if (n == 0) {
93 err_setstr(ValueError, "empty separator");
94 return NULL;
95 }
96
97 list = newlistobject(0);
98 if (list == NULL)
99 return NULL;
100
101 i = j = 0;
102 while (i+n <= len) {
103 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
104 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +0000105 if (item == NULL)
106 goto fail;
107 err = addlistitem(list, item);
108 DECREF(item);
109 if (err < 0)
110 goto fail;
Guido van Rossume270b431992-09-03 20:21:07 +0000111 i = j = i + n;
112 }
113 else
114 i++;
115 }
116 item = newsizedstringobject(s+j, (int)(len-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +0000117 if (item == NULL)
118 goto fail;
119 err = addlistitem(list, item);
120 DECREF(item);
121 if (err < 0)
122 goto fail;
Guido van Rossume270b431992-09-03 20:21:07 +0000123
124 return list;
Guido van Rossum572d2d91993-11-05 10:14:49 +0000125
126 fail:
127 DECREF(list);
128 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000129}
130
131
132static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000133strop_joinfields(self, args)
134 object *self; /* Not used */
135 object *args;
136{
137 object *seq, *item, *res;
138 object * (*getitem) FPROTO((object *, int));
139 char *sep, *p;
140 int seplen, seqlen, reslen, itemlen, i;
141
142 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
143 return NULL;
144 if (is_listobject(seq)) {
145 getitem = getlistitem;
146 seqlen = getlistsize(seq);
147 }
148 else if (is_tupleobject(seq)) {
149 getitem = gettupleitem;
150 seqlen = gettuplesize(seq);
151 }
152 else {
153 err_setstr(TypeError, "first argument must be list/tuple");
154 return NULL;
155 }
156 reslen = 0;
157 for (i = 0; i < seqlen; i++) {
158 item = getitem(seq, i);
159 if (!is_stringobject(item)) {
160 err_setstr(TypeError,
161 "first argument must be list/tuple of strings");
162 return NULL;
163 }
164 if (i > 0)
165 reslen = reslen + seplen;
166 reslen = reslen + getstringsize(item);
167 }
168 if (seqlen == 1) {
169 /* Optimization if there's only one item */
170 item = getitem(seq, 0);
171 INCREF(item);
172 return item;
173 }
174 res = newsizedstringobject((char *)NULL, reslen);
175 if (res == NULL)
176 return NULL;
177 p = getstringvalue(res);
178 for (i = 0; i < seqlen; i++) {
179 item = getitem(seq, i);
180 if (i > 0) {
181 memcpy(p, sep, seplen);
182 p += seplen;
183 }
184 itemlen = getstringsize(item);
185 memcpy(p, getstringvalue(item), itemlen);
186 p += itemlen;
187 }
188 if (p != getstringvalue(res) + reslen) {
189 err_setstr(SystemError, "strop.joinfields: assertion failed");
190 return NULL;
191 }
192 return res;
193}
194
195
196static object *
Guido van Rossume270b431992-09-03 20:21:07 +0000197strop_index(self, args)
198 object *self; /* Not used */
199 object *args;
200{
201 char *s, *sub;
202 int len, n, i;
203
204 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
Guido van Rossumee9012f1993-10-26 15:23:55 +0000205 if (i < 0)
206 i += len;
Guido van Rossume270b431992-09-03 20:21:07 +0000207 if (i < 0 || i+n > len) {
208 err_setstr(ValueError, "start offset out of range");
209 return NULL;
210 }
211 }
212 else {
213 err_clear();
214 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
215 return NULL;
216 i = 0;
217 }
218
219 if (n == 0)
220 return newintobject((long)i);
221
222 len -= n;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000223 for (; i <= len; ++i)
224 if (s[i] == sub[0] &&
225 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
226 return newintobject((long)i);
227
228 err_setstr(ValueError, "substring not found");
229 return NULL;
230}
231
232
233static object *
234strop_rindex(self, args)
235 object *self; /* Not used */
236 object *args;
237{
238 char *s, *sub;
239 int len, n, i;
240
241 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
242 if (i < 0)
243 i += len;
244 if (i < 0 || i+n > len) {
245 err_setstr(ValueError, "start offset out of range");
246 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000247 }
248 }
Guido van Rossumee9012f1993-10-26 15:23:55 +0000249 else {
250 err_clear();
251 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
252 return NULL;
253 i = len;
254 }
255
256 if (n == 0)
257 return newintobject((long)i);
258
259 for (i -= n; i >= 0; --i)
260 if (s[i] == sub[0] &&
261 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
262 return newintobject((long)i);
Guido van Rossume270b431992-09-03 20:21:07 +0000263
264 err_setstr(ValueError, "substring not found");
265 return NULL;
266}
267
268
269static object *
270strop_strip(self, args)
271 object *self; /* Not used */
272 object *args;
273{
274 char *s;
275 int len, i, j;
276 char c;
277
278 if (!getargs(args, "s#", &s, &len))
279 return NULL;
280
281 i = 0;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000282 while (i < len && ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000283 i++;
284 }
285
286 j = len;
287 do {
288 j--;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000289 } while (j >= i && ((c = s[j]), isspace(c)));
Guido van Rossume270b431992-09-03 20:21:07 +0000290 j++;
291
292 if (i == 0 && j == len) {
293 INCREF(args);
294 return args;
295 }
296 else
297 return newsizedstringobject(s+i, j-i);
298}
299
300
Guido van Rossum5c850621992-09-11 23:55:51 +0000301static object *
302strop_lower(self, args)
303 object *self; /* Not used */
304 object *args;
305{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000306 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000307 int i, n;
308 object *new;
309 int changed;
310
311 if (!getargs(args, "s#", &s, &n))
312 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000313 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000314 if (new == NULL)
315 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000316 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000317 changed = 0;
318 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000319 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000320 if (isupper(c)) {
321 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000322 *s_new = tolower(c);
323 } else
324 *s_new = c;
325 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000326 }
327 if (!changed) {
328 DECREF(new);
329 INCREF(args);
330 return args;
331 }
332 return new;
333}
334
335
336static object *
337strop_upper(self, args)
338 object *self; /* Not used */
339 object *args;
340{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000341 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000342 int i, n;
343 object *new;
344 int changed;
345
346 if (!getargs(args, "s#", &s, &n))
347 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000348 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000349 if (new == NULL)
350 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000351 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000352 changed = 0;
353 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000354 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000355 if (islower(c)) {
356 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000357 *s_new = toupper(c);
358 } else
359 *s_new = c;
360 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000361 }
362 if (!changed) {
363 DECREF(new);
364 INCREF(args);
365 return args;
366 }
367 return new;
368}
369
370
371static object *
372strop_swapcase(self, args)
373 object *self; /* Not used */
374 object *args;
375{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000376 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000377 int i, n;
378 object *new;
379 int changed;
380
381 if (!getargs(args, "s#", &s, &n))
382 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000383 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000384 if (new == NULL)
385 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000386 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000387 changed = 0;
388 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000389 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000390 if (islower(c)) {
391 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000392 *s_new = toupper(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000393 }
394 else if (isupper(c)) {
395 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000396 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000397 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000398 else
399 *s_new = c;
400 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000401 }
402 if (!changed) {
403 DECREF(new);
404 INCREF(args);
405 return args;
406 }
407 return new;
408}
409
410
Guido van Rossume270b431992-09-03 20:21:07 +0000411/* List of functions defined in the module */
412
413static struct methodlist strop_methods[] = {
414 {"index", strop_index},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000415 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000416 {"lower", strop_lower},
Guido van Rossumee9012f1993-10-26 15:23:55 +0000417 {"rindex", strop_rindex},
Guido van Rossume270b431992-09-03 20:21:07 +0000418 {"split", strop_split},
419 {"splitfields", strop_splitfields},
420 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000421 {"swapcase", strop_swapcase},
422 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000423 {NULL, NULL} /* sentinel */
424};
425
426
Guido van Rossume270b431992-09-03 20:21:07 +0000427void
428initstrop()
429{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000430 object *m, *d, *s;
431 char buf[256];
432 int c, n;
433 m = initmodule("strop", strop_methods);
434 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000435
436 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000437 n = 0;
438 for (c = 1; c < 256; c++) {
439 if (isspace(c))
440 buf[n++] = c;
441 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000442 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000443 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000444 dictinsert(d, "whitespace", s);
445 DECREF(s);
446 }
447 /* Create 'lowercase' object */
448 n = 0;
449 for (c = 1; c < 256; c++) {
450 if (islower(c))
451 buf[n++] = c;
452 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000453 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000454 if (s) {
455 dictinsert(d, "lowercase", s);
456 DECREF(s);
457 }
458
459 /* Create 'uppercase' object */
460 n = 0;
461 for (c = 1; c < 256; c++) {
462 if (isupper(c))
463 buf[n++] = c;
464 }
465 s = newsizedstringobject(buf, n);
466 if (s) {
467 dictinsert(d, "uppercase", s);
468 DECREF(s);
469 }
470
471 if (err_occurred())
472 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000473}