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