#ifndef NAME_H
#define NAME_H
/*
* name.h
*
* 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 <cassert>
#include <map>
#include <string>
#include <deque>
#include <iostream>
/**
* Represent strings by ints to facilitate fast comparison.
*
* Each Name object represents a string by a unique integer number.
* Comparing Name objects instead of comparing strings directly,
* reduces the complexity of string comparison to that of int comparison.
*
* Each Name object contains a Handle to the string it represents. Strings are
* mapped to Handles via an associative array. Handles are stored in a table,
* and each Handle contains its own index into this table as unique ID, as
* well as the string represented. Fast comparison of Name objects is achieved
* by comparing the indices stored in the handles. Reference counting
* permits deletion of unused Handles.
*
* @note Any string read by the interpreter should be converted to a Name
* at once.
* @note class Name maintains two static lookup tables and is thus not
* thread-safe.
*
*/
class Name
{
public:
typedef unsigned int handle_t;
/**
* Create Name without value.
*/
Name() : handle_(0) {}
Name(const char s[]) : handle_(insert(std::string(s))) {}
Name(const std::string &s) : handle_(insert(s)) {}
Name(const Name &n) : handle_(n.handle_) {}
/**
* Return string represented by Name.
*/
const std::string& toString(void) const;
/**
* Return table index for Name object.
*/
handle_t toIndex(void) const
{
return handle_;
}
bool operator== (const Name &n) const
{
return handle_ == n.handle_;
}
bool operator!= (const Name &n) const
{
return !(handle_ == n.handle_);
}
/**
* Non-alphabetic ordering of names.
* Entering Name's into dictionaries requires ordering. Ordering based
* on string comparison would be very slow. We thus compare based on
* table indices.
*/
bool operator< (const Name &n) const
{
return handle_ < n.handle_;
}
static bool lookup(const std::string &s)
{
HandleMap_ &table=handleMapInstance_();
return (table.find(s) != table.end());
}
static
size_t capacity();
static
size_t num_handles();
void print_handle(std::ostream&) const;
static void list_handles(std::ostream &);
static void list(std::ostream &);
static void info(std::ostream &);
private:
handle_t insert(const std::string&);
/**
* Datatype for map from strings to handles.
*/
typedef std::map<std::string, handle_t> HandleMap_;
typedef std::deque<std::string> HandleTable_;
/**
* Function returning a reference to the single map instance.
* Implementation akin to Meyers Singleton, see Alexandrescu, ch 6.4.
*/
static HandleMap_& handleMapInstance_();
static HandleTable_& handleTableInstance_();
/**
* Handle for the name represented by the Name object.
*/
handle_t handle_;
};
std::ostream& operator<<(std::ostream&, const Name&);
inline
Name::HandleTable_& Name::handleTableInstance_()
{
// Meyers singleton, created first time function is invoked.
static HandleTable_ handleTable(1,"0");
return handleTable;
}
inline
Name::HandleMap_& Name::handleMapInstance_()
{
// Meyers singleton, created first time function is invoked.
static HandleMap_ handleMap;
handleTableInstance_();
return handleMap;
}
#endif