blob: 477d14d6dc4a0c0c4b14a24bb85393478305f93f [file] [log] [blame]
Guido van Rossume270b431992-09-03 20:21:07 +00001/***********************************************************
Guido van Rossum9bfef441993-03-29 10:43:31 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, 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 Rossume270b431992-09-03 20:21:07 +000034
35static object *
36strop_split(self, args)
37 object *self; /* Not used */
38 object *args;
39{
40 int len, i, j;
41 char *s;
42 char c;
43 object *list, *item;
44
45 if (!getargs(args, "s#", &s, &len))
46 return NULL;
47 list = newlistobject(0);
48 if (list == NULL)
49 return NULL;
50
51 i = 0;
52 while (i < len) {
53 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000054 ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000055 i = i+1;
56 }
57 j = i;
58 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000059 !((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000060 i = i+1;
61 }
62 if (j < i) {
63 item = newsizedstringobject(s+j, (int)(i-j));
64 if (item == NULL || addlistitem(list, item) < 0) {
65 DECREF(list);
66 return NULL;
67 }
68 }
69 }
70
71 return list;
72}
73
74
75static object *
76strop_splitfields(self, args)
77 object *self; /* Not used */
78 object *args;
79{
80 int len, n, i, j;
81 char *s, *sub;
Guido van Rossume270b431992-09-03 20:21:07 +000082 object *list, *item;
83
84 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
85 return NULL;
86 if (n == 0) {
87 err_setstr(ValueError, "empty separator");
88 return NULL;
89 }
90
91 list = newlistobject(0);
92 if (list == NULL)
93 return NULL;
94
95 i = j = 0;
96 while (i+n <= len) {
97 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
98 item = newsizedstringobject(s+j, (int)(i-j));
99 if (item == NULL || addlistitem(list, item) < 0) {
100 DECREF(list);
101 return NULL;
102 }
103 i = j = i + n;
104 }
105 else
106 i++;
107 }
108 item = newsizedstringobject(s+j, (int)(len-j));
109 if (item == NULL || addlistitem(list, item) < 0) {
110 DECREF(list);
111 return NULL;
112 }
113
114 return list;
115}
116
117
118static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000119strop_joinfields(self, args)
120 object *self; /* Not used */
121 object *args;
122{
123 object *seq, *item, *res;
124 object * (*getitem) FPROTO((object *, int));
125 char *sep, *p;
126 int seplen, seqlen, reslen, itemlen, i;
127
128 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
129 return NULL;
130 if (is_listobject(seq)) {
131 getitem = getlistitem;
132 seqlen = getlistsize(seq);
133 }
134 else if (is_tupleobject(seq)) {
135 getitem = gettupleitem;
136 seqlen = gettuplesize(seq);
137 }
138 else {
139 err_setstr(TypeError, "first argument must be list/tuple");
140 return NULL;
141 }
142 reslen = 0;
143 for (i = 0; i < seqlen; i++) {
144 item = getitem(seq, i);
145 if (!is_stringobject(item)) {
146 err_setstr(TypeError,
147 "first argument must be list/tuple of strings");
148 return NULL;
149 }
150 if (i > 0)
151 reslen = reslen + seplen;
152 reslen = reslen + getstringsize(item);
153 }
154 if (seqlen == 1) {
155 /* Optimization if there's only one item */
156 item = getitem(seq, 0);
157 INCREF(item);
158 return item;
159 }
160 res = newsizedstringobject((char *)NULL, reslen);
161 if (res == NULL)
162 return NULL;
163 p = getstringvalue(res);
164 for (i = 0; i < seqlen; i++) {
165 item = getitem(seq, i);
166 if (i > 0) {
167 memcpy(p, sep, seplen);
168 p += seplen;
169 }
170 itemlen = getstringsize(item);
171 memcpy(p, getstringvalue(item), itemlen);
172 p += itemlen;
173 }
174 if (p != getstringvalue(res) + reslen) {
175 err_setstr(SystemError, "strop.joinfields: assertion failed");
176 return NULL;
177 }
178 return res;
179}
180
181
182static object *
Guido van Rossume270b431992-09-03 20:21:07 +0000183strop_index(self, args)
184 object *self; /* Not used */
185 object *args;
186{
187 char *s, *sub;
188 int len, n, i;
189
190 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
Guido van Rossumee9012f1993-10-26 15:23:55 +0000191 if (i < 0)
192 i += len;
Guido van Rossume270b431992-09-03 20:21:07 +0000193 if (i < 0 || i+n > len) {
194 err_setstr(ValueError, "start offset out of range");
195 return NULL;
196 }
197 }
198 else {
199 err_clear();
200 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
201 return NULL;
202 i = 0;
203 }
204
205 if (n == 0)
206 return newintobject((long)i);
207
208 len -= n;
Guido van Rossumee9012f1993-10-26 15:23:55 +0000209 for (; i <= len; ++i)
210 if (s[i] == sub[0] &&
211 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
212 return newintobject((long)i);
213
214 err_setstr(ValueError, "substring not found");
215 return NULL;
216}
217
218
219static object *
220strop_rindex(self, args)
221 object *self; /* Not used */
222 object *args;
223{
224 char *s, *sub;
225 int len, n, i;
226
227 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
228 if (i < 0)
229 i += len;
230 if (i < 0 || i+n > len) {
231 err_setstr(ValueError, "start offset out of range");
232 return NULL;
Guido van Rossume270b431992-09-03 20:21:07 +0000233 }
234 }
Guido van Rossumee9012f1993-10-26 15:23:55 +0000235 else {
236 err_clear();
237 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
238 return NULL;
239 i = len;
240 }
241
242 if (n == 0)
243 return newintobject((long)i);
244
245 for (i -= n; i >= 0; --i)
246 if (s[i] == sub[0] &&
247 (n == 1 || strncmp(&s[i+1], &sub[1], n-1) == 0))
248 return newintobject((long)i);
Guido van Rossume270b431992-09-03 20:21:07 +0000249
250 err_setstr(ValueError, "substring not found");
251 return NULL;
252}
253
254
255static object *
256strop_strip(self, args)
257 object *self; /* Not used */
258 object *args;
259{
260 char *s;
261 int len, i, j;
262 char c;
263
264 if (!getargs(args, "s#", &s, &len))
265 return NULL;
266
267 i = 0;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000268 while (i < len && ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000269 i++;
270 }
271
272 j = len;
273 do {
274 j--;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000275 } while (j >= i && ((c = s[j]), isspace(c)));
Guido van Rossume270b431992-09-03 20:21:07 +0000276 j++;
277
278 if (i == 0 && j == len) {
279 INCREF(args);
280 return args;
281 }
282 else
283 return newsizedstringobject(s+i, j-i);
284}
285
286
Guido van Rossum5c850621992-09-11 23:55:51 +0000287static object *
288strop_lower(self, args)
289 object *self; /* Not used */
290 object *args;
291{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000292 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000293 int i, n;
294 object *new;
295 int changed;
296
297 if (!getargs(args, "s#", &s, &n))
298 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000299 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000300 if (new == NULL)
301 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000302 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000303 changed = 0;
304 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000305 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000306 if (isupper(c)) {
307 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000308 *s_new = tolower(c);
309 } else
310 *s_new = c;
311 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000312 }
313 if (!changed) {
314 DECREF(new);
315 INCREF(args);
316 return args;
317 }
318 return new;
319}
320
321
322static object *
323strop_upper(self, args)
324 object *self; /* Not used */
325 object *args;
326{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000327 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000328 int i, n;
329 object *new;
330 int changed;
331
332 if (!getargs(args, "s#", &s, &n))
333 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000334 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000335 if (new == NULL)
336 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000337 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000338 changed = 0;
339 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000340 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000341 if (islower(c)) {
342 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000343 *s_new = toupper(c);
344 } else
345 *s_new = c;
346 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000347 }
348 if (!changed) {
349 DECREF(new);
350 INCREF(args);
351 return args;
352 }
353 return new;
354}
355
356
357static object *
358strop_swapcase(self, args)
359 object *self; /* Not used */
360 object *args;
361{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000362 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000363 int i, n;
364 object *new;
365 int changed;
366
367 if (!getargs(args, "s#", &s, &n))
368 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000369 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000370 if (new == NULL)
371 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000372 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000373 changed = 0;
374 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000375 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000376 if (islower(c)) {
377 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000378 *s_new = toupper(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000379 }
380 else if (isupper(c)) {
381 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000382 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000383 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000384 else
385 *s_new = c;
386 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000387 }
388 if (!changed) {
389 DECREF(new);
390 INCREF(args);
391 return args;
392 }
393 return new;
394}
395
396
Guido van Rossume270b431992-09-03 20:21:07 +0000397/* List of functions defined in the module */
398
399static struct methodlist strop_methods[] = {
400 {"index", strop_index},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000401 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000402 {"lower", strop_lower},
Guido van Rossumee9012f1993-10-26 15:23:55 +0000403 {"rindex", strop_rindex},
Guido van Rossume270b431992-09-03 20:21:07 +0000404 {"split", strop_split},
405 {"splitfields", strop_splitfields},
406 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000407 {"swapcase", strop_swapcase},
408 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000409 {NULL, NULL} /* sentinel */
410};
411
412
Guido van Rossume270b431992-09-03 20:21:07 +0000413void
414initstrop()
415{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000416 object *m, *d, *s;
417 char buf[256];
418 int c, n;
419 m = initmodule("strop", strop_methods);
420 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000421
422 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000423 n = 0;
424 for (c = 1; c < 256; c++) {
425 if (isspace(c))
426 buf[n++] = c;
427 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000428 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000429 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000430 dictinsert(d, "whitespace", s);
431 DECREF(s);
432 }
433 /* Create 'lowercase' object */
434 n = 0;
435 for (c = 1; c < 256; c++) {
436 if (islower(c))
437 buf[n++] = c;
438 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000439 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000440 if (s) {
441 dictinsert(d, "lowercase", s);
442 DECREF(s);
443 }
444
445 /* Create 'uppercase' object */
446 n = 0;
447 for (c = 1; c < 256; c++) {
448 if (isupper(c))
449 buf[n++] = c;
450 }
451 s = newsizedstringobject(buf, n);
452 if (s) {
453 dictinsert(d, "uppercase", s);
454 DECREF(s);
455 }
456
457 if (err_occurred())
458 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000459}