A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
print-introspected-doxygen.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9/**
10 * \file
11 * \ingroup utils
12 * Generate documentation from the TypeId database.
13 */
14
15#include "ns3/command-line.h"
16#include "ns3/config.h"
17#include "ns3/global-value.h"
18#include "ns3/log.h"
19#include "ns3/node-container.h"
20#include "ns3/object-vector.h"
21#include "ns3/object.h"
22#include "ns3/pointer.h"
23#include "ns3/simple-channel.h"
24#include "ns3/string.h"
25#include "ns3/system-path.h"
26
27#include <algorithm>
28#include <climits> // CHAR_BIT
29#include <iomanip>
30#include <iostream>
31#include <map>
32#include <utility> // as_const
33
34using namespace ns3;
35
36NS_LOG_COMPONENT_DEFINE("PrintIntrospectedDoxygen");
37
38namespace
39{
40/** Are we generating text or Doxygen? */
41bool outputText = false;
42
43/**
44 * Markup tokens.
45 * @{
46 */
47std::string anchor; ///< hyperlink anchor
48std::string argument; ///< function argument
49std::string boldStart; ///< start of bold span
50std::string boldStop; ///< end of bold span
51std::string breakBoth; ///< linebreak
52std::string breakHtmlOnly; ///< linebreak for html output only
53std::string breakTextOnly; ///< linebreak for text output only
54std::string brief; ///< brief tag
55std::string classStart; ///< start of a class
56std::string classStop; ///< end of a class
57std::string codeWord; ///< format next word as source code
58std::string commentStart; ///< start of code comment
59std::string commentStop; ///< end of code comment
60std::string copyDoc; ///< copy (or refer) to docs elsewhere
61std::string file; ///< file
62std::string flagSpanStart; ///< start of Attribute flag value
63std::string flagSpanStop; ///< end of Attribute flag value
64std::string functionStart; ///< start of a method/function
65std::string functionStop; ///< end of a method/function
66std::string headingStart; ///< start of section heading (h3)
67std::string headingStop; ///< end of section heading (h3)
68// Linking: [The link text displayed](\ref TheTarget)
69std::string hrefStart; ///< start of a link
70std::string hrefMid; ///< middle part of a link
71std::string hrefStop; ///< end of a link
72std::string indentHtmlOnly; ///< small indent
73std::string listLineStart; ///< start unordered list item
74std::string listLineStop; ///< end unordered list item
75std::string listStart; ///< start unordered list
76std::string listStop; ///< end unordered list
77std::string note; ///< start a note section
78std::string page; ///< start a separate page
79std::string reference; ///< reference tag
80std::string referenceNo; ///< block automatic references
81std::string returns; ///< the return value
82std::string sectionStart; ///< start of a section or group
83std::string seeAlso; ///< Reference to other docs
84std::string subSectionStart; ///< start a new subsection
85std::string templArgDeduced; ///< template argument deduced from function
86std::string templArgExplicit; ///< template argument required
87std::string templateArgument; ///< template argument
88std::string variable; ///< variable or class member
89
90/** @} */
91
92/**
93 * Alphabetize the AttributeInformation for a TypeId by the Attribute name
94 * \param tid The TypeId to process.
95 * \return The ordered list of Attributes.
96 */
97std::map<std::string, ns3::TypeId::AttributeInformation>
99{
100 std::map<std::string, ns3::TypeId::AttributeInformation> index;
101 for (uint32_t j = 0; j < tid.GetAttributeN(); j++)
102 {
103 struct TypeId::AttributeInformation info = tid.GetAttribute(j);
104 index[info.name] = info;
105 }
106 return index;
107}
108
109/**
110 * Alphabetize the TraceSourceInformation for a TypeId by the
111 * TraceSource name.
112 * \param tid The TypeId to process.
113 * \return The ordered list of TraceSourceInformation
114 */
115std::map<std::string, ns3::TypeId::TraceSourceInformation>
117{
118 std::map<std::string, ns3::TypeId::TraceSourceInformation> index;
119 for (uint32_t j = 0; j < tid.GetTraceSourceN(); j++)
120 {
122 index[info.name] = info;
123 }
124 return index;
125}
126
127} // unnamed namespace
128
129/**
130 * Initialize the markup strings, for either doxygen or text.
131 */
132void
134{
136 if (outputText)
137 {
138 anchor = "";
139 argument = " Arg: ";
140 boldStart = "";
141 boldStop = "";
142 breakBoth = "\n";
143 breakHtmlOnly = "";
144 breakTextOnly = "\n";
145 brief = "";
146 classStart = "";
147 classStop = "\n\n";
148 codeWord = " ";
149 commentStart = "===============================================================\n";
150 commentStop = "";
151 copyDoc = " See: ";
152 file = "File: introspected-doxygen.txt";
153 flagSpanStart = "";
154 flagSpanStop = "";
155 functionStart = "";
156 functionStop = "\n\n";
157 headingStart = "";
158 headingStop = "";
159 // Linking: The link text displayed (see TheTarget)
160 hrefStart = "";
161 hrefMid = " (see ";
162 hrefStop = ")";
163 indentHtmlOnly = "";
164 listLineStart = " * ";
165 listLineStop = "";
166 listStart = "";
167 listStop = "";
168 note = "Note: ";
169 page = "Page ";
170 reference = " ";
171 referenceNo = " ";
172 returns = " Returns: ";
173 sectionStart = "Section: ";
174 seeAlso = " See: ";
175 subSectionStart = "Subsection ";
176 templArgDeduced = "[deduced] ";
177 templArgExplicit = "[explicit] ";
178 templateArgument = "Template Arg: ";
179 variable = "Variable: ";
180 }
181 else
182 {
183 anchor = "\\anchor ";
184 argument = "\\param ";
185 boldStart = "<b>";
186 boldStop = "</b>";
187 breakBoth = "<br>";
188 breakHtmlOnly = "<br>";
189 breakTextOnly = "";
190 brief = "\\brief ";
191 classStart = "\\class ";
192 classStop = "";
193 codeWord = "\\p ";
194 commentStart = "/*!\n";
195 commentStop = "*/\n";
196 copyDoc = "\\copydoc ";
197 file = "\\file";
198 flagSpanStart = "<span class=\"mlabel\">";
199 flagSpanStop = "</span>";
200 functionStart = "\\fn ";
201 functionStop = "";
202 headingStart = "<h3>";
203 headingStop = "</h3>";
204 // Linking: [The link text displayed](\ref TheTarget)
205 hrefStart = "[";
206 hrefMid = "](\\ref ";
207 hrefStop = ")";
208 indentHtmlOnly = " ";
209 listLineStart = "<li>";
210 listLineStop = "</li>";
211 listStart = "<ul>";
212 listStop = "</ul>";
213 note = "\\note ";
214 page = "\\page ";
215 reference = " \\ref ";
216 referenceNo = " %";
217 returns = "\\returns ";
218 sectionStart = "\\ingroup ";
219 seeAlso = "\\see ";
220 subSectionStart = "\\addtogroup ";
221 templArgDeduced = "\\deduced ";
222 templArgExplicit = "\\explicit ";
223 templateArgument = "\\tparam ";
224 variable = "\\var ";
225 }
226} // SetMarkup()
227
228/***************************************************************
229 * Aggregation and configuration paths
230 ***************************************************************/
231
232/**
233 * Gather aggregation and configuration path information from registered types.
234 */
236{
237 public:
238 /**
239 * Record the a -> b aggregation relation.
240 *
241 * \param a [in] the source(?) TypeId name
242 * \param b [in] the destination(?) TypeId name
243 */
244 void RecordAggregationInfo(std::string a, std::string b);
245 /**
246 * Gather aggregation and configuration path information for tid
247 *
248 * \param tid [in] the TypeId to gather information from
249 */
250 void Gather(TypeId tid);
251 /**
252 * Print output in "a -> b" form on the stream.
253 * \param [in,out] os The output stream.
254 */
255 void Print(std::ostream& os) const;
256
257 /**
258 * \return the configuration paths for tid
259 *
260 * \param tid [in] the TypeId to return information for
261 */
262 std::vector<std::string> Get(TypeId tid) const;
263
264 /**
265 * \return the type names we couldn't aggregate.
266 */
267 std::vector<std::string> GetNoTypeIds() const;
268
269 private:
270 /**
271 * \return the current configuration path
272 */
273 std::string GetCurrentPath() const;
274 /**
275 * Gather attribute, configuration path information for tid
276 *
277 * \param tid [in] the TypeId to gather information from
278 */
279 void DoGather(TypeId tid);
280 /**
281 * Record the current config path for tid.
282 *
283 * \param tid [in] the TypeId to record.
284 */
285 void RecordOutput(TypeId tid);
286 /**
287 * \return whether the tid has already been processed
288 *
289 * \param tid [in] the TypeId to check.
290 */
291 bool HasAlreadyBeenProcessed(TypeId tid) const;
292 /**
293 * Configuration path for each TypeId
294 */
295 std::vector<std::pair<TypeId, std::string>> m_output;
296 /**
297 * Current configuration path
298 */
299 std::vector<std::string> m_currentPath;
300 /**
301 * List of TypeIds we've already processed
302 */
303 std::vector<TypeId> m_alreadyProcessed;
304 /**
305 * List of aggregation relationships.
306 */
307 std::vector<std::pair<TypeId, TypeId>> m_aggregates;
308 /**
309 * List of type names without TypeIds, because those modules aren't enabled.
310 *
311 * This is mutable because GetNoTypeIds sorts and uniquifies this list
312 * before returning it.
313 */
314 mutable std::vector<std::string> m_noTids;
315
316}; // class StaticInformation
317
318void
319StaticInformation::RecordAggregationInfo(std::string a, std::string b)
320{
321 NS_LOG_FUNCTION(this << a << b);
322 TypeId aTid;
323 bool found = TypeId::LookupByNameFailSafe(a, &aTid);
324 if (!found)
325 {
326 m_noTids.push_back(a);
327 return;
328 }
329 TypeId bTid;
330 found = TypeId::LookupByNameFailSafe(b, &bTid);
331 if (!found)
332 {
333 m_noTids.push_back(b);
334 return;
335 }
336
337 m_aggregates.emplace_back(aTid, bTid);
338}
339
340void
341StaticInformation::Print(std::ostream& os) const
342{
343 NS_LOG_FUNCTION(this);
344 for (const auto& item : m_output)
345 {
346 os << item.first.GetName() << " -> " << item.second << std::endl;
347 }
348}
349
350std::string
352{
353 NS_LOG_FUNCTION(this);
354 std::ostringstream oss;
355 for (const auto& item : m_currentPath)
356 {
357 oss << "/" << item;
358 }
359 return oss.str();
360}
361
362void
364{
365 NS_LOG_FUNCTION(this << tid);
366 m_output.emplace_back(tid, GetCurrentPath());
367}
368
369bool
371{
372 NS_LOG_FUNCTION(this << tid);
373 for (const auto& it : m_alreadyProcessed)
374 {
375 if (it == tid)
376 {
377 return true;
378 }
379 }
380 return false;
381}
382
383std::vector<std::string>
385{
386 NS_LOG_FUNCTION(this << tid);
387 std::vector<std::string> paths;
388 for (const auto& item : m_output)
389 {
390 if (item.first == tid)
391 {
392 paths.push_back(item.second);
393 }
394 }
395 return paths;
396}
397
398/**
399 * Helper to keep only the unique items in a container.
400 *
401 * The container is modified in place; the elements end up sorted.
402 *
403 * The container must support \c begin(), \c end() and \c erase(),
404 * which, among the STL containers, limits this to
405 * \c std::vector, \c std::dequeue and \c std::list.
406 *
407 * The container elements must support \c operator< (for \c std::sort)
408 * and \c operator== (for \c std::unique).
409 *
410 * \tparam T \deduced The container type.
411 * \param t The container.
412 */
413template <typename T>
414void
416{
417 std::sort(t.begin(), t.end());
418 t.erase(std::unique(t.begin(), t.end()), t.end());
419}
420
421std::vector<std::string>
423{
424 NS_LOG_FUNCTION(this);
426 return m_noTids;
427}
428
429void
431{
432 NS_LOG_FUNCTION(this << tid);
433 DoGather(tid);
435}
436
437void
439{
440 NS_LOG_FUNCTION(this << tid);
442 {
443 return;
444 }
445 RecordOutput(tid);
446 for (uint32_t i = 0; i < tid.GetAttributeN(); ++i)
447 {
448 struct TypeId::AttributeInformation info = tid.GetAttribute(i);
449 const auto ptrChecker = dynamic_cast<const PointerChecker*>(PeekPointer(info.checker));
450 if (ptrChecker != nullptr)
451 {
452 TypeId pointee = ptrChecker->GetPointeeTypeId();
453
454 // See if this is a pointer to an Object.
456 TypeId objectTypeId = object->GetTypeId();
457 if (objectTypeId == pointee)
458 {
459 // Stop the recursion at this attribute if it is a
460 // pointer to an Object, which create too many spurious
461 // paths in the list of attribute paths because any
462 // Object can be in that part of the path.
463 continue;
464 }
465
466 m_currentPath.push_back(info.name);
467 m_alreadyProcessed.push_back(tid);
468 DoGather(pointee);
469 m_alreadyProcessed.pop_back();
470 m_currentPath.pop_back();
471 continue;
472 }
473 // attempt to cast to an object vector.
474 const auto vectorChecker =
475 dynamic_cast<const ObjectPtrContainerChecker*>(PeekPointer(info.checker));
476 if (vectorChecker != nullptr)
477 {
478 TypeId item = vectorChecker->GetItemTypeId();
479 m_currentPath.push_back(info.name + "/[i]");
480 m_alreadyProcessed.push_back(tid);
481 DoGather(item);
482 m_alreadyProcessed.pop_back();
483 m_currentPath.pop_back();
484 continue;
485 }
486 }
487 for (uint32_t j = 0; j < TypeId::GetRegisteredN(); j++)
488 {
489 TypeId child = TypeId::GetRegistered(j);
490 if (child.IsChildOf(tid))
491 {
492 std::string childName = "$" + child.GetName();
493 m_currentPath.push_back(childName);
494 m_alreadyProcessed.push_back(tid);
495 DoGather(child);
496 m_alreadyProcessed.pop_back();
497 m_currentPath.pop_back();
498 }
499 }
500 for (const auto& item : m_aggregates)
501 {
502 if (item.first == tid || item.second == tid)
503 {
504 TypeId other;
505 if (item.first == tid)
506 {
507 other = item.second;
508 }
509 if (item.second == tid)
510 {
511 other = item.first;
512 }
513 std::string name = "$" + other.GetName();
514 m_currentPath.push_back(name);
515 m_alreadyProcessed.push_back(tid);
516 DoGather(other);
517 m_alreadyProcessed.pop_back();
518 m_currentPath.pop_back();
519 }
520 }
521} // StaticInformation::DoGather()
522
523/// Register aggregation relationships that are not automatically
524/// detected by this introspection program. Statements added here
525/// result in more configuration paths being added to the doxygen.
526/// \return instance of StaticInformation with the registered information
529{
531
532 static StaticInformation info;
533 static bool mapped = false;
534
535 if (mapped)
536 {
537 return info;
538 }
539
540 // Short circuit next call
541 mapped = true;
542
543 // The below statements register typical aggregation relationships
544 // in ns-3 programs, that otherwise aren't picked up automatically
545 // by the creation of the above node. To manually list other common
546 // aggregation relationships that you would like to see show up in
547 // the list of configuration paths in the doxygen, add additional
548 // statements below.
549 info.RecordAggregationInfo("ns3::Node", "ns3::TcpSocketFactory");
550 info.RecordAggregationInfo("ns3::Node", "ns3::UdpSocketFactory");
551 info.RecordAggregationInfo("ns3::Node", "ns3::PacketSocketFactory");
552 info.RecordAggregationInfo("ns3::Node", "ns3::MobilityModel");
553 info.RecordAggregationInfo("ns3::Node", "ns3::Ipv4L3Protocol");
554 info.RecordAggregationInfo("ns3::Node", "ns3::Ipv4NixVectorRouting");
555 info.RecordAggregationInfo("ns3::Node", "ns3::Icmpv4L4Protocol");
556 info.RecordAggregationInfo("ns3::Node", "ns3::ArpL3Protocol");
557 info.RecordAggregationInfo("ns3::Node", "ns3::Icmpv4L4Protocol");
558 info.RecordAggregationInfo("ns3::Node", "ns3::UdpL4Protocol");
559 info.RecordAggregationInfo("ns3::Node", "ns3::Ipv6L3Protocol");
560 info.RecordAggregationInfo("ns3::Node", "ns3::Icmpv6L4Protocol");
561 info.RecordAggregationInfo("ns3::Node", "ns3::TcpL4Protocol");
562 info.RecordAggregationInfo("ns3::Node", "ns3::RipNg");
563 info.RecordAggregationInfo("ns3::Node", "ns3::GlobalRouter");
564 info.RecordAggregationInfo("ns3::Node", "ns3::aodv::RoutingProtocol");
565 info.RecordAggregationInfo("ns3::Node", "ns3::dsdv::RoutingProtocol");
566 info.RecordAggregationInfo("ns3::Node", "ns3::dsr::DsrRouting");
567 info.RecordAggregationInfo("ns3::Node", "ns3::olsr::RoutingProtocol");
568 info.RecordAggregationInfo("ns3::Node", "ns3::EnergyHarvesterContainer");
569 info.RecordAggregationInfo("ns3::Node", "ns3::EnergySourceContainer");
570
571 // Create a channel object so that channels appear in the namespace
572 // paths that will be generated here.
573 Ptr<SimpleChannel> simpleChannel;
574 simpleChannel = CreateObject<SimpleChannel>();
575
576 for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN(); ++i)
577 {
579 info.Gather(object->GetInstanceTypeId());
580 }
581
582 return info;
583
584} // GetTypicalAggregations()
585
586/// Map from TypeId name to tid
587typedef std::map<std::string, int32_t> NameMap;
588typedef NameMap::const_iterator NameMapIterator; ///< NameMap iterator
589
590/**
591 * Create a map from the class names to their index in the vector of
592 * TypeId's so that the names will end up in alphabetical order.
593 *
594 * \returns NameMap
595 */
598{
600
601 static NameMap nameMap;
602 static bool mapped = false;
603
604 if (mapped)
605 {
606 return nameMap;
607 }
608
609 // Short circuit next call
610 mapped = true;
611
612 // Get typical aggregation relationships.
614
615 // Registered types
616 for (uint32_t i = 0; i < TypeId::GetRegisteredN(); i++)
617 {
620 {
621 continue;
622 }
623
624 // Capitalize all of letters in the name so that it sorts
625 // correctly in the map.
626 std::string name = tid.GetName();
627 std::transform(name.begin(), name.end(), name.begin(), ::toupper);
628
629 // Save this name's index.
630 nameMap[name] = i;
631 }
632
633 // Type names without TypeIds
634 std::vector<std::string> noTids = info.GetNoTypeIds();
635 for (const auto& item : noTids)
636 {
637 nameMap[item] = -1;
638 }
639
640 return nameMap;
641} // GetNameMap()
642
643/// List of TypeIds for a group
644using GroupList_t = std::set<TypeId>;
645/// Collection of group names with associated TypeIds
646using GroupsList_t = std::map<std::string, GroupList_t>;
647
648/**
649 * Get a sorted list of TypeId groups
650 * \returns a map of group name and associated TypeIds
651 */
654{
655 static GroupsList_t groups;
656 static bool mapped = false;
657 if (mapped)
658 {
659 return groups;
660 }
661
662 NameMap nameMap = GetNameMap();
663 for (const auto& item : nameMap)
664 {
665 // Handle only real TypeIds
666 if (item.second < 0)
667 {
668 continue;
669 }
670 // Get the class's index out of the map;
671 TypeId tid = TypeId::GetRegistered(item.second);
672 auto group = tid.GetGroupName();
673
674 if (!group.empty())
675 {
676 groups[group].insert(tid);
677 }
678 }
679 return groups;
680
681} // GetGroupsList()
682
683/***************************************************************
684 * Docs for a single TypeId
685 ***************************************************************/
686
687/**
688 * Print the support level for an Attribute or TraceSource
689 * \param os the output stream
690 * \param supportLevel the SupportLevel
691 * \param supportMsg optional support message
692 */
693void
695{
696 os << " " << listLineStart << "Support level: ";
697 os << flagSpanStart;
698 switch (supportLevel)
699 {
701 os << "SUPPORTED";
702 break;
704 os << "DEPRECATED";
705 break;
706 case TypeId::OBSOLETE:
707 os << "OBSOLETE";
708 break;
709 default:
710 os << "UNKNOWN";
711 }
712 os << flagSpanStop;
713 if (!supportMsg.empty())
714 {
715 os << ": " << supportMsg;
716 }
717 os << listLineStop << std::endl;
718} // PrintSupportLevel
719
720/**
721 * Print config paths
722 * \param os the output stream
723 * \param tid the type ID
724 */
725void
726PrintConfigPaths(std::ostream& os, const TypeId tid)
727{
728 NS_LOG_FUNCTION(tid);
729 std::vector<std::string> paths = GetTypicalAggregations().Get(tid);
730
731 // Config --------------
732 if (paths.empty())
733 {
734 os << "Introspection did not find any typical Config paths." << breakBoth << std::endl;
735 }
736 else
737 {
738 os << headingStart << "Config Paths" << headingStop << std::endl;
739 os << std::endl;
740 os << tid.GetName() << " is accessible through the following paths"
741 << " with Config::Set and Config::Connect:" << std::endl;
742 os << listStart << std::endl;
743 for (const auto& path : paths)
744 {
745 os << listLineStart << "\"" << path << "\"" << listLineStop << breakTextOnly
746 << std::endl;
747 }
748 os << listStop << std::endl;
749 }
750} // PrintConfigPaths()
751
752/**
753 * Print direct Attributes for this TypeId.
754 *
755 * Only attributes defined directly by this TypeId will be printed.
756 *
757 * \param [in,out] os The output stream.
758 * \param [in] tid The TypeId to print.
759 */
760void
761PrintAttributesTid(std::ostream& os, const TypeId tid)
762{
763 NS_LOG_FUNCTION(tid);
764
765 auto index = SortedAttributeInfo(tid);
766
767 os << listStart << std::endl;
768 for (const auto& [name, info] : index)
769 {
770 os << listLineStart << boldStart << name << boldStop << ": " << info.help << std::endl;
771 os << indentHtmlOnly << listStart << std::endl;
772 os << " " << listLineStart << "Set with class: " << reference
773 << info.checker->GetValueTypeName() << listLineStop << std::endl;
774
775 std::string underType;
776 if (info.checker->HasUnderlyingTypeInformation())
777 {
778 os << " " << listLineStart << "Underlying type: ";
779
780 std::string valType = info.checker->GetValueTypeName();
781 underType = info.checker->GetUnderlyingTypeInformation();
782 bool handled = false;
783 if ((valType != "ns3::EnumValue") && (underType != "std::string"))
784 {
785 // Indirect cases to handle
786 if (valType == "ns3::PointerValue")
787 {
788 const auto ptrChecker =
789 dynamic_cast<const PointerChecker*>(PeekPointer(info.checker));
790 if (ptrChecker != nullptr)
791 {
792 os << reference << "ns3::Ptr"
793 << "< " << reference << ptrChecker->GetPointeeTypeId().GetName() << ">";
794 handled = true;
795 }
796 }
797 else if (valType == "ns3::ObjectPtrContainerValue")
798 {
799 const auto ptrChecker =
800 dynamic_cast<const ObjectPtrContainerChecker*>(PeekPointer(info.checker));
801 if (ptrChecker != nullptr)
802 {
803 os << reference << "ns3::Ptr"
804 << "< " << reference << ptrChecker->GetItemTypeId().GetName() << ">";
805 handled = true;
806 }
807 }
808
809 // Helper to match first part of string
810 auto match = [&uType = std::as_const(underType)](const std::string& s) {
811 return uType.rfind(s, 0) == 0; // only checks position 0
812 };
813
814 if (match("bool") || match("double") || match("int8_t") || match("uint8_t") ||
815 match("int16_t") || match("uint16_t") || match("int32_t") ||
816 match("uint32_t") || match("int64_t") || match("uint64_t"))
817 {
818 os << underType;
819 handled = true;
820 }
821 }
822 if (!handled)
823 {
824 os << codeWord << underType;
825 }
826 os << listLineStop << std::endl;
827 }
828 if (info.flags & TypeId::ATTR_CONSTRUCT && info.accessor->HasSetter())
829 {
830 std::string value = info.initialValue->SerializeToString(info.checker);
831 if (underType == "std::string" && value.empty())
832 {
833 value = "\"\"";
834 }
835 os << " " << listLineStart << "Initial value: " << value << listLineStop
836 << std::endl;
837 }
838 bool moreFlags{false};
839 os << " " << listLineStart << "Flags: ";
840
841 auto myInfo = info; // See GitLab #1142
842 auto flagWrite = [&os, &moreFlags, myInfo](TypeId::AttributeFlag flag,
843 bool hasFunc,
844 std::string msg) -> void {
845 if (myInfo.flags & flag && hasFunc)
846 {
847 os << (outputText && moreFlags ? ", " : "") << flagSpanStart << msg << flagSpanStop;
848 moreFlags = true;
849 }
850 };
851 flagWrite(TypeId::ATTR_CONSTRUCT, info.accessor->HasSetter(), "construct");
852 flagWrite(TypeId::ATTR_SET, info.accessor->HasSetter(), "write");
853 flagWrite(TypeId::ATTR_GET, info.accessor->HasGetter(), "read");
854 os << listLineStop << std::endl;
855
856 PrintSupportLevel(os, info.supportLevel, info.supportMsg);
857
858 os << indentHtmlOnly << listStop << std::endl;
859 }
860 os << listStop << std::endl;
861} // PrintAttributesTid()
862
863/**
864 * Print the Attributes block for tid,
865 * including Attributes declared in base classes.
866 *
867 * All Attributes of this TypeId will be printed,
868 * including those defined in parent classes.
869 *
870 * \param [in,out] os The output stream.
871 * \param [in] tid The TypeId to print.
872 */
873void
874PrintAttributes(std::ostream& os, const TypeId tid)
875{
876 NS_LOG_FUNCTION(tid);
877 if (tid.GetAttributeN() == 0)
878 {
879 os << "No Attributes are defined for this type." << breakBoth << std::endl;
880 }
881 else
882 {
883 os << headingStart << "Attributes" << headingStop << std::endl;
884 PrintAttributesTid(os, tid);
885 }
886
887 // Attributes from base classes
888 TypeId tmp = tid.GetParent();
889 while (tmp.GetParent() != tmp)
890 {
891 if (tmp.GetAttributeN() != 0)
892 {
893 os << headingStart << "Attributes defined in parent class " << tmp.GetName()
894 << headingStop << std::endl;
895 PrintAttributesTid(os, tmp);
896 }
897 tmp = tmp.GetParent();
898
899 } // Attributes
900} // PrintAttributes()
901
902/**
903 * Print direct Trace sources for this TypeId.
904 *
905 * Only Trace sources defined directly by this TypeId will be printed.
906 *
907 * \param [in,out] os The output stream.
908 * \param [in] tid The TypeId to print.
909 */
910void
911PrintTraceSourcesTid(std::ostream& os, const TypeId tid)
912{
913 NS_LOG_FUNCTION(tid);
914
915 auto index = SortedTraceSourceInfo(tid);
916
917 os << listStart << std::endl;
918 for (const auto& [name, info] : index)
919 {
920 os << listLineStart << boldStart << name << boldStop << ": " << info.help << breakBoth;
921 os << indentHtmlOnly << listStart << std::endl;
922 os << " " << listLineStart;
923 if (!outputText)
924 {
925 // '%' prevents doxygen from linking to the Callback class...
926 os << " %";
927 }
928 os << "Callback signature: " << info.callback << std::endl;
929 os << listLineStop << std::endl;
930
931 PrintSupportLevel(os, info.supportLevel, info.supportMsg);
932 os << listStop << std::endl;
933 }
934 os << listStop << std::endl;
935} // PrintTraceSourcesTid()
936
937/**
938 * Print the Trace sources block for tid,
939 * including Trace sources declared in base classes.
940 *
941 * All Trace sources of this TypeId will be printed,
942 * including those defined in parent classes.
943 *
944 * \param [in,out] os The output stream.
945 * \param [in] tid The TypeId to print.
946 */
947void
948PrintTraceSources(std::ostream& os, const TypeId tid)
949{
950 NS_LOG_FUNCTION(tid);
951 if (tid.GetTraceSourceN() == 0)
952 {
953 os << "No TraceSources are defined for this type." << breakBoth << std::endl;
954 }
955 else
956 {
957 os << headingStart << "TraceSources" << headingStop << std::endl;
958 PrintTraceSourcesTid(os, tid);
959 }
960
961 // Trace sources from base classes
962 TypeId tmp = tid.GetParent();
963 while (tmp.GetParent() != tmp)
964 {
965 if (tmp.GetTraceSourceN() != 0)
966 {
967 os << headingStart << "TraceSources defined in parent class " << tmp.GetName()
968 << headingStop << std::endl;
969 PrintTraceSourcesTid(os, tmp);
970 }
971 tmp = tmp.GetParent();
972 }
973
974} // PrintTraceSources()
975
976/**
977 * Print the size of the type represented by this tid.
978 *
979 * \param [in,out] os The output stream.
980 * \param [in] tid The TypeId to print.
981 */
982void
983PrintSize(std::ostream& os, const TypeId tid)
984{
985 NS_LOG_FUNCTION(tid);
986 NS_ASSERT_MSG(CHAR_BIT != 0, "CHAR_BIT is zero");
987
988 std::size_t arch = (sizeof(void*) * CHAR_BIT);
989
990 os << boldStart << "Size" << boldStop << " of this type is " << tid.GetSize() << " bytes (on a "
991 << arch << "-bit architecture)." << std::endl;
992} // PrintSize()
993
994/**
995 * Print the doxy block for a single TypeId
996 *
997 * \param [in,out] os The output stream.
998 * \param [in] tid the TypeId
999 */
1000void
1001PrintTypeIdBlock(std::ostream& os, const TypeId tid)
1002{
1003 NS_LOG_FUNCTION(tid);
1004
1005 std::string name = tid.GetName();
1006
1007 os << commentStart << std::endl;
1008
1009 os << classStart << name << std::endl;
1010 os << std::endl;
1011
1012 PrintConfigPaths(os, tid);
1013 PrintAttributes(os, tid);
1014 PrintTraceSources(os, tid);
1015
1016 if (!tid.GetGroupName().empty())
1017 {
1018 os << boldStart << "Group:" << boldStop << " " << tid.GetGroupName() << "\n" << std::endl;
1019 }
1020
1021 PrintSize(os, tid);
1022
1023 os << commentStop << std::endl;
1024
1025} // PrintTypeIdBlock()
1026
1027/**
1028 * Print the doxy block for each TypeId
1029 *
1030 * \param [in,out] os The output stream.
1031 */
1032void
1033PrintTypeIdBlocks(std::ostream& os)
1034{
1036
1037 NameMap nameMap = GetNameMap();
1038
1039 // Iterate over the map, which will print the class names in
1040 // alphabetical order.
1041 for (const auto& item : nameMap)
1042 {
1043 // Handle only real TypeIds
1044 if (item.second < 0)
1045 {
1046 continue;
1047 }
1048 // Get the class's index out of the map;
1049 TypeId tid = TypeId::GetRegistered(item.second);
1050 PrintTypeIdBlock(os, tid);
1051 } // for class documentation
1052
1053} // PrintTypeIdBlocks()
1054
1055/***************************************************************
1056 * Lists of All things
1057 ***************************************************************/
1058
1059/**
1060 * Print the list of all TypeIds
1061 *
1062 * \param [in,out] os The output stream.
1063 */
1064void
1065PrintAllTypeIds(std::ostream& os)
1066{
1068 os << commentStart << page << "TypeIdList All ns3::TypeId's\n" << std::endl;
1069 os << "This is a list of all" << reference << "ns3::TypeId's.\n"
1070 << "For more information see the" << reference << "ns3::TypeId "
1071 << "section of this API documentation and the" << referenceNo << "TypeId section "
1072 << "in the Configuration and " << referenceNo << "Attributes chapter of the Manual.\n"
1073 << std::endl;
1074
1075 os << listStart << std::endl;
1076
1077 NameMap nameMap = GetNameMap();
1078 // Iterate over the map, which will print the class names in
1079 // alphabetical order.
1080 for (const auto& item : nameMap)
1081 {
1082 // Handle only real TypeIds
1083 if (item.second < 0)
1084 {
1085 continue;
1086 }
1087 // Get the class's index out of the map;
1088 TypeId tid = TypeId::GetRegistered(item.second);
1089
1090 os << indentHtmlOnly << listLineStart << boldStart << tid.GetName() << boldStop
1091 << listLineStop << std::endl;
1092 }
1093 os << listStop << std::endl;
1094 os << commentStop << std::endl;
1095
1096} // PrintAllTypeIds()
1097
1098/**
1099 * Print the list of all Attributes.
1100 *
1101 * \param [in,out] os The output stream.
1102 *
1103 * \todo Print this sorted by class (the current version)
1104 * as well as by Attribute name.
1105 */
1106void
1107PrintAllAttributes(std::ostream& os)
1108{
1110 os << commentStart << page << "AttributeList All Attributes\n" << std::endl;
1111 os << "This is a list of all" << reference << "attributes classes. "
1112 << "For more information see the" << reference << "attributes "
1113 << "section of this API documentation and the Attributes sections "
1114 << "in the Tutorial and Manual.\n"
1115 << std::endl;
1116
1117 NameMap nameMap = GetNameMap();
1118 // Iterate over the map, which will print the class names in
1119 // alphabetical order.
1120 for (const auto& item : nameMap)
1121 {
1122 // Handle only real TypeIds
1123 if (item.second < 0)
1124 {
1125 continue;
1126 }
1127 // Get the class's index out of the map;
1128 TypeId tid = TypeId::GetRegistered(item.second);
1129
1130 if (tid.GetAttributeN() == 0)
1131 {
1132 continue;
1133 }
1134
1135 auto index = SortedAttributeInfo(tid);
1136
1137 os << boldStart << tid.GetName() << boldStop << breakHtmlOnly << std::endl;
1138 os << listStart << std::endl;
1139 for (const auto& [name, info] : index)
1140 {
1141 os << listLineStart << boldStart << name << boldStop << ": " << info.help
1142 << listLineStop << std::endl;
1143 }
1144 os << listStop << std::endl;
1145 }
1146 os << commentStop << std::endl;
1147
1148} // PrintAllAttributes()
1149
1150/**
1151 * Print the list of all global variables.
1152 *
1153 * \param [in,out] os The output stream.
1154 */
1155void
1156PrintAllGlobals(std::ostream& os)
1157{
1159 os << commentStart << page << "GlobalValueList All GlobalValues\n" << std::endl;
1160 os << "This is a list of all" << reference << "ns3::GlobalValue instances.\n"
1161 << "See ns3::GlobalValue for how to set these." << std::endl;
1162
1163 os << listStart << std::endl;
1164 for (auto i = GlobalValue::Begin(); i != GlobalValue::End(); ++i)
1165 {
1166 StringValue val;
1167 (*i)->GetValue(val);
1168 os << indentHtmlOnly << listLineStart << boldStart << hrefStart << (*i)->GetName()
1169 << hrefMid << "GlobalValue" << (*i)->GetName() << hrefStop << boldStop << ": "
1170 << (*i)->GetHelp() << ". Default value: " << val.Get() << "." << listLineStop
1171 << std::endl;
1172 }
1173 os << listStop << std::endl;
1174 os << commentStop << std::endl;
1175
1176} // PrintAllGlobals()
1177
1178/**
1179 * Print the list of all groups
1180 *
1181 * \param [in,out] os The output stream.
1182 */
1183void
1184PrintAllGroups(std::ostream& os)
1185{
1187 os << commentStart << page << "GroupsList All Object Groups\n" << std::endl;
1188 os << "This is a list of all Object Groups.\n"
1189 << "Objects are added to groups by " << hrefStart << "ns3::TypeId::SetGroupName()" << hrefMid
1190 << "ns3::TypeId::SetGroupName" << hrefStop << "\n"
1191 << std::endl;
1192
1193 auto groups = GetGroupsList();
1194
1195 for (const auto& g : groups)
1196 {
1197 os << boldStart << g.first << boldStop << breakHtmlOnly << std::endl;
1198
1199 os << listStart << std::endl;
1200 for (const auto& tid : g.second)
1201 {
1202 os << indentHtmlOnly << listLineStart << hrefStart << tid.GetName() << hrefMid
1203 << tid.GetName() << hrefStop << listLineStop << std::endl;
1204 }
1205 os << listStop << std::endl;
1206 }
1207 os << commentStop << std::endl;
1208}
1209
1210/**
1211 * Print the list of all LogComponents.
1212 *
1213 * \param [in,out] os The output stream.
1214 */
1215void
1216PrintAllLogComponents(std::ostream& os)
1217{
1219 os << commentStart << page << "LogComponentList All LogComponents\n" << std::endl;
1220 os << "This is a list of all" << reference << "ns3::LogComponent instances.\n" << std::endl;
1221
1222 /**
1223 * \todo Switch to a border-less table, so the file links align
1224 * See https://www.doxygen.nl/manual/htmlcmds.html
1225 */
1227 // Find longest log name
1228 std::size_t widthL = std::string("Log Component").size();
1229 std::size_t widthR = std::string("file").size();
1230 for (const auto& it : (*logs))
1231 {
1232 widthL = std::max(widthL, it.first.size());
1233 std::string file = it.second->File();
1234 // Strip leading "../" related to depth in build directory
1235 // since doxygen only sees the path starting with "src/", etc.
1236 while (file.find("../") == 0)
1237 {
1238 file = file.substr(3);
1239 }
1240 widthR = std::max(widthR, file.size());
1241 }
1242 const std::string tLeft("| ");
1243 const std::string tMid(" | ");
1244 const std::string tRight(" |");
1245
1246 // Header line has to be padded to same length as separator line
1247 os << tLeft << std::setw(widthL) << std::left << "Log Component" << tMid << std::setw(widthR)
1248 << std::left << "File" << tRight << std::endl;
1249 os << tLeft << ":" << std::string(widthL - 1, '-') << tMid << ":"
1250 << std::string(widthR - 1, '-') << tRight << std::endl;
1251
1252 for (const auto& it : (*logs))
1253 {
1254 std::string file = it.second->File();
1255 // Strip leading "../" related to depth in build directory
1256 // since doxygen only sees the path starting with "src/", etc.
1257 while (file.find("../") == 0)
1258 {
1259 file = file.substr(3);
1260 }
1261
1262 os << tLeft << std::setw(widthL) << std::left << it.first << tMid << std::setw(widthR)
1263 << file << tRight << std::endl;
1264 }
1265 os << std::right << std::endl;
1266 os << commentStop << std::endl;
1267} // PrintAllLogComponents()
1268
1269/**
1270 * Print the list of all Trace sources.
1271 *
1272 * \param [in,out] os The output stream.
1273 *
1274 * \todo Print this sorted by class (the current version)
1275 * as well as by TraceSource name.
1276 */
1277void
1278PrintAllTraceSources(std::ostream& os)
1279{
1281 os << commentStart << page << "TraceSourceList All TraceSources\n" << std::endl;
1282 os << "This is a list of all" << reference << "tracing sources. "
1283 << "For more information see the " << reference << "tracing "
1284 << "section of this API documentation and the Tracing sections "
1285 << "in the Tutorial and Manual.\n"
1286 << std::endl;
1287
1288 NameMap nameMap = GetNameMap();
1289
1290 // Iterate over the map, which will print the class names in
1291 // alphabetical order.
1292 for (const auto& item : nameMap)
1293 {
1294 // Handle only real TypeIds
1295 if (item.second < 0)
1296 {
1297 continue;
1298 }
1299 // Get the class's index out of the map;
1300 TypeId tid = TypeId::GetRegistered(item.second);
1301
1302 if (tid.GetTraceSourceN() == 0)
1303 {
1304 continue;
1305 }
1306
1307 auto index = SortedTraceSourceInfo(tid);
1308
1309 os << boldStart << tid.GetName() << boldStop << breakHtmlOnly << std::endl;
1310
1311 os << listStart << std::endl;
1312 for (const auto& [name, info] : index)
1313 {
1314 os << listLineStart << boldStart << name << boldStop << ": " << info.help
1315 << listLineStop << std::endl;
1316 }
1317 os << listStop << std::endl;
1318 }
1319 os << commentStop << std::endl;
1320
1321} // PrintAllTraceSources()
1322
1323/***************************************************************
1324 * Docs for Attribute classes
1325 ***************************************************************/
1326
1327/**
1328 * Print the section definition for an AttributeValue.
1329 *
1330 * In doxygen form this will print a comment block with
1331 * \verbatim
1332 * \ingroup attributes
1333 * \defgroup attribute_<name>Value <name>Value
1334 * \endverbatim
1335 *
1336 * \param [in,out] os The output stream.
1337 * \param [in] name The base name of the resulting AttributeValue type.
1338 * \param [in] seeBase Print a "see also" pointing to the base class.
1339 */
1340void
1341PrintAttributeValueSection(std::ostream& os, const std::string& name, const bool seeBase = true)
1342{
1344 std::string section = "attribute_" + name;
1345
1346 // \ingroup attributes
1347 // \defgroup attribute_<name>Value <name> Attribute
1348 os << commentStart << sectionStart << "attributes\n"
1349 << subSectionStart << "attribute_" << name << " " << name << " Attribute\n"
1350 << "AttributeValue implementation for " << name << "\n";
1351 if (seeBase)
1352 {
1353 os << seeAlso << "ns3::" << name << "\n";
1354 }
1355 os << commentStop;
1356
1357} // PrintAttributeValueSection()
1358
1359/**
1360 * Print the AttributeValue documentation for a class.
1361 *
1362 * This will print documentation for the \pname{AttributeValue} class and methods.
1363 *
1364 * \param [in,out] os The output stream.
1365 * \param [in] name The token to use in defining the accessor name.
1366 * \param [in] type The underlying type name.
1367 * \param [in] header The header file which contains this declaration.
1368 */
1369void
1371 const std::string& name,
1372 const std::string& type,
1373 const std::string& header)
1374{
1375 NS_LOG_FUNCTION(name << type << header);
1376 std::string sectAttr = sectionStart + "attribute_" + name;
1377
1378 // \ingroup attribute_<name>Value
1379 // \class ns3::<name>Value "header"
1380 std::string valClass = name + "Value";
1381 std::string qualClass = " ns3::" + valClass;
1382
1383 os << commentStart << sectAttr << std::endl;
1384 os << classStart << qualClass << " \"" << header << "\"" << std::endl;
1385 os << "AttributeValue implementation for " << name << "." << std::endl;
1386 os << seeAlso << "AttributeValue" << std::endl;
1387 os << commentStop;
1388
1389 // Ctor: <name>Value::<name>Value
1390 os << commentStart << functionStart << qualClass << "::" << valClass;
1391 // Constructors
1392 os << "(const " << type << " & value)\n"
1393 << "Constructor.\n"
1394 << argument << "[in] value The " << name << " value to use.\n";
1395 os << commentStop;
1396
1397 // <name>Value::Get() const
1398 os << commentStart << functionStart << type << qualClass << "::Get() const\n"
1399 << returns << "The " << name << " value.\n"
1400 << commentStop;
1401
1402 // <name>Value::GetAccessor(T & value) const
1403 os << commentStart << functionStart << "bool" << qualClass << "::GetAccessor(T & value) const\n"
1404 << "Access the " << name << " value as type " << codeWord << "T.\n"
1405 << templateArgument << "T " << templArgExplicit << "The type to cast to.\n"
1406 << argument << "[out] value The " << name << " value, as type " << codeWord << "T.\n"
1407 << returns << "true.\n"
1408 << commentStop;
1409
1410 // <name>Value::Set(const name & value)
1411 if (type != "Callback") // Yuck
1412 {
1413 os << commentStart << functionStart << "void" << qualClass << "::Set(const " << type
1414 << " & value)\n"
1415 << "Set the value.\n"
1416 << argument << "[in] value The value to adopt.\n"
1417 << commentStop;
1418 }
1419
1420 // <name>Value::m_value
1421 os << commentStart << variable << type << qualClass << "::m_value\n"
1422 << "The stored " << name << " instance.\n"
1423 << commentStop << std::endl;
1424
1425} // PrintAttributeValueWithName()
1426
1427/**
1428 * Print the AttributeValue MakeAccessor documentation for a class.
1429 *
1430 * This will print documentation for the \pname{Make<name>Accessor} functions.
1431 *
1432 * \param [in,out] os The output stream.
1433 * \param [in] name The token to use in defining the accessor name.
1434 */
1435void
1436PrintMakeAccessors(std::ostream& os, const std::string& name)
1437{
1439 std::string sectAttr = sectionStart + "attribute_" + name + "\n";
1440 std::string make = "ns3::Make" + name + "Accessor ";
1441
1442 // \ingroup attribute_<name>Value
1443 // Make<name>Accessor(T1 a1)
1444 os << commentStart << sectAttr << functionStart << "ns3::Ptr<const ns3::AttributeAccessor> "
1445 << make << "(T1 a1)\n"
1446 << copyDoc << "ns3::MakeAccessorHelper(T1)\n"
1447 << seeAlso << "AttributeAccessor\n"
1448 << commentStop;
1449
1450 // \ingroup attribute_<name>Value
1451 // Make<name>Accessor(T1 a1)
1452 os << commentStart << sectAttr << functionStart << "ns3::Ptr<const ns3::AttributeAccessor> "
1453 << make << "(T1 a1, T2 a2)\n"
1454 << copyDoc << "ns3::MakeAccessorHelper(T1,T2)\n"
1455 << seeAlso << "AttributeAccessor\n"
1456 << commentStop;
1457} // PrintMakeAccessors()
1458
1459/**
1460 * Print the AttributeValue MakeChecker documentation for a class.
1461 *
1462 * This will print documentation for the \pname{Make<name>Checker} function.
1463 *
1464 * \param [in,out] os The output stream.
1465 * \param [in] name The token to use in defining the accessor name.
1466 * \param [in] header The header file which contains this declaration.
1467 */
1468void
1469PrintMakeChecker(std::ostream& os, const std::string& name, const std::string& header)
1470{
1471 NS_LOG_FUNCTION(name << header);
1472 std::string sectAttr = sectionStart + "attribute_" + name + "\n";
1473 std::string make = "ns3::Make" + name + "Checker ";
1474
1475 // \ingroup attribute_<name>Value
1476 // class <name>Checker
1477 os << commentStart << sectAttr << std::endl;
1478 os << classStart << " ns3::" << name << "Checker"
1479 << " \"" << header << "\"" << std::endl;
1480 os << "AttributeChecker implementation for " << name << "Value." << std::endl;
1481 os << seeAlso << "AttributeChecker" << std::endl;
1482 os << commentStop;
1483
1484 // \ingroup attribute_<name>Value
1485 // Make<name>Checker()
1486 os << commentStart << sectAttr << functionStart << "ns3::Ptr<const ns3::AttributeChecker> "
1487 << make << "()\n"
1488 << returns << "The AttributeChecker.\n"
1489 << seeAlso << "AttributeChecker\n"
1490 << commentStop;
1491} // PrintMakeChecker()
1492
1493/**Descriptor for an AttributeValue. */
1495{
1496 const std::string m_name; //!< The base name of the resulting AttributeValue type.
1497 const std::string m_type; //!< The name of the underlying type.
1498 const bool m_seeBase; //!< Print a "see also" pointing to the base class.
1499 const std::string m_header; //!< The header file name.
1500};
1501
1502/**
1503 * Print documentation corresponding to use of the
1504 * ATTRIBUTE_HELPER_HEADER macro or
1505 * ATTRIBUTE_VALUE_DEFINE_WITH_NAME macro.
1506 *
1507 * \param [in,out] os The output stream.
1508 * \param [in] attr The AttributeDescriptor.
1509 */
1510void
1511PrintAttributeHelper(std::ostream& os, const AttributeDescriptor& attr)
1512{
1513 NS_LOG_FUNCTION(attr.m_name << attr.m_type << attr.m_seeBase << attr.m_header);
1515 PrintAttributeValueWithName(os, attr.m_name, attr.m_type, attr.m_header);
1516 PrintMakeAccessors(os, attr.m_name);
1517 PrintMakeChecker(os, attr.m_name, attr.m_header);
1518} // PrintAttributeHelper()
1519
1520/**
1521 * Print documentation for Attribute implementations.
1522 * \param os The stream to print on.
1523 */
1524void
1526{
1528
1529 // clang-format off
1530 const AttributeDescriptor attributes [] =
1531 {
1532 // Name Type see Base header-file
1533 // Users of ATTRIBUTE_HELPER_HEADER
1534 //
1535 { "Address", "Address", true, "address.h" },
1536 { "Box", "Box", true, "box.h" },
1537 { "DataRate", "DataRate", true, "data-rate.h" },
1538 { "Length", "Length", true, "length.h" },
1539 { "Ipv4Address", "Ipv4Address", true, "ipv4-address.h" },
1540 { "Ipv4Mask", "Ipv4Mask", true, "ipv4-address.h" },
1541 { "Ipv6Address", "Ipv6Address", true, "ipv6-address.h" },
1542 { "Ipv6Prefix", "Ipv6Prefix", true, "ipv6-address.h" },
1543 { "Mac16Address", "Mac16Address", true, "mac16-address.h" },
1544 { "Mac48Address", "Mac48Address", true, "mac48-address.h" },
1545 { "Mac64Address", "Mac64Address", true, "mac64-address.h" },
1546 { "ObjectFactory", "ObjectFactory", true, "object-factory.h" },
1547 { "Priomap", "Priomap", true, "prio-queue-disc.h" },
1548 { "QueueSize", "QueueSize", true, "queue-size.h" },
1549 { "Rectangle", "Rectangle", true, "rectangle.h" },
1550 { "Ssid", "Ssid", true, "ssid.h" },
1551 { "TypeId", "TypeId", true, "type-id.h" },
1552 { "UanModesList", "UanModesList", true, "uan-tx-mode.h" },
1553 { "ValueClassTest", "ValueClassTest", false, "attribute-test-suite.cc" /* core/test/ */ },
1554 { "Vector2D", "Vector2D", true, "vector.h" },
1555 { "Vector3D", "Vector3D", true, "vector.h" },
1556 { "Waypoint", "Waypoint", true, "waypoint.h" },
1557 { "WifiMode", "WifiMode", true, "wifi-mode.h" },
1558
1559 // All three (Value, Access and Checkers) defined, but custom
1560 { "Boolean", "bool", false, "boolean.h" },
1561 { "Callback", "CallbackBase", true, "callback.h" },
1562 { "Double", "double", false, "double.h" },
1563 { "Enum", "T", false, "enum.h" },
1564 { "Integer", "int64_t", false, "integer.h" },
1565 { "String", "std::string", false, "string.h" },
1566 { "Time", "Time", true, "nstime.h" },
1567 { "Uinteger", "uint64_t", false, "uinteger.h" },
1568 { "", "", false, "last placeholder" }
1569 };
1570 // clang-format on
1571
1572 int i = 0;
1573 while (!attributes[i].m_name.empty())
1574 {
1575 PrintAttributeHelper(os, attributes[i]);
1576 ++i;
1577 }
1578
1579 PrintAttributeValueSection(os, "ObjectVector", false);
1580 PrintMakeAccessors(os, "ObjectVector");
1581 PrintMakeChecker(os, "ObjectVector", "object-vector.h");
1582
1583 PrintAttributeValueSection(os, "ObjectMap", false);
1584 PrintMakeAccessors(os, "ObjectMap");
1585 PrintMakeChecker(os, "ObjectMap", "object-map.h");
1586
1587} // PrintAttributeImplementations()
1588
1589/***************************************************************
1590 * Main
1591 ***************************************************************/
1592
1593int
1594main(int argc, char* argv[])
1595{
1597
1598 std::string typeId;
1599
1600 CommandLine cmd(__FILE__);
1601 cmd.Usage("Generate documentation for all ns-3 registered types, "
1602 "trace sources, attributes and global variables.");
1603 cmd.AddValue("output-text", "format output as plain text", outputText);
1604 cmd.AddValue("TypeId", "Print docs for just the given TypeId", typeId);
1605 cmd.Parse(argc, argv);
1606
1607 if (!typeId.empty())
1608 {
1609 outputText = true;
1610 SetMarkup();
1611
1612 TypeId tid;
1613
1614 bool validTypeId = TypeId::LookupByNameFailSafe(typeId, &tid);
1615 if (!validTypeId)
1616 {
1617 auto fqTypeId = "ns3::" + typeId;
1618 validTypeId = TypeId::LookupByNameFailSafe(fqTypeId, &tid);
1619 if (validTypeId)
1620 {
1621 std::cout << "\nFound fully qualified name " << fqTypeId << "\n\n";
1622 }
1623 }
1624 if (validTypeId)
1625 {
1626 PrintTypeIdBlock(std::cout, tid);
1627 return 0;
1628 }
1629 else
1630 {
1631 std::cerr << "Invalid TypeId name: " << typeId << "\n" << std::endl;
1632 std::cerr << cmd;
1633 exit(1);
1634 }
1635 }
1636
1637 SetMarkup();
1638
1639 // Create a Node, to force linking and instantiation of our TypeIds
1640 NodeContainer c;
1641 c.Create(1);
1642
1643 std::cout << std::endl;
1644 std::cout << commentStart << file << "\n"
1645 << sectionStart << "utils\n"
1646 << "Doxygen docs generated from the TypeId database.\n"
1647 << note << "This file is automatically generated by " << codeWord
1648 << "print-introspected-doxygen.cc. Do not edit this file! "
1649 << "Edit that file instead.\n"
1650 << commentStop << std::endl;
1651
1652 PrintTypeIdBlocks(std::cout);
1653
1654 PrintAllTypeIds(std::cout);
1655 PrintAllAttributes(std::cout);
1656 PrintAllGlobals(std::cout);
1657 PrintAllGroups(std::cout);
1658 PrintAllLogComponents(std::cout);
1659 PrintAllTraceSources(std::cout);
1661
1662 return 0;
1663}
Gather aggregation and configuration path information from registered types.
void DoGather(TypeId tid)
Gather attribute, configuration path information for tid.
std::vector< std::pair< TypeId, std::string > > m_output
Configuration path for each TypeId.
void Print(std::ostream &os) const
Print output in "a -> b" form on the stream.
std::vector< TypeId > m_alreadyProcessed
List of TypeIds we've already processed.
std::vector< std::string > m_noTids
List of type names without TypeIds, because those modules aren't enabled.
std::vector< std::string > m_currentPath
Current configuration path.
std::vector< std::string > GetNoTypeIds() const
bool HasAlreadyBeenProcessed(TypeId tid) const
void RecordAggregationInfo(std::string a, std::string b)
Record the a -> b aggregation relation.
std::vector< std::pair< TypeId, TypeId > > m_aggregates
List of aggregation relationships.
std::string GetCurrentPath() const
void Gather(TypeId tid)
Gather aggregation and configuration path information for tid.
std::vector< std::string > Get(TypeId tid) const
void RecordOutput(TypeId tid)
Record the current config path for tid.
Parse command-line arguments.
static Iterator Begin()
The Begin iterator.
static Iterator End()
The End iterator.
static ComponentList * GetComponentList()
Get the list of LogComponents.
Definition log.cc:132
std::unordered_map< std::string, LogComponent * > ComponentList
LogComponent name map.
Definition log.h:387
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
AttributeChecker implementation for ObjectPtrContainerValue.
AttributeChecker implementation for PointerValue.
Definition pointer.h:114
Smart pointer class similar to boost::intrusive_ptr.
Hold variables of type string.
Definition string.h:45
std::string Get() const
Definition string.cc:20
a unique identifier for an interface.
Definition type-id.h:48
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition type-id.cc:1041
std::size_t GetTraceSourceN() const
Get the number of Trace sources.
Definition type-id.cc:1193
bool MustHideFromDocumentation() const
Check if this TypeId should not be listed in documentation.
Definition type-id.cc:1162
AttributeFlag
Flags describing when a given attribute can be read or written.
Definition type-id.h:52
@ ATTR_GET
The attribute can be read.
Definition type-id.h:53
@ ATTR_SET
The attribute can be written.
Definition type-id.h:54
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition type-id.h:55
TypeId::TraceSourceInformation GetTraceSource(std::size_t i) const
Get the trace source by index.
Definition type-id.cc:1200
std::string GetGroupName() const
Get the group name.
Definition type-id.cc:1053
static uint16_t GetRegisteredN()
Get the number of registered TypeIds.
Definition type-id.cc:926
std::size_t GetAttributeN() const
Get the number of attributes.
Definition type-id.cc:1170
TypeId GetParent() const
Get the parent of this TypeId.
Definition type-id.cc:1025
static TypeId GetRegistered(uint16_t i)
Get a TypeId by index.
Definition type-id.cc:933
std::size_t GetSize() const
Get the size of this object.
Definition type-id.cc:1076
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition type-id.cc:1178
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition type-id.cc:886
SupportLevel
The level of support or deprecation for attributes or trace sources.
Definition type-id.h:62
@ SUPPORTED
Attribute or trace source is currently used.
Definition type-id.h:63
@ OBSOLETE
Attribute or trace source is not used anymore; simulation fails.
Definition type-id.h:65
@ DEPRECATED
Attribute or trace source is deprecated; user is warned.
Definition type-id.h:64
std::string GetName() const
Get the name.
Definition type-id.cc:1061
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< Object > GetRootNamespaceObject(uint32_t i)
Definition config.cc:1019
std::size_t GetRootNamespaceObjectN()
Definition config.cc:1012
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
std::string headingStart
start of section heading (h3)
std::string copyDoc
copy (or refer) to docs elsewhere
std::map< std::string, ns3::TypeId::TraceSourceInformation > SortedTraceSourceInfo(const TypeId tid)
Alphabetize the TraceSourceInformation for a TypeId by the TraceSource name.
std::string breakHtmlOnly
linebreak for html output only
std::map< std::string, ns3::TypeId::AttributeInformation > SortedAttributeInfo(const TypeId tid)
Alphabetize the AttributeInformation for a TypeId by the Attribute name.
std::string codeWord
format next word as source code
std::string breakTextOnly
linebreak for text output only
std::string flagSpanStart
start of Attribute flag value
std::string templArgDeduced
template argument deduced from function
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
StaticInformation GetTypicalAggregations()
Register aggregation relationships that are not automatically detected by this introspection program.
void PrintTraceSourcesTid(std::ostream &os, const TypeId tid)
Print direct Trace sources for this TypeId.
std::set< TypeId > GroupList_t
List of TypeIds for a group.
std::map< std::string, int32_t > NameMap
Map from TypeId name to tid.
void PrintMakeAccessors(std::ostream &os, const std::string &name)
Print the AttributeValue MakeAccessor documentation for a class.
void PrintAllTraceSources(std::ostream &os)
Print the list of all Trace sources.
void PrintAllLogComponents(std::ostream &os)
Print the list of all LogComponents.
void PrintAttributeHelper(std::ostream &os, const AttributeDescriptor &attr)
Print documentation corresponding to use of the ATTRIBUTE_HELPER_HEADER macro or ATTRIBUTE_VALUE_DEFI...
void PrintTypeIdBlock(std::ostream &os, const TypeId tid)
Print the doxy block for a single TypeId.
void PrintTypeIdBlocks(std::ostream &os)
Print the doxy block for each TypeId.
std::map< std::string, GroupList_t > GroupsList_t
Collection of group names with associated TypeIds.
void PrintAllAttributes(std::ostream &os)
Print the list of all Attributes.
void PrintAttributeValueWithName(std::ostream &os, const std::string &name, const std::string &type, const std::string &header)
Print the AttributeValue documentation for a class.
GroupsList_t GetGroupsList()
Get a sorted list of TypeId groups.
void PrintSupportLevel(std::ostream &os, TypeId::SupportLevel supportLevel, std::string supportMsg)
Print the support level for an Attribute or TraceSource.
void PrintSize(std::ostream &os, const TypeId tid)
Print the size of the type represented by this tid.
void Uniquefy(T t)
Helper to keep only the unique items in a container.
void PrintAttributeImplementations(std::ostream &os)
Print documentation for Attribute implementations.
NameMap GetNameMap()
Create a map from the class names to their index in the vector of TypeId's so that the names will end...
void PrintTraceSources(std::ostream &os, const TypeId tid)
Print the Trace sources block for tid, including Trace sources declared in base classes.
void SetMarkup()
Initialize the markup strings, for either doxygen or text.
NameMap::const_iterator NameMapIterator
NameMap iterator.
void PrintConfigPaths(std::ostream &os, const TypeId tid)
Print config paths.
void PrintAllTypeIds(std::ostream &os)
Print the list of all TypeIds.
void PrintAttributes(std::ostream &os, const TypeId tid)
Print the Attributes block for tid, including Attributes declared in base classes.
void PrintAllGroups(std::ostream &os)
Print the list of all groups.
void PrintAllGlobals(std::ostream &os)
Print the list of all global variables.
void PrintMakeChecker(std::ostream &os, const std::string &name, const std::string &header)
Print the AttributeValue MakeChecker documentation for a class.
void PrintAttributeValueSection(std::ostream &os, const std::string &name, const bool seeBase=true)
Print the section definition for an AttributeValue.
void PrintAttributesTid(std::ostream &os, const TypeId tid)
Print direct Attributes for this TypeId.
Descriptor for an AttributeValue.
const std::string m_header
The header file name.
const std::string m_type
The name of the underlying type.
const std::string m_name
The base name of the resulting AttributeValue type.
const bool m_seeBase
Print a "see also" pointing to the base class.
Attribute implementation.
Definition type-id.h:70
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition type-id.h:86
std::string name
Attribute name.
Definition type-id.h:72
Ptr< const AttributeChecker > checker
Checker object.
Definition type-id.h:84
std::string supportMsg
Support message.
Definition type-id.h:88
TraceSource implementation.
Definition type-id.h:93
std::string name
Trace name.
Definition type-id.h:95