perl 4.0.00: (no release announcement available)
[p5sagit/p5-mst-13.2.git] / array.c
1 /* $Header: array.c,v 4.0 91/03/20 01:03:32 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 4.0  91/03/20  01:03:32  lwall
10  * 4.0 baseline.
11  * 
12  */
13
14 #include "EXTERN.h"
15 #include "perl.h"
16
17 STR *
18 afetch(ar,key,lval)
19 register ARRAY *ar;
20 int key;
21 int lval;
22 {
23     STR *str;
24
25     if (key < 0 || key > ar->ary_fill) {
26         if (lval && key >= 0) {
27             if (ar->ary_flags & ARF_REAL)
28                 str = Str_new(5,0);
29             else
30                 str = str_mortal(&str_undef);
31             (void)astore(ar,key,str);
32             return str;
33         }
34         else
35             return &str_undef;
36     }
37     if (!ar->ary_array[key]) {
38         if (lval) {
39             str = Str_new(6,0);
40             (void)astore(ar,key,str);
41             return str;
42         }
43         return &str_undef;
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             if (ar->ary_alloc) {
74                 newmax = key + ar->ary_max / 5;
75               resize:
76                 Renew(ar->ary_alloc,newmax+1, STR*);
77                 Zero(&ar->ary_alloc[ar->ary_max+1], newmax - ar->ary_max, STR*);
78             }
79             else {
80                 newmax = key < 4 ? 4 : key;
81                 Newz(2,ar->ary_alloc, newmax+1, STR*);
82             }
83             ar->ary_array = ar->ary_alloc;
84             ar->ary_max = newmax;
85         }
86     }
87     if ((ar->ary_flags & ARF_REAL) && ar->ary_fill < key) {
88         while (++ar->ary_fill < key) {
89             if (ar->ary_array[ar->ary_fill] != Nullstr) {
90                 str_free(ar->ary_array[ar->ary_fill]);
91                 ar->ary_array[ar->ary_fill] = Nullstr;
92             }
93         }
94     }
95     retval = (ar->ary_array[key] != Nullstr);
96     if (retval && (ar->ary_flags & ARF_REAL))
97         str_free(ar->ary_array[key]);
98     ar->ary_array[key] = val;
99     return retval;
100 }
101
102 ARRAY *
103 anew(stab)
104 STAB *stab;
105 {
106     register ARRAY *ar;
107
108     New(1,ar,1,ARRAY);
109     ar->ary_magic = Str_new(7,0);
110     ar->ary_alloc = ar->ary_array = 0;
111     str_magic(ar->ary_magic, stab, '#', Nullch, 0);
112     ar->ary_max = ar->ary_fill = -1;
113     ar->ary_flags = ARF_REAL;
114     return ar;
115 }
116
117 ARRAY *
118 afake(stab,size,strp)
119 STAB *stab;
120 register int size;
121 register STR **strp;
122 {
123     register ARRAY *ar;
124
125     New(3,ar,1,ARRAY);
126     New(4,ar->ary_alloc,size+1,STR*);
127     Copy(strp,ar->ary_alloc,size,STR*);
128     ar->ary_array = ar->ary_alloc;
129     ar->ary_magic = Str_new(8,0);
130     str_magic(ar->ary_magic, stab, '#', Nullch, 0);
131     ar->ary_fill = size - 1;
132     ar->ary_max = size - 1;
133     ar->ary_flags = 0;
134     while (size--) {
135         (*strp++)->str_pok &= ~SP_TEMP;
136     }
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 #ifdef BUGGY_MSC5
220  # pragma loop_opt(off) /* don't loop-optimize the following code */
221 #endif /* BUGGY_MSC5 */
222         for (i = ar->ary_fill; i >= 0; i--) {
223             *dstr-- = *sstr--;
224 #ifdef BUGGY_MSC5
225  # pragma loop_opt()    /* loop-optimization back to command-line setting */
226 #endif /* BUGGY_MSC5 */
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 }