Maintenance 5.004_04 changes
[p5sagit/p5-mst-13.2.git] / av.c
CommitLineData
a0d0e21e 1/* av.c
79072805 2 *
9607fc9c 3 * Copyright (c) 1991-1997, Larry Wall
79072805 4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
a0d0e21e 8 */
9
10/*
11 * "...for the Entwives desired order, and plenty, and peace (by which they
12 * meant that things should remain where they had set them)." --Treebeard
79072805 13 */
14
15#include "EXTERN.h"
16#include "perl.h"
17
fb73857a 18void
a0d0e21e 19av_reify(av)
20AV* av;
21{
22 I32 key;
23 SV* sv;
fb73857a 24
25 if (AvREAL(av))
26 return;
a0d0e21e 27 key = AvMAX(av) + 1;
28 while (key > AvFILL(av) + 1)
29 AvARRAY(av)[--key] = &sv_undef;
30 while (key) {
31 sv = AvARRAY(av)[--key];
32 assert(sv);
33 if (sv != &sv_undef)
34 (void)SvREFCNT_inc(sv);
35 }
29de640a 36 key = AvARRAY(av) - AvALLOC(av);
37 while (key)
38 AvALLOC(av)[--key] = &sv_undef;
a0d0e21e 39 AvREAL_on(av);
40}
41
42void
43av_extend(av,key)
44AV *av;
45I32 key;
46{
47 if (key > AvMAX(av)) {
48 SV** ary;
49 I32 tmp;
50 I32 newmax;
51
52 if (AvALLOC(av) != AvARRAY(av)) {
53 ary = AvALLOC(av) + AvFILL(av) + 1;
54 tmp = AvARRAY(av) - AvALLOC(av);
55 Move(AvARRAY(av), AvALLOC(av), AvFILL(av)+1, SV*);
56 AvMAX(av) += tmp;
57 SvPVX(av) = (char*)AvALLOC(av);
58 if (AvREAL(av)) {
59 while (tmp)
60 ary[--tmp] = &sv_undef;
61 }
62
63 if (key > AvMAX(av) - 10) {
64 newmax = key + AvMAX(av);
65 goto resize;
66 }
67 }
68 else {
69 if (AvALLOC(av)) {
c07a80fd 70#ifndef STRANGE_MALLOC
4633a7c4 71 U32 bytes;
c07a80fd 72#endif
4633a7c4 73
a0d0e21e 74 newmax = key + AvMAX(av) / 5;
75 resize:
4633a7c4 76#ifdef STRANGE_MALLOC
a0d0e21e 77 Renew(AvALLOC(av),newmax+1, SV*);
4633a7c4 78#else
79 bytes = (newmax + 1) * sizeof(SV*);
80#define MALLOC_OVERHEAD 16
81 tmp = MALLOC_OVERHEAD;
82 while (tmp - MALLOC_OVERHEAD < bytes)
83 tmp += tmp;
84 tmp -= MALLOC_OVERHEAD;
85 tmp /= sizeof(SV*);
86 assert(tmp > newmax);
87 newmax = tmp - 1;
88 New(2,ary, newmax+1, SV*);
89 Copy(AvALLOC(av), ary, AvMAX(av)+1, SV*);
c07a80fd 90 if (AvMAX(av) > 64 && !nice_chunk) {
91 nice_chunk = (char*)AvALLOC(av);
92 nice_chunk_size = (AvMAX(av) + 1) * sizeof(SV*);
93 }
4633a7c4 94 else
95 Safefree(AvALLOC(av));
96 AvALLOC(av) = ary;
97#endif
a0d0e21e 98 ary = AvALLOC(av) + AvMAX(av) + 1;
99 tmp = newmax - AvMAX(av);
7d55f622 100 if (av == curstack) { /* Oops, grew stack (via av_store()?) */
a0d0e21e 101 stack_sp = AvALLOC(av) + (stack_sp - stack_base);
102 stack_base = AvALLOC(av);
103 stack_max = stack_base + newmax;
104 }
105 }
106 else {
107 newmax = key < 4 ? 4 : key;
108 New(2,AvALLOC(av), newmax+1, SV*);
109 ary = AvALLOC(av) + 1;
110 tmp = newmax;
111 AvALLOC(av)[0] = &sv_undef; /* For the stacks */
112 }
113 if (AvREAL(av)) {
114 while (tmp)
115 ary[--tmp] = &sv_undef;
116 }
117
118 SvPVX(av) = (char*)AvALLOC(av);
119 AvMAX(av) = newmax;
120 }
121 }
122}
123
79072805 124SV**
463ee0b2 125av_fetch(av,key,lval)
126register AV *av;
79072805 127I32 key;
128I32 lval;
129{
130 SV *sv;
131
a0d0e21e 132 if (!av)
133 return 0;
134
8990e307 135 if (SvRMAGICAL(av)) {
463ee0b2 136 if (mg_find((SV*)av,'P')) {
8990e307 137 sv = sv_newmortal();
463ee0b2 138 mg_copy((SV*)av, sv, 0, key);
463ee0b2 139 Sv = sv;
140 return &Sv;
141 }
142 }
143
a0d0e21e 144 if (key < 0) {
145 key += AvFILL(av) + 1;
146 if (key < 0)
147 return 0;
148 }
149 else if (key > AvFILL(av)) {
150 if (!lval)
151 return 0;
152 if (AvREALISH(av))
153 sv = NEWSV(5,0);
154 else
155 sv = sv_newmortal();
156 return av_store(av,key,sv);
79072805 157 }
a0d0e21e 158 if (AvARRAY(av)[key] == &sv_undef) {
4dbf4341 159 emptyness:
79072805 160 if (lval) {
161 sv = NEWSV(6,0);
463ee0b2 162 return av_store(av,key,sv);
79072805 163 }
164 return 0;
165 }
4dbf4341 166 else if (AvREIFY(av)
167 && (!AvARRAY(av)[key] /* eg. @_ could have freed elts */
168 || SvTYPE(AvARRAY(av)[key]) == SVTYPEMASK)) {
169 AvARRAY(av)[key] = &sv_undef; /* 1/2 reify */
170 goto emptyness;
171 }
463ee0b2 172 return &AvARRAY(av)[key];
79072805 173}
174
175SV**
463ee0b2 176av_store(av,key,val)
177register AV *av;
79072805 178I32 key;
179SV *val;
180{
79072805 181 SV** ary;
182
a0d0e21e 183 if (!av)
184 return 0;
43fcc5d2 185 if (!val)
186 val = &sv_undef;
463ee0b2 187
8990e307 188 if (SvRMAGICAL(av)) {
463ee0b2 189 if (mg_find((SV*)av,'P')) {
43fcc5d2 190 if (val != &sv_undef)
191 mg_copy((SV*)av, val, 0, key);
463ee0b2 192 return 0;
193 }
194 }
195
a0d0e21e 196 if (key < 0) {
197 key += AvFILL(av) + 1;
198 if (key < 0)
199 return 0;
79072805 200 }
43fcc5d2 201 if (SvREADONLY(av) && key >= AvFILL(av))
202 croak(no_modify);
49beac48 203 if (!AvREAL(av) && AvREIFY(av))
a0d0e21e 204 av_reify(av);
29de640a 205 if (key > AvMAX(av))
206 av_extend(av,key);
463ee0b2 207 ary = AvARRAY(av);
a0d0e21e 208 if (AvFILL(av) < key) {
209 if (!AvREAL(av)) {
7d55f622 210 if (av == curstack && key > stack_sp - stack_base)
a0d0e21e 211 stack_sp = stack_base + key; /* XPUSH in disguise */
212 do
213 ary[++AvFILL(av)] = &sv_undef;
214 while (AvFILL(av) < key);
79072805 215 }
a0d0e21e 216 AvFILL(av) = key;
79072805 217 }
a0d0e21e 218 else if (AvREAL(av))
219 SvREFCNT_dec(ary[key]);
79072805 220 ary[key] = val;
8990e307 221 if (SvSMAGICAL(av)) {
a0d0e21e 222 if (val != &sv_undef) {
223 MAGIC* mg = SvMAGIC(av);
224 sv_magic(val, (SV*)av, toLOWER(mg->mg_type), 0, key);
225 }
463ee0b2 226 mg_set((SV*)av);
227 }
79072805 228 return &ary[key];
229}
230
231AV *
232newAV()
233{
463ee0b2 234 register AV *av;
79072805 235
a0d0e21e 236 av = (AV*)NEWSV(3,0);
237 sv_upgrade((SV *)av, SVt_PVAV);
463ee0b2 238 AvREAL_on(av);
239 AvALLOC(av) = 0;
240 SvPVX(av) = 0;
241 AvMAX(av) = AvFILL(av) = -1;
242 return av;
79072805 243}
244
245AV *
246av_make(size,strp)
247register I32 size;
248register SV **strp;
249{
463ee0b2 250 register AV *av;
79072805 251 register I32 i;
252 register SV** ary;
253
a0d0e21e 254 av = (AV*)NEWSV(8,0);
255 sv_upgrade((SV *) av,SVt_PVAV);
a0d0e21e 256 AvFLAGS(av) = AVf_REAL;
573fa4ea 257 if (size) { /* `defined' was returning undef for size==0 anyway. */
258 New(4,ary,size,SV*);
259 AvALLOC(av) = ary;
260 SvPVX(av) = (char*)ary;
261 AvFILL(av) = size - 1;
262 AvMAX(av) = size - 1;
263 for (i = 0; i < size; i++) {
264 assert (*strp);
265 ary[i] = NEWSV(7,0);
266 sv_setsv(ary[i], *strp);
267 strp++;
268 }
79072805 269 }
463ee0b2 270 return av;
79072805 271}
272
273AV *
274av_fake(size,strp)
275register I32 size;
276register SV **strp;
277{
463ee0b2 278 register AV *av;
79072805 279 register SV** ary;
280
a0d0e21e 281 av = (AV*)NEWSV(9,0);
282 sv_upgrade((SV *)av, SVt_PVAV);
79072805 283 New(4,ary,size+1,SV*);
463ee0b2 284 AvALLOC(av) = ary;
79072805 285 Copy(strp,ary,size,SV*);
a0d0e21e 286 AvFLAGS(av) = AVf_REIFY;
463ee0b2 287 SvPVX(av) = (char*)ary;
288 AvFILL(av) = size - 1;
289 AvMAX(av) = size - 1;
79072805 290 while (size--) {
a0d0e21e 291 assert (*strp);
292 SvTEMP_off(*strp);
79072805 293 strp++;
294 }
463ee0b2 295 return av;
79072805 296}
297
298void
463ee0b2 299av_clear(av)
300register AV *av;
79072805 301{
302 register I32 key;
a0d0e21e 303 SV** ary;
79072805 304
7d55f622 305#ifdef DEBUGGING
306 if (SvREFCNT(av) <= 0) {
307 warn("Attempt to clear deleted array");
308 }
309#endif
a0d0e21e 310 if (!av || AvMAX(av) < 0)
79072805 311 return;
312 /*SUPPRESS 560*/
a0d0e21e 313
314 if (AvREAL(av)) {
315 ary = AvARRAY(av);
316 key = AvFILL(av) + 1;
317 while (key) {
318 SvREFCNT_dec(ary[--key]);
319 ary[key] = &sv_undef;
320 }
321 }
463ee0b2 322 if (key = AvARRAY(av) - AvALLOC(av)) {
323 AvMAX(av) += key;
a0d0e21e 324 SvPVX(av) = (char*)AvALLOC(av);
79072805 325 }
463ee0b2 326 AvFILL(av) = -1;
fb73857a 327
328 if (SvRMAGICAL(av))
329 mg_clear((SV*)av);
79072805 330}
331
332void
463ee0b2 333av_undef(av)
334register AV *av;
79072805 335{
336 register I32 key;
337
463ee0b2 338 if (!av)
79072805 339 return;
340 /*SUPPRESS 560*/
a0d0e21e 341 if (AvREAL(av)) {
342 key = AvFILL(av) + 1;
343 while (key)
344 SvREFCNT_dec(AvARRAY(av)[--key]);
345 }
463ee0b2 346 Safefree(AvALLOC(av));
347 AvALLOC(av) = 0;
348 SvPVX(av) = 0;
349 AvMAX(av) = AvFILL(av) = -1;
748a9306 350 if (AvARYLEN(av)) {
351 SvREFCNT_dec(AvARYLEN(av));
352 AvARYLEN(av) = 0;
353 }
79072805 354}
355
a0d0e21e 356void
463ee0b2 357av_push(av,val)
358register AV *av;
79072805 359SV *val;
360{
a0d0e21e 361 if (!av)
362 return;
363 av_store(av,AvFILL(av)+1,val);
79072805 364}
365
366SV *
463ee0b2 367av_pop(av)
368register AV *av;
79072805 369{
370 SV *retval;
371
a0d0e21e 372 if (!av || AvFILL(av) < 0)
373 return &sv_undef;
43fcc5d2 374 if (SvREADONLY(av))
375 croak(no_modify);
463ee0b2 376 retval = AvARRAY(av)[AvFILL(av)];
a0d0e21e 377 AvARRAY(av)[AvFILL(av)--] = &sv_undef;
8990e307 378 if (SvSMAGICAL(av))
463ee0b2 379 mg_set((SV*)av);
79072805 380 return retval;
381}
382
383void
463ee0b2 384av_unshift(av,num)
385register AV *av;
79072805 386register I32 num;
387{
388 register I32 i;
389 register SV **sstr,**dstr;
390
a0d0e21e 391 if (!av || num <= 0)
79072805 392 return;
43fcc5d2 393 if (SvREADONLY(av))
394 croak(no_modify);
49beac48 395 if (!AvREAL(av) && AvREIFY(av))
396 av_reify(av);
a0d0e21e 397 i = AvARRAY(av) - AvALLOC(av);
398 if (i) {
399 if (i > num)
400 i = num;
401 num -= i;
402
403 AvMAX(av) += i;
404 AvFILL(av) += i;
405 SvPVX(av) = (char*)(AvARRAY(av) - i);
406 }
407 if (num) {
408 av_extend(av,AvFILL(av)+num);
409 AvFILL(av) += num;
463ee0b2 410 dstr = AvARRAY(av) + AvFILL(av);
79072805 411 sstr = dstr - num;
412#ifdef BUGGY_MSC5
413 # pragma loop_opt(off) /* don't loop-optimize the following code */
414#endif /* BUGGY_MSC5 */
a0d0e21e 415 for (i = AvFILL(av) - num; i >= 0; --i) {
79072805 416 *dstr-- = *sstr--;
417#ifdef BUGGY_MSC5
418 # pragma loop_opt() /* loop-optimization back to command-line setting */
419#endif /* BUGGY_MSC5 */
420 }
a0d0e21e 421 while (num)
422 AvARRAY(av)[--num] = &sv_undef;
79072805 423 }
424}
425
426SV *
463ee0b2 427av_shift(av)
428register AV *av;
79072805 429{
430 SV *retval;
431
a0d0e21e 432 if (!av || AvFILL(av) < 0)
433 return &sv_undef;
43fcc5d2 434 if (SvREADONLY(av))
435 croak(no_modify);
463ee0b2 436 retval = *AvARRAY(av);
a0d0e21e 437 if (AvREAL(av))
438 *AvARRAY(av) = &sv_undef;
463ee0b2 439 SvPVX(av) = (char*)(AvARRAY(av) + 1);
440 AvMAX(av)--;
441 AvFILL(av)--;
8990e307 442 if (SvSMAGICAL(av))
463ee0b2 443 mg_set((SV*)av);
79072805 444 return retval;
445}
446
447I32
463ee0b2 448av_len(av)
449register AV *av;
79072805 450{
463ee0b2 451 return AvFILL(av);
79072805 452}
453
454void
463ee0b2 455av_fill(av, fill)
456register AV *av;
79072805 457I32 fill;
458{
a0d0e21e 459 if (!av)
460 croak("panic: null array");
79072805 461 if (fill < 0)
462 fill = -1;
463ee0b2 463 if (fill <= AvMAX(av)) {
a0d0e21e 464 I32 key = AvFILL(av);
465 SV** ary = AvARRAY(av);
466
467 if (AvREAL(av)) {
468 while (key > fill) {
469 SvREFCNT_dec(ary[key]);
470 ary[key--] = &sv_undef;
471 }
472 }
473 else {
474 while (key < fill)
475 ary[++key] = &sv_undef;
476 }
477
463ee0b2 478 AvFILL(av) = fill;
8990e307 479 if (SvSMAGICAL(av))
463ee0b2 480 mg_set((SV*)av);
481 }
a0d0e21e 482 else
483 (void)av_store(av,fill,&sv_undef);
79072805 484}