blob: 6430c0f2e689d25790edb32d430b2423ef3c47ff [file] [log] [blame]
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00001/* 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
11object *
12newsizedstringobject(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
32object *
33newstringobject(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
51unsigned int
52getstringsize(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 *
63getstringvalue(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
75static void
76stringprint(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
100static object *
101stringrepr(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
139static int
140stringlength(a)
141 stringobject *a;
142{
143 return a->ob_size;
144}
145
146static object *
147stringconcat(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
185static object *
186stringrepeat(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
218static object *
219stringslice(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
238static object *
239stringitem(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
250static int
251stringcompare(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
258static 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
268typeobject 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
285void
286joinstring(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
305int
306resizestring(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}