/* * dict.cc * * This file is part of NEST. * * Copyright (C) 2004 The NEST Initiative * * NEST is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * NEST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NEST. If not, see <http://www.gnu.org/licenses/>. * */ #include "dict.h" #include "dictdatum.h" #include "dictutils.h" #include "sliexceptions.h" #include <iomanip> #include <algorithm> #include <vector> #include <cstdlib> #include <string> const Token Dictionary::VoidToken; Dictionary::~Dictionary() { } const Token& Dictionary::operator[](const char *n) const { return operator[](Name(n)); } Token& Dictionary::operator[](const char *n) { return operator[](Name(n)); } void Dictionary::clear() { // First, clear all contained dictionaries for(TokenMap::iterator i = TokenMap::begin(); i != end(); ++i) { DictionaryDatum *d=dynamic_cast<DictionaryDatum*>((*i).second.datum()); if(d !=0) { if(d->get()!= this) (*d)->clear(); d->unlock(); } (*i).second.clear(); } // now clear dictionary itself; HEP 2004-09-08 TokenMap::clear(); } void Dictionary::info(std::ostream &out) const { out.setf(std::ios::left); if(size()>0) { // copy to vector and sort typedef std::vector<std::pair<Name, Token> >DataVec; DataVec data; std::copy(begin(), end(), std::inserter(data, data.begin())); std::sort(data.begin(), data.end(), DictItemLexicalOrder()); out << "--------------------------------------------------" << std::endl; out << std::setw(25) << "Name" << std::setw(20) << "Type" << "Value" << std::endl; out << "--------------------------------------------------" << std::endl; for(DataVec::const_iterator where = data.begin() ; where != data.end() ; ++ where) { out << std::setw(25) << where->first << std::setw(20) << where->second->gettypename() << where->second << std::endl; } out << "--------------------------------------------------" << std::endl; } out << "Total number of entries: "<< size() << std::endl; out.unsetf(std::ios::left); } void Dictionary::add_dict(const std::string& target, SLIInterpreter& i) { DictionaryDatum targetdict; // retrieve targetdict from interpreter Token d = i.baselookup(Name(target)); targetdict = getValue<DictionaryDatum>(d); for ( TokenMap::const_iterator it = TokenMap::begin() ; it != TokenMap::end() ; ++it ) if ( !targetdict->known(it->first) ) targetdict->insert(it->first, it->second); else { throw UndefinedName((it->first).toString()); // throw DictError(); } } void Dictionary::remove(const Name& n) { TokenMap::iterator it = find(n); if ( it != end() ) erase(it); } void Dictionary::remove_dict(const std::string& target, SLIInterpreter& i) { DictionaryDatum targetdict; // retrieve targetdict from interpreter Token d = i.baselookup(Name(target)); targetdict = getValue<DictionaryDatum>(d); for ( TokenMap::const_iterator it = TokenMap::begin() ; it != TokenMap::end() ; ++it ) { TokenMap::iterator tgt_it = targetdict->find(it->first); if ( tgt_it != targetdict->end() ) targetdict->erase(tgt_it); } } void Dictionary::clear_access_flags() { for ( TokenMap::iterator it = TokenMap::begin() ; it != TokenMap::end() ; ++it ) { /* Clear flags in nested dictionaries recursively. We first test whether the token is a DictionaryDatum and then call getValue(). This entails two dynamic casts, but is likely more efficient than a try-catch construction. */ if ( it->second.is_a<DictionaryDatum>() ) { DictionaryDatum subdict = getValue<DictionaryDatum>(it->second); subdict->clear_access_flags(); } // in recursion, getValue sets the access flag for it->second, so // we must clear it after recursion is done it->second.clear_access_flag(); } } bool Dictionary::all_accessed_(std::string& missed, std::string prefix) const { missed = ""; // build list of all non-accessed Token names for ( TokenMap::const_iterator it = TokenMap::begin() ; it != TokenMap::end() ; ++it ) { if ( !it->second.accessed() ) missed = missed + " " + prefix + it->first.toString(); else if ( it->second.is_a<DictionaryDatum>() ) { // recursively check if nested dictionary content was accessed // see also comments in clear_access_flags() // this sets access flag on it->second, but that does not matter, // since it is anyways set, otherwise we would not be recursing DictionaryDatum subdict = getValue<DictionaryDatum>(it->second); subdict->all_accessed_(missed, prefix + it->first.toString() + "::"); } } return missed.empty(); } std::ostream & operator<<(std::ostream &out, const Dictionary &d) { out << "<<"; for(TokenMap::const_iterator where = d.begin(); where != d.end(); where ++) { out << (*where).first << ' ' << (*where).second << ','; } out << ">>"; return out; } bool Dictionary::DictItemLexicalOrder::nocase_compare(char c1, char c2) { return std::toupper(c1) < std::toupper(c2); }