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