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