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