2 * Variable length arrays of strings
4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
12 __IDSTRING(rcsid_va_h, "$MirOS: contrib/code/jupp/va.h,v 1.5 2017/12/02 17:00:52 tg Exp $");
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
21 typedef unsigned char *aELEMENT;
23 /* aELEMENT adup(); */
24 #define adup(s) vsdup(s)
25 /* aELEMENT adel(); */
26 #define adel(s) vsrm(s)
28 #define acmp(a,b) vscmp((a),(b))
29 /* extern aELEMENT ablank; */
31 /* extern aELEMENT aterm; */
34 /************************/
35 /* Creation/Destruction */
36 /************************/
38 /* aELEMENT *vamk(int len);
39 * Create a variable length array. Space for 'len' elements is preallocated.
41 aELEMENT *vamk PARAMS((int len));
43 /* void varm(aELEMENT *vary);
44 * Free an array and everything which is in it. Does nothing if 'vary' is
47 void varm PARAMS((aELEMENT *vary));
49 /********************/
50 /* Space management */
51 /********************/
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.
59 * aSIZ returns 0 if you pass it 0. aSiz does not do this checking,
60 * but can be used as an lvalue.
62 #define aSIZ(a) ((a) ? *((int *)(a) - 2) : 0)
63 #define aSiz(a) (*((int *)(a) - 2))
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.
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
77 #define aLEN(a) ((a) ? *((int *)(a) - 1) : 0)
78 #define aLen(a) (*((int *)(a) - 1))
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.
84 int alen PARAMS((aELEMENT *ary));
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.
92 aELEMENT *vaensure PARAMS((aELEMENT *vary, int len));
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.
101 aELEMENT *vazap PARAMS((aELEMENT *vary, int pos, int n));
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.
107 aELEMENT *vatrunc PARAMS((aELEMENT *vary, int len));
109 /************************************/
110 /* Function which write to an array */
111 /************************************/
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
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.
121 aELEMENT *vafill PARAMS((aELEMENT *vary, int pos, aELEMENT el, int len));
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.
128 aELEMENT *vandup PARAMS((aELEMENT *vary, int pos, aELEMENT *array, int len));
130 /* aELEMENT *vadup(aELEMENT *vary);
131 * Duplicate array. This is just a functionalized version of:
133 * vandup(NULL,0,vary,aLEN(vary));
135 * but since you need to be able to refer to this particular function by
136 * address often it's given here.
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).
143 aELEMENT *vadup PARAMS((aELEMENT *vary));
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));
151 aELEMENT *_vaset PARAMS((aELEMENT *vary, int pos, aELEMENT el));
153 #define vaset(v,p,el) \
154 (!(v) || (p) > aLen(v) || ((p) == aLen(v) && (p) == aSiz(v)) ? \
155 _vaset((v),(p),(el)) \
158 ((v)[(p)+1] = (v)[p], (v)[p] = (el), aLen(v) = (p)+1, (v)) \
160 (adel((v)[p]), (v)[p] = (el), (v)) \
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.
169 #define vaadd(v,el) \
170 (!(v) || aLen(v) == aSiz(v) ? \
171 _vaset((v), aLEN(v), (el)) \
173 ((v)[aLen(v) + 1] = (v)[aLen(v)], (v)[aLen(v)] = (el), \
174 aLen(v) = aLen(v) + 1, (v)) \
177 /**************************************/
178 /* Functions which read from an array */
179 /**************************************/
181 /* These macros are used to generate the address/size pairs which get
182 * passed to the functions of the previous section.
185 /* { aELEMENT *, int } av(aELEMENT *array);
186 * Return array,size pair. Uses aLEN to get size.
188 #define av(a) (a), aLEN(a)
190 /* { aELEMENT *, int } az(aELEMENT *array);
191 * Return array,size pair. Uses alen to get size.
193 #define az(a) (a), alen(a)
195 /* { aELEMENT *, int } ac(aELEMENT *array);
196 * Return array,size pair. Uses 'sizeof' to get size.
198 #define ac(a) (a), (sizeof(a) / sizeof(aELEMENT))
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.
204 #define arest(a, p) ((a) + (p)), (((p) > aLEN(a)) ? 0 : aLen(a) - (p))
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.
211 #define apart(a, p, l) \
212 ((a) + (p)), ((p) >= aLEN(a) ? 0 : ((p) + (l) > aLen(a) ? aLen(a) - (p) : (l)))
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.
220 #define vaget(a, p) ((p) >= aLEN(a) ? aterm : (a)[p])
222 /*************************/
223 /* Searching and Sorting */
224 /*************************/
226 /* aELEMENT *vasort(aELEMENT *ary, int len)
227 * Sort the elements of an array (char or variable length) using qsort().
229 aELEMENT *vasort PARAMS((aELEMENT *ary, int len));
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.
235 aELEMENT *vawords PARAMS((aELEMENT *a, unsigned char *s, int len, unsigned char *sep, int seplen));