/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef OBJECT_NAMES_H
#define OBJECT_NAMES_H
#include "ptr.h"
#include "object.h"
/**
* \file
* \ingroup config
* Declaration of class ns3::Names.
*/
namespace ns3 {
/**
* \ingroup config
* \brief A directory of name and Ptr<Object> associations that allows us to
* give any ns3 Object a name.
*/
class Names
{
public:
/**
* \brief Add the association between the string "name" and the Ptr<Object> obj.
*
* The name may begin either with "/Names" to explicitly call out the fact
* that the name provided is installed under the root of the name space,
* or it may begin with the name of the first object in the path. For example,
* Names::Add ("/Names/client", obj) and Names::Add ("client", obj) accomplish
* exactly the same thing. A name at a given level in the name space path must
* be unique. In the case of the example above, it would be illegal to try and
* associate a different object with the same name: "client" at the same level
* ("/Names") in the path.
*
* As well as specifying a name at the root of the "/Names" namespace, the
* name parameter can contain a path that fully qualifies the name to
* be added. For example, if you previously have named an object "client"
* in the root namespace as above, you could name an object "under" that
* name by making a call like Names::Add ("/Names/client/eth0", obj). This
* will define the name "eth0" and make it reachable using the path specified.
* Note that Names::Add ("client/eth0", obj) would accomplish exactly the same
* thing.
*
* Duplicate names are not allowed at the same level in a path, however you may
* associate similar names with different paths. For example, if you define
* "/Names/Client", you may not define another "/Names/Client" just as you may
* not have two files with the same name in a classical filesystem. However,
* you may have "/Names/Client/eth0" and "/Names/Server/eth0" defined at the
* same time just as you might have different files of the same name under
* different directories.
*
* \param name The name of the object you want to associate; which may be
* prepended with a path to that object.
* \param object A smart pointer to the object itself.
*/
static void Add (std::string name, Ptr<Object> object);
/**
* \brief An intermediate form of Names::Add allowing you to provide a path to
* the parent object (under which you want this name to be defined) in the form
* of a name path string.
*
* In some cases, it is desirable to break up the path used to describe an item
* in the names namespace into a path and a name. This is analogous to a
* file system operation in which you provide a directory name and a file name.
*
* For example, consider a situation where you have previously named an object
* "/Names/server". If you further want to create an association for between a
* Ptr<Object> object that you want to live "under" the server in the name space
* -- perhaps "eth0" -- you could do this in two ways, depending on which was
* more convenient: Names::Add ("/Names/server/eth0", object) or, using the split
* path and name approach, Names::Add ("/Names/server", "eth0", object).
*
* Duplicate names are not allowed at the same level in a path, however you may
* associate similar names with different paths. For example, if you define
* "/Names/Client", you may not define another "/Names/Client" just as you may
* not have two files with the same name in a classical filesystem. However,
* you may have "/Names/Client/eth0" and "/Names/Server/eth0" defined at the
* same time just as you might have different files of the same name under
* different directories.
*
* \param path A path name describing a previously named object under which
* you want this new name to be defined.
* \param name The name of the object you want to associate.
* \param object A smart pointer to the object itself.
*
* \see Names::Add (Ptr<Object> context, std::string name, Ptr<Object> object);
*/
static void Add (std::string path, std::string name, Ptr<Object> object);
/**
* \brief A low-level form of Names::Add allowing you to specify the path to
* the parent object (under which you want this name to be defined) in the form
* of a previously named object.
*
* In some use cases, it is desirable to break up the path in the names name
* space into a path and a name. This is analogous to a file system operation
* in which you provide a directory name and a file name. Recall that the path
* string actually refers to a previously named object, "under" which you want
* to accomplish some naming action.
*
* However, the path is sometimes not available, and you only have the object
* that is represented by the path in the names name space. To support this
* use-case in a reasonably high-performance way, the path string is can be
* replaced by the object pointer to which that path would refer. In the spirit
* of the Config code where this use-case is most prominent, we refer to this
* object as the "context" for the names operation.
*
* You can think of the context roughly as the inode number of a directory file
* in Unix. The inode number can be used to look up the directory file which
* contains the list of file names defined at that directory level. Similarly
* the context is used to look up an internal name service entry which contains
* the names defined for that context.
*
* For example, consider a situation where you have previously named an object
* "/Names/server". If you further want to create an association for between a
* Ptr<Object> object that you want to live "under" the server in the name space
* -- perhaps "eth0" -- you could do this by providing a complete path to the
* new name: Names::Add ("/Names/server/eth0", object). If, however, somewhere
* in your code you only had a pointer to the server, say Ptr<Node> node, and
* not a handy path string, you could also accomplish this by
* Names::Add (node, "eth0", object).
*
* Duplicate names are not allowed at the same level in a path. In the case
* of this method, the context object gives the same information as a path
* string. You may associate similar names with different paths. For example,
* if you define"/Names/Client", you may not define another "/Names/Client"
* just as you may not have two files with the same name in a classical filesystem.
* However, you may have "/Names/Client/eth0" and "/Names/Server/eth0" defined at
* the same time just as you might have different files of the same name under
* different directories.
*
* \param context A smart pointer to an object that is used in place of the path
* under which you want this new name to be defined.
* \param name The name of the object you want to associate.
* \param object A smart pointer to the object itself.
*/
static void Add (Ptr<Object> context, std::string name, Ptr<Object> object);
/**
* \brief Rename a previously associated name.
*
* The name may begin either with "/Names" to explicitly call out the fact
* that the name provided is installed under the root of the name space,
* or it may begin with the name of the first object in the path. For example,
* Names::Rename ("/Names/client", "server") and Names::Rename ("client", "server")
* accomplish exactly the same thing. Names at a given level in the name space
* path must be unique. In the case of the example above, it would be illegal
* to try and rename a different object to the same name: "server" at the same
* level ("/Names") in the path.
*
* As well as specifying a name at the root of the "/Names" namespace, the
* name parameter can contain a path that fully qualifies the name to
* be changed. For example, if you previously have (re)named an object
* "server" in the root namespace as above, you could then rename an object
* "under" that name by making a call like Names::Rename ("/Names/server/csma", "eth0").
* This will rename the object previously associated with "/Names/server/csma"
* to "eth0" and make leave it reachable using the path "/Names/server/eth0".
* Note that Names::Rename ("server/csma", "eth0") would accomplish exactly the
* same thing.
*
* \param oldpath The current path name to the object you want to change.
* \param newname The new name of the object you want to change.
*
* \see Names::Add (std::string name, Ptr<Object> obj)
*/
static void Rename (std::string oldpath, std::string newname);
/**
* \brief An intermediate form of Names::Rename allowing you to provide a path to
* the parent object (under which you want this name to be changed) in the form
* of a name path string.
*
* In some cases, it is desirable to break up the path used to describe an item
* in the names namespace into a path and a name. This is analogous to a
* file system operation in which you provide a directory name and a file name.
*
* For example, consider a situation where you have previously named an object
* "/Names/server/csma". If you want to change the name "csma" to "eth0", you
* could do this in two ways, depending on which was more convenient:
* Names::Rename ("/Names/server/csma", "eth0") or, using the split
* path and name approach, Names::Rename ("/Names/server", "csma", "eth0").
*
* \param path A path name describing a previously named object under which
* you want this name change to occur (cf. directory).
* \param oldname The currently defined name of the object.
* \param newname The new name you want the object to have.
*/
static void Rename (std::string path, std::string oldname, std::string newname);
/**
* \brief A low-level form of Names::Rename allowing you to specify the path to
* the parent object (under which you want this name to be changed) in the form
* of a previously named object.
*
* In some use cases, it is desirable to break up the path in the names name
* space into a path and a name. This is analogous to a file system operation
* in which you provide a directory name and a file name. Recall that the path
* string actually refers to a previously named object, "under" which you want
* to accomplish some naming action.
*
* However, the path is sometimes not available, and you only have the object
* that is represented by the path in the names name space. To support this
* use-case in a reasonably high-performance way, the path string is can be
* replaced by the object pointer to which that path would refer. In the spirit
* of the Config code where this use-case is most prominent, we refer to this
* object as the "context" for the names operation.
*
* You can think of the context roughly as the inode number of a directory file
* in Unix. The inode number can be used to look up the directory file which
* contains the list of file names defined at that directory level. Similarly
* the context is used to look up an internal name service entry which contains
* the names defined for that context.
*
* For example, consider a situation where you have previously named an object
* "/Names/server/csma". If you later decide to rename the csma object to say
* "eth0" -- you could do this by providing a complete path as in
* Names::Rename ("/Names/server/csma", "eth0"). If, however, somewhere
* in your code you only had a pointer to the server, and not a handy path
* string, say Ptr<Node> node, you could also accomplish this by
* Names::Rename (node, "csma", "eth0").
*
* \param context A smart pointer to an object that is used in place of the path
* under which you want this new name to be defined.
* \param oldname The current shortname of the object you want to change.
* \param newname The new shortname of the object you want to change.
*/
static void Rename (Ptr<Object> context, std::string oldname, std::string newname);
/**
* \brief Given a pointer to an object, look to see if that object has a name
* associated with it and, if so, return the name of the object otherwise
* return an empty string.
*
* An object can be referred to in two ways. Either you can talk about it
* using its fully qualified path name, for example, "/Names/client/eth0"
* or you can refer to it by its name, in this case "eth0".
*
* This method returns the name of the object, e.g., "eth0".
*
* \param object A smart pointer to an object for which you want to find
* its name.
*
* \returns a string containing the name of the object if found, otherwise
* the empty string.
*/
static std::string FindName (Ptr<Object> object);
/**
* \brief Given a pointer to an object, look to see if that object has a name
* associated with it and return the fully qualified name path of the
* object otherwise return an empty string.
*
* An object can be referred to in two ways. Either you can talk about it
* using its fully qualified path name, for example, "/Names/client/eth0"
* or you can refer to it by its name, in this case "eth0".
*
* This method returns the name path of the object, e.g., "Names/client/eth0".
*
* \param object A smart pointer to an object for which you want to find
* its fullname.
*
* \returns a string containing the name path of the object, otherwise
* the empty string.
*/
static std::string FindPath (Ptr<Object> object);
/**
* \brief Clear the list of objects associated with names.
*/
static void Clear (void);
/**
* \brief Given a name path string, look to see if there's an object in the system
* with that associated to it. If there is, do a GetObject on the resulting
* object to convert it to the requested typename and return it.
*
* An object can be referred to in two ways. Either you can talk about it
* using its fully qualified path name, for example, "/Names/client/eth0"
* or you can refer to it by its name, in this case "eth0".
*
* This method requires that the name path of the object be provided, e.g.,
* "Names/client/eth0".
*
* \param path A string containing a name space path used to locate the object.
*
* \returns a smart pointer to the named object converted to the requested
* type.
*/
template <typename T>
static Ptr<T> Find (std::string path);
/**
* \brief Given a path to an object and an object name, look through the names defined
* under the path to see if there's an object there with the given name.
*
* In some cases, it is desirable to break up the path used to describe an item
* in the names namespace into a path and a name. This is analogous to a
* file system operation in which you provide a directory name and a file name.
*
* For example, consider a situation where you have previously named an object
* "/Names/server/eth0". If you want to discover the object which you associated
* with this path, you could do this in two ways, depending on which was more
* convenient: Names::Find ("/Names/server/eth0") or, using the split path and
* name approach, Names::Find ("/Names/server", "eth0").
*
* \param path A path name describing a previously named object under which
* you want to look for the specified name.
* \param name A string containing a name to search for.
*
* \returns a smart pointer to the named object converted to the requested
* type.
*/
template <typename T>
static Ptr<T> Find (std::string path, std::string name);
/**
* \brief Given a path to an object and an object name, look through the names defined
* under the path to see if there's an object there with the given name.
*
* In some cases, it is desirable to break up the path used to describe an item
* in the names namespace into a path and a name. This is analogous to a
* file system operation in which you provide a directory name and a file name.
*
* For example, consider a situation where you have previously named an object
* "/Names/server/eth0". If you want to discover the object which you associated
* with this path, you could do this in two ways, depending on which was more
* convenient: Names::Find ("/Names/server/eth0") or, using the split path and
* name approach, Names::Find ("/Names/server", "eth0").
*
* However, the path is sometimes not available, and you only have the object
* that is represented by the path in the names name space. To support this
* use-case in a reasonably high-performance way, the path string is can be
* replaced by the object pointer to which that path would refer. In the spirit
* of the Config code where this use-case is most prominent, we refer to this
* object as the "context" for the names operation.
*
* You can think of the context roughly as the inode number of a directory file
* in Unix. The inode number can be used to look up the directory file which
* contains the list of file names defined at that directory level. Similarly
* the context is used to look up an internal name service entry which contains
* the names defined for that context.
*
* \param context A smart pointer to an object that is used in place of the path
* under which you want this new name to be defined.
* \param name A string containing a name to search for.
*
* \returns a smart pointer to the named object converted to the requested
* type.
*/
template <typename T>
static Ptr<T> Find (Ptr<Object> context, std::string name);
private:
/**
* \brief Non-templated internal version of Names::Find
*
* \param path A string containing the path of the object to look for.
*
* \returns a smart pointer to the named object.
*/
static Ptr<Object> FindInternal (std::string path);
/**
* \brief Non-templated internal version of Names::Find
*
* \param path A string containing the path to search for the object in.
* \param name A string containing the name of the object to look for.
*
* \returns a smart pointer to the named object.
*/
static Ptr<Object> FindInternal (std::string path, std::string name);
/**
* \brief Non-templated internal version of Names::Find
*
* \param context A smart pointer to an object under which you want to look
* for the provided name.
* \param name A string containing the name to look for.
*
* \returns a smart pointer to the named object.
*/
static Ptr<Object> FindInternal (Ptr<Object> context, std::string name);
};
template <typename T>
/* static */
Ptr<T>
Names::Find (std::string path)
{
Ptr<Object> obj = FindInternal (path);
if (obj)
{
return obj->GetObject<T> ();
}
else
{
return 0;
}
}
template <typename T>
/* static */
Ptr<T>
Names::Find (std::string path, std::string name)
{
Ptr<Object> obj = FindInternal (path, name);
if (obj)
{
return obj->GetObject<T> ();
}
else
{
return 0;
}
}
template <typename T>
/* static */
Ptr<T>
Names::Find (Ptr<Object> context, std::string name)
{
Ptr<Object> obj = FindInternal (context, name);
if (obj)
{
return obj->GetObject<T> ();
}
else
{
return 0;
}
}
} // namespace ns3
#endif /* OBJECT_NAMES_H */