1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2011-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    StringBijection.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Michael Behrisch
13 /// @author  Jakob Erdmann
14 /// @date    Mar 2011
15 /// @version $Id$
16 ///
17 // Bidirectional map between string and something else
18 /****************************************************************************/
19 #ifndef StringBijection_h
20 #define StringBijection_h
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 
27 #include <iostream>
28 #include <map>
29 #include <vector>
30 #include <string>
31 #include <utils/common/UtilExceptions.h>
32 
33 // ===========================================================================
34 // class definitions
35 // ===========================================================================
36 /**
37  * Template container for maintaining a bidirectional map between strings and something else
38  * It is not always a bijection since it allows for duplicate entries on both sides if either
39  * checkDuplicates is set to false in the constructor or the insert function or if
40  * the addAlias function is used.
41  */
42 
43 template< class T  >
44 class StringBijection {
45 
46 public:
47 
48 #ifdef _MSC_VER
49 #pragma warning(push)
50 #pragma warning(disable:4510 4512 4610) // no default constructor and no assignment operator; conflicts with initializer
51 #endif
52     struct Entry {
53         const char* str;
54         const T key;
55     };
56 #ifdef _MSC_VER
57 #pragma warning(pop)
58 #endif
59 
60 
StringBijection()61     StringBijection() {}
62 
63 
64     StringBijection(Entry entries[], T terminatorKey, bool checkDuplicates = true) {
65         int i = 0;
66         do {
67             insert(entries[i].str, entries[i].key, checkDuplicates);
68         } while (entries[i++].key != terminatorKey);
69     }
70 
71 
72     void insert(const std::string str, const T key, bool checkDuplicates = true) {
73         if (checkDuplicates) {
74             if (has(key)) {
75                 // cannot use toString(key) because that might create an infinite loop
76                 throw InvalidArgument("Duplicate key.");
77             }
78             if (hasString(str)) {
79                 throw InvalidArgument("Duplicate string '" + str + "'.");
80             }
81         }
82         myString2T[str] = key;
83         myT2String[key] = str;
84     }
85 
86 
addAlias(const std::string str,const T key)87     void addAlias(const std::string str, const T key) {
88         myString2T[str] = key;
89     }
90 
91 
remove(const std::string str,const T key)92     void remove(const std::string str, const T key) {
93         myString2T.erase(str);
94         myT2String.erase(key);
95     }
96 
97 
get(const std::string & str)98     T get(const std::string& str) const {
99         if (hasString(str)) {
100             return myString2T.find(str)->second;
101         } else {
102             throw InvalidArgument("String '" + str + "' not found.");
103         }
104     }
105 
106 
getString(const T key)107     const std::string& getString(const T key) const {
108         if (has(key)) {
109             return myT2String.find(key)->second;
110         } else {
111             // cannot use toString(key) because that might create an infinite loop
112             throw InvalidArgument("Key not found.");
113         }
114     }
115 
116 
hasString(const std::string & str)117     bool hasString(const std::string& str) const {
118         return myString2T.count(str) != 0;
119     }
120 
121 
has(const T key)122     bool has(const T key) const {
123         return myT2String.count(key) != 0;
124     }
125 
126 
size()127     int size() const {
128         return (int)myString2T.size();
129     }
130 
131 
getStrings()132     std::vector<std::string> getStrings() const {
133         std::vector<std::string> result;
134         typename std::map<T, std::string>::const_iterator it; // learn something new every day
135         for (it = myT2String.begin(); it != myT2String.end(); it++) {
136             result.push_back(it->second);
137         }
138         return result;
139     }
140 
141 
addKeysInto(std::vector<T> & list)142     void addKeysInto(std::vector<T>& list) const {
143         typename std::map<T, std::string>::const_iterator it; // learn something new every day
144         for (it = myT2String.begin(); it != myT2String.end(); it++) {
145             list.push_back(it->first);
146         }
147     }
148 
149 
150 private:
151     std::map<std::string, T> myString2T;
152     std::map<T, std::string> myT2String;
153 
154 };
155 
156 #endif
157 
158 /****************************************************************************/
159 
160