OpenSWMM Engine  6.0.0-alpha.4
Data-oriented, plugin-extensible SWMM Engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
NameIndex.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
40
41#ifndef OPENSWMM_ENGINE_NAME_INDEX_HPP
42#define OPENSWMM_ENGINE_NAME_INDEX_HPP
43
44#include <string>
45#include <string_view>
46#include <unordered_map>
47#include <vector>
48#include <stdexcept>
49#include <optional>
50
52
53namespace openswmm {
54
71class NameIndex {
72public:
73 NameIndex() = default;
74
75 // -----------------------------------------------------------------------
76 // Insertion
77 // -----------------------------------------------------------------------
78
89 int add(const std::string& name) {
90 const int idx = try_add(name);
91 if (idx < 0) {
92 throw std::invalid_argument("NameIndex: duplicate name '" + name + "'");
93 }
94 return idx;
95 }
96
104 int try_add(const std::string& name) {
105 auto [it, inserted] = map_.emplace(name, static_cast<int>(names_.size()));
106 if (!inserted) return -1;
107 names_.push_back(name);
108 return it->second;
109 }
110
111 // -----------------------------------------------------------------------
112 // Lookup
113 // -----------------------------------------------------------------------
114
121 int find(std::string_view name) const noexcept {
122 auto it = map_.find(name);
123 if (it == map_.end()) return -1;
124 return it->second;
125 }
126
130 std::optional<int> try_find(std::string_view name) const noexcept {
131 auto it = map_.find(name);
132 if (it == map_.end()) return std::nullopt;
133 return it->second;
134 }
135
144 const std::string* canonical(std::string_view name) const noexcept {
145 auto it = map_.find(name);
146 if (it == map_.end()) return nullptr;
147 return &names_[static_cast<std::size_t>(it->second)];
148 }
149
154 const std::string& name_of(int idx) const {
155 return names_.at(static_cast<std::size_t>(idx));
156 }
157
158 // -----------------------------------------------------------------------
159 // Capacity
160 // -----------------------------------------------------------------------
161
163 int size() const noexcept { return static_cast<int>(names_.size()); }
164
166 bool empty() const noexcept { return names_.empty(); }
167
171 void reserve(std::size_t n) {
172 map_.reserve(n);
173 names_.reserve(n);
174 }
175
177 void clear() noexcept {
178 map_.clear();
179 names_.clear();
180 }
181
189 void pop_back() noexcept {
190 if (names_.empty()) return;
191 const std::string tail = names_.back();
192 map_.erase(tail);
193 names_.pop_back();
194 }
195
206 bool rename(int idx, const std::string& newName) noexcept {
207 if (idx < 0 || idx >= static_cast<int>(names_.size())) return false;
208 auto it = map_.find(newName);
209 if (it != map_.end() && it->second != idx) return false; // duplicate
210 map_.erase(names_[static_cast<std::size_t>(idx)]);
211 names_[static_cast<std::size_t>(idx)] = newName;
212 map_[newName] = idx;
213 return true;
214 }
215
231 void remove_at(int idx) noexcept {
232 if (idx < 0 || idx >= static_cast<int>(names_.size())) return;
233 names_.erase(names_.begin() + idx);
234 if (bulk_depth_ > 0) return; // map rebuilt once in end_bulk_remove()
235 rebuild_map_();
236 }
237
248 void begin_bulk_remove() noexcept { ++bulk_depth_; }
249
253 if (bulk_depth_ == 0 || --bulk_depth_ > 0) return;
254 rebuild_map_();
255 }
256
257 // -----------------------------------------------------------------------
258 // Iteration
259 // -----------------------------------------------------------------------
260
262 const std::vector<std::string>& names() const noexcept { return names_; }
263
264private:
265 void rebuild_map_() {
266 map_.clear();
267 map_.reserve(names_.size());
268 for (int i = 0; i < static_cast<int>(names_.size()); ++i)
269 map_[names_[static_cast<std::size_t>(i)]] = i;
270 }
271
273 std::unordered_map<std::string, int, CiHash, CiEqual> map_;
274 std::vector<std::string> names_;
275 int bulk_depth_ = 0;
276};
277
278} /* namespace openswmm */
279
280#endif /* OPENSWMM_ENGINE_NAME_INDEX_HPP */
Case-insensitive string helpers matching legacy SWMM name semantics.
void remove_at(int idx) noexcept
Remove the entry at idx and rebuild the name→index map.
Definition NameIndex.hpp:231
bool rename(int idx, const std::string &newName) noexcept
Rename the entry at idx to newName.
Definition NameIndex.hpp:206
void begin_bulk_remove() noexcept
Defer map rebuilds across a batch of remove_at() calls.
Definition NameIndex.hpp:248
int try_add(const std::string &name)
Non-throwing add.
Definition NameIndex.hpp:104
bool empty() const noexcept
True if no names are registered.
Definition NameIndex.hpp:166
int size() const noexcept
Number of registered names.
Definition NameIndex.hpp:163
int find(std::string_view name) const noexcept
Look up the index for a name (case-insensitive).
Definition NameIndex.hpp:121
int add(const std::string &name)
Add a new name and assign the next sequential index.
Definition NameIndex.hpp:89
const std::string * canonical(std::string_view name) const noexcept
Stored (original) spelling for a case-insensitive match.
Definition NameIndex.hpp:144
const std::string & name_of(int idx) const
Return the name for a given index.
Definition NameIndex.hpp:154
void pop_back() noexcept
Pop the tail entry — the name added most recently.
Definition NameIndex.hpp:189
const std::vector< std::string > & names() const noexcept
Read-only access to the ordered name list.
Definition NameIndex.hpp:262
void end_bulk_remove()
Close a begin_bulk_remove() scope; outermost close rebuilds the map once. Unbalanced calls are ignore...
Definition NameIndex.hpp:252
void clear() noexcept
Remove all entries.
Definition NameIndex.hpp:177
std::optional< int > try_find(std::string_view name) const noexcept
Look up the index (case-insensitive), returning std::optional.
Definition NameIndex.hpp:130
void reserve(std::size_t n)
Pre-allocate for a known count (avoids rehash during input).
Definition NameIndex.hpp:171
Definition NodeCoupling.cpp:16