blob: 326dfb8854a0f4729f0a1db92ad984dc4d62dc6a [file] [log] [blame]
Guido van Rossume270b431992-09-03 20:21:07 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The 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 Rossumb6775db1994-08-01 11:34:53 +000034#include <errno.h>
35
Guido van Rossume270b431992-09-03 20:21:07 +000036
37static object *
38strop_split(self, args)
39 object *self; /* Not used */
40 object *args;
41{
Guido van Rossum572d2d91993-11-05 10:14:49 +000042 int len, i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000043 char *s;
44 char c;
45 object *list, *item;
46
47 if (!getargs(args, "s#", &s, &len))
48 return NULL;
49 list = newlistobject(0);
50 if (list == NULL)
51 return NULL;
52
53 i = 0;
54 while (i < len) {
55 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000056 ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000057 i = i+1;
58 }
59 j = i;
60 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000061 !((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000062 i = i+1;
63 }
64 if (j < i) {
65 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +000066 if (item == NULL) {
67 DECREF(list);
68 return NULL;
69 }
70 err = addlistitem(list, item);
71 DECREF(item);
72 if (err < 0) {
Guido van Rossume270b431992-09-03 20:21:07 +000073 DECREF(list);
74 return NULL;
75 }
76 }
77 }
78
79 return list;
80}
81
82
83static object *
84strop_splitfields(self, args)
85 object *self; /* Not used */
86 object *args;
87{
Guido van Rossum572d2d91993-11-05 10:14:49 +000088 int len, n, i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000089 char *s, *sub;
Guido van Rossume270b431992-09-03 20:21:07 +000090 object *list, *item;
91
92 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
93 return NULL;
94 if (n == 0) {
95 err_setstr(ValueError, "empty separator");
96 return NULL;
97 }
98
99 list = newlistobject(0);
100 if (list == NULL)
101 return NULL;
102
103 i = j = 0;
104 while (i+n <= len) {
105 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
106 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +0000107 if (item == NULL)
108 goto fail;
109 err = addlistitem(list, item);
110 DECREF(item);
111 if (err < 0)
112 goto fail;
Guido van Rossume270b431992-09-03 20:21:07 +0000113 i = j = i + n;
114 }
115 else
116 i++;
117 }
118 item = newsizedstringobject(s+j, (int)(len-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +0000119 if (item == NULL)
120 goto fail;
121 err = addlistitem(list, item);
122 DECREF(item);
123 if (err < 0)
124 goto fail;
Guido van Rossume270b431992-09-03 20:21:07 +0000125
126 return list;
Guido van Rossum572d2d91993-11-05 10:14:49 +0000127
128 fail:
129 DECREF(list);
130 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000131}
132
133
134static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000135strop_joinfields(self, args)
136 object *self; /* Not used */
137 object *args;
138{
139 object *seq, *item, *res;
140 object * (*getitem) FPROTO((object *, int));
141 char *sep, *p;
142 int seplen, seqlen, reslen, itemlen, i;
143
144 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
145 return NULL;
146 if (is_listobject(seq)) {
147 getitem = getlistitem;
148 seqlen = getlistsize(seq);
149 }
150 else if (is_tupleobject(seq)) {
151 getitem = gettupleitem;
152 seqlen = gettuplesize(seq);
153 }
154 else {
155 err_setstr(TypeError, "first argument must be list/tuple");
156 return NULL;
157 }
158 reslen = 0;
159 for (i = 0; i < seqlen; i++) {
160 item = getitem(seq, i);
161 if (!is_stringobject(item)) {
162 err_setstr(TypeError,
163 "first argument must be list/tuple of strings");
164 return NULL;
165 }
166 if (i > 0)
167 reslen = reslen + seplen;
168 reslen = reslen + getstringsize(item);
169 }
170 if (seqlen == 1) {
171 /* Optimization if there's only one item */
172 item = getitem(seq, 0);
173 INCREF(item);
174 return item;
175 }
176 res = newsizedstringobject((char *)NULL, reslen);
177 if (res == NULL)
178 return NULL;
179 p = getstringvalue(res);
180 for (i = 0; i < seqlen; i++) {
181 item = getitem(seq, i);
182 if (i > 0) {
183 memcpy(p, sep, seplen);
184 p += seplen;
185 }
186 itemlen = getstringsize(item);
187 memcpy(p, getstringvalue(item), itemlen);
188 p += itemlen;
189 }
190 if (p != getstringvalue(res) + reslen) {
191 err_setstr(SystemError, "strop.joinfields: assertion failed");
192 return NULL;
193 }
194 return res;
195}
196
197
198static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000199strop_find(self, args)
Guido van Rossume270b431992-09-03 20:21:07 +0000200 object *self; /* Not used */
201 object *args;
202{
203 char *s, *sub;
204 int len, n, i;
205
206 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
Guido van Rossumee9012f1993-10-26 15:23:55 +0000207 if (i < 0)
208 i += len;
Guido van Rossum602099a1994-09-14 13:32:22 +0000209 if (i < 0)
210 i = 0;
Guido van Rossume270b431992-09-03 20:21:07 +0000211 }
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
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000228 return newintobject(-1L);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000229}
230
231
232static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000233strop_rfind(self, args)
Guido van Rossumee9012f1993-10-26 15:23:55 +0000234 object *self; /* Not used */
235 object *args;
236{
237 char *s, *sub;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000238 int len, n, i, j;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000239
240 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
241 if (i < 0)
242 i += len;
Guido van Rossum602099a1994-09-14 13:32:22 +0000243 if (i < 0)
244 i = 0;
Guido van Rossume270b431992-09-03 20:21:07 +0000245 }
Guido van Rossumee9012f1993-10-26 15:23:55 +0000246 else {
247 err_clear();
248 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
249 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000250 i = 0;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000251 }
252
253 if (n == 0)
Guido van Rossumc65a5251994-08-05 13:44:50 +0000254 return newintobject((long)len);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000255
Guido van Rossumb6775db1994-08-01 11:34:53 +0000256 for (j = len-n; j >= i; --j)
257 if (s[j] == sub[0] &&
258 (n == 1 || strncmp(&s[j+1], &sub[1], n-1) == 0))
259 return newintobject((long)j);
Guido van Rossume270b431992-09-03 20:21:07 +0000260
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000261 return newintobject(-1L);
Guido van Rossume270b431992-09-03 20:21:07 +0000262}
263
264
265static object *
266strop_strip(self, args)
267 object *self; /* Not used */
268 object *args;
269{
270 char *s;
271 int len, i, j;
272 char c;
273
274 if (!getargs(args, "s#", &s, &len))
275 return NULL;
276
277 i = 0;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000278 while (i < len && ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000279 i++;
280 }
281
282 j = len;
283 do {
284 j--;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000285 } while (j >= i && ((c = s[j]), isspace(c)));
Guido van Rossume270b431992-09-03 20:21:07 +0000286 j++;
287
288 if (i == 0 && j == len) {
289 INCREF(args);
290 return args;
291 }
292 else
293 return newsizedstringobject(s+i, j-i);
294}
295
296
Guido van Rossum5c850621992-09-11 23:55:51 +0000297static object *
298strop_lower(self, args)
299 object *self; /* Not used */
300 object *args;
301{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000302 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000303 int i, n;
304 object *new;
305 int changed;
306
307 if (!getargs(args, "s#", &s, &n))
308 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000309 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000310 if (new == NULL)
311 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000312 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000313 changed = 0;
314 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000315 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000316 if (isupper(c)) {
317 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000318 *s_new = tolower(c);
319 } else
320 *s_new = c;
321 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000322 }
323 if (!changed) {
324 DECREF(new);
325 INCREF(args);
326 return args;
327 }
328 return new;
329}
330
331
332static object *
333strop_upper(self, args)
334 object *self; /* Not used */
335 object *args;
336{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000337 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000338 int i, n;
339 object *new;
340 int changed;
341
342 if (!getargs(args, "s#", &s, &n))
343 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000344 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000345 if (new == NULL)
346 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000347 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000348 changed = 0;
349 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000350 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000351 if (islower(c)) {
352 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000353 *s_new = toupper(c);
354 } else
355 *s_new = c;
356 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000357 }
358 if (!changed) {
359 DECREF(new);
360 INCREF(args);
361 return args;
362 }
363 return new;
364}
365
366
367static object *
368strop_swapcase(self, args)
369 object *self; /* Not used */
370 object *args;
371{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000372 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000373 int i, n;
374 object *new;
375 int changed;
376
377 if (!getargs(args, "s#", &s, &n))
378 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000379 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000380 if (new == NULL)
381 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000382 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000383 changed = 0;
384 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000385 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000386 if (islower(c)) {
387 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000388 *s_new = toupper(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000389 }
390 else if (isupper(c)) {
391 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000392 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000393 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000394 else
395 *s_new = c;
396 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000397 }
398 if (!changed) {
399 DECREF(new);
400 INCREF(args);
401 return args;
402 }
403 return new;
404}
405
406
Guido van Rossumb6775db1994-08-01 11:34:53 +0000407static object *
408strop_atoi(self, args)
409 object *self; /* Not used */
410 object *args;
411{
412 extern long mystrtol PROTO((const char *, char **, int));
413 extern unsigned long mystrtoul PROTO((const char *, char **, int));
414 char *s, *end;
415 int base = 10;
416 long x;
417
418 if (args != NULL && is_tupleobject(args)) {
419 if (!getargs(args, "(si)", &s, &base))
420 return NULL;
421 if (base != 0 && base < 2 || base > 36) {
422 err_setstr(ValueError, "invalid base for atoi()");
423 return NULL;
424 }
425 }
426 else if (!getargs(args, "s", &s))
427 return NULL;
428 errno = 0;
429 if (base == 0 && s[0] == '0')
430 x = (long) mystrtoul(s, &end, base);
431 else
432 x = mystrtol(s, &end, base);
433 if (*end != '\0') {
434 err_setstr(ValueError, "invalid literal for atoi()");
435 return NULL;
436 }
437 else if (errno != 0) {
438 err_setstr(OverflowError, "atoi() literal too large");
439 return NULL;
440 }
441 return newintobject(x);
442}
443
444
445static object *
446strop_atol(self, args)
447 object *self; /* Not used */
448 object *args;
449{
450 char *s, *end;
451 int base = 10;
452 object *x;
453
454 if (args != NULL && is_tupleobject(args)) {
455 if (!getargs(args, "(si)", &s, &base))
456 return NULL;
457 if (base != 0 && base < 2 || base > 36) {
458 err_setstr(ValueError, "invalid base for atol()");
459 return NULL;
460 }
461 }
462 else if (!getargs(args, "s", &s))
463 return NULL;
464 x = long_escan(s, &end, base);
465 if (x == NULL)
466 return NULL;
467 if (base == 0 && (*end == 'l' || *end == 'L'))
468 end++;
469 if (*end != '\0') {
470 err_setstr(ValueError, "invalid literal for atol()");
471 DECREF(x);
472 return NULL;
473 }
474 return x;
475}
476
477
478static object *
479strop_atof(self, args)
480 object *self; /* Not used */
481 object *args;
482{
483 extern double strtod PROTO((const char *, char **));
484 char *s, *end;
485 double x;
486
487 if (!getargs(args, "s", &s))
488 return NULL;
489 errno = 0;
490 x = strtod(s, &end);
491 if (*end != '\0') {
492 err_setstr(ValueError, "invalid literal for atof()");
493 return NULL;
494 }
495 else if (errno != 0) {
496 err_setstr(OverflowError, "atof() literal too large");
497 return NULL;
498 }
499 return newfloatobject(x);
500}
501
502
Guido van Rossume270b431992-09-03 20:21:07 +0000503/* List of functions defined in the module */
504
505static struct methodlist strop_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000506 {"atof", strop_atof},
507 {"atoi", strop_atoi},
508 {"atol", strop_atol},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000509 {"find", strop_find},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000510 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000511 {"lower", strop_lower},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000512 {"rfind", strop_rfind},
Guido van Rossume270b431992-09-03 20:21:07 +0000513 {"split", strop_split},
514 {"splitfields", strop_splitfields},
515 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000516 {"swapcase", strop_swapcase},
517 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000518 {NULL, NULL} /* sentinel */
519};
520
521
Guido van Rossume270b431992-09-03 20:21:07 +0000522void
523initstrop()
524{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000525 object *m, *d, *s;
526 char buf[256];
527 int c, n;
528 m = initmodule("strop", strop_methods);
529 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000530
531 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000532 n = 0;
533 for (c = 1; c < 256; c++) {
534 if (isspace(c))
535 buf[n++] = c;
536 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000537 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000538 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000539 dictinsert(d, "whitespace", s);
540 DECREF(s);
541 }
542 /* Create 'lowercase' object */
543 n = 0;
544 for (c = 1; c < 256; c++) {
545 if (islower(c))
546 buf[n++] = c;
547 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000548 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000549 if (s) {
550 dictinsert(d, "lowercase", s);
551 DECREF(s);
552 }
553
554 /* Create 'uppercase' object */
555 n = 0;
556 for (c = 1; c < 256; c++) {
557 if (isupper(c))
558 buf[n++] = c;
559 }
560 s = newsizedstringobject(buf, n);
561 if (s) {
562 dictinsert(d, "uppercase", s);
563 DECREF(s);
564 }
565
566 if (err_occurred())
567 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000568}