blob: 90ee4fd166c8b2cb7f7ccb4dda468c4d8a1ab144 [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;
Guido van Rossume270b431992-09-03 20:21:07 +000044 object *list, *item;
45
46 if (!getargs(args, "s#", &s, &len))
47 return NULL;
48 list = newlistobject(0);
49 if (list == NULL)
50 return NULL;
51
52 i = 0;
53 while (i < len) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +000054 while (i < len && isspace(Py_CHARMASK(s[i]))) {
Guido van Rossume270b431992-09-03 20:21:07 +000055 i = i+1;
56 }
57 j = i;
Guido van Rossum7f7f2741995-02-10 17:01:56 +000058 while (i < len && isspace(Py_CHARMASK(s[i]))) {
Guido van Rossume270b431992-09-03 20:21:07 +000059 i = i+1;
60 }
61 if (j < i) {
62 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +000063 if (item == NULL) {
64 DECREF(list);
65 return NULL;
66 }
67 err = addlistitem(list, item);
68 DECREF(item);
69 if (err < 0) {
Guido van Rossume270b431992-09-03 20:21:07 +000070 DECREF(list);
71 return NULL;
72 }
73 }
74 }
75
76 return list;
77}
78
79
80static object *
81strop_splitfields(self, args)
82 object *self; /* Not used */
83 object *args;
84{
Guido van Rossum572d2d91993-11-05 10:14:49 +000085 int len, n, i, j, err;
Guido van Rossume270b431992-09-03 20:21:07 +000086 char *s, *sub;
Guido van Rossume270b431992-09-03 20:21:07 +000087 object *list, *item;
88
89 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
90 return NULL;
91 if (n == 0) {
92 err_setstr(ValueError, "empty separator");
93 return NULL;
94 }
95
96 list = newlistobject(0);
97 if (list == NULL)
98 return NULL;
99
100 i = j = 0;
101 while (i+n <= len) {
102 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
103 item = newsizedstringobject(s+j, (int)(i-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +0000104 if (item == NULL)
105 goto fail;
106 err = addlistitem(list, item);
107 DECREF(item);
108 if (err < 0)
109 goto fail;
Guido van Rossume270b431992-09-03 20:21:07 +0000110 i = j = i + n;
111 }
112 else
113 i++;
114 }
115 item = newsizedstringobject(s+j, (int)(len-j));
Guido van Rossum572d2d91993-11-05 10:14:49 +0000116 if (item == NULL)
117 goto fail;
118 err = addlistitem(list, item);
119 DECREF(item);
120 if (err < 0)
121 goto fail;
Guido van Rossume270b431992-09-03 20:21:07 +0000122
123 return list;
Guido van Rossum572d2d91993-11-05 10:14:49 +0000124
125 fail:
126 DECREF(list);
127 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000128}
129
130
131static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000132strop_joinfields(self, args)
133 object *self; /* Not used */
134 object *args;
135{
136 object *seq, *item, *res;
137 object * (*getitem) FPROTO((object *, int));
138 char *sep, *p;
139 int seplen, seqlen, reslen, itemlen, i;
140
141 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
142 return NULL;
143 if (is_listobject(seq)) {
144 getitem = getlistitem;
145 seqlen = getlistsize(seq);
146 }
147 else if (is_tupleobject(seq)) {
148 getitem = gettupleitem;
149 seqlen = gettuplesize(seq);
150 }
151 else {
152 err_setstr(TypeError, "first argument must be list/tuple");
153 return NULL;
154 }
155 reslen = 0;
156 for (i = 0; i < seqlen; i++) {
157 item = getitem(seq, i);
158 if (!is_stringobject(item)) {
159 err_setstr(TypeError,
160 "first argument must be list/tuple of strings");
161 return NULL;
162 }
163 if (i > 0)
164 reslen = reslen + seplen;
165 reslen = reslen + getstringsize(item);
166 }
167 if (seqlen == 1) {
168 /* Optimization if there's only one item */
169 item = getitem(seq, 0);
170 INCREF(item);
171 return item;
172 }
173 res = newsizedstringobject((char *)NULL, reslen);
174 if (res == NULL)
175 return NULL;
176 p = getstringvalue(res);
177 for (i = 0; i < seqlen; i++) {
178 item = getitem(seq, i);
179 if (i > 0) {
180 memcpy(p, sep, seplen);
181 p += seplen;
182 }
183 itemlen = getstringsize(item);
184 memcpy(p, getstringvalue(item), itemlen);
185 p += itemlen;
186 }
187 if (p != getstringvalue(res) + reslen) {
188 err_setstr(SystemError, "strop.joinfields: assertion failed");
189 return NULL;
190 }
191 return res;
192}
193
194
195static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000196strop_find(self, args)
Guido van Rossume270b431992-09-03 20:21:07 +0000197 object *self; /* Not used */
198 object *args;
199{
200 char *s, *sub;
201 int len, n, i;
202
203 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
Guido van Rossumee9012f1993-10-26 15:23:55 +0000204 if (i < 0)
205 i += len;
Guido van Rossum602099a1994-09-14 13:32:22 +0000206 if (i < 0)
207 i = 0;
Guido van Rossume270b431992-09-03 20:21:07 +0000208 }
209 else {
210 err_clear();
211 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
212 return NULL;
213 i = 0;
214 }
215
216 if (n == 0)
217 return newintobject((long)i);
218
219 len -= n;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000220 for (; i <= len; ++i)
221 if (s[i] == sub[0] &&
222 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
223 return newintobject((long)i);
224
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000225 return newintobject(-1L);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000226}
227
228
229static object *
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000230strop_rfind(self, args)
Guido van Rossumee9012f1993-10-26 15:23:55 +0000231 object *self; /* Not used */
232 object *args;
233{
234 char *s, *sub;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000235 int len, n, i, j;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000236
237 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
238 if (i < 0)
239 i += len;
Guido van Rossum602099a1994-09-14 13:32:22 +0000240 if (i < 0)
241 i = 0;
Guido van Rossume270b431992-09-03 20:21:07 +0000242 }
Guido van Rossumee9012f1993-10-26 15:23:55 +0000243 else {
244 err_clear();
245 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
246 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000247 i = 0;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000248 }
249
250 if (n == 0)
Guido van Rossumc65a5251994-08-05 13:44:50 +0000251 return newintobject((long)len);
Guido van Rossumee9012f1993-10-26 15:23:55 +0000252
Guido van Rossumb6775db1994-08-01 11:34:53 +0000253 for (j = len-n; j >= i; --j)
254 if (s[j] == sub[0] &&
255 (n == 1 || strncmp(&s[j+1], &sub[1], n-1) == 0))
256 return newintobject((long)j);
Guido van Rossume270b431992-09-03 20:21:07 +0000257
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000258 return newintobject(-1L);
Guido van Rossume270b431992-09-03 20:21:07 +0000259}
260
261
262static object *
263strop_strip(self, args)
264 object *self; /* Not used */
265 object *args;
266{
267 char *s;
268 int len, i, j;
Guido van Rossume270b431992-09-03 20:21:07 +0000269
270 if (!getargs(args, "s#", &s, &len))
271 return NULL;
272
273 i = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000274 while (i < len && isspace(Py_CHARMASK(s[i]))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000275 i++;
276 }
277
278 j = len;
279 do {
280 j--;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000281 } while (j >= i && isspace(Py_CHARMASK(s[i])));
Guido van Rossume270b431992-09-03 20:21:07 +0000282 j++;
283
284 if (i == 0 && j == len) {
285 INCREF(args);
286 return args;
287 }
288 else
289 return newsizedstringobject(s+i, j-i);
290}
291
292
Guido van Rossum5c850621992-09-11 23:55:51 +0000293static object *
294strop_lower(self, args)
295 object *self; /* Not used */
296 object *args;
297{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000298 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000299 int i, n;
300 object *new;
301 int changed;
302
303 if (!getargs(args, "s#", &s, &n))
304 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000305 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000306 if (new == NULL)
307 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000308 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000309 changed = 0;
310 for (i = 0; i < n; i++) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000311 int c = Py_CHARMASK(*s++);
Guido van Rossum5c850621992-09-11 23:55:51 +0000312 if (isupper(c)) {
313 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000314 *s_new = tolower(c);
315 } else
316 *s_new = c;
317 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000318 }
319 if (!changed) {
320 DECREF(new);
321 INCREF(args);
322 return args;
323 }
324 return new;
325}
326
327
328static object *
329strop_upper(self, args)
330 object *self; /* Not used */
331 object *args;
332{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000333 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000334 int i, n;
335 object *new;
336 int changed;
337
338 if (!getargs(args, "s#", &s, &n))
339 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000340 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000341 if (new == NULL)
342 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000343 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000344 changed = 0;
345 for (i = 0; i < n; i++) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000346 int c = Py_CHARMASK(*s++);
Guido van Rossum5c850621992-09-11 23:55:51 +0000347 if (islower(c)) {
348 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000349 *s_new = toupper(c);
350 } else
351 *s_new = c;
352 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000353 }
354 if (!changed) {
355 DECREF(new);
356 INCREF(args);
357 return args;
358 }
359 return new;
360}
361
362
363static object *
364strop_swapcase(self, args)
365 object *self; /* Not used */
366 object *args;
367{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000368 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000369 int i, n;
370 object *new;
371 int changed;
372
373 if (!getargs(args, "s#", &s, &n))
374 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000375 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000376 if (new == NULL)
377 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000378 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000379 changed = 0;
380 for (i = 0; i < n; i++) {
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000381 int c = Py_CHARMASK(*s++);
Guido van Rossum5c850621992-09-11 23:55:51 +0000382 if (islower(c)) {
383 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000384 *s_new = toupper(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000385 }
386 else if (isupper(c)) {
387 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000388 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000389 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000390 else
391 *s_new = c;
392 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000393 }
394 if (!changed) {
395 DECREF(new);
396 INCREF(args);
397 return args;
398 }
399 return new;
400}
401
402
Guido van Rossumb6775db1994-08-01 11:34:53 +0000403static object *
404strop_atoi(self, args)
405 object *self; /* Not used */
406 object *args;
407{
408 extern long mystrtol PROTO((const char *, char **, int));
409 extern unsigned long mystrtoul PROTO((const char *, char **, int));
410 char *s, *end;
411 int base = 10;
412 long x;
413
414 if (args != NULL && is_tupleobject(args)) {
415 if (!getargs(args, "(si)", &s, &base))
416 return NULL;
417 if (base != 0 && base < 2 || base > 36) {
418 err_setstr(ValueError, "invalid base for atoi()");
419 return NULL;
420 }
421 }
422 else if (!getargs(args, "s", &s))
423 return NULL;
424 errno = 0;
425 if (base == 0 && s[0] == '0')
426 x = (long) mystrtoul(s, &end, base);
427 else
428 x = mystrtol(s, &end, base);
429 if (*end != '\0') {
430 err_setstr(ValueError, "invalid literal for atoi()");
431 return NULL;
432 }
433 else if (errno != 0) {
434 err_setstr(OverflowError, "atoi() literal too large");
435 return NULL;
436 }
437 return newintobject(x);
438}
439
440
441static object *
442strop_atol(self, args)
443 object *self; /* Not used */
444 object *args;
445{
446 char *s, *end;
447 int base = 10;
448 object *x;
449
450 if (args != NULL && is_tupleobject(args)) {
451 if (!getargs(args, "(si)", &s, &base))
452 return NULL;
453 if (base != 0 && base < 2 || base > 36) {
454 err_setstr(ValueError, "invalid base for atol()");
455 return NULL;
456 }
457 }
458 else if (!getargs(args, "s", &s))
459 return NULL;
460 x = long_escan(s, &end, base);
461 if (x == NULL)
462 return NULL;
463 if (base == 0 && (*end == 'l' || *end == 'L'))
464 end++;
465 if (*end != '\0') {
466 err_setstr(ValueError, "invalid literal for atol()");
467 DECREF(x);
468 return NULL;
469 }
470 return x;
471}
472
473
474static object *
475strop_atof(self, args)
476 object *self; /* Not used */
477 object *args;
478{
479 extern double strtod PROTO((const char *, char **));
480 char *s, *end;
481 double x;
482
483 if (!getargs(args, "s", &s))
484 return NULL;
485 errno = 0;
486 x = strtod(s, &end);
487 if (*end != '\0') {
488 err_setstr(ValueError, "invalid literal for atof()");
489 return NULL;
490 }
491 else if (errno != 0) {
492 err_setstr(OverflowError, "atof() literal too large");
493 return NULL;
494 }
495 return newfloatobject(x);
496}
497
498
Guido van Rossume270b431992-09-03 20:21:07 +0000499/* List of functions defined in the module */
500
501static struct methodlist strop_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000502 {"atof", strop_atof},
503 {"atoi", strop_atoi},
504 {"atol", strop_atol},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000505 {"find", strop_find},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000506 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000507 {"lower", strop_lower},
Guido van Rossum5806a4f1994-08-17 13:15:46 +0000508 {"rfind", strop_rfind},
Guido van Rossume270b431992-09-03 20:21:07 +0000509 {"split", strop_split},
510 {"splitfields", strop_splitfields},
511 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000512 {"swapcase", strop_swapcase},
513 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000514 {NULL, NULL} /* sentinel */
515};
516
517
Guido van Rossume270b431992-09-03 20:21:07 +0000518void
519initstrop()
520{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000521 object *m, *d, *s;
522 char buf[256];
523 int c, n;
524 m = initmodule("strop", strop_methods);
525 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000526
527 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000528 n = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000529 for (c = 0; c < 256; c++) {
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000530 if (isspace(c))
531 buf[n++] = c;
532 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000533 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000534 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000535 dictinsert(d, "whitespace", s);
536 DECREF(s);
537 }
538 /* Create 'lowercase' object */
539 n = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000540 for (c = 0; c < 256; c++) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000541 if (islower(c))
542 buf[n++] = c;
543 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000544 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000545 if (s) {
546 dictinsert(d, "lowercase", s);
547 DECREF(s);
548 }
549
550 /* Create 'uppercase' object */
551 n = 0;
Guido van Rossum7f7f2741995-02-10 17:01:56 +0000552 for (c = 0; c < 256; c++) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000553 if (isupper(c))
554 buf[n++] = c;
555 }
556 s = newsizedstringobject(buf, n);
557 if (s) {
558 dictinsert(d, "uppercase", s);
559 DECREF(s);
560 }
561
562 if (err_occurred())
563 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000564}