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