2019-10-21 12:24:43 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// LibFile: queues.scad
|
|
|
|
// Queue data structure implementation.
|
|
|
|
// To use, add the following lines to the beginning of your file:
|
|
|
|
// ```
|
|
|
|
// use <BOSL2/std.scad>
|
|
|
|
// use <BOSL2/queues.scad>
|
|
|
|
// ```
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
// Section: Queue Data Structure
|
|
|
|
// A queue is a first-in-first-out collection of items. You can add items onto the tail of the
|
|
|
|
// queue, or pop items off the head. While you can treat a queue as an opaque data type, using the
|
|
|
|
// functions below, it's simply implemented as a list. This means that you can use any list
|
|
|
|
// function to manipulate the queue. The first item in the list is the head queue item.
|
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_init()
|
|
|
|
// Usage:
|
|
|
|
// queue = queue_init();
|
|
|
|
// Description:
|
|
|
|
// Creates an empty queue/list.
|
|
|
|
// Example:
|
|
|
|
// queue = queue_init(); // Return: []
|
|
|
|
function queue_init() = [];
|
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_empty()
|
|
|
|
// Usage:
|
|
|
|
// if (queue_empty(queue)) ...
|
|
|
|
// Description:
|
|
|
|
// Returns true if the given queue is empty.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue to test if empty.
|
|
|
|
// Example:
|
|
|
|
// queue = queue_init();
|
|
|
|
// is_empty = queue_empty(queue); // Returns: true
|
|
|
|
// queue2 = queue_add(queue, "foo");
|
|
|
|
// is_empty2 = queue_empty(queue2); // Returns: false
|
|
|
|
function queue_empty(queue) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
len(queue)==0;
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_size()
|
|
|
|
// Usage:
|
|
|
|
// depth = queue_size(queue);
|
|
|
|
// Description:
|
|
|
|
// Returns the number of items in the given queue.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue to get the size of.
|
|
|
|
// Example:
|
|
|
|
// queue = queue_init();
|
|
|
|
// depth = queue_size(queue); // Returns: 0
|
|
|
|
// queue2 = queue_add(queue, "foo");
|
|
|
|
// depth2 = queue_size(queue2); // Returns: 1
|
|
|
|
// queue3 = queue_add(queue2, ["bar","baz","qux"]);
|
|
|
|
// depth3 = queue_size(queue3); // Returns: 4
|
|
|
|
function queue_size(queue) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
len(queue);
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_head()
|
|
|
|
// Usage:
|
|
|
|
// item = queue_head(queue);
|
|
|
|
// list = queue_head(queue,n);
|
|
|
|
// Description:
|
|
|
|
// If `n` is not given, returns the first item from the head of the queue.
|
|
|
|
// If `n` is given, returns a list of the first `n` items from the head of the queue.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue/list to get item(s) from the head of.
|
|
|
|
// Example:
|
|
|
|
// queue = [4,5,6,7,8,9];
|
|
|
|
// item = queue_head(queue); // Returns: 4
|
|
|
|
// list = queue_head(queue,n=3); // Returns: [4,5,6]
|
|
|
|
function queue_head(queue,n=undef) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
is_undef(n)? (
|
|
|
|
queue[0]
|
|
|
|
) : (
|
|
|
|
let(queuesize = len(queue))
|
|
|
|
assert(is_num(n))
|
|
|
|
assert(n>=0)
|
|
|
|
assert(queuesize>=n, "queue underflow")
|
|
|
|
[for (i=[0:1:n-1]) queue[i]]
|
|
|
|
);
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_tail()
|
|
|
|
// Usage:
|
|
|
|
// item = queue_tail(queue);
|
|
|
|
// list = queue_tail(queue,n);
|
|
|
|
// Description:
|
|
|
|
// If `n` is not given, returns the last item from the tail of the queue.
|
|
|
|
// If `n` is given, returns a list of the last `n` items from the tail of the queue.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue/list to get item(s) from the tail of.
|
|
|
|
// Example:
|
|
|
|
// queue = [4,5,6,7,8,9];
|
|
|
|
// item = queue_tail(queue); // Returns: 9
|
|
|
|
// list = queue_tail(queue,n=3); // Returns: [7,8,9]
|
|
|
|
function queue_tail(queue,n=undef) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
let(queuesize = len(queue))
|
|
|
|
is_undef(n)? (
|
|
|
|
queue[queuesize-1]
|
|
|
|
) : (
|
|
|
|
assert(is_num(n))
|
|
|
|
assert(n>=0)
|
|
|
|
assert(queuesize>=n, "queue underflow")
|
|
|
|
[for (i=[0:1:n-1]) queue[queuesize-n+i]]
|
|
|
|
);
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_peek()
|
|
|
|
// Usage:
|
|
|
|
// item = queue_peek(queue,[pos]);
|
|
|
|
// list = queue_peek(queue,pos,n);
|
|
|
|
// Description:
|
|
|
|
// If `n` is not given, returns the queue item at position `pos`.
|
|
|
|
// If `n` is given, returns a list of the `n` queue items at and after position `pos`.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue to read from.
|
|
|
|
// pos = The position of the queue item to read. Default: 0
|
|
|
|
// n = The number of queue items to return. Default: undef (Return only the queue item at `pos`)
|
|
|
|
// Example:
|
|
|
|
// queue = [2,3,4,5,6,7,8,9];
|
|
|
|
// item = queue_peek(queue); // Returns: 2
|
|
|
|
// item2 = queue_peek(queue, 3); // Returns: 5
|
|
|
|
// list = queue_peek(queue, 4, 3); // Returns: [6,7,8]
|
|
|
|
function queue_peek(queue,pos=0,n=undef) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
assert(is_num(pos))
|
|
|
|
assert(pos>=0)
|
|
|
|
let(queuesize = len(queue))
|
|
|
|
assert(queuesize>=pos, "queue underflow")
|
|
|
|
is_undef(n)? (
|
|
|
|
queue[pos]
|
|
|
|
) : (
|
|
|
|
assert(is_num(n))
|
|
|
|
assert(n>=0)
|
|
|
|
assert(n<queuesize-pos)
|
|
|
|
[for (i=[0:1:n-1]) queue[pos+i]]
|
|
|
|
);
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_add()
|
|
|
|
// Usage:
|
|
|
|
// modified_queue = queue_add(queue,items);
|
|
|
|
// Description:
|
|
|
|
// Adds the given `items` onto the queue `queue`. Returns the modified queue.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue to modify.
|
|
|
|
// items = A value or list of values to add to the queue.
|
|
|
|
// Example:
|
|
|
|
// queue = [4,9,2,3];
|
|
|
|
// queue2 = queue_add(queue,7); // Returns: [4,9,2,3,7]
|
|
|
|
// queue3 = queue_add(queue2,[6,1]); // Returns: [4,9,2,3,7,6,1]
|
|
|
|
// queue4 = queue_add(queue,[[5,8]]); // Returns: [4,9,2,3,[5,8]]
|
|
|
|
// queue5 = queue_add(queue,[[5,8],6,7]); // Returns: [4,9,2,3,[5,8],6,7]
|
|
|
|
// Example: Typical Producer and Consumer
|
|
|
|
// q2 = queue_add(q, "foo");
|
|
|
|
// ...
|
|
|
|
// val = queue_head(q2);
|
|
|
|
// q3 = queue_pop(q2);
|
|
|
|
function queue_add(queue,items) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
is_list(items)? concat(queue, items) : concat(queue, [items]);
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Function: queue_pop()
|
|
|
|
// Usage:
|
|
|
|
// modified_queue = queue_pop(queue, [n]);
|
|
|
|
// Description:
|
|
|
|
// Removes `n` items from the head of the queue. Returns the modified queue.
|
|
|
|
// Arguments:
|
|
|
|
// queue = The queue to modify.
|
|
|
|
// n = The number of items to remove from the head of the queue. Default: 1
|
|
|
|
// Example:
|
|
|
|
// queue = [4,5,6,7,8,9];
|
|
|
|
// queue2 = queue_pop(queue); // Returns: [5,6,7,8,9]
|
|
|
|
// queue3 = queue_pop(queue2,n=3); // Returns: [8,9]
|
|
|
|
// Example: Typical Producer and Consumer
|
|
|
|
// q2 = queue_add(q, "foo");
|
|
|
|
// ...
|
|
|
|
// val = queue_head(q2);
|
|
|
|
// q3 = queue_pop(q2);
|
|
|
|
function queue_pop(queue,n=1) =
|
2020-05-30 02:04:34 +00:00
|
|
|
assert(is_list(queue))
|
|
|
|
assert(is_num(n))
|
|
|
|
assert(n>=0)
|
|
|
|
let(queuesize = len(queue))
|
|
|
|
assert(queuesize>=n, "queue underflow")
|
|
|
|
[for (i = [n:1:queuesize-1]) queue[i]];
|
2019-10-21 12:24:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-05-30 02:04:34 +00:00
|
|
|
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|