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