A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
print-introspected-doxygen.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <algorithm>
3 #include <map>
4 #include "ns3/object.h"
5 #include "ns3/pointer.h"
6 #include "ns3/object-vector.h"
7 #include "ns3/config.h"
8 #include "ns3/log.h"
9 #include "ns3/global-value.h"
10 #include "ns3/string.h"
11 #include "ns3/node-container.h"
12 
13 using namespace ns3;
14 
15 NS_LOG_COMPONENT_DEFINE ("PrintIntrospectedDoxygen");
16 
17 namespace
18 {
19  std::string anchor;
20  std::string boldStart;
21  std::string boldStop;
22  std::string breakBoth;
23  std::string breakHtmlOnly;
24  std::string breakTextOnly;
25  std::string brief;
26  std::string commentStart;
27  std::string commentStop;
34  std::string functionStart;
35  std::string functionStop;
36  std::string indentHtmlOnly;
37  std::string ingroupConstructs;
38  std::string listStart;
39  std::string listStop;
40  std::string listLineStart;
41  std::string listLineStop;
42  std::string reference;
43  std::string temporaryCharacter;
44 
45 } // anonymous namespace
46 
47 void
48 PrintAttributes (TypeId tid, std::ostream &os)
49 {
50  os << listStart << std::endl;
51  for (uint32_t j = 0; j < tid.GetAttributeN (); j++)
52  {
53  struct TypeId::AttributeInformation info = tid.GetAttribute(j);
54  os << listLineStart << boldStart << info.name << boldStop << ": "
55  << info.help << std::endl;
56  os << " " << listStart << std::endl
57  << " " << listLineStart << "Set with class: " << reference << info.checker->GetValueTypeName () << listLineStop << std::endl;
59  {
60  os << " " << listLineStart << "Underlying type: " << reference << info.checker->GetUnderlyingTypeInformation () << listLineStop << std::endl;
61  }
62  if (info.flags & TypeId::ATTR_CONSTRUCT && info.accessor->HasSetter ())
63  {
64  os << " " << listLineStart << "Initial value: " << info.initialValue->SerializeToString (info.checker) << listLineStop << std::endl;
65  }
66  os << " " << listLineStart << "Flags: ";
67  if (info.flags & TypeId::ATTR_CONSTRUCT && info.accessor->HasSetter ())
68  {
69  os << "construct ";
70  }
71  if (info.flags & TypeId::ATTR_SET && info.accessor->HasSetter ())
72  {
73  os << "write ";
74  }
75  if (info.flags & TypeId::ATTR_GET && info.accessor->HasGetter ())
76  {
77  os << "read ";
78  }
79  os << listLineStop << std::endl;
80  os << " " << listStop << " " << std::endl;
81 
82  }
83  os << listStop << std::endl;
84 }
85 
86 void
87 PrintTraceSources (TypeId tid, std::ostream &os)
88 {
89  os << listStart << std::endl;
90  for (uint32_t i = 0; i < tid.GetTraceSourceN (); ++i)
91  {
92  struct TypeId::TraceSourceInformation info = tid.GetTraceSource (i);
93  os << listLineStart << boldStart << info.name << boldStop << ": "
94  << info.help
95  << std::endl;
96  os << listLineStop << std::endl;
97  }
98  os << listStop << std::endl;
99 }
100 
101 
103 {
104 public:
105  void RecordAggregationInfo (std::string a, std::string b);
106  void Gather (TypeId tid);
107  void Print (void) const;
108 
109  std::vector<std::string> Get (TypeId tid);
110 
111 private:
112  std::string GetCurrentPath (void) const;
113  void DoGather (TypeId tid);
114  void RecordOutput (TypeId tid);
115  bool HasAlreadyBeenProcessed (TypeId tid) const;
116  void find_and_replace (std::string &source, const std::string find, std::string replace );
117  std::vector<std::pair<TypeId,std::string> > m_output;
118  std::vector<std::string> m_currentPath;
119  std::vector<TypeId> m_alreadyProcessed;
120  std::vector<std::pair<TypeId,TypeId> > m_aggregates;
121 };
122 
123 void
124 StaticInformation::RecordAggregationInfo (std::string a, std::string b)
125 {
126  m_aggregates.push_back (std::make_pair (TypeId::LookupByName (a), TypeId::LookupByName (b)));
127 }
128 
129 void
131 {
132  for (std::vector<std::pair<TypeId,std::string> >::const_iterator i = m_output.begin (); i != m_output.end (); ++i)
133  {
134  std::pair<TypeId,std::string> item = *i;
135  std::cout << item.first.GetName () << " -> " << item.second << std::endl;
136  }
137 }
138 
139 std::string
141 {
142  std::ostringstream oss;
143  for (std::vector<std::string>::const_iterator i = m_currentPath.begin (); i != m_currentPath.end (); ++i)
144  {
145  std::string item = *i;
146  oss << "/" << item;
147  }
148  return oss.str ();
149 }
150 
151 void
153 {
154  m_output.push_back (std::make_pair (tid, GetCurrentPath ()));
155 }
156 
157 bool
159 {
160  for (uint32_t i = 0; i < m_alreadyProcessed.size (); ++i)
161  {
162  if (m_alreadyProcessed[i] == tid)
163  {
164  return true;
165  }
166  }
167  return false;
168 }
169 
170 std::vector<std::string>
172 {
173  std::vector<std::string> paths;
174  for (uint32_t i = 0; i < m_output.size (); ++i)
175  {
176  std::pair<TypeId,std::string> tmp = m_output[i];
177  if (tmp.first == tid)
178  {
179  paths.push_back (tmp.second);
180  }
181  }
182  return paths;
183 }
184 
185 void
187 {
188  DoGather (tid);
189 
190  std::sort (m_output.begin (), m_output.end ());
191  m_output.erase (std::unique (m_output.begin (), m_output.end ()), m_output.end ());
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION (this);
198  if (HasAlreadyBeenProcessed (tid))
199  {
200  return;
201  }
202  RecordOutput (tid);
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  TypeId pointee = ptrChecker->GetPointeeTypeId ();
210 
211  // See if this is a pointer to an Object.
212  Ptr<Object> object = CreateObject<Object> ();
213  TypeId objectTypeId = object->GetTypeId ();
214  if (objectTypeId == pointee)
215  {
216  // Stop the recursion at this attribute if it is a
217  // pointer to an Object, which create too many spurious
218  // paths in the list of attribute paths because any
219  // Object can be in that part of the path.
220  continue;
221  }
222 
223  m_currentPath.push_back (info.name);
224  m_alreadyProcessed.push_back (tid);
225  DoGather (pointee);
226  m_alreadyProcessed.pop_back ();
227  m_currentPath.pop_back ();
228  continue;
229  }
230  // attempt to cast to an object vector.
231  const ObjectPtrContainerChecker *vectorChecker = dynamic_cast<const ObjectPtrContainerChecker *> (PeekPointer (info.checker));
232  if (vectorChecker != 0)
233  {
234  TypeId item = vectorChecker->GetItemTypeId ();
235  m_currentPath.push_back (info.name + "/[i]");
236  m_alreadyProcessed.push_back (tid);
237  DoGather (item);
238  m_alreadyProcessed.pop_back ();
239  m_currentPath.pop_back ();
240  continue;
241  }
242  }
243  for (uint32_t j = 0; j < TypeId::GetRegisteredN (); j++)
244  {
245  TypeId child = TypeId::GetRegistered (j);
246  if (child.IsChildOf (tid))
247  {
248  //please take a look at the following note for an explanation
249  std::string childName = "$" + temporaryCharacter + child.GetName ();
250  std::string replaceWith = "::" + temporaryCharacter;
251  find_and_replace(childName,"::",replaceWith);
252  m_currentPath.push_back (childName);
253  m_alreadyProcessed.push_back (tid);
254  DoGather (child);
255  m_alreadyProcessed.pop_back ();
256  m_currentPath.pop_back ();
257  }
258  }
259  for (uint32_t k = 0; k < m_aggregates.size (); ++k)
260  {
261  std::pair<TypeId,TypeId> tmp = m_aggregates[k];
262  if (tmp.first == tid || tmp.second == tid)
263  {
264  TypeId other;
265  if (tmp.first == tid)
266  {
267  other = tmp.second;
268  }
269  if (tmp.second == tid)
270  {
271  other = tmp.first;
272  }
284  std::string name = "$" + temporaryCharacter + other.GetName ();
285  //finding and replacing :: by ::% (for Doxygen version only).
286  std::string replaceWith = "::" + temporaryCharacter;
287  find_and_replace(name,"::",replaceWith);
288  m_currentPath.push_back (name);
289  m_alreadyProcessed.push_back (tid);
290  DoGather (other);
291  m_alreadyProcessed.pop_back ();
292  m_currentPath.pop_back ();
293  }
294  }
295 }
296 
297 void
298 StaticInformation::find_and_replace( std::string &source, const std::string find, std::string replace )
299 {
300  size_t j;
301  j = source.find (find);
302  while (j != std::string::npos )
303  {
304  source.replace (j, find.length (),replace);
305  j = source.find (find,j+1);
306  }
307 }
308 
309 void
310 PrintHelp (const char *program_name)
311 {
312  std::cout << "Usage: " << program_name << " [options]" << std::endl
313  << std::endl
314  << "Options:" << std::endl
315  << " --help : print these options" << std::endl
316  << " --output-text : format output as plain text" << std::endl;
317 }
318 
319 int main (int argc, char *argv[])
320 {
321  bool outputText = false;
322  char *programName = argv[0];
323 
324  argv++;
325 
326  while (*argv != 0)
327  {
328  char *arg = *argv;
329 
330  if (strcmp (arg, "--help") == 0)
331  {
332  PrintHelp (programName);
333  return 0;
334  }
335  else if (strcmp(arg, "--output-text") == 0)
336  {
337  outputText = true;
338  }
339  else
340  {
341  // un-recognized command-line argument
342  PrintHelp (programName);
343  return 0;
344  }
345  argv++;
346  }
347 
348  if (outputText)
349  {
350  anchor = "";
351  boldStart = "";
352  boldStop = "";
353  breakBoth = "\n";
354  breakHtmlOnly = "";
355  breakTextOnly = "\n";
356  brief = "";
357  commentStart = "===============================================================\n";
358  commentStop = "";
365  functionStart = "";
366  functionStop = "\n\n";
367  indentHtmlOnly = "";
368  ingroupConstructs = "";
369  listStart = "";
370  listStop = "";
371  listLineStart = " * ";
372  listLineStop = "";
373  reference = "";
374  temporaryCharacter = "";
375  }
376  else
377  {
378  anchor = "\\anchor ";
379  boldStart = "<b>";
380  boldStop = "</b>";
381  breakBoth = "<br>";
382  breakHtmlOnly = "<br>";
383  breakTextOnly = "";
384  brief = "\\brief ";
385  commentStart = "/*!";
386  commentStop = "*/";
387  defgroupAttributeListStart = "\\defgroup AttributeList ";
389  defgroupGlobalValueListStart = "\\defgroup GlobalValueList ";
391  defgroupTraceSourceListStart = "\\defgroup TraceSourceList ";
393  functionStart = "\\fn ";
394  functionStop = "";
395  indentHtmlOnly = " ";
396  ingroupConstructs = "\\ingroup constructs\n";
397  listStart = "<ul>";
398  listStop = "</ul>";
399  listLineStart = "<li>";
400  listLineStop = "</li>";
401  reference = "\\ref ";
402  temporaryCharacter = "%";
403  }
404 
405  NodeContainer c; c.Create (1);
406 
407  StaticInformation info;
408  info.RecordAggregationInfo ("ns3::Node", "ns3::TcpSocketFactory");
409  info.RecordAggregationInfo ("ns3::Node", "ns3::UdpSocketFactory");
410  info.RecordAggregationInfo ("ns3::Node", "ns3::PacketSocketFactory");
411  info.RecordAggregationInfo ("ns3::Node", "ns3::olsr::RoutingProtocol");
412  info.RecordAggregationInfo ("ns3::Node", "ns3::MobilityModel");
413  info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4L3Protocol");
414  info.RecordAggregationInfo ("ns3::Node", "ns3::ArpL3Protocol");
415 
416  for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i)
417  {
419  info.Gather (object->GetInstanceTypeId ());
420  }
421 
422  std::map< std::string, uint32_t> nameMap;
423  std::map< std::string, uint32_t>::const_iterator nameMapIterator;
424 
425  // Create a map from the class names to their index in the vector of
426  // TypeId's so that the names will end up in alphabetical order.
427  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
428  {
429  TypeId tid = TypeId::GetRegistered (i);
430  if (tid.MustHideFromDocumentation ())
431  {
432  continue;
433  }
434 
435  // Capitalize all of letters in the name so that it sorts
436  // correctly in the map.
437  std::string name = tid.GetName ();
438  for (uint32_t j = 0; j < name.length (); j++)
439  {
440  name[j] = toupper (name[j]);
441  }
442 
443  // Save this name's index.
444  nameMap[name] = i;
445  }
446 
447  // Iterate over the map, which will print the class names in
448  // alphabetical order.
449  for (nameMapIterator = nameMap.begin (); nameMapIterator != nameMap.end (); nameMapIterator++)
450  {
451  // Get the class's index out of the map;
452  uint32_t i = nameMapIterator->second;
453 
454  std::cout << commentStart << std::endl;
455  TypeId tid = TypeId::GetRegistered (i);
456  if (tid.MustHideFromDocumentation ())
457  {
458  continue;
459  }
460  std::cout << functionStart << "static TypeId " << tid.GetName () << "::GetTypeId (void)" << functionStop << std::endl;
461  std::cout << brief << "This method returns the TypeId associated to " << reference << tid.GetName () << "."
462  << std::endl << std::endl;
463  std::vector<std::string> paths = info.Get (tid);
464  if (!paths.empty ())
465  {
466  std::cout << "This object is accessible through the following paths with Config::Set and Config::Connect:"
467  << std::endl;
468  std::cout << listStart << std::endl;
469  for (uint32_t k = 0; k < paths.size (); ++k)
470  {
471  std::string path = paths[k];
472  std::cout << listLineStart << path << listLineStop << breakTextOnly << std::endl;
473  }
474  std::cout << listStop << std::endl;
475  }
476  if (tid.GetAttributeN () == 0)
477  {
478  std::cout << "No Attributes defined for this type." << breakBoth << std::endl;
479  }
480  else
481  {
482  std::cout << "Attributes defined for this type:" << breakHtmlOnly << std::endl;
483  PrintAttributes (tid, std::cout);
484  }
485  {
486  TypeId tmp = tid.GetParent ();
487  while (tmp.GetParent () != tmp)
488  {
489  if (tmp.GetAttributeN () != 0)
490  {
491  std::cout << "Attributes defined in parent class " << tmp.GetName () << ":" << breakHtmlOnly << std::endl;
492  PrintAttributes (tmp, std::cout);
493  }
494  tmp = tmp.GetParent ();
495  }
496  }
497  if (tid.GetTraceSourceN () == 0)
498  {
499  std::cout << "No TraceSources defined for this type." << breakBoth << std::endl;
500  }
501  else
502  {
503  std::cout << "TraceSources defined for this type:" << breakHtmlOnly << std::endl;
504  PrintTraceSources (tid, std::cout);
505  }
506  {
507  TypeId tmp = tid.GetParent ();
508  while (tmp.GetParent () != tmp)
509  {
510  if (tmp.GetTraceSourceN () != 0)
511  {
512  std::cout << "TraceSources defined in parent class " << tmp.GetName () << ":" << breakHtmlOnly << std::endl;
513  PrintTraceSources (tmp, std::cout);
514  }
515  tmp = tmp.GetParent ();
516  }
517  }
518  std::cout << commentStop << std::endl;
519  }
520 
521 
522  std::cout << commentStart << std::endl
524  << defgroupTraceSourceListStart << "The list of all trace sources." << defgroupTraceSourceListStop << std::endl;
525  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
526  {
527  TypeId tid = TypeId::GetRegistered (i);
528  if (tid.GetTraceSourceN () == 0 ||
530  {
531  continue;
532  }
533  std::cout << boldStart << tid.GetName () << boldStop << breakHtmlOnly << std::endl
534  << listStart << std::endl;
535  for (uint32_t j = 0; j < tid.GetTraceSourceN (); ++j)
536  {
537  struct TypeId::TraceSourceInformation info = tid.GetTraceSource(j);
538  std::cout << listLineStart << info.name << ": " << info.help << listLineStop << std::endl;
539  }
540  std::cout << listStop << std::endl;
541  }
542  std::cout << commentStop << std::endl;
543 
544  std::cout << commentStart << std::endl
546  << defgroupAttributeListStart << "The list of all attributes." << defgroupAttributeListStop << std::endl;
547  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
548  {
549  TypeId tid = TypeId::GetRegistered (i);
550  if (tid.GetAttributeN () == 0 ||
552  {
553  continue;
554  }
555  std::cout << boldStart << tid.GetName () << boldStop << breakHtmlOnly << std::endl
556  << listStart << std::endl;
557  for (uint32_t j = 0; j < tid.GetAttributeN (); ++j)
558  {
559  struct TypeId::AttributeInformation info = tid.GetAttribute(j);
560  std::cout << listLineStart << info.name << ": " << info.help << listLineStop << std::endl;
561  }
562  std::cout << listStop << std::endl;
563  }
564  std::cout << commentStop << std::endl;
565 
566 
567 
568  std::cout << commentStart << std::endl
570  << defgroupGlobalValueListStart << "The list of all global values." << defgroupGlobalValueListStop << std::endl
571  << listStart << std::endl;
573  {
574  StringValue val;
575  (*i)->GetValue (val);
576  std::cout << indentHtmlOnly << listLineStart << boldStart << anchor << "GlobalValue" << (*i)->GetName () << " " << (*i)->GetName () << boldStop << ": " << (*i)->GetHelp () << "(" << val.Get () << ")" << listLineStop << std::endl;
577  }
578  std::cout << listStop << std::endl
579  << commentStop << std::endl;
580 
581 
582  return 0;
583 }