1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 #ifndef OBJECT_NAMES_H
20 #define OBJECT_NAMES_H
21 
22 #include "ptr.h"
23 #include "object.h"
24 
25 /**
26  * \file
27  * \ingroup config
28  * Declaration of class ns3::Names.
29  */
30 
31 namespace ns3 {
32 
33 /**
34  * \ingroup config
35  * \brief A directory of name and Ptr<Object> associations that allows
36  * us to give any ns3 Object a name.
37  */
38 class Names
39 {
40 public:
41 
42   /**
43    * \brief Add the association between the string "name" and the
44    * Ptr<Object> obj.
45    *
46    * The name may begin either with "/Names" to explicitly call out
47    * the fact that the name provided is installed under the root of
48    * the name space, or it may begin with the name of the first object
49    * in the path.  For example, Names::Add ("/Names/client", obj) and
50    * Names::Add ("client", obj) accomplish exactly the same thing.  A
51    * name at a given level in the name space path must be unique.  In
52    * the case of the example above, it would be illegal to try and
53    * associate a different object with the same name: "client" at the
54    * same level ("/Names") in the path.
55    *
56    * As well as specifying a name at the root of the "/Names"
57    * namespace, the name parameter can contain a path that fully
58    * qualifies the name to be added.  For example, if you previously
59    * have named an object "client" in the root namespace as above, you
60    * could name an object "under" that name by making a call like
61    * Names::Add ("/Names/client/eth0", obj).  This will define the
62    * name "eth0" and make it reachable using the path specified.  Note
63    * that Names::Add ("client/eth0", obj) would accomplish exactly the
64    * same thing.
65    *
66    * Duplicate names are not allowed at the same level in a path,
67    * however you may associate similar names with different paths.
68    * For example, if you define "/Names/Client", you may not define
69    * another "/Names/Client" just as you may not have two files with
70    * the same name in a classical filesystem.  However, you may have
71    * "/Names/Client/eth0" and "/Names/Server/eth0" defined at the same
72    * time just as you might have different files of the same name
73    * under different directories.
74    *
75    * \param [in] name The name of the object you want to associate; which may be
76    *             prepended with a path to that object.
77    * \param [in] object A smart pointer to the object itself.
78    */
79   static void Add (std::string name, Ptr<Object> object);
80 
81   /**
82    * \brief An intermediate form of Names::Add allowing you to provide
83    * a path to the parent object (under which you want this name to be
84    * defined) in the form of a name path string.
85    *
86    * In some cases, it is desirable to break up the path used to
87    * describe an item in the names namespace into a path and a name.
88    * This is analogous to a file system operation in which you provide
89    * a directory name and a file name.
90    *
91    * For example, consider a situation where you have previously named
92    * an object "/Names/server".  If you further want to create an
93    * association for between a Ptr<Object> object that you want to
94    * live "under" the server in the name space -- perhaps "eth0" --
95    * you could do this in two ways, depending on which was more
96    * convenient: Names::Add ("/Names/server/eth0", object) or, using
97    * the split path and name approach, Names::Add ("/Names/server",
98    * "eth0", object).
99    *
100    * Duplicate names are not allowed at the same level in a path,
101    * however you may associate similar names with different paths.
102    * For example, if you define "/Names/Client", you may not define
103    * another "/Names/Client" just as you may not have two files with
104    * the same name in a classical filesystem.  However, you may have
105    * "/Names/Client/eth0" and "/Names/Server/eth0" defined at the same
106    * time just as you might have different files of the same name
107    * under different directories.
108    *
109    * \param [in] path A path name describing a previously named object
110    *             under which you want this new name to be defined.
111    * \param [in] name The name of the object you want to associate.
112    * \param [in] object A smart pointer to the object itself.
113    *
114    * \see Names::Add (Ptr<Object>,std::string,Ptr<Object>);
115    */
116   static void Add (std::string path, std::string name, Ptr<Object> object);
117 
118   /**
119    * \brief A low-level form of Names::Add allowing you to specify the
120    * path to the parent object (under which you want this name to be
121    * defined) in the form of a previously named object.
122    *
123    * In some use cases, it is desirable to break up the path in the
124    * names name space into a path and a name.  This is analogous to a
125    * file system operation in which you provide a directory name and a
126    * file name.  Recall that the path string actually refers to a
127    * previously named object, "under" which you want to accomplish
128    * some naming action.
129    *
130    * However, the path is sometimes not available, and you only have
131    * the object that is represented by the path in the names name
132    * space.  To support this use-case in a reasonably high-performance
133    * way, the path string is can be replaced by the object pointer to
134    * which that path would refer.  In the spirit of the Config code
135    * where this use-case is most prominent, we refer to this object as
136    * the "context" for the names operation.
137    *
138    * You can think of the context roughly as the inode number of a
139    * directory file in Unix.  The inode number can be used to look up
140    * the directory file which contains the list of file names defined
141    * at that directory level.  Similarly the context is used to look
142    * up an internal name service entry which contains the names
143    * defined for that context.
144    *
145    * For example, consider a situation where you have previously named
146    * an object "/Names/server".  If you further want to create an
147    * association for between a Ptr<Object> object that you want to
148    * live "under" the server in the name space -- perhaps "eth0" --
149    * you could do this by providing a complete path to the new name:
150    * Names::Add ("/Names/server/eth0", object).  If, however,
151    * somewhere in your code you only had a pointer to the server, say
152    * Ptr<Node> node, and not a handy path string, you could also
153    * accomplish this by Names::Add (node, "eth0", object).
154    *
155    * Duplicate names are not allowed at the same level in a path.  In
156    * the case of this method, the context object gives the same
157    * information as a path string.  You may associate similar names
158    * with different paths.  For example, if you define"/Names/Client",
159    * you may not define another "/Names/Client" just as you may not
160    * have two files with the same name in a classical filesystem.
161    * However, you may have "/Names/Client/eth0" and
162    * "/Names/Server/eth0" defined at the same time just as you might
163    * have different files of the same name under different
164    * directories.
165    *
166    * \param [in] context A smart pointer to an object that is used
167    *             in place of the path under which you want this new
168    *             name to be defined.
169    * \param [in] name The name of the object you want to associate.
170    * \param [in] object A smart pointer to the object itself.
171    */
172   static void Add (Ptr<Object> context, std::string name, Ptr<Object> object);
173 
174   /**
175    * \brief Rename a previously associated name.
176    *
177    * The name may begin either with "/Names" to explicitly call out
178    * the fact that the name provided is installed under the root of
179    * the name space, or it may begin with the name of the first object
180    * in the path.  For example, Names::Rename ("/Names/client",
181    * "server") and Names::Rename ("client", "server") accomplish
182    * exactly the same thing.  Names at a given level in the name space
183    * path must be unique. In the case of the example above, it would
184    * be illegal to try and rename a different object to the same name:
185    * "server" at the same level ("/Names") in the path.
186    *
187    * As well as specifying a name at the root of the "/Names"
188    * namespace, the name parameter can contain a path that fully
189    * qualifies the name to be changed.  For example, if you previously
190    * have (re)named an object "server" in the root namespace as above,
191    * you could then rename an object "under" that name by making a
192    * call like Names::Rename ("/Names/server/csma", "eth0").  This
193    * will rename the object previously associated with
194    * "/Names/server/csma" to "eth0" and make leave it reachable using
195    * the path "/Names/server/eth0".  Note that Names::Rename
196    * ("server/csma", "eth0") would accomplish exactly the same thing.
197    *
198    * \param [in] oldpath The current path name to the object you want
199    *             to change.
200    * \param [in] newname The new name of the object you want to change.
201    *
202    * \see Names::Add (std::string name, Ptr<Object> obj)
203    */
204   static void Rename (std::string oldpath, std::string newname);
205 
206   /**
207    * \brief An intermediate form of Names::Rename allowing you to
208    * provide a path to the parent object (under which you want this
209    * name to be changed) in the form of a name path string.
210    *
211    * In some cases, it is desirable to break up the path used to
212    * describe an item in the names namespace into a path and a name.
213    * This is analogous to a file system operation in which you provide
214    * a directory name and a file name.
215    *
216    * For example, consider a situation where you have previously named
217    * an object "/Names/server/csma".  If you want to change the name
218    * "csma" to "eth0", you could do this in two ways, depending on
219    * which was more convenient: Names::Rename ("/Names/server/csma",
220    * "eth0") or, using the split path and name approach, Names::Rename
221    * ("/Names/server", "csma", "eth0").
222    *
223    * \param [in] path A path name describing a previously named object
224    *             under which you want this name change to occur
225    *             (cf. directory).
226    * \param [in] oldname The currently defined name of the object.
227    * \param [in] newname The new name you want the object to have.
228    */
229   static void Rename (std::string path, std::string oldname, std::string newname);
230 
231   /**
232    * \brief A low-level form of Names::Rename allowing you to specify
233    * the path to the parent object (under which you want this name to
234    * be changed) in the form of a previously named object.
235    *
236    * In some use cases, it is desirable to break up the path in the
237    * names name space into a path and a name.  This is analogous to a
238    * file system operation in which you provide a directory name and a
239    * file name.  Recall that the path string actually refers to a
240    * previously named object, "under" which you want to accomplish
241    * some naming action.
242    *
243    * However, the path is sometimes not available, and you only have
244    * the object that is represented by the path in the names name
245    * space.  To support this use-case in a reasonably high-performance
246    * way, the path string is can be replaced by the object pointer to
247    * which that path would refer.  In the spirit of the Config code
248    * where this use-case is most prominent, we refer to this object as
249    * the "context" for the names operation.
250    *
251    * You can think of the context roughly as the inode number of a
252    * directory file in Unix.  The inode number can be used to look up
253    * the directory file which contains the list of file names defined
254    * at that directory level.  Similarly the context is used to look
255    * up an internal name service entry which contains the names
256    * defined for that context.
257    *
258    * For example, consider a situation where you have previously named
259    * an object "/Names/server/csma".  If you later decide to rename
260    * the csma object to say "eth0" -- you could do this by providing a
261    * complete path as in Names::Rename ("/Names/server/csma", "eth0").
262    * If, however, somewhere in your code you only had a pointer to the
263    * server, and not a handy path string, say Ptr<Node> node, you
264    * could also accomplish this by Names::Rename (node, "csma",
265    * "eth0").
266    *
267    * \param [in] context A smart pointer to an object that is used
268    *             in place of the path under which you want this
269    *             new name to be defined.
270    * \param [in] oldname The current shortname of the object you want
271    *             to change.
272    * \param [in] newname The new shortname of the object you want
273    *             to change.
274    */
275   static void Rename (Ptr<Object> context, std::string oldname, std::string newname);
276 
277   /**
278    * \brief Given a pointer to an object, look to see if that object
279    * has a name associated with it and, if so, return the name of the
280    * object otherwise return an empty string.
281    *
282    * An object can be referred to in two ways.  Either you can talk
283    * about it using its fully qualified path name, for example,
284    * "/Names/client/eth0" or you can refer to it by its name, in this
285    * case "eth0".
286    *
287    * This method returns the name of the object, e.g., "eth0".
288    *
289    * \param [in] object A smart pointer to an object for which you want
290    *             to find its name.
291    *
292    * \returns A string containing the name of the object if found,
293    *          otherwise the empty string.
294    */
295   static std::string FindName (Ptr<Object> object);
296 
297   /**
298    * \brief Given a pointer to an object, look to see if that object
299    * has a name associated with it and return the fully qualified name
300    * path of the object otherwise return an empty string.
301    *
302    * An object can be referred to in two ways.  Either you can talk
303    * about it using its fully qualified path name, for example,
304    * "/Names/client/eth0" or you can refer to it by its name, in this
305    * case "eth0".
306    *
307    * This method returns the name path of the object, e.g.,
308    * "Names/client/eth0".
309    *
310    * \param [in] object A smart pointer to an object for which you
311    *             want to find its fullname.
312    *
313    * \returns A string containing the name path of the object,
314    *          otherwise the empty string.
315    */
316   static std::string FindPath (Ptr<Object> object);
317 
318   /**
319    * \brief Clear the list of objects associated with names.
320    */
321 
322   static void Clear (void);
323 
324   /**
325    * \brief Given a name path string, look to see if there's an object
326    * in the system with that associated to it.  If there is, do a
327    * GetObject on the resulting object to convert it to the requested
328    * typename and return it.
329    *
330    * An object can be referred to in two ways.  Either you can talk
331    * about it using its fully qualified path name, for example,
332    * "/Names/client/eth0" or you can refer to it by its name, in this
333    * case "eth0".
334    *
335    * This method requires that the name path of the object be
336    * provided, e.g., "Names/client/eth0".
337    *
338    * \param [in] path A string containing a name space path used
339    *             to locate the object.
340    *
341    * \returns A smart pointer to the named object converted to
342    *          the requested type.
343    */
344   template <typename T>
345   static Ptr<T> Find (std::string path);
346 
347   /**
348    * \brief Given a path to an object and an object name, look through
349    * the names defined under the path to see if there's an object
350    * there with the given name.
351    *
352    * In some cases, it is desirable to break up the path used to
353    * describe an item in the names namespace into a path and a name.
354    * This is analogous to a file system operation in which you provide
355    * a directory name and a file name.
356    *
357    * For example, consider a situation where you have previously named
358    * an object "/Names/server/eth0".  If you want to discover the
359    * object which you associated with this path, you could do this in
360    * two ways, depending on which was more convenient: Names::Find
361    * ("/Names/server/eth0") or, using the split path and name
362    * approach, Names::Find ("/Names/server", "eth0").
363    *
364    * \param [in] path A path name describing a previously named object
365    *             under which you want to look for the specified name.
366    * \param [in] name A string containing a name to search for.
367    *
368    * \returns A smart pointer to the named object converted to
369    *          the requested type.
370    */
371   template <typename T>
372   static Ptr<T> Find (std::string path, std::string name);
373 
374   /**
375    * \brief Given a path to an object and an object name, look through
376    * the names defined under the path to see if there's an object
377    * there with the given name.
378    *
379    * In some cases, it is desirable to break up the path used to
380    * describe an item in the names namespace into a path and a name.
381    * This is analogous to a file system operation in which you provide
382    * a directory name and a file name.
383    *
384    * For example, consider a situation where you have previously named
385    * an object "/Names/server/eth0".  If you want to discover the
386    * object which you associated with this path, you could do this in
387    * two ways, depending on which was more convenient: Names::Find
388    * ("/Names/server/eth0") or, using the split path and name
389    * approach, Names::Find ("/Names/server", "eth0").
390    *
391    * However, the path is sometimes not available, and you only have
392    * the object that is represented by the path in the names name
393    * space.  To support this use-case in a reasonably high-performance
394    * way, the path string is can be replaced by the object pointer to
395    * which that path would refer.  In the spirit of the Config code
396    * where this use-case is most prominent, we refer to this object as
397    * the "context" for the names operation.
398    *
399    * You can think of the context roughly as the inode number of a
400    * directory file in Unix.  The inode number can be used to look up
401    * the directory file which contains the list of file names defined
402    * at that directory level.  Similarly the context is used to look
403    * up an internal name service entry which contains the names
404    * defined for that context.
405    *
406    * \param [in] context A smart pointer to an object that is used
407    *             in place of the path under which you want this
408    *             new name to be defined.
409    * \param [in] name A string containing a name to search for.
410    *
411    * \returns A smart pointer to the named object converted to
412    *          the requested type.
413    */
414   template <typename T>
415   static Ptr<T> Find (Ptr<Object> context, std::string name);
416 
417 private:
418   /**
419    * \brief Non-templated internal version of Names::Find
420    *
421    * \param [in] path A string containing the path of the object
422    *             to look for.
423    *
424    * \returns A smart pointer to the named object.
425    */
426   static Ptr<Object> FindInternal (std::string path);
427 
428   /**
429    * \brief Non-templated internal version of Names::Find
430    *
431    * \param [in] path A string containing the path to search
432    *             for the object in.
433    * \param [in] name A string containing the name of the object
434    *             to look for.
435    *
436    * \returns A smart pointer to the named object.
437    */
438   static Ptr<Object> FindInternal (std::string path, std::string name);
439 
440   /**
441    * \brief Non-templated internal version of Names::Find
442    *
443    * \param [in] context A smart pointer to an object under which
444    *             you want to look for the provided name.
445    * \param [in] name A string containing the name to look for.
446    *
447    * \returns A smart pointer to the named object.
448    */
449   static Ptr<Object> FindInternal (Ptr<Object> context, std::string name);
450 };
451 
452 
453 template <typename T>
454 /* static */
455 Ptr<T>
Find(std::string path)456 Names::Find (std::string path)
457 {
458   Ptr<Object> obj = FindInternal (path);
459   if (obj)
460     {
461       return obj->GetObject<T> ();
462     }
463   else
464     {
465       return 0;
466     }
467 }
468 
469 template <typename T>
470 /* static */
471 Ptr<T>
Find(std::string path,std::string name)472 Names::Find (std::string path, std::string name)
473 {
474   Ptr<Object> obj = FindInternal (path, name);
475   if (obj)
476     {
477       return obj->GetObject<T> ();
478     }
479   else
480     {
481       return 0;
482     }
483 }
484 
485 template <typename T>
486 /* static */
487 Ptr<T>
Find(Ptr<Object> context,std::string name)488 Names::Find (Ptr<Object> context, std::string name)
489 {
490   Ptr<Object> obj = FindInternal (context, name);
491   if (obj)
492     {
493       return obj->GetObject<T> ();
494     }
495   else
496     {
497       return 0;
498     }
499 }
500 
501 } // namespace ns3
502 
503 #endif /* OBJECT_NAMES_H */
504