1 /************************************************************************* 2 * 3 *N Module LINKLIST.C 4 * 5 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 6 * 7 * Purpose: 8 *P 9 * This module contains functions that make up a singly linked list 10 * data structure. It is generic in the sense that it can hold any 11 * type of data, including user-defined types and structures. That 12 * is why you must treat the data element as a void pointer and pass 13 * in its size when inserting into the list. These routines are 14 * assured of working with "non-pointer" types of data elements. 15 * If you try storing other lists, or structures with pointers hanging 16 * off of them, the results will become unpredictable. 17 *E 18 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 19 * 20 * Parameters: 21 *A 22 * N/A 23 *E 24 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 25 * 26 * History: 27 *H 28 * Barry Michaels Feb. 1990 DOS Turbo C 29 *E 30 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 31 * 32 * External Variables: 33 *X 34 * None 35 *E 36 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 37 * 38 * Functions Called: 39 *F 40 * linked_list_type ll_init(); 41 * int ll_empty( linked_list_type list ); 42 * position_type ll_first( linked_list_type list ); 43 * position_type ll_last( linked_list_type list ); 44 * position_type ll_next( position_type position ); 45 * position_type ll_previous( position_type position, linked_list_type 46 * list ); 47 * int ll_end( position_type position ); 48 * void ll_element( position_type position, void *element ); 49 * void ll_insert( void *element, unsigned size, position_type position ); 50 * void ll_delete( position_type position ); 51 * void ll_reset( linked_list_type list ); 52 * position_type ll_locate( void *element, linked_list_type list ); 53 * void ll_replace( void *element, position_type position ); 54 *E 55 *************************************************************************/ 56 #ifdef __MSDOS__ 57 #include <alloc.h> 58 #include <mem.h> 59 #else 60 #ifdef __APPLE__ 61 #include <sys/types.h> 62 #include <sys/malloc.h> 63 #else 64 #if !defined(__OpenBSD__) && !defined( __FreeBSD__) 65 #include <malloc.h> 66 #include <string.h> 67 #endif 68 #endif 69 #endif 70 71 #include <stdio.h> 72 #include <stdlib.h> 73 #include <ossim/vpfutil/linklist.h> 74 #include <string.h> 75 76 #ifndef __MSDOS__ 77 #define farmalloc malloc 78 #define farfree free 79 #define movmem(a,b,c) memmove(b,a,c) 80 #endif 81 82 /************************************************************************* 83 * 84 *N ll_init 85 * 86 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 87 * 88 * Purpose: 89 *P 90 * This function allocates and initializes a new linked list structure. 91 *E 92 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 93 * 94 * Parameters: 95 *A 96 * ll_init <output> == (linked_list_type) initialized head of the list. 97 *E 98 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 99 * 100 * History: 101 *H 102 * Barry Michaels Feb. 1990 DOS Turbo C 103 *E 104 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 105 * 106 * External Variables: 107 *X 108 * None 109 *E 110 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 111 * 112 * Functions Called: 113 *F 114 * None 115 *E 116 *************************************************************************/ 117 linked_list_type ll_init() 118 { 119 linked_list_type list; 120 121 if ((list = (linked_list_type) farmalloc( sizeof(cell_type) ))==NULL) { 122 printf("Out of memory in ll_init()\n"); 123 exit(1); 124 } 125 list->element = NULL; 126 list->element_size = 0; 127 list->next = NULL; 128 return list; 129 } 130 131 132 /************************************************************************* 133 * 134 *N ll_empty 135 * 136 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 137 * 138 * Purpose: 139 *P 140 * This function TRUE if the list is empty and FALSE if it is not. 141 *E 142 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 143 * 144 * Parameters: 145 *A 146 * list <input> == (linked_list_type) linked list being checked. 147 * ll_empty <output> == (int) boolean function result. 148 *E 149 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 150 * 151 * History: 152 *H 153 * Barry Michaels Feb. 1990 DOS Turbo C 154 *E 155 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 156 * 157 * External Variables: 158 *X 159 * None 160 *E 161 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 162 * 163 * Functions Called: 164 *F 165 * None 166 *E 167 *************************************************************************/ 168 int ll_empty( linked_list_type list ) 169 { 170 if (list == NULL) return TRUE; 171 if (list->next == NULL) 172 return TRUE; 173 else 174 return FALSE; 175 } 176 177 178 /************************************************************************* 179 * 180 *N ll_first 181 * 182 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 183 * 184 * Purpose: 185 *P 186 * This function returns the head of the list. 187 *E 188 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 189 * 190 * Parameters: 191 *A 192 * list <input> == (linked_list_type) linked list. 193 * ll_first <output> == (position_type) head of the list. 194 *E 195 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 196 * 197 * History: 198 *H 199 * Barry Michaels Feb. 1990 DOS Turbo C 200 *E 201 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 202 * 203 * External Variables: 204 *X 205 * None 206 *E 207 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 208 * 209 * Functions Called: 210 *F 211 * None 212 *E 213 *************************************************************************/ 214 position_type ll_first( linked_list_type list ) 215 { 216 return ((position_type) list); 217 } 218 219 220 /************************************************************************* 221 * 222 *N ll_last 223 * 224 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 225 * 226 * Purpose: 227 *P 228 * This function returns *THE* last position in the list, which is 229 * not useable. Use ll_previous to get to the las USEABLE link in 230 * the list. 231 *E 232 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 233 * 234 * Parameters: 235 *A 236 * list <input> == (linked_list_type) linked list. 237 * ll_last <output> == (position_type) tail of the list. 238 *E 239 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 240 * 241 * History: 242 *H 243 * Barry Michaels Feb. 1990 DOS Turbo C 244 *E 245 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 246 * 247 * External Variables: 248 *X 249 * None 250 *E 251 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 252 * 253 * Functions Called: 254 *F 255 * None 256 *E 257 *************************************************************************/ 258 position_type ll_last( linked_list_type list ) 259 { 260 position_type p; 261 262 p = (position_type) list; 263 while (p->next != NULL) 264 p = p->next; 265 return p; 266 } 267 268 269 /************************************************************************* 270 * 271 *N ll_next 272 * 273 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 274 * 275 * Purpose: 276 *P 277 * This function returns the next position in the list. 278 *E 279 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 280 * 281 * Parameters: 282 *A 283 * position <input> == (position_type) current position in the list. 284 * ll_next <output> == (position_type) next position in the list. 285 *E 286 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 287 * 288 * History: 289 *H 290 * Barry Michaels Feb. 1990 DOS Turbo C 291 *E 292 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 293 * 294 * External Variables: 295 *X 296 * None 297 *E 298 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 299 * 300 * Functions Called: 301 *F 302 * None 303 *E 304 *************************************************************************/ 305 position_type ll_next( position_type position ) 306 { 307 return(position->next); 308 } 309 310 311 /************************************************************************* 312 * 313 *N ll_previous 314 * 315 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 316 * 317 * Purpose: 318 *P 319 * This function returns the previous position in the list. Note: 320 * This is a singly linked list -> no backward pointer -> this 321 * operation is relatively inefficient. 322 *E 323 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 324 * 325 * Parameters: 326 *A 327 * position <input> == (position_type) current position. 328 * list <input> == (linked_list_type) linked list. 329 * ll_previous <output> == (position_type) previous position in the list. 330 *E 331 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 332 * 333 * History: 334 *H 335 * Barry Michaels Feb. 1990 DOS Turbo C 336 *E 337 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 338 * 339 * External Variables: 340 *X 341 * None 342 *E 343 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 344 * 345 * Functions Called: 346 *F 347 * None 348 *E 349 *************************************************************************/ 350 position_type ll_previous( position_type position, 351 linked_list_type list ) 352 { 353 position_type p; 354 355 if (position==list) return(position); 356 p = list; 357 while (p->next != position) 358 p = p->next; 359 return(p); 360 } 361 362 363 /************************************************************************* 364 * 365 *N ll_end 366 * 367 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 368 * 369 * Purpose: 370 *P 371 * This function determines if the given position is at the end of the 372 * list. 373 *E 374 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 375 * 376 * Parameters: 377 *A 378 * position <input> == (position_type) current position in the list. 379 * ll_end <output> == (int) TRUE -- if position is the end of the list. 380 * FALSE -- if not. 381 *E 382 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 383 * 384 * History: 385 *H 386 * Barry Michaels Feb. 1990 DOS Turbo C 387 *E 388 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 389 * 390 * External Variables: 391 *X 392 * None 393 *E 394 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 395 * 396 * Functions Called: 397 *F 398 * None 399 *E 400 *************************************************************************/ 401 int ll_end( position_type position ) 402 { 403 if (position == NULL) 404 return(TRUE); 405 else { 406 if (position->next == NULL) 407 return(TRUE); 408 else 409 return(FALSE); 410 } 411 } 412 413 414 /************************************************************************* 415 * 416 *N ll_element 417 * 418 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 419 * 420 * Purpose: 421 *P 422 * This function copies the element at position in the list into the 423 * contents of element. 424 *E 425 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 426 * 427 * Parameters: 428 *A 429 * position <input> == (position_type) position in the list. 430 * element <output> == (void *) pointer to the element data. 431 *E 432 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 433 * 434 * History: 435 *H 436 * Barry Michaels Feb. 1990 DOS Turbo C 437 *E 438 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 439 * 440 * External Variables: 441 *X 442 * None 443 *E 444 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 445 * 446 * Functions Called: 447 *F 448 * None 449 *E 450 *************************************************************************/ 451 void ll_element( position_type position, 452 void *element ) 453 { 454 movmem(position->next->element,element,position->next->element_size); 455 } 456 457 /************************************************************************* 458 * 459 *N ll_insert 460 * 461 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 462 * 463 * Purpose: 464 *P 465 * This function inserts a new cell into the list at position that will 466 * contain the data pointed to by element. 467 *E 468 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 469 * 470 * Parameters: 471 *A 472 * element <input> == (void *) pointer to the data element to insert. 473 * size <input> == (unsigned) size of the data element. 474 * position <input> == (position_type) position to insert the new cell. 475 *E 476 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 477 * 478 * History: 479 *H 480 * Barry Michaels Feb. 1990 DOS Turbo C 481 *E 482 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 483 * 484 * External Variables: 485 *X 486 * None 487 *E 488 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 489 * 490 * Functions Called: 491 *F 492 * None 493 *E 494 *************************************************************************/ 495 void ll_insert( void *element, 496 unsigned size, 497 position_type position ) 498 { 499 position_type temp; 500 501 if ((temp = (position_type) farmalloc( sizeof(cell_type) )) == NULL) { 502 printf("out of memory\n"); 503 abort(); 504 } 505 temp->next = position->next; 506 position->next = temp; 507 temp->element_size = size; 508 if ((temp->element = farmalloc( size ))==NULL) { 509 printf("out of memory\n"); 510 abort(); 511 } 512 movmem(element,temp->element,size); 513 514 } 515 516 517 /************************************************************************* 518 * 519 *N ll_delete 520 * 521 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 522 * 523 * Purpose: 524 *P 525 * This function deletes and disposes of a cell from the linked list. 526 *E 527 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 528 * 529 * Parameters: 530 *A 531 * position <input> == (position_type) position in the list to delete. 532 *E 533 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 534 * 535 * History: 536 *H 537 * Barry Michaels Feb. 1990 DOS Turbo C 538 *E 539 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 540 * 541 * External Variables: 542 *X 543 * None 544 *E 545 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 546 * 547 * Functions Called: 548 *F 549 * None 550 *E 551 *************************************************************************/ 552 void ll_delete( position_type position ) 553 { 554 position_type p; 555 556 if (position != NULL) { /* Cut the element out of the chain */ 557 p = position->next; 558 position->next = p->next; 559 farfree( p->element ); 560 farfree( p ); 561 } 562 } 563 564 565 566 567 /************************************************************************* 568 * 569 *N ll_reset 570 * 571 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 572 * 573 * Purpose: 574 *P 575 * This function empties out a linked list. 576 *E 577 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 578 * 579 * Parameters: 580 *A 581 * list <inout> == (linked_list_type) linked list to be emptied. 582 *E 583 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 584 * 585 * History: 586 *H 587 * Barry Michaels Feb. 1990 DOS Turbo C 588 *E 589 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 590 * 591 * External Variables: 592 *X 593 * None 594 *E 595 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 596 * 597 * Functions Called: 598 *F 599 * void ll_delete( position_type position ); 600 * int ll_empty( linked_list_type list ); 601 *E 602 *************************************************************************/ 603 void ll_reset( linked_list_type list ) 604 { 605 while (! ll_empty(list)) 606 ll_delete(ll_first(list)); 607 farfree(list); 608 list = NULL; 609 } 610 611 612 613 /************************************************************************* 614 * 615 *N ll_locate 616 * 617 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 618 * 619 * Purpose: 620 *P 621 * This function locates a position in the list by comparing data. 622 *E 623 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 624 * 625 * Parameters: 626 *A 627 * element <input> == (void *) pointer to the data element to locate. 628 * list <input> == (linked_list_type) linked list. 629 *E 630 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 631 * 632 * History: 633 *H 634 * Barry Michaels Feb. 1990 DOS Turbo C 635 *E 636 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 637 * 638 * External Variables: 639 *X 640 * None 641 *E 642 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 643 * 644 * Functions Called: 645 *F 646 * None 647 *E 648 *************************************************************************/ 649 position_type ll_locate( void *element, 650 linked_list_type list ) 651 { 652 position_type p; 653 654 p = list; 655 while (p->next != NULL) { 656 if ( memcmp(p->next->element,element,p->next->element_size) == 0 ) 657 return p; 658 else 659 p = p->next; 660 } 661 return NULL; 662 } 663 664 665 /************************************************************************* 666 * 667 *N ll_replace 668 * 669 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 670 * 671 * Purpose: 672 *P 673 * This function replaces an element in the linked list at the given 674 * position. WARNING: The new data element must be the same size as 675 * the previous data element or you will get some rather INTERESTING 676 * results. 677 *E 678 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 679 * 680 * Parameters: 681 *A 682 * element <input> == (void *) data element to replace existing data. 683 * position <input> == (position_type) position in the list to replace 684 * the data. 685 *E 686 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 687 * 688 * History: 689 *H 690 * Barry Michaels Feb. 1990 DOS Turbo C 691 *E 692 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 693 * 694 * External Variables: 695 *X 696 * None 697 *E 698 *:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 699 * 700 * Functions Called: 701 *F 702 * None 703 *E 704 *************************************************************************/ 705 void ll_replace( void *element, 706 position_type position ) 707 { 708 movmem(element,position->next->element,position->next->element_size); 709 } 710 711 712 713