OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
UserFlags.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2//
3// Copyright 2026 Caleb Buahin
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
58
59#ifndef OPENSWMM_ENGINE_USER_FLAGS_HPP
60#define OPENSWMM_ENGINE_USER_FLAGS_HPP
61
62#include <string>
63#include <unordered_map>
64#include <vector>
65#include <variant>
66#include <optional>
67#include <stdexcept>
68
69#include "StringCase.hpp"
70
71namespace openswmm {
72
73// ============================================================================
74// Type tag
75// ============================================================================
76
81enum class UserFlagType : int {
82 BOOLEAN = 0,
83 INTEGER = 1,
84 REAL = 2,
85 STRING = 3
86};
87
88// ============================================================================
89// Schema definition
90// ============================================================================
91
102 std::string name;
104 std::string description;
105};
106
107// ============================================================================
108// Per-object value
109// ============================================================================
110
115using UserFlagValue = std::variant<bool, int, double, std::string>;
116
124 std::string object_type;
125 std::string object_name;
126 std::string flag_name;
128};
129
130// ============================================================================
131// Container
132// ============================================================================
133
146public:
147
148 // ------------------------------------------------------------------
149 // Schema (from [USER_FLAGS])
150 // ------------------------------------------------------------------
151
156 void define(UserFlagDef def) {
157 const auto it = def_index_.find(def.name);
158 if (it != def_index_.end()) {
159 defs_[it->second] = std::move(def);
160 } else {
161 def_index_[def.name] = defs_.size();
162 defs_.push_back(std::move(def));
163 }
164 }
165
170 bool undefine(const std::string& name) {
171 const auto it = def_index_.find(name);
172 if (it == def_index_.end()) return false;
173 const std::size_t idx = it->second;
174 defs_.erase(defs_.begin() + static_cast<std::ptrdiff_t>(idx));
175 def_index_.erase(it);
176 // Reindex definitions that followed the erased slot.
177 for (auto& kv : def_index_)
178 if (kv.second > idx) --kv.second;
179 // Remove orphaned per-object values (key = "TYPE:NAME:FLAG";
180 // same left-to-right decomposition as InpWriter).
181 for (auto vit = values_.begin(); vit != values_.end(); ) {
182 const auto& key = vit->first;
183 const auto p1 = key.find(':');
184 const auto p2 = (p1 == std::string::npos)
185 ? std::string::npos : key.find(':', p1 + 1);
186 if (p2 != std::string::npos && key.compare(p2 + 1, std::string::npos, name) == 0)
187 vit = values_.erase(vit);
188 else
189 ++vit;
190 }
191 return true;
192 }
193
197 bool is_defined(const std::string& name) const {
198 return def_index_.count(name) != 0;
199 }
200
205 const UserFlagDef& get_def(const std::string& name) const {
206 const auto it = def_index_.find(name);
207 if (it == def_index_.end())
208 throw std::out_of_range("UserFlags: no definition for flag '" + name + "'");
209 return defs_[it->second];
210 }
211
215 const std::vector<UserFlagDef>& all_defs() const noexcept { return defs_; }
216
220 std::size_t def_count() const noexcept { return defs_.size(); }
221
222 // ------------------------------------------------------------------
223 // Per-object values (from [USER_FLAG_VALUES])
224 // ------------------------------------------------------------------
225
231 void set(const std::string& object_type,
232 const std::string& object_name,
233 const std::string& flag_name,
234 UserFlagValue value) {
235 values_[make_key(object_type, object_name, flag_name)] = std::move(value);
236 }
237
242 bool unset(const std::string& object_type,
243 const std::string& object_name,
244 const std::string& flag_name) {
245 return values_.erase(make_key(object_type, object_name, flag_name)) != 0;
246 }
247
251 bool has_value(const std::string& object_type,
252 const std::string& object_name,
253 const std::string& flag_name) const {
254 return values_.count(make_key(object_type, object_name, flag_name)) != 0;
255 }
256
261 const UserFlagValue& get_value(const std::string& object_type,
262 const std::string& object_name,
263 const std::string& flag_name) const {
264 const auto it = values_.find(make_key(object_type, object_name, flag_name));
265 if (it == values_.end())
266 throw std::out_of_range(
267 "UserFlags: no value for " + object_type + ":" +
268 object_name + ":" + flag_name);
269 return it->second;
270 }
271
275 std::optional<UserFlagValue> try_get_value(const std::string& object_type,
276 const std::string& object_name,
277 const std::string& flag_name) const {
278 const auto it = values_.find(make_key(object_type, object_name, flag_name));
279 if (it == values_.end()) return std::nullopt;
280 return it->second;
281 }
282
286 using ValueMap =
287 std::unordered_map<std::string, UserFlagValue, CiHash, CiEqual>;
288
292 const ValueMap& all_values() const noexcept {
293 return values_;
294 }
295
299 std::size_t value_count() const noexcept { return values_.size(); }
300
301 // ------------------------------------------------------------------
302 // Reset
303 // ------------------------------------------------------------------
304
308 void clear() noexcept {
309 defs_.clear();
310 def_index_.clear();
311 values_.clear();
312 }
313
314 // ------------------------------------------------------------------
315 // Composite-key helper (public for tests)
316 // ------------------------------------------------------------------
317
324 static std::string make_key(const std::string& object_type,
325 const std::string& object_name,
326 const std::string& flag_name) {
327 std::string key;
328 key.reserve(object_type.size() + 1 + object_name.size() + 1 + flag_name.size());
329 key += object_type;
330 key += ':';
331 key += object_name;
332 key += ':';
333 key += flag_name;
334 return key;
335 }
336
337private:
338 // Schema
339 std::vector<UserFlagDef> defs_;
340 std::unordered_map<std::string, std::size_t> def_index_;
341
342 // Per-object values
343 ValueMap values_;
344};
345
346} /* namespace openswmm */
347
348#endif /* OPENSWMM_ENGINE_USER_FLAGS_HPP */
Case-insensitive string helpers matching legacy SWMM name semantics.
Stores the full user-flags data: schema definitions + per-object values.
Definition UserFlags.hpp:145
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:275
void define(UserFlagDef def)
Register a flag definition.
Definition UserFlags.hpp:156
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:261
std::size_t def_count() const noexcept
Number of defined flag schemas.
Definition UserFlags.hpp:220
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:324
const ValueMap & all_values() const noexcept
All per-object value assignments, keyed by composite string.
Definition UserFlags.hpp:292
void clear() noexcept
Clear both schema definitions and per-object value assignments.
Definition UserFlags.hpp:308
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:251
const UserFlagDef & get_def(const std::string &name) const
Retrieve a flag definition by name.
Definition UserFlags.hpp:205
std::unordered_map< std::string, UserFlagValue, CiHash, CiEqual > ValueMap
Definition UserFlags.hpp:286
const std::vector< UserFlagDef > & all_defs() const noexcept
All flag definitions, in insertion order.
Definition UserFlags.hpp:215
bool undefine(const std::string &name)
Remove a flag definition and all per-object values assigned to it.
Definition UserFlags.hpp:170
bool is_defined(const std::string &name) const
Check whether a flag name has been defined (schema).
Definition UserFlags.hpp:197
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:231
std::size_t value_count() const noexcept
Number of per-object value assignments.
Definition UserFlags.hpp:299
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:242
std::variant< bool, int, double, std::string > UserFlagValue
A concrete flag value assigned to a specific object.
Definition UserFlags.hpp:115
UserFlagType
Value type for a user flag.
Definition UserFlags.hpp:81
@ INTEGER
Signed integer.
Definition UserFlags.hpp:83
@ STRING
Arbitrary string.
Definition UserFlags.hpp:85
@ REAL
Double-precision floating-point.
Definition UserFlags.hpp:84
@ BOOLEAN
YES/NO/TRUE/FALSE/1/0.
Definition UserFlags.hpp:82
Definition NodeCoupling.cpp:16
A (object_type, object_name, flag_name) → value assignment.
Definition UserFlags.hpp:123
std::string flag_name
Must match a name in UserFlags::defs_.
Definition UserFlags.hpp:126
std::string object_type
e.g. "NODE", "LINK", "SUBCATCHMENT"
Definition UserFlags.hpp:124
std::string object_name
Object identifier as it appears in the model.
Definition UserFlags.hpp:125
UserFlagValue value
Typed runtime value.
Definition UserFlags.hpp:127
Schema entry for a single user-defined flag.
Definition UserFlags.hpp:101
std::string description
Human-readable description (may be empty)
Definition UserFlags.hpp:104
UserFlagType type
Value type.
Definition UserFlags.hpp:103
std::string name
Flag identifier (uppercase)
Definition UserFlags.hpp:102