/*_____________________________________________________________________________ |/ / Queue add-on by David "Saturn" van Moolenbroek | Version 0.92, released 14-09-2006 -- support on #help.script/Quakenet | Use/modify however you want, but please keep my name in it. Thank you! | | Keywords: queue, hashtables | | This queue script allows you to easily create, add items to, get items | from, and delete queues. Queues are first-in-first-out: the items come | out of the queue in the order you put them into the queue. Simply put, | items can be queued using the /queue command, and dequeued using the | $queue().next identifier. Internally, this script uses hash tables. | | The script defines the following commands/identifiers: | | /queue [-dwks#] [item] | | Adds an item to the specified queue. | | The -d switch deletes the queue. Note that by default, a queue with no | items is still a queue, it needs to be deleted explicitly in order to | have all of its resources freed. If the -w switch is also specified, the | name field is interpreted as a wildcard and all matching queues are | freed. | | The -k switch tell the queue to delete itself after the last item has | been dequeued. This switch can only be used when the queue is created. | | The -s switch allows you to specify the size of the queue. An attempt | to add more items to the queue will result in an error message. This | switch can only be used when the queue is created. Queues cannot be | resized; however, nothing keeps you from specifying a huge initial size. | The default size is 1000 items. | | $queue(name/N) | | Properties: next, len, size | | This identifier returns information about a queue. If no properties are | specified, it returns the name of the queue if it exists, or the name of | the Nth queue, unless N is zero, in which case it returns the number of | queues. | | The "next" property dequeues and returns the first element from the | queue. The "peek" property returns the first element, but does not | dequeue it. | | The "len" property returns the number of items in the queue. | | The "size" property returns the size of the queue; that is, the total | amount of items that can potentially be stored in this queue. | | $queue(name/N,M) | | This allows you to enumerate the items in a queue. If M is zero, the | number of elements in the queue will be returned. Otherwise, the Mth | item in the queue will be returned, in the order they were added to the | queue. Note that $queue(name,0) is the same as $queue(name).len, and | $queue(name,1) is the same as $queue(name).peek. | | Simple example | | queue myqueue item 1 |\ queue myqueue item 2 | \ queue myqueue item 3 * | while ($queue(myqueue).len) { | echo -a $queue(myqueue).next * | } | * queue -d myqueue \ _\_____________________________________________________________________________ */ alias -l increase return $calc(($hget($1,start) + $2) % $hget($1,size)) alias queue { if ($isid) { ; $queue or $queue(0) if (!$1) return $hget(queue.index,0).item ; if it's a number, look up the matching name if ($1 isnum) var %n = $hget(queue.index,$1).item ; otherwise just use the name else var %n = $1 var %t = $hget(queue.table. $+ %n) ; $queue(N/,N) if ($0 >= 2) { ; only one additional parameter allowed, which should be a number if (($0 >= 3) || ($2 !isnum)) return $null ; if the second parameter is zero, return the item count if (!$2) return $iif(%t,$hget(%t,count),0) ; if the table doesn't exist, or the index is out of range, return nothing if ((!%t) || ($2 < 0) || ($2 > $hget(%t,count))) return $null ; otherwise, return the requested item return $hget(%t,$increase(%t,$2 - 1)) } ; $queue(N/).len if ($prop == len) return $iif(%t,$hget(%t,count),0) ; $queue(N/).size if ($prop == size) return $iif(%t,$hget(%t,size),0) ; we can safely return $null now, if the table doesn't exist if (!%t) return $null ; $queue(N/).next/.peek if (($prop == next) || ($prop == peek)) { ; if there are no items in the queue, we can't return one if (!$hget(%t,count)) return $null ; save the first item into a variable var %r = $hget(%t,$hget(%t,start)) if ($prop == next) { var %c = $calc($hget(%t,count) - 1) ; if no more items are left, and auto-kill is on, delete the queue if ((!%c) && ($hget(%t,kill))) { hfree queue.table. $+ $1 hdel queue.index $1 } ; otherwise, just delete the item and increase the counters else { hdel %t $hget(%t,start) hadd %t start $increase(%t,1) hadd %t count %c } } ; and return the saved item return %r } ; $queue(N/) return %n } var %s = 1000, %o ; parse the options if (-* iswm $1) { %o = $right($1,-1) tokenize 32 $2- if (s isletter %o) { if ($regex(%o,/s(\d+)$/)) %s = $regml(1) elseif (($right(%o,1) === s) && ($1 isnum)) { %s = $1 tokenize 32 $2- } else { echo $color(info) -aeqt * /queue: invalid parameters return } } } ; check if there are enough parameters if ($0 < 1) { echo $color(info) -aeqt * /queue: insufficient parameters return } var %t = queue.table. $+ $1 ; if -d was given, delete the queue(s) if (d isletter %o) { ; if -w was also given, delete all matching queues if (w isletter %o) { hfree -w %t while ($hfind(queue.index,$1,1,w).data) hdel queue.index $ifmatch } ; otherwise just delete one queue else { if (!$hget(%t)) return hfree queue.table. $+ $1 hdel queue.index $1 } ; bail out if there's nothing left to do, or -w was specified if ((($0 < 2) && (k !isletter %o) && (s !isletter %o)) || (w isletter %o)) return } ; if the queue doesn't exist, create it if (!$hget(%t)) { ; create the hashtable, and add it to the index ; short formula thanks to qwerty hmake %t $round($calc(%s ^ (4/5)),0) hadd -m queue.index $1 $1 ; initialize and add the first item hadd %t start 0 hadd %t size %s if ($0 > 1) { hadd %t 0 $2- hadd %t count 1 } else hadd %t count 0 if (k isletter %o) hadd %t kill $true } ; otherwise, merely add the item to it else { ; make sure the queue is not full if ($hget(%t,count) >= $hget(%t,size)) { echo $color(info) -aeqt * /queue: queue is full return } ; add the new item hadd %t $increase(%t,$hget(%t,count)) $2- hadd %t count $calc($hget(%t,count) + 1) } }