mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Implemented a nearly generic Queue in scriptland.
This commit is contained in:
parent
257b460b18
commit
5b81cfe7e2
4 changed files with 224 additions and 0 deletions
|
@ -12,6 +12,7 @@
|
||||||
@load base/utils/numbers
|
@load base/utils/numbers
|
||||||
@load base/utils/paths
|
@load base/utils/paths
|
||||||
@load base/utils/patterns
|
@load base/utils/patterns
|
||||||
|
@load base/utils/queue
|
||||||
@load base/utils/strings
|
@load base/utils/strings
|
||||||
@load base/utils/thresholds
|
@load base/utils/thresholds
|
||||||
@load base/utils/urls
|
@load base/utils/urls
|
||||||
|
|
177
scripts/base/utils/queue.bro
Normal file
177
scripts/base/utils/queue.bro
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
##! A FIFO string queue.
|
||||||
|
|
||||||
|
module Queue;
|
||||||
|
|
||||||
|
export {
|
||||||
|
## Settings for initializing the queue.
|
||||||
|
type Settings: record {
|
||||||
|
## If a maximum length is set for the queue
|
||||||
|
## it will maintain itself at that
|
||||||
|
## maximum length automatically.
|
||||||
|
max_len: count &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
## The internal data structure for the queue.
|
||||||
|
type Queue: record {};
|
||||||
|
|
||||||
|
## Initialize a queue record structure.
|
||||||
|
##
|
||||||
|
## s: A :bro:record:`Settings` record configuring the queue.
|
||||||
|
##
|
||||||
|
## Returns: An opaque queue record.
|
||||||
|
global init: function(s: Settings): Queue;
|
||||||
|
|
||||||
|
## Push a string onto the top of a queue.
|
||||||
|
##
|
||||||
|
## q: The queue to push the string into.
|
||||||
|
##
|
||||||
|
## val: The string to push
|
||||||
|
global push: function(q: Queue, val: any);
|
||||||
|
|
||||||
|
## Pop a string from the bottom of a queue.
|
||||||
|
##
|
||||||
|
## q: The queue to pop the string from.
|
||||||
|
##
|
||||||
|
## Returns: The string popped from the queue.
|
||||||
|
global pop: function(q: Queue): any;
|
||||||
|
|
||||||
|
## Merge two queue's together. If any settings are applied
|
||||||
|
## to the queues, the settings from q1 are used for the new
|
||||||
|
## merged queue.
|
||||||
|
##
|
||||||
|
## q1: The first queue. Settings are taken from here.
|
||||||
|
##
|
||||||
|
## q2: The second queue.
|
||||||
|
##
|
||||||
|
## Returns: A new queue from merging the other two together.
|
||||||
|
global merge: function(q1: Queue, q2: Queue): Queue;
|
||||||
|
|
||||||
|
## Get the number of items in a queue.
|
||||||
|
##
|
||||||
|
## q: The queue.
|
||||||
|
##
|
||||||
|
## Returns: The length of the queue.
|
||||||
|
global len: function(q: Queue): count;
|
||||||
|
|
||||||
|
## Get the contents of the queue as a string vector.
|
||||||
|
##
|
||||||
|
## q: The queue.
|
||||||
|
##
|
||||||
|
## Returns: A :bro:type:`vector of string` containing the
|
||||||
|
## current contents of q.
|
||||||
|
global get_str_vector: function(q: Queue): vector of string;
|
||||||
|
|
||||||
|
## Get the contents of the queue as a count vector. Use care
|
||||||
|
## with this function. If the data put into the queue wasn't
|
||||||
|
## integers you will get conversion errors.
|
||||||
|
##
|
||||||
|
## q: The queue.
|
||||||
|
##
|
||||||
|
## Returns: A :bro:type:`vector of count` containing the
|
||||||
|
## current contents of q.
|
||||||
|
global get_cnt_vector: function(q: Queue): vector of count;
|
||||||
|
}
|
||||||
|
|
||||||
|
redef record Queue += {
|
||||||
|
# Indicator for if the queue was appropriately initialized.
|
||||||
|
initialized: bool &default=F;
|
||||||
|
# The values are stored here.
|
||||||
|
vals: table[count] of any &optional;
|
||||||
|
# Settings for the queue.
|
||||||
|
settings: Settings &optional;
|
||||||
|
# The top value in the vals table.
|
||||||
|
top: count &default=0;
|
||||||
|
# The bottom value in the vals table.
|
||||||
|
bottom: count &default=0;
|
||||||
|
# The number of bytes in the queue.
|
||||||
|
size: count &default=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(s: Settings): Queue
|
||||||
|
{
|
||||||
|
local q: Queue;
|
||||||
|
q$vals=table();
|
||||||
|
q$settings = copy(s);
|
||||||
|
q$initialized=T;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
function push(q: Queue, val: any)
|
||||||
|
{
|
||||||
|
if ( q$settings?$max_len && len(q) >= q$settings$max_len )
|
||||||
|
pop(q);
|
||||||
|
q$vals[q$top] = val;
|
||||||
|
++q$top;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pop(q: Queue): any
|
||||||
|
{
|
||||||
|
local ret = q$vals[q$bottom];
|
||||||
|
delete q$vals[q$bottom];
|
||||||
|
++q$bottom;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge(q1: Queue, q2: Queue): Queue
|
||||||
|
{
|
||||||
|
local ret = init(q1$settings);
|
||||||
|
local i = q1$bottom;
|
||||||
|
local j = q2$bottom;
|
||||||
|
for ( ignored_val in q1$vals )
|
||||||
|
{
|
||||||
|
if ( i in q1$vals )
|
||||||
|
push(ret, q1$vals[i]);
|
||||||
|
if ( j in q2$vals )
|
||||||
|
push(ret, q2$vals[j]);
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function len(q: Queue): count
|
||||||
|
{
|
||||||
|
return |q$vals|;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_str_vector(q: Queue): vector of string
|
||||||
|
{
|
||||||
|
local ret: vector of string;
|
||||||
|
local i = q$bottom;
|
||||||
|
local j = 0;
|
||||||
|
# Really dumb hack, this is only to provide
|
||||||
|
# the iteration for the correct number of
|
||||||
|
# values in q$vals.
|
||||||
|
for ( ignored_val in q$vals )
|
||||||
|
{
|
||||||
|
if ( i >= q$top )
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret[j] = cat(q$vals[i]);
|
||||||
|
++j; ++i;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_cnt_vector(q: Queue): vector of count
|
||||||
|
{
|
||||||
|
local ret: vector of count;
|
||||||
|
local i = q$bottom;
|
||||||
|
local j = 0;
|
||||||
|
# Really dumb hack, this is only to provide
|
||||||
|
# the iteration for the correct number of
|
||||||
|
# values in q$vals.
|
||||||
|
for ( ignored_val in q$vals )
|
||||||
|
{
|
||||||
|
if ( i >= q$top )
|
||||||
|
break;
|
||||||
|
|
||||||
|
# TODO: this is terrible and should be replaced by
|
||||||
|
# a more generic version of the various
|
||||||
|
# functions to get vectors of values.
|
||||||
|
# (the way "any" works right now makes this impossible though)
|
||||||
|
ret[j] = to_count(cat(q$vals[i]));
|
||||||
|
++j; ++i;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
11
testing/btest/Baseline/scripts.base.utils.queue/output
Normal file
11
testing/btest/Baseline/scripts.base.utils.queue/output
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
This is a get_cnt_vector test: 3
|
||||||
|
This is a get_cnt_vector test: 4
|
||||||
|
This is a get_str_vector test: 3
|
||||||
|
This is a get_str_vector test: 4
|
||||||
|
Testing pop: 3
|
||||||
|
Length after pop: 1
|
||||||
|
Size of q2: 4
|
||||||
|
String queue value: test 1
|
||||||
|
String queue value: test 2
|
||||||
|
String queue value: test 2
|
||||||
|
String queue value: test 1
|
35
testing/btest/scripts/base/utils/queue.test
Normal file
35
testing/btest/scripts/base/utils/queue.test
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT > output
|
||||||
|
# @TEST-EXEC: btest-diff output
|
||||||
|
|
||||||
|
# This is loaded by default
|
||||||
|
@load base/utils/queue
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
local q = Queue::init([$max_len=2]);
|
||||||
|
Queue::push(q, 1);
|
||||||
|
Queue::push(q, 2);
|
||||||
|
Queue::push(q, 3);
|
||||||
|
Queue::push(q, 4);
|
||||||
|
local test1 = Queue::get_cnt_vector(q);
|
||||||
|
for ( i in test1 )
|
||||||
|
print fmt("This is a get_cnt_vector test: %d", test1[i]);
|
||||||
|
|
||||||
|
local test2 = Queue::get_str_vector(q);
|
||||||
|
for ( i in test2 )
|
||||||
|
print fmt("This is a get_str_vector test: %s", test2[i]);
|
||||||
|
|
||||||
|
local test_val = Queue::pop(q);
|
||||||
|
print fmt("Testing pop: %s", test_val);
|
||||||
|
print fmt("Length after pop: %d", Queue::len(q));
|
||||||
|
|
||||||
|
local q2 = Queue::init([]);
|
||||||
|
Queue::push(q2, "test 1");
|
||||||
|
Queue::push(q2, "test 2");
|
||||||
|
Queue::push(q2, "test 2");
|
||||||
|
Queue::push(q2, "test 1");
|
||||||
|
print fmt("Size of q2: %d", Queue::len(q2));
|
||||||
|
local test3: vector of string = Queue::get_str_vector(q2);
|
||||||
|
for ( i in test3 )
|
||||||
|
print fmt("String queue value: %s", test3[i]);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue