perl 5.0 alpha 2
[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(ar,key,lval)
32 register AV *ar;
33 I32 key;
34 I32 lval;
35 {
36     SV *sv;
37
38     if (key < 0 || key > AvFILL(ar)) {
39         if (lval && key >= 0) {
40             if (AvREAL(ar))
41                 sv = NEWSV(5,0);
42             else
43                 sv = sv_mortalcopy(&sv_undef);
44             return av_store(ar,key,sv);
45         }
46         else
47             return 0;
48     }
49     if (!AvARRAY(ar)[key]) {
50         if (lval) {
51             sv = NEWSV(6,0);
52             return av_store(ar,key,sv);
53         }
54         return 0;
55     }
56     return &AvARRAY(ar)[key];
57 }
58
59 SV**
60 av_store(ar,key,val)
61 register AV *ar;
62 I32 key;
63 SV *val;
64 {
65     I32 tmp;
66     SV** ary;
67
68     if (key < 0)
69         return 0;
70     if (key > AvMAX(ar)) {
71         I32 newmax;
72
73         if (AvALLOC(ar) != AvARRAY(ar)) {
74             tmp = AvARRAY(ar) - AvALLOC(ar);
75             Move(AvARRAY(ar), AvALLOC(ar), AvMAX(ar)+1, SV*);
76             Zero(AvALLOC(ar)+AvMAX(ar)+1, tmp, SV*);
77             AvMAX(ar) += tmp;
78             AvARRAY(ar) -= tmp;
79             if (key > AvMAX(ar) - 10) {
80                 newmax = key + AvMAX(ar);
81                 goto resize;
82             }
83         }
84         else {
85             if (AvALLOC(ar)) {
86                 newmax = key + AvMAX(ar) / 5;
87               resize:
88                 Renew(AvALLOC(ar),newmax+1, SV*);
89                 Zero(&AvALLOC(ar)[AvMAX(ar)+1], newmax - AvMAX(ar), SV*);
90             }
91             else {
92                 newmax = key < 4 ? 4 : key;
93                 Newz(2,AvALLOC(ar), newmax+1, SV*);
94             }
95             AvARRAY(ar) = AvALLOC(ar);
96             AvMAX(ar) = newmax;
97         }
98     }
99     ary = AvARRAY(ar);
100     if (AvREAL(ar)) {
101         if (AvFILL(ar) < key) {
102             while (++AvFILL(ar) < key) {
103                 if (ary[AvFILL(ar)] != Nullsv) {
104                     sv_free(ary[AvFILL(ar)]);
105                     ary[AvFILL(ar)] = Nullsv;
106                 }
107             }
108         }
109         if (ary[key])
110             sv_free(ary[key]);
111     }
112     ary[key] = val;
113     return &ary[key];
114 }
115
116 AV *
117 newAV()
118 {
119     register AV *ar;
120
121     Newz(1,ar,1,AV);
122     SvREFCNT(ar) = 1;
123     sv_upgrade(ar,SVt_PVAV);
124     AvREAL_on(ar);
125     AvALLOC(ar) = AvARRAY(ar) = 0;
126     AvMAX(ar) = AvFILL(ar) = -1;
127     return ar;
128 }
129
130 AV *
131 av_make(size,strp)
132 register I32 size;
133 register SV **strp;
134 {
135     register AV *ar;
136     register I32 i;
137     register SV** ary;
138
139     Newz(3,ar,1,AV);
140     sv_upgrade(ar,SVt_PVAV);
141     New(4,ary,size+1,SV*);
142     AvALLOC(ar) = ary;
143     Zero(ary,size,SV*);
144     AvREAL_on(ar);
145     AvARRAY(ar) = ary;
146     AvFILL(ar) = size - 1;
147     AvMAX(ar) = size - 1;
148     for (i = 0; i < size; i++) {
149         if (*strp) {
150             ary[i] = NEWSV(7,0);
151             sv_setsv(ary[i], *strp);
152         }
153         strp++;
154     }
155     return ar;
156 }
157
158 AV *
159 av_fake(size,strp)
160 register I32 size;
161 register SV **strp;
162 {
163     register AV *ar;
164     register SV** ary;
165
166     Newz(3,ar,1,AV);
167     SvREFCNT(ar) = 1;
168     sv_upgrade(ar,SVt_PVAV);
169     New(4,ary,size+1,SV*);
170     AvALLOC(ar) = ary;
171     Copy(strp,ary,size,SV*);
172     AvREAL_off(ar);
173     AvARRAY(ar) = ary;
174     AvFILL(ar) = size - 1;
175     AvMAX(ar) = size - 1;
176     while (size--) {
177         if (*strp)
178             SvTEMP_off(*strp);
179         strp++;
180     }
181     return ar;
182 }
183
184 void
185 av_clear(ar)
186 register AV *ar;
187 {
188     register I32 key;
189
190     if (!ar || !AvREAL(ar) || AvMAX(ar) < 0)
191         return;
192     /*SUPPRESS 560*/
193     if (key = AvARRAY(ar) - AvALLOC(ar)) {
194         AvMAX(ar) += key;
195         AvARRAY(ar) -= key;
196     }
197     for (key = 0; key <= AvMAX(ar); key++)
198         sv_free(AvARRAY(ar)[key]);
199     AvFILL(ar) = -1;
200     Zero(AvARRAY(ar), AvMAX(ar)+1, SV*);
201 }
202
203 void
204 av_undef(ar)
205 register AV *ar;
206 {
207     register I32 key;
208
209     if (!ar)
210         return;
211     /*SUPPRESS 560*/
212     if (key = AvARRAY(ar) - AvALLOC(ar)) {
213         AvMAX(ar) += key;
214         AvARRAY(ar) -= key;
215     }
216     if (AvREAL(ar)) {
217         for (key = 0; key <= AvMAX(ar); key++)
218             sv_free(AvARRAY(ar)[key]);
219     }
220     Safefree(AvALLOC(ar));
221     AvALLOC(ar) = AvARRAY(ar) = 0;
222     AvMAX(ar) = AvFILL(ar) = -1;
223 }
224
225 void
226 av_free(ar)
227 AV *ar;
228 {
229     av_undef(ar);
230     Safefree(ar);
231 }
232
233 bool
234 av_push(ar,val)
235 register AV *ar;
236 SV *val;
237 {
238     return av_store(ar,++(AvFILL(ar)),val) != 0;
239 }
240
241 SV *
242 av_pop(ar)
243 register AV *ar;
244 {
245     SV *retval;
246
247     if (AvFILL(ar) < 0)
248         return Nullsv;
249     retval = AvARRAY(ar)[AvFILL(ar)];
250     AvARRAY(ar)[AvFILL(ar)--] = Nullsv;
251     return retval;
252 }
253
254 void
255 av_popnulls(ar)
256 register AV *ar;
257 {
258     register I32 fill = AvFILL(ar);
259
260     while (fill >= 0 && !AvARRAY(ar)[fill])
261         fill--;
262     AvFILL(ar) = fill;
263 }
264
265 void
266 av_unshift(ar,num)
267 register AV *ar;
268 register I32 num;
269 {
270     register I32 i;
271     register SV **sstr,**dstr;
272
273     if (num <= 0)
274         return;
275     if (AvARRAY(ar) - AvALLOC(ar) >= num) {
276         AvMAX(ar) += num;
277         AvFILL(ar) += num;
278         while (num--)
279             *--AvARRAY(ar) = Nullsv;
280     }
281     else {
282         (void)av_store(ar,AvFILL(ar)+num,(SV*)0);       /* maybe extend array */
283         dstr = AvARRAY(ar) + AvFILL(ar);
284         sstr = dstr - num;
285 #ifdef BUGGY_MSC5
286  # pragma loop_opt(off) /* don't loop-optimize the following code */
287 #endif /* BUGGY_MSC5 */
288         for (i = AvFILL(ar) - num; i >= 0; i--) {
289             *dstr-- = *sstr--;
290 #ifdef BUGGY_MSC5
291  # pragma loop_opt()    /* loop-optimization back to command-line setting */
292 #endif /* BUGGY_MSC5 */
293         }
294         Zero(AvARRAY(ar), num, SV*);
295     }
296 }
297
298 SV *
299 av_shift(ar)
300 register AV *ar;
301 {
302     SV *retval;
303
304     if (AvFILL(ar) < 0)
305         return Nullsv;
306     retval = *AvARRAY(ar);
307     *(AvARRAY(ar)++) = Nullsv;
308     AvMAX(ar)--;
309     AvFILL(ar)--;
310     return retval;
311 }
312
313 I32
314 av_len(ar)
315 register AV *ar;
316 {
317     return AvFILL(ar);
318 }
319
320 void
321 av_fill(ar, fill)
322 register AV *ar;
323 I32 fill;
324 {
325     if (fill < 0)
326         fill = -1;
327     if (fill <= AvMAX(ar))
328         AvFILL(ar) = fill;
329     else {
330         AvFILL(ar) = fill - 1;          /* don't clobber in-between values */
331         (void)av_store(ar,fill,Nullsv);
332     }
333 }