1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  *  This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  *
16  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
17  */
18 
19 #include "attribute-iterator.h"
20 #include "ns3/config.h"
21 #include "ns3/log.h"
22 #include "ns3/pointer.h"
23 #include "ns3/object-ptr-container.h"
24 #include "ns3/string.h"
25 #include <fstream>
26 
27 
28 namespace ns3 {
29 
30 NS_LOG_COMPONENT_DEFINE ("AttributeIterator");
31 
AttributeIterator()32 AttributeIterator::AttributeIterator ()
33 {
34 }
35 
~AttributeIterator()36 AttributeIterator::~AttributeIterator ()
37 {
38 }
39 
40 void
Iterate(void)41 AttributeIterator::Iterate (void)
42 {
43   for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i)
44     {
45       Ptr<Object> object = Config::GetRootNamespaceObject (i);
46       StartVisitObject (object);
47       DoIterate (object);
48       EndVisitObject ();
49     }
50   NS_ASSERT (m_currentPath.empty ());
51   NS_ASSERT (m_examined.empty ());
52 }
53 
54 bool
IsExamined(Ptr<const Object> object)55 AttributeIterator::IsExamined (Ptr<const Object> object)
56 {
57   for (uint32_t i = 0; i < m_examined.size (); ++i)
58     {
59       if (object == m_examined[i])
60         {
61           return true;
62         }
63     }
64   return false;
65 }
66 
67 
68 std::string
GetCurrentPath(std::string attr) const69 AttributeIterator::GetCurrentPath (std::string attr) const
70 {
71   std::ostringstream oss;
72   for (uint32_t i = 0; i < m_currentPath.size (); ++i)
73     {
74       oss << "/" << m_currentPath[i];
75     }
76   if (attr != "")
77     {
78       oss << "/" << attr;
79     }
80   return oss.str ();
81 }
82 
83 std::string
GetCurrentPath(void) const84 AttributeIterator::GetCurrentPath (void) const
85 {
86   std::ostringstream oss;
87   for (uint32_t i = 0; i < m_currentPath.size (); ++i)
88     {
89       oss << "/" << m_currentPath[i];
90     }
91   return oss.str ();
92 }
93 
94 void
DoStartVisitObject(Ptr<Object> object)95 AttributeIterator::DoStartVisitObject (Ptr<Object> object)
96 {
97 }
98 void
DoEndVisitObject(void)99 AttributeIterator::DoEndVisitObject (void)
100 {
101 }
102 void
DoStartVisitPointerAttribute(Ptr<Object> object,std::string name,Ptr<Object> item)103 AttributeIterator::DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> item)
104 {
105 }
106 void
DoEndVisitPointerAttribute(void)107 AttributeIterator::DoEndVisitPointerAttribute (void)
108 {
109 }
110 void
DoStartVisitArrayAttribute(Ptr<Object> object,std::string name,const ObjectPtrContainerValue & vector)111 AttributeIterator::DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectPtrContainerValue &vector)
112 {
113 }
114 void
DoEndVisitArrayAttribute(void)115 AttributeIterator::DoEndVisitArrayAttribute (void)
116 {
117 }
118 void
DoStartVisitArrayItem(const ObjectPtrContainerValue & vector,uint32_t index,Ptr<Object> item)119 AttributeIterator::DoStartVisitArrayItem (const ObjectPtrContainerValue &vector, uint32_t index, Ptr<Object> item)
120 {
121 }
122 void
DoEndVisitArrayItem(void)123 AttributeIterator::DoEndVisitArrayItem (void)
124 {
125 }
126 
127 void
VisitAttribute(Ptr<Object> object,std::string name)128 AttributeIterator::VisitAttribute (Ptr<Object> object, std::string name)
129 {
130   m_currentPath.push_back (name);
131   DoVisitAttribute (object, name);
132   m_currentPath.pop_back ();
133 }
134 
135 void
StartVisitObject(Ptr<Object> object)136 AttributeIterator::StartVisitObject (Ptr<Object> object)
137 {
138   m_currentPath.push_back ("$" + object->GetInstanceTypeId ().GetName ());
139   DoStartVisitObject (object);
140 }
141 void
EndVisitObject(void)142 AttributeIterator::EndVisitObject (void)
143 {
144   m_currentPath.pop_back ();
145   DoEndVisitObject ();
146 }
147 void
StartVisitPointerAttribute(Ptr<Object> object,std::string name,Ptr<Object> value)148 AttributeIterator::StartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value)
149 {
150   m_currentPath.push_back (name);
151   m_currentPath.push_back ("$" + value->GetInstanceTypeId ().GetName ());
152   DoStartVisitPointerAttribute (object, name, value);
153 }
154 void
EndVisitPointerAttribute(void)155 AttributeIterator::EndVisitPointerAttribute (void)
156 {
157   m_currentPath.pop_back ();
158   m_currentPath.pop_back ();
159   DoEndVisitPointerAttribute ();
160 }
161 void
StartVisitArrayAttribute(Ptr<Object> object,std::string name,const ObjectPtrContainerValue & vector)162 AttributeIterator::StartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectPtrContainerValue &vector)
163 {
164   m_currentPath.push_back (name);
165   DoStartVisitArrayAttribute (object, name, vector);
166 }
167 void
EndVisitArrayAttribute(void)168 AttributeIterator::EndVisitArrayAttribute (void)
169 {
170   m_currentPath.pop_back ();
171   DoEndVisitArrayAttribute ();
172 }
173 
174 void
StartVisitArrayItem(const ObjectPtrContainerValue & vector,uint32_t index,Ptr<Object> item)175 AttributeIterator::StartVisitArrayItem (const ObjectPtrContainerValue &vector, uint32_t index, Ptr<Object> item)
176 {
177   std::ostringstream oss;
178   oss << index;
179   m_currentPath.push_back (oss.str ());
180   m_currentPath.push_back ("$" + item->GetInstanceTypeId ().GetName ());
181   DoStartVisitArrayItem (vector, index, item);
182 }
183 void
EndVisitArrayItem(void)184 AttributeIterator::EndVisitArrayItem (void)
185 {
186   m_currentPath.pop_back ();
187   m_currentPath.pop_back ();
188   DoEndVisitArrayItem ();
189 }
190 
191 
192 void
DoIterate(Ptr<Object> object)193 AttributeIterator::DoIterate (Ptr<Object> object)
194 {
195   if (IsExamined (object))
196     {
197       return;
198     }
199   TypeId tid;
200   for (tid = object->GetInstanceTypeId (); tid.HasParent (); tid = tid.GetParent ())
201     {
202       NS_LOG_DEBUG ("store " << tid.GetName ());
203       for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
204         {
205           struct TypeId::AttributeInformation info = tid.GetAttribute(i);
206           const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
207           if (ptrChecker != 0)
208             {
209               NS_LOG_DEBUG ("pointer attribute " << info.name);
210               PointerValue ptr;
211               object->GetAttribute (info.name, ptr);
212               Ptr<Object> tmp = ptr.Get<Object> ();
213               if (tmp != 0)
214                 {
215                   StartVisitPointerAttribute (object, info.name,
216                                               tmp);
217                   m_examined.push_back (object);
218                   DoIterate (tmp);
219                   m_examined.pop_back ();
220                   EndVisitPointerAttribute ();
221                 }
222               continue;
223             }
224           // attempt to cast to an object container
225           const ObjectPtrContainerChecker *vectorChecker = dynamic_cast<const ObjectPtrContainerChecker *> (PeekPointer (info.checker));
226           if (vectorChecker != 0)
227             {
228               NS_LOG_DEBUG ("ObjectPtrContainer attribute " << info.name);
229               ObjectPtrContainerValue vector;
230               object->GetAttribute (info.name, vector);
231               StartVisitArrayAttribute (object, info.name, vector);
232               ObjectPtrContainerValue::Iterator it;
233               for (it = vector.Begin (); it != vector.End (); ++it)
234                 {
235                   uint32_t j = (*it).first;
236                   NS_LOG_DEBUG ("ObjectPtrContainer attribute item " << j);
237                   Ptr<Object> tmp = (*it).second;
238                   if (tmp)
239                     {
240                       StartVisitArrayItem (vector, j, tmp);
241                       m_examined.push_back (object);
242                       DoIterate (tmp);
243                       m_examined.pop_back ();
244                       EndVisitArrayItem ();
245                     }
246                 }
247               EndVisitArrayAttribute ();
248               continue;
249             }
250           if ((info.flags & TypeId::ATTR_GET) && info.accessor->HasGetter () &&
251               (info.flags & TypeId::ATTR_SET) && info.accessor->HasSetter ())
252             {
253               VisitAttribute (object, info.name);
254             }
255           else
256             {
257               NS_LOG_DEBUG ("could not store " << info.name);
258             }
259         }
260     }
261   Object::AggregateIterator iter = object->GetAggregateIterator ();
262   bool recursiveAggregate = false;
263   while (iter.HasNext ())
264     {
265       Ptr<const Object> tmp = iter.Next ();
266       if (IsExamined (tmp))
267         {
268           recursiveAggregate = true;
269         }
270     }
271   if (!recursiveAggregate)
272     {
273       iter = object->GetAggregateIterator ();
274       while (iter.HasNext ())
275         {
276           Ptr<Object> tmp = const_cast<Object *> (PeekPointer (iter.Next ()));
277           StartVisitObject (tmp);
278           m_examined.push_back (object);
279           DoIterate (tmp);
280           m_examined.pop_back ();
281           EndVisitObject ();
282         }
283     }
284 }
285 
286 
287 } // namespace ns3
288