LEngine Class
Public Functions
| LEngine() | |
| ~LEngine() | |
| LEngine(const LEngine &) | |
| LEngine & | operator=(const LEngine &) |
| LLayer * | find_layer(const LString & path) |
| LLayer * | find_layer(std::deque<LString> name_list) |
| void | load_files(const LString & path, const LString & name_space = "") |
| void | resolve_links() |
| LLayer * | root() |
| LUnresolvedLinks | unresolved_links() |
Detailed Description
Runtime engine that loads .lyr files and manages the live data model.
To load .lyr files, create an engine instance and call load_files(),
passing the path of the folder containing the files.
LEngine engine;
engine.load_files("path/to/files");
This loads the top-level file statements (layers, attributes, group-sets, and state-sets) directly into the engine's root layer.
To prevent names from colliding between sets, a namespace name can be passed, creating a namespace layer under "namespace/..." which the set loads into.
engine.load_files("library/files", "Library"); // Load into "Library/..."
Namespace layers are find-or-create, so two load_files() calls passing
the same namespace merge under the same layer.
engine.load_files("library/files", "Library"); // Creates "Library"
engine.load_files("library/more", "Library"); // Merges into "Library"
Inheritance bases are resolved per set of loaded files. A dependent set of files needs to be loaded after the files it depends on.
// Given `Something << Library/Base` in "app/files/something.lyr" ...
engine.load_files("library/files", "Library"); // Resolves `Library/Base` first
engine.load_files("app/files", "Application"); // Safe to resolve `Something`
Once all desired sets of files have been loaded, invoke resolve_links()
which calls LLayer::resolve_links() recursively through the whole tree.
Use unresolved_links() afterwards to log which links failed to resolve.
engine.resolve_links();
LUnresolvedLinks unresolved = engine.unresolved_links();
for (const LUnresolvedLink& link : unresolved)
Layers::log(...);
The engine's root layer is the top of the hierarchy, with no parent itself.
The root can be acquired through root().
LLayer* root_layer = engine.root();
While you can find layers through LLayer::find_layer() after acquiring the
root, the engine provides find_layer() for convenience.
LLayer* lib_item = engine.root()->find_layer("Library/Item");
LLayer* also_lib_item = engine.find_layer("Library/Item"); // Skip `root()`
Member Function Documentation
LEngine()
Constructs a new engine.
~LEngine()
Destroys the engine.
LEngine(const LEngine &)
Explicit deletion of the copy constructor.
Engines are currently neither copyable nor movable. Copying would require cloning the loaded tree and remapping its internal pointers (resolved links, dependents), which isn't implemented.
Explicit deletion of the copy assignment operator.
Assigning one engine to another would require the same tree cloning as
copying, which isn't implemented. Since engines also have no move
assignment, this rules out resetting an engine with engine = LEngine();.
To start from a blank engine, construct a new one.
Finds a layer by its path.
Returns nullptr if the layer is not found.
Finds a layer by a list of path components.
Returns nullptr if the layer is not found.
void load_files(const LString & path, const LString & name_space = "")
Loads a set of .lyr files from the given directory path.
Recurses through subdirectories to discover and load all .lyr files
contained by path.
All top-level layers in the set are placed under a namespace node named
name_space (so they resolve at "namespace/..."), keeping one library's
names from colliding with another's. Pass an empty name_space
(the default) to load them directly at the root.
Any files that begin with an underscore (_), like _example.lyr, are
ignored during loading.
If a file has lexer or parser errors present, the errors are logged and the particular file is skipped, resulting in a tree that's partially constructed.
If no directory is found at the given path, no files are loaded and
the issue is logged.
void resolve_links()
Resolves all attribute links throughout the entire tree.
Call this after loading all desired files. It is safe to call this method again to resolve after loading another set.
This forward is provided for convenience so that the caller can skip
the root() acquisition.
LLayer * root()
Returns the root layer that contains all loaded content.
LUnresolvedLinks unresolved_links()
Returns every link in the loaded tree that failed to resolve.
Each entry names the declaring attribute, the link path, and the reason it failed: no target was found, or the target was rejected because the link would form a cycle. Call after resolve_links(); an empty list means every link landed. Unresolved links also fall back to their attribute's own value at read time, so this is the way to catch silent defaults early.