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