Dictionary.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 #ifndef DRAIN_DICTIONARY
32 #define DRAIN_DICTIONARY "Dictionary v2.0"
33 
34 //
35 #include <iostream>
36 #include <map>
37 #include <list>
38 #include <string>
39 
40 //#include "Log.h"
41 #include <drain/Sprinter.h>
42 
43 
44 
45 namespace drain {
46 
48 
52 // TODO: consider map<K, V> for faster search and order? But no, if still slow.
53 
62 template <class K, class V>
63 class Dictionary : public std::list<std::pair<K, V> > {
64 
65 public:
66 
67  typedef K key_t;
68  typedef V value_t;
69 
70  typedef std::pair<K, V> entry_t;
71  typedef std::list<entry_t> container_t;
72 
73  typedef std::list<key_t> keylist_t;
74  typedef std::list<value_t> valuelist_t;
75 
76 
77  Dictionary() : separator(','){};
78 
79  Dictionary(const Dictionary & d) : separator(d.separator){};
80 
81  Dictionary(std::initializer_list<entry_t> d) : std::list<entry_t>(d), separator(','){
82  };
83 
84 
85  virtual
86  ~Dictionary(){};
87 
88  inline
89  const container_t & getContainer() const {
90  return *this;
91  }
92 
93  entry_t & add(const K & key, const V & value){
94  this->push_back(entry_t(key, value));
95  return this->back();
96  }
97 
99  entry_t & set(const K & key, const V & value){
100  for (entry_t & entry: *this){
101  if (entry.first == key){
102  entry.second = value;
103  return entry;
104  }
105  }
106  this->push_back(entry_t(key, value));
107  return this->back();
108  }
109 
110  const V & operator[](const K & key) const {
111  return getValue(key);
112  }
113 
114  const V & operator()(const V & value) const {
115  return getKey(value);
116  }
117 
118 
119  typename container_t::const_iterator findByKey(const K & key) const {
120  for (typename container_t::const_iterator it = this->begin(); it != this->end(); ++it){
121  if (it->first == key)
122  return it;
123  }
124  return this->end();
125  }
126 
127  typename container_t::const_iterator findByValue(const V & value) const {
128  for (typename container_t::const_iterator it = this->begin(); it != this->end(); ++it){
129  if (it->second == value)
130  return it;
131  }
132  return this->end();
133  }
134 
135 
136  inline
137  bool hasKey(const K & key) const {
138  return (findByKey(key) != this->end());
139  }
140 
142  inline
143  bool hasValue(const V & value) const {
144  return (findByValue(value) != this->end());
145  }
146 
147 
149  const V & getValue(const K & key) const {
150  typename container_t::const_iterator it = findByKey(key);
151  if (it != this->end())
152  return it->second;
153  else {
154  static V empty;
155  return empty;
156  }
157 
158  }
159 
161  const K & getKey(const V & value) const {
162  typename container_t::const_iterator it = findByValue(value);
163  if (it != this->end())
164  return it->first;
165  else {
166  static K empty;
167  return empty;
168  }
169  }
170 
171 
172  const keylist_t & getKeys() const {
173 
174  #pragma omp critical
175  {
176  keyList.clear();
177  for (const entry_t & entry: *this){
178  keyList.push_back(entry.first);
179  }
180  }
181  return keyList;
182  }
183 
184  void getKeys(keylist_t & l) const {
185  for (const entry_t & entry: *this){
186  l.push_back(entry.first);
187  }
188  }
189 
190 
191  const valuelist_t & getValues() const {
192 
193  #pragma omp critical
194  {
195  valueList.clear();
196  for (const entry_t & entry: *this){
197  valueList.push_back(entry.second);
198  }
199  }
200  return valueList;
201  }
202 
203  void getValues(keylist_t & l) const {
204  for (const entry_t & entry: *this){
205  l.push_back(entry.second);
206  }
207  }
208 
209  char separator;
210 
211 protected:
212 
213  mutable
214  keylist_t keyList;
215 
216  mutable
217  valuelist_t valueList;
218 
219 
220 };
221 
222 /*
223 template <class K, class V>
224 inline
225 std::ostream & operator<<(std::ostream & ostr, const Dictionary<K,V> & dict) {
226  dict.toStream(ostr);
227  return ostr;
228 }
229 */
230 
231 template <class K, class V>
232 inline
233 std::ostream & operator<<(std::ostream & ostr, const Dictionary<K,V> & dict) {
234  // SprinterLayout(const char *arrayChars="[,]", const char *mapChars="{,}", const char *pairChars="(,)", const char *stringChars=nullptr)
235  // static drain::SprinterLayout dict_layout("{,}", "{,}", "{,}", "{,}");
236  static const SprinterLayout cmdArgLayout = {",", "?", "=", ""};
237  // Note: the following cast is (also) the only way to apply layout on a Dictionary
238  //ostr << drain::sprinter(dict.getContainer(), Sprinter::cppLayout);
239  ostr << drain::sprinter(dict.getContainer(), cmdArgLayout);
240  //ostr << drain::sprinter((const typename Dictionary<K,V>::container_t &)dict, Sprinter::cppLayout);
241  return ostr;
242 }
243 
244 /*
245 template <>
246 inline
247 std::ostream & Sprinter::toStream(std::ostream & ostr, const drain::Variable & x, const SprinterLayout & layout){
248  return Sprinter::toStream(ostr, (const drain::Castable &)x, layout);
249 }
250 */
251 
252 
253 
255 template <class K, class V>
256 class DictionaryPtr : public Dictionary<K, V*> {
257 
258 public:
259 
260  typedef Dictionary<K, V*> parent_t;
261 
262  DictionaryPtr(){};
263 
264  virtual
265  ~DictionaryPtr(){};
266 
267  //virtual
268  void add(const K & key, const V & value){
269  Dictionary<K, V*>::add(key, &value);
270  }
271 
272  typename parent_t::container_t::const_iterator findByValue(const V & value) const {
273  return parent_t::findByValue(& value);
274  }
275 
276  //virtual
277  const V & getValue(const K & key) const {
278  return *Dictionary<K, V*>::getValue(key);
279  }
280 
281  //virtual
282  const K & getKey(const V & value) const {
283  return Dictionary<K, V*>::getKey(&value);
284  }
285 
286 
287 };
288 
289 } // drain::
290 
291 
292 #endif
293 
294 // Drain
Associates type info.
Definition: Dictionary.h:256
Two-way mapping between strings and objects of template class T.
Definition: Dictionary.h:63
const V & getValue(const K &key) const
Given a key, return the first value associated with it.
Definition: Dictionary.h:149
const K & getKey(const V &value) const
Given a value, return the first key associated with it.
Definition: Dictionary.h:161
bool hasValue(const V &value) const
Given a key, return the first value associated with it.
Definition: Dictionary.h:143
entry_t & set(const K &key, const V &value)
Replaces existing or adds.
Definition: Dictionary.h:99
Definition: DataSelector.cpp:1277