blob: 68df4dea3d886ff49cde0e28e40ae4732304d1a4 [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 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 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
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000230 return newintobject(-1L);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000231}
232
233
234static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000235strop_rfind(self, args)
Guido van Rossumee9012f1993-10-26 15:23:55 +0000236 object *self; /* Not used */
237 object *args;
238{
239 char *s, *sub;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000240 int len, n, i, j;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000241
242 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
243 if (i < 0)
244 i += len;
245 if (i < 0 || i+n > len) {
246 err_setstr(ValueError, "start offset out of range");
247 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000248 }
249 }
Guido van Rossumee9012f1993-10-26 15:23:55 +0000250 else {
251 err_clear();
252 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
253 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000254 i = 0;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000255 }
256
257 if (n == 0)
Guido van Rossumc65a5251994-08-05 13:44:50 +0000258 return newintobject((long)len);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000259
Guido van Rossumb6775db1994-08-01 11:34:53 +0000260 for (j = len-n; j >= i; --j)
261 if (s[j] == sub[0] &&
262 (n == 1 || strncmp(&s[j+1], &sub[1], n-1) == 0))
263 return newintobject((long)j);
Guido van Rossume270b431992-09-03 20:21:07 +0000264
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000265 return newintobject(-1L);
Guido van Rossume270b431992-09-03 20:21:07 +0000266}
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 Rossumb6775db1994-08-01 11:34:53 +0000411static object *
412strop_atoi(self, args)
413 object *self; /* Not used */
414 object *args;
415{
416 extern long mystrtol PROTO((const char *, char **, int));
417 extern unsigned long mystrtoul PROTO((const char *, char **, int));
418 char *s, *end;
419 int base = 10;
420 long x;
421
422 if (args != NULL && is_tupleobject(args)) {
423 if (!getargs(args, "(si)", &s, &base))
424 return NULL;
425 if (base != 0 && base < 2 || base > 36) {
426 err_setstr(ValueError, "invalid base for atoi()");
427 return NULL;
428 }
429 }
430 else if (!getargs(args, "s", &s))
431 return NULL;
432 errno = 0;
433 if (base == 0 && s[0] == '0')
434 x = (long) mystrtoul(s, &end, base);
435 else
436 x = mystrtol(s, &end, base);
437 if (*end != '\0') {
438 err_setstr(ValueError, "invalid literal for atoi()");
439 return NULL;
440 }
441 else if (errno != 0) {
442 err_setstr(OverflowError, "atoi() literal too large");
443 return NULL;
444 }
445 return newintobject(x);
446}
447
448
449static object *
450strop_atol(self, args)
451 object *self; /* Not used */
452 object *args;
453{
454 char *s, *end;
455 int base = 10;
456 object *x;
457
458 if (args != NULL && is_tupleobject(args)) {
459 if (!getargs(args, "(si)", &s, &base))
460 return NULL;
461 if (base != 0 && base < 2 || base > 36) {
462 err_setstr(ValueError, "invalid base for atol()");
463 return NULL;
464 }
465 }
466 else if (!getargs(args, "s", &s))
467 return NULL;
468 x = long_escan(s, &end, base);
469 if (x == NULL)
470 return NULL;
471 if (base == 0 && (*end == 'l' || *end == 'L'))
472 end++;
473 if (*end != '\0') {
474 err_setstr(ValueError, "invalid literal for atol()");
475 DECREF(x);
476 return NULL;
477 }
478 return x;
479}
480
481
482static object *
483strop_atof(self, args)
484 object *self; /* Not used */
485 object *args;
486{
487 extern double strtod PROTO((const char *, char **));
488 char *s, *end;
489 double x;
490
491 if (!getargs(args, "s", &s))
492 return NULL;
493 errno = 0;
494 x = strtod(s, &end);
495 if (*end != '\0') {
496 err_setstr(ValueError, "invalid literal for atof()");
497 return NULL;
498 }
499 else if (errno != 0) {
500 err_setstr(OverflowError, "atof() literal too large");
501 return NULL;
502 }
503 return newfloatobject(x);
504}
505
506
Guido van Rossume270b431992-09-03 20:21:07 +0000507/* List of functions defined in the module */
508
509static struct methodlist strop_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000510 {"atof", strop_atof},
511 {"atoi", strop_atoi},
512 {"atol", strop_atol},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000513 {"find", strop_find},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000514 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000515 {"lower", strop_lower},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000516 {"rfind", strop_rfind},
Guido van Rossume270b431992-09-03 20:21:07 +0000517 {"split", strop_split},
518 {"splitfields", strop_splitfields},
519 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000520 {"swapcase", strop_swapcase},
521 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000522 {NULL, NULL} /* sentinel */
523};
524
525
Guido van Rossume270b431992-09-03 20:21:07 +0000526void
527initstrop()
528{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000529 object *m, *d, *s;
530 char buf[256];
531 int c, n;
532 m = initmodule("strop", strop_methods);
533 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000534
535 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000536 n = 0;
537 for (c = 1; c < 256; c++) {
538 if (isspace(c))
539 buf[n++] = c;
540 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000541 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000542 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000543 dictinsert(d, "whitespace", s);
544 DECREF(s);
545 }
546 /* Create 'lowercase' object */
547 n = 0;
548 for (c = 1; c < 256; c++) {
549 if (islower(c))
550 buf[n++] = c;
551 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000552 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000553 if (s) {
554 dictinsert(d, "lowercase", s);
555 DECREF(s);
556 }
557
558 /* Create 'uppercase' object */
559 n = 0;
560 for (c = 1; c < 256; c++) {
561 if (isupper(c))
562 buf[n++] = c;
563 }
564 s = newsizedstringobject(buf, n);
565 if (s) {
566 dictinsert(d, "uppercase", s);
567 DECREF(s);
568 }
569
570 if (err_occurred())
571 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000572}