utils/print-introspected-doxygen.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 02 Jul 2009 15:33:08 +0200
changeset 4641 7b5db4e35985
parent 4580 8092e3e83487
permissions -rw-r--r--
add an anchor for each generate documentation for a GlobalValue
     1 #include <iostream>
     2 #include "ns3/object.h"
     3 #include "ns3/pointer.h"
     4 #include "ns3/object-vector.h"
     5 #include "ns3/config.h"
     6 #include "ns3/log.h"
     7 #include "ns3/global-value.h"
     8 #include "ns3/string.h"
     9 #include "ns3/helper-module.h"
    10 
    11 using namespace ns3;
    12 
    13 NS_LOG_COMPONENT_DEFINE ("Main");
    14 
    15 void
    16 PrintAttributes (TypeId tid, std::ostream &os)
    17 {
    18   os << "<ul>"<<std::endl;
    19   for (uint32_t j = 0; j < tid.GetAttributeN (); j++)
    20     {
    21       os << "<li><b>" << tid.GetAttributeName (j) << "</b>: "
    22 		<< tid.GetAttributeHelp (j) << std::endl;
    23       Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (j);
    24       os << "  <ul>" << std::endl 
    25 	 << "    <li>Set with class: \\ref " <<  checker->GetValueTypeName () << "</li>" << std::endl;
    26       if (checker->HasUnderlyingTypeInformation ())
    27 	{
    28 	  os << "    <li>Underlying type: \\ref " << checker->GetUnderlyingTypeInformation () << "</li>" << std::endl;
    29 	}
    30       uint32_t flags = tid.GetAttributeFlags (j);
    31       Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (j);
    32       if (flags & TypeId::ATTR_CONSTRUCT && accessor->HasSetter ())
    33 	{
    34 	  Ptr<const AttributeValue> initial = tid.GetAttributeInitialValue (j);
    35 	  os << "    <li>Initial value: " << initial->SerializeToString (checker) << "</li>" << std::endl;
    36 	}
    37       os << "    <li>Flags: ";
    38       if (flags & TypeId::ATTR_CONSTRUCT && accessor->HasSetter ())
    39 	{
    40 	  os << "construct ";
    41 	}
    42       if (flags & TypeId::ATTR_SET && accessor->HasSetter ())
    43 	{
    44 	  os << "write ";
    45 	}
    46       if (flags & TypeId::ATTR_GET && accessor->HasGetter ())
    47 	{
    48 	  os << "read ";
    49 	}
    50       os << "</li>" << std::endl;
    51       os << "  </ul> " << std::endl;
    52       
    53     }
    54   os << "</ul>" << std::endl;
    55 }
    56 
    57 void
    58 PrintTraceSources (TypeId tid, std::ostream &os)
    59 {
    60   os << "<ul>"<<std::endl;
    61   for (uint32_t i = 0; i < tid.GetTraceSourceN (); ++i)
    62     {
    63       os << "<li><b>" << tid.GetTraceSourceName (i) << "</b>: "
    64 	 << tid.GetTraceSourceHelp (i)
    65 	 << std::endl;
    66       os << "</li>" << std::endl;
    67     }
    68   os << "</ul>"<<std::endl;
    69 }
    70 
    71 
    72 class StaticInformation
    73 {
    74 public:
    75   void RecordAggregationInfo (std::string a, std::string b);
    76   void Gather (TypeId tid);
    77   void Print (void) const;
    78 
    79   std::vector<std::string> Get (TypeId tid);
    80 
    81 private:
    82   std::string GetCurrentPath (void) const;
    83   void DoGather (TypeId tid);
    84   void RecordOutput (TypeId tid);
    85   bool HasAlreadyBeenProcessed (TypeId tid) const;
    86   void find_and_replace (std::string &source, const std::string find, std::string replace );
    87   std::vector<std::pair<TypeId,std::string> > m_output;
    88   std::vector<std::string> m_currentPath;
    89   std::vector<TypeId> m_alreadyProcessed;
    90   std::vector<std::pair<TypeId,TypeId> > m_aggregates;
    91 };
    92 
    93 void 
    94 StaticInformation::RecordAggregationInfo (std::string a, std::string b)
    95 {
    96   m_aggregates.push_back (std::make_pair (TypeId::LookupByName (a), TypeId::LookupByName (b)));
    97 }
    98 
    99 void 
   100 StaticInformation::Print (void) const
   101 {
   102   for (std::vector<std::pair<TypeId,std::string> >::const_iterator i = m_output.begin (); i != m_output.end (); ++i)
   103     {
   104       std::pair<TypeId,std::string> item = *i;
   105       std::cout << item.first.GetName () << " -> " << item.second << std::endl;
   106     }
   107 }
   108 
   109 std::string
   110 StaticInformation::GetCurrentPath (void) const
   111 {
   112   std::ostringstream oss;
   113   for (std::vector<std::string>::const_iterator i = m_currentPath.begin (); i != m_currentPath.end (); ++i)
   114     {
   115       std::string item = *i;
   116       oss << "/" << item;
   117     }
   118   return oss.str ();
   119 }
   120 
   121 void
   122 StaticInformation::RecordOutput (TypeId tid)
   123 {
   124   m_output.push_back (std::make_pair (tid, GetCurrentPath ()));
   125 }
   126 
   127 bool
   128 StaticInformation::HasAlreadyBeenProcessed (TypeId tid) const
   129 {
   130   for (uint32_t i = 0; i < m_alreadyProcessed.size (); ++i)
   131     {
   132       if (m_alreadyProcessed[i] == tid)
   133 	{
   134 	  return true;
   135 	}
   136     }
   137   return false;
   138 }
   139 
   140 std::vector<std::string> 
   141 StaticInformation::Get (TypeId tid)
   142 {
   143   std::vector<std::string> paths;
   144   for (uint32_t i = 0; i < m_output.size (); ++i)
   145     {
   146       std::pair<TypeId,std::string> tmp = m_output[i];
   147       if (tmp.first == tid)
   148 	{
   149 	  paths.push_back (tmp.second);
   150 	}
   151     }
   152   return paths;
   153 }
   154 
   155 void
   156 StaticInformation::Gather (TypeId tid)
   157 {
   158   DoGather (tid);
   159 
   160   std::sort (m_output.begin (), m_output.end ());
   161   m_output.erase (std::unique (m_output.begin (), m_output.end ()), m_output.end ());
   162 }
   163 
   164 void 
   165 StaticInformation::DoGather (TypeId tid)
   166 {
   167   NS_LOG_FUNCTION (this);
   168   if (HasAlreadyBeenProcessed (tid))
   169     {
   170       return;
   171     }
   172   RecordOutput (tid);
   173   for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
   174     {
   175       Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
   176       const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (checker));
   177       if (ptrChecker != 0)
   178         {
   179           TypeId pointee = ptrChecker->GetPointeeTypeId ();
   180           m_currentPath.push_back (tid.GetAttributeName (i));
   181           m_alreadyProcessed.push_back (tid);
   182           DoGather (pointee);
   183           m_alreadyProcessed.pop_back ();
   184           m_currentPath.pop_back ();
   185           continue;
   186         }
   187       // attempt to cast to an object vector.
   188       const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (checker));
   189       if (vectorChecker != 0)
   190         {
   191           TypeId item = vectorChecker->GetItemTypeId ();
   192           m_currentPath.push_back (tid.GetAttributeName (i) + "/[i]");
   193           m_alreadyProcessed.push_back (tid);
   194           DoGather (item);
   195           m_alreadyProcessed.pop_back ();
   196           m_currentPath.pop_back ();
   197           continue;
   198         }
   199     }
   200   for (uint32_t j = 0; j < TypeId::GetRegisteredN (); j++)
   201     {
   202       TypeId child = TypeId::GetRegistered (j);
   203       if (child.IsChildOf (tid))
   204         {
   205           //please take a look at the following note for an explanation 
   206           std::string childName = "$%" + child.GetName ();
   207           find_and_replace(childName,"::","::%");
   208           m_currentPath.push_back (childName);
   209           m_alreadyProcessed.push_back (tid);
   210           DoGather (child);
   211           m_alreadyProcessed.pop_back ();
   212           m_currentPath.pop_back ();
   213         }
   214     }
   215   for (uint32_t k = 0; k < m_aggregates.size (); ++k)
   216     {
   217       std::pair<TypeId,TypeId> tmp = m_aggregates[k];
   218       if (tmp.first == tid || tmp.second == tid)
   219         {
   220           TypeId other;
   221           if (tmp.first == tid)
   222             {
   223               other = tmp.second;
   224             }
   225           if (tmp.second == tid)
   226             {
   227               other = tmp.first;
   228             }
   229           /**
   230            * Note: we insert a % in the path below to ensure that doxygen does not
   231            * attempt to resolve the typeid names included in the string.
   232            * if the name contains ::, using the % sign will remove that sign
   233            * resulting for instance in $ns3MobilityModel instead of $ns3::MobilityModel
   234            * hence the output must be in the form $%ns3::%MobilityModel in order to
   235            * show correctly $ns3::MobilityModel
   236            * We add at the beginning of the name $% and we replace all the :: in the
   237            * string by ::%.
   238            */  
   239           std::string name = "$%" + other.GetName ();
   240           //finding and replacing :: by ::%
   241           find_and_replace(name,"::","::%");
   242           m_currentPath.push_back (name);
   243           m_alreadyProcessed.push_back (tid);
   244           DoGather (other);
   245           m_alreadyProcessed.pop_back ();
   246           m_currentPath.pop_back ();	  
   247         }
   248     }
   249 }
   250 
   251 void 
   252 StaticInformation::find_and_replace( std::string &source, const std::string find, std::string replace )
   253 {
   254   size_t j; 
   255   j = source.find (find);
   256   while (j != std::string::npos ) 
   257     {
   258       source.replace (j, find.length (),replace);
   259       j = source.find (find,j+1);
   260     }
   261 }
   262 
   263 int main (int argc, char *argv[])
   264 {
   265   NodeContainer c; c.Create (1);
   266 
   267   StaticInformation info;
   268   info.RecordAggregationInfo ("ns3::Node", "ns3::TcpSocketFactory");
   269   info.RecordAggregationInfo ("ns3::Node", "ns3::UdpSocketFactory");
   270   info.RecordAggregationInfo ("ns3::Node", "ns3::PacketSocketFactory");
   271   info.RecordAggregationInfo ("ns3::Node", "ns3::olsr::RoutingProtocol");
   272   info.RecordAggregationInfo ("ns3::Node", "ns3::MobilityModel");
   273   info.RecordAggregationInfo ("ns3::Node", "ns3::Ipv4L3Protocol");
   274   info.RecordAggregationInfo ("ns3::Node", "ns3::ArpL3Protocol");
   275 
   276   for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i)
   277     {
   278       Ptr<Object> object = Config::GetRootNamespaceObject (i);
   279       info.Gather (object->GetInstanceTypeId ());
   280     }
   281 
   282   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
   283     {
   284       std::cout << "/*!" << std::endl;
   285       TypeId tid = TypeId::GetRegistered (i);
   286       if (tid.MustHideFromDocumentation ())
   287 	{
   288 	  continue;
   289 	}
   290       std::cout << "\\fn static TypeId " << tid.GetName () << "::GetTypeId (void)" << std::endl;
   291       std::cout << "\\brief This method returns the TypeId associated to \\ref " << tid.GetName () 
   292 		<< std::endl << std::endl;
   293       std::vector<std::string> paths = info.Get (tid);
   294       if (!paths.empty ())
   295 	{
   296 	  std::cout << "This object is accessible through the following paths with Config::Set and Config::Connect:" 
   297 		    << std::endl;
   298 	  std::cout << "<ul>" << std::endl;
   299 	  for (uint32_t k = 0; k < paths.size (); ++k)
   300 	    {
   301 	      std::string path = paths[k];
   302 	      std::cout << "<li>" << path << "</li>" << std::endl;
   303 	    }
   304 	  std::cout << "</ul>" << std::endl;
   305 	}
   306       if (tid.GetAttributeN () == 0)
   307 	{
   308 	  std::cout << "No Attributes defined for this type.<br>" << std::endl;
   309 	}
   310       else
   311 	{
   312 	  std::cout << "Attributes defined for this type:<br>" << std::endl;
   313 	  PrintAttributes (tid, std::cout);
   314 	}
   315       {
   316 	TypeId tmp = tid.GetParent ();
   317 	while (tmp.GetParent () != tmp)
   318 	  {
   319 	    if (tmp.GetAttributeN () != 0)
   320 	      {
   321 		std::cout << "Attributes defined in parent class " << tmp.GetName () << ":<br>" << std::endl;
   322 		PrintAttributes (tmp, std::cout);
   323 	      }
   324 	    tmp = tmp.GetParent ();
   325 	  }
   326       }
   327       if (tid.GetTraceSourceN () == 0)
   328 	{
   329 	  std::cout << "No TraceSources defined for this type.<br>" << std::endl;
   330 	}
   331       else
   332 	{
   333 	  std::cout << "TraceSources defined for this type:<br>" << std::endl;
   334 	  PrintTraceSources (tid, std::cout);
   335 	}
   336       {
   337 	TypeId tmp = tid.GetParent ();
   338 	while (tmp.GetParent () != tmp)
   339 	  {
   340 	    if (tmp.GetTraceSourceN () != 0)
   341 	      {
   342 		std::cout << "TraceSources defined in parent class " << tmp.GetName () << ":<br>" << std::endl;
   343 		PrintTraceSources (tmp, std::cout);
   344 	      }
   345 	    tmp = tmp.GetParent ();
   346 	  }
   347       }
   348       std::cout << "*/" << std::endl;
   349     }
   350 
   351 
   352   std::cout << "/*!" << std::endl
   353 	    << "\\ingroup core" << std::endl
   354 	    << "\\defgroup TraceSourceList The list of all trace sources." << std::endl;
   355   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
   356     {
   357       TypeId tid = TypeId::GetRegistered (i);
   358       if (tid.GetTraceSourceN () == 0 ||
   359 	  tid.MustHideFromDocumentation ())
   360 	{
   361 	  continue;
   362 	}
   363       std::cout << "<b>" << tid.GetName () << "</b><br>" << std::endl
   364 		<< "<ul>" << std::endl;
   365       for (uint32_t j = 0; j < tid.GetTraceSourceN (); ++j)
   366 	{
   367 	  std::cout << "<li>" << tid.GetTraceSourceName (j) << ": " << tid.GetTraceSourceHelp (j) << "</li>" << std::endl;
   368 	}
   369       std::cout << "</ul>" << std::endl;
   370     }
   371   std::cout << "*/" << std::endl;
   372 
   373 
   374   std::cout << "/*!" << std::endl
   375 	    << "\\ingroup core" << std::endl
   376 	    << "\\defgroup AttributeList The list of all attributes." << std::endl;
   377   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); ++i)
   378     {
   379       TypeId tid = TypeId::GetRegistered (i);
   380       if (tid.GetAttributeN () == 0 ||
   381 	  tid.MustHideFromDocumentation ())
   382 	{
   383 	  continue;
   384 	}
   385       std::cout << "<b>" << tid.GetName () << "</b><br>" << std::endl
   386 		<< "<ul>" << std::endl;
   387       for (uint32_t j = 0; j < tid.GetAttributeN (); ++j)
   388 	{
   389 	  std::cout << "<li>" << tid.GetAttributeName (j) << ": " << tid.GetAttributeHelp (j) << "</li>" << std::endl;
   390 	}
   391       std::cout << "</ul>" << std::endl;
   392     }
   393   std::cout << "*/" << std::endl;
   394 
   395 
   396 
   397   std::cout << "/*!" << std::endl
   398 	    << "\\ingroup core" << std::endl
   399 	    << "\\defgroup GlobalValueList The list of all global values." << std::endl
   400 	    << "<ul>" << std::endl;
   401   for (GlobalValue::Iterator i = GlobalValue::Begin (); i != GlobalValue::End (); ++i)
   402     {
   403       StringValue val;
   404       (*i)->GetValue (val);
   405       std::cout << "  <li><b>\\anchor GlobalValue" << (*i)->GetName () << " " << (*i)->GetName () << "</b>: " << (*i)->GetHelp () << "(" << val.Get () << ")</li>" << std::endl;
   406     }
   407   std::cout << "</ul>" << std::endl
   408 	    << "*/" << std::endl;
   409 
   410 
   411   return 0;
   412 }