blob: 6fc2719c6939de1c63e1289349a3eb7c23f305d5 [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>
31
Guido van Rossume270b431992-09-03 20:21:07 +000032
33static object *
34strop_split(self, args)
35 object *self; /* Not used */
36 object *args;
37{
38 int len, i, j;
39 char *s;
40 char c;
41 object *list, *item;
42
43 if (!getargs(args, "s#", &s, &len))
44 return NULL;
45 list = newlistobject(0);
46 if (list == NULL)
47 return NULL;
48
49 i = 0;
50 while (i < len) {
51 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000052 ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000053 i = i+1;
54 }
55 j = i;
56 while (i < len &&
Guido van Rossumd05eb8b1993-07-08 11:12:36 +000057 !((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +000058 i = i+1;
59 }
60 if (j < i) {
61 item = newsizedstringobject(s+j, (int)(i-j));
62 if (item == NULL || addlistitem(list, item) < 0) {
63 DECREF(list);
64 return NULL;
65 }
66 }
67 }
68
69 return list;
70}
71
72
73static object *
74strop_splitfields(self, args)
75 object *self; /* Not used */
76 object *args;
77{
78 int len, n, i, j;
79 char *s, *sub;
80 char c;
81 object *list, *item;
82
83 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
84 return NULL;
85 if (n == 0) {
86 err_setstr(ValueError, "empty separator");
87 return NULL;
88 }
89
90 list = newlistobject(0);
91 if (list == NULL)
92 return NULL;
93
94 i = j = 0;
95 while (i+n <= len) {
96 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
97 item = newsizedstringobject(s+j, (int)(i-j));
98 if (item == NULL || addlistitem(list, item) < 0) {
99 DECREF(list);
100 return NULL;
101 }
102 i = j = i + n;
103 }
104 else
105 i++;
106 }
107 item = newsizedstringobject(s+j, (int)(len-j));
108 if (item == NULL || addlistitem(list, item) < 0) {
109 DECREF(list);
110 return NULL;
111 }
112
113 return list;
114}
115
116
117static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000118strop_joinfields(self, args)
119 object *self; /* Not used */
120 object *args;
121{
122 object *seq, *item, *res;
123 object * (*getitem) FPROTO((object *, int));
124 char *sep, *p;
125 int seplen, seqlen, reslen, itemlen, i;
126
127 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
128 return NULL;
129 if (is_listobject(seq)) {
130 getitem = getlistitem;
131 seqlen = getlistsize(seq);
132 }
133 else if (is_tupleobject(seq)) {
134 getitem = gettupleitem;
135 seqlen = gettuplesize(seq);
136 }
137 else {
138 err_setstr(TypeError, "first argument must be list/tuple");
139 return NULL;
140 }
141 reslen = 0;
142 for (i = 0; i < seqlen; i++) {
143 item = getitem(seq, i);
144 if (!is_stringobject(item)) {
145 err_setstr(TypeError,
146 "first argument must be list/tuple of strings");
147 return NULL;
148 }
149 if (i > 0)
150 reslen = reslen + seplen;
151 reslen = reslen + getstringsize(item);
152 }
153 if (seqlen == 1) {
154 /* Optimization if there's only one item */
155 item = getitem(seq, 0);
156 INCREF(item);
157 return item;
158 }
159 res = newsizedstringobject((char *)NULL, reslen);
160 if (res == NULL)
161 return NULL;
162 p = getstringvalue(res);
163 for (i = 0; i < seqlen; i++) {
164 item = getitem(seq, i);
165 if (i > 0) {
166 memcpy(p, sep, seplen);
167 p += seplen;
168 }
169 itemlen = getstringsize(item);
170 memcpy(p, getstringvalue(item), itemlen);
171 p += itemlen;
172 }
173 if (p != getstringvalue(res) + reslen) {
174 err_setstr(SystemError, "strop.joinfields: assertion failed");
175 return NULL;
176 }
177 return res;
178}
179
180
181static object *
Guido van Rossume270b431992-09-03 20:21:07 +0000182strop_index(self, args)
183 object *self; /* Not used */
184 object *args;
185{
186 char *s, *sub;
187 int len, n, i;
188
189 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
190 if (i < 0 || i+n > len) {
191 err_setstr(ValueError, "start offset out of range");
192 return NULL;
193 }
194 }
195 else {
196 err_clear();
197 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
198 return NULL;
199 i = 0;
200 }
201
202 if (n == 0)
203 return newintobject((long)i);
204
205 len -= n;
206 for (; i <= len; i++) {
207 if (s[i] == sub[0]) {
208 if (n == 1 || strncmp(s+i, sub, n) == 0)
209 return newintobject((long)i);
210 }
211 }
212
213 err_setstr(ValueError, "substring not found");
214 return NULL;
215}
216
217
218static object *
219strop_strip(self, args)
220 object *self; /* Not used */
221 object *args;
222{
223 char *s;
224 int len, i, j;
225 char c;
226
227 if (!getargs(args, "s#", &s, &len))
228 return NULL;
229
230 i = 0;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000231 while (i < len && ((c = s[i]), isspace(c))) {
Guido van Rossume270b431992-09-03 20:21:07 +0000232 i++;
233 }
234
235 j = len;
236 do {
237 j--;
Guido van Rossumd05eb8b1993-07-08 11:12:36 +0000238 } while (j >= i && ((c = s[j]), isspace(c)));
Guido van Rossume270b431992-09-03 20:21:07 +0000239 j++;
240
241 if (i == 0 && j == len) {
242 INCREF(args);
243 return args;
244 }
245 else
246 return newsizedstringobject(s+i, j-i);
247}
248
249
Guido van Rossum5c850621992-09-11 23:55:51 +0000250static object *
251strop_lower(self, args)
252 object *self; /* Not used */
253 object *args;
254{
255 char *s;
256 int i, n;
257 object *new;
258 int changed;
259
260 if (!getargs(args, "s#", &s, &n))
261 return NULL;
262 new = newsizedstringobject(s, n);
263 if (new == NULL)
264 return NULL;
265 s = getstringvalue(new);
266 changed = 0;
267 for (i = 0; i < n; i++) {
268 char c = s[i];
269 if (isupper(c)) {
270 changed = 1;
271 s[i] = tolower(c);
272 }
273 }
274 if (!changed) {
275 DECREF(new);
276 INCREF(args);
277 return args;
278 }
279 return new;
280}
281
282
283static object *
284strop_upper(self, args)
285 object *self; /* Not used */
286 object *args;
287{
288 char *s;
289 int i, n;
290 object *new;
291 int changed;
292
293 if (!getargs(args, "s#", &s, &n))
294 return NULL;
295 new = newsizedstringobject(s, n);
296 if (new == NULL)
297 return NULL;
298 s = getstringvalue(new);
299 changed = 0;
300 for (i = 0; i < n; i++) {
301 char c = s[i];
302 if (islower(c)) {
303 changed = 1;
304 s[i] = toupper(c);
305 }
306 }
307 if (!changed) {
308 DECREF(new);
309 INCREF(args);
310 return args;
311 }
312 return new;
313}
314
315
316static object *
317strop_swapcase(self, args)
318 object *self; /* Not used */
319 object *args;
320{
321 char *s;
322 int i, n;
323 object *new;
324 int changed;
325
326 if (!getargs(args, "s#", &s, &n))
327 return NULL;
328 new = newsizedstringobject(s, n);
329 if (new == NULL)
330 return NULL;
331 s = getstringvalue(new);
332 changed = 0;
333 for (i = 0; i < n; i++) {
334 char c = s[i];
335 if (islower(c)) {
336 changed = 1;
337 s[i] = toupper(c);
338 }
339 else if (isupper(c)) {
340 changed = 1;
341 s[i] = tolower(c);
342 }
343 }
344 if (!changed) {
345 DECREF(new);
346 INCREF(args);
347 return args;
348 }
349 return new;
350}
351
352
Guido van Rossume270b431992-09-03 20:21:07 +0000353/* List of functions defined in the module */
354
355static struct methodlist strop_methods[] = {
356 {"index", strop_index},
Guido van Rossumc89705d1992-11-26 08:54:07 +0000357 {"joinfields", strop_joinfields},
Guido van Rossum5c850621992-09-11 23:55:51 +0000358 {"lower", strop_lower},
Guido van Rossume270b431992-09-03 20:21:07 +0000359 {"split", strop_split},
360 {"splitfields", strop_splitfields},
361 {"strip", strop_strip},
Guido van Rossum5c850621992-09-11 23:55:51 +0000362 {"swapcase", strop_swapcase},
363 {"upper", strop_upper},
Guido van Rossume270b431992-09-03 20:21:07 +0000364 {NULL, NULL} /* sentinel */
365};
366
367
368/* Initialization function for the module (*must* be called initstrop) */
369
370void
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);
378 n = 0;
379 for (c = 1; c < 256; c++) {
380 if (isspace(c))
381 buf[n++] = c;
382 }
383 s = newsizedstringobject(buf, n);
384 dictinsert(d, "whitespace", s);
385 DECREF(s);
Guido van Rossume270b431992-09-03 20:21:07 +0000386}