OpenSWMM Engine  6.0.0-alpha.3
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.3)
Loading...
Searching...
No Matches
UserFlags.hpp
Go to the documentation of this file.
1
42
43#ifndef OPENSWMM_ENGINE_USER_FLAGS_HPP
44#define OPENSWMM_ENGINE_USER_FLAGS_HPP
45
46#include <string>
47#include <unordered_map>
48#include <vector>
49#include <variant>
50#include <optional>
51#include <stdexcept>
52
53namespace openswmm {
54
55// ============================================================================
56// Type tag
57// ============================================================================
58
63enum class UserFlagType : int {
64 BOOLEAN = 0,
65 INTEGER = 1,
66 REAL = 2,
67 STRING = 3
68};
69
70// ============================================================================
71// Schema definition
72// ============================================================================
73
84 std::string name;
86 std::string description;
87};
88
89// ============================================================================
90// Per-object value
91// ============================================================================
92
97using UserFlagValue = std::variant<bool, int, double, std::string>;
98
106 std::string object_type;
107 std::string object_name;
108 std::string flag_name;
110};
111
112// ============================================================================
113// Container
114// ============================================================================
115
128public:
129
130 // ------------------------------------------------------------------
131 // Schema (from [USER_FLAGS])
132 // ------------------------------------------------------------------
133
138 void define(UserFlagDef def) {
139 const auto it = def_index_.find(def.name);
140 if (it != def_index_.end()) {
141 defs_[it->second] = std::move(def);
142 } else {
143 def_index_[def.name] = defs_.size();
144 defs_.push_back(std::move(def));
145 }
146 }
147
152 bool undefine(const std::string& name) {
153 const auto it = def_index_.find(name);
154 if (it == def_index_.end()) return false;
155 const std::size_t idx = it->second;
156 defs_.erase(defs_.begin() + static_cast<std::ptrdiff_t>(idx));
157 def_index_.erase(it);
158 // Reindex definitions that followed the erased slot.
159 for (auto& kv : def_index_)
160 if (kv.second > idx) --kv.second;
161 // Remove orphaned per-object values (key = "TYPE:NAME:FLAG";
162 // same left-to-right decomposition as InpWriter).
163 for (auto vit = values_.begin(); vit != values_.end(); ) {
164 const auto& key = vit->first;
165 const auto p1 = key.find(':');
166 const auto p2 = (p1 == std::string::npos)
167 ? std::string::npos : key.find(':', p1 + 1);
168 if (p2 != std::string::npos && key.compare(p2 + 1, std::string::npos, name) == 0)
169 vit = values_.erase(vit);
170 else
171 ++vit;
172 }
173 return true;
174 }
175
179 bool is_defined(const std::string& name) const {
180 return def_index_.count(name) != 0;
181 }
182
187 const UserFlagDef& get_def(const std::string& name) const {
188 const auto it = def_index_.find(name);
189 if (it == def_index_.end())
190 throw std::out_of_range("UserFlags: no definition for flag '" + name + "'");
191 return defs_[it->second];
192 }
193
197 const std::vector<UserFlagDef>& all_defs() const noexcept { return defs_; }
198
202 std::size_t def_count() const noexcept { return defs_.size(); }
203
204 // ------------------------------------------------------------------
205 // Per-object values (from [USER_FLAG_VALUES])
206 // ------------------------------------------------------------------
207
213 void set(const std::string& object_type,
214 const std::string& object_name,
215 const std::string& flag_name,
216 UserFlagValue value) {
217 values_[make_key(object_type, object_name, flag_name)] = std::move(value);
218 }
219
224 bool unset(const std::string& object_type,
225 const std::string& object_name,
226 const std::string& flag_name) {
227 return values_.erase(make_key(object_type, object_name, flag_name)) != 0;
228 }
229
233 bool has_value(const std::string& object_type,
234 const std::string& object_name,
235 const std::string& flag_name) const {
236 return values_.count(make_key(object_type, object_name, flag_name)) != 0;
237 }
238
243 const UserFlagValue& get_value(const std::string& object_type,
244 const std::string& object_name,
245 const std::string& flag_name) const {
246 const auto it = values_.find(make_key(object_type, object_name, flag_name));
247 if (it == values_.end())
248 throw std::out_of_range(
249 "UserFlags: no value for " + object_type + ":" +
250 object_name + ":" + flag_name);
251 return it->second;
252 }
253
257 std::optional<UserFlagValue> try_get_value(const std::string& object_type,
258 const std::string& object_name,
259 const std::string& flag_name) const {
260 const auto it = values_.find(make_key(object_type, object_name, flag_name));
261 if (it == values_.end()) return std::nullopt;
262 return it->second;
263 }
264
268 const std::unordered_map<std::string, UserFlagValue>& all_values() const noexcept {
269 return values_;
270 }
271
275 std::size_t value_count() const noexcept { return values_.size(); }
276
277 // ------------------------------------------------------------------
278 // Reset
279 // ------------------------------------------------------------------
280
284 void clear() noexcept {
285 defs_.clear();
286 def_index_.clear();
287 values_.clear();
288 }
289
290 // ------------------------------------------------------------------
291 // Composite-key helper (public for tests)
292 // ------------------------------------------------------------------
293
300 static std::string make_key(const std::string& object_type,
301 const std::string& object_name,
302 const std::string& flag_name) {
303 std::string key;
304 key.reserve(object_type.size() + 1 + object_name.size() + 1 + flag_name.size());
305 key += object_type;
306 key += ':';
307 key += object_name;
308 key += ':';
309 key += flag_name;
310 return key;
311 }
312
313private:
314 // Schema
315 std::vector<UserFlagDef> defs_;
316 std::unordered_map<std::string, std::size_t> def_index_;
317
318 // Per-object values
319 std::unordered_map<std::string, UserFlagValue> values_;
320};
321
322} /* namespace openswmm */
323
324#endif /* OPENSWMM_ENGINE_USER_FLAGS_HPP */
Stores the full user-flags data: schema definitions + per-object values.
Definition UserFlags.hpp:127
std::optional< UserFlagValue > try_get_value(const std::string &object_type, const std::string &object_name, const std::string &flag_name) const
Retrieve the value, or nullopt if not assigned.
Definition UserFlags.hpp:257
void define(UserFlagDef def)
Register a flag definition.
Definition UserFlags.hpp:138
const UserFlagValue & get_value(const std::string &object_type, const std::string &object_name, const std::string &flag_name) const
Retrieve the value for (object_type, object_name, flag_name).
Definition UserFlags.hpp:243
std::size_t def_count() const noexcept
Number of defined flag schemas.
Definition UserFlags.hpp:202
static std::string make_key(const std::string &object_type, const std::string &object_name, const std::string &flag_name)
Build the composite lookup key "OBJECTTYPE:OBJECTNAME:FLAGNAME".
Definition UserFlags.hpp:300
void clear() noexcept
Clear both schema definitions and per-object value assignments.
Definition UserFlags.hpp:284
bool has_value(const std::string &object_type, const std::string &object_name, const std::string &flag_name) const
Check whether a value has been assigned for a given triple.
Definition UserFlags.hpp:233
const UserFlagDef & get_def(const std::string &name) const
Retrieve a flag definition by name.
Definition UserFlags.hpp:187
const std::unordered_map< std::string, UserFlagValue > & all_values() const noexcept
All per-object value assignments, keyed by composite string.
Definition UserFlags.hpp:268
const std::vector< UserFlagDef > & all_defs() const noexcept
All flag definitions, in insertion order.
Definition UserFlags.hpp:197
bool undefine(const std::string &name)
Remove a flag definition and all per-object values assigned to it.
Definition UserFlags.hpp:152
bool is_defined(const std::string &name) const
Check whether a flag name has been defined (schema).
Definition UserFlags.hpp:179
void set(const std::string &object_type, const std::string &object_name, const std::string &flag_name, UserFlagValue value)
Assign a value to (object_type, object_name, flag_name).
Definition UserFlags.hpp:213
std::size_t value_count() const noexcept
Number of per-object value assignments.
Definition UserFlags.hpp:275
bool unset(const std::string &object_type, const std::string &object_name, const std::string &flag_name)
Remove the value assigned to (object_type, object_name, flag_name).
Definition UserFlags.hpp:224
std::variant< bool, int, double, std::string > UserFlagValue
A concrete flag value assigned to a specific object.
Definition UserFlags.hpp:97
UserFlagType
Value type for a user flag.
Definition UserFlags.hpp:63
@ INTEGER
Signed integer.
Definition UserFlags.hpp:65
@ STRING
Arbitrary string.
Definition UserFlags.hpp:67
@ REAL
Double-precision floating-point.
Definition UserFlags.hpp:66
@ BOOLEAN
YES/NO/TRUE/FALSE/1/0.
Definition UserFlags.hpp:64
Definition NodeCoupling.cpp:15
A (object_type, object_name, flag_name) → value assignment.
Definition UserFlags.hpp:105
std::string flag_name
Must match a name in UserFlags::defs_.
Definition UserFlags.hpp:108
std::string object_type
e.g. "NODE", "LINK", "SUBCATCHMENT"
Definition UserFlags.hpp:106
std::string object_name
Object identifier as it appears in the model.
Definition UserFlags.hpp:107
UserFlagValue value
Typed runtime value.
Definition UserFlags.hpp:109
Schema entry for a single user-defined flag.
Definition UserFlags.hpp:83
std::string description
Human-readable description (may be empty)
Definition UserFlags.hpp:86
UserFlagType type
Value type.
Definition UserFlags.hpp:85
std::string name
Flag identifier (uppercase)
Definition UserFlags.hpp:84