xref: /haiku/src/apps/glteapot/util.h (revision 25a7b01d15612846f332751841da3579db313082)
1 /*
2 	Copyright 1999, Be Incorporated.   All Rights Reserved.
3 	This file may be used under the terms of the Be Sample Code License.
4 */
5 
6 #ifndef UTIL_H
7 #define UTIL_H
8 
9 #include <memory.h>
10 #include <stdlib.h>
11 #include "error.h"
12 
13 template <class contents>
14 struct LispNode {
15 	contents* car;
16 	LispNode* cdr;
17 
18 	/* Create a node with no next */
LispNodeLispNode19 	inline LispNode(contents* value)
20 		: car(value), cdr(0) { }
21 
22 	/* Create a node with specified next */
LispNodeLispNode23 	inline LispNode(contents* value, LispNode* next)
24  		: car (value), cdr(next) { }
25 
26 	/* Create a node and insert it in a list right after `prev' */
LispNodeLispNode27 	inline LispNode(LispNode* prev, contents* value)
28 		: car(value), cdr(prev->cdr) { prev->cdr = this; }
29 };
30 
31 
32 template <class contents>
33 struct LispList {
34 	LispNode<contents> *first;
35 
36 	/* -------- List creation --------------- */
37 	/* Create an empty list */
LispListLispList38 	inline LispList()
39 	{
40 		first = 0;
41 	}
42 
43 
44 	/* Create a list pointing to the specified node */
LispListLispList45 	inline LispList(LispNode<contents>* _first)
46 	{
47 		first = _first;
48 	}
49 
50 
51 	/* ?? */
LispListLispList52 	inline LispList(LispList &init)
53 	{
54 		first = init.first;
55 	}
56 
57 
58 	/* ---------- List queries ------------- */
is_emptyLispList59 	inline int is_empty()
60 	{
61 		return first == 0;
62 	}
63 
64 
65 	/* Determines if a thing is on the list */
is_presentLispList66 	inline int is_present(contents* element)
67 	{
68 		for (LispNode<contents>* node = first; node; node = node->cdr)
69 			if (node->car == element)
70 				return 1;
71 		return 0;
72 	}
73 
74 
75 	/* Returns the length of the list */
countLispList76 	inline int count()
77 	{
78 		int n = 0;
79 		for (LispNode<contents>* node = first; node; node = node->cdr)
80 			n++;
81 	    return n;
82 	}
83 
84 
85 	/* ----------- Adding "nodes" to the list ------------ */
86 	/* Add a specified node to the head of the list.  */
add_headLispList87 	inline void add_head(LispNode<contents>* new_element)
88 	{
89 		new_element->cdr = first;
90 		first = new_element;
91 	}
92 
93 
94 	/* Add a specified node anywhere on the list */
addLispList95 	inline void add(LispNode<contents>* new_element)
96 	{
97 		add_head (new_element);
98 	}
99 
100 
add_tailLispList101 	inline void add_tail(LispNode<contents>* new_element)
102 	{
103 		LispNode<contents>** pred = &first;
104 		while(*pred)
105 			pred = &(*pred)->cdr;
106 		*pred = new_element;
107 		new_element->cdr = 0;
108 	}
109 
110 
111 	/* ----------- Adding "contents" to the list ------------ */
112 	/* -----  (Which in my opinion is far more useful) ------ */
113 
114 	/* Create new node pointing to thing, & add to head of list. */
add_head_newLispList115 	inline void add_head_new(contents* new_element)
116 	{
117 		first = new LispNode<contents>(new_element, first);
118 	}
119 
120 
add_headLispList121 	inline void add_head(contents* new_element)
122 	{
123 		add_head_new(new_element);
124 	}
125 
126 
127 	/* Create new node pointing to thing, & add to end of list. */
add_tail_newLispList128 	inline void add_tail_new(contents* new_element)
129 	{
130 		LispNode< contents >** pred = &first;
131 		while (*pred)
132 			pred = &(*pred)->cdr;
133 
134 		*pred = new LispNode< contents >(new_element);
135 	}
136 
137 
add_tailLispList138 	inline void add_tail(contents* new_element)
139 	{
140 		add_tail_new(new_element);
141 	}
142 
143 
144 	/* Create new node pointing to thing, & add anywhere on list */
add_newLispList145 	inline void add_new(contents* new_element)
146 	{
147 		add_head_new(new_element);
148 	}
149 
150 
addLispList151 	inline void add(contents* new_element)
152 	{
153 		add_new(new_element);
154 	}
155 
156 
157 	/* Create and add a new node for a specified element,
158 		but only if it's not already on the list.  */
add_new_onceLispList159 	inline void add_new_once(contents* new_element)
160 	{
161 		if (!is_present(new_element))
162 			add_head_new(new_element);
163 	}
164 
165 
add_tail_onceLispList166 	inline void add_tail_once(contents *new_element)
167 	{
168 		if (!is_present(new_element))
169 			add_tail_new(new_element);
170 	}
171 
172 
173 	/* ------- Removing things from the list ------------ */
174 
175 	/* Remove and return the first node on the list j.h. */
rem_headLispList176 	inline LispNode<contents>* rem_head ()
177 	{
178 		LispNode<contents>* n = first;
179 
180 		if (n) {
181 			first = first->cdr;
182 		}
183 
184 		return n;
185 	}
186 
187 
188 	/* Remove and return any node on the list.  */
removeLispList189 	inline LispNode<contents>* remove ()
190 	{
191 		return( rem_head() );
192 	}
193 
194 
195 	/* Remove a specified node from the list.  */
removeLispList196 	inline void remove (LispNode<contents>* node)
197 	{
198 		for (LispNode<contents> **pp = &first; *pp; pp = &(*pp)->cdr)
199 			if (*pp == node) {
200 				*pp = (*pp)->cdr;
201 		  		return;
202 			}
203 	}
204 
205 
206 	/* Remove & delete all nodes pointing to a particular element. */
rem_delLispList207 	inline void rem_del (contents* element)
208 	{
209 		LispNode<contents>** pp = &first;
210 		while (*pp) {
211 			if ((*pp)->car == element) {
212 				LispNode<contents> *o = *pp;
213 				*pp = o->cdr;
214 				delete o;
215 			} else
216 				pp = &(*pp)->cdr;
217 		}
218 	}
219 
220 
221 	/* Remove and delete all nodes on the list.  */
rem_del_allLispList222 	inline void rem_del_all()
223 	{
224 		while (first) {
225 			LispNode<contents>* old = first;
226 			first = first->cdr;
227 			delete old;
228 		}
229 	}
230 
231 
232 	/* -------- Simple list storage (by j.h.) ------------ */
233 
234 	/* When you just want to hold a bunch of stuff on a list and then pull them
235 		off later.  Note that these calls do NOT check for to see if a thing is
236 		already on the list.  Use is_present() before adding.
237 	*/
238 	/* Put something anywhere on the list */
putLispList239 	inline void put( contents* c )
240 	{
241 		add_tail( c );
242 	}
243 
244 
245 	/* Put something at beginning of list */
put_headLispList246 	inline void put_head( contents* c )
247 	{
248 		add_head( c );
249 	}
250 
251 
252 	/* Put something at end of the list */
put_tailLispList253 	inline void put_tail( contents* c )
254 	{
255 		add_tail( c );
256 	}
257 
258 #if 0 /* leaks memory */
259 	  /* Take a specific thing off the list */
260 	  inline contents *get(contents *element)
261 	    {
262 	      contents *c = 0;
263 	      for (LispNode<contents> *node = first; node; node = node->cdr)
264 	      {
265 		if (node->car == element)
266 		{
267 		  c = node->car;
268 		  remove(node);
269 		  break;
270 		}
271 	      }
272 	      return c;
273 	    }
274 #endif
275 
276 	/* Take the first thing off the list */
get_headLispList277 	inline contents* get_head()
278 	{
279 		contents *c = 0;
280 		if(first) {
281 			c = first->car;
282 			delete rem_head();
283 		}
284 		return c;
285 	}
286 
287 
288 	/* Take something off the list */
getLispList289 	inline contents* get()
290 	{
291 		return(get_head());
292 	}
293 
294 
295 	/* XXX inline contents *get_tail() { } */
296 
297 /* -------- Stack simulation (by j.h.) ------------ */
298 	/* Put a thing onto the head of the list */
pushLispList299 	inline void push(contents* c)
300 	{
301 		put_head(c);
302 	}
303 
304 
305 	/* Remove a thing from the head of the list */
popLispList306 	inline contents* pop()
307 	{
308 		return(get_head());
309 	}
310 
311 	/* Pop everything off the stack.  Empty the stack/list. */
pop_allLispList312 	inline void pop_all()
313 	{
314 		rem_del_all();
315 	}
316 
317 
318 	/* ----------- list/list manipulations ------------ */
319 
320 	/* Add all elements present on another list to this list also. */
add_newLispList321 	inline void add_new(LispList other)
322 	{
323 		for (LispNode<contents>* n = other.first; n; n = n->cdr)
324 			add_new(n->car);
325 	}
326 
327 
add_new_onceLispList328 	inline void add_new_once(LispList other)
329 	{
330 		for (LispNode<contents>* n = other.first; n; n = n->cdr)
331 			add_new_once(n->car);
332 	}
333 
334 
335 	/* Remove and delete all nodes whose contents are also present
336 	   in a different list (set disjunction). */
rem_delLispList337 	inline void rem_del(LispList other)
338 	{
339 		for (LispNode<contents>* n = other.first; n; n = n->cdr)
340 			rem_del(n->car);
341 	}
342 };
343 
344 template <class thetype>
345 struct DoubleLinkedNode
346 {
347 	thetype* next;
348 	thetype* prev;
349 
DoubleLinkedNodeDoubleLinkedNode350 	DoubleLinkedNode()
351 	{
352 		next = prev = NULL;
353 	}
354 
355 
insert_afterDoubleLinkedNode356 	void insert_after(thetype* n)
357 	{
358 		if (next != NULL)
359 			next->prev = n;
360 
361 		n->next = next;
362 		n->prev = (thetype*)this;
363 		next = n;
364 	}
365 
366 
insert_beforeDoubleLinkedNode367 	void insert_before(thetype* n)
368 	{
369 		prev->next = n;
370 		n->next = (thetype*)this;
371 		n->prev = prev;
372 		prev = n;
373 	}
374 
375 
removeDoubleLinkedNode376 	void remove()
377 	{
378 		assert(prev != NULL);
379 		prev->next = next;
380 
381 		if (next != NULL)
382 			next->prev = prev;
383 	}
384 };
385 
386 
387 template <class thetype>
388 struct DoubleLinkedList : public DoubleLinkedNode<thetype>
389 {
DoubleLinkedListDoubleLinkedList390 	DoubleLinkedList() : DoubleLinkedNode<thetype>() {};
391 
insertDoubleLinkedList392 	void insert(thetype* n)
393 	{
394 		insert_after(n);
395 	}
396 
397 
addDoubleLinkedList398 	void add(thetype* n)
399 	{
400 		insert_after(n);
401 	}
402 };
403 
404 
405 template <class T>
406 struct BufferArray {
407 	T * items;
408 	int num_items;
409 	int num_slots;
410 	int slot_inc;
411 
resizeBufferArray412 	void resize(int i)
413 	{
414 		items = (T*)realloc(items,sizeof(T)*i);
415 		num_slots = i;
416 	}
417 
418 
419 	T & operator [](int index)
420 	{
421 		assert(index < num_items);
422 		return items[index];
423 	}
424 
425 
getBufferArray426 	T & get(int index)
427 	{
428 		assert(index < num_items);
429 		return items[index];
430 	}
431 
432 
addBufferArray433 	void add(T &item)
434 	{
435 		if (num_items == num_slots)
436 			resize(num_slots+slot_inc);
437 
438 		memcpy(items+num_items,&item,sizeof(item));
439 		num_items++;
440 	}
441 
442 
BufferArrayBufferArray443 	BufferArray(int start_slots, int _slot_inc)
444 	{
445 		num_slots = start_slots;
446 		slot_inc = _slot_inc;
447 		assert(slot_inc > 0);
448 		num_items = 0;
449 		items = (T*)malloc(sizeof(T)*num_slots);
450 	}
451 
452 
~BufferArrayBufferArray453 	~BufferArray()
454 	{
455 		free(items);
456 	}
457 };
458 
459 #endif // UTIL_H
460