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