blob: f00cfc78b507894153dd81cb2f8bec960613f574 [file] [log] [blame]
Guido van Rossume270b431992-09-03 20:21:07 +00001/***********************************************************
2Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
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
30
31static object *
32strop_split(self, args)
33 object *self; /* Not used */
34 object *args;
35{
36 int len, i, j;
37 char *s;
38 char c;
39 object *list, *item;
40
41 if (!getargs(args, "s#", &s, &len))
42 return NULL;
43 list = newlistobject(0);
44 if (list == NULL)
45 return NULL;
46
47 i = 0;
48 while (i < len) {
49 while (i < len &&
50 ((c = s[i]) == ' ' || c == '\t' || c == '\n')) {
51 i = i+1;
52 }
53 j = i;
54 while (i < len &&
55 !((c = s[i]) == ' ' || c == '\t' || c == '\n')) {
56 i = i+1;
57 }
58 if (j < i) {
59 item = newsizedstringobject(s+j, (int)(i-j));
60 if (item == NULL || addlistitem(list, item) < 0) {
61 DECREF(list);
62 return NULL;
63 }
64 }
65 }
66
67 return list;
68}
69
70
71static object *
72strop_splitfields(self, args)
73 object *self; /* Not used */
74 object *args;
75{
76 int len, n, i, j;
77 char *s, *sub;
78 char c;
79 object *list, *item;
80
81 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
82 return NULL;
83 if (n == 0) {
84 err_setstr(ValueError, "empty separator");
85 return NULL;
86 }
87
88 list = newlistobject(0);
89 if (list == NULL)
90 return NULL;
91
92 i = j = 0;
93 while (i+n <= len) {
94 if (s[i] == sub[0] && (n == 1 || strncmp(s+i, sub, n) == 0)) {
95 item = newsizedstringobject(s+j, (int)(i-j));
96 if (item == NULL || addlistitem(list, item) < 0) {
97 DECREF(list);
98 return NULL;
99 }
100 i = j = i + n;
101 }
102 else
103 i++;
104 }
105 item = newsizedstringobject(s+j, (int)(len-j));
106 if (item == NULL || addlistitem(list, item) < 0) {
107 DECREF(list);
108 return NULL;
109 }
110
111 return list;
112}
113
114
115static object *
Guido van Rossumc89705d1992-11-26 08:54:07 +0000116strop_joinfields(self, args)
117 object *self; /* Not used */
118 object *args;
119{
120 object *seq, *item, *res;
121 object * (*getitem) FPROTO((object *, int));
122 char *sep, *p;
123 int seplen, seqlen, reslen, itemlen, i;
124
125 if (!getargs(args, "(Os#)", &seq, &sep, &seplen))
126 return NULL;
127 if (is_listobject(seq)) {
128 getitem = getlistitem;
129 seqlen = getlistsize(seq);
130 }
131 else if (is_tupleobject(seq)) {
132 getitem = gettupleitem;
133 seqlen = gettuplesize(seq);
134 }
135 else {
136 err_setstr(TypeError, "first argument must be list/tuple");
137 return NULL;
138 }
139 reslen = 0;
140 for (i = 0; i < seqlen; i++) {
141 item = getitem(seq, i);
142 if (!is_stringobject(item)) {
143 err_setstr(TypeError,
144 "first argument must be list/tuple of strings");
145 return NULL;
146 }
147 if (i > 0)
148 reslen = reslen + seplen;
149 reslen = reslen + getstringsize(item);
150 }
151 if (seqlen == 1) {
152 /* Optimization if there's only one item */
153 item = getitem(seq, 0);
154 INCREF(item);
155 return item;
156 }
157 res = newsizedstringobject((char *)NULL, reslen);
158 if (res == NULL)
159 return NULL;
160 p = getstringvalue(res);
161 for (i = 0; i < seqlen; i++) {
162 item = getitem(seq, i);
163 if (i > 0) {
164 memcpy(p, sep, seplen);
165 p += seplen;
166 }
167 itemlen = getstringsize(item);
168 memcpy(p, getstringvalue(item), itemlen);
169 p += itemlen;
170 }
171 if (p != getstringvalue(res) + reslen) {
172 err_setstr(SystemError, "strop.joinfields: assertion failed");
173 return NULL;
174 }
175 return res;
176}
177
178
179static object *
Guido van Rossume270b431992-09-03 20:21:07 +0000180strop_index(self, args)
181 object *self; /* Not used */
182 object *args;
183{
184 char *s, *sub;
185 int len, n, i;
186
187 if (getargs(args, "(s#s#i)", &s, &len, &sub, &n, &i)) {
188 if (i < 0 || i+n > len) {
189 err_setstr(ValueError, "start offset out of range");
190 return NULL;
191 }
192 }
193 else {
194 err_clear();
195 if (!getargs(args, "(s#s#)", &s, &len, &sub, &n))
196 return NULL;
197 i = 0;
198 }
199
200 if (n == 0)
201 return newintobject((long)i);
202
203 len -= n;
204 for (; i <= len; i++) {
205 if (s[i] == sub[0]) {
206 if (n == 1 || strncmp(s+i, sub, n) == 0)
207 return newintobject((long)i);
208 }
209 }
210
211 err_setstr(ValueError, "substring not found");
212 return NULL;
213}
214
215
216static object *
217strop_strip(self, args)
218 object *self; /* Not used */
219 object *args;
220{
221 char *s;
222 int len, i, j;
223 char c;
224
225 if (!getargs(args, "s#", &s, &len))
226 return NULL;
227
228 i = 0;
229 while (i < len && ((c = s[i]) == ' ' || c == '\t' || c == '\n')) {
230 i++;
231 }
232
233 j = len;
234 do {
235 j--;
236 } while (j >= i && ((c = s[j]) == ' ' || c == '\t' || c == '\n'));
237 j++;
238
239 if (i == 0 && j == len) {
240 INCREF(args);
241 return args;
242 }
243 else
244 return newsizedstringobject(s+i, j-i);
245}
246
247
Guido van Rossum5c850621992-09-11 23:55:51 +0000248#include <ctype.h>
249
250static 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{
373 initmodule("strop", strop_methods);
374}