2019-11-09 02:05:41 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// LibFile: structs.scad
|
2022-04-07 20:38:28 +00:00
|
|
|
// This file provides manipulation of "structs". A "struct" is a data structure that
|
2022-04-21 04:26:20 +00:00
|
|
|
// associates arbitrary keys with values and allows you to get and set values
|
2023-03-15 07:31:40 +00:00
|
|
|
// by key.
|
2021-01-05 09:20:01 +00:00
|
|
|
// Includes:
|
|
|
|
// include <BOSL2/std.scad>
|
|
|
|
// include <BOSL2/structs.scad>
|
2021-12-13 23:48:30 +00:00
|
|
|
// FileGroup: Data Management
|
|
|
|
// FileSummary: Structure/Dictionary Manipulation
|
2019-11-09 02:05:41 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
2019-06-12 02:50:50 +00:00
|
|
|
// Section: struct operations
|
|
|
|
//
|
2022-04-07 20:38:28 +00:00
|
|
|
// A struct is a data structure that associates arbitrary keys (of any type) with values (of any type).
|
|
|
|
// Structures are implemented as lists of [key, value] pairs.
|
2019-06-12 02:50:50 +00:00
|
|
|
//
|
|
|
|
// An empty list `[]` is an empty structure and can be used wherever a structure input is required.
|
|
|
|
|
|
|
|
// Function: struct_set()
|
2023-04-29 01:50:51 +00:00
|
|
|
// Synopsis: Sets one or more key-value pairs in a struct.
|
2023-03-15 07:31:40 +00:00
|
|
|
// Topics: Data Structures, Dictionaries
|
2023-04-29 01:50:51 +00:00
|
|
|
// See Also: struct_set(), struct_remove(), struct_val(), struct_keys(), echo_struct(), is_struct()
|
2019-06-12 02:50:50 +00:00
|
|
|
// Usage:
|
2023-03-15 07:31:40 +00:00
|
|
|
// struct2 = struct_set(struct, key, value, [grow=]);
|
|
|
|
// struct2 = struct_set(struct, [key1, value1, key2, value2, ...], [grow=]);
|
2019-06-12 02:50:50 +00:00
|
|
|
// Description:
|
2023-03-15 07:31:40 +00:00
|
|
|
// Sets the key(s) in the structure to the specified value(s), returning a new updated structure. If a
|
|
|
|
// key exists its value is changed, otherwise the key is added to the structure. If `grow=false` then
|
2022-04-07 20:38:28 +00:00
|
|
|
// it is an error to set a key not already defined in the structure. If you specify the same key twice
|
2023-03-15 07:31:40 +00:00
|
|
|
// that is also an error. Note that key order will change when you change a key's value.
|
2019-06-12 02:50:50 +00:00
|
|
|
// Arguments:
|
2022-04-07 20:38:28 +00:00
|
|
|
// struct = input structure.
|
|
|
|
// key = key to set or list of key,value pairs to set
|
|
|
|
// value = value to set the key to (when giving a single key and value)
|
|
|
|
// ---
|
|
|
|
// grow = Set to true to allow structure to grow, or false for new keys to generate an error. Default: true
|
2023-08-12 17:36:32 +00:00
|
|
|
// Example: Create a struct containing just one key-value pair
|
|
|
|
// some_struct = struct_set([], "answer", 42);
|
|
|
|
// // 'some_struct' now contains a single value, 42, under one key, "answer".
|
|
|
|
// Example: Create a struct containing more than one key-value pair. Note that keys and values need not be the same type.
|
|
|
|
// some_struct = struct_set([], ["answer", 42, 2, "two", "quote", "What a nice day"]);
|
|
|
|
// // 'some struct' now contains these key-value pairs:
|
|
|
|
// // answer: 42
|
|
|
|
// // 2: two
|
|
|
|
// // quote: What a nice day
|
2022-04-07 20:38:28 +00:00
|
|
|
function struct_set(struct, key, value, grow=true) =
|
|
|
|
is_def(value) ? struct_set(struct,[key,value],grow=grow)
|
|
|
|
:
|
2023-03-15 07:31:40 +00:00
|
|
|
assert(is_list(key) && len(key)%2==0, "[key,value] pair list is not a list or has an odd length")
|
2022-04-07 20:38:28 +00:00
|
|
|
let(
|
|
|
|
new_entries = [for(i=[0:1:len(key)/2-1]) [key[2*i], key[2*i+1]]],
|
|
|
|
newkeys = column(new_entries,0),
|
|
|
|
indlist = search(newkeys, struct,0,0),
|
|
|
|
badkeys = grow ? (search([undef],new_entries,1,0)[0] != [] ? [undef] : [])
|
|
|
|
: [for(i=idx(indlist)) if (is_undef(newkeys[i]) || len(indlist[i])==0) newkeys[i]],
|
|
|
|
ind = flatten(indlist),
|
|
|
|
dupfind = search(newkeys, new_entries,0,0),
|
|
|
|
dupkeys = [for(i=idx(dupfind)) if (len(dupfind[i])>1) newkeys[i]]
|
|
|
|
)
|
|
|
|
assert(badkeys==[], str("Unknown or bad key ",_format_key(badkeys[0])," in struct_set"))
|
|
|
|
assert(dupkeys==[], str("Duplicate key ",_format_key(dupkeys[0])," for struct"))
|
|
|
|
concat(list_remove(struct,ind), new_entries);
|
|
|
|
|
|
|
|
function _format_key(key) = is_string(key) ? str("\"",key,"\""): key;
|
2019-06-12 02:50:50 +00:00
|
|
|
|
|
|
|
// Function: struct_remove()
|
2023-04-29 01:50:51 +00:00
|
|
|
// Synopsis: Removes one or more keys from a struct.
|
2023-03-15 07:31:40 +00:00
|
|
|
// Topics: Data Structures, Dictionaries
|
2023-04-29 01:50:51 +00:00
|
|
|
// See Also: struct_set(), struct_remove(), struct_val(), struct_keys(), echo_struct(), is_struct()
|
2019-06-12 02:50:50 +00:00
|
|
|
// Usage:
|
2023-03-15 07:31:40 +00:00
|
|
|
// struct2 = struct_remove(struct, key);
|
2019-06-12 02:50:50 +00:00
|
|
|
// Description:
|
2022-04-07 20:38:28 +00:00
|
|
|
// Remove key or list of keys from a structure. If you want to remove a single key which is a list
|
|
|
|
// you must pass it as a singleton list, or struct_remove will attempt to remove the listed items as keys.
|
2023-03-15 07:31:40 +00:00
|
|
|
// If you list the same item multiple times for removal it will be removed without error.
|
2019-06-12 02:50:50 +00:00
|
|
|
// Arguments:
|
2020-05-20 00:28:02 +00:00
|
|
|
// struct = input structure
|
2023-03-15 07:31:40 +00:00
|
|
|
// key = a single key or list of keys to remove.
|
2022-04-07 20:38:28 +00:00
|
|
|
function struct_remove(struct, key) =
|
2023-02-17 00:59:21 +00:00
|
|
|
!is_list(key) ? struct_remove(struct, [key]) :
|
2022-04-07 20:38:28 +00:00
|
|
|
let(ind = search(key, struct))
|
2023-02-17 00:59:21 +00:00
|
|
|
list_remove(struct, [for(i=ind) if (i!=[]) i]);
|
2020-05-20 00:28:02 +00:00
|
|
|
|
2019-06-12 02:50:50 +00:00
|
|
|
|
|
|
|
// Function: struct_val()
|
2023-04-29 01:50:51 +00:00
|
|
|
// Synopsis: Returns the value for an key in a struct.
|
2023-03-15 07:31:40 +00:00
|
|
|
// Topics: Data Structures, Dictionaries
|
2023-04-29 01:50:51 +00:00
|
|
|
// See Also: struct_set(), struct_remove(), struct_val(), struct_keys(), echo_struct(), is_struct()
|
2019-06-12 02:50:50 +00:00
|
|
|
// Usage:
|
2023-03-15 07:31:40 +00:00
|
|
|
// val = struct_val(struct, key, default);
|
2019-06-12 02:50:50 +00:00
|
|
|
// Description:
|
2022-04-07 20:38:28 +00:00
|
|
|
// Returns the value for the specified key in the structure, or default value if the key is not present
|
2019-06-12 02:50:50 +00:00
|
|
|
// Arguments:
|
2020-05-20 00:28:02 +00:00
|
|
|
// struct = input structure
|
2022-04-07 20:38:28 +00:00
|
|
|
// key = key whose value to return
|
|
|
|
// default = default value to return if key is not present. Default: undef
|
|
|
|
function struct_val(struct, key, default=undef) =
|
|
|
|
assert(is_def(key),"key is missing")
|
|
|
|
let(ind = search([key],struct)[0])
|
2020-11-13 16:10:04 +00:00
|
|
|
ind == [] ? default : struct[ind][1];
|
2020-05-20 00:28:02 +00:00
|
|
|
|
2019-06-12 02:50:50 +00:00
|
|
|
|
|
|
|
// Function: struct_keys()
|
2023-04-29 01:50:51 +00:00
|
|
|
// Synopsis: Returns a list of keys for a struct.
|
2023-03-15 07:31:40 +00:00
|
|
|
// Topics: Data Structures, Dictionaries
|
2023-04-29 01:50:51 +00:00
|
|
|
// See Also: struct_set(), struct_remove(), struct_val(), struct_keys(), echo_struct(), is_struct()
|
2019-06-12 02:50:50 +00:00
|
|
|
// Usage:
|
2023-03-15 07:31:40 +00:00
|
|
|
// keys = struct_keys(struct);
|
2019-06-12 02:50:50 +00:00
|
|
|
// Description:
|
2020-05-20 00:28:02 +00:00
|
|
|
// Returns a list of the keys in a structure
|
2019-06-12 02:50:50 +00:00
|
|
|
// Arguments:
|
2020-05-20 00:28:02 +00:00
|
|
|
// struct = input structure
|
2022-04-07 20:38:28 +00:00
|
|
|
function struct_keys(struct) = column(struct,0);
|
2020-05-20 00:28:02 +00:00
|
|
|
|
2019-06-12 02:50:50 +00:00
|
|
|
|
2022-04-07 21:28:41 +00:00
|
|
|
// Function&Module: echo_struct()
|
2023-04-29 01:50:51 +00:00
|
|
|
// Synopsis: Echoes the struct to the console in a formatted manner.
|
2023-03-15 07:31:40 +00:00
|
|
|
// Topics: Data Structures, Dictionaries
|
2023-04-29 01:50:51 +00:00
|
|
|
// See Also: struct_set(), struct_remove(), struct_val(), struct_keys(), echo_struct(), is_struct()
|
2019-06-12 02:50:50 +00:00
|
|
|
// Usage:
|
2023-03-15 07:31:40 +00:00
|
|
|
// echo_struct(struct, [name]);
|
|
|
|
// foo = echo_struct(struct, [name]);
|
2019-06-12 02:50:50 +00:00
|
|
|
// Description:
|
2022-04-07 20:38:28 +00:00
|
|
|
// Displays a list of structure keys and values, one pair per line, for easier reading.
|
2019-06-12 02:50:50 +00:00
|
|
|
// Arguments:
|
2020-05-20 00:28:02 +00:00
|
|
|
// struct = input structure
|
|
|
|
// name = optional structure name to list at the top of the output. Default: ""
|
2022-04-07 21:28:41 +00:00
|
|
|
function echo_struct(struct,name="") =
|
2020-10-25 22:36:30 +00:00
|
|
|
let( keylist = [for(entry=struct) str(" ",entry[0],": ",entry[1],"\n")])
|
2020-05-30 02:04:34 +00:00
|
|
|
echo(str("\nStructure ",name,"\n",str_join(keylist)))
|
|
|
|
undef;
|
2019-06-12 02:50:50 +00:00
|
|
|
|
2022-04-07 21:28:41 +00:00
|
|
|
module echo_struct(struct,name="") {
|
2020-08-27 23:25:41 +00:00
|
|
|
no_children($children);
|
2022-04-07 21:28:41 +00:00
|
|
|
dummy = echo_struct(struct,name);
|
2019-06-12 02:50:50 +00:00
|
|
|
}
|
|
|
|
|
2020-05-20 00:28:02 +00:00
|
|
|
|
|
|
|
// Function: is_struct()
|
2023-04-29 01:50:51 +00:00
|
|
|
// Synopsis: Returns true if the value is a struct.
|
2023-03-15 07:31:40 +00:00
|
|
|
// Topics: Data Structures, Dictionaries
|
2023-04-29 01:50:51 +00:00
|
|
|
// See Also: struct_set(), struct_remove(), struct_val(), struct_keys(), echo_struct(), is_struct()
|
2019-06-12 02:50:50 +00:00
|
|
|
// Usage:
|
2023-03-15 07:31:40 +00:00
|
|
|
// bool = is_struct(struct);
|
2020-05-20 00:28:02 +00:00
|
|
|
// Description:
|
2022-04-07 20:38:28 +00:00
|
|
|
// Returns true if the input is a list of pairs, false otherwise.
|
2020-05-20 00:28:02 +00:00
|
|
|
function is_struct(x) =
|
2022-04-07 20:38:28 +00:00
|
|
|
is_list(x) && [for (xx=x) if(!(is_list(xx) && len(xx)==2)) 1] == [];
|
2020-05-20 00:28:02 +00:00
|
|
|
|
|
|
|
|
2020-05-30 02:04:34 +00:00
|
|
|
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|