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