58489fd13922878391d1c87392e56793c190ab4e
[p5sagit/p5-mst-13.2.git] / av.c
1 /* $RCSfile: array.c,v $$Revision: 4.1 $$Date: 92/08/07 17:18:22 $
2  *
3  *    Copyright (c) 1991, 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  * $Log:        array.c,v $
9  * Revision 4.1  92/08/07  17:18:22  lwall
10  * Stage 6 Snapshot
11  * 
12  * Revision 4.0.1.3  92/06/08  11:45:05  lwall
13  * patch20: Perl now distinguishes overlapped copies from non-overlapped
14  * 
15  * Revision 4.0.1.2  91/11/05  16:00:14  lwall
16  * patch11: random cleanup
17  * patch11: passing non-existend array elements to subrouting caused core dump
18  * 
19  * Revision 4.0.1.1  91/06/07  10:19:08  lwall
20  * patch4: new copyright notice
21  * 
22  * Revision 4.0  91/03/20  01:03:32  lwall
23  * 4.0 baseline.
24  * 
25  */
26
27 #include "EXTERN.h"
28 #include "perl.h"
29
30 SV**
31 av_fetch(av,key,lval)
32 register AV *av;
33 I32 key;
34 I32 lval;
35 {
36     SV *sv;
37
38     if (SvRMAGICAL(av)) {
39         if (mg_find((SV*)av,'P')) {
40             if (key < 0)
41                 return 0;
42             sv = sv_newmortal();
43             mg_copy((SV*)av, sv, 0, key);
44             if (!lval) {
45                 mg_get((SV*)sv);
46                 sv_unmagic(sv,'p');
47             }
48             Sv = sv;
49             return &Sv;
50         }
51     }
52
53     if (key < 0 || key > AvFILL(av)) {
54         if (key < 0) {
55             key += AvFILL(av) + 1;
56             if (key < 0)
57                 return 0;
58         }
59         else {
60             if (!lval)
61                 return 0;
62             if (AvREAL(av))
63                 sv = NEWSV(5,0);
64             else
65                 sv = sv_newmortal();
66             return av_store(av,key,sv);
67         }
68     }
69     if (!AvARRAY(av)[key]) {
70         if (lval) {
71             sv = NEWSV(6,0);
72             return av_store(av,key,sv);
73         }
74         return 0;
75     }
76     return &AvARRAY(av)[key];
77 }
78
79 SV**
80 av_store(av,key,val)
81 register AV *av;
82 I32 key;
83 SV *val;
84 {
85     I32 tmp;
86     SV** ary;
87
88     if (key < 0) {
89         key += AvFILL(av) + 1;
90         if (key < 0)
91             return 0;
92     }
93
94     if (SvRMAGICAL(av)) {
95         if (mg_find((SV*)av,'P')) {
96             mg_copy((SV*)av, val, 0, key);
97             return 0;
98         }
99     }
100
101     if (key > AvMAX(av)) {
102         I32 newmax;
103
104         if (AvALLOC(av) != AvARRAY(av)) {
105             tmp = AvARRAY(av) - AvALLOC(av);
106             Move(AvARRAY(av), AvALLOC(av), AvMAX(av)+1, SV*);
107             Zero(AvALLOC(av)+AvMAX(av)+1, tmp, SV*);
108             AvMAX(av) += tmp;
109             SvPVX(av) = (char*)(AvARRAY(av) - tmp);
110             if (key > AvMAX(av) - 10) {
111                 newmax = key + AvMAX(av);
112                 goto resize;
113             }
114         }
115         else {
116             if (AvALLOC(av)) {
117                 newmax = key + AvMAX(av) / 5;
118               resize:
119                 Renew(AvALLOC(av),newmax+1, SV*);
120                 Zero(&AvALLOC(av)[AvMAX(av)+1], newmax - AvMAX(av), SV*);
121             }
122             else {
123                 newmax = key < 4 ? 4 : key;
124                 Newz(2,AvALLOC(av), newmax+1, SV*);
125             }
126             SvPVX(av) = (char*)AvALLOC(av);
127             AvMAX(av) = newmax;
128         }
129     }
130     ary = AvARRAY(av);
131     if (AvREAL(av)) {
132         if (AvFILL(av) < key) {
133             while (++AvFILL(av) < key) {
134                 if (ary[AvFILL(av)] != Nullsv) {
135                     SvREFCNT_dec(ary[AvFILL(av)]);
136                     ary[AvFILL(av)] = Nullsv;
137                 }
138             }
139         }
140         if (ary[key])
141             SvREFCNT_dec(ary[key]);
142     }
143     ary[key] = val;
144     if (SvSMAGICAL(av)) {
145         MAGIC* mg = SvMAGIC(av);
146         sv_magic(val, (SV*)av, tolower(mg->mg_type), 0, key);
147         mg_set((SV*)av);
148     }
149     return &ary[key];
150 }
151
152 AV *
153 newAV()
154 {
155     register AV *av;
156
157     Newz(1,av,1,AV);
158     SvREFCNT(av) = 1;
159     sv_upgrade(av,SVt_PVAV);
160     AvREAL_on(av);
161     AvALLOC(av) = 0;
162     SvPVX(av) = 0;
163     AvMAX(av) = AvFILL(av) = -1;
164     return av;
165 }
166
167 AV *
168 av_make(size,strp)
169 register I32 size;
170 register SV **strp;
171 {
172     register AV *av;
173     register I32 i;
174     register SV** ary;
175
176     Newz(3,av,1,AV);
177     sv_upgrade(av,SVt_PVAV);
178     New(4,ary,size+1,SV*);
179     AvALLOC(av) = ary;
180     Zero(ary,size,SV*);
181     AvREAL_on(av);
182     SvPVX(av) = (char*)ary;
183     AvFILL(av) = size - 1;
184     AvMAX(av) = size - 1;
185     for (i = 0; i < size; i++) {
186         if (*strp) {
187             ary[i] = NEWSV(7,0);
188             sv_setsv(ary[i], *strp);
189         }
190         strp++;
191     }
192     SvOK_on(av);
193     return av;
194 }
195
196 AV *
197 av_fake(size,strp)
198 register I32 size;
199 register SV **strp;
200 {
201     register AV *av;
202     register SV** ary;
203
204     Newz(3,av,1,AV);
205     SvREFCNT(av) = 1;
206     sv_upgrade(av,SVt_PVAV);
207     New(4,ary,size+1,SV*);
208     AvALLOC(av) = ary;
209     Copy(strp,ary,size,SV*);
210     AvREAL_off(av);
211     SvPVX(av) = (char*)ary;
212     AvFILL(av) = size - 1;
213     AvMAX(av) = size - 1;
214     while (size--) {
215         if (*strp)
216             SvTEMP_off(*strp);
217         strp++;
218     }
219     SvOK_on(av);
220     return av;
221 }
222
223 void
224 av_clear(av)
225 register AV *av;
226 {
227     register I32 key;
228
229     if (!av || !AvREAL(av) || AvMAX(av) < 0)
230         return;
231     /*SUPPRESS 560*/
232     if (key = AvARRAY(av) - AvALLOC(av)) {
233         AvMAX(av) += key;
234         SvPVX(av) = (char*)(AvARRAY(av) - key);
235     }
236     for (key = 0; key <= AvMAX(av); key++)
237         SvREFCNT_dec(AvARRAY(av)[key]);
238     AvFILL(av) = -1;
239     Zero(AvARRAY(av), AvMAX(av)+1, SV*);
240 }
241
242 void
243 av_undef(av)
244 register AV *av;
245 {
246     register I32 key;
247
248     if (!av)
249         return;
250     /*SUPPRESS 560*/
251     if (key = AvARRAY(av) - AvALLOC(av)) {
252         AvMAX(av) += key;
253         SvPVX(av) = (char*)(AvARRAY(av) - key);
254     }
255     if (AvREAL(av)) {
256         for (key = 0; key <= AvMAX(av); key++)
257             SvREFCNT_dec(AvARRAY(av)[key]);
258     }
259     Safefree(AvALLOC(av));
260     AvALLOC(av) = 0;
261     SvPVX(av) = 0;
262     AvMAX(av) = AvFILL(av) = -1;
263 }
264
265 bool
266 av_push(av,val)
267 register AV *av;
268 SV *val;
269 {
270     return av_store(av,++(AvFILL(av)),val) != 0;
271 }
272
273 SV *
274 av_pop(av)
275 register AV *av;
276 {
277     SV *retval;
278
279     if (AvFILL(av) < 0)
280         return Nullsv;
281     retval = AvARRAY(av)[AvFILL(av)];
282     AvARRAY(av)[AvFILL(av)--] = Nullsv;
283     if (SvSMAGICAL(av))
284         mg_set((SV*)av);
285     return retval;
286 }
287
288 void
289 av_popnulls(av)
290 register AV *av;
291 {
292     register I32 fill = AvFILL(av);
293
294     while (fill >= 0 && !AvARRAY(av)[fill])
295         fill--;
296     AvFILL(av) = fill;
297 }
298
299 void
300 av_unshift(av,num)
301 register AV *av;
302 register I32 num;
303 {
304     register I32 i;
305     register SV **sstr,**dstr;
306
307     if (num <= 0)
308         return;
309     if (AvARRAY(av) - AvALLOC(av) >= num) {
310         AvMAX(av) += num;
311         AvFILL(av) += num;
312         while (num--) {
313             SvPVX(av) = (char*)(AvARRAY(av) - 1);
314             *AvARRAY(av) = Nullsv;
315         }
316     }
317     else {
318         (void)av_store(av,AvFILL(av)+num,(SV*)0);       /* maybe extend array */
319         dstr = AvARRAY(av) + AvFILL(av);
320         sstr = dstr - num;
321 #ifdef BUGGY_MSC5
322  # pragma loop_opt(off) /* don't loop-optimize the following code */
323 #endif /* BUGGY_MSC5 */
324         for (i = AvFILL(av) - num; i >= 0; i--) {
325             *dstr-- = *sstr--;
326 #ifdef BUGGY_MSC5
327  # pragma loop_opt()    /* loop-optimization back to command-line setting */
328 #endif /* BUGGY_MSC5 */
329         }
330         Zero(AvARRAY(av), num, SV*);
331     }
332 }
333
334 SV *
335 av_shift(av)
336 register AV *av;
337 {
338     SV *retval;
339
340     if (AvFILL(av) < 0)
341         return Nullsv;
342     retval = *AvARRAY(av);
343     *AvARRAY(av) = Nullsv;
344     SvPVX(av) = (char*)(AvARRAY(av) + 1);
345     AvMAX(av)--;
346     AvFILL(av)--;
347     if (SvSMAGICAL(av))
348         mg_set((SV*)av);
349     return retval;
350 }
351
352 I32
353 av_len(av)
354 register AV *av;
355 {
356     return AvFILL(av);
357 }
358
359 void
360 av_fill(av, fill)
361 register AV *av;
362 I32 fill;
363 {
364     if (fill < 0)
365         fill = -1;
366     if (fill <= AvMAX(av)) {
367         AvFILL(av) = fill;
368         if (SvSMAGICAL(av))
369             mg_set((SV*)av);
370     }
371     else {
372         AvFILL(av) = fill - 1;          /* don't clobber in-between values */
373         (void)av_store(av,fill,Nullsv);
374     }
375 }