|
6
|
1 /* String object implementation */
|
|
|
2
|
|
|
3 #include <stdio.h>
|
|
|
4
|
|
|
5 #include "PROTO.h"
|
|
|
6 #include "object.h"
|
|
|
7 #include "stringobject.h"
|
|
|
8 #include "intobject.h"
|
|
|
9 #include "objimpl.h"
|
|
|
10
|
|
|
11 object *
|
|
|
12 newsizedstringobject(str, size)
|
|
|
13 char *str;
|
|
|
14 int size;
|
|
|
15 {
|
|
|
16 register stringobject *op = (stringobject *)
|
|
|
17 malloc(sizeof(stringobject) + size * sizeof(char));
|
|
|
18 if (op == NULL) {
|
|
|
19 errno = ENOMEM;
|
|
|
20 }
|
|
|
21 else {
|
|
|
22 NEWREF(op);
|
|
|
23 op->ob_type = &Stringtype;
|
|
|
24 op->ob_size = size;
|
|
|
25 if (str != NULL)
|
|
|
26 memcpy(op->ob_sval, str, size);
|
|
|
27 op->ob_sval[size] = '\0';
|
|
|
28 }
|
|
|
29 return (object *) op;
|
|
|
30 }
|
|
|
31
|
|
|
32 object *
|
|
|
33 newstringobject(str)
|
|
|
34 char *str;
|
|
|
35 {
|
|
|
36 register unsigned int size = strlen(str);
|
|
|
37 register stringobject *op = (stringobject *)
|
|
|
38 malloc(sizeof(stringobject) + size * sizeof(char));
|
|
|
39 if (op == NULL) {
|
|
|
40 errno = ENOMEM;
|
|
|
41 }
|
|
|
42 else {
|
|
|
43 NEWREF(op);
|
|
|
44 op->ob_type = &Stringtype;
|
|
|
45 op->ob_size = size;
|
|
|
46 strcpy(op->ob_sval, str);
|
|
|
47 }
|
|
|
48 return (object *) op;
|
|
|
49 }
|
|
|
50
|
|
|
51 unsigned int
|
|
|
52 getstringsize(op)
|
|
|
53 register object *op;
|
|
|
54 {
|
|
|
55 if (!is_stringobject(op)) {
|
|
|
56 errno = EBADF;
|
|
|
57 return -1;
|
|
|
58 }
|
|
|
59 return ((stringobject *)op) -> ob_size;
|
|
|
60 }
|
|
|
61
|
|
|
62 /*const*/ char *
|
|
|
63 getstringvalue(op)
|
|
|
64 register object *op;
|
|
|
65 {
|
|
|
66 if (!is_stringobject(op)) {
|
|
|
67 errno = EBADF;
|
|
|
68 return NULL;
|
|
|
69 }
|
|
|
70 return ((stringobject *)op) -> ob_sval;
|
|
|
71 }
|
|
|
72
|
|
|
73 /* Methods */
|
|
|
74
|
|
|
75 static void
|
|
|
76 stringprint(op, fp, flags)
|
|
|
77 stringobject *op;
|
|
|
78 FILE *fp;
|
|
|
79 int flags;
|
|
|
80 {
|
|
|
81 int i;
|
|
|
82 char c;
|
|
|
83 if (flags & PRINT_RAW) {
|
|
|
84 fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
|
|
|
85 return;
|
|
|
86 }
|
|
|
87 fprintf(fp, "'");
|
|
|
88 for (i = 0; i < op->ob_size; i++) {
|
|
|
89 c = op->ob_sval[i];
|
|
|
90 if (c == '\'' || c == '\\')
|
|
|
91 fprintf(fp, "\\%c", c);
|
|
|
92 else if (c < ' ' || c >= 0177)
|
|
|
93 fprintf(fp, "\\%03o", c&0377);
|
|
|
94 else
|
|
|
95 putc(c, fp);
|
|
|
96 }
|
|
|
97 fprintf(fp, "'");
|
|
|
98 }
|
|
|
99
|
|
|
100 static object *
|
|
|
101 stringrepr(op)
|
|
|
102 register stringobject *op;
|
|
|
103 {
|
|
|
104 /* XXX overflow? */
|
|
|
105 int newsize = 2 + 4 * op->ob_size * sizeof(char);
|
|
|
106 object *v = newsizedstringobject((char *)NULL, newsize);
|
|
|
107 if (v == NULL) {
|
|
|
108 errno = ENOMEM;
|
|
|
109 }
|
|
|
110 else {
|
|
|
111 register int i;
|
|
|
112 register char c;
|
|
|
113 register char *p;
|
|
|
114 NEWREF(v);
|
|
|
115 v->ob_type = &Stringtype;
|
|
|
116 ((stringobject *)v)->ob_size = newsize;
|
|
|
117 p = ((stringobject *)v)->ob_sval;
|
|
|
118 *p++ = '\'';
|
|
|
119 for (i = 0; i < op->ob_size; i++) {
|
|
|
120 c = op->ob_sval[i];
|
|
|
121 if (c == '\'' || c == '\\')
|
|
|
122 *p++ = '\\', *p++ = c;
|
|
|
123 else if (c < ' ' || c >= 0177) {
|
|
|
124 sprintf(p, "\\%03o", c&0377);
|
|
|
125 while (*p != '\0')
|
|
|
126 p++;
|
|
|
127
|
|
|
128 }
|
|
|
129 else
|
|
|
130 *p++ = c;
|
|
|
131 }
|
|
|
132 *p++ = '\'';
|
|
|
133 *p = '\0';
|
|
|
134 resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval));
|
|
|
135 }
|
|
|
136 return v;
|
|
|
137 }
|
|
|
138
|
|
|
139 static int
|
|
|
140 stringlength(a)
|
|
|
141 stringobject *a;
|
|
|
142 {
|
|
|
143 return a->ob_size;
|
|
|
144 }
|
|
|
145
|
|
|
146 static object *
|
|
|
147 stringconcat(a, bb)
|
|
|
148 register stringobject *a;
|
|
|
149 register object *bb;
|
|
|
150 {
|
|
|
151 register unsigned int size;
|
|
|
152 register stringobject *op;
|
|
|
153 if (!is_stringobject(bb)) {
|
|
|
154 errno = EINVAL;
|
|
|
155 return NULL;
|
|
|
156 }
|
|
|
157 #define b ((stringobject *)bb)
|
|
|
158 /* Optimize cases with empty left or right operand */
|
|
|
159 if (a->ob_size == 0) {
|
|
|
160 INCREF(bb);
|
|
|
161 return bb;
|
|
|
162 }
|
|
|
163 if (b->ob_size == 0) {
|
|
|
164 INCREF(a);
|
|
|
165 return (object *)a;
|
|
|
166 }
|
|
|
167 size = a->ob_size + b->ob_size;
|
|
|
168 op = (stringobject *)
|
|
|
169 malloc(sizeof(stringobject) + size * sizeof(char));
|
|
|
170 if (op == NULL) {
|
|
|
171 errno = ENOMEM;
|
|
|
172 }
|
|
|
173 else {
|
|
|
174 NEWREF(op);
|
|
|
175 op->ob_type = &Stringtype;
|
|
|
176 op->ob_size = size;
|
|
|
177 memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
|
|
|
178 memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
|
|
|
179 op->ob_sval[size] = '\0';
|
|
|
180 }
|
|
|
181 return (object *) op;
|
|
|
182 #undef b
|
|
|
183 }
|
|
|
184
|
|
|
185 static object *
|
|
|
186 stringrepeat(a, n)
|
|
|
187 register stringobject *a;
|
|
|
188 register int n;
|
|
|
189 {
|
|
|
190 register int i;
|
|
|
191 register unsigned int size;
|
|
|
192 register stringobject *op;
|
|
|
193 if (n < 0)
|
|
|
194 n = 0;
|
|
|
195 size = a->ob_size * n;
|
|
|
196 if (size == a->ob_size) {
|
|
|
197 INCREF(a);
|
|
|
198 return (object *)a;
|
|
|
199 }
|
|
|
200 op = (stringobject *)
|
|
|
201 malloc(sizeof(stringobject) + size * sizeof(char));
|
|
|
202 if (op == NULL) {
|
|
|
203 errno = ENOMEM;
|
|
|
204 }
|
|
|
205 else {
|
|
|
206 NEWREF(op);
|
|
|
207 op->ob_type = &Stringtype;
|
|
|
208 op->ob_size = size;
|
|
|
209 for (i = 0; i < size; i += a->ob_size)
|
|
|
210 memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
|
|
|
211 op->ob_sval[size] = '\0';
|
|
|
212 }
|
|
|
213 return (object *) op;
|
|
|
214 }
|
|
|
215
|
|
|
216 /* String slice a[i:j] consists of characters a[i] ... a[j-1] */
|
|
|
217
|
|
|
218 static object *
|
|
|
219 stringslice(a, i, j)
|
|
|
220 register stringobject *a;
|
|
|
221 register int i, j; /* May be negative! */
|
|
|
222 {
|
|
|
223 if (i < 0)
|
|
|
224 i = 0;
|
|
|
225 if (j < 0)
|
|
|
226 j = 0; /* Avoid signed/unsigned bug in next line */
|
|
|
227 if (j > a->ob_size)
|
|
|
228 j = a->ob_size;
|
|
|
229 if (i == 0 && j == a->ob_size) { /* It's the same as a */
|
|
|
230 INCREF(a);
|
|
|
231 return (object *)a;
|
|
|
232 }
|
|
|
233 if (j < i)
|
|
|
234 j = i;
|
|
|
235 return newsizedstringobject(a->ob_sval + i, (int) (j-i));
|
|
|
236 }
|
|
|
237
|
|
|
238 static object *
|
|
|
239 stringitem(a, i)
|
|
|
240 stringobject *a;
|
|
|
241 register int i;
|
|
|
242 {
|
|
|
243 if (i < 0 || i >= a->ob_size) {
|
|
|
244 errno = EDOM;
|
|
|
245 return NULL;
|
|
|
246 }
|
|
|
247 return stringslice(a, i, i+1);
|
|
|
248 }
|
|
|
249
|
|
|
250 static int
|
|
|
251 stringcompare(a, b)
|
|
|
252 stringobject *a, *b;
|
|
|
253 {
|
|
|
254 /* XXX should use memcmp on shortest size, then compare lengths */
|
|
|
255 return strcmp(a->ob_sval, b->ob_sval);
|
|
|
256 }
|
|
|
257
|
|
|
258 static sequence_methods string_as_sequence = {
|
|
|
259 stringlength, /*tp_length*/
|
|
|
260 stringconcat, /*tp_concat*/
|
|
|
261 stringrepeat, /*tp_repeat*/
|
|
|
262 stringitem, /*tp_item*/
|
|
|
263 stringslice, /*tp_slice*/
|
|
|
264 0, /*tp_ass_item*/
|
|
|
265 0, /*tp_ass_slice*/
|
|
|
266 };
|
|
|
267
|
|
|
268 typeobject Stringtype = {
|
|
|
269 OB_HEAD_INIT(&Typetype)
|
|
|
270 0,
|
|
|
271 "string",
|
|
|
272 sizeof(stringobject),
|
|
|
273 sizeof(char),
|
|
|
274 free, /*tp_dealloc*/
|
|
|
275 stringprint, /*tp_print*/
|
|
|
276 0, /*tp_getattr*/
|
|
|
277 0, /*tp_setattr*/
|
|
|
278 stringcompare, /*tp_compare*/
|
|
|
279 stringrepr, /*tp_repr*/
|
|
|
280 0, /*tp_as_number*/
|
|
|
281 &string_as_sequence, /*tp_as_sequence*/
|
|
|
282 0, /*tp_as_mapping*/
|
|
|
283 };
|
|
|
284
|
|
|
285 void
|
|
|
286 joinstring(pv, w)
|
|
|
287 register object **pv;
|
|
|
288 register object *w;
|
|
|
289 {
|
|
|
290 register object *v;
|
|
|
291 if (*pv == NULL || w == NULL || !is_stringobject(*pv))
|
|
|
292 return;
|
|
|
293 v = stringconcat((stringobject *) *pv, w);
|
|
|
294 DECREF(*pv);
|
|
|
295 *pv = v;
|
|
|
296 }
|
|
|
297
|
|
|
298 /* The following function breaks the notion that strings are immutable:
|
|
|
299 it changes the size of a string. We get away with this only if there
|
|
|
300 is only one module referencing the object. You can also think of it
|
|
|
301 as creating a new string object and destroying the old one, only
|
|
|
302 more efficiently. In any case, don't use this if the string may
|
|
|
303 already be known to some other part of the code... */
|
|
|
304
|
|
|
305 int
|
|
|
306 resizestring(pv, newsize)
|
|
|
307 object **pv;
|
|
|
308 int newsize;
|
|
|
309 {
|
|
|
310 register stringobject *v;
|
|
|
311 v = (stringobject *) *pv;
|
|
|
312 if (!is_stringobject(v) || v->ob_refcnt != 1) {
|
|
|
313 *pv = 0;
|
|
|
314 DECREF(v);
|
|
|
315 return errno = EBADF;
|
|
|
316 }
|
|
|
317 *pv = (object *)
|
|
|
318 realloc((char *)v,
|
|
|
319 sizeof(stringobject) + newsize * sizeof(char));
|
|
|
320 if (*pv == NULL) {
|
|
|
321 DECREF(v);
|
|
|
322 return errno = ENOMEM;
|
|
|
323 }
|
|
|
324 v = (stringobject *) *pv;
|
|
|
325 v->ob_size = newsize;
|
|
|
326 v->ob_sval[newsize] = '\0';
|
|
|
327 return 0;
|
|
|
328 }
|