blob: 0fd09b06d3cf9d4eb6184ed3540007901e503071 [file] [log] [blame]
Guido van Rossume270b431992-09-03 20:21:07 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossum9bfef441993-03-29 10:43:31 +00003Amsterdam, 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 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 Rossume270b431992-09-03 20:21:07 +0000199strop_index(self, args)
200 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 Rossume270b431992-09-03 20:21:07 +0000209 if (i < 0 || i+n > len) {
210 err_setstr(ValueError, "start offset out of range");
211 return NULL;
212 }
213 }
214 else {
215 err_clear();
216 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
217 return NULL;
218 i = 0;
219 }
220
221 if (n == 0)
222 return newintobject((long)i);
223
224 len -= n;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000225 for (; i <= len; ++i)
226 if (s[i] == sub[0] &&
227 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
228 return newintobject((long)i);
229
230 err_setstr(ValueError, "substring not found");
231 return NULL;
232}
233
234
235static object *
236strop_rindex(self, args)
237 object *self; /* Not used */
238 object *args;
239{
240 char *s, *sub;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000241 int len, n, i, j;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000242
243 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
244 if (i < 0)
245 i += len;
246 if (i < 0 || i+n > len) {
247 err_setstr(ValueError, "start offset out of range");
248 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000249 }
250 }
Guido van Rossumee9012f1993-10-26 15:23:55 +0000251 else {
252 err_clear();
253 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
254 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000255 i = 0;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000256 }
257
258 if (n == 0)
Guido van Rossumc65a5251994-08-05 13:44:50 +0000259 return newintobject((long)len);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000260
Guido van Rossumb6775db1994-08-01 11:34:53 +0000261 for (j = len-n; j >= i; --j)
262 if (s[j] == sub[0] &&
263 (n == 1 || strncmp(&s[j+1], &sub[1], n-1) == 0))
264 return newintobject((long)j);
Guido van Rossume270b431992-09-03 20:21:07 +0000265
266 err_setstr(ValueError, "substring not found");
267 return NULL;
268}
269
270
271static object *
272strop_strip(self, args)
273 object *self; /* Not used */
274 object *args;
275{
276 char *s;
277 int len, i, j;
278 char c;
279
280 if (!getargs(args, "s#", &s, &len))
281 return NULL;
282
283 i = 0;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000284 while (i < len && ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000285 i++;
286 }
287
288 j = len;
289 do {
290 j--;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000291 } while (j >= i && ((c = s[j]), isspace(c)));
Guido van Rossume270b431992-09-03 20:21:07 +0000292 j++;
293
294 if (i == 0 && j == len) {
295 INCREF(args);
296 return args;
297 }
298 else
299 return newsizedstringobject(s+i, j-i);
300}
301
302
Guido van Rossum5c850621992-09-11 23:55:51 +0000303static object *
304strop_lower(self, args)
305 object *self; /* Not used */
306 object *args;
307{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000308 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000309 int i, n;
310 object *new;
311 int changed;
312
313 if (!getargs(args, "s#", &s, &n))
314 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000315 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000316 if (new == NULL)
317 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000318 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000319 changed = 0;
320 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000321 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000322 if (isupper(c)) {
323 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000324 *s_new = tolower(c);
325 } else
326 *s_new = c;
327 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000328 }
329 if (!changed) {
330 DECREF(new);
331 INCREF(args);
332 return args;
333 }
334 return new;
335}
336
337
338static object *
339strop_upper(self, args)
340 object *self; /* Not used */
341 object *args;
342{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000343 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000344 int i, n;
345 object *new;
346 int changed;
347
348 if (!getargs(args, "s#", &s, &n))
349 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000350 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000351 if (new == NULL)
352 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000353 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000354 changed = 0;
355 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000356 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000357 if (islower(c)) {
358 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000359 *s_new = toupper(c);
360 } else
361 *s_new = c;
362 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000363 }
364 if (!changed) {
365 DECREF(new);
366 INCREF(args);
367 return args;
368 }
369 return new;
370}
371
372
373static object *
374strop_swapcase(self, args)
375 object *self; /* Not used */
376 object *args;
377{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000378 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000379 int i, n;
380 object *new;
381 int changed;
382
383 if (!getargs(args, "s#", &s, &n))
384 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000385 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000386 if (new == NULL)
387 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000388 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000389 changed = 0;
390 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000391 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000392 if (islower(c)) {
393 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000394 *s_new = toupper(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000395 }
396 else if (isupper(c)) {
397 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000398 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000399 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000400 else
401 *s_new = c;
402 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000403 }
404 if (!changed) {
405 DECREF(new);
406 INCREF(args);
407 return args;
408 }
409 return new;
410}
411
412
Guido van Rossumb6775db1994-08-01 11:34:53 +0000413static object *
414strop_atoi(self, args)
415 object *self; /* Not used */
416 object *args;
417{
418 extern long mystrtol PROTO((const char *, char **, int));
419 extern unsigned long mystrtoul PROTO((const char *, char **, int));
420 char *s, *end;
421 int base = 10;
422 long x;
423
424 if (args != NULL && is_tupleobject(args)) {
425 if (!getargs(args, "(si)", &s, &base))
426 return NULL;
427 if (base != 0 && base < 2 || base > 36) {
428 err_setstr(ValueError, "invalid base for atoi()");
429 return NULL;
430 }
431 }
432 else if (!getargs(args, "s", &s))
433 return NULL;
434 errno = 0;
435 if (base == 0 && s[0] == '0')
436 x = (long) mystrtoul(s, &end, base);
437 else
438 x = mystrtol(s, &end, base);
439 if (*end != '\0') {
440 err_setstr(ValueError, "invalid literal for atoi()");
441 return NULL;
442 }
443 else if (errno != 0) {
444 err_setstr(OverflowError, "atoi() literal too large");
445 return NULL;
446 }
447 return newintobject(x);
448}
449
450
451static object *
452strop_atol(self, args)
453 object *self; /* Not used */
454 object *args;
455{
456 char *s, *end;
457 int base = 10;
458 object *x;
459
460 if (args != NULL && is_tupleobject(args)) {
461 if (!getargs(args, "(si)", &s, &base))
462 return NULL;
463 if (base != 0 && base < 2 || base > 36) {
464 err_setstr(ValueError, "invalid base for atol()");
465 return NULL;
466 }
467 }
468 else if (!getargs(args, "s", &s))
469 return NULL;
470 x = long_escan(s, &end, base);
471 if (x == NULL)
472 return NULL;
473 if (base == 0 && (*end == 'l' || *end == 'L'))
474 end++;
475 if (*end != '\0') {
476 err_setstr(ValueError, "invalid literal for atol()");
477 DECREF(x);
478 return NULL;
479 }
480 return x;
481}
482
483
484static object *
485strop_atof(self, args)
486 object *self; /* Not used */
487 object *args;
488{
489 extern double strtod PROTO((const char *, char **));
490 char *s, *end;
491 double x;
492
493 if (!getargs(args, "s", &s))
494 return NULL;
495 errno = 0;
496 x = strtod(s, &end);
497 if (*end != '\0') {
498 err_setstr(ValueError, "invalid literal for atof()");
499 return NULL;
500 }
501 else if (errno != 0) {
502 err_setstr(OverflowError, "atof() literal too large");
503 return NULL;
504 }
505 return newfloatobject(x);
506}
507
508
Guido van Rossume270b431992-09-03 20:21:07 +0000509/* List of functions defined in the module */
510
511static struct methodlist strop_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000512 {"atof", strop_atof},
513 {"atoi", strop_atoi},
514 {"atol", strop_atol},
Guido van Rossume270b431992-09-03 20:21:07 +0000515 {"index", strop_index},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000516 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000517 {"lower", strop_lower},
Guido van Rossumee9012f1993-10-26 15:23:55 +0000518 {"rindex", strop_rindex},
Guido van Rossume270b431992-09-03 20:21:07 +0000519 {"split", strop_split},
520 {"splitfields", strop_splitfields},
521 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000522 {"swapcase", strop_swapcase},
523 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000524 {NULL, NULL} /* sentinel */
525};
526
527
Guido van Rossume270b431992-09-03 20:21:07 +0000528void
529initstrop()
530{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000531 object *m, *d, *s;
532 char buf[256];
533 int c, n;
534 m = initmodule("strop", strop_methods);
535 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000536
537 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000538 n = 0;
539 for (c = 1; c < 256; c++) {
540 if (isspace(c))
541 buf[n++] = c;
542 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000543 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000544 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000545 dictinsert(d, "whitespace", s);
546 DECREF(s);
547 }
548 /* Create 'lowercase' object */
549 n = 0;
550 for (c = 1; c < 256; c++) {
551 if (islower(c))
552 buf[n++] = c;
553 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000554 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000555 if (s) {
556 dictinsert(d, "lowercase", s);
557 DECREF(s);
558 }
559
560 /* Create 'uppercase' object */
561 n = 0;
562 for (c = 1; c < 256; c++) {
563 if (isupper(c))
564 buf[n++] = c;
565 }
566 s = newsizedstringobject(buf, n);
567 if (s) {
568 dictinsert(d, "uppercase", s);
569 DECREF(s);
570 }
571
572 if (err_occurred())
573 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000574}