perl 5.0 alpha 6
[perl.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 void
266 av_free(av)
267 AV *av;
268 {
269     av_undef(av);
270     Safefree(av);
271 }
272
273 bool
274 av_push(av,val)
275 register AV *av;
276 SV *val;
277 {
278     return av_store(av,++(AvFILL(av)),val) != 0;
279 }
280
281 SV *
282 av_pop(av)
283 register AV *av;
284 {
285     SV *retval;
286
287     if (AvFILL(av) < 0)
288         return Nullsv;
289     retval = AvARRAY(av)[AvFILL(av)];
290     AvARRAY(av)[AvFILL(av)--] = Nullsv;
291     if (SvSMAGICAL(av))
292         mg_set((SV*)av);
293     return retval;
294 }
295
296 void
297 av_popnulls(av)
298 register AV *av;
299 {
300     register I32 fill = AvFILL(av);
301
302     while (fill >= 0 && !AvARRAY(av)[fill])
303         fill--;
304     AvFILL(av) = fill;
305 }
306
307 void
308 av_unshift(av,num)
309 register AV *av;
310 register I32 num;
311 {
312     register I32 i;
313     register SV **sstr,**dstr;
314
315     if (num <= 0)
316         return;
317     if (AvARRAY(av) - AvALLOC(av) >= num) {
318         AvMAX(av) += num;
319         AvFILL(av) += num;
320         while (num--) {
321             SvPVX(av) = (char*)(AvARRAY(av) - 1);
322             *AvARRAY(av) = Nullsv;
323         }
324     }
325     else {
326         (void)av_store(av,AvFILL(av)+num,(SV*)0);       /* maybe extend array */
327         dstr = AvARRAY(av) + AvFILL(av);
328         sstr = dstr - num;
329 #ifdef BUGGY_MSC5
330  # pragma loop_opt(off) /* don't loop-optimize the following code */
331 #endif /* BUGGY_MSC5 */
332         for (i = AvFILL(av) - num; i >= 0; i--) {
333             *dstr-- = *sstr--;
334 #ifdef BUGGY_MSC5
335  # pragma loop_opt()    /* loop-optimization back to command-line setting */
336 #endif /* BUGGY_MSC5 */
337         }
338         Zero(AvARRAY(av), num, SV*);
339     }
340 }
341
342 SV *
343 av_shift(av)
344 register AV *av;
345 {
346     SV *retval;
347
348     if (AvFILL(av) < 0)
349         return Nullsv;
350     retval = *AvARRAY(av);
351     *AvARRAY(av) = Nullsv;
352     SvPVX(av) = (char*)(AvARRAY(av) + 1);
353     AvMAX(av)--;
354     AvFILL(av)--;
355     if (SvSMAGICAL(av))
356         mg_set((SV*)av);
357     return retval;
358 }
359
360 I32
361 av_len(av)
362 register AV *av;
363 {
364     return AvFILL(av);
365 }
366
367 void
368 av_fill(av, fill)
369 register AV *av;
370 I32 fill;
371 {
372     if (fill < 0)
373         fill = -1;
374     if (fill <= AvMAX(av)) {
375         AvFILL(av) = fill;
376         if (SvSMAGICAL(av))
377             mg_set((SV*)av);
378     }
379     else {
380         AvFILL(av) = fill - 1;          /* don't clobber in-between values */
381         (void)av_store(av,fill,Nullsv);
382     }
383 }