dict¶
Description¶
The native file format used by dictIO shares, by intention, some commonalities with the OpenFOAM file format, but is kept simpler and more tolerant to different flavours of string formatting.
Structure¶
The basic structure of a dict file consists of
header (block comment) [optional]
include directive(s) [optional]
key’d elements (each written as key value pair)
As header and include directives are optional, in its simplest form a dict file can contain just a single key’d element:
var1 3.14159;
Header¶
The default block comment used as header in dict files generated by dictIO looks as follows:
/*---------------------------------*- C++ -*----------------------------------*\
filetype dictionary; coding utf-8; version 0.1; local --; purpose --;
\*----------------------------------------------------------------------------*/
#include Directive(s)¶
One of the most powerful features of dict files is their ability to be cascaded through the use of #include directives. An #include directive declares a (child) dict file to be merged into the (parent) dict when reading.
This allows to separate i.e. a case agnostic configuration file from its case specific parameterization: While the core configuration dict is kept unchanged, case specific parameterization is accomplished by varying only the parameter dict.
An #include directive consists of the #include statement followed by the path to the dict to be included:
#include 'a_paramDict_in_same_folder'
#include 'subfolder/a_paramDict_in_subfolder' // Posix style with forward slashes is recommended (will work also on Windows)
#include '../a_paramDict_in_parent_folder'
#include 'subfolder\a_paramDict_in_subfolder' // also ok, but not recommended
#include '..\a_paramDict_in_parent_folder'
Element Types¶
The following element types are supported in dict files read and written by dictIO. The table also indicates to which Python data type they are casted when a dict file is read.
element type |
example |
(Python type) |
---|---|---|
boolean |
true, false, on, off |
bool |
number |
1, 1.0 |
int, float |
none |
None, none, NULL, null |
None |
string |
aString, ‘a string’, “a string” |
str |
dict |
{key1 value1; key2 value2;} |
dict |
list |
(1.0 2.0 3.0) |
list |
reference |
$var1 |
(type of var1) |
expression |
“$var1 + 4” |
(type of var1) |
Examples¶
Below examples demonstrate the different element types supported by dictIO in dict files.
booleans¶
bool1 true; // True
bool2 false; // False
bool3 True; // True
bool4 False; // False
bool5 on; // True
bool6 off; // False
bool7 ON; // True
bool8 OFF; // False
numbers¶
int1 0; // int
int2 120; // int
float1 3.5; // float
float2 1.00000000e+00; // float
nones¶
none1 None; // None
none2 none; // None
none3 NULL; // None
none4 null; // None
strings¶
string1 '';
string2 'string';
string3 'string with spaces';
string4 singleWordsWithoutSpacesCanAlsoBeDeclaredWithoutQuotes;
string5 'string with single quotes';
string6 "string with double quotes";
dicts¶
emptyDict
{
}
dictWithNumbers
{
var1 1;
var2 2.0;
var3 3.14;
}
dictWithStrings
{
string1 'string1';
string2 'string2 has spaces';
string3 'string3';
string4 'string4 is ok but note that string5 is empty';
string5 '';
}
lists¶
emptyList
(
);
listWithNumbers
(
1 2.0 3.14
);
matrix // a matrix is represented by a list of lists
(
(11 12 13)
(21 22 23)
(31 32 33)
);
listWithStrings
(
'string1' 'string2 has spaces' 'string3' 'string4 is ok but note that string5 is empty' ''
);
References and Expressions¶
Any key’d element in a dict file can also be treated as a variable that can be pointed to using references. A reference is denoted by a $ character followed by the key of the element being referenced, also known as $keyword syntax.
References, in turn, can be used inside expressions. Expressions are double-quoted strings containing a mathematical expression where at least one operand is a reference.
Below code listing demonstrates the use of references and expressions:
varA 1.0;
varB 2.0;
list (1.0 2.0 3.0);
matrix
(
(11 12 13)
(21 22 23)
(31 32 33)
);
reference1 $varA; // simple reference to a variable. References are prefixed with $.
reference2 $list[0]; // indexed reference to an item in a list.
reference3 $matrix[0]; // indexed reference to a specific row in a matrix (=returns a list).
reference4 $matrix[0][1]; // indexed reference to a specific value in a matrix.
expression1 "$varA"; // expression. However, result of this expression is same as using a simple reference without double quotes.
expression2 "$varA + 4"; // expression with one reference and one constant.
expression3 "$varA + $varB"; // expression with two references.
expression4 "$list[0] + 3.14"; // expression with an indexed reference.
Nesting¶
Both dicts and lists can be nested. In fact, dicts and lists in a dict file can be arbitrarily nested.
While lexically possible, readability of nested data structures quickly suffers. In dict files intended to be read and edited by humans, such as configuration files, nesting should hence be used carefully and reasonably limited (an example that commonly causes misinterpretation is where a dict is nested inside a list, see section The dict-in-a-list Pitfall further below).
From a pure lexical / technical point of view, though, complex nesting of dicts and lists is possible. So, in cases where dict files are written and read purely by machines, this can provide additional capabilities.
nesting
{
emptyNestedDict
{
}
emptyNestedList
(
);
nestedDictWithNestedList
{
list1
(
1.00000000e+00 2.20972831e-17 3.15717747e-18
);
list2
(
2.20972831e-17 1.00000000e+00 -7.07290050e-18
);
list3
(
3.15717747e-18 -7.07290050e-18 1.00000000e+00
);
}
nestedListWithNestedList
(
(
1.00000000e+00 2.20972831e-17 3.15717747e-18
)
(
2.20972831e-17 1.00000000e+00 -7.07290050e-18
)
(
3.15717747e-18 -7.07290050e-18 1.00000000e+00
)
);
nestedListWithNestedDict
(
(
11 12 13
)
{
value21 21;
value22 22;
value23 23;
}
(
31 32 33
)
);
}
The dict-in-a-list Pitfall¶
A very prominent example where nesting of dicts and lists deteriorates human readibility and causes misinterpretation is where a dict is nested inside a list. Read below example to see why:
keyToADict // This is a key. You can access its value (the subsequent dict {}) as a key'd element -> myDict['keyToADict']
{ // This is the key'd element associated with key 'keyToADict'. It is of type dict.
keyToAList // This is a key. You can access its value (the subsequent list ()) as a key'd element -> myDict['keyToADict']['keyToAList']
( // This is the key'd element associated with key 'keyToAList'. It is of type list.
notAKey // This is NOT a key. It is a list element of type string. You can access it by its index -> myDict['keyToADict']['keyToAList'][0]
{ // This is NOT a key'd element. It is a list element of type dict. You can access it by its index -> myDict['keyToADict']['keyToAList'][1]
key1 value1; // This is a key'd element inside the surrounding dict -> myDict['keyToADict']['keyToAList'][1]['key1']
key2 value2; // This is a key'd element inside the surrounding dict -> myDict['keyToADict']['keyToAList'][1]['key2']
}
notAKey // another list element -> myDict['keyToADict']['keyToAList'][2]
notAKey // yet another list element -> myDict['keyToADict']['keyToAList'][3]
notAKey // yet .. well, you got the point .. -> myDict['keyToADict']['keyToAList'][4]
notAKey // NOT A KEY !! -> myDict['keyToADict']['keyToAList'][5]
{ // another list element of type dict -> myDict['keyToADict']['keyToAList'][6]
key1 value1; // This is a key'd element inside the surrounding dict -> myDict['keyToADict']['keyToAList'][6]['key1']
key2 value2; // This is a key'd element inside the surrounding dict -> myDict['keyToADict']['keyToAList'][6]['key2']
}
);
}