blob: a82c3138ed918b9e58589f41bef026f4817be19f [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 *
Guido van Rossum009e79b1995-05-03 17:40:23 +000038split_whitespace(s, len)
Guido van Rossume270b431992-09-03 20:21:07 +000039 char *s;
Guido van Rossum009e79b1995-05-03 17:40:23 +000040 int len;
41{
42 int i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000043 object *list, *item;
44
Guido van Rossume270b431992-09-03 20:21:07 +000045 list = newlistobject(0);
46 if (list == NULL)
47 return NULL;
48
49 i = 0;
50 while (i < len) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +000051 while (i < len && isspace(Py_CHARMASK(s[i]))) {
Guido van Rossume270b431992-09-03 20:21:07 +000052 i = i+1;
53 }
54 j = i;
Guido van Rossumee1813d1995-02-14 00:58:59 +000055 while (i < len && !isspace(Py_CHARMASK(s[i]))) {
Guido van Rossume270b431992-09-03 20:21:07 +000056 i = i+1;
57 }
58 if (j < i) {
59 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +000060 if (item == NULL) {
61 DECREF(list);
62 return NULL;
63 }
64 err = addlistitem(list, item);
65 DECREF(item);
66 if (err < 0) {
Guido van Rossume270b431992-09-03 20:21:07 +000067 DECREF(list);
68 return NULL;
69 }
70 }
71 }
72
73 return list;
74}
75
76
77static object *
78strop_splitfields(self, args)
79 object *self; /* Not used */
80 object *args;
81{
Guido van Rossum572d2d91993-11-05 10:14:49 +000082 int len, n, i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000083 char *s, *sub;
Guido van Rossume270b431992-09-03 20:21:07 +000084 object *list, *item;
85
Guido van Rossum009e79b1995-05-03 17:40:23 +000086 sub = NULL;
87 n = 0;
88 if (!newgetargs(args, "s#|z#", &s, &len, &sub, &n))
Guido van Rossume270b431992-09-03 20:21:07 +000089 return NULL;
Guido van Rossum009e79b1995-05-03 17:40:23 +000090 if (sub == NULL)
91 return split_whitespace(s, len);
Guido van Rossume270b431992-09-03 20:21:07 +000092 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
Guido van Rossum009e79b1995-05-03 17:40:23 +0000142 sep = NULL;
143 seplen = 0;
144 if (!newgetargs(args, "O|s#", &seq, &sep, &seplen))
Guido van Rossumc89705d1992-11-26 08:54:07 +0000145 return NULL;
Guido van Rossum009e79b1995-05-03 17:40:23 +0000146 if (sep == NULL) {
147 sep = " ";
148 seplen = 1;
149 }
Guido van Rossumc89705d1992-11-26 08:54:07 +0000150 if (is_listobject(seq)) {
151 getitem = getlistitem;
152 seqlen = getlistsize(seq);
153 }
154 else if (is_tupleobject(seq)) {
155 getitem = gettupleitem;
156 seqlen = gettuplesize(seq);
157 }
158 else {
159 err_setstr(TypeError, "first argument must be list/tuple");
160 return NULL;
161 }
162 reslen = 0;
163 for (i = 0; i < seqlen; i++) {
164 item = getitem(seq, i);
165 if (!is_stringobject(item)) {
166 err_setstr(TypeError,
167 "first argument must be list/tuple of strings");
168 return NULL;
169 }
170 if (i > 0)
171 reslen = reslen + seplen;
172 reslen = reslen + getstringsize(item);
173 }
174 if (seqlen == 1) {
175 /* Optimization if there's only one item */
176 item = getitem(seq, 0);
177 INCREF(item);
178 return item;
179 }
180 res = newsizedstringobject((char *)NULL, reslen);
181 if (res == NULL)
182 return NULL;
183 p = getstringvalue(res);
184 for (i = 0; i < seqlen; i++) {
185 item = getitem(seq, i);
186 if (i > 0) {
187 memcpy(p, sep, seplen);
188 p += seplen;
189 }
190 itemlen = getstringsize(item);
191 memcpy(p, getstringvalue(item), itemlen);
192 p += itemlen;
193 }
194 if (p != getstringvalue(res) + reslen) {
195 err_setstr(SystemError, "strop.joinfields: assertion failed");
196 return NULL;
197 }
198 return res;
199}
200
201
202static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000203strop_find(self, args)
Guido van Rossume270b431992-09-03 20:21:07 +0000204 object *self; /* Not used */
205 object *args;
206{
207 char *s, *sub;
208 int len, n, i;
209
210 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
Guido van Rossumee9012f1993-10-26 15:23:55 +0000211 if (i < 0)
212 i += len;
Guido van Rossum602099a1994-09-14 13:32:22 +0000213 if (i < 0)
214 i = 0;
Guido van Rossume270b431992-09-03 20:21:07 +0000215 }
216 else {
217 err_clear();
218 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
219 return NULL;
220 i = 0;
221 }
222
223 if (n == 0)
224 return newintobject((long)i);
225
226 len -= n;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000227 for (; i <= len; ++i)
228 if (s[i] == sub[0] &&
229 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
230 return newintobject((long)i);
231
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000232 return newintobject(-1L);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000233}
234
235
236static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000237strop_rfind(self, args)
Guido van Rossumee9012f1993-10-26 15:23:55 +0000238 object *self; /* Not used */
239 object *args;
240{
241 char *s, *sub;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000242 int len, n, i, j;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000243
244 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
245 if (i < 0)
246 i += len;
Guido van Rossum602099a1994-09-14 13:32:22 +0000247 if (i < 0)
248 i = 0;
Guido van Rossume270b431992-09-03 20:21:07 +0000249 }
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;
Guido van Rossume270b431992-09-03 20:21:07 +0000276
277 if (!getargs(args, "s#", &s, &len))
278 return NULL;
279
280 i = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000281 while (i < len && isspace(Py_CHARMASK(s[i]))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000282 i++;
283 }
284
285 j = len;
286 do {
287 j--;
Guido van Rossumee1813d1995-02-14 00:58:59 +0000288 } while (j >= i && isspace(Py_CHARMASK(s[j])));
Guido van Rossume270b431992-09-03 20:21:07 +0000289 j++;
290
291 if (i == 0 && j == len) {
292 INCREF(args);
293 return args;
294 }
295 else
296 return newsizedstringobject(s+i, j-i);
297}
298
299
Guido van Rossum5c850621992-09-11 23:55:51 +0000300static object *
301strop_lower(self, args)
302 object *self; /* Not used */
303 object *args;
304{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000305 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000306 int i, n;
307 object *new;
308 int changed;
309
310 if (!getargs(args, "s#", &s, &n))
311 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000312 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000313 if (new == NULL)
314 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000315 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000316 changed = 0;
317 for (i = 0; i < n; i++) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000318 int c = Py_CHARMASK(*s++);
Guido van Rossum5c850621992-09-11 23:55:51 +0000319 if (isupper(c)) {
320 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000321 *s_new = tolower(c);
322 } else
323 *s_new = c;
324 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000325 }
326 if (!changed) {
327 DECREF(new);
328 INCREF(args);
329 return args;
330 }
331 return new;
332}
333
334
335static object *
336strop_upper(self, args)
337 object *self; /* Not used */
338 object *args;
339{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000340 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000341 int i, n;
342 object *new;
343 int changed;
344
345 if (!getargs(args, "s#", &s, &n))
346 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000347 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000348 if (new == NULL)
349 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000350 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000351 changed = 0;
352 for (i = 0; i < n; i++) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000353 int c = Py_CHARMASK(*s++);
Guido van Rossum5c850621992-09-11 23:55:51 +0000354 if (islower(c)) {
355 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000356 *s_new = toupper(c);
357 } else
358 *s_new = c;
359 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000360 }
361 if (!changed) {
362 DECREF(new);
363 INCREF(args);
364 return args;
365 }
366 return new;
367}
368
369
370static object *
371strop_swapcase(self, args)
372 object *self; /* Not used */
373 object *args;
374{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000375 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000376 int i, n;
377 object *new;
378 int changed;
379
380 if (!getargs(args, "s#", &s, &n))
381 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000382 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000383 if (new == NULL)
384 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000385 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000386 changed = 0;
387 for (i = 0; i < n; i++) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000388 int c = Py_CHARMASK(*s++);
Guido van Rossum5c850621992-09-11 23:55:51 +0000389 if (islower(c)) {
390 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000391 *s_new = toupper(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000392 }
393 else if (isupper(c)) {
394 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000395 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000396 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000397 else
398 *s_new = c;
399 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000400 }
401 if (!changed) {
402 DECREF(new);
403 INCREF(args);
404 return args;
405 }
406 return new;
407}
408
409
Guido van Rossumb6775db1994-08-01 11:34:53 +0000410static object *
411strop_atoi(self, args)
412 object *self; /* Not used */
413 object *args;
414{
415 extern long mystrtol PROTO((const char *, char **, int));
416 extern unsigned long mystrtoul PROTO((const char *, char **, int));
417 char *s, *end;
418 int base = 10;
419 long x;
420
421 if (args != NULL && is_tupleobject(args)) {
422 if (!getargs(args, "(si)", &s, &base))
423 return NULL;
424 if (base != 0 && base < 2 || base > 36) {
425 err_setstr(ValueError, "invalid base for atoi()");
426 return NULL;
427 }
428 }
429 else if (!getargs(args, "s", &s))
430 return NULL;
431 errno = 0;
432 if (base == 0 && s[0] == '0')
433 x = (long) mystrtoul(s, &end, base);
434 else
435 x = mystrtol(s, &end, base);
436 if (*end != '\0') {
437 err_setstr(ValueError, "invalid literal for atoi()");
438 return NULL;
439 }
440 else if (errno != 0) {
441 err_setstr(OverflowError, "atoi() literal too large");
442 return NULL;
443 }
444 return newintobject(x);
445}
446
447
448static object *
449strop_atol(self, args)
450 object *self; /* Not used */
451 object *args;
452{
453 char *s, *end;
454 int base = 10;
455 object *x;
456
457 if (args != NULL && is_tupleobject(args)) {
458 if (!getargs(args, "(si)", &s, &base))
459 return NULL;
460 if (base != 0 && base < 2 || base > 36) {
461 err_setstr(ValueError, "invalid base for atol()");
462 return NULL;
463 }
464 }
465 else if (!getargs(args, "s", &s))
466 return NULL;
467 x = long_escan(s, &end, base);
468 if (x == NULL)
469 return NULL;
470 if (base == 0 && (*end == 'l' || *end == 'L'))
471 end++;
472 if (*end != '\0') {
473 err_setstr(ValueError, "invalid literal for atol()");
474 DECREF(x);
475 return NULL;
476 }
477 return x;
478}
479
480
481static object *
482strop_atof(self, args)
483 object *self; /* Not used */
484 object *args;
485{
486 extern double strtod PROTO((const char *, char **));
487 char *s, *end;
488 double x;
489
490 if (!getargs(args, "s", &s))
491 return NULL;
492 errno = 0;
493 x = strtod(s, &end);
494 if (*end != '\0') {
495 err_setstr(ValueError, "invalid literal for atof()");
496 return NULL;
497 }
498 else if (errno != 0) {
499 err_setstr(OverflowError, "atof() literal too large");
500 return NULL;
501 }
502 return newfloatobject(x);
503}
504
505
Guido van Rossuma3127e81995-09-13 17:39:06 +0000506static object *
507strop_translate(self, args)
508 object *self;
509 object *args;
510{
511 char *input, *table, *output;
512 int inlen, tablen;
513 object *result;
514 int i;
515
516 if (!newgetargs(args, "s#s#", &input, &inlen, &table, &tablen))
517 return NULL;
518 if (tablen != 256) {
519 err_setstr(ValueError,
520 "translation table must be 256 characters long");
521 return NULL;
522 }
523 result = newsizedstringobject((char *)NULL, inlen);
524 if (result == NULL)
525 return NULL;
526 output = getstringvalue(result);
527 for (i = 0; i < inlen; i++) {
528 int c = Py_CHARMASK(*input++);
529 *output++ = table[c];
530 }
531 return result;
532}
533
534
Guido van Rossume270b431992-09-03 20:21:07 +0000535/* List of functions defined in the module */
536
537static struct methodlist strop_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000538 {"atof", strop_atof},
539 {"atoi", strop_atoi},
540 {"atol", strop_atol},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000541 {"find", strop_find},
Guido van Rossum009e79b1995-05-03 17:40:23 +0000542 {"join", strop_joinfields, 1},
543 {"joinfields", strop_joinfields, 1},
Guido van Rossum5c850621992-09-11 23:55:51 +0000544 {"lower", strop_lower},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000545 {"rfind", strop_rfind},
Guido van Rossum009e79b1995-05-03 17:40:23 +0000546 {"split", strop_splitfields, 1},
547 {"splitfields", strop_splitfields, 1},
Guido van Rossume270b431992-09-03 20:21:07 +0000548 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000549 {"swapcase", strop_swapcase},
Guido van Rossuma3127e81995-09-13 17:39:06 +0000550 {"translate", strop_translate, 1},
Guido van Rossum5c850621992-09-11 23:55:51 +0000551 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000552 {NULL, NULL} /* sentinel */
553};
554
555
Guido van Rossume270b431992-09-03 20:21:07 +0000556void
557initstrop()
558{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000559 object *m, *d, *s;
560 char buf[256];
561 int c, n;
562 m = initmodule("strop", strop_methods);
563 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000564
565 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000566 n = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000567 for (c = 0; c < 256; c++) {
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000568 if (isspace(c))
569 buf[n++] = c;
570 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000571 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000572 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000573 dictinsert(d, "whitespace", s);
574 DECREF(s);
575 }
576 /* Create 'lowercase' object */
577 n = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000578 for (c = 0; c < 256; c++) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000579 if (islower(c))
580 buf[n++] = c;
581 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000582 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000583 if (s) {
584 dictinsert(d, "lowercase", s);
585 DECREF(s);
586 }
587
588 /* Create 'uppercase' object */
589 n = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000590 for (c = 0; c < 256; c++) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000591 if (isupper(c))
592 buf[n++] = c;
593 }
594 s = newsizedstringobject(buf, n);
595 if (s) {
596 dictinsert(d, "uppercase", s);
597 DECREF(s);
598 }
599
600 if (err_occurred())
601 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000602}