1 /*
2 * dict.cc
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 #include "dict.h"
24
25 // C++ includes:
26 #include <algorithm>
27 #include <cstdlib>
28 #include <iomanip>
29 #include <string>
30 #include <vector>
31
32 // Includes from sli:
33 #include "dictdatum.h"
34 #include "dictutils.h"
35 #include "sliexceptions.h"
36
37 const Token Dictionary::VoidToken;
38
~Dictionary()39 Dictionary::~Dictionary()
40 {
41 }
42
operator [](const char * n) const43 const Token& Dictionary::operator[]( const char* n ) const
44 {
45 return operator[]( Name( n ) );
46 }
47
operator [](const char * n)48 Token& Dictionary::operator[]( const char* n )
49 {
50 return operator[]( Name( n ) );
51 }
52
53 void
clear()54 Dictionary::clear()
55 {
56 TokenMap cp( *this );
57 TokenMap::clear();
58
59 for ( TokenMap::iterator i = cp.begin(); i != cp.end(); ++i )
60 {
61 Token* tok = &i->second;
62 Datum* datum = tok->datum();
63 DictionaryDatum* d = dynamic_cast< DictionaryDatum* >( datum );
64 if ( not d )
65 {
66 continue;
67 }
68
69 Dictionary* dt = d->get();
70 d->unlock();
71 dt->clear();
72 }
73 }
74
75 void
info(std::ostream & out) const76 Dictionary::info( std::ostream& out ) const
77 {
78 out.setf( std::ios::left );
79 if ( size() > 0 )
80 {
81 // copy to vector and sort
82 typedef std::vector< std::pair< Name, Token > > DataVec;
83 DataVec data;
84 std::copy( begin(), end(), std::inserter( data, data.begin() ) );
85 std::sort( data.begin(), data.end(), DictItemLexicalOrder() );
86
87 out << "--------------------------------------------------" << std::endl;
88 out << std::setw( 25 ) << "Name" << std::setw( 20 ) << "Type"
89 << "Value" << std::endl;
90 out << "--------------------------------------------------" << std::endl;
91
92 for ( DataVec::const_iterator where = data.begin(); where != data.end(); ++where )
93 {
94 out << std::setw( 25 ) << where->first << std::setw( 20 ) << where->second->gettypename() << where->second
95 << std::endl;
96 }
97 out << "--------------------------------------------------" << std::endl;
98 }
99 out << "Total number of entries: " << size() << std::endl;
100
101 out.unsetf( std::ios::left );
102 }
103
104 void
add_dict(const std::string & target,SLIInterpreter & i)105 Dictionary::add_dict( const std::string& target, SLIInterpreter& i )
106 {
107 DictionaryDatum targetdict;
108
109 // retrieve targetdict from interpreter
110 Token d = i.baselookup( Name( target ) );
111 targetdict = getValue< DictionaryDatum >( d );
112
113 for ( TokenMap::const_iterator it = TokenMap::begin(); it != TokenMap::end(); ++it )
114 {
115 if ( not targetdict->known( it->first ) )
116 {
117 targetdict->insert( it->first, it->second );
118 }
119 else
120 {
121 throw UndefinedName( ( it->first ).toString() );
122 // throw DictError();
123 }
124 }
125 }
126
127 void
remove(const Name & n)128 Dictionary::remove( const Name& n )
129 {
130 TokenMap::iterator it = find( n );
131 if ( it != end() )
132 {
133 erase( it );
134 }
135 }
136
137 void
remove_dict(const std::string & target,SLIInterpreter & i)138 Dictionary::remove_dict( const std::string& target, SLIInterpreter& i )
139 {
140 DictionaryDatum targetdict;
141
142 // retrieve targetdict from interpreter
143 Token d = i.baselookup( Name( target ) );
144 targetdict = getValue< DictionaryDatum >( d );
145
146 for ( TokenMap::const_iterator it = TokenMap::begin(); it != TokenMap::end(); ++it )
147 {
148 TokenMap::iterator tgt_it = targetdict->find( it->first );
149 if ( tgt_it != targetdict->end() )
150 {
151 targetdict->erase( tgt_it );
152 }
153 }
154 }
155
156 void
clear_access_flags()157 Dictionary::clear_access_flags()
158 {
159 for ( TokenMap::iterator it = TokenMap::begin(); it != TokenMap::end(); ++it )
160 {
161 /*
162 Clear flags in nested dictionaries recursively.
163 We first test whether the token is a DictionaryDatum
164 and then call getValue(). This entails two dynamic casts,
165 but is likely more efficient than a try-catch construction.
166 */
167 if ( it->second.is_a< DictionaryDatum >() )
168 {
169 DictionaryDatum subdict = getValue< DictionaryDatum >( it->second );
170 subdict->clear_access_flags();
171 }
172
173 // in recursion, getValue sets the access flag for it->second, so
174 // we must clear it after recursion is done
175 it->second.clear_access_flag();
176 }
177 }
178
179 bool
all_accessed_(std::string & missed,std::string prefix) const180 Dictionary::all_accessed_( std::string& missed, std::string prefix ) const
181 {
182 missed = "";
183
184 // build list of all non-accessed Token names
185 for ( TokenMap::const_iterator it = TokenMap::begin(); it != TokenMap::end(); ++it )
186 {
187 if ( not it->second.accessed() )
188 {
189 missed = missed + " " + prefix + it->first.toString();
190 }
191 else if ( it->second.is_a< DictionaryDatum >() )
192 {
193 // recursively check if nested dictionary content was accessed
194 // see also comments in clear_access_flags()
195
196 // this sets access flag on it->second, but that does not matter,
197 // since it is anyways set, otherwise we would not be recursing
198 DictionaryDatum subdict = getValue< DictionaryDatum >( it->second );
199
200 subdict->all_accessed_( missed, prefix + it->first.toString() + "::" );
201 }
202 }
203
204 return missed.empty();
205 }
206
operator <<(std::ostream & out,const Dictionary & d)207 std::ostream& operator<<( std::ostream& out, const Dictionary& d )
208 {
209 out << "<<";
210
211 for ( TokenMap::const_iterator where = d.begin(); where != d.end(); ++where )
212 {
213 out << ( *where ).first << ' ' << ( *where ).second << ',';
214 }
215 out << ">>";
216
217 return out;
218 }
219
220 bool
nocase_compare(char c1,char c2)221 Dictionary::DictItemLexicalOrder::nocase_compare( char c1, char c2 )
222 {
223 return std::toupper( c1 ) < std::toupper( c2 );
224 }
225