1 /*
2 * dict.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #ifndef DICT_H
24 #define DICT_H
25 /*
26 SLI's dictionary class
27 */
28 // C++ includes:
29 #include <map>
30
31 // Includes from sli:
32 #include "name.h"
33 #include "sliexceptions.h"
34 #include "token.h"
35
36
37 typedef std::map< Name, Token, std::less< Name > > TokenMap;
38
39 inline bool operator==( const TokenMap& x, const TokenMap& y )
40 {
41 return ( x.size() == y.size() ) && equal( x.begin(), x.end(), y.begin() );
42 }
43
44 /** A class that associates names and tokens.
45 * @ingroup TokenHandling
46 */
47 class Dictionary : private TokenMap
48 {
49 /**
50 * Helper class for lexicographical sorting of dictionary entries.
51 * Provides comparison operator for ascending, case-insensitive
52 * lexicographical ordering.
53 * @see This is a simplified version of the class presented in
54 * N.M.Josuttis, The C++ Standard Library, Addison Wesley, 1999,
55 * ch. 6.6.6.
56 */
57 class DictItemLexicalOrder
58 {
59 private:
60 static bool nocase_compare( char c1, char c2 );
61
62 public:
operator()63 bool operator()( const std::pair< Name, Token >& lhs, const std::pair< Name, Token >& rhs ) const
64 {
65 const std::string& ls = lhs.first.toString();
66 const std::string& rs = rhs.first.toString();
67
68 return std::lexicographical_compare( ls.begin(), ls.end(), rs.begin(), rs.end(), nocase_compare );
69 }
70 };
71
72 public:
Dictionary()73 Dictionary()
74 : refs_on_dictstack_( 0 )
75 {
76 }
Dictionary(const Dictionary & d)77 Dictionary( const Dictionary& d )
78 : TokenMap( d )
79 , refs_on_dictstack_( 0 )
80 {
81 }
82 ~Dictionary();
83
84 using TokenMap::erase;
85 using TokenMap::size;
86 using TokenMap::begin;
87 using TokenMap::end;
88 using TokenMap::iterator;
89 using TokenMap::find;
90
91 void clear();
92
93 /**
94 * Lookup and return Token with given name in dictionary.
95 * If the name is not found, an empty token is returned.
96 * This version of lookup is deprecated and will disappear in future versions.
97 * Please use lookup2() instead.
98 * @note The token returned should @b always be stored as a
99 * <tt>const \&</tt>, so that the control flag for
100 * dictionary read-out is set on the Token in the dictionary,
101 * not its copy.
102 */
103
104 const Token& lookup( const Name& n ) const;
105
106 /**
107 * lookup a name in the dictionary. If the name is not found an UndefinedName
108 * exception is thrown.
109 * lookup2 is the preferred way to retrieve entries from the dictionary.
110 * @note The token returned should @b always be stored as a
111 * <tt>const \&</tt>, so that the control flag for
112 * dictionary read-out is set on the Token in the dictionary,
113 * not its copy.
114 */
115 const Token& lookup2( const Name& n ) const; // throws UndefinedName
116 bool known( const Name& ) const;
117
118 //! Returns true if name is known but token has not been accessed
119 bool known_but_not_accessed( const Name& ) const;
120
121 Token& insert( const Name& n, const Token& t );
122 Token& insert_move( const Name&, Token& );
123
124 //! Remove entry from dictionary
125 void remove( const Name& n );
126
127 const Token& operator[]( const Name& ) const;
128 Token& operator[]( const Name& );
129 const Token& operator[]( const char* ) const;
130 Token& operator[]( const char* );
131
132 bool
empty(void)133 empty( void ) const
134 {
135 return TokenMap::empty();
136 }
137
138 void info( std::ostream& ) const;
139
140 bool operator==( const Dictionary& d ) const
141 {
142 return ::operator==( *this, d );
143 }
144
145 /**
146 * Add the contents of this dictionary to another.
147 * The target dictionary is given by names and must be retrieved via
148 * the interpreter.
149 * @todo Allow for free formatting of target dictionary entries
150 * via functor, and add traits to allow duplicates.
151 * @see remove_dict
152 */
153 void add_dict( const std::string&, SLIInterpreter& );
154
155 /**
156 * Remove entries found in another dictionary from this.
157 * @see add_dict
158 */
159 void remove_dict( const std::string&, SLIInterpreter& );
160
161 /**
162 * Clear access flags on all dictionary elements.
163 * Flags for nested dictionaries are cleared recursively.
164 * @see all_accessed()
165 */
166 void clear_access_flags();
167
168 /**
169 * Check whether all elements have been accessed.
170 * Checks nested dictionaries recursively.
171 * @param std::string& contains string with names of non-accessed entries
172 * @returns true if all dictionary elements have been accessed
173 * @note this is just a wrapper, all_accessed_() does the work, hides
174 * recursion
175 * @see clear_access_flags(), all_accessed_()
176 */
177 bool
all_accessed(std::string & missed)178 all_accessed( std::string& missed ) const
179 {
180 return all_accessed_( missed );
181 }
182
183 friend std::ostream& operator<<( std::ostream&, const Dictionary& );
184
185 /**
186 * Constant iterator for dictionary.
187 * Dictionary inherits privately from std::map to hide implementation
188 * details. To allow for inspection of all elements in a dictionary,
189 * we export the constant iterator type and begin() and end() methods.
190 */
191 typedef TokenMap::const_iterator const_iterator;
192
193 /**
194 * First element in dictionary.
195 * Dictionary inherits privately from std::map to hide implementation
196 * details. To allow for inspection of all elements in a dictionary,
197 * we export the constant iterator type and begin() and end() methods.
198 */
199 // const_iterator begin() const;
200
201 /**
202 * One-past-last element in dictionary.
203 * Dictionary inherits privately from std::map to hide implementation
204 * details. To allow for inspection of all elements in a dictionary,
205 * we export the constant iterator type and begin() and end() methods.
206 */
207 // const_iterator end() const;
208
209 /**
210 *
211 */
212 void initialize_property_array( Name propname );
213
214 /**
215 * This function is called when a dictionary is pushed to the dictionary
216 * stack. The dictioray stack must keep track about which dictioraries are on
217 * the dictionary stack. If a dictionary is modified and it is on the
218 * dictionary stack, the cache of the dictionary stack must
219 * be adjusted. This is e.g. the case for the systemdict or the errordict.
220 */
221 void
add_dictstack_reference()222 add_dictstack_reference()
223 {
224 ++refs_on_dictstack_;
225 }
226
227 /**
228 * This function is called when the dictionary is popped from the dictionary
229 * stack.
230 */
231 void
remove_dictstack_reference()232 remove_dictstack_reference()
233 {
234 --refs_on_dictstack_;
235 }
236
237 /**
238 * Returns true, if the dictionary has references on the dictionary stack.
239 */
240 bool
is_on_dictstack()241 is_on_dictstack() const
242 {
243 return refs_on_dictstack_ > 0;
244 }
245
246
247 private:
248 /**
249 * Worker function checking whether all elements have been accessed.
250 * Checks nested dictionaries recursively.
251 * @param std::string& contains string with names of non-accessed entries
252 * @param std::string prefix for nested dictionary entries, built during
253 * recursion
254 * @returns true if all dictionary elements have been accessed
255 * @note this is just the worker for all_accessed()
256 * @see clear_access_flags(), all_accessed()
257 */
258
259 int refs_on_dictstack_;
260 bool all_accessed_( std::string&, std::string prefix = std::string() ) const;
261 static const Token VoidToken;
262 };
263
264 inline const Token&
lookup(const Name & n)265 Dictionary::lookup( const Name& n ) const
266 {
267 TokenMap::const_iterator where = find( n );
268 if ( where != end() )
269 {
270 return ( *where ).second;
271 }
272 else
273 {
274 return Dictionary::VoidToken;
275 }
276 }
277
278 inline const Token&
lookup2(const Name & n)279 Dictionary::lookup2( const Name& n ) const
280 {
281 TokenMap::const_iterator where = find( n );
282 if ( where != end() )
283 {
284 return ( *where ).second;
285 }
286 else
287 {
288 throw UndefinedName( n.toString() );
289 }
290 }
291
292 inline bool
known(const Name & n)293 Dictionary::known( const Name& n ) const
294 {
295 TokenMap::const_iterator where = find( n );
296 if ( where != end() )
297 {
298 return true;
299 }
300 else
301 {
302 return false;
303 }
304 }
305
306 inline bool
known_but_not_accessed(const Name & n)307 Dictionary::known_but_not_accessed( const Name& n ) const
308 {
309 TokenMap::const_iterator where = find( n );
310 if ( where != end() )
311 {
312 return not where->second.accessed();
313 }
314 else
315 {
316 return false;
317 }
318 }
319
320 inline Token&
insert(const Name & n,const Token & t)321 Dictionary::insert( const Name& n, const Token& t )
322 {
323 return TokenMap::operator[]( n ) = t;
324 }
325
326
327 inline const Token& Dictionary::operator[]( const Name& n ) const
328 {
329 TokenMap::const_iterator where = find( n );
330 if ( where != end() )
331 {
332 return ( *where ).second;
333 }
334 else
335 {
336 throw UndefinedName( n.toString() );
337 }
338 }
339
340
341 inline Token& Dictionary::operator[]( const Name& n )
342 {
343 return TokenMap::operator[]( n );
344 }
345
346 inline Token&
insert_move(const Name & n,Token & t)347 Dictionary::insert_move( const Name& n, Token& t )
348 {
349 Token& result = TokenMap::operator[]( n );
350 result.move( t );
351 return result;
352 }
353
354
355 #endif
356