perl 3.0 patch #30 patch #29, continued
[perl.git] / array.c
1 /* $Header: array.c,v 3.0.1.3 90/10/15 14:56:17 lwall Locked $
2  *
3  *    Copyright (c) 1989, Larry Wall
4  *
5  *    You may distribute under the terms of the GNU General Public License
6  *    as specified in the README file that comes with the perl 3.0 kit.
7  *
8  * $Log:        array.c,v $
9  * Revision 3.0.1.3  90/10/15  14:56:17  lwall
10  * patch29: non-existent array values no longer cause core dumps
11  * 
12  * Revision 3.0.1.2  90/08/13  21:52:20  lwall
13  * patch28: defined(@array) and defined(%array) didn't work right
14  * 
15  * Revision 3.0.1.1  89/11/17  15:02:52  lwall
16  * patch5: nested foreach on same array didn't work
17  * 
18  * Revision 3.0  89/10/18  15:08:33  lwall
19  * 3.0 baseline
20  * 
21  */
22
23 #include "EXTERN.h"
24 #include "perl.h"
25
26 STR *
27 afetch(ar,key,lval)
28 register ARRAY *ar;
29 int key;
30 int lval;
31 {
32     STR *str;
33
34     if (key < 0 || key > ar->ary_fill) {
35         if (lval && key >= 0) {
36             if (ar->ary_flags & ARF_REAL)
37                 str = Str_new(5,0);
38             else
39                 str = str_static(&str_undef);
40             (void)astore(ar,key,str);
41             return str;
42         }
43         else
44             return &str_undef;
45     }
46     if (!ar->ary_array[key]) {
47         if (lval) {
48             str = Str_new(6,0);
49             (void)astore(ar,key,str);
50             return str;
51         }
52         return &str_undef;
53     }
54     return ar->ary_array[key];
55 }
56
57 bool
58 astore(ar,key,val)
59 register ARRAY *ar;
60 int key;
61 STR *val;
62 {
63     int retval;
64
65     if (key < 0)
66         return FALSE;
67     if (key > ar->ary_max) {
68         int newmax;
69
70         if (ar->ary_alloc != ar->ary_array) {
71             retval = ar->ary_array - ar->ary_alloc;
72             Copy(ar->ary_array, ar->ary_alloc, ar->ary_max+1, STR*);
73             Zero(ar->ary_alloc+ar->ary_max+1, retval, STR*);
74             ar->ary_max += retval;
75             ar->ary_array -= retval;
76             if (key > ar->ary_max - 10) {
77                 newmax = key + ar->ary_max;
78                 goto resize;
79             }
80         }
81         else {
82             if (ar->ary_alloc) {
83                 newmax = key + ar->ary_max / 5;
84               resize:
85                 Renew(ar->ary_alloc,newmax+1, STR*);
86                 Zero(&ar->ary_alloc[ar->ary_max+1], newmax - ar->ary_max, STR*);
87             }
88             else {
89                 newmax = key < 4 ? 4 : key;
90                 Newz(2,ar->ary_alloc, newmax+1, STR*);
91             }
92             ar->ary_array = ar->ary_alloc;
93             ar->ary_max = newmax;
94         }
95     }
96     if ((ar->ary_flags & ARF_REAL) && ar->ary_fill < key) {
97         while (++ar->ary_fill < key) {
98             if (ar->ary_array[ar->ary_fill] != Nullstr) {
99                 str_free(ar->ary_array[ar->ary_fill]);
100                 ar->ary_array[ar->ary_fill] = Nullstr;
101             }
102         }
103     }
104     retval = (ar->ary_array[key] != Nullstr);
105     if (retval && (ar->ary_flags & ARF_REAL))
106         str_free(ar->ary_array[key]);
107     ar->ary_array[key] = val;
108     return retval;
109 }
110
111 ARRAY *
112 anew(stab)
113 STAB *stab;
114 {
115     register ARRAY *ar;
116
117     New(1,ar,1,ARRAY);
118     ar->ary_magic = Str_new(7,0);
119     ar->ary_alloc = ar->ary_array = 0;
120     str_magic(ar->ary_magic, stab, '#', Nullch, 0);
121     ar->ary_max = ar->ary_fill = -1;
122     ar->ary_flags = ARF_REAL;
123     return ar;
124 }
125
126 ARRAY *
127 afake(stab,size,strp)
128 STAB *stab;
129 int size;
130 STR **strp;
131 {
132     register ARRAY *ar;
133
134     New(3,ar,1,ARRAY);
135     New(4,ar->ary_alloc,size+1,STR*);
136     Copy(strp,ar->ary_alloc,size,STR*);
137     ar->ary_array = ar->ary_alloc;
138     ar->ary_magic = Str_new(8,0);
139     str_magic(ar->ary_magic, stab, '#', Nullch, 0);
140     ar->ary_fill = size - 1;
141     ar->ary_max = size - 1;
142     ar->ary_flags = 0;
143     return ar;
144 }
145
146 void
147 aclear(ar)
148 register ARRAY *ar;
149 {
150     register int key;
151
152     if (!ar || !(ar->ary_flags & ARF_REAL) || ar->ary_max < 0)
153         return;
154     if (key = ar->ary_array - ar->ary_alloc) {
155         ar->ary_max += key;
156         ar->ary_array -= key;
157     }
158     for (key = 0; key <= ar->ary_max; key++)
159         str_free(ar->ary_array[key]);
160     ar->ary_fill = -1;
161     Zero(ar->ary_array, ar->ary_max+1, STR*);
162 }
163
164 void
165 afree(ar)
166 register ARRAY *ar;
167 {
168     register int key;
169
170     if (!ar)
171         return;
172     if (key = ar->ary_array - ar->ary_alloc) {
173         ar->ary_max += key;
174         ar->ary_array -= key;
175     }
176     if (ar->ary_flags & ARF_REAL) {
177         for (key = 0; key <= ar->ary_max; key++)
178             str_free(ar->ary_array[key]);
179     }
180     str_free(ar->ary_magic);
181     Safefree(ar->ary_alloc);
182     Safefree(ar);
183 }
184
185 bool
186 apush(ar,val)
187 register ARRAY *ar;
188 STR *val;
189 {
190     return astore(ar,++(ar->ary_fill),val);
191 }
192
193 STR *
194 apop(ar)
195 register ARRAY *ar;
196 {
197     STR *retval;
198
199     if (ar->ary_fill < 0)
200         return Nullstr;
201     retval = ar->ary_array[ar->ary_fill];
202     ar->ary_array[ar->ary_fill--] = Nullstr;
203     return retval;
204 }
205
206 aunshift(ar,num)
207 register ARRAY *ar;
208 register int num;
209 {
210     register int i;
211     register STR **sstr,**dstr;
212
213     if (num <= 0)
214         return;
215     if (ar->ary_array - ar->ary_alloc >= num) {
216         ar->ary_max += num;
217         ar->ary_fill += num;
218         while (num--)
219             *--ar->ary_array = Nullstr;
220     }
221     else {
222         (void)astore(ar,ar->ary_fill+num,(STR*)0);      /* maybe extend array */
223         dstr = ar->ary_array + ar->ary_fill;
224         sstr = dstr - num;
225         for (i = ar->ary_fill; i >= 0; i--) {
226             *dstr-- = *sstr--;
227         }
228         Zero(ar->ary_array, num, STR*);
229     }
230 }
231
232 STR *
233 ashift(ar)
234 register ARRAY *ar;
235 {
236     STR *retval;
237
238     if (ar->ary_fill < 0)
239         return Nullstr;
240     retval = *ar->ary_array;
241     *(ar->ary_array++) = Nullstr;
242     ar->ary_max--;
243     ar->ary_fill--;
244     return retval;
245 }
246
247 int
248 alen(ar)
249 register ARRAY *ar;
250 {
251     return ar->ary_fill;
252 }
253
254 afill(ar, fill)
255 register ARRAY *ar;
256 int fill;
257 {
258     if (fill < 0)
259         fill = -1;
260     if (fill <= ar->ary_max)
261         ar->ary_fill = fill;
262     else
263         (void)astore(ar,fill,Nullstr);
264 }