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** |
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 | } |