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