e161c2e22d89a06d82a19b867f4c310a85d4ba4a
[alioth/jupp.git] / va.h
1 /*
2  *      Variable length arrays of strings
3  *      Copyright
4  *              (C) 1992 Joseph H. Allen
5  *
6  *      This file is part of JOE (Joe's Own Editor)
7  */
8 #ifndef _JOE_VA_H
9 #define _JOE_VA_H 1
10
11 #ifdef EXTERN_B_C
12 __RCSID("$MirOS: contrib/code/jupp/va.h,v 1.4 2017/12/02 02:07:37 tg Exp $");
13 #endif
14
15 #include "vs.h"
16
17 /* Functions and global variable you have to define.  Replace these with
18  * macros or defines here if they are not to be actual functions
19  */
20
21 typedef unsigned char *aELEMENT;
22
23 /* aELEMENT adup(); */
24 #define adup(s) vsdup(s)
25 /* aELEMENT adel(); */
26 #define adel(s) vsrm(s)
27 /* int acmp(); */
28 #define acmp(a,b) vscmp((a),(b))
29 /* extern aELEMENT ablank; */
30 #define ablank NULL
31 /* extern aELEMENT aterm; */
32 #define aterm NULL
33
34 /************************/
35 /* Creation/Destruction */
36 /************************/
37
38 /* aELEMENT *vamk(int len);
39  * Create a variable length array.  Space for 'len' elements is preallocated.
40  */
41 aELEMENT *vamk PARAMS((int len));
42
43 /* void varm(aELEMENT *vary);
44  * Free an array and everything which is in it.  Does nothing if 'vary' is
45  * 0.
46  */
47 void varm PARAMS((aELEMENT *vary));
48
49 /********************/
50 /* Space management */
51 /********************/
52
53 /* int aSIZ(aELEMENT *vary);
54  * int aSiz(aELEMENT *vary);
55  * Access size part of array.  This int indicates the number of elements which
56  * can fit in the array before realloc needs to be called.  It does not include
57  * the extra space needed for the terminator and the header.
58  *
59  * aSIZ returns 0 if you pass it 0.  aSiz does not do this checking,
60  * but can be used as an lvalue.
61  */
62 #define aSIZ(a) ((a) ? *((int *)(a) - 2) : 0)
63 #define aSiz(a) (*((int *)(a) - 2))
64
65 /* int aLEN(aELEMENT *vary);
66  * int aLen(aELEMENT *vary);
67  * Access length part of array.  This int indicates the number of elements
68  * currently in the array (not including the terminator).  This should be
69  * used primarily for reading the size of the array.  It can be used for
70  * setting the size of the array, but it must be used with care since it
71  * does not eliminate elements (if the size decreases) or make sure there's
72  * enough room (if the size increases).  See vensure and vtrunc.
73  *
74  * aLEN return a length of zero if 'vary' is 0.
75  * aLen doesn't do this checking, but can be used as an lvalue
76  */
77 #define aLEN(a) ((a) ? *((int *)(a) - 1) : 0)
78 #define aLen(a) (*((int *)(a) - 1))
79
80 /* int alen(aELEMENT *ary);
81  * Compute length of char or variable length array by searching for termination
82  * element.  Returns 0 if 'vary' is 0.
83  */
84 int alen PARAMS((aELEMENT *ary));
85
86 /* aELEMENT *vaensure(aELEMENT *vary, int len);
87  * Make sure there's enough space in the array for 'len' elements.  Whenever
88  * vaensure reallocs the array, it allocates 25% more than the necessary
89  * minimum space in anticipation of future expansion.  If 'vary' is 0,
90  * it creates a new array.
91  */
92 aELEMENT *vaensure PARAMS((aELEMENT *vary, int len));
93
94 /* aELEMENT *vazap(aELEMENT *vary, int pos, int n);
95  * Destroy n elements from an array beginning at pos.  Is ok if pos/n go
96  * past end of array.  This does not change the aLEN() value of the array.
97  * This does nothing and returns 0 if 'vary' is 0.  Note that this
98  * function does not actually write to the array.  This does not stop if
99  * a aterm is encountered.
100  */
101 aELEMENT *vazap PARAMS((aELEMENT *vary, int pos, int n));
102
103 /* aELEMENT *vatrunc(aELEMENT *vary, int len);
104  * Truncate array to indicated size.  This zaps or expands with blank elements
105  * and sets the LEN() of the array.  A new array is created if 'vary' is 0.
106  */
107 aELEMENT *vatrunc PARAMS((aELEMENT *vary, int len));
108
109 /************************************/
110 /* Function which write to an array */
111 /************************************/
112
113 /* aELEMENT *vafill(aELEMENT *vary, int pos, aELEMENT el, int len);
114  * Set 'len' element of 'vary' beginning at 'pos' to duplications of 'el'.
115  * Ok, if pos/len are past end of array.  If 'vary' is 0, a new array is
116  * created.
117  *
118  * This does not zap previous values.  If you need that to happen, call
119  * vazap first.  It does move the terminator around properly though.
120  */
121 aELEMENT *vafill PARAMS((aELEMENT *vary, int pos, aELEMENT el, int len));
122
123 /* aELEMENT *vandup(aELEMENT *vary, int pos, aELEMENT *array, int len);
124  * Duplicate 'len' elements from 'array' onto 'vary' beginning at position
125  * 'pos'.  'array' can be a char array since its length is passed seperately.  A
126  * new array is created if 'vary' is 0.
127  */
128 aELEMENT *vandup PARAMS((aELEMENT *vary, int pos, aELEMENT *array, int len));
129
130 /* aELEMENT *vadup(aELEMENT *vary);
131  * Duplicate array.  This is just a functionalized version of:
132  *
133  *   vandup(NULL,0,vary,aLEN(vary));
134  *
135  * but since you need to be able to refer to this particular function by
136  * address often it's given here.
137  *
138  * (actually, there's bazillions of these simple combinations of the above
139  * functions and the macros of the next section.  You'll probably want to make
140  * functionalized instances of the ones you use most often - especially since
141  * the macros aren't safe).
142  */
143 aELEMENT *vadup PARAMS((aELEMENT *vary));
144
145 /* aELEMENT *vaset(aELEMENT *vary, int pos, aELEMENT element);
146  * Set an element in an array.  Any value of 'pos' is valid.  A new array
147  * is created if 'vary' is 0.  The previous contents of the position is
148  * deleted.    This does not duplicate 'element'.  If you need 'element'
149  * duplicated, call: vaset(vary,pos,adup(element));
150  */
151 aELEMENT *_vaset PARAMS((aELEMENT *vary, int pos, aELEMENT el));
152
153 #define vaset(v,p,el)  \
154  (!(v) || (p) > aLen(v) || ((p) == aLen(v) && (p) == aSiz(v)) ?  \
155   _vaset((v),(p),(el)) \
156  : \
157   ((p) == aLen(v) ? \
158    ((v)[(p)+1] = (v)[p], (v)[p] = (el), aLen(v) = (p)+1, (v)) \
159   : \
160    (adel((v)[p]), (v)[p] = (el), (v)) \
161   ) \
162  )
163
164 /* aELEMENT *vaadd(aELEMENT *vary, aELEMENT element);
165  * Concatenate a single element to the end of 'vary'.  A new array is created
166  * if 'vary' is 0.  This does not duplicate element: call
167  * vaadd(vary,adup(element));  If you need it duplicated.
168  */
169 #define vaadd(v,el) \
170  (!(v) || aLen(v) == aSiz(v) ? \
171   _vaset((v), aLEN(v), (el)) \
172  : \
173   ((v)[aLen(v) + 1] = (v)[aLen(v)], (v)[aLen(v)] = (el), \
174    aLen(v) = aLen(v) + 1, (v)) \
175  )
176
177 /**************************************/
178 /* Functions which read from an array */
179 /**************************************/
180
181 /* These macros are used to generate the address/size pairs which get
182  * passed to the functions of the previous section.
183  */
184
185 /* { aELEMENT *, int } av(aELEMENT *array);
186  * Return array,size pair.  Uses aLEN to get size.
187  */
188 #define av(a) (a), aLEN(a)
189
190 /* { aELEMENT *, int } az(aELEMENT *array);
191  * Return array,size pair.  Uses alen to get size.
192  */
193 #define az(a) (a), alen(a)
194
195 /* { aELEMENT *, int } ac(aELEMENT *array);
196  * Return array,size pair.  Uses 'sizeof' to get size.
197  */
198 #define ac(a) (a), (sizeof(a) / sizeof(aELEMENT))
199
200 /* { aELEMENT *, int } arest(aELEMENT *vary, int pos);
201  * Return array,size pair of rest of array beginning at pos.  If
202  * pos is past end of array, gives size of 0.
203  */
204 #define arest(a, p) ((a) + (p)), (((p) > aLEN(a)) ? 0 : aLen(a) - (p))
205
206 /* { aELEMENT *, int } apart(aELEMENT *vary, int pos, int len);
207  * Return array,size pair of 'len' elements of array beginning with pos.  If
208  * pos is past end of array, gives size of 0.  If pos+len is past end of array,
209  * returns number of elements to end of array.
210  */
211 #define apart(a, p, l) \
212  ((a) + (p)), ((p) >= aLEN(a) ? 0 : ((p) + (l) > aLen(a) ? aLen(a) - (p) : (l)))
213
214 /* aELEMENT vaget(aELEMENT *vary, int pos);
215  * Get an element from an array.  Any value of pos is valid; if it's past the
216  * end of the array or if 'vary' is 0, the terminator is returned.  This
217  * does not make a duplicate of the returned element.  If you want that, pass
218  * the return value of this to adup.
219  */
220 #define vaget(a, p) ((p) >= aLEN(a) ? aterm : (a)[p])
221
222 /*************************/
223 /* Searching and Sorting */
224 /*************************/
225
226 /* aELEMENT *vasort(aELEMENT *ary, int len)
227  * Sort the elements of an array (char or variable length) using qsort().
228  */
229 aELEMENT *vasort PARAMS((aELEMENT *ary, int len));
230
231 /* aELEMENT *vawords(aELEMENT *a, char *s, int len, char *sep, int seplen);
232  * Generate list of strings out of words in 's' seperated with the characters
233  * in 'sep'.  The characters in 'sep' must be sorted.
234  */
235 aELEMENT *vawords PARAMS((aELEMENT *a, unsigned char *s, int len, unsigned char *sep, int seplen));
236
237 #endif