Mercurial > cpython-lru_cache-weakref
annotate Objects/stringobject.c @ 82:554ac659b2cb legacy-trunk
Fix wrong #ifdef.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Sun, 18 Nov 1990 17:41:19 +0000 |
| parents | ac4522e99ca9 |
| children | a6934380c6e7 |
| rev | line source |
|---|---|
| 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" | |
| 27 | 10 #include "errors.h" |
| 6 | 11 |
| 12 object * | |
| 13 newsizedstringobject(str, size) | |
| 14 char *str; | |
| 15 int size; | |
| 16 { | |
| 17 register stringobject *op = (stringobject *) | |
| 18 malloc(sizeof(stringobject) + size * sizeof(char)); | |
| 27 | 19 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'; | |
| 6 | 27 return (object *) op; |
| 28 } | |
| 29 | |
| 30 object * | |
| 31 newstringobject(str) | |
| 32 char *str; | |
| 33 { | |
| 34 register unsigned int size = strlen(str); | |
| 35 register stringobject *op = (stringobject *) | |
| 36 malloc(sizeof(stringobject) + size * sizeof(char)); | |
| 27 | 37 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); | |
| 6 | 43 return (object *) op; |
| 44 } | |
| 45 | |
| 46 unsigned int | |
| 47 getstringsize(op) | |
| 48 register object *op; | |
| 49 { | |
| 50 if (!is_stringobject(op)) { | |
| 27 | 51 err_badcall(); |
| 6 | 52 return -1; |
| 53 } | |
| 54 return ((stringobject *)op) -> ob_size; | |
| 55 } | |
| 56 | |
| 57 /*const*/ char * | |
| 58 getstringvalue(op) | |
| 59 register object *op; | |
| 60 { | |
| 61 if (!is_stringobject(op)) { | |
| 27 | 62 err_badcall(); |
| 6 | 63 return NULL; |
| 64 } | |
| 65 return ((stringobject *)op) -> ob_sval; | |
| 66 } | |
| 67 | |
| 68 /* Methods */ | |
| 69 | |
| 70 static void | |
| 71 stringprint(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 | |
| 95 static object * | |
| 96 stringrepr(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) { | |
| 27 | 103 return err_nomem(); |
| 6 | 104 } |
| 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)); | |
| 27 | 130 return v; |
| 6 | 131 } |
| 132 } | |
| 133 | |
| 134 static int | |
| 135 stringlength(a) | |
| 136 stringobject *a; | |
| 137 { | |
| 138 return a->ob_size; | |
| 139 } | |
| 140 | |
| 141 static object * | |
| 142 stringconcat(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)) { | |
| 27 | 149 err_badarg(); |
| 6 | 150 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)); | |
| 27 | 165 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'; | |
| 6 | 173 return (object *) op; |
| 174 #undef b | |
| 175 } | |
| 176 | |
| 177 static object * | |
| 178 stringrepeat(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)); | |
| 27 | 194 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'; | |
| 6 | 202 return (object *) op; |
| 203 } | |
| 204 | |
| 205 /* String slice a[i:j] consists of characters a[i] ... a[j-1] */ | |
| 206 | |
| 207 static object * | |
| 208 stringslice(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 | |
| 227 static object * | |
| 228 stringitem(a, i) | |
| 229 stringobject *a; | |
| 230 register int i; | |
| 231 { | |
| 232 if (i < 0 || i >= a->ob_size) { | |
| 27 | 233 err_setstr(IndexError, "string index out of range"); |
| 6 | 234 return NULL; |
| 235 } | |
| 236 return stringslice(a, i, i+1); | |
| 237 } | |
| 238 | |
| 239 static int | |
| 240 stringcompare(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 | |
| 247 static 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 | |
| 257 typeobject 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 | |
| 274 void | |
| 275 joinstring(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 | |
| 294 int | |
| 295 resizestring(pv, newsize) | |
| 296 object **pv; | |
| 297 int newsize; | |
| 298 { | |
|
71
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
299 register object *v; |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
300 register stringobject *sv; |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
301 v = *pv; |
| 6 | 302 if (!is_stringobject(v) || v->ob_refcnt != 1) { |
| 303 *pv = 0; | |
| 304 DECREF(v); | |
| 27 | 305 err_badcall(); |
| 306 return -1; | |
| 6 | 307 } |
|
71
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
308 /* XXX UNREF/NEWREF interface should be more symmetrical */ |
| 82 | 309 #ifdef REF_DEBUG |
|
71
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
310 --ref_total; |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
311 #endif |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
312 UNREF(v); |
| 6 | 313 *pv = (object *) |
| 314 realloc((char *)v, | |
| 315 sizeof(stringobject) + newsize * sizeof(char)); | |
| 316 if (*pv == NULL) { | |
|
71
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
317 DEL(v); |
| 27 | 318 err_nomem(); |
| 319 return -1; | |
| 6 | 320 } |
|
71
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
321 NEWREF(*pv); |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
322 sv = (stringobject *) *pv; |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
323 sv->ob_size = newsize; |
|
ac4522e99ca9
Fixed resizestring() to work if reference tracing is turned on.
Guido van Rossum <guido@python.org>
parents:
27
diff
changeset
|
324 sv->ob_sval[newsize] = '\0'; |
| 6 | 325 return 0; |
| 326 } |
