* sortloot() - the story so far... * * The original implementation constructed and returned an array * of pointers to objects in the requested order. Callers had to * count the number of objects, allocate the array, pass one * object at a time to the routine which populates it, traverse * the objects via stepping through the array, then free the * array. The
| 590 | * instead of simple 'struct obj *' entries. |
| 591 | */ |
| 592 | Loot * |
| 593 | sortloot( |
| 594 | struct obj **olist, /* old version might have changed *olist, we don't */ |
| 595 | unsigned mode, /* flags for sortloot_cmp() */ |
| 596 | boolean by_nexthere, /* T: traverse via obj->nexthere, F: via obj->nobj */ |
| 597 | boolean (*filterfunc)(struct obj *)) /* optional filter */ |
| 598 | { |
| 599 | static Loot zerosli; |
| 600 | Loot *sliarray; |
| 601 | struct obj *o; |
| 602 | unsigned n, i; |
| 603 | boolean augment_filter; |
| 604 | |
| 605 | for (n = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj) |
| 606 | ++n; |
| 607 | /* note: if there is a filter function, this might overallocate */ |
| 608 | sliarray = (Loot *) alloc((n + 1) * sizeof *sliarray); |
| 609 | |
| 610 | /* the 'keep cockatrice corpses' flag is overloaded with sort mode */ |
| 611 | augment_filter = (mode & SORTLOOT_PETRIFY) ? TRUE : FALSE; |
| 612 | mode &= ~SORTLOOT_PETRIFY; /* remove flag, leaving mode */ |
| 613 | /* populate aliarray[0..n-1] */ |
| 614 | for (i = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj) { |
| 615 | if (filterfunc && !(*filterfunc)(o) |
| 616 | /* caller may be asking us to override filterfunc (in order |
| 617 | to do a cockatrice corpse touch check during pickup even |
| 618 | if/when the filter rejects food class) */ |
| 619 | && (!augment_filter || o->otyp != CORPSE |
| 620 | || !touch_petrifies(&mons[o->corpsenm]))) |
| 621 | continue; |
| 622 | sliarray[i] = zerosli; |
| 623 | sliarray[i].obj = o, sliarray[i].indx = (int) i; |
| 624 | ++i; |
| 625 | } |
| 626 | n = i; |
| 627 | /* add a terminator so that we don't have to pass 'n' back to caller */ |
| 628 | sliarray[n] = zerosli; |
| 629 | sliarray[n].indx = -1; |
| 630 | |
| 631 | /* do the sort; if no sorting is requested, we'll just return |
| 632 | a sortloot_item array reflecting the current ordering */ |
| 633 | if (mode && n > 1) { |
| 634 | gs.sortlootmode = mode; /* extra input for sortloot_cmp() */ |
| 635 | qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp); |
| 636 | gs.sortlootmode = 0; /* reset static mode flags */ |
| 637 | /* if sortloot_cmp formatted any objects, discard their strings now */ |
| 638 | for (i = 0; i < n; ++i) |
| 639 | if (sliarray[i].str) |
| 640 | free((genericptr_t) sliarray[i].str), sliarray[i].str = 0; |
| 641 | } |
| 642 | return sliarray; |
| 643 | } |
| 644 | |
| 645 | /* sortloot() callers should use this to free up memory it allocates */ |
| 646 | void |
no test coverage detected