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