1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
# This package provides a list of all things in the moo, and allows you
# to look up things by number and by type, etc. (Actually, it's not a
# list, it's a hash, but don't tell anyone outside this package. ;-)
package ThingList;
use UNIVERSAL qw(isa);
use strict;
# Here's the hash of things.
my %thinglist=();
# This is a function that just returns a reference to the thing that has
# a specified id number.
sub FindByNum {
my $num=shift;
return $thinglist{$num};
}
# Given the name of a thing, and (optionally) that thing's type, returns
# the things of that type with that name or alias. If called in a scalar
# context, returns only the first one found. If called in a list context,
# returns all of them. This is a case insensitive search.
sub FindByName {
my $name=lc(shift);
my $type=shift;
my @ret=();
my $id;
foreach $id (sort {$a <=> $b} keys %thinglist) {
next if ($type && ! isa($thinglist{$id},$type));
if ($thinglist{$id}->isalias($name)) {
if (!wantarray) {
return $thinglist{$id}
}
else {
push @ret,$thinglist{$id};
}
}
}
if (!wantarray) {
return undef;
}
else {
return @ret;
}
}
# Returns all things, (or just the first if called in scalar context).
sub All {
FindByType();
}
# Given an object type, returns things of that type. If called in a scalar
# context, returns only the first one found. If called in a list context,
# returns all of them. If you don't pass it a type, it operates on all things.
sub FindByType {
my $type=shift || "Thing";
# Minor optimization..
if ($type eq "Thing" && wantarray) {
return values %thinglist
}
my @ret=();
my $id;
foreach $id (sort {$a <=> $b} keys %thinglist) {
if (isa($thinglist{$id},$type)) {
if (!wantarray) {
return $thinglist{$id};
}
else {
push @ret,$thinglist{$id};
}
}
}
if (!wantarray) {
return undef;
}
else {
return @ret;
}
}
# Passed a new thing, adds it to the list. The things should already have it's
# id set. Returns the thing.
sub add {
my $thing=shift;
$thinglist{$thing->id}=$thing;
}
# Remove the thing from the list. Note that if this isn't called, an object
# will never really go away, since there will still be a reference to it
# on the list.
sub remove {
my $thing=shift;
delete $thinglist{$thing->id};
}
# This just returns a suggested id that's free on the thinglist, for objects
# that don't care what their id is.
sub GetId {
# TODO: Should do this more efficiently - I know i can do it in
# O(n), and I suspect it's possible to do it quicker than that.
# This is O(n log n), of course:
my @list=sort { $a <=> $b } (keys %thinglist);
return $list[$#list]+1;
}
1
|