blob: 6686abf58f19c94c301b19bbb77452db4893296f [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{
257 char *s;
258 int i, n;
259 object *new;
260 int changed;
261
262 if (!getargs(args, "s#", &s, &n))
263 return NULL;
264 new = newsizedstringobject(s, n);
265 if (new == NULL)
266 return NULL;
267 s = getstringvalue(new);
268 changed = 0;
269 for (i = 0; i < n; i++) {
270 char c = s[i];
271 if (isupper(c)) {
272 changed = 1;
273 s[i] = tolower(c);
274 }
275 }
276 if (!changed) {
277 DECREF(new);
278 INCREF(args);
279 return args;
280 }
281 return new;
282}
283
284
285static object *
286strop_upper(self, args)
287 object *self; /* Not used */
288 object *args;
289{
290 char *s;
291 int i, n;
292 object *new;
293 int changed;
294
295 if (!getargs(args, "s#", &s, &n))
296 return NULL;
297 new = newsizedstringobject(s, n);
298 if (new == NULL)
299 return NULL;
300 s = getstringvalue(new);
301 changed = 0;
302 for (i = 0; i < n; i++) {
303 char c = s[i];
304 if (islower(c)) {
305 changed = 1;
306 s[i] = toupper(c);
307 }
308 }
309 if (!changed) {
310 DECREF(new);
311 INCREF(args);
312 return args;
313 }
314 return new;
315}
316
317
318static object *
319strop_swapcase(self, args)
320 object *self; /* Not used */
321 object *args;
322{
323 char *s;
324 int i, n;
325 object *new;
326 int changed;
327
328 if (!getargs(args, "s#", &s, &n))
329 return NULL;
330 new = newsizedstringobject(s, n);
331 if (new == NULL)
332 return NULL;
333 s = getstringvalue(new);
334 changed = 0;
335 for (i = 0; i < n; i++) {
336 char c = s[i];
337 if (islower(c)) {
338 changed = 1;
339 s[i] = toupper(c);
340 }
341 else if (isupper(c)) {
342 changed = 1;
343 s[i] = tolower(c);
344 }
345 }
346 if (!changed) {
347 DECREF(new);
348 INCREF(args);
349 return args;
350 }
351 return new;
352}
353
354
Guido van Rossume270b431992-09-03 20:21:07 +0000355/* List of functions defined in the module */
356
357static struct methodlist strop_methods[] = {
358 {"index", strop_index},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000359 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000360 {"lower", strop_lower},
Guido van Rossume270b431992-09-03 20:21:07 +0000361 {"split", strop_split},
362 {"splitfields", strop_splitfields},
363 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000364 {"swapcase", strop_swapcase},
365 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000366 {NULL, NULL} /* sentinel */
367};
368
369
Guido van Rossume270b431992-09-03 20:21:07 +0000370void
371initstrop()
372{
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000373 object *m, *d, *s;
374 char buf[256];
375 int c, n;
376 m = initmodule("strop", strop_methods);
377 d = getmoduledict(m);
Guido van Rossume22e6441993-07-09 10:51:31 +0000378
379 /* Create 'whitespace' object */
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000380 n = 0;
381 for (c = 1; c < 256; c++) {
382 if (isspace(c))
383 buf[n++] = c;
384 }
Sjoerd Mullenderd96ec441993-09-14 08:37:39 +0000385 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000386 if (s) {
Guido van Rossume22e6441993-07-09 10:51:31 +0000387 dictinsert(d, "whitespace", s);
388 DECREF(s);
389 }
390 /* Create 'lowercase' object */
391 n = 0;
392 for (c = 1; c < 256; c++) {
393 if (islower(c))
394 buf[n++] = c;
395 }
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000396 s = newsizedstringobject(buf, n);
Guido van Rossume22e6441993-07-09 10:51:31 +0000397 if (s) {
398 dictinsert(d, "lowercase", s);
399 DECREF(s);
400 }
401
402 /* Create 'uppercase' object */
403 n = 0;
404 for (c = 1; c < 256; c++) {
405 if (isupper(c))
406 buf[n++] = c;
407 }
408 s = newsizedstringobject(buf, n);
409 if (s) {
410 dictinsert(d, "uppercase", s);
411 DECREF(s);
412 }
413
414 if (err_occurred())
415 fatal("can't initialize module strop");
Guido van Rossume270b431992-09-03 20:21:07 +0000416}