blob: 3a941a8daf1cda763acb84b7cdfde3aa2bdf8882 [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;
82 char c;
83 object *list, *item;
84
85 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
86 return NULL;
87 if (n == 0) {
88 err_setstr(ValueError, "empty separator");
89 return NULL;
90 }
91
92 list = newlistobject(0);
93 if (list == NULL)
94 return NULL;
95
96 i = j = 0;
97 while (i+n <= len) {
98 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
99 item = newsizedstringobject(s+j, (int)(i-j));
100 if (item == NULL || addlistitem(list, item) < 0) {
101 DECREF(list);
102 return NULL;
103 }
104 i = j = i + n;
105 }
106 else
107 i++;
108 }
109 item = newsizedstringobject(s+j, (int)(len-j));
110 if (item == NULL || addlistitem(list, item) < 0) {
111 DECREF(list);
112 return NULL;
113 }
114
115 return list;
116}
117
118
119static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000120strop_joinfields(self, args)
121 object *self; /* Not used */
122 object *args;
123{
124 object *seq, *item, *res;
125 object * (*getitem) FPROTO((object *, int));
126 char *sep, *p;
127 int seplen, seqlen, reslen, itemlen, i;
128
129 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
130 return NULL;
131 if (is_listobject(seq)) {
132 getitem = getlistitem;
133 seqlen = getlistsize(seq);
134 }
135 else if (is_tupleobject(seq)) {
136 getitem = gettupleitem;
137 seqlen = gettuplesize(seq);
138 }
139 else {
140 err_setstr(TypeError, "first argument must be list/tuple");
141 return NULL;
142 }
143 reslen = 0;
144 for (i = 0; i < seqlen; i++) {
145 item = getitem(seq, i);
146 if (!is_stringobject(item)) {
147 err_setstr(TypeError,
148 "first argument must be list/tuple of strings");
149 return NULL;
150 }
151 if (i > 0)
152 reslen = reslen + seplen;
153 reslen = reslen + getstringsize(item);
154 }
155 if (seqlen == 1) {
156 /* Optimization if there's only one item */
157 item = getitem(seq, 0);
158 INCREF(item);
159 return item;
160 }
161 res = newsizedstringobject((char *)NULL, reslen);
162 if (res == NULL)
163 return NULL;
164 p = getstringvalue(res);
165 for (i = 0; i < seqlen; i++) {
166 item = getitem(seq, i);
167 if (i > 0) {
168 memcpy(p, sep, seplen);
169 p += seplen;
170 }
171 itemlen = getstringsize(item);
172 memcpy(p, getstringvalue(item), itemlen);
173 p += itemlen;
174 }
175 if (p != getstringvalue(res) + reslen) {
176 err_setstr(SystemError, "strop.joinfields: assertion failed");
177 return NULL;
178 }
179 return res;
180}
181
182
183static object *
Guido van Rossume270b431992-09-03 20:21:07 +0000184strop_index(self, args)
185 object *self; /* Not used */
186 object *args;
187{
188 char *s, *sub;
189 int len, n, i;
190
191 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
192 if (i < 0 || i+n > len) {
193 err_setstr(ValueError, "start offset out of range");
194 return NULL;
195 }
196 }
197 else {
198 err_clear();
199 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
200 return NULL;
201 i = 0;
202 }
203
204 if (n == 0)
205 return newintobject((long)i);
206
207 len -= n;
208 for (; i <= len; i++) {
209 if (s[i] == sub[0]) {
210 if (n == 1 || strncmp(s+i, sub, n) == 0)
211 return newintobject((long)i);
212 }
213 }
214
215 err_setstr(ValueError, "substring not found");
216 return NULL;
217}
218
219
220static object *
221strop_strip(self, args)
222 object *self; /* Not used */
223 object *args;
224{
225 char *s;
226 int len, i, j;
227 char c;
228
229 if (!getargs(args, "s#", &s, &len))
230 return NULL;
231
232 i = 0;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000233 while (i < len && ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000234 i++;
235 }
236
237 j = len;
238 do {
239 j--;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000240 } while (j >= i && ((c = s[j]), isspace(c)));
Guido van Rossume270b431992-09-03 20:21:07 +0000241 j++;
242
243 if (i == 0 && j == len) {
244 INCREF(args);
245 return args;
246 }
247 else
248 return newsizedstringobject(s+i, j-i);
249}
250
251
Guido van Rossum5c850621992-09-11 23:55:51 +0000252static object *
253strop_lower(self, args)
254 object *self; /* Not used */
255 object *args;
256{
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000257 char *s, *s_new;
Guido van Rossum5c850621992-09-11 23:55:51 +0000258 int i, n;
259 object *new;
260 int changed;
261
262 if (!getargs(args, "s#", &s, &n))
263 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000264 new = newsizedstringobject(NULL, n);
Guido van Rossum5c850621992-09-11 23:55:51 +0000265 if (new == NULL)
266 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000267 s_new = getstringvalue(new);
Guido van Rossum5c850621992-09-11 23:55:51 +0000268 changed = 0;
269 for (i = 0; i < n; i++) {
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000270 char c = *s++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000271 if (isupper(c)) {
272 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000273 *s_new = tolower(c);
274 } else
275 *s_new = c;
276 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000277 }
278 if (!changed) {
279 DECREF(new);
280 INCREF(args);
281 return args;
282 }
283 return new;
284}
285
286
287static object *
288strop_upper(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 (islower(c)) {
307 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000308 *s_new = toupper(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_swapcase(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);
Guido van Rossum5c850621992-09-11 23:55:51 +0000344 }
345 else if (isupper(c)) {
346 changed = 1;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000347 *s_new = tolower(c);
Guido van Rossum5c850621992-09-11 23:55:51 +0000348 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000349 else
350 *s_new = c;
351 s_new++;
Guido van Rossum5c850621992-09-11 23:55:51 +0000352 }
353 if (!changed) {
354 DECREF(new);
355 INCREF(args);
356 return args;
357 }
358 return new;
359}
360
361
Guido van Rossume270b431992-09-03 20:21:07 +0000362/* List of functions defined in the module */
363
364static struct methodlist strop_methods[] = {
365 {"index", strop_index},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000366 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000367 {"lower", strop_lower},
Guido van Rossume270b431992-09-03 20:21:07 +0000368 {"split", strop_split},
369 {"splitfields", strop_splitfields},
370 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000371 {"swapcase", strop_swapcase},
372 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000373 {NULL, NULL} /* sentinel */
374};
375
376
Guido van Rossume270b431992-09-03 20:21:07 +0000377void
378initstrop()
379{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000380 object *m, *d, *s;
381 char buf[256];
382 int c, n;
383 m = initmodule("strop", strop_methods);
384 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000385
386 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000387 n = 0;
388 for (c = 1; c < 256; c++) {
389 if (isspace(c))
390 buf[n++] = c;
391 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000392 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000393 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000394 dictinsert(d, "whitespace", s);
395 DECREF(s);
396 }
397 /* Create 'lowercase' object */
398 n = 0;
399 for (c = 1; c < 256; c++) {
400 if (islower(c))
401 buf[n++] = c;
402 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000403 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000404 if (s) {
405 dictinsert(d, "lowercase", s);
406 DECREF(s);
407 }
408
409 /* Create 'uppercase' object */
410 n = 0;
411 for (c = 1; c < 256; c++) {
412 if (isupper(c))
413 buf[n++] = c;
414 }
415 s = newsizedstringobject(buf, n);
416 if (s) {
417 dictinsert(d, "uppercase", s);
418 DECREF(s);
419 }
420
421 if (err_occurred())
422 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000423}