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