MIRA
Scope.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2025 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_XML_MACROS_SCOPE_H_
48 #define _MIRA_XML_MACROS_SCOPE_H_
49 
50 #include <string>
51 #include <unordered_map>
52 
53 #include <xml/macros/IMacro.h>
54 
55 namespace mira::xmlmacros {
56 
57 struct Identifier
58 {
59  std::string xmlns;
60  std::string name;
61 
62  [[nodiscard]] std::string toString() const
63  {
64  return xmlns + ":" + name;
65  }
66 };
67 
68 using Definitions = std::unordered_map<std::string, xmlmacros::MacroPtr>;
69 
76 struct Scope
77 {
78  using Ptr = std::shared_ptr<Scope>;
79 
80  Scope::Ptr parent = nullptr;
81 
82  // Set of definitions for each namespace.
83  std::unordered_map<std::string, Definitions> namespaces;
84 
85  [[nodiscard]] MacroPtr findOptional(const Identifier& id) const
86  {
87  auto ns = namespaces.find(id.xmlns);
88 
89  if (ns != namespaces.end()) {
90  auto it = ns->second.find(id.name);
91 
92  if (it != ns->second.end()) {
93  return it->second;
94  }
95  }
96 
97  if (parent != nullptr) {
98  return parent->findOptional(id);
99  }
100 
101  return nullptr;
102  }
103 
104  [[nodiscard]] MacroPtr find(const Identifier& name) const
105  {
106  auto ptr = findOptional(name);
107 
108  if (ptr == nullptr) {
109  MIRA_THROW(XInvalidConfig,
110  "No definition for macro \"" + name.xmlns + ":" + name.name + "\" found.");
111  }
112 
113  return ptr;
114  }
115 
116  void define(Identifier id, MacroPtr macro)
117  {
118  auto ns = namespaces.find(id.xmlns);
119 
120  if (ns == namespaces.end()) {
121  namespaces[id.xmlns] = {};
122  ns = namespaces.find(id.xmlns);
123  }
124 
125  if (ns->second.find(id.name) != ns->second.end()) {
126  MIRA_THROW(XInvalidConfig, "Macro \"" + id.toString() + "\" already defined in this scope.");
127  }
128 
129  ns->second.insert(std::make_pair(std::move(id.name), std::move(macro)));
130  }
131 
138  {
139  for (auto& [_, ns] : namespaces) {
140  std::vector<std::remove_reference_t<decltype(ns)>::iterator> toErase;
141 
142  for (auto it = ns.begin(); it != ns.end(); ++it) {
143  if (it->second.use_count() == 1) {
144  toErase.emplace_back(it);
145  }
146  }
147 
148  for (auto it : toErase) {
149  ns.erase(it);
150  }
151  }
152  }
153 }; // struct Scope
154 
156 
157 } // namespace mira::xmlmacros
158 
159 #endif // _MIRA_XML_MACROS_SCOPE_H_
MacroPtr findOptional(const Identifier &id) const
Definition: Scope.h:85
Definition: Scope.h:57
std::shared_ptr< Scope > Ptr
Definition: Scope.h:78
std::unordered_map< std::string, Definitions > namespaces
Definition: Scope.h:83
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:78
std::string name
Definition: Scope.h:60
std::string toString(const T &value, int precision=-1)
Converts any data type to string (the data type must support the stream << operator).
Definition: ToString.h:252
Variable scope of the macro processor.
Definition: Scope.h:76
MacroPtr find(const Identifier &name) const
Definition: Scope.h:104
std::string toString() const
Definition: Scope.h:62
std::unordered_map< std::string, xmlmacros::MacroPtr > Definitions
Definition: Scope.h:68
Scope::Ptr parent
Definition: Scope.h:80
void collectGarbage()
Remove any definitions that no one else depends on.
Definition: Scope.h:137
Scope::Ptr ScopePtr
Definition: Scope.h:155
Interface for implementing XML macros.
std::shared_ptr< IMacro > MacroPtr
Definition: IMacro.h:99
std::string xmlns
Definition: Scope.h:59
Definition: Builtins.h:56
void define(Identifier id, MacroPtr macro)
Definition: Scope.h:116