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