/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2011-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file StringBijection.h14/// @author Daniel Krajzewicz15/// @author Michael Behrisch16/// @author Jakob Erdmann17/// @date Mar 201118///19// Bidirectional map between string and something else20/****************************************************************************/21#pragma once22#include <config.h>23#include <iostream>24#include <map>25#include <vector>26#include <string>27#include <utils/common/UtilExceptions.h>2829// ===========================================================================30// class definitions31// ===========================================================================32/**33* Template container for maintaining a bidirectional map between strings and something else34* It is not always a bijection since it allows for duplicate entries on both sides if either35* checkDuplicates is set to false in the constructor or the insert function or if36* the addAlias function is used.37*/38template< class T >39class StringBijection {4041public:4243#ifdef _MSC_VER44#pragma warning(push)45#pragma warning(disable:4510 4512 4610) // no default constructor and no assignment operator; conflicts with initializer46#endif47/// @brief bijection entry48struct Entry {49const std::string str;50const T key;51};52#ifdef _MSC_VER53#pragma warning(pop)54#endif5556/// @brief default constructor57StringBijection() {}5859/// @brief parameter constructor60StringBijection(Entry entries[], T terminatorKey, bool checkDuplicates = true) {61int i = 0;62do {63insert(entries[i].str, entries[i].key, checkDuplicates);64} while (entries[i++].key != terminatorKey);65}6667/// @brief insert string and their associated key68void insert(const std::string str, const T key, bool checkDuplicates = true) {69if (checkDuplicates) {70if (has(key)) {71// cannot use toString(key) because that might create an infinite loop72throw InvalidArgument("Duplicate key.");73}74if (hasString(str)) {75throw InvalidArgument("Duplicate string '" + str + "'.");76}77}78myString2T[str] = key;79myT2String[key] = str;80}8182/// @brief add alias to the given key83void addAlias(const std::string str, const T key) {84myString2T[str] = key;85}8687/// @brief remove string88void remove(const std::string str, const T key) {89myString2T.erase(str);90myT2String.erase(key);91}9293/// @brief get key94T get(const std::string& str) const {95if (hasString(str)) {96return myString2T.find(str)->second;97} else {98throw InvalidArgument("String '" + str + "' not found.");99}100}101102/// @brief get string103const std::string& getString(const T key) const {104if (has(key)) {105return myT2String.find(key)->second;106} else {107// cannot use toString(key) because that might create an infinite loop108throw InvalidArgument("Key not found.");109}110}111112/// @brief check if the given string exist113bool hasString(const std::string& str) const {114return myString2T.count(str) != 0;115}116117/// @brief check if the given key exist118bool has(const T key) const {119return myT2String.count(key) != 0;120}121122/// @brief get number of key-attributes123int size() const {124return (int)myString2T.size();125}126127/// @brief get all strings128std::vector<std::string> getStrings() const {129std::vector<std::string> result;130for (auto item : myT2String) {131result.push_back(item.second);132}133return result;134}135136/// @brief get all keys137std::vector<T> getValues() const {138std::vector<T> result;139for (auto item : myT2String) {140result.push_back(item.first);141}142return result;143}144145/// @brief add the given list of keys146void addKeysInto(std::vector<T>& list) const {147typename std::map<T, std::string>::const_iterator it; // learn something new every day148for (it = myT2String.begin(); it != myT2String.end(); it++) {149list.push_back(it->first);150}151}152153/// @brief get multiline string (all strings concatenated and separated by '\n')154/// @note this will be removed after unifying all FXFileDialog155std::string getMultilineString() const {156std::string result;157if (myT2String.size() > 0) {158for (auto item : myT2String) {159result.append(item.second + "\n");160}161result.pop_back();162}163return result;164}165166private:167/// @brief map with the keys vinculated with strings168std::map<std::string, T> myString2T;169170/// @brief map with the strings vinculated with keys171std::map<T, std::string> myT2String;172};173174175